From 7a7857f47b33f1b63fb585d2dc6c60d87c3e928f Mon Sep 17 00:00:00 2001 From: aliaspider Date: Mon, 9 Nov 2015 19:55:28 +0100 Subject: C++ --> C99 --- src/65c816.h | 5 +- src/DSP1_gp32.c | 514 ++++++ src/DSP1_gp32.cpp | 514 ------ src/apu.c | 1005 +++++++++++ src/apu.cpp | 1002 ----------- src/apu.h | 12 +- src/apumem.h | 8 +- src/asmmemfuncs.h | 4 +- src/c4.c | 432 +++++ src/c4.cpp | 431 ----- src/c4.h | 4 +- src/c4emu.c | 892 ++++++++++ src/c4emu.cpp | 876 ---------- src/cheats.c | 393 +++++ src/cheats.cpp | 391 ----- src/cheats.h | 12 +- src/cheats2.c | 232 +++ src/cheats2.cpp | 230 --- src/clip.c | 737 ++++++++ src/clip.cpp | 731 -------- src/cpu.c | 169 ++ src/cpu.cpp | 169 -- src/cpuexec.c | 541 ++++++ src/cpuexec.cpp | 541 ------ src/cpuexec.h | 25 +- src/cpuops.c | 4247 +++++++++++++++++++++++++++++++++++++++++++++++ src/cpuops.cpp | 4247 ----------------------------------------------- src/data.c | 489 ++++++ src/data.cpp | 489 ------ src/display.h | 7 +- src/dma.c | 875 ++++++++++ src/dma.cpp | 873 ---------- src/dsp1.c | 1195 +++++++++++++ src/dsp1.cpp | 1195 ------------- src/dsp1.h | 7 +- src/fxemu.c | 721 ++++++++ src/fxemu.cpp | 721 -------- src/fxemu.h | 6 +- src/fxinst.c | 1916 +++++++++++++++++++++ src/fxinst.cpp | 1916 --------------------- src/fxinst.h | 4 +- src/getset.h | 168 +- src/gfx.c | 3772 +++++++++++++++++++++++++++++++++++++++++ src/gfx.cpp | 3772 ----------------------------------------- src/gfx.h | 23 +- src/gfx16.c | 3443 ++++++++++++++++++++++++++++++++++++++ src/gfx16.cpp | 3443 -------------------------------------- src/globals.c | 437 +++++ src/globals.cpp | 436 ----- src/memmap.c | 2759 ++++++++++++++++++++++++++++++ src/memmap.cpp | 2758 ------------------------------ src/memmap.h | 15 +- src/missing.h | 12 +- src/mode7.c | 572 +++++++ src/mode7.cpp | 572 ------- src/mode7_t.h | 16 +- src/mode7_t.h.new | 16 +- src/mode7add.c | 5 + src/mode7add.cpp | 5 - src/mode7add1_2.c | 6 + src/mode7add1_2.cpp | 6 - src/mode7add1_2prio.c | 8 + src/mode7add1_2prio.cpp | 8 - src/mode7addprio.c | 5 + src/mode7addprio.cpp | 5 - src/mode7new.c | 506 ++++++ src/mode7new.cpp | 506 ------ src/mode7prio.c | 603 +++++++ src/mode7prio.cpp | 603 ------- src/mode7prio_t.h | 16 +- src/mode7prio_t.h.last | 16 +- src/mode7sub.c | 6 + src/mode7sub.cpp | 6 - src/mode7sub1_2.c | 6 + src/mode7sub1_2.cpp | 6 - src/mode7sub1_2prio.c | 5 + src/mode7sub1_2prio.cpp | 5 - src/mode7subprio.c | 6 + src/mode7subprio.cpp | 6 - src/os9x_asm_cpu.c | 255 +++ src/os9x_asm_cpu.cpp | 255 --- src/port.h | 1 + src/ppu.c | 1416 ++++++++++++++++ src/ppu.cpp | 1413 ---------------- src/ppu.h | 33 +- src/ppu_.c | 2486 +++++++++++++++++++++++++++ src/ppu_.cpp | 2486 --------------------------- src/rops.c | 238 +++ src/rops.cpp | 238 --- src/rops.h | 2 + src/sa1.c | 775 +++++++++ src/sa1.cpp | 775 --------- src/sa1.h | 26 +- src/sa1cpu.c | 125 ++ src/sa1cpu.cpp | 125 -- src/sar.h | 13 +- src/sdd1.c | 131 ++ src/sdd1.cpp | 131 -- src/sdd1emu.c | 414 +++++ src/sdd1emu.cpp | 414 ----- src/sdd1emu.h | 4 +- src/seta.c | 107 ++ src/seta.cpp | 107 -- src/seta010.c | 751 +++++++++ src/seta010.cpp | 751 --------- src/seta011.c | 233 +++ src/seta011.cpp | 233 --- src/seta018.c | 255 +++ src/seta018.cpp | 255 --- src/snaporig.c | 411 +++++ src/snaporig.cpp | 411 ----- src/snapshot.c | 945 +++++++++++ src/snapshot.cpp | 945 ----------- src/snes9x.cpp | 655 -------- src/snes9x.h | 22 +- src/soundux.c | 1196 +++++++++++++ src/soundux.cpp | 1196 ------------- src/soundux.h | 3 +- src/spc700.c | 2509 ++++++++++++++++++++++++++++ src/spc700.cpp | 2509 ---------------------------- src/spc700.h | 5 +- src/srtc.c | 528 ++++++ src/srtc.cpp | 528 ------ src/tile.c | 1346 +++++++++++++++ src/tile.cpp | 1346 --------------- src/tile16.c | 1858 +++++++++++++++++++++ src/tile16.cpp | 1858 --------------------- src/tile16.cpp.bak | 24 +- src/tile16_t.h | 24 +- src/tile16add.c | 48 + src/tile16add.cpp | 48 - src/tile16add1_2.c | 48 + src/tile16add1_2.cpp | 48 - src/tile16f_t.h | 16 +- src/tile16fadd1_2.c | 61 + src/tile16fadd1_2.cpp | 61 - src/tile16fsub1_2.c | 87 + src/tile16fsub1_2.cpp | 87 - src/tile16noprio.c | 403 +++++ src/tile16noprio.cpp | 403 ----- src/tile16sub.c | 48 + src/tile16sub.cpp | 48 - src/tile16sub1_2.c | 50 + src/tile16sub1_2.cpp | 50 - 144 files changed, 43502 insertions(+), 44107 deletions(-) create mode 100644 src/DSP1_gp32.c delete mode 100644 src/DSP1_gp32.cpp create mode 100644 src/apu.c delete mode 100644 src/apu.cpp create mode 100644 src/c4.c delete mode 100644 src/c4.cpp create mode 100644 src/c4emu.c delete mode 100644 src/c4emu.cpp create mode 100644 src/cheats.c delete mode 100644 src/cheats.cpp create mode 100644 src/cheats2.c delete mode 100644 src/cheats2.cpp create mode 100644 src/clip.c delete mode 100644 src/clip.cpp create mode 100644 src/cpu.c delete mode 100644 src/cpu.cpp create mode 100644 src/cpuexec.c delete mode 100644 src/cpuexec.cpp create mode 100644 src/cpuops.c delete mode 100644 src/cpuops.cpp create mode 100644 src/data.c delete mode 100644 src/data.cpp create mode 100644 src/dma.c delete mode 100644 src/dma.cpp create mode 100644 src/dsp1.c delete mode 100644 src/dsp1.cpp create mode 100644 src/fxemu.c delete mode 100644 src/fxemu.cpp create mode 100644 src/fxinst.c delete mode 100644 src/fxinst.cpp create mode 100644 src/gfx.c delete mode 100644 src/gfx.cpp create mode 100644 src/gfx16.c delete mode 100644 src/gfx16.cpp create mode 100644 src/globals.c delete mode 100644 src/globals.cpp create mode 100644 src/memmap.c delete mode 100644 src/memmap.cpp create mode 100644 src/mode7.c delete mode 100644 src/mode7.cpp create mode 100644 src/mode7add.c delete mode 100644 src/mode7add.cpp create mode 100644 src/mode7add1_2.c delete mode 100644 src/mode7add1_2.cpp create mode 100644 src/mode7add1_2prio.c delete mode 100644 src/mode7add1_2prio.cpp create mode 100644 src/mode7addprio.c delete mode 100644 src/mode7addprio.cpp create mode 100644 src/mode7new.c delete mode 100644 src/mode7new.cpp create mode 100644 src/mode7prio.c delete mode 100644 src/mode7prio.cpp create mode 100644 src/mode7sub.c delete mode 100644 src/mode7sub.cpp create mode 100644 src/mode7sub1_2.c delete mode 100644 src/mode7sub1_2.cpp create mode 100644 src/mode7sub1_2prio.c delete mode 100644 src/mode7sub1_2prio.cpp create mode 100644 src/mode7subprio.c delete mode 100644 src/mode7subprio.cpp create mode 100644 src/os9x_asm_cpu.c delete mode 100644 src/os9x_asm_cpu.cpp create mode 100644 src/ppu.c delete mode 100644 src/ppu.cpp create mode 100644 src/ppu_.c delete mode 100644 src/ppu_.cpp create mode 100644 src/rops.c delete mode 100644 src/rops.cpp create mode 100644 src/sa1.c delete mode 100644 src/sa1.cpp create mode 100644 src/sa1cpu.c delete mode 100644 src/sa1cpu.cpp create mode 100644 src/sdd1.c delete mode 100644 src/sdd1.cpp create mode 100644 src/sdd1emu.c delete mode 100644 src/sdd1emu.cpp create mode 100644 src/seta.c delete mode 100644 src/seta.cpp create mode 100644 src/seta010.c delete mode 100644 src/seta010.cpp create mode 100644 src/seta011.c delete mode 100644 src/seta011.cpp create mode 100644 src/seta018.c delete mode 100644 src/seta018.cpp create mode 100644 src/snaporig.c delete mode 100644 src/snaporig.cpp create mode 100644 src/snapshot.c delete mode 100644 src/snapshot.cpp delete mode 100644 src/snes9x.cpp create mode 100644 src/soundux.c delete mode 100644 src/soundux.cpp create mode 100644 src/spc700.c delete mode 100644 src/spc700.cpp create mode 100644 src/srtc.c delete mode 100644 src/srtc.cpp create mode 100644 src/tile.c delete mode 100644 src/tile.cpp create mode 100644 src/tile16.c delete mode 100644 src/tile16.cpp create mode 100644 src/tile16add.c delete mode 100644 src/tile16add.cpp create mode 100644 src/tile16add1_2.c delete mode 100644 src/tile16add1_2.cpp create mode 100644 src/tile16fadd1_2.c delete mode 100644 src/tile16fadd1_2.cpp create mode 100644 src/tile16fsub1_2.c delete mode 100644 src/tile16fsub1_2.cpp create mode 100644 src/tile16noprio.c delete mode 100644 src/tile16noprio.cpp create mode 100644 src/tile16sub.c delete mode 100644 src/tile16sub.cpp create mode 100644 src/tile16sub1_2.c delete mode 100644 src/tile16sub1_2.cpp (limited to 'src') diff --git a/src/65c816.h b/src/65c816.h index aa251dc..1ab8e54 100644 --- a/src/65c816.h +++ b/src/65c816.h @@ -105,7 +105,8 @@ typedef union uint16 W; } ALIGN_BY_ONE pair; -struct SRegisters{ +typedef struct +{ uint8 PB; uint8 DB; pair P; @@ -115,7 +116,7 @@ struct SRegisters{ pair S; pair Y; uint16 PC; -} PACKING; +}PACKING SRegisters; #define Registers CPU.Regs //EXTERN_C struct SRegisters Registers; diff --git a/src/DSP1_gp32.c b/src/DSP1_gp32.c new file mode 100644 index 0000000..7c89cbf --- /dev/null +++ b/src/DSP1_gp32.c @@ -0,0 +1,514 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include "snes9x.h" +#include "dsp1.h" +#include "missing.h" +#include "memmap.h" +#include + +#include "dsp1emu_gp32.c" + +void S9xInitDSP1 () +{ + static bool8 init = FALSE; + + if (!init) + { + InitDSP (); + init = TRUE; + } +} + +void S9xResetDSP1 () +{ + S9xInitDSP1 (); + + DSP1.waiting4command = TRUE; + DSP1.in_count = 0; + DSP1.out_count = 0; + DSP1.in_index = 0; + DSP1.out_index = 0; + DSP1.first_parameter = TRUE; +} + +uint8 S9xGetDSP (uint16 address) +{ + uint8 t; + + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if (DSP1.out_count) + { + if ((address & 1) == 0) + t = (uint8) DSP1.output [DSP1.out_index]; + else + { + t = (uint8) (DSP1.output [DSP1.out_index] >> 8); + DSP1.out_index++; + if (--DSP1.out_count == 0) + { + if (DSP1.command == 0x1a || DSP1.command == 0x0a) + { + DSPOp0A (); + DSP1.out_count = 4; + DSP1.out_index = 0; + DSP1.output [0] = Op0AA; + DSP1.output [1] = Op0AB; + DSP1.output [2] = Op0AC; + DSP1.output [3] = Op0AD; + } + } + DSP1.waiting4command = TRUE; + } + } + else + { + // Top Gear 3000 requires this value.... + t = 0xff; + } + } + else + t = 0x80; + + return (t); +} + +void S9xSetDSP (uint8 byte, uint16 address) +{ + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if ((address & 1) == 0) + { + if (DSP1.waiting4command) + { + DSP1.command = byte; + DSP1.in_index = 0; + DSP1.waiting4command = FALSE; + DSP1.first_parameter = TRUE; + + // Mario Kart uses 0x00, 0x02, 0x06, 0x0c, 0x28, 0x0a + switch (byte) + { + case 0x00: DSP1.in_count = 2; break; + case 0x10: DSP1.in_count = 2; break; + case 0x04: DSP1.in_count = 2; break; + case 0x08: DSP1.in_count = 3; break; + case 0x18: DSP1.in_count = 4; break; + case 0x28: DSP1.in_count = 3; break; + case 0x0c: DSP1.in_count = 3; break; + case 0x1c: DSP1.in_count = 6; break; + case 0x02: DSP1.in_count = 7; break; + case 0x0a: DSP1.in_count = 1; break; + case 0x1a: DSP1.in_count = 1; break; + case 0x06: DSP1.in_count = 3; break; + case 0x0e: DSP1.in_count = 2; break; + case 0x01: DSP1.in_count = 4; break; + case 0x11: DSP1.in_count = 4; break; + case 0x21: DSP1.in_count = 4; break; + case 0x0d: DSP1.in_count = 3; break; + case 0x1d: DSP1.in_count = 3; break; + case 0x2d: DSP1.in_count = 3; break; + case 0x03: DSP1.in_count = 3; break; + case 0x13: DSP1.in_count = 3; break; + case 0x23: DSP1.in_count = 3; break; + case 0x0b: DSP1.in_count = 3; break; + case 0x1b: DSP1.in_count = 3; break; + case 0x2b: DSP1.in_count = 3; break; + case 0x14: DSP1.in_count = 6; break; +// case 0x80: DSP1.in_count = 2; break; + + default: + case 0x80: + DSP1.in_count = 0; + DSP1.waiting4command = TRUE; + DSP1.first_parameter = TRUE; + break; + } + } + else + { + DSP1.parameters [DSP1.in_index] = byte; + DSP1.first_parameter = FALSE; + } + } + else + { + if (DSP1.waiting4command || + (DSP1.first_parameter && byte == 0x80)) + { + DSP1.waiting4command = TRUE; + DSP1.first_parameter = FALSE; + } + else + if (DSP1.first_parameter) + { + } + else + { + if (DSP1.in_count) + { + DSP1.parameters [DSP1.in_index] |= (byte << 8); + if (--DSP1.in_count == 0) + { + // Actually execute the command + DSP1.waiting4command = TRUE; + DSP1.out_index = 0; + switch (DSP1.command) + { + case 0x00: // Multiple + Op00Multiplicand = (int16) DSP1.parameters [0]; + Op00Multiplier = (int16) DSP1.parameters [1]; + + DSPOp00 (); + + DSP1.out_count = 1; + DSP1.output [0] = Op00Result; + break; + + case 0x10: // Inverse + Op10Coefficient = (int16) DSP1.parameters [0]; + Op10Exponent = (int16) DSP1.parameters [1]; + + DSPOp10 (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint16) (int16) Op10CoefficientR; + DSP1.output [1] = (uint16) (int16) Op10ExponentR; + break; + + case 0x04: // Sin and Cos of angle + Op04Angle = (int16) DSP1.parameters [0]; + Op04Radius = (uint16) DSP1.parameters [1]; + + DSPOp04 (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint16) Op04Sin; + DSP1.output [1] = (uint16) Op04Cos; + break; + + case 0x08: // Radius + Op08X = (int16) DSP1.parameters [0]; + Op08Y = (int16) DSP1.parameters [1]; + Op08Z = (int16) DSP1.parameters [2]; + + DSPOp08 (); + + DSP1.out_count = 2; + DSP1.output [0] = (int16) Op08Ll; + DSP1.output [1] = (int16) Op08Lh; + break; + + case 0x18: // Range + + Op18X = (int16) DSP1.parameters [0]; + Op18Y = (int16) DSP1.parameters [1]; + Op18Z = (int16) DSP1.parameters [2]; + Op18R = (int16) DSP1.parameters [3]; + + DSPOp18 (); + + DSP1.out_count = 1; + DSP1.output [0] = Op18D; + break; + + case 0x28: // Distance (vector length) + Op28X = (int16) DSP1.parameters [0]; + Op28Y = (int16) DSP1.parameters [1]; + Op28Z = (int16) DSP1.parameters [2]; + + DSPOp28 (); + + DSP1.out_count = 1; + DSP1.output [0] = (uint16) Op28R; + break; + + case 0x0c: // Rotate (2D rotate) + Op0CA = (int16) DSP1.parameters [0]; + Op0CX1 = (int16) DSP1.parameters [1]; + Op0CY1 = (int16) DSP1.parameters [2]; + + DSPOp0C (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint16) Op0CX2; + DSP1.output [1] = (uint16) Op0CY2; + break; + + case 0x1c: // Polar (3D rotate) + Op1CZ = DSP1.parameters [0]; + Op1CX = DSP1.parameters [1]; + Op1CY = DSP1.parameters [2]; + Op1CXBR = DSP1.parameters [3]; + Op1CYBR = DSP1.parameters [4]; + Op1CZBR = DSP1.parameters [5]; + + DSPOp1C (); + + DSP1.out_count = 3; + DSP1.output [0] = (uint16) Op1CXAR; + DSP1.output [1] = (uint16) Op1CYAR; + DSP1.output [2] = (uint16) Op1CZAR; + break; + + case 0x02: // Parameter (Projection) + Op02FX = DSP1.parameters [0]; + Op02FY = DSP1.parameters [1]; + Op02FZ = DSP1.parameters [2]; + Op02LFE = DSP1.parameters [3]; + Op02LES = DSP1.parameters [4]; + Op02AAS = DSP1.parameters [5]; + Op02AZS = DSP1.parameters [6]; + + DSPOp02 (); + + DSP1.out_count = 4; + DSP1.output [0] = Op02VOF; + DSP1.output [1] = Op02VVA; + DSP1.output [2] = Op02CX; + DSP1.output [3] = Op02CY; + break; + + case 0x1a: // Raster mode 7 matrix data + case 0x0a: + Op0AVS = DSP1.parameters [0]; + + DSPOp0A (); + + DSP1.out_count = 4; + DSP1.output [0] = Op0AA; + DSP1.output [1] = Op0AB; + DSP1.output [2] = Op0AC; + DSP1.output [3] = Op0AD; + break; + + case 0x06: // Project object + Op06X = (int16) DSP1.parameters [0]; + Op06Y = (int16) DSP1.parameters [1]; + Op06Z = (int16) DSP1.parameters [2]; + + DSPOp06 (); + + DSP1.out_count = 3; + DSP1.output [0] = Op06H; + DSP1.output [1] = Op06V; + DSP1.output [2] = Op06S; + break; + + case 0x0e: // Target + Op0EH = (int16) DSP1.parameters [0]; + Op0EV = (int16) DSP1.parameters [1]; + + DSPOp0E (); + + DSP1.out_count = 2; + DSP1.output [0] = Op0EX; + DSP1.output [1] = Op0EY; + break; + + // Extra commands used by Pilot Wings + case 0x01: // Set attitude matrix A + Op01m = (int16) DSP1.parameters [0]; + Op01Zr = (int16) DSP1.parameters [1]; + Op01Xr = (int16) DSP1.parameters [2]; + Op01Yr = (int16) DSP1.parameters [3]; + + DSPOp01 (); + break; + + case 0x11: // Set attitude matrix B + Op11m = (int16) DSP1.parameters [0]; + Op11Zr = (int16) DSP1.parameters [1]; + Op11Xr = (int16) DSP1.parameters [2]; + Op11Yr = (int16) DSP1.parameters [3]; + + DSPOp11 (); + break; + + case 0x21: // Set attitude matrix C + Op21m = (int16) DSP1.parameters [0]; + Op21Zr = (int16) DSP1.parameters [1]; + Op21Xr = (int16) DSP1.parameters [2]; + Op21Yr = (int16) DSP1.parameters [3]; + + DSPOp21 (); + break; + + case 0x0d: // Objective matrix A + Op0DX = (int16) DSP1.parameters [0]; + Op0DY = (int16) DSP1.parameters [1]; + Op0DZ = (int16) DSP1.parameters [2]; + + DSPOp0D (); + + DSP1.out_count = 3; + DSP1.output [0] = (uint16) Op0DF; + DSP1.output [1] = (uint16) Op0DL; + DSP1.output [2] = (uint16) Op0DU; + break; + + case 0x1d: // Objective matrix B + Op1DX = (int16) DSP1.parameters [0]; + Op1DY = (int16) DSP1.parameters [1]; + Op1DZ = (int16) DSP1.parameters [2]; + + DSPOp1D (); + + DSP1.out_count = 3; + DSP1.output [0] = (uint16) Op1DF; + DSP1.output [1] = (uint16) Op1DL; + DSP1.output [2] = (uint16) Op1DU; + break; + + case 0x2d: // Objective matrix C + Op2DX = (int16) DSP1.parameters [0]; + Op2DY = (int16) DSP1.parameters [1]; + Op2DZ = (int16) DSP1.parameters [2]; + + DSPOp2D (); + + DSP1.out_count = 3; + DSP1.output [0] = (uint16) Op2DF; + DSP1.output [1] = (uint16) Op2DL; + DSP1.output [2] = (uint16) Op2DU; + break; + + case 0x03: // Subjective matrix A + Op03F = (int16) DSP1.parameters [0]; + Op03L = (int16) DSP1.parameters [1]; + Op03U = (int16) DSP1.parameters [2]; + + DSPOp03 (); + + DSP1.out_count = 3; + DSP1.output [0] = (uint16) Op03X; + DSP1.output [1] = (uint16) Op03Y; + DSP1.output [2] = (uint16) Op03Z; + break; + + case 0x13: // Subjective matrix B + Op13F = (int16) DSP1.parameters [0]; + Op13L = (int16) DSP1.parameters [1]; + Op13U = (int16) DSP1.parameters [2]; + + DSPOp13 (); + + DSP1.out_count = 3; + DSP1.output [0] = (uint16) Op13X; + DSP1.output [1] = (uint16) Op13Y; + DSP1.output [2] = (uint16) Op13Z; + break; + + case 0x23: // Subjective matrix C + Op23F = (int16) DSP1.parameters [0]; + Op23L = (int16) DSP1.parameters [1]; + Op23U = (int16) DSP1.parameters [2]; + + DSPOp23 (); + + DSP1.out_count = 3; + DSP1.output [0] = (uint16) Op23X; + DSP1.output [1] = (uint16) Op23Y; + DSP1.output [2] = (uint16) Op23Z; + break; + + case 0x0b: + Op0BX = (int16) DSP1.parameters [0]; + Op0BY = (int16) DSP1.parameters [1]; + Op0BZ = (int16) DSP1.parameters [2]; + + DSPOp0B (); + + DSP1.out_count = 1; + DSP1.output [0] = (uint16) Op0BS; + break; + + case 0x1b: + Op1BX = (int16) DSP1.parameters [0]; + Op1BY = (int16) DSP1.parameters [1]; + Op1BZ = (int16) DSP1.parameters [2]; + + DSPOp1B (); + + DSP1.out_count = 1; + DSP1.output [0] = (uint16) Op1BS; + break; + + case 0x2b: + Op2BX = (int16) DSP1.parameters [0]; + Op2BY = (int16) DSP1.parameters [1]; + Op2BZ = (int16) DSP1.parameters [2]; + + DSPOp0B (); + + DSP1.out_count = 1; + DSP1.output [0] = (uint16) Op2BS; + break; + + case 0x14: // Gyrate + Op14Zr = (int16) DSP1.parameters [0]; + Op14Xr = (int16) DSP1.parameters [1]; + Op14Yr = (int16) DSP1.parameters [2]; + Op14U = (int16) DSP1.parameters [3]; + Op14F = (int16) DSP1.parameters [4]; + Op14L = (int16) DSP1.parameters [5]; + + DSPOp14 (); + + DSP1.out_count = 3; + DSP1.output [0] = (uint16) Op14Zrr; + DSP1.output [1] = (uint16) Op14Xrr; + DSP1.output [2] = (uint16) Op14Yrr; + break; + + default: + break; + } + } + else + DSP1.in_index++; + } + } + } + } +} diff --git a/src/DSP1_gp32.cpp b/src/DSP1_gp32.cpp deleted file mode 100644 index 7c89cbf..0000000 --- a/src/DSP1_gp32.cpp +++ /dev/null @@ -1,514 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include "snes9x.h" -#include "dsp1.h" -#include "missing.h" -#include "memmap.h" -#include - -#include "dsp1emu_gp32.c" - -void S9xInitDSP1 () -{ - static bool8 init = FALSE; - - if (!init) - { - InitDSP (); - init = TRUE; - } -} - -void S9xResetDSP1 () -{ - S9xInitDSP1 (); - - DSP1.waiting4command = TRUE; - DSP1.in_count = 0; - DSP1.out_count = 0; - DSP1.in_index = 0; - DSP1.out_index = 0; - DSP1.first_parameter = TRUE; -} - -uint8 S9xGetDSP (uint16 address) -{ - uint8 t; - - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { - if (DSP1.out_count) - { - if ((address & 1) == 0) - t = (uint8) DSP1.output [DSP1.out_index]; - else - { - t = (uint8) (DSP1.output [DSP1.out_index] >> 8); - DSP1.out_index++; - if (--DSP1.out_count == 0) - { - if (DSP1.command == 0x1a || DSP1.command == 0x0a) - { - DSPOp0A (); - DSP1.out_count = 4; - DSP1.out_index = 0; - DSP1.output [0] = Op0AA; - DSP1.output [1] = Op0AB; - DSP1.output [2] = Op0AC; - DSP1.output [3] = Op0AD; - } - } - DSP1.waiting4command = TRUE; - } - } - else - { - // Top Gear 3000 requires this value.... - t = 0xff; - } - } - else - t = 0x80; - - return (t); -} - -void S9xSetDSP (uint8 byte, uint16 address) -{ - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { - if ((address & 1) == 0) - { - if (DSP1.waiting4command) - { - DSP1.command = byte; - DSP1.in_index = 0; - DSP1.waiting4command = FALSE; - DSP1.first_parameter = TRUE; - - // Mario Kart uses 0x00, 0x02, 0x06, 0x0c, 0x28, 0x0a - switch (byte) - { - case 0x00: DSP1.in_count = 2; break; - case 0x10: DSP1.in_count = 2; break; - case 0x04: DSP1.in_count = 2; break; - case 0x08: DSP1.in_count = 3; break; - case 0x18: DSP1.in_count = 4; break; - case 0x28: DSP1.in_count = 3; break; - case 0x0c: DSP1.in_count = 3; break; - case 0x1c: DSP1.in_count = 6; break; - case 0x02: DSP1.in_count = 7; break; - case 0x0a: DSP1.in_count = 1; break; - case 0x1a: DSP1.in_count = 1; break; - case 0x06: DSP1.in_count = 3; break; - case 0x0e: DSP1.in_count = 2; break; - case 0x01: DSP1.in_count = 4; break; - case 0x11: DSP1.in_count = 4; break; - case 0x21: DSP1.in_count = 4; break; - case 0x0d: DSP1.in_count = 3; break; - case 0x1d: DSP1.in_count = 3; break; - case 0x2d: DSP1.in_count = 3; break; - case 0x03: DSP1.in_count = 3; break; - case 0x13: DSP1.in_count = 3; break; - case 0x23: DSP1.in_count = 3; break; - case 0x0b: DSP1.in_count = 3; break; - case 0x1b: DSP1.in_count = 3; break; - case 0x2b: DSP1.in_count = 3; break; - case 0x14: DSP1.in_count = 6; break; -// case 0x80: DSP1.in_count = 2; break; - - default: - case 0x80: - DSP1.in_count = 0; - DSP1.waiting4command = TRUE; - DSP1.first_parameter = TRUE; - break; - } - } - else - { - DSP1.parameters [DSP1.in_index] = byte; - DSP1.first_parameter = FALSE; - } - } - else - { - if (DSP1.waiting4command || - (DSP1.first_parameter && byte == 0x80)) - { - DSP1.waiting4command = TRUE; - DSP1.first_parameter = FALSE; - } - else - if (DSP1.first_parameter) - { - } - else - { - if (DSP1.in_count) - { - DSP1.parameters [DSP1.in_index] |= (byte << 8); - if (--DSP1.in_count == 0) - { - // Actually execute the command - DSP1.waiting4command = TRUE; - DSP1.out_index = 0; - switch (DSP1.command) - { - case 0x00: // Multiple - Op00Multiplicand = (int16) DSP1.parameters [0]; - Op00Multiplier = (int16) DSP1.parameters [1]; - - DSPOp00 (); - - DSP1.out_count = 1; - DSP1.output [0] = Op00Result; - break; - - case 0x10: // Inverse - Op10Coefficient = (int16) DSP1.parameters [0]; - Op10Exponent = (int16) DSP1.parameters [1]; - - DSPOp10 (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint16) (int16) Op10CoefficientR; - DSP1.output [1] = (uint16) (int16) Op10ExponentR; - break; - - case 0x04: // Sin and Cos of angle - Op04Angle = (int16) DSP1.parameters [0]; - Op04Radius = (uint16) DSP1.parameters [1]; - - DSPOp04 (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint16) Op04Sin; - DSP1.output [1] = (uint16) Op04Cos; - break; - - case 0x08: // Radius - Op08X = (int16) DSP1.parameters [0]; - Op08Y = (int16) DSP1.parameters [1]; - Op08Z = (int16) DSP1.parameters [2]; - - DSPOp08 (); - - DSP1.out_count = 2; - DSP1.output [0] = (int16) Op08Ll; - DSP1.output [1] = (int16) Op08Lh; - break; - - case 0x18: // Range - - Op18X = (int16) DSP1.parameters [0]; - Op18Y = (int16) DSP1.parameters [1]; - Op18Z = (int16) DSP1.parameters [2]; - Op18R = (int16) DSP1.parameters [3]; - - DSPOp18 (); - - DSP1.out_count = 1; - DSP1.output [0] = Op18D; - break; - - case 0x28: // Distance (vector length) - Op28X = (int16) DSP1.parameters [0]; - Op28Y = (int16) DSP1.parameters [1]; - Op28Z = (int16) DSP1.parameters [2]; - - DSPOp28 (); - - DSP1.out_count = 1; - DSP1.output [0] = (uint16) Op28R; - break; - - case 0x0c: // Rotate (2D rotate) - Op0CA = (int16) DSP1.parameters [0]; - Op0CX1 = (int16) DSP1.parameters [1]; - Op0CY1 = (int16) DSP1.parameters [2]; - - DSPOp0C (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint16) Op0CX2; - DSP1.output [1] = (uint16) Op0CY2; - break; - - case 0x1c: // Polar (3D rotate) - Op1CZ = DSP1.parameters [0]; - Op1CX = DSP1.parameters [1]; - Op1CY = DSP1.parameters [2]; - Op1CXBR = DSP1.parameters [3]; - Op1CYBR = DSP1.parameters [4]; - Op1CZBR = DSP1.parameters [5]; - - DSPOp1C (); - - DSP1.out_count = 3; - DSP1.output [0] = (uint16) Op1CXAR; - DSP1.output [1] = (uint16) Op1CYAR; - DSP1.output [2] = (uint16) Op1CZAR; - break; - - case 0x02: // Parameter (Projection) - Op02FX = DSP1.parameters [0]; - Op02FY = DSP1.parameters [1]; - Op02FZ = DSP1.parameters [2]; - Op02LFE = DSP1.parameters [3]; - Op02LES = DSP1.parameters [4]; - Op02AAS = DSP1.parameters [5]; - Op02AZS = DSP1.parameters [6]; - - DSPOp02 (); - - DSP1.out_count = 4; - DSP1.output [0] = Op02VOF; - DSP1.output [1] = Op02VVA; - DSP1.output [2] = Op02CX; - DSP1.output [3] = Op02CY; - break; - - case 0x1a: // Raster mode 7 matrix data - case 0x0a: - Op0AVS = DSP1.parameters [0]; - - DSPOp0A (); - - DSP1.out_count = 4; - DSP1.output [0] = Op0AA; - DSP1.output [1] = Op0AB; - DSP1.output [2] = Op0AC; - DSP1.output [3] = Op0AD; - break; - - case 0x06: // Project object - Op06X = (int16) DSP1.parameters [0]; - Op06Y = (int16) DSP1.parameters [1]; - Op06Z = (int16) DSP1.parameters [2]; - - DSPOp06 (); - - DSP1.out_count = 3; - DSP1.output [0] = Op06H; - DSP1.output [1] = Op06V; - DSP1.output [2] = Op06S; - break; - - case 0x0e: // Target - Op0EH = (int16) DSP1.parameters [0]; - Op0EV = (int16) DSP1.parameters [1]; - - DSPOp0E (); - - DSP1.out_count = 2; - DSP1.output [0] = Op0EX; - DSP1.output [1] = Op0EY; - break; - - // Extra commands used by Pilot Wings - case 0x01: // Set attitude matrix A - Op01m = (int16) DSP1.parameters [0]; - Op01Zr = (int16) DSP1.parameters [1]; - Op01Xr = (int16) DSP1.parameters [2]; - Op01Yr = (int16) DSP1.parameters [3]; - - DSPOp01 (); - break; - - case 0x11: // Set attitude matrix B - Op11m = (int16) DSP1.parameters [0]; - Op11Zr = (int16) DSP1.parameters [1]; - Op11Xr = (int16) DSP1.parameters [2]; - Op11Yr = (int16) DSP1.parameters [3]; - - DSPOp11 (); - break; - - case 0x21: // Set attitude matrix C - Op21m = (int16) DSP1.parameters [0]; - Op21Zr = (int16) DSP1.parameters [1]; - Op21Xr = (int16) DSP1.parameters [2]; - Op21Yr = (int16) DSP1.parameters [3]; - - DSPOp21 (); - break; - - case 0x0d: // Objective matrix A - Op0DX = (int16) DSP1.parameters [0]; - Op0DY = (int16) DSP1.parameters [1]; - Op0DZ = (int16) DSP1.parameters [2]; - - DSPOp0D (); - - DSP1.out_count = 3; - DSP1.output [0] = (uint16) Op0DF; - DSP1.output [1] = (uint16) Op0DL; - DSP1.output [2] = (uint16) Op0DU; - break; - - case 0x1d: // Objective matrix B - Op1DX = (int16) DSP1.parameters [0]; - Op1DY = (int16) DSP1.parameters [1]; - Op1DZ = (int16) DSP1.parameters [2]; - - DSPOp1D (); - - DSP1.out_count = 3; - DSP1.output [0] = (uint16) Op1DF; - DSP1.output [1] = (uint16) Op1DL; - DSP1.output [2] = (uint16) Op1DU; - break; - - case 0x2d: // Objective matrix C - Op2DX = (int16) DSP1.parameters [0]; - Op2DY = (int16) DSP1.parameters [1]; - Op2DZ = (int16) DSP1.parameters [2]; - - DSPOp2D (); - - DSP1.out_count = 3; - DSP1.output [0] = (uint16) Op2DF; - DSP1.output [1] = (uint16) Op2DL; - DSP1.output [2] = (uint16) Op2DU; - break; - - case 0x03: // Subjective matrix A - Op03F = (int16) DSP1.parameters [0]; - Op03L = (int16) DSP1.parameters [1]; - Op03U = (int16) DSP1.parameters [2]; - - DSPOp03 (); - - DSP1.out_count = 3; - DSP1.output [0] = (uint16) Op03X; - DSP1.output [1] = (uint16) Op03Y; - DSP1.output [2] = (uint16) Op03Z; - break; - - case 0x13: // Subjective matrix B - Op13F = (int16) DSP1.parameters [0]; - Op13L = (int16) DSP1.parameters [1]; - Op13U = (int16) DSP1.parameters [2]; - - DSPOp13 (); - - DSP1.out_count = 3; - DSP1.output [0] = (uint16) Op13X; - DSP1.output [1] = (uint16) Op13Y; - DSP1.output [2] = (uint16) Op13Z; - break; - - case 0x23: // Subjective matrix C - Op23F = (int16) DSP1.parameters [0]; - Op23L = (int16) DSP1.parameters [1]; - Op23U = (int16) DSP1.parameters [2]; - - DSPOp23 (); - - DSP1.out_count = 3; - DSP1.output [0] = (uint16) Op23X; - DSP1.output [1] = (uint16) Op23Y; - DSP1.output [2] = (uint16) Op23Z; - break; - - case 0x0b: - Op0BX = (int16) DSP1.parameters [0]; - Op0BY = (int16) DSP1.parameters [1]; - Op0BZ = (int16) DSP1.parameters [2]; - - DSPOp0B (); - - DSP1.out_count = 1; - DSP1.output [0] = (uint16) Op0BS; - break; - - case 0x1b: - Op1BX = (int16) DSP1.parameters [0]; - Op1BY = (int16) DSP1.parameters [1]; - Op1BZ = (int16) DSP1.parameters [2]; - - DSPOp1B (); - - DSP1.out_count = 1; - DSP1.output [0] = (uint16) Op1BS; - break; - - case 0x2b: - Op2BX = (int16) DSP1.parameters [0]; - Op2BY = (int16) DSP1.parameters [1]; - Op2BZ = (int16) DSP1.parameters [2]; - - DSPOp0B (); - - DSP1.out_count = 1; - DSP1.output [0] = (uint16) Op2BS; - break; - - case 0x14: // Gyrate - Op14Zr = (int16) DSP1.parameters [0]; - Op14Xr = (int16) DSP1.parameters [1]; - Op14Yr = (int16) DSP1.parameters [2]; - Op14U = (int16) DSP1.parameters [3]; - Op14F = (int16) DSP1.parameters [4]; - Op14L = (int16) DSP1.parameters [5]; - - DSPOp14 (); - - DSP1.out_count = 3; - DSP1.output [0] = (uint16) Op14Zrr; - DSP1.output [1] = (uint16) Op14Xrr; - DSP1.output [2] = (uint16) Op14Yrr; - break; - - default: - break; - } - } - else - DSP1.in_index++; - } - } - } - } -} diff --git a/src/apu.c b/src/apu.c new file mode 100644 index 0000000..a75a001 --- /dev/null +++ b/src/apu.c @@ -0,0 +1,1005 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +#include "snes9x.h" +#include "spc700.h" +#include "apu.h" +#include "soundux.h" +#include "cpuexec.h" + +/* For note-triggered SPC dump support */ +//#include "snapshot.h" + +//extern int NoiseFreq [32]; + +#undef ABS +#define ABS(a) ((a) < 0 ? -(a) : (a)) +#define ENVX_SHIFT 24 + + +unsigned long AttackRate [16] = { + 4100, 2600, 1500, 1000, 640, 380, 260, 160, + 96, 64, 40, 24, 16, 10, 6, 1 +}; + +unsigned long DecayRate [8] = { + 1200, 740, 440, 290, 180, 110, 74, 37 +}; + +unsigned long SustainRate [32] = { + /*~0*/0xFFFFFFFF, 38000, 28000, 24000, 19000, 14000, 12000, 9400, + 7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500, + 1200, 880, 740, 590, 440, 370, 290, 220, + 180, 150, 110, 92, 74, 55, 37, 18 +}; + +unsigned long IncreaseRate [32] = { + /*~0*/0xFFFFFFFF, 4100, 3100, 2600, 2000, 1500, 1300, 1000, + 770, 640, 510, 380, 320, 260, 190, 160, + 130, 96, 80, 64, 48, 40, 32, 24, + 20, 16, 12, 10, 8, 6, 4, 2 +}; + +unsigned long DecreaseRateExp [32] = { + /*~0*/0xFFFFFFFF, 38000, 28000, 24000, 19000, 14000, 12000, 9400, + 7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500, + 1200, 880, 740, 590, 440, 370, 290, 220, + 180, 150, 110, 92, 74, 55, 37, 18 +}; + +// precalculated env rates for S9xSetEnvRate +unsigned long AttackERate [16][10]; +unsigned long DecayERate [8][10]; +unsigned long SustainERate [32][10]; +unsigned long IncreaseERate [32][10]; +unsigned long DecreaseERateExp[32][10]; +unsigned long KeyOffERate[10]; + + +static inline void S9xSetEnvelopeRate (int channel, unsigned long rate, int direction, int target, unsigned int mode) +{ + S9xSetEnvRate (&SoundData.channels [channel], rate, direction, target, mode); +} + +static inline void S9xSetSoundADSR (int channel, int attack_ind, int decay_ind, + int sustain_ind, int sustain_level, int release_rate) +{ + int attack_rate = AttackRate [attack_ind]; + int decay_rate = DecayRate [decay_ind]; + int sustain_rate = SustainRate [sustain_ind]; + + // Hack for ROMs that use a very short attack rate, key on a + // channel, then switch to decay mode. e.g. Final Fantasy II. + if (attack_rate == 1) + attack_rate = 0; + + SoundData.channels[channel].env_ind_attack = attack_ind; + SoundData.channels[channel].env_ind_decay = decay_ind; + SoundData.channels[channel].env_ind_sustain = sustain_ind; + + SoundData.channels[channel].attack_rate = attack_rate; + SoundData.channels[channel].decay_rate = decay_rate; + SoundData.channels[channel].sustain_rate = sustain_rate; + SoundData.channels[channel].release_rate = release_rate; + SoundData.channels[channel].sustain_level = sustain_level + 1; + + switch (SoundData.channels[channel].state) + { + case SOUND_ATTACK: + S9xSetEnvelopeRate (channel, attack_rate, 1, 127, 0); + break; + + case SOUND_DECAY: + S9xSetEnvelopeRate (channel, decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3, 1<<28); + break; + case SOUND_SUSTAIN: + S9xSetEnvelopeRate (channel, sustain_rate, -1, 0, 2<<28); + break; + } +} + +static inline void S9xSetSoundVolume (int channel, short volume_left, short volume_right) +{ + Channel *ch = &SoundData.channels[channel]; + if (!so.stereo) + volume_left = (ABS(volume_right) + ABS(volume_left)) / 2; + + ch->volume_left = volume_left; + ch->volume_right = volume_right; + ch-> left_vol_level = (ch->envx * volume_left) / 128; + ch->right_vol_level = (ch->envx * volume_right) / 128; +} + +static inline void S9xSetMasterVolume (short volume_left, short volume_right) +{ + if (Settings.DisableMasterVolume) + { + SoundData.master_volume_left = 127; + SoundData.master_volume_right = 127; + SoundData.master_volume [0] = SoundData.master_volume [1] = 127; + } + else + { + if (!so.stereo) + volume_left = (ABS (volume_right) + ABS (volume_left)) / 2; + SoundData.master_volume_left = volume_left; + SoundData.master_volume_right = volume_right; + SoundData.master_volume [0] = volume_left; + SoundData.master_volume [1] = volume_right; + } +} + +static inline void S9xSetEchoVolume (short volume_left, short volume_right) +{ + if (!so.stereo) + volume_left = (ABS (volume_right) + ABS (volume_left)) / 2; + SoundData.echo_volume_left = volume_left; + SoundData.echo_volume_right = volume_right; + SoundData.echo_volume [0] = volume_left; + SoundData.echo_volume [1] = volume_right; +} + +static inline void S9xSetEchoWriteEnable (uint8 byte) +{ + SoundData.echo_write_enabled = byte; + S9xSetEchoDelay (APU.DSP [APU_EDL] & 15); +} + +static inline void S9xSetFrequencyModulationEnable (uint8 byte) +{ + SoundData.pitch_mod = byte & (0xFE);//~1; +} + +static inline int S9xGetEnvelopeHeight (int channel) +{ + if ((Settings.SoundEnvelopeHeightReading || + SNESGameFixes.SoundEnvelopeHeightReading2) && + SoundData.channels[channel].state != SOUND_SILENT && + SoundData.channels[channel].state != SOUND_GAIN) + { + return (SoundData.channels[channel].envx); + } + + //siren fix from XPP + if (SNESGameFixes.SoundEnvelopeHeightReading2 && + SoundData.channels[channel].state != SOUND_SILENT) + { + return (SoundData.channels[channel].envx); + } + + return (0); +} + +static inline void S9xSetSoundHertz (int channel, int hertz) +{ + SoundData.channels[channel].hertz = hertz; + S9xSetSoundFrequency (channel, hertz); +} + +static inline void S9xSetSoundType (int channel, int type_of_sound) +{ + SoundData.channels[channel].type = type_of_sound; +} + +static inline bool8 S9xSetSoundMode (int channel, int mode) +{ + Channel *ch = &SoundData.channels[channel]; + + switch (mode) + { + case MODE_RELEASE: + if (ch->mode != MODE_NONE) + { + ch->mode = MODE_RELEASE; + return (TRUE); + } + break; + + case MODE_DECREASE_LINEAR: + case MODE_DECREASE_EXPONENTIAL: + case MODE_GAIN: + if (ch->mode != MODE_RELEASE) + { + ch->mode = mode; + if (ch->state != SOUND_SILENT) + ch->state = mode; + + return (TRUE); + } + break; + + case MODE_INCREASE_LINEAR: + case MODE_INCREASE_BENT_LINE: + if (ch->mode != MODE_RELEASE) + { + ch->mode = mode; + if (ch->state != SOUND_SILENT) + ch->state = mode; + + + + + return (TRUE); + } + break; + + case MODE_ADSR: + if (ch->mode == MODE_NONE || ch->mode == MODE_ADSR) + { + ch->mode = mode; + return (TRUE); + } + } + + return (FALSE); +} + +static inline void S9xPlaySample (int channel) +{ + Channel *ch = &SoundData.channels[channel]; + + ch->state = SOUND_SILENT; + ch->mode = MODE_NONE; + ch->envx = 0; + ch->envxx = 0; + + ch->g_index=0; + ch->gaussian[0]=ch->gaussian[1]=ch->gaussian[2]=ch->gaussian[3]=0; + + S9xFixEnvelope (channel, + APU.DSP [APU_GAIN + (channel << 4)], + APU.DSP [APU_ADSR1 + (channel << 4)], + APU.DSP [APU_ADSR2 + (channel << 4)]); + + ch->sample_number = APU.DSP [APU_SRCN + channel * 0x10]; + if (APU.DSP [APU_NON] & (1 << channel)) + ch->type = SOUND_NOISE; + else + ch->type = SOUND_SAMPLE; + + S9xSetSoundFrequency (channel, ch->hertz); + ch->loop = FALSE; + ch->needs_decode = TRUE; + ch->last_block = FALSE; + ch->previous [0] = ch->previous[1] = 0; + ch->block_pointer = *S9xGetSampleAddress(ch->sample_number); + ch->sample_pointer = 0; + ch->env_error = 0; + ch->next_sample = 0; + ch->interpolate = 0; + ch->last_valid_header=0; + switch (ch->mode) + { + case MODE_ADSR: + if (ch->attack_rate == 0) + { + if (ch->decay_rate == 0 || ch->sustain_level == 8) + { + ch->state = SOUND_SUSTAIN; + ch->envx = (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3; + S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28); + } + else + { + ch->state = SOUND_DECAY; + ch->envx = MAX_ENVELOPE_HEIGHT; + S9xSetEnvRate (ch, ch->decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28); + } + ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; + ch->right_vol_level = (ch->envx * ch->volume_right) / 128; + } + else + { + ch->state = SOUND_ATTACK; + ch->envx = 0; + ch->left_vol_level = 0; + ch->right_vol_level = 0; + S9xSetEnvRate (ch, ch->attack_rate, 1, MAX_ENVELOPE_HEIGHT, 0); + } + ch->envxx = ch->envx << ENVX_SHIFT; + break; + + case MODE_GAIN: + ch->state = SOUND_GAIN; + break; + + case MODE_INCREASE_LINEAR: + ch->state = SOUND_INCREASE_LINEAR; + break; + + case MODE_INCREASE_BENT_LINE: + ch->state = SOUND_INCREASE_BENT_LINE; + break; + + case MODE_DECREASE_LINEAR: + ch->state = SOUND_DECREASE_LINEAR; + break; + + case MODE_DECREASE_EXPONENTIAL: + ch->state = SOUND_DECREASE_EXPONENTIAL; + break; + + default: + break; + } + + S9xFixEnvelope (channel, + APU.DSP [APU_GAIN + (channel << 4)], + APU.DSP [APU_ADSR1 + (channel << 4)], + APU.DSP [APU_ADSR2 + (channel << 4)]); +} + +uint32 Spc700JumpTab_15; + +bool8 S9xInitAPU () +{ + // notaz + memset(&IAPU, 0, sizeof(IAPU)); + IAPU.ExtraRAM = APU.ExtraRAM; + IAPU.asmJumpTab = &Spc700JumpTab_15; // Normal case: ONE_APU_CYCLE = 15 + + IAPU.RAM = (uint8 *) malloc (0x10000); + IAPU.ShadowRAM = NULL;//(uint8 *) malloc (0x10000); + IAPU.CachedSamples = NULL;//(uint8 *) malloc (0x40000); + + if (!IAPU.RAM /*|| !IAPU.ShadowRAM || !IAPU.CachedSamples*/) + { + S9xDeinitAPU (); + return (FALSE); + } + + return (TRUE); +} + +void S9xDeinitAPU () +{ + if (IAPU.RAM) + { + free ((char *) IAPU.RAM); + IAPU.RAM = NULL; + } + if (IAPU.ShadowRAM) + { + free ((char *) IAPU.ShadowRAM); + IAPU.ShadowRAM = NULL; + } + if (IAPU.CachedSamples) + { + free ((char *) IAPU.CachedSamples); + IAPU.CachedSamples = NULL; + } +} + +EXTERN_C uint8 APUROM [64]; + +void S9xResetAPU () +{ + int i, j; +// Settings.APUEnabled = Settings.NextAPUEnabled; + + ZeroMemory(IAPU.RAM, 0x100); + memset(IAPU.RAM+0x20, 0xFF, 0x20); + memset(IAPU.RAM+0x60, 0xFF, 0x20); + memset(IAPU.RAM+0xA0, 0xFF, 0x20); + memset(IAPU.RAM+0xE0, 0xFF, 0x20); + + + for(i=1;i<256;i++) + { + memcpy(IAPU.RAM+(i<<8), IAPU.RAM, 0x100); + } + //ZeroMemory (IAPU.CachedSamples, 0x40000); + ZeroMemory (APU.OutPorts, 4); + IAPU.DirectPage = IAPU.RAM; + memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); + memmove (APU.ExtraRAM, APUROM, sizeof (APUROM)); + IAPU.PC = IAPU.RAM + IAPU.RAM [0xfffe] + (IAPU.RAM [0xffff] << 8); + CPU.APU_Cycles = 0; + IAPU.YA.W = 0; + IAPU.X = 0; + IAPU.S = 0xff; + IAPU.P = 0; + S9xAPUUnpackStatus (); + CPU.APU_APUExecuting = Settings.APUEnabled; +#ifdef SPC700_SHUTDOWN + IAPU.WaitAddress1 = NULL; + IAPU.WaitAddress2 = NULL; + IAPU.WaitCounter = 0; +#endif + APU.ShowROM = TRUE; + IAPU.RAM [0xf1] = 0x80; + + for (i = 0; i < 3; i++) + { + APU.TimerEnabled [i] = FALSE; + APU.TimerValueWritten [i] = 0; + APU.TimerTarget [i] = 0; + APU.Timer [i] = 0; + } + for (j = 0; j < 0x80; j++) + APU.DSP [j] = 0; + + IAPU.TwoCycles = IAPU.OneCycle * 2; + + for (i = 0; i < 256; i++) + S9xAPUCycles [i] = S9xAPUCycleLengths [i] * IAPU.OneCycle; + + APU.DSP [APU_ENDX] = 0; + APU.DSP [APU_KOFF] = 0; + APU.DSP [APU_KON] = 0; + APU.DSP [APU_FLG] = APU_MUTE | APU_ECHO_DISABLED; + APU.KeyedChannels = 0; + + S9xResetSound (TRUE); + S9xSetEchoEnable (0); +} + +extern int framecpto; +void S9xSetAPUDSP (uint8 byte) +{ + uint8 reg = IAPU.RAM [0xf2]; + static uint8 KeyOn; + static uint8 KeyOnPrev; + int i; + +/* char str[64]; + if (byte!=0) + { + sprintf(str,"fr : %d\nwrite dsp %d\ncpu cycle=%d pc=%04X",framecpto,byte,CPU.Cycles,CPU.PC-CPU.PCBase); + S9xMessage(0,0,str); + gp32_pause(); + }*/ + + //extern uint8 spc_dump_dsp[0x100]; + + //spc_dump_dsp[reg] = byte; + + switch (reg) + { + case APU_FLG: + if (byte & APU_SOFT_RESET) + { + APU.DSP [reg] = APU_MUTE | APU_ECHO_DISABLED | (byte & 0x1f); + APU.DSP [APU_ENDX] = 0; + APU.DSP [APU_KOFF] = 0; + APU.DSP [APU_KON] = 0; + S9xSetEchoWriteEnable (FALSE); + // Kill sound + S9xResetSound (FALSE); + } + else + { + S9xSetEchoWriteEnable (!(byte & APU_ECHO_DISABLED)); + if (byte & APU_MUTE) + { + S9xSetSoundMute (TRUE); + } + else + S9xSetSoundMute (FALSE); + + SoundData.noise_hertz = NoiseFreq [byte & 0x1f]; + for (i = 0; i < 8; i++) + { + if (SoundData.channels [i].type == SOUND_NOISE) + S9xSetSoundFrequency (i, SoundData.noise_hertz); + } + } + break; + case APU_NON: + if (byte != APU.DSP [APU_NON]) + { + int c; + uint8 mask = 1; + for (c = 0; c < 8; c++, mask <<= 1) + { + int type; + if (byte & mask) + { + type = SOUND_NOISE; + } + else + { + type = SOUND_SAMPLE; + } + S9xSetSoundType (c, type); + } + } + break; + case APU_MVOL_LEFT: + if (byte != APU.DSP [APU_MVOL_LEFT]) + { + S9xSetMasterVolume ((signed char) byte, + (signed char) APU.DSP [APU_MVOL_RIGHT]); + } + break; + case APU_MVOL_RIGHT: + if (byte != APU.DSP [APU_MVOL_RIGHT]) + { + S9xSetMasterVolume ((signed char) APU.DSP [APU_MVOL_LEFT], + (signed char) byte); + } + break; + case APU_EVOL_LEFT: + if (byte != APU.DSP [APU_EVOL_LEFT]) + { + S9xSetEchoVolume ((signed char) byte, + (signed char) APU.DSP [APU_EVOL_RIGHT]); + } + break; + case APU_EVOL_RIGHT: + if (byte != APU.DSP [APU_EVOL_RIGHT]) + { + S9xSetEchoVolume ((signed char) APU.DSP [APU_EVOL_LEFT], + (signed char) byte); + } + break; + case APU_ENDX: + byte = 0; + break; + + case APU_KOFF: + // if (byte) + { + int c; + uint8 mask = 1; + for (c = 0; c < 8; c++, mask <<= 1) + { + if ((byte & mask) != 0) + { + if (APU.KeyedChannels & mask) + { + { + KeyOnPrev&=~mask; + APU.KeyedChannels &= ~mask; + APU.DSP [APU_KON] &= ~mask; + //APU.DSP [APU_KOFF] |= mask; + S9xSetSoundKeyOff (c); + } + } + } + else if((KeyOnPrev&mask)!=0) + { + KeyOnPrev&=~mask; + APU.KeyedChannels |= mask; + //APU.DSP [APU_KON] |= mask; + APU.DSP [APU_KOFF] &= ~mask; + APU.DSP [APU_ENDX] &= ~mask; + S9xPlaySample (c); + } + } + } + //KeyOnPrev=0; + APU.DSP [APU_KOFF] = byte; + return; + case APU_KON: + + if (byte) + { + int c; + uint8 mask = 1; + for (c = 0; c < 8; c++, mask <<= 1) + { + if ((byte & mask) != 0) + { + // Pac-In-Time requires that channels can be key-on + // regardeless of their current state. + if((APU.DSP [APU_KOFF] & mask) ==0) + { + KeyOnPrev&=~mask; + APU.KeyedChannels |= mask; + //APU.DSP [APU_KON] |= mask; + //APU.DSP [APU_KOFF] &= ~mask; + APU.DSP [APU_ENDX] &= ~mask; + S9xPlaySample (c); + } + else KeyOn|=mask; + } + } + } + //spc_is_dumping_temp = byte; + return; + + case APU_VOL_LEFT + 0x00: + case APU_VOL_LEFT + 0x10: + case APU_VOL_LEFT + 0x20: + case APU_VOL_LEFT + 0x30: + case APU_VOL_LEFT + 0x40: + case APU_VOL_LEFT + 0x50: + case APU_VOL_LEFT + 0x60: + case APU_VOL_LEFT + 0x70: +// At Shin Megami Tensei suggestion 6/11/00 +// if (byte != APU.DSP [reg]) + { + S9xSetSoundVolume (reg >> 4, (signed char) byte, + (signed char) APU.DSP [reg + 1]); + } + break; + case APU_VOL_RIGHT + 0x00: + case APU_VOL_RIGHT + 0x10: + case APU_VOL_RIGHT + 0x20: + case APU_VOL_RIGHT + 0x30: + case APU_VOL_RIGHT + 0x40: + case APU_VOL_RIGHT + 0x50: + case APU_VOL_RIGHT + 0x60: + case APU_VOL_RIGHT + 0x70: +// At Shin Megami Tensei suggestion 6/11/00 +// if (byte != APU.DSP [reg]) + { + S9xSetSoundVolume (reg >> 4, (signed char) APU.DSP [reg - 1], + (signed char) byte); + } + break; + + case APU_P_LOW + 0x00: + case APU_P_LOW + 0x10: + case APU_P_LOW + 0x20: + case APU_P_LOW + 0x30: + case APU_P_LOW + 0x40: + case APU_P_LOW + 0x50: + case APU_P_LOW + 0x60: + case APU_P_LOW + 0x70: + S9xSetSoundHertz (reg >> 4, (((byte + (APU.DSP [reg + 1] << 8)) & FREQUENCY_MASK) * 32000) >> 12); + break; + + case APU_P_HIGH + 0x00: + case APU_P_HIGH + 0x10: + case APU_P_HIGH + 0x20: + case APU_P_HIGH + 0x30: + case APU_P_HIGH + 0x40: + case APU_P_HIGH + 0x50: + case APU_P_HIGH + 0x60: + case APU_P_HIGH + 0x70: + S9xSetSoundHertz (reg >> 4, + (((byte << 8) + APU.DSP [reg - 1]) & FREQUENCY_MASK) * 8); + break; + + case APU_SRCN + 0x00: + case APU_SRCN + 0x10: + case APU_SRCN + 0x20: + case APU_SRCN + 0x30: + case APU_SRCN + 0x40: + case APU_SRCN + 0x50: + case APU_SRCN + 0x60: + case APU_SRCN + 0x70: + if (byte != APU.DSP [reg]) + { + //S9xSetSoundSample (reg >> 4, byte); // notaz: seems to be unused? + } + break; + + case APU_ADSR1 + 0x00: + case APU_ADSR1 + 0x10: + case APU_ADSR1 + 0x20: + case APU_ADSR1 + 0x30: + case APU_ADSR1 + 0x40: + case APU_ADSR1 + 0x50: + case APU_ADSR1 + 0x60: + case APU_ADSR1 + 0x70: + if (byte != APU.DSP [reg]) + { + { + S9xFixEnvelope (reg >> 4, APU.DSP [reg + 2], byte, + APU.DSP [reg + 1]); + } + } + break; + + case APU_ADSR2 + 0x00: + case APU_ADSR2 + 0x10: + case APU_ADSR2 + 0x20: + case APU_ADSR2 + 0x30: + case APU_ADSR2 + 0x40: + case APU_ADSR2 + 0x50: + case APU_ADSR2 + 0x60: + case APU_ADSR2 + 0x70: + if (byte != APU.DSP [reg]) + { + { + S9xFixEnvelope (reg >> 4, APU.DSP [reg + 1], APU.DSP [reg - 1], + byte); + } + } + break; + + case APU_GAIN + 0x00: + case APU_GAIN + 0x10: + case APU_GAIN + 0x20: + case APU_GAIN + 0x30: + case APU_GAIN + 0x40: + case APU_GAIN + 0x50: + case APU_GAIN + 0x60: + case APU_GAIN + 0x70: + if (byte != APU.DSP [reg]) + { + { + S9xFixEnvelope (reg >> 4, byte, APU.DSP [reg - 2], + APU.DSP [reg - 1]); + } + } + break; + + case APU_ENVX + 0x00: + case APU_ENVX + 0x10: + case APU_ENVX + 0x20: + case APU_ENVX + 0x30: + case APU_ENVX + 0x40: + case APU_ENVX + 0x50: + case APU_ENVX + 0x60: + case APU_ENVX + 0x70: + break; + + case APU_OUTX + 0x00: + case APU_OUTX + 0x10: + case APU_OUTX + 0x20: + case APU_OUTX + 0x30: + case APU_OUTX + 0x40: + case APU_OUTX + 0x50: + case APU_OUTX + 0x60: + case APU_OUTX + 0x70: + break; + + case APU_DIR: + break; + + case APU_PMON: + if (byte != APU.DSP [APU_PMON]) + { + S9xSetFrequencyModulationEnable (byte); + } + break; + + case APU_EON: + if (byte != APU.DSP [APU_EON]) + { + S9xSetEchoEnable (byte); + } + break; + + case APU_EFB: + S9xSetEchoFeedback ((signed char) byte); + break; + + case APU_ESA: + break; + + case APU_EDL: + S9xSetEchoDelay (byte & 0xf); + break; + + case APU_C0: + case APU_C1: + case APU_C2: + case APU_C3: + case APU_C4: + case APU_C5: + case APU_C6: + case APU_C7: + S9xSetFilterCoefficient (reg >> 4, (signed char) byte); + break; + default: +// XXX +//printf ("Write %02x to unknown APU register %02x\n", byte, reg); + break; + } + + KeyOnPrev|=KeyOn; + KeyOn=0; + + if (reg < 0x80) + APU.DSP [reg] = byte; +} + +void S9xFixEnvelope (int channel, uint8 gain, uint8 adsr1, uint8 adsr2) +{ + if (adsr1 & 0x80) + { + // ADSR mode + + // XXX: can DSP be switched to ADSR mode directly from GAIN/INCREASE/ + // DECREASE mode? And if so, what stage of the sequence does it start + // at? + if (S9xSetSoundMode (channel, MODE_ADSR)) + { + S9xSetSoundADSR (channel, adsr1 & 0xf, (adsr1 >> 4) & 7, adsr2 & 0x1f, (adsr2 >> 5) & 7, 8); + } + } + else + { + // Gain mode + if ((gain & 0x80) == 0) + { + if (S9xSetSoundMode (channel, MODE_GAIN)) + { + S9xSetEnvelopeRate (channel, 0, 0, gain & 0x7f, 0); + S9xSetEnvelopeHeight (channel, gain & 0x7f); + } + } + else + { + + if (gain & 0x40) + { + // Increase mode + if (S9xSetSoundMode (channel, (gain & 0x20) ? + MODE_INCREASE_BENT_LINE : + MODE_INCREASE_LINEAR)) + { + S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f], 1, 127, (3<<28)|gain); + } + } + else + { + if(gain & 0x20) { + if (S9xSetSoundMode (channel, MODE_DECREASE_EXPONENTIAL)) + S9xSetEnvelopeRate (channel, DecreaseRateExp [gain & 0x1f] / 2, -1, 0, (4<<28)|gain); + } else { + if (S9xSetSoundMode (channel, MODE_DECREASE_LINEAR)) + S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f], -1, 0, (3<<28)|gain); + } + } + } + } +} + +void S9xSetAPUControl (uint8 byte) +{ +//if (byte & 0x40) +//printf ("*** Special SPC700 timing enabled\n"); + if ((byte & 1) != 0 && !APU.TimerEnabled [0]) + { + APU.Timer [0] = 0; + IAPU.RAM [0xfd] = 0; + if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0) + APU.TimerTarget [0] = 0x100; + } + if ((byte & 2) != 0 && !APU.TimerEnabled [1]) + { + APU.Timer [1] = 0; + IAPU.RAM [0xfe] = 0; + if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0) + APU.TimerTarget [1] = 0x100; + } + if ((byte & 4) != 0 && !APU.TimerEnabled [2]) + { + APU.Timer [2] = 0; + IAPU.RAM [0xff] = 0; + if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0) + APU.TimerTarget [2] = 0x100; + } + APU.TimerEnabled [0] = byte & 1; + APU.TimerEnabled [1] = (byte & 2) >> 1; + APU.TimerEnabled [2] = (byte & 4) >> 2; + + if (byte & 0x10) + IAPU.RAM [0xF4] = IAPU.RAM [0xF5] = 0; + + if (byte & 0x20) + IAPU.RAM [0xF6] = IAPU.RAM [0xF7] = 0; + + if (byte & 0x80) + { + if (!APU.ShowROM) + { + memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); + APU.ShowROM = TRUE; + } + } + else + { + if (APU.ShowROM) + { + APU.ShowROM = FALSE; + memmove (&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof (APUROM)); + } + } + IAPU.RAM [0xf1] = byte; +} + +void S9xSetAPUTimer (uint16 Address, uint8 byte) +{ + IAPU.RAM [Address] = byte; + + switch (Address) + { + case 0xfa: + if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0) + APU.TimerTarget [0] = 0x100; + APU.TimerValueWritten [0] = TRUE; + break; + case 0xfb: + if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0) + APU.TimerTarget [1] = 0x100; + APU.TimerValueWritten [1] = TRUE; + break; + case 0xfc: + if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0) + APU.TimerTarget [2] = 0x100; + APU.TimerValueWritten [2] = TRUE; + break; + } +} + +uint8 S9xGetAPUDSP () +{ + uint8 reg = IAPU.RAM [0xf2] & 0x7f; + uint8 byte = APU.DSP [reg]; + + switch (reg) + { + case APU_KON: + break; + case APU_KOFF: + break; + case APU_OUTX + 0x00: + case APU_OUTX + 0x10: + case APU_OUTX + 0x20: + case APU_OUTX + 0x30: + case APU_OUTX + 0x40: + case APU_OUTX + 0x50: + case APU_OUTX + 0x60: + case APU_OUTX + 0x70: + if (SoundData.channels [reg >> 4].state == SOUND_SILENT) + return (0); + return ((SoundData.channels [reg >> 4].sample >> 8) | + (SoundData.channels [reg >> 4].sample & 0xff)); + + case APU_ENVX + 0x00: + case APU_ENVX + 0x10: + case APU_ENVX + 0x20: + case APU_ENVX + 0x30: + case APU_ENVX + 0x40: + case APU_ENVX + 0x50: + case APU_ENVX + 0x60: + case APU_ENVX + 0x70: + return 0; +// return ((uint8) S9xGetEnvelopeHeight (reg >> 4)); + + case APU_ENDX: +// To fix speech in Magical Drop 2 6/11/00 +// APU.DSP [APU_ENDX] = 0; + break; + default: + break; + } + return (byte); +} diff --git a/src/apu.cpp b/src/apu.cpp deleted file mode 100644 index 48ee2d8..0000000 --- a/src/apu.cpp +++ /dev/null @@ -1,1002 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -#include "snes9x.h" -#include "spc700.h" -#include "apu.h" -#include "soundux.h" -#include "cpuexec.h" - -/* For note-triggered SPC dump support */ -//#include "snapshot.h" - -//extern int NoiseFreq [32]; - -#undef ABS -#define ABS(a) ((a) < 0 ? -(a) : (a)) -#define ENVX_SHIFT 24 - - -unsigned long AttackRate [16] = { - 4100, 2600, 1500, 1000, 640, 380, 260, 160, - 96, 64, 40, 24, 16, 10, 6, 1 -}; - -unsigned long DecayRate [8] = { - 1200, 740, 440, 290, 180, 110, 74, 37 -}; - -unsigned long SustainRate [32] = { - /*~0*/0xFFFFFFFF, 38000, 28000, 24000, 19000, 14000, 12000, 9400, - 7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500, - 1200, 880, 740, 590, 440, 370, 290, 220, - 180, 150, 110, 92, 74, 55, 37, 18 -}; - -unsigned long IncreaseRate [32] = { - /*~0*/0xFFFFFFFF, 4100, 3100, 2600, 2000, 1500, 1300, 1000, - 770, 640, 510, 380, 320, 260, 190, 160, - 130, 96, 80, 64, 48, 40, 32, 24, - 20, 16, 12, 10, 8, 6, 4, 2 -}; - -unsigned long DecreaseRateExp [32] = { - /*~0*/0xFFFFFFFF, 38000, 28000, 24000, 19000, 14000, 12000, 9400, - 7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500, - 1200, 880, 740, 590, 440, 370, 290, 220, - 180, 150, 110, 92, 74, 55, 37, 18 -}; - -// precalculated env rates for S9xSetEnvRate -unsigned long AttackERate [16][10]; -unsigned long DecayERate [8][10]; -unsigned long SustainERate [32][10]; -unsigned long IncreaseERate [32][10]; -unsigned long DecreaseERateExp[32][10]; -unsigned long KeyOffERate[10]; - - -static inline void S9xSetEnvelopeRate (int channel, unsigned long rate, int direction, int target, unsigned int mode) -{ - S9xSetEnvRate (&SoundData.channels [channel], rate, direction, target, mode); -} - -static inline void S9xSetSoundADSR (int channel, int attack_ind, int decay_ind, - int sustain_ind, int sustain_level, int release_rate) -{ - int attack_rate = AttackRate [attack_ind]; - int decay_rate = DecayRate [decay_ind]; - int sustain_rate = SustainRate [sustain_ind]; - - // Hack for ROMs that use a very short attack rate, key on a - // channel, then switch to decay mode. e.g. Final Fantasy II. - if (attack_rate == 1) - attack_rate = 0; - - SoundData.channels[channel].env_ind_attack = attack_ind; - SoundData.channels[channel].env_ind_decay = decay_ind; - SoundData.channels[channel].env_ind_sustain = sustain_ind; - - SoundData.channels[channel].attack_rate = attack_rate; - SoundData.channels[channel].decay_rate = decay_rate; - SoundData.channels[channel].sustain_rate = sustain_rate; - SoundData.channels[channel].release_rate = release_rate; - SoundData.channels[channel].sustain_level = sustain_level + 1; - - switch (SoundData.channels[channel].state) - { - case SOUND_ATTACK: - S9xSetEnvelopeRate (channel, attack_rate, 1, 127, 0); - break; - - case SOUND_DECAY: - S9xSetEnvelopeRate (channel, decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3, 1<<28); - break; - case SOUND_SUSTAIN: - S9xSetEnvelopeRate (channel, sustain_rate, -1, 0, 2<<28); - break; - } -} - -static inline void S9xSetSoundVolume (int channel, short volume_left, short volume_right) -{ - Channel *ch = &SoundData.channels[channel]; - if (!so.stereo) - volume_left = (ABS(volume_right) + ABS(volume_left)) / 2; - - ch->volume_left = volume_left; - ch->volume_right = volume_right; - ch-> left_vol_level = (ch->envx * volume_left) / 128; - ch->right_vol_level = (ch->envx * volume_right) / 128; -} - -static inline void S9xSetMasterVolume (short volume_left, short volume_right) -{ - if (Settings.DisableMasterVolume) - { - SoundData.master_volume_left = 127; - SoundData.master_volume_right = 127; - SoundData.master_volume [0] = SoundData.master_volume [1] = 127; - } - else - { - if (!so.stereo) - volume_left = (ABS (volume_right) + ABS (volume_left)) / 2; - SoundData.master_volume_left = volume_left; - SoundData.master_volume_right = volume_right; - SoundData.master_volume [0] = volume_left; - SoundData.master_volume [1] = volume_right; - } -} - -static inline void S9xSetEchoVolume (short volume_left, short volume_right) -{ - if (!so.stereo) - volume_left = (ABS (volume_right) + ABS (volume_left)) / 2; - SoundData.echo_volume_left = volume_left; - SoundData.echo_volume_right = volume_right; - SoundData.echo_volume [0] = volume_left; - SoundData.echo_volume [1] = volume_right; -} - -static inline void S9xSetEchoWriteEnable (uint8 byte) -{ - SoundData.echo_write_enabled = byte; - S9xSetEchoDelay (APU.DSP [APU_EDL] & 15); -} - -static inline void S9xSetFrequencyModulationEnable (uint8 byte) -{ - SoundData.pitch_mod = byte & (0xFE);//~1; -} - -static inline int S9xGetEnvelopeHeight (int channel) -{ - if ((Settings.SoundEnvelopeHeightReading || - SNESGameFixes.SoundEnvelopeHeightReading2) && - SoundData.channels[channel].state != SOUND_SILENT && - SoundData.channels[channel].state != SOUND_GAIN) - { - return (SoundData.channels[channel].envx); - } - - //siren fix from XPP - if (SNESGameFixes.SoundEnvelopeHeightReading2 && - SoundData.channels[channel].state != SOUND_SILENT) - { - return (SoundData.channels[channel].envx); - } - - return (0); -} - -static inline void S9xSetSoundHertz (int channel, int hertz) -{ - SoundData.channels[channel].hertz = hertz; - S9xSetSoundFrequency (channel, hertz); -} - -static inline void S9xSetSoundType (int channel, int type_of_sound) -{ - SoundData.channels[channel].type = type_of_sound; -} - -static inline bool8 S9xSetSoundMode (int channel, int mode) -{ - Channel *ch = &SoundData.channels[channel]; - - switch (mode) - { - case MODE_RELEASE: - if (ch->mode != MODE_NONE) - { - ch->mode = MODE_RELEASE; - return (TRUE); - } - break; - - case MODE_DECREASE_LINEAR: - case MODE_DECREASE_EXPONENTIAL: - case MODE_GAIN: - if (ch->mode != MODE_RELEASE) - { - ch->mode = mode; - if (ch->state != SOUND_SILENT) - ch->state = mode; - - return (TRUE); - } - break; - - case MODE_INCREASE_LINEAR: - case MODE_INCREASE_BENT_LINE: - if (ch->mode != MODE_RELEASE) - { - ch->mode = mode; - if (ch->state != SOUND_SILENT) - ch->state = mode; - - - - - return (TRUE); - } - break; - - case MODE_ADSR: - if (ch->mode == MODE_NONE || ch->mode == MODE_ADSR) - { - ch->mode = mode; - return (TRUE); - } - } - - return (FALSE); -} - -static inline void S9xPlaySample (int channel) -{ - Channel *ch = &SoundData.channels[channel]; - - ch->state = SOUND_SILENT; - ch->mode = MODE_NONE; - ch->envx = 0; - ch->envxx = 0; - - ch->g_index=0; - ch->gaussian[0]=ch->gaussian[1]=ch->gaussian[2]=ch->gaussian[3]=0; - - S9xFixEnvelope (channel, - APU.DSP [APU_GAIN + (channel << 4)], - APU.DSP [APU_ADSR1 + (channel << 4)], - APU.DSP [APU_ADSR2 + (channel << 4)]); - - ch->sample_number = APU.DSP [APU_SRCN + channel * 0x10]; - if (APU.DSP [APU_NON] & (1 << channel)) - ch->type = SOUND_NOISE; - else - ch->type = SOUND_SAMPLE; - - S9xSetSoundFrequency (channel, ch->hertz); - ch->loop = FALSE; - ch->needs_decode = TRUE; - ch->last_block = FALSE; - ch->previous [0] = ch->previous[1] = 0; - ch->block_pointer = *S9xGetSampleAddress(ch->sample_number); - ch->sample_pointer = 0; - ch->env_error = 0; - ch->next_sample = 0; - ch->interpolate = 0; - ch->last_valid_header=0; - switch (ch->mode) - { - case MODE_ADSR: - if (ch->attack_rate == 0) - { - if (ch->decay_rate == 0 || ch->sustain_level == 8) - { - ch->state = SOUND_SUSTAIN; - ch->envx = (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28); - } - else - { - ch->state = SOUND_DECAY; - ch->envx = MAX_ENVELOPE_HEIGHT; - S9xSetEnvRate (ch, ch->decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28); - } - ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; - ch->right_vol_level = (ch->envx * ch->volume_right) / 128; - } - else - { - ch->state = SOUND_ATTACK; - ch->envx = 0; - ch->left_vol_level = 0; - ch->right_vol_level = 0; - S9xSetEnvRate (ch, ch->attack_rate, 1, MAX_ENVELOPE_HEIGHT, 0); - } - ch->envxx = ch->envx << ENVX_SHIFT; - break; - - case MODE_GAIN: - ch->state = SOUND_GAIN; - break; - - case MODE_INCREASE_LINEAR: - ch->state = SOUND_INCREASE_LINEAR; - break; - - case MODE_INCREASE_BENT_LINE: - ch->state = SOUND_INCREASE_BENT_LINE; - break; - - case MODE_DECREASE_LINEAR: - ch->state = SOUND_DECREASE_LINEAR; - break; - - case MODE_DECREASE_EXPONENTIAL: - ch->state = SOUND_DECREASE_EXPONENTIAL; - break; - - default: - break; - } - - S9xFixEnvelope (channel, - APU.DSP [APU_GAIN + (channel << 4)], - APU.DSP [APU_ADSR1 + (channel << 4)], - APU.DSP [APU_ADSR2 + (channel << 4)]); -} - -extern "C" uint32 Spc700JumpTab_15; - -bool8 S9xInitAPU () -{ - // notaz - memset(&IAPU, 0, sizeof(IAPU)); - IAPU.ExtraRAM = APU.ExtraRAM; - IAPU.asmJumpTab = &Spc700JumpTab_15; // Normal case: ONE_APU_CYCLE = 15 - - IAPU.RAM = (uint8 *) malloc (0x10000); - IAPU.ShadowRAM = NULL;//(uint8 *) malloc (0x10000); - IAPU.CachedSamples = NULL;//(uint8 *) malloc (0x40000); - - if (!IAPU.RAM /*|| !IAPU.ShadowRAM || !IAPU.CachedSamples*/) - { - S9xDeinitAPU (); - return (FALSE); - } - - return (TRUE); -} - -void S9xDeinitAPU () -{ - if (IAPU.RAM) - { - free ((char *) IAPU.RAM); - IAPU.RAM = NULL; - } - if (IAPU.ShadowRAM) - { - free ((char *) IAPU.ShadowRAM); - IAPU.ShadowRAM = NULL; - } - if (IAPU.CachedSamples) - { - free ((char *) IAPU.CachedSamples); - IAPU.CachedSamples = NULL; - } -} - -EXTERN_C uint8 APUROM [64]; - -void S9xResetAPU () -{ -// Settings.APUEnabled = Settings.NextAPUEnabled; - - ZeroMemory(IAPU.RAM, 0x100); - memset(IAPU.RAM+0x20, 0xFF, 0x20); - memset(IAPU.RAM+0x60, 0xFF, 0x20); - memset(IAPU.RAM+0xA0, 0xFF, 0x20); - memset(IAPU.RAM+0xE0, 0xFF, 0x20); - - for(int i=1;i<256;i++) - { - memcpy(IAPU.RAM+(i<<8), IAPU.RAM, 0x100); - } - //ZeroMemory (IAPU.CachedSamples, 0x40000); - ZeroMemory (APU.OutPorts, 4); - IAPU.DirectPage = IAPU.RAM; - memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); - memmove (APU.ExtraRAM, APUROM, sizeof (APUROM)); - IAPU.PC = IAPU.RAM + IAPU.RAM [0xfffe] + (IAPU.RAM [0xffff] << 8); - CPU.APU_Cycles = 0; - IAPU.YA.W = 0; - IAPU.X = 0; - IAPU.S = 0xff; - IAPU.P = 0; - S9xAPUUnpackStatus (); - CPU.APU_APUExecuting = Settings.APUEnabled; -#ifdef SPC700_SHUTDOWN - IAPU.WaitAddress1 = NULL; - IAPU.WaitAddress2 = NULL; - IAPU.WaitCounter = 0; -#endif - APU.ShowROM = TRUE; - IAPU.RAM [0xf1] = 0x80; - - int i; - - for (i = 0; i < 3; i++) - { - APU.TimerEnabled [i] = FALSE; - APU.TimerValueWritten [i] = 0; - APU.TimerTarget [i] = 0; - APU.Timer [i] = 0; - } - for (int j = 0; j < 0x80; j++) - APU.DSP [j] = 0; - - IAPU.TwoCycles = IAPU.OneCycle * 2; - - for (i = 0; i < 256; i++) - S9xAPUCycles [i] = S9xAPUCycleLengths [i] * IAPU.OneCycle; - - APU.DSP [APU_ENDX] = 0; - APU.DSP [APU_KOFF] = 0; - APU.DSP [APU_KON] = 0; - APU.DSP [APU_FLG] = APU_MUTE | APU_ECHO_DISABLED; - APU.KeyedChannels = 0; - - S9xResetSound (TRUE); - S9xSetEchoEnable (0); -} - -extern int framecpto; -void S9xSetAPUDSP (uint8 byte) -{ - uint8 reg = IAPU.RAM [0xf2]; - static uint8 KeyOn; - static uint8 KeyOnPrev; - int i; - -/* char str[64]; - if (byte!=0) - { - sprintf(str,"fr : %d\nwrite dsp %d\ncpu cycle=%d pc=%04X",framecpto,byte,CPU.Cycles,CPU.PC-CPU.PCBase); - S9xMessage(0,0,str); - gp32_pause(); - }*/ - - //extern uint8 spc_dump_dsp[0x100]; - - //spc_dump_dsp[reg] = byte; - - switch (reg) - { - case APU_FLG: - if (byte & APU_SOFT_RESET) - { - APU.DSP [reg] = APU_MUTE | APU_ECHO_DISABLED | (byte & 0x1f); - APU.DSP [APU_ENDX] = 0; - APU.DSP [APU_KOFF] = 0; - APU.DSP [APU_KON] = 0; - S9xSetEchoWriteEnable (FALSE); - // Kill sound - S9xResetSound (FALSE); - } - else - { - S9xSetEchoWriteEnable (!(byte & APU_ECHO_DISABLED)); - if (byte & APU_MUTE) - { - S9xSetSoundMute (TRUE); - } - else - S9xSetSoundMute (FALSE); - - SoundData.noise_hertz = NoiseFreq [byte & 0x1f]; - for (i = 0; i < 8; i++) - { - if (SoundData.channels [i].type == SOUND_NOISE) - S9xSetSoundFrequency (i, SoundData.noise_hertz); - } - } - break; - case APU_NON: - if (byte != APU.DSP [APU_NON]) - { - uint8 mask = 1; - for (int c = 0; c < 8; c++, mask <<= 1) - { - int type; - if (byte & mask) - { - type = SOUND_NOISE; - } - else - { - type = SOUND_SAMPLE; - } - S9xSetSoundType (c, type); - } - } - break; - case APU_MVOL_LEFT: - if (byte != APU.DSP [APU_MVOL_LEFT]) - { - S9xSetMasterVolume ((signed char) byte, - (signed char) APU.DSP [APU_MVOL_RIGHT]); - } - break; - case APU_MVOL_RIGHT: - if (byte != APU.DSP [APU_MVOL_RIGHT]) - { - S9xSetMasterVolume ((signed char) APU.DSP [APU_MVOL_LEFT], - (signed char) byte); - } - break; - case APU_EVOL_LEFT: - if (byte != APU.DSP [APU_EVOL_LEFT]) - { - S9xSetEchoVolume ((signed char) byte, - (signed char) APU.DSP [APU_EVOL_RIGHT]); - } - break; - case APU_EVOL_RIGHT: - if (byte != APU.DSP [APU_EVOL_RIGHT]) - { - S9xSetEchoVolume ((signed char) APU.DSP [APU_EVOL_LEFT], - (signed char) byte); - } - break; - case APU_ENDX: - byte = 0; - break; - - case APU_KOFF: - // if (byte) - { - uint8 mask = 1; - for (int c = 0; c < 8; c++, mask <<= 1) - { - if ((byte & mask) != 0) - { - if (APU.KeyedChannels & mask) - { - { - KeyOnPrev&=~mask; - APU.KeyedChannels &= ~mask; - APU.DSP [APU_KON] &= ~mask; - //APU.DSP [APU_KOFF] |= mask; - S9xSetSoundKeyOff (c); - } - } - } - else if((KeyOnPrev&mask)!=0) - { - KeyOnPrev&=~mask; - APU.KeyedChannels |= mask; - //APU.DSP [APU_KON] |= mask; - APU.DSP [APU_KOFF] &= ~mask; - APU.DSP [APU_ENDX] &= ~mask; - S9xPlaySample (c); - } - } - } - //KeyOnPrev=0; - APU.DSP [APU_KOFF] = byte; - return; - case APU_KON: - - if (byte) - { - uint8 mask = 1; - for (int c = 0; c < 8; c++, mask <<= 1) - { - if ((byte & mask) != 0) - { - // Pac-In-Time requires that channels can be key-on - // regardeless of their current state. - if((APU.DSP [APU_KOFF] & mask) ==0) - { - KeyOnPrev&=~mask; - APU.KeyedChannels |= mask; - //APU.DSP [APU_KON] |= mask; - //APU.DSP [APU_KOFF] &= ~mask; - APU.DSP [APU_ENDX] &= ~mask; - S9xPlaySample (c); - } - else KeyOn|=mask; - } - } - } - //spc_is_dumping_temp = byte; - return; - - case APU_VOL_LEFT + 0x00: - case APU_VOL_LEFT + 0x10: - case APU_VOL_LEFT + 0x20: - case APU_VOL_LEFT + 0x30: - case APU_VOL_LEFT + 0x40: - case APU_VOL_LEFT + 0x50: - case APU_VOL_LEFT + 0x60: - case APU_VOL_LEFT + 0x70: -// At Shin Megami Tensei suggestion 6/11/00 -// if (byte != APU.DSP [reg]) - { - S9xSetSoundVolume (reg >> 4, (signed char) byte, - (signed char) APU.DSP [reg + 1]); - } - break; - case APU_VOL_RIGHT + 0x00: - case APU_VOL_RIGHT + 0x10: - case APU_VOL_RIGHT + 0x20: - case APU_VOL_RIGHT + 0x30: - case APU_VOL_RIGHT + 0x40: - case APU_VOL_RIGHT + 0x50: - case APU_VOL_RIGHT + 0x60: - case APU_VOL_RIGHT + 0x70: -// At Shin Megami Tensei suggestion 6/11/00 -// if (byte != APU.DSP [reg]) - { - S9xSetSoundVolume (reg >> 4, (signed char) APU.DSP [reg - 1], - (signed char) byte); - } - break; - - case APU_P_LOW + 0x00: - case APU_P_LOW + 0x10: - case APU_P_LOW + 0x20: - case APU_P_LOW + 0x30: - case APU_P_LOW + 0x40: - case APU_P_LOW + 0x50: - case APU_P_LOW + 0x60: - case APU_P_LOW + 0x70: - S9xSetSoundHertz (reg >> 4, (((byte + (APU.DSP [reg + 1] << 8)) & FREQUENCY_MASK) * 32000) >> 12); - break; - - case APU_P_HIGH + 0x00: - case APU_P_HIGH + 0x10: - case APU_P_HIGH + 0x20: - case APU_P_HIGH + 0x30: - case APU_P_HIGH + 0x40: - case APU_P_HIGH + 0x50: - case APU_P_HIGH + 0x60: - case APU_P_HIGH + 0x70: - S9xSetSoundHertz (reg >> 4, - (((byte << 8) + APU.DSP [reg - 1]) & FREQUENCY_MASK) * 8); - break; - - case APU_SRCN + 0x00: - case APU_SRCN + 0x10: - case APU_SRCN + 0x20: - case APU_SRCN + 0x30: - case APU_SRCN + 0x40: - case APU_SRCN + 0x50: - case APU_SRCN + 0x60: - case APU_SRCN + 0x70: - if (byte != APU.DSP [reg]) - { - //S9xSetSoundSample (reg >> 4, byte); // notaz: seems to be unused? - } - break; - - case APU_ADSR1 + 0x00: - case APU_ADSR1 + 0x10: - case APU_ADSR1 + 0x20: - case APU_ADSR1 + 0x30: - case APU_ADSR1 + 0x40: - case APU_ADSR1 + 0x50: - case APU_ADSR1 + 0x60: - case APU_ADSR1 + 0x70: - if (byte != APU.DSP [reg]) - { - { - S9xFixEnvelope (reg >> 4, APU.DSP [reg + 2], byte, - APU.DSP [reg + 1]); - } - } - break; - - case APU_ADSR2 + 0x00: - case APU_ADSR2 + 0x10: - case APU_ADSR2 + 0x20: - case APU_ADSR2 + 0x30: - case APU_ADSR2 + 0x40: - case APU_ADSR2 + 0x50: - case APU_ADSR2 + 0x60: - case APU_ADSR2 + 0x70: - if (byte != APU.DSP [reg]) - { - { - S9xFixEnvelope (reg >> 4, APU.DSP [reg + 1], APU.DSP [reg - 1], - byte); - } - } - break; - - case APU_GAIN + 0x00: - case APU_GAIN + 0x10: - case APU_GAIN + 0x20: - case APU_GAIN + 0x30: - case APU_GAIN + 0x40: - case APU_GAIN + 0x50: - case APU_GAIN + 0x60: - case APU_GAIN + 0x70: - if (byte != APU.DSP [reg]) - { - { - S9xFixEnvelope (reg >> 4, byte, APU.DSP [reg - 2], - APU.DSP [reg - 1]); - } - } - break; - - case APU_ENVX + 0x00: - case APU_ENVX + 0x10: - case APU_ENVX + 0x20: - case APU_ENVX + 0x30: - case APU_ENVX + 0x40: - case APU_ENVX + 0x50: - case APU_ENVX + 0x60: - case APU_ENVX + 0x70: - break; - - case APU_OUTX + 0x00: - case APU_OUTX + 0x10: - case APU_OUTX + 0x20: - case APU_OUTX + 0x30: - case APU_OUTX + 0x40: - case APU_OUTX + 0x50: - case APU_OUTX + 0x60: - case APU_OUTX + 0x70: - break; - - case APU_DIR: - break; - - case APU_PMON: - if (byte != APU.DSP [APU_PMON]) - { - S9xSetFrequencyModulationEnable (byte); - } - break; - - case APU_EON: - if (byte != APU.DSP [APU_EON]) - { - S9xSetEchoEnable (byte); - } - break; - - case APU_EFB: - S9xSetEchoFeedback ((signed char) byte); - break; - - case APU_ESA: - break; - - case APU_EDL: - S9xSetEchoDelay (byte & 0xf); - break; - - case APU_C0: - case APU_C1: - case APU_C2: - case APU_C3: - case APU_C4: - case APU_C5: - case APU_C6: - case APU_C7: - S9xSetFilterCoefficient (reg >> 4, (signed char) byte); - break; - default: -// XXX -//printf ("Write %02x to unknown APU register %02x\n", byte, reg); - break; - } - - KeyOnPrev|=KeyOn; - KeyOn=0; - - if (reg < 0x80) - APU.DSP [reg] = byte; -} - -void S9xFixEnvelope (int channel, uint8 gain, uint8 adsr1, uint8 adsr2) -{ - if (adsr1 & 0x80) - { - // ADSR mode - - // XXX: can DSP be switched to ADSR mode directly from GAIN/INCREASE/ - // DECREASE mode? And if so, what stage of the sequence does it start - // at? - if (S9xSetSoundMode (channel, MODE_ADSR)) - { - S9xSetSoundADSR (channel, adsr1 & 0xf, (adsr1 >> 4) & 7, adsr2 & 0x1f, (adsr2 >> 5) & 7, 8); - } - } - else - { - // Gain mode - if ((gain & 0x80) == 0) - { - if (S9xSetSoundMode (channel, MODE_GAIN)) - { - S9xSetEnvelopeRate (channel, 0, 0, gain & 0x7f, 0); - S9xSetEnvelopeHeight (channel, gain & 0x7f); - } - } - else - { - - if (gain & 0x40) - { - // Increase mode - if (S9xSetSoundMode (channel, (gain & 0x20) ? - MODE_INCREASE_BENT_LINE : - MODE_INCREASE_LINEAR)) - { - S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f], 1, 127, (3<<28)|gain); - } - } - else - { - if(gain & 0x20) { - if (S9xSetSoundMode (channel, MODE_DECREASE_EXPONENTIAL)) - S9xSetEnvelopeRate (channel, DecreaseRateExp [gain & 0x1f] / 2, -1, 0, (4<<28)|gain); - } else { - if (S9xSetSoundMode (channel, MODE_DECREASE_LINEAR)) - S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f], -1, 0, (3<<28)|gain); - } - } - } - } -} - -void S9xSetAPUControl (uint8 byte) -{ -//if (byte & 0x40) -//printf ("*** Special SPC700 timing enabled\n"); - if ((byte & 1) != 0 && !APU.TimerEnabled [0]) - { - APU.Timer [0] = 0; - IAPU.RAM [0xfd] = 0; - if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0) - APU.TimerTarget [0] = 0x100; - } - if ((byte & 2) != 0 && !APU.TimerEnabled [1]) - { - APU.Timer [1] = 0; - IAPU.RAM [0xfe] = 0; - if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0) - APU.TimerTarget [1] = 0x100; - } - if ((byte & 4) != 0 && !APU.TimerEnabled [2]) - { - APU.Timer [2] = 0; - IAPU.RAM [0xff] = 0; - if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0) - APU.TimerTarget [2] = 0x100; - } - APU.TimerEnabled [0] = byte & 1; - APU.TimerEnabled [1] = (byte & 2) >> 1; - APU.TimerEnabled [2] = (byte & 4) >> 2; - - if (byte & 0x10) - IAPU.RAM [0xF4] = IAPU.RAM [0xF5] = 0; - - if (byte & 0x20) - IAPU.RAM [0xF6] = IAPU.RAM [0xF7] = 0; - - if (byte & 0x80) - { - if (!APU.ShowROM) - { - memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM)); - APU.ShowROM = TRUE; - } - } - else - { - if (APU.ShowROM) - { - APU.ShowROM = FALSE; - memmove (&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof (APUROM)); - } - } - IAPU.RAM [0xf1] = byte; -} - -void S9xSetAPUTimer (uint16 Address, uint8 byte) -{ - IAPU.RAM [Address] = byte; - - switch (Address) - { - case 0xfa: - if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0) - APU.TimerTarget [0] = 0x100; - APU.TimerValueWritten [0] = TRUE; - break; - case 0xfb: - if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0) - APU.TimerTarget [1] = 0x100; - APU.TimerValueWritten [1] = TRUE; - break; - case 0xfc: - if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0) - APU.TimerTarget [2] = 0x100; - APU.TimerValueWritten [2] = TRUE; - break; - } -} - -uint8 S9xGetAPUDSP () -{ - uint8 reg = IAPU.RAM [0xf2] & 0x7f; - uint8 byte = APU.DSP [reg]; - - switch (reg) - { - case APU_KON: - break; - case APU_KOFF: - break; - case APU_OUTX + 0x00: - case APU_OUTX + 0x10: - case APU_OUTX + 0x20: - case APU_OUTX + 0x30: - case APU_OUTX + 0x40: - case APU_OUTX + 0x50: - case APU_OUTX + 0x60: - case APU_OUTX + 0x70: - if (SoundData.channels [reg >> 4].state == SOUND_SILENT) - return (0); - return ((SoundData.channels [reg >> 4].sample >> 8) | - (SoundData.channels [reg >> 4].sample & 0xff)); - - case APU_ENVX + 0x00: - case APU_ENVX + 0x10: - case APU_ENVX + 0x20: - case APU_ENVX + 0x30: - case APU_ENVX + 0x40: - case APU_ENVX + 0x50: - case APU_ENVX + 0x60: - case APU_ENVX + 0x70: - return 0; -// return ((uint8) S9xGetEnvelopeHeight (reg >> 4)); - - case APU_ENDX: -// To fix speech in Magical Drop 2 6/11/00 -// APU.DSP [APU_ENDX] = 0; - break; - default: - break; - } - return (byte); -} diff --git a/src/apu.h b/src/apu.h index 0f13bb2..cae7ded 100644 --- a/src/apu.h +++ b/src/apu.h @@ -51,7 +51,7 @@ typedef union } YAndA; */ -struct SAPU +typedef struct { int32 Cycles; // 0x00 bool8 ShowROM; // 0x04 @@ -64,9 +64,9 @@ struct SAPU uint16 TimerTarget [3]; bool8 TimerEnabled [3]; bool8 TimerValueWritten [3]; -}; +}SAPU; -struct SIAPU +typedef struct { uint8 *DirectPage; // 0x00 uint32 Address; // 0x04 c core only @@ -97,11 +97,11 @@ struct SIAPU uint8 *RAM; // 0x44 uint8 *ExtraRAM; // 0x48 shortcut to APU.ExtraRAM -}; +}SIAPU; -EXTERN_C struct SAPU APU; -EXTERN_C struct SIAPU IAPU; +EXTERN_C SAPU APU; +EXTERN_C SIAPU IAPU; STATIC inline void S9xAPUUnpackStatus() { diff --git a/src/apumem.h b/src/apumem.h index 2abe3d9..27390be 100644 --- a/src/apumem.h +++ b/src/apumem.h @@ -47,7 +47,7 @@ extern uint8 W4; extern uint8 APUROM[64]; END_EXTERN_C -INLINE uint8 S9xAPUGetByteZ (uint8 Address) +static INLINE uint8 S9xAPUGetByteZ (uint8 Address) { if (Address >= 0xf0 && IAPU.DirectPage == IAPU.RAM) { @@ -65,7 +65,7 @@ INLINE uint8 S9xAPUGetByteZ (uint8 Address) return (IAPU.DirectPage [Address]); } -INLINE void S9xAPUSetByteZ (uint8 val, uint8 Address) +static INLINE void S9xAPUSetByteZ (uint8 val, uint8 Address) { if (Address >= 0xf0 && IAPU.DirectPage == IAPU.RAM) { @@ -94,7 +94,7 @@ INLINE void S9xAPUSetByteZ (uint8 val, uint8 Address) IAPU.DirectPage [Address] = val; } -INLINE uint8 S9xAPUGetByte (uint32 Address) +static INLINE uint8 S9xAPUGetByte (uint32 Address) { Address &= 0xffff; @@ -113,7 +113,7 @@ INLINE uint8 S9xAPUGetByte (uint32 Address) return (IAPU.RAM [Address]); } -INLINE void S9xAPUSetByte (uint8 val, uint32 Address) +static INLINE void S9xAPUSetByte (uint8 val, uint32 Address) { Address &= 0xffff; diff --git a/src/asmmemfuncs.h b/src/asmmemfuncs.h index 0f4e514..aee7a27 100644 --- a/src/asmmemfuncs.h +++ b/src/asmmemfuncs.h @@ -3,7 +3,7 @@ #ifdef ARM_ASM #define memset32(_dst, _c, _count) \ -({ uint32_t *dst = (_dst); register uint32_t c asm ("r7") = (_c); int count = (_count); register uint32_t dummy0 asm ("r4"), dummy1 asm ("r5"), dummy2 asm ("r6"); \ +({ uint32_t *dst = (_dst); register uint32_t c __asm__ ("r7") = (_c); int count = (_count); register uint32_t dummy0 __asm__ ("r4"), dummy1 __asm__ ("r5"), dummy2 __asm__ ("r6"); \ __asm__ __volatile__ ( \ " cmp %[count], #4\n" \ " blt 2f\n" \ @@ -36,7 +36,7 @@ }) #define memset16(_dst, _c, _count) \ -({ uint16_t *dst = (_dst); register uint16_t c asm ("r7") = (_c); int count = (_count); register uint32_t dummy0 asm ("r4"), dummy1 asm ("r5"), dummy2 asm ("r6"); \ +({ uint16_t *dst = (_dst); register uint16_t c __asm__ ("r7") = (_c); int count = (_count); register uint32_t dummy0 __asm__ ("r4"), dummy1 __asm__ ("r5"), dummy2 __asm__ ("r6"); \ __asm__ __volatile__ ( \ " cmp %[count], #2\n" \ " blt 3f\n" \ diff --git a/src/c4.c b/src/c4.c new file mode 100644 index 0000000..8546631 --- /dev/null +++ b/src/c4.c @@ -0,0 +1,432 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2003 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2003 Matthew Kendora and + Brad Jorsch (anomie@users.sourceforge.net) + + + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and + Nach (n-a-c-h@users.sourceforge.net) + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2003 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman (jweidman@slip.net), + neviksti (neviksti@hotmail.com), and + Kris Bleakley (stinkfish@bigpond.com) + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2003 zsKnight, pagefault (pagefault@zsnes.com) + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar and Gary Henderson. + + + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and distribute Snes9x in both binary and + source form, for non-commercial purposes, is hereby granted without fee, + providing that this license information and copyright notice appear with + all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes + charging money for Snes9x or software derived from Snes9x. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +*******************************************************************************/ + +#ifndef __GP32__ +#include +#endif + +#include +#include "c4.h" +//#include "memmap.h" + +START_EXTERN_C + +short C4WFXVal; +short C4WFYVal; +short C4WFZVal; +short C4WFX2Val; +short C4WFY2Val; +short C4WFDist; +short C4WFScale; + +static long tanval; +static long c4x, c4y, c4z; +static long c4x2, c4y2, c4z2; + +const short C4_MulTable[256] = { + 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, + 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0028, 0x002b, 0x002f, + 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, 0x0045, 0x0048, + 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005b, 0x005e, 0x0061, + 0x0064, 0x0067, 0x006a, 0x006d, 0x0071, 0x0074, 0x0077, 0x007a, + 0x007d, 0x0080, 0x0083, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093, + 0x0096, 0x0099, 0x009d, 0x00a0, 0x00a3, 0x00a6, 0x00a9, 0x00ac, + 0x00af, 0x00b3, 0x00b6, 0x00b9, 0x00bc, 0x00bf, 0x00c2, 0x00c5, + 0x00c9, 0x00cc, 0x00cf, 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00df, + 0x00e2, 0x00e5, 0x00e8, 0x00eb, 0x00ee, 0x00f1, 0x00f5, 0x00f8, + 0x00fb, 0x00fe, 0x0101, 0x0104, 0x0107, 0x010b, 0x010e, 0x0111, + 0x0114, 0x0117, 0x011a, 0x011d, 0x0121, 0x0124, 0x0127, 0x012a, + 0x012d, 0x0130, 0x0133, 0x0137, 0x013a, 0x013d, 0x0140, 0x0143, + 0x0146, 0x0149, 0x014d, 0x0150, 0x0153, 0x0156, 0x0159, 0x015c, + 0x015f, 0x0163, 0x0166, 0x0169, 0x016c, 0x016f, 0x0172, 0x0175, + 0x0178, 0x017c, 0x017f, 0x0182, 0x0185, 0x0188, 0x018b, 0x018e, + 0x0192, 0x0195, 0x0198, 0x019b, 0x019e, 0x01a1, 0x01a4, 0x01a8, + 0x01ab, 0x01ae, 0x01b1, 0x01b4, 0x01b7, 0x01ba, 0x01be, 0x01c1, + 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01d0, 0x01d4, 0x01d7, 0x01da, + 0x01dd, 0x01e0, 0x01e3, 0x01e6, 0x01ea, 0x01ed, 0x01f0, 0x01f3, + 0x01f6, 0x01f9, 0x01fc, 0x0200, 0x0203, 0x0206, 0x0209, 0x020c, + 0x020f, 0x0212, 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225, + 0x0228, 0x022c, 0x022f, 0x0232, 0x0235, 0x0238, 0x023b, 0x023e, + 0x0242, 0x0245, 0x0248, 0x024b, 0x024e, 0x0251, 0x0254, 0x0258, + 0x025b, 0x025e, 0x0261, 0x0264, 0x0267, 0x026a, 0x026e, 0x0271, + 0x0274, 0x0277, 0x027a, 0x027d, 0x0280, 0x0284, 0x0287, 0x028a, + 0x028d, 0x0290, 0x0293, 0x0296, 0x029a, 0x029d, 0x02a0, 0x02a3, + 0x02a6, 0x02a9, 0x02ac, 0x02b0, 0x02b3, 0x02b6, 0x02b9, 0x02bc, + 0x02bf, 0x02c2, 0x02c6, 0x02c9, 0x02cc, 0x02cf, 0x02d2, 0x02d5, + 0x02d8, 0x02db, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ee, + 0x02f1, 0x02f5, 0x02f8, 0x02fb, 0x02fe, 0x0301, 0x0304, 0x0307, + 0x030b, 0x030e, 0x0311, 0x0314, 0x0317, 0x031a, 0x031d, 0x0321}; + +const short C4_SinTable[256] = { + 0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, + 0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, + 0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, + 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, + 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, + 0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, + 0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, + 0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, + 0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, + 0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, + 0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, + 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, + 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, + 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, + 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, + 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, + -0x0000, -0x0324, -0x0647, -0x096a, -0x0c8b, -0x0fab, -0x12c8, -0x15e2, + -0x18f8, -0x1c0b, -0x1f19, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, + -0x30fb, -0x33de, -0x36ba, -0x398c, -0x3c56, -0x3f17, -0x41ce, -0x447a, + -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, + -0x5a82, -0x5cb4, -0x5ed7, -0x60ec, -0x62f2, -0x64e8, -0x66cf, -0x68a6, + -0x6a6d, -0x6c24, -0x6dca, -0x6f5f, -0x70e2, -0x7255, -0x73b5, -0x7504, + -0x7641, -0x776c, -0x7884, -0x798a, -0x7a7d, -0x7b5d, -0x7c29, -0x7ce3, + -0x7d8a, -0x7e1d, -0x7e9d, -0x7f09, -0x7f62, -0x7fa7, -0x7fd8, -0x7ff6, + -0x7fff, -0x7ff6, -0x7fd8, -0x7fa7, -0x7f62, -0x7f09, -0x7e9d, -0x7e1d, + -0x7d8a, -0x7ce3, -0x7c29, -0x7b5d, -0x7a7d, -0x798a, -0x7884, -0x776c, + -0x7641, -0x7504, -0x73b5, -0x7255, -0x70e2, -0x6f5f, -0x6dca, -0x6c24, + -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f2, -0x60ec, -0x5ed7, -0x5cb4, + -0x5a82, -0x5842, -0x55f5, -0x539b, -0x5133, -0x4ebf, -0x4c3f, -0x49b4, + -0x471c, -0x447a, -0x41ce, -0x3f17, -0x3c56, -0x398c, -0x36ba, -0x33de, + -0x30fb, -0x2e11, -0x2b1f, -0x2826, -0x2528, -0x2223, -0x1f19, -0x1c0b, + -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324}; + +short C4_Sin(short Angle) +{ + if (Angle < 0) { + if (Angle == -32768) return 0; + return -C4_Sin(-Angle); + } + int S = C4_SinTable[Angle >> 8] + (C4_MulTable[Angle & 0xff] * C4_SinTable[0x40 + (Angle >> 8)] >> 15); + if (S > 32767) S = 32767; + return (short) S; +} + +short C4_Cos(short Angle) +{ + if (Angle < 0) { + if (Angle == -32768) return -32768; + Angle = -Angle; + } + int S = C4_SinTable[0x40 + (Angle >> 8)] - (C4_MulTable[Angle & 0xff] * C4_SinTable[Angle >> 8] >> 15); + if (S < -32768) S = -32767; + return (short) S; +} +const short atantbl[] = { 0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 34, 35, 36, 36, 37, 37, 38, 39, 39, 40, 40, 41, 42, 42, 43, 43, 44, 44, 45, 46, 46, 47, 47, 48, 49, 49, 50, 50, 51, 51, 52, 53, 53, 54, 54, 55, 55, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 62, 62, 63, 63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 86, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91, 92, 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, 96, 97, 97, 98, 98, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 103, 103, 104, 104, 104, 105, 105, 106, 106, 106, 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 111, 111, 111, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 116, 116, 117, 117, 117, 118, 118, 118, 119, 119, 119, 120, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 124, 124, 124, 125, 125, 125, 126, 126, 126, 127, 127 }; + +short _abs (short val) +{ + return ((val >= 0) ? val : -val); +} + +short _atan2 (short x, short y) +{ + int x1,y1; + x1 = _abs (x); + y1 = _abs (y); + + if (x == 0) return 0; + + if ( ((x >= 0) && (y >= 0)) || ( (x < 0) && (y < 0)) ) { + if (x1 > y1) { + return atantbl[(unsigned char)((y1 << 8) / x1)]; + } else { + return atantbl[(unsigned char)((x1 << 8) / y1)]; + } + } else { + if (x1 > y1) { + return -atantbl[(unsigned char)((y1 << 8) / x1)]; + } else { + return -atantbl[(unsigned char)((x1 << 8) / y1)]; + } + } +} + +/*long _isqrt(long x) +{ + long s, t; + + if (x <= 0) return 0; + + s = 1; t = x; + while (s < t) { s <<= 1; t >>= 1; } + do { + t = s; + s = (x / s + s) >> 1; + } while (s < t); + + return t; +} +*/ + +static unsigned int _isqrt (unsigned long val) +{ + unsigned int temp, g=0; + + if (val >= 0x40000000) { + g = 0x8000; + val -= 0x40000000; + } + + #define INNER_ISQRT(s) \ + temp = (g << (s)) + (1 << ((s) * 2 - 2)); \ + if (val >= temp) { \ + g += 1 << ((s)-1); \ + val -= temp; \ + } + + INNER_ISQRT (15) + INNER_ISQRT (14) + INNER_ISQRT (13) + INNER_ISQRT (12) + INNER_ISQRT (11) + INNER_ISQRT (10) + INNER_ISQRT ( 9) + INNER_ISQRT ( 8) + INNER_ISQRT ( 7) + INNER_ISQRT ( 6) + INNER_ISQRT ( 5) + INNER_ISQRT ( 4) + INNER_ISQRT ( 3) + INNER_ISQRT ( 2) + + #undef INNER_ISQRT + + temp = g+g+1; + if (val >= temp) g++; + return g; +} + +void C4TransfWireFrame () +{ + c4x = C4WFXVal; + c4y = C4WFYVal; + c4z = C4WFZVal - 0x95; + + // Rotate X + tanval = -C4WFX2Val << 9; + c4y2 = (c4y * C4_Cos(tanval) - c4z * C4_Sin(tanval)) >> 15; + c4z2 = (c4y * C4_Sin(tanval) + c4z * C4_Cos(tanval)) >> 15; + + // Rotate Y + tanval = -C4WFY2Val << 9; + c4x2 = (c4x * C4_Cos(tanval) + c4z2 * C4_Sin(tanval)) >> 15; + c4z = (c4x * -C4_Sin(tanval) + c4z2 * C4_Cos(tanval)) >> 15; + + // Rotate Z + tanval = -C4WFDist << 9; + c4x = (c4x2 * C4_Cos(tanval) - c4y2 * C4_Sin(tanval)) >> 15; + c4y = (c4x2 * C4_Sin(tanval) + c4y2 * C4_Cos(tanval)) >> 15; + + // Scale + C4WFXVal = (short)(((long)c4x*C4WFScale*0x95)/(0x90*(c4z+0x95))); + C4WFYVal = (short)(((long)c4y*C4WFScale*0x95)/(0x90*(c4z+0x95))); + +} + +void C4TransfWireFrame2 () +{ + c4x = C4WFXVal; + c4y = C4WFYVal; + c4z = C4WFZVal; + + // Rotate X + tanval = -C4WFX2Val << 9; + c4y2 = (c4y * C4_Cos(tanval) - c4z * C4_Sin(tanval)) >> 15; + c4z2 = (c4y * C4_Sin(tanval) + c4z * C4_Cos(tanval)) >> 15; + + // Rotate Y + tanval = -C4WFY2Val << 9; + c4x2 = (c4x * C4_Cos(tanval) + c4z2 * C4_Sin(tanval)) >> 15; + c4z = (c4x * -C4_Sin(tanval) + c4z2 * C4_Cos(tanval)) >> 15; + + // Rotate Z + tanval = -C4WFDist << 9; + c4x = (c4x2 * C4_Cos(tanval) - c4y2 * C4_Sin(tanval)) >> 15; + c4y = (c4x2 * C4_Sin(tanval) + c4y2 * C4_Cos(tanval)) >> 15; + + // Scale + C4WFXVal =(short)(((long)c4x * C4WFScale) / 0x100); + C4WFYVal =(short)(((long)c4y * C4WFScale) / 0x100); + +} + +void C4CalcWireFrame () +{ + C4WFXVal = C4WFX2Val - C4WFXVal; + C4WFYVal = C4WFY2Val - C4WFYVal; + if (_abs (C4WFXVal) > _abs (C4WFYVal)) + { + C4WFDist = _abs (C4WFXVal) + 1; + C4WFYVal = (short) ( ((long)C4WFYVal << 8) / _abs (C4WFXVal) ); + if (C4WFXVal < 0) + C4WFXVal = -256; + else + C4WFXVal = 256; + } + else + { + if (C4WFYVal != 0) + { + C4WFDist = _abs(C4WFYVal)+1; + C4WFXVal = (short) ( ((long)C4WFXVal << 8) / _abs (C4WFYVal) ); + if (C4WFYVal < 0) + C4WFYVal = -256; + else + C4WFYVal = 256; + } + else + C4WFDist = 0; + } +} + +short C41FXVal; +short C41FYVal; +short C41FAngleRes; +short C41FDist; +short C41FDistVal; + +void C4Op1F () +{ + if (C41FXVal == 0) + { + if (C41FYVal > 0) + C41FAngleRes = 0x80; + else + C41FAngleRes = 0x180; + } + else + { + C41FAngleRes = (short)(_atan2(C41FYVal, C41FXVal) / 2); + C41FAngleRes = C41FAngleRes; + if (C41FXVal< 0) + C41FAngleRes += 0x100; + C41FAngleRes &= 0x1FF; + } +/* + if (C41FXVal == 0) + { + if (C41FYVal > 0) + C41FAngleRes = 0x80; + else + C41FAngleRes = 0x180; + } + else + { + tanval = (double) C41FYVal / C41FXVal; + C41FAngleRes = (short) (atan (tanval) / (3.141592675 * 2) * 512); + C41FAngleRes = C41FAngleRes; + if (C41FXVal< 0) + C41FAngleRes += 0x100; + C41FAngleRes &= 0x1FF; + } +*/ +} + +void C4Op15() +{ + tanval = (short)_isqrt ((long) C41FYVal * C41FYVal + (long) C41FXVal * C41FXVal); + C41FDist = tanval; +/* + tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + C41FDist = (short) tanval; +*/ +} + +void C4Op0D() +{ + tanval = (short)_isqrt ((long) C41FYVal * C41FYVal + (long) C41FXVal * C41FXVal); + tanval = C41FDistVal / tanval; + C41FYVal = (short) (((long)C41FYVal * tanval * 99) / 100); + C41FXVal = (short) (((long)C41FXVal * tanval * 98) / 100); +/* + tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + tanval = C41FDistVal / tanval; + C41FYVal = (short) (C41FYVal * tanval * 0.99); + C41FXVal = (short) (C41FXVal * tanval * 0.98); +*/ +} + +#ifdef ZSNES_C4 +void C4LoaDMem(char *C4RAM) +{ + memmove(C4RAM+(READ_WORD(C4RAM+0x1f45)&0x1fff), + C4GetMemPointer(READ_3WORD(C4RAM+0x1f40)), + READ_WORD(C4RAM+0x1f43)); +} +#endif + +END_EXTERN_C + diff --git a/src/c4.cpp b/src/c4.cpp deleted file mode 100644 index bc0cd78..0000000 --- a/src/c4.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2003 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2003 Matthew Kendora and - Brad Jorsch (anomie@users.sourceforge.net) - - - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and - Nach (n-a-c-h@users.sourceforge.net) - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2003 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman (jweidman@slip.net), - neviksti (neviksti@hotmail.com), and - Kris Bleakley (stinkfish@bigpond.com) - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2003 zsKnight, pagefault (pagefault@zsnes.com) - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar and Gary Henderson. - - - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ - -#ifndef __GP32__ -#include -#endif - -#include -#include "c4.h" -//#include "memmap.h" - -extern "C" { - -short C4WFXVal; -short C4WFYVal; -short C4WFZVal; -short C4WFX2Val; -short C4WFY2Val; -short C4WFDist; -short C4WFScale; - -static long tanval; -static long c4x, c4y, c4z; -static long c4x2, c4y2, c4z2; - -const short C4_MulTable[256] = { - 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, - 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0028, 0x002b, 0x002f, - 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, 0x0045, 0x0048, - 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005b, 0x005e, 0x0061, - 0x0064, 0x0067, 0x006a, 0x006d, 0x0071, 0x0074, 0x0077, 0x007a, - 0x007d, 0x0080, 0x0083, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093, - 0x0096, 0x0099, 0x009d, 0x00a0, 0x00a3, 0x00a6, 0x00a9, 0x00ac, - 0x00af, 0x00b3, 0x00b6, 0x00b9, 0x00bc, 0x00bf, 0x00c2, 0x00c5, - 0x00c9, 0x00cc, 0x00cf, 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00df, - 0x00e2, 0x00e5, 0x00e8, 0x00eb, 0x00ee, 0x00f1, 0x00f5, 0x00f8, - 0x00fb, 0x00fe, 0x0101, 0x0104, 0x0107, 0x010b, 0x010e, 0x0111, - 0x0114, 0x0117, 0x011a, 0x011d, 0x0121, 0x0124, 0x0127, 0x012a, - 0x012d, 0x0130, 0x0133, 0x0137, 0x013a, 0x013d, 0x0140, 0x0143, - 0x0146, 0x0149, 0x014d, 0x0150, 0x0153, 0x0156, 0x0159, 0x015c, - 0x015f, 0x0163, 0x0166, 0x0169, 0x016c, 0x016f, 0x0172, 0x0175, - 0x0178, 0x017c, 0x017f, 0x0182, 0x0185, 0x0188, 0x018b, 0x018e, - 0x0192, 0x0195, 0x0198, 0x019b, 0x019e, 0x01a1, 0x01a4, 0x01a8, - 0x01ab, 0x01ae, 0x01b1, 0x01b4, 0x01b7, 0x01ba, 0x01be, 0x01c1, - 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01d0, 0x01d4, 0x01d7, 0x01da, - 0x01dd, 0x01e0, 0x01e3, 0x01e6, 0x01ea, 0x01ed, 0x01f0, 0x01f3, - 0x01f6, 0x01f9, 0x01fc, 0x0200, 0x0203, 0x0206, 0x0209, 0x020c, - 0x020f, 0x0212, 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225, - 0x0228, 0x022c, 0x022f, 0x0232, 0x0235, 0x0238, 0x023b, 0x023e, - 0x0242, 0x0245, 0x0248, 0x024b, 0x024e, 0x0251, 0x0254, 0x0258, - 0x025b, 0x025e, 0x0261, 0x0264, 0x0267, 0x026a, 0x026e, 0x0271, - 0x0274, 0x0277, 0x027a, 0x027d, 0x0280, 0x0284, 0x0287, 0x028a, - 0x028d, 0x0290, 0x0293, 0x0296, 0x029a, 0x029d, 0x02a0, 0x02a3, - 0x02a6, 0x02a9, 0x02ac, 0x02b0, 0x02b3, 0x02b6, 0x02b9, 0x02bc, - 0x02bf, 0x02c2, 0x02c6, 0x02c9, 0x02cc, 0x02cf, 0x02d2, 0x02d5, - 0x02d8, 0x02db, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ee, - 0x02f1, 0x02f5, 0x02f8, 0x02fb, 0x02fe, 0x0301, 0x0304, 0x0307, - 0x030b, 0x030e, 0x0311, 0x0314, 0x0317, 0x031a, 0x031d, 0x0321}; - -const short C4_SinTable[256] = { - 0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, - 0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, - 0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, - 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, - 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, - 0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, - 0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, - 0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, - 0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, - 0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, - 0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, - 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, - 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, - 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, - 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, - 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, - -0x0000, -0x0324, -0x0647, -0x096a, -0x0c8b, -0x0fab, -0x12c8, -0x15e2, - -0x18f8, -0x1c0b, -0x1f19, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, - -0x30fb, -0x33de, -0x36ba, -0x398c, -0x3c56, -0x3f17, -0x41ce, -0x447a, - -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, - -0x5a82, -0x5cb4, -0x5ed7, -0x60ec, -0x62f2, -0x64e8, -0x66cf, -0x68a6, - -0x6a6d, -0x6c24, -0x6dca, -0x6f5f, -0x70e2, -0x7255, -0x73b5, -0x7504, - -0x7641, -0x776c, -0x7884, -0x798a, -0x7a7d, -0x7b5d, -0x7c29, -0x7ce3, - -0x7d8a, -0x7e1d, -0x7e9d, -0x7f09, -0x7f62, -0x7fa7, -0x7fd8, -0x7ff6, - -0x7fff, -0x7ff6, -0x7fd8, -0x7fa7, -0x7f62, -0x7f09, -0x7e9d, -0x7e1d, - -0x7d8a, -0x7ce3, -0x7c29, -0x7b5d, -0x7a7d, -0x798a, -0x7884, -0x776c, - -0x7641, -0x7504, -0x73b5, -0x7255, -0x70e2, -0x6f5f, -0x6dca, -0x6c24, - -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f2, -0x60ec, -0x5ed7, -0x5cb4, - -0x5a82, -0x5842, -0x55f5, -0x539b, -0x5133, -0x4ebf, -0x4c3f, -0x49b4, - -0x471c, -0x447a, -0x41ce, -0x3f17, -0x3c56, -0x398c, -0x36ba, -0x33de, - -0x30fb, -0x2e11, -0x2b1f, -0x2826, -0x2528, -0x2223, -0x1f19, -0x1c0b, - -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324}; - -short C4_Sin(short Angle) -{ - if (Angle < 0) { - if (Angle == -32768) return 0; - return -C4_Sin(-Angle); - } - int S = C4_SinTable[Angle >> 8] + (C4_MulTable[Angle & 0xff] * C4_SinTable[0x40 + (Angle >> 8)] >> 15); - if (S > 32767) S = 32767; - return (short) S; -} - -short C4_Cos(short Angle) -{ - if (Angle < 0) { - if (Angle == -32768) return -32768; - Angle = -Angle; - } - int S = C4_SinTable[0x40 + (Angle >> 8)] - (C4_MulTable[Angle & 0xff] * C4_SinTable[Angle >> 8] >> 15); - if (S < -32768) S = -32767; - return (short) S; -} -const short atantbl[] = { 0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 34, 35, 36, 36, 37, 37, 38, 39, 39, 40, 40, 41, 42, 42, 43, 43, 44, 44, 45, 46, 46, 47, 47, 48, 49, 49, 50, 50, 51, 51, 52, 53, 53, 54, 54, 55, 55, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 62, 62, 63, 63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 86, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91, 92, 92, 92, 93, 93, 94, 94, 95, 95, 96, 96, 96, 97, 97, 98, 98, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 103, 103, 104, 104, 104, 105, 105, 106, 106, 106, 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 111, 111, 111, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 116, 116, 117, 117, 117, 118, 118, 118, 119, 119, 119, 120, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 124, 124, 124, 125, 125, 125, 126, 126, 126, 127, 127 }; - -short _abs (short val) -{ - return ((val >= 0) ? val : -val); -} - -short _atan2 (short x, short y) -{ - int x1,y1; - x1 = _abs (x); - y1 = _abs (y); - - if (x == 0) return 0; - - if ( ((x >= 0) && (y >= 0)) || ( (x < 0) && (y < 0)) ) { - if (x1 > y1) { - return atantbl[(unsigned char)((y1 << 8) / x1)]; - } else { - return atantbl[(unsigned char)((x1 << 8) / y1)]; - } - } else { - if (x1 > y1) { - return -atantbl[(unsigned char)((y1 << 8) / x1)]; - } else { - return -atantbl[(unsigned char)((x1 << 8) / y1)]; - } - } -} - -/*long _isqrt(long x) -{ - long s, t; - - if (x <= 0) return 0; - - s = 1; t = x; - while (s < t) { s <<= 1; t >>= 1; } - do { - t = s; - s = (x / s + s) >> 1; - } while (s < t); - - return t; -} -*/ - -static unsigned int _isqrt (unsigned long val) -{ - unsigned int temp, g=0; - - if (val >= 0x40000000) { - g = 0x8000; - val -= 0x40000000; - } - - #define INNER_ISQRT(s) \ - temp = (g << (s)) + (1 << ((s) * 2 - 2)); \ - if (val >= temp) { \ - g += 1 << ((s)-1); \ - val -= temp; \ - } - - INNER_ISQRT (15) - INNER_ISQRT (14) - INNER_ISQRT (13) - INNER_ISQRT (12) - INNER_ISQRT (11) - INNER_ISQRT (10) - INNER_ISQRT ( 9) - INNER_ISQRT ( 8) - INNER_ISQRT ( 7) - INNER_ISQRT ( 6) - INNER_ISQRT ( 5) - INNER_ISQRT ( 4) - INNER_ISQRT ( 3) - INNER_ISQRT ( 2) - - #undef INNER_ISQRT - - temp = g+g+1; - if (val >= temp) g++; - return g; -} - -void C4TransfWireFrame () -{ - c4x = C4WFXVal; - c4y = C4WFYVal; - c4z = C4WFZVal - 0x95; - - // Rotate X - tanval = -C4WFX2Val << 9; - c4y2 = (c4y * C4_Cos(tanval) - c4z * C4_Sin(tanval)) >> 15; - c4z2 = (c4y * C4_Sin(tanval) + c4z * C4_Cos(tanval)) >> 15; - - // Rotate Y - tanval = -C4WFY2Val << 9; - c4x2 = (c4x * C4_Cos(tanval) + c4z2 * C4_Sin(tanval)) >> 15; - c4z = (c4x * -C4_Sin(tanval) + c4z2 * C4_Cos(tanval)) >> 15; - - // Rotate Z - tanval = -C4WFDist << 9; - c4x = (c4x2 * C4_Cos(tanval) - c4y2 * C4_Sin(tanval)) >> 15; - c4y = (c4x2 * C4_Sin(tanval) + c4y2 * C4_Cos(tanval)) >> 15; - - // Scale - C4WFXVal = (short)(((long)c4x*C4WFScale*0x95)/(0x90*(c4z+0x95))); - C4WFYVal = (short)(((long)c4y*C4WFScale*0x95)/(0x90*(c4z+0x95))); - -} - -void C4TransfWireFrame2 () -{ - c4x = C4WFXVal; - c4y = C4WFYVal; - c4z = C4WFZVal; - - // Rotate X - tanval = -C4WFX2Val << 9; - c4y2 = (c4y * C4_Cos(tanval) - c4z * C4_Sin(tanval)) >> 15; - c4z2 = (c4y * C4_Sin(tanval) + c4z * C4_Cos(tanval)) >> 15; - - // Rotate Y - tanval = -C4WFY2Val << 9; - c4x2 = (c4x * C4_Cos(tanval) + c4z2 * C4_Sin(tanval)) >> 15; - c4z = (c4x * -C4_Sin(tanval) + c4z2 * C4_Cos(tanval)) >> 15; - - // Rotate Z - tanval = -C4WFDist << 9; - c4x = (c4x2 * C4_Cos(tanval) - c4y2 * C4_Sin(tanval)) >> 15; - c4y = (c4x2 * C4_Sin(tanval) + c4y2 * C4_Cos(tanval)) >> 15; - - // Scale - C4WFXVal =(short)(((long)c4x * C4WFScale) / 0x100); - C4WFYVal =(short)(((long)c4y * C4WFScale) / 0x100); - -} - -void C4CalcWireFrame () -{ - C4WFXVal = C4WFX2Val - C4WFXVal; - C4WFYVal = C4WFY2Val - C4WFYVal; - if (_abs (C4WFXVal) > _abs (C4WFYVal)) - { - C4WFDist = _abs (C4WFXVal) + 1; - C4WFYVal = (short) ( ((long)C4WFYVal << 8) / _abs (C4WFXVal) ); - if (C4WFXVal < 0) - C4WFXVal = -256; - else - C4WFXVal = 256; - } - else - { - if (C4WFYVal != 0) - { - C4WFDist = _abs(C4WFYVal)+1; - C4WFXVal = (short) ( ((long)C4WFXVal << 8) / _abs (C4WFYVal) ); - if (C4WFYVal < 0) - C4WFYVal = -256; - else - C4WFYVal = 256; - } - else - C4WFDist = 0; - } -} - -short C41FXVal; -short C41FYVal; -short C41FAngleRes; -short C41FDist; -short C41FDistVal; - -void C4Op1F () -{ - if (C41FXVal == 0) - { - if (C41FYVal > 0) - C41FAngleRes = 0x80; - else - C41FAngleRes = 0x180; - } - else - { - C41FAngleRes = (short)(_atan2(C41FYVal, C41FXVal) / 2); - C41FAngleRes = C41FAngleRes; - if (C41FXVal< 0) - C41FAngleRes += 0x100; - C41FAngleRes &= 0x1FF; - } -/* - if (C41FXVal == 0) - { - if (C41FYVal > 0) - C41FAngleRes = 0x80; - else - C41FAngleRes = 0x180; - } - else - { - tanval = (double) C41FYVal / C41FXVal; - C41FAngleRes = (short) (atan (tanval) / (3.141592675 * 2) * 512); - C41FAngleRes = C41FAngleRes; - if (C41FXVal< 0) - C41FAngleRes += 0x100; - C41FAngleRes &= 0x1FF; - } -*/ -} - -void C4Op15() -{ - tanval = (short)_isqrt ((long) C41FYVal * C41FYVal + (long) C41FXVal * C41FXVal); - C41FDist = tanval; -/* - tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); - C41FDist = (short) tanval; -*/ -} - -void C4Op0D() -{ - tanval = (short)_isqrt ((long) C41FYVal * C41FYVal + (long) C41FXVal * C41FXVal); - tanval = C41FDistVal / tanval; - C41FYVal = (short) (((long)C41FYVal * tanval * 99) / 100); - C41FXVal = (short) (((long)C41FXVal * tanval * 98) / 100); -/* - tanval = sqrt ((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); - tanval = C41FDistVal / tanval; - C41FYVal = (short) (C41FYVal * tanval * 0.99); - C41FXVal = (short) (C41FXVal * tanval * 0.98); -*/ -} - -#ifdef ZSNES_C4 -void C4LoaDMem(char *C4RAM) -{ - memmove(C4RAM+(READ_WORD(C4RAM+0x1f45)&0x1fff), - C4GetMemPointer(READ_3WORD(C4RAM+0x1f40)), - READ_WORD(C4RAM+0x1f43)); -} -#endif -}//end extern C - diff --git a/src/c4.h b/src/c4.h index 9efe17d..ace7320 100644 --- a/src/c4.h +++ b/src/c4.h @@ -78,7 +78,7 @@ #include "port.h" #include "memmap.h" -extern "C" { +START_EXTERN_C extern int16 C4WFXVal; extern int16 C4WFYVal; @@ -105,7 +105,7 @@ void C4Op0D(); extern int16 C4CosTable[]; extern int16 C4SinTable[]; -} +END_EXTERN_C static inline uint8 *C4GetMemPointer(uint32 Address){ return (Memory.ROM + ((Address&0xff0000)>>1) + (Address&0x7fff)); diff --git a/src/c4emu.c b/src/c4emu.c new file mode 100644 index 0000000..d7a47a4 --- /dev/null +++ b/src/c4emu.c @@ -0,0 +1,892 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2003 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2003 Matthew Kendora and + Brad Jorsch (anomie@users.sourceforge.net) + + + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and + Nach (n-a-c-h@users.sourceforge.net) + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2003 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman (jweidman@slip.net), + neviksti (neviksti@hotmail.com), and + Kris Bleakley (stinkfish@bigpond.com) + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2003 zsKnight, pagefault (pagefault@zsnes.com) + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar and Gary Henderson. + + + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and distribute Snes9x in both binary and + source form, for non-commercial purposes, is hereby granted without fee, + providing that this license information and copyright notice appear with + all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes + charging money for Snes9x or software derived from Snes9x. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +*******************************************************************************/ + +#ifndef __GP32__ +#ifdef HAVE_CONFIG_H + #include +#endif +#endif + +#include +#include "snes9x.h" +#include "sar.h" +#include "memmap.h" +#include "ppu.h" +#include "c4.h" + +void S9xInitC4 () +{ + // Stupid zsnes code, we can't do the logical thing without breaking + // savestates +// Memory.C4RAM = &Memory.FillRAM [0x6000]; + memset(Memory.C4RAM, 0, 0x2000); +} + +uint8 S9xGetC4 (uint16 Address) +{ + if(Address==0x7f5e) return 0; + return (Memory.C4RAM [Address-0x6000]); +} + +static uint8 C4TestPattern [12 * 4] = +{ + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0x00, 0x00, + 0x80, 0xff, 0xff, 0x7f, + 0x00, 0x80, 0x00, 0xff, + 0x7f, 0x00, 0xff, 0x7f, + 0xff, 0x7f, 0xff, 0xff, + 0x00, 0x00, 0x01, 0xff, + 0xff, 0xfe, 0x00, 0x01, + 0x00, 0xff, 0xfe, 0x00 +}; + + +static void C4ConvOAM(void){ + uint8 *ptr; + uint8 *OAMptr=Memory.C4RAM+(Memory.C4RAM[0x626]<<2); + for(ptr=Memory.C4RAM+0x1fd; ptr>OAMptr; ptr-=4){ + // Clear OAM-to-be + *ptr=0xe0; + } + + uint16 globalX, globalY; + uint8 *OAMptr2; + int16 SprX, SprY; + uint8 SprName, SprAttr; + uint8 SprCount; + + globalX=READ_WORD(Memory.C4RAM+0x0621); + globalY=READ_WORD(Memory.C4RAM+0x0623); + OAMptr2=Memory.C4RAM+0x200+(Memory.C4RAM[0x626]>>2); + + if(Memory.C4RAM[0x0620]!=0){ + int i; + SprCount=128-Memory.C4RAM[0x626]; + uint8 offset=(Memory.C4RAM[0x626]&3)*2; + uint8 *srcptr=Memory.C4RAM+0x220; + for(i=Memory.C4RAM[0x0620]; i>0 && SprCount>0; i--, srcptr+=16){ + SprX=READ_WORD(srcptr)-globalX; + SprY=READ_WORD(srcptr+2)-globalY; + SprName=srcptr[5]; + SprAttr=srcptr[4] | srcptr[0x06]; // XXX: mask bits? + + uint8 *sprptr=C4GetMemPointer(READ_3WORD(srcptr+7)); + if(*sprptr!=0){ + int16 X, Y; + int SprCnt; + for(SprCnt=*sprptr++; SprCnt>0 && SprCount>0; SprCnt--, sprptr+=4){ + X=(int8)sprptr[1]; + if(SprAttr&0x40){ // flip X + X=-X-((sprptr[0]&0x20)?16:8); + } + X+=SprX; + if(X>=-16 && X<=272){ + Y=(int8)sprptr[2]; + if(SprAttr&0x80){ + Y=-Y-((sprptr[0]&0x20)?16:8); + } + Y+=SprY; + if(Y>=-16 && Y<=224){ + OAMptr[0]=X&0xff; + OAMptr[1]=(uint8)Y; + OAMptr[2]=SprName+sprptr[3]; + OAMptr[3]=SprAttr^(sprptr[0]&0xc0); // XXX: Carry from SprName addition? + *OAMptr2 &= ~(3<0){ + OAMptr[0]=(uint8)SprX; + OAMptr[1]=(uint8)SprY; + OAMptr[2]=SprName; + OAMptr[3]=SprAttr; + *OAMptr2 &= ~(3<>12)>=w || (Y>>12)>=h){ + byte=0; + } else { + uint32 addr=(Y>>12)*w+(X>>12); + byte=Memory.C4RAM[0x600+(addr>>1)]; + if(addr&1) byte>>=4; + } + + // De-bitplanify + if(byte&1) Memory.C4RAM[outidx]|=bit; + if(byte&2) Memory.C4RAM[outidx+1]|=bit; + if(byte&4) Memory.C4RAM[outidx+16]|=bit; + if(byte&8) Memory.C4RAM[outidx+17]|=bit; + + bit>>=1; + if(bit==0){ + bit=0x80; + outidx+=32; + } + + X+=A; // Add 1 to output x => add an A and a C + Y+=C; + } + outidx+=2+row_padding; + if(outidx&0x10){ + outidx&=~0x10; + } else { + outidx-=w*4+row_padding; + } + LineX+=B; // Add 1 to output y => add a B and a D + LineY+=D; + } +} + +static void C4DrawLine(int32 X1, int32 Y1, int16 Z1, + int32 X2, int32 Y2, int16 Z2, uint8 Color){ + // Transform coordinates + C4WFXVal=(short)X1; + C4WFYVal=(short)Y1; + C4WFZVal=Z1; + C4WFScale=Memory.C4RAM[0x1f90]; + C4WFX2Val=Memory.C4RAM[0x1f86]; + C4WFY2Val=Memory.C4RAM[0x1f87]; + C4WFDist=Memory.C4RAM[0x1f88]; + C4TransfWireFrame2(); + X1=(C4WFXVal+48)<<8; + Y1=(C4WFYVal+48)<<8; + + C4WFXVal=(short)X2; + C4WFYVal=(short)Y2; + C4WFZVal=Z2; + C4TransfWireFrame2(); + X2=(C4WFXVal+48)<<8; + Y2=(C4WFYVal+48)<<8; + + // get line info + C4WFXVal=(short)(X1>>8); + C4WFYVal=(short)(Y1>>8); + C4WFX2Val=(short)(X2>>8); + C4WFY2Val=(short)(Y2>>8); + C4CalcWireFrame(); + X2=(int16)C4WFXVal; + Y2=(int16)C4WFYVal; + + // render line + int i; + for(i=C4WFDist?C4WFDist:1; i>0; i--) + { //.loop + if(X1>0xff && Y1>0xff && X1<0x6000 && Y1<0x6000) + { + uint16 addr=((X1&~0x7ff) + (Y1&~0x7ff)*12 + (Y1&0x700))>>7; + addr=(((Y1>>8)>>3)<<8)-(((Y1>>8)>>3)<<6)+(((X1>>8)>>3)<<4)+((Y1>>8)&7)*2; + uint8 bit=0x80>>((X1>>8)&7); + Memory.C4RAM[addr+0x300]&=~bit; + Memory.C4RAM[addr+0x301]&=~bit; + if(Color&1) Memory.C4RAM[addr+0x300]|=bit; + if(Color&2) Memory.C4RAM[addr+0x301]|=bit; + } + X1+=X2; + Y1+=Y2; + } +} + +static void C4DrawWireFrame(void) +{ + uint8 *line=C4GetMemPointer(READ_3WORD(Memory.C4RAM+0x1f80)); + uint8 *point1, *point2; + int16 X1, Y1, Z1; + int16 X2, Y2, Z2; + uint8 Color; + + int i; + for(i=Memory.C4RAM[0x0295]; i>0; i--, line+=5){ + if(line[0]==0xff && line[1]==0xff){ + uint8 *tmp=line-5; + while(tmp[2]==0xff && tmp[3]==0xff) tmp-=5; + point1=C4GetMemPointer((Memory.C4RAM[0x1f82]<<16) | (tmp[2]<<8) | tmp[3]); + } else { + point1=C4GetMemPointer((Memory.C4RAM[0x1f82]<<16) | (line[0]<<8) | line[1]); + } + point2=C4GetMemPointer((Memory.C4RAM[0x1f82]<<16) | (line[2]<<8) | line[3]); + + X1=(point1[0]<<8) | point1[1]; + Y1=(point1[2]<<8) | point1[3]; + Z1=(point1[4]<<8) | point1[5]; + X2=(point2[0]<<8) | point2[1]; + Y2=(point2[2]<<8) | point2[3]; + Z2=(point2[4]<<8) | point2[5]; + Color=line[4]; + C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color); + } +} + +static void C4TransformLines(void){ + C4WFX2Val=Memory.C4RAM[0x1f83]; + C4WFY2Val=Memory.C4RAM[0x1f86]; + C4WFDist=Memory.C4RAM[0x1f89]; + C4WFScale=Memory.C4RAM[0x1f8c]; + + // transform vertices + uint8 *ptr=Memory.C4RAM; + { + int i; + for(i=READ_WORD(Memory.C4RAM+0x1f80); i>0; i--, ptr+=0x10) + { + C4WFXVal=READ_WORD(ptr+1); + C4WFYVal=READ_WORD(ptr+5); + C4WFZVal=READ_WORD(ptr+9); + C4TransfWireFrame(); + + // displace + WRITE_WORD(ptr+1, C4WFXVal+0x80); + WRITE_WORD(ptr+5, C4WFYVal+0x50); + } + } + WRITE_WORD(Memory.C4RAM+0x600, 23); + WRITE_WORD(Memory.C4RAM+0x602, 0x60); + WRITE_WORD(Memory.C4RAM+0x605, 0x40); + WRITE_WORD(Memory.C4RAM+0x600+8, 23); + WRITE_WORD(Memory.C4RAM+0x602+8, 0x60); + WRITE_WORD(Memory.C4RAM+0x605+8, 0x40); + + ptr=Memory.C4RAM+0xb02; + uint8 *ptr2=Memory.C4RAM; + { + int i; + for(i=READ_WORD(Memory.C4RAM+0xb00); i>0; i--, ptr+=2, ptr2+=8) + { + C4WFXVal=READ_WORD(Memory.C4RAM+(ptr[0]<<4)+1); + C4WFYVal=READ_WORD(Memory.C4RAM+(ptr[0]<<4)+5); + C4WFX2Val=READ_WORD(Memory.C4RAM+(ptr[1]<<4)+1); + C4WFY2Val=READ_WORD(Memory.C4RAM+(ptr[1]<<4)+5); + C4CalcWireFrame(); + WRITE_WORD(ptr2+0x600, C4WFDist?C4WFDist:1); + WRITE_WORD(ptr2+0x602, C4WFXVal); + WRITE_WORD(ptr2+0x605, C4WFYVal); + } + } +} +static void C4BitPlaneWave(){ + static uint16 bmpdata[]={ + 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, 0x000E, + 0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020A, 0x020C, 0x020E, + 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E, + 0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060A, 0x060C, 0x060E, + 0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080A, 0x080C, 0x080E + }; + + uint8 *dst=Memory.C4RAM; + uint32 waveptr=Memory.C4RAM[0x1f83]; + uint16 mask1=0xc0c0; + uint16 mask2=0x3f3f; + + int j; + for(j=0; j<0x10; j++){ + do { + int16 height=-((int8)Memory.C4RAM[waveptr+0xb00])-16; + int i; + for(i=0; i<40; i++){ + uint16 tmp=READ_WORD(dst+bmpdata[i]) & mask2; + if(height>=0){ + if(height<8){ + tmp|=mask1&READ_WORD(Memory.C4RAM+0xa00+height*2); + } else { + tmp|=mask1&0xff00; + } + } + WRITE_WORD(dst+bmpdata[i], tmp); + height++; + } + waveptr=(waveptr+1)&0x7f; + mask1=(mask1>>2)|(mask1<<6); + mask2=(mask2>>2)|(mask2<<6); + } while(mask1!=0xc0c0); + dst+=16; + + do { + int16 height=-((int8)Memory.C4RAM[waveptr+0xb00])-16; + int i; + for(i=0; i<40; i++){ + uint16 tmp=READ_WORD(dst+bmpdata[i]) & mask2; + if(height>=0){ + if(height<8){ + tmp|=mask1&READ_WORD(Memory.C4RAM+0xa10+height*2); + } else { + tmp|=mask1&0xff00; + } + } + WRITE_WORD(dst+bmpdata[i], tmp); + height++; + } + waveptr=(waveptr+1)&0x7f; + mask1=(mask1>>2)|(mask1<<6); + mask2=(mask2>>2)|(mask2<<6); + } while(mask1!=0xc0c0); + dst+=16; + } +} + +static void C4SprDisintegrate() +{ + uint8 width, height; + uint32 StartX, StartY; + uint8 *src; + int32 scaleX, scaleY; + int32 Cx, Cy; + + width=Memory.C4RAM[0x1f89]; + height=Memory.C4RAM[0x1f8c]; + Cx=(int16)READ_WORD(Memory.C4RAM+0x1f80); + Cy=(int16)READ_WORD(Memory.C4RAM+0x1f83); + + scaleX=(int16)READ_WORD(Memory.C4RAM+0x1f86); + scaleY=(int16)READ_WORD(Memory.C4RAM+0x1f8f); + StartX=-Cx*scaleX+(Cx<<8); + StartY=-Cy*scaleY+(Cy<<8); + src=Memory.C4RAM+0x600; + + memset(Memory.C4RAM, 0, width*height/2); + + uint32 y, i; + for(y=StartY, i=0; i>8)>8)>8)*width+(x>>8)<0x2000) + { + uint8 pixel=(j&1)?(*src>>4):*src; + int idx=(y>>11)*width*4+(x>>11)*32+((y>>8)&7)*2; + uint8 mask=0x80>>((x>>8)&7); + if(pixel&1) Memory.C4RAM[idx]|=mask; + if(pixel&2) Memory.C4RAM[idx+1]|=mask; + if(pixel&4) Memory.C4RAM[idx+16]|=mask; + if(pixel&8) Memory.C4RAM[idx+17]|=mask; + } + if(j&1) src++; + } + } +} + +static void S9xC4ProcessSprites() +{ + switch(Memory.C4RAM[0x1f4d]) + { + case 0x00: // Build OAM + C4ConvOAM(); + break; + + case 0x03: // Scale/Rotate + C4DoScaleRotate(0); + break; + + case 0x05: // Transform Lines + C4TransformLines(); + break; + + case 0x07: // Scale/Rotate + C4DoScaleRotate(64); + break; + + case 0x08: // Draw wireframe + C4DrawWireFrame(); + break; + + case 0x0b: // Disintegrate + C4SprDisintegrate(); + break; + + case 0x0c: // Wave + C4BitPlaneWave(); + break; + + default: + break; + } +} + +void S9xSetC4 (uint8 byte, uint16 Address) +{ + int i; + + Memory.C4RAM [Address-0x6000] = byte; + if (Address == 0x7f4f) + { + if(Memory.C4RAM[0x1f4d]==0x0e && byte<0x40 && (byte&3)==0) + { + Memory.C4RAM[0x1f80]=byte>>2; + } + else + { + switch (byte) + { + case 0x00: // Sprite + S9xC4ProcessSprites(); + break; + + case 0x01: // Draw wireframe + memset(Memory.C4RAM+0x300, 0, 16*12*3*4); + C4DrawWireFrame(); + break; + + case 0x05: // Propulsion (?) + { + int32 tmp=0x10000; + if(READ_WORD(Memory.C4RAM+0x1f83)){ + tmp=SAR32((tmp/READ_WORD(Memory.C4RAM+0x1f83))*READ_WORD(Memory.C4RAM+0x1f81), 8); + } + WRITE_WORD(Memory.C4RAM+0x1f80, (uint16)tmp); + } + break; + + case 0x0d: // Set vector length + C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); + C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); + C41FDistVal=READ_WORD(Memory.C4RAM+0x1f86); + C4Op0D(); + WRITE_WORD(Memory.C4RAM+0x1f89, C41FXVal); + WRITE_WORD(Memory.C4RAM+0x1f8c, C41FYVal); + break; + + case 0x10: // Polar to rectangluar + { + int32 tmp=SAR32((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4CosTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 16); + WRITE_3WORD(Memory.C4RAM+0x1f86, tmp); + tmp=SAR32((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4SinTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 16); + WRITE_3WORD(Memory.C4RAM+0x1f89, (tmp-SAR32(tmp, 6))); + } + break; + + case 0x13: // Polar to rectangluar + { + int32 tmp=SAR32((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4CosTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 8); + WRITE_3WORD(Memory.C4RAM+0x1f86, tmp); + tmp=SAR32((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4SinTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 8); + WRITE_3WORD(Memory.C4RAM+0x1f89, tmp); + } + break; + + case 0x15: // Pythagorean + C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); + C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); + C41FDist=(int16)sqrtf((float)C41FXVal*C41FXVal + (float)C41FYVal*C41FYVal); + WRITE_WORD(Memory.C4RAM+0x1f80, C41FDist); + break; + + case 0x1f: // atan + C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); + C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); + C4Op1F(); + WRITE_WORD(Memory.C4RAM+0x1f86, C41FAngleRes); + break; + + case 0x22: // Trapezoid + { + int16 angle1=READ_WORD(Memory.C4RAM+0x1f8c)&0x1ff; + int16 angle2=READ_WORD(Memory.C4RAM+0x1f8f)&0x1ff; + int32 tan1=(C4CosTable[angle1]!=0)?((((int32)C4SinTable[angle1])<<16)/C4CosTable[angle1]):(int32)0x80000000; + int32 tan2=(C4CosTable[angle2]!=0)?((((int32)C4SinTable[angle2])<<16)/C4CosTable[angle2]):(int32)0x80000000; + int16 y = READ_WORD(Memory.C4RAM+0x1f83) - READ_WORD(Memory.C4RAM+0x1f89); + int16 left, right; + int j; + for(j=0; j<225; j++) + { + if(y>=0) + { + left = SAR32((int32)tan1*y, 16) - + READ_WORD(Memory.C4RAM+0x1f80) + + READ_WORD(Memory.C4RAM+0x1f86); + right = SAR32((int32)tan2*y, 16) - + READ_WORD(Memory.C4RAM+0x1f80) + + READ_WORD(Memory.C4RAM+0x1f86) + + READ_WORD(Memory.C4RAM+0x1f93); + + if(left<0 && right<0){ + left=1; + right=0; + } else if(left<0){ + left=0; + } else if(right<0){ + right=0; + } + if(left>255 && right>255){ + left=255; + right=254; + } else if(left>255){ + left=255; + } else if(right>255){ + right=255; + } + } + else + { + left=1; + right=0; + } + Memory.C4RAM[j+0x800] = (uint8)left; + Memory.C4RAM[j+0x900] = (uint8)right; + y++; + } + } + break; + + case 0x25: // Multiply + { + int32 foo=READ_3WORD(Memory.C4RAM+0x1f80); + int32 bar=READ_3WORD(Memory.C4RAM+0x1f83); + foo*=bar; + WRITE_3WORD(Memory.C4RAM+0x1f80, foo); + } + break; + + case 0x2d: // Transform Coords + C4WFXVal=READ_WORD(Memory.C4RAM+0x1f81); + C4WFYVal=READ_WORD(Memory.C4RAM+0x1f84); + C4WFZVal=READ_WORD(Memory.C4RAM+0x1f87); + C4WFX2Val=Memory.C4RAM[0x1f89]; + C4WFY2Val=Memory.C4RAM[0x1f8a]; + C4WFDist=Memory.C4RAM[0x1f8b]; + C4WFScale=READ_WORD(Memory.C4RAM+0x1f90); + C4TransfWireFrame2(); + WRITE_WORD(Memory.C4RAM+0x1f80, C4WFXVal); + WRITE_WORD(Memory.C4RAM+0x1f83, C4WFYVal); + break; + + case 0x40: // Sum + { + uint16 sum=0; + int i; + for(i=0; i<0x800; sum+=Memory.C4RAM[i++]); + WRITE_WORD(Memory.C4RAM+0x1f80, sum); + } + break; + + case 0x54: // Square + { + int64 a=SAR64((int64)READ_3WORD(Memory.C4RAM+0x1f80)<<40, 40); + // printf("%08X%08X\n", (uint32)(a>>32), (uint32)(a&0xFFFFFFFF)); + a*=a; + // printf("%08X%08X\n", (uint32)(a>>32), (uint32)(a&0xFFFFFFFF)); + WRITE_3WORD(Memory.C4RAM+0x1f83, a); + WRITE_3WORD(Memory.C4RAM+0x1f86, (a>>24)); + } + break; + + case 0x5c: // Immediate Reg + for (i = 0; i < 12 * 4; i++) + Memory.C4RAM [i] = C4TestPattern [i]; + break; + + case 0x89: // Immediate ROM + Memory.C4RAM [0x1f80] = 0x36; + Memory.C4RAM [0x1f81] = 0x43; + Memory.C4RAM [0x1f82] = 0x05; + break; + + default: + break; + } + } + } else if (Address == 0x7f47) { + memmove(Memory.C4RAM+(READ_WORD(Memory.C4RAM+0x1f45)&0x1fff), + C4GetMemPointer(READ_3WORD(Memory.C4RAM+0x1f40)), + READ_WORD(Memory.C4RAM+0x1f43)); + } +} + +int16 C4SinTable[512] = { + 0, 402, 804, 1206, 1607, 2009, 2410, 2811, + 3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997, + 6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126, + 9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167, + 12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090, + 15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869, + 18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475, + 20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884, + 23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073, + 25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020, + 27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707, + 28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117, + 30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237, + 31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057, + 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, + 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765, + 32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647, + 32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214, + 32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471, + 31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425, + 30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086, + 28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466, + 27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583, + 25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453, + 23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097, + 20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537, + 18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800, + 15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910, + 12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896, + 9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786, + 6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611, + 3211, 2811, 2410, 2009, 1607, 1206, 804, 402, + 0, -402, -804, -1206, -1607, -2009, -2410, -2811, + -3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997, + -6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126, + -9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167, + -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090, + -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869, + -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475, + -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884, + -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073, + -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020, + -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707, + -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117, + -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237, + -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057, + -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568, + -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765, + -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647, + -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214, + -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471, + -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425, + -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086, + -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466, + -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583, + -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453, + -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097, + -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537, + -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800, + -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910, + -12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896, + -9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786, + -6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611, + -3211, -2811, -2410, -2009, -1607, -1206, -804, -402 +}; + +int16 C4CosTable[512] = { + 32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647, + 32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214, + 32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471, + 31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425, + 30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086, + 28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466, + 27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583, + 25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453, + 23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097, + 20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537, + 18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800, + 15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910, + 12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896, + 9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786, + 6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611, + 3211, 2811, 2410, 2009, 1607, 1206, 804, 402, + 0, -402, -804, -1206, -1607, -2009, -2410, -2811, + -3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997, + -6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126, + -9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167, + -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090, + -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869, + -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475, + -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884, + -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073, + -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020, + -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707, + -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117, + -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237, + -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057, + -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568, + -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765, + -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647, + -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214, + -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471, + -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425, + -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086, + -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466, + -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583, + -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453, + -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097, + -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537, + -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800, + -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910, + -12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896, + -9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786, + -6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611, + -3211, -2811, -2410, -2009, -1607, -1206, -804, -402, + 0, 402, 804, 1206, 1607, 2009, 2410, 2811, + 3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997, + 6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126, + 9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167, + 12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090, + 15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869, + 18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475, + 20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884, + 23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073, + 25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020, + 27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707, + 28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117, + 30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237, + 31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057, + 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, + 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765 +}; diff --git a/src/c4emu.cpp b/src/c4emu.cpp deleted file mode 100644 index efe8cb8..0000000 --- a/src/c4emu.cpp +++ /dev/null @@ -1,876 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2003 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2002 - 2003 Matthew Kendora and - Brad Jorsch (anomie@users.sourceforge.net) - - - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and - Nach (n-a-c-h@users.sourceforge.net) - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2003 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman (jweidman@slip.net), - neviksti (neviksti@hotmail.com), and - Kris Bleakley (stinkfish@bigpond.com) - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2003 zsKnight, pagefault (pagefault@zsnes.com) - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar and Gary Henderson. - - - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ - -#ifndef __GP32__ -#ifdef HAVE_CONFIG_H - #include -#endif -#endif - -#include -#include "snes9x.h" -#include "sar.h" -#include "memmap.h" -#include "ppu.h" -#include "c4.h" - -void S9xInitC4 () -{ - // Stupid zsnes code, we can't do the logical thing without breaking - // savestates -// Memory.C4RAM = &Memory.FillRAM [0x6000]; - memset(Memory.C4RAM, 0, 0x2000); -} - -uint8 S9xGetC4 (uint16 Address) -{ - if(Address==0x7f5e) return 0; - return (Memory.C4RAM [Address-0x6000]); -} - -static uint8 C4TestPattern [12 * 4] = -{ - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x00, - 0x80, 0xff, 0xff, 0x7f, - 0x00, 0x80, 0x00, 0xff, - 0x7f, 0x00, 0xff, 0x7f, - 0xff, 0x7f, 0xff, 0xff, - 0x00, 0x00, 0x01, 0xff, - 0xff, 0xfe, 0x00, 0x01, - 0x00, 0xff, 0xfe, 0x00 -}; - - -static void C4ConvOAM(void){ - uint8 *OAMptr=Memory.C4RAM+(Memory.C4RAM[0x626]<<2); - for(uint8 *i=Memory.C4RAM+0x1fd; i>OAMptr; i-=4){ - // Clear OAM-to-be - *i=0xe0; - } - - uint16 globalX, globalY; - uint8 *OAMptr2; - int16 SprX, SprY; - uint8 SprName, SprAttr; - uint8 SprCount; - - globalX=READ_WORD(Memory.C4RAM+0x0621); - globalY=READ_WORD(Memory.C4RAM+0x0623); - OAMptr2=Memory.C4RAM+0x200+(Memory.C4RAM[0x626]>>2); - - if(Memory.C4RAM[0x0620]!=0){ - SprCount=128-Memory.C4RAM[0x626]; - uint8 offset=(Memory.C4RAM[0x626]&3)*2; - uint8 *srcptr=Memory.C4RAM+0x220; - for(int i=Memory.C4RAM[0x0620]; i>0 && SprCount>0; i--, srcptr+=16){ - SprX=READ_WORD(srcptr)-globalX; - SprY=READ_WORD(srcptr+2)-globalY; - SprName=srcptr[5]; - SprAttr=srcptr[4] | srcptr[0x06]; // XXX: mask bits? - - uint8 *sprptr=C4GetMemPointer(READ_3WORD(srcptr+7)); - if(*sprptr!=0){ - int16 X, Y; - for(int SprCnt=*sprptr++; SprCnt>0 && SprCount>0; SprCnt--, sprptr+=4){ - X=(int8)sprptr[1]; - if(SprAttr&0x40){ // flip X - X=-X-((sprptr[0]&0x20)?16:8); - } - X+=SprX; - if(X>=-16 && X<=272){ - Y=(int8)sprptr[2]; - if(SprAttr&0x80){ - Y=-Y-((sprptr[0]&0x20)?16:8); - } - Y+=SprY; - if(Y>=-16 && Y<=224){ - OAMptr[0]=X&0xff; - OAMptr[1]=(uint8)Y; - OAMptr[2]=SprName+sprptr[3]; - OAMptr[3]=SprAttr^(sprptr[0]&0xc0); // XXX: Carry from SprName addition? - *OAMptr2 &= ~(3<0){ - OAMptr[0]=(uint8)SprX; - OAMptr[1]=(uint8)SprY; - OAMptr[2]=SprName; - OAMptr[3]=SprAttr; - *OAMptr2 &= ~(3<>12)>=w || (Y>>12)>=h){ - byte=0; - } else { - uint32 addr=(Y>>12)*w+(X>>12); - byte=Memory.C4RAM[0x600+(addr>>1)]; - if(addr&1) byte>>=4; - } - - // De-bitplanify - if(byte&1) Memory.C4RAM[outidx]|=bit; - if(byte&2) Memory.C4RAM[outidx+1]|=bit; - if(byte&4) Memory.C4RAM[outidx+16]|=bit; - if(byte&8) Memory.C4RAM[outidx+17]|=bit; - - bit>>=1; - if(bit==0){ - bit=0x80; - outidx+=32; - } - - X+=A; // Add 1 to output x => add an A and a C - Y+=C; - } - outidx+=2+row_padding; - if(outidx&0x10){ - outidx&=~0x10; - } else { - outidx-=w*4+row_padding; - } - LineX+=B; // Add 1 to output y => add a B and a D - LineY+=D; - } -} - -static void C4DrawLine(int32 X1, int32 Y1, int16 Z1, - int32 X2, int32 Y2, int16 Z2, uint8 Color){ - // Transform coordinates - C4WFXVal=(short)X1; - C4WFYVal=(short)Y1; - C4WFZVal=Z1; - C4WFScale=Memory.C4RAM[0x1f90]; - C4WFX2Val=Memory.C4RAM[0x1f86]; - C4WFY2Val=Memory.C4RAM[0x1f87]; - C4WFDist=Memory.C4RAM[0x1f88]; - C4TransfWireFrame2(); - X1=(C4WFXVal+48)<<8; - Y1=(C4WFYVal+48)<<8; - - C4WFXVal=(short)X2; - C4WFYVal=(short)Y2; - C4WFZVal=Z2; - C4TransfWireFrame2(); - X2=(C4WFXVal+48)<<8; - Y2=(C4WFYVal+48)<<8; - - // get line info - C4WFXVal=(short)(X1>>8); - C4WFYVal=(short)(Y1>>8); - C4WFX2Val=(short)(X2>>8); - C4WFY2Val=(short)(Y2>>8); - C4CalcWireFrame(); - X2=(int16)C4WFXVal; - Y2=(int16)C4WFYVal; - - // render line - for(int i=C4WFDist?C4WFDist:1; i>0; i--) - { //.loop - if(X1>0xff && Y1>0xff && X1<0x6000 && Y1<0x6000) - { - uint16 addr=((X1&~0x7ff) + (Y1&~0x7ff)*12 + (Y1&0x700))>>7; - addr=(((Y1>>8)>>3)<<8)-(((Y1>>8)>>3)<<6)+(((X1>>8)>>3)<<4)+((Y1>>8)&7)*2; - uint8 bit=0x80>>((X1>>8)&7); - Memory.C4RAM[addr+0x300]&=~bit; - Memory.C4RAM[addr+0x301]&=~bit; - if(Color&1) Memory.C4RAM[addr+0x300]|=bit; - if(Color&2) Memory.C4RAM[addr+0x301]|=bit; - } - X1+=X2; - Y1+=Y2; - } -} - -static void C4DrawWireFrame(void) -{ - uint8 *line=C4GetMemPointer(READ_3WORD(Memory.C4RAM+0x1f80)); - uint8 *point1, *point2; - int16 X1, Y1, Z1; - int16 X2, Y2, Z2; - uint8 Color; - - for(int i=Memory.C4RAM[0x0295]; i>0; i--, line+=5){ - if(line[0]==0xff && line[1]==0xff){ - uint8 *tmp=line-5; - while(tmp[2]==0xff && tmp[3]==0xff) tmp-=5; - point1=C4GetMemPointer((Memory.C4RAM[0x1f82]<<16) | (tmp[2]<<8) | tmp[3]); - } else { - point1=C4GetMemPointer((Memory.C4RAM[0x1f82]<<16) | (line[0]<<8) | line[1]); - } - point2=C4GetMemPointer((Memory.C4RAM[0x1f82]<<16) | (line[2]<<8) | line[3]); - - X1=(point1[0]<<8) | point1[1]; - Y1=(point1[2]<<8) | point1[3]; - Z1=(point1[4]<<8) | point1[5]; - X2=(point2[0]<<8) | point2[1]; - Y2=(point2[2]<<8) | point2[3]; - Z2=(point2[4]<<8) | point2[5]; - Color=line[4]; - C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color); - } -} - -static void C4TransformLines(void){ - C4WFX2Val=Memory.C4RAM[0x1f83]; - C4WFY2Val=Memory.C4RAM[0x1f86]; - C4WFDist=Memory.C4RAM[0x1f89]; - C4WFScale=Memory.C4RAM[0x1f8c]; - - // transform vertices - uint8 *ptr=Memory.C4RAM; - { - for(int i=READ_WORD(Memory.C4RAM+0x1f80); i>0; i--, ptr+=0x10) - { - C4WFXVal=READ_WORD(ptr+1); - C4WFYVal=READ_WORD(ptr+5); - C4WFZVal=READ_WORD(ptr+9); - C4TransfWireFrame(); - - // displace - WRITE_WORD(ptr+1, C4WFXVal+0x80); - WRITE_WORD(ptr+5, C4WFYVal+0x50); - } - } - WRITE_WORD(Memory.C4RAM+0x600, 23); - WRITE_WORD(Memory.C4RAM+0x602, 0x60); - WRITE_WORD(Memory.C4RAM+0x605, 0x40); - WRITE_WORD(Memory.C4RAM+0x600+8, 23); - WRITE_WORD(Memory.C4RAM+0x602+8, 0x60); - WRITE_WORD(Memory.C4RAM+0x605+8, 0x40); - - ptr=Memory.C4RAM+0xb02; - uint8 *ptr2=Memory.C4RAM; - { - for(int i=READ_WORD(Memory.C4RAM+0xb00); i>0; i--, ptr+=2, ptr2+=8) - { - C4WFXVal=READ_WORD(Memory.C4RAM+(ptr[0]<<4)+1); - C4WFYVal=READ_WORD(Memory.C4RAM+(ptr[0]<<4)+5); - C4WFX2Val=READ_WORD(Memory.C4RAM+(ptr[1]<<4)+1); - C4WFY2Val=READ_WORD(Memory.C4RAM+(ptr[1]<<4)+5); - C4CalcWireFrame(); - WRITE_WORD(ptr2+0x600, C4WFDist?C4WFDist:1); - WRITE_WORD(ptr2+0x602, C4WFXVal); - WRITE_WORD(ptr2+0x605, C4WFYVal); - } - } -} -static void C4BitPlaneWave(){ - static uint16 bmpdata[]={ - 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000A, 0x000C, 0x000E, - 0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020A, 0x020C, 0x020E, - 0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E, - 0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060A, 0x060C, 0x060E, - 0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080A, 0x080C, 0x080E - }; - - uint8 *dst=Memory.C4RAM; - uint32 waveptr=Memory.C4RAM[0x1f83]; - uint16 mask1=0xc0c0; - uint16 mask2=0x3f3f; - - for(int j=0; j<0x10; j++){ - do { - int16 height=-((int8)Memory.C4RAM[waveptr+0xb00])-16; - for(int i=0; i<40; i++){ - uint16 tmp=READ_WORD(dst+bmpdata[i]) & mask2; - if(height>=0){ - if(height<8){ - tmp|=mask1&READ_WORD(Memory.C4RAM+0xa00+height*2); - } else { - tmp|=mask1&0xff00; - } - } - WRITE_WORD(dst+bmpdata[i], tmp); - height++; - } - waveptr=(waveptr+1)&0x7f; - mask1=(mask1>>2)|(mask1<<6); - mask2=(mask2>>2)|(mask2<<6); - } while(mask1!=0xc0c0); - dst+=16; - - do { - int16 height=-((int8)Memory.C4RAM[waveptr+0xb00])-16; - for(int i=0; i<40; i++){ - uint16 tmp=READ_WORD(dst+bmpdata[i]) & mask2; - if(height>=0){ - if(height<8){ - tmp|=mask1&READ_WORD(Memory.C4RAM+0xa10+height*2); - } else { - tmp|=mask1&0xff00; - } - } - WRITE_WORD(dst+bmpdata[i], tmp); - height++; - } - waveptr=(waveptr+1)&0x7f; - mask1=(mask1>>2)|(mask1<<6); - mask2=(mask2>>2)|(mask2<<6); - } while(mask1!=0xc0c0); - dst+=16; - } -} - -static void C4SprDisintegrate() -{ - uint8 width, height; - uint32 StartX, StartY; - uint8 *src; - int32 scaleX, scaleY; - int32 Cx, Cy; - - width=Memory.C4RAM[0x1f89]; - height=Memory.C4RAM[0x1f8c]; - Cx=(int16)READ_WORD(Memory.C4RAM+0x1f80); - Cy=(int16)READ_WORD(Memory.C4RAM+0x1f83); - - scaleX=(int16)READ_WORD(Memory.C4RAM+0x1f86); - scaleY=(int16)READ_WORD(Memory.C4RAM+0x1f8f); - StartX=-Cx*scaleX+(Cx<<8); - StartY=-Cy*scaleY+(Cy<<8); - src=Memory.C4RAM+0x600; - - memset(Memory.C4RAM, 0, width*height/2); - - for(uint32 y=StartY, i=0; i>8)>8)>8)*width+(x>>8)<0x2000) - { - uint8 pixel=(j&1)?(*src>>4):*src; - int idx=(y>>11)*width*4+(x>>11)*32+((y>>8)&7)*2; - uint8 mask=0x80>>((x>>8)&7); - if(pixel&1) Memory.C4RAM[idx]|=mask; - if(pixel&2) Memory.C4RAM[idx+1]|=mask; - if(pixel&4) Memory.C4RAM[idx+16]|=mask; - if(pixel&8) Memory.C4RAM[idx+17]|=mask; - } - if(j&1) src++; - } - } -} - -static void S9xC4ProcessSprites() -{ - switch(Memory.C4RAM[0x1f4d]) - { - case 0x00: // Build OAM - C4ConvOAM(); - break; - - case 0x03: // Scale/Rotate - C4DoScaleRotate(0); - break; - - case 0x05: // Transform Lines - C4TransformLines(); - break; - - case 0x07: // Scale/Rotate - C4DoScaleRotate(64); - break; - - case 0x08: // Draw wireframe - C4DrawWireFrame(); - break; - - case 0x0b: // Disintegrate - C4SprDisintegrate(); - break; - - case 0x0c: // Wave - C4BitPlaneWave(); - break; - - default: - break; - } -} - -void S9xSetC4 (uint8 byte, uint16 Address) -{ - int i; - - Memory.C4RAM [Address-0x6000] = byte; - if (Address == 0x7f4f) - { - if(Memory.C4RAM[0x1f4d]==0x0e && byte<0x40 && (byte&3)==0) - { - Memory.C4RAM[0x1f80]=byte>>2; - } - else - { - switch (byte) - { - case 0x00: // Sprite - S9xC4ProcessSprites(); - break; - - case 0x01: // Draw wireframe - memset(Memory.C4RAM+0x300, 0, 16*12*3*4); - C4DrawWireFrame(); - break; - - case 0x05: // Propulsion (?) - { - int32 tmp=0x10000; - if(READ_WORD(Memory.C4RAM+0x1f83)){ - tmp=SAR((tmp/READ_WORD(Memory.C4RAM+0x1f83))*READ_WORD(Memory.C4RAM+0x1f81), 8); - } - WRITE_WORD(Memory.C4RAM+0x1f80, (uint16)tmp); - } - break; - - case 0x0d: // Set vector length - C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); - C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); - C41FDistVal=READ_WORD(Memory.C4RAM+0x1f86); - C4Op0D(); - WRITE_WORD(Memory.C4RAM+0x1f89, C41FXVal); - WRITE_WORD(Memory.C4RAM+0x1f8c, C41FYVal); - break; - - case 0x10: // Polar to rectangluar - { - int32 tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4CosTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 16); - WRITE_3WORD(Memory.C4RAM+0x1f86, tmp); - tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4SinTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 16); - WRITE_3WORD(Memory.C4RAM+0x1f89, (tmp-SAR(tmp, 6))); - } - break; - - case 0x13: // Polar to rectangluar - { - int32 tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4CosTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 8); - WRITE_3WORD(Memory.C4RAM+0x1f86, tmp); - tmp=SAR((int32)READ_WORD(Memory.C4RAM+0x1f83)*C4SinTable[READ_WORD(Memory.C4RAM+0x1f80)&0x1ff]*2, 8); - WRITE_3WORD(Memory.C4RAM+0x1f89, tmp); - } - break; - - case 0x15: // Pythagorean - C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); - C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); - C41FDist=(int16)sqrtf((float)C41FXVal*C41FXVal + (float)C41FYVal*C41FYVal); - WRITE_WORD(Memory.C4RAM+0x1f80, C41FDist); - break; - - case 0x1f: // atan - C41FXVal=READ_WORD(Memory.C4RAM+0x1f80); - C41FYVal=READ_WORD(Memory.C4RAM+0x1f83); - C4Op1F(); - WRITE_WORD(Memory.C4RAM+0x1f86, C41FAngleRes); - break; - - case 0x22: // Trapezoid - { - int16 angle1=READ_WORD(Memory.C4RAM+0x1f8c)&0x1ff; - int16 angle2=READ_WORD(Memory.C4RAM+0x1f8f)&0x1ff; - int32 tan1=(C4CosTable[angle1]!=0)?((((int32)C4SinTable[angle1])<<16)/C4CosTable[angle1]):0x80000000; - int32 tan2=(C4CosTable[angle2]!=0)?((((int32)C4SinTable[angle2])<<16)/C4CosTable[angle2]):0x80000000; - int16 y = READ_WORD(Memory.C4RAM+0x1f83) - READ_WORD(Memory.C4RAM+0x1f89); - int16 left, right; - for(int j=0; j<225; j++) - { - if(y>=0) - { - left = SAR((int32)tan1*y, 16) - - READ_WORD(Memory.C4RAM+0x1f80) + - READ_WORD(Memory.C4RAM+0x1f86); - right = SAR((int32)tan2*y, 16) - - READ_WORD(Memory.C4RAM+0x1f80) + - READ_WORD(Memory.C4RAM+0x1f86) + - READ_WORD(Memory.C4RAM+0x1f93); - - if(left<0 && right<0){ - left=1; - right=0; - } else if(left<0){ - left=0; - } else if(right<0){ - right=0; - } - if(left>255 && right>255){ - left=255; - right=254; - } else if(left>255){ - left=255; - } else if(right>255){ - right=255; - } - } - else - { - left=1; - right=0; - } - Memory.C4RAM[j+0x800] = (uint8)left; - Memory.C4RAM[j+0x900] = (uint8)right; - y++; - } - } - break; - - case 0x25: // Multiply - { - int32 foo=READ_3WORD(Memory.C4RAM+0x1f80); - int32 bar=READ_3WORD(Memory.C4RAM+0x1f83); - foo*=bar; - WRITE_3WORD(Memory.C4RAM+0x1f80, foo); - } - break; - - case 0x2d: // Transform Coords - C4WFXVal=READ_WORD(Memory.C4RAM+0x1f81); - C4WFYVal=READ_WORD(Memory.C4RAM+0x1f84); - C4WFZVal=READ_WORD(Memory.C4RAM+0x1f87); - C4WFX2Val=Memory.C4RAM[0x1f89]; - C4WFY2Val=Memory.C4RAM[0x1f8a]; - C4WFDist=Memory.C4RAM[0x1f8b]; - C4WFScale=READ_WORD(Memory.C4RAM+0x1f90); - C4TransfWireFrame2(); - WRITE_WORD(Memory.C4RAM+0x1f80, C4WFXVal); - WRITE_WORD(Memory.C4RAM+0x1f83, C4WFYVal); - break; - - case 0x40: // Sum - { - uint16 sum=0; - for(int i=0; i<0x800; sum+=Memory.C4RAM[i++]); - WRITE_WORD(Memory.C4RAM+0x1f80, sum); - } - break; - - case 0x54: // Square - { - int64 a=SAR((int64)READ_3WORD(Memory.C4RAM+0x1f80)<<40, 40); - // printf("%08X%08X\n", (uint32)(a>>32), (uint32)(a&0xFFFFFFFF)); - a*=a; - // printf("%08X%08X\n", (uint32)(a>>32), (uint32)(a&0xFFFFFFFF)); - WRITE_3WORD(Memory.C4RAM+0x1f83, a); - WRITE_3WORD(Memory.C4RAM+0x1f86, (a>>24)); - } - break; - - case 0x5c: // Immediate Reg - for (i = 0; i < 12 * 4; i++) - Memory.C4RAM [i] = C4TestPattern [i]; - break; - - case 0x89: // Immediate ROM - Memory.C4RAM [0x1f80] = 0x36; - Memory.C4RAM [0x1f81] = 0x43; - Memory.C4RAM [0x1f82] = 0x05; - break; - - default: - break; - } - } - } else if (Address == 0x7f47) { - memmove(Memory.C4RAM+(READ_WORD(Memory.C4RAM+0x1f45)&0x1fff), - C4GetMemPointer(READ_3WORD(Memory.C4RAM+0x1f40)), - READ_WORD(Memory.C4RAM+0x1f43)); - } -} - -int16 C4SinTable[512] = { - 0, 402, 804, 1206, 1607, 2009, 2410, 2811, - 3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997, - 6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126, - 9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167, - 12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090, - 15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869, - 18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475, - 20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884, - 23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073, - 25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020, - 27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707, - 28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117, - 30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237, - 31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057, - 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, - 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765, - 32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647, - 32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214, - 32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471, - 31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425, - 30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086, - 28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466, - 27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583, - 25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453, - 23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097, - 20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537, - 18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800, - 15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910, - 12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896, - 9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786, - 6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611, - 3211, 2811, 2410, 2009, 1607, 1206, 804, 402, - 0, -402, -804, -1206, -1607, -2009, -2410, -2811, - -3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997, - -6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126, - -9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167, - -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090, - -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869, - -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475, - -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884, - -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073, - -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020, - -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707, - -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117, - -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237, - -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057, - -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568, - -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765, - -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647, - -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214, - -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471, - -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425, - -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086, - -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466, - -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583, - -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453, - -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097, - -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537, - -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800, - -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910, - -12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896, - -9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786, - -6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611, - -3211, -2811, -2410, -2009, -1607, -1206, -804, -402 -}; - -int16 C4CosTable[512] = { - 32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647, - 32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214, - 32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471, - 31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425, - 30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086, - 28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466, - 27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583, - 25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453, - 23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097, - 20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537, - 18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800, - 15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910, - 12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896, - 9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786, - 6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611, - 3211, 2811, 2410, 2009, 1607, 1206, 804, 402, - 0, -402, -804, -1206, -1607, -2009, -2410, -2811, - -3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997, - -6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126, - -9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167, - -12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090, - -15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869, - -18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475, - -20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884, - -23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073, - -25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020, - -27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707, - -28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117, - -30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237, - -31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057, - -32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568, - -32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765, - -32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647, - -32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214, - -32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471, - -31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425, - -30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086, - -28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466, - -27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583, - -25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453, - -23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097, - -20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537, - -18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800, - -15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910, - -12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896, - -9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786, - -6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611, - -3211, -2811, -2410, -2009, -1607, -1206, -804, -402, - 0, 402, 804, 1206, 1607, 2009, 2410, 2811, - 3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997, - 6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126, - 9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167, - 12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090, - 15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869, - 18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475, - 20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884, - 23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073, - 25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020, - 27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707, - 28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117, - 30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237, - 31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057, - 32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568, - 32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765 -}; diff --git a/src/cheats.c b/src/cheats.c new file mode 100644 index 0000000..863f174 --- /dev/null +++ b/src/cheats.c @@ -0,0 +1,393 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include +#include +#include +#include "snes9x.h" +#include "cheats.h" +#include "memmap.h" + +static bool8 S9xAllHex (const char *code, int len) +{ + int i; + for (i = 0; i < len; i++) + if ((code [i] < '0' || code [i] > '9') && + (code [i] < 'a' || code [i] > 'f') && + (code [i] < 'A' || code [i] > 'F')) + return (FALSE); + + return (TRUE); +} + +const char *S9xProActionReplayToRaw (const char *code, uint32* address, uint8* byte) +{ + uint32 data = 0; + if (strlen (code) != 8 || !S9xAllHex (code, 8) || + sscanf (code, "%x", &data) != 1) + return ("Invalid Pro Action Replay code - should be 8 hex digits in length."); + + *address = data >> 8; + *byte = (uint8) data; + return (NULL); +} + +const char *S9xGoldFingerToRaw (const char *code, uint32* address, bool8* sram, + uint8* num_bytes, uint8 bytes[3]) +{ + char tmp [15]; + if (strlen (code) != 14) + return ("Invalid Gold Finger code should be 14 hex digits in length."); + + strncpy (tmp, code, 5); + tmp [5] = 0; + if (sscanf (tmp, "%x", address) != 1) + return ("Invalid Gold Finger code."); + + int i; + for (i = 0; i < 3; i++) + { + strncpy (tmp, code + 5 + i * 2, 2); + tmp [2] = 0; + int byte; + if (sscanf (tmp, "%x", &byte) != 1) + break; + bytes [i] = (uint8) byte; + } + *num_bytes = i; + *sram = code [13] == '1'; + return (NULL); +} + +const char *S9xGameGenieToRaw (const char *code, uint32* address, uint8* byte) +{ + char new_code [12]; + + if (strlen (code) != 9 || *(code + 4) != '-' || !S9xAllHex (code, 4) || + !S9xAllHex (code + 5, 4)) + return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'."); + + strcpy (new_code, "0x"); + strncpy (new_code + 2, code, 4); + strcpy (new_code + 6, code + 5); + + static char *real_hex = "0123456789ABCDEF"; + static char *genie_hex = "DF4709156BC8A23E"; + + int i; + for (i = 2; i < 10; i++) + { + if (islower (new_code [i])) + new_code [i] = toupper (new_code [i]); + int j; + for (j = 0; j < 16; j++) + { + if (new_code [i] == genie_hex [j]) + { + new_code [i] = real_hex [j]; + break; + } + } + if (j == 16) + return ("Invalid hex-character in Game Genie(tm) code"); + } + uint32 data = 0; + sscanf (new_code, "%x", &data); + *byte = (uint8)(data >> 24); + *address = data & 0xffffff; + *address = ((*address & 0x003c00) << 10) + + ((*address & 0x00003c) << 14) + + ((*address & 0xf00000) >> 8) + + ((*address & 0x000003) << 10) + + ((*address & 0x00c000) >> 6) + + ((*address & 0x0f0000) >> 12) + + ((*address & 0x0003c0) >> 6); + + return (NULL); +} + +void S9xStartCheatSearch (SCheatData *d) +{ + memmove (d->CWRAM, d->RAM, 0x20000); + memmove (d->CSRAM, d->SRAM, 0x10000); + memmove (d->CIRAM, &d->FillRAM [0x3000], 0x2000); + memset ((char *) d->WRAM_BITS, 0xff, 0x20000 >> 3); + memset ((char *) d->SRAM_BITS, 0xff, 0x10000 >> 3); + memset ((char *) d->IRAM_BITS, 0xff, 0x2000 >> 3); +} + +#define BIT_CLEAR(a,v) \ +(a)[(v) >> 5] &= ~(1 << ((v) & 31)) + +#define BIT_SET(a,v) \ +(a)[(v) >> 5] |= 1 << ((v) & 31) + +#define TEST_BIT(a,v) \ +((a)[(v) >> 5] & (1 << ((v) & 31))) + +#define _C(c,a,b) \ +((c) == S9X_LESS_THAN ? (a) < (b) : \ + (c) == S9X_GREATER_THAN ? (a) > (b) : \ + (c) == S9X_LESS_THAN_OR_EQUAL ? (a) <= (b) : \ + (c) == S9X_GREATER_THAN_OR_EQUAL ? (a) >= (b) : \ + (c) == S9X_EQUAL ? (a) == (b) : \ + (a) != (b)) + +#define _D(s,m,o) \ +((s) == S9X_8_BITS ? (uint8) (*((m) + (o))) : \ + (s) == S9X_16_BITS ? ((uint16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ + (s) == S9X_24_BITS ? ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16))) : \ +((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) + +#define _DS(s,m,o) \ +((s) == S9X_8_BITS ? ((int8) *((m) + (o))) : \ + (s) == S9X_16_BITS ? ((int16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ + (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ + ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) + +void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, + S9xCheatDataSize size, bool8 is_signed, bool8 update) +{ + int l; + + switch (size) + { + case S9X_8_BITS: l = 0; break; + case S9X_16_BITS: l = 1; break; + case S9X_24_BITS: l = 2; break; + default: + case S9X_32_BITS: l = 3; break; + } + + int i; + if (is_signed) + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, _DS(size, d->RAM, i), _DS(size, d->CWRAM, i))) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, _DS(size, d->SRAM, i), _DS(size, d->CSRAM, i))) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, _DS(size, d->FillRAM + 0x3000, i), _DS(size, d->CIRAM, i))) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } + else + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, _D(size, d->RAM, i), _D(size, d->CWRAM, i))) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, _D(size, d->SRAM, i), _D(size, d->CSRAM, i))) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, _D(size, d->FillRAM + 0x3000, i), _D(size, d->CIRAM, i))) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } +} + +void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, + S9xCheatDataSize size, uint32 value, + bool8 is_signed, bool8 update) +{ + int l; + + switch (size) + { + case S9X_8_BITS: l = 0; break; + case S9X_16_BITS: l = 1; break; + case S9X_24_BITS: l = 2; break; + default: + case S9X_32_BITS: l = 3; break; + } + + int i; + + if (is_signed) + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, _DS(size, d->RAM, i), (int32) value)) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, _DS(size, d->SRAM, i), (int32) value)) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, _DS(size, d->FillRAM + 0x3000, i), (int32) value)) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } + else + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT (d->WRAM_BITS, i) && + _C(cmp, _D(size, d->RAM, i), value)) + { + if (update) + d->CWRAM [i] = d->RAM [i]; + } + else + BIT_CLEAR (d->WRAM_BITS, i); + } + + for (i = 0; i < 0x10000 - l; i++) + { + if (TEST_BIT (d->SRAM_BITS, i) && + _C(cmp, _D(size, d->SRAM, i), value)) + { + if (update) + d->CSRAM [i] = d->SRAM [i]; + } + else + BIT_CLEAR (d->SRAM_BITS, i); + } + + for (i = 0; i < 0x2000 - l; i++) + { + if (TEST_BIT (d->IRAM_BITS, i) && + _C(cmp, _D(size, d->FillRAM + 0x3000, i), value)) + { + if (update) + d->CIRAM [i] = d->FillRAM [i + 0x3000]; + } + else + BIT_CLEAR (d->IRAM_BITS, i); + } + } +} + +void S9xOutputCheatSearchResults (SCheatData *d) +{ + int i; + for (i = 0; i < 0x20000; i++) + { + if (TEST_BIT (d->WRAM_BITS, i)) + printf ("WRAM: %05x: %02x\n", i, d->RAM [i]); + } + + for (i = 0; i < 0x10000; i++) + { + if (TEST_BIT (d->SRAM_BITS, i)) + printf ("SRAM: %04x: %02x\n", i, d->SRAM [i]); + } + + for (i = 0; i < 0x2000; i++) + { + if (TEST_BIT (d->IRAM_BITS, i)) + printf ("IRAM: %05x: %02x\n", i, d->FillRAM [i + 0x3000]); + } +} diff --git a/src/cheats.cpp b/src/cheats.cpp deleted file mode 100644 index 966e0b9..0000000 --- a/src/cheats.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include -#include -#include -#include "snes9x.h" -#include "cheats.h" -#include "memmap.h" - -static bool8 S9xAllHex (const char *code, int len) -{ - for (int i = 0; i < len; i++) - if ((code [i] < '0' || code [i] > '9') && - (code [i] < 'a' || code [i] > 'f') && - (code [i] < 'A' || code [i] > 'F')) - return (FALSE); - - return (TRUE); -} - -const char *S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte) -{ - uint32 data = 0; - if (strlen (code) != 8 || !S9xAllHex (code, 8) || - sscanf (code, "%x", &data) != 1) - return ("Invalid Pro Action Replay code - should be 8 hex digits in length."); - - address = data >> 8; - byte = (uint8) data; - return (NULL); -} - -const char *S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, - uint8 &num_bytes, uint8 bytes[3]) -{ - char tmp [15]; - if (strlen (code) != 14) - return ("Invalid Gold Finger code should be 14 hex digits in length."); - - strncpy (tmp, code, 5); - tmp [5] = 0; - if (sscanf (tmp, "%x", &address) != 1) - return ("Invalid Gold Finger code."); - - int i; - for (i = 0; i < 3; i++) - { - strncpy (tmp, code + 5 + i * 2, 2); - tmp [2] = 0; - int byte; - if (sscanf (tmp, "%x", &byte) != 1) - break; - bytes [i] = (uint8) byte; - } - num_bytes = i; - sram = code [13] == '1'; - return (NULL); -} - -const char *S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte) -{ - char new_code [12]; - - if (strlen (code) != 9 || *(code + 4) != '-' || !S9xAllHex (code, 4) || - !S9xAllHex (code + 5, 4)) - return ("Invalid Game Genie(tm) code - should be 'xxxx-xxxx'."); - - strcpy (new_code, "0x"); - strncpy (new_code + 2, code, 4); - strcpy (new_code + 6, code + 5); - - static char *real_hex = "0123456789ABCDEF"; - static char *genie_hex = "DF4709156BC8A23E"; - - for (int i = 2; i < 10; i++) - { - if (islower (new_code [i])) - new_code [i] = toupper (new_code [i]); - int j; - for (j = 0; j < 16; j++) - { - if (new_code [i] == genie_hex [j]) - { - new_code [i] = real_hex [j]; - break; - } - } - if (j == 16) - return ("Invalid hex-character in Game Genie(tm) code"); - } - uint32 data = 0; - sscanf (new_code, "%x", &data); - byte = (uint8)(data >> 24); - address = data & 0xffffff; - address = ((address & 0x003c00) << 10) + - ((address & 0x00003c) << 14) + - ((address & 0xf00000) >> 8) + - ((address & 0x000003) << 10) + - ((address & 0x00c000) >> 6) + - ((address & 0x0f0000) >> 12) + - ((address & 0x0003c0) >> 6); - - return (NULL); -} - -void S9xStartCheatSearch (SCheatData *d) -{ - memmove (d->CWRAM, d->RAM, 0x20000); - memmove (d->CSRAM, d->SRAM, 0x10000); - memmove (d->CIRAM, &d->FillRAM [0x3000], 0x2000); - memset ((char *) d->WRAM_BITS, 0xff, 0x20000 >> 3); - memset ((char *) d->SRAM_BITS, 0xff, 0x10000 >> 3); - memset ((char *) d->IRAM_BITS, 0xff, 0x2000 >> 3); -} - -#define BIT_CLEAR(a,v) \ -(a)[(v) >> 5] &= ~(1 << ((v) & 31)) - -#define BIT_SET(a,v) \ -(a)[(v) >> 5] |= 1 << ((v) & 31) - -#define TEST_BIT(a,v) \ -((a)[(v) >> 5] & (1 << ((v) & 31))) - -#define _C(c,a,b) \ -((c) == S9X_LESS_THAN ? (a) < (b) : \ - (c) == S9X_GREATER_THAN ? (a) > (b) : \ - (c) == S9X_LESS_THAN_OR_EQUAL ? (a) <= (b) : \ - (c) == S9X_GREATER_THAN_OR_EQUAL ? (a) >= (b) : \ - (c) == S9X_EQUAL ? (a) == (b) : \ - (a) != (b)) - -#define _D(s,m,o) \ -((s) == S9X_8_BITS ? (uint8) (*((m) + (o))) : \ - (s) == S9X_16_BITS ? ((uint16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ - (s) == S9X_24_BITS ? ((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16))) : \ -((uint32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) - -#define _DS(s,m,o) \ -((s) == S9X_8_BITS ? ((int8) *((m) + (o))) : \ - (s) == S9X_16_BITS ? ((int16) (*((m) + (o)) + (*((m) + (o) + 1) << 8))) : \ - (s) == S9X_24_BITS ? (((int32) ((*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16)) << 8)) >> 8): \ - ((int32) (*((m) + (o)) + (*((m) + (o) + 1) << 8) + (*((m) + (o) + 2) << 16) + (*((m) + (o) + 3) << 24)))) - -void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, - S9xCheatDataSize size, bool8 is_signed, bool8 update) -{ - int l; - - switch (size) - { - case S9X_8_BITS: l = 0; break; - case S9X_16_BITS: l = 1; break; - case S9X_24_BITS: l = 2; break; - default: - case S9X_32_BITS: l = 3; break; - } - - int i; - if (is_signed) - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT (d->WRAM_BITS, i) && - _C(cmp, _DS(size, d->RAM, i), _DS(size, d->CWRAM, i))) - { - if (update) - d->CWRAM [i] = d->RAM [i]; - } - else - BIT_CLEAR (d->WRAM_BITS, i); - } - - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT (d->SRAM_BITS, i) && - _C(cmp, _DS(size, d->SRAM, i), _DS(size, d->CSRAM, i))) - { - if (update) - d->CSRAM [i] = d->SRAM [i]; - } - else - BIT_CLEAR (d->SRAM_BITS, i); - } - - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT (d->IRAM_BITS, i) && - _C(cmp, _DS(size, d->FillRAM + 0x3000, i), _DS(size, d->CIRAM, i))) - { - if (update) - d->CIRAM [i] = d->FillRAM [i + 0x3000]; - } - else - BIT_CLEAR (d->IRAM_BITS, i); - } - } - else - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT (d->WRAM_BITS, i) && - _C(cmp, _D(size, d->RAM, i), _D(size, d->CWRAM, i))) - { - if (update) - d->CWRAM [i] = d->RAM [i]; - } - else - BIT_CLEAR (d->WRAM_BITS, i); - } - - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT (d->SRAM_BITS, i) && - _C(cmp, _D(size, d->SRAM, i), _D(size, d->CSRAM, i))) - { - if (update) - d->CSRAM [i] = d->SRAM [i]; - } - else - BIT_CLEAR (d->SRAM_BITS, i); - } - - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT (d->IRAM_BITS, i) && - _C(cmp, _D(size, d->FillRAM + 0x3000, i), _D(size, d->CIRAM, i))) - { - if (update) - d->CIRAM [i] = d->FillRAM [i + 0x3000]; - } - else - BIT_CLEAR (d->IRAM_BITS, i); - } - } -} - -void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, - S9xCheatDataSize size, uint32 value, - bool8 is_signed, bool8 update) -{ - int l; - - switch (size) - { - case S9X_8_BITS: l = 0; break; - case S9X_16_BITS: l = 1; break; - case S9X_24_BITS: l = 2; break; - default: - case S9X_32_BITS: l = 3; break; - } - - int i; - - if (is_signed) - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT (d->WRAM_BITS, i) && - _C(cmp, _DS(size, d->RAM, i), (int32) value)) - { - if (update) - d->CWRAM [i] = d->RAM [i]; - } - else - BIT_CLEAR (d->WRAM_BITS, i); - } - - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT (d->SRAM_BITS, i) && - _C(cmp, _DS(size, d->SRAM, i), (int32) value)) - { - if (update) - d->CSRAM [i] = d->SRAM [i]; - } - else - BIT_CLEAR (d->SRAM_BITS, i); - } - - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT (d->IRAM_BITS, i) && - _C(cmp, _DS(size, d->FillRAM + 0x3000, i), (int32) value)) - { - if (update) - d->CIRAM [i] = d->FillRAM [i + 0x3000]; - } - else - BIT_CLEAR (d->IRAM_BITS, i); - } - } - else - { - for (i = 0; i < 0x20000 - l; i++) - { - if (TEST_BIT (d->WRAM_BITS, i) && - _C(cmp, _D(size, d->RAM, i), value)) - { - if (update) - d->CWRAM [i] = d->RAM [i]; - } - else - BIT_CLEAR (d->WRAM_BITS, i); - } - - for (i = 0; i < 0x10000 - l; i++) - { - if (TEST_BIT (d->SRAM_BITS, i) && - _C(cmp, _D(size, d->SRAM, i), value)) - { - if (update) - d->CSRAM [i] = d->SRAM [i]; - } - else - BIT_CLEAR (d->SRAM_BITS, i); - } - - for (i = 0; i < 0x2000 - l; i++) - { - if (TEST_BIT (d->IRAM_BITS, i) && - _C(cmp, _D(size, d->FillRAM + 0x3000, i), value)) - { - if (update) - d->CIRAM [i] = d->FillRAM [i + 0x3000]; - } - else - BIT_CLEAR (d->IRAM_BITS, i); - } - } -} - -void S9xOutputCheatSearchResults (SCheatData *d) -{ - int i; - for (i = 0; i < 0x20000; i++) - { - if (TEST_BIT (d->WRAM_BITS, i)) - printf ("WRAM: %05x: %02x\n", i, d->RAM [i]); - } - - for (i = 0; i < 0x10000; i++) - { - if (TEST_BIT (d->SRAM_BITS, i)) - printf ("SRAM: %04x: %02x\n", i, d->SRAM [i]); - } - - for (i = 0; i < 0x2000; i++) - { - if (TEST_BIT (d->IRAM_BITS, i)) - printf ("IRAM: %05x: %02x\n", i, d->FillRAM [i + 0x3000]); - } -} diff --git a/src/cheats.h b/src/cheats.h index 0ac09ec..ca800b4 100644 --- a/src/cheats.h +++ b/src/cheats.h @@ -53,7 +53,7 @@ struct SCheat #define MAX_CHEATS 75 -struct SCheatData +typedef struct { struct SCheat c [MAX_CHEATS]; uint32 num_cheats; @@ -66,7 +66,7 @@ struct SCheatData uint32 WRAM_BITS [0x20000 >> 3]; uint32 SRAM_BITS [0x10000 >> 3]; uint32 IRAM_BITS [0x2000 >> 3]; -}; +}SCheatData; typedef enum { @@ -81,10 +81,10 @@ typedef enum void S9xInitCheatData (); -const char *S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte); -const char *S9xProActionReplayToRaw (const char *code, uint32 &address, uint8 &byte); -const char *S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram, - uint8 &num_bytes, uint8 bytes[3]); +const char *S9xGameGenieToRaw (const char *code, uint32 *address, uint8 *byte); +const char *S9xProActionReplayToRaw (const char *code, uint32 *address, uint8 *byte); +const char *S9xGoldFingerToRaw (const char *code, uint32* address, bool8* sram, + uint8* num_bytes, uint8 bytes[3]); void S9xApplyCheats (); void S9xApplyCheat (uint32 which1); void S9xRemoveCheats (); diff --git a/src/cheats2.c b/src/cheats2.c new file mode 100644 index 0000000..3e8017e --- /dev/null +++ b/src/cheats2.c @@ -0,0 +1,232 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include +#include +#include +#include "snes9x.h" +#include "cheats.h" +#include "memmap.h" + +extern SCheatData Cheat; + +void S9xInitCheatData () +{ + Cheat.RAM = Memory.RAM; + Cheat.SRAM = SRAM; + Cheat.FillRAM = Memory.FillRAM; +} + +void S9xAddCheat (bool8 enable, bool8 save_current_value, + uint32 address, uint8 byte) +{ + if (Cheat.num_cheats < sizeof (Cheat.c) / sizeof (Cheat. c [0])) + { + Cheat.c [Cheat.num_cheats].address = address; + Cheat.c [Cheat.num_cheats].byte = byte; + Cheat.c [Cheat.num_cheats].enabled = TRUE; + if (save_current_value) + { + Cheat.c [Cheat.num_cheats].saved_byte = S9xGetByte (address); + Cheat.c [Cheat.num_cheats].saved = TRUE; + } + Cheat.num_cheats++; + } +} + +void S9xDeleteCheat (uint32 which1) +{ + if (which1 < Cheat.num_cheats) + { + if (Cheat.c [which1].enabled) + S9xRemoveCheat (which1); + + memmove (&Cheat.c [which1], &Cheat.c [which1 + 1], + sizeof (Cheat.c [0]) * (Cheat.num_cheats - which1 - 1)); + Cheat.num_cheats = 0; + } +} + +void S9xDeleteCheats () +{ + S9xRemoveCheats (); + Cheat.num_cheats = 0; +} + +void S9xEnableCheat (uint32 which1) +{ + if (which1 < Cheat.num_cheats && !Cheat.c [which1].enabled) + { + Cheat.c [which1].enabled = TRUE; + S9xApplyCheat (which1); + } +} + +void S9xDisableCheat (uint32 which1) +{ + if (which1 < Cheat.num_cheats && Cheat.c [which1].enabled) + { + S9xRemoveCheat (which1); + Cheat.c [which1].enabled = FALSE; + } +} + +void S9xRemoveCheat (uint32 which1) +{ + if (Cheat.c [which1].saved) + { + uint32 address = Cheat.c [which1].address; + + int block = (address >> MEMMAP_SHIFT) & MEMMAP_MASK; + uint8 *ptr = Memory.Map [block]; + + if (ptr >= (uint8 *) MAP_LAST) + *(ptr + (address & 0xffff)) = Cheat.c [which1].saved_byte; + else + S9xSetByte (address, Cheat.c [which1].saved_byte); + } +} + +void S9xApplyCheat (uint32 which1) +{ + uint32 address = Cheat.c [which1].address; + + if (!Cheat.c [which1].saved) + Cheat.c [which1].saved_byte = S9xGetByte (address); + + int block = (address >> MEMMAP_SHIFT) & MEMMAP_MASK; + uint8 *ptr = Memory.Map [block]; + + if (ptr >= (uint8 *) MAP_LAST) + *(ptr + (address & 0xffff)) = Cheat.c [which1].byte; + else + S9xSetByte (address, Cheat.c [which1].byte); + Cheat.c [which1].saved = TRUE; +} + +void S9xApplyCheats () +{ + if (Settings.ApplyCheats) + { + uint32 i; + for (i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c [i].enabled) + S9xApplyCheat (i); + } +} + +void S9xRemoveCheats () +{ + uint32 i; + for (i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c [i].enabled) + S9xRemoveCheat (i); +} + +bool8 S9xLoadCheatFile (const char *filename) +{ + Cheat.num_cheats = 0; + + FILE *fs = fopen (filename, "rb"); + uint8 data [28]; + + if (!fs) + return (FALSE); + + while (fread ((void *) data, 1, 28, fs) == 28) + { + Cheat.c [Cheat.num_cheats].enabled = (data [0] & 4) == 0; + Cheat.c [Cheat.num_cheats].byte = data [1]; + Cheat.c [Cheat.num_cheats].address = data [2] | (data [3] << 8) | (data [4] << 16); + Cheat.c [Cheat.num_cheats].saved_byte = data [5]; + Cheat.c [Cheat.num_cheats].saved = (data [0] & 8) != 0; + memmove (Cheat.c [Cheat.num_cheats].name, &data [8], 20); + Cheat.c [Cheat.num_cheats++].name [20] = 0; + } + fclose (fs); + + return (TRUE); +} + +bool8 S9xSaveCheatFile (const char *filename) +{ + if (Cheat.num_cheats == 0) + { + (void) remove (filename); + return (TRUE); + } + + FILE *fs = fopen (filename, "wb"); + uint8 data [28]; + + if (!fs) + return (FALSE); + + uint32 i; + for (i = 0; i < Cheat.num_cheats; i++) + { + memset (data, 0, 28); + if (i == 0) + { + data [6] = 254; + data [7] = 252; + } + if (!Cheat.c [i].enabled) + data [0] |= 4; + + if (Cheat.c [i].saved) + data [0] |= 8; + + data [1] = Cheat.c [i].byte; + data [2] = (uint8) Cheat.c [i].address; + data [3] = (uint8) (Cheat.c [i].address >> 8); + data [4] = (uint8) (Cheat.c [i].address >> 16); + data [5] = Cheat.c [i].saved_byte; + + memmove (&data [8], Cheat.c [i].name, 19); + if (fwrite (data, 28, 1, fs) != 1) + { + fclose (fs); + return (FALSE); + } + } + return (fclose (fs) == 0); +} + diff --git a/src/cheats2.cpp b/src/cheats2.cpp deleted file mode 100644 index ec8062a..0000000 --- a/src/cheats2.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include -#include -#include -#include "snes9x.h" -#include "cheats.h" -#include "memmap.h" - -extern SCheatData Cheat; - -void S9xInitCheatData () -{ - Cheat.RAM = Memory.RAM; - Cheat.SRAM = ::SRAM; - Cheat.FillRAM = Memory.FillRAM; -} - -void S9xAddCheat (bool8 enable, bool8 save_current_value, - uint32 address, uint8 byte) -{ - if (Cheat.num_cheats < sizeof (Cheat.c) / sizeof (Cheat. c [0])) - { - Cheat.c [Cheat.num_cheats].address = address; - Cheat.c [Cheat.num_cheats].byte = byte; - Cheat.c [Cheat.num_cheats].enabled = TRUE; - if (save_current_value) - { - Cheat.c [Cheat.num_cheats].saved_byte = S9xGetByte (address); - Cheat.c [Cheat.num_cheats].saved = TRUE; - } - Cheat.num_cheats++; - } -} - -void S9xDeleteCheat (uint32 which1) -{ - if (which1 < Cheat.num_cheats) - { - if (Cheat.c [which1].enabled) - S9xRemoveCheat (which1); - - memmove (&Cheat.c [which1], &Cheat.c [which1 + 1], - sizeof (Cheat.c [0]) * (Cheat.num_cheats - which1 - 1)); - Cheat.num_cheats = 0; - } -} - -void S9xDeleteCheats () -{ - S9xRemoveCheats (); - Cheat.num_cheats = 0; -} - -void S9xEnableCheat (uint32 which1) -{ - if (which1 < Cheat.num_cheats && !Cheat.c [which1].enabled) - { - Cheat.c [which1].enabled = TRUE; - S9xApplyCheat (which1); - } -} - -void S9xDisableCheat (uint32 which1) -{ - if (which1 < Cheat.num_cheats && Cheat.c [which1].enabled) - { - S9xRemoveCheat (which1); - Cheat.c [which1].enabled = FALSE; - } -} - -void S9xRemoveCheat (uint32 which1) -{ - if (Cheat.c [which1].saved) - { - uint32 address = Cheat.c [which1].address; - - int block = (address >> MEMMAP_SHIFT) & MEMMAP_MASK; - uint8 *ptr = Memory.Map [block]; - - if (ptr >= (uint8 *) CMemory::MAP_LAST) - *(ptr + (address & 0xffff)) = Cheat.c [which1].saved_byte; - else - S9xSetByte (address, Cheat.c [which1].saved_byte); - } -} - -void S9xApplyCheat (uint32 which1) -{ - uint32 address = Cheat.c [which1].address; - - if (!Cheat.c [which1].saved) - Cheat.c [which1].saved_byte = S9xGetByte (address); - - int block = (address >> MEMMAP_SHIFT) & MEMMAP_MASK; - uint8 *ptr = Memory.Map [block]; - - if (ptr >= (uint8 *) CMemory::MAP_LAST) - *(ptr + (address & 0xffff)) = Cheat.c [which1].byte; - else - S9xSetByte (address, Cheat.c [which1].byte); - Cheat.c [which1].saved = TRUE; -} - -void S9xApplyCheats () -{ - if (Settings.ApplyCheats) - { - for (uint32 i = 0; i < Cheat.num_cheats; i++) - if (Cheat.c [i].enabled) - S9xApplyCheat (i); - } -} - -void S9xRemoveCheats () -{ - for (uint32 i = 0; i < Cheat.num_cheats; i++) - if (Cheat.c [i].enabled) - S9xRemoveCheat (i); -} - -bool8 S9xLoadCheatFile (const char *filename) -{ - Cheat.num_cheats = 0; - - FILE *fs = fopen (filename, "rb"); - uint8 data [28]; - - if (!fs) - return (FALSE); - - while (fread ((void *) data, 1, 28, fs) == 28) - { - Cheat.c [Cheat.num_cheats].enabled = (data [0] & 4) == 0; - Cheat.c [Cheat.num_cheats].byte = data [1]; - Cheat.c [Cheat.num_cheats].address = data [2] | (data [3] << 8) | (data [4] << 16); - Cheat.c [Cheat.num_cheats].saved_byte = data [5]; - Cheat.c [Cheat.num_cheats].saved = (data [0] & 8) != 0; - memmove (Cheat.c [Cheat.num_cheats].name, &data [8], 20); - Cheat.c [Cheat.num_cheats++].name [20] = 0; - } - fclose (fs); - - return (TRUE); -} - -bool8 S9xSaveCheatFile (const char *filename) -{ - if (Cheat.num_cheats == 0) - { - (void) remove (filename); - return (TRUE); - } - - FILE *fs = fopen (filename, "wb"); - uint8 data [28]; - - if (!fs) - return (FALSE); - - uint32 i; - for (i = 0; i < Cheat.num_cheats; i++) - { - memset (data, 0, 28); - if (i == 0) - { - data [6] = 254; - data [7] = 252; - } - if (!Cheat.c [i].enabled) - data [0] |= 4; - - if (Cheat.c [i].saved) - data [0] |= 8; - - data [1] = Cheat.c [i].byte; - data [2] = (uint8) Cheat.c [i].address; - data [3] = (uint8) (Cheat.c [i].address >> 8); - data [4] = (uint8) (Cheat.c [i].address >> 16); - data [5] = Cheat.c [i].saved_byte; - - memmove (&data [8], Cheat.c [i].name, 19); - if (fwrite (data, 28, 1, fs) != 1) - { - fclose (fs); - return (FALSE); - } - } - return (fclose (fs) == 0); -} - diff --git a/src/clip.c b/src/clip.c new file mode 100644 index 0000000..a6d0292 --- /dev/null +++ b/src/clip.c @@ -0,0 +1,737 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include + +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" + +struct Band +{ + uint32 Left; + uint32 Right; +}; + +#undef MIN +#undef MAX +#define MIN(A,B) ((A) < (B) ? (A) : (B)) +#define MAX(A,B) ((A) > (B) ? (A) : (B)) +#define BAND_EMPTY(B) (B.Left >= B.Right) +#define BANDS_INTERSECT(A,B) ((A.Left >= B.Left && A.Left < B.Right) || \ + (A.Right > B.Left && A.Right <= B.Right)) +#define OR_BANDS(R,A,B) {\ + R.Left = MIN(A.Left, B.Left); \ + R.Right = MAX(A.Right, B.Right);} + +#define AND_BANDS(R,A,B) {\ + R.Left = MAX(A.Left, B.Left); \ + R.Right = MIN(A.Right, B.Right);} + +static int IntCompare (const void *d1, const void *d2) +{ +/* + if (*(uint32 *) d1 > *(uint32 *) d2) + return (1); + else + if (*(uint32 *) d1 < *(uint32 *) d2) + return (-1); + return (0); +*/ + return (*(uint32 *) d1 - *(uint32 *) d2); +} + +static int BandCompare (const void *d1, const void *d2) +{ +/* + if (((struct Band *) d1)->Left > ((struct Band *) d2)->Left) + return (1); + else + if (((struct Band *) d1)->Left < ((struct Band *) d2)->Left) + return (-1); + return (0); +*/ + return (((struct Band *) d1)->Left - ((struct Band *) d2)->Left); +} + +void ComputeClipWindow(bool8_32 invert, int w, int wok, ClipData *pClip) { + pClip->Count[w] = 0; + + if (!Settings.DisableGraphicWindows) + { + if (pClip->Count [5] || wok) + { + struct Band Win1[3]; + struct Band Win2[3]; + uint32 Window1Enabled = 0; + uint32 Window2Enabled = 0; + if (wok) + { + if (PPU.ClipWindow1Enable [w]) + { + if (!PPU.ClipWindow1Inside [w]) + { + Win1[0].Left = PPU.Window1Left; + Win1[0].Right = PPU.Window1Right + 1; + Window1Enabled = 1; + } + else + { + if (PPU.Window1Left <= PPU.Window1Right) + { + if (PPU.Window1Left > 0) + { + Win1[0].Left = 0; + Win1[0].Right = PPU.Window1Left; + Window1Enabled = 1; + } + if (PPU.Window1Right < 255) + { + Win1[Window1Enabled].Left = PPU.Window1Right + 1; + Win1[Window1Enabled++].Right = 256; + } + if (Window1Enabled == 0) + { + Win1[0].Left = 1; + Win1[0].Right = 0; + Window1Enabled = 1; + } + } + else + { + // 'outside' a window with no range - + // appears to be the whole screen. + Win1[0].Left = 0; + Win1[0].Right = 256; + Window1Enabled = 1; + } + } + } + if (PPU.ClipWindow2Enable [w]) + { + if (!PPU.ClipWindow2Inside [w]) + { + Win2[0].Left = PPU.Window2Left; + Win2[0].Right = PPU.Window2Right + 1; + Window2Enabled = 1; + } + else + { + if (PPU.Window2Left <= PPU.Window2Right) + { + if (PPU.Window2Left > 0) + { + Win2[0].Left = 0; + Win2[0].Right = PPU.Window2Left; + Window2Enabled = 1; + } + if (PPU.Window2Right < 255) + { + Win2[Window2Enabled].Left = PPU.Window2Right + 1; + Win2[Window2Enabled++].Right = 256; + } + if (Window2Enabled == 0) + { + Win2[0].Left = 1; + Win2[0].Right = 0; + Window2Enabled = 1; + } + } + else + { + Win2[0].Left = 0; + Win2[0].Right = 256; + Window2Enabled = 1; + } + } + } + } + if (Window1Enabled && Window2Enabled) + { + // Overlap logic + // + // Each window will be in one of three states: + // 1. (Left > Right. One band) + // 2. | ---------------- | (Left >= 0, Right <= 255, Left <= Right. One band) + // 3. |------------ ----------| (Left1 == 0, Right1 < Left2; Left2 > Right1, Right2 == 255. Two bands) + + struct Band Bands [6]; + int B = 0; + switch (PPU.ClipWindowOverlapLogic [w] ^ 1) + { + case CLIP_OR: + if (Window1Enabled == 1) + { + if (BAND_EMPTY(Win1[0])) + { + B = Window2Enabled; + memmove (Bands, Win2, + sizeof(Win2[0]) * Window2Enabled); + } + else + { + if (Window2Enabled == 1) + { + if (BAND_EMPTY (Win2[0])) + Bands[B++] = Win1[0]; + else + { + if (BANDS_INTERSECT (Win1[0], Win2[0])) + { + OR_BANDS(Bands[0],Win1[0], Win2[0]) + B = 1; + } + else + { + Bands[B++] = Win1[0]; + Bands[B++] = Win2[0]; + } + } + } + else + { + if (BANDS_INTERSECT(Win1[0], Win2[0])) + { + OR_BANDS(Bands[0], Win1[0], Win2[0]) + if (BANDS_INTERSECT(Win1[0], Win2[1])) + OR_BANDS(Bands[1], Win1[0], Win2[1]) + else + Bands[1] = Win2[1]; + B = 1; + if (BANDS_INTERSECT(Bands[0], Bands[1])) + OR_BANDS(Bands[0], Bands[0], Bands[1]) + else + B = 2; + } + else + if (BANDS_INTERSECT(Win1[0], Win2[1])) + { + Bands[B++] = Win2[0]; + OR_BANDS(Bands[B], Win1[0], Win2[1]); + B++; + } + else + { + Bands[0] = Win2[0]; + Bands[1] = Win1[0]; + Bands[2] = Win2[1]; + B = 3; + } + } + } + } + else + if (Window2Enabled == 1) + { + if (BAND_EMPTY(Win2[0])) + { + // Window 2 defines an empty range - just + // use window 1 as the clipping (which + // could also be empty). + B = Window1Enabled; + memmove (Bands, Win1, + sizeof(Win1[0]) * Window1Enabled); + } + else + { + // Window 1 has two bands and Window 2 has one. + // Neither is an empty region. + if (BANDS_INTERSECT(Win2[0], Win1[0])) + { + OR_BANDS(Bands[0], Win2[0], Win1[0]) + if (BANDS_INTERSECT(Win2[0], Win1[1])) + OR_BANDS(Bands[1], Win2[0], Win1[1]) + else + Bands[1] = Win1[1]; + B = 1; + if (BANDS_INTERSECT(Bands[0], Bands[1])) + OR_BANDS(Bands[0], Bands[0], Bands[1]) + else + B = 2; + } + else + if (BANDS_INTERSECT(Win2[0], Win1[1])) + { + Bands[B++] = Win1[0]; + OR_BANDS(Bands[B], Win2[0], Win1[1]); + B++; + } + else + { + Bands[0] = Win1[0]; + Bands[1] = Win2[0]; + Bands[2] = Win1[1]; + B = 3; + } + } + } + else + { + // Both windows have two bands + OR_BANDS(Bands[0], Win1[0], Win2[0]); + OR_BANDS(Bands[1], Win1[1], Win2[1]); + B = 1; + if (BANDS_INTERSECT(Bands[0], Bands[1])) + OR_BANDS(Bands[0], Bands[0], Bands[1]) + else + B = 2; + } + break; + + case CLIP_AND: + if (Window1Enabled == 1) + { + // Window 1 has one band + if (BAND_EMPTY(Win1[0])) + Bands [B++] = Win1[0]; + else + if (Window2Enabled == 1) + { + if (BAND_EMPTY (Win2[0])) + Bands [B++] = Win2[0]; + else + { + AND_BANDS(Bands[0], Win1[0], Win2[0]); + B = 1; + } + } + else + { + AND_BANDS(Bands[0], Win1[0], Win2[0]); + AND_BANDS(Bands[1], Win1[0], Win2[1]); + B = 2; + } + } + else + if (Window2Enabled == 1) + { + if (BAND_EMPTY(Win2[0])) + Bands[B++] = Win2[0]; + else + { + // Window 1 has two bands. + AND_BANDS(Bands[0], Win1[0], Win2[0]); + AND_BANDS(Bands[1], Win1[1], Win2[0]); + B = 2; + } + } + else + { + // Both windows have two bands. + AND_BANDS(Bands[0], Win1[0], Win2[0]); + AND_BANDS(Bands[1], Win1[1], Win2[1]); + B = 2; + if (BANDS_INTERSECT(Win1[0], Win2[1])) + { + AND_BANDS(Bands[2], Win1[0], Win2[1]); + B = 3; + } + else + if (BANDS_INTERSECT(Win1[1], Win2[0])) + { + AND_BANDS(Bands[2], Win1[1], Win2[0]); + B = 3; + } + } + break; + case CLIP_XNOR: + invert = !invert; + // Fall... + + case CLIP_XOR: + if (Window1Enabled == 1 && BAND_EMPTY(Win1[0])) + { + B = Window2Enabled; + memmove (Bands, Win2, + sizeof(Win2[0]) * Window2Enabled); + } + else + if (Window2Enabled == 1 && BAND_EMPTY(Win2[0])) + { + B = Window1Enabled; + memmove (Bands, Win1, + sizeof(Win1[0]) * Window1Enabled); + } + else + { + uint32 p = 0; + uint32 points [10]; + uint32 i; + + invert = !invert; + // Build an array of points (window edges) + points [p++] = 0; + for (i = 0; i < Window1Enabled; i++) + { + points [p++] = Win1[i].Left; + points [p++] = Win1[i].Right; + } + for (i = 0; i < Window2Enabled; i++) + { + points [p++] = Win2[i].Left; + points [p++] = Win2[i].Right; + } + points [p++] = 256; + // Sort them + qsort ((void *) points, p, sizeof (points [0]), + IntCompare); + for (i = 0; i < p; i += 2) + { + if (points [i] == points [i + 1]) + continue; + Bands [B].Left = points [i]; + while (i + 2 < p && + points [i + 1] == points [i + 2]) + { + i += 2; + } + Bands [B++].Right = points [i + 1]; + } + } + break; + } + if (invert) + { + int b; + int j = 0; + int empty_band_count = 0; + + // First remove all empty bands from the list. + for (b = 0; b < B; b++) + { + if (!BAND_EMPTY(Bands[b])) + { + if (b != j) + Bands[j] = Bands[b]; + j++; + } + else + empty_band_count++; + } + + if (j > 0) + { + if (j == 1) + { + j = 0; + // Easy case to deal with, so special case it. + + if (Bands[0].Left > 0) + { + pClip->Left[j][w] = 0; + pClip->Right[j++][w] = Bands[0].Left + 1; + } + if (Bands[0].Right < 256) + { + pClip->Left[j][w] = Bands[0].Right; + pClip->Right[j++][w] = 256; + } + if (j == 0) + { + pClip->Left[j][w] = 1; + pClip->Right[j++][w] = 0; + } + } + else + { + // Now sort the bands into order + B = j; + qsort ((void *) Bands, B, + sizeof (Bands [0]), BandCompare); + + // Now invert the area the bands cover + j = 0; + for (b = 0; b < B; b++) + { + if (b == 0 && Bands[b].Left > 0) + { + pClip->Left[j][w] = 0; + pClip->Right[j++][w] = Bands[b].Left + 1; + } + else + if (b == B - 1 && Bands[b].Right < 256) + { + pClip->Left[j][w] = Bands[b].Right; + pClip->Right[j++][w] = 256; + } + if (b < B - 1) + { + pClip->Left[j][w] = Bands[b].Right; + pClip->Right[j++][w] = Bands[b + 1].Left + 1; + } + } + } + } + else + { + // Inverting a window that consisted of only + // empty bands is the whole width of the screen. + // Needed for Mario Kart's rear-view mirror display. + if (empty_band_count) + { + pClip->Left[j][w] = 0; + pClip->Right[j][w] = 256; + j++; + } + } + pClip->Count[w] = j; + } + else + { + int j; + for (j = 0; j < B; j++) + { + pClip->Left[j][w] = Bands[j].Left; + pClip->Right[j][w] = Bands[j].Right; + } + pClip->Count [w] = B; + } + } + else + { + // Only one window enabled so no need to perform + // complex overlap logic... + + if (Window1Enabled) + { + if (invert) + { + int j = 0; + + if (Window1Enabled == 1) + { + if (Win1[0].Left <= Win1[0].Right) + { + if (Win1[0].Left > 0) + { + pClip->Left[0][w] = 0; + pClip->Right[0][w] = Win1[0].Left; + j = 1; + } + if (Win1[0].Right < 256) + { + pClip->Left[j][w] = Win1[0].Right; + pClip->Right[j++][w] = 256; + } + if (j == 0) + { + pClip->Left[0][w] = 1; + pClip->Right[0][w] = 0; + j = 1; + } + } + else + { + pClip->Left[0][w] = 0; + pClip->Right[0][w] = 256; + j = 1; + } + } + else + { + pClip->Left [0][w] = Win1[0].Right; + pClip->Right[0][w] = Win1[1].Left; + j = 1; + } + pClip->Count [w] = j; + } + else + { + uint32 j; + for (j = 0; j < Window1Enabled; j++) + { + pClip->Left [j][w] = Win1[j].Left; + pClip->Right [j][w] = Win1[j].Right; + } + pClip->Count [w] = Window1Enabled; + } + } + else + if (Window2Enabled) + { + if (invert) + { + int j = 0; + if (Window2Enabled == 1) + { + if (Win2[0].Left <= Win2[0].Right) + { + if (Win2[0].Left > 0) + { + pClip->Left[0][w] = 0; + pClip->Right[0][w] = Win2[0].Left; + j = 1; + } + if (Win2[0].Right < 256) + { + pClip->Left[j][w] = Win2[0].Right; + pClip->Right[j++][w] = 256; + } + if (j == 0) + { + pClip->Left[0][w] = 1; + pClip->Right[0][w] = 0; + j = 1; + } + } + else + { + pClip->Left[0][w] = 0; + pClip->Right[0][w] = 256; + j = 1; + } + } + else + { + pClip->Left [0][w] = Win2[0].Right; + pClip->Right[0][w] = Win2[1].Left + 1; + j = 1; + } + pClip->Count [w] = j; + } + else + { + uint32 j; + for (j = 0; j < Window2Enabled; j++) + { + pClip->Left [j][w] = Win2[j].Left; + pClip->Right [j][w] = Win2[j].Right; + } + pClip->Count [w] = Window2Enabled; + } + } + } + + if ((w != 5) && (pClip->Count [5])) + { + //if + //{ + // Colour window enabled. Set the + // clip windows for all remaining backgrounds to be + // the same as the colour window. + if (pClip->Count [w] == 0) + { + pClip->Count [w] = pClip->Count [5]; + int i; + for (i = pClip->Count[w]-1; i >= 0 ; i--) + { + pClip->Left [i][w] = pClip->Left [i][5]; + pClip->Right [i][w] = pClip->Right [i][5]; + } + } + else + { + // Intersect the colour window with the bg's + // own clip window. + int i, j; + //for (i = 0; i < pClip->Count [w]; i++) + for (i = pClip->Count [w] - 1; i >= 0 ; i--) + { + //for (j = 0; j < pClip->Count [5]; j++) + for (j = pClip->Count [5] - 1; j >= 0 ; j--) + { + if((pClip->Left[i][w] >= pClip->Left[j][5] && pClip->Left[i][w] < pClip->Right[j][5]) || (pClip->Left[j][5] >= pClip->Left[i][w] && pClip->Left[j][5] < pClip->Right[i][w])){ + // Found an intersection! + pClip->Left[i][w]=MAX(pClip->Left[i][w], pClip->Left[j][5]); + pClip->Right[i][w]=MIN(pClip->Right[i][w], pClip->Right[j][5]); + goto Clip_ok; + } + } + // no intersection, nullify it + pClip->Left[i][w]=1; + pClip->Right[i][w]=0; +Clip_ok: + j=0; // dummy statement + } + } + //} + } + } // if (w == 5 | ... + } // if (!Settings.DisableGraphicWindows) +} + +void ComputeClipWindows () +{ + // Main screen + // - Colour window + if ((GFX.r2130_s & 0xc0) == 0xc0) { + // The whole of the main screen is switched off, + // completely clip everything. + int i; + for (i = 0; i < 6; i++) { + IPPU.Clip [0].Count [i] = 1; + IPPU.Clip [0].Left [0][i] = 1; + IPPU.Clip [0].Right [0][i] = 0; + } + } + else if (GFX.r2130_s & 0xc0) ComputeClipWindow(((GFX.r2130_s & 0xc0) == 0x40), 5, 1, &IPPU.Clip [0]); + else IPPU.Clip[0].Count[5] = 0; + // - Objs + ComputeClipWindow(FALSE, 4, (GFX.r212c_s & GFX.r212e_s & (1 << 4)), &IPPU.Clip [0]); + // - Backgrounds + ComputeClipWindow(FALSE, 3, (GFX.r212c_s & GFX.r212e_s & (1 << 3)), &IPPU.Clip [0]); + ComputeClipWindow(FALSE, 2, (GFX.r212c_s & GFX.r212e_s & (1 << 2)), &IPPU.Clip [0]); + ComputeClipWindow(FALSE, 1, (GFX.r212c_s & GFX.r212e_s & (1 << 1)), &IPPU.Clip [0]); + ComputeClipWindow(FALSE, 0, (GFX.r212c_s & GFX.r212e_s & (1 << 0)), &IPPU.Clip [0]); + + // Sub screen + // - Colour window + if ((GFX.r2130_s & 0x30) == 0x30) { + // The sub-screen is switched off, completely + // clip everything. + int i; + for (i = 0; i < 6; i++) { + IPPU.Clip [1].Count [i] = 1; + IPPU.Clip [1].Left [0][i] = 1; + IPPU.Clip [1].Right [0][i] = 0; + } + } + else if (GFX.r2130_s & 0x30) ComputeClipWindow(((GFX.r2130_s & 0x30) == 0x10), 5, 1, &IPPU.Clip [1]); + else IPPU.Clip[1].Count[5] = 0; + // - Objs + ComputeClipWindow(FALSE, 4, (GFX.r212d_s & GFX.r212f_s & (1 << 4)), &IPPU.Clip [1]); + // - Backgrounds + ComputeClipWindow(FALSE, 3, (GFX.r212d_s & GFX.r212f_s & (1 << 3)), &IPPU.Clip [1]); + ComputeClipWindow(FALSE, 2, (GFX.r212d_s & GFX.r212f_s & (1 << 2)), &IPPU.Clip [1]); + ComputeClipWindow(FALSE, 1, (GFX.r212d_s & GFX.r212f_s & (1 << 1)), &IPPU.Clip [1]); + ComputeClipWindow(FALSE, 0, (GFX.r212d_s & GFX.r212f_s & (1 << 0)), &IPPU.Clip [1]); + + PPU.RecomputeClipWindows = FALSE; +} diff --git a/src/clip.cpp b/src/clip.cpp deleted file mode 100644 index e991b92..0000000 --- a/src/clip.cpp +++ /dev/null @@ -1,731 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include - -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" - -struct Band -{ - uint32 Left; - uint32 Right; -}; - -#undef MIN -#undef MAX -#define MIN(A,B) ((A) < (B) ? (A) : (B)) -#define MAX(A,B) ((A) > (B) ? (A) : (B)) -#define BAND_EMPTY(B) (B.Left >= B.Right) -#define BANDS_INTERSECT(A,B) ((A.Left >= B.Left && A.Left < B.Right) || \ - (A.Right > B.Left && A.Right <= B.Right)) -#define OR_BANDS(R,A,B) {\ - R.Left = MIN(A.Left, B.Left); \ - R.Right = MAX(A.Right, B.Right);} - -#define AND_BANDS(R,A,B) {\ - R.Left = MAX(A.Left, B.Left); \ - R.Right = MIN(A.Right, B.Right);} - -static int IntCompare (const void *d1, const void *d2) -{ -/* - if (*(uint32 *) d1 > *(uint32 *) d2) - return (1); - else - if (*(uint32 *) d1 < *(uint32 *) d2) - return (-1); - return (0); -*/ - return (*(uint32 *) d1 - *(uint32 *) d2); -} - -static int BandCompare (const void *d1, const void *d2) -{ -/* - if (((struct Band *) d1)->Left > ((struct Band *) d2)->Left) - return (1); - else - if (((struct Band *) d1)->Left < ((struct Band *) d2)->Left) - return (-1); - return (0); -*/ - return (((struct Band *) d1)->Left - ((struct Band *) d2)->Left); -} - -void ComputeClipWindow(bool8_32 invert, int w, int wok, struct ClipData *pClip) { - pClip->Count[w] = 0; - - if (!Settings.DisableGraphicWindows) - { - if (pClip->Count [5] || wok) - { - struct Band Win1[3]; - struct Band Win2[3]; - uint32 Window1Enabled = 0; - uint32 Window2Enabled = 0; - if (wok) - { - if (PPU.ClipWindow1Enable [w]) - { - if (!PPU.ClipWindow1Inside [w]) - { - Win1[0].Left = PPU.Window1Left; - Win1[0].Right = PPU.Window1Right + 1; - Window1Enabled = 1; - } - else - { - if (PPU.Window1Left <= PPU.Window1Right) - { - if (PPU.Window1Left > 0) - { - Win1[0].Left = 0; - Win1[0].Right = PPU.Window1Left; - Window1Enabled = 1; - } - if (PPU.Window1Right < 255) - { - Win1[Window1Enabled].Left = PPU.Window1Right + 1; - Win1[Window1Enabled++].Right = 256; - } - if (Window1Enabled == 0) - { - Win1[0].Left = 1; - Win1[0].Right = 0; - Window1Enabled = 1; - } - } - else - { - // 'outside' a window with no range - - // appears to be the whole screen. - Win1[0].Left = 0; - Win1[0].Right = 256; - Window1Enabled = 1; - } - } - } - if (PPU.ClipWindow2Enable [w]) - { - if (!PPU.ClipWindow2Inside [w]) - { - Win2[0].Left = PPU.Window2Left; - Win2[0].Right = PPU.Window2Right + 1; - Window2Enabled = 1; - } - else - { - if (PPU.Window2Left <= PPU.Window2Right) - { - if (PPU.Window2Left > 0) - { - Win2[0].Left = 0; - Win2[0].Right = PPU.Window2Left; - Window2Enabled = 1; - } - if (PPU.Window2Right < 255) - { - Win2[Window2Enabled].Left = PPU.Window2Right + 1; - Win2[Window2Enabled++].Right = 256; - } - if (Window2Enabled == 0) - { - Win2[0].Left = 1; - Win2[0].Right = 0; - Window2Enabled = 1; - } - } - else - { - Win2[0].Left = 0; - Win2[0].Right = 256; - Window2Enabled = 1; - } - } - } - } - if (Window1Enabled && Window2Enabled) - { - // Overlap logic - // - // Each window will be in one of three states: - // 1. (Left > Right. One band) - // 2. | ---------------- | (Left >= 0, Right <= 255, Left <= Right. One band) - // 3. |------------ ----------| (Left1 == 0, Right1 < Left2; Left2 > Right1, Right2 == 255. Two bands) - - struct Band Bands [6]; - int B = 0; - switch (PPU.ClipWindowOverlapLogic [w] ^ 1) - { - case CLIP_OR: - if (Window1Enabled == 1) - { - if (BAND_EMPTY(Win1[0])) - { - B = Window2Enabled; - memmove (Bands, Win2, - sizeof(Win2[0]) * Window2Enabled); - } - else - { - if (Window2Enabled == 1) - { - if (BAND_EMPTY (Win2[0])) - Bands[B++] = Win1[0]; - else - { - if (BANDS_INTERSECT (Win1[0], Win2[0])) - { - OR_BANDS(Bands[0],Win1[0], Win2[0]) - B = 1; - } - else - { - Bands[B++] = Win1[0]; - Bands[B++] = Win2[0]; - } - } - } - else - { - if (BANDS_INTERSECT(Win1[0], Win2[0])) - { - OR_BANDS(Bands[0], Win1[0], Win2[0]) - if (BANDS_INTERSECT(Win1[0], Win2[1])) - OR_BANDS(Bands[1], Win1[0], Win2[1]) - else - Bands[1] = Win2[1]; - B = 1; - if (BANDS_INTERSECT(Bands[0], Bands[1])) - OR_BANDS(Bands[0], Bands[0], Bands[1]) - else - B = 2; - } - else - if (BANDS_INTERSECT(Win1[0], Win2[1])) - { - Bands[B++] = Win2[0]; - OR_BANDS(Bands[B], Win1[0], Win2[1]); - B++; - } - else - { - Bands[0] = Win2[0]; - Bands[1] = Win1[0]; - Bands[2] = Win2[1]; - B = 3; - } - } - } - } - else - if (Window2Enabled == 1) - { - if (BAND_EMPTY(Win2[0])) - { - // Window 2 defines an empty range - just - // use window 1 as the clipping (which - // could also be empty). - B = Window1Enabled; - memmove (Bands, Win1, - sizeof(Win1[0]) * Window1Enabled); - } - else - { - // Window 1 has two bands and Window 2 has one. - // Neither is an empty region. - if (BANDS_INTERSECT(Win2[0], Win1[0])) - { - OR_BANDS(Bands[0], Win2[0], Win1[0]) - if (BANDS_INTERSECT(Win2[0], Win1[1])) - OR_BANDS(Bands[1], Win2[0], Win1[1]) - else - Bands[1] = Win1[1]; - B = 1; - if (BANDS_INTERSECT(Bands[0], Bands[1])) - OR_BANDS(Bands[0], Bands[0], Bands[1]) - else - B = 2; - } - else - if (BANDS_INTERSECT(Win2[0], Win1[1])) - { - Bands[B++] = Win1[0]; - OR_BANDS(Bands[B], Win2[0], Win1[1]); - B++; - } - else - { - Bands[0] = Win1[0]; - Bands[1] = Win2[0]; - Bands[2] = Win1[1]; - B = 3; - } - } - } - else - { - // Both windows have two bands - OR_BANDS(Bands[0], Win1[0], Win2[0]); - OR_BANDS(Bands[1], Win1[1], Win2[1]); - B = 1; - if (BANDS_INTERSECT(Bands[0], Bands[1])) - OR_BANDS(Bands[0], Bands[0], Bands[1]) - else - B = 2; - } - break; - - case CLIP_AND: - if (Window1Enabled == 1) - { - // Window 1 has one band - if (BAND_EMPTY(Win1[0])) - Bands [B++] = Win1[0]; - else - if (Window2Enabled == 1) - { - if (BAND_EMPTY (Win2[0])) - Bands [B++] = Win2[0]; - else - { - AND_BANDS(Bands[0], Win1[0], Win2[0]); - B = 1; - } - } - else - { - AND_BANDS(Bands[0], Win1[0], Win2[0]); - AND_BANDS(Bands[1], Win1[0], Win2[1]); - B = 2; - } - } - else - if (Window2Enabled == 1) - { - if (BAND_EMPTY(Win2[0])) - Bands[B++] = Win2[0]; - else - { - // Window 1 has two bands. - AND_BANDS(Bands[0], Win1[0], Win2[0]); - AND_BANDS(Bands[1], Win1[1], Win2[0]); - B = 2; - } - } - else - { - // Both windows have two bands. - AND_BANDS(Bands[0], Win1[0], Win2[0]); - AND_BANDS(Bands[1], Win1[1], Win2[1]); - B = 2; - if (BANDS_INTERSECT(Win1[0], Win2[1])) - { - AND_BANDS(Bands[2], Win1[0], Win2[1]); - B = 3; - } - else - if (BANDS_INTERSECT(Win1[1], Win2[0])) - { - AND_BANDS(Bands[2], Win1[1], Win2[0]); - B = 3; - } - } - break; - case CLIP_XNOR: - invert = !invert; - // Fall... - - case CLIP_XOR: - if (Window1Enabled == 1 && BAND_EMPTY(Win1[0])) - { - B = Window2Enabled; - memmove (Bands, Win2, - sizeof(Win2[0]) * Window2Enabled); - } - else - if (Window2Enabled == 1 && BAND_EMPTY(Win2[0])) - { - B = Window1Enabled; - memmove (Bands, Win1, - sizeof(Win1[0]) * Window1Enabled); - } - else - { - uint32 p = 0; - uint32 points [10]; - uint32 i; - - invert = !invert; - // Build an array of points (window edges) - points [p++] = 0; - for (i = 0; i < Window1Enabled; i++) - { - points [p++] = Win1[i].Left; - points [p++] = Win1[i].Right; - } - for (i = 0; i < Window2Enabled; i++) - { - points [p++] = Win2[i].Left; - points [p++] = Win2[i].Right; - } - points [p++] = 256; - // Sort them - qsort ((void *) points, p, sizeof (points [0]), - IntCompare); - for (i = 0; i < p; i += 2) - { - if (points [i] == points [i + 1]) - continue; - Bands [B].Left = points [i]; - while (i + 2 < p && - points [i + 1] == points [i + 2]) - { - i += 2; - } - Bands [B++].Right = points [i + 1]; - } - } - break; - } - if (invert) - { - int b; - int j = 0; - int empty_band_count = 0; - - // First remove all empty bands from the list. - for (b = 0; b < B; b++) - { - if (!BAND_EMPTY(Bands[b])) - { - if (b != j) - Bands[j] = Bands[b]; - j++; - } - else - empty_band_count++; - } - - if (j > 0) - { - if (j == 1) - { - j = 0; - // Easy case to deal with, so special case it. - - if (Bands[0].Left > 0) - { - pClip->Left[j][w] = 0; - pClip->Right[j++][w] = Bands[0].Left + 1; - } - if (Bands[0].Right < 256) - { - pClip->Left[j][w] = Bands[0].Right; - pClip->Right[j++][w] = 256; - } - if (j == 0) - { - pClip->Left[j][w] = 1; - pClip->Right[j++][w] = 0; - } - } - else - { - // Now sort the bands into order - B = j; - qsort ((void *) Bands, B, - sizeof (Bands [0]), BandCompare); - - // Now invert the area the bands cover - j = 0; - for (b = 0; b < B; b++) - { - if (b == 0 && Bands[b].Left > 0) - { - pClip->Left[j][w] = 0; - pClip->Right[j++][w] = Bands[b].Left + 1; - } - else - if (b == B - 1 && Bands[b].Right < 256) - { - pClip->Left[j][w] = Bands[b].Right; - pClip->Right[j++][w] = 256; - } - if (b < B - 1) - { - pClip->Left[j][w] = Bands[b].Right; - pClip->Right[j++][w] = Bands[b + 1].Left + 1; - } - } - } - } - else - { - // Inverting a window that consisted of only - // empty bands is the whole width of the screen. - // Needed for Mario Kart's rear-view mirror display. - if (empty_band_count) - { - pClip->Left[j][w] = 0; - pClip->Right[j][w] = 256; - j++; - } - } - pClip->Count[w] = j; - } - else - { - for (int j = 0; j < B; j++) - { - pClip->Left[j][w] = Bands[j].Left; - pClip->Right[j][w] = Bands[j].Right; - } - pClip->Count [w] = B; - } - } - else - { - // Only one window enabled so no need to perform - // complex overlap logic... - - if (Window1Enabled) - { - if (invert) - { - int j = 0; - - if (Window1Enabled == 1) - { - if (Win1[0].Left <= Win1[0].Right) - { - if (Win1[0].Left > 0) - { - pClip->Left[0][w] = 0; - pClip->Right[0][w] = Win1[0].Left; - j = 1; - } - if (Win1[0].Right < 256) - { - pClip->Left[j][w] = Win1[0].Right; - pClip->Right[j++][w] = 256; - } - if (j == 0) - { - pClip->Left[0][w] = 1; - pClip->Right[0][w] = 0; - j = 1; - } - } - else - { - pClip->Left[0][w] = 0; - pClip->Right[0][w] = 256; - j = 1; - } - } - else - { - pClip->Left [0][w] = Win1[0].Right; - pClip->Right[0][w] = Win1[1].Left; - j = 1; - } - pClip->Count [w] = j; - } - else - { - for (uint32 j = 0; j < Window1Enabled; j++) - { - pClip->Left [j][w] = Win1[j].Left; - pClip->Right [j][w] = Win1[j].Right; - } - pClip->Count [w] = Window1Enabled; - } - } - else - if (Window2Enabled) - { - if (invert) - { - int j = 0; - if (Window2Enabled == 1) - { - if (Win2[0].Left <= Win2[0].Right) - { - if (Win2[0].Left > 0) - { - pClip->Left[0][w] = 0; - pClip->Right[0][w] = Win2[0].Left; - j = 1; - } - if (Win2[0].Right < 256) - { - pClip->Left[j][w] = Win2[0].Right; - pClip->Right[j++][w] = 256; - } - if (j == 0) - { - pClip->Left[0][w] = 1; - pClip->Right[0][w] = 0; - j = 1; - } - } - else - { - pClip->Left[0][w] = 0; - pClip->Right[0][w] = 256; - j = 1; - } - } - else - { - pClip->Left [0][w] = Win2[0].Right; - pClip->Right[0][w] = Win2[1].Left + 1; - j = 1; - } - pClip->Count [w] = j; - } - else - { - for (uint32 j = 0; j < Window2Enabled; j++) - { - pClip->Left [j][w] = Win2[j].Left; - pClip->Right [j][w] = Win2[j].Right; - } - pClip->Count [w] = Window2Enabled; - } - } - } - - if ((w != 5) && (pClip->Count [5])) - { - //if - //{ - // Colour window enabled. Set the - // clip windows for all remaining backgrounds to be - // the same as the colour window. - if (pClip->Count [w] == 0) - { - pClip->Count [w] = pClip->Count [5]; - for (int i = pClip->Count[w]-1; i >= 0 ; i--) - { - pClip->Left [i][w] = pClip->Left [i][5]; - pClip->Right [i][w] = pClip->Right [i][5]; - } - } - else - { - // Intersect the colour window with the bg's - // own clip window. - int i, j; - //for (i = 0; i < pClip->Count [w]; i++) - for (i = pClip->Count [w] - 1; i >= 0 ; i--) - { - //for (j = 0; j < pClip->Count [5]; j++) - for (j = pClip->Count [5] - 1; j >= 0 ; j--) - { - if((pClip->Left[i][w] >= pClip->Left[j][5] && pClip->Left[i][w] < pClip->Right[j][5]) || (pClip->Left[j][5] >= pClip->Left[i][w] && pClip->Left[j][5] < pClip->Right[i][w])){ - // Found an intersection! - pClip->Left[i][w]=MAX(pClip->Left[i][w], pClip->Left[j][5]); - pClip->Right[i][w]=MIN(pClip->Right[i][w], pClip->Right[j][5]); - goto Clip_ok; - } - } - // no intersection, nullify it - pClip->Left[i][w]=1; - pClip->Right[i][w]=0; -Clip_ok: - j=0; // dummy statement - } - } - //} - } - } // if (w == 5 | ... - } // if (!Settings.DisableGraphicWindows) -} - -void ComputeClipWindows () -{ - // Main screen - // - Colour window - if ((GFX.r2130_s & 0xc0) == 0xc0) { - // The whole of the main screen is switched off, - // completely clip everything. - for (int i = 0; i < 6; i++) { - IPPU.Clip [0].Count [i] = 1; - IPPU.Clip [0].Left [0][i] = 1; - IPPU.Clip [0].Right [0][i] = 0; - } - } - else if (GFX.r2130_s & 0xc0) ComputeClipWindow(((GFX.r2130_s & 0xc0) == 0x40), 5, 1, &IPPU.Clip [0]); - else IPPU.Clip[0].Count[5] = 0; - // - Objs - ComputeClipWindow(FALSE, 4, (GFX.r212c_s & GFX.r212e_s & (1 << 4)), &IPPU.Clip [0]); - // - Backgrounds - ComputeClipWindow(FALSE, 3, (GFX.r212c_s & GFX.r212e_s & (1 << 3)), &IPPU.Clip [0]); - ComputeClipWindow(FALSE, 2, (GFX.r212c_s & GFX.r212e_s & (1 << 2)), &IPPU.Clip [0]); - ComputeClipWindow(FALSE, 1, (GFX.r212c_s & GFX.r212e_s & (1 << 1)), &IPPU.Clip [0]); - ComputeClipWindow(FALSE, 0, (GFX.r212c_s & GFX.r212e_s & (1 << 0)), &IPPU.Clip [0]); - - // Sub screen - // - Colour window - if ((GFX.r2130_s & 0x30) == 0x30) { - // The sub-screen is switched off, completely - // clip everything. - for (int i = 0; i < 6; i++) { - IPPU.Clip [1].Count [i] = 1; - IPPU.Clip [1].Left [0][i] = 1; - IPPU.Clip [1].Right [0][i] = 0; - } - } - else if (GFX.r2130_s & 0x30) ComputeClipWindow(((GFX.r2130_s & 0x30) == 0x10), 5, 1, &IPPU.Clip [1]); - else IPPU.Clip[1].Count[5] = 0; - // - Objs - ComputeClipWindow(FALSE, 4, (GFX.r212d_s & GFX.r212f_s & (1 << 4)), &IPPU.Clip [1]); - // - Backgrounds - ComputeClipWindow(FALSE, 3, (GFX.r212d_s & GFX.r212f_s & (1 << 3)), &IPPU.Clip [1]); - ComputeClipWindow(FALSE, 2, (GFX.r212d_s & GFX.r212f_s & (1 << 2)), &IPPU.Clip [1]); - ComputeClipWindow(FALSE, 1, (GFX.r212d_s & GFX.r212f_s & (1 << 1)), &IPPU.Clip [1]); - ComputeClipWindow(FALSE, 0, (GFX.r212d_s & GFX.r212f_s & (1 << 0)), &IPPU.Clip [1]); - - PPU.RecomputeClipWindows = FALSE; -} diff --git a/src/cpu.c b/src/cpu.c new file mode 100644 index 0000000..044e62a --- /dev/null +++ b/src/cpu.c @@ -0,0 +1,169 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "dsp1.h" +#include "cpuexec.h" +#include "apu.h" +#include "dma.h" +#ifdef USE_SA1 +#include "sa1.h" +#endif +//#include "cheats.h" +#include "srtc.h" +#include "sdd1.h" +//#include "spc7110.h" + +#include "soundux.h" + +#ifdef SUPER_FX +#include "fxemu.h" + +extern FxInit_s SuperFX; + +void S9xResetSuperFX () +{ + SuperFX.vFlags = 0; //FX_FLAG_ROM_BUFFER;// | FX_FLAG_ADDRESS_CHECKING; + FxReset (&SuperFX); +} +#endif + +void S9xResetCPU () +{ + Registers.PB = 0; + Registers.PC = S9xGetWord (0xFFFC); + Registers.D.W = 0; + Registers.DB = 0; + Registers.SH = 1; + Registers.SL = 0xFF; + Registers.XH = 0; + Registers.YH = 0; + Registers.P.W = 0; + + ICPU.ShiftedPB = 0; + ICPU.ShiftedDB = 0; + SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); + ClearFlags (Decimal); + + CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); + CPU.BranchSkip = FALSE; + CPU.NMIActive = FALSE; + CPU.IRQActive = FALSE; + CPU.WaitingForInterrupt = FALSE; + CPU.InDMA = FALSE; + CPU.WhichEvent = HBLANK_START_EVENT; + + CPU.PC = NULL; + CPU.PCBase = NULL; + CPU.PCAtOpcodeStart = NULL; + CPU.WaitAddress = NULL; + CPU.WaitCounter = 0; + CPU.Cycles = 0; + CPU.NextEvent = Settings.HBlankStart; + CPU.V_Counter = 0; + CPU.MemSpeed = SLOW_ONE_CYCLE; + CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; + CPU.FastROMSpeed = SLOW_ONE_CYCLE; + CPU.AutoSaveTimer = 0; + CPU.SRAMModified = FALSE; + // CPU.NMITriggerPoint = 4; // Set when ROM image loaded + CPU.BRKTriggered = FALSE; + //CPU.TriedInterleavedMode2 = FALSE; // Reset when ROM image loaded + CPU.NMICycleCount = 0; + CPU.IRQCycleCount = 0; + S9xSetPCBase (Registers.PC); + +#ifndef ASMCPU +#ifndef VAR_CYCLES + ICPU.Speed = S9xE1M1X1; +#endif + ICPU.S9xOpcodes = S9xOpcodesM1X1; + S9xUnpackStatus(); +#endif + + ICPU.CPUExecuting = TRUE; +} + + +void S9xReset (void) +{ +#ifdef SUPER_FX + if (Settings.SuperFX) + S9xResetSuperFX (); +#endif + + ZeroMemory (Memory.FillRAM, 0x8000); + memset (Memory.VRAM, 0x00, 0x10000); + memset (Memory.RAM, 0x55, 0x20000); + +/* if(Settings.SPC7110) + S9xSpc7110Reset();*/ + S9xResetCPU (); + S9xResetPPU (); + S9xResetSRTC (); + if (Settings.SDD1) + S9xResetSDD1 (); + + S9xResetDMA (); + S9xResetAPU (); + S9xResetDSP1 (); +#ifdef USE_SA1 + S9xSA1Init (); +#endif + + if (Settings.C4) + S9xInitC4 (); + + S9xResetSound(1); + + Settings.Paused = FALSE; + + //Init CPU Map & co + CPU.Memory_Map=(uint8*)&(Memory.Map); + CPU.Memory_WriteMap=(uint8*)&(Memory.WriteMap); + CPU.Memory_MemorySpeed=Memory.MemorySpeed; + CPU.Memory_BlockIsRAM=(uint8*)&(Memory.BlockIsRAM); + CPU.Memory_SRAM=Memory.SRAM; + CPU.Memory_BWRAM=Memory.BWRAM; +// CPU.Memory_SRAMMask=Memory.SRAMMask; + +} diff --git a/src/cpu.cpp b/src/cpu.cpp deleted file mode 100644 index 1c998d6..0000000 --- a/src/cpu.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "dsp1.h" -#include "cpuexec.h" -#include "apu.h" -#include "dma.h" -#ifdef USE_SA1 -#include "sa1.h" -#endif -//#include "cheats.h" -#include "srtc.h" -#include "sdd1.h" -//#include "spc7110.h" - -#include "soundux.h" - -#ifdef SUPER_FX -#include "fxemu.h" - -extern struct FxInit_s SuperFX; - -void S9xResetSuperFX () -{ - SuperFX.vFlags = 0; //FX_FLAG_ROM_BUFFER;// | FX_FLAG_ADDRESS_CHECKING; - FxReset (&SuperFX); -} -#endif - -void S9xResetCPU () -{ - Registers.PB = 0; - Registers.PC = S9xGetWord (0xFFFC); - Registers.D.W = 0; - Registers.DB = 0; - Registers.SH = 1; - Registers.SL = 0xFF; - Registers.XH = 0; - Registers.YH = 0; - Registers.P.W = 0; - - ICPU.ShiftedPB = 0; - ICPU.ShiftedDB = 0; - SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); - ClearFlags (Decimal); - - CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); - CPU.BranchSkip = FALSE; - CPU.NMIActive = FALSE; - CPU.IRQActive = FALSE; - CPU.WaitingForInterrupt = FALSE; - CPU.InDMA = FALSE; - CPU.WhichEvent = HBLANK_START_EVENT; - - CPU.PC = NULL; - CPU.PCBase = NULL; - CPU.PCAtOpcodeStart = NULL; - CPU.WaitAddress = NULL; - CPU.WaitCounter = 0; - CPU.Cycles = 0; - CPU.NextEvent = Settings.HBlankStart; - CPU.V_Counter = 0; - CPU.MemSpeed = SLOW_ONE_CYCLE; - CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; - CPU.FastROMSpeed = SLOW_ONE_CYCLE; - CPU.AutoSaveTimer = 0; - CPU.SRAMModified = FALSE; - // CPU.NMITriggerPoint = 4; // Set when ROM image loaded - CPU.BRKTriggered = FALSE; - //CPU.TriedInterleavedMode2 = FALSE; // Reset when ROM image loaded - CPU.NMICycleCount = 0; - CPU.IRQCycleCount = 0; - S9xSetPCBase (Registers.PC); - -#ifndef ASMCPU -#ifndef VAR_CYCLES - ICPU.Speed = S9xE1M1X1; -#endif - ICPU.S9xOpcodes = S9xOpcodesM1X1; - S9xUnpackStatus(); -#endif - - ICPU.CPUExecuting = TRUE; -} - - -void S9xReset (void) -{ -#ifdef SUPER_FX - if (Settings.SuperFX) - S9xResetSuperFX (); -#endif - - ZeroMemory (Memory.FillRAM, 0x8000); - memset (Memory.VRAM, 0x00, 0x10000); - memset (Memory.RAM, 0x55, 0x20000); - -/* if(Settings.SPC7110) - S9xSpc7110Reset();*/ - S9xResetCPU (); - S9xResetPPU (); - S9xResetSRTC (); - if (Settings.SDD1) - S9xResetSDD1 (); - - S9xResetDMA (); - S9xResetAPU (); - S9xResetDSP1 (); -#ifdef USE_SA1 - S9xSA1Init (); -#endif - - if (Settings.C4) - S9xInitC4 (); - - S9xResetSound(1); - - Settings.Paused = FALSE; - - //Init CPU Map & co - CPU.Memory_Map=(uint8*)&(Memory.Map); - CPU.Memory_WriteMap=(uint8*)&(Memory.WriteMap); - CPU.Memory_MemorySpeed=Memory.MemorySpeed; - CPU.Memory_BlockIsRAM=(uint8*)&(Memory.BlockIsRAM); - CPU.Memory_SRAM=Memory.SRAM; - CPU.Memory_BWRAM=Memory.BWRAM; -// CPU.Memory_SRAMMask=Memory.SRAMMask; - -} diff --git a/src/cpuexec.c b/src/cpuexec.c new file mode 100644 index 0000000..3cd25c3 --- /dev/null +++ b/src/cpuexec.c @@ -0,0 +1,541 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + + + +#include "snes9x.h" + +#include "memmap.h" +#include "cpuops.h" +#include "ppu.h" +#include "cpuexec.h" +#include "snapshot.h" +#include "gfx.h" +#include "missing.h" +#include "apu.h" +#include "dma.h" +#include "fxemu.h" +#ifdef USE_SA1 +#include "sa1.h" +#endif + +#include "os9x_asm_cpu.h" + + +void (*S9x_Current_HBlank_Event)(); + + +#ifndef ASMCPU + #ifdef USE_SA1 +void S9xMainLoop_SA1_APU (void) +{ + for (;;) + { + asm_APU_EXECUTE(1); + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) + { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + ++CPU.PC; + } + S9xOpcode_NMI (); + } + } + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) + { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + CPU.IRQCycleCount--; + } + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#else + CPU.Cycles += ICPU.Speed [*CPU.PC]; +#endif + (*ICPU.S9xOpcodes[*CPU.PC++].S9xOpcode) (); + + + //S9xUpdateAPUTimer (); + + + if (SA1.Executing) + S9xSA1MainLoop (); + DO_HBLANK_CHECK (); + + } +} + +void S9xMainLoop_SA1_NoAPU (void) +{ + for (;;) + { + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) + { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + ++CPU.PC; + } + S9xOpcode_NMI (); + } + } + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) + { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + CPU.IRQCycleCount--; + } + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#else + CPU.Cycles += ICPU.Speed [*CPU.PC]; +#endif + (*ICPU.S9xOpcodes[*CPU.PC++].S9xOpcode) (); + + + //S9xUpdateAPUTimer (); + + + if (SA1.Executing) + S9xSA1MainLoop (); + DO_HBLANK_CHECK (); + + } +} + // USE_SA1 + #endif + +void S9xMainLoop_NoSA1_APU (void) +{ + for (;;) + { + asm_APU_EXECUTE(1); + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) + { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + ++CPU.PC; + } + S9xOpcode_NMI (); + } + } + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) + { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + CPU.IRQCycleCount--; + } + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#else + CPU.Cycles += ICPU.Speed [*CPU.PC]; +#endif + (*ICPU.S9xOpcodes[*CPU.PC++].S9xOpcode) (); + + + //S9xUpdateAPUTimer (); + + DO_HBLANK_CHECK (); + } +} + +void S9xMainLoop_NoSA1_NoAPU (void) +{ + for (;;) + { + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (--CPU.NMICycleCount == 0) + { + CPU.Flags &= ~NMI_FLAG; + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + ++CPU.PC; + } + S9xOpcode_NMI (); + } + } + + if (CPU.Flags & IRQ_PENDING_FLAG) + { + if (CPU.IRQCycleCount == 0) + { + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } + if (CPU.IRQActive && !Settings.DisableIRQ) + { + if (!CheckFlag (IRQ)) + S9xOpcode_IRQ (); + } + else + CPU.Flags &= ~IRQ_PENDING_FLAG; + } + else + CPU.IRQCycleCount--; + } + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + } + +#ifdef CPU_SHUTDOWN + CPU.PCAtOpcodeStart = CPU.PC; +#endif +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#else + CPU.Cycles += ICPU.Speed [*CPU.PC]; +#endif + (*ICPU.S9xOpcodes[*CPU.PC++].S9xOpcode) (); + + + //S9xUpdateAPUTimer (); + + + DO_HBLANK_CHECK (); + + } +} +#endif + + +void +S9xMainLoop (void) +{ +#ifndef ASMCPU + if (Settings.APUEnabled == 1) { + #ifdef USE_SA1 + if (Settings.SA1) S9xMainLoop_SA1_APU(); + else + #endif + S9xMainLoop_NoSA1_APU(); + } else { + #ifdef USE_SA1 + if (Settings.SA1) S9xMainLoop_SA1_NoAPU(); + else S9xMainLoop_NoSA1_NoAPU(); + #endif + + } +#else + if (Settings.asmspc700) asmMainLoop_spcAsm(&CPU); + else asmMainLoop_spcC(&CPU); +#endif + Registers.PC = CPU.PC - CPU.PCBase; + +#ifndef ASMCPU + S9xPackStatus (); +#endif + + S9xAPUPackStatus (); + + + //if (CPU.Flags & SCAN_KEYS_FLAG) + // { + CPU.Flags &= ~SCAN_KEYS_FLAG; + //} + + if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2) + { + CPU.TriedInterleavedMode2 = TRUE; + CPU.BRKTriggered = FALSE; + S9xDeinterleaveMode2 (); + } +} + +void S9xSetIRQ (uint32 source) +{ + CPU.IRQActive |= source; + CPU.Flags |= IRQ_PENDING_FLAG; + CPU.IRQCycleCount = 3; + if (CPU.WaitingForInterrupt) + { + // Force IRQ to trigger immediately after WAI - + // Final Fantasy Mystic Quest crashes without this. + CPU.IRQCycleCount = 0; + CPU.WaitingForInterrupt = FALSE; + CPU.PC++; + } +} + +void S9xClearIRQ (uint32 source) +{ + CLEAR_IRQ_SOURCE (source); +} + +void S9xDoHBlankProcessing () +{ +#ifdef CPU_SHUTDOWN + CPU.WaitCounter++; +#endif + + switch (CPU.WhichEvent) + { + case HBLANK_START_EVENT: + if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) + IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); + break; + + case HBLANK_END_EVENT: + asm_APU_EXECUTE(3); // notaz: run spc700 in sound 'speed hack' mode + if(Settings.SuperFX) + S9xSuperFXExec (); + + CPU.Cycles -= Settings.H_Max; + if (/*IAPU.APUExecuting*/CPU.APU_APUExecuting) + CPU.APU_Cycles -= Settings.H_Max; + else + CPU.APU_Cycles = 0; + + CPU.NextEvent = -1; + ICPU.Scanline++; + + if (++CPU.V_Counter >= (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) + { + CPU.V_Counter = 0; + CPU.NMIActive = FALSE; + ICPU.Frame++; + PPU.HVBeamCounterLatched = 0; + CPU.Flags |= SCAN_KEYS_FLAG; + S9xStartHDMA (); + } + + if (PPU.VTimerEnabled && !PPU.HTimerEnabled && + CPU.V_Counter == PPU.IRQVBeamPos) + { + S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); + } + + if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) + { + // Start of V-blank + S9xEndScreenRefresh (); + IPPU.HDMA = 0; + // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. + missing.dma_this_frame = 0; + IPPU.MaxBrightness = PPU.Brightness; + PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; + + if(!PPU.ForcedBlanking){ + PPU.OAMAddr = PPU.SavedOAMAddr; + PPU.OAMFlip = 0; + PPU.FirstSprite = 0; + if(PPU.OAMPriorityRotation) + PPU.FirstSprite = PPU.OAMAddr>>1; + } + + Memory.FillRAM[0x4210] = 0x80; + if (Memory.FillRAM[0x4200] & 0x80) + { + CPU.NMIActive = TRUE; + CPU.Flags |= NMI_FLAG; + CPU.NMICycleCount = CPU.NMITriggerPoint; + } + + } + + if (CPU.V_Counter == PPU.ScreenHeight + 3) + S9xUpdateJoypads (); + + if (CPU.V_Counter == FIRST_VISIBLE_LINE) + { + Memory.FillRAM[0x4210] = 0; + CPU.Flags &= ~NMI_FLAG; + S9xStartScreenRefresh (); + } + if (CPU.V_Counter >= FIRST_VISIBLE_LINE && + CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) + { + RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE); + } + // Use TimerErrorCounter to skip update of SPC700 timers once + // every 128 updates. Needed because this section of code is called + // once every emulated 63.5 microseconds, which coresponds to + // 15.750KHz, but the SPC700 timers need to be updated at multiples + // of 8KHz, hence the error correction. + // IAPU.TimerErrorCounter++; + // if (IAPU.TimerErrorCounter >= ) + // IAPU.TimerErrorCounter = 0; + // else + { + if (APU.TimerEnabled [2]) + { + APU.Timer [2] += 4; + while (APU.Timer [2] >= APU.TimerTarget [2]) + { + IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; + APU.Timer [2] -= APU.TimerTarget [2]; +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + /*IAPU.APUExecuting*/CPU.APU_APUExecuting= TRUE; +#endif + } + } + if (CPU.V_Counter & 1) + { + if (APU.TimerEnabled [0]) + { + APU.Timer [0]++; + if (APU.Timer [0] >= APU.TimerTarget [0]) + { + IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf; + APU.Timer [0] = 0; +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + /*IAPU.APUExecuting*/CPU.APU_APUExecuting = TRUE; +#endif + } + } + if (APU.TimerEnabled [1]) + { + APU.Timer [1]++; + if (APU.Timer [1] >= APU.TimerTarget [1]) + { + IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf; + APU.Timer [1] = 0; +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; + /*IAPU.APUExecuting*/CPU.APU_APUExecuting = TRUE; +#endif + } + } + } + } + break; + case HTIMER_BEFORE_EVENT: + case HTIMER_AFTER_EVENT: + if (PPU.HTimerEnabled && + (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)) + { + S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE); + } + break; + } + S9xReschedule (); +} + diff --git a/src/cpuexec.cpp b/src/cpuexec.cpp deleted file mode 100644 index 3cd25c3..0000000 --- a/src/cpuexec.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - - - -#include "snes9x.h" - -#include "memmap.h" -#include "cpuops.h" -#include "ppu.h" -#include "cpuexec.h" -#include "snapshot.h" -#include "gfx.h" -#include "missing.h" -#include "apu.h" -#include "dma.h" -#include "fxemu.h" -#ifdef USE_SA1 -#include "sa1.h" -#endif - -#include "os9x_asm_cpu.h" - - -void (*S9x_Current_HBlank_Event)(); - - -#ifndef ASMCPU - #ifdef USE_SA1 -void S9xMainLoop_SA1_APU (void) -{ - for (;;) - { - asm_APU_EXECUTE(1); - if (CPU.Flags) - { - if (CPU.Flags & NMI_FLAG) - { - if (--CPU.NMICycleCount == 0) - { - CPU.Flags &= ~NMI_FLAG; - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - ++CPU.PC; - } - S9xOpcode_NMI (); - } - } - - if (CPU.Flags & IRQ_PENDING_FLAG) - { - if (CPU.IRQCycleCount == 0) - { - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - if (CPU.IRQActive && !Settings.DisableIRQ) - { - if (!CheckFlag (IRQ)) - S9xOpcode_IRQ (); - } - else - CPU.Flags &= ~IRQ_PENDING_FLAG; - } - else - CPU.IRQCycleCount--; - } - if (CPU.Flags & SCAN_KEYS_FLAG) - break; - } - -#ifdef CPU_SHUTDOWN - CPU.PCAtOpcodeStart = CPU.PC; -#endif -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#else - CPU.Cycles += ICPU.Speed [*CPU.PC]; -#endif - (*ICPU.S9xOpcodes[*CPU.PC++].S9xOpcode) (); - - - //S9xUpdateAPUTimer (); - - - if (SA1.Executing) - S9xSA1MainLoop (); - DO_HBLANK_CHECK (); - - } -} - -void S9xMainLoop_SA1_NoAPU (void) -{ - for (;;) - { - if (CPU.Flags) - { - if (CPU.Flags & NMI_FLAG) - { - if (--CPU.NMICycleCount == 0) - { - CPU.Flags &= ~NMI_FLAG; - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - ++CPU.PC; - } - S9xOpcode_NMI (); - } - } - - if (CPU.Flags & IRQ_PENDING_FLAG) - { - if (CPU.IRQCycleCount == 0) - { - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - if (CPU.IRQActive && !Settings.DisableIRQ) - { - if (!CheckFlag (IRQ)) - S9xOpcode_IRQ (); - } - else - CPU.Flags &= ~IRQ_PENDING_FLAG; - } - else - CPU.IRQCycleCount--; - } - if (CPU.Flags & SCAN_KEYS_FLAG) - break; - } - -#ifdef CPU_SHUTDOWN - CPU.PCAtOpcodeStart = CPU.PC; -#endif -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#else - CPU.Cycles += ICPU.Speed [*CPU.PC]; -#endif - (*ICPU.S9xOpcodes[*CPU.PC++].S9xOpcode) (); - - - //S9xUpdateAPUTimer (); - - - if (SA1.Executing) - S9xSA1MainLoop (); - DO_HBLANK_CHECK (); - - } -} - // USE_SA1 - #endif - -void S9xMainLoop_NoSA1_APU (void) -{ - for (;;) - { - asm_APU_EXECUTE(1); - if (CPU.Flags) - { - if (CPU.Flags & NMI_FLAG) - { - if (--CPU.NMICycleCount == 0) - { - CPU.Flags &= ~NMI_FLAG; - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - ++CPU.PC; - } - S9xOpcode_NMI (); - } - } - - if (CPU.Flags & IRQ_PENDING_FLAG) - { - if (CPU.IRQCycleCount == 0) - { - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - if (CPU.IRQActive && !Settings.DisableIRQ) - { - if (!CheckFlag (IRQ)) - S9xOpcode_IRQ (); - } - else - CPU.Flags &= ~IRQ_PENDING_FLAG; - } - else - CPU.IRQCycleCount--; - } - if (CPU.Flags & SCAN_KEYS_FLAG) - break; - } - -#ifdef CPU_SHUTDOWN - CPU.PCAtOpcodeStart = CPU.PC; -#endif -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#else - CPU.Cycles += ICPU.Speed [*CPU.PC]; -#endif - (*ICPU.S9xOpcodes[*CPU.PC++].S9xOpcode) (); - - - //S9xUpdateAPUTimer (); - - DO_HBLANK_CHECK (); - } -} - -void S9xMainLoop_NoSA1_NoAPU (void) -{ - for (;;) - { - if (CPU.Flags) - { - if (CPU.Flags & NMI_FLAG) - { - if (--CPU.NMICycleCount == 0) - { - CPU.Flags &= ~NMI_FLAG; - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - ++CPU.PC; - } - S9xOpcode_NMI (); - } - } - - if (CPU.Flags & IRQ_PENDING_FLAG) - { - if (CPU.IRQCycleCount == 0) - { - if (CPU.WaitingForInterrupt) - { - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } - if (CPU.IRQActive && !Settings.DisableIRQ) - { - if (!CheckFlag (IRQ)) - S9xOpcode_IRQ (); - } - else - CPU.Flags &= ~IRQ_PENDING_FLAG; - } - else - CPU.IRQCycleCount--; - } - if (CPU.Flags & SCAN_KEYS_FLAG) - break; - } - -#ifdef CPU_SHUTDOWN - CPU.PCAtOpcodeStart = CPU.PC; -#endif -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#else - CPU.Cycles += ICPU.Speed [*CPU.PC]; -#endif - (*ICPU.S9xOpcodes[*CPU.PC++].S9xOpcode) (); - - - //S9xUpdateAPUTimer (); - - - DO_HBLANK_CHECK (); - - } -} -#endif - - -void -S9xMainLoop (void) -{ -#ifndef ASMCPU - if (Settings.APUEnabled == 1) { - #ifdef USE_SA1 - if (Settings.SA1) S9xMainLoop_SA1_APU(); - else - #endif - S9xMainLoop_NoSA1_APU(); - } else { - #ifdef USE_SA1 - if (Settings.SA1) S9xMainLoop_SA1_NoAPU(); - else S9xMainLoop_NoSA1_NoAPU(); - #endif - - } -#else - if (Settings.asmspc700) asmMainLoop_spcAsm(&CPU); - else asmMainLoop_spcC(&CPU); -#endif - Registers.PC = CPU.PC - CPU.PCBase; - -#ifndef ASMCPU - S9xPackStatus (); -#endif - - S9xAPUPackStatus (); - - - //if (CPU.Flags & SCAN_KEYS_FLAG) - // { - CPU.Flags &= ~SCAN_KEYS_FLAG; - //} - - if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2) - { - CPU.TriedInterleavedMode2 = TRUE; - CPU.BRKTriggered = FALSE; - S9xDeinterleaveMode2 (); - } -} - -void S9xSetIRQ (uint32 source) -{ - CPU.IRQActive |= source; - CPU.Flags |= IRQ_PENDING_FLAG; - CPU.IRQCycleCount = 3; - if (CPU.WaitingForInterrupt) - { - // Force IRQ to trigger immediately after WAI - - // Final Fantasy Mystic Quest crashes without this. - CPU.IRQCycleCount = 0; - CPU.WaitingForInterrupt = FALSE; - CPU.PC++; - } -} - -void S9xClearIRQ (uint32 source) -{ - CLEAR_IRQ_SOURCE (source); -} - -void S9xDoHBlankProcessing () -{ -#ifdef CPU_SHUTDOWN - CPU.WaitCounter++; -#endif - - switch (CPU.WhichEvent) - { - case HBLANK_START_EVENT: - if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) - IPPU.HDMA = S9xDoHDMA (IPPU.HDMA); - break; - - case HBLANK_END_EVENT: - asm_APU_EXECUTE(3); // notaz: run spc700 in sound 'speed hack' mode - if(Settings.SuperFX) - S9xSuperFXExec (); - - CPU.Cycles -= Settings.H_Max; - if (/*IAPU.APUExecuting*/CPU.APU_APUExecuting) - CPU.APU_Cycles -= Settings.H_Max; - else - CPU.APU_Cycles = 0; - - CPU.NextEvent = -1; - ICPU.Scanline++; - - if (++CPU.V_Counter >= (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER)) - { - CPU.V_Counter = 0; - CPU.NMIActive = FALSE; - ICPU.Frame++; - PPU.HVBeamCounterLatched = 0; - CPU.Flags |= SCAN_KEYS_FLAG; - S9xStartHDMA (); - } - - if (PPU.VTimerEnabled && !PPU.HTimerEnabled && - CPU.V_Counter == PPU.IRQVBeamPos) - { - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - - if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) - { - // Start of V-blank - S9xEndScreenRefresh (); - IPPU.HDMA = 0; - // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. - missing.dma_this_frame = 0; - IPPU.MaxBrightness = PPU.Brightness; - PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; - - if(!PPU.ForcedBlanking){ - PPU.OAMAddr = PPU.SavedOAMAddr; - PPU.OAMFlip = 0; - PPU.FirstSprite = 0; - if(PPU.OAMPriorityRotation) - PPU.FirstSprite = PPU.OAMAddr>>1; - } - - Memory.FillRAM[0x4210] = 0x80; - if (Memory.FillRAM[0x4200] & 0x80) - { - CPU.NMIActive = TRUE; - CPU.Flags |= NMI_FLAG; - CPU.NMICycleCount = CPU.NMITriggerPoint; - } - - } - - if (CPU.V_Counter == PPU.ScreenHeight + 3) - S9xUpdateJoypads (); - - if (CPU.V_Counter == FIRST_VISIBLE_LINE) - { - Memory.FillRAM[0x4210] = 0; - CPU.Flags &= ~NMI_FLAG; - S9xStartScreenRefresh (); - } - if (CPU.V_Counter >= FIRST_VISIBLE_LINE && - CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) - { - RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE); - } - // Use TimerErrorCounter to skip update of SPC700 timers once - // every 128 updates. Needed because this section of code is called - // once every emulated 63.5 microseconds, which coresponds to - // 15.750KHz, but the SPC700 timers need to be updated at multiples - // of 8KHz, hence the error correction. - // IAPU.TimerErrorCounter++; - // if (IAPU.TimerErrorCounter >= ) - // IAPU.TimerErrorCounter = 0; - // else - { - if (APU.TimerEnabled [2]) - { - APU.Timer [2] += 4; - while (APU.Timer [2] >= APU.TimerTarget [2]) - { - IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf; - APU.Timer [2] -= APU.TimerTarget [2]; -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; - /*IAPU.APUExecuting*/CPU.APU_APUExecuting= TRUE; -#endif - } - } - if (CPU.V_Counter & 1) - { - if (APU.TimerEnabled [0]) - { - APU.Timer [0]++; - if (APU.Timer [0] >= APU.TimerTarget [0]) - { - IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf; - APU.Timer [0] = 0; -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; - /*IAPU.APUExecuting*/CPU.APU_APUExecuting = TRUE; -#endif - } - } - if (APU.TimerEnabled [1]) - { - APU.Timer [1]++; - if (APU.Timer [1] >= APU.TimerTarget [1]) - { - IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf; - APU.Timer [1] = 0; -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; - /*IAPU.APUExecuting*/CPU.APU_APUExecuting = TRUE; -#endif - } - } - } - } - break; - case HTIMER_BEFORE_EVENT: - case HTIMER_AFTER_EVENT: - if (PPU.HTimerEnabled && - (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos)) - { - S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE); - } - break; - } - S9xReschedule (); -} - diff --git a/src/cpuexec.h b/src/cpuexec.h index 649d0ec..de057bf 100644 --- a/src/cpuexec.h +++ b/src/cpuexec.h @@ -40,26 +40,27 @@ */ #ifndef _CPUEXEC_H_ #define _CPUEXEC_H_ -#include "ppu.h" -#include "memmap.h" +//#include "ppu.h" +//#include "memmap.h" +#include "snes9x.h" #include "65c816.h" #define DO_HBLANK_CHECK() \ if (CPU.Cycles >= CPU.NextEvent) \ S9xDoHBlankProcessing (); -struct SOpcodes { +typedef struct{ #ifdef __WIN32__ void (__cdecl *S9xOpcode)( void); #else void (*S9xOpcode)( void); #endif -}; +}SOpcodes; -struct SICPU +typedef struct { uint8 *Speed; - struct SOpcodes *S9xOpcodes; + SOpcodes *S9xOpcodes; uint8 _Carry; uint8 _Zero; uint8 _Negative; @@ -70,7 +71,7 @@ struct SICPU uint32 Frame; uint32 Scanline; uint32 FrameAdvanceCount; -}; +}SICPU; START_EXTERN_C void S9xMainLoop (void); @@ -79,10 +80,10 @@ void S9xDoHBlankProcessing (); void S9xClearIRQ (uint32); void S9xSetIRQ (uint32); -extern struct SOpcodes S9xOpcodesM1X1 [256]; -extern struct SOpcodes S9xOpcodesM1X0 [256]; -extern struct SOpcodes S9xOpcodesM0X1 [256]; -extern struct SOpcodes S9xOpcodesM0X0 [256]; +extern SOpcodes S9xOpcodesM1X1 [256]; +extern SOpcodes S9xOpcodesM1X0 [256]; +extern SOpcodes S9xOpcodesM0X1 [256]; +extern SOpcodes S9xOpcodesM0X0 [256]; #ifndef VAR_CYCLES extern uint8 S9xE1M1X1 [256]; @@ -92,7 +93,7 @@ extern uint8 S9xE0M0X0 [256]; extern uint8 S9xE0M0X1 [256]; #endif -extern struct SICPU ICPU; +extern SICPU ICPU; END_EXTERN_C STATIC inline void CLEAR_IRQ_SOURCE (uint32 M) diff --git a/src/cpuops.c b/src/cpuops.c new file mode 100644 index 0000000..011ef73 --- /dev/null +++ b/src/cpuops.c @@ -0,0 +1,4247 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +/**********************************************************************************************/ +/* CPU-S9xOpcodes.CPP */ +/* This file contains all the opcodes */ +/**********************************************************************************************/ + +#include "snes9x.h" +#include "memmap.h" +#include "missing.h" +#include "apu.h" +#include "sa1.h" +//#include "spc7110.h" + +#include "cpuexec.h" +#include "cpuaddr.h" +#include "cpuops.h" +#include "cpumacro.h" +#include "apu.h" + +/* ADC *************************************************************************************** */ +static void Op69M1 (void) +{ + Immediate8 (); + ADC8 (); +} + +static void Op69M0 (void) +{ + Immediate16 (); + ADC16 (); +} + +static void Op65M1 (void) +{ + Direct (); + ADC8 (); +} + +static void Op65M0 (void) +{ + Direct (); + ADC16 (); +} + +static void Op75M1 (void) +{ + DirectIndexedX (); + ADC8 (); +} + +static void Op75M0 (void) +{ + DirectIndexedX (); + ADC16 (); +} + +static void Op72M1 (void) +{ + DirectIndirect (); + ADC8 (); +} + +static void Op72M0 (void) +{ + DirectIndirect (); + ADC16 (); +} + +static void Op61M1 (void) +{ + DirectIndexedIndirect (); + ADC8 (); +} + +static void Op61M0 (void) +{ + DirectIndexedIndirect (); + ADC16 (); +} + +static void Op71M1 (void) +{ + DirectIndirectIndexed (); + ADC8 (); +} + +static void Op71M0 (void) +{ + DirectIndirectIndexed (); + ADC16 (); +} + +static void Op67M1 (void) +{ + DirectIndirectLong (); + ADC8 (); +} + +static void Op67M0 (void) +{ + DirectIndirectLong (); + ADC16 (); +} + +static void Op77M1 (void) +{ + DirectIndirectIndexedLong (); + ADC8 (); +} + +static void Op77M0 (void) +{ + DirectIndirectIndexedLong (); + ADC16 (); +} + +static void Op6DM1 (void) +{ + Absolute (); + ADC8 (); +} + +static void Op6DM0 (void) +{ + Absolute (); + ADC16 (); +} + +static void Op7DM1 (void) +{ + AbsoluteIndexedX (); + ADC8 (); +} + +static void Op7DM0 (void) +{ + AbsoluteIndexedX (); + ADC16 (); +} + +static void Op79M1 (void) +{ + AbsoluteIndexedY (); + ADC8 (); +} + +static void Op79M0 (void) +{ + AbsoluteIndexedY (); + ADC16 (); +} + +static void Op6FM1 (void) +{ + AbsoluteLong (); + ADC8 (); +} + +static void Op6FM0 (void) +{ + AbsoluteLong (); + ADC16 (); +} + +static void Op7FM1 (void) +{ + AbsoluteLongIndexedX (); + ADC8 (); +} + +static void Op7FM0 (void) +{ + AbsoluteLongIndexedX (); + ADC16 (); +} + +static void Op63M1 (void) +{ + StackRelative (); + ADC8 (); +} + +static void Op63M0 (void) +{ + StackRelative (); + ADC16 (); +} + +static void Op73M1 (void) +{ + StackRelativeIndirectIndexed (); + ADC8 (); +} + +static void Op73M0 (void) +{ + StackRelativeIndirectIndexed (); + ADC16 (); +} + +/**********************************************************************************************/ + +/* AND *************************************************************************************** */ +static void Op29M1 (void) +{ + Registers.AL &= *CPU.PC++; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (Registers.AL); +} + +static void Op29M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + Registers.A.W &= *(uint16 *) CPU.PC; +#else + Registers.A.W &= *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + CPU.PC += 2; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (Registers.A.W); +} + +static void Op25M1 (void) +{ + Direct (); + AND8 (); +} + +static void Op25M0 (void) +{ + Direct (); + AND16 (); +} + +static void Op35M1 (void) +{ + DirectIndexedX (); + AND8 (); +} + +static void Op35M0 (void) +{ + DirectIndexedX (); + AND16 (); +} + +static void Op32M1 (void) +{ + DirectIndirect (); + AND8 (); +} + +static void Op32M0 (void) +{ + DirectIndirect (); + AND16 (); +} + +static void Op21M1 (void) +{ + DirectIndexedIndirect (); + AND8 (); +} + +static void Op21M0 (void) +{ + DirectIndexedIndirect (); + AND16 (); +} + +static void Op31M1 (void) +{ + DirectIndirectIndexed (); + AND8 (); +} + +static void Op31M0 (void) +{ + DirectIndirectIndexed (); + AND16 (); +} + +static void Op27M1 (void) +{ + DirectIndirectLong (); + AND8 (); +} + +static void Op27M0 (void) +{ + DirectIndirectLong (); + AND16 (); +} + +static void Op37M1 (void) +{ + DirectIndirectIndexedLong (); + AND8 (); +} + +static void Op37M0 (void) +{ + DirectIndirectIndexedLong (); + AND16 (); +} + +static void Op2DM1 (void) +{ + Absolute (); + AND8 (); +} + +static void Op2DM0 (void) +{ + Absolute (); + AND16 (); +} + +static void Op3DM1 (void) +{ + AbsoluteIndexedX (); + AND8 (); +} + +static void Op3DM0 (void) +{ + AbsoluteIndexedX (); + AND16 (); +} + +static void Op39M1 (void) +{ + AbsoluteIndexedY (); + AND8 (); +} + +static void Op39M0 (void) +{ + AbsoluteIndexedY (); + AND16 (); +} + +static void Op2FM1 (void) +{ + AbsoluteLong (); + AND8 (); +} + +static void Op2FM0 (void) +{ + AbsoluteLong (); + AND16 (); +} + +static void Op3FM1 (void) +{ + AbsoluteLongIndexedX (); + AND8 (); +} + +static void Op3FM0 (void) +{ + AbsoluteLongIndexedX (); + AND16 (); +} + +static void Op23M1 (void) +{ + StackRelative (); + AND8 (); +} + +static void Op23M0 (void) +{ + StackRelative (); + AND16 (); +} + +static void Op33M1 (void) +{ + StackRelativeIndirectIndexed (); + AND8 (); +} + +static void Op33M0 (void) +{ + StackRelativeIndirectIndexed (); + AND16 (); +} +/**********************************************************************************************/ + +/* ASL *************************************************************************************** */ +static void Op0AM1 (void) +{ + A_ASL8 (); +} + +static void Op0AM0 (void) +{ + A_ASL16 (); +} + +static void Op06M1 (void) +{ + Direct (); + ASL8 (); +} + +static void Op06M0 (void) +{ + Direct (); + ASL16 (); +} + +static void Op16M1 (void) +{ + DirectIndexedX (); + ASL8 (); +} + +static void Op16M0 (void) +{ + DirectIndexedX (); + ASL16 (); + +} + +static void Op0EM1 (void) +{ + Absolute (); + ASL8 (); +} + +static void Op0EM0 (void) +{ + Absolute (); + ASL16 (); +} + +static void Op1EM1 (void) +{ + AbsoluteIndexedX (); + ASL8 (); +} + +static void Op1EM0 (void) +{ + AbsoluteIndexedX (); + ASL16 (); +} +/**********************************************************************************************/ + +/* BIT *************************************************************************************** */ +static void Op89M1 (void) +{ + ICPU._Zero = Registers.AL & *CPU.PC++; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void Op89M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + ICPU._Zero = (Registers.A.W & *(uint16 *) CPU.PC) != 0; +#else + ICPU._Zero = (Registers.A.W & (*CPU.PC + (*(CPU.PC + 1) << 8))) != 0; +#endif +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2; +#endif + CPU.PC += 2; +} + +static void Op24M1 (void) +{ + Direct (); + BIT8 (); +} + +static void Op24M0 (void) +{ + Direct (); + BIT16 (); +} + +static void Op34M1 (void) +{ + DirectIndexedX (); + BIT8 (); +} + +static void Op34M0 (void) +{ + DirectIndexedX (); + BIT16 (); +} + +static void Op2CM1 (void) +{ + Absolute (); + BIT8 (); +} + +static void Op2CM0 (void) +{ + Absolute (); + BIT16 (); +} + +static void Op3CM1 (void) +{ + AbsoluteIndexedX (); + BIT8 (); +} + +static void Op3CM0 (void) +{ + AbsoluteIndexedX (); + BIT16 (); +} +/**********************************************************************************************/ + +/* CMP *************************************************************************************** */ +static void OpC9M1 (void) +{ + long s9xInt32 = (int) Registers.AL - (int) *CPU.PC++; + ICPU._Carry = s9xInt32 >= 0; + SetZN8 ((uint8) s9xInt32); +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpC9M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + long s9xInt32 = (long) Registers.A.W - (long) *(uint16 *) CPU.PC; +#else + long s9xInt32 = (long) Registers.A.W - + (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); +#endif + ICPU._Carry = s9xInt32 >= 0; + SetZN16 ((uint16) s9xInt32); + CPU.PC += 2; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpC5M1 (void) +{ + Direct (); + CMP8 (); +} + +static void OpC5M0 (void) +{ + Direct (); + CMP16 (); +} + +static void OpD5M1 (void) +{ + DirectIndexedX (); + CMP8 (); +} + +static void OpD5M0 (void) +{ + DirectIndexedX (); + CMP16 (); +} + +static void OpD2M1 (void) +{ + DirectIndirect (); + CMP8 (); +} + +static void OpD2M0 (void) +{ + DirectIndirect (); + CMP16 (); +} + +static void OpC1M1 (void) +{ + DirectIndexedIndirect (); + CMP8 (); +} + +static void OpC1M0 (void) +{ + DirectIndexedIndirect (); + CMP16 (); +} + +static void OpD1M1 (void) +{ + DirectIndirectIndexed (); + CMP8 (); +} + +static void OpD1M0 (void) +{ + DirectIndirectIndexed (); + CMP16 (); +} + +static void OpC7M1 (void) +{ + DirectIndirectLong (); + CMP8 (); +} + +static void OpC7M0 (void) +{ + DirectIndirectLong (); + CMP16 (); +} + +static void OpD7M1 (void) +{ + DirectIndirectIndexedLong (); + CMP8 (); +} + +static void OpD7M0 (void) +{ + DirectIndirectIndexedLong (); + CMP16 (); +} + +static void OpCDM1 (void) +{ + Absolute (); + CMP8 (); +} + +static void OpCDM0 (void) +{ + Absolute (); + CMP16 (); +} + +static void OpDDM1 (void) +{ + AbsoluteIndexedX (); + CMP8 (); +} + +static void OpDDM0 (void) +{ + AbsoluteIndexedX (); + CMP16 (); +} + +static void OpD9M1 (void) +{ + AbsoluteIndexedY (); + CMP8 (); +} + +static void OpD9M0 (void) +{ + AbsoluteIndexedY (); + CMP16 (); +} + +static void OpCFM1 (void) +{ + AbsoluteLong (); + CMP8 (); +} + +static void OpCFM0 (void) +{ + AbsoluteLong (); + CMP16 (); +} + +static void OpDFM1 (void) +{ + AbsoluteLongIndexedX (); + CMP8 (); +} + +static void OpDFM0 (void) +{ + AbsoluteLongIndexedX (); + CMP16 (); +} + +static void OpC3M1 (void) +{ + StackRelative (); + CMP8 (); +} + +static void OpC3M0 (void) +{ + StackRelative (); + CMP16 (); +} + +static void OpD3M1 (void) +{ + StackRelativeIndirectIndexed (); + CMP8 (); +} + +static void OpD3M0 (void) +{ + StackRelativeIndirectIndexed (); + CMP16 (); +} + +/**********************************************************************************************/ + +/* CMX *************************************************************************************** */ +static void OpE0X1 (void) +{ + long s9xInt32 = (int) Registers.XL - (int) *CPU.PC++; + ICPU._Carry = s9xInt32 >= 0; + SetZN8 ((uint8) s9xInt32); +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpE0X0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + long s9xInt32 = (long) Registers.X.W - (long) *(uint16 *) CPU.PC; +#else + long s9xInt32 = (long) Registers.X.W - + (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); +#endif + ICPU._Carry = s9xInt32 >= 0; + SetZN16 ((uint16) s9xInt32); + CPU.PC += 2; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpE4X1 (void) +{ + Direct (); + CMX8 (); +} + +static void OpE4X0 (void) +{ + Direct (); + CMX16 (); +} + +static void OpECX1 (void) +{ + Absolute (); + CMX8 (); +} + +static void OpECX0 (void) +{ + Absolute (); + CMX16 (); +} + +/**********************************************************************************************/ + +/* CMY *************************************************************************************** */ +static void OpC0X1 (void) +{ + long s9xInt32 = (int) Registers.YL - (int) *CPU.PC++; + ICPU._Carry = s9xInt32 >= 0; + SetZN8 ((uint8) s9xInt32); +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#endif +} + +static void OpC0X0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + long s9xInt32 = (long) Registers.Y.W - (long) *(uint16 *) CPU.PC; +#else + long s9xInt32 = (long) Registers.Y.W - + (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); +#endif + ICPU._Carry = s9xInt32 >= 0; + SetZN16 ((uint16) s9xInt32); + CPU.PC += 2; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2; +#endif +} + +static void OpC4X1 (void) +{ + Direct (); + CMY8 (); +} + +static void OpC4X0 (void) +{ + Direct (); + CMY16 (); +} + +static void OpCCX1 (void) +{ + Absolute (); + CMY8 (); +} + +static void OpCCX0 (void) +{ + Absolute (); + CMY16 (); +} + +/**********************************************************************************************/ + +/* DEC *************************************************************************************** */ +static void Op3AM1 (void) +{ + A_DEC8 (); +} + +static void Op3AM0 (void) +{ + A_DEC16 (); +} + +static void OpC6M1 (void) +{ + Direct (); + DEC8 (); +} + +static void OpC6M0 (void) +{ + Direct (); + DEC16 (); +} + +static void OpD6M1 (void) +{ + DirectIndexedX (); + DEC8 (); +} + +static void OpD6M0 (void) +{ + DirectIndexedX (); + DEC16 (); +} + +static void OpCEM1 (void) +{ + Absolute (); + DEC8 (); +} + +static void OpCEM0 (void) +{ + Absolute (); + DEC16 (); +} + +static void OpDEM1 (void) +{ + AbsoluteIndexedX (); + DEC8 (); +} + +static void OpDEM0 (void) +{ + AbsoluteIndexedX (); + DEC16 (); +} + +/**********************************************************************************************/ + +/* EOR *************************************************************************************** */ +static void Op49M1 (void) +{ + Registers.AL ^= *CPU.PC++; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (Registers.AL); +} + +static void Op49M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + Registers.A.W ^= *(uint16 *) CPU.PC; +#else + Registers.A.W ^= *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + CPU.PC += 2; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (Registers.A.W); +} + +static void Op45M1 (void) +{ + Direct (); + EOR8 (); +} + +static void Op45M0 (void) +{ + Direct (); + EOR16 (); +} + +static void Op55M1 (void) +{ + DirectIndexedX (); + EOR8 (); +} + +static void Op55M0 (void) +{ + DirectIndexedX (); + EOR16 (); +} + +static void Op52M1 (void) +{ + DirectIndirect (); + EOR8 (); +} + +static void Op52M0 (void) +{ + DirectIndirect (); + EOR16 (); +} + +static void Op41M1 (void) +{ + DirectIndexedIndirect (); + EOR8 (); +} + +static void Op41M0 (void) +{ + DirectIndexedIndirect (); + EOR16 (); +} + +static void Op51M1 (void) +{ + DirectIndirectIndexed (); + EOR8 (); +} + +static void Op51M0 (void) +{ + DirectIndirectIndexed (); + EOR16 (); +} + +static void Op47M1 (void) +{ + DirectIndirectLong (); + EOR8 (); +} + +static void Op47M0 (void) +{ + DirectIndirectLong (); + EOR16 (); +} + +static void Op57M1 (void) +{ + DirectIndirectIndexedLong (); + EOR8 (); +} + +static void Op57M0 (void) +{ + DirectIndirectIndexedLong (); + EOR16 (); +} + +static void Op4DM1 (void) +{ + Absolute (); + EOR8 (); +} + +static void Op4DM0 (void) +{ + Absolute (); + EOR16 (); +} + +static void Op5DM1 (void) +{ + AbsoluteIndexedX (); + EOR8 (); +} + +static void Op5DM0 (void) +{ + AbsoluteIndexedX (); + EOR16 (); +} + +static void Op59M1 (void) +{ + AbsoluteIndexedY (); + EOR8 (); +} + +static void Op59M0 (void) +{ + AbsoluteIndexedY (); + EOR16 (); +} + +static void Op4FM1 (void) +{ + AbsoluteLong (); + EOR8 (); +} + +static void Op4FM0 (void) +{ + AbsoluteLong (); + EOR16 (); +} + +static void Op5FM1 (void) +{ + AbsoluteLongIndexedX (); + EOR8 (); +} + +static void Op5FM0 (void) +{ + AbsoluteLongIndexedX (); + EOR16 (); +} + +static void Op43M1 (void) +{ + StackRelative (); + EOR8 (); +} + +static void Op43M0 (void) +{ + StackRelative (); + EOR16 (); +} + +static void Op53M1 (void) +{ + StackRelativeIndirectIndexed (); + EOR8 (); +} + +static void Op53M0 (void) +{ + StackRelativeIndirectIndexed (); + EOR16 (); +} + +/**********************************************************************************************/ + +/* INC *************************************************************************************** */ +static void Op1AM1 (void) +{ + A_INC8 (); +} + +static void Op1AM0 (void) +{ + A_INC16 (); +} + +static void OpE6M1 (void) +{ + Direct (); + INC8 (); +} + +static void OpE6M0 (void) +{ + Direct (); + INC16 (); +} + +static void OpF6M1 (void) +{ + DirectIndexedX (); + INC8 (); +} + +static void OpF6M0 (void) +{ + DirectIndexedX (); + INC16 (); +} + +static void OpEEM1 (void) +{ + Absolute (); + INC8 (); +} + +static void OpEEM0 (void) +{ + Absolute (); + INC16 (); +} + +static void OpFEM1 (void) +{ + AbsoluteIndexedX (); + INC8 (); +} + +static void OpFEM0 (void) +{ + AbsoluteIndexedX (); + INC16 (); +} + +/**********************************************************************************************/ +/* LDA *************************************************************************************** */ +static void OpA9M1 (void) +{ + Registers.AL = *CPU.PC++; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (Registers.AL); +} + +static void OpA9M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + Registers.A.W = *(uint16 *) CPU.PC; +#else + Registers.A.W = *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + + CPU.PC += 2; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (Registers.A.W); +} + +static void OpA5M1 (void) +{ + Direct (); + LDA8 (); +} + +static void OpA5M0 (void) +{ + Direct (); + LDA16 (); +} + +static void OpB5M1 (void) +{ + DirectIndexedX (); + LDA8 (); +} + +static void OpB5M0 (void) +{ + DirectIndexedX (); + LDA16 (); +} + +static void OpB2M1 (void) +{ + DirectIndirect (); + LDA8 (); +} + +static void OpB2M0 (void) +{ + DirectIndirect (); + LDA16 (); +} + +static void OpA1M1 (void) +{ + DirectIndexedIndirect (); + LDA8 (); +} + +static void OpA1M0 (void) +{ + DirectIndexedIndirect (); + LDA16 (); +} + +static void OpB1M1 (void) +{ + DirectIndirectIndexed (); + LDA8 (); +} + +static void OpB1M0 (void) +{ + DirectIndirectIndexed (); + LDA16 (); +} + +static void OpA7M1 (void) +{ + DirectIndirectLong (); + LDA8 (); +} + +static void OpA7M0 (void) +{ + DirectIndirectLong (); + LDA16 (); +} + +static void OpB7M1 (void) +{ + DirectIndirectIndexedLong (); + LDA8 (); +} + +static void OpB7M0 (void) +{ + DirectIndirectIndexedLong (); + LDA16 (); +} + +static void OpADM1 (void) +{ + Absolute (); + LDA8 (); +} + +static void OpADM0 (void) +{ + Absolute (); + LDA16 (); +} + +static void OpBDM1 (void) +{ + AbsoluteIndexedX (); + LDA8 (); +} + +static void OpBDM0 (void) +{ + AbsoluteIndexedX (); + LDA16 (); +} + +static void OpB9M1 (void) +{ + AbsoluteIndexedY (); + LDA8 (); +} + +static void OpB9M0 (void) +{ + AbsoluteIndexedY (); + LDA16 (); +} + +static void OpAFM1 (void) +{ + AbsoluteLong (); + LDA8 (); +} + +static void OpAFM0 (void) +{ + AbsoluteLong (); + LDA16 (); +} + +static void OpBFM1 (void) +{ + AbsoluteLongIndexedX (); + LDA8 (); +} + +static void OpBFM0 (void) +{ + AbsoluteLongIndexedX (); + LDA16 (); +} + +static void OpA3M1 (void) +{ + StackRelative (); + LDA8 (); +} + +static void OpA3M0 (void) +{ + StackRelative (); + LDA16 (); +} + +static void OpB3M1 (void) +{ + StackRelativeIndirectIndexed (); + LDA8 (); +} + +static void OpB3M0 (void) +{ + StackRelativeIndirectIndexed (); + LDA16 (); +} + +/**********************************************************************************************/ + +/* LDX *************************************************************************************** */ +static void OpA2X1 (void) +{ + Registers.XL = *CPU.PC++; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (Registers.XL); +} + +static void OpA2X0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + Registers.X.W = *(uint16 *) CPU.PC; +#else + Registers.X.W = *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + CPU.PC += 2; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (Registers.X.W); +} + +static void OpA6X1 (void) +{ + Direct (); + LDX8 (); +} + +static void OpA6X0 (void) +{ + Direct (); + LDX16 (); +} + +static void OpB6X1 (void) +{ + DirectIndexedY (); + LDX8 (); +} + +static void OpB6X0 (void) +{ + DirectIndexedY (); + LDX16 (); +} + +static void OpAEX1 (void) +{ + Absolute (); + LDX8 (); +} + +static void OpAEX0 (void) +{ + Absolute (); + LDX16 (); +} + +static void OpBEX1 (void) +{ + AbsoluteIndexedY (); + LDX8 (); +} + +static void OpBEX0 (void) +{ + AbsoluteIndexedY (); + LDX16 (); +} +/**********************************************************************************************/ + +/* LDY *************************************************************************************** */ +static void OpA0X1 (void) +{ + Registers.YL = *CPU.PC++; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (Registers.YL); +} + +static void OpA0X0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + Registers.Y.W = *(uint16 *) CPU.PC; +#else + Registers.Y.W = *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + + CPU.PC += 2; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (Registers.Y.W); +} + +static void OpA4X1 (void) +{ + Direct (); + LDY8 (); +} + +static void OpA4X0 (void) +{ + Direct (); + LDY16 (); +} + +static void OpB4X1 (void) +{ + DirectIndexedX (); + LDY8 (); +} + +static void OpB4X0 (void) +{ + DirectIndexedX (); + LDY16 (); +} + +static void OpACX1 (void) +{ + Absolute (); + LDY8 (); +} + +static void OpACX0 (void) +{ + Absolute (); + LDY16 (); +} + +static void OpBCX1 (void) +{ + AbsoluteIndexedX (); + LDY8 (); +} + +static void OpBCX0 (void) +{ + AbsoluteIndexedX (); + LDY16 (); +} +/**********************************************************************************************/ + +/* LSR *************************************************************************************** */ +static void Op4AM1 (void) +{ + A_LSR8 (); +} + +static void Op4AM0 (void) +{ + A_LSR16 (); +} + +static void Op46M1 (void) +{ + Direct (); + LSR8 (); +} + +static void Op46M0 (void) +{ + Direct (); + LSR16 (); +} + +static void Op56M1 (void) +{ + DirectIndexedX (); + LSR8 (); +} + +static void Op56M0 (void) +{ + DirectIndexedX (); + LSR16 (); +} + +static void Op4EM1 (void) +{ + Absolute (); + LSR8 (); +} + +static void Op4EM0 (void) +{ + Absolute (); + LSR16 (); +} + +static void Op5EM1 (void) +{ + AbsoluteIndexedX (); + LSR8 (); +} + +static void Op5EM0 (void) +{ + AbsoluteIndexedX (); + LSR16 (); +} + +/**********************************************************************************************/ + +/* ORA *************************************************************************************** */ +static void Op09M1 (void) +{ + Registers.AL |= *CPU.PC++; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; +#endif + SetZN8 (Registers.AL); +} + +static void Op09M0 (void) +{ +#ifdef FAST_LSB_WORD_ACCESS + Registers.A.W |= *(uint16 *) CPU.PC; +#else + Registers.A.W |= *CPU.PC + (*(CPU.PC + 1) << 8); +#endif + CPU.PC += 2; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2; +#endif + SetZN16 (Registers.A.W); +} + +static void Op05M1 (void) +{ + Direct (); + ORA8 (); +} + +static void Op05M0 (void) +{ + Direct (); + ORA16 (); +} + +static void Op15M1 (void) +{ + DirectIndexedX (); + ORA8 (); +} + +static void Op15M0 (void) +{ + DirectIndexedX (); + ORA16 (); +} + +static void Op12M1 (void) +{ + DirectIndirect (); + ORA8 (); +} + +static void Op12M0 (void) +{ + DirectIndirect (); + ORA16 (); +} + +static void Op01M1 (void) +{ + DirectIndexedIndirect (); + ORA8 (); +} + +static void Op01M0 (void) +{ + DirectIndexedIndirect (); + ORA16 (); +} + +static void Op11M1 (void) +{ + DirectIndirectIndexed (); + ORA8 (); +} + +static void Op11M0 (void) +{ + DirectIndirectIndexed (); + ORA16 (); +} + +static void Op07M1 (void) +{ + DirectIndirectLong (); + ORA8 (); +} + +static void Op07M0 (void) +{ + DirectIndirectLong (); + ORA16 (); +} + +static void Op17M1 (void) +{ + DirectIndirectIndexedLong (); + ORA8 (); +} + +static void Op17M0 (void) +{ + DirectIndirectIndexedLong (); + ORA16 (); +} + +static void Op0DM1 (void) +{ + Absolute (); + ORA8 (); +} + +static void Op0DM0 (void) +{ + Absolute (); + ORA16 (); +} + +static void Op1DM1 (void) +{ + AbsoluteIndexedX (); + ORA8 (); +} + +static void Op1DM0 (void) +{ + AbsoluteIndexedX (); + ORA16 (); +} + +static void Op19M1 (void) +{ + AbsoluteIndexedY (); + ORA8 (); +} + +static void Op19M0 (void) +{ + AbsoluteIndexedY (); + ORA16 (); +} + +static void Op0FM1 (void) +{ + AbsoluteLong (); + ORA8 (); +} + +static void Op0FM0 (void) +{ + AbsoluteLong (); + ORA16 (); +} + +static void Op1FM1 (void) +{ + AbsoluteLongIndexedX (); + ORA8 (); +} + +static void Op1FM0 (void) +{ + AbsoluteLongIndexedX (); + ORA16 (); +} + +static void Op03M1 (void) +{ + StackRelative (); + ORA8 (); +} + +static void Op03M0 (void) +{ + StackRelative (); + ORA16 (); +} + +static void Op13M1 (void) +{ + StackRelativeIndirectIndexed (); + ORA8 (); +} + +static void Op13M0 (void) +{ + StackRelativeIndirectIndexed (); + ORA16 (); +} + +/**********************************************************************************************/ + +/* ROL *************************************************************************************** */ +static void Op2AM1 (void) +{ + A_ROL8 (); +} + +static void Op2AM0 (void) +{ + A_ROL16 (); +} + +static void Op26M1 (void) +{ + Direct (); + ROL8 (); +} + +static void Op26M0 (void) +{ + Direct (); + ROL16 (); +} + +static void Op36M1 (void) +{ + DirectIndexedX (); + ROL8 (); +} + +static void Op36M0 (void) +{ + DirectIndexedX (); + ROL16 (); +} + +static void Op2EM1 (void) +{ + Absolute (); + ROL8 (); +} + +static void Op2EM0 (void) +{ + Absolute (); + ROL16 (); +} + +static void Op3EM1 (void) +{ + AbsoluteIndexedX (); + ROL8 (); +} + +static void Op3EM0 (void) +{ + AbsoluteIndexedX (); + ROL16 (); +} +/**********************************************************************************************/ + +/* ROR *************************************************************************************** */ +static void Op6AM1 (void) +{ + A_ROR8 (); +} + +static void Op6AM0 (void) +{ + A_ROR16 (); +} + +static void Op66M1 (void) +{ + Direct (); + ROR8 (); +} + +static void Op66M0 (void) +{ + Direct (); + ROR16 (); +} + +static void Op76M1 (void) +{ + DirectIndexedX (); + ROR8 (); +} + +static void Op76M0 (void) +{ + DirectIndexedX (); + ROR16 (); +} + +static void Op6EM1 (void) +{ + Absolute (); + ROR8 (); +} + +static void Op6EM0 (void) +{ + Absolute (); + ROR16 (); +} + +static void Op7EM1 (void) +{ + AbsoluteIndexedX (); + ROR8 (); +} + +static void Op7EM0 (void) +{ + AbsoluteIndexedX (); + ROR16 (); +} +/**********************************************************************************************/ + +/* SBC *************************************************************************************** */ +static void OpE9M1 (void) +{ + Immediate8 (); + SBC8 (); +} + +static void OpE9M0 (void) +{ + Immediate16 (); + SBC16 (); +} + +static void OpE5M1 (void) +{ + Direct (); + SBC8 (); +} + +static void OpE5M0 (void) +{ + Direct (); + SBC16 (); +} + +static void OpF5M1 (void) +{ + DirectIndexedX (); + SBC8 (); +} + +static void OpF5M0 (void) +{ + DirectIndexedX (); + SBC16 (); +} + +static void OpF2M1 (void) +{ + DirectIndirect (); + SBC8 (); +} + +static void OpF2M0 (void) +{ + DirectIndirect (); + SBC16 (); +} + +static void OpE1M1 (void) +{ + DirectIndexedIndirect (); + SBC8 (); +} + +static void OpE1M0 (void) +{ + DirectIndexedIndirect (); + SBC16 (); +} + +static void OpF1M1 (void) +{ + DirectIndirectIndexed (); + SBC8 (); +} + +static void OpF1M0 (void) +{ + DirectIndirectIndexed (); + SBC16 (); +} + +static void OpE7M1 (void) +{ + DirectIndirectLong (); + SBC8 (); +} + +static void OpE7M0 (void) +{ + DirectIndirectLong (); + SBC16 (); +} + +static void OpF7M1 (void) +{ + DirectIndirectIndexedLong (); + SBC8 (); +} + +static void OpF7M0 (void) +{ + DirectIndirectIndexedLong (); + SBC16 (); +} + +static void OpEDM1 (void) +{ + Absolute (); + SBC8 (); +} + +static void OpEDM0 (void) +{ + Absolute (); + SBC16 (); +} + +static void OpFDM1 (void) +{ + AbsoluteIndexedX (); + SBC8 (); +} + +static void OpFDM0 (void) +{ + AbsoluteIndexedX (); + SBC16 (); +} + +static void OpF9M1 (void) +{ + AbsoluteIndexedY (); + SBC8 (); +} + +static void OpF9M0 (void) +{ + AbsoluteIndexedY (); + SBC16 (); +} + +static void OpEFM1 (void) +{ + AbsoluteLong (); + SBC8 (); +} + +static void OpEFM0 (void) +{ + AbsoluteLong (); + SBC16 (); +} + +static void OpFFM1 (void) +{ + AbsoluteLongIndexedX (); + SBC8 (); +} + +static void OpFFM0 (void) +{ + AbsoluteLongIndexedX (); + SBC16 (); +} + +static void OpE3M1 (void) +{ + StackRelative (); + SBC8 (); +} + +static void OpE3M0 (void) +{ + StackRelative (); + SBC16 (); +} + +static void OpF3M1 (void) +{ + StackRelativeIndirectIndexed (); + SBC8 (); +} + +static void OpF3M0 (void) +{ + StackRelativeIndirectIndexed (); + SBC16 (); +} +/**********************************************************************************************/ + +/* STA *************************************************************************************** */ +static void Op85M1 (void) +{ + Direct (); + STA8 (); +} + +static void Op85M0 (void) +{ + Direct (); + STA16 (); +} + +static void Op95M1 (void) +{ + DirectIndexedX (); + STA8 (); +} + +static void Op95M0 (void) +{ + DirectIndexedX (); + STA16 (); +} + +static void Op92M1 (void) +{ + DirectIndirect (); + STA8 (); +} + +static void Op92M0 (void) +{ + DirectIndirect (); + STA16 (); +} + +static void Op81M1 (void) +{ + DirectIndexedIndirect (); + STA8 (); +#ifdef VAR_CYCLES + if (CheckIndex ()) + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op81M0 (void) +{ + DirectIndexedIndirect (); + STA16 (); +#ifdef VAR_CYCLES + if (CheckIndex ()) + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op91M1 (void) +{ + DirectIndirectIndexed (); + STA8 (); +} + +static void Op91M0 (void) +{ + DirectIndirectIndexed (); + STA16 (); +} + +static void Op87M1 (void) +{ + DirectIndirectLong (); + STA8 (); +} + +static void Op87M0 (void) +{ + DirectIndirectLong (); + STA16 (); +} + +static void Op97M1 (void) +{ + DirectIndirectIndexedLong (); + STA8 (); +} + +static void Op97M0 (void) +{ + DirectIndirectIndexedLong (); + STA16 (); +} + +static void Op8DM1 (void) +{ + Absolute (); + STA8 (); +} + +static void Op8DM0 (void) +{ + Absolute (); + STA16 (); +} + +static void Op9DM1 (void) +{ + AbsoluteIndexedX (); + STA8 (); +} + +static void Op9DM0 (void) +{ + AbsoluteIndexedX (); + STA16 (); +} + +static void Op99M1 (void) +{ + AbsoluteIndexedY (); + STA8 (); +} + +static void Op99M0 (void) +{ + AbsoluteIndexedY (); + STA16 (); +} + +static void Op8FM1 (void) +{ + AbsoluteLong (); + STA8 (); +} + +static void Op8FM0 (void) +{ + AbsoluteLong (); + STA16 (); +} + +static void Op9FM1 (void) +{ + AbsoluteLongIndexedX (); + STA8 (); +} + +static void Op9FM0 (void) +{ + AbsoluteLongIndexedX (); + STA16 (); +} + +static void Op83M1 (void) +{ + StackRelative (); + STA8 (); +} + +static void Op83M0 (void) +{ + StackRelative (); + STA16 (); +} + +static void Op93M1 (void) +{ + StackRelativeIndirectIndexed (); + STA8 (); +} + +static void Op93M0 (void) +{ + StackRelativeIndirectIndexed (); + STA16 (); +} +/**********************************************************************************************/ + +/* STX *************************************************************************************** */ +static void Op86X1 (void) +{ + Direct (); + STX8 (); +} + +static void Op86X0 (void) +{ + Direct (); + STX16 (); +} + +static void Op96X1 (void) +{ + DirectIndexedY (); + STX8 (); +} + +static void Op96X0 (void) +{ + DirectIndexedY (); + STX16 (); +} + +static void Op8EX1 (void) +{ + Absolute (); + STX8 (); +} + +static void Op8EX0 (void) +{ + Absolute (); + STX16 (); +} +/**********************************************************************************************/ + +/* STY *************************************************************************************** */ +static void Op84X1 (void) +{ + Direct (); + STY8 (); +} + +static void Op84X0 (void) +{ + Direct (); + STY16 (); +} + +static void Op94X1 (void) +{ + DirectIndexedX (); + STY8 (); +} + +static void Op94X0 (void) +{ + DirectIndexedX (); + STY16 (); +} + +static void Op8CX1 (void) +{ + Absolute (); + STY8 (); +} + +static void Op8CX0 (void) +{ + Absolute (); + STY16 (); +} +/**********************************************************************************************/ + +/* STZ *************************************************************************************** */ +static void Op64M1 (void) +{ + Direct (); + STZ8 (); +} + +static void Op64M0 (void) +{ + Direct (); + STZ16 (); +} + +static void Op74M1 (void) +{ + DirectIndexedX (); + STZ8 (); +} + +static void Op74M0 (void) +{ + DirectIndexedX (); + STZ16 (); +} + +static void Op9CM1 (void) +{ + Absolute (); + STZ8 (); +} + +static void Op9CM0 (void) +{ + Absolute (); + STZ16 (); +} + +static void Op9EM1 (void) +{ + AbsoluteIndexedX (); + STZ8 (); +} + +static void Op9EM0 (void) +{ + AbsoluteIndexedX (); + STZ16 (); +} + +/**********************************************************************************************/ + +/* TRB *************************************************************************************** */ +static void Op14M1 (void) +{ + Direct (); + TRB8 (); +} + +static void Op14M0 (void) +{ + Direct (); + TRB16 (); +} + +static void Op1CM1 (void) +{ + Absolute (); + TRB8 (); +} + +static void Op1CM0 (void) +{ + Absolute (); + TRB16 (); +} +/**********************************************************************************************/ + +/* TSB *************************************************************************************** */ +static void Op04M1 (void) +{ + Direct (); + TSB8 (); +} + +static void Op04M0 (void) +{ + Direct (); + TSB16 (); +} + +static void Op0CM1 (void) +{ + Absolute (); + TSB8 (); +} + +static void Op0CM0 (void) +{ + Absolute (); + TSB16 (); +} + +/**********************************************************************************************/ + +/* Branch Instructions *********************************************************************** */ +#ifndef SA1_OPCODES +#define BranchCheck0()\ + if( CPU.BranchSkip)\ + {\ + CPU.BranchSkip = FALSE;\ + if (!Settings.SoundSkipMethod)\ + if( CPU.PC - CPU.PCBase > OpAddress)\ + return;\ + } + +#define BranchCheck1()\ + if( CPU.BranchSkip)\ + {\ + CPU.BranchSkip = FALSE;\ + if (!Settings.SoundSkipMethod) {\ + if( CPU.PC - CPU.PCBase > OpAddress)\ + return;\ + } else \ + if (Settings.SoundSkipMethod == 1)\ + return;\ + if (Settings.SoundSkipMethod == 3)\ + if( CPU.PC - CPU.PCBase > OpAddress)\ + return;\ + else\ + CPU.PC = CPU.PCBase + OpAddress;\ + } + +#define BranchCheck2()\ + if( CPU.BranchSkip)\ + {\ + CPU.BranchSkip = FALSE;\ + if (!Settings.SoundSkipMethod) {\ + if( CPU.PC - CPU.PCBase > OpAddress)\ + return;\ + } else \ + if (Settings.SoundSkipMethod == 1)\ + CPU.PC = CPU.PCBase + OpAddress;\ + if (Settings.SoundSkipMethod == 3)\ + if (CPU.PC - CPU.PCBase > OpAddress)\ + return;\ + else\ + CPU.PC = CPU.PCBase + OpAddress;\ + } +#else +#define BranchCheck0() +#define BranchCheck1() +#define BranchCheck2() +#endif + +#ifdef CPU_SHUTDOWN +#ifndef SA1_OPCODES +static inline void CPUShutdown() { + if (Settings.Shutdown && CPU.PC == CPU.WaitAddress) { + // Don't skip cycles with a pending NMI or IRQ - could cause delayed + // interrupt. Interrupts are delayed for a few cycles already, but + // the delay could allow the shutdown code to cycle skip again. + // Was causing screen flashing on Top Gear 3000. + + if (CPU.WaitCounter == 0 && !(CPU.Flags & (IRQ_PENDING_FLAG | NMI_FLAG))) { + CPU.WaitAddress = NULL; +#ifdef USE_SA1 + if (Settings.SA1) S9xSA1ExecuteDuringSleep (); + CPU.Cycles = CPU.NextEvent; +#endif + //S9xUpdateAPUTimer(); + asm_APU_EXECUTE2(); + } else { + if (CPU.WaitCounter >= 2) CPU.WaitCounter = 1; + else CPU.WaitCounter--; + } + } +} +#else +static inline void CPUShutdown() +{ + if (Settings.Shutdown && CPU.PC == CPU.WaitAddress) + { + if (CPU.WaitCounter >= 1) + { + SA1.Executing = FALSE; + SA1.CPUExecuting = FALSE; + } + else + CPU.WaitCounter++; + } +} +#endif +#else +#define CPUShutdown() +#endif + +/* BCC */ +static void Op90 (void) +{ + Relative (); + BranchCheck0 (); + if (!CheckCarry ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles++; +#endif +#endif + CPUShutdown (); + } +} + +/* BCS */ +static void OpB0 (void) +{ + Relative (); + BranchCheck0 (); + if (CheckCarry ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles++; +#endif +#endif + CPUShutdown (); + } +} + +/* BEQ */ +static void OpF0 (void) +{ + Relative (); + BranchCheck2 (); + if (CheckZero ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles++; +#endif +#endif + CPUShutdown (); + } +} + +/* BMI */ +static void Op30 (void) +{ + Relative (); + + + BranchCheck1 (); + if (CheckNegative ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles++; +#endif +#endif + CPUShutdown (); + } +} + +/* BNE */ +static void OpD0 (void) +{ + Relative (); + BranchCheck1 (); + if (!CheckZero ()) + { + CPU.PC = CPU.PCBase + OpAddress; + +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles++; +#endif +#endif + CPUShutdown (); + } +} + +/* BPL */ +static void Op10 (void) +{ + Relative (); + BranchCheck1 (); + if (!CheckNegative ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles++; +#endif +#endif + CPUShutdown (); + } +} + +/* BRA */ +static void Op80 (void) +{ + Relative (); + CPU.PC = CPU.PCBase + OpAddress; +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles++; +#endif +#endif + CPUShutdown (); +} + +/* BVC */ +static void Op50 (void) +{ + Relative (); + BranchCheck0 (); + if (!CheckOverflow ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles++; +#endif +#endif + CPUShutdown (); + } +} + +/* BVS */ +static void Op70 (void) +{ + Relative (); + BranchCheck0 (); + if (CheckOverflow ()) + { + CPU.PC = CPU.PCBase + OpAddress; +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles++; +#endif +#endif + CPUShutdown (); + } +} +/**********************************************************************************************/ + +/* ClearFlag Instructions ******************************************************************** */ +/* CLC */ +static void Op18 (void) +{ + ClearCarry (); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +/* CLD */ +static void OpD8 (void) +{ + ClearDecimal (); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +/* CLI */ +static void Op58 (void) +{ + ClearIRQ (); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +/* CHECK_FOR_IRQ(); */ +} + +/* CLV */ +static void OpB8 (void) +{ + ClearOverflow (); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} +/**********************************************************************************************/ + +/* DEX/DEY *********************************************************************************** */ +static void OpCAX1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + Registers.XL--; + SetZN8 (Registers.XL); +} + +static void OpCAX0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + Registers.X.W--; + SetZN16 (Registers.X.W); +} + +static void Op88X1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + Registers.YL--; + SetZN8 (Registers.YL); +} + +static void Op88X0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + Registers.Y.W--; + SetZN16 (Registers.Y.W); +} +/**********************************************************************************************/ + +/* INX/INY *********************************************************************************** */ +static void OpE8X1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + Registers.XL++; + SetZN8 (Registers.XL); +} + +static void OpE8X0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + Registers.X.W++; + SetZN16 (Registers.X.W); +} + +static void OpC8X1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + Registers.YL++; + SetZN8 (Registers.YL); +} + +static void OpC8X0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = NULL; +#endif + + Registers.Y.W++; + SetZN16 (Registers.Y.W); +} + +/**********************************************************************************************/ + +/* NOP *************************************************************************************** */ +static void OpEA (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + +} +/**********************************************************************************************/ + +/* PUSH Instructions ************************************************************************* */ +#define PushW(w) \ + S9xSetWord (w, Registers.S.W - 1);\ + Registers.S.W -= 2; +#define PushB(b)\ + S9xSetByte (b, Registers.S.W--); + +static void OpF4 (void) +{ + Absolute (); + PushW ((unsigned short)OpAddress); +} + +static void OpD4 (void) +{ + DirectIndirect (); + PushW ((unsigned short)OpAddress); +} + +static void Op62 (void) +{ + RelativeLong (); + PushW ((unsigned short)OpAddress); +} + +static void Op48M1 (void) +{ + PushB (Registers.AL); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op48M0 (void) +{ + PushW (Registers.A.W); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op8B (void) +{ + PushB (Registers.DB); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op0B (void) +{ + PushW (Registers.D.W); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op4B (void) +{ + PushB (Registers.PB); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op08 (void) +{ + S9xPackStatus (); + PushB (Registers.PL); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpDAX1 (void) +{ + PushB (Registers.XL); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpDAX0 (void) +{ + PushW (Registers.X.W); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op5AX1 (void) +{ + PushB (Registers.YL); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op5AX0 (void) +{ + PushW (Registers.Y.W); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} +/**********************************************************************************************/ + +/* PULL Instructions ************************************************************************* */ +#define PullW(w) \ + w = S9xGetWord (Registers.S.W + 1); \ + Registers.S.W += 2; + +#define PullB(b)\ + b = S9xGetByte (++Registers.S.W); + +static void Op68M1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif + PullB (Registers.AL); + SetZN8 (Registers.AL); +} + +static void Op68M0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif + PullW (Registers.A.W); + SetZN16 (Registers.A.W); +} + +static void OpAB (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif + PullB (Registers.DB); + SetZN8 (Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; +} + +/* PHP */ +static void Op2B (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif + PullW (Registers.D.W); + SetZN16 (Registers.D.W); +} + +/* PLP */ +static void Op28 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif + PullB (Registers.PL); + S9xUnpackStatus (); + + if (CheckIndex ()) + { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); +/* CHECK_FOR_IRQ();*/ +} + +static void OpFAX1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif + PullB (Registers.XL); + SetZN8 (Registers.XL); +} + +static void OpFAX0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif + PullW (Registers.X.W); + SetZN16 (Registers.X.W); +} + +static void Op7AX1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif + PullB (Registers.YL); + SetZN8 (Registers.YL); +} + +static void Op7AX0 (void) +{ +#ifdef VAR_CYCLES + + CPU.Cycles += TWO_CYCLES; +#endif + PullW (Registers.Y.W); + SetZN16 (Registers.Y.W); +} + +/**********************************************************************************************/ + +/* SetFlag Instructions ********************************************************************** */ +/* SEC */ +static void Op38 (void) +{ + SetCarry (); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +/* SED */ +static void OpF8 (void) +{ + SetDecimal (); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + missing.decimal_mode = 1; +} + +/* SEI */ +static void Op78 (void) +{ + SetIRQ (); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} +/**********************************************************************************************/ + +/* Transfer Instructions ********************************************************************* */ +/* TAX8 */ +static void OpAAX1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.XL = Registers.AL; + SetZN8 (Registers.XL); +} + +/* TAX16 */ +static void OpAAX0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.X.W = Registers.A.W; + SetZN16 (Registers.X.W); +} + +/* TAY8 */ +static void OpA8X1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.YL = Registers.AL; + SetZN8 (Registers.YL); +} + +/* TAY16 */ +static void OpA8X0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.Y.W = Registers.A.W; + SetZN16 (Registers.Y.W); +} + +static void Op5B (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.D.W = Registers.A.W; + SetZN16 (Registers.D.W); +} + +static void Op1B (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.S.W = Registers.A.W; + if (CheckEmulation()) + Registers.SH = 1; +} + +static void Op7B (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.A.W = Registers.D.W; + SetZN16 (Registers.A.W); +} + +static void Op3B (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.A.W = Registers.S.W; + SetZN16 (Registers.A.W); +} + +static void OpBAX1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.XL = Registers.SL; + SetZN8 (Registers.XL); +} + +static void OpBAX0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.X.W = Registers.S.W; + SetZN16 (Registers.X.W); +} + +static void Op8AM1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.AL = Registers.XL; + SetZN8 (Registers.AL); +} + +static void Op8AM0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.A.W = Registers.X.W; + SetZN16 (Registers.A.W); +} + +static void Op9A (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.S.W = Registers.X.W; + if (CheckEmulation()) + Registers.SH = 1; +} + +static void Op9BX1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.YL = Registers.XL; + SetZN8 (Registers.YL); +} + +static void Op9BX0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.Y.W = Registers.X.W; + SetZN16 (Registers.Y.W); +} + +static void Op98M1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.AL = Registers.YL; + SetZN8 (Registers.AL); +} + +static void Op98M0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.A.W = Registers.Y.W; + SetZN16 (Registers.A.W); +} + +static void OpBBX1 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.XL = Registers.YL; + SetZN8 (Registers.XL); +} + +static void OpBBX0 (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + Registers.X.W = Registers.Y.W; + SetZN16 (Registers.X.W); +} + +/**********************************************************************************************/ + +/* XCE *************************************************************************************** */ +static void OpFB (void) +{ +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + + uint8 A1 = ICPU._Carry; + uint8 A2 = Registers.PH; + ICPU._Carry = A2 & 1; + Registers.PH = A1; + + if (CheckEmulation()) + { + SetFlags (MemoryFlag | IndexFlag); + Registers.SH = 1; + missing.emulate6502 = 1; + } + if (CheckIndex ()) + { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); +} +/**********************************************************************************************/ + +/* BRK *************************************************************************************** */ +static void Op00 (void) +{ +#ifndef SA1_OPCODES + CPU.BRKTriggered = TRUE; +#endif + + if (!CheckEmulation()) + { + PushB (Registers.PB); + PushW (CPU.PC - CPU.PCBase + 1); + S9xPackStatus (); + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; + ICPU.ShiftedPB = 0; + S9xSetPCBase (S9xGetWord (0xFFE6)); +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#else +#ifndef SA1_OPCODES + CPU.Cycles += 8; +#endif +#endif + } + else + { + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; + ICPU.ShiftedPB = 0; + S9xSetPCBase (S9xGetWord (0xFFFE)); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles += 6; +#endif +#endif + } +} +/**********************************************************************************************/ + +/* BRL ************************************************************************************** */ +static void Op82 (void) +{ + RelativeLong (); + S9xSetPCBase (ICPU.ShiftedPB + OpAddress); +} +/**********************************************************************************************/ + +/* IRQ *************************************************************************************** */ +void S9xOpcode_IRQ (void) +{ + if (!CheckEmulation()) + { + PushB (Registers.PB); + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; + ICPU.ShiftedPB = 0; +#ifdef SA1_OPCODES + S9xSA1SetPCBase (Memory.FillRAM [0x2207] | + (Memory.FillRAM [0x2208] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) + S9xSetPCBase (Memory.FillRAM [0x220e] | + (Memory.FillRAM [0x220f] << 8)); + else + S9xSetPCBase (S9xGetWord (0xFFEE)); +#endif +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#else +#ifndef SA1_OPCODES + CPU.Cycles += 8; +#endif +#endif + } + else + { + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; + ICPU.ShiftedPB = 0; +#ifdef SA1_OPCODES + S9xSA1SetPCBase (Memory.FillRAM [0x2207] | + (Memory.FillRAM [0x2208] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) + S9xSetPCBase (Memory.FillRAM [0x220e] | + (Memory.FillRAM [0x220f] << 8)); + else + S9xSetPCBase (S9xGetWord (0xFFFE)); +#endif +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles += 6; +#endif +#endif + } +} + +/**********************************************************************************************/ + +/* NMI *************************************************************************************** */ +void S9xOpcode_NMI (void) +{ + if (!CheckEmulation()) + { + PushB (Registers.PB); + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; + ICPU.ShiftedPB = 0; +#ifdef SA1_OPCODES + S9xSA1SetPCBase (Memory.FillRAM [0x2205] | + (Memory.FillRAM [0x2206] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) + S9xSetPCBase (Memory.FillRAM [0x220c] | + (Memory.FillRAM [0x220d] << 8)); + else + S9xSetPCBase (S9xGetWord (0xFFEA)); +#endif +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#else +#ifndef SA1_OPCODES + CPU.Cycles += 8; +#endif +#endif + } + else + { + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; + ICPU.ShiftedPB = 0; +#ifdef SA1_OPCODES + S9xSA1SetPCBase (Memory.FillRAM [0x2205] | + (Memory.FillRAM [0x2206] << 8)); +#else + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) + S9xSetPCBase (Memory.FillRAM [0x220c] | + (Memory.FillRAM [0x220d] << 8)); + else + S9xSetPCBase (S9xGetWord (0xFFFA)); +#endif +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles += 6; +#endif +#endif + } +} +/**********************************************************************************************/ + +/* COP *************************************************************************************** */ +static void Op02 (void) +{ + if (!CheckEmulation()) + { + PushB (Registers.PB); + PushW (CPU.PC - CPU.PCBase + 1); + S9xPackStatus (); + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; + ICPU.ShiftedPB = 0; + S9xSetPCBase (S9xGetWord (0xFFE4)); +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#else +#ifndef SA1_OPCODES + CPU.Cycles += 8; +#endif +#endif + } + else + { + PushW (CPU.PC - CPU.PCBase); + S9xPackStatus (); + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; + ICPU.ShiftedPB = 0; + S9xSetPCBase (S9xGetWord (0xFFF4)); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else +#ifndef SA1_OPCODES + CPU.Cycles += 6; +#endif +#endif + } +} +/**********************************************************************************************/ + +/* JML *************************************************************************************** */ +static void OpDC (void) +{ + AbsoluteIndirectLong (); + Registers.PB = (uint8) (OpAddress >> 16); + ICPU.ShiftedPB = OpAddress & 0xff0000; + S9xSetPCBase (OpAddress); +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif +} + +static void Op5C (void) +{ + AbsoluteLong (); + Registers.PB = (uint8) (OpAddress >> 16); + ICPU.ShiftedPB = OpAddress & 0xff0000; + S9xSetPCBase (OpAddress); +} +/**********************************************************************************************/ + +/* JMP *************************************************************************************** */ +static void Op4C (void) +{ + Absolute (); + S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); +#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) + CPUShutdown (); +#endif +} + +static void Op6C (void) +{ + AbsoluteIndirect (); + S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); +} + +static void Op7C (void) +{ + AbsoluteIndexedIndirect (); + S9xSetPCBase (ICPU.ShiftedPB + OpAddress); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} +/**********************************************************************************************/ + +/* JSL/RTL *********************************************************************************** */ +static void Op22 (void) +{ + AbsoluteLong (); + PushB (Registers.PB); + PushW (CPU.PC - CPU.PCBase - 1); + Registers.PB = (uint8) (OpAddress >> 16); + ICPU.ShiftedPB = OpAddress & 0xff0000; + S9xSetPCBase (OpAddress); +} + +static void Op6B (void) +{ + PullW (Registers.PC); + PullB (Registers.PB); + ICPU.ShiftedPB = Registers.PB << 16; + S9xSetPCBase (ICPU.ShiftedPB + ((Registers.PC + 1) & 0xffff)); +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif +} +/**********************************************************************************************/ + +/* JSR/RTS *********************************************************************************** */ +static void Op20 (void) +{ + Absolute (); + PushW (CPU.PC - CPU.PCBase - 1); + S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void OpFC (void) +{ + AbsoluteIndexedIndirect (); + PushW (CPU.PC - CPU.PCBase - 1); + S9xSetPCBase (ICPU.ShiftedPB + OpAddress); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif +} + +static void Op60 (void) +{ + PullW (Registers.PC); + S9xSetPCBase (ICPU.ShiftedPB + ((Registers.PC + 1) & 0xffff)); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE * 3; +#endif +} + +/**********************************************************************************************/ + +/* MVN/MVP *********************************************************************************** */ +static void Op54X1 (void) +{ + uint32 SrcBank; + +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; +#endif + + Registers.DB = *CPU.PC++; + ICPU.ShiftedDB = Registers.DB << 16; + SrcBank = *CPU.PC++; + + S9xSetByte (S9xGetByte ((SrcBank << 16) + Registers.X.W), + ICPU.ShiftedDB + Registers.Y.W); + + Registers.XL++; + Registers.YL++; + Registers.A.W--; + if (Registers.A.W != 0xffff) + CPU.PC -= 3; +} + +static void Op54X0 (void) +{ + uint32 SrcBank; + +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; +#endif + + Registers.DB = *CPU.PC++; + ICPU.ShiftedDB = Registers.DB << 16; + SrcBank = *CPU.PC++; + + S9xSetByte (S9xGetByte ((SrcBank << 16) + Registers.X.W), + ICPU.ShiftedDB + Registers.Y.W); + + Registers.X.W++; + Registers.Y.W++; + Registers.A.W--; + if (Registers.A.W != 0xffff) + CPU.PC -= 3; +} + +static void Op44X1 (void) +{ + uint32 SrcBank; + +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; +#endif + Registers.DB = *CPU.PC++; + ICPU.ShiftedDB = Registers.DB << 16; + SrcBank = *CPU.PC++; + S9xSetByte (S9xGetByte ((SrcBank << 16) + Registers.X.W), + ICPU.ShiftedDB + Registers.Y.W); + + Registers.XL--; + Registers.YL--; + Registers.A.W--; + if (Registers.A.W != 0xffff) + CPU.PC -= 3; +} + +static void Op44X0 (void) +{ + uint32 SrcBank; + +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; +#endif + Registers.DB = *CPU.PC++; + ICPU.ShiftedDB = Registers.DB << 16; + SrcBank = *CPU.PC++; + S9xSetByte (S9xGetByte ((SrcBank << 16) + Registers.X.W), + ICPU.ShiftedDB + Registers.Y.W); + + Registers.X.W--; + Registers.Y.W--; + Registers.A.W--; + if (Registers.A.W != 0xffff) + CPU.PC -= 3; +} + +/**********************************************************************************************/ + +/* REP/SEP *********************************************************************************** */ +static void OpC2 (void) +{ + uint8 Work8 = ~*CPU.PC++; + Registers.PL &= Work8; + ICPU._Carry &= Work8; + ICPU._Overflow &= (Work8 >> 6); + ICPU._Negative &= Work8; + ICPU._Zero |= ~Work8 & Zero; + +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + if (CheckEmulation()) + { + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + if (CheckIndex ()) + { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); +/* CHECK_FOR_IRQ(); */ +} + +static void OpE2 (void) +{ + uint8 Work8 = *CPU.PC++; + Registers.PL |= Work8; + ICPU._Carry |= Work8 & 1; + ICPU._Overflow |= (Work8 >> 6) & 1; + ICPU._Negative |= Work8; + if (Work8 & Zero) + ICPU._Zero = 0; +#ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; +#endif + if (CheckEmulation()) + { + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + if (CheckIndex ()) + { + Registers.XH = 0; + Registers.YH = 0; + } + S9xFixCycles(); +} +/**********************************************************************************************/ + +/* XBA *************************************************************************************** */ +static void OpEB (void) +{ + uint8 Work8 = Registers.AL; + Registers.AL = Registers.AH; + Registers.AH = Work8; + + SetZN8 (Registers.AL); +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif +} +/**********************************************************************************************/ + +/* RTI *************************************************************************************** */ +static void Op40 (void) +{ + PullB (Registers.PL); + S9xUnpackStatus (); + PullW (Registers.PC); + if (!CheckEmulation()) + { + PullB (Registers.PB); + ICPU.ShiftedPB = Registers.PB << 16; + } + else + { + SetFlags (MemoryFlag | IndexFlag); + missing.emulate6502 = 1; + } + S9xSetPCBase (ICPU.ShiftedPB + Registers.PC); + + if (CheckIndex ()) + { + Registers.XH = 0; + Registers.YH = 0; + } +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#endif + S9xFixCycles(); +/* CHECK_FOR_IRQ(); */ +} + +/**********************************************************************************************/ + +/* STP/WAI/DB ******************************************************************************** */ +// WAI +static void OpCB (void) +{ + if (CPU.IRQActive) + { +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#else +#ifndef SA1_OPCODES + CPU.Cycles += 2; +#endif +#endif + } + else + { + CPU.WaitingForInterrupt = TRUE; + CPU.PC--; +#ifdef CPU_SHUTDOWN +#ifndef SA1_OPCODES + if (Settings.Shutdown) + { + CPU.Cycles = CPU.NextEvent; + asm_APU_EXECUTE2(); + } +#else + if (Settings.Shutdown) + { + SA1.CPUExecuting = FALSE; + SA1.Executing = FALSE; + } +#endif +#endif + } +} + +// STP +static void OpDB (void) +{ + CPU.PC--; + CPU.Flags |= DEBUG_MODE_FLAG; +} + +// Reserved S9xOpcode +static void Op42 (void) { +#ifndef SA1_OPCODES + uint8 b; + + CPU.WaitAddress = NULL; + CPU.Cycles = CPU.NextEvent; + asm_APU_EXECUTE2(); + //debug_log("toto"); + b=*CPU.PC++; + + //relative + signed char s9xInt8=0xF0|(b&0xF); + #ifdef VAR_CYCLES + CPU.Cycles += CPU.MemSpeed; + #endif + OpAddress = ((int) (CPU.PC - CPU.PCBase) + s9xInt8) & 0xffff; + + switch (b&0xF0) { + case 0x10: //BPL + BranchCheck1 (); + if (!CheckNegative ()) { + CPU.PC = CPU.PCBase + OpAddress; + #ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; + #else + #ifndef SA1_OPCODES + CPU.Cycles++; + #endif + #endif + CPUShutdown (); + } + return; + case 0x30: //BMI + BranchCheck1 (); + if (CheckNegative ()) { + CPU.PC = CPU.PCBase + OpAddress; + #ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; + #else + #ifndef SA1_OPCODES + CPU.Cycles++; + #endif + #endif + CPUShutdown (); + } + return; + case 0x50: //BVC + BranchCheck0 (); + if (!CheckOverflow ()) { + CPU.PC = CPU.PCBase + OpAddress; + #ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; + #else + #ifndef SA1_OPCODES + CPU.Cycles++; + #endif + #endif + CPUShutdown (); + } + return; + case 0x70: //BVS + BranchCheck0 (); + if (CheckOverflow ()) { + CPU.PC = CPU.PCBase + OpAddress; + #ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; + #else + #ifndef SA1_OPCODES + CPU.Cycles++; + #endif + #endif + CPUShutdown (); + } + return; + case 0x80: //BRA + //op80 + CPU.PC = CPU.PCBase + OpAddress; + #ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; + #else + #ifndef SA1_OPCODES + CPU.Cycles++; + #endif + #endif + CPUShutdown (); + return; + case 0x90: //BCC + BranchCheck0 (); + if (!CheckCarry ()) { + CPU.PC = CPU.PCBase + OpAddress; + #ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; + #else + #ifndef SA1_OPCODES + CPU.Cycles++; + #endif + #endif + CPUShutdown (); + } + return; + case 0xB0: //BCS + BranchCheck0 (); + if (CheckCarry ()) { + CPU.PC = CPU.PCBase + OpAddress; + #ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; + #else + #ifndef SA1_OPCODES + CPU.Cycles++; + #endif + #endif + CPUShutdown (); + } + return; + case 0xD0: //BNE + BranchCheck1 (); + if (!CheckZero ()) { + CPU.PC = CPU.PCBase + OpAddress; + #ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; + #else + #ifndef SA1_OPCODES + CPU.Cycles++; + #endif + #endif + CPUShutdown (); + } + return; + case 0xF0: //BEQ + BranchCheck2 (); + if (CheckZero ()) { + CPU.PC = CPU.PCBase + OpAddress; + #ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; + #else + #ifndef SA1_OPCODES + CPU.Cycles++; + #endif + #endif + CPUShutdown (); + } + return; + } +#endif +} + +/**********************************************************************************************/ + +/**********************************************************************************************/ +/* CPU-S9xOpcodes Definitions */ +/**********************************************************************************************/ +SOpcodes S9xOpcodesM1X1[256] = +{ + {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, + {Op05M1}, {Op06M1}, {Op07M1}, {Op08}, {Op09M1}, + {Op0AM1}, {Op0B}, {Op0CM1}, {Op0DM1}, {Op0EM1}, + {Op0FM1}, {Op10}, {Op11M1}, {Op12M1}, {Op13M1}, + {Op14M1}, {Op15M1}, {Op16M1}, {Op17M1}, {Op18}, + {Op19M1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1}, + {Op1EM1}, {Op1FM1}, {Op20}, {Op21M1}, {Op22}, + {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, + {Op28}, {Op29M1}, {Op2AM1}, {Op2B}, {Op2CM1}, + {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30}, {Op31M1}, + {Op32M1}, {Op33M1}, {Op34M1}, {Op35M1}, {Op36M1}, + {Op37M1}, {Op38}, {Op39M1}, {Op3AM1}, {Op3B}, + {Op3CM1}, {Op3DM1}, {Op3EM1}, {Op3FM1}, {Op40}, + {Op41M1}, {Op42}, {Op43M1}, {Op44X1}, {Op45M1}, + {Op46M1}, {Op47M1}, {Op48M1}, {Op49M1}, {Op4AM1}, + {Op4B}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, + {Op50}, {Op51M1}, {Op52M1}, {Op53M1}, {Op54X1}, + {Op55M1}, {Op56M1}, {Op57M1}, {Op58}, {Op59M1}, + {Op5AX1}, {Op5B}, {Op5C}, {Op5DM1}, {Op5EM1}, + {Op5FM1}, {Op60}, {Op61M1}, {Op62}, {Op63M1}, + {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68M1}, + {Op69M1}, {Op6AM1}, {Op6B}, {Op6C}, {Op6DM1}, + {Op6EM1}, {Op6FM1}, {Op70}, {Op71M1}, {Op72M1}, + {Op73M1}, {Op74M1}, {Op75M1}, {Op76M1}, {Op77M1}, + {Op78}, {Op79M1}, {Op7AX1}, {Op7B}, {Op7C}, + {Op7DM1}, {Op7EM1}, {Op7FM1}, {Op80}, {Op81M1}, + {Op82}, {Op83M1}, {Op84X1}, {Op85M1}, {Op86X1}, + {Op87M1}, {Op88X1}, {Op89M1}, {Op8AM1}, {Op8B}, + {Op8CX1}, {Op8DM1}, {Op8EX1}, {Op8FM1}, {Op90}, + {Op91M1}, {Op92M1}, {Op93M1}, {Op94X1}, {Op95M1}, + {Op96X1}, {Op97M1}, {Op98M1}, {Op99M1}, {Op9A}, + {Op9BX1}, {Op9CM1}, {Op9DM1}, {Op9EM1}, {Op9FM1}, + {OpA0X1}, {OpA1M1}, {OpA2X1}, {OpA3M1}, {OpA4X1}, + {OpA5M1}, {OpA6X1}, {OpA7M1}, {OpA8X1}, {OpA9M1}, + {OpAAX1}, {OpAB}, {OpACX1}, {OpADM1}, {OpAEX1}, + {OpAFM1}, {OpB0}, {OpB1M1}, {OpB2M1}, {OpB3M1}, + {OpB4X1}, {OpB5M1}, {OpB6X1}, {OpB7M1}, {OpB8}, + {OpB9M1}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM1}, + {OpBEX1}, {OpBFM1}, {OpC0X1}, {OpC1M1}, {OpC2}, + {OpC3M1}, {OpC4X1}, {OpC5M1}, {OpC6M1}, {OpC7M1}, + {OpC8X1}, {OpC9M1}, {OpCAX1}, {OpCB}, {OpCCX1}, + {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0}, {OpD1M1}, + {OpD2M1}, {OpD3M1}, {OpD4}, {OpD5M1}, {OpD6M1}, + {OpD7M1}, {OpD8}, {OpD9M1}, {OpDAX1}, {OpDB}, + {OpDC}, {OpDDM1}, {OpDEM1}, {OpDFM1}, {OpE0X1}, + {OpE1M1}, {OpE2}, {OpE3M1}, {OpE4X1}, {OpE5M1}, + {OpE6M1}, {OpE7M1}, {OpE8X1}, {OpE9M1}, {OpEA}, + + {OpEB}, {OpECX1}, {OpEDM1}, {OpEEM1}, {OpEFM1}, + {OpF0}, {OpF1M1}, {OpF2M1}, {OpF3M1}, {OpF4}, + {OpF5M1}, {OpF6M1}, {OpF7M1}, {OpF8}, {OpF9M1}, + {OpFAX1}, {OpFB}, {OpFC}, {OpFDM1}, {OpFEM1}, + {OpFFM1} +}; + +SOpcodes S9xOpcodesM1X0[256] = +{ + {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, + {Op05M1}, {Op06M1}, {Op07M1}, {Op08}, {Op09M1}, + {Op0AM1}, {Op0B}, {Op0CM1}, {Op0DM1}, {Op0EM1}, + {Op0FM1}, {Op10}, {Op11M1}, {Op12M1}, {Op13M1}, + {Op14M1}, {Op15M1}, {Op16M1}, {Op17M1}, {Op18}, + {Op19M1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1}, + {Op1EM1}, {Op1FM1}, {Op20}, {Op21M1}, {Op22}, + {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, + {Op28}, {Op29M1}, {Op2AM1}, {Op2B}, {Op2CM1}, + {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30}, {Op31M1}, + {Op32M1}, {Op33M1}, {Op34M1}, {Op35M1}, {Op36M1}, + {Op37M1}, {Op38}, {Op39M1}, {Op3AM1}, {Op3B}, + {Op3CM1}, {Op3DM1}, {Op3EM1}, {Op3FM1}, {Op40}, + {Op41M1}, {Op42}, {Op43M1}, {Op44X0}, {Op45M1}, + {Op46M1}, {Op47M1}, {Op48M1}, {Op49M1}, {Op4AM1}, + {Op4B}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, + {Op50}, {Op51M1}, {Op52M1}, {Op53M1}, {Op54X0}, + {Op55M1}, {Op56M1}, {Op57M1}, {Op58}, {Op59M1}, + {Op5AX0}, {Op5B}, {Op5C}, {Op5DM1}, {Op5EM1}, + {Op5FM1}, {Op60}, {Op61M1}, {Op62}, {Op63M1}, + {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68M1}, + {Op69M1}, {Op6AM1}, {Op6B}, {Op6C}, {Op6DM1}, + {Op6EM1}, {Op6FM1}, {Op70}, {Op71M1}, {Op72M1}, + {Op73M1}, {Op74M1}, {Op75M1}, {Op76M1}, {Op77M1}, + {Op78}, {Op79M1}, {Op7AX0}, {Op7B}, {Op7C}, + {Op7DM1}, {Op7EM1}, {Op7FM1}, {Op80}, {Op81M1}, + {Op82}, {Op83M1}, {Op84X0}, {Op85M1}, {Op86X0}, + {Op87M1}, {Op88X0}, {Op89M1}, {Op8AM1}, {Op8B}, + {Op8CX0}, {Op8DM1}, {Op8EX0}, {Op8FM1}, {Op90}, + {Op91M1}, {Op92M1}, {Op93M1}, {Op94X0}, {Op95M1}, + {Op96X0}, {Op97M1}, {Op98M1}, {Op99M1}, {Op9A}, + {Op9BX0}, {Op9CM1}, {Op9DM1}, {Op9EM1}, {Op9FM1}, + {OpA0X0}, {OpA1M1}, {OpA2X0}, {OpA3M1}, {OpA4X0}, + {OpA5M1}, {OpA6X0}, {OpA7M1}, {OpA8X0}, {OpA9M1}, + {OpAAX0}, {OpAB}, {OpACX0}, {OpADM1}, {OpAEX0}, + {OpAFM1}, {OpB0}, {OpB1M1}, {OpB2M1}, {OpB3M1}, + {OpB4X0}, {OpB5M1}, {OpB6X0}, {OpB7M1}, {OpB8}, + {OpB9M1}, {OpBAX0}, {OpBBX0}, {OpBCX0}, {OpBDM1}, + {OpBEX0}, {OpBFM1}, {OpC0X0}, {OpC1M1}, {OpC2}, + {OpC3M1}, {OpC4X0}, {OpC5M1}, {OpC6M1}, {OpC7M1}, + {OpC8X0}, {OpC9M1}, {OpCAX0}, {OpCB}, {OpCCX0}, + {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0}, {OpD1M1}, + {OpD2M1}, {OpD3M1}, {OpD4}, {OpD5M1}, {OpD6M1}, + {OpD7M1}, {OpD8}, {OpD9M1}, {OpDAX0}, {OpDB}, + {OpDC}, {OpDDM1}, {OpDEM1}, {OpDFM1}, {OpE0X0}, + {OpE1M1}, {OpE2}, {OpE3M1}, {OpE4X0}, {OpE5M1}, + {OpE6M1}, {OpE7M1}, {OpE8X0}, {OpE9M1}, {OpEA}, + {OpEB}, {OpECX0}, {OpEDM1}, {OpEEM1}, {OpEFM1}, + {OpF0}, {OpF1M1}, {OpF2M1}, {OpF3M1}, {OpF4}, + {OpF5M1}, {OpF6M1}, {OpF7M1}, {OpF8}, {OpF9M1}, + {OpFAX0}, {OpFB}, {OpFC}, {OpFDM1}, {OpFEM1}, + {OpFFM1} +}; + +SOpcodes S9xOpcodesM0X0[256] = +{ + {Op00}, {Op01M0}, {Op02}, {Op03M0}, {Op04M0}, + {Op05M0}, {Op06M0}, {Op07M0}, {Op08}, {Op09M0}, + {Op0AM0}, {Op0B}, {Op0CM0}, {Op0DM0}, {Op0EM0}, + {Op0FM0}, {Op10}, {Op11M0}, {Op12M0}, {Op13M0}, + {Op14M0}, {Op15M0}, {Op16M0}, {Op17M0}, {Op18}, + {Op19M0}, {Op1AM0}, {Op1B}, {Op1CM0}, {Op1DM0}, + {Op1EM0}, {Op1FM0}, {Op20}, {Op21M0}, {Op22}, + {Op23M0}, {Op24M0}, {Op25M0}, {Op26M0}, {Op27M0}, + {Op28}, {Op29M0}, {Op2AM0}, {Op2B}, {Op2CM0}, + {Op2DM0}, {Op2EM0}, {Op2FM0}, {Op30}, {Op31M0}, + {Op32M0}, {Op33M0}, {Op34M0}, {Op35M0}, {Op36M0}, + {Op37M0}, {Op38}, {Op39M0}, {Op3AM0}, {Op3B}, + {Op3CM0}, {Op3DM0}, {Op3EM0}, {Op3FM0}, {Op40}, + {Op41M0}, {Op42}, {Op43M0}, {Op44X0}, {Op45M0}, + {Op46M0}, {Op47M0}, {Op48M0}, {Op49M0}, {Op4AM0}, + {Op4B}, {Op4C}, {Op4DM0}, {Op4EM0}, {Op4FM0}, + {Op50}, {Op51M0}, {Op52M0}, {Op53M0}, {Op54X0}, + {Op55M0}, {Op56M0}, {Op57M0}, {Op58}, {Op59M0}, + {Op5AX0}, {Op5B}, {Op5C}, {Op5DM0}, {Op5EM0}, + {Op5FM0}, {Op60}, {Op61M0}, {Op62}, {Op63M0}, + {Op64M0}, {Op65M0}, {Op66M0}, {Op67M0}, {Op68M0}, + {Op69M0}, {Op6AM0}, {Op6B}, {Op6C}, {Op6DM0}, + {Op6EM0}, {Op6FM0}, {Op70}, {Op71M0}, {Op72M0}, + {Op73M0}, {Op74M0}, {Op75M0}, {Op76M0}, {Op77M0}, + {Op78}, {Op79M0}, {Op7AX0}, {Op7B}, {Op7C}, + {Op7DM0}, {Op7EM0}, {Op7FM0}, {Op80}, {Op81M0}, + {Op82}, {Op83M0}, {Op84X0}, {Op85M0}, {Op86X0}, + {Op87M0}, {Op88X0}, {Op89M0}, {Op8AM0}, {Op8B}, + {Op8CX0}, {Op8DM0}, {Op8EX0}, {Op8FM0}, {Op90}, + {Op91M0}, {Op92M0}, {Op93M0}, {Op94X0}, {Op95M0}, + {Op96X0}, {Op97M0}, {Op98M0}, {Op99M0}, {Op9A}, + {Op9BX0}, {Op9CM0}, {Op9DM0}, {Op9EM0}, {Op9FM0}, + {OpA0X0}, {OpA1M0}, {OpA2X0}, {OpA3M0}, {OpA4X0}, + {OpA5M0}, {OpA6X0}, {OpA7M0}, {OpA8X0}, {OpA9M0}, + {OpAAX0}, {OpAB}, {OpACX0}, {OpADM0}, {OpAEX0}, + {OpAFM0}, {OpB0}, {OpB1M0}, {OpB2M0}, {OpB3M0}, + {OpB4X0}, {OpB5M0}, {OpB6X0}, {OpB7M0}, {OpB8}, + {OpB9M0}, {OpBAX0}, {OpBBX0}, {OpBCX0}, {OpBDM0}, + {OpBEX0}, {OpBFM0}, {OpC0X0}, {OpC1M0}, {OpC2}, + {OpC3M0}, {OpC4X0}, {OpC5M0}, {OpC6M0}, {OpC7M0}, + {OpC8X0}, {OpC9M0}, {OpCAX0}, {OpCB}, {OpCCX0}, + {OpCDM0}, {OpCEM0}, {OpCFM0}, {OpD0}, {OpD1M0}, + {OpD2M0}, {OpD3M0}, {OpD4}, {OpD5M0}, {OpD6M0}, + {OpD7M0}, {OpD8}, {OpD9M0}, {OpDAX0}, {OpDB}, + {OpDC}, {OpDDM0}, {OpDEM0}, {OpDFM0}, {OpE0X0}, + {OpE1M0}, {OpE2}, {OpE3M0}, {OpE4X0}, {OpE5M0}, + {OpE6M0}, {OpE7M0}, {OpE8X0}, {OpE9M0}, {OpEA}, + {OpEB}, {OpECX0}, {OpEDM0}, {OpEEM0}, {OpEFM0}, + {OpF0}, {OpF1M0}, {OpF2M0}, {OpF3M0}, {OpF4}, + {OpF5M0}, {OpF6M0}, {OpF7M0}, {OpF8}, {OpF9M0}, + {OpFAX0}, {OpFB}, {OpFC}, {OpFDM0}, {OpFEM0}, + {OpFFM0} +}; + +SOpcodes S9xOpcodesM0X1[256] = +{ + {Op00}, {Op01M0}, {Op02}, {Op03M0}, {Op04M0}, + {Op05M0}, {Op06M0}, {Op07M0}, {Op08}, {Op09M0}, + {Op0AM0}, {Op0B}, {Op0CM0}, {Op0DM0}, {Op0EM0}, + {Op0FM0}, {Op10}, {Op11M0}, {Op12M0}, {Op13M0}, + {Op14M0}, {Op15M0}, {Op16M0}, {Op17M0}, {Op18}, + {Op19M0}, {Op1AM0}, {Op1B}, {Op1CM0}, {Op1DM0}, + {Op1EM0}, {Op1FM0}, {Op20}, {Op21M0}, {Op22}, + {Op23M0}, {Op24M0}, {Op25M0}, {Op26M0}, {Op27M0}, + {Op28}, {Op29M0}, {Op2AM0}, {Op2B}, {Op2CM0}, + {Op2DM0}, {Op2EM0}, {Op2FM0}, {Op30}, {Op31M0}, + {Op32M0}, {Op33M0}, {Op34M0}, {Op35M0}, {Op36M0}, + {Op37M0}, {Op38}, {Op39M0}, {Op3AM0}, {Op3B}, + {Op3CM0}, {Op3DM0}, {Op3EM0}, {Op3FM0}, {Op40}, + {Op41M0}, {Op42}, {Op43M0}, {Op44X1}, {Op45M0}, + {Op46M0}, {Op47M0}, {Op48M0}, {Op49M0}, {Op4AM0}, + {Op4B}, {Op4C}, {Op4DM0}, {Op4EM0}, {Op4FM0}, + {Op50}, {Op51M0}, {Op52M0}, {Op53M0}, {Op54X1}, + {Op55M0}, {Op56M0}, {Op57M0}, {Op58}, {Op59M0}, + {Op5AX1}, {Op5B}, {Op5C}, {Op5DM0}, {Op5EM0}, + {Op5FM0}, {Op60}, {Op61M0}, {Op62}, {Op63M0}, + {Op64M0}, {Op65M0}, {Op66M0}, {Op67M0}, {Op68M0}, + {Op69M0}, {Op6AM0}, {Op6B}, {Op6C}, {Op6DM0}, + {Op6EM0}, {Op6FM0}, {Op70}, {Op71M0}, {Op72M0}, + {Op73M0}, {Op74M0}, {Op75M0}, {Op76M0}, {Op77M0}, + {Op78}, {Op79M0}, {Op7AX1}, {Op7B}, {Op7C}, + {Op7DM0}, {Op7EM0}, {Op7FM0}, {Op80}, {Op81M0}, + {Op82}, {Op83M0}, {Op84X1}, {Op85M0}, {Op86X1}, + {Op87M0}, {Op88X1}, {Op89M0}, {Op8AM0}, {Op8B}, + {Op8CX1}, {Op8DM0}, {Op8EX1}, {Op8FM0}, {Op90}, + {Op91M0}, {Op92M0}, {Op93M0}, {Op94X1}, {Op95M0}, + {Op96X1}, {Op97M0}, {Op98M0}, {Op99M0}, {Op9A}, + {Op9BX1}, {Op9CM0}, {Op9DM0}, {Op9EM0}, {Op9FM0}, + {OpA0X1}, {OpA1M0}, {OpA2X1}, {OpA3M0}, {OpA4X1}, + {OpA5M0}, {OpA6X1}, {OpA7M0}, {OpA8X1}, {OpA9M0}, + {OpAAX1}, {OpAB}, {OpACX1}, {OpADM0}, {OpAEX1}, + {OpAFM0}, {OpB0}, {OpB1M0}, {OpB2M0}, {OpB3M0}, + {OpB4X1}, {OpB5M0}, {OpB6X1}, {OpB7M0}, {OpB8}, + {OpB9M0}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM0}, + {OpBEX1}, {OpBFM0}, {OpC0X1}, {OpC1M0}, {OpC2}, + {OpC3M0}, {OpC4X1}, {OpC5M0}, {OpC6M0}, {OpC7M0}, + {OpC8X1}, {OpC9M0}, {OpCAX1}, {OpCB}, {OpCCX1}, + {OpCDM0}, {OpCEM0}, {OpCFM0}, {OpD0}, {OpD1M0}, + {OpD2M0}, {OpD3M0}, {OpD4}, {OpD5M0}, {OpD6M0}, + {OpD7M0}, {OpD8}, {OpD9M0}, {OpDAX1}, {OpDB}, + {OpDC}, {OpDDM0}, {OpDEM0}, {OpDFM0}, {OpE0X1}, + {OpE1M0}, {OpE2}, {OpE3M0}, {OpE4X1}, {OpE5M0}, + {OpE6M0}, {OpE7M0}, {OpE8X1}, {OpE9M0}, {OpEA}, + {OpEB}, {OpECX1}, {OpEDM0}, {OpEEM0}, {OpEFM0}, + {OpF0}, {OpF1M0}, {OpF2M0}, {OpF3M0}, {OpF4}, + {OpF5M0}, {OpF6M0}, {OpF7M0}, {OpF8}, {OpF9M0}, + {OpFAX1}, {OpFB}, {OpFC}, {OpFDM0}, {OpFEM0}, + {OpFFM0} +}; + diff --git a/src/cpuops.cpp b/src/cpuops.cpp deleted file mode 100644 index 6e4499b..0000000 --- a/src/cpuops.cpp +++ /dev/null @@ -1,4247 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -/**********************************************************************************************/ -/* CPU-S9xOpcodes.CPP */ -/* This file contains all the opcodes */ -/**********************************************************************************************/ - -#include "snes9x.h" -#include "memmap.h" -#include "missing.h" -#include "apu.h" -#include "sa1.h" -//#include "spc7110.h" - -#include "cpuexec.h" -#include "cpuaddr.h" -#include "cpuops.h" -#include "cpumacro.h" -#include "apu.h" - -/* ADC *************************************************************************************** */ -static void Op69M1 (void) -{ - Immediate8 (); - ADC8 (); -} - -static void Op69M0 (void) -{ - Immediate16 (); - ADC16 (); -} - -static void Op65M1 (void) -{ - Direct (); - ADC8 (); -} - -static void Op65M0 (void) -{ - Direct (); - ADC16 (); -} - -static void Op75M1 (void) -{ - DirectIndexedX (); - ADC8 (); -} - -static void Op75M0 (void) -{ - DirectIndexedX (); - ADC16 (); -} - -static void Op72M1 (void) -{ - DirectIndirect (); - ADC8 (); -} - -static void Op72M0 (void) -{ - DirectIndirect (); - ADC16 (); -} - -static void Op61M1 (void) -{ - DirectIndexedIndirect (); - ADC8 (); -} - -static void Op61M0 (void) -{ - DirectIndexedIndirect (); - ADC16 (); -} - -static void Op71M1 (void) -{ - DirectIndirectIndexed (); - ADC8 (); -} - -static void Op71M0 (void) -{ - DirectIndirectIndexed (); - ADC16 (); -} - -static void Op67M1 (void) -{ - DirectIndirectLong (); - ADC8 (); -} - -static void Op67M0 (void) -{ - DirectIndirectLong (); - ADC16 (); -} - -static void Op77M1 (void) -{ - DirectIndirectIndexedLong (); - ADC8 (); -} - -static void Op77M0 (void) -{ - DirectIndirectIndexedLong (); - ADC16 (); -} - -static void Op6DM1 (void) -{ - Absolute (); - ADC8 (); -} - -static void Op6DM0 (void) -{ - Absolute (); - ADC16 (); -} - -static void Op7DM1 (void) -{ - AbsoluteIndexedX (); - ADC8 (); -} - -static void Op7DM0 (void) -{ - AbsoluteIndexedX (); - ADC16 (); -} - -static void Op79M1 (void) -{ - AbsoluteIndexedY (); - ADC8 (); -} - -static void Op79M0 (void) -{ - AbsoluteIndexedY (); - ADC16 (); -} - -static void Op6FM1 (void) -{ - AbsoluteLong (); - ADC8 (); -} - -static void Op6FM0 (void) -{ - AbsoluteLong (); - ADC16 (); -} - -static void Op7FM1 (void) -{ - AbsoluteLongIndexedX (); - ADC8 (); -} - -static void Op7FM0 (void) -{ - AbsoluteLongIndexedX (); - ADC16 (); -} - -static void Op63M1 (void) -{ - StackRelative (); - ADC8 (); -} - -static void Op63M0 (void) -{ - StackRelative (); - ADC16 (); -} - -static void Op73M1 (void) -{ - StackRelativeIndirectIndexed (); - ADC8 (); -} - -static void Op73M0 (void) -{ - StackRelativeIndirectIndexed (); - ADC16 (); -} - -/**********************************************************************************************/ - -/* AND *************************************************************************************** */ -static void Op29M1 (void) -{ - Registers.AL &= *CPU.PC++; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (Registers.AL); -} - -static void Op29M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - Registers.A.W &= *(uint16 *) CPU.PC; -#else - Registers.A.W &= *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - CPU.PC += 2; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (Registers.A.W); -} - -static void Op25M1 (void) -{ - Direct (); - AND8 (); -} - -static void Op25M0 (void) -{ - Direct (); - AND16 (); -} - -static void Op35M1 (void) -{ - DirectIndexedX (); - AND8 (); -} - -static void Op35M0 (void) -{ - DirectIndexedX (); - AND16 (); -} - -static void Op32M1 (void) -{ - DirectIndirect (); - AND8 (); -} - -static void Op32M0 (void) -{ - DirectIndirect (); - AND16 (); -} - -static void Op21M1 (void) -{ - DirectIndexedIndirect (); - AND8 (); -} - -static void Op21M0 (void) -{ - DirectIndexedIndirect (); - AND16 (); -} - -static void Op31M1 (void) -{ - DirectIndirectIndexed (); - AND8 (); -} - -static void Op31M0 (void) -{ - DirectIndirectIndexed (); - AND16 (); -} - -static void Op27M1 (void) -{ - DirectIndirectLong (); - AND8 (); -} - -static void Op27M0 (void) -{ - DirectIndirectLong (); - AND16 (); -} - -static void Op37M1 (void) -{ - DirectIndirectIndexedLong (); - AND8 (); -} - -static void Op37M0 (void) -{ - DirectIndirectIndexedLong (); - AND16 (); -} - -static void Op2DM1 (void) -{ - Absolute (); - AND8 (); -} - -static void Op2DM0 (void) -{ - Absolute (); - AND16 (); -} - -static void Op3DM1 (void) -{ - AbsoluteIndexedX (); - AND8 (); -} - -static void Op3DM0 (void) -{ - AbsoluteIndexedX (); - AND16 (); -} - -static void Op39M1 (void) -{ - AbsoluteIndexedY (); - AND8 (); -} - -static void Op39M0 (void) -{ - AbsoluteIndexedY (); - AND16 (); -} - -static void Op2FM1 (void) -{ - AbsoluteLong (); - AND8 (); -} - -static void Op2FM0 (void) -{ - AbsoluteLong (); - AND16 (); -} - -static void Op3FM1 (void) -{ - AbsoluteLongIndexedX (); - AND8 (); -} - -static void Op3FM0 (void) -{ - AbsoluteLongIndexedX (); - AND16 (); -} - -static void Op23M1 (void) -{ - StackRelative (); - AND8 (); -} - -static void Op23M0 (void) -{ - StackRelative (); - AND16 (); -} - -static void Op33M1 (void) -{ - StackRelativeIndirectIndexed (); - AND8 (); -} - -static void Op33M0 (void) -{ - StackRelativeIndirectIndexed (); - AND16 (); -} -/**********************************************************************************************/ - -/* ASL *************************************************************************************** */ -static void Op0AM1 (void) -{ - A_ASL8 (); -} - -static void Op0AM0 (void) -{ - A_ASL16 (); -} - -static void Op06M1 (void) -{ - Direct (); - ASL8 (); -} - -static void Op06M0 (void) -{ - Direct (); - ASL16 (); -} - -static void Op16M1 (void) -{ - DirectIndexedX (); - ASL8 (); -} - -static void Op16M0 (void) -{ - DirectIndexedX (); - ASL16 (); - -} - -static void Op0EM1 (void) -{ - Absolute (); - ASL8 (); -} - -static void Op0EM0 (void) -{ - Absolute (); - ASL16 (); -} - -static void Op1EM1 (void) -{ - AbsoluteIndexedX (); - ASL8 (); -} - -static void Op1EM0 (void) -{ - AbsoluteIndexedX (); - ASL16 (); -} -/**********************************************************************************************/ - -/* BIT *************************************************************************************** */ -static void Op89M1 (void) -{ - ICPU._Zero = Registers.AL & *CPU.PC++; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void Op89M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - ICPU._Zero = (Registers.A.W & *(uint16 *) CPU.PC) != 0; -#else - ICPU._Zero = (Registers.A.W & (*CPU.PC + (*(CPU.PC + 1) << 8))) != 0; -#endif -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2; -#endif - CPU.PC += 2; -} - -static void Op24M1 (void) -{ - Direct (); - BIT8 (); -} - -static void Op24M0 (void) -{ - Direct (); - BIT16 (); -} - -static void Op34M1 (void) -{ - DirectIndexedX (); - BIT8 (); -} - -static void Op34M0 (void) -{ - DirectIndexedX (); - BIT16 (); -} - -static void Op2CM1 (void) -{ - Absolute (); - BIT8 (); -} - -static void Op2CM0 (void) -{ - Absolute (); - BIT16 (); -} - -static void Op3CM1 (void) -{ - AbsoluteIndexedX (); - BIT8 (); -} - -static void Op3CM0 (void) -{ - AbsoluteIndexedX (); - BIT16 (); -} -/**********************************************************************************************/ - -/* CMP *************************************************************************************** */ -static void OpC9M1 (void) -{ - long s9xInt32 = (int) Registers.AL - (int) *CPU.PC++; - ICPU._Carry = s9xInt32 >= 0; - SetZN8 ((uint8) s9xInt32); -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpC9M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - long s9xInt32 = (long) Registers.A.W - (long) *(uint16 *) CPU.PC; -#else - long s9xInt32 = (long) Registers.A.W - - (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); -#endif - ICPU._Carry = s9xInt32 >= 0; - SetZN16 ((uint16) s9xInt32); - CPU.PC += 2; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpC5M1 (void) -{ - Direct (); - CMP8 (); -} - -static void OpC5M0 (void) -{ - Direct (); - CMP16 (); -} - -static void OpD5M1 (void) -{ - DirectIndexedX (); - CMP8 (); -} - -static void OpD5M0 (void) -{ - DirectIndexedX (); - CMP16 (); -} - -static void OpD2M1 (void) -{ - DirectIndirect (); - CMP8 (); -} - -static void OpD2M0 (void) -{ - DirectIndirect (); - CMP16 (); -} - -static void OpC1M1 (void) -{ - DirectIndexedIndirect (); - CMP8 (); -} - -static void OpC1M0 (void) -{ - DirectIndexedIndirect (); - CMP16 (); -} - -static void OpD1M1 (void) -{ - DirectIndirectIndexed (); - CMP8 (); -} - -static void OpD1M0 (void) -{ - DirectIndirectIndexed (); - CMP16 (); -} - -static void OpC7M1 (void) -{ - DirectIndirectLong (); - CMP8 (); -} - -static void OpC7M0 (void) -{ - DirectIndirectLong (); - CMP16 (); -} - -static void OpD7M1 (void) -{ - DirectIndirectIndexedLong (); - CMP8 (); -} - -static void OpD7M0 (void) -{ - DirectIndirectIndexedLong (); - CMP16 (); -} - -static void OpCDM1 (void) -{ - Absolute (); - CMP8 (); -} - -static void OpCDM0 (void) -{ - Absolute (); - CMP16 (); -} - -static void OpDDM1 (void) -{ - AbsoluteIndexedX (); - CMP8 (); -} - -static void OpDDM0 (void) -{ - AbsoluteIndexedX (); - CMP16 (); -} - -static void OpD9M1 (void) -{ - AbsoluteIndexedY (); - CMP8 (); -} - -static void OpD9M0 (void) -{ - AbsoluteIndexedY (); - CMP16 (); -} - -static void OpCFM1 (void) -{ - AbsoluteLong (); - CMP8 (); -} - -static void OpCFM0 (void) -{ - AbsoluteLong (); - CMP16 (); -} - -static void OpDFM1 (void) -{ - AbsoluteLongIndexedX (); - CMP8 (); -} - -static void OpDFM0 (void) -{ - AbsoluteLongIndexedX (); - CMP16 (); -} - -static void OpC3M1 (void) -{ - StackRelative (); - CMP8 (); -} - -static void OpC3M0 (void) -{ - StackRelative (); - CMP16 (); -} - -static void OpD3M1 (void) -{ - StackRelativeIndirectIndexed (); - CMP8 (); -} - -static void OpD3M0 (void) -{ - StackRelativeIndirectIndexed (); - CMP16 (); -} - -/**********************************************************************************************/ - -/* CMX *************************************************************************************** */ -static void OpE0X1 (void) -{ - long s9xInt32 = (int) Registers.XL - (int) *CPU.PC++; - ICPU._Carry = s9xInt32 >= 0; - SetZN8 ((uint8) s9xInt32); -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpE0X0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - long s9xInt32 = (long) Registers.X.W - (long) *(uint16 *) CPU.PC; -#else - long s9xInt32 = (long) Registers.X.W - - (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); -#endif - ICPU._Carry = s9xInt32 >= 0; - SetZN16 ((uint16) s9xInt32); - CPU.PC += 2; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpE4X1 (void) -{ - Direct (); - CMX8 (); -} - -static void OpE4X0 (void) -{ - Direct (); - CMX16 (); -} - -static void OpECX1 (void) -{ - Absolute (); - CMX8 (); -} - -static void OpECX0 (void) -{ - Absolute (); - CMX16 (); -} - -/**********************************************************************************************/ - -/* CMY *************************************************************************************** */ -static void OpC0X1 (void) -{ - long s9xInt32 = (int) Registers.YL - (int) *CPU.PC++; - ICPU._Carry = s9xInt32 >= 0; - SetZN8 ((uint8) s9xInt32); -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#endif -} - -static void OpC0X0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - long s9xInt32 = (long) Registers.Y.W - (long) *(uint16 *) CPU.PC; -#else - long s9xInt32 = (long) Registers.Y.W - - (long) (*CPU.PC + (*(CPU.PC + 1) << 8)); -#endif - ICPU._Carry = s9xInt32 >= 0; - SetZN16 ((uint16) s9xInt32); - CPU.PC += 2; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2; -#endif -} - -static void OpC4X1 (void) -{ - Direct (); - CMY8 (); -} - -static void OpC4X0 (void) -{ - Direct (); - CMY16 (); -} - -static void OpCCX1 (void) -{ - Absolute (); - CMY8 (); -} - -static void OpCCX0 (void) -{ - Absolute (); - CMY16 (); -} - -/**********************************************************************************************/ - -/* DEC *************************************************************************************** */ -static void Op3AM1 (void) -{ - A_DEC8 (); -} - -static void Op3AM0 (void) -{ - A_DEC16 (); -} - -static void OpC6M1 (void) -{ - Direct (); - DEC8 (); -} - -static void OpC6M0 (void) -{ - Direct (); - DEC16 (); -} - -static void OpD6M1 (void) -{ - DirectIndexedX (); - DEC8 (); -} - -static void OpD6M0 (void) -{ - DirectIndexedX (); - DEC16 (); -} - -static void OpCEM1 (void) -{ - Absolute (); - DEC8 (); -} - -static void OpCEM0 (void) -{ - Absolute (); - DEC16 (); -} - -static void OpDEM1 (void) -{ - AbsoluteIndexedX (); - DEC8 (); -} - -static void OpDEM0 (void) -{ - AbsoluteIndexedX (); - DEC16 (); -} - -/**********************************************************************************************/ - -/* EOR *************************************************************************************** */ -static void Op49M1 (void) -{ - Registers.AL ^= *CPU.PC++; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (Registers.AL); -} - -static void Op49M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - Registers.A.W ^= *(uint16 *) CPU.PC; -#else - Registers.A.W ^= *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - CPU.PC += 2; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (Registers.A.W); -} - -static void Op45M1 (void) -{ - Direct (); - EOR8 (); -} - -static void Op45M0 (void) -{ - Direct (); - EOR16 (); -} - -static void Op55M1 (void) -{ - DirectIndexedX (); - EOR8 (); -} - -static void Op55M0 (void) -{ - DirectIndexedX (); - EOR16 (); -} - -static void Op52M1 (void) -{ - DirectIndirect (); - EOR8 (); -} - -static void Op52M0 (void) -{ - DirectIndirect (); - EOR16 (); -} - -static void Op41M1 (void) -{ - DirectIndexedIndirect (); - EOR8 (); -} - -static void Op41M0 (void) -{ - DirectIndexedIndirect (); - EOR16 (); -} - -static void Op51M1 (void) -{ - DirectIndirectIndexed (); - EOR8 (); -} - -static void Op51M0 (void) -{ - DirectIndirectIndexed (); - EOR16 (); -} - -static void Op47M1 (void) -{ - DirectIndirectLong (); - EOR8 (); -} - -static void Op47M0 (void) -{ - DirectIndirectLong (); - EOR16 (); -} - -static void Op57M1 (void) -{ - DirectIndirectIndexedLong (); - EOR8 (); -} - -static void Op57M0 (void) -{ - DirectIndirectIndexedLong (); - EOR16 (); -} - -static void Op4DM1 (void) -{ - Absolute (); - EOR8 (); -} - -static void Op4DM0 (void) -{ - Absolute (); - EOR16 (); -} - -static void Op5DM1 (void) -{ - AbsoluteIndexedX (); - EOR8 (); -} - -static void Op5DM0 (void) -{ - AbsoluteIndexedX (); - EOR16 (); -} - -static void Op59M1 (void) -{ - AbsoluteIndexedY (); - EOR8 (); -} - -static void Op59M0 (void) -{ - AbsoluteIndexedY (); - EOR16 (); -} - -static void Op4FM1 (void) -{ - AbsoluteLong (); - EOR8 (); -} - -static void Op4FM0 (void) -{ - AbsoluteLong (); - EOR16 (); -} - -static void Op5FM1 (void) -{ - AbsoluteLongIndexedX (); - EOR8 (); -} - -static void Op5FM0 (void) -{ - AbsoluteLongIndexedX (); - EOR16 (); -} - -static void Op43M1 (void) -{ - StackRelative (); - EOR8 (); -} - -static void Op43M0 (void) -{ - StackRelative (); - EOR16 (); -} - -static void Op53M1 (void) -{ - StackRelativeIndirectIndexed (); - EOR8 (); -} - -static void Op53M0 (void) -{ - StackRelativeIndirectIndexed (); - EOR16 (); -} - -/**********************************************************************************************/ - -/* INC *************************************************************************************** */ -static void Op1AM1 (void) -{ - A_INC8 (); -} - -static void Op1AM0 (void) -{ - A_INC16 (); -} - -static void OpE6M1 (void) -{ - Direct (); - INC8 (); -} - -static void OpE6M0 (void) -{ - Direct (); - INC16 (); -} - -static void OpF6M1 (void) -{ - DirectIndexedX (); - INC8 (); -} - -static void OpF6M0 (void) -{ - DirectIndexedX (); - INC16 (); -} - -static void OpEEM1 (void) -{ - Absolute (); - INC8 (); -} - -static void OpEEM0 (void) -{ - Absolute (); - INC16 (); -} - -static void OpFEM1 (void) -{ - AbsoluteIndexedX (); - INC8 (); -} - -static void OpFEM0 (void) -{ - AbsoluteIndexedX (); - INC16 (); -} - -/**********************************************************************************************/ -/* LDA *************************************************************************************** */ -static void OpA9M1 (void) -{ - Registers.AL = *CPU.PC++; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (Registers.AL); -} - -static void OpA9M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - Registers.A.W = *(uint16 *) CPU.PC; -#else - Registers.A.W = *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - - CPU.PC += 2; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (Registers.A.W); -} - -static void OpA5M1 (void) -{ - Direct (); - LDA8 (); -} - -static void OpA5M0 (void) -{ - Direct (); - LDA16 (); -} - -static void OpB5M1 (void) -{ - DirectIndexedX (); - LDA8 (); -} - -static void OpB5M0 (void) -{ - DirectIndexedX (); - LDA16 (); -} - -static void OpB2M1 (void) -{ - DirectIndirect (); - LDA8 (); -} - -static void OpB2M0 (void) -{ - DirectIndirect (); - LDA16 (); -} - -static void OpA1M1 (void) -{ - DirectIndexedIndirect (); - LDA8 (); -} - -static void OpA1M0 (void) -{ - DirectIndexedIndirect (); - LDA16 (); -} - -static void OpB1M1 (void) -{ - DirectIndirectIndexed (); - LDA8 (); -} - -static void OpB1M0 (void) -{ - DirectIndirectIndexed (); - LDA16 (); -} - -static void OpA7M1 (void) -{ - DirectIndirectLong (); - LDA8 (); -} - -static void OpA7M0 (void) -{ - DirectIndirectLong (); - LDA16 (); -} - -static void OpB7M1 (void) -{ - DirectIndirectIndexedLong (); - LDA8 (); -} - -static void OpB7M0 (void) -{ - DirectIndirectIndexedLong (); - LDA16 (); -} - -static void OpADM1 (void) -{ - Absolute (); - LDA8 (); -} - -static void OpADM0 (void) -{ - Absolute (); - LDA16 (); -} - -static void OpBDM1 (void) -{ - AbsoluteIndexedX (); - LDA8 (); -} - -static void OpBDM0 (void) -{ - AbsoluteIndexedX (); - LDA16 (); -} - -static void OpB9M1 (void) -{ - AbsoluteIndexedY (); - LDA8 (); -} - -static void OpB9M0 (void) -{ - AbsoluteIndexedY (); - LDA16 (); -} - -static void OpAFM1 (void) -{ - AbsoluteLong (); - LDA8 (); -} - -static void OpAFM0 (void) -{ - AbsoluteLong (); - LDA16 (); -} - -static void OpBFM1 (void) -{ - AbsoluteLongIndexedX (); - LDA8 (); -} - -static void OpBFM0 (void) -{ - AbsoluteLongIndexedX (); - LDA16 (); -} - -static void OpA3M1 (void) -{ - StackRelative (); - LDA8 (); -} - -static void OpA3M0 (void) -{ - StackRelative (); - LDA16 (); -} - -static void OpB3M1 (void) -{ - StackRelativeIndirectIndexed (); - LDA8 (); -} - -static void OpB3M0 (void) -{ - StackRelativeIndirectIndexed (); - LDA16 (); -} - -/**********************************************************************************************/ - -/* LDX *************************************************************************************** */ -static void OpA2X1 (void) -{ - Registers.XL = *CPU.PC++; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (Registers.XL); -} - -static void OpA2X0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - Registers.X.W = *(uint16 *) CPU.PC; -#else - Registers.X.W = *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - CPU.PC += 2; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (Registers.X.W); -} - -static void OpA6X1 (void) -{ - Direct (); - LDX8 (); -} - -static void OpA6X0 (void) -{ - Direct (); - LDX16 (); -} - -static void OpB6X1 (void) -{ - DirectIndexedY (); - LDX8 (); -} - -static void OpB6X0 (void) -{ - DirectIndexedY (); - LDX16 (); -} - -static void OpAEX1 (void) -{ - Absolute (); - LDX8 (); -} - -static void OpAEX0 (void) -{ - Absolute (); - LDX16 (); -} - -static void OpBEX1 (void) -{ - AbsoluteIndexedY (); - LDX8 (); -} - -static void OpBEX0 (void) -{ - AbsoluteIndexedY (); - LDX16 (); -} -/**********************************************************************************************/ - -/* LDY *************************************************************************************** */ -static void OpA0X1 (void) -{ - Registers.YL = *CPU.PC++; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (Registers.YL); -} - -static void OpA0X0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - Registers.Y.W = *(uint16 *) CPU.PC; -#else - Registers.Y.W = *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - - CPU.PC += 2; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (Registers.Y.W); -} - -static void OpA4X1 (void) -{ - Direct (); - LDY8 (); -} - -static void OpA4X0 (void) -{ - Direct (); - LDY16 (); -} - -static void OpB4X1 (void) -{ - DirectIndexedX (); - LDY8 (); -} - -static void OpB4X0 (void) -{ - DirectIndexedX (); - LDY16 (); -} - -static void OpACX1 (void) -{ - Absolute (); - LDY8 (); -} - -static void OpACX0 (void) -{ - Absolute (); - LDY16 (); -} - -static void OpBCX1 (void) -{ - AbsoluteIndexedX (); - LDY8 (); -} - -static void OpBCX0 (void) -{ - AbsoluteIndexedX (); - LDY16 (); -} -/**********************************************************************************************/ - -/* LSR *************************************************************************************** */ -static void Op4AM1 (void) -{ - A_LSR8 (); -} - -static void Op4AM0 (void) -{ - A_LSR16 (); -} - -static void Op46M1 (void) -{ - Direct (); - LSR8 (); -} - -static void Op46M0 (void) -{ - Direct (); - LSR16 (); -} - -static void Op56M1 (void) -{ - DirectIndexedX (); - LSR8 (); -} - -static void Op56M0 (void) -{ - DirectIndexedX (); - LSR16 (); -} - -static void Op4EM1 (void) -{ - Absolute (); - LSR8 (); -} - -static void Op4EM0 (void) -{ - Absolute (); - LSR16 (); -} - -static void Op5EM1 (void) -{ - AbsoluteIndexedX (); - LSR8 (); -} - -static void Op5EM0 (void) -{ - AbsoluteIndexedX (); - LSR16 (); -} - -/**********************************************************************************************/ - -/* ORA *************************************************************************************** */ -static void Op09M1 (void) -{ - Registers.AL |= *CPU.PC++; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; -#endif - SetZN8 (Registers.AL); -} - -static void Op09M0 (void) -{ -#ifdef FAST_LSB_WORD_ACCESS - Registers.A.W |= *(uint16 *) CPU.PC; -#else - Registers.A.W |= *CPU.PC + (*(CPU.PC + 1) << 8); -#endif - CPU.PC += 2; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2; -#endif - SetZN16 (Registers.A.W); -} - -static void Op05M1 (void) -{ - Direct (); - ORA8 (); -} - -static void Op05M0 (void) -{ - Direct (); - ORA16 (); -} - -static void Op15M1 (void) -{ - DirectIndexedX (); - ORA8 (); -} - -static void Op15M0 (void) -{ - DirectIndexedX (); - ORA16 (); -} - -static void Op12M1 (void) -{ - DirectIndirect (); - ORA8 (); -} - -static void Op12M0 (void) -{ - DirectIndirect (); - ORA16 (); -} - -static void Op01M1 (void) -{ - DirectIndexedIndirect (); - ORA8 (); -} - -static void Op01M0 (void) -{ - DirectIndexedIndirect (); - ORA16 (); -} - -static void Op11M1 (void) -{ - DirectIndirectIndexed (); - ORA8 (); -} - -static void Op11M0 (void) -{ - DirectIndirectIndexed (); - ORA16 (); -} - -static void Op07M1 (void) -{ - DirectIndirectLong (); - ORA8 (); -} - -static void Op07M0 (void) -{ - DirectIndirectLong (); - ORA16 (); -} - -static void Op17M1 (void) -{ - DirectIndirectIndexedLong (); - ORA8 (); -} - -static void Op17M0 (void) -{ - DirectIndirectIndexedLong (); - ORA16 (); -} - -static void Op0DM1 (void) -{ - Absolute (); - ORA8 (); -} - -static void Op0DM0 (void) -{ - Absolute (); - ORA16 (); -} - -static void Op1DM1 (void) -{ - AbsoluteIndexedX (); - ORA8 (); -} - -static void Op1DM0 (void) -{ - AbsoluteIndexedX (); - ORA16 (); -} - -static void Op19M1 (void) -{ - AbsoluteIndexedY (); - ORA8 (); -} - -static void Op19M0 (void) -{ - AbsoluteIndexedY (); - ORA16 (); -} - -static void Op0FM1 (void) -{ - AbsoluteLong (); - ORA8 (); -} - -static void Op0FM0 (void) -{ - AbsoluteLong (); - ORA16 (); -} - -static void Op1FM1 (void) -{ - AbsoluteLongIndexedX (); - ORA8 (); -} - -static void Op1FM0 (void) -{ - AbsoluteLongIndexedX (); - ORA16 (); -} - -static void Op03M1 (void) -{ - StackRelative (); - ORA8 (); -} - -static void Op03M0 (void) -{ - StackRelative (); - ORA16 (); -} - -static void Op13M1 (void) -{ - StackRelativeIndirectIndexed (); - ORA8 (); -} - -static void Op13M0 (void) -{ - StackRelativeIndirectIndexed (); - ORA16 (); -} - -/**********************************************************************************************/ - -/* ROL *************************************************************************************** */ -static void Op2AM1 (void) -{ - A_ROL8 (); -} - -static void Op2AM0 (void) -{ - A_ROL16 (); -} - -static void Op26M1 (void) -{ - Direct (); - ROL8 (); -} - -static void Op26M0 (void) -{ - Direct (); - ROL16 (); -} - -static void Op36M1 (void) -{ - DirectIndexedX (); - ROL8 (); -} - -static void Op36M0 (void) -{ - DirectIndexedX (); - ROL16 (); -} - -static void Op2EM1 (void) -{ - Absolute (); - ROL8 (); -} - -static void Op2EM0 (void) -{ - Absolute (); - ROL16 (); -} - -static void Op3EM1 (void) -{ - AbsoluteIndexedX (); - ROL8 (); -} - -static void Op3EM0 (void) -{ - AbsoluteIndexedX (); - ROL16 (); -} -/**********************************************************************************************/ - -/* ROR *************************************************************************************** */ -static void Op6AM1 (void) -{ - A_ROR8 (); -} - -static void Op6AM0 (void) -{ - A_ROR16 (); -} - -static void Op66M1 (void) -{ - Direct (); - ROR8 (); -} - -static void Op66M0 (void) -{ - Direct (); - ROR16 (); -} - -static void Op76M1 (void) -{ - DirectIndexedX (); - ROR8 (); -} - -static void Op76M0 (void) -{ - DirectIndexedX (); - ROR16 (); -} - -static void Op6EM1 (void) -{ - Absolute (); - ROR8 (); -} - -static void Op6EM0 (void) -{ - Absolute (); - ROR16 (); -} - -static void Op7EM1 (void) -{ - AbsoluteIndexedX (); - ROR8 (); -} - -static void Op7EM0 (void) -{ - AbsoluteIndexedX (); - ROR16 (); -} -/**********************************************************************************************/ - -/* SBC *************************************************************************************** */ -static void OpE9M1 (void) -{ - Immediate8 (); - SBC8 (); -} - -static void OpE9M0 (void) -{ - Immediate16 (); - SBC16 (); -} - -static void OpE5M1 (void) -{ - Direct (); - SBC8 (); -} - -static void OpE5M0 (void) -{ - Direct (); - SBC16 (); -} - -static void OpF5M1 (void) -{ - DirectIndexedX (); - SBC8 (); -} - -static void OpF5M0 (void) -{ - DirectIndexedX (); - SBC16 (); -} - -static void OpF2M1 (void) -{ - DirectIndirect (); - SBC8 (); -} - -static void OpF2M0 (void) -{ - DirectIndirect (); - SBC16 (); -} - -static void OpE1M1 (void) -{ - DirectIndexedIndirect (); - SBC8 (); -} - -static void OpE1M0 (void) -{ - DirectIndexedIndirect (); - SBC16 (); -} - -static void OpF1M1 (void) -{ - DirectIndirectIndexed (); - SBC8 (); -} - -static void OpF1M0 (void) -{ - DirectIndirectIndexed (); - SBC16 (); -} - -static void OpE7M1 (void) -{ - DirectIndirectLong (); - SBC8 (); -} - -static void OpE7M0 (void) -{ - DirectIndirectLong (); - SBC16 (); -} - -static void OpF7M1 (void) -{ - DirectIndirectIndexedLong (); - SBC8 (); -} - -static void OpF7M0 (void) -{ - DirectIndirectIndexedLong (); - SBC16 (); -} - -static void OpEDM1 (void) -{ - Absolute (); - SBC8 (); -} - -static void OpEDM0 (void) -{ - Absolute (); - SBC16 (); -} - -static void OpFDM1 (void) -{ - AbsoluteIndexedX (); - SBC8 (); -} - -static void OpFDM0 (void) -{ - AbsoluteIndexedX (); - SBC16 (); -} - -static void OpF9M1 (void) -{ - AbsoluteIndexedY (); - SBC8 (); -} - -static void OpF9M0 (void) -{ - AbsoluteIndexedY (); - SBC16 (); -} - -static void OpEFM1 (void) -{ - AbsoluteLong (); - SBC8 (); -} - -static void OpEFM0 (void) -{ - AbsoluteLong (); - SBC16 (); -} - -static void OpFFM1 (void) -{ - AbsoluteLongIndexedX (); - SBC8 (); -} - -static void OpFFM0 (void) -{ - AbsoluteLongIndexedX (); - SBC16 (); -} - -static void OpE3M1 (void) -{ - StackRelative (); - SBC8 (); -} - -static void OpE3M0 (void) -{ - StackRelative (); - SBC16 (); -} - -static void OpF3M1 (void) -{ - StackRelativeIndirectIndexed (); - SBC8 (); -} - -static void OpF3M0 (void) -{ - StackRelativeIndirectIndexed (); - SBC16 (); -} -/**********************************************************************************************/ - -/* STA *************************************************************************************** */ -static void Op85M1 (void) -{ - Direct (); - STA8 (); -} - -static void Op85M0 (void) -{ - Direct (); - STA16 (); -} - -static void Op95M1 (void) -{ - DirectIndexedX (); - STA8 (); -} - -static void Op95M0 (void) -{ - DirectIndexedX (); - STA16 (); -} - -static void Op92M1 (void) -{ - DirectIndirect (); - STA8 (); -} - -static void Op92M0 (void) -{ - DirectIndirect (); - STA16 (); -} - -static void Op81M1 (void) -{ - DirectIndexedIndirect (); - STA8 (); -#ifdef VAR_CYCLES - if (CheckIndex ()) - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op81M0 (void) -{ - DirectIndexedIndirect (); - STA16 (); -#ifdef VAR_CYCLES - if (CheckIndex ()) - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op91M1 (void) -{ - DirectIndirectIndexed (); - STA8 (); -} - -static void Op91M0 (void) -{ - DirectIndirectIndexed (); - STA16 (); -} - -static void Op87M1 (void) -{ - DirectIndirectLong (); - STA8 (); -} - -static void Op87M0 (void) -{ - DirectIndirectLong (); - STA16 (); -} - -static void Op97M1 (void) -{ - DirectIndirectIndexedLong (); - STA8 (); -} - -static void Op97M0 (void) -{ - DirectIndirectIndexedLong (); - STA16 (); -} - -static void Op8DM1 (void) -{ - Absolute (); - STA8 (); -} - -static void Op8DM0 (void) -{ - Absolute (); - STA16 (); -} - -static void Op9DM1 (void) -{ - AbsoluteIndexedX (); - STA8 (); -} - -static void Op9DM0 (void) -{ - AbsoluteIndexedX (); - STA16 (); -} - -static void Op99M1 (void) -{ - AbsoluteIndexedY (); - STA8 (); -} - -static void Op99M0 (void) -{ - AbsoluteIndexedY (); - STA16 (); -} - -static void Op8FM1 (void) -{ - AbsoluteLong (); - STA8 (); -} - -static void Op8FM0 (void) -{ - AbsoluteLong (); - STA16 (); -} - -static void Op9FM1 (void) -{ - AbsoluteLongIndexedX (); - STA8 (); -} - -static void Op9FM0 (void) -{ - AbsoluteLongIndexedX (); - STA16 (); -} - -static void Op83M1 (void) -{ - StackRelative (); - STA8 (); -} - -static void Op83M0 (void) -{ - StackRelative (); - STA16 (); -} - -static void Op93M1 (void) -{ - StackRelativeIndirectIndexed (); - STA8 (); -} - -static void Op93M0 (void) -{ - StackRelativeIndirectIndexed (); - STA16 (); -} -/**********************************************************************************************/ - -/* STX *************************************************************************************** */ -static void Op86X1 (void) -{ - Direct (); - STX8 (); -} - -static void Op86X0 (void) -{ - Direct (); - STX16 (); -} - -static void Op96X1 (void) -{ - DirectIndexedY (); - STX8 (); -} - -static void Op96X0 (void) -{ - DirectIndexedY (); - STX16 (); -} - -static void Op8EX1 (void) -{ - Absolute (); - STX8 (); -} - -static void Op8EX0 (void) -{ - Absolute (); - STX16 (); -} -/**********************************************************************************************/ - -/* STY *************************************************************************************** */ -static void Op84X1 (void) -{ - Direct (); - STY8 (); -} - -static void Op84X0 (void) -{ - Direct (); - STY16 (); -} - -static void Op94X1 (void) -{ - DirectIndexedX (); - STY8 (); -} - -static void Op94X0 (void) -{ - DirectIndexedX (); - STY16 (); -} - -static void Op8CX1 (void) -{ - Absolute (); - STY8 (); -} - -static void Op8CX0 (void) -{ - Absolute (); - STY16 (); -} -/**********************************************************************************************/ - -/* STZ *************************************************************************************** */ -static void Op64M1 (void) -{ - Direct (); - STZ8 (); -} - -static void Op64M0 (void) -{ - Direct (); - STZ16 (); -} - -static void Op74M1 (void) -{ - DirectIndexedX (); - STZ8 (); -} - -static void Op74M0 (void) -{ - DirectIndexedX (); - STZ16 (); -} - -static void Op9CM1 (void) -{ - Absolute (); - STZ8 (); -} - -static void Op9CM0 (void) -{ - Absolute (); - STZ16 (); -} - -static void Op9EM1 (void) -{ - AbsoluteIndexedX (); - STZ8 (); -} - -static void Op9EM0 (void) -{ - AbsoluteIndexedX (); - STZ16 (); -} - -/**********************************************************************************************/ - -/* TRB *************************************************************************************** */ -static void Op14M1 (void) -{ - Direct (); - TRB8 (); -} - -static void Op14M0 (void) -{ - Direct (); - TRB16 (); -} - -static void Op1CM1 (void) -{ - Absolute (); - TRB8 (); -} - -static void Op1CM0 (void) -{ - Absolute (); - TRB16 (); -} -/**********************************************************************************************/ - -/* TSB *************************************************************************************** */ -static void Op04M1 (void) -{ - Direct (); - TSB8 (); -} - -static void Op04M0 (void) -{ - Direct (); - TSB16 (); -} - -static void Op0CM1 (void) -{ - Absolute (); - TSB8 (); -} - -static void Op0CM0 (void) -{ - Absolute (); - TSB16 (); -} - -/**********************************************************************************************/ - -/* Branch Instructions *********************************************************************** */ -#ifndef SA1_OPCODES -#define BranchCheck0()\ - if( CPU.BranchSkip)\ - {\ - CPU.BranchSkip = FALSE;\ - if (!Settings.SoundSkipMethod)\ - if( CPU.PC - CPU.PCBase > OpAddress)\ - return;\ - } - -#define BranchCheck1()\ - if( CPU.BranchSkip)\ - {\ - CPU.BranchSkip = FALSE;\ - if (!Settings.SoundSkipMethod) {\ - if( CPU.PC - CPU.PCBase > OpAddress)\ - return;\ - } else \ - if (Settings.SoundSkipMethod == 1)\ - return;\ - if (Settings.SoundSkipMethod == 3)\ - if( CPU.PC - CPU.PCBase > OpAddress)\ - return;\ - else\ - CPU.PC = CPU.PCBase + OpAddress;\ - } - -#define BranchCheck2()\ - if( CPU.BranchSkip)\ - {\ - CPU.BranchSkip = FALSE;\ - if (!Settings.SoundSkipMethod) {\ - if( CPU.PC - CPU.PCBase > OpAddress)\ - return;\ - } else \ - if (Settings.SoundSkipMethod == 1)\ - CPU.PC = CPU.PCBase + OpAddress;\ - if (Settings.SoundSkipMethod == 3)\ - if (CPU.PC - CPU.PCBase > OpAddress)\ - return;\ - else\ - CPU.PC = CPU.PCBase + OpAddress;\ - } -#else -#define BranchCheck0() -#define BranchCheck1() -#define BranchCheck2() -#endif - -#ifdef CPU_SHUTDOWN -#ifndef SA1_OPCODES -inline void CPUShutdown() { - if (Settings.Shutdown && CPU.PC == CPU.WaitAddress) { - // Don't skip cycles with a pending NMI or IRQ - could cause delayed - // interrupt. Interrupts are delayed for a few cycles already, but - // the delay could allow the shutdown code to cycle skip again. - // Was causing screen flashing on Top Gear 3000. - - if (CPU.WaitCounter == 0 && !(CPU.Flags & (IRQ_PENDING_FLAG | NMI_FLAG))) { - CPU.WaitAddress = NULL; -#ifdef USE_SA1 - if (Settings.SA1) S9xSA1ExecuteDuringSleep (); - CPU.Cycles = CPU.NextEvent; -#endif - //S9xUpdateAPUTimer(); - asm_APU_EXECUTE2(); - } else { - if (CPU.WaitCounter >= 2) CPU.WaitCounter = 1; - else CPU.WaitCounter--; - } - } -} -#else -inline void CPUShutdown() -{ - if (Settings.Shutdown && CPU.PC == CPU.WaitAddress) - { - if (CPU.WaitCounter >= 1) - { - SA1.Executing = FALSE; - SA1.CPUExecuting = FALSE; - } - else - CPU.WaitCounter++; - } -} -#endif -#else -#define CPUShutdown() -#endif - -/* BCC */ -static void Op90 (void) -{ - Relative (); - BranchCheck0 (); - if (!CheckCarry ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif -#endif - CPUShutdown (); - } -} - -/* BCS */ -static void OpB0 (void) -{ - Relative (); - BranchCheck0 (); - if (CheckCarry ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif -#endif - CPUShutdown (); - } -} - -/* BEQ */ -static void OpF0 (void) -{ - Relative (); - BranchCheck2 (); - if (CheckZero ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif -#endif - CPUShutdown (); - } -} - -/* BMI */ -static void Op30 (void) -{ - Relative (); - - - BranchCheck1 (); - if (CheckNegative ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif -#endif - CPUShutdown (); - } -} - -/* BNE */ -static void OpD0 (void) -{ - Relative (); - BranchCheck1 (); - if (!CheckZero ()) - { - CPU.PC = CPU.PCBase + OpAddress; - -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif -#endif - CPUShutdown (); - } -} - -/* BPL */ -static void Op10 (void) -{ - Relative (); - BranchCheck1 (); - if (!CheckNegative ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif -#endif - CPUShutdown (); - } -} - -/* BRA */ -static void Op80 (void) -{ - Relative (); - CPU.PC = CPU.PCBase + OpAddress; -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif -#endif - CPUShutdown (); -} - -/* BVC */ -static void Op50 (void) -{ - Relative (); - BranchCheck0 (); - if (!CheckOverflow ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif -#endif - CPUShutdown (); - } -} - -/* BVS */ -static void Op70 (void) -{ - Relative (); - BranchCheck0 (); - if (CheckOverflow ()) - { - CPU.PC = CPU.PCBase + OpAddress; -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles++; -#endif -#endif - CPUShutdown (); - } -} -/**********************************************************************************************/ - -/* ClearFlag Instructions ******************************************************************** */ -/* CLC */ -static void Op18 (void) -{ - ClearCarry (); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -/* CLD */ -static void OpD8 (void) -{ - ClearDecimal (); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -/* CLI */ -static void Op58 (void) -{ - ClearIRQ (); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -/* CHECK_FOR_IRQ(); */ -} - -/* CLV */ -static void OpB8 (void) -{ - ClearOverflow (); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} -/**********************************************************************************************/ - -/* DEX/DEY *********************************************************************************** */ -static void OpCAX1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - Registers.XL--; - SetZN8 (Registers.XL); -} - -static void OpCAX0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - Registers.X.W--; - SetZN16 (Registers.X.W); -} - -static void Op88X1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - Registers.YL--; - SetZN8 (Registers.YL); -} - -static void Op88X0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - Registers.Y.W--; - SetZN16 (Registers.Y.W); -} -/**********************************************************************************************/ - -/* INX/INY *********************************************************************************** */ -static void OpE8X1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - Registers.XL++; - SetZN8 (Registers.XL); -} - -static void OpE8X0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - Registers.X.W++; - SetZN16 (Registers.X.W); -} - -static void OpC8X1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - Registers.YL++; - SetZN8 (Registers.YL); -} - -static void OpC8X0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = NULL; -#endif - - Registers.Y.W++; - SetZN16 (Registers.Y.W); -} - -/**********************************************************************************************/ - -/* NOP *************************************************************************************** */ -static void OpEA (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - -} -/**********************************************************************************************/ - -/* PUSH Instructions ************************************************************************* */ -#define PushW(w) \ - S9xSetWord (w, Registers.S.W - 1);\ - Registers.S.W -= 2; -#define PushB(b)\ - S9xSetByte (b, Registers.S.W--); - -static void OpF4 (void) -{ - Absolute (); - PushW ((unsigned short)OpAddress); -} - -static void OpD4 (void) -{ - DirectIndirect (); - PushW ((unsigned short)OpAddress); -} - -static void Op62 (void) -{ - RelativeLong (); - PushW ((unsigned short)OpAddress); -} - -static void Op48M1 (void) -{ - PushB (Registers.AL); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op48M0 (void) -{ - PushW (Registers.A.W); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op8B (void) -{ - PushB (Registers.DB); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op0B (void) -{ - PushW (Registers.D.W); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op4B (void) -{ - PushB (Registers.PB); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op08 (void) -{ - S9xPackStatus (); - PushB (Registers.PL); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpDAX1 (void) -{ - PushB (Registers.XL); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpDAX0 (void) -{ - PushW (Registers.X.W); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op5AX1 (void) -{ - PushB (Registers.YL); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op5AX0 (void) -{ - PushW (Registers.Y.W); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} -/**********************************************************************************************/ - -/* PULL Instructions ************************************************************************* */ -#define PullW(w) \ - w = S9xGetWord (Registers.S.W + 1); \ - Registers.S.W += 2; - -#define PullB(b)\ - b = S9xGetByte (++Registers.S.W); - -static void Op68M1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif - PullB (Registers.AL); - SetZN8 (Registers.AL); -} - -static void Op68M0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif - PullW (Registers.A.W); - SetZN16 (Registers.A.W); -} - -static void OpAB (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif - PullB (Registers.DB); - SetZN8 (Registers.DB); - ICPU.ShiftedDB = Registers.DB << 16; -} - -/* PHP */ -static void Op2B (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif - PullW (Registers.D.W); - SetZN16 (Registers.D.W); -} - -/* PLP */ -static void Op28 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif - PullB (Registers.PL); - S9xUnpackStatus (); - - if (CheckIndex ()) - { - Registers.XH = 0; - Registers.YH = 0; - } - S9xFixCycles(); -/* CHECK_FOR_IRQ();*/ -} - -static void OpFAX1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif - PullB (Registers.XL); - SetZN8 (Registers.XL); -} - -static void OpFAX0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif - PullW (Registers.X.W); - SetZN16 (Registers.X.W); -} - -static void Op7AX1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif - PullB (Registers.YL); - SetZN8 (Registers.YL); -} - -static void Op7AX0 (void) -{ -#ifdef VAR_CYCLES - - CPU.Cycles += TWO_CYCLES; -#endif - PullW (Registers.Y.W); - SetZN16 (Registers.Y.W); -} - -/**********************************************************************************************/ - -/* SetFlag Instructions ********************************************************************** */ -/* SEC */ -static void Op38 (void) -{ - SetCarry (); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -/* SED */ -static void OpF8 (void) -{ - SetDecimal (); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - missing.decimal_mode = 1; -} - -/* SEI */ -static void Op78 (void) -{ - SetIRQ (); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} -/**********************************************************************************************/ - -/* Transfer Instructions ********************************************************************* */ -/* TAX8 */ -static void OpAAX1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.XL = Registers.AL; - SetZN8 (Registers.XL); -} - -/* TAX16 */ -static void OpAAX0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.X.W = Registers.A.W; - SetZN16 (Registers.X.W); -} - -/* TAY8 */ -static void OpA8X1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.YL = Registers.AL; - SetZN8 (Registers.YL); -} - -/* TAY16 */ -static void OpA8X0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.Y.W = Registers.A.W; - SetZN16 (Registers.Y.W); -} - -static void Op5B (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.D.W = Registers.A.W; - SetZN16 (Registers.D.W); -} - -static void Op1B (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.S.W = Registers.A.W; - if (CheckEmulation()) - Registers.SH = 1; -} - -static void Op7B (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.A.W = Registers.D.W; - SetZN16 (Registers.A.W); -} - -static void Op3B (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.A.W = Registers.S.W; - SetZN16 (Registers.A.W); -} - -static void OpBAX1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.XL = Registers.SL; - SetZN8 (Registers.XL); -} - -static void OpBAX0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.X.W = Registers.S.W; - SetZN16 (Registers.X.W); -} - -static void Op8AM1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.AL = Registers.XL; - SetZN8 (Registers.AL); -} - -static void Op8AM0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.A.W = Registers.X.W; - SetZN16 (Registers.A.W); -} - -static void Op9A (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.S.W = Registers.X.W; - if (CheckEmulation()) - Registers.SH = 1; -} - -static void Op9BX1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.YL = Registers.XL; - SetZN8 (Registers.YL); -} - -static void Op9BX0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.Y.W = Registers.X.W; - SetZN16 (Registers.Y.W); -} - -static void Op98M1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.AL = Registers.YL; - SetZN8 (Registers.AL); -} - -static void Op98M0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.A.W = Registers.Y.W; - SetZN16 (Registers.A.W); -} - -static void OpBBX1 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.XL = Registers.YL; - SetZN8 (Registers.XL); -} - -static void OpBBX0 (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - Registers.X.W = Registers.Y.W; - SetZN16 (Registers.X.W); -} - -/**********************************************************************************************/ - -/* XCE *************************************************************************************** */ -static void OpFB (void) -{ -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - - uint8 A1 = ICPU._Carry; - uint8 A2 = Registers.PH; - ICPU._Carry = A2 & 1; - Registers.PH = A1; - - if (CheckEmulation()) - { - SetFlags (MemoryFlag | IndexFlag); - Registers.SH = 1; - missing.emulate6502 = 1; - } - if (CheckIndex ()) - { - Registers.XH = 0; - Registers.YH = 0; - } - S9xFixCycles(); -} -/**********************************************************************************************/ - -/* BRK *************************************************************************************** */ -static void Op00 (void) -{ -#ifndef SA1_OPCODES - CPU.BRKTriggered = TRUE; -#endif - - if (!CheckEmulation()) - { - PushB (Registers.PB); - PushW (CPU.PC - CPU.PCBase + 1); - S9xPackStatus (); - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; - ICPU.ShiftedPB = 0; - S9xSetPCBase (S9xGetWord (0xFFE6)); -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#else -#ifndef SA1_OPCODES - CPU.Cycles += 8; -#endif -#endif - } - else - { - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; - ICPU.ShiftedPB = 0; - S9xSetPCBase (S9xGetWord (0xFFFE)); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles += 6; -#endif -#endif - } -} -/**********************************************************************************************/ - -/* BRL ************************************************************************************** */ -static void Op82 (void) -{ - RelativeLong (); - S9xSetPCBase (ICPU.ShiftedPB + OpAddress); -} -/**********************************************************************************************/ - -/* IRQ *************************************************************************************** */ -void S9xOpcode_IRQ (void) -{ - if (!CheckEmulation()) - { - PushB (Registers.PB); - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; - ICPU.ShiftedPB = 0; -#ifdef SA1_OPCODES - S9xSA1SetPCBase (Memory.FillRAM [0x2207] | - (Memory.FillRAM [0x2208] << 8)); -#else - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) - S9xSetPCBase (Memory.FillRAM [0x220e] | - (Memory.FillRAM [0x220f] << 8)); - else - S9xSetPCBase (S9xGetWord (0xFFEE)); -#endif -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#else -#ifndef SA1_OPCODES - CPU.Cycles += 8; -#endif -#endif - } - else - { - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; - ICPU.ShiftedPB = 0; -#ifdef SA1_OPCODES - S9xSA1SetPCBase (Memory.FillRAM [0x2207] | - (Memory.FillRAM [0x2208] << 8)); -#else - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) - S9xSetPCBase (Memory.FillRAM [0x220e] | - (Memory.FillRAM [0x220f] << 8)); - else - S9xSetPCBase (S9xGetWord (0xFFFE)); -#endif -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles += 6; -#endif -#endif - } -} - -/**********************************************************************************************/ - -/* NMI *************************************************************************************** */ -void S9xOpcode_NMI (void) -{ - if (!CheckEmulation()) - { - PushB (Registers.PB); - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; - ICPU.ShiftedPB = 0; -#ifdef SA1_OPCODES - S9xSA1SetPCBase (Memory.FillRAM [0x2205] | - (Memory.FillRAM [0x2206] << 8)); -#else - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) - S9xSetPCBase (Memory.FillRAM [0x220c] | - (Memory.FillRAM [0x220d] << 8)); - else - S9xSetPCBase (S9xGetWord (0xFFEA)); -#endif -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#else -#ifndef SA1_OPCODES - CPU.Cycles += 8; -#endif -#endif - } - else - { - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; - ICPU.ShiftedPB = 0; -#ifdef SA1_OPCODES - S9xSA1SetPCBase (Memory.FillRAM [0x2205] | - (Memory.FillRAM [0x2206] << 8)); -#else - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) - S9xSetPCBase (Memory.FillRAM [0x220c] | - (Memory.FillRAM [0x220d] << 8)); - else - S9xSetPCBase (S9xGetWord (0xFFFA)); -#endif -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles += 6; -#endif -#endif - } -} -/**********************************************************************************************/ - -/* COP *************************************************************************************** */ -static void Op02 (void) -{ - if (!CheckEmulation()) - { - PushB (Registers.PB); - PushW (CPU.PC - CPU.PCBase + 1); - S9xPackStatus (); - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; - ICPU.ShiftedPB = 0; - S9xSetPCBase (S9xGetWord (0xFFE4)); -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#else -#ifndef SA1_OPCODES - CPU.Cycles += 8; -#endif -#endif - } - else - { - PushW (CPU.PC - CPU.PCBase); - S9xPackStatus (); - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; - ICPU.ShiftedPB = 0; - S9xSetPCBase (S9xGetWord (0xFFF4)); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else -#ifndef SA1_OPCODES - CPU.Cycles += 6; -#endif -#endif - } -} -/**********************************************************************************************/ - -/* JML *************************************************************************************** */ -static void OpDC (void) -{ - AbsoluteIndirectLong (); - Registers.PB = (uint8) (OpAddress >> 16); - ICPU.ShiftedPB = OpAddress & 0xff0000; - S9xSetPCBase (OpAddress); -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif -} - -static void Op5C (void) -{ - AbsoluteLong (); - Registers.PB = (uint8) (OpAddress >> 16); - ICPU.ShiftedPB = OpAddress & 0xff0000; - S9xSetPCBase (OpAddress); -} -/**********************************************************************************************/ - -/* JMP *************************************************************************************** */ -static void Op4C (void) -{ - Absolute (); - S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); -#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) - CPUShutdown (); -#endif -} - -static void Op6C (void) -{ - AbsoluteIndirect (); - S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); -} - -static void Op7C (void) -{ - AbsoluteIndexedIndirect (); - S9xSetPCBase (ICPU.ShiftedPB + OpAddress); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} -/**********************************************************************************************/ - -/* JSL/RTL *********************************************************************************** */ -static void Op22 (void) -{ - AbsoluteLong (); - PushB (Registers.PB); - PushW (CPU.PC - CPU.PCBase - 1); - Registers.PB = (uint8) (OpAddress >> 16); - ICPU.ShiftedPB = OpAddress & 0xff0000; - S9xSetPCBase (OpAddress); -} - -static void Op6B (void) -{ - PullW (Registers.PC); - PullB (Registers.PB); - ICPU.ShiftedPB = Registers.PB << 16; - S9xSetPCBase (ICPU.ShiftedPB + ((Registers.PC + 1) & 0xffff)); -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif -} -/**********************************************************************************************/ - -/* JSR/RTS *********************************************************************************** */ -static void Op20 (void) -{ - Absolute (); - PushW (CPU.PC - CPU.PCBase - 1); - S9xSetPCBase (ICPU.ShiftedPB + (OpAddress & 0xffff)); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void OpFC (void) -{ - AbsoluteIndexedIndirect (); - PushW (CPU.PC - CPU.PCBase - 1); - S9xSetPCBase (ICPU.ShiftedPB + OpAddress); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif -} - -static void Op60 (void) -{ - PullW (Registers.PC); - S9xSetPCBase (ICPU.ShiftedPB + ((Registers.PC + 1) & 0xffff)); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE * 3; -#endif -} - -/**********************************************************************************************/ - -/* MVN/MVP *********************************************************************************** */ -static void Op54X1 (void) -{ - uint32 SrcBank; - -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; -#endif - - Registers.DB = *CPU.PC++; - ICPU.ShiftedDB = Registers.DB << 16; - SrcBank = *CPU.PC++; - - S9xSetByte (S9xGetByte ((SrcBank << 16) + Registers.X.W), - ICPU.ShiftedDB + Registers.Y.W); - - Registers.XL++; - Registers.YL++; - Registers.A.W--; - if (Registers.A.W != 0xffff) - CPU.PC -= 3; -} - -static void Op54X0 (void) -{ - uint32 SrcBank; - -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; -#endif - - Registers.DB = *CPU.PC++; - ICPU.ShiftedDB = Registers.DB << 16; - SrcBank = *CPU.PC++; - - S9xSetByte (S9xGetByte ((SrcBank << 16) + Registers.X.W), - ICPU.ShiftedDB + Registers.Y.W); - - Registers.X.W++; - Registers.Y.W++; - Registers.A.W--; - if (Registers.A.W != 0xffff) - CPU.PC -= 3; -} - -static void Op44X1 (void) -{ - uint32 SrcBank; - -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; -#endif - Registers.DB = *CPU.PC++; - ICPU.ShiftedDB = Registers.DB << 16; - SrcBank = *CPU.PC++; - S9xSetByte (S9xGetByte ((SrcBank << 16) + Registers.X.W), - ICPU.ShiftedDB + Registers.Y.W); - - Registers.XL--; - Registers.YL--; - Registers.A.W--; - if (Registers.A.W != 0xffff) - CPU.PC -= 3; -} - -static void Op44X0 (void) -{ - uint32 SrcBank; - -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeedx2 + TWO_CYCLES; -#endif - Registers.DB = *CPU.PC++; - ICPU.ShiftedDB = Registers.DB << 16; - SrcBank = *CPU.PC++; - S9xSetByte (S9xGetByte ((SrcBank << 16) + Registers.X.W), - ICPU.ShiftedDB + Registers.Y.W); - - Registers.X.W--; - Registers.Y.W--; - Registers.A.W--; - if (Registers.A.W != 0xffff) - CPU.PC -= 3; -} - -/**********************************************************************************************/ - -/* REP/SEP *********************************************************************************** */ -static void OpC2 (void) -{ - uint8 Work8 = ~*CPU.PC++; - Registers.PL &= Work8; - ICPU._Carry &= Work8; - ICPU._Overflow &= (Work8 >> 6); - ICPU._Negative &= Work8; - ICPU._Zero |= ~Work8 & Zero; - -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - if (CheckEmulation()) - { - SetFlags (MemoryFlag | IndexFlag); - missing.emulate6502 = 1; - } - if (CheckIndex ()) - { - Registers.XH = 0; - Registers.YH = 0; - } - S9xFixCycles(); -/* CHECK_FOR_IRQ(); */ -} - -static void OpE2 (void) -{ - uint8 Work8 = *CPU.PC++; - Registers.PL |= Work8; - ICPU._Carry |= Work8 & 1; - ICPU._Overflow |= (Work8 >> 6) & 1; - ICPU._Negative |= Work8; - if (Work8 & Zero) - ICPU._Zero = 0; -#ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed + ONE_CYCLE; -#endif - if (CheckEmulation()) - { - SetFlags (MemoryFlag | IndexFlag); - missing.emulate6502 = 1; - } - if (CheckIndex ()) - { - Registers.XH = 0; - Registers.YH = 0; - } - S9xFixCycles(); -} -/**********************************************************************************************/ - -/* XBA *************************************************************************************** */ -static void OpEB (void) -{ - uint8 Work8 = Registers.AL; - Registers.AL = Registers.AH; - Registers.AH = Work8; - - SetZN8 (Registers.AL); -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif -} -/**********************************************************************************************/ - -/* RTI *************************************************************************************** */ -static void Op40 (void) -{ - PullB (Registers.PL); - S9xUnpackStatus (); - PullW (Registers.PC); - if (!CheckEmulation()) - { - PullB (Registers.PB); - ICPU.ShiftedPB = Registers.PB << 16; - } - else - { - SetFlags (MemoryFlag | IndexFlag); - missing.emulate6502 = 1; - } - S9xSetPCBase (ICPU.ShiftedPB + Registers.PC); - - if (CheckIndex ()) - { - Registers.XH = 0; - Registers.YH = 0; - } -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#endif - S9xFixCycles(); -/* CHECK_FOR_IRQ(); */ -} - -/**********************************************************************************************/ - -/* STP/WAI/DB ******************************************************************************** */ -// WAI -static void OpCB (void) -{ - if (CPU.IRQActive) - { -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#else -#ifndef SA1_OPCODES - CPU.Cycles += 2; -#endif -#endif - } - else - { - CPU.WaitingForInterrupt = TRUE; - CPU.PC--; -#ifdef CPU_SHUTDOWN -#ifndef SA1_OPCODES - if (Settings.Shutdown) - { - CPU.Cycles = CPU.NextEvent; - asm_APU_EXECUTE2(); - } -#else - if (Settings.Shutdown) - { - SA1.CPUExecuting = FALSE; - SA1.Executing = FALSE; - } -#endif -#endif - } -} - -// STP -static void OpDB (void) -{ - CPU.PC--; - CPU.Flags |= DEBUG_MODE_FLAG; -} - -// Reserved S9xOpcode -static void Op42 (void) { -#ifndef SA1_OPCODES - uint8 b; - - CPU.WaitAddress = NULL; - CPU.Cycles = CPU.NextEvent; - asm_APU_EXECUTE2(); - //debug_log("toto"); - b=*CPU.PC++; - - //relative - signed char s9xInt8=0xF0|(b&0xF); - #ifdef VAR_CYCLES - CPU.Cycles += CPU.MemSpeed; - #endif - OpAddress = ((int) (CPU.PC - CPU.PCBase) + s9xInt8) & 0xffff; - - switch (b&0xF0) { - case 0x10: //BPL - BranchCheck1 (); - if (!CheckNegative ()) { - CPU.PC = CPU.PCBase + OpAddress; - #ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; - #else - #ifndef SA1_OPCODES - CPU.Cycles++; - #endif - #endif - CPUShutdown (); - } - return; - case 0x30: //BMI - BranchCheck1 (); - if (CheckNegative ()) { - CPU.PC = CPU.PCBase + OpAddress; - #ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; - #else - #ifndef SA1_OPCODES - CPU.Cycles++; - #endif - #endif - CPUShutdown (); - } - return; - case 0x50: //BVC - BranchCheck0 (); - if (!CheckOverflow ()) { - CPU.PC = CPU.PCBase + OpAddress; - #ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; - #else - #ifndef SA1_OPCODES - CPU.Cycles++; - #endif - #endif - CPUShutdown (); - } - return; - case 0x70: //BVS - BranchCheck0 (); - if (CheckOverflow ()) { - CPU.PC = CPU.PCBase + OpAddress; - #ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; - #else - #ifndef SA1_OPCODES - CPU.Cycles++; - #endif - #endif - CPUShutdown (); - } - return; - case 0x80: //BRA - //op80 - CPU.PC = CPU.PCBase + OpAddress; - #ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; - #else - #ifndef SA1_OPCODES - CPU.Cycles++; - #endif - #endif - CPUShutdown (); - return; - case 0x90: //BCC - BranchCheck0 (); - if (!CheckCarry ()) { - CPU.PC = CPU.PCBase + OpAddress; - #ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; - #else - #ifndef SA1_OPCODES - CPU.Cycles++; - #endif - #endif - CPUShutdown (); - } - return; - case 0xB0: //BCS - BranchCheck0 (); - if (CheckCarry ()) { - CPU.PC = CPU.PCBase + OpAddress; - #ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; - #else - #ifndef SA1_OPCODES - CPU.Cycles++; - #endif - #endif - CPUShutdown (); - } - return; - case 0xD0: //BNE - BranchCheck1 (); - if (!CheckZero ()) { - CPU.PC = CPU.PCBase + OpAddress; - #ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; - #else - #ifndef SA1_OPCODES - CPU.Cycles++; - #endif - #endif - CPUShutdown (); - } - return; - case 0xF0: //BEQ - BranchCheck2 (); - if (CheckZero ()) { - CPU.PC = CPU.PCBase + OpAddress; - #ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; - #else - #ifndef SA1_OPCODES - CPU.Cycles++; - #endif - #endif - CPUShutdown (); - } - return; - } -#endif -} - -/**********************************************************************************************/ - -/**********************************************************************************************/ -/* CPU-S9xOpcodes Definitions */ -/**********************************************************************************************/ -struct SOpcodes S9xOpcodesM1X1[256] = -{ - {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, - {Op05M1}, {Op06M1}, {Op07M1}, {Op08}, {Op09M1}, - {Op0AM1}, {Op0B}, {Op0CM1}, {Op0DM1}, {Op0EM1}, - {Op0FM1}, {Op10}, {Op11M1}, {Op12M1}, {Op13M1}, - {Op14M1}, {Op15M1}, {Op16M1}, {Op17M1}, {Op18}, - {Op19M1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1}, - {Op1EM1}, {Op1FM1}, {Op20}, {Op21M1}, {Op22}, - {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, - {Op28}, {Op29M1}, {Op2AM1}, {Op2B}, {Op2CM1}, - {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30}, {Op31M1}, - {Op32M1}, {Op33M1}, {Op34M1}, {Op35M1}, {Op36M1}, - {Op37M1}, {Op38}, {Op39M1}, {Op3AM1}, {Op3B}, - {Op3CM1}, {Op3DM1}, {Op3EM1}, {Op3FM1}, {Op40}, - {Op41M1}, {Op42}, {Op43M1}, {Op44X1}, {Op45M1}, - {Op46M1}, {Op47M1}, {Op48M1}, {Op49M1}, {Op4AM1}, - {Op4B}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, - {Op50}, {Op51M1}, {Op52M1}, {Op53M1}, {Op54X1}, - {Op55M1}, {Op56M1}, {Op57M1}, {Op58}, {Op59M1}, - {Op5AX1}, {Op5B}, {Op5C}, {Op5DM1}, {Op5EM1}, - {Op5FM1}, {Op60}, {Op61M1}, {Op62}, {Op63M1}, - {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68M1}, - {Op69M1}, {Op6AM1}, {Op6B}, {Op6C}, {Op6DM1}, - {Op6EM1}, {Op6FM1}, {Op70}, {Op71M1}, {Op72M1}, - {Op73M1}, {Op74M1}, {Op75M1}, {Op76M1}, {Op77M1}, - {Op78}, {Op79M1}, {Op7AX1}, {Op7B}, {Op7C}, - {Op7DM1}, {Op7EM1}, {Op7FM1}, {Op80}, {Op81M1}, - {Op82}, {Op83M1}, {Op84X1}, {Op85M1}, {Op86X1}, - {Op87M1}, {Op88X1}, {Op89M1}, {Op8AM1}, {Op8B}, - {Op8CX1}, {Op8DM1}, {Op8EX1}, {Op8FM1}, {Op90}, - {Op91M1}, {Op92M1}, {Op93M1}, {Op94X1}, {Op95M1}, - {Op96X1}, {Op97M1}, {Op98M1}, {Op99M1}, {Op9A}, - {Op9BX1}, {Op9CM1}, {Op9DM1}, {Op9EM1}, {Op9FM1}, - {OpA0X1}, {OpA1M1}, {OpA2X1}, {OpA3M1}, {OpA4X1}, - {OpA5M1}, {OpA6X1}, {OpA7M1}, {OpA8X1}, {OpA9M1}, - {OpAAX1}, {OpAB}, {OpACX1}, {OpADM1}, {OpAEX1}, - {OpAFM1}, {OpB0}, {OpB1M1}, {OpB2M1}, {OpB3M1}, - {OpB4X1}, {OpB5M1}, {OpB6X1}, {OpB7M1}, {OpB8}, - {OpB9M1}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM1}, - {OpBEX1}, {OpBFM1}, {OpC0X1}, {OpC1M1}, {OpC2}, - {OpC3M1}, {OpC4X1}, {OpC5M1}, {OpC6M1}, {OpC7M1}, - {OpC8X1}, {OpC9M1}, {OpCAX1}, {OpCB}, {OpCCX1}, - {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0}, {OpD1M1}, - {OpD2M1}, {OpD3M1}, {OpD4}, {OpD5M1}, {OpD6M1}, - {OpD7M1}, {OpD8}, {OpD9M1}, {OpDAX1}, {OpDB}, - {OpDC}, {OpDDM1}, {OpDEM1}, {OpDFM1}, {OpE0X1}, - {OpE1M1}, {OpE2}, {OpE3M1}, {OpE4X1}, {OpE5M1}, - {OpE6M1}, {OpE7M1}, {OpE8X1}, {OpE9M1}, {OpEA}, - - {OpEB}, {OpECX1}, {OpEDM1}, {OpEEM1}, {OpEFM1}, - {OpF0}, {OpF1M1}, {OpF2M1}, {OpF3M1}, {OpF4}, - {OpF5M1}, {OpF6M1}, {OpF7M1}, {OpF8}, {OpF9M1}, - {OpFAX1}, {OpFB}, {OpFC}, {OpFDM1}, {OpFEM1}, - {OpFFM1} -}; - -struct SOpcodes S9xOpcodesM1X0[256] = -{ - {Op00}, {Op01M1}, {Op02}, {Op03M1}, {Op04M1}, - {Op05M1}, {Op06M1}, {Op07M1}, {Op08}, {Op09M1}, - {Op0AM1}, {Op0B}, {Op0CM1}, {Op0DM1}, {Op0EM1}, - {Op0FM1}, {Op10}, {Op11M1}, {Op12M1}, {Op13M1}, - {Op14M1}, {Op15M1}, {Op16M1}, {Op17M1}, {Op18}, - {Op19M1}, {Op1AM1}, {Op1B}, {Op1CM1}, {Op1DM1}, - {Op1EM1}, {Op1FM1}, {Op20}, {Op21M1}, {Op22}, - {Op23M1}, {Op24M1}, {Op25M1}, {Op26M1}, {Op27M1}, - {Op28}, {Op29M1}, {Op2AM1}, {Op2B}, {Op2CM1}, - {Op2DM1}, {Op2EM1}, {Op2FM1}, {Op30}, {Op31M1}, - {Op32M1}, {Op33M1}, {Op34M1}, {Op35M1}, {Op36M1}, - {Op37M1}, {Op38}, {Op39M1}, {Op3AM1}, {Op3B}, - {Op3CM1}, {Op3DM1}, {Op3EM1}, {Op3FM1}, {Op40}, - {Op41M1}, {Op42}, {Op43M1}, {Op44X0}, {Op45M1}, - {Op46M1}, {Op47M1}, {Op48M1}, {Op49M1}, {Op4AM1}, - {Op4B}, {Op4C}, {Op4DM1}, {Op4EM1}, {Op4FM1}, - {Op50}, {Op51M1}, {Op52M1}, {Op53M1}, {Op54X0}, - {Op55M1}, {Op56M1}, {Op57M1}, {Op58}, {Op59M1}, - {Op5AX0}, {Op5B}, {Op5C}, {Op5DM1}, {Op5EM1}, - {Op5FM1}, {Op60}, {Op61M1}, {Op62}, {Op63M1}, - {Op64M1}, {Op65M1}, {Op66M1}, {Op67M1}, {Op68M1}, - {Op69M1}, {Op6AM1}, {Op6B}, {Op6C}, {Op6DM1}, - {Op6EM1}, {Op6FM1}, {Op70}, {Op71M1}, {Op72M1}, - {Op73M1}, {Op74M1}, {Op75M1}, {Op76M1}, {Op77M1}, - {Op78}, {Op79M1}, {Op7AX0}, {Op7B}, {Op7C}, - {Op7DM1}, {Op7EM1}, {Op7FM1}, {Op80}, {Op81M1}, - {Op82}, {Op83M1}, {Op84X0}, {Op85M1}, {Op86X0}, - {Op87M1}, {Op88X0}, {Op89M1}, {Op8AM1}, {Op8B}, - {Op8CX0}, {Op8DM1}, {Op8EX0}, {Op8FM1}, {Op90}, - {Op91M1}, {Op92M1}, {Op93M1}, {Op94X0}, {Op95M1}, - {Op96X0}, {Op97M1}, {Op98M1}, {Op99M1}, {Op9A}, - {Op9BX0}, {Op9CM1}, {Op9DM1}, {Op9EM1}, {Op9FM1}, - {OpA0X0}, {OpA1M1}, {OpA2X0}, {OpA3M1}, {OpA4X0}, - {OpA5M1}, {OpA6X0}, {OpA7M1}, {OpA8X0}, {OpA9M1}, - {OpAAX0}, {OpAB}, {OpACX0}, {OpADM1}, {OpAEX0}, - {OpAFM1}, {OpB0}, {OpB1M1}, {OpB2M1}, {OpB3M1}, - {OpB4X0}, {OpB5M1}, {OpB6X0}, {OpB7M1}, {OpB8}, - {OpB9M1}, {OpBAX0}, {OpBBX0}, {OpBCX0}, {OpBDM1}, - {OpBEX0}, {OpBFM1}, {OpC0X0}, {OpC1M1}, {OpC2}, - {OpC3M1}, {OpC4X0}, {OpC5M1}, {OpC6M1}, {OpC7M1}, - {OpC8X0}, {OpC9M1}, {OpCAX0}, {OpCB}, {OpCCX0}, - {OpCDM1}, {OpCEM1}, {OpCFM1}, {OpD0}, {OpD1M1}, - {OpD2M1}, {OpD3M1}, {OpD4}, {OpD5M1}, {OpD6M1}, - {OpD7M1}, {OpD8}, {OpD9M1}, {OpDAX0}, {OpDB}, - {OpDC}, {OpDDM1}, {OpDEM1}, {OpDFM1}, {OpE0X0}, - {OpE1M1}, {OpE2}, {OpE3M1}, {OpE4X0}, {OpE5M1}, - {OpE6M1}, {OpE7M1}, {OpE8X0}, {OpE9M1}, {OpEA}, - {OpEB}, {OpECX0}, {OpEDM1}, {OpEEM1}, {OpEFM1}, - {OpF0}, {OpF1M1}, {OpF2M1}, {OpF3M1}, {OpF4}, - {OpF5M1}, {OpF6M1}, {OpF7M1}, {OpF8}, {OpF9M1}, - {OpFAX0}, {OpFB}, {OpFC}, {OpFDM1}, {OpFEM1}, - {OpFFM1} -}; - -struct SOpcodes S9xOpcodesM0X0[256] = -{ - {Op00}, {Op01M0}, {Op02}, {Op03M0}, {Op04M0}, - {Op05M0}, {Op06M0}, {Op07M0}, {Op08}, {Op09M0}, - {Op0AM0}, {Op0B}, {Op0CM0}, {Op0DM0}, {Op0EM0}, - {Op0FM0}, {Op10}, {Op11M0}, {Op12M0}, {Op13M0}, - {Op14M0}, {Op15M0}, {Op16M0}, {Op17M0}, {Op18}, - {Op19M0}, {Op1AM0}, {Op1B}, {Op1CM0}, {Op1DM0}, - {Op1EM0}, {Op1FM0}, {Op20}, {Op21M0}, {Op22}, - {Op23M0}, {Op24M0}, {Op25M0}, {Op26M0}, {Op27M0}, - {Op28}, {Op29M0}, {Op2AM0}, {Op2B}, {Op2CM0}, - {Op2DM0}, {Op2EM0}, {Op2FM0}, {Op30}, {Op31M0}, - {Op32M0}, {Op33M0}, {Op34M0}, {Op35M0}, {Op36M0}, - {Op37M0}, {Op38}, {Op39M0}, {Op3AM0}, {Op3B}, - {Op3CM0}, {Op3DM0}, {Op3EM0}, {Op3FM0}, {Op40}, - {Op41M0}, {Op42}, {Op43M0}, {Op44X0}, {Op45M0}, - {Op46M0}, {Op47M0}, {Op48M0}, {Op49M0}, {Op4AM0}, - {Op4B}, {Op4C}, {Op4DM0}, {Op4EM0}, {Op4FM0}, - {Op50}, {Op51M0}, {Op52M0}, {Op53M0}, {Op54X0}, - {Op55M0}, {Op56M0}, {Op57M0}, {Op58}, {Op59M0}, - {Op5AX0}, {Op5B}, {Op5C}, {Op5DM0}, {Op5EM0}, - {Op5FM0}, {Op60}, {Op61M0}, {Op62}, {Op63M0}, - {Op64M0}, {Op65M0}, {Op66M0}, {Op67M0}, {Op68M0}, - {Op69M0}, {Op6AM0}, {Op6B}, {Op6C}, {Op6DM0}, - {Op6EM0}, {Op6FM0}, {Op70}, {Op71M0}, {Op72M0}, - {Op73M0}, {Op74M0}, {Op75M0}, {Op76M0}, {Op77M0}, - {Op78}, {Op79M0}, {Op7AX0}, {Op7B}, {Op7C}, - {Op7DM0}, {Op7EM0}, {Op7FM0}, {Op80}, {Op81M0}, - {Op82}, {Op83M0}, {Op84X0}, {Op85M0}, {Op86X0}, - {Op87M0}, {Op88X0}, {Op89M0}, {Op8AM0}, {Op8B}, - {Op8CX0}, {Op8DM0}, {Op8EX0}, {Op8FM0}, {Op90}, - {Op91M0}, {Op92M0}, {Op93M0}, {Op94X0}, {Op95M0}, - {Op96X0}, {Op97M0}, {Op98M0}, {Op99M0}, {Op9A}, - {Op9BX0}, {Op9CM0}, {Op9DM0}, {Op9EM0}, {Op9FM0}, - {OpA0X0}, {OpA1M0}, {OpA2X0}, {OpA3M0}, {OpA4X0}, - {OpA5M0}, {OpA6X0}, {OpA7M0}, {OpA8X0}, {OpA9M0}, - {OpAAX0}, {OpAB}, {OpACX0}, {OpADM0}, {OpAEX0}, - {OpAFM0}, {OpB0}, {OpB1M0}, {OpB2M0}, {OpB3M0}, - {OpB4X0}, {OpB5M0}, {OpB6X0}, {OpB7M0}, {OpB8}, - {OpB9M0}, {OpBAX0}, {OpBBX0}, {OpBCX0}, {OpBDM0}, - {OpBEX0}, {OpBFM0}, {OpC0X0}, {OpC1M0}, {OpC2}, - {OpC3M0}, {OpC4X0}, {OpC5M0}, {OpC6M0}, {OpC7M0}, - {OpC8X0}, {OpC9M0}, {OpCAX0}, {OpCB}, {OpCCX0}, - {OpCDM0}, {OpCEM0}, {OpCFM0}, {OpD0}, {OpD1M0}, - {OpD2M0}, {OpD3M0}, {OpD4}, {OpD5M0}, {OpD6M0}, - {OpD7M0}, {OpD8}, {OpD9M0}, {OpDAX0}, {OpDB}, - {OpDC}, {OpDDM0}, {OpDEM0}, {OpDFM0}, {OpE0X0}, - {OpE1M0}, {OpE2}, {OpE3M0}, {OpE4X0}, {OpE5M0}, - {OpE6M0}, {OpE7M0}, {OpE8X0}, {OpE9M0}, {OpEA}, - {OpEB}, {OpECX0}, {OpEDM0}, {OpEEM0}, {OpEFM0}, - {OpF0}, {OpF1M0}, {OpF2M0}, {OpF3M0}, {OpF4}, - {OpF5M0}, {OpF6M0}, {OpF7M0}, {OpF8}, {OpF9M0}, - {OpFAX0}, {OpFB}, {OpFC}, {OpFDM0}, {OpFEM0}, - {OpFFM0} -}; - -struct SOpcodes S9xOpcodesM0X1[256] = -{ - {Op00}, {Op01M0}, {Op02}, {Op03M0}, {Op04M0}, - {Op05M0}, {Op06M0}, {Op07M0}, {Op08}, {Op09M0}, - {Op0AM0}, {Op0B}, {Op0CM0}, {Op0DM0}, {Op0EM0}, - {Op0FM0}, {Op10}, {Op11M0}, {Op12M0}, {Op13M0}, - {Op14M0}, {Op15M0}, {Op16M0}, {Op17M0}, {Op18}, - {Op19M0}, {Op1AM0}, {Op1B}, {Op1CM0}, {Op1DM0}, - {Op1EM0}, {Op1FM0}, {Op20}, {Op21M0}, {Op22}, - {Op23M0}, {Op24M0}, {Op25M0}, {Op26M0}, {Op27M0}, - {Op28}, {Op29M0}, {Op2AM0}, {Op2B}, {Op2CM0}, - {Op2DM0}, {Op2EM0}, {Op2FM0}, {Op30}, {Op31M0}, - {Op32M0}, {Op33M0}, {Op34M0}, {Op35M0}, {Op36M0}, - {Op37M0}, {Op38}, {Op39M0}, {Op3AM0}, {Op3B}, - {Op3CM0}, {Op3DM0}, {Op3EM0}, {Op3FM0}, {Op40}, - {Op41M0}, {Op42}, {Op43M0}, {Op44X1}, {Op45M0}, - {Op46M0}, {Op47M0}, {Op48M0}, {Op49M0}, {Op4AM0}, - {Op4B}, {Op4C}, {Op4DM0}, {Op4EM0}, {Op4FM0}, - {Op50}, {Op51M0}, {Op52M0}, {Op53M0}, {Op54X1}, - {Op55M0}, {Op56M0}, {Op57M0}, {Op58}, {Op59M0}, - {Op5AX1}, {Op5B}, {Op5C}, {Op5DM0}, {Op5EM0}, - {Op5FM0}, {Op60}, {Op61M0}, {Op62}, {Op63M0}, - {Op64M0}, {Op65M0}, {Op66M0}, {Op67M0}, {Op68M0}, - {Op69M0}, {Op6AM0}, {Op6B}, {Op6C}, {Op6DM0}, - {Op6EM0}, {Op6FM0}, {Op70}, {Op71M0}, {Op72M0}, - {Op73M0}, {Op74M0}, {Op75M0}, {Op76M0}, {Op77M0}, - {Op78}, {Op79M0}, {Op7AX1}, {Op7B}, {Op7C}, - {Op7DM0}, {Op7EM0}, {Op7FM0}, {Op80}, {Op81M0}, - {Op82}, {Op83M0}, {Op84X1}, {Op85M0}, {Op86X1}, - {Op87M0}, {Op88X1}, {Op89M0}, {Op8AM0}, {Op8B}, - {Op8CX1}, {Op8DM0}, {Op8EX1}, {Op8FM0}, {Op90}, - {Op91M0}, {Op92M0}, {Op93M0}, {Op94X1}, {Op95M0}, - {Op96X1}, {Op97M0}, {Op98M0}, {Op99M0}, {Op9A}, - {Op9BX1}, {Op9CM0}, {Op9DM0}, {Op9EM0}, {Op9FM0}, - {OpA0X1}, {OpA1M0}, {OpA2X1}, {OpA3M0}, {OpA4X1}, - {OpA5M0}, {OpA6X1}, {OpA7M0}, {OpA8X1}, {OpA9M0}, - {OpAAX1}, {OpAB}, {OpACX1}, {OpADM0}, {OpAEX1}, - {OpAFM0}, {OpB0}, {OpB1M0}, {OpB2M0}, {OpB3M0}, - {OpB4X1}, {OpB5M0}, {OpB6X1}, {OpB7M0}, {OpB8}, - {OpB9M0}, {OpBAX1}, {OpBBX1}, {OpBCX1}, {OpBDM0}, - {OpBEX1}, {OpBFM0}, {OpC0X1}, {OpC1M0}, {OpC2}, - {OpC3M0}, {OpC4X1}, {OpC5M0}, {OpC6M0}, {OpC7M0}, - {OpC8X1}, {OpC9M0}, {OpCAX1}, {OpCB}, {OpCCX1}, - {OpCDM0}, {OpCEM0}, {OpCFM0}, {OpD0}, {OpD1M0}, - {OpD2M0}, {OpD3M0}, {OpD4}, {OpD5M0}, {OpD6M0}, - {OpD7M0}, {OpD8}, {OpD9M0}, {OpDAX1}, {OpDB}, - {OpDC}, {OpDDM0}, {OpDEM0}, {OpDFM0}, {OpE0X1}, - {OpE1M0}, {OpE2}, {OpE3M0}, {OpE4X1}, {OpE5M0}, - {OpE6M0}, {OpE7M0}, {OpE8X1}, {OpE9M0}, {OpEA}, - {OpEB}, {OpECX1}, {OpEDM0}, {OpEEM0}, {OpEFM0}, - {OpF0}, {OpF1M0}, {OpF2M0}, {OpF3M0}, {OpF4}, - {OpF5M0}, {OpF6M0}, {OpF7M0}, {OpF8}, {OpF9M0}, - {OpFAX1}, {OpFB}, {OpFC}, {OpFDM0}, {OpFEM0}, - {OpFFM0} -}; - diff --git a/src/data.c b/src/data.c new file mode 100644 index 0000000..2a25eab --- /dev/null +++ b/src/data.c @@ -0,0 +1,489 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include "snes9x.h" +/* +uint8 add32_32 [32][32] = { +{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, + 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, + 0x1e,0x1f}, +{ 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e, + 0x1f,0x1f}, +{ 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + 0x1f,0x1f}, +{ 0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11, + 0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12, + 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13, + 0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14, + 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15, + 0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16, + 0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, + 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, + 0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, + 0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c, + 0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, + 0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f}, +{ 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, + 0x1f,0x1f} +}; + +uint8 add32_32_half [32][32] = { +{ 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, + 0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e, + 0x0f,0x0f}, +{ 0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07, + 0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f, + 0x0f,0x10}, +{ 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08, + 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f, + 0x10,0x10}, +{ 0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08, + 0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10, + 0x10,0x11}, +{ 0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09, + 0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10, + 0x11,0x11}, +{ 0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09, + 0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11, + 0x11,0x12}, +{ 0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a, + 0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11, + 0x12,0x12}, +{ 0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a, + 0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12, + 0x12,0x13}, +{ 0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b, + 0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12, + 0x13,0x13}, +{ 0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b, + 0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13, + 0x13,0x14}, +{ 0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c, + 0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13, + 0x14,0x14}, +{ 0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c, + 0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14, + 0x14,0x15}, +{ 0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d, + 0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14, + 0x15,0x15}, +{ 0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d, + 0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15, + 0x15,0x16}, +{ 0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e, + 0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15, + 0x16,0x16}, +{ 0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e, + 0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16, + 0x16,0x17}, +{ 0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f, + 0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16, + 0x17,0x17}, +{ 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f, + 0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17, + 0x17,0x18}, +{ 0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10, + 0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17, + 0x18,0x18}, +{ 0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10, + 0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18, + 0x18,0x19}, +{ 0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11, + 0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18, + 0x19,0x19}, +{ 0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11, + 0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19, + 0x19,0x1a}, +{ 0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12, + 0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19, + 0x1a,0x1a}, +{ 0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12, + 0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a, + 0x1a,0x1b}, +{ 0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13, + 0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a, + 0x1b,0x1b}, +{ 0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13, + 0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b, + 0x1b,0x1c}, +{ 0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14, + 0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b, + 0x1c,0x1c}, +{ 0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14, + 0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c, + 0x1c,0x1d}, +{ 0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15, + 0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c, + 0x1d,0x1d}, +{ 0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15, + 0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c,0x1d, + 0x1d,0x1e}, +{ 0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16, + 0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c,0x1d,0x1d, + 0x1e,0x1e}, +{ 0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16, + 0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c,0x1d,0x1d,0x1e, + 0x1e,0x1f} +}; +uint8 sub32_32 [32][32] = { +{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, + 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, + 0x1e,0x1f}, +{ 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, + 0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c, + 0x1d,0x1e}, +{ 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c, + 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, + 0x1c,0x1d}, +{ 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, + 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, + 0x1b,0x1c}, +{ 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a, + 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x1a,0x1b}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, + 0x19,0x1a}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16, + 0x17,0x18}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06, + 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15, + 0x16,0x17}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05, + 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14, + 0x15,0x16}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04, + 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13, + 0x14,0x15}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03, + 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12, + 0x13,0x14}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, + 0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11, + 0x12,0x13}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, + 0x11,0x12}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, + 0x0f,0x10}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, + 0x0e,0x0f}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c, + 0x0d,0x0e}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, + 0x0c,0x0d}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a, + 0x0b,0x0c}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, + 0x0a,0x0b}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x09,0x0a}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06, + 0x07,0x08}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05, + 0x06,0x07}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04, + 0x05,0x06}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03, + 0x04,0x05}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, + 0x03,0x04}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x02,0x03}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x02}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00} +}; + +uint8 sub32_32_half [32][32] = { +{ 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, + 0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e, + 0x0f,0x0f}, +{ 0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06, + 0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e, + 0x0e,0x0f}, +{ 0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06, + 0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d, + 0x0e,0x0e}, +{ 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05, + 0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d, + 0x0d,0x0e}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05, + 0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c, + 0x0d,0x0d}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04, + 0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c, + 0x0c,0x0d}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04, + 0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b, + 0x0c,0x0c}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03, + 0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b, + 0x0b,0x0c}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03, + 0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a, + 0x0b,0x0b}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02, + 0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a, + 0x0a,0x0b}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02, + 0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09, + 0x0a,0x0a}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01, + 0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09, + 0x09,0x0a}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08, + 0x09,0x09}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08, + 0x08,0x09}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07, + 0x08,0x08}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, + 0x07,0x08}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06, + 0x07,0x07}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06, + 0x06,0x07}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05, + 0x06,0x06}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05, + 0x05,0x06}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04, + 0x05,0x05}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04, + 0x04,0x05}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03, + 0x04,0x04}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03, + 0x03,0x04}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02, + 0x03,0x03}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02, + 0x02,0x03}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01, + 0x02,0x02}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x01,0x02}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x01}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00} +}; +*/ + +uint8 mul_brightness [16][32] = { +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}, +{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02, + 0x02,0x02}, +{ 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04,0x04, + 0x04,0x04}, +{ 0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x03,0x03, + 0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x06,0x06, + 0x06,0x06}, +{ 0x00,0x00,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x04, + 0x04,0x04,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x08, + 0x08,0x08}, +{ 0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05, + 0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a, + 0x0a,0x0a}, +{ 0x00,0x00,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x06, + 0x06,0x06,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0c, + 0x0c,0x0c}, +{ 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, + 0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e, + 0x0e,0x0e}, +{ 0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07, + 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f, + 0x10,0x11}, +{ 0x00,0x01,0x01,0x02,0x02,0x03,0x04,0x04,0x05,0x05,0x06,0x07,0x07,0x08,0x08, + 0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x10,0x10,0x11,0x11, + 0x12,0x13}, +{ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x05,0x06,0x07,0x07,0x08,0x09,0x09, + 0x0a,0x0b,0x0b,0x0c,0x0d,0x0d,0x0e,0x0f,0x0f,0x10,0x11,0x11,0x12,0x13,0x13, + 0x14,0x15}, +{ 0x00,0x01,0x01,0x02,0x03,0x04,0x04,0x05,0x06,0x07,0x07,0x08,0x09,0x0a,0x0a, + 0x0b,0x0c,0x0c,0x0d,0x0e,0x0f,0x0f,0x10,0x11,0x12,0x12,0x13,0x14,0x15,0x15, + 0x16,0x17}, +{ 0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x06,0x07,0x08,0x09,0x0a,0x0a,0x0b, + 0x0c,0x0d,0x0e,0x0e,0x0f,0x10,0x11,0x12,0x12,0x13,0x14,0x15,0x16,0x16,0x17, + 0x18,0x19}, +{ 0x00,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0a,0x0b,0x0c, + 0x0d,0x0e,0x0f,0x10,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x17,0x18,0x19, + 0x1a,0x1b}, +{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, + 0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, + 0x1c,0x1d}, +{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, + 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, + 0x1e,0x1f} +}; + diff --git a/src/data.cpp b/src/data.cpp deleted file mode 100644 index 2a25eab..0000000 --- a/src/data.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include "snes9x.h" -/* -uint8 add32_32 [32][32] = { -{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, - 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, - 0x1e,0x1f}, -{ 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e, - 0x1f,0x1f}, -{ 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, - 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, - 0x1f,0x1f}, -{ 0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11, - 0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12, - 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13, - 0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14, - 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15, - 0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16, - 0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, - 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, - 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, - 0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, - 0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c, - 0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, - 0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f}, -{ 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f, - 0x1f,0x1f} -}; - -uint8 add32_32_half [32][32] = { -{ 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, - 0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e, - 0x0f,0x0f}, -{ 0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07, - 0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f, - 0x0f,0x10}, -{ 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08, - 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f, - 0x10,0x10}, -{ 0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08, - 0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10, - 0x10,0x11}, -{ 0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09, - 0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10, - 0x11,0x11}, -{ 0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09, - 0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11, - 0x11,0x12}, -{ 0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a, - 0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11, - 0x12,0x12}, -{ 0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a, - 0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12, - 0x12,0x13}, -{ 0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b, - 0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12, - 0x13,0x13}, -{ 0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b, - 0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13, - 0x13,0x14}, -{ 0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c, - 0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13, - 0x14,0x14}, -{ 0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c, - 0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14, - 0x14,0x15}, -{ 0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d, - 0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14, - 0x15,0x15}, -{ 0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d, - 0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15, - 0x15,0x16}, -{ 0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e, - 0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15, - 0x16,0x16}, -{ 0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e, - 0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16, - 0x16,0x17}, -{ 0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f, - 0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16, - 0x17,0x17}, -{ 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f, - 0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17, - 0x17,0x18}, -{ 0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10, - 0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17, - 0x18,0x18}, -{ 0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10, - 0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18, - 0x18,0x19}, -{ 0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11, - 0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18, - 0x19,0x19}, -{ 0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11, - 0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19, - 0x19,0x1a}, -{ 0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12, - 0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19, - 0x1a,0x1a}, -{ 0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12, - 0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a, - 0x1a,0x1b}, -{ 0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13, - 0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a, - 0x1b,0x1b}, -{ 0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13, - 0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b, - 0x1b,0x1c}, -{ 0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14, - 0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b, - 0x1c,0x1c}, -{ 0x0d,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14, - 0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c, - 0x1c,0x1d}, -{ 0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15, - 0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c, - 0x1d,0x1d}, -{ 0x0e,0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15, - 0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c,0x1d, - 0x1d,0x1e}, -{ 0x0f,0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16, - 0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c,0x1d,0x1d, - 0x1e,0x1e}, -{ 0x0f,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16, - 0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b,0x1b,0x1c,0x1c,0x1d,0x1d,0x1e, - 0x1e,0x1f} -}; -uint8 sub32_32 [32][32] = { -{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, - 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, - 0x1e,0x1f}, -{ 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, - 0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c, - 0x1d,0x1e}, -{ 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c, - 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, - 0x1c,0x1d}, -{ 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, - 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a, - 0x1b,0x1c}, -{ 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a, - 0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, - 0x1a,0x1b}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, - 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, - 0x19,0x1a}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, - 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, - 0x18,0x19}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16, - 0x17,0x18}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06, - 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15, - 0x16,0x17}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05, - 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14, - 0x15,0x16}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04, - 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13, - 0x14,0x15}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03, - 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12, - 0x13,0x14}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, - 0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11, - 0x12,0x13}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, - 0x11,0x12}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, - 0x10,0x11}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, - 0x0f,0x10}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, - 0x0e,0x0f}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c, - 0x0d,0x0e}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, - 0x0c,0x0d}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a, - 0x0b,0x0c}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, - 0x0a,0x0b}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, - 0x09,0x0a}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, - 0x08,0x09}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06, - 0x07,0x08}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05, - 0x06,0x07}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04, - 0x05,0x06}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03, - 0x04,0x05}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, - 0x03,0x04}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0x02,0x03}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x02}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x01}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00} -}; - -uint8 sub32_32_half [32][32] = { -{ 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, - 0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e, - 0x0f,0x0f}, -{ 0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06, - 0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e, - 0x0e,0x0f}, -{ 0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06, - 0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d, - 0x0e,0x0e}, -{ 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05, - 0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d, - 0x0d,0x0e}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05, - 0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c, - 0x0d,0x0d}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04, - 0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c, - 0x0c,0x0d}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04, - 0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b, - 0x0c,0x0c}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03, - 0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b, - 0x0b,0x0c}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03, - 0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a, - 0x0b,0x0b}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02, - 0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09,0x0a, - 0x0a,0x0b}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02, - 0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09,0x09, - 0x0a,0x0a}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01, - 0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08,0x09, - 0x09,0x0a}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08,0x08, - 0x09,0x09}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07,0x08, - 0x08,0x09}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07, - 0x08,0x08}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, - 0x07,0x08}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06, - 0x07,0x07}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06, - 0x06,0x07}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05, - 0x06,0x06}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05, - 0x05,0x06}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04, - 0x05,0x05}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04, - 0x04,0x05}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03, - 0x04,0x04}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03, - 0x03,0x04}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x02, - 0x03,0x03}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02, - 0x02,0x03}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01, - 0x02,0x02}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0x01,0x02}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x01}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x01}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00} -}; -*/ - -uint8 mul_brightness [16][32] = { -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00}, -{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01, - 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02, - 0x02,0x02}, -{ 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04,0x04, - 0x04,0x04}, -{ 0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x03,0x03, - 0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x06,0x06, - 0x06,0x06}, -{ 0x00,0x00,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x04, - 0x04,0x04,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x08, - 0x08,0x08}, -{ 0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05, - 0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a, - 0x0a,0x0a}, -{ 0x00,0x00,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x06, - 0x06,0x06,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0c, - 0x0c,0x0c}, -{ 0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07, - 0x07,0x07,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e, - 0x0e,0x0e}, -{ 0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,0x07,0x07, - 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f, - 0x10,0x11}, -{ 0x00,0x01,0x01,0x02,0x02,0x03,0x04,0x04,0x05,0x05,0x06,0x07,0x07,0x08,0x08, - 0x09,0x0a,0x0a,0x0b,0x0b,0x0c,0x0d,0x0d,0x0e,0x0e,0x0f,0x10,0x10,0x11,0x11, - 0x12,0x13}, -{ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x05,0x06,0x07,0x07,0x08,0x09,0x09, - 0x0a,0x0b,0x0b,0x0c,0x0d,0x0d,0x0e,0x0f,0x0f,0x10,0x11,0x11,0x12,0x13,0x13, - 0x14,0x15}, -{ 0x00,0x01,0x01,0x02,0x03,0x04,0x04,0x05,0x06,0x07,0x07,0x08,0x09,0x0a,0x0a, - 0x0b,0x0c,0x0c,0x0d,0x0e,0x0f,0x0f,0x10,0x11,0x12,0x12,0x13,0x14,0x15,0x15, - 0x16,0x17}, -{ 0x00,0x01,0x02,0x02,0x03,0x04,0x05,0x06,0x06,0x07,0x08,0x09,0x0a,0x0a,0x0b, - 0x0c,0x0d,0x0e,0x0e,0x0f,0x10,0x11,0x12,0x12,0x13,0x14,0x15,0x16,0x16,0x17, - 0x18,0x19}, -{ 0x00,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0a,0x0b,0x0c, - 0x0d,0x0e,0x0f,0x10,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x17,0x18,0x19, - 0x1a,0x1b}, -{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d, - 0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b, - 0x1c,0x1d}, -{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, - 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, - 0x1e,0x1f} -}; - diff --git a/src/display.h b/src/display.h index 753652b..77ee89c 100644 --- a/src/display.h +++ b/src/display.h @@ -46,12 +46,10 @@ START_EXTERN_C void S9xSetPalette (); void S9xTextMode (); void S9xGraphicsMode (); -char *S9xParseArgs (char **argv, int argc); -void S9xParseArg (char **argv, int &index, int argc); void S9xExtraUsage (); uint32 S9xReadJoypad (int which1_0_to_4); -bool8_32 S9xReadMousePosition (int which1_0_to_1, int &x, int &y, uint32 &buttons); -bool8_32 S9xReadSuperScopePosition (int &x, int &y, uint32 &buttons); +bool8_32 S9xReadMousePosition (int which1_0_to_1, int* x, int* y, uint32* buttons); +bool8_32 S9xReadSuperScopePosition (int* x, int* y, uint32* buttons); void S9xUsage (); void S9xInitDisplay (int argc, char **argv); @@ -60,7 +58,6 @@ void S9xInitInputDevices (); void S9xSetTitle (const char *title); void S9xProcessEvents (bool8_32 block); void S9xPutImage (int width, int height); -void S9xParseDisplayArg (char **argv, int &index, int argc); void S9xToggleSoundChannel (int channel); void S9xSetInfoString (const char *string); int S9xMinCommandLineArgs (); diff --git a/src/dma.c b/src/dma.c new file mode 100644 index 0000000..7e6e941 --- /dev/null +++ b/src/dma.c @@ -0,0 +1,875 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include "snes9x.h" + +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" +#include "missing.h" +#include "dma.h" +#include "apu.h" +#include "gfx.h" +#ifdef USE_SA1 +#include "sa1.h" +#endif + +//SDD1 +#include "sdd1emu.h" +uint8 buffer[0x10000]; +//SDD1// + +extern int HDMA_ModeByteCounts [8]; +extern uint8 *HDMAMemPointers [8]; +extern uint8 *HDMABasePointers [8]; + +static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2) +{ + return (*(uint32 *) p1 - *(uint32 *) p2); +} + +/**********************************************************************************************/ +/* S9xDoDMA() */ +/* This function preforms the general dma transfer */ +/**********************************************************************************************/ +void S9xDoDMA (uint8 Channel) +{ + uint8 Work; + + if (Channel > 7 || CPU.InDMA) + return; + + CPU.InDMA = TRUE; + bool8 in_sa1_dma = FALSE; + uint8 *in_sdd1_dma = NULL; + SDMA *d = &DMA[Channel]; + + int count = d->TransferBytes; + + if (count == 0) + count = 0x10000; + + int inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); + + if((d->ABank==0x7E||d->ABank==0x7F)&&d->BAddress==0x80) + { + d->AAddress+= d->TransferBytes; + goto update_address; + } + switch (d->BAddress) + { + case 0x18: + case 0x19: + if (IPPU.RenderThisFrame) +#ifdef __DEBUG__ + printf("FLUSH_REDRAW by DMA BAddress %x", d->BAddress); +#endif + FLUSH_REDRAW (); + + break; + } + + if (Settings.SDD1) + { + if (d->AAddressFixed && Memory.FillRAM [0x4801] > 0) + { + // Hacky support for pre-decompressed S-DD1 data + inc = !d->AAddressDecrement ? 1 : -1; + uint32 address = (((d->ABank << 16) | d->AAddress) & 0xfffff) << 4; + + address |= Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)]; + if(Settings.SDD1Pack) + { + uint8* in_ptr=GetBasePointer(((d->ABank << 16) | d->AAddress)); + in_ptr+=d->AAddress; + + SDD1_decompress(buffer,in_ptr,d->TransferBytes); + in_sdd1_dma=buffer; + } + else + { + #if 1 + void *ptr = bsearch (&address, Memory.SDD1Index, + Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); + if (ptr) + in_sdd1_dma = *(uint32 *) ((uint8 *) ptr + 4) + Memory.SDD1Data; + #else + uint8 *ptr = Memory.SDD1Index; + + for (uint32 e = 0; e < Memory.SDD1Entries; e++, ptr += 12) + { + if (address == *(uint32 *) ptr) + { + in_sdd1_dma = *(uint32 *) (ptr + 4) + Memory.SDD1Data; + break; + } + } + #endif + +/* if (!in_sdd1_dma) + { + // No matching decompressed data found. Must be some new + // graphics not encountered before. Log it if it hasn't been + // already. + uint8 *p = Memory.SDD1LoggedData; + bool8 found = FALSE; + uint8 SDD1Bank = Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)] | 0xf0; + + for (uint32 i = 0; i < Memory.SDD1LoggedDataCount; i++, p += 8) + { + if (*p == d->ABank || + *(p + 1) == (d->AAddress >> 8) && + *(p + 2) == (d->AAddress & 0xff) && + *(p + 3) == (count >> 8) && + *(p + 4) == (count & 0xff) && + *(p + 7) == SDD1Bank) + { + found = TRUE; + break; + } + } + if (!found && Memory.SDD1LoggedDataCount < MEMMAP_MAX_SDD1_LOGGED_ENTRIES) + { + *p = d->ABank; + *(p + 1) = d->AAddress >> 8; + *(p + 2) = d->AAddress & 0xff; + *(p + 3) = count >> 8; + *(p + 4) = count & 0xff; + *(p + 7) = SDD1Bank; + Memory.SDD1LoggedDataCount += 1; + } + } +*/ } + } + + Memory.FillRAM [0x4801] = 0; + } + +#ifdef USE_SA1 + if (d->BAddress == 0x18 && SA1.in_char_dma && (d->ABank & 0xf0) == 0x40) +#else + if (d->BAddress == 0x18 && (d->ABank & 0xf0) == 0x40) +#endif + { + // Perform packed bitmap to PPU character format conversion on the + // data before transmitting it to V-RAM via-DMA. + int num_chars = 1 << ((Memory.FillRAM [0x2231] >> 2) & 7); + int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : + (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; + + int bytes_per_char = 8 * depth; + int bytes_per_line = depth * num_chars; + int char_line_bytes = bytes_per_char * num_chars; + uint32 addr = (d->AAddress / char_line_bytes) * char_line_bytes; + uint8 *base = GetBasePointer ((d->ABank << 16) + addr) + addr; + uint8 *buffer = &Memory.ROM [MAX_ROM_SIZE - 0x10000]; + uint8 *p = buffer; + uint32 inc = char_line_bytes - (d->AAddress % char_line_bytes); + uint32 char_count = inc / bytes_per_char; + + in_sa1_dma = TRUE; + +//printf ("%08x,", base); fflush (stdout); +//printf ("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n", +//depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes); + int i; + + switch (depth) + { + case 2: + for (i = 0; i < count; i += inc, base += char_line_bytes, + inc = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 2; + for (uint32 j = 0; j < char_count && p - buffer < count; + j++, line += 2) + { + uint8 *q = line; + for (int l = 0; l < 8; l++, q += bytes_per_line) + { + for (int b = 0; b < 2; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1); + } + p += 2; + } + } + } + break; + case 4: + for (i = 0; i < count; i += inc, base += char_line_bytes, + inc = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 4; + for (uint32 j = 0; j < char_count && p - buffer < count; + j++, line += 4) + { + uint8 *q = line; + int l; + for (l = 0; l < 8; l++, q += bytes_per_line) + { + int b; + for (b = 0; b < 4; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1); + } + p += 2; + } + p += 32 - 16; + } + } + break; + case 8: + for (i = 0; i < count; i += inc, base += char_line_bytes, + inc = char_line_bytes, char_count = num_chars) + { + uint8 *line = base + (num_chars - char_count) * 8; + for (uint32 j = 0; j < char_count && p - buffer < count; + j++, line += 8) + { + uint8 *q = line; + for (int l = 0; l < 8; l++, q += bytes_per_line) + { + for (int b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); + *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); + *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); + *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); + } + p += 2; + } + p += 64 - 16; + } + } + break; + } + + } + + if (!d->TransferDirection) + { +#ifdef VAR_CYCLES + //reflects extra cycle used by DMA + CPU.Cycles += 8 * (count+1); +#else + //needs fixing for the extra DMA cycle + CPU.Cycles += (1+count) + ((1+count) >> 2); +#endif + uint8 *base = GetBasePointer ((d->ABank << 16) + d->AAddress); + uint16 p = d->AAddress; + + if (!base) + base = Memory.ROM; + + if (in_sa1_dma) + { + base = &Memory.ROM [MAX_ROM_SIZE - 0x10000]; + p = 0; + } + + if (in_sdd1_dma) + { + base = in_sdd1_dma; + p = 0; + } + + if (inc > 0) + d->AAddress += count; + else + if (inc < 0) + d->AAddress -= count; + + if (d->TransferMode == 0 || d->TransferMode == 2) + { + switch (d->BAddress) + { + case 0x04: + do + { + Work = *(base + p); + REGISTER_2104(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + break; + case 0x18: + IPPU.FirstVRAMRead = TRUE; + if (!PPU.VMA.FullGraphicCount) + { + do + { + Work = *(base + p); + REGISTER_2118_linear(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2118_tile(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + } + break; + case 0x19: + IPPU.FirstVRAMRead = TRUE; + if (!PPU.VMA.FullGraphicCount) + { + do + { + Work = *(base + p); + REGISTER_2119_linear(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2119_tile(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + } + break; + case 0x22: + do + { + Work = *(base + p); + REGISTER_2122(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + break; + case 0x80: + do + { + Work = *(base + p); + REGISTER_2180(Work); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + break; + default: + do + { + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + CHECK_SOUND(); + } while (--count > 0); + break; + } + } + else + if (d->TransferMode == 1 || d->TransferMode == 5) + { + if (d->BAddress == 0x18) + { + // Write to V-RAM + IPPU.FirstVRAMRead = TRUE; + if (!PPU.VMA.FullGraphicCount) + { + while (count > 1) + { + Work = *(base + p); + REGISTER_2118_linear(Work); + p += inc; + + Work = *(base + p); + REGISTER_2119_linear(Work); + p += inc; + CHECK_SOUND(); + count -= 2; + } + if (count == 1) + { + Work = *(base + p); + REGISTER_2118_linear(Work); + p += inc; + } + } + else + { + while (count > 1) + { + Work = *(base + p); + REGISTER_2118_tile(Work); + p += inc; + + Work = *(base + p); + REGISTER_2119_tile(Work); + p += inc; + CHECK_SOUND(); + count -= 2; + } + if (count == 1) + { + Work = *(base + p); + REGISTER_2118_tile(Work); + p += inc; + } + } + } + else + { + // DMA mode 1 general case + while (count > 1) + { + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + + Work = *(base + p); + S9xSetPPU (Work, 0x2101 + d->BAddress); + p += inc; + CHECK_SOUND(); + count -= 2; + } + if (count == 1) + { + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + } + } + } + else + if (d->TransferMode == 3) + { + do + { + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + if (count <= 1) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + if (count <= 2) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2101 + d->BAddress); + p += inc; + if (count <= 3) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2101 + d->BAddress); + p += inc; + CHECK_SOUND(); + count -= 4; + } while (count > 0); + } + else + if (d->TransferMode == 4) + { + do + { + Work = *(base + p); + S9xSetPPU (Work, 0x2100 + d->BAddress); + p += inc; + if (count <= 1) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2101 + d->BAddress); + p += inc; + if (count <= 2) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2102 + d->BAddress); + p += inc; + if (count <= 3) + break; + + Work = *(base + p); + S9xSetPPU (Work, 0x2103 + d->BAddress); + p += inc; + CHECK_SOUND(); + count -= 4; + } while (count > 0); + } + } + else + { + do + { + switch (d->TransferMode) + { + case 0: + case 2: +#ifndef VAR_CYCLES + CPU.Cycles += 1; +#endif + Work = S9xGetPPU (0x2100 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + --count; + break; + + case 1: + case 5: +#ifndef VAR_CYCLES + CPU.Cycles += 3; +#endif + Work = S9xGetPPU (0x2100 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2101 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + count--; + break; + + case 3: +#ifndef VAR_CYCLES + CPU.Cycles += 6; +#endif + Work = S9xGetPPU (0x2100 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2100 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2101 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2101 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + count--; + break; + + case 4: +#ifndef VAR_CYCLES + CPU.Cycles += 6; +#endif + Work = S9xGetPPU (0x2100 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2101 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2102 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + if (!--count) + break; + + Work = S9xGetPPU (0x2103 + d->BAddress); + S9xSetByte (Work, (d->ABank << 16) + d->AAddress); + d->AAddress += inc; + count--; + break; + + default: + count = 0; + break; + } + CHECK_SOUND(); + } while (count); + } + +//#ifdef SPC700_C +#ifdef SPC700_SHUTDOWN + CPU.APU_APUExecuting = Settings.APUEnabled; +#endif + asm_APU_EXECUTE(1); // execute but only in normal mode +//#endif + while (CPU.Cycles > CPU.NextEvent) + S9xDoHBlankProcessing (); + +update_address: + // Super Punch-Out requires that the A-BUS address be updated after the + // DMA transfer. + Memory.FillRAM[0x4302 + (Channel << 4)] = (uint8) d->AAddress; + Memory.FillRAM[0x4303 + (Channel << 4)] = d->AAddress >> 8; + + // Secret of the Mana requires that the DMA bytes transfer count be set to + // zero when DMA has completed. + Memory.FillRAM [0x4305 + (Channel << 4)] = 0; + Memory.FillRAM [0x4306 + (Channel << 4)] = 0; + + DMA[Channel].IndirectAddress = 0; + d->TransferBytes = 0; + + CPU.InDMA = FALSE; +} + +void S9xStartHDMA () +{ + //if (Settings.DisableHDMA) + //IPPU.HDMA = 0; + //else + missing.hdma_this_frame = IPPU.HDMA = Memory.FillRAM [0x420c]; + + IPPU.HDMAStarted = TRUE; + + for (uint8 i = 0; i < 8; i++) + { + if (IPPU.HDMA & (1 << i)) + { + DMA [i].LineCount = 0; + DMA [i].FirstLine = TRUE; + DMA [i].Address = DMA [i].AAddress; + } + HDMAMemPointers [i] = NULL; + } +} + +uint8 S9xDoHDMA (uint8 byte) +{ + SDMA *p = &DMA [0]; + + int d = 0; + + for (uint8 mask = 1; mask; mask <<= 1, p++, d++) + { + if (byte & mask) + { + if (!p->LineCount) + { + uint8 line = S9xGetByte ((p->ABank << 16) + p->Address); + if (line == 0x80) + { + p->Repeat = TRUE; + p->LineCount = 128; + } + else + { + p->Repeat = !(line & 0x80); + p->LineCount = line & 0x7f; + } + + // Disable H-DMA'ing into V-RAM (register 2118) for Hook + if (!p->LineCount || p->BAddress == 0x18) + { + byte &= ~mask; + p->IndirectAddress += HDMAMemPointers [d] - HDMABasePointers [d]; + Memory.FillRAM [0x4305 + (d << 4)] = (uint8) p->IndirectAddress; + Memory.FillRAM [0x4306 + (d << 4)] = p->IndirectAddress >> 8; + continue; + } + + p->Address++; + p->FirstLine = 1; + if (p->HDMAIndirectAddressing) + { + p->IndirectBank = Memory.FillRAM [0x4307 + (d << 4)]; + p->IndirectAddress = S9xGetWord ((p->ABank << 16) + p->Address); + p->Address += 2; + } + else + { + p->IndirectBank = p->ABank; + p->IndirectAddress = p->Address; + } + HDMABasePointers [d] = HDMAMemPointers [d] = + S9xGetMemPointer ((p->IndirectBank << 16) + p->IndirectAddress); + } + else + { + + if (!HDMAMemPointers [d]) + { + if (!p->HDMAIndirectAddressing) + { + p->IndirectBank = p->ABank; + p->IndirectAddress = p->Address; + } + + if (!(HDMABasePointers [d] = HDMAMemPointers [d] = + S9xGetMemPointer ((p->IndirectBank << 16) + p->IndirectAddress))) + { + byte &= ~mask; + continue; + } + // Uncommenting the following line breaks Punchout - it starts + // H-DMA during the frame. + //p->FirstLine = TRUE; + } + } + if (p->Repeat && !p->FirstLine) + { + p->LineCount--; + continue; + } + switch (p->TransferMode) + { + case 0: +#ifndef VAR_CYCLES + CPU.Cycles += 1; +#else + CPU.Cycles += 8; +#endif + S9xSetPPU (*HDMAMemPointers [d]++, 0x2100 + p->BAddress); + break; + case 1: + case 5: +#ifndef VAR_CYCLES + CPU.Cycles += 3; +#else + CPU.Cycles += 16; +#endif + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); + HDMAMemPointers [d] += 2; + break; + case 2: + case 6: +#ifndef VAR_CYCLES + CPU.Cycles += 3; +#else + CPU.Cycles += 16; +#endif + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2100 + p->BAddress); + HDMAMemPointers [d] += 2; + break; + case 3: + case 7: +#ifndef VAR_CYCLES + CPU.Cycles += 6; +#else + CPU.Cycles += 32; +#endif + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 2), 0x2101 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 3), 0x2101 + p->BAddress); + HDMAMemPointers [d] += 4; + break; + case 4: +#ifndef VAR_CYCLES + CPU.Cycles += 6; +#else + CPU.Cycles += 32; +#endif + S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 2), 0x2102 + p->BAddress); + S9xSetPPU (*(HDMAMemPointers [d] + 3), 0x2103 + p->BAddress); + HDMAMemPointers [d] += 4; + break; + } + if (!p->HDMAIndirectAddressing) + p->Address += HDMA_ModeByteCounts [p->TransferMode]; + p->FirstLine = FALSE; + p->LineCount--; + } + } + return (byte); +} + +void S9xResetDMA () +{ + int d; + for (d = 0; d < 8; d++) + { + DMA [d].TransferDirection = FALSE; + DMA [d].HDMAIndirectAddressing = FALSE; + DMA [d].AAddressFixed = TRUE; + DMA [d].AAddressDecrement = FALSE; + DMA [d].TransferMode = 0xff; + DMA [d].ABank = 0xff; + DMA [d].AAddress = 0xffff; + DMA [d].Address = 0xffff; + DMA [d].BAddress = 0xff; + DMA [d].TransferBytes = 0xffff; + } + for (int c = 0x4300; c < 0x4380; c += 0x10) + { + for (d = c; d < c + 12; d++) + Memory.FillRAM [d] = 0xff; + + Memory.FillRAM [c + 0xf] = 0xff; + } +} diff --git a/src/dma.cpp b/src/dma.cpp deleted file mode 100644 index 61c4d4e..0000000 --- a/src/dma.cpp +++ /dev/null @@ -1,873 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include "snes9x.h" - -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "missing.h" -#include "dma.h" -#include "apu.h" -#include "gfx.h" -#ifdef USE_SA1 -#include "sa1.h" -#endif - -//SDD1 -#include "sdd1emu.h" -uint8 buffer[0x10000]; -//SDD1// - -extern int HDMA_ModeByteCounts [8]; -extern uint8 *HDMAMemPointers [8]; -extern uint8 *HDMABasePointers [8]; - -static int S9xCompareSDD1IndexEntries (const void *p1, const void *p2) -{ - return (*(uint32 *) p1 - *(uint32 *) p2); -} - -/**********************************************************************************************/ -/* S9xDoDMA() */ -/* This function preforms the general dma transfer */ -/**********************************************************************************************/ -void S9xDoDMA (uint8 Channel) -{ - uint8 Work; - - if (Channel > 7 || CPU.InDMA) - return; - - CPU.InDMA = TRUE; - bool8 in_sa1_dma = FALSE; - uint8 *in_sdd1_dma = NULL; - SDMA *d = &DMA[Channel]; - - int count = d->TransferBytes; - - if (count == 0) - count = 0x10000; - - int inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); - - if((d->ABank==0x7E||d->ABank==0x7F)&&d->BAddress==0x80) - { - d->AAddress+= d->TransferBytes; - goto update_address; - } - switch (d->BAddress) - { - case 0x18: - case 0x19: - if (IPPU.RenderThisFrame) -#ifdef __DEBUG__ - printf("FLUSH_REDRAW by DMA BAddress %x", d->BAddress); -#endif - FLUSH_REDRAW (); - - break; - } - - if (Settings.SDD1) - { - if (d->AAddressFixed && Memory.FillRAM [0x4801] > 0) - { - // Hacky support for pre-decompressed S-DD1 data - inc = !d->AAddressDecrement ? 1 : -1; - uint32 address = (((d->ABank << 16) | d->AAddress) & 0xfffff) << 4; - - address |= Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)]; - if(Settings.SDD1Pack) - { - uint8* in_ptr=GetBasePointer(((d->ABank << 16) | d->AAddress)); - in_ptr+=d->AAddress; - - SDD1_decompress(buffer,in_ptr,d->TransferBytes); - in_sdd1_dma=buffer; - } - else - { - #if 1 - void *ptr = bsearch (&address, Memory.SDD1Index, - Memory.SDD1Entries, 12, S9xCompareSDD1IndexEntries); - if (ptr) - in_sdd1_dma = *(uint32 *) ((uint8 *) ptr + 4) + Memory.SDD1Data; - #else - uint8 *ptr = Memory.SDD1Index; - - for (uint32 e = 0; e < Memory.SDD1Entries; e++, ptr += 12) - { - if (address == *(uint32 *) ptr) - { - in_sdd1_dma = *(uint32 *) (ptr + 4) + Memory.SDD1Data; - break; - } - } - #endif - -/* if (!in_sdd1_dma) - { - // No matching decompressed data found. Must be some new - // graphics not encountered before. Log it if it hasn't been - // already. - uint8 *p = Memory.SDD1LoggedData; - bool8 found = FALSE; - uint8 SDD1Bank = Memory.FillRAM [0x4804 + ((d->ABank - 0xc0) >> 4)] | 0xf0; - - for (uint32 i = 0; i < Memory.SDD1LoggedDataCount; i++, p += 8) - { - if (*p == d->ABank || - *(p + 1) == (d->AAddress >> 8) && - *(p + 2) == (d->AAddress & 0xff) && - *(p + 3) == (count >> 8) && - *(p + 4) == (count & 0xff) && - *(p + 7) == SDD1Bank) - { - found = TRUE; - break; - } - } - if (!found && Memory.SDD1LoggedDataCount < MEMMAP_MAX_SDD1_LOGGED_ENTRIES) - { - *p = d->ABank; - *(p + 1) = d->AAddress >> 8; - *(p + 2) = d->AAddress & 0xff; - *(p + 3) = count >> 8; - *(p + 4) = count & 0xff; - *(p + 7) = SDD1Bank; - Memory.SDD1LoggedDataCount += 1; - } - } -*/ } - } - - Memory.FillRAM [0x4801] = 0; - } - -#ifdef USE_SA1 - if (d->BAddress == 0x18 && SA1.in_char_dma && (d->ABank & 0xf0) == 0x40) -#else - if (d->BAddress == 0x18 && (d->ABank & 0xf0) == 0x40) -#endif - { - // Perform packed bitmap to PPU character format conversion on the - // data before transmitting it to V-RAM via-DMA. - int num_chars = 1 << ((Memory.FillRAM [0x2231] >> 2) & 7); - int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : - (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; - - int bytes_per_char = 8 * depth; - int bytes_per_line = depth * num_chars; - int char_line_bytes = bytes_per_char * num_chars; - uint32 addr = (d->AAddress / char_line_bytes) * char_line_bytes; - uint8 *base = GetBasePointer ((d->ABank << 16) + addr) + addr; - uint8 *buffer = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000]; - uint8 *p = buffer; - uint32 inc = char_line_bytes - (d->AAddress % char_line_bytes); - uint32 char_count = inc / bytes_per_char; - - in_sa1_dma = TRUE; - -//printf ("%08x,", base); fflush (stdout); -//printf ("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n", -//depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes); - int i; - - switch (depth) - { - case 2: - for (i = 0; i < count; i += inc, base += char_line_bytes, - inc = char_line_bytes, char_count = num_chars) - { - uint8 *line = base + (num_chars - char_count) * 2; - for (uint32 j = 0; j < char_count && p - buffer < count; - j++, line += 2) - { - uint8 *q = line; - for (int l = 0; l < 8; l++, q += bytes_per_line) - { - for (int b = 0; b < 2; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1); - } - p += 2; - } - } - } - break; - case 4: - for (i = 0; i < count; i += inc, base += char_line_bytes, - inc = char_line_bytes, char_count = num_chars) - { - uint8 *line = base + (num_chars - char_count) * 4; - for (uint32 j = 0; j < char_count && p - buffer < count; - j++, line += 4) - { - uint8 *q = line; - for (int l = 0; l < 8; l++, q += bytes_per_line) - { - for (int b = 0; b < 4; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); - *(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1); - } - p += 2; - } - p += 32 - 16; - } - } - break; - case 8: - for (i = 0; i < count; i += inc, base += char_line_bytes, - inc = char_line_bytes, char_count = num_chars) - { - uint8 *line = base + (num_chars - char_count) * 8; - for (uint32 j = 0; j < char_count && p - buffer < count; - j++, line += 8) - { - uint8 *q = line; - for (int l = 0; l < 8; l++, q += bytes_per_line) - { - for (int b = 0; b < 8; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); - *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); - *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); - *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); - *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); - } - p += 2; - } - p += 64 - 16; - } - } - break; - } - - } - - if (!d->TransferDirection) - { -#ifdef VAR_CYCLES - //reflects extra cycle used by DMA - CPU.Cycles += 8 * (count+1); -#else - //needs fixing for the extra DMA cycle - CPU.Cycles += (1+count) + ((1+count) >> 2); -#endif - uint8 *base = GetBasePointer ((d->ABank << 16) + d->AAddress); - uint16 p = d->AAddress; - - if (!base) - base = Memory.ROM; - - if (in_sa1_dma) - { - base = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000]; - p = 0; - } - - if (in_sdd1_dma) - { - base = in_sdd1_dma; - p = 0; - } - - if (inc > 0) - d->AAddress += count; - else - if (inc < 0) - d->AAddress -= count; - - if (d->TransferMode == 0 || d->TransferMode == 2) - { - switch (d->BAddress) - { - case 0x04: - do - { - Work = *(base + p); - REGISTER_2104(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - case 0x18: - IPPU.FirstVRAMRead = TRUE; - if (!PPU.VMA.FullGraphicCount) - { - do - { - Work = *(base + p); - REGISTER_2118_linear(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - else - { - do - { - Work = *(base + p); - REGISTER_2118_tile(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - break; - case 0x19: - IPPU.FirstVRAMRead = TRUE; - if (!PPU.VMA.FullGraphicCount) - { - do - { - Work = *(base + p); - REGISTER_2119_linear(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - else - { - do - { - Work = *(base + p); - REGISTER_2119_tile(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - } - break; - case 0x22: - do - { - Work = *(base + p); - REGISTER_2122(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - case 0x80: - do - { - Work = *(base + p); - REGISTER_2180(Work); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - default: - do - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - CHECK_SOUND(); - } while (--count > 0); - break; - } - } - else - if (d->TransferMode == 1 || d->TransferMode == 5) - { - if (d->BAddress == 0x18) - { - // Write to V-RAM - IPPU.FirstVRAMRead = TRUE; - if (!PPU.VMA.FullGraphicCount) - { - while (count > 1) - { - Work = *(base + p); - REGISTER_2118_linear(Work); - p += inc; - - Work = *(base + p); - REGISTER_2119_linear(Work); - p += inc; - CHECK_SOUND(); - count -= 2; - } - if (count == 1) - { - Work = *(base + p); - REGISTER_2118_linear(Work); - p += inc; - } - } - else - { - while (count > 1) - { - Work = *(base + p); - REGISTER_2118_tile(Work); - p += inc; - - Work = *(base + p); - REGISTER_2119_tile(Work); - p += inc; - CHECK_SOUND(); - count -= 2; - } - if (count == 1) - { - Work = *(base + p); - REGISTER_2118_tile(Work); - p += inc; - } - } - } - else - { - // DMA mode 1 general case - while (count > 1) - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - CHECK_SOUND(); - count -= 2; - } - if (count == 1) - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - } - } - } - else - if (d->TransferMode == 3) - { - do - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (count <= 1) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (count <= 2) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - if (count <= 3) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - CHECK_SOUND(); - count -= 4; - } while (count > 0); - } - else - if (d->TransferMode == 4) - { - do - { - Work = *(base + p); - S9xSetPPU (Work, 0x2100 + d->BAddress); - p += inc; - if (count <= 1) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2101 + d->BAddress); - p += inc; - if (count <= 2) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2102 + d->BAddress); - p += inc; - if (count <= 3) - break; - - Work = *(base + p); - S9xSetPPU (Work, 0x2103 + d->BAddress); - p += inc; - CHECK_SOUND(); - count -= 4; - } while (count > 0); - } - } - else - { - do - { - switch (d->TransferMode) - { - case 0: - case 2: -#ifndef VAR_CYCLES - CPU.Cycles += 1; -#endif - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - --count; - break; - - case 1: - case 5: -#ifndef VAR_CYCLES - CPU.Cycles += 3; -#endif - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; - - case 3: -#ifndef VAR_CYCLES - CPU.Cycles += 6; -#endif - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; - - case 4: -#ifndef VAR_CYCLES - CPU.Cycles += 6; -#endif - Work = S9xGetPPU (0x2100 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2101 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2102 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - if (!--count) - break; - - Work = S9xGetPPU (0x2103 + d->BAddress); - S9xSetByte (Work, (d->ABank << 16) + d->AAddress); - d->AAddress += inc; - count--; - break; - - default: - count = 0; - break; - } - CHECK_SOUND(); - } while (count); - } - -//#ifdef SPC700_C -#ifdef SPC700_SHUTDOWN - CPU.APU_APUExecuting = Settings.APUEnabled; -#endif - asm_APU_EXECUTE(1); // execute but only in normal mode -//#endif - while (CPU.Cycles > CPU.NextEvent) - S9xDoHBlankProcessing (); - -update_address: - // Super Punch-Out requires that the A-BUS address be updated after the - // DMA transfer. - Memory.FillRAM[0x4302 + (Channel << 4)] = (uint8) d->AAddress; - Memory.FillRAM[0x4303 + (Channel << 4)] = d->AAddress >> 8; - - // Secret of the Mana requires that the DMA bytes transfer count be set to - // zero when DMA has completed. - Memory.FillRAM [0x4305 + (Channel << 4)] = 0; - Memory.FillRAM [0x4306 + (Channel << 4)] = 0; - - DMA[Channel].IndirectAddress = 0; - d->TransferBytes = 0; - - CPU.InDMA = FALSE; -} - -void S9xStartHDMA () -{ - //if (Settings.DisableHDMA) - //IPPU.HDMA = 0; - //else - missing.hdma_this_frame = IPPU.HDMA = Memory.FillRAM [0x420c]; - - IPPU.HDMAStarted = TRUE; - - for (uint8 i = 0; i < 8; i++) - { - if (IPPU.HDMA & (1 << i)) - { - DMA [i].LineCount = 0; - DMA [i].FirstLine = TRUE; - DMA [i].Address = DMA [i].AAddress; - } - HDMAMemPointers [i] = NULL; - } -} - -uint8 S9xDoHDMA (uint8 byte) -{ - struct SDMA *p = &DMA [0]; - - int d = 0; - - for (uint8 mask = 1; mask; mask <<= 1, p++, d++) - { - if (byte & mask) - { - if (!p->LineCount) - { - uint8 line = S9xGetByte ((p->ABank << 16) + p->Address); - if (line == 0x80) - { - p->Repeat = TRUE; - p->LineCount = 128; - } - else - { - p->Repeat = !(line & 0x80); - p->LineCount = line & 0x7f; - } - - // Disable H-DMA'ing into V-RAM (register 2118) for Hook - if (!p->LineCount || p->BAddress == 0x18) - { - byte &= ~mask; - p->IndirectAddress += HDMAMemPointers [d] - HDMABasePointers [d]; - Memory.FillRAM [0x4305 + (d << 4)] = (uint8) p->IndirectAddress; - Memory.FillRAM [0x4306 + (d << 4)] = p->IndirectAddress >> 8; - continue; - } - - p->Address++; - p->FirstLine = 1; - if (p->HDMAIndirectAddressing) - { - p->IndirectBank = Memory.FillRAM [0x4307 + (d << 4)]; - p->IndirectAddress = S9xGetWord ((p->ABank << 16) + p->Address); - p->Address += 2; - } - else - { - p->IndirectBank = p->ABank; - p->IndirectAddress = p->Address; - } - HDMABasePointers [d] = HDMAMemPointers [d] = - S9xGetMemPointer ((p->IndirectBank << 16) + p->IndirectAddress); - } - else - { - - if (!HDMAMemPointers [d]) - { - if (!p->HDMAIndirectAddressing) - { - p->IndirectBank = p->ABank; - p->IndirectAddress = p->Address; - } - - if (!(HDMABasePointers [d] = HDMAMemPointers [d] = - S9xGetMemPointer ((p->IndirectBank << 16) + p->IndirectAddress))) - { - byte &= ~mask; - continue; - } - // Uncommenting the following line breaks Punchout - it starts - // H-DMA during the frame. - //p->FirstLine = TRUE; - } - } - if (p->Repeat && !p->FirstLine) - { - p->LineCount--; - continue; - } - switch (p->TransferMode) - { - case 0: -#ifndef VAR_CYCLES - CPU.Cycles += 1; -#else - CPU.Cycles += 8; -#endif - S9xSetPPU (*HDMAMemPointers [d]++, 0x2100 + p->BAddress); - break; - case 1: - case 5: -#ifndef VAR_CYCLES - CPU.Cycles += 3; -#else - CPU.Cycles += 16; -#endif - S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); - HDMAMemPointers [d] += 2; - break; - case 2: - case 6: -#ifndef VAR_CYCLES - CPU.Cycles += 3; -#else - CPU.Cycles += 16; -#endif - S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2100 + p->BAddress); - HDMAMemPointers [d] += 2; - break; - case 3: - case 7: -#ifndef VAR_CYCLES - CPU.Cycles += 6; -#else - CPU.Cycles += 32; -#endif - S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2100 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 2), 0x2101 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 3), 0x2101 + p->BAddress); - HDMAMemPointers [d] += 4; - break; - case 4: -#ifndef VAR_CYCLES - CPU.Cycles += 6; -#else - CPU.Cycles += 32; -#endif - S9xSetPPU (*(HDMAMemPointers [d] + 0), 0x2100 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 1), 0x2101 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 2), 0x2102 + p->BAddress); - S9xSetPPU (*(HDMAMemPointers [d] + 3), 0x2103 + p->BAddress); - HDMAMemPointers [d] += 4; - break; - } - if (!p->HDMAIndirectAddressing) - p->Address += HDMA_ModeByteCounts [p->TransferMode]; - p->FirstLine = FALSE; - p->LineCount--; - } - } - return (byte); -} - -void S9xResetDMA () -{ - int d; - for (d = 0; d < 8; d++) - { - DMA [d].TransferDirection = FALSE; - DMA [d].HDMAIndirectAddressing = FALSE; - DMA [d].AAddressFixed = TRUE; - DMA [d].AAddressDecrement = FALSE; - DMA [d].TransferMode = 0xff; - DMA [d].ABank = 0xff; - DMA [d].AAddress = 0xffff; - DMA [d].Address = 0xffff; - DMA [d].BAddress = 0xff; - DMA [d].TransferBytes = 0xffff; - } - for (int c = 0x4300; c < 0x4380; c += 0x10) - { - for (d = c; d < c + 12; d++) - Memory.FillRAM [d] = 0xff; - - Memory.FillRAM [c + 0xf] = 0xff; - } -} diff --git a/src/dsp1.c b/src/dsp1.c new file mode 100644 index 0000000..f2ea308 --- /dev/null +++ b/src/dsp1.c @@ -0,0 +1,1195 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and distribute Snes9x in both binary and + source form, for non-commercial purposes, is hereby granted without fee, + providing that this license information and copyright notice appear with + all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes + charging money for Snes9x or software derived from Snes9x. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +*******************************************************************************/ +#include "snes9x.h" +#include "dsp1.h" +#include "missing.h" +#include "memmap.h" +#include + +#include "dsp1emu.c" +#include "dsp2emu.c" +//#include "dsp3emu.cpp" + +void (*SetDSP)(uint8, uint16)=&DSP1SetByte; +uint8 (*GetDSP)(uint16)=&DSP1GetByte; + +void S9xInitDSP1 () +{ + static bool8 init = FALSE; + + if (!init) + { + InitDSP (); + init = TRUE; + } +} + +void S9xResetDSP1 () +{ + S9xInitDSP1 (); + + DSP1.waiting4command = TRUE; + DSP1.in_count = 0; + DSP1.out_count = 0; + DSP1.in_index = 0; + DSP1.out_index = 0; + DSP1.first_parameter = TRUE; +} + +uint8 S9xGetDSP (uint16 address) +{ + uint8 t; + +#ifdef DEBUGGER + if (Settings.TraceDSP) + { + sprintf (String, "DSP read: 0x%04X", address); + S9xMessage (S9X_TRACE, S9X_TRACE_DSP1, String); + } +#endif + + t=(*GetDSP)(address); + //DSP1GetByte(address); + return (t); +} + +void S9xSetDSP (uint8 byte, uint16 address) +{ +#ifdef DEBUGGER + missing.unknowndsp_write = address; + if (Settings.TraceDSP) + { + sprintf (String, "DSP write: 0x%04X=0x%02X", address, byte); + S9xMessage (S9X_TRACE, S9X_TRACE_DSP1, String); + } +#endif + (*SetDSP)(byte, address); + //DSP1SetByte(byte, address); +} + +void DSP1SetByte(uint8 byte, uint16 address) +{ + if( (address & 0xf000) == 0x6000 || (address & 0x7fff) < 0x4000 ) + { +// if ((address & 1) == 0) +// { + if((DSP1.command==0x0A||DSP1.command==0x1A)&&DSP1.out_count!=0) + { + DSP1.out_count--; + DSP1.out_index++; + return; + } + else if (DSP1.waiting4command) + { + DSP1.command = byte; + DSP1.in_index = 0; + DSP1.waiting4command = FALSE; + DSP1.first_parameter = TRUE; +// printf("Op%02X\n",byte); + // Mario Kart uses 0x00, 0x02, 0x06, 0x0c, 0x28, 0x0a + switch (byte) + { + case 0x00: DSP1.in_count = 2; break; + case 0x30: + case 0x10: DSP1.in_count = 2; break; + case 0x20: DSP1.in_count = 2; break; + case 0x24: + case 0x04: DSP1.in_count = 2; break; + case 0x08: DSP1.in_count = 3; break; + case 0x18: DSP1.in_count = 4; break; + case 0x28: DSP1.in_count = 3; break; + case 0x38: DSP1.in_count = 4; break; + case 0x2c: + case 0x0c: DSP1.in_count = 3; break; + case 0x3c: + case 0x1c: DSP1.in_count = 6; break; + case 0x32: + case 0x22: + case 0x12: + case 0x02: DSP1.in_count = 7; break; + case 0x0a: DSP1.in_count = 1; break; + case 0x3a: + case 0x2a: + case 0x1a: + DSP1. command =0x1a; + DSP1.in_count = 1; break; + case 0x16: + case 0x26: + case 0x36: + case 0x06: DSP1.in_count = 3; break; + case 0x1e: + case 0x2e: + case 0x3e: + case 0x0e: DSP1.in_count = 2; break; + case 0x05: + case 0x35: + case 0x31: + case 0x01: DSP1.in_count = 4; break; + case 0x15: + case 0x11: DSP1.in_count = 4; break; + case 0x25: + case 0x21: DSP1.in_count = 4; break; + case 0x09: + case 0x39: + case 0x3d: + case 0x0d: DSP1.in_count = 3; break; + case 0x19: + case 0x1d: DSP1.in_count = 3; break; + case 0x29: + case 0x2d: DSP1.in_count = 3; break; + case 0x33: + case 0x03: DSP1.in_count = 3; break; + case 0x13: DSP1.in_count = 3; break; + case 0x23: DSP1.in_count = 3; break; + case 0x3b: + case 0x0b: DSP1.in_count = 3; break; + case 0x1b: DSP1.in_count = 3; break; + case 0x2b: DSP1.in_count = 3; break; + case 0x34: + case 0x14: DSP1.in_count = 6; break; + case 0x07: + case 0x0f: DSP1.in_count = 1; break; + case 0x27: + case 0x2F: DSP1.in_count=1; break; + case 0x17: + case 0x37: + case 0x3F: + DSP1.command=0x1f; + case 0x1f: DSP1.in_count = 1; break; + // case 0x80: DSP1.in_count = 2; break; + default: + //printf("Op%02X\n",byte); + case 0x80: + DSP1.in_count = 0; + DSP1.waiting4command = TRUE; + DSP1.first_parameter = TRUE; + break; + } + DSP1.in_count<<=1; + } + else + { + DSP1.parameters [DSP1.in_index] = byte; + DSP1.first_parameter = FALSE; + DSP1.in_index++; + } + + if (DSP1.waiting4command || + (DSP1.first_parameter && byte == 0x80)) + { + DSP1.waiting4command = TRUE; + DSP1.first_parameter = FALSE; + } + else if(DSP1.first_parameter && (DSP1.in_count != 0 || (DSP1.in_count==0&&DSP1.in_index==0))) + { + } +// else if (DSP1.first_parameter) +// { +// } + else + { + if (DSP1.in_count) + { + //DSP1.parameters [DSP1.in_index] |= (byte << 8); + if (--DSP1.in_count == 0) + { + // Actually execute the command + DSP1.waiting4command = TRUE; + DSP1.out_index = 0; + switch (DSP1.command) + { + case 0x1f: + DSP1.out_count=2048; + break; + case 0x00: // Multiple + Op00Multiplicand = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op00Multiplier = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + + DSPOp00 (); + + DSP1.out_count = 2; + DSP1.output [0] = Op00Result&0xFF; + DSP1.output [1] = (Op00Result>>8)&0xFF; + break; + + case 0x20: // Multiple + Op20Multiplicand = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op20Multiplier = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + + DSPOp20 (); + + DSP1.out_count = 2; + DSP1.output [0] = Op20Result&0xFF; + DSP1.output [1] = (Op20Result>>8)&0xFF; + break; + + case 0x30: + case 0x10: // Inverse + Op10Coefficient = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op10Exponent = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + + DSPOp10 (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (((int16) Op10CoefficientR)&0xFF); + DSP1.output [1] = (uint8) ((((int16) Op10CoefficientR)>>8)&0xFF); + DSP1.output [2] = (uint8) (((int16) Op10ExponentR)&0xff); + DSP1.output [3] = (uint8) ((((int16) Op10ExponentR)>>8)&0xff); + break; + + case 0x24: + case 0x04: // Sin and Cos of angle + Op04Angle = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op04Radius = (uint16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + + DSPOp04 (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (Op04Sin&0xFF); + DSP1.output [1] = (uint8) ((Op04Sin>>8)&0xFF); + DSP1.output [2] = (uint8) (Op04Cos&0xFF); + DSP1.output [3] = (uint8) ((Op04Cos>>8)&0xFF); + break; + + case 0x08: // Radius + Op08X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op08Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op08Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp08 (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (((int16) Op08Ll)&0xFF); + DSP1.output [1] = (uint8) ((((int16) Op08Ll)>>8)&0xFF); + DSP1.output [2] = (uint8) (((int16) Op08Lh)&0xFF); + DSP1.output [3] = (uint8) ((((int16) Op08Lh)>>8)&0xFF); + break; + + case 0x18: // Range + + Op18X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op18Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op18Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op18R = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + + DSPOp18 (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op18D&0xFF); + DSP1.output [1] = (uint8) ((Op18D>>8)&0xFF); + break; + + case 0x38: // Range + + Op38X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op38Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op38Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op38R = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + + DSPOp38 (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op38D&0xFF); + DSP1.output [1] = (uint8) ((Op38D>>8)&0xFF); + break; + + case 0x28: // Distance (vector length) + Op28X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op28Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op28Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp28 (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op28R&0xFF); + DSP1.output [1] = (uint8) ((Op28R>>8)&0xFF); + break; + + case 0x2c: + case 0x0c: // Rotate (2D rotate) + Op0CA = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0CX1 = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op0CY1 = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp0C (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (Op0CX2&0xFF); + DSP1.output [1] = (uint8) ((Op0CX2>>8)&0xFF); + DSP1.output [2] = (uint8) (Op0CY2&0xFF); + DSP1.output [3] = (uint8) ((Op0CY2>>8)&0xFF); + break; + + case 0x3c: + case 0x1c: // Polar (3D rotate) + Op1CZ = (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + //MK: reversed X and Y on neviksti and John's advice. + Op1CY = (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op1CX = (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op1CXBR = (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + Op1CYBR = (DSP1.parameters [8]|(DSP1.parameters[9]<<8)); + Op1CZBR = (DSP1.parameters [10]|(DSP1.parameters[11]<<8)); + + DSPOp1C (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op1CXAR&0xFF); + DSP1.output [1] = (uint8) ((Op1CXAR>>8)&0xFF); + DSP1.output [2] = (uint8) (Op1CYAR&0xFF); + DSP1.output [3] = (uint8) ((Op1CYAR>>8)&0xFF); + DSP1.output [4] = (uint8) (Op1CZAR&0xFF); + DSP1.output [5] = (uint8) ((Op1CZAR>>8)&0xFF); + break; + + case 0x32: + case 0x22: + case 0x12: + case 0x02: // Parameter (Projection) + Op02FX = (short)(DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op02FY = (short)(DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op02FZ = (short)(DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op02LFE = (short)(DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + Op02LES = (short)(DSP1.parameters [8]|(DSP1.parameters[9]<<8)); + Op02AAS = (unsigned short)(DSP1.parameters [10]|(DSP1.parameters[11]<<8)); + Op02AZS = (unsigned short)(DSP1.parameters [12]|(DSP1.parameters[13]<<8)); + + DSPOp02 (); + + DSP1.out_count = 8; + DSP1.output [0] = (uint8) (Op02VOF&0xFF); + DSP1.output [1] = (uint8) ((Op02VOF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op02VVA&0xFF); + DSP1.output [3] = (uint8) ((Op02VVA>>8)&0xFF); + DSP1.output [4] = (uint8) (Op02CX&0xFF); + DSP1.output [5] = (uint8) ((Op02CX>>8)&0xFF); + DSP1.output [6] = (uint8) (Op02CY&0xFF); + DSP1.output [7] = (uint8) ((Op02CY>>8)&0xFF); + break; + + case 0x3a: //1a Mirror + case 0x2a: //1a Mirror + case 0x1a: // Raster mode 7 matrix data + case 0x0a: + Op0AVS = (short)(DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + + DSPOp0A (); + + DSP1.out_count = 8; + DSP1.output [0] = (uint8) (Op0AA&0xFF); + DSP1.output [2] = (uint8) (Op0AB&0xFF); + DSP1.output [4] = (uint8) (Op0AC&0xFF); + DSP1.output [6] = (uint8) (Op0AD&0xFF); + DSP1.output [1] = (uint8) ((Op0AA>>8)&0xFF); + DSP1.output [3] = (uint8) ((Op0AB>>8)&0xFF); + DSP1.output [5] = (uint8) ((Op0AC>>8)&0xFF); + DSP1.output [7] = (uint8) ((Op0AD>>8)&0xFF); + DSP1.in_index=0; + break; + + case 0x16: + case 0x26: + case 0x36: + case 0x06: // Project object + Op06X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op06Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op06Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp06 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op06H&0xff); + DSP1.output [1] = (uint8) ((Op06H>>8)&0xFF); + DSP1.output [2] = (uint8) (Op06V&0xFF); + DSP1.output [3] = (uint8) ((Op06V>>8)&0xFF); + DSP1.output [4] = (uint8) (Op06S&0xFF); + DSP1.output [5] = (uint8) ((Op06S>>8)&0xFF); + break; + + case 0x1e: + case 0x2e: + case 0x3e: + case 0x0e: // Target + Op0EH = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0EV = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + + DSPOp0E (); + + DSP1.out_count = 4; + DSP1.output [0] = (uint8) (Op0EX&0xFF); + DSP1.output [1] = (uint8) ((Op0EX>>8)&0xFF); + DSP1.output [2] = (uint8) (Op0EY&0xFF); + DSP1.output [3] = (uint8) ((Op0EY>>8)&0xFF); + break; + + // Extra commands used by Pilot Wings + case 0x05: + case 0x35: + case 0x31: + case 0x01: // Set attitude matrix A + Op01m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op01Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op01Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op01Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + + DSPOp01 (); + break; + + case 0x15: + case 0x11: // Set attitude matrix B + Op11m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op11Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op11Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op11Xr = (int16) (DSP1.parameters [7]|(DSP1.parameters[7]<<8)); + + DSPOp11 (); + break; + + case 0x25: + case 0x21: // Set attitude matrix C + Op21m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op21Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op21Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op21Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + + DSPOp21 (); + break; + + case 0x09: + case 0x39: + case 0x3d: + case 0x0d: // Objective matrix A + Op0DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op0DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp0D (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op0DF&0xFF); + DSP1.output [1] = (uint8) ((Op0DF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op0DL&0xFF); + DSP1.output [3] = (uint8) ((Op0DL>>8)&0xFF); + DSP1.output [4] = (uint8) (Op0DU&0xFF); + DSP1.output [5] = (uint8) ((Op0DU>>8)&0xFF); + break; + + case 0x19: + case 0x1d: // Objective matrix B + Op1DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op1DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op1DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp1D (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op1DF&0xFF); + DSP1.output [1] = (uint8) ((Op1DF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op1DL&0xFF); + DSP1.output [3] = (uint8) ((Op1DL>>8)&0xFF); + DSP1.output [4] = (uint8) (Op1DU&0xFF); + DSP1.output [5] = (uint8) ((Op1DU>>8)&0xFF); + break; + + case 0x29: + case 0x2d: // Objective matrix C + Op2DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op2DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op2DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp2D (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op2DF&0xFF); + DSP1.output [1] = (uint8) ((Op2DF>>8)&0xFF); + DSP1.output [2] = (uint8) (Op2DL&0xFF); + DSP1.output [3] = (uint8) ((Op2DL>>8)&0xFF); + DSP1.output [4] = (uint8) (Op2DU&0xFF); + DSP1.output [5] = (uint8) ((Op2DU>>8)&0xFF); + break; + + case 0x33: + case 0x03: // Subjective matrix A + Op03F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op03L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op03U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp03 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op03X&0xFF); + DSP1.output [1] = (uint8) ((Op03X>>8)&0xFF); + DSP1.output [2] = (uint8) (Op03Y&0xFF); + DSP1.output [3] = (uint8) ((Op03Y>>8)&0xFF); + DSP1.output [4] = (uint8) (Op03Z&0xFF); + DSP1.output [5] = (uint8) ((Op03Z>>8)&0xFF); + break; + + case 0x13: // Subjective matrix B + Op13F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op13L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op13U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp13 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op13X&0xFF); + DSP1.output [1] = (uint8) ((Op13X>>8)&0xFF); + DSP1.output [2] = (uint8) (Op13Y&0xFF); + DSP1.output [3] = (uint8) ((Op13Y>>8)&0xFF); + DSP1.output [4] = (uint8) (Op13Z&0xFF); + DSP1.output [5] = (uint8) ((Op13Z>>8)&0xFF); + break; + + case 0x23: // Subjective matrix C + Op23F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op23L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op23U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp23 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op23X&0xFF); + DSP1.output [1] = (uint8) ((Op23X>>8)&0xFF); + DSP1.output [2] = (uint8) (Op23Y&0xFF); + DSP1.output [3] = (uint8) ((Op23Y>>8)&0xFF); + DSP1.output [4] = (uint8) (Op23Z&0xFF); + DSP1.output [5] = (uint8) ((Op23Z>>8)&0xFF); + break; + + case 0x3b: + case 0x0b: + Op0BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op0BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op0BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp0B (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op0BS&0xFF); + DSP1.output [1] = (uint8) ((Op0BS>>8)&0xFF); + break; + + case 0x1b: + Op1BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op1BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op1BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp1B (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op1BS&0xFF); + DSP1.output [1] = (uint8) ((Op1BS>>8)&0xFF); + break; + + case 0x2b: + Op2BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op2BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op2BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + + DSPOp2B (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8) (Op2BS&0xFF); + DSP1.output [1] = (uint8) ((Op2BS>>8)&0xFF); + break; + + case 0x34: + case 0x14: + Op14Zr = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + Op14Xr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); + Op14Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); + Op14U = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); + Op14F = (int16) (DSP1.parameters [8]|(DSP1.parameters[9]<<8)); + Op14L = (int16) (DSP1.parameters [10]|(DSP1.parameters[11]<<8)); + + DSPOp14 (); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (Op14Zrr&0xFF); + DSP1.output [1] = (uint8) ((Op14Zrr>>8)&0xFF); + DSP1.output [2] = (uint8) (Op14Xrr&0xFF); + DSP1.output [3] = (uint8) ((Op14Xrr>>8)&0xFF); + DSP1.output [4] = (uint8) (Op14Yrr&0xFF); + DSP1.output [5] = (uint8) ((Op14Yrr>>8)&0xFF); + break; + + case 0x27: + case 0x2F: + Op2FUnknown = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + + DSPOp2F (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8)(Op2FSize&0xFF); + DSP1.output [1] = (uint8)((Op2FSize>>8)&0xFF); + break; + + + case 0x07: + case 0x0F: + Op0FRamsize = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); + + DSPOp0F (); + + DSP1.out_count = 2; + DSP1.output [0] = (uint8)(Op0FPass&0xFF); + DSP1.output [1] = (uint8)((Op0FPass>>8)&0xFF); + break; + + default: + break; + } + } + } + } + } +} + +uint8 DSP1GetByte(uint16 address) +{ + uint8 t; + if ((address & 0xf000) == 0x6000 || +// (address >= 0x8000 && address < 0xc000)) + (address&0x7fff) < 0x4000) + { + if (DSP1.out_count) + { + //if ((address & 1) == 0) + t = (uint8) DSP1.output [DSP1.out_index]; + //else + //{ + // t = (uint8) (DSP1.output [DSP1.out_index] >> 8); + DSP1.out_index++; + if (--DSP1.out_count == 0) + { + if (DSP1.command == 0x1a || DSP1.command == 0x0a) + { + DSPOp0A (); + DSP1.out_count = 8; + DSP1.out_index = 0; + DSP1.output [0] = (Op0AA&0xFF); + DSP1.output [1] = (Op0AA>>8)&0xFF; + DSP1.output [2] = (Op0AB&0xFF); + DSP1.output [3] = (Op0AB>>8)&0xFF; + DSP1.output [4] = (Op0AC&0xFF); + DSP1.output [5] = (Op0AC>>8)&0xFF; + DSP1.output [6] = (Op0AD&0xFF); + DSP1.output [7] = (Op0AD>>8)&0xFF; + } + if(DSP1.command==0x1f) + { + if((DSP1.out_index%2)!=0) + { + t=(uint8)DSP1ROM[DSP1.out_index>>1]; + } + else + { + t=DSP1ROM[DSP1.out_index>>1]>>8; + } + } + } + DSP1.waiting4command = TRUE; + //} + } + else + { + // Top Gear 3000 requires this value.... + // if(4==Settings.DSPVersion) + t = 0xff; + //Ballz3d requires this one: + // else t = 0x00; + } + } + else t = 0x80; + return t; +} + +void DSP2SetByte(uint8 byte, uint16 address) +{ + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if (DSP1.waiting4command) + { + DSP1.command = byte; + DSP1.in_index = 0; + DSP1.waiting4command = FALSE; +// DSP1.first_parameter = TRUE; +// printf("Op%02X\n",byte); + switch (byte) + { + case 0x01:DSP1.in_count=32;break; + case 0x03:DSP1.in_count=1;break; + case 0x05:DSP1.in_count=1;break; + case 0x09:DSP1.in_count=4;break; + case 0x06:DSP1.in_count=1;break; + case 0x0D:DSP1.in_count=2;break; + default: + printf("Op%02X\n",byte); + case 0x0f:DSP1.in_count=0;break; + } + } + else + { + DSP1.parameters [DSP1.in_index] = byte; +// DSP1.first_parameter = FALSE; + DSP1.in_index++; + } + + if (DSP1.in_count==DSP1.in_index) + { + //DSP1.parameters [DSP1.in_index] |= (byte << 8); + // Actually execute the command + DSP1.waiting4command = TRUE; + DSP1.out_index = 0; + switch (DSP1.command) + { + case 0x0D: + if(DSP2Op0DHasLen) + { + DSP2Op0DHasLen=false; + DSP1.out_count=DSP2Op0DOutLen; + //execute Op5 + DSP2_Op0D(); + } + else + { + DSP2Op0DInLen=DSP1.parameters[0]; + DSP2Op0DOutLen=DSP1.parameters[1]; + DSP1.in_index=0; + DSP1.in_count=(DSP2Op0DInLen+1)>>1; + DSP2Op0DHasLen=true; + if(byte) + DSP1.waiting4command=false; + } + break; + case 0x06: + if(DSP2Op06HasLen) + { + DSP2Op06HasLen=false; + DSP1.out_count=DSP2Op06Len; + //execute Op5 + DSP2_Op06(); + } + else + { + DSP2Op06Len=DSP1.parameters[0]; + DSP1.in_index=0; + DSP1.in_count=DSP2Op06Len; + DSP2Op06HasLen=true; + if(byte) + DSP1.waiting4command=false; + } + break; + case 0x01: + DSP1.out_count=32; + DSP2_Op01(); + break; + case 0x09: + // Multiply - don't yet know if this is signed or unsigned + DSP2Op09Word1 = DSP1.parameters[0] | (DSP1.parameters[1]<<8); + DSP2Op09Word2 = DSP1.parameters[2] | (DSP1.parameters[3]<<8); + DSP1.out_count=4; +#ifdef FAST_LSB_WORD_ACCESS + *(uint32 *)DSP1.output = DSP2Op09Word1 * DSP2Op09Word2; +#else + uint32 temp; + temp=DSP2Op09Word1 * DSP2Op09Word2; + DSP1.output[0]=temp&0xFF; + DSP1.output[1]=(temp>>8)&0xFF; + DSP1.output[2]=(temp>>16)&0xFF; + DSP1.output[3]=(temp>>24)&0xFF; +#endif + break; + case 0x05: + if(DSP2Op05HasLen) + { + DSP2Op05HasLen=false; + DSP1.out_count=DSP2Op05Len; + //execute Op5 + DSP2_Op05(); + } + else + { + DSP2Op05Len=DSP1.parameters[0]; + DSP1.in_index=0; + DSP1.in_count=2*DSP2Op05Len; + DSP2Op05HasLen=true; + if(byte) + DSP1.waiting4command=false; + } + break; + + case 0x03: + DSP2Op05Transparent= DSP1.parameters[0]; + //DSP2Op03(); + break; + case 0x0f: + default: + break; + } + } + } +} + +uint8 DSP2GetByte(uint16 address) +{ + uint8 t; + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if (DSP1.out_count) + { + t = (uint8) DSP1.output [DSP1.out_index]; + DSP1.out_index++; + if(DSP1.out_count==DSP1.out_index) + DSP1.out_count=0; + } + else + { + t = 0xff; + } + } + else t = 0x80; + return t; +} + +/*struct SDSP4 { + bool8 waiting4command; + bool8 half_command; + uint16 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters [512]; + uint8 output [512]; +}; + +SDSP4 DSP4; + +//#include "dsp4emu.cpp" + +bool DSP4_init=FALSE; + +void DSP4SetByte(uint8 byte, uint16 address) +{ + if(!DSP4_init) + { + // bootup + DSP4.waiting4command=1; + DSP4_init=TRUE; + } + + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if(DSP4.out_index>16); + } + break; + + // unknown: horizontal mapping command + case 0x0011: + { + int16 a,b,c,d,m; + + a = DSP4_READ_WORD(6); + b = DSP4_READ_WORD(4); + c = DSP4_READ_WORD(2); + d = DSP4_READ_WORD(0); + + DSP4_UnknownOP11(a,b,c,d,m); + + DSP4.out_count = 2; + DSP4_WRITE_WORD(0,m); + break; + } + + // track projection + case 0x0001: DSP4_Op01(); break; + + // track projection (pass 2) + case 0x0007: DSP4_Op07(); break; + + // zone projections (fuel/repair/lap/teleport/...) + case 0x0008: DSP4_Op08(); break; + + // sprite transformation + case 0x0009: DSP4_Op09(); break; + + // fast track projection + case 0x000D: DSP4_Op0D(); break; + + // single-player selection + case 0x0003: DSP4_Op03(); break; + + // clear OAM + case 0x0005: + { + op06_index = 0; + op06_offset = 0; + for( int lcv=0; lcv<32; lcv++ ) + op06_OAM[lcv] = 0; + break; + } + + // multi-player selection + case 0x000E: DSP4_Op0E(); break; + +#undef PRINT + + // transfer OAM + case 0x0006: + { + DSP4.out_count = 32; + for( int lcv=0; lcv<32; lcv++ ) + DSP4.output[lcv] = op06_OAM[lcv]; + } + break; + + // unknown + case 0x000A: + { + int16 in1a = DSP4_READ_WORD(0); + int16 in2a = DSP4_READ_WORD(2); + int16 in3a = DSP4_READ_WORD(4); + int16 out1a,out2a,out3a,out4a; + + // NOTE: Snes9x only! + // For some odd reason, the input nybbles are reversed + + DSP4_Op0A(in2a,out1a,out2a,out3a,out4a); + + DSP4.out_count=8; + + // Hack: Reverse the outputs for now to compensate + // Otherwise the AI gets really flaky + DSP4_WRITE_WORD(0,out2a); + DSP4_WRITE_WORD(2,out1a); + DSP4_WRITE_WORD(4,out4a); + DSP4_WRITE_WORD(6,out3a); + } + break; + + // set OAM + case 0x000B: + { + int16 sp_x = DSP4_READ_WORD(0); + int16 sp_y = DSP4_READ_WORD(2); + int16 oam = DSP4_READ_WORD(4); + + if ((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb)) + { + short Row = (sp_y >> 3) & 0x1f; + + if (RowCount[Row] < MaxTilesPerRow) + { + RowCount[Row]++; + + // yield OAM output + DSP4.out_count = 6; + DSP4_WRITE_WORD(0,1); + + // pack OAM data: x,y,name,attr + DSP4.output[2] = sp_x & 0xff; + DSP4.output[3] = sp_y & 0xff; + DSP4_WRITE_WORD(4,oam); + + // OAM: size,msb data + DSP4_Op06(0,0); + } + } + } + break; + + default: break; + } + } + } +} + +uint8 DSP4GetByte(uint16 address) +{ + uint8 t; + if ((address & 0xf000) == 0x6000 || + (address >= 0x8000 && address < 0xc000)) + { + if (DSP4.out_count) + { + t = (uint8) DSP4.output [DSP4.out_index]; + DSP4.out_index++; + if(DSP4.out_count==DSP4.out_index) + DSP4.out_count=0; + } + else + t = 0xff; + } + else + { + t = 0x80; + } + + return t; +} +*/ \ No newline at end of file diff --git a/src/dsp1.cpp b/src/dsp1.cpp deleted file mode 100644 index f2ea308..0000000 --- a/src/dsp1.cpp +++ /dev/null @@ -1,1195 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ -#include "snes9x.h" -#include "dsp1.h" -#include "missing.h" -#include "memmap.h" -#include - -#include "dsp1emu.c" -#include "dsp2emu.c" -//#include "dsp3emu.cpp" - -void (*SetDSP)(uint8, uint16)=&DSP1SetByte; -uint8 (*GetDSP)(uint16)=&DSP1GetByte; - -void S9xInitDSP1 () -{ - static bool8 init = FALSE; - - if (!init) - { - InitDSP (); - init = TRUE; - } -} - -void S9xResetDSP1 () -{ - S9xInitDSP1 (); - - DSP1.waiting4command = TRUE; - DSP1.in_count = 0; - DSP1.out_count = 0; - DSP1.in_index = 0; - DSP1.out_index = 0; - DSP1.first_parameter = TRUE; -} - -uint8 S9xGetDSP (uint16 address) -{ - uint8 t; - -#ifdef DEBUGGER - if (Settings.TraceDSP) - { - sprintf (String, "DSP read: 0x%04X", address); - S9xMessage (S9X_TRACE, S9X_TRACE_DSP1, String); - } -#endif - - t=(*GetDSP)(address); - //DSP1GetByte(address); - return (t); -} - -void S9xSetDSP (uint8 byte, uint16 address) -{ -#ifdef DEBUGGER - missing.unknowndsp_write = address; - if (Settings.TraceDSP) - { - sprintf (String, "DSP write: 0x%04X=0x%02X", address, byte); - S9xMessage (S9X_TRACE, S9X_TRACE_DSP1, String); - } -#endif - (*SetDSP)(byte, address); - //DSP1SetByte(byte, address); -} - -void DSP1SetByte(uint8 byte, uint16 address) -{ - if( (address & 0xf000) == 0x6000 || (address & 0x7fff) < 0x4000 ) - { -// if ((address & 1) == 0) -// { - if((DSP1.command==0x0A||DSP1.command==0x1A)&&DSP1.out_count!=0) - { - DSP1.out_count--; - DSP1.out_index++; - return; - } - else if (DSP1.waiting4command) - { - DSP1.command = byte; - DSP1.in_index = 0; - DSP1.waiting4command = FALSE; - DSP1.first_parameter = TRUE; -// printf("Op%02X\n",byte); - // Mario Kart uses 0x00, 0x02, 0x06, 0x0c, 0x28, 0x0a - switch (byte) - { - case 0x00: DSP1.in_count = 2; break; - case 0x30: - case 0x10: DSP1.in_count = 2; break; - case 0x20: DSP1.in_count = 2; break; - case 0x24: - case 0x04: DSP1.in_count = 2; break; - case 0x08: DSP1.in_count = 3; break; - case 0x18: DSP1.in_count = 4; break; - case 0x28: DSP1.in_count = 3; break; - case 0x38: DSP1.in_count = 4; break; - case 0x2c: - case 0x0c: DSP1.in_count = 3; break; - case 0x3c: - case 0x1c: DSP1.in_count = 6; break; - case 0x32: - case 0x22: - case 0x12: - case 0x02: DSP1.in_count = 7; break; - case 0x0a: DSP1.in_count = 1; break; - case 0x3a: - case 0x2a: - case 0x1a: - DSP1. command =0x1a; - DSP1.in_count = 1; break; - case 0x16: - case 0x26: - case 0x36: - case 0x06: DSP1.in_count = 3; break; - case 0x1e: - case 0x2e: - case 0x3e: - case 0x0e: DSP1.in_count = 2; break; - case 0x05: - case 0x35: - case 0x31: - case 0x01: DSP1.in_count = 4; break; - case 0x15: - case 0x11: DSP1.in_count = 4; break; - case 0x25: - case 0x21: DSP1.in_count = 4; break; - case 0x09: - case 0x39: - case 0x3d: - case 0x0d: DSP1.in_count = 3; break; - case 0x19: - case 0x1d: DSP1.in_count = 3; break; - case 0x29: - case 0x2d: DSP1.in_count = 3; break; - case 0x33: - case 0x03: DSP1.in_count = 3; break; - case 0x13: DSP1.in_count = 3; break; - case 0x23: DSP1.in_count = 3; break; - case 0x3b: - case 0x0b: DSP1.in_count = 3; break; - case 0x1b: DSP1.in_count = 3; break; - case 0x2b: DSP1.in_count = 3; break; - case 0x34: - case 0x14: DSP1.in_count = 6; break; - case 0x07: - case 0x0f: DSP1.in_count = 1; break; - case 0x27: - case 0x2F: DSP1.in_count=1; break; - case 0x17: - case 0x37: - case 0x3F: - DSP1.command=0x1f; - case 0x1f: DSP1.in_count = 1; break; - // case 0x80: DSP1.in_count = 2; break; - default: - //printf("Op%02X\n",byte); - case 0x80: - DSP1.in_count = 0; - DSP1.waiting4command = TRUE; - DSP1.first_parameter = TRUE; - break; - } - DSP1.in_count<<=1; - } - else - { - DSP1.parameters [DSP1.in_index] = byte; - DSP1.first_parameter = FALSE; - DSP1.in_index++; - } - - if (DSP1.waiting4command || - (DSP1.first_parameter && byte == 0x80)) - { - DSP1.waiting4command = TRUE; - DSP1.first_parameter = FALSE; - } - else if(DSP1.first_parameter && (DSP1.in_count != 0 || (DSP1.in_count==0&&DSP1.in_index==0))) - { - } -// else if (DSP1.first_parameter) -// { -// } - else - { - if (DSP1.in_count) - { - //DSP1.parameters [DSP1.in_index] |= (byte << 8); - if (--DSP1.in_count == 0) - { - // Actually execute the command - DSP1.waiting4command = TRUE; - DSP1.out_index = 0; - switch (DSP1.command) - { - case 0x1f: - DSP1.out_count=2048; - break; - case 0x00: // Multiple - Op00Multiplicand = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op00Multiplier = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - - DSPOp00 (); - - DSP1.out_count = 2; - DSP1.output [0] = Op00Result&0xFF; - DSP1.output [1] = (Op00Result>>8)&0xFF; - break; - - case 0x20: // Multiple - Op20Multiplicand = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op20Multiplier = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - - DSPOp20 (); - - DSP1.out_count = 2; - DSP1.output [0] = Op20Result&0xFF; - DSP1.output [1] = (Op20Result>>8)&0xFF; - break; - - case 0x30: - case 0x10: // Inverse - Op10Coefficient = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op10Exponent = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - - DSPOp10 (); - - DSP1.out_count = 4; - DSP1.output [0] = (uint8) (((int16) Op10CoefficientR)&0xFF); - DSP1.output [1] = (uint8) ((((int16) Op10CoefficientR)>>8)&0xFF); - DSP1.output [2] = (uint8) (((int16) Op10ExponentR)&0xff); - DSP1.output [3] = (uint8) ((((int16) Op10ExponentR)>>8)&0xff); - break; - - case 0x24: - case 0x04: // Sin and Cos of angle - Op04Angle = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op04Radius = (uint16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - - DSPOp04 (); - - DSP1.out_count = 4; - DSP1.output [0] = (uint8) (Op04Sin&0xFF); - DSP1.output [1] = (uint8) ((Op04Sin>>8)&0xFF); - DSP1.output [2] = (uint8) (Op04Cos&0xFF); - DSP1.output [3] = (uint8) ((Op04Cos>>8)&0xFF); - break; - - case 0x08: // Radius - Op08X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op08Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op08Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp08 (); - - DSP1.out_count = 4; - DSP1.output [0] = (uint8) (((int16) Op08Ll)&0xFF); - DSP1.output [1] = (uint8) ((((int16) Op08Ll)>>8)&0xFF); - DSP1.output [2] = (uint8) (((int16) Op08Lh)&0xFF); - DSP1.output [3] = (uint8) ((((int16) Op08Lh)>>8)&0xFF); - break; - - case 0x18: // Range - - Op18X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op18Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op18Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op18R = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - - DSPOp18 (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8) (Op18D&0xFF); - DSP1.output [1] = (uint8) ((Op18D>>8)&0xFF); - break; - - case 0x38: // Range - - Op38X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op38Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op38Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op38R = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - - DSPOp38 (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8) (Op38D&0xFF); - DSP1.output [1] = (uint8) ((Op38D>>8)&0xFF); - break; - - case 0x28: // Distance (vector length) - Op28X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op28Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op28Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp28 (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8) (Op28R&0xFF); - DSP1.output [1] = (uint8) ((Op28R>>8)&0xFF); - break; - - case 0x2c: - case 0x0c: // Rotate (2D rotate) - Op0CA = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op0CX1 = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op0CY1 = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp0C (); - - DSP1.out_count = 4; - DSP1.output [0] = (uint8) (Op0CX2&0xFF); - DSP1.output [1] = (uint8) ((Op0CX2>>8)&0xFF); - DSP1.output [2] = (uint8) (Op0CY2&0xFF); - DSP1.output [3] = (uint8) ((Op0CY2>>8)&0xFF); - break; - - case 0x3c: - case 0x1c: // Polar (3D rotate) - Op1CZ = (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - //MK: reversed X and Y on neviksti and John's advice. - Op1CY = (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op1CX = (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op1CXBR = (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - Op1CYBR = (DSP1.parameters [8]|(DSP1.parameters[9]<<8)); - Op1CZBR = (DSP1.parameters [10]|(DSP1.parameters[11]<<8)); - - DSPOp1C (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op1CXAR&0xFF); - DSP1.output [1] = (uint8) ((Op1CXAR>>8)&0xFF); - DSP1.output [2] = (uint8) (Op1CYAR&0xFF); - DSP1.output [3] = (uint8) ((Op1CYAR>>8)&0xFF); - DSP1.output [4] = (uint8) (Op1CZAR&0xFF); - DSP1.output [5] = (uint8) ((Op1CZAR>>8)&0xFF); - break; - - case 0x32: - case 0x22: - case 0x12: - case 0x02: // Parameter (Projection) - Op02FX = (short)(DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op02FY = (short)(DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op02FZ = (short)(DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op02LFE = (short)(DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - Op02LES = (short)(DSP1.parameters [8]|(DSP1.parameters[9]<<8)); - Op02AAS = (unsigned short)(DSP1.parameters [10]|(DSP1.parameters[11]<<8)); - Op02AZS = (unsigned short)(DSP1.parameters [12]|(DSP1.parameters[13]<<8)); - - DSPOp02 (); - - DSP1.out_count = 8; - DSP1.output [0] = (uint8) (Op02VOF&0xFF); - DSP1.output [1] = (uint8) ((Op02VOF>>8)&0xFF); - DSP1.output [2] = (uint8) (Op02VVA&0xFF); - DSP1.output [3] = (uint8) ((Op02VVA>>8)&0xFF); - DSP1.output [4] = (uint8) (Op02CX&0xFF); - DSP1.output [5] = (uint8) ((Op02CX>>8)&0xFF); - DSP1.output [6] = (uint8) (Op02CY&0xFF); - DSP1.output [7] = (uint8) ((Op02CY>>8)&0xFF); - break; - - case 0x3a: //1a Mirror - case 0x2a: //1a Mirror - case 0x1a: // Raster mode 7 matrix data - case 0x0a: - Op0AVS = (short)(DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - - DSPOp0A (); - - DSP1.out_count = 8; - DSP1.output [0] = (uint8) (Op0AA&0xFF); - DSP1.output [2] = (uint8) (Op0AB&0xFF); - DSP1.output [4] = (uint8) (Op0AC&0xFF); - DSP1.output [6] = (uint8) (Op0AD&0xFF); - DSP1.output [1] = (uint8) ((Op0AA>>8)&0xFF); - DSP1.output [3] = (uint8) ((Op0AB>>8)&0xFF); - DSP1.output [5] = (uint8) ((Op0AC>>8)&0xFF); - DSP1.output [7] = (uint8) ((Op0AD>>8)&0xFF); - DSP1.in_index=0; - break; - - case 0x16: - case 0x26: - case 0x36: - case 0x06: // Project object - Op06X = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op06Y = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op06Z = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp06 (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op06H&0xff); - DSP1.output [1] = (uint8) ((Op06H>>8)&0xFF); - DSP1.output [2] = (uint8) (Op06V&0xFF); - DSP1.output [3] = (uint8) ((Op06V>>8)&0xFF); - DSP1.output [4] = (uint8) (Op06S&0xFF); - DSP1.output [5] = (uint8) ((Op06S>>8)&0xFF); - break; - - case 0x1e: - case 0x2e: - case 0x3e: - case 0x0e: // Target - Op0EH = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op0EV = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - - DSPOp0E (); - - DSP1.out_count = 4; - DSP1.output [0] = (uint8) (Op0EX&0xFF); - DSP1.output [1] = (uint8) ((Op0EX>>8)&0xFF); - DSP1.output [2] = (uint8) (Op0EY&0xFF); - DSP1.output [3] = (uint8) ((Op0EY>>8)&0xFF); - break; - - // Extra commands used by Pilot Wings - case 0x05: - case 0x35: - case 0x31: - case 0x01: // Set attitude matrix A - Op01m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op01Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op01Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op01Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - - DSPOp01 (); - break; - - case 0x15: - case 0x11: // Set attitude matrix B - Op11m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op11Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op11Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op11Xr = (int16) (DSP1.parameters [7]|(DSP1.parameters[7]<<8)); - - DSPOp11 (); - break; - - case 0x25: - case 0x21: // Set attitude matrix C - Op21m = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op21Zr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op21Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op21Xr = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - - DSPOp21 (); - break; - - case 0x09: - case 0x39: - case 0x3d: - case 0x0d: // Objective matrix A - Op0DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op0DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op0DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp0D (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op0DF&0xFF); - DSP1.output [1] = (uint8) ((Op0DF>>8)&0xFF); - DSP1.output [2] = (uint8) (Op0DL&0xFF); - DSP1.output [3] = (uint8) ((Op0DL>>8)&0xFF); - DSP1.output [4] = (uint8) (Op0DU&0xFF); - DSP1.output [5] = (uint8) ((Op0DU>>8)&0xFF); - break; - - case 0x19: - case 0x1d: // Objective matrix B - Op1DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op1DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op1DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp1D (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op1DF&0xFF); - DSP1.output [1] = (uint8) ((Op1DF>>8)&0xFF); - DSP1.output [2] = (uint8) (Op1DL&0xFF); - DSP1.output [3] = (uint8) ((Op1DL>>8)&0xFF); - DSP1.output [4] = (uint8) (Op1DU&0xFF); - DSP1.output [5] = (uint8) ((Op1DU>>8)&0xFF); - break; - - case 0x29: - case 0x2d: // Objective matrix C - Op2DX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op2DY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op2DZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp2D (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op2DF&0xFF); - DSP1.output [1] = (uint8) ((Op2DF>>8)&0xFF); - DSP1.output [2] = (uint8) (Op2DL&0xFF); - DSP1.output [3] = (uint8) ((Op2DL>>8)&0xFF); - DSP1.output [4] = (uint8) (Op2DU&0xFF); - DSP1.output [5] = (uint8) ((Op2DU>>8)&0xFF); - break; - - case 0x33: - case 0x03: // Subjective matrix A - Op03F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op03L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op03U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp03 (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op03X&0xFF); - DSP1.output [1] = (uint8) ((Op03X>>8)&0xFF); - DSP1.output [2] = (uint8) (Op03Y&0xFF); - DSP1.output [3] = (uint8) ((Op03Y>>8)&0xFF); - DSP1.output [4] = (uint8) (Op03Z&0xFF); - DSP1.output [5] = (uint8) ((Op03Z>>8)&0xFF); - break; - - case 0x13: // Subjective matrix B - Op13F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op13L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op13U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp13 (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op13X&0xFF); - DSP1.output [1] = (uint8) ((Op13X>>8)&0xFF); - DSP1.output [2] = (uint8) (Op13Y&0xFF); - DSP1.output [3] = (uint8) ((Op13Y>>8)&0xFF); - DSP1.output [4] = (uint8) (Op13Z&0xFF); - DSP1.output [5] = (uint8) ((Op13Z>>8)&0xFF); - break; - - case 0x23: // Subjective matrix C - Op23F = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op23L = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op23U = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp23 (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op23X&0xFF); - DSP1.output [1] = (uint8) ((Op23X>>8)&0xFF); - DSP1.output [2] = (uint8) (Op23Y&0xFF); - DSP1.output [3] = (uint8) ((Op23Y>>8)&0xFF); - DSP1.output [4] = (uint8) (Op23Z&0xFF); - DSP1.output [5] = (uint8) ((Op23Z>>8)&0xFF); - break; - - case 0x3b: - case 0x0b: - Op0BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op0BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op0BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp0B (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8) (Op0BS&0xFF); - DSP1.output [1] = (uint8) ((Op0BS>>8)&0xFF); - break; - - case 0x1b: - Op1BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op1BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op1BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp1B (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8) (Op1BS&0xFF); - DSP1.output [1] = (uint8) ((Op1BS>>8)&0xFF); - break; - - case 0x2b: - Op2BX = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op2BY = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op2BZ = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - - DSPOp2B (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8) (Op2BS&0xFF); - DSP1.output [1] = (uint8) ((Op2BS>>8)&0xFF); - break; - - case 0x34: - case 0x14: - Op14Zr = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - Op14Xr = (int16) (DSP1.parameters [2]|(DSP1.parameters[3]<<8)); - Op14Yr = (int16) (DSP1.parameters [4]|(DSP1.parameters[5]<<8)); - Op14U = (int16) (DSP1.parameters [6]|(DSP1.parameters[7]<<8)); - Op14F = (int16) (DSP1.parameters [8]|(DSP1.parameters[9]<<8)); - Op14L = (int16) (DSP1.parameters [10]|(DSP1.parameters[11]<<8)); - - DSPOp14 (); - - DSP1.out_count = 6; - DSP1.output [0] = (uint8) (Op14Zrr&0xFF); - DSP1.output [1] = (uint8) ((Op14Zrr>>8)&0xFF); - DSP1.output [2] = (uint8) (Op14Xrr&0xFF); - DSP1.output [3] = (uint8) ((Op14Xrr>>8)&0xFF); - DSP1.output [4] = (uint8) (Op14Yrr&0xFF); - DSP1.output [5] = (uint8) ((Op14Yrr>>8)&0xFF); - break; - - case 0x27: - case 0x2F: - Op2FUnknown = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - - DSPOp2F (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8)(Op2FSize&0xFF); - DSP1.output [1] = (uint8)((Op2FSize>>8)&0xFF); - break; - - - case 0x07: - case 0x0F: - Op0FRamsize = (int16) (DSP1.parameters [0]|(DSP1.parameters[1]<<8)); - - DSPOp0F (); - - DSP1.out_count = 2; - DSP1.output [0] = (uint8)(Op0FPass&0xFF); - DSP1.output [1] = (uint8)((Op0FPass>>8)&0xFF); - break; - - default: - break; - } - } - } - } - } -} - -uint8 DSP1GetByte(uint16 address) -{ - uint8 t; - if ((address & 0xf000) == 0x6000 || -// (address >= 0x8000 && address < 0xc000)) - (address&0x7fff) < 0x4000) - { - if (DSP1.out_count) - { - //if ((address & 1) == 0) - t = (uint8) DSP1.output [DSP1.out_index]; - //else - //{ - // t = (uint8) (DSP1.output [DSP1.out_index] >> 8); - DSP1.out_index++; - if (--DSP1.out_count == 0) - { - if (DSP1.command == 0x1a || DSP1.command == 0x0a) - { - DSPOp0A (); - DSP1.out_count = 8; - DSP1.out_index = 0; - DSP1.output [0] = (Op0AA&0xFF); - DSP1.output [1] = (Op0AA>>8)&0xFF; - DSP1.output [2] = (Op0AB&0xFF); - DSP1.output [3] = (Op0AB>>8)&0xFF; - DSP1.output [4] = (Op0AC&0xFF); - DSP1.output [5] = (Op0AC>>8)&0xFF; - DSP1.output [6] = (Op0AD&0xFF); - DSP1.output [7] = (Op0AD>>8)&0xFF; - } - if(DSP1.command==0x1f) - { - if((DSP1.out_index%2)!=0) - { - t=(uint8)DSP1ROM[DSP1.out_index>>1]; - } - else - { - t=DSP1ROM[DSP1.out_index>>1]>>8; - } - } - } - DSP1.waiting4command = TRUE; - //} - } - else - { - // Top Gear 3000 requires this value.... - // if(4==Settings.DSPVersion) - t = 0xff; - //Ballz3d requires this one: - // else t = 0x00; - } - } - else t = 0x80; - return t; -} - -void DSP2SetByte(uint8 byte, uint16 address) -{ - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { - if (DSP1.waiting4command) - { - DSP1.command = byte; - DSP1.in_index = 0; - DSP1.waiting4command = FALSE; -// DSP1.first_parameter = TRUE; -// printf("Op%02X\n",byte); - switch (byte) - { - case 0x01:DSP1.in_count=32;break; - case 0x03:DSP1.in_count=1;break; - case 0x05:DSP1.in_count=1;break; - case 0x09:DSP1.in_count=4;break; - case 0x06:DSP1.in_count=1;break; - case 0x0D:DSP1.in_count=2;break; - default: - printf("Op%02X\n",byte); - case 0x0f:DSP1.in_count=0;break; - } - } - else - { - DSP1.parameters [DSP1.in_index] = byte; -// DSP1.first_parameter = FALSE; - DSP1.in_index++; - } - - if (DSP1.in_count==DSP1.in_index) - { - //DSP1.parameters [DSP1.in_index] |= (byte << 8); - // Actually execute the command - DSP1.waiting4command = TRUE; - DSP1.out_index = 0; - switch (DSP1.command) - { - case 0x0D: - if(DSP2Op0DHasLen) - { - DSP2Op0DHasLen=false; - DSP1.out_count=DSP2Op0DOutLen; - //execute Op5 - DSP2_Op0D(); - } - else - { - DSP2Op0DInLen=DSP1.parameters[0]; - DSP2Op0DOutLen=DSP1.parameters[1]; - DSP1.in_index=0; - DSP1.in_count=(DSP2Op0DInLen+1)>>1; - DSP2Op0DHasLen=true; - if(byte) - DSP1.waiting4command=false; - } - break; - case 0x06: - if(DSP2Op06HasLen) - { - DSP2Op06HasLen=false; - DSP1.out_count=DSP2Op06Len; - //execute Op5 - DSP2_Op06(); - } - else - { - DSP2Op06Len=DSP1.parameters[0]; - DSP1.in_index=0; - DSP1.in_count=DSP2Op06Len; - DSP2Op06HasLen=true; - if(byte) - DSP1.waiting4command=false; - } - break; - case 0x01: - DSP1.out_count=32; - DSP2_Op01(); - break; - case 0x09: - // Multiply - don't yet know if this is signed or unsigned - DSP2Op09Word1 = DSP1.parameters[0] | (DSP1.parameters[1]<<8); - DSP2Op09Word2 = DSP1.parameters[2] | (DSP1.parameters[3]<<8); - DSP1.out_count=4; -#ifdef FAST_LSB_WORD_ACCESS - *(uint32 *)DSP1.output = DSP2Op09Word1 * DSP2Op09Word2; -#else - uint32 temp; - temp=DSP2Op09Word1 * DSP2Op09Word2; - DSP1.output[0]=temp&0xFF; - DSP1.output[1]=(temp>>8)&0xFF; - DSP1.output[2]=(temp>>16)&0xFF; - DSP1.output[3]=(temp>>24)&0xFF; -#endif - break; - case 0x05: - if(DSP2Op05HasLen) - { - DSP2Op05HasLen=false; - DSP1.out_count=DSP2Op05Len; - //execute Op5 - DSP2_Op05(); - } - else - { - DSP2Op05Len=DSP1.parameters[0]; - DSP1.in_index=0; - DSP1.in_count=2*DSP2Op05Len; - DSP2Op05HasLen=true; - if(byte) - DSP1.waiting4command=false; - } - break; - - case 0x03: - DSP2Op05Transparent= DSP1.parameters[0]; - //DSP2Op03(); - break; - case 0x0f: - default: - break; - } - } - } -} - -uint8 DSP2GetByte(uint16 address) -{ - uint8 t; - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { - if (DSP1.out_count) - { - t = (uint8) DSP1.output [DSP1.out_index]; - DSP1.out_index++; - if(DSP1.out_count==DSP1.out_index) - DSP1.out_count=0; - } - else - { - t = 0xff; - } - } - else t = 0x80; - return t; -} - -/*struct SDSP4 { - bool8 waiting4command; - bool8 half_command; - uint16 command; - uint32 in_count; - uint32 in_index; - uint32 out_count; - uint32 out_index; - uint8 parameters [512]; - uint8 output [512]; -}; - -SDSP4 DSP4; - -//#include "dsp4emu.cpp" - -bool DSP4_init=FALSE; - -void DSP4SetByte(uint8 byte, uint16 address) -{ - if(!DSP4_init) - { - // bootup - DSP4.waiting4command=1; - DSP4_init=TRUE; - } - - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { - if(DSP4.out_index>16); - } - break; - - // unknown: horizontal mapping command - case 0x0011: - { - int16 a,b,c,d,m; - - a = DSP4_READ_WORD(6); - b = DSP4_READ_WORD(4); - c = DSP4_READ_WORD(2); - d = DSP4_READ_WORD(0); - - DSP4_UnknownOP11(a,b,c,d,m); - - DSP4.out_count = 2; - DSP4_WRITE_WORD(0,m); - break; - } - - // track projection - case 0x0001: DSP4_Op01(); break; - - // track projection (pass 2) - case 0x0007: DSP4_Op07(); break; - - // zone projections (fuel/repair/lap/teleport/...) - case 0x0008: DSP4_Op08(); break; - - // sprite transformation - case 0x0009: DSP4_Op09(); break; - - // fast track projection - case 0x000D: DSP4_Op0D(); break; - - // single-player selection - case 0x0003: DSP4_Op03(); break; - - // clear OAM - case 0x0005: - { - op06_index = 0; - op06_offset = 0; - for( int lcv=0; lcv<32; lcv++ ) - op06_OAM[lcv] = 0; - break; - } - - // multi-player selection - case 0x000E: DSP4_Op0E(); break; - -#undef PRINT - - // transfer OAM - case 0x0006: - { - DSP4.out_count = 32; - for( int lcv=0; lcv<32; lcv++ ) - DSP4.output[lcv] = op06_OAM[lcv]; - } - break; - - // unknown - case 0x000A: - { - int16 in1a = DSP4_READ_WORD(0); - int16 in2a = DSP4_READ_WORD(2); - int16 in3a = DSP4_READ_WORD(4); - int16 out1a,out2a,out3a,out4a; - - // NOTE: Snes9x only! - // For some odd reason, the input nybbles are reversed - - DSP4_Op0A(in2a,out1a,out2a,out3a,out4a); - - DSP4.out_count=8; - - // Hack: Reverse the outputs for now to compensate - // Otherwise the AI gets really flaky - DSP4_WRITE_WORD(0,out2a); - DSP4_WRITE_WORD(2,out1a); - DSP4_WRITE_WORD(4,out4a); - DSP4_WRITE_WORD(6,out3a); - } - break; - - // set OAM - case 0x000B: - { - int16 sp_x = DSP4_READ_WORD(0); - int16 sp_y = DSP4_READ_WORD(2); - int16 oam = DSP4_READ_WORD(4); - - if ((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb)) - { - short Row = (sp_y >> 3) & 0x1f; - - if (RowCount[Row] < MaxTilesPerRow) - { - RowCount[Row]++; - - // yield OAM output - DSP4.out_count = 6; - DSP4_WRITE_WORD(0,1); - - // pack OAM data: x,y,name,attr - DSP4.output[2] = sp_x & 0xff; - DSP4.output[3] = sp_y & 0xff; - DSP4_WRITE_WORD(4,oam); - - // OAM: size,msb data - DSP4_Op06(0,0); - } - } - } - break; - - default: break; - } - } - } -} - -uint8 DSP4GetByte(uint16 address) -{ - uint8 t; - if ((address & 0xf000) == 0x6000 || - (address >= 0x8000 && address < 0xc000)) - { - if (DSP4.out_count) - { - t = (uint8) DSP4.output [DSP4.out_index]; - DSP4.out_index++; - if(DSP4.out_count==DSP4.out_index) - DSP4.out_count=0; - } - else - t = 0xff; - } - else - { - t = 0x80; - } - - return t; -} -*/ \ No newline at end of file diff --git a/src/dsp1.h b/src/dsp1.h index 82fe3f1..ccd9efe 100644 --- a/src/dsp1.h +++ b/src/dsp1.h @@ -106,7 +106,8 @@ void DSP3_Reset(); void DSP4SetByte(uint8 byte, uint16 address); uint8 DSP4GetByte(uint16 address); -struct SDSP1 { +typedef struct +{ uint8 version; bool8 waiting4command; bool8 first_parameter; @@ -117,7 +118,7 @@ struct SDSP1 { uint32 out_index; uint8 parameters [512]; uint8 output [512]; -}; +}SDSP1; START_EXTERN_C void S9xResetDSP1 (); @@ -125,6 +126,6 @@ uint8 S9xGetDSP (uint16 Address); void S9xSetDSP (uint8 Byte, uint16 Address); END_EXTERN_C -extern struct SDSP1 DSP1; +extern SDSP1 DSP1; #endif diff --git a/src/fxemu.c b/src/fxemu.c new file mode 100644 index 0000000..0fda5e5 --- /dev/null +++ b/src/fxemu.c @@ -0,0 +1,721 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and distribute Snes9x in both binary and + source form, for non-commercial purposes, is hereby granted without fee, + providing that this license information and copyright notice appear with + all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes + charging money for Snes9x or software derived from Snes9x. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +*******************************************************************************/ +#include "fxemu.h" +#include "fxinst.h" +#include +#include +#include + +/* The FxChip Emulator's internal variables */ +FxRegs_s GSU = FxRegs_s_null; + +uint32 (**fx_ppfFunctionTable)(uint32) = 0; +void (**fx_ppfPlotTable)() = 0; +void (**fx_ppfOpcodeTable)() = 0; + +#if 0 +void fx_setCache() +{ + uint32 c; + GSU.bCacheActive = TRUE; + GSU.pvRegisters[0x3e] &= 0xf0; + c = (uint32)GSU.pvRegisters[0x3e]; + c |= ((uint32)GSU.pvRegisters[0x3f])<<8; + if(c == GSU.vCacheBaseReg) + return; + GSU.vCacheBaseReg = c; + GSU.vCacheFlags = 0; + if(c < (0x10000-512)) + { + uint8 const* t = &ROM(c); + memcpy(GSU.pvCache,t,512); + } + else + { + uint8 const* t1; + uint8 const* t2; + uint32 i = 0x10000 - c; + t1 = &ROM(c); + t2 = &ROM(0); + memcpy(GSU.pvCache,t1,i); + memcpy(&GSU.pvCache[i],t2,512-i); + } +} +#endif + +void FxCacheWriteAccess(uint16 vAddress) +{ +#if 0 + if(!GSU.bCacheActive) + { + uint8 v = GSU.pvCache[GSU.pvCache[vAddress&0x1ff]; + fx_setCache(); + GSU.pvCache[GSU.pvCache[vAddress&0x1ff] = v; + } +#endif + if((vAddress & 0x00f) == 0x00f) + GSU.vCacheFlags |= 1 << ((vAddress&0x1f0) >> 4); +} + +void FxFlushCache() +{ + GSU.vCacheFlags = 0; + GSU.vCacheBaseReg = 0; + GSU.bCacheActive = FALSE; +// GSU.vPipe = 0x1; +} + +static inline void fx_backupCache() +{ +#if 0 + uint32 i; + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); + if(v) + for(i=0; i<32; i++) + { + if(v&1) + { + if(c < (0x10000-16)) + { + uint8 * t = &GSU.pvPrgBank[c]; + memcpy(&GSU.avCacheBackup[i<<4],t,16); + memcpy(t,&GSU.pvCache[i<<4],16); + } + else + { + uint8 * t1; + uint8 * t2; + uint32 a = 0x10000 - c; + t1 = &GSU.pvPrgBank[c]; + t2 = &GSU.pvPrgBank[0]; + memcpy(&GSU.avCacheBackup[i<<4],t1,a); + memcpy(t1,&GSU.pvCache[i<<4],a); + memcpy(&GSU.avCacheBackup[(i<<4)+a],t2,16-a); + memcpy(t2,&GSU.pvCache[(i<<4)+a],16-a); + } + } + c = USEX16(c+16); + v >>= 1; + } +#endif +} + +static inline void fx_restoreCache() +{ +#if 0 + uint32 i; + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); + if(v) + for(i=0; i<32; i++) + { + if(v&1) + { + if(c < (0x10000-16)) + { + uint8 * t = &GSU.pvPrgBank[c]; + memcpy(t,&GSU.avCacheBackup[i<<4],16); + memcpy(&GSU.pvCache[i<<4],t,16); + } + else + { + uint8 * t1; + uint8 * t2; + uint32 a = 0x10000 - c; + t1 = &GSU.pvPrgBank[c]; + t2 = &GSU.pvPrgBank[0]; + memcpy(t1,&GSU.avCacheBackup[i<<4],a); + memcpy(&GSU.pvCache[i<<4],t1,a); + memcpy(t2,&GSU.avCacheBackup[(i<<4)+a],16-a); + memcpy(&GSU.pvCache[(i<<4)+a],t2,16-a); + } + } + c = USEX16(c+16); + v >>= 1; + } +#endif +} + +void fx_flushCache() +{ + fx_restoreCache(); + GSU.vCacheFlags = 0; + GSU.bCacheActive = FALSE; +} + + +void fx_updateRamBank(uint8 Byte) +{ + // Update BankReg and Bank pointer + GSU.vRamBankReg = (uint32)Byte & (FX_RAM_BANKS-1); + GSU.pvRamBank = GSU.apvRamBank[Byte & 0x3]; +} + + +static inline void fx_readRegisterSpace() +{ + int i; + uint8 *p; + static uint32 avHeight[] = { 128, 160, 192, 256 }; + static uint32 avMult[] = { 16, 32, 32, 64 }; + + GSU.vErrorCode = 0; + + /* Update R0-R15 */ + p = GSU.pvRegisters; + for(i=0; i<16; i++) + { + GSU.avReg[i] = *p++; + GSU.avReg[i] += ((uint32)(*p++)) << 8; + } + + /* Update other registers */ + p = GSU.pvRegisters; + GSU.vStatusReg = (uint32)p[GSU_SFR]; + GSU.vStatusReg |= ((uint32)p[GSU_SFR+1]) << 8; + GSU.vPrgBankReg = (uint32)p[GSU_PBR]; + GSU.vRomBankReg = (uint32)p[GSU_ROMBR]; + GSU.vRamBankReg = ((uint32)p[GSU_RAMBR]) & (FX_RAM_BANKS-1); + GSU.vCacheBaseReg = (uint32)p[GSU_CBR]; + GSU.vCacheBaseReg |= ((uint32)p[GSU_CBR+1]) << 8; + + /* Update status register variables */ + GSU.vZero = !(GSU.vStatusReg & FLG_Z); + GSU.vSign = (GSU.vStatusReg & FLG_S) << 12; + GSU.vOverflow = (GSU.vStatusReg & FLG_OV) << 16; + GSU.vCarry = (GSU.vStatusReg & FLG_CY) >> 2; + + /* Set bank pointers */ + GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; + GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; + GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; + + /* Set screen pointers */ + GSU.pvScreenBase = &GSU.pvRam[ USEX8(p[GSU_SCBR]) << 10 ]; + i = (int)(!!(p[GSU_SCMR] & 0x04)); + i |= ((int)(!!(p[GSU_SCMR] & 0x20))) << 1; + GSU.vScreenHeight = GSU.vScreenRealHeight = avHeight[i]; + GSU.vMode = p[GSU_SCMR] & 0x03; +#if 0 + if(GSU.vMode == 2) + error illegal color depth GSU.vMode; +#endif + if(i == 3) + GSU.vScreenSize = (256/8) * (256/8) * 32; + else + GSU.vScreenSize = (GSU.vScreenHeight/8) * (256/8) * avMult[GSU.vMode]; + if (GSU.vPlotOptionReg & 0x10) + { + /* OBJ Mode (for drawing into sprites) */ + GSU.vScreenHeight = 256; + } +#if 0 + if(GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) + error illegal address for screen base register +#else + if(GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) + GSU.pvScreenBase = GSU.pvRam + (GSU.nRamBanks * 65536) - GSU.vScreenSize; +#endif + GSU.pfPlot = fx_apfPlotTable[GSU.vMode]; + GSU.pfRpix = fx_apfPlotTable[GSU.vMode + 5]; + + fx_ppfOpcodeTable[0x04c] = GSU.pfPlot; + fx_ppfOpcodeTable[0x14c] = GSU.pfRpix; + fx_ppfOpcodeTable[0x24c] = GSU.pfPlot; + fx_ppfOpcodeTable[0x34c] = GSU.pfRpix; + + fx_computeScreenPointers (); + + fx_backupCache(); +} + +void fx_dirtySCBR() +{ + GSU.vSCBRDirty = TRUE; +} + +void fx_computeScreenPointers () +{ + if (GSU.vMode != GSU.vPrevMode || + GSU.vPrevScreenHeight != GSU.vScreenHeight || + GSU.vSCBRDirty) + { + int i; + + GSU.vSCBRDirty = FALSE; + + /* Make a list of pointers to the start of each screen column */ + switch (GSU.vScreenHeight) + { + case 128: + switch (GSU.vMode) + { + case 0: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = i << 8; + } + break; + case 1: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); + GSU.x[i] = i << 9; + } + break; + case 2: + case 3: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); + GSU.x[i] = i << 10; + } + break; + } + break; + case 160: + switch (GSU.vMode) + { + case 0: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = (i << 8) + (i << 6); + } + break; + case 1: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); + GSU.x[i] = (i << 9) + (i << 7); + } + break; + case 2: + case 3: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); + GSU.x[i] = (i << 10) + (i << 8); + } + break; + } + break; + case 192: + switch (GSU.vMode) + { + case 0: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = (i << 8) + (i << 7); + } + break; + case 1: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); + GSU.x[i] = (i << 9) + (i << 8); + } + break; + case 2: + case 3: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); + GSU.x[i] = (i << 10) + (i << 9); + } + break; + } + break; + case 256: + switch (GSU.vMode) + { + case 0: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + + ((i & 0x10) << 9) + ((i & 0xf) << 8); + GSU.x[i] = ((i & 0x10) << 8) + ((i & 0xf) << 4); + } + break; + case 1: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + + ((i & 0x10) << 10) + ((i & 0xf) << 9); + GSU.x[i] = ((i & 0x10) << 9) + ((i & 0xf) << 5); + } + break; + case 2: + case 3: + for (i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + + ((i & 0x10) << 11) + ((i & 0xf) << 10); + GSU.x[i] = ((i & 0x10) << 10) + ((i & 0xf) << 6); + } + break; + } + break; + } + GSU.vPrevMode = GSU.vMode; + GSU.vPrevScreenHeight = GSU.vScreenHeight; + } +} + +static inline void fx_writeRegisterSpace() +{ + int i; + uint8 *p; + + p = GSU.pvRegisters; + for(i=0; i<16; i++) + { + *p++ = (uint8)GSU.avReg[i]; + *p++ = (uint8)(GSU.avReg[i] >> 8); + } + + /* Update status register */ + if( USEX16(GSU.vZero) == 0 ) SF(Z); + else CF(Z); + if( GSU.vSign & 0x8000 ) SF(S); + else CF(S); + if(GSU.vOverflow >= 0x8000 || GSU.vOverflow < -0x8000) SF(OV); + else CF(OV); + if(GSU.vCarry) SF(CY); + else CF(CY); + + p = GSU.pvRegisters; + p[GSU_SFR] = (uint8)GSU.vStatusReg; + p[GSU_SFR+1] = (uint8)(GSU.vStatusReg>>8); + p[GSU_PBR] = (uint8)GSU.vPrgBankReg; + p[GSU_ROMBR] = (uint8)GSU.vRomBankReg; + p[GSU_RAMBR] = (uint8)GSU.vRamBankReg; + p[GSU_CBR] = (uint8)GSU.vCacheBaseReg; + p[GSU_CBR+1] = (uint8)(GSU.vCacheBaseReg>>8); + + fx_restoreCache(); +} + +/* Reset the FxChip */ +void FxReset(FxInit_s *psFxInfo) +{ + int i; + static uint32 (**appfFunction[])(uint32) = { + &fx_apfFunctionTable[0], +#if 0 + &fx_a_apfFunctionTable[0], + &fx_r_apfFunctionTable[0], + &fx_ar_apfFunctionTable[0], +#endif + }; + static void (**appfPlot[])() = { + &fx_apfPlotTable[0], +#if 0 + &fx_a_apfPlotTable[0], + &fx_r_apfPlotTable[0], + &fx_ar_apfPlotTable[0], +#endif + }; + static void (**appfOpcode[])() = { + &fx_apfOpcodeTable[0], +#if 0 + &fx_a_apfOpcodeTable[0], + &fx_r_apfOpcodeTable[0], + &fx_ar_apfOpcodeTable[0], +#endif + }; + + /* Get function pointers for the current emulation mode */ + fx_ppfFunctionTable = appfFunction[psFxInfo->vFlags & 0x3]; + fx_ppfPlotTable = appfPlot[psFxInfo->vFlags & 0x3]; + fx_ppfOpcodeTable = appfOpcode[psFxInfo->vFlags & 0x3]; + + /* Clear all internal variables */ + memset((uint8*)&GSU,0,sizeof(FxRegs_s)); + + /* Set default registers */ + GSU.pvSreg = GSU.pvDreg = &R0; + + /* Set RAM and ROM pointers */ + GSU.pvRegisters = psFxInfo->pvRegisters; + GSU.nRamBanks = psFxInfo->nRamBanks; + GSU.pvRam = psFxInfo->pvRam; + GSU.nRomBanks = psFxInfo->nRomBanks; + GSU.pvRom = psFxInfo->pvRom; + GSU.vPrevScreenHeight = ~0; + GSU.vPrevMode = ~0; + + /* The GSU can't access more than 2mb (16mbits) */ + if(GSU.nRomBanks > 0x20) + GSU.nRomBanks = 0x20; + + /* Clear FxChip register space */ + memset(GSU.pvRegisters,0,0x300); + + /* Set FxChip version Number */ + GSU.pvRegisters[0x3b] = 0; + + /* Make ROM bank table */ + for(i=0; i<256; i++) + { + uint32 b = i & 0x7f; + if (b >= 0x40) + { + if (GSU.nRomBanks > 1) + b %= GSU.nRomBanks; + else + b &= 1; + + GSU.apvRomBank[i] = &GSU.pvRom[ b << 16 ]; + } + else + { + b %= GSU.nRomBanks * 2; + GSU.apvRomBank[i] = &GSU.pvRom[ (b << 16) + 0x200000]; + } + } + + /* Make RAM bank table */ + for(i=0; i<4; i++) + { + GSU.apvRamBank[i] = &GSU.pvRam[(i % GSU.nRamBanks) << 16]; + GSU.apvRomBank[0x70 + i] = GSU.apvRamBank[i]; + } + + /* Start with a nop in the pipe */ + GSU.vPipe = 0x01; + + /* Set pointer to GSU cache */ + GSU.pvCache = &GSU.pvRegisters[0x100]; + + fx_readRegisterSpace(); +} + +static uint8 fx_checkStartAddress() +{ + /* Check if we start inside the cache */ + if(GSU.bCacheActive && R15 >= GSU.vCacheBaseReg && R15 < (GSU.vCacheBaseReg+512)) + return TRUE; + + /* Check if we're in an unused area */ + if(GSU.vPrgBankReg < 0x40 && R15 < 0x8000) + return FALSE; + if(GSU.vPrgBankReg >= 0x60 && GSU.vPrgBankReg <= 0x6f) + return FALSE; + if(GSU.vPrgBankReg >= 0x74) + return FALSE; + + /* Check if we're in RAM and the RAN flag is not set */ + if(GSU.vPrgBankReg >= 0x70 && GSU.vPrgBankReg <= 0x73 && !(SCMR&(1<<3)) ) + return FALSE; + + /* If not, we're in ROM, so check if the RON flag is set */ + if(!(SCMR&(1<<4))) + return FALSE; + + return TRUE; +} + +/* Execute until the next stop instruction */ +int FxEmulate(uint32 nInstructions) +{ + uint32 vCount; + + /* Read registers and initialize GSU session */ + fx_readRegisterSpace(); + + /* Check if the start address is valid */ + if(!fx_checkStartAddress()) + { + CF(G); + fx_writeRegisterSpace(); + return 0; + } + + /* Execute GSU session */ + CF(IRQ); + + if(GSU.bBreakPoint) + vCount = fx_ppfFunctionTable[FX_FUNCTION_RUN_TO_BREAKPOINT](nInstructions); + else + vCount = fx_ppfFunctionTable[FX_FUNCTION_RUN](nInstructions); + + /* Store GSU registers */ + fx_writeRegisterSpace(); + + /* Check for error code */ + if(GSU.vErrorCode) + return GSU.vErrorCode; + else + return vCount; +} + +/* Breakpoints */ +void FxBreakPointSet(uint32 vAddress) +{ + GSU.bBreakPoint = TRUE; + GSU.vBreakPoint = USEX16(vAddress); +} +void FxBreakPointClear() +{ + GSU.bBreakPoint = FALSE; +} + +/* Step by step execution */ +int FxStepOver(uint32 nInstructions) +{ + uint32 vCount; + fx_readRegisterSpace(); + + /* Check if the start address is valid */ + if(!fx_checkStartAddress()) + { + CF(G); +#if 0 + GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; + return FX_ERROR_ILLEGAL_ADDRESS; +#else + return 0; +#endif + } + + if( PIPE >= 0xf0 ) + GSU.vStepPoint = USEX16(R15+3); + else if( (PIPE >= 0x05 && PIPE <= 0x0f) || (PIPE >= 0xa0 && PIPE <= 0xaf) ) + GSU.vStepPoint = USEX16(R15+2); + else + GSU.vStepPoint = USEX16(R15+1); + vCount = fx_ppfFunctionTable[FX_FUNCTION_STEP_OVER](nInstructions); + fx_writeRegisterSpace(); + if(GSU.vErrorCode) + return GSU.vErrorCode; + else + return vCount; +} + +/* Errors */ +int FxGetErrorCode() +{ + return GSU.vErrorCode; +} + +int FxGetIllegalAddress() +{ + return GSU.vIllegalAddress; +} + +/* Access to internal registers */ +uint32 FxGetColorRegister() +{ + return GSU.vColorReg & 0xff; +} + +uint32 FxGetPlotOptionRegister() +{ + return GSU.vPlotOptionReg & 0x1f; +} + +uint32 FxGetSourceRegisterIndex() +{ + return GSU.pvSreg - GSU.avReg; +} + +uint32 FxGetDestinationRegisterIndex() +{ + return GSU.pvDreg - GSU.avReg; +} + +uint8 FxPipe() +{ + return GSU.vPipe; +} + diff --git a/src/fxemu.cpp b/src/fxemu.cpp deleted file mode 100644 index b958862..0000000 --- a/src/fxemu.cpp +++ /dev/null @@ -1,721 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ -#include "fxemu.h" -#include "fxinst.h" -#include -#include -#include - -/* The FxChip Emulator's internal variables */ -struct FxRegs_s GSU = FxRegs_s_null; - -uint32 (**fx_ppfFunctionTable)(uint32) = 0; -void (**fx_ppfPlotTable)() = 0; -void (**fx_ppfOpcodeTable)() = 0; - -#if 0 -void fx_setCache() -{ - uint32 c; - GSU.bCacheActive = TRUE; - GSU.pvRegisters[0x3e] &= 0xf0; - c = (uint32)GSU.pvRegisters[0x3e]; - c |= ((uint32)GSU.pvRegisters[0x3f])<<8; - if(c == GSU.vCacheBaseReg) - return; - GSU.vCacheBaseReg = c; - GSU.vCacheFlags = 0; - if(c < (0x10000-512)) - { - uint8 const* t = &ROM(c); - memcpy(GSU.pvCache,t,512); - } - else - { - uint8 const* t1; - uint8 const* t2; - uint32 i = 0x10000 - c; - t1 = &ROM(c); - t2 = &ROM(0); - memcpy(GSU.pvCache,t1,i); - memcpy(&GSU.pvCache[i],t2,512-i); - } -} -#endif - -void FxCacheWriteAccess(uint16 vAddress) -{ -#if 0 - if(!GSU.bCacheActive) - { - uint8 v = GSU.pvCache[GSU.pvCache[vAddress&0x1ff]; - fx_setCache(); - GSU.pvCache[GSU.pvCache[vAddress&0x1ff] = v; - } -#endif - if((vAddress & 0x00f) == 0x00f) - GSU.vCacheFlags |= 1 << ((vAddress&0x1f0) >> 4); -} - -void FxFlushCache() -{ - GSU.vCacheFlags = 0; - GSU.vCacheBaseReg = 0; - GSU.bCacheActive = FALSE; -// GSU.vPipe = 0x1; -} - -static inline void fx_backupCache() -{ -#if 0 - uint32 i; - uint32 v = GSU.vCacheFlags; - uint32 c = USEX16(GSU.vCacheBaseReg); - if(v) - for(i=0; i<32; i++) - { - if(v&1) - { - if(c < (0x10000-16)) - { - uint8 * t = &GSU.pvPrgBank[c]; - memcpy(&GSU.avCacheBackup[i<<4],t,16); - memcpy(t,&GSU.pvCache[i<<4],16); - } - else - { - uint8 * t1; - uint8 * t2; - uint32 a = 0x10000 - c; - t1 = &GSU.pvPrgBank[c]; - t2 = &GSU.pvPrgBank[0]; - memcpy(&GSU.avCacheBackup[i<<4],t1,a); - memcpy(t1,&GSU.pvCache[i<<4],a); - memcpy(&GSU.avCacheBackup[(i<<4)+a],t2,16-a); - memcpy(t2,&GSU.pvCache[(i<<4)+a],16-a); - } - } - c = USEX16(c+16); - v >>= 1; - } -#endif -} - -static inline void fx_restoreCache() -{ -#if 0 - uint32 i; - uint32 v = GSU.vCacheFlags; - uint32 c = USEX16(GSU.vCacheBaseReg); - if(v) - for(i=0; i<32; i++) - { - if(v&1) - { - if(c < (0x10000-16)) - { - uint8 * t = &GSU.pvPrgBank[c]; - memcpy(t,&GSU.avCacheBackup[i<<4],16); - memcpy(&GSU.pvCache[i<<4],t,16); - } - else - { - uint8 * t1; - uint8 * t2; - uint32 a = 0x10000 - c; - t1 = &GSU.pvPrgBank[c]; - t2 = &GSU.pvPrgBank[0]; - memcpy(t1,&GSU.avCacheBackup[i<<4],a); - memcpy(&GSU.pvCache[i<<4],t1,a); - memcpy(t2,&GSU.avCacheBackup[(i<<4)+a],16-a); - memcpy(&GSU.pvCache[(i<<4)+a],t2,16-a); - } - } - c = USEX16(c+16); - v >>= 1; - } -#endif -} - -void fx_flushCache() -{ - fx_restoreCache(); - GSU.vCacheFlags = 0; - GSU.bCacheActive = FALSE; -} - - -void fx_updateRamBank(uint8 Byte) -{ - // Update BankReg and Bank pointer - GSU.vRamBankReg = (uint32)Byte & (FX_RAM_BANKS-1); - GSU.pvRamBank = GSU.apvRamBank[Byte & 0x3]; -} - - -static inline void fx_readRegisterSpace() -{ - int i; - uint8 *p; - static uint32 avHeight[] = { 128, 160, 192, 256 }; - static uint32 avMult[] = { 16, 32, 32, 64 }; - - GSU.vErrorCode = 0; - - /* Update R0-R15 */ - p = GSU.pvRegisters; - for(i=0; i<16; i++) - { - GSU.avReg[i] = *p++; - GSU.avReg[i] += ((uint32)(*p++)) << 8; - } - - /* Update other registers */ - p = GSU.pvRegisters; - GSU.vStatusReg = (uint32)p[GSU_SFR]; - GSU.vStatusReg |= ((uint32)p[GSU_SFR+1]) << 8; - GSU.vPrgBankReg = (uint32)p[GSU_PBR]; - GSU.vRomBankReg = (uint32)p[GSU_ROMBR]; - GSU.vRamBankReg = ((uint32)p[GSU_RAMBR]) & (FX_RAM_BANKS-1); - GSU.vCacheBaseReg = (uint32)p[GSU_CBR]; - GSU.vCacheBaseReg |= ((uint32)p[GSU_CBR+1]) << 8; - - /* Update status register variables */ - GSU.vZero = !(GSU.vStatusReg & FLG_Z); - GSU.vSign = (GSU.vStatusReg & FLG_S) << 12; - GSU.vOverflow = (GSU.vStatusReg & FLG_OV) << 16; - GSU.vCarry = (GSU.vStatusReg & FLG_CY) >> 2; - - /* Set bank pointers */ - GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; - GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; - GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; - - /* Set screen pointers */ - GSU.pvScreenBase = &GSU.pvRam[ USEX8(p[GSU_SCBR]) << 10 ]; - i = (int)(!!(p[GSU_SCMR] & 0x04)); - i |= ((int)(!!(p[GSU_SCMR] & 0x20))) << 1; - GSU.vScreenHeight = GSU.vScreenRealHeight = avHeight[i]; - GSU.vMode = p[GSU_SCMR] & 0x03; -#if 0 - if(GSU.vMode == 2) - error illegal color depth GSU.vMode; -#endif - if(i == 3) - GSU.vScreenSize = (256/8) * (256/8) * 32; - else - GSU.vScreenSize = (GSU.vScreenHeight/8) * (256/8) * avMult[GSU.vMode]; - if (GSU.vPlotOptionReg & 0x10) - { - /* OBJ Mode (for drawing into sprites) */ - GSU.vScreenHeight = 256; - } -#if 0 - if(GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) - error illegal address for screen base register -#else - if(GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) - GSU.pvScreenBase = GSU.pvRam + (GSU.nRamBanks * 65536) - GSU.vScreenSize; -#endif - GSU.pfPlot = fx_apfPlotTable[GSU.vMode]; - GSU.pfRpix = fx_apfPlotTable[GSU.vMode + 5]; - - fx_ppfOpcodeTable[0x04c] = GSU.pfPlot; - fx_ppfOpcodeTable[0x14c] = GSU.pfRpix; - fx_ppfOpcodeTable[0x24c] = GSU.pfPlot; - fx_ppfOpcodeTable[0x34c] = GSU.pfRpix; - - fx_computeScreenPointers (); - - fx_backupCache(); -} - -void fx_dirtySCBR() -{ - GSU.vSCBRDirty = TRUE; -} - -void fx_computeScreenPointers () -{ - if (GSU.vMode != GSU.vPrevMode || - GSU.vPrevScreenHeight != GSU.vScreenHeight || - GSU.vSCBRDirty) - { - int i; - - GSU.vSCBRDirty = FALSE; - - /* Make a list of pointers to the start of each screen column */ - switch (GSU.vScreenHeight) - { - case 128: - switch (GSU.vMode) - { - case 0: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); - GSU.x[i] = i << 8; - } - break; - case 1: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); - GSU.x[i] = i << 9; - } - break; - case 2: - case 3: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); - GSU.x[i] = i << 10; - } - break; - } - break; - case 160: - switch (GSU.vMode) - { - case 0: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); - GSU.x[i] = (i << 8) + (i << 6); - } - break; - case 1: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); - GSU.x[i] = (i << 9) + (i << 7); - } - break; - case 2: - case 3: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); - GSU.x[i] = (i << 10) + (i << 8); - } - break; - } - break; - case 192: - switch (GSU.vMode) - { - case 0: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); - GSU.x[i] = (i << 8) + (i << 7); - } - break; - case 1: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); - GSU.x[i] = (i << 9) + (i << 8); - } - break; - case 2: - case 3: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + (i << 6); - GSU.x[i] = (i << 10) + (i << 9); - } - break; - } - break; - case 256: - switch (GSU.vMode) - { - case 0: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + - ((i & 0x10) << 9) + ((i & 0xf) << 8); - GSU.x[i] = ((i & 0x10) << 8) + ((i & 0xf) << 4); - } - break; - case 1: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + - ((i & 0x10) << 10) + ((i & 0xf) << 9); - GSU.x[i] = ((i & 0x10) << 9) + ((i & 0xf) << 5); - } - break; - case 2: - case 3: - for (i = 0; i < 32; i++) - { - GSU.apvScreen[i] = GSU.pvScreenBase + - ((i & 0x10) << 11) + ((i & 0xf) << 10); - GSU.x[i] = ((i & 0x10) << 10) + ((i & 0xf) << 6); - } - break; - } - break; - } - GSU.vPrevMode = GSU.vMode; - GSU.vPrevScreenHeight = GSU.vScreenHeight; - } -} - -static inline void fx_writeRegisterSpace() -{ - int i; - uint8 *p; - - p = GSU.pvRegisters; - for(i=0; i<16; i++) - { - *p++ = (uint8)GSU.avReg[i]; - *p++ = (uint8)(GSU.avReg[i] >> 8); - } - - /* Update status register */ - if( USEX16(GSU.vZero) == 0 ) SF(Z); - else CF(Z); - if( GSU.vSign & 0x8000 ) SF(S); - else CF(S); - if(GSU.vOverflow >= 0x8000 || GSU.vOverflow < -0x8000) SF(OV); - else CF(OV); - if(GSU.vCarry) SF(CY); - else CF(CY); - - p = GSU.pvRegisters; - p[GSU_SFR] = (uint8)GSU.vStatusReg; - p[GSU_SFR+1] = (uint8)(GSU.vStatusReg>>8); - p[GSU_PBR] = (uint8)GSU.vPrgBankReg; - p[GSU_ROMBR] = (uint8)GSU.vRomBankReg; - p[GSU_RAMBR] = (uint8)GSU.vRamBankReg; - p[GSU_CBR] = (uint8)GSU.vCacheBaseReg; - p[GSU_CBR+1] = (uint8)(GSU.vCacheBaseReg>>8); - - fx_restoreCache(); -} - -/* Reset the FxChip */ -void FxReset(struct FxInit_s *psFxInfo) -{ - int i; - static uint32 (**appfFunction[])(uint32) = { - &fx_apfFunctionTable[0], -#if 0 - &fx_a_apfFunctionTable[0], - &fx_r_apfFunctionTable[0], - &fx_ar_apfFunctionTable[0], -#endif - }; - static void (**appfPlot[])() = { - &fx_apfPlotTable[0], -#if 0 - &fx_a_apfPlotTable[0], - &fx_r_apfPlotTable[0], - &fx_ar_apfPlotTable[0], -#endif - }; - static void (**appfOpcode[])() = { - &fx_apfOpcodeTable[0], -#if 0 - &fx_a_apfOpcodeTable[0], - &fx_r_apfOpcodeTable[0], - &fx_ar_apfOpcodeTable[0], -#endif - }; - - /* Get function pointers for the current emulation mode */ - fx_ppfFunctionTable = appfFunction[psFxInfo->vFlags & 0x3]; - fx_ppfPlotTable = appfPlot[psFxInfo->vFlags & 0x3]; - fx_ppfOpcodeTable = appfOpcode[psFxInfo->vFlags & 0x3]; - - /* Clear all internal variables */ - memset((uint8*)&GSU,0,sizeof(struct FxRegs_s)); - - /* Set default registers */ - GSU.pvSreg = GSU.pvDreg = &R0; - - /* Set RAM and ROM pointers */ - GSU.pvRegisters = psFxInfo->pvRegisters; - GSU.nRamBanks = psFxInfo->nRamBanks; - GSU.pvRam = psFxInfo->pvRam; - GSU.nRomBanks = psFxInfo->nRomBanks; - GSU.pvRom = psFxInfo->pvRom; - GSU.vPrevScreenHeight = ~0; - GSU.vPrevMode = ~0; - - /* The GSU can't access more than 2mb (16mbits) */ - if(GSU.nRomBanks > 0x20) - GSU.nRomBanks = 0x20; - - /* Clear FxChip register space */ - memset(GSU.pvRegisters,0,0x300); - - /* Set FxChip version Number */ - GSU.pvRegisters[0x3b] = 0; - - /* Make ROM bank table */ - for(i=0; i<256; i++) - { - uint32 b = i & 0x7f; - if (b >= 0x40) - { - if (GSU.nRomBanks > 1) - b %= GSU.nRomBanks; - else - b &= 1; - - GSU.apvRomBank[i] = &GSU.pvRom[ b << 16 ]; - } - else - { - b %= GSU.nRomBanks * 2; - GSU.apvRomBank[i] = &GSU.pvRom[ (b << 16) + 0x200000]; - } - } - - /* Make RAM bank table */ - for(i=0; i<4; i++) - { - GSU.apvRamBank[i] = &GSU.pvRam[(i % GSU.nRamBanks) << 16]; - GSU.apvRomBank[0x70 + i] = GSU.apvRamBank[i]; - } - - /* Start with a nop in the pipe */ - GSU.vPipe = 0x01; - - /* Set pointer to GSU cache */ - GSU.pvCache = &GSU.pvRegisters[0x100]; - - fx_readRegisterSpace(); -} - -static uint8 fx_checkStartAddress() -{ - /* Check if we start inside the cache */ - if(GSU.bCacheActive && R15 >= GSU.vCacheBaseReg && R15 < (GSU.vCacheBaseReg+512)) - return TRUE; - - /* Check if we're in an unused area */ - if(GSU.vPrgBankReg < 0x40 && R15 < 0x8000) - return FALSE; - if(GSU.vPrgBankReg >= 0x60 && GSU.vPrgBankReg <= 0x6f) - return FALSE; - if(GSU.vPrgBankReg >= 0x74) - return FALSE; - - /* Check if we're in RAM and the RAN flag is not set */ - if(GSU.vPrgBankReg >= 0x70 && GSU.vPrgBankReg <= 0x73 && !(SCMR&(1<<3)) ) - return FALSE; - - /* If not, we're in ROM, so check if the RON flag is set */ - if(!(SCMR&(1<<4))) - return FALSE; - - return TRUE; -} - -/* Execute until the next stop instruction */ -int FxEmulate(uint32 nInstructions) -{ - uint32 vCount; - - /* Read registers and initialize GSU session */ - fx_readRegisterSpace(); - - /* Check if the start address is valid */ - if(!fx_checkStartAddress()) - { - CF(G); - fx_writeRegisterSpace(); - return 0; - } - - /* Execute GSU session */ - CF(IRQ); - - if(GSU.bBreakPoint) - vCount = fx_ppfFunctionTable[FX_FUNCTION_RUN_TO_BREAKPOINT](nInstructions); - else - vCount = fx_ppfFunctionTable[FX_FUNCTION_RUN](nInstructions); - - /* Store GSU registers */ - fx_writeRegisterSpace(); - - /* Check for error code */ - if(GSU.vErrorCode) - return GSU.vErrorCode; - else - return vCount; -} - -/* Breakpoints */ -void FxBreakPointSet(uint32 vAddress) -{ - GSU.bBreakPoint = TRUE; - GSU.vBreakPoint = USEX16(vAddress); -} -void FxBreakPointClear() -{ - GSU.bBreakPoint = FALSE; -} - -/* Step by step execution */ -int FxStepOver(uint32 nInstructions) -{ - uint32 vCount; - fx_readRegisterSpace(); - - /* Check if the start address is valid */ - if(!fx_checkStartAddress()) - { - CF(G); -#if 0 - GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; - return FX_ERROR_ILLEGAL_ADDRESS; -#else - return 0; -#endif - } - - if( PIPE >= 0xf0 ) - GSU.vStepPoint = USEX16(R15+3); - else if( (PIPE >= 0x05 && PIPE <= 0x0f) || (PIPE >= 0xa0 && PIPE <= 0xaf) ) - GSU.vStepPoint = USEX16(R15+2); - else - GSU.vStepPoint = USEX16(R15+1); - vCount = fx_ppfFunctionTable[FX_FUNCTION_STEP_OVER](nInstructions); - fx_writeRegisterSpace(); - if(GSU.vErrorCode) - return GSU.vErrorCode; - else - return vCount; -} - -/* Errors */ -int FxGetErrorCode() -{ - return GSU.vErrorCode; -} - -int FxGetIllegalAddress() -{ - return GSU.vIllegalAddress; -} - -/* Access to internal registers */ -uint32 FxGetColorRegister() -{ - return GSU.vColorReg & 0xff; -} - -uint32 FxGetPlotOptionRegister() -{ - return GSU.vPlotOptionReg & 0x1f; -} - -uint32 FxGetSourceRegisterIndex() -{ - return GSU.pvSreg - GSU.avReg; -} - -uint32 FxGetDestinationRegisterIndex() -{ - return GSU.pvDreg - GSU.avReg; -} - -uint8 FxPipe() -{ - return GSU.vPipe; -} - diff --git a/src/fxemu.h b/src/fxemu.h index 01ce839..00fc41a 100644 --- a/src/fxemu.h +++ b/src/fxemu.h @@ -112,7 +112,7 @@ typedef int int32; #endif /* The FxInfo_s structure, the link between the FxEmulator and the Snes Emulator */ -struct FxInit_s +typedef struct { uint32 vFlags; uint8 * pvRegisters; /* 768 bytes located in the memory at address 0x3000 */ @@ -120,10 +120,10 @@ struct FxInit_s uint8 * pvRam; /* Pointer to GSU-RAM */ uint32 nRomBanks; /* Number of 32kb-banks in Cart-ROM */ uint8 * pvRom; /* Pointer to Cart-ROM */ -}; +}FxInit_s; /* Reset the FxChip */ -extern void FxReset(struct FxInit_s *psFxInfo); +extern void FxReset(FxInit_s *psFxInfo); /* Execute until the next stop instruction */ extern int FxEmulate(uint32 nInstructions); diff --git a/src/fxinst.c b/src/fxinst.c new file mode 100644 index 0000000..ec21723 --- /dev/null +++ b/src/fxinst.c @@ -0,0 +1,1916 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and distribute Snes9x in both binary and + source form, for non-commercial purposes, is hereby granted without fee, + providing that this license information and copyright notice appear with + all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes + charging money for Snes9x or software derived from Snes9x. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +*******************************************************************************/ +#define FX_DO_ROMBUFFER + +#include "fxemu.h" +#include "fxinst.h" +#include +#include + +extern FxRegs_s GSU; +int gsu_bank [512] = {0}; + +/* Set this define if you wish the plot instruction to check for y-pos limits */ +/* (I don't think it's nessecary) */ +#define CHECK_LIMITS + +/* Codes used: + * + * rn = a GSU register (r0-r15) + * #n = 4 bit immediate value + * #pp = 8 bit immediate value + * (yy) = 8 bit word address (0x0000 - 0x01fe) + * #xx = 16 bit immediate value + * (xx) = 16 bit address (0x0000 - 0xffff) + * + */ + +/* 00 - stop - stop GSU execution (and maybe generate an IRQ) */ +static inline void fx_stop() +{ + CF(G); + GSU.vCounter = 0; + GSU.vInstCount = GSU.vCounter; + + /* Check if we need to generate an IRQ */ + if(!(GSU.pvRegisters[GSU_CFGR] & 0x80)) + SF(IRQ); + + GSU.vPlotOptionReg = 0; + GSU.vPipe = 1; + CLRFLAGS; + R15++; +} + +/* 01 - nop - no operation */ +static inline void fx_nop() { CLRFLAGS; R15++; } + +extern void fx_flushCache(); + +/* 02 - cache - reintialize GSU cache */ +static inline void fx_cache() +{ + uint32 c = R15 & 0xfff0; + if(GSU.vCacheBaseReg != c || !GSU.bCacheActive) + { + fx_flushCache(); + GSU.vCacheBaseReg = c; + GSU.bCacheActive = TRUE; +#if 0 + if(c < (0x10000-512)) + { + uint8 const* t = &ROM(c); + memcpy(GSU.pvCache,t,512); + } + else + { + uint8 const* t1; + uint8 const* t2; + uint32 i = 0x10000 - c; + t1 = &ROM(c); + t2 = &ROM(0); + memcpy(GSU.pvCache,t1,i); + memcpy(&GSU.pvCache[i],t2,512-i); + } +#endif + } + R15++; + CLRFLAGS; +} + +/* 03 - lsr - logic shift right */ +static inline void fx_lsr() +{ + uint32 v; + GSU.vCarry = SREG & 1; + v = USEX16(SREG) >> 1; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +/* 04 - rol - rotate left */ +static inline void fx_rol() +{ + uint32 v = USEX16((SREG << 1) + GSU.vCarry); + GSU.vCarry = (SREG >> 15) & 1; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +/* 05 - bra - branch always */ +static inline void fx_bra() { uint8 v = PIPE; R15++; FETCHPIPE; R15 += SEX8(v); } + +/* Branch on condition */ +#define BRA_COND(cond) uint8 v = PIPE; R15++; FETCHPIPE; if(cond) R15 += SEX8(v); else R15++; + +#define TEST_S (GSU.vSign & 0x8000) +#define TEST_Z (USEX16(GSU.vZero) == 0) +#define TEST_OV (GSU.vOverflow >= 0x8000 || GSU.vOverflow < -0x8000) +#define TEST_CY (GSU.vCarry & 1) + +/* 06 - blt - branch on less than */ +static inline void fx_blt() { BRA_COND( (TEST_S!=0) != (TEST_OV!=0) ); } + +/* 07 - bge - branch on greater or equals */ +static inline void fx_bge() { BRA_COND( (TEST_S!=0) == (TEST_OV!=0)); } + +/* 08 - bne - branch on not equal */ +static inline void fx_bne() { BRA_COND( !TEST_Z ); } + +/* 09 - beq - branch on equal */ +static inline void fx_beq() { BRA_COND( TEST_Z ); } + +/* 0a - bpl - branch on plus */ +static inline void fx_bpl() { BRA_COND( !TEST_S ); } + +/* 0b - bmi - branch on minus */ +static inline void fx_bmi() { BRA_COND( TEST_S ); } + +/* 0c - bcc - branch on carry clear */ +static inline void fx_bcc() { BRA_COND( !TEST_CY ); } + +/* 0d - bcs - branch on carry set */ +static inline void fx_bcs() { BRA_COND( TEST_CY ); } + +/* 0e - bvc - branch on overflow clear */ +static inline void fx_bvc() { BRA_COND( !TEST_OV ); } + +/* 0f - bvs - branch on overflow set */ +static inline void fx_bvs() { BRA_COND( TEST_OV ); } + +/* 10-1f - to rn - set register n as destination register */ +/* 10-1f(B) - move rn - move one register to another (if B flag is set) */ +#define FX_TO(reg) \ +if(TF(B)) { GSU.avReg[(reg)] = SREG; CLRFLAGS; } \ +else { GSU.pvDreg = &GSU.avReg[reg]; } R15++; +#define FX_TO_R14(reg) \ +if(TF(B)) { GSU.avReg[(reg)] = SREG; CLRFLAGS; READR14; } \ +else { GSU.pvDreg = &GSU.avReg[reg]; } R15++; +#define FX_TO_R15(reg) \ +if(TF(B)) { GSU.avReg[(reg)] = SREG; CLRFLAGS; } \ +else { GSU.pvDreg = &GSU.avReg[reg]; R15++; } +static inline void fx_to_r0() { FX_TO(0); } +static inline void fx_to_r1() { FX_TO(1); } +static inline void fx_to_r2() { FX_TO(2); } +static inline void fx_to_r3() { FX_TO(3); } +static inline void fx_to_r4() { FX_TO(4); } +static inline void fx_to_r5() { FX_TO(5); } +static inline void fx_to_r6() { FX_TO(6); } +static inline void fx_to_r7() { FX_TO(7); } +static inline void fx_to_r8() { FX_TO(8); } +static inline void fx_to_r9() { FX_TO(9); } +static inline void fx_to_r10() { FX_TO(10); } +static inline void fx_to_r11() { FX_TO(11); } +static inline void fx_to_r12() { FX_TO(12); } +static inline void fx_to_r13() { FX_TO(13); } +static inline void fx_to_r14() { FX_TO_R14(14); } +static inline void fx_to_r15() { FX_TO_R15(15); } + +/* 20-2f - to rn - set register n as source and destination register */ +#define FX_WITH(reg) SF(B); GSU.pvSreg = GSU.pvDreg = &GSU.avReg[reg]; R15++; +static inline void fx_with_r0() { FX_WITH(0); } +static inline void fx_with_r1() { FX_WITH(1); } +static inline void fx_with_r2() { FX_WITH(2); } +static inline void fx_with_r3() { FX_WITH(3); } +static inline void fx_with_r4() { FX_WITH(4); } +static inline void fx_with_r5() { FX_WITH(5); } +static inline void fx_with_r6() { FX_WITH(6); } +static inline void fx_with_r7() { FX_WITH(7); } +static inline void fx_with_r8() { FX_WITH(8); } +static inline void fx_with_r9() { FX_WITH(9); } +static inline void fx_with_r10() { FX_WITH(10); } +static inline void fx_with_r11() { FX_WITH(11); } +static inline void fx_with_r12() { FX_WITH(12); } +static inline void fx_with_r13() { FX_WITH(13); } +static inline void fx_with_r14() { FX_WITH(14); } +static inline void fx_with_r15() { FX_WITH(15); } + +/* 30-3b - stw (rn) - store word */ +#define FX_STW(reg) \ +GSU.vLastRamAdr = GSU.avReg[reg]; \ +RAM(GSU.avReg[reg]) = (uint8)SREG; \ +RAM(GSU.avReg[reg]^1) = (uint8)(SREG>>8); \ +CLRFLAGS; R15++ +static inline void fx_stw_r0() { FX_STW(0); } +static inline void fx_stw_r1() { FX_STW(1); } +static inline void fx_stw_r2() { FX_STW(2); } +static inline void fx_stw_r3() { FX_STW(3); } +static inline void fx_stw_r4() { FX_STW(4); } +static inline void fx_stw_r5() { FX_STW(5); } +static inline void fx_stw_r6() { FX_STW(6); } +static inline void fx_stw_r7() { FX_STW(7); } +static inline void fx_stw_r8() { FX_STW(8); } +static inline void fx_stw_r9() { FX_STW(9); } +static inline void fx_stw_r10() { FX_STW(10); } +static inline void fx_stw_r11() { FX_STW(11); } + +/* 30-3b(ALT1) - stb (rn) - store byte */ +#define FX_STB(reg) \ +GSU.vLastRamAdr = GSU.avReg[reg]; \ +RAM(GSU.avReg[reg]) = (uint8)SREG; \ +CLRFLAGS; R15++ +static inline void fx_stb_r0() { FX_STB(0); } +static inline void fx_stb_r1() { FX_STB(1); } +static inline void fx_stb_r2() { FX_STB(2); } +static inline void fx_stb_r3() { FX_STB(3); } +static inline void fx_stb_r4() { FX_STB(4); } +static inline void fx_stb_r5() { FX_STB(5); } +static inline void fx_stb_r6() { FX_STB(6); } +static inline void fx_stb_r7() { FX_STB(7); } +static inline void fx_stb_r8() { FX_STB(8); } +static inline void fx_stb_r9() { FX_STB(9); } +static inline void fx_stb_r10() { FX_STB(10); } +static inline void fx_stb_r11() { FX_STB(11); } + +/* 3c - loop - decrement loop counter, and branch on not zero */ +static inline void fx_loop() +{ + GSU.vSign = GSU.vZero = --R12; + if( (uint16) R12 != 0 ) + R15 = R13; + else + R15++; + + CLRFLAGS; +} + +/* 3d - alt1 - set alt1 mode */ +static inline void fx_alt1() { SF(ALT1); CF(B); R15++; } + +/* 3e - alt2 - set alt2 mode */ +static inline void fx_alt2() { SF(ALT2); CF(B); R15++; } + +/* 3f - alt3 - set alt3 mode */ +static inline void fx_alt3() { SF(ALT1); SF(ALT2); CF(B); R15++; } + +/* 40-4b - ldw (rn) - load word from RAM */ +#define FX_LDW(reg) uint32 v; \ +GSU.vLastRamAdr = GSU.avReg[reg]; \ +v = (uint32)RAM(GSU.avReg[reg]); \ +v |= ((uint32)RAM(GSU.avReg[reg]^1))<<8; \ +R15++; DREG = v; \ +TESTR14; \ +CLRFLAGS +static inline void fx_ldw_r0() { FX_LDW(0); } +static inline void fx_ldw_r1() { FX_LDW(1); } +static inline void fx_ldw_r2() { FX_LDW(2); } +static inline void fx_ldw_r3() { FX_LDW(3); } +static inline void fx_ldw_r4() { FX_LDW(4); } +static inline void fx_ldw_r5() { FX_LDW(5); } +static inline void fx_ldw_r6() { FX_LDW(6); } +static inline void fx_ldw_r7() { FX_LDW(7); } +static inline void fx_ldw_r8() { FX_LDW(8); } +static inline void fx_ldw_r9() { FX_LDW(9); } +static inline void fx_ldw_r10() { FX_LDW(10); } +static inline void fx_ldw_r11() { FX_LDW(11); } + +/* 40-4b(ALT1) - ldb (rn) - load byte */ +#define FX_LDB(reg) uint32 v; \ +GSU.vLastRamAdr = GSU.avReg[reg]; \ +v = (uint32)RAM(GSU.avReg[reg]); \ +R15++; DREG = v; \ +TESTR14; \ +CLRFLAGS +static inline void fx_ldb_r0() { FX_LDB(0); } +static inline void fx_ldb_r1() { FX_LDB(1); } +static inline void fx_ldb_r2() { FX_LDB(2); } +static inline void fx_ldb_r3() { FX_LDB(3); } +static inline void fx_ldb_r4() { FX_LDB(4); } +static inline void fx_ldb_r5() { FX_LDB(5); } +static inline void fx_ldb_r6() { FX_LDB(6); } +static inline void fx_ldb_r7() { FX_LDB(7); } +static inline void fx_ldb_r8() { FX_LDB(8); } +static inline void fx_ldb_r9() { FX_LDB(9); } +static inline void fx_ldb_r10() { FX_LDB(10); } +static inline void fx_ldb_r11() { FX_LDB(11); } + +/* 4c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static inline void fx_plot_2bit() +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v,c; + + R15++; + CLRFLAGS; + R1++; + +#ifdef CHECK_LIMITS + if(y >= GSU.vScreenHeight) return; +#endif + if(GSU.vPlotOptionReg & 0x02) + c = (x^y)&1 ? (uint8)(GSU.vColorReg>>4) : (uint8)GSU.vColorReg; + else + c = (uint8)GSU.vColorReg; + + if( !(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) return; + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); + + if(c & 0x01) a[0] |= v; + else a[0] &= ~v; + if(c & 0x02) a[1] |= v; + else a[1] &= ~v; +} + +/* 2c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ +static inline void fx_rpix_2bit() +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; + + R15++; + CLRFLAGS; +#ifdef CHECK_LIMITS + if(y >= GSU.vScreenHeight) return; +#endif + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); + + DREG = 0; + DREG |= ((uint32)((a[0] & v) != 0)) << 0; + DREG |= ((uint32)((a[1] & v) != 0)) << 1; + TESTR14; +} + +/* 4c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static inline void fx_plot_4bit() +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v,c; + + R15++; + CLRFLAGS; + R1++; + +#ifdef CHECK_LIMITS + if(y >= GSU.vScreenHeight) return; +#endif + if(GSU.vPlotOptionReg & 0x02) + c = (x^y)&1 ? (uint8)(GSU.vColorReg>>4) : (uint8)GSU.vColorReg; + else + c = (uint8)GSU.vColorReg; + + if( !(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) return; + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); + + if(c & 0x01) a[0x00] |= v; + else a[0x00] &= ~v; + if(c & 0x02) a[0x01] |= v; + else a[0x01] &= ~v; + if(c & 0x04) a[0x10] |= v; + else a[0x10] &= ~v; + if(c & 0x08) a[0x11] |= v; + else a[0x11] &= ~v; +} + +/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ +static inline void fx_rpix_4bit() +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; + + R15++; + CLRFLAGS; + +#ifdef CHECK_LIMITS + if(y >= GSU.vScreenHeight) return; +#endif + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); + + DREG = 0; + DREG |= ((uint32)((a[0x00] & v) != 0)) << 0; + DREG |= ((uint32)((a[0x01] & v) != 0)) << 1; + DREG |= ((uint32)((a[0x10] & v) != 0)) << 2; + DREG |= ((uint32)((a[0x11] & v) != 0)) << 3; + TESTR14; +} + +/* 8c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static inline void fx_plot_8bit() +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v,c; + + R15++; + CLRFLAGS; + R1++; + +#ifdef CHECK_LIMITS + if(y >= GSU.vScreenHeight) return; +#endif + c = (uint8)GSU.vColorReg; + if( !(GSU.vPlotOptionReg & 0x10) ) + { + if( !(GSU.vPlotOptionReg & 0x01) && !(c&0xf)) return; + } + else + if( !(GSU.vPlotOptionReg & 0x01) && !c) return; + + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); + + if(c & 0x01) a[0x00] |= v; + else a[0x00] &= ~v; + if(c & 0x02) a[0x01] |= v; + else a[0x01] &= ~v; + if(c & 0x04) a[0x10] |= v; + else a[0x10] &= ~v; + if(c & 0x08) a[0x11] |= v; + else a[0x11] &= ~v; + if(c & 0x10) a[0x20] |= v; + else a[0x20] &= ~v; + if(c & 0x20) a[0x21] |= v; + else a[0x21] &= ~v; + if(c & 0x40) a[0x30] |= v; + else a[0x30] &= ~v; + if(c & 0x80) a[0x31] |= v; + else a[0x31] &= ~v; +} + +/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ +static inline void fx_rpix_8bit() +{ + uint32 x = USEX8(R1); + uint32 y = USEX8(R2); + uint8 *a; + uint8 v; + + R15++; + CLRFLAGS; + +#ifdef CHECK_LIMITS + if(y >= GSU.vScreenHeight) return; +#endif + a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); + v = 128 >> (x&7); + + DREG = 0; + DREG |= ((uint32)((a[0x00] & v) != 0)) << 0; + DREG |= ((uint32)((a[0x01] & v) != 0)) << 1; + DREG |= ((uint32)((a[0x10] & v) != 0)) << 2; + DREG |= ((uint32)((a[0x11] & v) != 0)) << 3; + DREG |= ((uint32)((a[0x20] & v) != 0)) << 4; + DREG |= ((uint32)((a[0x21] & v) != 0)) << 5; + DREG |= ((uint32)((a[0x30] & v) != 0)) << 6; + DREG |= ((uint32)((a[0x31] & v) != 0)) << 7; + GSU.vZero = DREG; + TESTR14; +} + +/* 4o - plot - plot pixel with R1,R2 as x,y and the color register as the color */ +static inline void fx_plot_obj() +{ + printf ("ERROR fx_plot_obj called\n"); +} + +/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ +static inline void fx_rpix_obj() +{ + printf ("ERROR fx_rpix_obj called\n"); +} + +/* 4d - swap - swap upper and lower byte of a register */ +static inline void fx_swap() +{ + uint8 c = (uint8)SREG; + uint8 d = (uint8)(SREG>>8); + uint32 v = (((uint32)c)<<8)|((uint32)d); + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +/* 4e - color - copy source register to color register */ +static inline void fx_color() +{ + uint8 c = (uint8)SREG; + if(GSU.vPlotOptionReg & 0x04) + c = (c&0xf0) | (c>>4); + if(GSU.vPlotOptionReg & 0x08) + { + GSU.vColorReg &= 0xf0; + GSU.vColorReg |= c & 0x0f; + } + else + GSU.vColorReg = USEX8(c); + CLRFLAGS; + R15++; +} + +/* 4e(ALT1) - cmode - set plot option register */ +static inline void fx_cmode() +{ + GSU.vPlotOptionReg = SREG; + + if(GSU.vPlotOptionReg & 0x10) + { + /* OBJ Mode (for drawing into sprites) */ + GSU.vScreenHeight = 256; + } + else + GSU.vScreenHeight = GSU.vScreenRealHeight; + + fx_computeScreenPointers (); + CLRFLAGS; + R15++; +} + +/* 4f - not - perform exclusive exor with 1 on all bits */ +static inline void fx_not() +{ + uint32 v = ~SREG; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +/* 50-5f - add rn - add, register + register */ +#define FX_ADD(reg) \ +int32 s = SUSEX16(SREG) + SUSEX16(GSU.avReg[reg]); \ +GSU.vCarry = s >= 0x10000; \ +GSU.vOverflow = ~(SREG ^ GSU.avReg[reg]) & (GSU.avReg[reg] ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static inline void fx_add_r0() { FX_ADD(0); } +static inline void fx_add_r1() { FX_ADD(1); } +static inline void fx_add_r2() { FX_ADD(2); } +static inline void fx_add_r3() { FX_ADD(3); } +static inline void fx_add_r4() { FX_ADD(4); } +static inline void fx_add_r5() { FX_ADD(5); } +static inline void fx_add_r6() { FX_ADD(6); } +static inline void fx_add_r7() { FX_ADD(7); } +static inline void fx_add_r8() { FX_ADD(8); } +static inline void fx_add_r9() { FX_ADD(9); } +static inline void fx_add_r10() { FX_ADD(10); } +static inline void fx_add_r11() { FX_ADD(11); } +static inline void fx_add_r12() { FX_ADD(12); } +static inline void fx_add_r13() { FX_ADD(13); } +static inline void fx_add_r14() { FX_ADD(14); } +static inline void fx_add_r15() { FX_ADD(15); } + +/* 50-5f(ALT1) - adc rn - add with carry, register + register */ +#define FX_ADC(reg) \ +int32 s = SUSEX16(SREG) + SUSEX16(GSU.avReg[reg]) + SEX16(GSU.vCarry); \ +GSU.vCarry = s >= 0x10000; \ +GSU.vOverflow = ~(SREG ^ GSU.avReg[reg]) & (GSU.avReg[reg] ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static inline void fx_adc_r0() { FX_ADC(0); } +static inline void fx_adc_r1() { FX_ADC(1); } +static inline void fx_adc_r2() { FX_ADC(2); } +static inline void fx_adc_r3() { FX_ADC(3); } +static inline void fx_adc_r4() { FX_ADC(4); } +static inline void fx_adc_r5() { FX_ADC(5); } +static inline void fx_adc_r6() { FX_ADC(6); } +static inline void fx_adc_r7() { FX_ADC(7); } +static inline void fx_adc_r8() { FX_ADC(8); } +static inline void fx_adc_r9() { FX_ADC(9); } +static inline void fx_adc_r10() { FX_ADC(10); } +static inline void fx_adc_r11() { FX_ADC(11); } +static inline void fx_adc_r12() { FX_ADC(12); } +static inline void fx_adc_r13() { FX_ADC(13); } +static inline void fx_adc_r14() { FX_ADC(14); } +static inline void fx_adc_r15() { FX_ADC(15); } + +/* 50-5f(ALT2) - add #n - add, register + immediate */ +#define FX_ADD_I(imm) \ +int32 s = SUSEX16(SREG) + imm; \ +GSU.vCarry = s >= 0x10000; \ +GSU.vOverflow = ~(SREG ^ imm) & (imm ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static inline void fx_add_i0() { FX_ADD_I(0); } +static inline void fx_add_i1() { FX_ADD_I(1); } +static inline void fx_add_i2() { FX_ADD_I(2); } +static inline void fx_add_i3() { FX_ADD_I(3); } +static inline void fx_add_i4() { FX_ADD_I(4); } +static inline void fx_add_i5() { FX_ADD_I(5); } +static inline void fx_add_i6() { FX_ADD_I(6); } +static inline void fx_add_i7() { FX_ADD_I(7); } +static inline void fx_add_i8() { FX_ADD_I(8); } +static inline void fx_add_i9() { FX_ADD_I(9); } +static inline void fx_add_i10() { FX_ADD_I(10); } +static inline void fx_add_i11() { FX_ADD_I(11); } +static inline void fx_add_i12() { FX_ADD_I(12); } +static inline void fx_add_i13() { FX_ADD_I(13); } +static inline void fx_add_i14() { FX_ADD_I(14); } +static inline void fx_add_i15() { FX_ADD_I(15); } + +/* 50-5f(ALT3) - adc #n - add with carry, register + immediate */ +#define FX_ADC_I(imm) \ +int32 s = SUSEX16(SREG) + imm + SUSEX16(GSU.vCarry); \ +GSU.vCarry = s >= 0x10000; \ +GSU.vOverflow = ~(SREG ^ imm) & (imm ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static inline void fx_adc_i0() { FX_ADC_I(0); } +static inline void fx_adc_i1() { FX_ADC_I(1); } +static inline void fx_adc_i2() { FX_ADC_I(2); } +static inline void fx_adc_i3() { FX_ADC_I(3); } +static inline void fx_adc_i4() { FX_ADC_I(4); } +static inline void fx_adc_i5() { FX_ADC_I(5); } +static inline void fx_adc_i6() { FX_ADC_I(6); } +static inline void fx_adc_i7() { FX_ADC_I(7); } +static inline void fx_adc_i8() { FX_ADC_I(8); } +static inline void fx_adc_i9() { FX_ADC_I(9); } +static inline void fx_adc_i10() { FX_ADC_I(10); } +static inline void fx_adc_i11() { FX_ADC_I(11); } +static inline void fx_adc_i12() { FX_ADC_I(12); } +static inline void fx_adc_i13() { FX_ADC_I(13); } +static inline void fx_adc_i14() { FX_ADC_I(14); } +static inline void fx_adc_i15() { FX_ADC_I(15); } + +/* 60-6f - sub rn - subtract, register - register */ +#define FX_SUB(reg) \ +int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]); \ +GSU.vCarry = s >= 0; \ +GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static inline void fx_sub_r0() { FX_SUB(0); } +static inline void fx_sub_r1() { FX_SUB(1); } +static inline void fx_sub_r2() { FX_SUB(2); } +static inline void fx_sub_r3() { FX_SUB(3); } +static inline void fx_sub_r4() { FX_SUB(4); } +static inline void fx_sub_r5() { FX_SUB(5); } +static inline void fx_sub_r6() { FX_SUB(6); } +static inline void fx_sub_r7() { FX_SUB(7); } +static inline void fx_sub_r8() { FX_SUB(8); } +static inline void fx_sub_r9() { FX_SUB(9); } +static inline void fx_sub_r10() { FX_SUB(10); } +static inline void fx_sub_r11() { FX_SUB(11); } +static inline void fx_sub_r12() { FX_SUB(12); } +static inline void fx_sub_r13() { FX_SUB(13); } +static inline void fx_sub_r14() { FX_SUB(14); } +static inline void fx_sub_r15() { FX_SUB(15); } + +/* 60-6f(ALT1) - sbc rn - subtract with carry, register - register */ +#define FX_SBC(reg) \ +int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]) - (SUSEX16(GSU.vCarry^1)); \ +GSU.vCarry = s >= 0; \ +GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static inline void fx_sbc_r0() { FX_SBC(0); } +static inline void fx_sbc_r1() { FX_SBC(1); } +static inline void fx_sbc_r2() { FX_SBC(2); } +static inline void fx_sbc_r3() { FX_SBC(3); } +static inline void fx_sbc_r4() { FX_SBC(4); } +static inline void fx_sbc_r5() { FX_SBC(5); } +static inline void fx_sbc_r6() { FX_SBC(6); } +static inline void fx_sbc_r7() { FX_SBC(7); } +static inline void fx_sbc_r8() { FX_SBC(8); } +static inline void fx_sbc_r9() { FX_SBC(9); } +static inline void fx_sbc_r10() { FX_SBC(10); } +static inline void fx_sbc_r11() { FX_SBC(11); } +static inline void fx_sbc_r12() { FX_SBC(12); } +static inline void fx_sbc_r13() { FX_SBC(13); } +static inline void fx_sbc_r14() { FX_SBC(14); } +static inline void fx_sbc_r15() { FX_SBC(15); } + +/* 60-6f(ALT2) - sub #n - subtract, register - immediate */ +#define FX_SUB_I(imm) \ +int32 s = SUSEX16(SREG) - imm; \ +GSU.vCarry = s >= 0; \ +GSU.vOverflow = (SREG ^ imm) & (SREG ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; DREG = s; \ +TESTR14; \ +CLRFLAGS +static inline void fx_sub_i0() { FX_SUB_I(0); } +static inline void fx_sub_i1() { FX_SUB_I(1); } +static inline void fx_sub_i2() { FX_SUB_I(2); } +static inline void fx_sub_i3() { FX_SUB_I(3); } +static inline void fx_sub_i4() { FX_SUB_I(4); } +static inline void fx_sub_i5() { FX_SUB_I(5); } +static inline void fx_sub_i6() { FX_SUB_I(6); } +static inline void fx_sub_i7() { FX_SUB_I(7); } +static inline void fx_sub_i8() { FX_SUB_I(8); } +static inline void fx_sub_i9() { FX_SUB_I(9); } +static inline void fx_sub_i10() { FX_SUB_I(10); } +static inline void fx_sub_i11() { FX_SUB_I(11); } +static inline void fx_sub_i12() { FX_SUB_I(12); } +static inline void fx_sub_i13() { FX_SUB_I(13); } +static inline void fx_sub_i14() { FX_SUB_I(14); } +static inline void fx_sub_i15() { FX_SUB_I(15); } + +/* 60-6f(ALT3) - cmp rn - compare, register, register */ +#define FX_CMP(reg) \ +int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]); \ +GSU.vCarry = s >= 0; \ +GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ +GSU.vSign = s; \ +GSU.vZero = s; \ +R15++; \ +CLRFLAGS; +static inline void fx_cmp_r0() { FX_CMP(0); } +static inline void fx_cmp_r1() { FX_CMP(1); } +static inline void fx_cmp_r2() { FX_CMP(2); } +static inline void fx_cmp_r3() { FX_CMP(3); } +static inline void fx_cmp_r4() { FX_CMP(4); } +static inline void fx_cmp_r5() { FX_CMP(5); } +static inline void fx_cmp_r6() { FX_CMP(6); } +static inline void fx_cmp_r7() { FX_CMP(7); } +static inline void fx_cmp_r8() { FX_CMP(8); } +static inline void fx_cmp_r9() { FX_CMP(9); } +static inline void fx_cmp_r10() { FX_CMP(10); } +static inline void fx_cmp_r11() { FX_CMP(11); } +static inline void fx_cmp_r12() { FX_CMP(12); } +static inline void fx_cmp_r13() { FX_CMP(13); } +static inline void fx_cmp_r14() { FX_CMP(14); } +static inline void fx_cmp_r15() { FX_CMP(15); } + +/* 70 - merge - R7 as upper byte, R8 as lower byte (used for texture-mapping) */ +static inline void fx_merge() +{ + uint32 v = (R7&0xff00) | ((R8&0xff00)>>8); + R15++; DREG = v; + GSU.vOverflow = (v & 0xc0c0) << 16; + GSU.vZero = !(v & 0xf0f0); + GSU.vSign = ((v | (v<<8)) & 0x8000); + GSU.vCarry = (v & 0xe0e0) != 0; + TESTR14; + CLRFLAGS; +} + +/* 71-7f - and rn - reister & register */ +#define FX_AND(reg) \ +uint32 v = SREG & GSU.avReg[reg]; \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_and_r1() { FX_AND(1); } +static inline void fx_and_r2() { FX_AND(2); } +static inline void fx_and_r3() { FX_AND(3); } +static inline void fx_and_r4() { FX_AND(4); } +static inline void fx_and_r5() { FX_AND(5); } +static inline void fx_and_r6() { FX_AND(6); } +static inline void fx_and_r7() { FX_AND(7); } +static inline void fx_and_r8() { FX_AND(8); } +static inline void fx_and_r9() { FX_AND(9); } +static inline void fx_and_r10() { FX_AND(10); } +static inline void fx_and_r11() { FX_AND(11); } +static inline void fx_and_r12() { FX_AND(12); } +static inline void fx_and_r13() { FX_AND(13); } +static inline void fx_and_r14() { FX_AND(14); } +static inline void fx_and_r15() { FX_AND(15); } + +/* 71-7f(ALT1) - bic rn - reister & ~register */ +#define FX_BIC(reg) \ +uint32 v = SREG & ~GSU.avReg[reg]; \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_bic_r1() { FX_BIC(1); } +static inline void fx_bic_r2() { FX_BIC(2); } +static inline void fx_bic_r3() { FX_BIC(3); } +static inline void fx_bic_r4() { FX_BIC(4); } +static inline void fx_bic_r5() { FX_BIC(5); } +static inline void fx_bic_r6() { FX_BIC(6); } +static inline void fx_bic_r7() { FX_BIC(7); } +static inline void fx_bic_r8() { FX_BIC(8); } +static inline void fx_bic_r9() { FX_BIC(9); } +static inline void fx_bic_r10() { FX_BIC(10); } +static inline void fx_bic_r11() { FX_BIC(11); } +static inline void fx_bic_r12() { FX_BIC(12); } +static inline void fx_bic_r13() { FX_BIC(13); } +static inline void fx_bic_r14() { FX_BIC(14); } +static inline void fx_bic_r15() { FX_BIC(15); } + +/* 71-7f(ALT2) - and #n - reister & immediate */ +#define FX_AND_I(imm) \ +uint32 v = SREG & imm; \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_and_i1() { FX_AND_I(1); } +static inline void fx_and_i2() { FX_AND_I(2); } +static inline void fx_and_i3() { FX_AND_I(3); } +static inline void fx_and_i4() { FX_AND_I(4); } +static inline void fx_and_i5() { FX_AND_I(5); } +static inline void fx_and_i6() { FX_AND_I(6); } +static inline void fx_and_i7() { FX_AND_I(7); } +static inline void fx_and_i8() { FX_AND_I(8); } +static inline void fx_and_i9() { FX_AND_I(9); } +static inline void fx_and_i10() { FX_AND_I(10); } +static inline void fx_and_i11() { FX_AND_I(11); } +static inline void fx_and_i12() { FX_AND_I(12); } +static inline void fx_and_i13() { FX_AND_I(13); } +static inline void fx_and_i14() { FX_AND_I(14); } +static inline void fx_and_i15() { FX_AND_I(15); } + +/* 71-7f(ALT3) - bic #n - reister & ~immediate */ +#define FX_BIC_I(imm) \ +uint32 v = SREG & ~imm; \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_bic_i1() { FX_BIC_I(1); } +static inline void fx_bic_i2() { FX_BIC_I(2); } +static inline void fx_bic_i3() { FX_BIC_I(3); } +static inline void fx_bic_i4() { FX_BIC_I(4); } +static inline void fx_bic_i5() { FX_BIC_I(5); } +static inline void fx_bic_i6() { FX_BIC_I(6); } +static inline void fx_bic_i7() { FX_BIC_I(7); } +static inline void fx_bic_i8() { FX_BIC_I(8); } +static inline void fx_bic_i9() { FX_BIC_I(9); } +static inline void fx_bic_i10() { FX_BIC_I(10); } +static inline void fx_bic_i11() { FX_BIC_I(11); } +static inline void fx_bic_i12() { FX_BIC_I(12); } +static inline void fx_bic_i13() { FX_BIC_I(13); } +static inline void fx_bic_i14() { FX_BIC_I(14); } +static inline void fx_bic_i15() { FX_BIC_I(15); } + +/* 80-8f - mult rn - 8 bit to 16 bit signed multiply, register * register */ +#define FX_MULT(reg) \ +uint32 v = (uint32)(SEX8(SREG) * SEX8(GSU.avReg[reg])); \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_mult_r0() { FX_MULT(0); } +static inline void fx_mult_r1() { FX_MULT(1); } +static inline void fx_mult_r2() { FX_MULT(2); } +static inline void fx_mult_r3() { FX_MULT(3); } +static inline void fx_mult_r4() { FX_MULT(4); } +static inline void fx_mult_r5() { FX_MULT(5); } +static inline void fx_mult_r6() { FX_MULT(6); } +static inline void fx_mult_r7() { FX_MULT(7); } +static inline void fx_mult_r8() { FX_MULT(8); } +static inline void fx_mult_r9() { FX_MULT(9); } +static inline void fx_mult_r10() { FX_MULT(10); } +static inline void fx_mult_r11() { FX_MULT(11); } +static inline void fx_mult_r12() { FX_MULT(12); } +static inline void fx_mult_r13() { FX_MULT(13); } +static inline void fx_mult_r14() { FX_MULT(14); } +static inline void fx_mult_r15() { FX_MULT(15); } + +/* 80-8f(ALT1) - umult rn - 8 bit to 16 bit unsigned multiply, register * register */ +#define FX_UMULT(reg) \ +uint32 v = USEX8(SREG) * USEX8(GSU.avReg[reg]); \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_umult_r0() { FX_UMULT(0); } +static inline void fx_umult_r1() { FX_UMULT(1); } +static inline void fx_umult_r2() { FX_UMULT(2); } +static inline void fx_umult_r3() { FX_UMULT(3); } +static inline void fx_umult_r4() { FX_UMULT(4); } +static inline void fx_umult_r5() { FX_UMULT(5); } +static inline void fx_umult_r6() { FX_UMULT(6); } +static inline void fx_umult_r7() { FX_UMULT(7); } +static inline void fx_umult_r8() { FX_UMULT(8); } +static inline void fx_umult_r9() { FX_UMULT(9); } +static inline void fx_umult_r10() { FX_UMULT(10); } +static inline void fx_umult_r11() { FX_UMULT(11); } +static inline void fx_umult_r12() { FX_UMULT(12); } +static inline void fx_umult_r13() { FX_UMULT(13); } +static inline void fx_umult_r14() { FX_UMULT(14); } +static inline void fx_umult_r15() { FX_UMULT(15); } + +/* 80-8f(ALT2) - mult #n - 8 bit to 16 bit signed multiply, register * immediate */ +#define FX_MULT_I(imm) \ +uint32 v = (uint32) (SEX8(SREG) * ((int32)imm)); \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_mult_i0() { FX_MULT_I(0); } +static inline void fx_mult_i1() { FX_MULT_I(1); } +static inline void fx_mult_i2() { FX_MULT_I(2); } +static inline void fx_mult_i3() { FX_MULT_I(3); } +static inline void fx_mult_i4() { FX_MULT_I(4); } +static inline void fx_mult_i5() { FX_MULT_I(5); } +static inline void fx_mult_i6() { FX_MULT_I(6); } +static inline void fx_mult_i7() { FX_MULT_I(7); } +static inline void fx_mult_i8() { FX_MULT_I(8); } +static inline void fx_mult_i9() { FX_MULT_I(9); } +static inline void fx_mult_i10() { FX_MULT_I(10); } +static inline void fx_mult_i11() { FX_MULT_I(11); } +static inline void fx_mult_i12() { FX_MULT_I(12); } +static inline void fx_mult_i13() { FX_MULT_I(13); } +static inline void fx_mult_i14() { FX_MULT_I(14); } +static inline void fx_mult_i15() { FX_MULT_I(15); } + +/* 80-8f(ALT3) - umult #n - 8 bit to 16 bit unsigned multiply, register * immediate */ +#define FX_UMULT_I(imm) \ +uint32 v = USEX8(SREG) * ((uint32)imm); \ +R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_umult_i0() { FX_UMULT_I(0); } +static inline void fx_umult_i1() { FX_UMULT_I(1); } +static inline void fx_umult_i2() { FX_UMULT_I(2); } +static inline void fx_umult_i3() { FX_UMULT_I(3); } +static inline void fx_umult_i4() { FX_UMULT_I(4); } +static inline void fx_umult_i5() { FX_UMULT_I(5); } +static inline void fx_umult_i6() { FX_UMULT_I(6); } +static inline void fx_umult_i7() { FX_UMULT_I(7); } +static inline void fx_umult_i8() { FX_UMULT_I(8); } +static inline void fx_umult_i9() { FX_UMULT_I(9); } +static inline void fx_umult_i10() { FX_UMULT_I(10); } +static inline void fx_umult_i11() { FX_UMULT_I(11); } +static inline void fx_umult_i12() { FX_UMULT_I(12); } +static inline void fx_umult_i13() { FX_UMULT_I(13); } +static inline void fx_umult_i14() { FX_UMULT_I(14); } +static inline void fx_umult_i15() { FX_UMULT_I(15); } + +/* 90 - sbk - store word to last accessed RAM address */ +static inline void fx_sbk() +{ + RAM(GSU.vLastRamAdr) = (uint8)SREG; + RAM(GSU.vLastRamAdr^1) = (uint8)(SREG>>8); + CLRFLAGS; + R15++; +} + +/* 91-94 - link #n - R11 = R15 + immediate */ +#define FX_LINK_I(lkn) R11 = R15 + lkn; CLRFLAGS; R15++ +static inline void fx_link_i1() { FX_LINK_I(1); } +static inline void fx_link_i2() { FX_LINK_I(2); } +static inline void fx_link_i3() { FX_LINK_I(3); } +static inline void fx_link_i4() { FX_LINK_I(4); } + +/* 95 - sex - sign extend 8 bit to 16 bit */ +static inline void fx_sex() +{ + uint32 v = (uint32)SEX8(SREG); + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +/* 96 - asr - aritmetric shift right by one */ +static inline void fx_asr() +{ + uint32 v; + GSU.vCarry = SREG & 1; + v = (uint32)(SEX16(SREG)>>1); + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +/* 96(ALT1) - div2 - aritmetric shift right by one */ +static inline void fx_div2() +{ + uint32 v; + int32 s = SEX16(SREG); + GSU.vCarry = s & 1; + if(s == -1) + v = 0; + else + v = (uint32)(s>>1); + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +/* 97 - ror - rotate right by one */ +static inline void fx_ror() +{ + uint32 v = (USEX16(SREG)>>1) | (GSU.vCarry<<15); + GSU.vCarry = SREG & 1; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +/* 98-9d - jmp rn - jump to address of register */ +#define FX_JMP(reg) \ +R15 = GSU.avReg[reg]; \ +CLRFLAGS; +static inline void fx_jmp_r8() { FX_JMP(8); } +static inline void fx_jmp_r9() { FX_JMP(9); } +static inline void fx_jmp_r10() { FX_JMP(10); } +static inline void fx_jmp_r11() { FX_JMP(11); } +static inline void fx_jmp_r12() { FX_JMP(12); } +static inline void fx_jmp_r13() { FX_JMP(13); } + +/* 98-9d(ALT1) - ljmp rn - set program bank to source register and jump to address of register */ +#define FX_LJMP(reg) \ +GSU.vPrgBankReg = GSU.avReg[reg] & 0x7f; \ +GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; \ +R15 = SREG; \ +GSU.bCacheActive = FALSE; fx_cache(); R15--; +static inline void fx_ljmp_r8() { FX_LJMP(8); } +static inline void fx_ljmp_r9() { FX_LJMP(9); } +static inline void fx_ljmp_r10() { FX_LJMP(10); } +static inline void fx_ljmp_r11() { FX_LJMP(11); } +static inline void fx_ljmp_r12() { FX_LJMP(12); } +static inline void fx_ljmp_r13() { FX_LJMP(13); } + +/* 9e - lob - set upper byte to zero (keep low byte) */ +static inline void fx_lob() +{ + uint32 v = USEX8(SREG); + R15++; DREG = v; + GSU.vSign = v<<8; + GSU.vZero = v<<8; + TESTR14; + CLRFLAGS; +} + +/* 9f - fmult - 16 bit to 32 bit signed multiplication, upper 16 bits only */ +static inline void fx_fmult() +{ + uint32 v; + uint32 c = (uint32) (SEX16(SREG) * SEX16(R6)); + v = c >> 16; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + GSU.vCarry = (c >> 15) & 1; + TESTR14; + CLRFLAGS; +} + +/* 9f(ALT1) - lmult - 16 bit to 32 bit signed multiplication */ +static inline void fx_lmult() +{ + uint32 v; + uint32 c = (uint32) (SEX16(SREG) * SEX16(R6)); + R4 = c; + v = c >> 16; + R15++; DREG = v; + GSU.vSign = v; + GSU.vZero = v; + /* XXX R6 or R4? */ + GSU.vCarry = (R4 >> 15) & 1; /* should it be bit 15 of R4 instead? */ + TESTR14; + CLRFLAGS; +} + +/* a0-af - ibt rn,#pp - immediate byte transfer */ +#define FX_IBT(reg) \ +uint8 v = PIPE; R15++; \ +FETCHPIPE; R15++; \ +GSU.avReg[reg] = SEX8(v); \ +CLRFLAGS; +static inline void fx_ibt_r0() { FX_IBT(0); } +static inline void fx_ibt_r1() { FX_IBT(1); } +static inline void fx_ibt_r2() { FX_IBT(2); } +static inline void fx_ibt_r3() { FX_IBT(3); } +static inline void fx_ibt_r4() { FX_IBT(4); } +static inline void fx_ibt_r5() { FX_IBT(5); } +static inline void fx_ibt_r6() { FX_IBT(6); } +static inline void fx_ibt_r7() { FX_IBT(7); } +static inline void fx_ibt_r8() { FX_IBT(8); } +static inline void fx_ibt_r9() { FX_IBT(9); } +static inline void fx_ibt_r10() { FX_IBT(10); } +static inline void fx_ibt_r11() { FX_IBT(11); } +static inline void fx_ibt_r12() { FX_IBT(12); } +static inline void fx_ibt_r13() { FX_IBT(13); } +static inline void fx_ibt_r14() { FX_IBT(14); READR14; } +static inline void fx_ibt_r15() { FX_IBT(15); } + +/* a0-af(ALT1) - lms rn,(yy) - load word from RAM (short address) */ +#define FX_LMS(reg) \ +GSU.vLastRamAdr = ((uint32)PIPE) << 1; \ +R15++; FETCHPIPE; R15++; \ +GSU.avReg[reg] = (uint32)RAM(GSU.vLastRamAdr); \ +GSU.avReg[reg] |= ((uint32)RAM(GSU.vLastRamAdr+1))<<8; \ +CLRFLAGS; +static inline void fx_lms_r0() { FX_LMS(0); } +static inline void fx_lms_r1() { FX_LMS(1); } +static inline void fx_lms_r2() { FX_LMS(2); } +static inline void fx_lms_r3() { FX_LMS(3); } +static inline void fx_lms_r4() { FX_LMS(4); } +static inline void fx_lms_r5() { FX_LMS(5); } +static inline void fx_lms_r6() { FX_LMS(6); } +static inline void fx_lms_r7() { FX_LMS(7); } +static inline void fx_lms_r8() { FX_LMS(8); } +static inline void fx_lms_r9() { FX_LMS(9); } +static inline void fx_lms_r10() { FX_LMS(10); } +static inline void fx_lms_r11() { FX_LMS(11); } +static inline void fx_lms_r12() { FX_LMS(12); } +static inline void fx_lms_r13() { FX_LMS(13); } +static inline void fx_lms_r14() { FX_LMS(14); READR14; } +static inline void fx_lms_r15() { FX_LMS(15); } + +/* a0-af(ALT2) - sms (yy),rn - store word in RAM (short address) */ +/* If rn == r15, is the value of r15 before or after the extra byte is read? */ +#define FX_SMS(reg) \ +uint32 v = GSU.avReg[reg]; \ +GSU.vLastRamAdr = ((uint32)PIPE) << 1; \ +R15++; FETCHPIPE; \ +RAM(GSU.vLastRamAdr) = (uint8)v; \ +RAM(GSU.vLastRamAdr+1) = (uint8)(v>>8); \ +CLRFLAGS; R15++; +static inline void fx_sms_r0() { FX_SMS(0); } +static inline void fx_sms_r1() { FX_SMS(1); } +static inline void fx_sms_r2() { FX_SMS(2); } +static inline void fx_sms_r3() { FX_SMS(3); } +static inline void fx_sms_r4() { FX_SMS(4); } +static inline void fx_sms_r5() { FX_SMS(5); } +static inline void fx_sms_r6() { FX_SMS(6); } +static inline void fx_sms_r7() { FX_SMS(7); } +static inline void fx_sms_r8() { FX_SMS(8); } +static inline void fx_sms_r9() { FX_SMS(9); } +static inline void fx_sms_r10() { FX_SMS(10); } +static inline void fx_sms_r11() { FX_SMS(11); } +static inline void fx_sms_r12() { FX_SMS(12); } +static inline void fx_sms_r13() { FX_SMS(13); } +static inline void fx_sms_r14() { FX_SMS(14); } +static inline void fx_sms_r15() { FX_SMS(15); } + +/* b0-bf - from rn - set source register */ +/* b0-bf(B) - moves rn - move register to register, and set flags, (if B flag is set) */ +#define FX_FROM(reg) \ +if(TF(B)) { uint32 v = GSU.avReg[reg]; R15++; DREG = v; \ +GSU.vOverflow = (v&0x80) << 16; GSU.vSign = v; GSU.vZero = v; TESTR14; CLRFLAGS; } \ +else { GSU.pvSreg = &GSU.avReg[reg]; R15++; } +static inline void fx_from_r0() { FX_FROM(0); } +static inline void fx_from_r1() { FX_FROM(1); } +static inline void fx_from_r2() { FX_FROM(2); } +static inline void fx_from_r3() { FX_FROM(3); } +static inline void fx_from_r4() { FX_FROM(4); } +static inline void fx_from_r5() { FX_FROM(5); } +static inline void fx_from_r6() { FX_FROM(6); } +static inline void fx_from_r7() { FX_FROM(7); } +static inline void fx_from_r8() { FX_FROM(8); } +static inline void fx_from_r9() { FX_FROM(9); } +static inline void fx_from_r10() { FX_FROM(10); } +static inline void fx_from_r11() { FX_FROM(11); } +static inline void fx_from_r12() { FX_FROM(12); } +static inline void fx_from_r13() { FX_FROM(13); } +static inline void fx_from_r14() { FX_FROM(14); } +static inline void fx_from_r15() { FX_FROM(15); } + +/* c0 - hib - move high-byte to low-byte */ +static inline void fx_hib() +{ + uint32 v = USEX8(SREG>>8); + R15++; DREG = v; + GSU.vSign = v<<8; + GSU.vZero = v<<8; + TESTR14; + CLRFLAGS; +} + +/* c1-cf - or rn */ +#define FX_OR(reg) \ +uint32 v = SREG | GSU.avReg[reg]; R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_or_r1() { FX_OR(1); } +static inline void fx_or_r2() { FX_OR(2); } +static inline void fx_or_r3() { FX_OR(3); } +static inline void fx_or_r4() { FX_OR(4); } +static inline void fx_or_r5() { FX_OR(5); } +static inline void fx_or_r6() { FX_OR(6); } +static inline void fx_or_r7() { FX_OR(7); } +static inline void fx_or_r8() { FX_OR(8); } +static inline void fx_or_r9() { FX_OR(9); } +static inline void fx_or_r10() { FX_OR(10); } +static inline void fx_or_r11() { FX_OR(11); } +static inline void fx_or_r12() { FX_OR(12); } +static inline void fx_or_r13() { FX_OR(13); } +static inline void fx_or_r14() { FX_OR(14); } +static inline void fx_or_r15() { FX_OR(15); } + +/* c1-cf(ALT1) - xor rn */ +#define FX_XOR(reg) \ +uint32 v = SREG ^ GSU.avReg[reg]; R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_xor_r1() { FX_XOR(1); } +static inline void fx_xor_r2() { FX_XOR(2); } +static inline void fx_xor_r3() { FX_XOR(3); } +static inline void fx_xor_r4() { FX_XOR(4); } +static inline void fx_xor_r5() { FX_XOR(5); } +static inline void fx_xor_r6() { FX_XOR(6); } +static inline void fx_xor_r7() { FX_XOR(7); } +static inline void fx_xor_r8() { FX_XOR(8); } +static inline void fx_xor_r9() { FX_XOR(9); } +static inline void fx_xor_r10() { FX_XOR(10); } +static inline void fx_xor_r11() { FX_XOR(11); } +static inline void fx_xor_r12() { FX_XOR(12); } +static inline void fx_xor_r13() { FX_XOR(13); } +static inline void fx_xor_r14() { FX_XOR(14); } +static inline void fx_xor_r15() { FX_XOR(15); } + +/* c1-cf(ALT2) - or #n */ +#define FX_OR_I(imm) \ +uint32 v = SREG | imm; R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_or_i1() { FX_OR_I(1); } +static inline void fx_or_i2() { FX_OR_I(2); } +static inline void fx_or_i3() { FX_OR_I(3); } +static inline void fx_or_i4() { FX_OR_I(4); } +static inline void fx_or_i5() { FX_OR_I(5); } +static inline void fx_or_i6() { FX_OR_I(6); } +static inline void fx_or_i7() { FX_OR_I(7); } +static inline void fx_or_i8() { FX_OR_I(8); } +static inline void fx_or_i9() { FX_OR_I(9); } +static inline void fx_or_i10() { FX_OR_I(10); } +static inline void fx_or_i11() { FX_OR_I(11); } +static inline void fx_or_i12() { FX_OR_I(12); } +static inline void fx_or_i13() { FX_OR_I(13); } +static inline void fx_or_i14() { FX_OR_I(14); } +static inline void fx_or_i15() { FX_OR_I(15); } + +/* c1-cf(ALT3) - xor #n */ +#define FX_XOR_I(imm) \ +uint32 v = SREG ^ imm; R15++; DREG = v; \ +GSU.vSign = v; \ +GSU.vZero = v; \ +TESTR14; \ +CLRFLAGS; +static inline void fx_xor_i1() { FX_XOR_I(1); } +static inline void fx_xor_i2() { FX_XOR_I(2); } +static inline void fx_xor_i3() { FX_XOR_I(3); } +static inline void fx_xor_i4() { FX_XOR_I(4); } +static inline void fx_xor_i5() { FX_XOR_I(5); } +static inline void fx_xor_i6() { FX_XOR_I(6); } +static inline void fx_xor_i7() { FX_XOR_I(7); } +static inline void fx_xor_i8() { FX_XOR_I(8); } +static inline void fx_xor_i9() { FX_XOR_I(9); } +static inline void fx_xor_i10() { FX_XOR_I(10); } +static inline void fx_xor_i11() { FX_XOR_I(11); } +static inline void fx_xor_i12() { FX_XOR_I(12); } +static inline void fx_xor_i13() { FX_XOR_I(13); } +static inline void fx_xor_i14() { FX_XOR_I(14); } +static inline void fx_xor_i15() { FX_XOR_I(15); } + +/* d0-de - inc rn - increase by one */ +#define FX_INC(reg) \ +GSU.avReg[reg] += 1; \ +GSU.vSign = GSU.avReg[reg]; \ +GSU.vZero = GSU.avReg[reg]; \ +CLRFLAGS; R15++; +static inline void fx_inc_r0() { FX_INC(0); } +static inline void fx_inc_r1() { FX_INC(1); } +static inline void fx_inc_r2() { FX_INC(2); } +static inline void fx_inc_r3() { FX_INC(3); } +static inline void fx_inc_r4() { FX_INC(4); } +static inline void fx_inc_r5() { FX_INC(5); } +static inline void fx_inc_r6() { FX_INC(6); } +static inline void fx_inc_r7() { FX_INC(7); } +static inline void fx_inc_r8() { FX_INC(8); } +static inline void fx_inc_r9() { FX_INC(9); } +static inline void fx_inc_r10() { FX_INC(10); } +static inline void fx_inc_r11() { FX_INC(11); } +static inline void fx_inc_r12() { FX_INC(12); } +static inline void fx_inc_r13() { FX_INC(13); } +static inline void fx_inc_r14() { FX_INC(14); READR14; } + +/* df - getc - transfer ROM buffer to color register */ +static inline void fx_getc() +{ +#ifndef FX_DO_ROMBUFFER + uint8 c; + c = ROM(R14); +#else + uint8 c = GSU.vRomBuffer; +#endif + if(GSU.vPlotOptionReg & 0x04) + c = (c&0xf0) | (c>>4); + if(GSU.vPlotOptionReg & 0x08) + { + GSU.vColorReg &= 0xf0; + GSU.vColorReg |= c & 0x0f; + } + else + GSU.vColorReg = USEX8(c); + CLRFLAGS; + R15++; +} + +/* df(ALT2) - ramb - set current RAM bank */ +static inline void fx_ramb() +{ + GSU.vRamBankReg = SREG & (FX_RAM_BANKS-1); + GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; + CLRFLAGS; + R15++; +} + +/* df(ALT3) - romb - set current ROM bank */ +static inline void fx_romb() +{ + GSU.vRomBankReg = USEX8(SREG) & 0x7f; + GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; + CLRFLAGS; + R15++; +} + +/* e0-ee - dec rn - decrement by one */ +#define FX_DEC(reg) \ +GSU.avReg[reg] -= 1; \ +GSU.vSign = GSU.avReg[reg]; \ +GSU.vZero = GSU.avReg[reg]; \ +CLRFLAGS; R15++; +static inline void fx_dec_r0() { FX_DEC(0); } +static inline void fx_dec_r1() { FX_DEC(1); } +static inline void fx_dec_r2() { FX_DEC(2); } +static inline void fx_dec_r3() { FX_DEC(3); } +static inline void fx_dec_r4() { FX_DEC(4); } +static inline void fx_dec_r5() { FX_DEC(5); } +static inline void fx_dec_r6() { FX_DEC(6); } +static inline void fx_dec_r7() { FX_DEC(7); } +static inline void fx_dec_r8() { FX_DEC(8); } +static inline void fx_dec_r9() { FX_DEC(9); } +static inline void fx_dec_r10() { FX_DEC(10); } +static inline void fx_dec_r11() { FX_DEC(11); } +static inline void fx_dec_r12() { FX_DEC(12); } +static inline void fx_dec_r13() { FX_DEC(13); } +static inline void fx_dec_r14() { FX_DEC(14); READR14; } + +/* ef - getb - get byte from ROM at address R14 */ +static inline void fx_getb() +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + v = (uint32)ROM(R14); +#else + v = (uint32)GSU.vRomBuffer; +#endif + R15++; DREG = v; + TESTR14; + CLRFLAGS; +} + +/* ef(ALT1) - getbh - get high-byte from ROM at address R14 */ +static inline void fx_getbh() +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + uint32 c; + c = (uint32)ROM(R14); +#else + uint32 c = USEX8(GSU.vRomBuffer); +#endif + v = USEX8(SREG) | (c<<8); + R15++; DREG = v; + TESTR14; + CLRFLAGS; +} + +/* ef(ALT2) - getbl - get low-byte from ROM at address R14 */ +static inline void fx_getbl() +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + uint32 c; + c = (uint32)ROM(R14); +#else + uint32 c = USEX8(GSU.vRomBuffer); +#endif + v = (SREG & 0xff00) | c; + R15++; DREG = v; + TESTR14; + CLRFLAGS; +} + +/* ef(ALT3) - getbs - get sign extended byte from ROM at address R14 */ +static inline void fx_getbs() +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + int8 c; + c = ROM(R14); + v = SEX8(c); +#else + v = SEX8(GSU.vRomBuffer); +#endif + R15++; DREG = v; + TESTR14; + CLRFLAGS; +} + +/* f0-ff - iwt rn,#xx - immediate word transfer to register */ +#define FX_IWT(reg) \ +uint32 v = PIPE; R15++; FETCHPIPE; R15++; \ +v |= USEX8(PIPE) << 8; FETCHPIPE; R15++; \ +GSU.avReg[reg] = v; \ +CLRFLAGS; +static inline void fx_iwt_r0() { FX_IWT(0); } +static inline void fx_iwt_r1() { FX_IWT(1); } +static inline void fx_iwt_r2() { FX_IWT(2); } +static inline void fx_iwt_r3() { FX_IWT(3); } +static inline void fx_iwt_r4() { FX_IWT(4); } +static inline void fx_iwt_r5() { FX_IWT(5); } +static inline void fx_iwt_r6() { FX_IWT(6); } +static inline void fx_iwt_r7() { FX_IWT(7); } +static inline void fx_iwt_r8() { FX_IWT(8); } +static inline void fx_iwt_r9() { FX_IWT(9); } +static inline void fx_iwt_r10() { FX_IWT(10); } +static inline void fx_iwt_r11() { FX_IWT(11); } +static inline void fx_iwt_r12() { FX_IWT(12); } +static inline void fx_iwt_r13() { FX_IWT(13); } +static inline void fx_iwt_r14() { FX_IWT(14); READR14; } +static inline void fx_iwt_r15() { FX_IWT(15); } + +/* f0-ff(ALT1) - lm rn,(xx) - load word from RAM */ +#define FX_LM(reg) \ +GSU.vLastRamAdr = PIPE; R15++; FETCHPIPE; R15++; \ +GSU.vLastRamAdr |= USEX8(PIPE) << 8; FETCHPIPE; R15++; \ +GSU.avReg[reg] = RAM(GSU.vLastRamAdr); \ +GSU.avReg[reg] |= USEX8(RAM(GSU.vLastRamAdr^1)) << 8; \ +CLRFLAGS; +static inline void fx_lm_r0() { FX_LM(0); } +static inline void fx_lm_r1() { FX_LM(1); } +static inline void fx_lm_r2() { FX_LM(2); } +static inline void fx_lm_r3() { FX_LM(3); } +static inline void fx_lm_r4() { FX_LM(4); } +static inline void fx_lm_r5() { FX_LM(5); } +static inline void fx_lm_r6() { FX_LM(6); } +static inline void fx_lm_r7() { FX_LM(7); } +static inline void fx_lm_r8() { FX_LM(8); } +static inline void fx_lm_r9() { FX_LM(9); } +static inline void fx_lm_r10() { FX_LM(10); } +static inline void fx_lm_r11() { FX_LM(11); } +static inline void fx_lm_r12() { FX_LM(12); } +static inline void fx_lm_r13() { FX_LM(13); } +static inline void fx_lm_r14() { FX_LM(14); READR14; } +static inline void fx_lm_r15() { FX_LM(15); } + +/* f0-ff(ALT2) - sm (xx),rn - store word in RAM */ +/* If rn == r15, is the value of r15 before or after the extra bytes are read? */ +#define FX_SM(reg) \ +uint32 v = GSU.avReg[reg]; \ +GSU.vLastRamAdr = PIPE; R15++; FETCHPIPE; R15++; \ +GSU.vLastRamAdr |= USEX8(PIPE) << 8; FETCHPIPE; \ +RAM(GSU.vLastRamAdr) = (uint8)v; \ +RAM(GSU.vLastRamAdr^1) = (uint8)(v>>8); \ +CLRFLAGS; R15++; +static inline void fx_sm_r0() { FX_SM(0); } +static inline void fx_sm_r1() { FX_SM(1); } +static inline void fx_sm_r2() { FX_SM(2); } +static inline void fx_sm_r3() { FX_SM(3); } +static inline void fx_sm_r4() { FX_SM(4); } +static inline void fx_sm_r5() { FX_SM(5); } +static inline void fx_sm_r6() { FX_SM(6); } +static inline void fx_sm_r7() { FX_SM(7); } +static inline void fx_sm_r8() { FX_SM(8); } +static inline void fx_sm_r9() { FX_SM(9); } +static inline void fx_sm_r10() { FX_SM(10); } +static inline void fx_sm_r11() { FX_SM(11); } +static inline void fx_sm_r12() { FX_SM(12); } +static inline void fx_sm_r13() { FX_SM(13); } +static inline void fx_sm_r14() { FX_SM(14); } +static inline void fx_sm_r15() { FX_SM(15); } + +/*** GSU executions functions ***/ + +static uint32 fx_run(uint32 nInstructions) +{ + GSU.vCounter = nInstructions; + READR14; + while( TF(G) && (GSU.vCounter-- > 0) ) + FX_STEP; + /* +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); +#endif +*/ + return (nInstructions - GSU.vInstCount); +} + +static uint32 fx_run_to_breakpoint(uint32 nInstructions) +{ + uint32 vCounter = 0; + while(TF(G) && vCounter < nInstructions) + { + vCounter++; + FX_STEP; + if(USEX16(R15) == GSU.vBreakPoint) + { + GSU.vErrorCode = FX_BREAKPOINT; + break; + } + } + /* +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); +#endif +*/ + return vCounter; +} + +static uint32 fx_step_over(uint32 nInstructions) +{ + uint32 vCounter = 0; + while(TF(G) && vCounter < nInstructions) + { + vCounter++; + FX_STEP; + if(USEX16(R15) == GSU.vBreakPoint) + { + GSU.vErrorCode = FX_BREAKPOINT; + break; + } + if(USEX16(R15) == GSU.vStepPoint) + break; + } + /* +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); +#endif +*/ + return vCounter; +} + +#ifdef FX_FUNCTION_TABLE +uint32 (*FX_FUNCTION_TABLE[])(uint32) = +#else +uint32 (*fx_apfFunctionTable[])(uint32) = +#endif +{ + &fx_run, + &fx_run_to_breakpoint, + &fx_step_over, +}; + +/*** Special table for the different plot configurations ***/ + +#ifdef FX_PLOT_TABLE +void (*FX_PLOT_TABLE[])() = +#else +void (*fx_apfPlotTable[])() = +#endif +{ + &fx_plot_2bit, &fx_plot_4bit, &fx_plot_4bit, &fx_plot_8bit, &fx_plot_obj, + &fx_rpix_2bit, &fx_rpix_4bit, &fx_rpix_4bit, &fx_rpix_8bit, &fx_rpix_obj, +}; + +/*** Opcode table ***/ + +#ifdef FX_OPCODE_TABLE +void (*FX_OPCODE_TABLE[])() = +#else +void (*fx_apfOpcodeTable[])() = +#endif +{ + /* + * ALT0 Table + */ + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, + &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, + &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit,&fx_swap, &fx_color, &fx_not, + /* 50 - 5f */ + &fx_add_r0, &fx_add_r1, &fx_add_r2, &fx_add_r3, &fx_add_r4, &fx_add_r5, &fx_add_r6, &fx_add_r7, + &fx_add_r8, &fx_add_r9, &fx_add_r10, &fx_add_r11, &fx_add_r12, &fx_add_r13, &fx_add_r14, &fx_add_r15, + /* 60 - 6f */ + &fx_sub_r0, &fx_sub_r1, &fx_sub_r2, &fx_sub_r3, &fx_sub_r4, &fx_sub_r5, &fx_sub_r6, &fx_sub_r7, + &fx_sub_r8, &fx_sub_r9, &fx_sub_r10, &fx_sub_r11, &fx_sub_r12, &fx_sub_r13, &fx_sub_r14, &fx_sub_r15, + /* 70 - 7f */ + &fx_merge, &fx_and_r1, &fx_and_r2, &fx_and_r3, &fx_and_r4, &fx_and_r5, &fx_and_r6, &fx_and_r7, + &fx_and_r8, &fx_and_r9, &fx_and_r10, &fx_and_r11, &fx_and_r12, &fx_and_r13, &fx_and_r14, &fx_and_r15, + /* 80 - 8f */ + &fx_mult_r0, &fx_mult_r1, &fx_mult_r2, &fx_mult_r3, &fx_mult_r4, &fx_mult_r5, &fx_mult_r6, &fx_mult_r7, + &fx_mult_r8, &fx_mult_r9, &fx_mult_r10, &fx_mult_r11, &fx_mult_r12, &fx_mult_r13, &fx_mult_r14, &fx_mult_r15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, + &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, + /* a0 - af */ + &fx_ibt_r0, &fx_ibt_r1, &fx_ibt_r2, &fx_ibt_r3, &fx_ibt_r4, &fx_ibt_r5, &fx_ibt_r6, &fx_ibt_r7, + &fx_ibt_r8, &fx_ibt_r9, &fx_ibt_r10, &fx_ibt_r11, &fx_ibt_r12, &fx_ibt_r13, &fx_ibt_r14, &fx_ibt_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_or_r1, &fx_or_r2, &fx_or_r3, &fx_or_r4, &fx_or_r5, &fx_or_r6, &fx_or_r7, + &fx_or_r8, &fx_or_r9, &fx_or_r10, &fx_or_r11, &fx_or_r12, &fx_or_r13, &fx_or_r14, &fx_or_r15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getb, + /* f0 - ff */ + &fx_iwt_r0, &fx_iwt_r1, &fx_iwt_r2, &fx_iwt_r3, &fx_iwt_r4, &fx_iwt_r5, &fx_iwt_r6, &fx_iwt_r7, + &fx_iwt_r8, &fx_iwt_r9, &fx_iwt_r10, &fx_iwt_r11, &fx_iwt_r12, &fx_iwt_r13, &fx_iwt_r14, &fx_iwt_r15, + + /* + * ALT1 Table + */ + + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, + &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, + &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit,&fx_swap, &fx_cmode, &fx_not, + /* 50 - 5f */ + &fx_adc_r0, &fx_adc_r1, &fx_adc_r2, &fx_adc_r3, &fx_adc_r4, &fx_adc_r5, &fx_adc_r6, &fx_adc_r7, + &fx_adc_r8, &fx_adc_r9, &fx_adc_r10, &fx_adc_r11, &fx_adc_r12, &fx_adc_r13, &fx_adc_r14, &fx_adc_r15, + /* 60 - 6f */ + &fx_sbc_r0, &fx_sbc_r1, &fx_sbc_r2, &fx_sbc_r3, &fx_sbc_r4, &fx_sbc_r5, &fx_sbc_r6, &fx_sbc_r7, + &fx_sbc_r8, &fx_sbc_r9, &fx_sbc_r10, &fx_sbc_r11, &fx_sbc_r12, &fx_sbc_r13, &fx_sbc_r14, &fx_sbc_r15, + /* 70 - 7f */ + &fx_merge, &fx_bic_r1, &fx_bic_r2, &fx_bic_r3, &fx_bic_r4, &fx_bic_r5, &fx_bic_r6, &fx_bic_r7, + &fx_bic_r8, &fx_bic_r9, &fx_bic_r10, &fx_bic_r11, &fx_bic_r12, &fx_bic_r13, &fx_bic_r14, &fx_bic_r15, + /* 80 - 8f */ + &fx_umult_r0,&fx_umult_r1,&fx_umult_r2, &fx_umult_r3, &fx_umult_r4, &fx_umult_r5, &fx_umult_r6, &fx_umult_r7, + &fx_umult_r8,&fx_umult_r9,&fx_umult_r10,&fx_umult_r11,&fx_umult_r12,&fx_umult_r13,&fx_umult_r14,&fx_umult_r15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, + &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, + /* a0 - af */ + &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, + &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_xor_r1, &fx_xor_r2, &fx_xor_r3, &fx_xor_r4, &fx_xor_r5, &fx_xor_r6, &fx_xor_r7, + &fx_xor_r8, &fx_xor_r9, &fx_xor_r10, &fx_xor_r11, &fx_xor_r12, &fx_xor_r13, &fx_xor_r14, &fx_xor_r15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbh, + /* f0 - ff */ + &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, + &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, + + /* + * ALT2 Table + */ + + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, + &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, + &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit,&fx_swap, &fx_color, &fx_not, + /* 50 - 5f */ + &fx_add_i0, &fx_add_i1, &fx_add_i2, &fx_add_i3, &fx_add_i4, &fx_add_i5, &fx_add_i6, &fx_add_i7, + &fx_add_i8, &fx_add_i9, &fx_add_i10, &fx_add_i11, &fx_add_i12, &fx_add_i13, &fx_add_i14, &fx_add_i15, + /* 60 - 6f */ + &fx_sub_i0, &fx_sub_i1, &fx_sub_i2, &fx_sub_i3, &fx_sub_i4, &fx_sub_i5, &fx_sub_i6, &fx_sub_i7, + &fx_sub_i8, &fx_sub_i9, &fx_sub_i10, &fx_sub_i11, &fx_sub_i12, &fx_sub_i13, &fx_sub_i14, &fx_sub_i15, + /* 70 - 7f */ + &fx_merge, &fx_and_i1, &fx_and_i2, &fx_and_i3, &fx_and_i4, &fx_and_i5, &fx_and_i6, &fx_and_i7, + &fx_and_i8, &fx_and_i9, &fx_and_i10, &fx_and_i11, &fx_and_i12, &fx_and_i13, &fx_and_i14, &fx_and_i15, + /* 80 - 8f */ + &fx_mult_i0, &fx_mult_i1, &fx_mult_i2, &fx_mult_i3, &fx_mult_i4, &fx_mult_i5, &fx_mult_i6, &fx_mult_i7, + &fx_mult_i8, &fx_mult_i9, &fx_mult_i10, &fx_mult_i11, &fx_mult_i12, &fx_mult_i13, &fx_mult_i14, &fx_mult_i15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, + &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, + /* a0 - af */ + &fx_sms_r0, &fx_sms_r1, &fx_sms_r2, &fx_sms_r3, &fx_sms_r4, &fx_sms_r5, &fx_sms_r6, &fx_sms_r7, + &fx_sms_r8, &fx_sms_r9, &fx_sms_r10, &fx_sms_r11, &fx_sms_r12, &fx_sms_r13, &fx_sms_r14, &fx_sms_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_or_i1, &fx_or_i2, &fx_or_i3, &fx_or_i4, &fx_or_i5, &fx_or_i6, &fx_or_i7, + &fx_or_i8, &fx_or_i9, &fx_or_i10, &fx_or_i11, &fx_or_i12, &fx_or_i13, &fx_or_i14, &fx_or_i15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_ramb, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbl, + /* f0 - ff */ + &fx_sm_r0, &fx_sm_r1, &fx_sm_r2, &fx_sm_r3, &fx_sm_r4, &fx_sm_r5, &fx_sm_r6, &fx_sm_r7, + &fx_sm_r8, &fx_sm_r9, &fx_sm_r10, &fx_sm_r11, &fx_sm_r12, &fx_sm_r13, &fx_sm_r14, &fx_sm_r15, + + /* + * ALT3 Table + */ + + /* 00 - 0f */ + &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, + &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, + /* 10 - 1f */ + &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, + &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, + /* 20 - 2f */ + &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, + &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, + /* 30 - 3f */ + &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, + &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, + /* 40 - 4f */ + &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, + &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit,&fx_swap, &fx_cmode, &fx_not, + /* 50 - 5f */ + &fx_adc_i0, &fx_adc_i1, &fx_adc_i2, &fx_adc_i3, &fx_adc_i4, &fx_adc_i5, &fx_adc_i6, &fx_adc_i7, + &fx_adc_i8, &fx_adc_i9, &fx_adc_i10, &fx_adc_i11, &fx_adc_i12, &fx_adc_i13, &fx_adc_i14, &fx_adc_i15, + /* 60 - 6f */ + &fx_cmp_r0, &fx_cmp_r1, &fx_cmp_r2, &fx_cmp_r3, &fx_cmp_r4, &fx_cmp_r5, &fx_cmp_r6, &fx_cmp_r7, + &fx_cmp_r8, &fx_cmp_r9, &fx_cmp_r10, &fx_cmp_r11, &fx_cmp_r12, &fx_cmp_r13, &fx_cmp_r14, &fx_cmp_r15, + /* 70 - 7f */ + &fx_merge, &fx_bic_i1, &fx_bic_i2, &fx_bic_i3, &fx_bic_i4, &fx_bic_i5, &fx_bic_i6, &fx_bic_i7, + &fx_bic_i8, &fx_bic_i9, &fx_bic_i10, &fx_bic_i11, &fx_bic_i12, &fx_bic_i13, &fx_bic_i14, &fx_bic_i15, + /* 80 - 8f */ + &fx_umult_i0,&fx_umult_i1,&fx_umult_i2, &fx_umult_i3, &fx_umult_i4, &fx_umult_i5, &fx_umult_i6, &fx_umult_i7, + &fx_umult_i8,&fx_umult_i9,&fx_umult_i10,&fx_umult_i11,&fx_umult_i12,&fx_umult_i13,&fx_umult_i14,&fx_umult_i15, + /* 90 - 9f */ + &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, + &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, + /* a0 - af */ + &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, + &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, + /* b0 - bf */ + &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, + &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, + /* c0 - cf */ + &fx_hib, &fx_xor_i1, &fx_xor_i2, &fx_xor_i3, &fx_xor_i4, &fx_xor_i5, &fx_xor_i6, &fx_xor_i7, + &fx_xor_i8, &fx_xor_i9, &fx_xor_i10, &fx_xor_i11, &fx_xor_i12, &fx_xor_i13, &fx_xor_i14, &fx_xor_i15, + /* d0 - df */ + &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, + &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_romb, + /* e0 - ef */ + &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, + &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbs, + /* f0 - ff */ + &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, + &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, +}; + diff --git a/src/fxinst.cpp b/src/fxinst.cpp deleted file mode 100644 index acdca50..0000000 --- a/src/fxinst.cpp +++ /dev/null @@ -1,1916 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ -#define FX_DO_ROMBUFFER - -#include "fxemu.h" -#include "fxinst.h" -#include -#include - -extern struct FxRegs_s GSU; -int gsu_bank [512] = {0}; - -/* Set this define if you wish the plot instruction to check for y-pos limits */ -/* (I don't think it's nessecary) */ -#define CHECK_LIMITS - -/* Codes used: - * - * rn = a GSU register (r0-r15) - * #n = 4 bit immediate value - * #pp = 8 bit immediate value - * (yy) = 8 bit word address (0x0000 - 0x01fe) - * #xx = 16 bit immediate value - * (xx) = 16 bit address (0x0000 - 0xffff) - * - */ - -/* 00 - stop - stop GSU execution (and maybe generate an IRQ) */ -static inline void fx_stop() -{ - CF(G); - GSU.vCounter = 0; - GSU.vInstCount = GSU.vCounter; - - /* Check if we need to generate an IRQ */ - if(!(GSU.pvRegisters[GSU_CFGR] & 0x80)) - SF(IRQ); - - GSU.vPlotOptionReg = 0; - GSU.vPipe = 1; - CLRFLAGS; - R15++; -} - -/* 01 - nop - no operation */ -static inline void fx_nop() { CLRFLAGS; R15++; } - -extern void fx_flushCache(); - -/* 02 - cache - reintialize GSU cache */ -static inline void fx_cache() -{ - uint32 c = R15 & 0xfff0; - if(GSU.vCacheBaseReg != c || !GSU.bCacheActive) - { - fx_flushCache(); - GSU.vCacheBaseReg = c; - GSU.bCacheActive = TRUE; -#if 0 - if(c < (0x10000-512)) - { - uint8 const* t = &ROM(c); - memcpy(GSU.pvCache,t,512); - } - else - { - uint8 const* t1; - uint8 const* t2; - uint32 i = 0x10000 - c; - t1 = &ROM(c); - t2 = &ROM(0); - memcpy(GSU.pvCache,t1,i); - memcpy(&GSU.pvCache[i],t2,512-i); - } -#endif - } - R15++; - CLRFLAGS; -} - -/* 03 - lsr - logic shift right */ -static inline void fx_lsr() -{ - uint32 v; - GSU.vCarry = SREG & 1; - v = USEX16(SREG) >> 1; - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -/* 04 - rol - rotate left */ -static inline void fx_rol() -{ - uint32 v = USEX16((SREG << 1) + GSU.vCarry); - GSU.vCarry = (SREG >> 15) & 1; - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -/* 05 - bra - branch always */ -static inline void fx_bra() { uint8 v = PIPE; R15++; FETCHPIPE; R15 += SEX8(v); } - -/* Branch on condition */ -#define BRA_COND(cond) uint8 v = PIPE; R15++; FETCHPIPE; if(cond) R15 += SEX8(v); else R15++; - -#define TEST_S (GSU.vSign & 0x8000) -#define TEST_Z (USEX16(GSU.vZero) == 0) -#define TEST_OV (GSU.vOverflow >= 0x8000 || GSU.vOverflow < -0x8000) -#define TEST_CY (GSU.vCarry & 1) - -/* 06 - blt - branch on less than */ -static inline void fx_blt() { BRA_COND( (TEST_S!=0) != (TEST_OV!=0) ); } - -/* 07 - bge - branch on greater or equals */ -static inline void fx_bge() { BRA_COND( (TEST_S!=0) == (TEST_OV!=0)); } - -/* 08 - bne - branch on not equal */ -static inline void fx_bne() { BRA_COND( !TEST_Z ); } - -/* 09 - beq - branch on equal */ -static inline void fx_beq() { BRA_COND( TEST_Z ); } - -/* 0a - bpl - branch on plus */ -static inline void fx_bpl() { BRA_COND( !TEST_S ); } - -/* 0b - bmi - branch on minus */ -static inline void fx_bmi() { BRA_COND( TEST_S ); } - -/* 0c - bcc - branch on carry clear */ -static inline void fx_bcc() { BRA_COND( !TEST_CY ); } - -/* 0d - bcs - branch on carry set */ -static inline void fx_bcs() { BRA_COND( TEST_CY ); } - -/* 0e - bvc - branch on overflow clear */ -static inline void fx_bvc() { BRA_COND( !TEST_OV ); } - -/* 0f - bvs - branch on overflow set */ -static inline void fx_bvs() { BRA_COND( TEST_OV ); } - -/* 10-1f - to rn - set register n as destination register */ -/* 10-1f(B) - move rn - move one register to another (if B flag is set) */ -#define FX_TO(reg) \ -if(TF(B)) { GSU.avReg[(reg)] = SREG; CLRFLAGS; } \ -else { GSU.pvDreg = &GSU.avReg[reg]; } R15++; -#define FX_TO_R14(reg) \ -if(TF(B)) { GSU.avReg[(reg)] = SREG; CLRFLAGS; READR14; } \ -else { GSU.pvDreg = &GSU.avReg[reg]; } R15++; -#define FX_TO_R15(reg) \ -if(TF(B)) { GSU.avReg[(reg)] = SREG; CLRFLAGS; } \ -else { GSU.pvDreg = &GSU.avReg[reg]; R15++; } -static inline void fx_to_r0() { FX_TO(0); } -static inline void fx_to_r1() { FX_TO(1); } -static inline void fx_to_r2() { FX_TO(2); } -static inline void fx_to_r3() { FX_TO(3); } -static inline void fx_to_r4() { FX_TO(4); } -static inline void fx_to_r5() { FX_TO(5); } -static inline void fx_to_r6() { FX_TO(6); } -static inline void fx_to_r7() { FX_TO(7); } -static inline void fx_to_r8() { FX_TO(8); } -static inline void fx_to_r9() { FX_TO(9); } -static inline void fx_to_r10() { FX_TO(10); } -static inline void fx_to_r11() { FX_TO(11); } -static inline void fx_to_r12() { FX_TO(12); } -static inline void fx_to_r13() { FX_TO(13); } -static inline void fx_to_r14() { FX_TO_R14(14); } -static inline void fx_to_r15() { FX_TO_R15(15); } - -/* 20-2f - to rn - set register n as source and destination register */ -#define FX_WITH(reg) SF(B); GSU.pvSreg = GSU.pvDreg = &GSU.avReg[reg]; R15++; -static inline void fx_with_r0() { FX_WITH(0); } -static inline void fx_with_r1() { FX_WITH(1); } -static inline void fx_with_r2() { FX_WITH(2); } -static inline void fx_with_r3() { FX_WITH(3); } -static inline void fx_with_r4() { FX_WITH(4); } -static inline void fx_with_r5() { FX_WITH(5); } -static inline void fx_with_r6() { FX_WITH(6); } -static inline void fx_with_r7() { FX_WITH(7); } -static inline void fx_with_r8() { FX_WITH(8); } -static inline void fx_with_r9() { FX_WITH(9); } -static inline void fx_with_r10() { FX_WITH(10); } -static inline void fx_with_r11() { FX_WITH(11); } -static inline void fx_with_r12() { FX_WITH(12); } -static inline void fx_with_r13() { FX_WITH(13); } -static inline void fx_with_r14() { FX_WITH(14); } -static inline void fx_with_r15() { FX_WITH(15); } - -/* 30-3b - stw (rn) - store word */ -#define FX_STW(reg) \ -GSU.vLastRamAdr = GSU.avReg[reg]; \ -RAM(GSU.avReg[reg]) = (uint8)SREG; \ -RAM(GSU.avReg[reg]^1) = (uint8)(SREG>>8); \ -CLRFLAGS; R15++ -static inline void fx_stw_r0() { FX_STW(0); } -static inline void fx_stw_r1() { FX_STW(1); } -static inline void fx_stw_r2() { FX_STW(2); } -static inline void fx_stw_r3() { FX_STW(3); } -static inline void fx_stw_r4() { FX_STW(4); } -static inline void fx_stw_r5() { FX_STW(5); } -static inline void fx_stw_r6() { FX_STW(6); } -static inline void fx_stw_r7() { FX_STW(7); } -static inline void fx_stw_r8() { FX_STW(8); } -static inline void fx_stw_r9() { FX_STW(9); } -static inline void fx_stw_r10() { FX_STW(10); } -static inline void fx_stw_r11() { FX_STW(11); } - -/* 30-3b(ALT1) - stb (rn) - store byte */ -#define FX_STB(reg) \ -GSU.vLastRamAdr = GSU.avReg[reg]; \ -RAM(GSU.avReg[reg]) = (uint8)SREG; \ -CLRFLAGS; R15++ -static inline void fx_stb_r0() { FX_STB(0); } -static inline void fx_stb_r1() { FX_STB(1); } -static inline void fx_stb_r2() { FX_STB(2); } -static inline void fx_stb_r3() { FX_STB(3); } -static inline void fx_stb_r4() { FX_STB(4); } -static inline void fx_stb_r5() { FX_STB(5); } -static inline void fx_stb_r6() { FX_STB(6); } -static inline void fx_stb_r7() { FX_STB(7); } -static inline void fx_stb_r8() { FX_STB(8); } -static inline void fx_stb_r9() { FX_STB(9); } -static inline void fx_stb_r10() { FX_STB(10); } -static inline void fx_stb_r11() { FX_STB(11); } - -/* 3c - loop - decrement loop counter, and branch on not zero */ -static inline void fx_loop() -{ - GSU.vSign = GSU.vZero = --R12; - if( (uint16) R12 != 0 ) - R15 = R13; - else - R15++; - - CLRFLAGS; -} - -/* 3d - alt1 - set alt1 mode */ -static inline void fx_alt1() { SF(ALT1); CF(B); R15++; } - -/* 3e - alt2 - set alt2 mode */ -static inline void fx_alt2() { SF(ALT2); CF(B); R15++; } - -/* 3f - alt3 - set alt3 mode */ -static inline void fx_alt3() { SF(ALT1); SF(ALT2); CF(B); R15++; } - -/* 40-4b - ldw (rn) - load word from RAM */ -#define FX_LDW(reg) uint32 v; \ -GSU.vLastRamAdr = GSU.avReg[reg]; \ -v = (uint32)RAM(GSU.avReg[reg]); \ -v |= ((uint32)RAM(GSU.avReg[reg]^1))<<8; \ -R15++; DREG = v; \ -TESTR14; \ -CLRFLAGS -static inline void fx_ldw_r0() { FX_LDW(0); } -static inline void fx_ldw_r1() { FX_LDW(1); } -static inline void fx_ldw_r2() { FX_LDW(2); } -static inline void fx_ldw_r3() { FX_LDW(3); } -static inline void fx_ldw_r4() { FX_LDW(4); } -static inline void fx_ldw_r5() { FX_LDW(5); } -static inline void fx_ldw_r6() { FX_LDW(6); } -static inline void fx_ldw_r7() { FX_LDW(7); } -static inline void fx_ldw_r8() { FX_LDW(8); } -static inline void fx_ldw_r9() { FX_LDW(9); } -static inline void fx_ldw_r10() { FX_LDW(10); } -static inline void fx_ldw_r11() { FX_LDW(11); } - -/* 40-4b(ALT1) - ldb (rn) - load byte */ -#define FX_LDB(reg) uint32 v; \ -GSU.vLastRamAdr = GSU.avReg[reg]; \ -v = (uint32)RAM(GSU.avReg[reg]); \ -R15++; DREG = v; \ -TESTR14; \ -CLRFLAGS -static inline void fx_ldb_r0() { FX_LDB(0); } -static inline void fx_ldb_r1() { FX_LDB(1); } -static inline void fx_ldb_r2() { FX_LDB(2); } -static inline void fx_ldb_r3() { FX_LDB(3); } -static inline void fx_ldb_r4() { FX_LDB(4); } -static inline void fx_ldb_r5() { FX_LDB(5); } -static inline void fx_ldb_r6() { FX_LDB(6); } -static inline void fx_ldb_r7() { FX_LDB(7); } -static inline void fx_ldb_r8() { FX_LDB(8); } -static inline void fx_ldb_r9() { FX_LDB(9); } -static inline void fx_ldb_r10() { FX_LDB(10); } -static inline void fx_ldb_r11() { FX_LDB(11); } - -/* 4c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ -static inline void fx_plot_2bit() -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v,c; - - R15++; - CLRFLAGS; - R1++; - -#ifdef CHECK_LIMITS - if(y >= GSU.vScreenHeight) return; -#endif - if(GSU.vPlotOptionReg & 0x02) - c = (x^y)&1 ? (uint8)(GSU.vColorReg>>4) : (uint8)GSU.vColorReg; - else - c = (uint8)GSU.vColorReg; - - if( !(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) return; - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x&7); - - if(c & 0x01) a[0] |= v; - else a[0] &= ~v; - if(c & 0x02) a[1] |= v; - else a[1] &= ~v; -} - -/* 2c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ -static inline void fx_rpix_2bit() -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v; - - R15++; - CLRFLAGS; -#ifdef CHECK_LIMITS - if(y >= GSU.vScreenHeight) return; -#endif - - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x&7); - - DREG = 0; - DREG |= ((uint32)((a[0] & v) != 0)) << 0; - DREG |= ((uint32)((a[1] & v) != 0)) << 1; - TESTR14; -} - -/* 4c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ -static inline void fx_plot_4bit() -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v,c; - - R15++; - CLRFLAGS; - R1++; - -#ifdef CHECK_LIMITS - if(y >= GSU.vScreenHeight) return; -#endif - if(GSU.vPlotOptionReg & 0x02) - c = (x^y)&1 ? (uint8)(GSU.vColorReg>>4) : (uint8)GSU.vColorReg; - else - c = (uint8)GSU.vColorReg; - - if( !(GSU.vPlotOptionReg & 0x01) && !(c & 0xf)) return; - - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x&7); - - if(c & 0x01) a[0x00] |= v; - else a[0x00] &= ~v; - if(c & 0x02) a[0x01] |= v; - else a[0x01] &= ~v; - if(c & 0x04) a[0x10] |= v; - else a[0x10] &= ~v; - if(c & 0x08) a[0x11] |= v; - else a[0x11] &= ~v; -} - -/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ -static inline void fx_rpix_4bit() -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v; - - R15++; - CLRFLAGS; - -#ifdef CHECK_LIMITS - if(y >= GSU.vScreenHeight) return; -#endif - - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x&7); - - DREG = 0; - DREG |= ((uint32)((a[0x00] & v) != 0)) << 0; - DREG |= ((uint32)((a[0x01] & v) != 0)) << 1; - DREG |= ((uint32)((a[0x10] & v) != 0)) << 2; - DREG |= ((uint32)((a[0x11] & v) != 0)) << 3; - TESTR14; -} - -/* 8c - plot - plot pixel with R1,R2 as x,y and the color register as the color */ -static inline void fx_plot_8bit() -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v,c; - - R15++; - CLRFLAGS; - R1++; - -#ifdef CHECK_LIMITS - if(y >= GSU.vScreenHeight) return; -#endif - c = (uint8)GSU.vColorReg; - if( !(GSU.vPlotOptionReg & 0x10) ) - { - if( !(GSU.vPlotOptionReg & 0x01) && !(c&0xf)) return; - } - else - if( !(GSU.vPlotOptionReg & 0x01) && !c) return; - - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x&7); - - if(c & 0x01) a[0x00] |= v; - else a[0x00] &= ~v; - if(c & 0x02) a[0x01] |= v; - else a[0x01] &= ~v; - if(c & 0x04) a[0x10] |= v; - else a[0x10] &= ~v; - if(c & 0x08) a[0x11] |= v; - else a[0x11] &= ~v; - if(c & 0x10) a[0x20] |= v; - else a[0x20] &= ~v; - if(c & 0x20) a[0x21] |= v; - else a[0x21] &= ~v; - if(c & 0x40) a[0x30] |= v; - else a[0x30] &= ~v; - if(c & 0x80) a[0x31] |= v; - else a[0x31] &= ~v; -} - -/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ -static inline void fx_rpix_8bit() -{ - uint32 x = USEX8(R1); - uint32 y = USEX8(R2); - uint8 *a; - uint8 v; - - R15++; - CLRFLAGS; - -#ifdef CHECK_LIMITS - if(y >= GSU.vScreenHeight) return; -#endif - a = GSU.apvScreen[y >> 3] + GSU.x[x >> 3] + ((y & 7) << 1); - v = 128 >> (x&7); - - DREG = 0; - DREG |= ((uint32)((a[0x00] & v) != 0)) << 0; - DREG |= ((uint32)((a[0x01] & v) != 0)) << 1; - DREG |= ((uint32)((a[0x10] & v) != 0)) << 2; - DREG |= ((uint32)((a[0x11] & v) != 0)) << 3; - DREG |= ((uint32)((a[0x20] & v) != 0)) << 4; - DREG |= ((uint32)((a[0x21] & v) != 0)) << 5; - DREG |= ((uint32)((a[0x30] & v) != 0)) << 6; - DREG |= ((uint32)((a[0x31] & v) != 0)) << 7; - GSU.vZero = DREG; - TESTR14; -} - -/* 4o - plot - plot pixel with R1,R2 as x,y and the color register as the color */ -static inline void fx_plot_obj() -{ - printf ("ERROR fx_plot_obj called\n"); -} - -/* 4c(ALT1) - rpix - read color of the pixel with R1,R2 as x,y */ -static inline void fx_rpix_obj() -{ - printf ("ERROR fx_rpix_obj called\n"); -} - -/* 4d - swap - swap upper and lower byte of a register */ -static inline void fx_swap() -{ - uint8 c = (uint8)SREG; - uint8 d = (uint8)(SREG>>8); - uint32 v = (((uint32)c)<<8)|((uint32)d); - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -/* 4e - color - copy source register to color register */ -static inline void fx_color() -{ - uint8 c = (uint8)SREG; - if(GSU.vPlotOptionReg & 0x04) - c = (c&0xf0) | (c>>4); - if(GSU.vPlotOptionReg & 0x08) - { - GSU.vColorReg &= 0xf0; - GSU.vColorReg |= c & 0x0f; - } - else - GSU.vColorReg = USEX8(c); - CLRFLAGS; - R15++; -} - -/* 4e(ALT1) - cmode - set plot option register */ -static inline void fx_cmode() -{ - GSU.vPlotOptionReg = SREG; - - if(GSU.vPlotOptionReg & 0x10) - { - /* OBJ Mode (for drawing into sprites) */ - GSU.vScreenHeight = 256; - } - else - GSU.vScreenHeight = GSU.vScreenRealHeight; - - fx_computeScreenPointers (); - CLRFLAGS; - R15++; -} - -/* 4f - not - perform exclusive exor with 1 on all bits */ -static inline void fx_not() -{ - uint32 v = ~SREG; - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -/* 50-5f - add rn - add, register + register */ -#define FX_ADD(reg) \ -int32 s = SUSEX16(SREG) + SUSEX16(GSU.avReg[reg]); \ -GSU.vCarry = s >= 0x10000; \ -GSU.vOverflow = ~(SREG ^ GSU.avReg[reg]) & (GSU.avReg[reg] ^ s) & 0x8000; \ -GSU.vSign = s; \ -GSU.vZero = s; \ -R15++; DREG = s; \ -TESTR14; \ -CLRFLAGS -static inline void fx_add_r0() { FX_ADD(0); } -static inline void fx_add_r1() { FX_ADD(1); } -static inline void fx_add_r2() { FX_ADD(2); } -static inline void fx_add_r3() { FX_ADD(3); } -static inline void fx_add_r4() { FX_ADD(4); } -static inline void fx_add_r5() { FX_ADD(5); } -static inline void fx_add_r6() { FX_ADD(6); } -static inline void fx_add_r7() { FX_ADD(7); } -static inline void fx_add_r8() { FX_ADD(8); } -static inline void fx_add_r9() { FX_ADD(9); } -static inline void fx_add_r10() { FX_ADD(10); } -static inline void fx_add_r11() { FX_ADD(11); } -static inline void fx_add_r12() { FX_ADD(12); } -static inline void fx_add_r13() { FX_ADD(13); } -static inline void fx_add_r14() { FX_ADD(14); } -static inline void fx_add_r15() { FX_ADD(15); } - -/* 50-5f(ALT1) - adc rn - add with carry, register + register */ -#define FX_ADC(reg) \ -int32 s = SUSEX16(SREG) + SUSEX16(GSU.avReg[reg]) + SEX16(GSU.vCarry); \ -GSU.vCarry = s >= 0x10000; \ -GSU.vOverflow = ~(SREG ^ GSU.avReg[reg]) & (GSU.avReg[reg] ^ s) & 0x8000; \ -GSU.vSign = s; \ -GSU.vZero = s; \ -R15++; DREG = s; \ -TESTR14; \ -CLRFLAGS -static inline void fx_adc_r0() { FX_ADC(0); } -static inline void fx_adc_r1() { FX_ADC(1); } -static inline void fx_adc_r2() { FX_ADC(2); } -static inline void fx_adc_r3() { FX_ADC(3); } -static inline void fx_adc_r4() { FX_ADC(4); } -static inline void fx_adc_r5() { FX_ADC(5); } -static inline void fx_adc_r6() { FX_ADC(6); } -static inline void fx_adc_r7() { FX_ADC(7); } -static inline void fx_adc_r8() { FX_ADC(8); } -static inline void fx_adc_r9() { FX_ADC(9); } -static inline void fx_adc_r10() { FX_ADC(10); } -static inline void fx_adc_r11() { FX_ADC(11); } -static inline void fx_adc_r12() { FX_ADC(12); } -static inline void fx_adc_r13() { FX_ADC(13); } -static inline void fx_adc_r14() { FX_ADC(14); } -static inline void fx_adc_r15() { FX_ADC(15); } - -/* 50-5f(ALT2) - add #n - add, register + immediate */ -#define FX_ADD_I(imm) \ -int32 s = SUSEX16(SREG) + imm; \ -GSU.vCarry = s >= 0x10000; \ -GSU.vOverflow = ~(SREG ^ imm) & (imm ^ s) & 0x8000; \ -GSU.vSign = s; \ -GSU.vZero = s; \ -R15++; DREG = s; \ -TESTR14; \ -CLRFLAGS -static inline void fx_add_i0() { FX_ADD_I(0); } -static inline void fx_add_i1() { FX_ADD_I(1); } -static inline void fx_add_i2() { FX_ADD_I(2); } -static inline void fx_add_i3() { FX_ADD_I(3); } -static inline void fx_add_i4() { FX_ADD_I(4); } -static inline void fx_add_i5() { FX_ADD_I(5); } -static inline void fx_add_i6() { FX_ADD_I(6); } -static inline void fx_add_i7() { FX_ADD_I(7); } -static inline void fx_add_i8() { FX_ADD_I(8); } -static inline void fx_add_i9() { FX_ADD_I(9); } -static inline void fx_add_i10() { FX_ADD_I(10); } -static inline void fx_add_i11() { FX_ADD_I(11); } -static inline void fx_add_i12() { FX_ADD_I(12); } -static inline void fx_add_i13() { FX_ADD_I(13); } -static inline void fx_add_i14() { FX_ADD_I(14); } -static inline void fx_add_i15() { FX_ADD_I(15); } - -/* 50-5f(ALT3) - adc #n - add with carry, register + immediate */ -#define FX_ADC_I(imm) \ -int32 s = SUSEX16(SREG) + imm + SUSEX16(GSU.vCarry); \ -GSU.vCarry = s >= 0x10000; \ -GSU.vOverflow = ~(SREG ^ imm) & (imm ^ s) & 0x8000; \ -GSU.vSign = s; \ -GSU.vZero = s; \ -R15++; DREG = s; \ -TESTR14; \ -CLRFLAGS -static inline void fx_adc_i0() { FX_ADC_I(0); } -static inline void fx_adc_i1() { FX_ADC_I(1); } -static inline void fx_adc_i2() { FX_ADC_I(2); } -static inline void fx_adc_i3() { FX_ADC_I(3); } -static inline void fx_adc_i4() { FX_ADC_I(4); } -static inline void fx_adc_i5() { FX_ADC_I(5); } -static inline void fx_adc_i6() { FX_ADC_I(6); } -static inline void fx_adc_i7() { FX_ADC_I(7); } -static inline void fx_adc_i8() { FX_ADC_I(8); } -static inline void fx_adc_i9() { FX_ADC_I(9); } -static inline void fx_adc_i10() { FX_ADC_I(10); } -static inline void fx_adc_i11() { FX_ADC_I(11); } -static inline void fx_adc_i12() { FX_ADC_I(12); } -static inline void fx_adc_i13() { FX_ADC_I(13); } -static inline void fx_adc_i14() { FX_ADC_I(14); } -static inline void fx_adc_i15() { FX_ADC_I(15); } - -/* 60-6f - sub rn - subtract, register - register */ -#define FX_SUB(reg) \ -int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]); \ -GSU.vCarry = s >= 0; \ -GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ -GSU.vSign = s; \ -GSU.vZero = s; \ -R15++; DREG = s; \ -TESTR14; \ -CLRFLAGS -static inline void fx_sub_r0() { FX_SUB(0); } -static inline void fx_sub_r1() { FX_SUB(1); } -static inline void fx_sub_r2() { FX_SUB(2); } -static inline void fx_sub_r3() { FX_SUB(3); } -static inline void fx_sub_r4() { FX_SUB(4); } -static inline void fx_sub_r5() { FX_SUB(5); } -static inline void fx_sub_r6() { FX_SUB(6); } -static inline void fx_sub_r7() { FX_SUB(7); } -static inline void fx_sub_r8() { FX_SUB(8); } -static inline void fx_sub_r9() { FX_SUB(9); } -static inline void fx_sub_r10() { FX_SUB(10); } -static inline void fx_sub_r11() { FX_SUB(11); } -static inline void fx_sub_r12() { FX_SUB(12); } -static inline void fx_sub_r13() { FX_SUB(13); } -static inline void fx_sub_r14() { FX_SUB(14); } -static inline void fx_sub_r15() { FX_SUB(15); } - -/* 60-6f(ALT1) - sbc rn - subtract with carry, register - register */ -#define FX_SBC(reg) \ -int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]) - (SUSEX16(GSU.vCarry^1)); \ -GSU.vCarry = s >= 0; \ -GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ -GSU.vSign = s; \ -GSU.vZero = s; \ -R15++; DREG = s; \ -TESTR14; \ -CLRFLAGS -static inline void fx_sbc_r0() { FX_SBC(0); } -static inline void fx_sbc_r1() { FX_SBC(1); } -static inline void fx_sbc_r2() { FX_SBC(2); } -static inline void fx_sbc_r3() { FX_SBC(3); } -static inline void fx_sbc_r4() { FX_SBC(4); } -static inline void fx_sbc_r5() { FX_SBC(5); } -static inline void fx_sbc_r6() { FX_SBC(6); } -static inline void fx_sbc_r7() { FX_SBC(7); } -static inline void fx_sbc_r8() { FX_SBC(8); } -static inline void fx_sbc_r9() { FX_SBC(9); } -static inline void fx_sbc_r10() { FX_SBC(10); } -static inline void fx_sbc_r11() { FX_SBC(11); } -static inline void fx_sbc_r12() { FX_SBC(12); } -static inline void fx_sbc_r13() { FX_SBC(13); } -static inline void fx_sbc_r14() { FX_SBC(14); } -static inline void fx_sbc_r15() { FX_SBC(15); } - -/* 60-6f(ALT2) - sub #n - subtract, register - immediate */ -#define FX_SUB_I(imm) \ -int32 s = SUSEX16(SREG) - imm; \ -GSU.vCarry = s >= 0; \ -GSU.vOverflow = (SREG ^ imm) & (SREG ^ s) & 0x8000; \ -GSU.vSign = s; \ -GSU.vZero = s; \ -R15++; DREG = s; \ -TESTR14; \ -CLRFLAGS -static inline void fx_sub_i0() { FX_SUB_I(0); } -static inline void fx_sub_i1() { FX_SUB_I(1); } -static inline void fx_sub_i2() { FX_SUB_I(2); } -static inline void fx_sub_i3() { FX_SUB_I(3); } -static inline void fx_sub_i4() { FX_SUB_I(4); } -static inline void fx_sub_i5() { FX_SUB_I(5); } -static inline void fx_sub_i6() { FX_SUB_I(6); } -static inline void fx_sub_i7() { FX_SUB_I(7); } -static inline void fx_sub_i8() { FX_SUB_I(8); } -static inline void fx_sub_i9() { FX_SUB_I(9); } -static inline void fx_sub_i10() { FX_SUB_I(10); } -static inline void fx_sub_i11() { FX_SUB_I(11); } -static inline void fx_sub_i12() { FX_SUB_I(12); } -static inline void fx_sub_i13() { FX_SUB_I(13); } -static inline void fx_sub_i14() { FX_SUB_I(14); } -static inline void fx_sub_i15() { FX_SUB_I(15); } - -/* 60-6f(ALT3) - cmp rn - compare, register, register */ -#define FX_CMP(reg) \ -int32 s = SUSEX16(SREG) - SUSEX16(GSU.avReg[reg]); \ -GSU.vCarry = s >= 0; \ -GSU.vOverflow = (SREG ^ GSU.avReg[reg]) & (SREG ^ s) & 0x8000; \ -GSU.vSign = s; \ -GSU.vZero = s; \ -R15++; \ -CLRFLAGS; -static inline void fx_cmp_r0() { FX_CMP(0); } -static inline void fx_cmp_r1() { FX_CMP(1); } -static inline void fx_cmp_r2() { FX_CMP(2); } -static inline void fx_cmp_r3() { FX_CMP(3); } -static inline void fx_cmp_r4() { FX_CMP(4); } -static inline void fx_cmp_r5() { FX_CMP(5); } -static inline void fx_cmp_r6() { FX_CMP(6); } -static inline void fx_cmp_r7() { FX_CMP(7); } -static inline void fx_cmp_r8() { FX_CMP(8); } -static inline void fx_cmp_r9() { FX_CMP(9); } -static inline void fx_cmp_r10() { FX_CMP(10); } -static inline void fx_cmp_r11() { FX_CMP(11); } -static inline void fx_cmp_r12() { FX_CMP(12); } -static inline void fx_cmp_r13() { FX_CMP(13); } -static inline void fx_cmp_r14() { FX_CMP(14); } -static inline void fx_cmp_r15() { FX_CMP(15); } - -/* 70 - merge - R7 as upper byte, R8 as lower byte (used for texture-mapping) */ -static inline void fx_merge() -{ - uint32 v = (R7&0xff00) | ((R8&0xff00)>>8); - R15++; DREG = v; - GSU.vOverflow = (v & 0xc0c0) << 16; - GSU.vZero = !(v & 0xf0f0); - GSU.vSign = ((v | (v<<8)) & 0x8000); - GSU.vCarry = (v & 0xe0e0) != 0; - TESTR14; - CLRFLAGS; -} - -/* 71-7f - and rn - reister & register */ -#define FX_AND(reg) \ -uint32 v = SREG & GSU.avReg[reg]; \ -R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_and_r1() { FX_AND(1); } -static inline void fx_and_r2() { FX_AND(2); } -static inline void fx_and_r3() { FX_AND(3); } -static inline void fx_and_r4() { FX_AND(4); } -static inline void fx_and_r5() { FX_AND(5); } -static inline void fx_and_r6() { FX_AND(6); } -static inline void fx_and_r7() { FX_AND(7); } -static inline void fx_and_r8() { FX_AND(8); } -static inline void fx_and_r9() { FX_AND(9); } -static inline void fx_and_r10() { FX_AND(10); } -static inline void fx_and_r11() { FX_AND(11); } -static inline void fx_and_r12() { FX_AND(12); } -static inline void fx_and_r13() { FX_AND(13); } -static inline void fx_and_r14() { FX_AND(14); } -static inline void fx_and_r15() { FX_AND(15); } - -/* 71-7f(ALT1) - bic rn - reister & ~register */ -#define FX_BIC(reg) \ -uint32 v = SREG & ~GSU.avReg[reg]; \ -R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_bic_r1() { FX_BIC(1); } -static inline void fx_bic_r2() { FX_BIC(2); } -static inline void fx_bic_r3() { FX_BIC(3); } -static inline void fx_bic_r4() { FX_BIC(4); } -static inline void fx_bic_r5() { FX_BIC(5); } -static inline void fx_bic_r6() { FX_BIC(6); } -static inline void fx_bic_r7() { FX_BIC(7); } -static inline void fx_bic_r8() { FX_BIC(8); } -static inline void fx_bic_r9() { FX_BIC(9); } -static inline void fx_bic_r10() { FX_BIC(10); } -static inline void fx_bic_r11() { FX_BIC(11); } -static inline void fx_bic_r12() { FX_BIC(12); } -static inline void fx_bic_r13() { FX_BIC(13); } -static inline void fx_bic_r14() { FX_BIC(14); } -static inline void fx_bic_r15() { FX_BIC(15); } - -/* 71-7f(ALT2) - and #n - reister & immediate */ -#define FX_AND_I(imm) \ -uint32 v = SREG & imm; \ -R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_and_i1() { FX_AND_I(1); } -static inline void fx_and_i2() { FX_AND_I(2); } -static inline void fx_and_i3() { FX_AND_I(3); } -static inline void fx_and_i4() { FX_AND_I(4); } -static inline void fx_and_i5() { FX_AND_I(5); } -static inline void fx_and_i6() { FX_AND_I(6); } -static inline void fx_and_i7() { FX_AND_I(7); } -static inline void fx_and_i8() { FX_AND_I(8); } -static inline void fx_and_i9() { FX_AND_I(9); } -static inline void fx_and_i10() { FX_AND_I(10); } -static inline void fx_and_i11() { FX_AND_I(11); } -static inline void fx_and_i12() { FX_AND_I(12); } -static inline void fx_and_i13() { FX_AND_I(13); } -static inline void fx_and_i14() { FX_AND_I(14); } -static inline void fx_and_i15() { FX_AND_I(15); } - -/* 71-7f(ALT3) - bic #n - reister & ~immediate */ -#define FX_BIC_I(imm) \ -uint32 v = SREG & ~imm; \ -R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_bic_i1() { FX_BIC_I(1); } -static inline void fx_bic_i2() { FX_BIC_I(2); } -static inline void fx_bic_i3() { FX_BIC_I(3); } -static inline void fx_bic_i4() { FX_BIC_I(4); } -static inline void fx_bic_i5() { FX_BIC_I(5); } -static inline void fx_bic_i6() { FX_BIC_I(6); } -static inline void fx_bic_i7() { FX_BIC_I(7); } -static inline void fx_bic_i8() { FX_BIC_I(8); } -static inline void fx_bic_i9() { FX_BIC_I(9); } -static inline void fx_bic_i10() { FX_BIC_I(10); } -static inline void fx_bic_i11() { FX_BIC_I(11); } -static inline void fx_bic_i12() { FX_BIC_I(12); } -static inline void fx_bic_i13() { FX_BIC_I(13); } -static inline void fx_bic_i14() { FX_BIC_I(14); } -static inline void fx_bic_i15() { FX_BIC_I(15); } - -/* 80-8f - mult rn - 8 bit to 16 bit signed multiply, register * register */ -#define FX_MULT(reg) \ -uint32 v = (uint32)(SEX8(SREG) * SEX8(GSU.avReg[reg])); \ -R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_mult_r0() { FX_MULT(0); } -static inline void fx_mult_r1() { FX_MULT(1); } -static inline void fx_mult_r2() { FX_MULT(2); } -static inline void fx_mult_r3() { FX_MULT(3); } -static inline void fx_mult_r4() { FX_MULT(4); } -static inline void fx_mult_r5() { FX_MULT(5); } -static inline void fx_mult_r6() { FX_MULT(6); } -static inline void fx_mult_r7() { FX_MULT(7); } -static inline void fx_mult_r8() { FX_MULT(8); } -static inline void fx_mult_r9() { FX_MULT(9); } -static inline void fx_mult_r10() { FX_MULT(10); } -static inline void fx_mult_r11() { FX_MULT(11); } -static inline void fx_mult_r12() { FX_MULT(12); } -static inline void fx_mult_r13() { FX_MULT(13); } -static inline void fx_mult_r14() { FX_MULT(14); } -static inline void fx_mult_r15() { FX_MULT(15); } - -/* 80-8f(ALT1) - umult rn - 8 bit to 16 bit unsigned multiply, register * register */ -#define FX_UMULT(reg) \ -uint32 v = USEX8(SREG) * USEX8(GSU.avReg[reg]); \ -R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_umult_r0() { FX_UMULT(0); } -static inline void fx_umult_r1() { FX_UMULT(1); } -static inline void fx_umult_r2() { FX_UMULT(2); } -static inline void fx_umult_r3() { FX_UMULT(3); } -static inline void fx_umult_r4() { FX_UMULT(4); } -static inline void fx_umult_r5() { FX_UMULT(5); } -static inline void fx_umult_r6() { FX_UMULT(6); } -static inline void fx_umult_r7() { FX_UMULT(7); } -static inline void fx_umult_r8() { FX_UMULT(8); } -static inline void fx_umult_r9() { FX_UMULT(9); } -static inline void fx_umult_r10() { FX_UMULT(10); } -static inline void fx_umult_r11() { FX_UMULT(11); } -static inline void fx_umult_r12() { FX_UMULT(12); } -static inline void fx_umult_r13() { FX_UMULT(13); } -static inline void fx_umult_r14() { FX_UMULT(14); } -static inline void fx_umult_r15() { FX_UMULT(15); } - -/* 80-8f(ALT2) - mult #n - 8 bit to 16 bit signed multiply, register * immediate */ -#define FX_MULT_I(imm) \ -uint32 v = (uint32) (SEX8(SREG) * ((int32)imm)); \ -R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_mult_i0() { FX_MULT_I(0); } -static inline void fx_mult_i1() { FX_MULT_I(1); } -static inline void fx_mult_i2() { FX_MULT_I(2); } -static inline void fx_mult_i3() { FX_MULT_I(3); } -static inline void fx_mult_i4() { FX_MULT_I(4); } -static inline void fx_mult_i5() { FX_MULT_I(5); } -static inline void fx_mult_i6() { FX_MULT_I(6); } -static inline void fx_mult_i7() { FX_MULT_I(7); } -static inline void fx_mult_i8() { FX_MULT_I(8); } -static inline void fx_mult_i9() { FX_MULT_I(9); } -static inline void fx_mult_i10() { FX_MULT_I(10); } -static inline void fx_mult_i11() { FX_MULT_I(11); } -static inline void fx_mult_i12() { FX_MULT_I(12); } -static inline void fx_mult_i13() { FX_MULT_I(13); } -static inline void fx_mult_i14() { FX_MULT_I(14); } -static inline void fx_mult_i15() { FX_MULT_I(15); } - -/* 80-8f(ALT3) - umult #n - 8 bit to 16 bit unsigned multiply, register * immediate */ -#define FX_UMULT_I(imm) \ -uint32 v = USEX8(SREG) * ((uint32)imm); \ -R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_umult_i0() { FX_UMULT_I(0); } -static inline void fx_umult_i1() { FX_UMULT_I(1); } -static inline void fx_umult_i2() { FX_UMULT_I(2); } -static inline void fx_umult_i3() { FX_UMULT_I(3); } -static inline void fx_umult_i4() { FX_UMULT_I(4); } -static inline void fx_umult_i5() { FX_UMULT_I(5); } -static inline void fx_umult_i6() { FX_UMULT_I(6); } -static inline void fx_umult_i7() { FX_UMULT_I(7); } -static inline void fx_umult_i8() { FX_UMULT_I(8); } -static inline void fx_umult_i9() { FX_UMULT_I(9); } -static inline void fx_umult_i10() { FX_UMULT_I(10); } -static inline void fx_umult_i11() { FX_UMULT_I(11); } -static inline void fx_umult_i12() { FX_UMULT_I(12); } -static inline void fx_umult_i13() { FX_UMULT_I(13); } -static inline void fx_umult_i14() { FX_UMULT_I(14); } -static inline void fx_umult_i15() { FX_UMULT_I(15); } - -/* 90 - sbk - store word to last accessed RAM address */ -static inline void fx_sbk() -{ - RAM(GSU.vLastRamAdr) = (uint8)SREG; - RAM(GSU.vLastRamAdr^1) = (uint8)(SREG>>8); - CLRFLAGS; - R15++; -} - -/* 91-94 - link #n - R11 = R15 + immediate */ -#define FX_LINK_I(lkn) R11 = R15 + lkn; CLRFLAGS; R15++ -static inline void fx_link_i1() { FX_LINK_I(1); } -static inline void fx_link_i2() { FX_LINK_I(2); } -static inline void fx_link_i3() { FX_LINK_I(3); } -static inline void fx_link_i4() { FX_LINK_I(4); } - -/* 95 - sex - sign extend 8 bit to 16 bit */ -static inline void fx_sex() -{ - uint32 v = (uint32)SEX8(SREG); - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -/* 96 - asr - aritmetric shift right by one */ -static inline void fx_asr() -{ - uint32 v; - GSU.vCarry = SREG & 1; - v = (uint32)(SEX16(SREG)>>1); - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -/* 96(ALT1) - div2 - aritmetric shift right by one */ -static inline void fx_div2() -{ - uint32 v; - int32 s = SEX16(SREG); - GSU.vCarry = s & 1; - if(s == -1) - v = 0; - else - v = (uint32)(s>>1); - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -/* 97 - ror - rotate right by one */ -static inline void fx_ror() -{ - uint32 v = (USEX16(SREG)>>1) | (GSU.vCarry<<15); - GSU.vCarry = SREG & 1; - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - TESTR14; - CLRFLAGS; -} - -/* 98-9d - jmp rn - jump to address of register */ -#define FX_JMP(reg) \ -R15 = GSU.avReg[reg]; \ -CLRFLAGS; -static inline void fx_jmp_r8() { FX_JMP(8); } -static inline void fx_jmp_r9() { FX_JMP(9); } -static inline void fx_jmp_r10() { FX_JMP(10); } -static inline void fx_jmp_r11() { FX_JMP(11); } -static inline void fx_jmp_r12() { FX_JMP(12); } -static inline void fx_jmp_r13() { FX_JMP(13); } - -/* 98-9d(ALT1) - ljmp rn - set program bank to source register and jump to address of register */ -#define FX_LJMP(reg) \ -GSU.vPrgBankReg = GSU.avReg[reg] & 0x7f; \ -GSU.pvPrgBank = GSU.apvRomBank[GSU.vPrgBankReg]; \ -R15 = SREG; \ -GSU.bCacheActive = FALSE; fx_cache(); R15--; -static inline void fx_ljmp_r8() { FX_LJMP(8); } -static inline void fx_ljmp_r9() { FX_LJMP(9); } -static inline void fx_ljmp_r10() { FX_LJMP(10); } -static inline void fx_ljmp_r11() { FX_LJMP(11); } -static inline void fx_ljmp_r12() { FX_LJMP(12); } -static inline void fx_ljmp_r13() { FX_LJMP(13); } - -/* 9e - lob - set upper byte to zero (keep low byte) */ -static inline void fx_lob() -{ - uint32 v = USEX8(SREG); - R15++; DREG = v; - GSU.vSign = v<<8; - GSU.vZero = v<<8; - TESTR14; - CLRFLAGS; -} - -/* 9f - fmult - 16 bit to 32 bit signed multiplication, upper 16 bits only */ -static inline void fx_fmult() -{ - uint32 v; - uint32 c = (uint32) (SEX16(SREG) * SEX16(R6)); - v = c >> 16; - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - GSU.vCarry = (c >> 15) & 1; - TESTR14; - CLRFLAGS; -} - -/* 9f(ALT1) - lmult - 16 bit to 32 bit signed multiplication */ -static inline void fx_lmult() -{ - uint32 v; - uint32 c = (uint32) (SEX16(SREG) * SEX16(R6)); - R4 = c; - v = c >> 16; - R15++; DREG = v; - GSU.vSign = v; - GSU.vZero = v; - /* XXX R6 or R4? */ - GSU.vCarry = (R4 >> 15) & 1; /* should it be bit 15 of R4 instead? */ - TESTR14; - CLRFLAGS; -} - -/* a0-af - ibt rn,#pp - immediate byte transfer */ -#define FX_IBT(reg) \ -uint8 v = PIPE; R15++; \ -FETCHPIPE; R15++; \ -GSU.avReg[reg] = SEX8(v); \ -CLRFLAGS; -static inline void fx_ibt_r0() { FX_IBT(0); } -static inline void fx_ibt_r1() { FX_IBT(1); } -static inline void fx_ibt_r2() { FX_IBT(2); } -static inline void fx_ibt_r3() { FX_IBT(3); } -static inline void fx_ibt_r4() { FX_IBT(4); } -static inline void fx_ibt_r5() { FX_IBT(5); } -static inline void fx_ibt_r6() { FX_IBT(6); } -static inline void fx_ibt_r7() { FX_IBT(7); } -static inline void fx_ibt_r8() { FX_IBT(8); } -static inline void fx_ibt_r9() { FX_IBT(9); } -static inline void fx_ibt_r10() { FX_IBT(10); } -static inline void fx_ibt_r11() { FX_IBT(11); } -static inline void fx_ibt_r12() { FX_IBT(12); } -static inline void fx_ibt_r13() { FX_IBT(13); } -static inline void fx_ibt_r14() { FX_IBT(14); READR14; } -static inline void fx_ibt_r15() { FX_IBT(15); } - -/* a0-af(ALT1) - lms rn,(yy) - load word from RAM (short address) */ -#define FX_LMS(reg) \ -GSU.vLastRamAdr = ((uint32)PIPE) << 1; \ -R15++; FETCHPIPE; R15++; \ -GSU.avReg[reg] = (uint32)RAM(GSU.vLastRamAdr); \ -GSU.avReg[reg] |= ((uint32)RAM(GSU.vLastRamAdr+1))<<8; \ -CLRFLAGS; -static inline void fx_lms_r0() { FX_LMS(0); } -static inline void fx_lms_r1() { FX_LMS(1); } -static inline void fx_lms_r2() { FX_LMS(2); } -static inline void fx_lms_r3() { FX_LMS(3); } -static inline void fx_lms_r4() { FX_LMS(4); } -static inline void fx_lms_r5() { FX_LMS(5); } -static inline void fx_lms_r6() { FX_LMS(6); } -static inline void fx_lms_r7() { FX_LMS(7); } -static inline void fx_lms_r8() { FX_LMS(8); } -static inline void fx_lms_r9() { FX_LMS(9); } -static inline void fx_lms_r10() { FX_LMS(10); } -static inline void fx_lms_r11() { FX_LMS(11); } -static inline void fx_lms_r12() { FX_LMS(12); } -static inline void fx_lms_r13() { FX_LMS(13); } -static inline void fx_lms_r14() { FX_LMS(14); READR14; } -static inline void fx_lms_r15() { FX_LMS(15); } - -/* a0-af(ALT2) - sms (yy),rn - store word in RAM (short address) */ -/* If rn == r15, is the value of r15 before or after the extra byte is read? */ -#define FX_SMS(reg) \ -uint32 v = GSU.avReg[reg]; \ -GSU.vLastRamAdr = ((uint32)PIPE) << 1; \ -R15++; FETCHPIPE; \ -RAM(GSU.vLastRamAdr) = (uint8)v; \ -RAM(GSU.vLastRamAdr+1) = (uint8)(v>>8); \ -CLRFLAGS; R15++; -static inline void fx_sms_r0() { FX_SMS(0); } -static inline void fx_sms_r1() { FX_SMS(1); } -static inline void fx_sms_r2() { FX_SMS(2); } -static inline void fx_sms_r3() { FX_SMS(3); } -static inline void fx_sms_r4() { FX_SMS(4); } -static inline void fx_sms_r5() { FX_SMS(5); } -static inline void fx_sms_r6() { FX_SMS(6); } -static inline void fx_sms_r7() { FX_SMS(7); } -static inline void fx_sms_r8() { FX_SMS(8); } -static inline void fx_sms_r9() { FX_SMS(9); } -static inline void fx_sms_r10() { FX_SMS(10); } -static inline void fx_sms_r11() { FX_SMS(11); } -static inline void fx_sms_r12() { FX_SMS(12); } -static inline void fx_sms_r13() { FX_SMS(13); } -static inline void fx_sms_r14() { FX_SMS(14); } -static inline void fx_sms_r15() { FX_SMS(15); } - -/* b0-bf - from rn - set source register */ -/* b0-bf(B) - moves rn - move register to register, and set flags, (if B flag is set) */ -#define FX_FROM(reg) \ -if(TF(B)) { uint32 v = GSU.avReg[reg]; R15++; DREG = v; \ -GSU.vOverflow = (v&0x80) << 16; GSU.vSign = v; GSU.vZero = v; TESTR14; CLRFLAGS; } \ -else { GSU.pvSreg = &GSU.avReg[reg]; R15++; } -static inline void fx_from_r0() { FX_FROM(0); } -static inline void fx_from_r1() { FX_FROM(1); } -static inline void fx_from_r2() { FX_FROM(2); } -static inline void fx_from_r3() { FX_FROM(3); } -static inline void fx_from_r4() { FX_FROM(4); } -static inline void fx_from_r5() { FX_FROM(5); } -static inline void fx_from_r6() { FX_FROM(6); } -static inline void fx_from_r7() { FX_FROM(7); } -static inline void fx_from_r8() { FX_FROM(8); } -static inline void fx_from_r9() { FX_FROM(9); } -static inline void fx_from_r10() { FX_FROM(10); } -static inline void fx_from_r11() { FX_FROM(11); } -static inline void fx_from_r12() { FX_FROM(12); } -static inline void fx_from_r13() { FX_FROM(13); } -static inline void fx_from_r14() { FX_FROM(14); } -static inline void fx_from_r15() { FX_FROM(15); } - -/* c0 - hib - move high-byte to low-byte */ -static inline void fx_hib() -{ - uint32 v = USEX8(SREG>>8); - R15++; DREG = v; - GSU.vSign = v<<8; - GSU.vZero = v<<8; - TESTR14; - CLRFLAGS; -} - -/* c1-cf - or rn */ -#define FX_OR(reg) \ -uint32 v = SREG | GSU.avReg[reg]; R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_or_r1() { FX_OR(1); } -static inline void fx_or_r2() { FX_OR(2); } -static inline void fx_or_r3() { FX_OR(3); } -static inline void fx_or_r4() { FX_OR(4); } -static inline void fx_or_r5() { FX_OR(5); } -static inline void fx_or_r6() { FX_OR(6); } -static inline void fx_or_r7() { FX_OR(7); } -static inline void fx_or_r8() { FX_OR(8); } -static inline void fx_or_r9() { FX_OR(9); } -static inline void fx_or_r10() { FX_OR(10); } -static inline void fx_or_r11() { FX_OR(11); } -static inline void fx_or_r12() { FX_OR(12); } -static inline void fx_or_r13() { FX_OR(13); } -static inline void fx_or_r14() { FX_OR(14); } -static inline void fx_or_r15() { FX_OR(15); } - -/* c1-cf(ALT1) - xor rn */ -#define FX_XOR(reg) \ -uint32 v = SREG ^ GSU.avReg[reg]; R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_xor_r1() { FX_XOR(1); } -static inline void fx_xor_r2() { FX_XOR(2); } -static inline void fx_xor_r3() { FX_XOR(3); } -static inline void fx_xor_r4() { FX_XOR(4); } -static inline void fx_xor_r5() { FX_XOR(5); } -static inline void fx_xor_r6() { FX_XOR(6); } -static inline void fx_xor_r7() { FX_XOR(7); } -static inline void fx_xor_r8() { FX_XOR(8); } -static inline void fx_xor_r9() { FX_XOR(9); } -static inline void fx_xor_r10() { FX_XOR(10); } -static inline void fx_xor_r11() { FX_XOR(11); } -static inline void fx_xor_r12() { FX_XOR(12); } -static inline void fx_xor_r13() { FX_XOR(13); } -static inline void fx_xor_r14() { FX_XOR(14); } -static inline void fx_xor_r15() { FX_XOR(15); } - -/* c1-cf(ALT2) - or #n */ -#define FX_OR_I(imm) \ -uint32 v = SREG | imm; R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_or_i1() { FX_OR_I(1); } -static inline void fx_or_i2() { FX_OR_I(2); } -static inline void fx_or_i3() { FX_OR_I(3); } -static inline void fx_or_i4() { FX_OR_I(4); } -static inline void fx_or_i5() { FX_OR_I(5); } -static inline void fx_or_i6() { FX_OR_I(6); } -static inline void fx_or_i7() { FX_OR_I(7); } -static inline void fx_or_i8() { FX_OR_I(8); } -static inline void fx_or_i9() { FX_OR_I(9); } -static inline void fx_or_i10() { FX_OR_I(10); } -static inline void fx_or_i11() { FX_OR_I(11); } -static inline void fx_or_i12() { FX_OR_I(12); } -static inline void fx_or_i13() { FX_OR_I(13); } -static inline void fx_or_i14() { FX_OR_I(14); } -static inline void fx_or_i15() { FX_OR_I(15); } - -/* c1-cf(ALT3) - xor #n */ -#define FX_XOR_I(imm) \ -uint32 v = SREG ^ imm; R15++; DREG = v; \ -GSU.vSign = v; \ -GSU.vZero = v; \ -TESTR14; \ -CLRFLAGS; -static inline void fx_xor_i1() { FX_XOR_I(1); } -static inline void fx_xor_i2() { FX_XOR_I(2); } -static inline void fx_xor_i3() { FX_XOR_I(3); } -static inline void fx_xor_i4() { FX_XOR_I(4); } -static inline void fx_xor_i5() { FX_XOR_I(5); } -static inline void fx_xor_i6() { FX_XOR_I(6); } -static inline void fx_xor_i7() { FX_XOR_I(7); } -static inline void fx_xor_i8() { FX_XOR_I(8); } -static inline void fx_xor_i9() { FX_XOR_I(9); } -static inline void fx_xor_i10() { FX_XOR_I(10); } -static inline void fx_xor_i11() { FX_XOR_I(11); } -static inline void fx_xor_i12() { FX_XOR_I(12); } -static inline void fx_xor_i13() { FX_XOR_I(13); } -static inline void fx_xor_i14() { FX_XOR_I(14); } -static inline void fx_xor_i15() { FX_XOR_I(15); } - -/* d0-de - inc rn - increase by one */ -#define FX_INC(reg) \ -GSU.avReg[reg] += 1; \ -GSU.vSign = GSU.avReg[reg]; \ -GSU.vZero = GSU.avReg[reg]; \ -CLRFLAGS; R15++; -static inline void fx_inc_r0() { FX_INC(0); } -static inline void fx_inc_r1() { FX_INC(1); } -static inline void fx_inc_r2() { FX_INC(2); } -static inline void fx_inc_r3() { FX_INC(3); } -static inline void fx_inc_r4() { FX_INC(4); } -static inline void fx_inc_r5() { FX_INC(5); } -static inline void fx_inc_r6() { FX_INC(6); } -static inline void fx_inc_r7() { FX_INC(7); } -static inline void fx_inc_r8() { FX_INC(8); } -static inline void fx_inc_r9() { FX_INC(9); } -static inline void fx_inc_r10() { FX_INC(10); } -static inline void fx_inc_r11() { FX_INC(11); } -static inline void fx_inc_r12() { FX_INC(12); } -static inline void fx_inc_r13() { FX_INC(13); } -static inline void fx_inc_r14() { FX_INC(14); READR14; } - -/* df - getc - transfer ROM buffer to color register */ -static inline void fx_getc() -{ -#ifndef FX_DO_ROMBUFFER - uint8 c; - c = ROM(R14); -#else - uint8 c = GSU.vRomBuffer; -#endif - if(GSU.vPlotOptionReg & 0x04) - c = (c&0xf0) | (c>>4); - if(GSU.vPlotOptionReg & 0x08) - { - GSU.vColorReg &= 0xf0; - GSU.vColorReg |= c & 0x0f; - } - else - GSU.vColorReg = USEX8(c); - CLRFLAGS; - R15++; -} - -/* df(ALT2) - ramb - set current RAM bank */ -static inline void fx_ramb() -{ - GSU.vRamBankReg = SREG & (FX_RAM_BANKS-1); - GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; - CLRFLAGS; - R15++; -} - -/* df(ALT3) - romb - set current ROM bank */ -static inline void fx_romb() -{ - GSU.vRomBankReg = USEX8(SREG) & 0x7f; - GSU.pvRomBank = GSU.apvRomBank[GSU.vRomBankReg]; - CLRFLAGS; - R15++; -} - -/* e0-ee - dec rn - decrement by one */ -#define FX_DEC(reg) \ -GSU.avReg[reg] -= 1; \ -GSU.vSign = GSU.avReg[reg]; \ -GSU.vZero = GSU.avReg[reg]; \ -CLRFLAGS; R15++; -static inline void fx_dec_r0() { FX_DEC(0); } -static inline void fx_dec_r1() { FX_DEC(1); } -static inline void fx_dec_r2() { FX_DEC(2); } -static inline void fx_dec_r3() { FX_DEC(3); } -static inline void fx_dec_r4() { FX_DEC(4); } -static inline void fx_dec_r5() { FX_DEC(5); } -static inline void fx_dec_r6() { FX_DEC(6); } -static inline void fx_dec_r7() { FX_DEC(7); } -static inline void fx_dec_r8() { FX_DEC(8); } -static inline void fx_dec_r9() { FX_DEC(9); } -static inline void fx_dec_r10() { FX_DEC(10); } -static inline void fx_dec_r11() { FX_DEC(11); } -static inline void fx_dec_r12() { FX_DEC(12); } -static inline void fx_dec_r13() { FX_DEC(13); } -static inline void fx_dec_r14() { FX_DEC(14); READR14; } - -/* ef - getb - get byte from ROM at address R14 */ -static inline void fx_getb() -{ - uint32 v; -#ifndef FX_DO_ROMBUFFER - v = (uint32)ROM(R14); -#else - v = (uint32)GSU.vRomBuffer; -#endif - R15++; DREG = v; - TESTR14; - CLRFLAGS; -} - -/* ef(ALT1) - getbh - get high-byte from ROM at address R14 */ -static inline void fx_getbh() -{ - uint32 v; -#ifndef FX_DO_ROMBUFFER - uint32 c; - c = (uint32)ROM(R14); -#else - uint32 c = USEX8(GSU.vRomBuffer); -#endif - v = USEX8(SREG) | (c<<8); - R15++; DREG = v; - TESTR14; - CLRFLAGS; -} - -/* ef(ALT2) - getbl - get low-byte from ROM at address R14 */ -static inline void fx_getbl() -{ - uint32 v; -#ifndef FX_DO_ROMBUFFER - uint32 c; - c = (uint32)ROM(R14); -#else - uint32 c = USEX8(GSU.vRomBuffer); -#endif - v = (SREG & 0xff00) | c; - R15++; DREG = v; - TESTR14; - CLRFLAGS; -} - -/* ef(ALT3) - getbs - get sign extended byte from ROM at address R14 */ -static inline void fx_getbs() -{ - uint32 v; -#ifndef FX_DO_ROMBUFFER - int8 c; - c = ROM(R14); - v = SEX8(c); -#else - v = SEX8(GSU.vRomBuffer); -#endif - R15++; DREG = v; - TESTR14; - CLRFLAGS; -} - -/* f0-ff - iwt rn,#xx - immediate word transfer to register */ -#define FX_IWT(reg) \ -uint32 v = PIPE; R15++; FETCHPIPE; R15++; \ -v |= USEX8(PIPE) << 8; FETCHPIPE; R15++; \ -GSU.avReg[reg] = v; \ -CLRFLAGS; -static inline void fx_iwt_r0() { FX_IWT(0); } -static inline void fx_iwt_r1() { FX_IWT(1); } -static inline void fx_iwt_r2() { FX_IWT(2); } -static inline void fx_iwt_r3() { FX_IWT(3); } -static inline void fx_iwt_r4() { FX_IWT(4); } -static inline void fx_iwt_r5() { FX_IWT(5); } -static inline void fx_iwt_r6() { FX_IWT(6); } -static inline void fx_iwt_r7() { FX_IWT(7); } -static inline void fx_iwt_r8() { FX_IWT(8); } -static inline void fx_iwt_r9() { FX_IWT(9); } -static inline void fx_iwt_r10() { FX_IWT(10); } -static inline void fx_iwt_r11() { FX_IWT(11); } -static inline void fx_iwt_r12() { FX_IWT(12); } -static inline void fx_iwt_r13() { FX_IWT(13); } -static inline void fx_iwt_r14() { FX_IWT(14); READR14; } -static inline void fx_iwt_r15() { FX_IWT(15); } - -/* f0-ff(ALT1) - lm rn,(xx) - load word from RAM */ -#define FX_LM(reg) \ -GSU.vLastRamAdr = PIPE; R15++; FETCHPIPE; R15++; \ -GSU.vLastRamAdr |= USEX8(PIPE) << 8; FETCHPIPE; R15++; \ -GSU.avReg[reg] = RAM(GSU.vLastRamAdr); \ -GSU.avReg[reg] |= USEX8(RAM(GSU.vLastRamAdr^1)) << 8; \ -CLRFLAGS; -static inline void fx_lm_r0() { FX_LM(0); } -static inline void fx_lm_r1() { FX_LM(1); } -static inline void fx_lm_r2() { FX_LM(2); } -static inline void fx_lm_r3() { FX_LM(3); } -static inline void fx_lm_r4() { FX_LM(4); } -static inline void fx_lm_r5() { FX_LM(5); } -static inline void fx_lm_r6() { FX_LM(6); } -static inline void fx_lm_r7() { FX_LM(7); } -static inline void fx_lm_r8() { FX_LM(8); } -static inline void fx_lm_r9() { FX_LM(9); } -static inline void fx_lm_r10() { FX_LM(10); } -static inline void fx_lm_r11() { FX_LM(11); } -static inline void fx_lm_r12() { FX_LM(12); } -static inline void fx_lm_r13() { FX_LM(13); } -static inline void fx_lm_r14() { FX_LM(14); READR14; } -static inline void fx_lm_r15() { FX_LM(15); } - -/* f0-ff(ALT2) - sm (xx),rn - store word in RAM */ -/* If rn == r15, is the value of r15 before or after the extra bytes are read? */ -#define FX_SM(reg) \ -uint32 v = GSU.avReg[reg]; \ -GSU.vLastRamAdr = PIPE; R15++; FETCHPIPE; R15++; \ -GSU.vLastRamAdr |= USEX8(PIPE) << 8; FETCHPIPE; \ -RAM(GSU.vLastRamAdr) = (uint8)v; \ -RAM(GSU.vLastRamAdr^1) = (uint8)(v>>8); \ -CLRFLAGS; R15++; -static inline void fx_sm_r0() { FX_SM(0); } -static inline void fx_sm_r1() { FX_SM(1); } -static inline void fx_sm_r2() { FX_SM(2); } -static inline void fx_sm_r3() { FX_SM(3); } -static inline void fx_sm_r4() { FX_SM(4); } -static inline void fx_sm_r5() { FX_SM(5); } -static inline void fx_sm_r6() { FX_SM(6); } -static inline void fx_sm_r7() { FX_SM(7); } -static inline void fx_sm_r8() { FX_SM(8); } -static inline void fx_sm_r9() { FX_SM(9); } -static inline void fx_sm_r10() { FX_SM(10); } -static inline void fx_sm_r11() { FX_SM(11); } -static inline void fx_sm_r12() { FX_SM(12); } -static inline void fx_sm_r13() { FX_SM(13); } -static inline void fx_sm_r14() { FX_SM(14); } -static inline void fx_sm_r15() { FX_SM(15); } - -/*** GSU executions functions ***/ - -static uint32 fx_run(uint32 nInstructions) -{ - GSU.vCounter = nInstructions; - READR14; - while( TF(G) && (GSU.vCounter-- > 0) ) - FX_STEP; - /* -#ifndef FX_ADDRESS_CHECK - GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); -#endif -*/ - return (nInstructions - GSU.vInstCount); -} - -static uint32 fx_run_to_breakpoint(uint32 nInstructions) -{ - uint32 vCounter = 0; - while(TF(G) && vCounter < nInstructions) - { - vCounter++; - FX_STEP; - if(USEX16(R15) == GSU.vBreakPoint) - { - GSU.vErrorCode = FX_BREAKPOINT; - break; - } - } - /* -#ifndef FX_ADDRESS_CHECK - GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); -#endif -*/ - return vCounter; -} - -static uint32 fx_step_over(uint32 nInstructions) -{ - uint32 vCounter = 0; - while(TF(G) && vCounter < nInstructions) - { - vCounter++; - FX_STEP; - if(USEX16(R15) == GSU.vBreakPoint) - { - GSU.vErrorCode = FX_BREAKPOINT; - break; - } - if(USEX16(R15) == GSU.vStepPoint) - break; - } - /* -#ifndef FX_ADDRESS_CHECK - GSU.vPipeAdr = USEX16(R15-1) | (USEX8(GSU.vPrgBankReg)<<16); -#endif -*/ - return vCounter; -} - -#ifdef FX_FUNCTION_TABLE -uint32 (*FX_FUNCTION_TABLE[])(uint32) = -#else -uint32 (*fx_apfFunctionTable[])(uint32) = -#endif -{ - &fx_run, - &fx_run_to_breakpoint, - &fx_step_over, -}; - -/*** Special table for the different plot configurations ***/ - -#ifdef FX_PLOT_TABLE -void (*FX_PLOT_TABLE[])() = -#else -void (*fx_apfPlotTable[])() = -#endif -{ - &fx_plot_2bit, &fx_plot_4bit, &fx_plot_4bit, &fx_plot_8bit, &fx_plot_obj, - &fx_rpix_2bit, &fx_rpix_4bit, &fx_rpix_4bit, &fx_rpix_8bit, &fx_rpix_obj, -}; - -/*** Opcode table ***/ - -#ifdef FX_OPCODE_TABLE -void (*FX_OPCODE_TABLE[])() = -#else -void (*fx_apfOpcodeTable[])() = -#endif -{ - /* - * ALT0 Table - */ - /* 00 - 0f */ - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - /* 10 - 1f */ - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - /* 30 - 3f */ - &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, - &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - /* 40 - 4f */ - &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, - &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit,&fx_swap, &fx_color, &fx_not, - /* 50 - 5f */ - &fx_add_r0, &fx_add_r1, &fx_add_r2, &fx_add_r3, &fx_add_r4, &fx_add_r5, &fx_add_r6, &fx_add_r7, - &fx_add_r8, &fx_add_r9, &fx_add_r10, &fx_add_r11, &fx_add_r12, &fx_add_r13, &fx_add_r14, &fx_add_r15, - /* 60 - 6f */ - &fx_sub_r0, &fx_sub_r1, &fx_sub_r2, &fx_sub_r3, &fx_sub_r4, &fx_sub_r5, &fx_sub_r6, &fx_sub_r7, - &fx_sub_r8, &fx_sub_r9, &fx_sub_r10, &fx_sub_r11, &fx_sub_r12, &fx_sub_r13, &fx_sub_r14, &fx_sub_r15, - /* 70 - 7f */ - &fx_merge, &fx_and_r1, &fx_and_r2, &fx_and_r3, &fx_and_r4, &fx_and_r5, &fx_and_r6, &fx_and_r7, - &fx_and_r8, &fx_and_r9, &fx_and_r10, &fx_and_r11, &fx_and_r12, &fx_and_r13, &fx_and_r14, &fx_and_r15, - /* 80 - 8f */ - &fx_mult_r0, &fx_mult_r1, &fx_mult_r2, &fx_mult_r3, &fx_mult_r4, &fx_mult_r5, &fx_mult_r6, &fx_mult_r7, - &fx_mult_r8, &fx_mult_r9, &fx_mult_r10, &fx_mult_r11, &fx_mult_r12, &fx_mult_r13, &fx_mult_r14, &fx_mult_r15, - /* 90 - 9f */ - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, - &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, - /* a0 - af */ - &fx_ibt_r0, &fx_ibt_r1, &fx_ibt_r2, &fx_ibt_r3, &fx_ibt_r4, &fx_ibt_r5, &fx_ibt_r6, &fx_ibt_r7, - &fx_ibt_r8, &fx_ibt_r9, &fx_ibt_r10, &fx_ibt_r11, &fx_ibt_r12, &fx_ibt_r13, &fx_ibt_r14, &fx_ibt_r15, - /* b0 - bf */ - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - /* c0 - cf */ - &fx_hib, &fx_or_r1, &fx_or_r2, &fx_or_r3, &fx_or_r4, &fx_or_r5, &fx_or_r6, &fx_or_r7, - &fx_or_r8, &fx_or_r9, &fx_or_r10, &fx_or_r11, &fx_or_r12, &fx_or_r13, &fx_or_r14, &fx_or_r15, - /* d0 - df */ - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, - /* e0 - ef */ - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getb, - /* f0 - ff */ - &fx_iwt_r0, &fx_iwt_r1, &fx_iwt_r2, &fx_iwt_r3, &fx_iwt_r4, &fx_iwt_r5, &fx_iwt_r6, &fx_iwt_r7, - &fx_iwt_r8, &fx_iwt_r9, &fx_iwt_r10, &fx_iwt_r11, &fx_iwt_r12, &fx_iwt_r13, &fx_iwt_r14, &fx_iwt_r15, - - /* - * ALT1 Table - */ - - /* 00 - 0f */ - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - /* 10 - 1f */ - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - /* 30 - 3f */ - &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, - &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - /* 40 - 4f */ - &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, - &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit,&fx_swap, &fx_cmode, &fx_not, - /* 50 - 5f */ - &fx_adc_r0, &fx_adc_r1, &fx_adc_r2, &fx_adc_r3, &fx_adc_r4, &fx_adc_r5, &fx_adc_r6, &fx_adc_r7, - &fx_adc_r8, &fx_adc_r9, &fx_adc_r10, &fx_adc_r11, &fx_adc_r12, &fx_adc_r13, &fx_adc_r14, &fx_adc_r15, - /* 60 - 6f */ - &fx_sbc_r0, &fx_sbc_r1, &fx_sbc_r2, &fx_sbc_r3, &fx_sbc_r4, &fx_sbc_r5, &fx_sbc_r6, &fx_sbc_r7, - &fx_sbc_r8, &fx_sbc_r9, &fx_sbc_r10, &fx_sbc_r11, &fx_sbc_r12, &fx_sbc_r13, &fx_sbc_r14, &fx_sbc_r15, - /* 70 - 7f */ - &fx_merge, &fx_bic_r1, &fx_bic_r2, &fx_bic_r3, &fx_bic_r4, &fx_bic_r5, &fx_bic_r6, &fx_bic_r7, - &fx_bic_r8, &fx_bic_r9, &fx_bic_r10, &fx_bic_r11, &fx_bic_r12, &fx_bic_r13, &fx_bic_r14, &fx_bic_r15, - /* 80 - 8f */ - &fx_umult_r0,&fx_umult_r1,&fx_umult_r2, &fx_umult_r3, &fx_umult_r4, &fx_umult_r5, &fx_umult_r6, &fx_umult_r7, - &fx_umult_r8,&fx_umult_r9,&fx_umult_r10,&fx_umult_r11,&fx_umult_r12,&fx_umult_r13,&fx_umult_r14,&fx_umult_r15, - /* 90 - 9f */ - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, - &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, - /* a0 - af */ - &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, - &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, - /* b0 - bf */ - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - /* c0 - cf */ - &fx_hib, &fx_xor_r1, &fx_xor_r2, &fx_xor_r3, &fx_xor_r4, &fx_xor_r5, &fx_xor_r6, &fx_xor_r7, - &fx_xor_r8, &fx_xor_r9, &fx_xor_r10, &fx_xor_r11, &fx_xor_r12, &fx_xor_r13, &fx_xor_r14, &fx_xor_r15, - /* d0 - df */ - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_getc, - /* e0 - ef */ - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbh, - /* f0 - ff */ - &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, - &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, - - /* - * ALT2 Table - */ - - /* 00 - 0f */ - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - /* 10 - 1f */ - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - /* 30 - 3f */ - &fx_stw_r0, &fx_stw_r1, &fx_stw_r2, &fx_stw_r3, &fx_stw_r4, &fx_stw_r5, &fx_stw_r6, &fx_stw_r7, - &fx_stw_r8, &fx_stw_r9, &fx_stw_r10, &fx_stw_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - /* 40 - 4f */ - &fx_ldw_r0, &fx_ldw_r1, &fx_ldw_r2, &fx_ldw_r3, &fx_ldw_r4, &fx_ldw_r5, &fx_ldw_r6, &fx_ldw_r7, - &fx_ldw_r8, &fx_ldw_r9, &fx_ldw_r10, &fx_ldw_r11, &fx_plot_2bit,&fx_swap, &fx_color, &fx_not, - /* 50 - 5f */ - &fx_add_i0, &fx_add_i1, &fx_add_i2, &fx_add_i3, &fx_add_i4, &fx_add_i5, &fx_add_i6, &fx_add_i7, - &fx_add_i8, &fx_add_i9, &fx_add_i10, &fx_add_i11, &fx_add_i12, &fx_add_i13, &fx_add_i14, &fx_add_i15, - /* 60 - 6f */ - &fx_sub_i0, &fx_sub_i1, &fx_sub_i2, &fx_sub_i3, &fx_sub_i4, &fx_sub_i5, &fx_sub_i6, &fx_sub_i7, - &fx_sub_i8, &fx_sub_i9, &fx_sub_i10, &fx_sub_i11, &fx_sub_i12, &fx_sub_i13, &fx_sub_i14, &fx_sub_i15, - /* 70 - 7f */ - &fx_merge, &fx_and_i1, &fx_and_i2, &fx_and_i3, &fx_and_i4, &fx_and_i5, &fx_and_i6, &fx_and_i7, - &fx_and_i8, &fx_and_i9, &fx_and_i10, &fx_and_i11, &fx_and_i12, &fx_and_i13, &fx_and_i14, &fx_and_i15, - /* 80 - 8f */ - &fx_mult_i0, &fx_mult_i1, &fx_mult_i2, &fx_mult_i3, &fx_mult_i4, &fx_mult_i5, &fx_mult_i6, &fx_mult_i7, - &fx_mult_i8, &fx_mult_i9, &fx_mult_i10, &fx_mult_i11, &fx_mult_i12, &fx_mult_i13, &fx_mult_i14, &fx_mult_i15, - /* 90 - 9f */ - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_asr, &fx_ror, - &fx_jmp_r8, &fx_jmp_r9, &fx_jmp_r10, &fx_jmp_r11, &fx_jmp_r12, &fx_jmp_r13, &fx_lob, &fx_fmult, - /* a0 - af */ - &fx_sms_r0, &fx_sms_r1, &fx_sms_r2, &fx_sms_r3, &fx_sms_r4, &fx_sms_r5, &fx_sms_r6, &fx_sms_r7, - &fx_sms_r8, &fx_sms_r9, &fx_sms_r10, &fx_sms_r11, &fx_sms_r12, &fx_sms_r13, &fx_sms_r14, &fx_sms_r15, - /* b0 - bf */ - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - /* c0 - cf */ - &fx_hib, &fx_or_i1, &fx_or_i2, &fx_or_i3, &fx_or_i4, &fx_or_i5, &fx_or_i6, &fx_or_i7, - &fx_or_i8, &fx_or_i9, &fx_or_i10, &fx_or_i11, &fx_or_i12, &fx_or_i13, &fx_or_i14, &fx_or_i15, - /* d0 - df */ - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_ramb, - /* e0 - ef */ - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbl, - /* f0 - ff */ - &fx_sm_r0, &fx_sm_r1, &fx_sm_r2, &fx_sm_r3, &fx_sm_r4, &fx_sm_r5, &fx_sm_r6, &fx_sm_r7, - &fx_sm_r8, &fx_sm_r9, &fx_sm_r10, &fx_sm_r11, &fx_sm_r12, &fx_sm_r13, &fx_sm_r14, &fx_sm_r15, - - /* - * ALT3 Table - */ - - /* 00 - 0f */ - &fx_stop, &fx_nop, &fx_cache, &fx_lsr, &fx_rol, &fx_bra, &fx_bge, &fx_blt, - &fx_bne, &fx_beq, &fx_bpl, &fx_bmi, &fx_bcc, &fx_bcs, &fx_bvc, &fx_bvs, - /* 10 - 1f */ - &fx_to_r0, &fx_to_r1, &fx_to_r2, &fx_to_r3, &fx_to_r4, &fx_to_r5, &fx_to_r6, &fx_to_r7, - &fx_to_r8, &fx_to_r9, &fx_to_r10, &fx_to_r11, &fx_to_r12, &fx_to_r13, &fx_to_r14, &fx_to_r15, - /* 20 - 2f */ - &fx_with_r0, &fx_with_r1, &fx_with_r2, &fx_with_r3, &fx_with_r4, &fx_with_r5, &fx_with_r6, &fx_with_r7, - &fx_with_r8, &fx_with_r9, &fx_with_r10, &fx_with_r11, &fx_with_r12, &fx_with_r13, &fx_with_r14, &fx_with_r15, - /* 30 - 3f */ - &fx_stb_r0, &fx_stb_r1, &fx_stb_r2, &fx_stb_r3, &fx_stb_r4, &fx_stb_r5, &fx_stb_r6, &fx_stb_r7, - &fx_stb_r8, &fx_stb_r9, &fx_stb_r10, &fx_stb_r11, &fx_loop, &fx_alt1, &fx_alt2, &fx_alt3, - /* 40 - 4f */ - &fx_ldb_r0, &fx_ldb_r1, &fx_ldb_r2, &fx_ldb_r3, &fx_ldb_r4, &fx_ldb_r5, &fx_ldb_r6, &fx_ldb_r7, - &fx_ldb_r8, &fx_ldb_r9, &fx_ldb_r10, &fx_ldb_r11, &fx_rpix_2bit,&fx_swap, &fx_cmode, &fx_not, - /* 50 - 5f */ - &fx_adc_i0, &fx_adc_i1, &fx_adc_i2, &fx_adc_i3, &fx_adc_i4, &fx_adc_i5, &fx_adc_i6, &fx_adc_i7, - &fx_adc_i8, &fx_adc_i9, &fx_adc_i10, &fx_adc_i11, &fx_adc_i12, &fx_adc_i13, &fx_adc_i14, &fx_adc_i15, - /* 60 - 6f */ - &fx_cmp_r0, &fx_cmp_r1, &fx_cmp_r2, &fx_cmp_r3, &fx_cmp_r4, &fx_cmp_r5, &fx_cmp_r6, &fx_cmp_r7, - &fx_cmp_r8, &fx_cmp_r9, &fx_cmp_r10, &fx_cmp_r11, &fx_cmp_r12, &fx_cmp_r13, &fx_cmp_r14, &fx_cmp_r15, - /* 70 - 7f */ - &fx_merge, &fx_bic_i1, &fx_bic_i2, &fx_bic_i3, &fx_bic_i4, &fx_bic_i5, &fx_bic_i6, &fx_bic_i7, - &fx_bic_i8, &fx_bic_i9, &fx_bic_i10, &fx_bic_i11, &fx_bic_i12, &fx_bic_i13, &fx_bic_i14, &fx_bic_i15, - /* 80 - 8f */ - &fx_umult_i0,&fx_umult_i1,&fx_umult_i2, &fx_umult_i3, &fx_umult_i4, &fx_umult_i5, &fx_umult_i6, &fx_umult_i7, - &fx_umult_i8,&fx_umult_i9,&fx_umult_i10,&fx_umult_i11,&fx_umult_i12,&fx_umult_i13,&fx_umult_i14,&fx_umult_i15, - /* 90 - 9f */ - &fx_sbk, &fx_link_i1, &fx_link_i2, &fx_link_i3, &fx_link_i4, &fx_sex, &fx_div2, &fx_ror, - &fx_ljmp_r8, &fx_ljmp_r9, &fx_ljmp_r10, &fx_ljmp_r11, &fx_ljmp_r12, &fx_ljmp_r13, &fx_lob, &fx_lmult, - /* a0 - af */ - &fx_lms_r0, &fx_lms_r1, &fx_lms_r2, &fx_lms_r3, &fx_lms_r4, &fx_lms_r5, &fx_lms_r6, &fx_lms_r7, - &fx_lms_r8, &fx_lms_r9, &fx_lms_r10, &fx_lms_r11, &fx_lms_r12, &fx_lms_r13, &fx_lms_r14, &fx_lms_r15, - /* b0 - bf */ - &fx_from_r0, &fx_from_r1, &fx_from_r2, &fx_from_r3, &fx_from_r4, &fx_from_r5, &fx_from_r6, &fx_from_r7, - &fx_from_r8, &fx_from_r9, &fx_from_r10, &fx_from_r11, &fx_from_r12, &fx_from_r13, &fx_from_r14, &fx_from_r15, - /* c0 - cf */ - &fx_hib, &fx_xor_i1, &fx_xor_i2, &fx_xor_i3, &fx_xor_i4, &fx_xor_i5, &fx_xor_i6, &fx_xor_i7, - &fx_xor_i8, &fx_xor_i9, &fx_xor_i10, &fx_xor_i11, &fx_xor_i12, &fx_xor_i13, &fx_xor_i14, &fx_xor_i15, - /* d0 - df */ - &fx_inc_r0, &fx_inc_r1, &fx_inc_r2, &fx_inc_r3, &fx_inc_r4, &fx_inc_r5, &fx_inc_r6, &fx_inc_r7, - &fx_inc_r8, &fx_inc_r9, &fx_inc_r10, &fx_inc_r11, &fx_inc_r12, &fx_inc_r13, &fx_inc_r14, &fx_romb, - /* e0 - ef */ - &fx_dec_r0, &fx_dec_r1, &fx_dec_r2, &fx_dec_r3, &fx_dec_r4, &fx_dec_r5, &fx_dec_r6, &fx_dec_r7, - &fx_dec_r8, &fx_dec_r9, &fx_dec_r10, &fx_dec_r11, &fx_dec_r12, &fx_dec_r13, &fx_dec_r14, &fx_getbs, - /* f0 - ff */ - &fx_lm_r0, &fx_lm_r1, &fx_lm_r2, &fx_lm_r3, &fx_lm_r4, &fx_lm_r5, &fx_lm_r6, &fx_lm_r7, - &fx_lm_r8, &fx_lm_r9, &fx_lm_r10, &fx_lm_r11, &fx_lm_r12, &fx_lm_r13, &fx_lm_r14, &fx_lm_r15, -}; - diff --git a/src/fxinst.h b/src/fxinst.h index bc0143c..ace3b12 100644 --- a/src/fxinst.h +++ b/src/fxinst.h @@ -216,7 +216,7 @@ /* Address checking (definately slow) */ /* #define FX_ADDRESS_CHECK */ -struct FxRegs_s +typedef struct { /* FxChip registers */ uint32 avReg[16]; /* 16 Generic registers */ @@ -281,7 +281,7 @@ struct FxRegs_s uint32 vCounter; uint32 vInstCount; uint32 vSCBRDirty; /* if SCBR is written, our cached screen pointers need updating */ -}; +}FxRegs_s; #define FxRegs_s_null { \ {0}, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ diff --git a/src/getset.h b/src/getset.h index 00387e1..0351cd3 100644 --- a/src/getset.h +++ b/src/getset.h @@ -52,7 +52,7 @@ extern int oppause; //extern uint16 mem_check; -INLINE uint8 S9xGetByte (uint32 Address) +static INLINE uint8 S9xGetByte (uint32 Address) { #ifdef __show_io__ char str[64]; @@ -69,7 +69,7 @@ INLINE uint8 S9xGetByte (uint32 Address) #else uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK]; #endif - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + if (GetAddress >= (uint8 *) MAP_LAST) { #ifdef VAR_CYCLES CPU.Cycles += Memory.MemorySpeed [block]; @@ -83,52 +83,52 @@ INLINE uint8 S9xGetByte (uint32 Address) switch ((intptr_t) GetAddress) { - case CMemory::MAP_PPU: + case MAP_PPU: #ifdef VAR_CYCLES if (!CPU.InDMA) CPU.Cycles += ONE_CYCLE; #endif return (S9xGetPPU (Address & 0xffff)); - case CMemory::MAP_CPU: + case MAP_CPU: #ifdef VAR_CYCLES CPU.Cycles += ONE_CYCLE; #endif return (S9xGetCPU (Address & 0xffff)); - case CMemory::MAP_DSP: + case MAP_DSP: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif return (S9xGetDSP (Address & 0xffff)); - case CMemory::MAP_SA1RAM: - case CMemory::MAP_LOROM_SRAM: + case MAP_SA1RAM: + case MAP_LOROM_SRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif return (*(Memory.SRAM + ((Address & CPU.Memory_SRAMMask)))); - case CMemory::MAP_HIROM_SRAM: + case MAP_HIROM_SRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif return (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & CPU.Memory_SRAMMask))); - case CMemory::MAP_DEBUG: + case MAP_DEBUG: #ifdef DEBUGGER printf ("R(B) %06x\n", Address); #endif - case CMemory::MAP_BWRAM: + case MAP_BWRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); //#ifndef __GP32__ - case CMemory::MAP_C4: + case MAP_C4: return (S9xGetC4 (Address & 0xffff)); //#endif default: - case CMemory::MAP_NONE: + case MAP_NONE: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif @@ -139,7 +139,7 @@ INLINE uint8 S9xGetByte (uint32 Address) } } -INLINE uint16 S9xGetWord (uint32 Address) +static INLINE uint16 S9xGetWord (uint32 Address) { #ifdef __show_io__ char str[64]; @@ -160,7 +160,7 @@ INLINE uint16 S9xGetWord (uint32 Address) #else uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK]; #endif - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + if (GetAddress >= (uint8 *) MAP_LAST) { #ifdef VAR_CYCLES CPU.Cycles += Memory.MemorySpeed [block] << 1; @@ -179,34 +179,34 @@ INLINE uint16 S9xGetWord (uint32 Address) switch ((intptr_t) GetAddress) { - case CMemory::MAP_PPU: + case MAP_PPU: #ifdef VAR_CYCLES if (!CPU.InDMA) CPU.Cycles += TWO_CYCLES; #endif return (S9xGetPPU (Address & 0xffff) | (S9xGetPPU ((Address + 1) & 0xffff) << 8)); - case CMemory::MAP_CPU: + case MAP_CPU: #ifdef VAR_CYCLES CPU.Cycles += TWO_CYCLES; #endif return (S9xGetCPU (Address & 0xffff) | (S9xGetCPU ((Address + 1) & 0xffff) << 8)); - case CMemory::MAP_DSP: + case MAP_DSP: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE * 2; #endif return (S9xGetDSP (Address & 0xffff) | (S9xGetDSP ((Address + 1) & 0xffff) << 8)); - case CMemory::MAP_SA1RAM: - case CMemory::MAP_LOROM_SRAM: + case MAP_SA1RAM: + case MAP_LOROM_SRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE * 2; #endif return (*(Memory.SRAM + (Address & CPU.Memory_SRAMMask)) | (*(Memory.SRAM + ((Address + 1) & CPU.Memory_SRAMMask)) << 8)); - case CMemory::MAP_HIROM_SRAM: + case MAP_HIROM_SRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE * 2; #endif @@ -217,25 +217,25 @@ INLINE uint16 S9xGetWord (uint32 Address) ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & CPU.Memory_SRAMMask)) << 8)); - case CMemory::MAP_BWRAM: + case MAP_BWRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE * 2; #endif return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) | (*(Memory.BWRAM + (((Address + 1) & 0x7fff) - 0x6000)) << 8)); - case CMemory::MAP_DEBUG: + case MAP_DEBUG: #ifdef DEBUGGER printf ("R(W) %06x\n", Address); #endif //#ifndef __GP32__ - case CMemory::MAP_C4: + case MAP_C4: return (S9xGetC4 (Address & 0xffff) | (S9xGetC4 ((Address + 1) & 0xffff) << 8)); //#endif default: - case CMemory::MAP_NONE: + case MAP_NONE: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE * 2; #endif @@ -246,7 +246,7 @@ INLINE uint16 S9xGetWord (uint32 Address) } } -INLINE void S9xSetByte (uint8 Byte, uint32 Address) +static INLINE void S9xSetByte (uint8 Byte, uint32 Address) { #ifdef __show_io__ char str[64]; @@ -268,7 +268,7 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) uint8 *SetAddress = Memory.WriteMap [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK]; #endif - if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + if (SetAddress >= (uint8 *) MAP_LAST) { #ifdef VAR_CYCLES CPU.Cycles += Memory.MemorySpeed [block]; @@ -292,7 +292,7 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) switch ((intptr_t) SetAddress) { - case CMemory::MAP_PPU: + case MAP_PPU: #ifdef VAR_CYCLES if (!CPU.InDMA) CPU.Cycles += ONE_CYCLE; @@ -300,21 +300,21 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) S9xSetPPU (Byte, Address & 0xffff); return; - case CMemory::MAP_CPU: + case MAP_CPU: #ifdef VAR_CYCLES CPU.Cycles += ONE_CYCLE; #endif S9xSetCPU (Byte, Address & 0xffff); return; - case CMemory::MAP_DSP: + case MAP_DSP: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif S9xSetDSP (Byte, Address & 0xffff); return; - case CMemory::MAP_LOROM_SRAM: + case MAP_LOROM_SRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif @@ -325,7 +325,7 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) } return; - case CMemory::MAP_HIROM_SRAM: + case MAP_HIROM_SRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif @@ -337,7 +337,7 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) } return; - case CMemory::MAP_BWRAM: + case MAP_BWRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif @@ -345,12 +345,12 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) CPU.SRAMModified = TRUE; return; - case CMemory::MAP_DEBUG: + case MAP_DEBUG: #ifdef DEBUGGER printf ("W(B) %06x\n", Address); #endif - case CMemory::MAP_SA1RAM: + case MAP_SA1RAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif @@ -360,12 +360,12 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) #endif break; //#ifndef __GP32__ - case CMemory::MAP_C4: + case MAP_C4: S9xSetC4 (Byte, Address & 0xffff); return; //#endif default: - case CMemory::MAP_NONE: + case MAP_NONE: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif @@ -376,7 +376,7 @@ INLINE void S9xSetByte (uint8 Byte, uint32 Address) } } -INLINE void S9xSetWord (uint16 Word, uint32 Address) +static INLINE void S9xSetWord (uint16 Word, uint32 Address) { #ifdef __show_io__ char str[64]; @@ -397,7 +397,7 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address) uint8 *SetAddress = Memory.WriteMap [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK]; #endif - if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + if (SetAddress >= (uint8 *) MAP_LAST) { #ifdef VAR_CYCLES CPU.Cycles += Memory.MemorySpeed [block] << 1; @@ -430,7 +430,7 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address) switch ((intptr_t) SetAddress) { - case CMemory::MAP_PPU: + case MAP_PPU: #ifdef VAR_CYCLES if (!CPU.InDMA) CPU.Cycles += TWO_CYCLES; @@ -439,7 +439,7 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address) S9xSetPPU (Word >> 8, (Address & 0xffff) + 1); return; - case CMemory::MAP_CPU: + case MAP_CPU: #ifdef VAR_CYCLES CPU.Cycles += TWO_CYCLES; #endif @@ -447,7 +447,7 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address) S9xSetCPU (Word >> 8, (Address & 0xffff) + 1); return; - case CMemory::MAP_DSP: + case MAP_DSP: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE * 2; #endif @@ -455,7 +455,7 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address) S9xSetDSP (Word >> 8, (Address & 0xffff) + 1); return; - case CMemory::MAP_LOROM_SRAM: + case MAP_LOROM_SRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE * 2; #endif @@ -467,7 +467,7 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address) } return; - case CMemory::MAP_HIROM_SRAM: + case MAP_HIROM_SRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE * 2; #endif @@ -483,7 +483,7 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address) } return; - case CMemory::MAP_BWRAM: + case MAP_BWRAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE * 2; #endif @@ -492,12 +492,12 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address) CPU.SRAMModified = TRUE; return; - case CMemory::MAP_DEBUG: + case MAP_DEBUG: #ifdef DEBUGGER printf ("W(W) %06x\n", Address); #endif - case CMemory::MAP_SA1RAM: + case MAP_SA1RAM: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE; #endif @@ -508,13 +508,13 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address) #endif break; //#ifndef __GP32__ - case CMemory::MAP_C4: + case MAP_C4: S9xSetC4 (Word & 0xff, Address & 0xffff); S9xSetC4 ((uint8) (Word >> 8), (Address + 1) & 0xffff); return; //#endif default: - case CMemory::MAP_NONE: + case MAP_NONE: #ifdef VAR_CYCLES CPU.Cycles += SLOW_ONE_CYCLE * 2; #endif @@ -525,38 +525,38 @@ INLINE void S9xSetWord (uint16 Word, uint32 Address) } } -INLINE uint8 *GetBasePointer (uint32 Address) +static INLINE uint8 *GetBasePointer (uint32 Address) { uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK]; - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + if (GetAddress >= (uint8 *) MAP_LAST) return (GetAddress); switch ((intptr_t) GetAddress) { - case CMemory::MAP_PPU: + case MAP_PPU: return (Memory.FillRAM - 0x2000); - case CMemory::MAP_CPU: + case MAP_CPU: return (Memory.FillRAM - 0x4000); - case CMemory::MAP_DSP: + case MAP_DSP: return (Memory.FillRAM - 0x6000); - case CMemory::MAP_SA1RAM: - case CMemory::MAP_LOROM_SRAM: + case MAP_SA1RAM: + case MAP_LOROM_SRAM: return (Memory.SRAM); - case CMemory::MAP_BWRAM: + case MAP_BWRAM: return (Memory.BWRAM - 0x6000); - case CMemory::MAP_HIROM_SRAM: + case MAP_HIROM_SRAM: return (Memory.SRAM - 0x6000); //#ifndef __GP32__ - case CMemory::MAP_C4: + case MAP_C4: return (Memory.C4RAM - 0x6000); //#endif - case CMemory::MAP_DEBUG: + case MAP_DEBUG: #ifdef DEBUGGER printf ("GBP %06x\n", Address); #endif default: - case CMemory::MAP_NONE: + case MAP_NONE: #ifdef DEBUGGER printf ("GBP %06x\n", Address); #endif @@ -564,37 +564,37 @@ INLINE uint8 *GetBasePointer (uint32 Address) } } -INLINE uint8 *S9xGetMemPointer (uint32 Address) +static INLINE uint8 *S9xGetMemPointer (uint32 Address) { uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK]; - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + if (GetAddress >= (uint8 *) MAP_LAST) return (GetAddress + (Address & 0xffff)); switch ((intptr_t) GetAddress) { - case CMemory::MAP_PPU: + case MAP_PPU: return (Memory.FillRAM - 0x2000 + (Address & 0xffff)); - case CMemory::MAP_CPU: + case MAP_CPU: return (Memory.FillRAM - 0x4000 + (Address & 0xffff)); - case CMemory::MAP_DSP: + case MAP_DSP: return (Memory.FillRAM - 0x6000 + (Address & 0xffff)); - case CMemory::MAP_SA1RAM: - case CMemory::MAP_LOROM_SRAM: + case MAP_SA1RAM: + case MAP_LOROM_SRAM: return (Memory.SRAM + (Address & 0xffff)); - case CMemory::MAP_BWRAM: + case MAP_BWRAM: return (Memory.BWRAM - 0x6000 + (Address & 0xffff)); - case CMemory::MAP_HIROM_SRAM: + case MAP_HIROM_SRAM: return (Memory.SRAM - 0x6000 + (Address & 0xffff)); //#ifndef __GP32__ - case CMemory::MAP_C4: + case MAP_C4: return (Memory.C4RAM - 0x6000 + (Address & 0xffff)); //#endif - case CMemory::MAP_DEBUG: + case MAP_DEBUG: #ifdef DEBUGGER printf ("GMP %06x\n", Address); #endif default: - case CMemory::MAP_NONE: + case MAP_NONE: #ifdef DEBUGGER printf ("GMP %06x\n", Address); #endif @@ -602,7 +602,7 @@ INLINE uint8 *S9xGetMemPointer (uint32 Address) } } -INLINE void S9xSetPCBase (uint32 Address) +static INLINE void S9xSetPCBase (uint32 Address) { #ifdef VAR_CYCLES int block; @@ -610,7 +610,7 @@ INLINE void S9xSetPCBase (uint32 Address) #else uint8 *GetAddress = Memory.Map [(Address >> MEMMAP_SHIFT) & MEMMAP_MASK]; #endif - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + if (GetAddress >= (uint8 *) MAP_LAST) { #ifdef VAR_CYCLES CPU.MemSpeed = Memory.MemorySpeed [block]; @@ -623,7 +623,7 @@ INLINE void S9xSetPCBase (uint32 Address) switch ((intptr_t) GetAddress) { - case CMemory::MAP_PPU: + case MAP_PPU: #ifdef VAR_CYCLES CPU.MemSpeed = ONE_CYCLE; CPU.MemSpeedx2 = TWO_CYCLES; @@ -632,7 +632,7 @@ INLINE void S9xSetPCBase (uint32 Address) CPU.PC = CPU.PCBase + (Address & 0xffff); return; - case CMemory::MAP_CPU: + case MAP_CPU: #ifdef VAR_CYCLES CPU.MemSpeed = ONE_CYCLE; CPU.MemSpeedx2 = TWO_CYCLES; @@ -641,7 +641,7 @@ INLINE void S9xSetPCBase (uint32 Address) CPU.PC = CPU.PCBase + (Address & 0xffff); return; - case CMemory::MAP_DSP: + case MAP_DSP: #ifdef VAR_CYCLES CPU.MemSpeed = SLOW_ONE_CYCLE; CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; @@ -650,8 +650,8 @@ INLINE void S9xSetPCBase (uint32 Address) CPU.PC = CPU.PCBase + (Address & 0xffff); return; - case CMemory::MAP_SA1RAM: - case CMemory::MAP_LOROM_SRAM: + case MAP_SA1RAM: + case MAP_LOROM_SRAM: #ifdef VAR_CYCLES CPU.MemSpeed = SLOW_ONE_CYCLE; CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; @@ -660,7 +660,7 @@ INLINE void S9xSetPCBase (uint32 Address) CPU.PC = CPU.PCBase + (Address & 0xffff); return; - case CMemory::MAP_BWRAM: + case MAP_BWRAM: #ifdef VAR_CYCLES CPU.MemSpeed = SLOW_ONE_CYCLE; CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; @@ -668,7 +668,7 @@ INLINE void S9xSetPCBase (uint32 Address) CPU.PCBase = Memory.BWRAM - 0x6000; CPU.PC = CPU.PCBase + (Address & 0xffff); return; - case CMemory::MAP_HIROM_SRAM: + case MAP_HIROM_SRAM: #ifdef VAR_CYCLES CPU.MemSpeed = SLOW_ONE_CYCLE; CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; @@ -677,7 +677,7 @@ INLINE void S9xSetPCBase (uint32 Address) CPU.PC = CPU.PCBase + (Address & 0xffff); return; //#ifndef __GP32__ - case CMemory::MAP_C4: + case MAP_C4: #ifdef VAR_CYCLES CPU.MemSpeed = SLOW_ONE_CYCLE; CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; @@ -686,13 +686,13 @@ INLINE void S9xSetPCBase (uint32 Address) CPU.PC = CPU.PCBase + (Address & 0xffff); return; //#endif - case CMemory::MAP_DEBUG: + case MAP_DEBUG: #ifdef DEBUGGER printf ("SBP %06x\n", Address); #endif default: - case CMemory::MAP_NONE: + case MAP_NONE: #ifdef VAR_CYCLES CPU.MemSpeed = SLOW_ONE_CYCLE; CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; diff --git a/src/gfx.c b/src/gfx.c new file mode 100644 index 0000000..5ad08d1 --- /dev/null +++ b/src/gfx.c @@ -0,0 +1,3772 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include "snes9x.h" + +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" +#include "display.h" +#include "gfx.h" +#include "apu.h" +#include "cheats.h" +#include +#include "asmmemfuncs.h" +uint32 TileBlank; + +const int tx_table[16] = { +// t1 = 16, t2 = 0 + // FLIP = 0x00 + 16 + 0, // 0x00 + 16 + 1, // 0x01 + + // FLIP = 0x01 + 16 + 1 - 0, // 0x02 + 16 + 1 - 1, // 0x03 + + // FLIP = 0x02 + 0 + 0, // 0x04 + 0 + 1, // 0x05 + + // FLIP = 0x03 + 0 + 1 - 0, // 0x06 + 0 + 1 - 1, // 0x07 + +// t1 = 0, t2 = 16 + // FLIP = 0x00 + 0 + 0, // 0x08 + 0 + 1, // 0x09 + + // FLIP = 0x01 + 0 + 1 - 0, // 0x0A + 0 + 1 - 1, // 0x0B + + // FLIP = 0x02 + 16 + 0, // 0x0C + 16 + 1, // 0x0D + + // FLIP = 0x03 + 16 + 1 - 0, // 0x0E + 16 + 1 - 1 // 0x0F +}; + +#define M7 19 +#define M8 19 + +void ComputeClipWindows (); +static void S9xDisplayFrameRate (); +static void S9xDisplayString (const char *string); + +extern uint8 BitShifts[8][4]; +extern uint8 TileShifts[8][4]; +extern uint8 PaletteShifts[8][4]; +extern uint8 PaletteMasks[8][4]; +extern uint8 Depths[8][4]; +extern uint8 BGSizes [2]; + +extern NormalTileRenderer DrawTilePtr; +extern ClippedTileRenderer DrawClippedTilePtr; +extern NormalTileRenderer DrawHiResTilePtr; +extern ClippedTileRenderer DrawHiResClippedTilePtr; +extern LargePixelRenderer DrawLargePixelPtr; + +extern SBG BG; + +extern SLineData LineData[240]; +extern SLineMatrixData LineMatrixData [240]; + +extern uint8 Mode7Depths [2]; + +#define CLIP_10_BIT_SIGNED(a) \ + ((a)%1023) +#define ON_MAIN(N) (GFX.r212c & (1 << (N))) + +#define SUB_OR_ADD(N) \ +(GFX.r2131 & (1 << (N))) + +#define ON_SUB(N) \ +((GFX.r2130 & 0x30) != 0x30 && \ + (GFX.r2130 & 2) && \ + (GFX.r212d & (1 << N))) + +#define ANYTHING_ON_SUB \ +((GFX.r2130 & 0x30) != 0x30 && \ + (GFX.r2130 & 2) && \ + (GFX.r212d & 0x1f)) + +#define ADD_OR_SUB_ON_ANYTHING \ +(GFX.r2131 & 0x3f) + +#define BLACK BUILD_PIXEL(0,0,0) + +void DrawTile (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawTilex2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTilex2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawTilex2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTilex2x2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawLargePixel (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawTile16_OBJ (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile16x2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawLargePixel16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Add (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Sub (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Add (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Sub (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawHiResTile16 (uint32 Tile, uint32 Offset, + uint32 StartLine, uint32 LineCount); + +bool8_32 S9xGraphicsInit () +{ + register uint32 PixelOdd = 1; + register uint32 PixelEven = 2; + +#ifdef GFX_MULTI_FORMAT + if (GFX.BuildPixel == NULL) + S9xSetRenderPixelFormat (RGB565); +#endif + + for (uint8 bitshift = 0; bitshift < 4; bitshift++) + { + for (register int i = 0; i < 16; i++) + { + register uint32 h = 0; + register uint32 l = 0; + +#if defined(LSB_FIRST) + if (i & 8) + h |= PixelOdd; + if (i & 4) + h |= PixelOdd << 8; + if (i & 2) + h |= PixelOdd << 16; + if (i & 1) + h |= PixelOdd << 24; + if (i & 8) + l |= PixelOdd; + if (i & 4) + l |= PixelOdd << 8; + if (i & 2) + l |= PixelOdd << 16; + if (i & 1) + l |= PixelOdd << 24; +#else + if (i & 8) + h |= (PixelOdd << 24); + if (i & 4) + h |= (PixelOdd << 16); + if (i & 2) + h |= (PixelOdd << 8); + if (i & 1) + h |= PixelOdd; + if (i & 8) + l |= (PixelOdd << 24); + if (i & 4) + l |= (PixelOdd << 16); + if (i & 2) + l |= (PixelOdd << 8); + if (i & 1) + l |= PixelOdd; +#endif + + odd_high[bitshift][i] = h; + odd_low[bitshift][i] = l; + h = l = 0; + +#if defined(LSB_FIRST) + if (i & 8) + h |= PixelEven; + if (i & 4) + h |= PixelEven << 8; + if (i & 2) + h |= PixelEven << 16; + if (i & 1) + h |= PixelEven << 24; + if (i & 8) + l |= PixelEven; + if (i & 4) + l |= PixelEven << 8; + if (i & 2) + l |= PixelEven << 16; + if (i & 1) + l |= PixelEven << 24; +#else + if (i & 8) + h |= (PixelEven << 24); + if (i & 4) + h |= (PixelEven << 16); + if (i & 2) + h |= (PixelEven << 8); + if (i & 1) + h |= PixelEven; + if (i & 8) + l |= (PixelEven << 24); + if (i & 4) + l |= (PixelEven << 16); + if (i & 2) + l |= (PixelEven << 8); + if (i & 1) + l |= PixelEven; +#endif + + even_high[bitshift][i] = h; + even_low[bitshift][i] = l; + } + PixelEven <<= 2; + PixelOdd <<= 2; + } + + GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; + GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; + //GFX.InfoStringTimeout = 0; + //GFX.InfoString = NULL; + + PPU.BG_Forced = 0; + IPPU.OBJChanged = TRUE; + + IPPU.DirectColourMapsNeedRebuild = TRUE; + DrawTilePtr = DrawTile16; + DrawClippedTilePtr = DrawClippedTile16; + DrawLargePixelPtr = DrawLargePixel16; + DrawHiResTilePtr= DrawHiResTile16; + DrawHiResClippedTilePtr = DrawHiResClippedTile16; + S9xFixColourBrightness (); + + if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000))) + return (FALSE); + + if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) || + !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000))) + { + if (GFX.ZERO_OR_X2) + { + free ((char *) GFX.ZERO_OR_X2); + GFX.ZERO_OR_X2 = NULL; + } + if (GFX.X2) + { + free ((char *) GFX.X2); + GFX.X2 = NULL; + } + return (FALSE); + } + uint32 r, g, b; + + // Build a lookup table that multiplies a packed RGB value by 2 with + // saturation. + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r << 1; + if (r2 > MAX_RED) + r2 = MAX_RED; + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g << 1; + if (g2 > MAX_GREEN) + g2 = MAX_GREEN; + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b << 1; + if (b2 > MAX_BLUE) + b2 = MAX_BLUE; + GFX.X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); + GFX.X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); + } + } + } + ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16)); + ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16)); + // Build a lookup table that if the top bit of the color value is zero + // then the value is zero, otherwise multiply the value by 2. Used by + // the color subtraction code. + +#if defined(OLD_COLOUR_BLENDING) + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if ((r2 & 0x10) == 0) + r2 = 0; + else + r2 = (r2 << 1) & MAX_RED; + + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if ((g2 & GREEN_HI_BIT) == 0) + g2 = 0; + else + g2 = (g2 << 1) & MAX_GREEN; + + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if ((b2 & 0x10) == 0) + b2 = 0; + else + b2 = (b2 << 1) & MAX_BLUE; + + GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); + GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); + } + } + } +#else + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if ((r2 & 0x10) == 0) + r2 = 0; + else + r2 = (r2 << 1) & MAX_RED; + + if (r2 == 0) + r2 = 1; + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if ((g2 & GREEN_HI_BIT) == 0) + g2 = 0; + else + g2 = (g2 << 1) & MAX_GREEN; + + if (g2 == 0) + g2 = 1; + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if ((b2 & 0x10) == 0) + b2 = 0; + else + b2 = (b2 << 1) & MAX_BLUE; + + if (b2 == 0) + b2 = 1; + GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); + GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); + } + } + } +#endif + + // Build a lookup table that if the top bit of the color value is zero + // then the value is zero, otherwise its just the value. + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if ((r2 & 0x10) == 0) + r2 = 0; + else + r2 &= ~0x10; + + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if ((g2 & GREEN_HI_BIT) == 0) + g2 = 0; + else + g2 &= ~GREEN_HI_BIT; + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if ((b2 & 0x10) == 0) + b2 = 0; + else + b2 &= ~0x10; + + GFX.ZERO [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); + GFX.ZERO [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); + } + } + } + + return (TRUE); +} + +void S9xGraphicsDeinit (void) +{ + // Free any memory allocated in S9xGraphicsInit + if (GFX.X2) + { + free ((char *) GFX.X2); + GFX.X2 = NULL; + } + if (GFX.ZERO_OR_X2) + { + free ((char *) GFX.ZERO_OR_X2); + GFX.ZERO_OR_X2 = NULL; + } + if (GFX.ZERO) + { + free ((char *) GFX.ZERO); + GFX.ZERO = NULL; + } +} + +void S9xBuildDirectColourMaps () +{ + for (uint32 p = 0; p < 8; p++) + { + for (uint32 c = 0; c < 256; c++) + { +// XXX: Brightness + DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1), + ((c & 0x38) >> 1) | (p & 2), + ((c & 0xc0) >> 3) | (p & 4)); + } + } + IPPU.DirectColourMapsNeedRebuild = FALSE; +} + +void S9xStartScreenRefresh () +{ + if (IPPU.RenderThisFrame) + { + if (!S9xInitUpdate ()) + { + IPPU.RenderThisFrame = FALSE; + return; + } + IPPU.RenderedFramesCount++; + IPPU.PreviousLine = IPPU.CurrentLine = 0; + IPPU.MaxBrightness = PPU.Brightness; + IPPU.LatchedBlanking = PPU.ForcedBlanking; + IPPU.LatchedInterlace = (Memory.FillRAM[0x2133] & 1); + IPPU.RenderedScreenWidth = 256; + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + IPPU.DoubleWidthPixels = FALSE; + + PPU.RecomputeClipWindows = TRUE; + GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; + GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; + } + if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) + { + IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; + IPPU.RenderedFramesCount = 0; + IPPU.FrameCount = 0; + } +} + +void RenderLine (uint8 C) +{ + if (IPPU.RenderThisFrame) + { + + LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1; + LineData[C].BG[0].HOffset = PPU.BG[0].HOffset; + LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1; + LineData[C].BG[1].HOffset = PPU.BG[1].HOffset; + + if (PPU.BGMode == 7) + { + SLineMatrixData *p = &LineMatrixData [C]; + p->MatrixA = PPU.MatrixA; + p->MatrixB = PPU.MatrixB; + p->MatrixC = PPU.MatrixC; + p->MatrixD = PPU.MatrixD; + p->CentreX = PPU.CentreX; + p->CentreY = PPU.CentreY; + } + else + { + if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 && + PPU.BG[2].HOffset == 0xe000) + { + LineData[C].BG[2].VOffset = 0xe1; + LineData[C].BG[2].HOffset = 0; + } + else + { + LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1; + LineData[C].BG[2].HOffset = PPU.BG[2].HOffset; + LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1; + LineData[C].BG[3].HOffset = PPU.BG[3].HOffset; + } + + } + IPPU.CurrentLine = C + 1; + } +} + + +void S9xEndScreenRefresh() +{ + IPPU.HDMAStarted = FALSE; + +//RC + if (IPPU.RenderThisFrame) + { + FLUSH_REDRAW (); + if (IPPU.ColorsChanged) + { + IPPU.ColorsChanged = FALSE; + } + + + S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, + 1); + } +#ifndef RC_OPTIMIZED + S9xApplyCheats (); +#endif + + +#ifdef DEBUGGER + if (CPU.Flags & FRAME_ADVANCE_FLAG) + { + if (ICPU.FrameAdvanceCount) + { + ICPU.FrameAdvanceCount--; + IPPU.RenderThisFrame = TRUE; + IPPU.FrameSkip = 0; + } + else + { + CPU.Flags &= ~FRAME_ADVANCE_FLAG; + CPU.Flags |= DEBUG_MODE_FLAG; + } + } +#endif + +/* + if (CPU.SRAMModified) + { + if (!CPU.AutoSaveTimer) + { + if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond)) + CPU.SRAMModified = FALSE; + } + else + { + if (!--CPU.AutoSaveTimer) + { + S9xAutoSaveSRAM (); + CPU.SRAMModified = FALSE; + } + } + } +*/ +} + +void S9xSetInfoString (const char *string) +{ + } + +static INLINE void SelectTileRenderer (bool8_32 normal) +{ + if (normal) + { + DrawTilePtr = DrawTile16; + DrawClippedTilePtr = DrawClippedTile16; + DrawLargePixelPtr = DrawLargePixel16; + } + else + { + if (GFX.r2131 & 0x80) + { + if (GFX.r2131 & 0x40) + { + if (GFX.r2130 & 2) + { + DrawTilePtr = DrawTile16Sub1_2; + DrawClippedTilePtr = DrawClippedTile16Sub1_2; + } + else + { + // Fixed colour substraction + DrawTilePtr = DrawTile16FixedSub1_2; + DrawClippedTilePtr = DrawClippedTile16FixedSub1_2; + } + DrawLargePixelPtr = DrawLargePixel16Sub1_2; + } + else + { + DrawTilePtr = DrawTile16Sub; + DrawClippedTilePtr = DrawClippedTile16Sub; + DrawLargePixelPtr = DrawLargePixel16Sub; + } + } + else + { + if (GFX.r2131 & 0x40) + { + if (GFX.r2130 & 2) + { + DrawTilePtr = DrawTile16Add1_2; + DrawClippedTilePtr = DrawClippedTile16Add1_2; + } + else + { + // Fixed colour addition + DrawTilePtr = DrawTile16FixedAdd1_2; + DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2; + } + DrawLargePixelPtr = DrawLargePixel16Add1_2; + } + else + { + DrawTilePtr = DrawTile16Add; + DrawClippedTilePtr = DrawClippedTile16Add; + DrawLargePixelPtr = DrawLargePixel16Add; + } + } + } +} + +void S9xSetupOBJ () +{ + int SmallSize; + int LargeSize; + + switch (PPU.OBJSizeSelect) + { + case 0: + SmallSize = 8; + LargeSize = 16; + break; + case 1: + SmallSize = 8; + LargeSize = 32; + break; + case 2: + SmallSize = 8; + LargeSize = 64; + break; + case 3: + SmallSize = 16; + LargeSize = 32; + break; + case 4: + SmallSize = 16; + LargeSize = 64; + break; + case 5: + default: + SmallSize = 32; + LargeSize = 64; + break; + } + + int C = 0; + + int FirstSprite = PPU.FirstSprite & 0x7f; + int S = FirstSprite; + do + { + int Size; + if (PPU.OBJ [S].Size) + Size = LargeSize; + else + Size = SmallSize; + + long VPos = PPU.OBJ [S].VPos; + + if (VPos >= PPU.ScreenHeight) + VPos -= 256; + if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size && + VPos < PPU.ScreenHeight && VPos > -Size) + { + GFX.OBJList [C++] = S; + GFX.Sizes[S] = Size; + GFX.VPositions[S] = VPos; + } + S = (S + 1) & 0x7f; + } while (S != FirstSprite); + + // Terminate the list + GFX.OBJList [C] = -1; + IPPU.OBJChanged = FALSE; +} + +void DrawOBJS (bool8_32 OnMain = FALSE, uint8 D = 0) +{ + uint32 O; + uint32 BaseTile, Tile; + + CHECK_SOUND(); + + BG.BitShift = 4; + BG.TileShift = 5; + BG.TileAddress = PPU.OBJNameBase; + BG.StartPalette = 128; + BG.PaletteShift = 4; + BG.PaletteMask = 7; + BG.Buffer = IPPU.TileCache [TILE_4BIT]; + BG.Buffered = IPPU.TileCached [TILE_4BIT]; + BG.NameSelect = PPU.OBJNameSelect; + BG.DirectColourMode = FALSE; + + GFX.Z1 = D + 2; + + if ( DrawTilePtr == DrawTile16 ){ + DrawTilePtr = DrawTile16_OBJ; + } + int I = 0; + for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++]) + { + int VPos = GFX.VPositions [S]; + int Size = GFX.Sizes[S]; + int TileInc = 1; + int Offset; + + if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY) + continue; + + if (OnMain && SUB_OR_ADD(4)) + { + SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4); + if ( DrawTilePtr == DrawTile16 ){ + DrawTilePtr = DrawTile16_OBJ; + } + } + + BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10); + + if (PPU.OBJ[S].HFlip) + { + BaseTile += ((Size >> 3) - 1) | H_FLIP; + TileInc = -1; + } + if (PPU.OBJ[S].VFlip) + BaseTile |= V_FLIP; + + int clipcount = GFX.pCurrentClip->Count [4]; + if (!clipcount) + clipcount = 1; + + GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D; + + for (int clip = 0; clip < clipcount; clip++) + { + int Left; + int Right; + if (!GFX.pCurrentClip->Count [4]) + { + Left = 0; + Right = 256; + } + else + { + Left = GFX.pCurrentClip->Left [clip][4]; + Right = GFX.pCurrentClip->Right [clip][4]; + } + + if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left || + PPU.OBJ[S].HPos >= Right) + continue; + + for (int Y = 0; Y < Size; Y += 8) + { + if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY) + { + int StartLine; + int TileLine; + int LineCount; + int Last; + + if ((StartLine = VPos + Y) < (int) GFX.StartY) + { + StartLine = GFX.StartY - StartLine; + LineCount = 8 - StartLine; + } + else + { + StartLine = 0; + LineCount = 8; + } + if ((Last = VPos + Y + 7 - GFX.EndY) > 0) + if ((LineCount -= Last) <= 0) + break; + + TileLine = StartLine << 3; + O = (VPos + Y + StartLine) * GFX_PPL; + if (!PPU.OBJ[S].VFlip) + Tile = BaseTile + (Y << 1); + else + Tile = BaseTile + ((Size - Y - 8) << 1); + + int Middle = Size >> 3; + if (PPU.OBJ[S].HPos < Left) + { + Tile += ((Left - PPU.OBJ[S].HPos) >> 3) * TileInc; + Middle -= (Left - PPU.OBJ[S].HPos) >> 3; + O += Left * GFX_PIXSIZE; + if ((Offset = (Left - PPU.OBJ[S].HPos) & 7)) + { + O -= Offset * GFX_PIXSIZE; + int W = 8 - Offset; + int Width = Right - Left; + if (W > Width) + W = Width; + (*DrawClippedTilePtr) (Tile, O, Offset, W, + TileLine, LineCount); + + if (W >= Width) + continue; + Tile += TileInc; + Middle--; + O += 8 * GFX_PIXSIZE; + } + } + else + O += PPU.OBJ[S].HPos * GFX_PIXSIZE; + + if (PPU.OBJ[S].HPos + Size >= Right) + { + Middle -= ((PPU.OBJ[S].HPos + Size + 7) - + Right) >> 3; + Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7; + } + else + Offset = 0; + + for (int X = 0; X < Middle; X++, O += 8 * GFX_PIXSIZE, + Tile += TileInc) + { + (*DrawTilePtr) (Tile, O, TileLine, LineCount); + } + if (Offset) + { + (*DrawClippedTilePtr) (Tile, O, 0, Offset, + TileLine, LineCount); + } + } + } + } + } +} + +void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ + CHECK_SOUND(); + + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint8 depths [2] = {Z1, Z2}; + + if (BGMode == 0) + BG.StartPalette = bg << 5; + else + BG.StartPalette = 0; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if (PPU.BG[bg].SCSize & 1) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if(((uint8*)SC1-Memory.VRAM)>=0x10000) + SC1-=0x08000; + + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + + if (PPU.BG[bg].SCSize & 1) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + + uint32 Lines; + uint32 OffsetMask; + uint32 OffsetShift; + + if (BG.TileSize == 16) + { + OffsetMask = 0x3ff; + OffsetShift = 4; + } + else + { + OffsetMask = 0x1ff; + OffsetShift = 3; + } + + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) + { + uint32 VOffset = LineData [Y].BG[bg].VOffset; + uint32 HOffset = LineData [Y].BG[bg].HOffset; + uint32 MosaicOffset = Y % PPU.Mosaic; + + for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || + (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + break; + + uint32 MosaicLine = VOffset + Y - MosaicOffset; + + if (Y + Lines > GFX.EndY) + Lines = GFX.EndY + 1 - Y; + uint32 VirtAlign = (MosaicLine & 7) << 3; + + uint16 *b1; + uint16 *b2; + + uint32 ScreenLine = MosaicLine >> OffsetShift; + uint32 Rem16 = MosaicLine & 15; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + uint16 *t; + uint32 Left = 0; + uint32 Right = 256; + + uint32 ClipCount = GFX.pCurrentClip->Count [bg]; + uint32 HPos = HOffset; + uint32 PixWidth = PPU.Mosaic; + + if (!ClipCount) + ClipCount = 1; + + for (uint32 clip = 0; clip < ClipCount; clip++) + { + if (GFX.pCurrentClip->Count [bg]) + { + Left = GFX.pCurrentClip->Left [clip][bg]; + Right = GFX.pCurrentClip->Right [clip][bg]; + uint32 r = Left % PPU.Mosaic; + HPos = HOffset + Left; + PixWidth = PPU.Mosaic - r; + } + uint32 s = Y * GFX_PPL + Left * GFX_PIXSIZE; + for (uint32 x = Left; x < Right; x += PixWidth, + s += PixWidth * GFX_PIXSIZE, + HPos += PixWidth, PixWidth = PPU.Mosaic) + { + uint32 Quot = (HPos & OffsetMask) >> 3; + + if (x + PixWidth >= Right) + PixWidth = Right - x; + + if (BG.TileSize == 8) + { + if (Quot > 31) + t = b2 + (Quot & 0x1f); + else + t = b1 + Quot; + } + else + { + if (Quot > 63) + t = b2 + ((Quot >> 1) & 0x1f); + else + t = b1 + (Quot >> 1); + } + + Tile = READ_2BYTES (t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + // Draw tile... + if (BG.TileSize != 8) + { + if (Tile & H_FLIP) + { + // Horizontal flip, but what about vertical flip ? + if (Tile & V_FLIP) + { + // Both horzontal & vertical flip + if (Rem16 < 8) + { + (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + else + { + // Horizontal flip only + if (Rem16 > 7) + { + (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + } + else + { + // No horizontal flip, but is there a vertical flip ? + if (Tile & V_FLIP) + { + // Vertical flip only + if (Rem16 < 8) + { + (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + else + { + // Normal unflipped + if (Rem16 > 7) + { + (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + } + } + else + (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + } +} + +void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ + CHECK_SOUND(); + + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint16 *BPS0; + uint16 *BPS1; + uint16 *BPS2; + uint16 *BPS3; + uint32 Width; + int VOffsetOffset = BGMode == 4 ? 0 : 32; + uint8 depths [2] = {Z1, Z2}; + + BG.StartPalette = 0; + + BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; + + if (PPU.BG[2].SCSize & 1) + BPS1 = BPS0 + 1024; + else + BPS1 = BPS0; + + if (PPU.BG[2].SCSize & 2) + BPS2 = BPS1 + 1024; + else + BPS2 = BPS0; + + if (PPU.BG[2].SCSize & 1) + BPS3 = BPS2 + 1024; + else + BPS3 = BPS2; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if (PPU.BG[bg].SCSize & 1) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if(((uint8*)SC1-Memory.VRAM)>=0x10000) + SC1-=0x08000; + + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + + if (PPU.BG[bg].SCSize & 1) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + + static const int Lines = 1; + int OffsetMask; + int OffsetShift; + int OffsetEnableMask = 1 << (bg + 13); + + if (BG.TileSize == 16) + { + OffsetMask = 0x3ff; + OffsetShift = 4; + } + else + { + OffsetMask = 0x1ff; + OffsetShift = 3; + } + + TileBlank = 0xFFFFFFFF; + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++) + { + uint32 VOff = LineData [Y].BG[2].VOffset - 1; + uint32 HOff = LineData [Y].BG[2].HOffset; + int VirtAlign; + int ScreenLine = VOff >> 3; + uint16 *s0; + uint16 *s1; + uint16 *s2; + + if (ScreenLine & 0x20) + s1 = BPS2, s2 = BPS3; + else + s1 = BPS0, s2 = BPS1; + + s1 += (ScreenLine & 0x1f) << 5; + s2 += (ScreenLine & 0x1f) << 5; + + if(BGMode != 4) + { + if((ScreenLine & 0x1f) == 0x1f) + { + if(ScreenLine & 0x20) + VOffsetOffset = BPS0 - BPS2 - 0x1f*32; + else + VOffsetOffset = BPS2 - BPS0 - 0x1f*32; + } + else + { + VOffsetOffset = 32; + } + } + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) + clipcount = 1; + + for (int clip = 0; clip < clipcount; clip++) + { + uint32 Left; + uint32 Right; + + if (!GFX.pCurrentClip->Count [bg]) + { + Left = 0; + Right = 256; + } + else + { + Left = GFX.pCurrentClip->Left [clip][bg]; + Right = GFX.pCurrentClip->Right [clip][bg]; + + if (Right <= Left) + continue; + } + + uint32 VOffset; + uint32 HOffset; + uint32 LineHOffset=LineData [Y].BG[bg].HOffset; + uint32 Offset; + uint32 HPos; + uint32 Quot; + uint32 Count; + uint16 *t; + uint32 Quot2; + uint32 VCellOffset; + uint32 HCellOffset; + uint16 *b1; + uint16 *b2; + uint32 TotalCount = 0; + uint32 MaxCount = 8; + + uint32 s = Left * GFX_PIXSIZE + Y * GFX_PPL; + bool8_32 left_hand_edge = (Left == 0); + Width = Right - Left; + + if (Left & 7) + MaxCount = 8 - (Left & 7); + + while (Left < Right) + { + if (left_hand_edge) + { + // The SNES offset-per-tile background mode has a + // hardware limitation that the offsets cannot be set + // for the tile at the left-hand edge of the screen. + VOffset = LineData [Y].BG[bg].VOffset; + HOffset = LineHOffset; + left_hand_edge = FALSE; + } + else + { + // All subsequent offset tile data is shifted left by one, + // hence the - 1 below. + Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3; + + if (Quot2 > 31) + s0 = s2 + (Quot2 & 0x1f); + else + s0 = s1 + Quot2; + + HCellOffset = READ_2BYTES (s0); + + if (BGMode == 4) + { + VOffset = LineData [Y].BG[bg].VOffset; + HOffset=LineHOffset; + if ((HCellOffset & OffsetEnableMask)) + { + if (HCellOffset & 0x8000) + VOffset = HCellOffset + 1; + else + HOffset = HCellOffset; + } + } + else + { + VCellOffset = READ_2BYTES (s0 + VOffsetOffset); + if ((VCellOffset & OffsetEnableMask)) + VOffset = VCellOffset + 1; + else + VOffset = LineData [Y].BG[bg].VOffset; + + if ((HCellOffset & OffsetEnableMask)) + HOffset = (HCellOffset & ~7)|(LineHOffset&7); + else + HOffset=LineHOffset; + } + } + VirtAlign = ((Y + VOffset) & 7) << 3; + ScreenLine = (VOffset + Y) >> OffsetShift; + + int tx_index; + tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + HPos = (HOffset + Left) & OffsetMask; + + Quot = HPos >> 3; + + if (BG.TileSize == 8) + { + if (Quot > 31) + t = b2 + (Quot & 0x1f); + else + t = b1 + Quot; + } + else + { + if (Quot > 63) + t = b2 + ((Quot >> 1) & 0x1f); + else + t = b1 + (Quot >> 1); + } + + if (MaxCount + TotalCount > Width) + MaxCount = Width - TotalCount; + + Offset = HPos & 7; + + Count = 8 - Offset; + if (Count > MaxCount) + Count = MaxCount; + + s -= Offset * GFX_PIXSIZE; + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + if (Tile != TileBlank) + if (BG.TileSize == 8) + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); + else + { + Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)]; + if (Tile != TileBlank){ + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); + } + } + + Left += Count; + TotalCount += Count; + s += (Offset + Count) * GFX_PIXSIZE; + MaxCount = 8; + } + } + } +} + +void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2) +{ + CHECK_SOUND(); + + uint8 depths [2] = {Z1, Z2}; + + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint32 Width; + + BG.StartPalette = 0; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if ((PPU.BG[bg].SCSize & 1)) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if((SC1-(unsigned short*)Memory.VRAM)>0x10000) + SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000]; + + if ((PPU.BG[bg].SCSize & 2)) + SC2 = SC1 + 1024; + else SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + if ((PPU.BG[bg].SCSize & 1)) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + int Lines; + int VOffsetMask; + int VOffsetShift; + + if (BG.TileSize == 16) + { + VOffsetMask = 0x3ff; + VOffsetShift = 4; + } + else + { + VOffsetMask = 0x1ff; + VOffsetShift = 3; + } + int endy = GFX.EndY; + + for (int Y = GFX.StartY; Y <= endy; Y += Lines) + { + int y = Y; + uint32 VOffset = LineData [y].BG[bg].VOffset; + uint32 HOffset = LineData [y].BG[bg].HOffset; + int VirtAlign = (Y + VOffset) & 7; + + for (Lines = 1; Lines < 8 - VirtAlign; Lines++) + if ((VOffset != LineData [y + Lines].BG[bg].VOffset) || + (HOffset != LineData [y + Lines].BG[bg].HOffset)) + break; + + HOffset <<= 1; + if (Y + Lines > endy) + Lines = endy + 1 - Y; + + int ScreenLine = (VOffset + Y) >> VOffsetShift; + int t1; + int t2; + if (((VOffset + Y) & 15) > 7) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + uint16 *b1; + uint16 *b2; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) + clipcount = 1; + for (int clip = 0; clip < clipcount; clip++) + { + int Left; + int Right; + + if (!GFX.pCurrentClip->Count [bg]) + { + Left = 0; + Right = 512; + } + else + { + Left = GFX.pCurrentClip->Left [clip][bg] * 2; + Right = GFX.pCurrentClip->Right [clip][bg] * 2; + + if (Right <= Left) + continue; + } + + uint32 s = (Left>>1) * GFX_PIXSIZE + Y * GFX_PPL; + uint32 HPos = (HOffset + Left * GFX_PIXSIZE) & 0x3ff; + + uint32 Quot = HPos >> 3; + uint32 Count = 0; + + uint16 *t; + if (Quot > 63) + t = b2 + ((Quot >> 1) & 0x1f); + else + t = b1 + (Quot >> 1); + + Width = Right - Left; + // Left hand edge clipped tile + if (HPos & 7) + { + int Offset = (HPos & 7); + Count = 8 - Offset; + if (Count > Width) + Count = Width; + s -= (Offset>>1); + Tile = READ_2BYTES (t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + if (BG.TileSize == 8) + { + if (!(Tile & H_FLIP)) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + { + // H flip + (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + + t += Quot & 1; + if (Quot == 63) + t = b2; + else if (Quot == 127) + t = b1; + Quot++; + s += 4; + } + + // Middle, unclipped tiles + Count = Width - Count; + int Middle = Count >> 3; + Count &= 7; + for (int C = Middle; C > 0; s += 4, Quot++, C--) + { + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + if (BG.TileSize == 8) + { + if (!(Tile & H_FLIP)) + { + // Normal, unflipped + (*DrawHiResTilePtr) (Tile + (Quot & 1), + s, VirtAlign, Lines); + } + else + { + // H flip + (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1), + s, VirtAlign, Lines); + } + } + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1), + s, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1), + s, VirtAlign, Lines); + } + } + + t += Quot & 1; + if (Quot == 63) + t = b2; + else + if (Quot == 127) + t = b1; + } + + // Right-hand edge clipped tiles + if (Count) + { + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + if (BG.TileSize == 8) + { + if (!(Tile & H_FLIP)) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + else + { + // H flip + (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + } + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + } + } + } + } +} + +void DrawBackground_8 (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint32 Width; + uint8 depths [2] = {Z1, Z2}; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if (PPU.BG[bg].SCSize & 1) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if(SC1>=(unsigned short*)(Memory.VRAM+0x10000)) + SC1=(uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0])%0x10000]; + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + if (PPU.BG[bg].SCSize & 1) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + + int Lines; + + TileBlank = 0xFFFFFFFF; + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){ + uint32 VOffset = LineData [Y].BG[bg].VOffset; + uint32 HOffset = LineData [Y].BG[bg].HOffset; + int VirtAlign = (Y + VOffset) & 7; + + for (Lines = 1; Lines < 8 - VirtAlign; Lines++) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || + (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + break; + + if (Y + Lines > GFX.EndY) + Lines = GFX.EndY + 1 - Y; + + VirtAlign <<= 3; + + uint32 ScreenLine = (VOffset + Y) >> 3; + uint16 *b1; + uint16 *b2; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) + clipcount = 1; + for (int clip = 0; clip < clipcount; clip++){ + uint32 Left; + uint32 Right; + + if (!GFX.pCurrentClip->Count [bg]){ + Left = 0; + Right = 256; + } else { + Left = GFX.pCurrentClip->Left [clip][bg]; + Right = GFX.pCurrentClip->Right [clip][bg]; + + if (Right <= Left) + continue; + } + + uint32 s = Left + Y * GFX_PPL; + uint32 HPos = (HOffset + Left) & 0x1ff; + uint32 Quot = HPos >> 3; + uint32 Count = 0; + uint16 *t; + + if (Quot > 31) t = b2 + (Quot & 0x1f); else t = b1 + Quot; + + Width = Right - Left; + + // Left hand edge clipped tile + if (HPos & 7){ + uint32 Offset = (HPos & 7); + Count = 8 - Offset; + if (Count > Width) Count = Width; + s -= Offset; + Tile = READ_2BYTES(t); + if (Tile != TileBlank){ + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); + } + t++; + if (Quot == 31) t = b2; else if (Quot == 63) t = b1; + Quot++; + s += 8; + } + + // Middle, unclipped tiles + Count = Width - Count; + for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){ + Tile = READ_2BYTES(t); + if (Tile != TileBlank){ + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + (*DrawTilePtr) (Tile, s, VirtAlign, Lines); + } + + t++; + if (Quot == 31) t = b2; else if (Quot == 63) t = b1; + } + + // Right-hand edge clipped tiles + if (Count){ + Tile = READ_2BYTES(t); + if (Tile != TileBlank){ + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines); + } + } + } + } + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; +} + +void DrawBackground_16 (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint32 Width; + uint8 depths [2] = {Z1, Z2}; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if (PPU.BG[bg].SCSize & 1) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if(SC1>=(unsigned short*)(Memory.VRAM+0x10000)) + SC1=(uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0])%0x10000]; + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + if (PPU.BG[bg].SCSize & 1) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + + int Lines; + + TileBlank = 0xFFFFFFFF; + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){ + uint32 VOffset = LineData [Y].BG[bg].VOffset; + uint32 HOffset = LineData [Y].BG[bg].HOffset; + int VirtAlign = (Y + VOffset) & 7; + + for (Lines = 1; Lines < 8 - VirtAlign; Lines++) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || + (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + break; + + if (Y + Lines > GFX.EndY) + Lines = GFX.EndY + 1 - Y; + + VirtAlign <<= 3; + + uint32 ScreenLine = (VOffset + Y) >> 4; + int tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3; + uint16 *b1; + uint16 *b2; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) + clipcount = 1; + for (int clip = 0; clip < clipcount; clip++){ + uint32 Left; + uint32 Right; + + if (!GFX.pCurrentClip->Count [bg]){ + Left = 0; + Right = 256; + } else { + Left = GFX.pCurrentClip->Left [clip][bg]; + Right = GFX.pCurrentClip->Right [clip][bg]; + + if (Right <= Left) + continue; + } + + uint32 s = Left + Y * GFX_PPL; + uint32 HPos = (HOffset + Left) & 0x3ff; + uint32 Quot = HPos >> 3; + uint32 Count = 0; + uint16 *t; + + if (Quot > 63) t = b2 + ((Quot >> 1) & 0x1f); else t = b1 + (Quot >> 1); + + Width = Right - Left; + + // Left hand edge clipped tile + if (HPos & 7){ + uint32 Offset = (HPos & 7); + Count = 8 - Offset; + if (Count > Width) Count = Width; + s -= Offset; + Tile = READ_2BYTES(t); + Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)]; + if (Tile != TileBlank){ + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); + } + + t += Quot & 1; + if (Quot == 63) t = b2; else if (Quot == 127) t = b1; + Quot++; + s += 8; + } + + // Middle, unclipped tiles + Count = Width - Count; + for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){ + Tile = READ_2BYTES(t); + Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)]; + if (Tile != TileBlank){ + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + (*DrawTilePtr) (Tile, s, VirtAlign, Lines); + } + + t += Quot & 1; + if (Quot == 63) t = b2; else if (Quot == 127) t = b1; + } + + // Right-hand edge clipped tiles + if (Count){ + Tile = READ_2BYTES(t); + Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)]; + if (Tile != TileBlank){ + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines); + } + } + } + } + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; +} + +inline void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ +//StartAnalyze(); + + BG.TileSize = BGSizes [PPU.BG[bg].BGSize]; + BG.BitShift = BitShifts[BGMode][bg]; + BG.TileShift = TileShifts[BGMode][bg]; + BG.TileAddress = PPU.BG[bg].NameBase << 1; + BG.NameSelect = 0; + BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]]; + BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]]; + BG.PaletteShift = PaletteShifts[BGMode][bg]; + BG.PaletteMask = PaletteMasks[BGMode][bg]; + BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 && + (GFX.r2130 & 1); + + if ( DrawTilePtr == DrawTile16_OBJ ){ + DrawTilePtr = DrawTile16; + } + + if (PPU.BGMosaic [bg] && PPU.Mosaic > 1){ + DrawBackgroundMosaic (BGMode, bg, Z1, Z2); + return; + + } + switch (BGMode) + { + case 2: + case 4: // Used by Puzzle Bobble + DrawBackgroundOffset (BGMode, bg, Z1, Z2); + return; + + case 5: + case 6: // XXX: is also offset per tile. + DrawBackgroundMode5 (BGMode, bg, Z1, Z2); + return; + } + CHECK_SOUND(); + + if (BGMode == 0) + BG.StartPalette = bg << 5; + else BG.StartPalette = 0; + + if (BG.TileSize == 8){ + DrawBackground_8 (BGMode, bg, Z1, Z2); + } else { + DrawBackground_16 (BGMode, bg, Z1, Z2); + } +} + +#define RENDER_BACKGROUND_MODE7(FUNC) \ + CHECK_SOUND(); \ +\ + uint8 *VRAM1 = Memory.VRAM + 1; \ + if (GFX.r2130 & 1) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps (); \ + GFX.ScreenColors = DirectColourMaps [0]; \ + } \ + else \ + GFX.ScreenColors = IPPU.ScreenColors; \ +\ + int aa, cc; \ + int dir; \ + int startx, endx; \ + uint32 Left = 0; \ + uint32 Right = 256; \ + uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \ +\ + if (!ClipCount) \ + ClipCount = 1; \ +\ + Screen += GFX.StartY * GFX_PITCH; \ + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \ +\ + for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, l++) \ + { \ + int yy; \ +\ + int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \ + int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \ +\ + int32 CentreX = ((int32) l->CentreX << M7) >> M7; \ + int32 CentreY = ((int32) l->CentreY << M7) >> M7; \ +\ + if (PPU.Mode7VFlip) \ + yy = 255 - (int) Line; \ + else \ + yy = Line; \ +\ + if (PPU.Mode7Repeat == 0) \ + yy += (VOffset - CentreY) % 1023; \ + else \ + yy += VOffset - CentreY; \ + int BB = l->MatrixB * yy + (CentreX << 8); \ + int DD = l->MatrixD * yy + (CentreY << 8); \ +\ + for (uint32 clip = 0; clip < ClipCount; clip++) \ + { \ + if (GFX.pCurrentClip->Count [bg]) \ + { \ + Left = GFX.pCurrentClip->Left [clip][bg]; \ + Right = GFX.pCurrentClip->Right [clip][bg]; \ + if (Right <= Left) \ + continue; \ + } \ + uint16 *p = (uint16 *) Screen + Left; \ +\ + if (PPU.Mode7HFlip) \ + { \ + startx = Right - 1; \ + endx = Left - 1; \ + dir = -1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } \ + else \ + { \ + startx = Left; \ + endx = Right; \ + dir = 1; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ + int xx; \ + if (PPU.Mode7Repeat == 0) \ + xx = startx + (HOffset - CentreX) % 1023; \ + else \ + xx = startx + HOffset - CentreX; \ + int AA = l->MatrixA * xx; \ + int CC = l->MatrixC * xx; \ +\ + if (!PPU.Mode7Repeat) \ + { \ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++) \ + { \ + register int X = ((AA + BB) >> 8) & 0x3ff; \ + register int Y = ((CC + DD) >> 8) & 0x3ff; \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + if (b) \ + { \ + *p = (FUNC); \ + } \ + } \ + } \ + else \ + { \ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++) \ + { \ + int X = ((AA + BB) >> 8); \ + int Y = ((CC + DD) >> 8); \ +\ + if (Settings.Dezaemon && PPU.Mode7Repeat == 2) \ + { \ + X &= 0x7ff; \ + Y &= 0x7ff; \ + } \ +\ + if (((X | Y) & ~0x3ff) == 0) \ + { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + if (b) \ + { \ + *p = (FUNC); \ + } \ + } \ + else \ + { \ + if (PPU.Mode7Repeat == 3) \ + { \ + X = (x + HOffset) & 7; \ + Y = (yy + CentreY) & 7; \ + uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + if (b ) \ + { \ + *p = (FUNC); \ + } \ + } \ + } \ + } \ + } \ + } \ + } + +#define RENDER_BACKGROUND_MODE7ADDSUB(DEPTH, FUNC) \ + CHECK_SOUND(); \ +\ + uint8 *VRAM1 = Memory.VRAM + 1; \ + if (GFX.r2130 & 1) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps (); \ + GFX.ScreenColors = DirectColourMaps [0]; \ + } \ + else \ + GFX.ScreenColors = IPPU.ScreenColors; \ +\ + int aa, cc; \ + int dir; \ + int startx, endx; \ + uint32 Left = 0; \ + uint32 Right = 256; \ + uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \ +\ + if (!ClipCount) \ + ClipCount = 1; \ +\ + Screen += GFX.StartY * GFX_PITCH; \ + uint8 *Depth = GFX.DB + GFX.StartY * GFX_PPL; \ + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \ +\ + for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) \ + { \ + int yy; \ +\ + int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \ + int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \ +\ + int32 CentreX = ((int32) l->CentreX << M7) >> M7; \ + int32 CentreY = ((int32) l->CentreY << M7) >> M7; \ +\ + if (PPU.Mode7VFlip) \ + yy = 255 - (int) Line; \ + else \ + yy = Line; \ +\ + if (PPU.Mode7Repeat == 0) \ + yy += (VOffset - CentreY) % 1023; \ + else \ + yy += VOffset - CentreY; \ + int BB = l->MatrixB * yy + (CentreX << 8); \ + int DD = l->MatrixD * yy + (CentreY << 8); \ +\ + for (uint32 clip = 0; clip < ClipCount; clip++) \ + { \ + if (GFX.pCurrentClip->Count [bg]) \ + { \ + Left = GFX.pCurrentClip->Left [clip][bg]; \ + Right = GFX.pCurrentClip->Right [clip][bg]; \ + if (Right <= Left) \ + continue; \ + } \ + uint16 *p = (uint16 *) Screen + Left; \ + uint8 *d = Depth + Left; \ +\ + if (PPU.Mode7HFlip) \ + { \ + startx = Right - 1; \ + endx = Left - 1; \ + dir = -1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } \ + else \ + { \ + startx = Left; \ + endx = Right; \ + dir = 1; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ + int xx; \ + if (PPU.Mode7Repeat == 0) \ + xx = startx + (HOffset - CentreX) % 1023; \ + else \ + xx = startx + HOffset - CentreX; \ + int AA = l->MatrixA * xx; \ + int CC = l->MatrixC * xx; \ +\ + if (!PPU.Mode7Repeat) \ + { \ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ + { \ + int X = ((AA + BB) >> 8) & 0x3ff; \ + int Y = ((CC + DD) >> 8) & 0x3ff; \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + if (DEPTH > *d && (b) ) \ + { \ + *p = (FUNC); \ + *d = DEPTH; \ + } \ + } \ + } \ + else \ + { \ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ + { \ + int X = ((AA + BB) >> 8); \ + int Y = ((CC + DD) >> 8); \ +\ + if (Settings.Dezaemon && PPU.Mode7Repeat == 2) \ + { \ + X &= 0x7ff; \ + Y &= 0x7ff; \ + } \ +\ + if (((X | Y) & ~0x3ff) == 0) \ + { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + if (DEPTH > *d && (b) ) \ + { \ + *p = (FUNC); \ + *d = DEPTH; \ + } \ + } \ + else \ + { \ + if (PPU.Mode7Repeat == 3) \ + { \ + X = (x + HOffset) & 7; \ + Y = (yy + CentreY) & 7; \ + uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + if (DEPTH > *d && (b) ) \ + { \ + *p = (FUNC); \ + *d = DEPTH; \ + } \ + } \ + } \ + } \ + } \ + } \ + } + +#define RENDER_BACKGROUND_MODE7PRIO(FUNC) \ + CHECK_SOUND(); \ +\ + uint8 *VRAM1 = Memory.VRAM + 1; \ + if (GFX.r2130 & 1) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps (); \ + GFX.ScreenColors = DirectColourMaps [0]; \ + } \ + else \ + GFX.ScreenColors = IPPU.ScreenColors; \ +\ + int aa, cc; \ + int dir; \ + int startx, endx; \ + uint32 Left = 0; \ + uint32 Right = 256; \ + uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \ +\ + if (!ClipCount) \ + ClipCount = 1; \ +\ + Screen += GFX.StartY * GFX_PITCH; \ + uint8 *Depth = GFX.DB + GFX.StartY * GFX_PPL; \ + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \ +\ + for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) \ + { \ + int yy; \ +\ + int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \ + int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \ +\ + int32 CentreX = ((int32) l->CentreX << M7) >> M7; \ + int32 CentreY = ((int32) l->CentreY << M7) >> M7; \ +\ + if (PPU.Mode7VFlip) \ + yy = 255 - (int) Line; \ + else \ + yy = Line; \ +\ + if (PPU.Mode7Repeat == 0) \ + yy += (VOffset - CentreY) % 1023; \ + else \ + yy += VOffset - CentreY; \ + int BB = l->MatrixB * yy + (CentreX << 8); \ + int DD = l->MatrixD * yy + (CentreY << 8); \ +\ + for (uint32 clip = 0; clip < ClipCount; clip++) \ + { \ + if (GFX.pCurrentClip->Count [bg]) \ + { \ + Left = GFX.pCurrentClip->Left [clip][bg]; \ + Right = GFX.pCurrentClip->Right [clip][bg]; \ + if (Right <= Left) \ + continue; \ + } \ + uint16 *p = (uint16 *) Screen + Left; \ + uint8 *d = Depth + Left; \ +\ + if (PPU.Mode7HFlip) \ + { \ + startx = Right - 1; \ + endx = Left - 1; \ + dir = -1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } \ + else \ + { \ + startx = Left; \ + endx = Right; \ + dir = 1; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ + int xx; \ + if (PPU.Mode7Repeat == 0) \ + xx = startx + (HOffset - CentreX) % 1023; \ + else \ + xx = startx + HOffset - CentreX; \ + int AA = l->MatrixA * xx; \ + int CC = l->MatrixC * xx; \ +\ + if (!PPU.Mode7Repeat) \ + { \ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ + { \ + int X = ((AA + BB) >> 8) & 0x3ff; \ + int Y = ((CC + DD) >> 8) & 0x3ff; \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & 0x80) >> 7]; \ + if (GFX.Z1 > *d && (b & 0x7f) ) \ + { \ + *p = (FUNC); \ + *d = GFX.Z1; \ + } \ + } \ + } \ + else \ + { \ + for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ + { \ + int X = ((AA + BB) >> 8); \ + int Y = ((CC + DD) >> 8); \ +\ + if (Settings.Dezaemon && PPU.Mode7Repeat == 2) \ + { \ + X &= 0x7ff; \ + Y &= 0x7ff; \ + } \ +\ + if (((X | Y) & ~0x3ff) == 0) \ + { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & 0x80) >> 7]; \ + if (GFX.Z1 > *d && (b & 0x7f) ) \ + { \ + *p = (FUNC); \ + *d = GFX.Z1; \ + } \ + } \ + else \ + { \ + if (PPU.Mode7Repeat == 3) \ + { \ + X = (x + HOffset) & 7; \ + Y = (yy + CentreY) & 7; \ + uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + GFX.Z1 = Mode7Depths [(b & 0x80) >> 7]; \ + if (GFX.Z1 > *d && (b & 0x7f) ) \ + { \ + *p = (FUNC); \ + *d = GFX.Z1; \ + } \ + } \ + } \ + } \ + } \ + } \ + } + +void DrawBGMode7Background16New (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7 (GFX.ScreenColors [b & 0xff]); +} + +void DrawBGMode7Background16 (uint8 *Screen, int bg, int depth) +{ + RENDER_BACKGROUND_MODE7ADDSUB (depth, GFX.ScreenColors [b & 0xff]); +} + +void DrawBGMode7Background16Add (uint8 *Screen, int bg, int depth) +{ + RENDER_BACKGROUND_MODE7ADDSUB (depth, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_ADD (GFX.ScreenColors [b & 0xff], + p [GFX.Delta]) : + COLOR_ADD (GFX.ScreenColors [b & 0xff], + GFX.FixedColour)) : + GFX.ScreenColors [b & 0xff]); + +} + +void DrawBGMode7Background16Add1_2 (uint8 *Screen, int bg, int depth) +{ + RENDER_BACKGROUND_MODE7ADDSUB (depth, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_ADD1_2 (GFX.ScreenColors [b & 0xff], + p [GFX.Delta]) : + COLOR_ADD (GFX.ScreenColors [b & 0xff], + GFX.FixedColour)) : + GFX.ScreenColors [b & 0xff]); +} + +void DrawBGMode7Background16Sub (uint8 *Screen, int bg, int depth) +{ + RENDER_BACKGROUND_MODE7ADDSUB (depth, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_SUB (GFX.ScreenColors [b & 0xff], + p [GFX.Delta]) : + COLOR_SUB (GFX.ScreenColors [b & 0xff], + GFX.FixedColour)) : + GFX.ScreenColors [b & 0xff]); +} + +void DrawBGMode7Background16Sub1_2 (uint8 *Screen, int bg, int depth) +{ + RENDER_BACKGROUND_MODE7ADDSUB (depth, *(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_SUB1_2 (GFX.ScreenColors [b & 0xff], + p [GFX.Delta]) : + COLOR_SUB (GFX.ScreenColors [b & 0xff], + GFX.FixedColour)) : + GFX.ScreenColors [b & 0xff]); +} + +void DrawBGMode7Background16Prio (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7PRIO (GFX.ScreenColors [b & 0x7f]); +} + +void DrawBGMode7Background16AddPrio (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7PRIO (*(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_ADD (GFX.ScreenColors [b & 0x7f], + p [GFX.Delta]) : + COLOR_ADD (GFX.ScreenColors [b & 0x7f], + GFX.FixedColour)) : + GFX.ScreenColors [b & 0x7f]); +} + +void DrawBGMode7Background16Add1_2Prio (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7PRIO (*(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_ADD1_2 (GFX.ScreenColors [b & 0x7f], + p [GFX.Delta]) : + COLOR_ADD (GFX.ScreenColors [b & 0x7f], + GFX.FixedColour)) : + GFX.ScreenColors [b & 0x7f]); +} + +void DrawBGMode7Background16SubPrio (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7PRIO (*(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_SUB (GFX.ScreenColors [b & 0x7f], + p [GFX.Delta]) : + COLOR_SUB (GFX.ScreenColors [b & 0x7f], + GFX.FixedColour)) : + GFX.ScreenColors [b & 0x7f]); +} + +void DrawBGMode7Background16Sub1_2Prio (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7PRIO (*(d + GFX.DepthDelta) ? + (*(d + GFX.DepthDelta) != 1 ? + COLOR_SUB1_2 (GFX.ScreenColors [b & 0x7f], + p [GFX.Delta]) : + COLOR_SUB (GFX.ScreenColors [b & 0x7f], + GFX.FixedColour)) : + GFX.ScreenColors [b & 0x7f]); +} + +#define _BUILD_SETUP(F) \ +GFX.BuildPixel = BuildPixel##F; \ +GFX.BuildPixel2 = BuildPixel2##F; \ +GFX.DecomposePixel = DecomposePixel##F; \ +RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_##F; \ +GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_##F; \ +BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_##F; \ +RED_HI_BIT_MASK = RED_HI_BIT_MASK_##F; \ +GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_##F; \ +BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_##F; \ +MAX_RED = MAX_RED_##F; \ +MAX_GREEN = MAX_GREEN_##F; \ +MAX_BLUE = MAX_BLUE_##F; \ +GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \ +SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \ +RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_##F | \ + GREEN_LOW_BIT_MASK_##F | \ + BLUE_LOW_BIT_MASK_##F); \ +RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_##F | \ + GREEN_HI_BIT_MASK_##F | \ + BLUE_HI_BIT_MASK_##F); \ +RGB_HI_BITS_MASKx2 = ((RED_HI_BIT_MASK_##F | \ + GREEN_HI_BIT_MASK_##F | \ + BLUE_HI_BIT_MASK_##F) << 1); \ +RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; \ +FIRST_COLOR_MASK = FIRST_COLOR_MASK_##F; \ +SECOND_COLOR_MASK = SECOND_COLOR_MASK_##F; \ +THIRD_COLOR_MASK = THIRD_COLOR_MASK_##F; \ +ALPHA_BITS_MASK = ALPHA_BITS_MASK_##F; \ +FIRST_THIRD_COLOR_MASK = FIRST_COLOR_MASK | THIRD_COLOR_MASK; \ +TWO_LOW_BITS_MASK = RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1); \ +HIGH_BITS_SHIFTED_TWO_MASK = (( (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & \ + ~TWO_LOW_BITS_MASK ) >> 2); + +void RenderScreen (uint8 *Screen, bool8_32 sub, bool8_32 force_no_add, uint8 D) +{ + bool8_32 BG0; + bool8_32 BG1; + bool8_32 BG2; + bool8_32 BG3; + bool8_32 OB; + + GFX.S = Screen; + + if (!sub) + { + GFX.pCurrentClip = &IPPU.Clip [0]; + BG0 = ON_MAIN (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0); + BG1 = ON_MAIN (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1); + BG2 = ON_MAIN (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2); + BG3 = ON_MAIN (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3); + OB = ON_MAIN (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); + } + else + { + GFX.pCurrentClip = &IPPU.Clip [1]; + BG0 = ON_SUB (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0); + BG1 = ON_SUB (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1); + BG2 = ON_SUB (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2); + BG3 = ON_SUB (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3); + OB = ON_SUB (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); + } + + sub |= force_no_add; + + if (PPU.BGMode <= 1) + { + if (OB) + { + SelectTileRenderer (sub || !SUB_OR_ADD(4), false); + DrawOBJS (!sub, D); + } + if (BG0) + { + SelectTileRenderer (sub || !SUB_OR_ADD(0), false); + DrawBackground (PPU.BGMode, 0, D + 10, D + 14); + } + if (BG1) + { + SelectTileRenderer (sub || !SUB_OR_ADD(1), false); + DrawBackground (PPU.BGMode, 1, D + 9, D + 13); + } + if (BG2) + { + SelectTileRenderer (sub || !SUB_OR_ADD(2), false); + DrawBackground (PPU.BGMode, 2, D + 3, + PPU.BG3Priority ? D + 17 : D + 6); + } + if (BG3 && PPU.BGMode == 0) + { + SelectTileRenderer (sub || !SUB_OR_ADD(3), false); + DrawBackground (PPU.BGMode, 3, D + 2, D + 5); + } + } + else if (PPU.BGMode != 7) + { + if (OB) + { + SelectTileRenderer (sub || !SUB_OR_ADD(4), false); + DrawOBJS (!sub, D); + } + if (BG0) + { + SelectTileRenderer (sub || !SUB_OR_ADD(0), false); + DrawBackground (PPU.BGMode, 0, D + 5, D + 13); + } + if (PPU.BGMode != 6 && BG1) + { + SelectTileRenderer (sub || !SUB_OR_ADD(1), false); + DrawBackground (PPU.BGMode, 1, D + 2, D + 9); + } + } + else + { + if (OB && ((SNESGameFixes.Mode7Hack && D) || !SNESGameFixes.Mode7Hack)) + { + SelectTileRenderer (sub || !SUB_OR_ADD(4), false); + DrawOBJS (!sub, D); + } + if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1)) + { + int bg; + + if ((Memory.FillRAM [0x2133] & 0x40)&&BG1) + { + Mode7Depths [0] = (BG0?5:1) + D; + Mode7Depths [1] = 9 + D; + bg = 1; + if (sub || !SUB_OR_ADD(0)) + { + DrawBGMode7Background16Prio (Screen, bg); + } + else + { + if (GFX.r2131 & 0x80) + { + if (GFX.r2131 & 0x40) + { + DrawBGMode7Background16Sub1_2Prio (Screen, bg); + } + else + { + DrawBGMode7Background16SubPrio (Screen, bg); + } + } + else + { + if (GFX.r2131 & 0x40) + { + DrawBGMode7Background16Add1_2Prio (Screen, bg); + } + else + { + DrawBGMode7Background16AddPrio (Screen, bg); + } + } + } + } + else + { + bg = 0; + if (sub || !SUB_OR_ADD(0)) + { + if (D || !SNESGameFixes.Mode7Hack) + DrawBGMode7Background16 (Screen, bg, D+5); + else + DrawBGMode7Background16New (Screen, bg); + } + else + { + if (GFX.r2131 & 0x80) + { + if (GFX.r2131 & 0x40) + { + DrawBGMode7Background16Sub1_2 (Screen, bg, D+5); + } + else + { + DrawBGMode7Background16Sub (Screen, bg, D+5); + } + } + else + { + if (GFX.r2131 & 0x40) + { + DrawBGMode7Background16Add1_2 (Screen, bg, D+5); + } + else + { + DrawBGMode7Background16Add (Screen, bg, D+5); + } + } + } + } + } + if (OB && SNESGameFixes.Mode7Hack && D==0) + { + SelectTileRenderer (sub || !SUB_OR_ADD(4), false); + DrawOBJS (!sub, D); + } + + } +} + +#include "font.h" + +void DisplayChar (uint8 *Screen, uint8 c) +{ + int line = (((c & 0x7f) - 32) >> 4) * font_height; + int offset = (((c & 0x7f) - 32) & 15) * font_width; + int h, w; + uint16 *s = (uint16 *) Screen; + for (h = 0; h < font_height; h++, line++, + s += GFX_PPL - font_width) + { + for (w = 0; w < font_width; w++, s++) + { + uint8 p = font [line][offset + w]; + + if (p == '#') + *s = 0xffff; + else + if (p == '.') + *s = BLACK; + } + } +} + +static void S9xDisplayFrameRate () +{ + uint8 *Screen = GFX.Screen + 2 + + (IPPU.RenderedScreenHeight - font_height - 1) * GFX_PITCH; + char string [10]; + int len = 5; + + sprintf (string, "%02d/%02d", IPPU.DisplayedRenderedFrameCount, + (int) Memory.ROMFramesPerSecond); + + int i; + for (i = 0; i < len; i++) + { + DisplayChar (Screen, string [i]); + Screen += (font_width - 1) * sizeof (uint16); + } +} + +static void S9xDisplayString (const char *string) +{ + uint8 *Screen = GFX.Screen + 2 + + (IPPU.RenderedScreenHeight - font_height * 5) * GFX_PITCH; + int len = strlen (string); + int max_chars = IPPU.RenderedScreenWidth / (font_width - 1); + int char_count = 0; + int i; + + for (i = 0; i < len; i++, char_count++) + { + if (char_count >= max_chars || string [i] < 32) + { + Screen -= (font_width - 1) * sizeof (uint16) * max_chars; + Screen += font_height * GFX_PITCH; + if (Screen >= GFX.Screen + GFX_PITCH * IPPU.RenderedScreenHeight) + break; + char_count -= max_chars; + } + if (string [i] < 32) + continue; + DisplayChar (Screen, string [i]); + Screen += (font_width - 1) * sizeof (uint16); + } +} + +void S9xUpdateScreen () // ~30-50ms! (called from FLUSH_REDRAW()) +{ + int32 x2 = 1; + + GFX.S = GFX.Screen; + + unsigned char *memoryfillram = Memory.FillRAM; + + // get local copies of vid registers to be used later + GFX.r2131 = memoryfillram [0x2131]; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN + GFX.r212c = memoryfillram [0x212c]; // MAIN SCREEN, DESIGNATION - used to enable BGS + GFX.r212d = memoryfillram [0x212d]; // SUB SCREEN DESIGNATION - used to enable sub BGS + GFX.r2130 = memoryfillram [0x2130]; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION + + // If external sync is off and + // main screens have not been configured the same as the sub screen and + // color addition and subtraction has been diabled then + // Pseudo is 1 + // anything else it is 0 + GFX.Pseudo = (memoryfillram [0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION? + (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens? + (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS? + + // If sprite data has been changed then go through and + // refresh the sprites. + if (IPPU.OBJChanged) + { + S9xSetupOBJ (); + } + + if (PPU.RecomputeClipWindows) + { + ComputeClipWindows (); + PPU.RecomputeClipWindows = FALSE; + } + + GFX.StartY = IPPU.PreviousLine; + if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) + GFX.EndY = PPU.ScreenHeight - 1; + + uint32 starty = GFX.StartY; + uint32 endy = GFX.EndY; + + if (Settings.SupportHiRes && + (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.LatchedInterlace)) + { + if (PPU.BGMode == 5 || PPU.BGMode == 6) + { + IPPU.RenderedScreenWidth = 512; + x2 = 2; + } + if (IPPU.LatchedInterlace) + { + starty = GFX.StartY * 2; + endy = GFX.EndY * 2 + 1; + } + if (!IPPU.DoubleWidthPixels) + { + // The game has switched from lo-res to hi-res mode part way down + // the screen. Scale any existing lo-res pixels on screen + for (register uint32 y = 0; y < GFX.StartY; y++) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + 255; + register uint16 *q = (uint16 *) (GFX.Screen + y * GFX_PITCH) + 510; + for (register int x = 255; x >= 0; x--, p--, q -= 2) + *q = *(q + 1) = *p; + } + IPPU.DoubleWidthPixels = TRUE; + } + } + + uint32 black = BLACK | (BLACK << 16); + + // Are we worrying about transparencies? + if (Settings.Transparency) + { + if (GFX.Pseudo) + { + GFX.r2131 = 0x5f; //0101 1111 - enable addition/subtraction on all BGS and sprites and "1/2 OF COLOR DATA" DESIGNATION + GFX.r212c &= (Memory.FillRAM [0x212d] | 0xf0); + GFX.r212d |= (Memory.FillRAM [0x212c] & 0x0f); + GFX.r2130 |= 2; // enable ADDITION/SUBTRACTION FOR SUB SCREEN + } + + // Check to see if any transparency effects are currently in use + if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING && + (GFX.r2130 & 0x30) != 0x30 && + !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0)) + { + // transparency effects in use, so lets get busy! + ClipData *pClip; + uint32 fixedColour; + GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed], + IPPU.XB [PPU.FixedColourGreen], + IPPU.XB [PPU.FixedColourBlue]); + fixedColour = (GFX.FixedColour<<16|GFX.FixedColour); + // Clear the z-buffer, marking areas 'covered' by the fixed + // colour as depth 1. + pClip = &IPPU.Clip [1]; + + // Clear the z-buffer + + if (pClip->Count [5]) + { + + // Colour window enabled. + +#ifdef RC_OPTIMIZED + for (uint32 y = starty; y <= endy; y++) + { + + ZeroMemory (GFX.SubZBuffer + y * GFX_ZPITCH, + IPPU.RenderedScreenWidth); + ZeroMemory (GFX.ZBuffer + y * GFX_ZPITCH, + IPPU.RenderedScreenWidth); + + if (IPPU.Clip [0].Count [5]) + { + memset ((GFX.SubScreen + y * GFX_PITCH), black, IPPU.RenderedScreenWidth); + } + for (uint32 c = 0; c < pClip->Count [5]; c++) + { + if (pClip->Right [c][5] > pClip->Left [c][5]) + { + memset (GFX.SubZBuffer + y * GFX_ZPITCH + pClip->Left [c][5] * x2, + 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2); + if (IPPU.Clip [0].Count [5]) + { + // Blast, have to clear the sub-screen to the fixed-colour + // because there is a colour window in effect clipping + // the main screen that will allow the sub-screen + // 'underneath' to show through. + memset ((GFX.SubScreen + y * GFX_PITCH) + pClip->Left [c][5] * x2, + GFX.FixedColour, + pClip->Right[c][5]*x2 - pClip->Left [c][5] * x2); + } + } + } + } + +#else // NOT RC_OPTIMIZED + // loop around all of the lines being updated + for (uint32 y = starty; y <= endy; y++) + { + // Clear the subZbuffer + memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH),0, + IPPU.RenderedScreenWidth>>2); + // Clear the Zbuffer + memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, + IPPU.RenderedScreenWidth>>2); + + // if there is clipping then clear subscreen to a black color + if (IPPU.Clip [0].Count [5]) + { + memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), black, IPPU.RenderedScreenWidth>>1); + } + + // loop through all window clippings + for (uint32 c = 0; c < pClip->Count [5]; c++) + { + if (pClip->Right [c][5] > pClip->Left [c][5]) + { + memset (GFX.SubZBuffer + y * GFX_ZPITCH + pClip->Left [c][5] * x2, + 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2); + if (IPPU.Clip [0].Count [5]) + { + // Blast, have to clear the sub-screen to the fixed-colour + // because there is a colour window in effect clipping + // the main screen that will allow the sub-screen + // 'underneath' to show through. + + register uint16 *p = (uint16 *) (GFX.SubScreen + y * GFX_PITCH); + register uint16 *q = p + pClip->Right [c][5] * x2; + p += pClip->Left [c][5] * x2; + + while (p < q) + *p++ = (uint16) GFX.FixedColour; + } + } + } + } +#endif +//#undef RC_OPTIMIZED + + } + else + { + // No windows are clipping the main screen + // this simplifies the screen clearing process +#ifdef RC_OPTIMIZED + + if (GFX_ZPITCH == (uint32)IPPU.RenderedScreenWidth) + { + + memset (GFX.ZBuffer + starty * GFX_ZPITCH, 0, GFX_ZPITCH * (endy - starty - 1)); + memset (GFX.SubZBuffer + starty * GFX_ZPITCH, 1, GFX_ZPITCH * (endy - starty - 1)); + } + else + { + for (uint32 y = starty; y <= endy; y++) + { + ZeroMemory (GFX.ZBuffer + y * GFX_ZPITCH, + IPPU.RenderedScreenWidth); + memset (GFX.SubZBuffer + y * GFX_ZPITCH, 1, + IPPU.RenderedScreenWidth); + } + } + + if (IPPU.Clip [0].Count [5]) + { + // Blast, have to clear the sub-screen to the fixed-colour + // because there is a colour window in effect clipping + // the main screen that will allow the sub-screen + // 'underneath' to show through. + if (GFX_PITCH == (uint32)IPPU.RenderedScreenWidth) + { + memset ((GFX.SubScreen + starty * GFX_PITCH), + GFX.FixedColour | (GFX.FixedColour << 16), + GFX_PITCH * (endy - starty - 1)); + } + else + { + for (uint32 y = starty; y <= endy; y++) + { + memset ((GFX.SubScreen + y * GFX_PITCH), + GFX.FixedColour | (GFX.FixedColour << 16), + IPPU.RenderedScreenWidth); + } + } + } + +#else // NOT RC_OPTIMIZED + // loop through all of the lines to be updated + for (uint32 y = starty; y <= endy; y++) + { + // Clear the Zbuffer + memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, + IPPU.RenderedScreenWidth>>2); + // clear the sub Zbuffer to 1 + memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH), 0x01010101, + IPPU.RenderedScreenWidth>>2); + if (IPPU.Clip [0].Count [5]) + { + // Blast, have to clear the sub-screen to the fixed-colour + // because there is a colour window in effect clipping + // the main screen that will allow the sub-screen + // 'underneath' to show through. + + + memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), fixedColour, + IPPU.RenderedScreenWidth>>1); + } + } +#endif + + } + + if (ANYTHING_ON_SUB) + { + GFX.DB = GFX.SubZBuffer; + RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH); + } + + if (IPPU.Clip [0].Count [5]) + { + for (uint32 y = starty; y <= endy; y++) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH); + register uint8 *d = GFX.SubZBuffer + y * GFX_ZPITCH ; + register uint8 *e = d + IPPU.RenderedScreenWidth; + + while (d < e) + { + if (*d > 1) + *p = *(p + GFX.Delta); + else + *p = BLACK; + d++; + p++; + } + } + } + + GFX.DB = GFX.ZBuffer; + RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH); + if (SUB_OR_ADD(5)) + { + uint32 back = IPPU.ScreenColors [0]; + uint32 Left = 0; + uint32 Right = 256; + uint32 Count; + + pClip = &IPPU.Clip [0]; + + for (uint32 y = starty; y <= endy; y++) + { + if (!(Count = pClip->Count [5])) + { + Left = 0; + Right = 256 * x2; + Count = 1; + } + + for (uint32 b = 0; b < Count; b++) + { + if (pClip->Count [5]) + { + Left = pClip->Left [b][5] * x2; + Right = pClip->Right [b][5] * x2; + if (Right <= Left) + continue; + } + + if (GFX.r2131 & 0x80) + { + if (GFX.r2131 & 0x40) + { + // Subtract, halving the result. + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; + register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; + register uint8 *s = GFX.SubZBuffer + y * GFX_ZPITCH + Left; + register uint8 *e = d + Right; + uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour); + + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = COLOR_SUB1_2 (back, *(p + GFX.Delta)); + else + *p = back_fixed; + } + else + *p = (uint16) back; + } + d++; + p++; + s++; + } + } + else + { + // Subtract + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; + register uint8 *s = GFX.SubZBuffer + y * GFX_ZPITCH + Left; + register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; + register uint8 *e = d + Right; + uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour); + + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = COLOR_SUB (back, *(p + GFX.Delta)); + else + *p = back_fixed; + } + else + *p = (uint16) back; + } + d++; + p++; + s++; + } + } + } + else + if (GFX.r2131 & 0x40) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; + register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; + register uint8 *s = GFX.SubZBuffer + y * GFX_ZPITCH + Left; + register uint8 *e = d + Right; + uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour); + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = COLOR_ADD1_2 (back, *(p + GFX.Delta)); + else + *p = back_fixed; + } + else + *p = (uint16) back; + } + d++; + p++; + s++; + } + } + else + if (back != 0) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; + register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; + register uint8 *s = GFX.SubZBuffer + y * GFX_ZPITCH + Left; + register uint8 *e = d + Right; + uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour); + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = COLOR_ADD (back, *(p + GFX.Delta)); + else + *p = back_fixed; + } + else + *p = (uint16) back; + } + d++; + p++; + s++; + } + } + else + { + if (!pClip->Count [5]) + { + // The backdrop has not been cleared yet - so + // copy the sub-screen to the main screen + // or fill it with the back-drop colour if the + // sub-screen is clear. + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; + register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; + register uint8 *s = GFX.SubZBuffer + y * GFX_ZPITCH + Left; + register uint8 *e = d + Right; + d += Left; + while (d < e) + { + if (*d == 0) + { + if (*s) + { + if (*s != 1) + *p = *(p + GFX.Delta); + else + *p = GFX.FixedColour; + } + else + *p = (uint16) back; + } + d++; + p++; + s++; + } + } + } + } + } + + } + else + { + // Subscreen not being added to back + uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); + pClip = &IPPU.Clip [0]; + + if (pClip->Count [5]) + { + for (uint32 y = starty; y <= endy; y++) + { + for (uint32 b = 0; b < pClip->Count [5]; b++) + { + uint32 Left = pClip->Left [b][5] * x2; + uint32 Right = pClip->Right [b][5] * x2; + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; + register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; + register uint8 *e = d + Right; + d += Left; + + while (d < e) + { + if (*d++ == 0) + *p = (int16) back; + p++; + } + } + } + } + else + { + for (uint32 y = starty; y <= endy; y++) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH); + register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; + register uint8 *e = d + 256 * x2; + + while (d < e) + { + if (*d == 0) +#ifdef RC_OPTIMIZED + *p++ = back; + d++; +#else + *p = (int16) back; + d++; + p++; +#endif + } + } + } + } + } + else + { + // 16bit and transparency but currently no transparency effects in + // operation. + + // get the back colour of the current screen + uint32 back = IPPU.ScreenColors [0] | + (IPPU.ScreenColors [0] << 16); + + // if forceblanking in use then use black instead of the back color + if (PPU.ForcedBlanking) + back = black; + + // not sure what Clip is used for yet + // could be a check to see if there is any clipping present? + if (IPPU.Clip [0].Count[5]) + { + +#ifdef RC_OPTIMIZED + if (GFX_PITCH == (uint32)IPPU.RenderedScreenWidth) + { + memset (GFX.Screen + starty * GFX_PITCH, black, + GFX_PITCH * (endy - starty - 1)); + } + else + { + for (uint32 y = starty; y <= endy; y++) + { + memset (GFX.Screen + y * GFX_PITCH, black, + GFX_PITCH); + } + } + for (uint32 y = starty; y <= endy; y++) + { + for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++) + { + if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5]) + { + + memset ((GFX.Screen + y * GFX_PITCH) + IPPU.Clip [0].Left [c][5] * x2, + back, + IPPU.Clip [0].Right [c][5] * x2 - IPPU.Clip [0].Left [c][5] * x2); + } + } + } +#else + // loop through all of the lines that are going to be updated as part of this screen update + for (uint32 y = starty; y <= endy; y++) + { + memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), black, + IPPU.RenderedScreenWidth>>1); + + if (black!=back) + { + for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++) + { + if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5]) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH); // get pointer to current line in screen buffer + register uint16 *q = p + IPPU.Clip [0].Right [c][5] * x2; // get pointer to end of line + p += IPPU.Clip [0].Left [c][5] * x2; + + while (p < q) + *p++ = (uint16) back; // fill all pixels in clipped section with the back colour + } + } + } + } +#endif + } + else + { +#ifdef RC_OPTIMIZED + if (GFX_PITCH == (uint32)IPPU.RenderedScreenWidth) + { + memset (GFX.Screen + starty * GFX_PITCH, back, + GFX_PITCH * (endy - starty - 1)); + } + else + { + for (uint32 y = starty; y <= endy; y++) + { + memset (GFX.Screen + y * GFX_PITCH, back, + GFX_PITCH); + } + } +#else + // there is no clipping to worry about so just fill with the back colour + for (uint32 y = starty; y <= endy; y++) + { + memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back, + IPPU.RenderedScreenWidth>>1); + } +#endif + } + + // If Forced blanking is not in effect + if (!PPU.ForcedBlanking) + { +#ifdef RC_OPTIMIZED + if (GFX_ZPITCH == (uint32)IPPU.RenderedScreenWidth) + { + memset (GFX.ZBuffer + starty * GFX_ZPITCH, 0, + GFX_ZPITCH * (endy - starty - 1)); + } + else + { + for (uint32 y = starty; y <= endy; y++) + { + memset (GFX.ZBuffer + y * GFX_ZPITCH, 0, + GFX_ZPITCH); + } + } +#else + // Clear the Zbuffer for each of the lines which are going to be updated + for (uint32 y = starty; y <= endy; y++) + { + memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0, + IPPU.RenderedScreenWidth>>2); + } +#endif + GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object + RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH); + } + } + } + else // Transparencys are disabled, ahh lovely ... nice and easy. + { + // get back colour to be used in clearing the screen + register uint32 back; + if (!(Memory.FillRAM [0x2131] & 0x80) &&(Memory.FillRAM[0x2131] & 0x20) && + (PPU.FixedColourRed || PPU.FixedColourGreen || PPU.FixedColourBlue)) + { + back = (IPPU.XB[PPU.FixedColourRed]<<11) | + (IPPU.XB[PPU.FixedColourGreen] << 6) | + (IPPU.XB[PPU.FixedColourBlue] << 1) | 1; + back = (back << 16) | back; + } + else + { + back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); + } + + // if Forcedblanking in use then back colour becomes black + if (PPU.ForcedBlanking) + back = black; + else + { + SelectTileRenderer (TRUE); //selects the tile renderers to be used + // TRUE means to use the default + // FALSE means use best renderer based on current + // graphics register settings + } + + // now clear all graphics lines which are being updated using the back colour + for (register uint32 y = starty; y <= endy; y++) + { + memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back, + IPPU.RenderedScreenWidth>>1); + } + + if (!PPU.ForcedBlanking) + { + // Loop through all lines being updated and clear the + // zbuffer for each of the lines + for (uint32 y = starty; y <= endy; y++) + { + memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0, + IPPU.RenderedScreenWidth>>2); + } + GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object + GFX.pCurrentClip = &IPPU.Clip [0]; + +// Define an inline function to handle clipping +#define FIXCLIP(n) \ +if (GFX.r212c & (1 << (n))) \ + GFX.pCurrentClip = &IPPU.Clip [0]; \ +else \ + GFX.pCurrentClip = &IPPU.Clip [1] + +// Define an inline function to handle which BGs are being displayed +#define DISPLAY(n) ((GFX.r212c & n) || ((GFX.r212d & n) && subadd)) + + uint8 subadd = GFX.r2131 & 0x3f; + + // go through all BGS are check if they need to be displayed + bool8_32 BG0 = DISPLAY(1) && !(Settings.os9x_hack & GFX_IGNORE_BG0); + bool8_32 BG1 = DISPLAY(2) && !(Settings.os9x_hack & GFX_IGNORE_BG1); + bool8_32 BG2 = DISPLAY(4) && !(Settings.os9x_hack & GFX_IGNORE_BG2); + bool8_32 BG3 = DISPLAY(8) && !(Settings.os9x_hack & GFX_IGNORE_BG3); + bool8_32 OB = DISPLAY(16) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); + + if (PPU.BGMode <= 1) + { + // screen modes 0 and 1 + if (OB) + { + FIXCLIP(4); + DrawOBJS (FALSE, 0); + } + if (BG0) + { + FIXCLIP(0); + DrawBackground (PPU.BGMode, 0, 10, 14); + } + if (BG1) + { + FIXCLIP(1); + DrawBackground (PPU.BGMode, 1, 9, 13); + } + if (BG2) + { + FIXCLIP(2); + DrawBackground (PPU.BGMode, 2, 3, + PPU.BG3Priority ? 17 : 6); + } + if (BG3 && PPU.BGMode == 0) + { + FIXCLIP(3); + DrawBackground (PPU.BGMode, 3, 2, 5); + } + } + else if (PPU.BGMode != 7) + { + // screen modes 2 and up but not mode 7 + if (OB) + { + FIXCLIP(4); + DrawOBJS (FALSE, 0); + } + if (BG0) + { + FIXCLIP(0); + DrawBackground (PPU.BGMode, 0, 5, 13); + } + if (BG1 && PPU.BGMode != 6) + { + FIXCLIP(1); + DrawBackground (PPU.BGMode, 1, 2, 9); + } + } + else + { + // screen mode 7 + GFX.Mode7Mask = 0xff; + GFX.Mode7PriorityMask = 0; + int bg = 0; + DrawBGMode7Background16New (GFX.Screen, bg); + if (OB) + { + FIXCLIP(4); + DrawOBJS (FALSE, 0); + } + } + } + } +#ifndef RC_OPTIMIZE // no hi res + if (Settings.SupportHiRes && PPU.BGMode != 5 && PPU.BGMode != 6) + { + if (IPPU.DoubleWidthPixels) + { + // Mixure of background modes used on screen - scale width + // of all non-mode 5 and 6 pixels. + for (register uint32 y = GFX.StartY; y <= GFX.EndY; y++) + { + register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + 255; + register uint16 *q = (uint16 *) (GFX.Screen + y * GFX_PITCH) + 510; + for (register int x = 255; x >= 0; x--, p--, q -= 2) + *q = *(q + 1) = *p; + } + + } + + if (IPPU.LatchedInterlace) + { + // Interlace is enabled - double the height of all non-mode 5 and 6 + // pixels. + for (uint32 y = GFX.StartY; y <= GFX.EndY; y++) + { + memcpy32 ((uint32_t*)(GFX.Screen + (y * 2 + 1) * GFX_PITCH), + (uint32_t*)(GFX.Screen + y * 2 * GFX_PITCH), + GFX_PITCH>>2); + } + } + } +#endif + IPPU.PreviousLine = IPPU.CurrentLine; +} + +#ifdef GFX_MULTI_FORMAT + +#define _BUILD_PIXEL(F) \ +uint32 BuildPixel##F(uint32 R, uint32 G, uint32 B) \ +{ \ + return (BUILD_PIXEL_##F(R,G,B)); \ +}\ +uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \ +{ \ + return (BUILD_PIXEL2_##F(R,G,B)); \ +} \ +void DecomposePixel##F(uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \ +{ \ + DECOMPOSE_PIXEL_##F(pixel,R,G,B); \ +} + +_BUILD_PIXEL(RGB565) +_BUILD_PIXEL(RGB555) +_BUILD_PIXEL(BGR565) +_BUILD_PIXEL(BGR555) +_BUILD_PIXEL(GBR565) +_BUILD_PIXEL(GBR555) +_BUILD_PIXEL(RGB5551) + +bool8_32 S9xSetRenderPixelFormat (int format) +{ + extern uint32 current_graphic_format; + + current_graphic_format = format; + + switch (format) + { + case RGB565: + _BUILD_SETUP(RGB565) + return (TRUE); + case RGB555: + _BUILD_SETUP(RGB555) + return (TRUE); + case BGR565: + _BUILD_SETUP(BGR565) + return (TRUE); + case BGR555: + _BUILD_SETUP(BGR555) + return (TRUE); + case GBR565: + _BUILD_SETUP(GBR565) + return (TRUE); + case GBR555: + _BUILD_SETUP(GBR555) + return (TRUE); + case RGB5551: + _BUILD_SETUP(RGB5551) + return (TRUE); + default: + break; + } + return (FALSE); +} +#endif diff --git a/src/gfx.cpp b/src/gfx.cpp deleted file mode 100644 index fe8f2b4..0000000 --- a/src/gfx.cpp +++ /dev/null @@ -1,3772 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include "snes9x.h" - -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "display.h" -#include "gfx.h" -#include "apu.h" -#include "cheats.h" -#include -#include "asmmemfuncs.h" -uint32 TileBlank; - -const int tx_table[16] = { -// t1 = 16, t2 = 0 - // FLIP = 0x00 - 16 + 0, // 0x00 - 16 + 1, // 0x01 - - // FLIP = 0x01 - 16 + 1 - 0, // 0x02 - 16 + 1 - 1, // 0x03 - - // FLIP = 0x02 - 0 + 0, // 0x04 - 0 + 1, // 0x05 - - // FLIP = 0x03 - 0 + 1 - 0, // 0x06 - 0 + 1 - 1, // 0x07 - -// t1 = 0, t2 = 16 - // FLIP = 0x00 - 0 + 0, // 0x08 - 0 + 1, // 0x09 - - // FLIP = 0x01 - 0 + 1 - 0, // 0x0A - 0 + 1 - 1, // 0x0B - - // FLIP = 0x02 - 16 + 0, // 0x0C - 16 + 1, // 0x0D - - // FLIP = 0x03 - 16 + 1 - 0, // 0x0E - 16 + 1 - 1 // 0x0F -}; - -#define M7 19 -#define M8 19 - -void ComputeClipWindows (); -static void S9xDisplayFrameRate (); -static void S9xDisplayString (const char *string); - -extern uint8 BitShifts[8][4]; -extern uint8 TileShifts[8][4]; -extern uint8 PaletteShifts[8][4]; -extern uint8 PaletteMasks[8][4]; -extern uint8 Depths[8][4]; -extern uint8 BGSizes [2]; - -extern NormalTileRenderer DrawTilePtr; -extern ClippedTileRenderer DrawClippedTilePtr; -extern NormalTileRenderer DrawHiResTilePtr; -extern ClippedTileRenderer DrawHiResClippedTilePtr; -extern LargePixelRenderer DrawLargePixelPtr; - -extern struct SBG BG; - -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; - -extern uint8 Mode7Depths [2]; - -#define CLIP_10_BIT_SIGNED(a) \ - ((a)%1023) -#define ON_MAIN(N) (GFX.r212c & (1 << (N))) - -#define SUB_OR_ADD(N) \ -(GFX.r2131 & (1 << (N))) - -#define ON_SUB(N) \ -((GFX.r2130 & 0x30) != 0x30 && \ - (GFX.r2130 & 2) && \ - (GFX.r212d & (1 << N))) - -#define ANYTHING_ON_SUB \ -((GFX.r2130 & 0x30) != 0x30 && \ - (GFX.r2130 & 2) && \ - (GFX.r212d & 0x1f)) - -#define ADD_OR_SUB_ON_ANYTHING \ -(GFX.r2131 & 0x3f) - -#define BLACK BUILD_PIXEL(0,0,0) - -void DrawTile (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawTilex2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTilex2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawTilex2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTilex2x2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawLargePixel (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawTile16_OBJ (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile16x2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawLargePixel16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Add (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Sub (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Add (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Sub (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawHiResTile16 (uint32 Tile, uint32 Offset, - uint32 StartLine, uint32 LineCount); - -bool8_32 S9xGraphicsInit () -{ - register uint32 PixelOdd = 1; - register uint32 PixelEven = 2; - -#ifdef GFX_MULTI_FORMAT - if (GFX.BuildPixel == NULL) - S9xSetRenderPixelFormat (RGB565); -#endif - - for (uint8 bitshift = 0; bitshift < 4; bitshift++) - { - for (register int i = 0; i < 16; i++) - { - register uint32 h = 0; - register uint32 l = 0; - -#if defined(LSB_FIRST) - if (i & 8) - h |= PixelOdd; - if (i & 4) - h |= PixelOdd << 8; - if (i & 2) - h |= PixelOdd << 16; - if (i & 1) - h |= PixelOdd << 24; - if (i & 8) - l |= PixelOdd; - if (i & 4) - l |= PixelOdd << 8; - if (i & 2) - l |= PixelOdd << 16; - if (i & 1) - l |= PixelOdd << 24; -#else - if (i & 8) - h |= (PixelOdd << 24); - if (i & 4) - h |= (PixelOdd << 16); - if (i & 2) - h |= (PixelOdd << 8); - if (i & 1) - h |= PixelOdd; - if (i & 8) - l |= (PixelOdd << 24); - if (i & 4) - l |= (PixelOdd << 16); - if (i & 2) - l |= (PixelOdd << 8); - if (i & 1) - l |= PixelOdd; -#endif - - odd_high[bitshift][i] = h; - odd_low[bitshift][i] = l; - h = l = 0; - -#if defined(LSB_FIRST) - if (i & 8) - h |= PixelEven; - if (i & 4) - h |= PixelEven << 8; - if (i & 2) - h |= PixelEven << 16; - if (i & 1) - h |= PixelEven << 24; - if (i & 8) - l |= PixelEven; - if (i & 4) - l |= PixelEven << 8; - if (i & 2) - l |= PixelEven << 16; - if (i & 1) - l |= PixelEven << 24; -#else - if (i & 8) - h |= (PixelEven << 24); - if (i & 4) - h |= (PixelEven << 16); - if (i & 2) - h |= (PixelEven << 8); - if (i & 1) - h |= PixelEven; - if (i & 8) - l |= (PixelEven << 24); - if (i & 4) - l |= (PixelEven << 16); - if (i & 2) - l |= (PixelEven << 8); - if (i & 1) - l |= PixelEven; -#endif - - even_high[bitshift][i] = h; - even_low[bitshift][i] = l; - } - PixelEven <<= 2; - PixelOdd <<= 2; - } - - GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; - GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; - //GFX.InfoStringTimeout = 0; - //GFX.InfoString = NULL; - - PPU.BG_Forced = 0; - IPPU.OBJChanged = TRUE; - - IPPU.DirectColourMapsNeedRebuild = TRUE; - DrawTilePtr = DrawTile16; - DrawClippedTilePtr = DrawClippedTile16; - DrawLargePixelPtr = DrawLargePixel16; - DrawHiResTilePtr= DrawHiResTile16; - DrawHiResClippedTilePtr = DrawHiResClippedTile16; - S9xFixColourBrightness (); - - if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000))) - return (FALSE); - - if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) || - !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000))) - { - if (GFX.ZERO_OR_X2) - { - free ((char *) GFX.ZERO_OR_X2); - GFX.ZERO_OR_X2 = NULL; - } - if (GFX.X2) - { - free ((char *) GFX.X2); - GFX.X2 = NULL; - } - return (FALSE); - } - uint32 r, g, b; - - // Build a lookup table that multiplies a packed RGB value by 2 with - // saturation. - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r << 1; - if (r2 > MAX_RED) - r2 = MAX_RED; - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g << 1; - if (g2 > MAX_GREEN) - g2 = MAX_GREEN; - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b << 1; - if (b2 > MAX_BLUE) - b2 = MAX_BLUE; - GFX.X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); - GFX.X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); - } - } - } - ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16)); - ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16)); - // Build a lookup table that if the top bit of the color value is zero - // then the value is zero, otherwise multiply the value by 2. Used by - // the color subtraction code. - -#if defined(OLD_COLOUR_BLENDING) - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r; - if ((r2 & 0x10) == 0) - r2 = 0; - else - r2 = (r2 << 1) & MAX_RED; - - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g; - if ((g2 & GREEN_HI_BIT) == 0) - g2 = 0; - else - g2 = (g2 << 1) & MAX_GREEN; - - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b; - if ((b2 & 0x10) == 0) - b2 = 0; - else - b2 = (b2 << 1) & MAX_BLUE; - - GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); - GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); - } - } - } -#else - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r; - if ((r2 & 0x10) == 0) - r2 = 0; - else - r2 = (r2 << 1) & MAX_RED; - - if (r2 == 0) - r2 = 1; - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g; - if ((g2 & GREEN_HI_BIT) == 0) - g2 = 0; - else - g2 = (g2 << 1) & MAX_GREEN; - - if (g2 == 0) - g2 = 1; - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b; - if ((b2 & 0x10) == 0) - b2 = 0; - else - b2 = (b2 << 1) & MAX_BLUE; - - if (b2 == 0) - b2 = 1; - GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); - GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); - } - } - } -#endif - - // Build a lookup table that if the top bit of the color value is zero - // then the value is zero, otherwise its just the value. - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r; - if ((r2 & 0x10) == 0) - r2 = 0; - else - r2 &= ~0x10; - - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g; - if ((g2 & GREEN_HI_BIT) == 0) - g2 = 0; - else - g2 &= ~GREEN_HI_BIT; - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b; - if ((b2 & 0x10) == 0) - b2 = 0; - else - b2 &= ~0x10; - - GFX.ZERO [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); - GFX.ZERO [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); - } - } - } - - return (TRUE); -} - -void S9xGraphicsDeinit (void) -{ - // Free any memory allocated in S9xGraphicsInit - if (GFX.X2) - { - free ((char *) GFX.X2); - GFX.X2 = NULL; - } - if (GFX.ZERO_OR_X2) - { - free ((char *) GFX.ZERO_OR_X2); - GFX.ZERO_OR_X2 = NULL; - } - if (GFX.ZERO) - { - free ((char *) GFX.ZERO); - GFX.ZERO = NULL; - } -} - -void S9xBuildDirectColourMaps () -{ - for (uint32 p = 0; p < 8; p++) - { - for (uint32 c = 0; c < 256; c++) - { -// XXX: Brightness - DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1), - ((c & 0x38) >> 1) | (p & 2), - ((c & 0xc0) >> 3) | (p & 4)); - } - } - IPPU.DirectColourMapsNeedRebuild = FALSE; -} - -void S9xStartScreenRefresh () -{ - if (IPPU.RenderThisFrame) - { - if (!S9xInitUpdate ()) - { - IPPU.RenderThisFrame = FALSE; - return; - } - IPPU.RenderedFramesCount++; - IPPU.PreviousLine = IPPU.CurrentLine = 0; - IPPU.MaxBrightness = PPU.Brightness; - IPPU.LatchedBlanking = PPU.ForcedBlanking; - IPPU.LatchedInterlace = (Memory.FillRAM[0x2133] & 1); - IPPU.RenderedScreenWidth = 256; - IPPU.RenderedScreenHeight = PPU.ScreenHeight; - IPPU.DoubleWidthPixels = FALSE; - - PPU.RecomputeClipWindows = TRUE; - GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; - GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; - } - if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) - { - IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; - IPPU.RenderedFramesCount = 0; - IPPU.FrameCount = 0; - } -} - -void RenderLine (uint8 C) -{ - if (IPPU.RenderThisFrame) - { - - LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1; - LineData[C].BG[0].HOffset = PPU.BG[0].HOffset; - LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1; - LineData[C].BG[1].HOffset = PPU.BG[1].HOffset; - - if (PPU.BGMode == 7) - { - struct SLineMatrixData *p = &LineMatrixData [C]; - p->MatrixA = PPU.MatrixA; - p->MatrixB = PPU.MatrixB; - p->MatrixC = PPU.MatrixC; - p->MatrixD = PPU.MatrixD; - p->CentreX = PPU.CentreX; - p->CentreY = PPU.CentreY; - } - else - { - if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 && - PPU.BG[2].HOffset == 0xe000) - { - LineData[C].BG[2].VOffset = 0xe1; - LineData[C].BG[2].HOffset = 0; - } - else - { - LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1; - LineData[C].BG[2].HOffset = PPU.BG[2].HOffset; - LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1; - LineData[C].BG[3].HOffset = PPU.BG[3].HOffset; - } - - } - IPPU.CurrentLine = C + 1; - } -} - - -void S9xEndScreenRefresh() -{ - IPPU.HDMAStarted = FALSE; - -//RC - if (IPPU.RenderThisFrame) - { - FLUSH_REDRAW (); - if (IPPU.ColorsChanged) - { - IPPU.ColorsChanged = FALSE; - } - - - S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, - 1); - } -#ifndef RC_OPTIMIZED - S9xApplyCheats (); -#endif - - -#ifdef DEBUGGER - if (CPU.Flags & FRAME_ADVANCE_FLAG) - { - if (ICPU.FrameAdvanceCount) - { - ICPU.FrameAdvanceCount--; - IPPU.RenderThisFrame = TRUE; - IPPU.FrameSkip = 0; - } - else - { - CPU.Flags &= ~FRAME_ADVANCE_FLAG; - CPU.Flags |= DEBUG_MODE_FLAG; - } - } -#endif - -/* - if (CPU.SRAMModified) - { - if (!CPU.AutoSaveTimer) - { - if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond)) - CPU.SRAMModified = FALSE; - } - else - { - if (!--CPU.AutoSaveTimer) - { - S9xAutoSaveSRAM (); - CPU.SRAMModified = FALSE; - } - } - } -*/ -} - -void S9xSetInfoString (const char *string) -{ - } - -INLINE void SelectTileRenderer (bool8_32 normal) -{ - if (normal) - { - DrawTilePtr = DrawTile16; - DrawClippedTilePtr = DrawClippedTile16; - DrawLargePixelPtr = DrawLargePixel16; - } - else - { - if (GFX.r2131 & 0x80) - { - if (GFX.r2131 & 0x40) - { - if (GFX.r2130 & 2) - { - DrawTilePtr = DrawTile16Sub1_2; - DrawClippedTilePtr = DrawClippedTile16Sub1_2; - } - else - { - // Fixed colour substraction - DrawTilePtr = DrawTile16FixedSub1_2; - DrawClippedTilePtr = DrawClippedTile16FixedSub1_2; - } - DrawLargePixelPtr = DrawLargePixel16Sub1_2; - } - else - { - DrawTilePtr = DrawTile16Sub; - DrawClippedTilePtr = DrawClippedTile16Sub; - DrawLargePixelPtr = DrawLargePixel16Sub; - } - } - else - { - if (GFX.r2131 & 0x40) - { - if (GFX.r2130 & 2) - { - DrawTilePtr = DrawTile16Add1_2; - DrawClippedTilePtr = DrawClippedTile16Add1_2; - } - else - { - // Fixed colour addition - DrawTilePtr = DrawTile16FixedAdd1_2; - DrawClippedTilePtr = DrawClippedTile16FixedAdd1_2; - } - DrawLargePixelPtr = DrawLargePixel16Add1_2; - } - else - { - DrawTilePtr = DrawTile16Add; - DrawClippedTilePtr = DrawClippedTile16Add; - DrawLargePixelPtr = DrawLargePixel16Add; - } - } - } -} - -void S9xSetupOBJ () -{ - int SmallSize; - int LargeSize; - - switch (PPU.OBJSizeSelect) - { - case 0: - SmallSize = 8; - LargeSize = 16; - break; - case 1: - SmallSize = 8; - LargeSize = 32; - break; - case 2: - SmallSize = 8; - LargeSize = 64; - break; - case 3: - SmallSize = 16; - LargeSize = 32; - break; - case 4: - SmallSize = 16; - LargeSize = 64; - break; - case 5: - default: - SmallSize = 32; - LargeSize = 64; - break; - } - - int C = 0; - - int FirstSprite = PPU.FirstSprite & 0x7f; - int S = FirstSprite; - do - { - int Size; - if (PPU.OBJ [S].Size) - Size = LargeSize; - else - Size = SmallSize; - - long VPos = PPU.OBJ [S].VPos; - - if (VPos >= PPU.ScreenHeight) - VPos -= 256; - if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size && - VPos < PPU.ScreenHeight && VPos > -Size) - { - GFX.OBJList [C++] = S; - GFX.Sizes[S] = Size; - GFX.VPositions[S] = VPos; - } - S = (S + 1) & 0x7f; - } while (S != FirstSprite); - - // Terminate the list - GFX.OBJList [C] = -1; - IPPU.OBJChanged = FALSE; -} - -void DrawOBJS (bool8_32 OnMain = FALSE, uint8 D = 0) -{ - uint32 O; - uint32 BaseTile, Tile; - - CHECK_SOUND(); - - BG.BitShift = 4; - BG.TileShift = 5; - BG.TileAddress = PPU.OBJNameBase; - BG.StartPalette = 128; - BG.PaletteShift = 4; - BG.PaletteMask = 7; - BG.Buffer = IPPU.TileCache [TILE_4BIT]; - BG.Buffered = IPPU.TileCached [TILE_4BIT]; - BG.NameSelect = PPU.OBJNameSelect; - BG.DirectColourMode = FALSE; - - GFX.Z1 = D + 2; - - if ( DrawTilePtr == DrawTile16 ){ - DrawTilePtr = DrawTile16_OBJ; - } - int I = 0; - for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++]) - { - int VPos = GFX.VPositions [S]; - int Size = GFX.Sizes[S]; - int TileInc = 1; - int Offset; - - if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY) - continue; - - if (OnMain && SUB_OR_ADD(4)) - { - SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4); - if ( DrawTilePtr == DrawTile16 ){ - DrawTilePtr = DrawTile16_OBJ; - } - } - - BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10); - - if (PPU.OBJ[S].HFlip) - { - BaseTile += ((Size >> 3) - 1) | H_FLIP; - TileInc = -1; - } - if (PPU.OBJ[S].VFlip) - BaseTile |= V_FLIP; - - int clipcount = GFX.pCurrentClip->Count [4]; - if (!clipcount) - clipcount = 1; - - GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D; - - for (int clip = 0; clip < clipcount; clip++) - { - int Left; - int Right; - if (!GFX.pCurrentClip->Count [4]) - { - Left = 0; - Right = 256; - } - else - { - Left = GFX.pCurrentClip->Left [clip][4]; - Right = GFX.pCurrentClip->Right [clip][4]; - } - - if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left || - PPU.OBJ[S].HPos >= Right) - continue; - - for (int Y = 0; Y < Size; Y += 8) - { - if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY) - { - int StartLine; - int TileLine; - int LineCount; - int Last; - - if ((StartLine = VPos + Y) < (int) GFX.StartY) - { - StartLine = GFX.StartY - StartLine; - LineCount = 8 - StartLine; - } - else - { - StartLine = 0; - LineCount = 8; - } - if ((Last = VPos + Y + 7 - GFX.EndY) > 0) - if ((LineCount -= Last) <= 0) - break; - - TileLine = StartLine << 3; - O = (VPos + Y + StartLine) * GFX_PPL; - if (!PPU.OBJ[S].VFlip) - Tile = BaseTile + (Y << 1); - else - Tile = BaseTile + ((Size - Y - 8) << 1); - - int Middle = Size >> 3; - if (PPU.OBJ[S].HPos < Left) - { - Tile += ((Left - PPU.OBJ[S].HPos) >> 3) * TileInc; - Middle -= (Left - PPU.OBJ[S].HPos) >> 3; - O += Left * GFX_PIXSIZE; - if ((Offset = (Left - PPU.OBJ[S].HPos) & 7)) - { - O -= Offset * GFX_PIXSIZE; - int W = 8 - Offset; - int Width = Right - Left; - if (W > Width) - W = Width; - (*DrawClippedTilePtr) (Tile, O, Offset, W, - TileLine, LineCount); - - if (W >= Width) - continue; - Tile += TileInc; - Middle--; - O += 8 * GFX_PIXSIZE; - } - } - else - O += PPU.OBJ[S].HPos * GFX_PIXSIZE; - - if (PPU.OBJ[S].HPos + Size >= Right) - { - Middle -= ((PPU.OBJ[S].HPos + Size + 7) - - Right) >> 3; - Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7; - } - else - Offset = 0; - - for (int X = 0; X < Middle; X++, O += 8 * GFX_PIXSIZE, - Tile += TileInc) - { - (*DrawTilePtr) (Tile, O, TileLine, LineCount); - } - if (Offset) - { - (*DrawClippedTilePtr) (Tile, O, 0, Offset, - TileLine, LineCount); - } - } - } - } - } -} - -void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ - CHECK_SOUND(); - - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint8 depths [2] = {Z1, Z2}; - - if (BGMode == 0) - BG.StartPalette = bg << 5; - else - BG.StartPalette = 0; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if (PPU.BG[bg].SCSize & 1) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if(((uint8*)SC1-Memory.VRAM)>=0x10000) - SC1-=0x08000; - - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - - if (PPU.BG[bg].SCSize & 1) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - - uint32 Lines; - uint32 OffsetMask; - uint32 OffsetShift; - - if (BG.TileSize == 16) - { - OffsetMask = 0x3ff; - OffsetShift = 4; - } - else - { - OffsetMask = 0x1ff; - OffsetShift = 3; - } - - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) - { - uint32 VOffset = LineData [Y].BG[bg].VOffset; - uint32 HOffset = LineData [Y].BG[bg].HOffset; - uint32 MosaicOffset = Y % PPU.Mosaic; - - for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) - break; - - uint32 MosaicLine = VOffset + Y - MosaicOffset; - - if (Y + Lines > GFX.EndY) - Lines = GFX.EndY + 1 - Y; - uint32 VirtAlign = (MosaicLine & 7) << 3; - - uint16 *b1; - uint16 *b2; - - uint32 ScreenLine = MosaicLine >> OffsetShift; - uint32 Rem16 = MosaicLine & 15; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - uint16 *t; - uint32 Left = 0; - uint32 Right = 256; - - uint32 ClipCount = GFX.pCurrentClip->Count [bg]; - uint32 HPos = HOffset; - uint32 PixWidth = PPU.Mosaic; - - if (!ClipCount) - ClipCount = 1; - - for (uint32 clip = 0; clip < ClipCount; clip++) - { - if (GFX.pCurrentClip->Count [bg]) - { - Left = GFX.pCurrentClip->Left [clip][bg]; - Right = GFX.pCurrentClip->Right [clip][bg]; - uint32 r = Left % PPU.Mosaic; - HPos = HOffset + Left; - PixWidth = PPU.Mosaic - r; - } - uint32 s = Y * GFX_PPL + Left * GFX_PIXSIZE; - for (uint32 x = Left; x < Right; x += PixWidth, - s += PixWidth * GFX_PIXSIZE, - HPos += PixWidth, PixWidth = PPU.Mosaic) - { - uint32 Quot = (HPos & OffsetMask) >> 3; - - if (x + PixWidth >= Right) - PixWidth = Right - x; - - if (BG.TileSize == 8) - { - if (Quot > 31) - t = b2 + (Quot & 0x1f); - else - t = b1 + Quot; - } - else - { - if (Quot > 63) - t = b2 + ((Quot >> 1) & 0x1f); - else - t = b1 + (Quot >> 1); - } - - Tile = READ_2BYTES (t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - // Draw tile... - if (BG.TileSize != 8) - { - if (Tile & H_FLIP) - { - // Horizontal flip, but what about vertical flip ? - if (Tile & V_FLIP) - { - // Both horzontal & vertical flip - if (Rem16 < 8) - { - (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - else - { - // Horizontal flip only - if (Rem16 > 7) - { - (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - } - else - { - // No horizontal flip, but is there a vertical flip ? - if (Tile & V_FLIP) - { - // Vertical flip only - if (Rem16 < 8) - { - (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - else - { - // Normal unflipped - if (Rem16 > 7) - { - (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - } - } - else - (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - } -} - -void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ - CHECK_SOUND(); - - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint16 *BPS0; - uint16 *BPS1; - uint16 *BPS2; - uint16 *BPS3; - uint32 Width; - int VOffsetOffset = BGMode == 4 ? 0 : 32; - uint8 depths [2] = {Z1, Z2}; - - BG.StartPalette = 0; - - BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; - - if (PPU.BG[2].SCSize & 1) - BPS1 = BPS0 + 1024; - else - BPS1 = BPS0; - - if (PPU.BG[2].SCSize & 2) - BPS2 = BPS1 + 1024; - else - BPS2 = BPS0; - - if (PPU.BG[2].SCSize & 1) - BPS3 = BPS2 + 1024; - else - BPS3 = BPS2; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if (PPU.BG[bg].SCSize & 1) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if(((uint8*)SC1-Memory.VRAM)>=0x10000) - SC1-=0x08000; - - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - - if (PPU.BG[bg].SCSize & 1) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - - static const int Lines = 1; - int OffsetMask; - int OffsetShift; - int OffsetEnableMask = 1 << (bg + 13); - - if (BG.TileSize == 16) - { - OffsetMask = 0x3ff; - OffsetShift = 4; - } - else - { - OffsetMask = 0x1ff; - OffsetShift = 3; - } - - TileBlank = 0xFFFFFFFF; - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++) - { - uint32 VOff = LineData [Y].BG[2].VOffset - 1; - uint32 HOff = LineData [Y].BG[2].HOffset; - int VirtAlign; - int ScreenLine = VOff >> 3; - uint16 *s0; - uint16 *s1; - uint16 *s2; - - if (ScreenLine & 0x20) - s1 = BPS2, s2 = BPS3; - else - s1 = BPS0, s2 = BPS1; - - s1 += (ScreenLine & 0x1f) << 5; - s2 += (ScreenLine & 0x1f) << 5; - - if(BGMode != 4) - { - if((ScreenLine & 0x1f) == 0x1f) - { - if(ScreenLine & 0x20) - VOffsetOffset = BPS0 - BPS2 - 0x1f*32; - else - VOffsetOffset = BPS2 - BPS0 - 0x1f*32; - } - else - { - VOffsetOffset = 32; - } - } - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) - clipcount = 1; - - for (int clip = 0; clip < clipcount; clip++) - { - uint32 Left; - uint32 Right; - - if (!GFX.pCurrentClip->Count [bg]) - { - Left = 0; - Right = 256; - } - else - { - Left = GFX.pCurrentClip->Left [clip][bg]; - Right = GFX.pCurrentClip->Right [clip][bg]; - - if (Right <= Left) - continue; - } - - uint32 VOffset; - uint32 HOffset; - uint32 LineHOffset=LineData [Y].BG[bg].HOffset; - uint32 Offset; - uint32 HPos; - uint32 Quot; - uint32 Count; - uint16 *t; - uint32 Quot2; - uint32 VCellOffset; - uint32 HCellOffset; - uint16 *b1; - uint16 *b2; - uint32 TotalCount = 0; - uint32 MaxCount = 8; - - uint32 s = Left * GFX_PIXSIZE + Y * GFX_PPL; - bool8_32 left_hand_edge = (Left == 0); - Width = Right - Left; - - if (Left & 7) - MaxCount = 8 - (Left & 7); - - while (Left < Right) - { - if (left_hand_edge) - { - // The SNES offset-per-tile background mode has a - // hardware limitation that the offsets cannot be set - // for the tile at the left-hand edge of the screen. - VOffset = LineData [Y].BG[bg].VOffset; - HOffset = LineHOffset; - left_hand_edge = FALSE; - } - else - { - // All subsequent offset tile data is shifted left by one, - // hence the - 1 below. - Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3; - - if (Quot2 > 31) - s0 = s2 + (Quot2 & 0x1f); - else - s0 = s1 + Quot2; - - HCellOffset = READ_2BYTES (s0); - - if (BGMode == 4) - { - VOffset = LineData [Y].BG[bg].VOffset; - HOffset=LineHOffset; - if ((HCellOffset & OffsetEnableMask)) - { - if (HCellOffset & 0x8000) - VOffset = HCellOffset + 1; - else - HOffset = HCellOffset; - } - } - else - { - VCellOffset = READ_2BYTES (s0 + VOffsetOffset); - if ((VCellOffset & OffsetEnableMask)) - VOffset = VCellOffset + 1; - else - VOffset = LineData [Y].BG[bg].VOffset; - - if ((HCellOffset & OffsetEnableMask)) - HOffset = (HCellOffset & ~7)|(LineHOffset&7); - else - HOffset=LineHOffset; - } - } - VirtAlign = ((Y + VOffset) & 7) << 3; - ScreenLine = (VOffset + Y) >> OffsetShift; - - int tx_index; - tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - HPos = (HOffset + Left) & OffsetMask; - - Quot = HPos >> 3; - - if (BG.TileSize == 8) - { - if (Quot > 31) - t = b2 + (Quot & 0x1f); - else - t = b1 + Quot; - } - else - { - if (Quot > 63) - t = b2 + ((Quot >> 1) & 0x1f); - else - t = b1 + (Quot >> 1); - } - - if (MaxCount + TotalCount > Width) - MaxCount = Width - TotalCount; - - Offset = HPos & 7; - - Count = 8 - Offset; - if (Count > MaxCount) - Count = MaxCount; - - s -= Offset * GFX_PIXSIZE; - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - if (Tile != TileBlank) - if (BG.TileSize == 8) - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); - else - { - Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)]; - if (Tile != TileBlank){ - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); - } - } - - Left += Count; - TotalCount += Count; - s += (Offset + Count) * GFX_PIXSIZE; - MaxCount = 8; - } - } - } -} - -void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2) -{ - CHECK_SOUND(); - - uint8 depths [2] = {Z1, Z2}; - - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint32 Width; - - BG.StartPalette = 0; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if ((PPU.BG[bg].SCSize & 1)) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if((SC1-(unsigned short*)Memory.VRAM)>0x10000) - SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000]; - - if ((PPU.BG[bg].SCSize & 2)) - SC2 = SC1 + 1024; - else SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - if ((PPU.BG[bg].SCSize & 1)) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - int Lines; - int VOffsetMask; - int VOffsetShift; - - if (BG.TileSize == 16) - { - VOffsetMask = 0x3ff; - VOffsetShift = 4; - } - else - { - VOffsetMask = 0x1ff; - VOffsetShift = 3; - } - int endy = GFX.EndY; - - for (int Y = GFX.StartY; Y <= endy; Y += Lines) - { - int y = Y; - uint32 VOffset = LineData [y].BG[bg].VOffset; - uint32 HOffset = LineData [y].BG[bg].HOffset; - int VirtAlign = (Y + VOffset) & 7; - - for (Lines = 1; Lines < 8 - VirtAlign; Lines++) - if ((VOffset != LineData [y + Lines].BG[bg].VOffset) || - (HOffset != LineData [y + Lines].BG[bg].HOffset)) - break; - - HOffset <<= 1; - if (Y + Lines > endy) - Lines = endy + 1 - Y; - - int ScreenLine = (VOffset + Y) >> VOffsetShift; - int t1; - int t2; - if (((VOffset + Y) & 15) > 7) - { - t1 = 16; - t2 = 0; - } - else - { - t1 = 0; - t2 = 16; - } - uint16 *b1; - uint16 *b2; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) - clipcount = 1; - for (int clip = 0; clip < clipcount; clip++) - { - int Left; - int Right; - - if (!GFX.pCurrentClip->Count [bg]) - { - Left = 0; - Right = 512; - } - else - { - Left = GFX.pCurrentClip->Left [clip][bg] * 2; - Right = GFX.pCurrentClip->Right [clip][bg] * 2; - - if (Right <= Left) - continue; - } - - uint32 s = (Left>>1) * GFX_PIXSIZE + Y * GFX_PPL; - uint32 HPos = (HOffset + Left * GFX_PIXSIZE) & 0x3ff; - - uint32 Quot = HPos >> 3; - uint32 Count = 0; - - uint16 *t; - if (Quot > 63) - t = b2 + ((Quot >> 1) & 0x1f); - else - t = b1 + (Quot >> 1); - - Width = Right - Left; - // Left hand edge clipped tile - if (HPos & 7) - { - int Offset = (HPos & 7); - Count = 8 - Offset; - if (Count > Width) - Count = Width; - s -= (Offset>>1); - Tile = READ_2BYTES (t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - if (BG.TileSize == 8) - { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - - t += Quot & 1; - if (Quot == 63) - t = b2; - else if (Quot == 127) - t = b1; - Quot++; - s += 4; - } - - // Middle, unclipped tiles - Count = Width - Count; - int Middle = Count >> 3; - Count &= 7; - for (int C = Middle; C > 0; s += 4, Quot++, C--) - { - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - if (BG.TileSize == 8) - { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResTilePtr) (Tile + (Quot & 1), - s, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1), - s, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1), - s, VirtAlign, Lines); - } - } - - t += Quot & 1; - if (Quot == 63) - t = b2; - else - if (Quot == 127) - t = b1; - } - - // Right-hand edge clipped tiles - if (Count) - { - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - if (BG.TileSize == 8) - { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - } - } - } - } -} - -void DrawBackground_8 (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint32 Width; - uint8 depths [2] = {Z1, Z2}; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if (PPU.BG[bg].SCSize & 1) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if(SC1>=(unsigned short*)(Memory.VRAM+0x10000)) - SC1=(uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0])%0x10000]; - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - if (PPU.BG[bg].SCSize & 1) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - - int Lines; - - TileBlank = 0xFFFFFFFF; - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){ - uint32 VOffset = LineData [Y].BG[bg].VOffset; - uint32 HOffset = LineData [Y].BG[bg].HOffset; - int VirtAlign = (Y + VOffset) & 7; - - for (Lines = 1; Lines < 8 - VirtAlign; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) - break; - - if (Y + Lines > GFX.EndY) - Lines = GFX.EndY + 1 - Y; - - VirtAlign <<= 3; - - uint32 ScreenLine = (VOffset + Y) >> 3; - uint16 *b1; - uint16 *b2; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) - clipcount = 1; - for (int clip = 0; clip < clipcount; clip++){ - uint32 Left; - uint32 Right; - - if (!GFX.pCurrentClip->Count [bg]){ - Left = 0; - Right = 256; - } else { - Left = GFX.pCurrentClip->Left [clip][bg]; - Right = GFX.pCurrentClip->Right [clip][bg]; - - if (Right <= Left) - continue; - } - - uint32 s = Left + Y * GFX_PPL; - uint32 HPos = (HOffset + Left) & 0x1ff; - uint32 Quot = HPos >> 3; - uint32 Count = 0; - uint16 *t; - - if (Quot > 31) t = b2 + (Quot & 0x1f); else t = b1 + Quot; - - Width = Right - Left; - - // Left hand edge clipped tile - if (HPos & 7){ - uint32 Offset = (HPos & 7); - Count = 8 - Offset; - if (Count > Width) Count = Width; - s -= Offset; - Tile = READ_2BYTES(t); - if (Tile != TileBlank){ - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); - } - t++; - if (Quot == 31) t = b2; else if (Quot == 63) t = b1; - Quot++; - s += 8; - } - - // Middle, unclipped tiles - Count = Width - Count; - for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){ - Tile = READ_2BYTES(t); - if (Tile != TileBlank){ - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - (*DrawTilePtr) (Tile, s, VirtAlign, Lines); - } - - t++; - if (Quot == 31) t = b2; else if (Quot == 63) t = b1; - } - - // Right-hand edge clipped tiles - if (Count){ - Tile = READ_2BYTES(t); - if (Tile != TileBlank){ - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines); - } - } - } - } - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; -} - -void DrawBackground_16 (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint32 Width; - uint8 depths [2] = {Z1, Z2}; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if (PPU.BG[bg].SCSize & 1) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if(SC1>=(unsigned short*)(Memory.VRAM+0x10000)) - SC1=(uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0])%0x10000]; - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - if (PPU.BG[bg].SCSize & 1) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - - int Lines; - - TileBlank = 0xFFFFFFFF; - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){ - uint32 VOffset = LineData [Y].BG[bg].VOffset; - uint32 HOffset = LineData [Y].BG[bg].HOffset; - int VirtAlign = (Y + VOffset) & 7; - - for (Lines = 1; Lines < 8 - VirtAlign; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) - break; - - if (Y + Lines > GFX.EndY) - Lines = GFX.EndY + 1 - Y; - - VirtAlign <<= 3; - - uint32 ScreenLine = (VOffset + Y) >> 4; - int tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3; - uint16 *b1; - uint16 *b2; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) - clipcount = 1; - for (int clip = 0; clip < clipcount; clip++){ - uint32 Left; - uint32 Right; - - if (!GFX.pCurrentClip->Count [bg]){ - Left = 0; - Right = 256; - } else { - Left = GFX.pCurrentClip->Left [clip][bg]; - Right = GFX.pCurrentClip->Right [clip][bg]; - - if (Right <= Left) - continue; - } - - uint32 s = Left + Y * GFX_PPL; - uint32 HPos = (HOffset + Left) & 0x3ff; - uint32 Quot = HPos >> 3; - uint32 Count = 0; - uint16 *t; - - if (Quot > 63) t = b2 + ((Quot >> 1) & 0x1f); else t = b1 + (Quot >> 1); - - Width = Right - Left; - - // Left hand edge clipped tile - if (HPos & 7){ - uint32 Offset = (HPos & 7); - Count = 8 - Offset; - if (Count > Width) Count = Width; - s -= Offset; - Tile = READ_2BYTES(t); - Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)]; - if (Tile != TileBlank){ - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); - } - - t += Quot & 1; - if (Quot == 63) t = b2; else if (Quot == 127) t = b1; - Quot++; - s += 8; - } - - // Middle, unclipped tiles - Count = Width - Count; - for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){ - Tile = READ_2BYTES(t); - Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)]; - if (Tile != TileBlank){ - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - (*DrawTilePtr) (Tile, s, VirtAlign, Lines); - } - - t += Quot & 1; - if (Quot == 63) t = b2; else if (Quot == 127) t = b1; - } - - // Right-hand edge clipped tiles - if (Count){ - Tile = READ_2BYTES(t); - Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)]; - if (Tile != TileBlank){ - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines); - } - } - } - } - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; -} - -inline void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ -//StartAnalyze(); - - BG.TileSize = BGSizes [PPU.BG[bg].BGSize]; - BG.BitShift = BitShifts[BGMode][bg]; - BG.TileShift = TileShifts[BGMode][bg]; - BG.TileAddress = PPU.BG[bg].NameBase << 1; - BG.NameSelect = 0; - BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]]; - BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]]; - BG.PaletteShift = PaletteShifts[BGMode][bg]; - BG.PaletteMask = PaletteMasks[BGMode][bg]; - BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 && - (GFX.r2130 & 1); - - if ( DrawTilePtr == DrawTile16_OBJ ){ - DrawTilePtr = DrawTile16; - } - - if (PPU.BGMosaic [bg] && PPU.Mosaic > 1){ - DrawBackgroundMosaic (BGMode, bg, Z1, Z2); - return; - - } - switch (BGMode) - { - case 2: - case 4: // Used by Puzzle Bobble - DrawBackgroundOffset (BGMode, bg, Z1, Z2); - return; - - case 5: - case 6: // XXX: is also offset per tile. - DrawBackgroundMode5 (BGMode, bg, Z1, Z2); - return; - } - CHECK_SOUND(); - - if (BGMode == 0) - BG.StartPalette = bg << 5; - else BG.StartPalette = 0; - - if (BG.TileSize == 8){ - DrawBackground_8 (BGMode, bg, Z1, Z2); - } else { - DrawBackground_16 (BGMode, bg, Z1, Z2); - } -} - -#define RENDER_BACKGROUND_MODE7(FUNC) \ - CHECK_SOUND(); \ -\ - uint8 *VRAM1 = Memory.VRAM + 1; \ - if (GFX.r2130 & 1) \ - { \ - if (IPPU.DirectColourMapsNeedRebuild) \ - S9xBuildDirectColourMaps (); \ - GFX.ScreenColors = DirectColourMaps [0]; \ - } \ - else \ - GFX.ScreenColors = IPPU.ScreenColors; \ -\ - int aa, cc; \ - int dir; \ - int startx, endx; \ - uint32 Left = 0; \ - uint32 Right = 256; \ - uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \ -\ - if (!ClipCount) \ - ClipCount = 1; \ -\ - Screen += GFX.StartY * GFX_PITCH; \ - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \ -\ - for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, l++) \ - { \ - int yy; \ -\ - int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \ - int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \ -\ - int32 CentreX = ((int32) l->CentreX << M7) >> M7; \ - int32 CentreY = ((int32) l->CentreY << M7) >> M7; \ -\ - if (PPU.Mode7VFlip) \ - yy = 255 - (int) Line; \ - else \ - yy = Line; \ -\ - if (PPU.Mode7Repeat == 0) \ - yy += (VOffset - CentreY) % 1023; \ - else \ - yy += VOffset - CentreY; \ - int BB = l->MatrixB * yy + (CentreX << 8); \ - int DD = l->MatrixD * yy + (CentreY << 8); \ -\ - for (uint32 clip = 0; clip < ClipCount; clip++) \ - { \ - if (GFX.pCurrentClip->Count [bg]) \ - { \ - Left = GFX.pCurrentClip->Left [clip][bg]; \ - Right = GFX.pCurrentClip->Right [clip][bg]; \ - if (Right <= Left) \ - continue; \ - } \ - uint16 *p = (uint16 *) Screen + Left; \ -\ - if (PPU.Mode7HFlip) \ - { \ - startx = Right - 1; \ - endx = Left - 1; \ - dir = -1; \ - aa = -l->MatrixA; \ - cc = -l->MatrixC; \ - } \ - else \ - { \ - startx = Left; \ - endx = Right; \ - dir = 1; \ - aa = l->MatrixA; \ - cc = l->MatrixC; \ - } \ - int xx; \ - if (PPU.Mode7Repeat == 0) \ - xx = startx + (HOffset - CentreX) % 1023; \ - else \ - xx = startx + HOffset - CentreX; \ - int AA = l->MatrixA * xx; \ - int CC = l->MatrixC * xx; \ -\ - if (!PPU.Mode7Repeat) \ - { \ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++) \ - { \ - register int X = ((AA + BB) >> 8) & 0x3ff; \ - register int Y = ((CC + DD) >> 8) & 0x3ff; \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - if (b) \ - { \ - *p = (FUNC); \ - } \ - } \ - } \ - else \ - { \ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++) \ - { \ - int X = ((AA + BB) >> 8); \ - int Y = ((CC + DD) >> 8); \ -\ - if (Settings.Dezaemon && PPU.Mode7Repeat == 2) \ - { \ - X &= 0x7ff; \ - Y &= 0x7ff; \ - } \ -\ - if (((X | Y) & ~0x3ff) == 0) \ - { \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - if (b) \ - { \ - *p = (FUNC); \ - } \ - } \ - else \ - { \ - if (PPU.Mode7Repeat == 3) \ - { \ - X = (x + HOffset) & 7; \ - Y = (yy + CentreY) & 7; \ - uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ - if (b ) \ - { \ - *p = (FUNC); \ - } \ - } \ - } \ - } \ - } \ - } \ - } - -#define RENDER_BACKGROUND_MODE7ADDSUB(DEPTH, FUNC) \ - CHECK_SOUND(); \ -\ - uint8 *VRAM1 = Memory.VRAM + 1; \ - if (GFX.r2130 & 1) \ - { \ - if (IPPU.DirectColourMapsNeedRebuild) \ - S9xBuildDirectColourMaps (); \ - GFX.ScreenColors = DirectColourMaps [0]; \ - } \ - else \ - GFX.ScreenColors = IPPU.ScreenColors; \ -\ - int aa, cc; \ - int dir; \ - int startx, endx; \ - uint32 Left = 0; \ - uint32 Right = 256; \ - uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \ -\ - if (!ClipCount) \ - ClipCount = 1; \ -\ - Screen += GFX.StartY * GFX_PITCH; \ - uint8 *Depth = GFX.DB + GFX.StartY * GFX_PPL; \ - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \ -\ - for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) \ - { \ - int yy; \ -\ - int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \ - int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \ -\ - int32 CentreX = ((int32) l->CentreX << M7) >> M7; \ - int32 CentreY = ((int32) l->CentreY << M7) >> M7; \ -\ - if (PPU.Mode7VFlip) \ - yy = 255 - (int) Line; \ - else \ - yy = Line; \ -\ - if (PPU.Mode7Repeat == 0) \ - yy += (VOffset - CentreY) % 1023; \ - else \ - yy += VOffset - CentreY; \ - int BB = l->MatrixB * yy + (CentreX << 8); \ - int DD = l->MatrixD * yy + (CentreY << 8); \ -\ - for (uint32 clip = 0; clip < ClipCount; clip++) \ - { \ - if (GFX.pCurrentClip->Count [bg]) \ - { \ - Left = GFX.pCurrentClip->Left [clip][bg]; \ - Right = GFX.pCurrentClip->Right [clip][bg]; \ - if (Right <= Left) \ - continue; \ - } \ - uint16 *p = (uint16 *) Screen + Left; \ - uint8 *d = Depth + Left; \ -\ - if (PPU.Mode7HFlip) \ - { \ - startx = Right - 1; \ - endx = Left - 1; \ - dir = -1; \ - aa = -l->MatrixA; \ - cc = -l->MatrixC; \ - } \ - else \ - { \ - startx = Left; \ - endx = Right; \ - dir = 1; \ - aa = l->MatrixA; \ - cc = l->MatrixC; \ - } \ - int xx; \ - if (PPU.Mode7Repeat == 0) \ - xx = startx + (HOffset - CentreX) % 1023; \ - else \ - xx = startx + HOffset - CentreX; \ - int AA = l->MatrixA * xx; \ - int CC = l->MatrixC * xx; \ -\ - if (!PPU.Mode7Repeat) \ - { \ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ - { \ - int X = ((AA + BB) >> 8) & 0x3ff; \ - int Y = ((CC + DD) >> 8) & 0x3ff; \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - if (DEPTH > *d && (b) ) \ - { \ - *p = (FUNC); \ - *d = DEPTH; \ - } \ - } \ - } \ - else \ - { \ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ - { \ - int X = ((AA + BB) >> 8); \ - int Y = ((CC + DD) >> 8); \ -\ - if (Settings.Dezaemon && PPU.Mode7Repeat == 2) \ - { \ - X &= 0x7ff; \ - Y &= 0x7ff; \ - } \ -\ - if (((X | Y) & ~0x3ff) == 0) \ - { \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - if (DEPTH > *d && (b) ) \ - { \ - *p = (FUNC); \ - *d = DEPTH; \ - } \ - } \ - else \ - { \ - if (PPU.Mode7Repeat == 3) \ - { \ - X = (x + HOffset) & 7; \ - Y = (yy + CentreY) & 7; \ - uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ - if (DEPTH > *d && (b) ) \ - { \ - *p = (FUNC); \ - *d = DEPTH; \ - } \ - } \ - } \ - } \ - } \ - } \ - } - -#define RENDER_BACKGROUND_MODE7PRIO(FUNC) \ - CHECK_SOUND(); \ -\ - uint8 *VRAM1 = Memory.VRAM + 1; \ - if (GFX.r2130 & 1) \ - { \ - if (IPPU.DirectColourMapsNeedRebuild) \ - S9xBuildDirectColourMaps (); \ - GFX.ScreenColors = DirectColourMaps [0]; \ - } \ - else \ - GFX.ScreenColors = IPPU.ScreenColors; \ -\ - int aa, cc; \ - int dir; \ - int startx, endx; \ - uint32 Left = 0; \ - uint32 Right = 256; \ - uint32 ClipCount = GFX.pCurrentClip->Count [bg]; \ -\ - if (!ClipCount) \ - ClipCount = 1; \ -\ - Screen += GFX.StartY * GFX_PITCH; \ - uint8 *Depth = GFX.DB + GFX.StartY * GFX_PPL; \ - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; \ -\ - for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) \ - { \ - int yy; \ -\ - int32 HOffset = ((int32) LineData [Line].BG[0].HOffset << M7) >> M7; \ - int32 VOffset = ((int32) LineData [Line].BG[0].VOffset << M7) >> M7; \ -\ - int32 CentreX = ((int32) l->CentreX << M7) >> M7; \ - int32 CentreY = ((int32) l->CentreY << M7) >> M7; \ -\ - if (PPU.Mode7VFlip) \ - yy = 255 - (int) Line; \ - else \ - yy = Line; \ -\ - if (PPU.Mode7Repeat == 0) \ - yy += (VOffset - CentreY) % 1023; \ - else \ - yy += VOffset - CentreY; \ - int BB = l->MatrixB * yy + (CentreX << 8); \ - int DD = l->MatrixD * yy + (CentreY << 8); \ -\ - for (uint32 clip = 0; clip < ClipCount; clip++) \ - { \ - if (GFX.pCurrentClip->Count [bg]) \ - { \ - Left = GFX.pCurrentClip->Left [clip][bg]; \ - Right = GFX.pCurrentClip->Right [clip][bg]; \ - if (Right <= Left) \ - continue; \ - } \ - uint16 *p = (uint16 *) Screen + Left; \ - uint8 *d = Depth + Left; \ -\ - if (PPU.Mode7HFlip) \ - { \ - startx = Right - 1; \ - endx = Left - 1; \ - dir = -1; \ - aa = -l->MatrixA; \ - cc = -l->MatrixC; \ - } \ - else \ - { \ - startx = Left; \ - endx = Right; \ - dir = 1; \ - aa = l->MatrixA; \ - cc = l->MatrixC; \ - } \ - int xx; \ - if (PPU.Mode7Repeat == 0) \ - xx = startx + (HOffset - CentreX) % 1023; \ - else \ - xx = startx + HOffset - CentreX; \ - int AA = l->MatrixA * xx; \ - int CC = l->MatrixC * xx; \ -\ - if (!PPU.Mode7Repeat) \ - { \ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ - { \ - int X = ((AA + BB) >> 8) & 0x3ff; \ - int Y = ((CC + DD) >> 8) & 0x3ff; \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & 0x80) >> 7]; \ - if (GFX.Z1 > *d && (b & 0x7f) ) \ - { \ - *p = (FUNC); \ - *d = GFX.Z1; \ - } \ - } \ - } \ - else \ - { \ - for (int x = startx; x != endx; x += dir, AA += aa, CC += cc, p++, d++) \ - { \ - int X = ((AA + BB) >> 8); \ - int Y = ((CC + DD) >> 8); \ -\ - if (Settings.Dezaemon && PPU.Mode7Repeat == 2) \ - { \ - X &= 0x7ff; \ - Y &= 0x7ff; \ - } \ -\ - if (((X | Y) & ~0x3ff) == 0) \ - { \ - uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ - uint32 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & 0x80) >> 7]; \ - if (GFX.Z1 > *d && (b & 0x7f) ) \ - { \ - *p = (FUNC); \ - *d = GFX.Z1; \ - } \ - } \ - else \ - { \ - if (PPU.Mode7Repeat == 3) \ - { \ - X = (x + HOffset) & 7; \ - Y = (yy + CentreY) & 7; \ - uint32 b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ - GFX.Z1 = Mode7Depths [(b & 0x80) >> 7]; \ - if (GFX.Z1 > *d && (b & 0x7f) ) \ - { \ - *p = (FUNC); \ - *d = GFX.Z1; \ - } \ - } \ - } \ - } \ - } \ - } \ - } - -void DrawBGMode7Background16New (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7 (GFX.ScreenColors [b & 0xff]); -} - -void DrawBGMode7Background16 (uint8 *Screen, int bg, int depth) -{ - RENDER_BACKGROUND_MODE7ADDSUB (depth, GFX.ScreenColors [b & 0xff]); -} - -void DrawBGMode7Background16Add (uint8 *Screen, int bg, int depth) -{ - RENDER_BACKGROUND_MODE7ADDSUB (depth, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_ADD (GFX.ScreenColors [b & 0xff], - p [GFX.Delta]) : - COLOR_ADD (GFX.ScreenColors [b & 0xff], - GFX.FixedColour)) : - GFX.ScreenColors [b & 0xff]); - -} - -void DrawBGMode7Background16Add1_2 (uint8 *Screen, int bg, int depth) -{ - RENDER_BACKGROUND_MODE7ADDSUB (depth, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_ADD1_2 (GFX.ScreenColors [b & 0xff], - p [GFX.Delta]) : - COLOR_ADD (GFX.ScreenColors [b & 0xff], - GFX.FixedColour)) : - GFX.ScreenColors [b & 0xff]); -} - -void DrawBGMode7Background16Sub (uint8 *Screen, int bg, int depth) -{ - RENDER_BACKGROUND_MODE7ADDSUB (depth, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB (GFX.ScreenColors [b & 0xff], - p [GFX.Delta]) : - COLOR_SUB (GFX.ScreenColors [b & 0xff], - GFX.FixedColour)) : - GFX.ScreenColors [b & 0xff]); -} - -void DrawBGMode7Background16Sub1_2 (uint8 *Screen, int bg, int depth) -{ - RENDER_BACKGROUND_MODE7ADDSUB (depth, *(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB1_2 (GFX.ScreenColors [b & 0xff], - p [GFX.Delta]) : - COLOR_SUB (GFX.ScreenColors [b & 0xff], - GFX.FixedColour)) : - GFX.ScreenColors [b & 0xff]); -} - -void DrawBGMode7Background16Prio (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7PRIO (GFX.ScreenColors [b & 0x7f]); -} - -void DrawBGMode7Background16AddPrio (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7PRIO (*(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_ADD (GFX.ScreenColors [b & 0x7f], - p [GFX.Delta]) : - COLOR_ADD (GFX.ScreenColors [b & 0x7f], - GFX.FixedColour)) : - GFX.ScreenColors [b & 0x7f]); -} - -void DrawBGMode7Background16Add1_2Prio (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7PRIO (*(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_ADD1_2 (GFX.ScreenColors [b & 0x7f], - p [GFX.Delta]) : - COLOR_ADD (GFX.ScreenColors [b & 0x7f], - GFX.FixedColour)) : - GFX.ScreenColors [b & 0x7f]); -} - -void DrawBGMode7Background16SubPrio (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7PRIO (*(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB (GFX.ScreenColors [b & 0x7f], - p [GFX.Delta]) : - COLOR_SUB (GFX.ScreenColors [b & 0x7f], - GFX.FixedColour)) : - GFX.ScreenColors [b & 0x7f]); -} - -void DrawBGMode7Background16Sub1_2Prio (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7PRIO (*(d + GFX.DepthDelta) ? - (*(d + GFX.DepthDelta) != 1 ? - COLOR_SUB1_2 (GFX.ScreenColors [b & 0x7f], - p [GFX.Delta]) : - COLOR_SUB (GFX.ScreenColors [b & 0x7f], - GFX.FixedColour)) : - GFX.ScreenColors [b & 0x7f]); -} - -#define _BUILD_SETUP(F) \ -GFX.BuildPixel = BuildPixel##F; \ -GFX.BuildPixel2 = BuildPixel2##F; \ -GFX.DecomposePixel = DecomposePixel##F; \ -RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_##F; \ -GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_##F; \ -BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_##F; \ -RED_HI_BIT_MASK = RED_HI_BIT_MASK_##F; \ -GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_##F; \ -BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_##F; \ -MAX_RED = MAX_RED_##F; \ -MAX_GREEN = MAX_GREEN_##F; \ -MAX_BLUE = MAX_BLUE_##F; \ -GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \ -SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \ -RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_##F | \ - GREEN_LOW_BIT_MASK_##F | \ - BLUE_LOW_BIT_MASK_##F); \ -RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_##F | \ - GREEN_HI_BIT_MASK_##F | \ - BLUE_HI_BIT_MASK_##F); \ -RGB_HI_BITS_MASKx2 = ((RED_HI_BIT_MASK_##F | \ - GREEN_HI_BIT_MASK_##F | \ - BLUE_HI_BIT_MASK_##F) << 1); \ -RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; \ -FIRST_COLOR_MASK = FIRST_COLOR_MASK_##F; \ -SECOND_COLOR_MASK = SECOND_COLOR_MASK_##F; \ -THIRD_COLOR_MASK = THIRD_COLOR_MASK_##F; \ -ALPHA_BITS_MASK = ALPHA_BITS_MASK_##F; \ -FIRST_THIRD_COLOR_MASK = FIRST_COLOR_MASK | THIRD_COLOR_MASK; \ -TWO_LOW_BITS_MASK = RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1); \ -HIGH_BITS_SHIFTED_TWO_MASK = (( (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & \ - ~TWO_LOW_BITS_MASK ) >> 2); - -void RenderScreen (uint8 *Screen, bool8_32 sub, bool8_32 force_no_add, uint8 D) -{ - bool8_32 BG0; - bool8_32 BG1; - bool8_32 BG2; - bool8_32 BG3; - bool8_32 OB; - - GFX.S = Screen; - - if (!sub) - { - GFX.pCurrentClip = &IPPU.Clip [0]; - BG0 = ON_MAIN (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0); - BG1 = ON_MAIN (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1); - BG2 = ON_MAIN (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2); - BG3 = ON_MAIN (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3); - OB = ON_MAIN (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); - } - else - { - GFX.pCurrentClip = &IPPU.Clip [1]; - BG0 = ON_SUB (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0); - BG1 = ON_SUB (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1); - BG2 = ON_SUB (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2); - BG3 = ON_SUB (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3); - OB = ON_SUB (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); - } - - sub |= force_no_add; - - if (PPU.BGMode <= 1) - { - if (OB) - { - SelectTileRenderer (sub || !SUB_OR_ADD(4)); - DrawOBJS (!sub, D); - } - if (BG0) - { - SelectTileRenderer (sub || !SUB_OR_ADD(0)); - DrawBackground (PPU.BGMode, 0, D + 10, D + 14); - } - if (BG1) - { - SelectTileRenderer (sub || !SUB_OR_ADD(1)); - DrawBackground (PPU.BGMode, 1, D + 9, D + 13); - } - if (BG2) - { - SelectTileRenderer (sub || !SUB_OR_ADD(2)); - DrawBackground (PPU.BGMode, 2, D + 3, - PPU.BG3Priority ? D + 17 : D + 6); - } - if (BG3 && PPU.BGMode == 0) - { - SelectTileRenderer (sub || !SUB_OR_ADD(3)); - DrawBackground (PPU.BGMode, 3, D + 2, D + 5); - } - } - else if (PPU.BGMode != 7) - { - if (OB) - { - SelectTileRenderer (sub || !SUB_OR_ADD(4)); - DrawOBJS (!sub, D); - } - if (BG0) - { - SelectTileRenderer (sub || !SUB_OR_ADD(0)); - DrawBackground (PPU.BGMode, 0, D + 5, D + 13); - } - if (PPU.BGMode != 6 && BG1) - { - SelectTileRenderer (sub || !SUB_OR_ADD(1)); - DrawBackground (PPU.BGMode, 1, D + 2, D + 9); - } - } - else - { - if (OB && ((SNESGameFixes.Mode7Hack && D) || !SNESGameFixes.Mode7Hack)) - { - SelectTileRenderer (sub || !SUB_OR_ADD(4)); - DrawOBJS (!sub, D); - } - if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1)) - { - int bg; - - if ((Memory.FillRAM [0x2133] & 0x40)&&BG1) - { - Mode7Depths [0] = (BG0?5:1) + D; - Mode7Depths [1] = 9 + D; - bg = 1; - if (sub || !SUB_OR_ADD(0)) - { - DrawBGMode7Background16Prio (Screen, bg); - } - else - { - if (GFX.r2131 & 0x80) - { - if (GFX.r2131 & 0x40) - { - DrawBGMode7Background16Sub1_2Prio (Screen, bg); - } - else - { - DrawBGMode7Background16SubPrio (Screen, bg); - } - } - else - { - if (GFX.r2131 & 0x40) - { - DrawBGMode7Background16Add1_2Prio (Screen, bg); - } - else - { - DrawBGMode7Background16AddPrio (Screen, bg); - } - } - } - } - else - { - bg = 0; - if (sub || !SUB_OR_ADD(0)) - { - if (D || !SNESGameFixes.Mode7Hack) - DrawBGMode7Background16 (Screen, bg, D+5); - else - DrawBGMode7Background16New (Screen, bg); - } - else - { - if (GFX.r2131 & 0x80) - { - if (GFX.r2131 & 0x40) - { - DrawBGMode7Background16Sub1_2 (Screen, bg, D+5); - } - else - { - DrawBGMode7Background16Sub (Screen, bg, D+5); - } - } - else - { - if (GFX.r2131 & 0x40) - { - DrawBGMode7Background16Add1_2 (Screen, bg, D+5); - } - else - { - DrawBGMode7Background16Add (Screen, bg, D+5); - } - } - } - } - } - if (OB && SNESGameFixes.Mode7Hack && D==0) - { - SelectTileRenderer (sub || !SUB_OR_ADD(4)); - DrawOBJS (!sub, D); - } - - } -} - -#include "font.h" - -void DisplayChar (uint8 *Screen, uint8 c) -{ - int line = (((c & 0x7f) - 32) >> 4) * font_height; - int offset = (((c & 0x7f) - 32) & 15) * font_width; - int h, w; - uint16 *s = (uint16 *) Screen; - for (h = 0; h < font_height; h++, line++, - s += GFX_PPL - font_width) - { - for (w = 0; w < font_width; w++, s++) - { - uint8 p = font [line][offset + w]; - - if (p == '#') - *s = 0xffff; - else - if (p == '.') - *s = BLACK; - } - } -} - -static void S9xDisplayFrameRate () -{ - uint8 *Screen = GFX.Screen + 2 + - (IPPU.RenderedScreenHeight - font_height - 1) * GFX_PITCH; - char string [10]; - int len = 5; - - sprintf (string, "%02d/%02d", IPPU.DisplayedRenderedFrameCount, - (int) Memory.ROMFramesPerSecond); - - int i; - for (i = 0; i < len; i++) - { - DisplayChar (Screen, string [i]); - Screen += (font_width - 1) * sizeof (uint16); - } -} - -static void S9xDisplayString (const char *string) -{ - uint8 *Screen = GFX.Screen + 2 + - (IPPU.RenderedScreenHeight - font_height * 5) * GFX_PITCH; - int len = strlen (string); - int max_chars = IPPU.RenderedScreenWidth / (font_width - 1); - int char_count = 0; - int i; - - for (i = 0; i < len; i++, char_count++) - { - if (char_count >= max_chars || string [i] < 32) - { - Screen -= (font_width - 1) * sizeof (uint16) * max_chars; - Screen += font_height * GFX_PITCH; - if (Screen >= GFX.Screen + GFX_PITCH * IPPU.RenderedScreenHeight) - break; - char_count -= max_chars; - } - if (string [i] < 32) - continue; - DisplayChar (Screen, string [i]); - Screen += (font_width - 1) * sizeof (uint16); - } -} - -void S9xUpdateScreen () // ~30-50ms! (called from FLUSH_REDRAW()) -{ - int32 x2 = 1; - - GFX.S = GFX.Screen; - - unsigned char *memoryfillram = Memory.FillRAM; - - // get local copies of vid registers to be used later - GFX.r2131 = memoryfillram [0x2131]; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN - GFX.r212c = memoryfillram [0x212c]; // MAIN SCREEN, DESIGNATION - used to enable BGS - GFX.r212d = memoryfillram [0x212d]; // SUB SCREEN DESIGNATION - used to enable sub BGS - GFX.r2130 = memoryfillram [0x2130]; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION - - // If external sync is off and - // main screens have not been configured the same as the sub screen and - // color addition and subtraction has been diabled then - // Pseudo is 1 - // anything else it is 0 - GFX.Pseudo = (memoryfillram [0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION? - (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens? - (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS? - - // If sprite data has been changed then go through and - // refresh the sprites. - if (IPPU.OBJChanged) - { - S9xSetupOBJ (); - } - - if (PPU.RecomputeClipWindows) - { - ComputeClipWindows (); - PPU.RecomputeClipWindows = FALSE; - } - - GFX.StartY = IPPU.PreviousLine; - if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) - GFX.EndY = PPU.ScreenHeight - 1; - - uint32 starty = GFX.StartY; - uint32 endy = GFX.EndY; - - if (Settings.SupportHiRes && - (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.LatchedInterlace)) - { - if (PPU.BGMode == 5 || PPU.BGMode == 6) - { - IPPU.RenderedScreenWidth = 512; - x2 = 2; - } - if (IPPU.LatchedInterlace) - { - starty = GFX.StartY * 2; - endy = GFX.EndY * 2 + 1; - } - if (!IPPU.DoubleWidthPixels) - { - // The game has switched from lo-res to hi-res mode part way down - // the screen. Scale any existing lo-res pixels on screen - for (register uint32 y = 0; y < GFX.StartY; y++) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + 255; - register uint16 *q = (uint16 *) (GFX.Screen + y * GFX_PITCH) + 510; - for (register int x = 255; x >= 0; x--, p--, q -= 2) - *q = *(q + 1) = *p; - } - IPPU.DoubleWidthPixels = TRUE; - } - } - - uint32 black = BLACK | (BLACK << 16); - - // Are we worrying about transparencies? - if (Settings.Transparency) - { - if (GFX.Pseudo) - { - GFX.r2131 = 0x5f; //0101 1111 - enable addition/subtraction on all BGS and sprites and "1/2 OF COLOR DATA" DESIGNATION - GFX.r212c &= (Memory.FillRAM [0x212d] | 0xf0); - GFX.r212d |= (Memory.FillRAM [0x212c] & 0x0f); - GFX.r2130 |= 2; // enable ADDITION/SUBTRACTION FOR SUB SCREEN - } - - // Check to see if any transparency effects are currently in use - if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING && - (GFX.r2130 & 0x30) != 0x30 && - !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0)) - { - // transparency effects in use, so lets get busy! - struct ClipData *pClip; - uint32 fixedColour; - GFX.FixedColour = BUILD_PIXEL (IPPU.XB [PPU.FixedColourRed], - IPPU.XB [PPU.FixedColourGreen], - IPPU.XB [PPU.FixedColourBlue]); - fixedColour = (GFX.FixedColour<<16|GFX.FixedColour); - // Clear the z-buffer, marking areas 'covered' by the fixed - // colour as depth 1. - pClip = &IPPU.Clip [1]; - - // Clear the z-buffer - - if (pClip->Count [5]) - { - - // Colour window enabled. - -#ifdef RC_OPTIMIZED - for (uint32 y = starty; y <= endy; y++) - { - - ZeroMemory (GFX.SubZBuffer + y * GFX_ZPITCH, - IPPU.RenderedScreenWidth); - ZeroMemory (GFX.ZBuffer + y * GFX_ZPITCH, - IPPU.RenderedScreenWidth); - - if (IPPU.Clip [0].Count [5]) - { - memset ((GFX.SubScreen + y * GFX_PITCH), black, IPPU.RenderedScreenWidth); - } - for (uint32 c = 0; c < pClip->Count [5]; c++) - { - if (pClip->Right [c][5] > pClip->Left [c][5]) - { - memset (GFX.SubZBuffer + y * GFX_ZPITCH + pClip->Left [c][5] * x2, - 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2); - if (IPPU.Clip [0].Count [5]) - { - // Blast, have to clear the sub-screen to the fixed-colour - // because there is a colour window in effect clipping - // the main screen that will allow the sub-screen - // 'underneath' to show through. - memset ((GFX.SubScreen + y * GFX_PITCH) + pClip->Left [c][5] * x2, - GFX.FixedColour, - pClip->Right[c][5]*x2 - pClip->Left [c][5] * x2); - } - } - } - } - -#else // NOT RC_OPTIMIZED - // loop around all of the lines being updated - for (uint32 y = starty; y <= endy; y++) - { - // Clear the subZbuffer - memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH),0, - IPPU.RenderedScreenWidth>>2); - // Clear the Zbuffer - memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, - IPPU.RenderedScreenWidth>>2); - - // if there is clipping then clear subscreen to a black color - if (IPPU.Clip [0].Count [5]) - { - memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), black, IPPU.RenderedScreenWidth>>1); - } - - // loop through all window clippings - for (uint32 c = 0; c < pClip->Count [5]; c++) - { - if (pClip->Right [c][5] > pClip->Left [c][5]) - { - memset (GFX.SubZBuffer + y * GFX_ZPITCH + pClip->Left [c][5] * x2, - 1, (pClip->Right [c][5] - pClip->Left [c][5]) * x2); - if (IPPU.Clip [0].Count [5]) - { - // Blast, have to clear the sub-screen to the fixed-colour - // because there is a colour window in effect clipping - // the main screen that will allow the sub-screen - // 'underneath' to show through. - - register uint16 *p = (uint16 *) (GFX.SubScreen + y * GFX_PITCH); - register uint16 *q = p + pClip->Right [c][5] * x2; - p += pClip->Left [c][5] * x2; - - while (p < q) - *p++ = (uint16) GFX.FixedColour; - } - } - } - } -#endif -//#undef RC_OPTIMIZED - - } - else - { - // No windows are clipping the main screen - // this simplifies the screen clearing process -#ifdef RC_OPTIMIZED - - if (GFX_ZPITCH == (uint32)IPPU.RenderedScreenWidth) - { - - memset (GFX.ZBuffer + starty * GFX_ZPITCH, 0, GFX_ZPITCH * (endy - starty - 1)); - memset (GFX.SubZBuffer + starty * GFX_ZPITCH, 1, GFX_ZPITCH * (endy - starty - 1)); - } - else - { - for (uint32 y = starty; y <= endy; y++) - { - ZeroMemory (GFX.ZBuffer + y * GFX_ZPITCH, - IPPU.RenderedScreenWidth); - memset (GFX.SubZBuffer + y * GFX_ZPITCH, 1, - IPPU.RenderedScreenWidth); - } - } - - if (IPPU.Clip [0].Count [5]) - { - // Blast, have to clear the sub-screen to the fixed-colour - // because there is a colour window in effect clipping - // the main screen that will allow the sub-screen - // 'underneath' to show through. - if (GFX_PITCH == (uint32)IPPU.RenderedScreenWidth) - { - memset ((GFX.SubScreen + starty * GFX_PITCH), - GFX.FixedColour | (GFX.FixedColour << 16), - GFX_PITCH * (endy - starty - 1)); - } - else - { - for (uint32 y = starty; y <= endy; y++) - { - memset ((GFX.SubScreen + y * GFX_PITCH), - GFX.FixedColour | (GFX.FixedColour << 16), - IPPU.RenderedScreenWidth); - } - } - } - -#else // NOT RC_OPTIMIZED - // loop through all of the lines to be updated - for (uint32 y = starty; y <= endy; y++) - { - // Clear the Zbuffer - memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, - IPPU.RenderedScreenWidth>>2); - // clear the sub Zbuffer to 1 - memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH), 0x01010101, - IPPU.RenderedScreenWidth>>2); - if (IPPU.Clip [0].Count [5]) - { - // Blast, have to clear the sub-screen to the fixed-colour - // because there is a colour window in effect clipping - // the main screen that will allow the sub-screen - // 'underneath' to show through. - - - memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), fixedColour, - IPPU.RenderedScreenWidth>>1); - } - } -#endif - - } - - if (ANYTHING_ON_SUB) - { - GFX.DB = GFX.SubZBuffer; - RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH); - } - - if (IPPU.Clip [0].Count [5]) - { - for (uint32 y = starty; y <= endy; y++) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH); - register uint8 *d = GFX.SubZBuffer + y * GFX_ZPITCH ; - register uint8 *e = d + IPPU.RenderedScreenWidth; - - while (d < e) - { - if (*d > 1) - *p = *(p + GFX.Delta); - else - *p = BLACK; - d++; - p++; - } - } - } - - GFX.DB = GFX.ZBuffer; - RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH); - if (SUB_OR_ADD(5)) - { - uint32 back = IPPU.ScreenColors [0]; - uint32 Left = 0; - uint32 Right = 256; - uint32 Count; - - pClip = &IPPU.Clip [0]; - - for (uint32 y = starty; y <= endy; y++) - { - if (!(Count = pClip->Count [5])) - { - Left = 0; - Right = 256 * x2; - Count = 1; - } - - for (uint32 b = 0; b < Count; b++) - { - if (pClip->Count [5]) - { - Left = pClip->Left [b][5] * x2; - Right = pClip->Right [b][5] * x2; - if (Right <= Left) - continue; - } - - if (GFX.r2131 & 0x80) - { - if (GFX.r2131 & 0x40) - { - // Subtract, halving the result. - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; - register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; - register uint8 *s = GFX.SubZBuffer + y * GFX_ZPITCH + Left; - register uint8 *e = d + Right; - uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour); - - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = COLOR_SUB1_2 (back, *(p + GFX.Delta)); - else - *p = back_fixed; - } - else - *p = (uint16) back; - } - d++; - p++; - s++; - } - } - else - { - // Subtract - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; - register uint8 *s = GFX.SubZBuffer + y * GFX_ZPITCH + Left; - register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; - register uint8 *e = d + Right; - uint16 back_fixed = COLOR_SUB (back, GFX.FixedColour); - - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = COLOR_SUB (back, *(p + GFX.Delta)); - else - *p = back_fixed; - } - else - *p = (uint16) back; - } - d++; - p++; - s++; - } - } - } - else - if (GFX.r2131 & 0x40) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; - register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; - register uint8 *s = GFX.SubZBuffer + y * GFX_ZPITCH + Left; - register uint8 *e = d + Right; - uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour); - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = COLOR_ADD1_2 (back, *(p + GFX.Delta)); - else - *p = back_fixed; - } - else - *p = (uint16) back; - } - d++; - p++; - s++; - } - } - else - if (back != 0) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; - register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; - register uint8 *s = GFX.SubZBuffer + y * GFX_ZPITCH + Left; - register uint8 *e = d + Right; - uint16 back_fixed = COLOR_ADD (back, GFX.FixedColour); - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = COLOR_ADD (back, *(p + GFX.Delta)); - else - *p = back_fixed; - } - else - *p = (uint16) back; - } - d++; - p++; - s++; - } - } - else - { - if (!pClip->Count [5]) - { - // The backdrop has not been cleared yet - so - // copy the sub-screen to the main screen - // or fill it with the back-drop colour if the - // sub-screen is clear. - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; - register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; - register uint8 *s = GFX.SubZBuffer + y * GFX_ZPITCH + Left; - register uint8 *e = d + Right; - d += Left; - while (d < e) - { - if (*d == 0) - { - if (*s) - { - if (*s != 1) - *p = *(p + GFX.Delta); - else - *p = GFX.FixedColour; - } - else - *p = (uint16) back; - } - d++; - p++; - s++; - } - } - } - } - } - - } - else - { - // Subscreen not being added to back - uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); - pClip = &IPPU.Clip [0]; - - if (pClip->Count [5]) - { - for (uint32 y = starty; y <= endy; y++) - { - for (uint32 b = 0; b < pClip->Count [5]; b++) - { - uint32 Left = pClip->Left [b][5] * x2; - uint32 Right = pClip->Right [b][5] * x2; - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + Left; - register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; - register uint8 *e = d + Right; - d += Left; - - while (d < e) - { - if (*d++ == 0) - *p = (int16) back; - p++; - } - } - } - } - else - { - for (uint32 y = starty; y <= endy; y++) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH); - register uint8 *d = GFX.ZBuffer + y * GFX_ZPITCH; - register uint8 *e = d + 256 * x2; - - while (d < e) - { - if (*d == 0) -#ifdef RC_OPTIMIZED - *p++ = back; - d++; -#else - *p = (int16) back; - d++; - p++; -#endif - } - } - } - } - } - else - { - // 16bit and transparency but currently no transparency effects in - // operation. - - // get the back colour of the current screen - uint32 back = IPPU.ScreenColors [0] | - (IPPU.ScreenColors [0] << 16); - - // if forceblanking in use then use black instead of the back color - if (PPU.ForcedBlanking) - back = black; - - // not sure what Clip is used for yet - // could be a check to see if there is any clipping present? - if (IPPU.Clip [0].Count[5]) - { - -#ifdef RC_OPTIMIZED - if (GFX_PITCH == (uint32)IPPU.RenderedScreenWidth) - { - memset (GFX.Screen + starty * GFX_PITCH, black, - GFX_PITCH * (endy - starty - 1)); - } - else - { - for (uint32 y = starty; y <= endy; y++) - { - memset (GFX.Screen + y * GFX_PITCH, black, - GFX_PITCH); - } - } - for (uint32 y = starty; y <= endy; y++) - { - for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++) - { - if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5]) - { - - memset ((GFX.Screen + y * GFX_PITCH) + IPPU.Clip [0].Left [c][5] * x2, - back, - IPPU.Clip [0].Right [c][5] * x2 - IPPU.Clip [0].Left [c][5] * x2); - } - } - } -#else - // loop through all of the lines that are going to be updated as part of this screen update - for (uint32 y = starty; y <= endy; y++) - { - memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), black, - IPPU.RenderedScreenWidth>>1); - - if (black!=back) - { - for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++) - { - if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5]) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH); // get pointer to current line in screen buffer - register uint16 *q = p + IPPU.Clip [0].Right [c][5] * x2; // get pointer to end of line - p += IPPU.Clip [0].Left [c][5] * x2; - - while (p < q) - *p++ = (uint16) back; // fill all pixels in clipped section with the back colour - } - } - } - } -#endif - } - else - { -#ifdef RC_OPTIMIZED - if (GFX_PITCH == (uint32)IPPU.RenderedScreenWidth) - { - memset (GFX.Screen + starty * GFX_PITCH, back, - GFX_PITCH * (endy - starty - 1)); - } - else - { - for (uint32 y = starty; y <= endy; y++) - { - memset (GFX.Screen + y * GFX_PITCH, back, - GFX_PITCH); - } - } -#else - // there is no clipping to worry about so just fill with the back colour - for (uint32 y = starty; y <= endy; y++) - { - memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back, - IPPU.RenderedScreenWidth>>1); - } -#endif - } - - // If Forced blanking is not in effect - if (!PPU.ForcedBlanking) - { -#ifdef RC_OPTIMIZED - if (GFX_ZPITCH == (uint32)IPPU.RenderedScreenWidth) - { - memset (GFX.ZBuffer + starty * GFX_ZPITCH, 0, - GFX_ZPITCH * (endy - starty - 1)); - } - else - { - for (uint32 y = starty; y <= endy; y++) - { - memset (GFX.ZBuffer + y * GFX_ZPITCH, 0, - GFX_ZPITCH); - } - } -#else - // Clear the Zbuffer for each of the lines which are going to be updated - for (uint32 y = starty; y <= endy; y++) - { - memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0, - IPPU.RenderedScreenWidth>>2); - } -#endif - GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object - RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH); - } - } - } - else // Transparencys are disabled, ahh lovely ... nice and easy. - { - // get back colour to be used in clearing the screen - register uint32 back; - if (!(Memory.FillRAM [0x2131] & 0x80) &&(Memory.FillRAM[0x2131] & 0x20) && - (PPU.FixedColourRed || PPU.FixedColourGreen || PPU.FixedColourBlue)) - { - back = (IPPU.XB[PPU.FixedColourRed]<<11) | - (IPPU.XB[PPU.FixedColourGreen] << 6) | - (IPPU.XB[PPU.FixedColourBlue] << 1) | 1; - back = (back << 16) | back; - } - else - { - back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); - } - - // if Forcedblanking in use then back colour becomes black - if (PPU.ForcedBlanking) - back = black; - else - { - SelectTileRenderer (TRUE); //selects the tile renderers to be used - // TRUE means to use the default - // FALSE means use best renderer based on current - // graphics register settings - } - - // now clear all graphics lines which are being updated using the back colour - for (register uint32 y = starty; y <= endy; y++) - { - memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back, - IPPU.RenderedScreenWidth>>1); - } - - if (!PPU.ForcedBlanking) - { - // Loop through all lines being updated and clear the - // zbuffer for each of the lines - for (uint32 y = starty; y <= endy; y++) - { - memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0, - IPPU.RenderedScreenWidth>>2); - } - GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object - GFX.pCurrentClip = &IPPU.Clip [0]; - -// Define an inline function to handle clipping -#define FIXCLIP(n) \ -if (GFX.r212c & (1 << (n))) \ - GFX.pCurrentClip = &IPPU.Clip [0]; \ -else \ - GFX.pCurrentClip = &IPPU.Clip [1] - -// Define an inline function to handle which BGs are being displayed -#define DISPLAY(n) ((GFX.r212c & n) || ((GFX.r212d & n) && subadd)) - - uint8 subadd = GFX.r2131 & 0x3f; - - // go through all BGS are check if they need to be displayed - bool8_32 BG0 = DISPLAY(1) && !(Settings.os9x_hack & GFX_IGNORE_BG0); - bool8_32 BG1 = DISPLAY(2) && !(Settings.os9x_hack & GFX_IGNORE_BG1); - bool8_32 BG2 = DISPLAY(4) && !(Settings.os9x_hack & GFX_IGNORE_BG2); - bool8_32 BG3 = DISPLAY(8) && !(Settings.os9x_hack & GFX_IGNORE_BG3); - bool8_32 OB = DISPLAY(16) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); - - if (PPU.BGMode <= 1) - { - // screen modes 0 and 1 - if (OB) - { - FIXCLIP(4); - DrawOBJS (); - } - if (BG0) - { - FIXCLIP(0); - DrawBackground (PPU.BGMode, 0, 10, 14); - } - if (BG1) - { - FIXCLIP(1); - DrawBackground (PPU.BGMode, 1, 9, 13); - } - if (BG2) - { - FIXCLIP(2); - DrawBackground (PPU.BGMode, 2, 3, - PPU.BG3Priority ? 17 : 6); - } - if (BG3 && PPU.BGMode == 0) - { - FIXCLIP(3); - DrawBackground (PPU.BGMode, 3, 2, 5); - } - } - else if (PPU.BGMode != 7) - { - // screen modes 2 and up but not mode 7 - if (OB) - { - FIXCLIP(4); - DrawOBJS (); - } - if (BG0) - { - FIXCLIP(0); - DrawBackground (PPU.BGMode, 0, 5, 13); - } - if (BG1 && PPU.BGMode != 6) - { - FIXCLIP(1); - DrawBackground (PPU.BGMode, 1, 2, 9); - } - } - else - { - // screen mode 7 - GFX.Mode7Mask = 0xff; - GFX.Mode7PriorityMask = 0; - int bg = 0; - DrawBGMode7Background16New (GFX.Screen, bg); - if (OB) - { - FIXCLIP(4); - DrawOBJS (); - } - } - } - } -#ifndef RC_OPTIMIZE // no hi res - if (Settings.SupportHiRes && PPU.BGMode != 5 && PPU.BGMode != 6) - { - if (IPPU.DoubleWidthPixels) - { - // Mixure of background modes used on screen - scale width - // of all non-mode 5 and 6 pixels. - for (register uint32 y = GFX.StartY; y <= GFX.EndY; y++) - { - register uint16 *p = (uint16 *) (GFX.Screen + y * GFX_PITCH) + 255; - register uint16 *q = (uint16 *) (GFX.Screen + y * GFX_PITCH) + 510; - for (register int x = 255; x >= 0; x--, p--, q -= 2) - *q = *(q + 1) = *p; - } - - } - - if (IPPU.LatchedInterlace) - { - // Interlace is enabled - double the height of all non-mode 5 and 6 - // pixels. - for (uint32 y = GFX.StartY; y <= GFX.EndY; y++) - { - memcpy32 ((uint32_t*)(GFX.Screen + (y * 2 + 1) * GFX_PITCH), - (uint32_t*)(GFX.Screen + y * 2 * GFX_PITCH), - GFX_PITCH>>2); - } - } - } -#endif - IPPU.PreviousLine = IPPU.CurrentLine; -} - -#ifdef GFX_MULTI_FORMAT - -#define _BUILD_PIXEL(F) \ -uint32 BuildPixel##F(uint32 R, uint32 G, uint32 B) \ -{ \ - return (BUILD_PIXEL_##F(R,G,B)); \ -}\ -uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \ -{ \ - return (BUILD_PIXEL2_##F(R,G,B)); \ -} \ -void DecomposePixel##F(uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \ -{ \ - DECOMPOSE_PIXEL_##F(pixel,R,G,B); \ -} - -_BUILD_PIXEL(RGB565) -_BUILD_PIXEL(RGB555) -_BUILD_PIXEL(BGR565) -_BUILD_PIXEL(BGR555) -_BUILD_PIXEL(GBR565) -_BUILD_PIXEL(GBR555) -_BUILD_PIXEL(RGB5551) - -bool8_32 S9xSetRenderPixelFormat (int format) -{ - extern uint32 current_graphic_format; - - current_graphic_format = format; - - switch (format) - { - case RGB565: - _BUILD_SETUP(RGB565) - return (TRUE); - case RGB555: - _BUILD_SETUP(RGB555) - return (TRUE); - case BGR565: - _BUILD_SETUP(BGR565) - return (TRUE); - case BGR555: - _BUILD_SETUP(BGR555) - return (TRUE); - case GBR565: - _BUILD_SETUP(GBR565) - return (TRUE); - case GBR555: - _BUILD_SETUP(GBR555) - return (TRUE); - case RGB5551: - _BUILD_SETUP(RGB5551) - return (TRUE); - default: - break; - } - return (FALSE); -} -#endif diff --git a/src/gfx.h b/src/gfx.h index ce94a3c..c9616e8 100644 --- a/src/gfx.h +++ b/src/gfx.h @@ -42,13 +42,14 @@ #define _GFX_H_ #include "port.h" +#include "ppu.h" #define GFX_PIXSIZE 1 #define GFX_PITCH 640 #define GFX_ZPITCH 320 #define GFX_PPL 320 -struct SGFX{ +typedef struct{ // Initialize these variables uint8 *Screen; uint8 *SubScreen; @@ -73,7 +74,7 @@ struct SGFX{ uint32 FixedColour; uint32 StartY; uint32 EndY; - struct ClipData *pCurrentClip; + ClipData *pCurrentClip; uint32 Mode7Mask; uint32 Mode7PriorityMask; @@ -99,20 +100,20 @@ struct SGFX{ uint32 (*BuildPixel2) (uint32 R, uint32 G, uint32 B); void (*DecomposePixel) (uint32 Pixel, uint32 &R, uint32 &G, uint32 &B); #endif -}; +}SGFX; -struct SLineData { +typedef struct { struct { uint16 VOffset; uint16 HOffset; } BG [4]; -}; +}SLineData; #define H_FLIP 0x4000 #define V_FLIP 0x8000 #define BLANK_TILE 2 -struct SBG +typedef struct { uint32 TileSize; uint32 BitShift; @@ -128,9 +129,9 @@ struct SBG uint8 *Buffer; uint8 *Buffered; bool8 DirectColourMode; -}; +}SBG; -struct SLineMatrixData +typedef struct { short MatrixA; short MatrixB; @@ -138,7 +139,7 @@ struct SLineMatrixData short MatrixD; short CentreX; short CentreY; -}; +}SLineMatrixData; extern uint32 odd_high [4][16]; extern uint32 odd_low [4][16]; @@ -249,7 +250,7 @@ START_EXTERN_C void S9xStartScreenRefresh (); void S9xDrawScanLine (uint8 Line); void S9xEndScreenRefresh (); -void S9xSetupOBJ (struct SOBJ *); +void S9xSetupOBJ (); void S9xUpdateScreen (); //extern void (*S9xUpdateScreen)(); //void SelectUpdateScreen(); @@ -258,7 +259,7 @@ void S9xBuildDirectColourMaps (); // External port interface which must be implemented or initialised for each // port. -extern struct SGFX GFX; +extern SGFX GFX; bool8_32 S9xGraphicsInit (); void S9xGraphicsDeinit(); diff --git a/src/gfx16.c b/src/gfx16.c new file mode 100644 index 0000000..0012b78 --- /dev/null +++ b/src/gfx16.c @@ -0,0 +1,3443 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include "snes9x.h" + +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" +#include "display.h" +#include "gfx.h" +#include "apu.h" +#include "cheats.h" +#include +#include "asmmemfuncs.h" +#include "mode7.h" +#include "rops.h" +#include "tile16.h" +uint32 TileBlank; + +//#define __DEBUG__ + +#ifdef __DEBUG__ + #define DBG(b) printf(b) +#else + #define DBG(b) +#endif + + +const int tx_table[16] = { +// t1 = 16, t2 = 0 + // FLIP = 0x00 + 16 + 0, // 0x00 + 16 + 1, // 0x01 + + // FLIP = 0x01 + 16 + 1 - 0, // 0x02 + 16 + 1 - 1, // 0x03 + + // FLIP = 0x02 + 0 + 0, // 0x04 + 0 + 1, // 0x05 + + // FLIP = 0x03 + 0 + 1 - 0, // 0x06 + 0 + 1 - 1, // 0x07 + +// t1 = 0, t2 = 16 + // FLIP = 0x00 + 0 + 0, // 0x08 + 0 + 1, // 0x09 + + // FLIP = 0x01 + 0 + 1 - 0, // 0x0A + 0 + 1 - 1, // 0x0B + + // FLIP = 0x02 + 16 + 0, // 0x0C + 16 + 1, // 0x0D + + // FLIP = 0x03 + 16 + 1 - 0, // 0x0E + 16 + 1 - 1 // 0x0F +}; + +#define M7 19 +#define M8 19 + +void ComputeClipWindows (); +static void S9xDisplayFrameRate (); +static void S9xDisplayString (const char *string); + +extern uint8 BitShifts[8][4]; +extern uint8 TileShifts[8][4]; +extern uint8 PaletteShifts[8][4]; +extern uint8 PaletteMasks[8][4]; +extern uint8 Depths[8][4]; +extern uint8 BGSizes [2]; + +extern NormalTileRenderer DrawTilePtr; +extern ClippedTileRenderer DrawClippedTilePtr; +extern NormalTileRenderer DrawHiResTilePtr; +extern ClippedTileRenderer DrawHiResClippedTilePtr; +extern LargePixelRenderer DrawLargePixelPtr; + +extern SBG BG; + +extern SLineData LineData[240]; +extern SLineMatrixData LineMatrixData [240]; + +extern uint8 Mode7Depths [2]; + +#define ON_MAIN(N) (GFX.r212c & (1 << (N))) + +#define SUB_OR_ADD(N) \ +(GFX.r2131 & (1 << (N))) + +#define ON_SUB(N) \ +((GFX.r2130 & 0x30) != 0x30 && \ + (GFX.r2130 & 2) && \ + (GFX.r212d & (1 << N))) + +#define ANYTHING_ON_SUB \ +((GFX.r2130 & 0x30) != 0x30 && \ + (GFX.r2130 & 2) && \ + (GFX.r212d & 0x1f)) + +#define ADD_OR_SUB_ON_ANYTHING \ +(GFX.r2131 & 0x3f) + +#define BLACK BUILD_PIXEL(0,0,0) + +void DrawNoZTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount); +void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile16x2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); +void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); +void DrawLargePixel16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawNoZTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Add (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawNoZTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawNoZTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + + +void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Sub (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawNoZTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + + +void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount); + +void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Add (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Sub (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount); + +void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount); + +void DrawHiResTile16 (uint32 Tile, uint32 Offset, + uint32 StartLine, uint32 LineCount); + +bool8_32 S9xGraphicsInit () +{ + register uint32 PixelOdd = 1; + register uint32 PixelEven = 2; + +#ifdef GFX_MULTI_FORMAT + if (GFX.BuildPixel == NULL) + S9xSetRenderPixelFormat (RGB565); +#endif + + for (uint8 bitshift = 0; bitshift < 4; bitshift++) + { + for (register int i = 0; i < 16; i++) + { + register uint32 h = 0; + register uint32 l = 0; + +#if defined(LSB_FIRST) +// Wiz usa LSB_FIRST + if (i & 8) + h |= PixelOdd; + if (i & 4) + h |= PixelOdd << 8; + if (i & 2) + h |= PixelOdd << 16; + if (i & 1) + h |= PixelOdd << 24; + if (i & 8) + l |= PixelOdd; + if (i & 4) + l |= PixelOdd << 8; + if (i & 2) + l |= PixelOdd << 16; + if (i & 1) + l |= PixelOdd << 24; +#else + if (i & 8) + h |= (PixelOdd << 24); + if (i & 4) + h |= (PixelOdd << 16); + if (i & 2) + h |= (PixelOdd << 8); + if (i & 1) + h |= PixelOdd; + if (i & 8) + l |= (PixelOdd << 24); + if (i & 4) + l |= (PixelOdd << 16); + if (i & 2) + l |= (PixelOdd << 8); + if (i & 1) + l |= PixelOdd; +#endif + + odd_high[bitshift][i] = h; + odd_low[bitshift][i] = l; + h = l = 0; + +#if defined(LSB_FIRST) + if (i & 8) + h |= PixelEven; + if (i & 4) + h |= PixelEven << 8; + if (i & 2) + h |= PixelEven << 16; + if (i & 1) + h |= PixelEven << 24; + if (i & 8) + l |= PixelEven; + if (i & 4) + l |= PixelEven << 8; + if (i & 2) + l |= PixelEven << 16; + if (i & 1) + l |= PixelEven << 24; +#else + if (i & 8) + h |= (PixelEven << 24); + if (i & 4) + h |= (PixelEven << 16); + if (i & 2) + h |= (PixelEven << 8); + if (i & 1) + h |= PixelEven; + if (i & 8) + l |= (PixelEven << 24); + if (i & 4) + l |= (PixelEven << 16); + if (i & 2) + l |= (PixelEven << 8); + if (i & 1) + l |= PixelEven; +#endif + + even_high[bitshift][i] = h; + even_low[bitshift][i] = l; + } + PixelEven <<= 2; + PixelOdd <<= 2; + } + + GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; + GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; + //GFX.InfoStringTimeout = 0; + //GFX.InfoString = NULL; + + PPU.BG_Forced = 0; + IPPU.OBJChanged = TRUE; + + IPPU.DirectColourMapsNeedRebuild = TRUE; + DrawTilePtr = DrawTile16; + DrawClippedTilePtr = DrawClippedTile16; + DrawLargePixelPtr = DrawLargePixel16; + DrawHiResTilePtr= DrawHiResTile16; + DrawHiResClippedTilePtr = DrawHiResClippedTile16; + S9xFixColourBrightness (); + + if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000))) + return (FALSE); + + if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) || + !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000))) + { + if (GFX.ZERO_OR_X2) + { + free ((char *) GFX.ZERO_OR_X2); + GFX.ZERO_OR_X2 = NULL; + } + if (GFX.X2) + { + free ((char *) GFX.X2); + GFX.X2 = NULL; + } + return (FALSE); + } + uint32 r, g, b; + + // Build a lookup table that multiplies a packed RGB value by 2 with + // saturation. + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r << 1; + if (r2 > MAX_RED) + r2 = MAX_RED; + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g << 1; + if (g2 > MAX_GREEN) + g2 = MAX_GREEN; + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b << 1; + if (b2 > MAX_BLUE) + b2 = MAX_BLUE; + GFX.X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); + GFX.X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); + } + } + } + ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16)); + ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16)); + // Build a lookup table that if the top bit of the color value is zero + // then the value is zero, otherwise multiply the value by 2. Used by + // the color subtraction code. + +#if defined(OLD_COLOUR_BLENDING) + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if ((r2 & 0x10) == 0) + r2 = 0; + else + r2 = (r2 << 1) & MAX_RED; + + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if ((g2 & GREEN_HI_BIT) == 0) + g2 = 0; + else + g2 = (g2 << 1) & MAX_GREEN; + + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if ((b2 & 0x10) == 0) + b2 = 0; + else + b2 = (b2 << 1) & MAX_BLUE; + + GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); + GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); + } + } + } +#else + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if ((r2 & 0x10) == 0) + r2 = 0; + else + r2 = (r2 << 1) & MAX_RED; + + if (r2 == 0) + r2 = 1; + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if ((g2 & GREEN_HI_BIT) == 0) + g2 = 0; + else + g2 = (g2 << 1) & MAX_GREEN; + + if (g2 == 0) + g2 = 1; + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if ((b2 & 0x10) == 0) + b2 = 0; + else + b2 = (b2 << 1) & MAX_BLUE; + + if (b2 == 0) + b2 = 1; + GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); + GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); + } + } + } +#endif + + // Build a lookup table that if the top bit of the color value is zero + // then the value is zero, otherwise its just the value. + for (r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if ((r2 & 0x10) == 0) + r2 = 0; + else + r2 &= ~0x10; + + for (g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if ((g2 & GREEN_HI_BIT) == 0) + g2 = 0; + else + g2 &= ~GREEN_HI_BIT; + for (b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if ((b2 & 0x10) == 0) + b2 = 0; + else + b2 &= ~0x10; + + GFX.ZERO [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); + GFX.ZERO [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); + } + } + } + + return (TRUE); +} + +void S9xGraphicsDeinit (void) +{ + // Free any memory allocated in S9xGraphicsInit + if (GFX.X2) + { + free ((char *) GFX.X2); + GFX.X2 = NULL; + } + if (GFX.ZERO_OR_X2) + { + free ((char *) GFX.ZERO_OR_X2); + GFX.ZERO_OR_X2 = NULL; + } + if (GFX.ZERO) + { + free ((char *) GFX.ZERO); + GFX.ZERO = NULL; + } +} + +void S9xBuildDirectColourMaps () +{ + for (uint32 p = 0; p < 8; p++) + { + for (uint32 c = 0; c < 256; c++) + { +// XXX: Brightness + /* + DirectColourMaps [p][c] = BUILD_PIXEL (IPPU.XB[((c & 7) << 2) | ((p & 1) << 1)], + IPPU.XB[((c & 0x38) >> 1) | (p & 2)], + IPPU.XB[((c & 0xc0) >> 3) | (p & 4)]); + */ + DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1), + ((c & 0x38) >> 1) | (p & 2), + ((c & 0xc0) >> 3) | (p & 4)); + + } + } + IPPU.DirectColourMapsNeedRebuild = FALSE; +} + +void S9xStartScreenRefresh () +{ + RESET_ROPS(0); + + if (IPPU.RenderThisFrame) + { + if (!S9xInitUpdate ()) + { + IPPU.RenderThisFrame = FALSE; + return; + } + IPPU.RenderedFramesCount++; + IPPU.PreviousLine = IPPU.CurrentLine = 0; + IPPU.MaxBrightness = PPU.Brightness; + IPPU.LatchedBlanking = PPU.ForcedBlanking; + IPPU.LatchedInterlace = (Memory.FillRAM[0x2133] & 1); + IPPU.RenderedScreenWidth = 256; + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + IPPU.DoubleWidthPixels = FALSE; + + PPU.RecomputeClipWindows = TRUE; + PPU.BG[0].OffsetsChanged = 0; + PPU.BG[1].OffsetsChanged = 0; + PPU.BG[2].OffsetsChanged = 0; + PPU.BG[3].OffsetsChanged = 0; + GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; + GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; + } + + if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) + { + IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; + IPPU.RenderedFramesCount = 0; + IPPU.FrameCount = 0; + } +} + +void RenderLine (uint8 C) +{ + if (IPPU.RenderThisFrame) + { + + LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1; + LineData[C].BG[0].HOffset = PPU.BG[0].HOffset; + LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1; + LineData[C].BG[1].HOffset = PPU.BG[1].HOffset; + + //if (PPU.BGMode == 7) + if ((Memory.FillRAM[0x2105] & 7) == 7) + { + SLineMatrixData *p = &LineMatrixData [C]; + p->MatrixA = PPU.MatrixA; + p->MatrixB = PPU.MatrixB; + p->MatrixC = PPU.MatrixC; + p->MatrixD = PPU.MatrixD; + p->CentreX = PPU.CentreX; + p->CentreY = PPU.CentreY; + } + else + { + if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 && + PPU.BG[2].HOffset == 0xe000) + { + LineData[C].BG[2].VOffset = 0xe1; + LineData[C].BG[2].HOffset = 0; + } + else + { + LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1; + LineData[C].BG[2].HOffset = PPU.BG[2].HOffset; + LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1; + LineData[C].BG[3].HOffset = PPU.BG[3].HOffset; + } + + } + IPPU.CurrentLine = C + 1; + } +} + + +void S9xEndScreenRefresh() +{ + IPPU.HDMAStarted = FALSE; + +//RC + if (IPPU.RenderThisFrame) + { + FLUSH_REDRAW (); + //if (IPPU.ColorsChanged) + //{ + IPPU.ColorsChanged = FALSE; + //} + + S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, + 1); + } +#ifndef RC_OPTIMIZED + S9xApplyCheats (); +#endif + + +#ifdef DEBUGGER + if (CPU.Flags & FRAME_ADVANCE_FLAG) + { + if (ICPU.FrameAdvanceCount) + { + ICPU.FrameAdvanceCount--; + IPPU.RenderThisFrame = TRUE; + IPPU.FrameSkip = 0; + } + else + { + CPU.Flags &= ~FRAME_ADVANCE_FLAG; + CPU.Flags |= DEBUG_MODE_FLAG; + } + } +#endif + +/* + if (CPU.SRAMModified) + { + if (!CPU.AutoSaveTimer) + { + if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond)) + CPU.SRAMModified = FALSE; + } + else + { + if (!--CPU.AutoSaveTimer) + { + S9xAutoSaveSRAM (); + CPU.SRAMModified = FALSE; + } + } + } +*/ +} + +void S9xSetInfoString (const char *string) +{ + } + + + +int TileRenderer; +TileRendererSet TileRenderers[] = { + {DrawTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 0 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 0 + {DrawTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 1 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 1 + {DrawTile16FixedAdd1_2, DrawClippedTile16FixedAdd1_2, DrawLargePixel16Add1_2}, // 2 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 0 + {DrawTile16Add1_2, DrawClippedTile16Add1_2, DrawLargePixel16Add1_2}, // 3 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 1 + {DrawTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 4 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 0 + {DrawTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 5 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 1 + {DrawTile16FixedSub1_2, DrawClippedTile16FixedSub1_2, DrawLargePixel16Sub1_2}, // 6 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 0 + {DrawTile16Sub1_2, DrawClippedTile16Sub1_2, DrawLargePixel16Sub1_2}, // 7 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 1 + {DrawTile16, DrawClippedTile16, DrawLargePixel16} // 8 -> normal + }; +#ifdef __FAST_OBJS__ +TileRendererSet TileRenderersNoZ[] = { + {DrawNoZTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 0 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 0 + {DrawNoZTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 1 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 1 + {DrawTile16FixedAdd1_2, DrawClippedTile16FixedAdd1_2, DrawLargePixel16Add1_2}, // 2 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 0 + {DrawNoZTile16Add1_2, DrawClippedTile16Add1_2, DrawLargePixel16Add1_2}, // 3 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 1 + {DrawNoZTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 4 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 0 + {DrawNoZTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 5 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 1 + {DrawTile16FixedSub1_2, DrawClippedTile16FixedSub1_2, DrawLargePixel16Sub1_2}, // 6 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 0 + {DrawNoZTile16Sub1_2, DrawClippedTile16Sub1_2, DrawLargePixel16Sub1_2}, // 7 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 1 + {DrawNoZTile16, DrawClippedTile16, DrawLargePixel16} // 8 -> normal + }; +#endif +static INLINE void SelectTileRenderer (bool8_32 normal, bool NoZ) +{ + if (normal) { + TileRenderer = 8; + } + else { + TileRenderer = (((GFX.r2131 >> 5) & 0x06) | ((GFX.r2130 >> 1) & 1)); + } + +#ifdef __DEBUG__ + char *TRName[] = { + "Add", "Add", "FixedAdd1_2", "Add1_2", + "Sub", "Sub", "FixedSub1_2", "Sub1_2", + "Normal" + }; + printf("SelectTileRenderer: %s\n", TRName[TileRenderer]); +#endif + +#ifdef __FAST_OBJS__ + if (NoZ) { + DrawTilePtr = TileRenderersNoZ[TileRenderer].Normal; + DrawClippedTilePtr = TileRenderersNoZ[TileRenderer].Clipped; + DrawLargePixelPtr = TileRenderersNoZ[TileRenderer].Large; + } + else { +#endif + DrawTilePtr = TileRenderers[TileRenderer].Normal; + DrawClippedTilePtr = TileRenderers[TileRenderer].Clipped; + DrawLargePixelPtr = TileRenderers[TileRenderer].Large; +#ifdef __FAST_OBJS__ + } +#endif +} + +void S9xSetupOBJ () +{ + int SmallSize; + int LargeSize; + + switch (PPU.OBJSizeSelect) + { + case 0: + SmallSize = 8; + LargeSize = 16; + break; + case 1: + SmallSize = 8; + LargeSize = 32; + break; + case 2: + SmallSize = 8; + LargeSize = 64; + break; + case 3: + SmallSize = 16; + LargeSize = 32; + break; + case 4: + SmallSize = 16; + LargeSize = 64; + break; + case 5: + default: + SmallSize = 32; + LargeSize = 64; + break; + } + + int C = 0; + + int FirstSprite = PPU.FirstSprite & 0x7f; + int S = FirstSprite; + do + { + int Size; + if (PPU.OBJ [S].Size) + Size = LargeSize; + else + Size = SmallSize; + + long VPos = PPU.OBJ [S].VPos; + + if (VPos >= PPU.ScreenHeight) + VPos -= 256; + if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size && + VPos < PPU.ScreenHeight && VPos > -Size) + { +#ifndef __FAST_OBJS__ + GFX.OBJList[C++] = S; +#else + int x = 0; + int a, b; + // -- Sort objects (from low to high priority) + while (x < C) { + a = GFX.OBJList[x]; + if (PPU.OBJ[a].Priority >= PPU.OBJ[S].Priority) break; + x++; + } + + GFX.OBJList[x] = S; + x++; C++; + + while (x < C) { + b = GFX.OBJList[x]; + GFX.OBJList[x] = a; + a = b; + x++; + } +#endif + // -- + GFX.Sizes[S] = Size; + GFX.VPositions[S] = VPos; + } + S = (S + 1) & 0x7f; + } while (S != FirstSprite); + + // Terminate the list + GFX.OBJList [C] = -1; + IPPU.OBJChanged = FALSE; +} + +void DrawOBJS (bool8_32 OnMain, uint8 D) +{ + int bg_ta_ns; + int bg_ta; + uint32 O; + uint32 BaseTile, Tile; + + CHECK_SOUND(); + + BG.BitShift = 4; + SelectConvertTile(); + BG.TileShift = 5; + //BG.TileAddress = PPU.OBJNameBase; + BG.StartPalette = 128; + BG.PaletteShift = 4; + BG.PaletteMask = 7; + BG.Buffer = IPPU.TileCache [TILE_4BIT]; + BG.Buffered = IPPU.TileCached [TILE_4BIT]; + //BG.NameSelect = PPU.OBJNameSelect; + BG.DirectColourMode = FALSE; + + SelectPalette(); + bg_ta = PPU.OBJNameBase; + bg_ta_ns = bg_ta + PPU.OBJNameSelect; + + GFX.Z1 = D + 2; + + DBG("Draw Objects.\n"); + + int I = 0; + for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++]) + { + int VPos = GFX.VPositions [S]; + int Size = GFX.Sizes[S]; + int TileInc = 1; + int Offset; + + if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY) + continue; + + if (OnMain && SUB_OR_ADD(4)) + { +#ifndef __FAST_OBJS__ + SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4, false); +#else + SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4, true); +#endif + } + + BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10); + + if (PPU.OBJ[S].HFlip) + { + BaseTile += ((Size >> 3) - 1) | H_FLIP; + TileInc = -1; + } + + if (PPU.OBJ[S].VFlip) BaseTile |= V_FLIP; + //BaseTile |= PPU.OBJ[S].VFlip << 15; + + int clipcount = GFX.pCurrentClip->Count [4]; + if (!clipcount) clipcount = 1; + + GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D; + + for (int clip = 0; clip < clipcount; clip++) + { + int Left; + int Right; + if (!GFX.pCurrentClip->Count [4]) + { + Left = 0; + Right = 256; + } + else + { + Left = GFX.pCurrentClip->Left [clip][4]; + Right = GFX.pCurrentClip->Right [clip][4]; + } + + if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left || + PPU.OBJ[S].HPos >= Right) + continue; + + for (int Y = 0; Y < Size; Y += 8) + { + if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY) + { + int StartLine; + int TileLine; + int LineCount; + int Last; + + if ((StartLine = VPos + Y) < (int) GFX.StartY) + { + StartLine = GFX.StartY - StartLine; + LineCount = 8 - StartLine; + } + else + { + StartLine = 0; + LineCount = 8; + } + if ((Last = VPos + Y + 7 - GFX.EndY) > 0) + if ((LineCount -= Last) <= 0) + break; + + TileLine = StartLine << 3; + + O = (VPos + Y + StartLine) * GFX_PPL; + if (!PPU.OBJ[S].VFlip) Tile = BaseTile + (Y << 1); + else Tile = BaseTile + ((Size - Y - 8) << 1); + + if (Tile & 0x100) BG.TileAddress = bg_ta_ns; + else BG.TileAddress = bg_ta; + + int Middle = Size >> 3; + if (PPU.OBJ[S].HPos < Left) + { + Tile += ((Left - PPU.OBJ[S].HPos) >> 3) * TileInc; + Middle -= (Left - PPU.OBJ[S].HPos) >> 3; + O += Left * GFX_PIXSIZE; + if ((Offset = (Left - PPU.OBJ[S].HPos) & 7)) + { + O -= Offset * GFX_PIXSIZE; + int W = 8 - Offset; + int Width = Right - Left; + if (W > Width) W = Width; + //if (Tile & 0x100) BG.TileAddress = bg_ta_ns; + //else BG.TileAddress = bg_ta; + (*DrawClippedTilePtr) (Tile, O, Offset, W, TileLine, LineCount); + + if (W >= Width) + continue; + Tile += TileInc; + Middle--; + O += 8 * GFX_PIXSIZE; + } + } + else + O += PPU.OBJ[S].HPos * GFX_PIXSIZE; + + if (PPU.OBJ[S].HPos + Size >= Right) + { + Middle -= ((PPU.OBJ[S].HPos + Size + 7) - + Right) >> 3; + Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7; + } + else + Offset = 0; + + for (int X = 0; X < Middle; X++, O += 8 * GFX_PIXSIZE, + Tile += TileInc) + { + //if (Tile & 0x100) BG.TileAddress = bg_ta_ns; + //else BG.TileAddress = bg_ta; + (*DrawTilePtr) (Tile, O, TileLine, LineCount); + } + if (Offset) + { + //if (Tile & 0x100) BG.TileAddress = bg_ta_ns; + //else BG.TileAddress = bg_ta; + (*DrawClippedTilePtr) (Tile, O, 0, Offset, TileLine, LineCount); + } + } + } + } + } +} +void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ +#ifdef __DEBUG__ + printf("DrawBackgroundMosaic(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2); +#endif + CHECK_SOUND(); + + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint8 depths [2] = {Z1, Z2}; + + if (BGMode == 0) + BG.StartPalette = bg << 5; + else + BG.StartPalette = 0; + SelectPalette(); + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if (PPU.BG[bg].SCSize & 1) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if(((uint8*)SC1-Memory.VRAM)>=0x10000) + SC1-=0x08000; + + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + + if (PPU.BG[bg].SCSize & 1) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + + uint32 Lines; + uint32 OffsetMask; + uint32 OffsetShift; + + if (BG.TileSize == 16) + { + OffsetMask = 0x3ff; + OffsetShift = 4; + } + else + { + OffsetMask = 0x1ff; + OffsetShift = 3; + } + + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) + { + uint32 VOffset = LineData [Y].BG[bg].VOffset; + uint32 HOffset = LineData [Y].BG[bg].HOffset; + uint32 MosaicOffset = Y % PPU.Mosaic; + + for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || + (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + break; + + uint32 MosaicLine = VOffset + Y - MosaicOffset; + + if (Y + Lines > GFX.EndY) + Lines = GFX.EndY + 1 - Y; + uint32 VirtAlign = (MosaicLine & 7) << 3; + + uint16 *b1; + uint16 *b2; + + uint32 ScreenLine = MosaicLine >> OffsetShift; + uint32 Rem16 = MosaicLine & 15; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + uint16 *t; + uint32 Left = 0; + uint32 Right = 256; + + uint32 ClipCount = GFX.pCurrentClip->Count [bg]; + uint32 HPos = HOffset; + uint32 PixWidth = PPU.Mosaic; + + if (!ClipCount) + ClipCount = 1; + + for (uint32 clip = 0; clip < ClipCount; clip++) + { + if (GFX.pCurrentClip->Count [bg]) + { + Left = GFX.pCurrentClip->Left [clip][bg]; + Right = GFX.pCurrentClip->Right [clip][bg]; + uint32 r = Left % PPU.Mosaic; + HPos = HOffset + Left; + PixWidth = PPU.Mosaic - r; + } + uint32 s = Y * GFX_PPL + Left * GFX_PIXSIZE; + for (uint32 x = Left; x < Right; x += PixWidth, + s += PixWidth * GFX_PIXSIZE, + HPos += PixWidth, PixWidth = PPU.Mosaic) + { + uint32 Quot = (HPos & OffsetMask) >> 3; + + if (x + PixWidth >= Right) + PixWidth = Right - x; + + if (BG.TileSize == 8) + { + if (Quot > 31) + t = b2 + (Quot & 0x1f); + else + t = b1 + Quot; + } + else + { + if (Quot > 63) + t = b2 + ((Quot >> 1) & 0x1f); + else + t = b1 + (Quot >> 1); + } + + Tile = READ_2BYTES (t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + // Draw tile... + if (BG.TileSize != 8) + { + if (Tile & H_FLIP) + { + // Horizontal flip, but what about vertical flip ? + if (Tile & V_FLIP) + { + // Both horzontal & vertical flip + if (Rem16 < 8) + { + (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + else + { + // Horizontal flip only + if (Rem16 > 7) + { + (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + } + else + { + // No horizontal flip, but is there a vertical flip ? + if (Tile & V_FLIP) + { + // Vertical flip only + if (Rem16 < 8) + { + (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + else + { + // Normal unflipped + if (Rem16 > 7) + { + (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + else + { + (*DrawLargePixelPtr) (Tile + (Quot & 1), s, + HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + } + } + else + (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth, + VirtAlign, Lines); + } + } + } +} + +void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ +#ifdef __DEBUG__ + printf("DrawBackgroundOffset(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2); +#endif + + CHECK_SOUND(); + + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint16 *BPS0; + uint16 *BPS1; + uint16 *BPS2; + uint16 *BPS3; + uint32 Width; + int VOffsetOffset = BGMode == 4 ? 0 : 32; + uint8 depths [2] = {Z1, Z2}; + + BG.StartPalette = 0; + SelectPalette(); + + BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; + + if (PPU.BG[2].SCSize & 1) + BPS1 = BPS0 + 1024; + else + BPS1 = BPS0; + + if (PPU.BG[2].SCSize & 2) + BPS2 = BPS1 + 1024; + else + BPS2 = BPS0; + + if (PPU.BG[2].SCSize & 1) + BPS3 = BPS2 + 1024; + else + BPS3 = BPS2; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if (PPU.BG[bg].SCSize & 1) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if(((uint8*)SC1-Memory.VRAM)>=0x10000) + SC1-=0x08000; + + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + + if (PPU.BG[bg].SCSize & 1) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + + static const int Lines = 1; + int OffsetMask; + int OffsetShift; + int OffsetEnableMask = 1 << (bg + 13); + + if (BG.TileSize == 16) + { + OffsetMask = 0x3ff; + OffsetShift = 4; + } + else + { + OffsetMask = 0x1ff; + OffsetShift = 3; + } + + TileBlank = 0xFFFFFFFF; + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++) + { + uint32 VOff = LineData [Y].BG[2].VOffset - 1; + uint32 HOff = LineData [Y].BG[2].HOffset; + int VirtAlign; + int ScreenLine = VOff >> 3; + uint16 *s0; + uint16 *s1; + uint16 *s2; +#ifdef __DEBUG__ + printf("Processing line: %d\n", Y); +#endif + if (ScreenLine & 0x20) + s1 = BPS2, s2 = BPS3; + else + s1 = BPS0, s2 = BPS1; + + s1 += (ScreenLine & 0x1f) << 5; + s2 += (ScreenLine & 0x1f) << 5; + + if(BGMode != 4) + { + if((ScreenLine & 0x1f) == 0x1f) + { + if(ScreenLine & 0x20) + VOffsetOffset = BPS0 - BPS2 - 0x1f*32; + else + VOffsetOffset = BPS2 - BPS0 - 0x1f*32; + } + else + { + VOffsetOffset = 32; + } + } + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) + clipcount = 1; + + for (int clip = 0; clip < clipcount; clip++) + { + uint32 Left; + uint32 Right; +#ifdef __DEBUG__ + printf("Processing clip: %d/%d\n", clip, clipcount); +#endif + + if (!GFX.pCurrentClip->Count [bg]) + { + Left = 0; + Right = 256; + } + else + { + Left = GFX.pCurrentClip->Left [clip][bg]; + Right = GFX.pCurrentClip->Right [clip][bg]; + + if (Right <= Left) + continue; + } + + uint32 VOffset; + uint32 HOffset; + uint32 LineHOffset=LineData [Y].BG[bg].HOffset; + uint32 Offset; + uint32 HPos; + uint32 Quot; + uint32 Count; + uint16 *t; + uint32 Quot2; + uint32 VCellOffset; + uint32 HCellOffset; + uint16 *b1; + uint16 *b2; + uint32 TotalCount = 0; + uint32 MaxCount = 8; + + uint32 s = Left * GFX_PIXSIZE + Y * GFX_PPL; + bool8_32 left_hand_edge = (Left == 0); + Width = Right - Left; + + if (Left & 7) + MaxCount = 8 - (Left & 7); + + while (Left < Right) + { +#ifdef __DEBUG__ + printf("Left: %d, Right: %d\n", Left, Right); +#endif + if (left_hand_edge) + { + // The SNES offset-per-tile background mode has a + // hardware limitation that the offsets cannot be set + // for the tile at the left-hand edge of the screen. + VOffset = LineData [Y].BG[bg].VOffset; + HOffset = LineHOffset; + left_hand_edge = FALSE; + } + else + { + // All subsequent offset tile data is shifted left by one, + // hence the - 1 below. + Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3; + + if (Quot2 > 31) + s0 = s2 + (Quot2 & 0x1f); + else + s0 = s1 + Quot2; + + HCellOffset = READ_2BYTES (s0); + + if (BGMode == 4) + { + VOffset = LineData [Y].BG[bg].VOffset; + HOffset=LineHOffset; + if ((HCellOffset & OffsetEnableMask)) + { + if (HCellOffset & 0x8000) + VOffset = HCellOffset + 1; + else + HOffset = HCellOffset; + } + } + else + { + VCellOffset = READ_2BYTES (s0 + VOffsetOffset); + if ((VCellOffset & OffsetEnableMask)) + VOffset = VCellOffset + 1; + else + VOffset = LineData [Y].BG[bg].VOffset; + + if ((HCellOffset & OffsetEnableMask)) + HOffset = (HCellOffset & ~7)|(LineHOffset&7); + else + HOffset=LineHOffset; + } + } + VirtAlign = ((Y + VOffset) & 7) << 3; + ScreenLine = (VOffset + Y) >> OffsetShift; + + int tx_index; + tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + HPos = (HOffset + Left) & OffsetMask; + + Quot = HPos >> 3; + + if (BG.TileSize == 8) + { + if (Quot > 31) + t = b2 + (Quot & 0x1f); + else + t = b1 + Quot; + } + else + { + if (Quot > 63) + t = b2 + ((Quot >> 1) & 0x1f); + else + t = b1 + (Quot >> 1); + } + + if (MaxCount + TotalCount > Width) + MaxCount = Width - TotalCount; + + Offset = HPos & 7; + + Count = 8 - Offset; + if (Count > MaxCount) + Count = MaxCount; + + s -= Offset * GFX_PIXSIZE; + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + if (Tile != TileBlank) + if (BG.TileSize == 8) + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); + else + { + Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)]; + if (Tile != TileBlank){ + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); + } + } + + Left += Count; + TotalCount += Count; + s += (Offset + Count) * GFX_PIXSIZE; + MaxCount = 8; + } + } + } +} + +void DrawBackgroundMode5 (uint32 BGMODE, uint32 bg, uint8 Z1, uint8 Z2) +{ +#ifdef __DEBUG__ + printf("DrawBackgroundMode5(?, %i, %i, %i)\n", bg, Z1, Z2); +#endif + + CHECK_SOUND(); + + uint8 depths [2] = {Z1, Z2}; + + uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint32 Width; + + BG.StartPalette = 0; + SelectPalette(); + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + if ((PPU.BG[bg].SCSize & 1)) + SC1 = SC0 + 1024; + else + SC1 = SC0; + + if((SC1-(unsigned short*)Memory.VRAM)>0x10000) + SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000]; + + if ((PPU.BG[bg].SCSize & 2)) + SC2 = SC1 + 1024; + else SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) + SC2-=0x08000; + + if ((PPU.BG[bg].SCSize & 1)) + SC3 = SC2 + 1024; + else + SC3 = SC2; + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) + SC3-=0x08000; + int Lines; + int VOffsetMask; + int VOffsetShift; + + if (BG.TileSize == 16) + { + VOffsetMask = 0x3ff; + VOffsetShift = 4; + } + else + { + VOffsetMask = 0x1ff; + VOffsetShift = 3; + } + int endy = GFX.EndY; + + for (int Y = GFX.StartY; Y <= endy; Y += Lines) + { + //int y = Y; + uint32 VOffset = LineData [Y].BG[bg].VOffset; + uint32 HOffset = LineData [Y].BG[bg].HOffset; + int VirtAlign = (Y + VOffset) & 7; + + for (Lines = 1; Lines < 8 - VirtAlign; Lines++) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || + (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + break; + + HOffset <<= 1; + if (Y + Lines > endy) + Lines = endy + 1 - Y; + + int ScreenLine = (VOffset + Y) >> VOffsetShift; + int t1; + int t2; + if (((VOffset + Y) & 15) > 7) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + uint16 *b1; + uint16 *b2; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) + clipcount = 1; + for (int clip = 0; clip < clipcount; clip++) + { + int Left; + int Right; + + if (!GFX.pCurrentClip->Count [bg]) + { + Left = 0; + Right = 512; + } + else + { + Left = GFX.pCurrentClip->Left [clip][bg] * 2; + Right = GFX.pCurrentClip->Right [clip][bg] * 2; + + if (Right <= Left) + continue; + } + + uint32 s = (Left>>1) * GFX_PIXSIZE + Y * GFX_PPL; + uint32 HPos = (HOffset + Left * GFX_PIXSIZE) & 0x3ff; + + uint32 Quot = HPos >> 3; + uint32 Count = 0; + + uint16 *t; + if (Quot > 63) + t = b2 + ((Quot >> 1) & 0x1f); + else + t = b1 + (Quot >> 1); + + Width = Right - Left; + // Left hand edge clipped tile + if (HPos & 7) + { + int Offset = (HPos & 7); + Count = 8 - Offset; + if (Count > Width) + Count = Width; + s -= (Offset>>1); + Tile = READ_2BYTES (t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + + if (BG.TileSize == 8) + { + if (!(Tile & H_FLIP)) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + { + // H flip + (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), + s, Offset, Count, VirtAlign, Lines); + } + } + + t += Quot & 1; + if (Quot == 63) + t = b2; + else if (Quot == 127) + t = b1; + Quot++; + s += 4; + } + + // Middle, unclipped tiles + Count = Width - Count; + int Middle = Count >> 3; + Count &= 7; + for (int C = Middle; C > 0; s += 4, Quot++, C--) + { + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + if (BG.TileSize == 8) + { + if (!(Tile & H_FLIP)) + { + // Normal, unflipped + (*DrawHiResTilePtr) (Tile + (Quot & 1), + s, VirtAlign, Lines); + } + else + { + // H flip + (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1), + s, VirtAlign, Lines); + } + } + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1), + s, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1), + s, VirtAlign, Lines); + } + } + + t += Quot & 1; + if (Quot == 63) + t = b2; + else + if (Quot == 127) + t = b1; + } + + // Right-hand edge clipped tiles + if (Count) + { + Tile = READ_2BYTES(t); + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + if (BG.TileSize == 8) + { + if (!(Tile & H_FLIP)) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + else + { + // H flip + (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + } + else + { + if (!(Tile & (V_FLIP | H_FLIP))) + { + // Normal, unflipped + (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + else + if (Tile & H_FLIP) + { + if (Tile & V_FLIP) + { + // H & V flip + (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + else + { + // H flip only + (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + } + else + { + // V flip only + (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), + s, 0, Count, VirtAlign, Lines); + } + } + } + } + } +} + +void DrawBackground_8(uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ +#ifdef __DEBUG__ + printf("DrawBackground_8(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2); +#endif + //uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint32 depths [2] = {Z1, Z2}; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + SC1 = SC0 + ((PPU.BG[bg].SCSize & 1) << 10); + + if(SC1 >= (unsigned short*)(Memory.VRAM+0x10000)) SC1 = (uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0]) & 0xffff]; + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) SC2 -= 0x08000; + + SC3 = SC2 + ((PPU.BG[bg].SCSize & 1) << 10); + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) SC3 -= 0x08000; + + int Lines; + + int oc = PPU.BG[bg].OffsetsChanged; + uint32 VOffset, HOffset; + if (!oc) { + VOffset = LineData [GFX.StartY].BG[bg].VOffset; + HOffset = LineData [GFX.StartY].BG[bg].HOffset; + } + TileBlank = 0xFFFFFFFF; + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){ + int y_ppl = Y * GFX_PPL; + if (oc) { + VOffset = LineData [Y].BG[bg].VOffset; + HOffset = LineData [Y].BG[bg].HOffset; + } + int VirtAlign = (Y + VOffset) & 7; + + int maxLines = GFX.EndY - Y + 1; + if ((8 - VirtAlign) < maxLines) maxLines = (8 - VirtAlign); + + if (oc) { + for (Lines = 1; Lines < maxLines; Lines++) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || + (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + break; + } else Lines = maxLines; + + VirtAlign <<= 3; + + uint32 ScreenLine = (VOffset + Y) >> 3; + uint16 *b1; + uint16 *b2; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + uint32 Left; + uint32 Right; + int clip = 0; + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) { + Left = 0; + Right = 256; + } + + do { + if (clipcount) { + Left = GFX.pCurrentClip->Left [clip][bg]; + Right = GFX.pCurrentClip->Right [clip][bg]; + + if (Right <= Left) {clip++; continue;} + } + + uint32 s = Left + y_ppl; + uint32 HPos = (HOffset + Left) & 0x1ff; + uint32 Quot = HPos >> 3; + uint32 Count = 0; + uint16 *t; + uint16 *b; + + if (Quot > 31) { + t = b2 + (Quot & 0x1f); + b = b1; + Quot -= 32; + } + else { + t = b1 + Quot; + b = b2; + } + + uint32 Width = Right - Left; + + // Left hand edge clipped tile + uint32 Offset = (HPos & 7); + if (Offset){ + Count = 8 - Offset; + if (Count > Width) Count = Width; + s -= Offset; + //uint32 Tile = READ_2BYTES(t); + register uint32 Tile = *(t++); + if (Tile != TileBlank){ + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); + } + //t++; + if (Quot == 31) t = b; + //else if (Quot == 63) t = b1; + Quot++; + s += 8; + } + + // Middle, unclipped tiles + Count = Width - Count; + for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){ + //uint32 Tile = READ_2BYTES(t); + register uint32 Tile = *(t++); + if (Tile != TileBlank){ + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + (*DrawTilePtr) (Tile, s, VirtAlign, Lines); + } + + //t++; + if (Quot == 31) t = b; + //else if (Quot == 63) t = b1; + } + + // Right-hand edge clipped tiles + if (Count & 7){ + //uint32 Tile = READ_2BYTES(t); + register uint32 Tile = *t; + if (Tile != TileBlank){ + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines); + } + } + clip ++; + } while (clip < clipcount); + } +} + +void DrawBackground_16 (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ +#ifdef __DEBUG__ + printf("DrawBackground_16(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2); +#endif + //uint32 Tile; + uint16 *SC0; + uint16 *SC1; + uint16 *SC2; + uint16 *SC3; + uint32 depths [2] = {Z1, Z2}; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + + SC1 = SC0 + ((PPU.BG[bg].SCSize & 1) << 10); + + if(SC1 >= (unsigned short*)(Memory.VRAM+0x10000)) SC1 = (uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0]) & 0xffff]; + + if (PPU.BG[bg].SCSize & 2) + SC2 = SC1 + 1024; + else + SC2 = SC0; + + if(((uint8*)SC2-Memory.VRAM)>=0x10000) SC2 -= 0x08000; + + SC3 = SC2 + ((PPU.BG[bg].SCSize & 1) << 10); + + if(((uint8*)SC3-Memory.VRAM)>=0x10000) SC3 -= 0x08000; + + int Lines; + + int oc = PPU.BG[bg].OffsetsChanged; + uint32 VOffset, HOffset; + if (!oc) { + VOffset = LineData [GFX.StartY].BG[bg].VOffset; + HOffset = LineData [GFX.StartY].BG[bg].HOffset; + } + + TileBlank = 0xFFFFFFFF; + unsigned int tb1 = 0xffffffff; + unsigned int tb2 = 0xffffffff; + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){ + int y_ppl = Y * GFX_PPL; + if (oc) { + VOffset = LineData [Y].BG[bg].VOffset; + HOffset = LineData [Y].BG[bg].HOffset; + } + int VirtAlign = (Y + VOffset) & 7; + + int maxLines = GFX.EndY - Y + 1; + if ((8 - VirtAlign) < maxLines) maxLines = (8 - VirtAlign); + + if (oc) { + for (Lines = 1; Lines < maxLines; Lines++) + if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || + (HOffset != LineData [Y + Lines].BG[bg].HOffset)) + break; + } else Lines = maxLines; + + VirtAlign <<= 3; + + uint32 ScreenLine = (VOffset + Y) >> 4; + int tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3; + uint16 *b1; + uint16 *b2; + + if (ScreenLine & 0x20) + b1 = SC2, b2 = SC3; + else + b1 = SC0, b2 = SC1; + + b1 += (ScreenLine & 0x1f) << 5; + b2 += (ScreenLine & 0x1f) << 5; + + uint32 Left; + uint32 Right; + int clip = 0; + int clipcount = GFX.pCurrentClip->Count [bg]; + if (!clipcount) { + Left = 0; + Right = 256; + } + + do { + if (clipcount) { + Left = GFX.pCurrentClip->Left [clip][bg]; + Right = GFX.pCurrentClip->Right [clip][bg]; + + if (Right <= Left) {clip++; continue;} + } + + uint32 s = Left + y_ppl; + uint32 HPos = (HOffset + Left) & 0x3ff; + uint32 Quot = HPos >> 3; + uint32 Count = 0; + uint16 *t; + uint16 *b; + + if (Quot > 63) { + t = b2 + ((Quot >> 1) & 0x1f); + b = b1; + Quot -= 64; + } + else { + t = b1 + (Quot >> 1); + b = b2; + } + + + uint32 Width = Right - Left; + + register uint32 Tile; + if (Quot & 1) { + Tile = *(t++); + Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13)]; + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + } + + // Left hand edge clipped tile + uint32 Offset = (HPos & 7); + if (Offset){ + Count = 8 - Offset; + if (Count > Width) Count = Width; + s -= Offset; + if (!(Quot & 1)) { + Tile = *(t++); + Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13)]; + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + if (Tile != tb1) { + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); + tb1 = TileBlank; + } + } + else { + if (Tile & H_FLIP) Tile--; + else Tile++; + if (Quot == 63) t = b; + if (Tile != tb2) { + (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); + tb2 = TileBlank; + } + } + Quot++; + s += 8; + } + + // Middle, unclipped tiles + Count = Width - Count; + for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){ + if (!(Quot & 1)) { + Tile = *(t++); + Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13)]; + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + if (Tile != tb1){ + (*DrawTilePtr) (Tile, s, VirtAlign, Lines); + tb1 = TileBlank; + } + } + else { + if (Tile & H_FLIP) Tile--; + else Tile++; + if (Quot == 63) t = b; + if (Tile != tb2){ + (*DrawTilePtr) (Tile, s, VirtAlign, Lines); + tb2 = TileBlank; + } + } + } + + // Right-hand edge clipped tiles + if (Count & 7){ + if (!(Quot & 1)) { + Tile = *(t++); + Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13)]; + GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; + if (Tile != tb1) (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines); + } + else { + if (Tile & H_FLIP) Tile--; + else Tile++; + if (Tile != tb2) (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines); + } + } + clip ++; + } while (clip < clipcount); + } +} + + +static inline void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) +{ +//StartAnalyze(); + + BG.TileSize = BGSizes [PPU.BG[bg].BGSize]; + BG.BitShift = BitShifts[BGMode][bg]; + SelectConvertTile(); + BG.TileShift = TileShifts[BGMode][bg]; + BG.TileAddress = PPU.BG[bg].NameBase << 1; + //BG.NameSelect = 0; + BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]]; + BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]]; + BG.PaletteShift = PaletteShifts[BGMode][bg]; + BG.PaletteMask = PaletteMasks[BGMode][bg]; + BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 && (GFX.r2130 & 1); + + DBG("Draw Background.\n"); + + if (IPPU.DirectColourMapsNeedRebuild && BG.DirectColourMode) S9xBuildDirectColourMaps (); + + if (PPU.BGMosaic [bg] && PPU.Mosaic > 1){ + DrawBackgroundMosaic (BGMode, bg, Z1, Z2); + return; + + } + switch (BGMode) + { + case 2: + case 4: // Used by Puzzle Bobble + DrawBackgroundOffset (BGMode, bg, Z1, Z2); + break; + + case 5: + case 6: // XXX: is also offset per tile. + DrawBackgroundMode5 (BGMode, bg, Z1, Z2); + break; + case 0: + case 1: + case 3: + CHECK_SOUND(); + + if (BGMode == 0) BG.StartPalette = bg << 5; + else BG.StartPalette = 0; + SelectPalette(); + + if (BG.TileSize == 8) DrawBackground_8 (BGMode, bg, Z1, Z2); + else DrawBackground_16 (BGMode, bg, Z1, Z2); + break; + } +} + +#define _BUILD_SETUP(F) \ +GFX.BuildPixel = BuildPixel##F; \ +GFX.BuildPixel2 = BuildPixel2##F; \ +GFX.DecomposePixel = DecomposePixel##F; \ +RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_##F; \ +GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_##F; \ +BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_##F; \ +RED_HI_BIT_MASK = RED_HI_BIT_MASK_##F; \ +GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_##F; \ +BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_##F; \ +MAX_RED = MAX_RED_##F; \ +MAX_GREEN = MAX_GREEN_##F; \ +MAX_BLUE = MAX_BLUE_##F; \ +GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \ +SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \ +RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_##F | \ + GREEN_LOW_BIT_MASK_##F | \ + BLUE_LOW_BIT_MASK_##F); \ +RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_##F | \ + GREEN_HI_BIT_MASK_##F | \ + BLUE_HI_BIT_MASK_##F); \ +RGB_HI_BITS_MASKx2 = ((RED_HI_BIT_MASK_##F | \ + GREEN_HI_BIT_MASK_##F | \ + BLUE_HI_BIT_MASK_##F) << 1); \ +RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; \ +FIRST_COLOR_MASK = FIRST_COLOR_MASK_##F; \ +SECOND_COLOR_MASK = SECOND_COLOR_MASK_##F; \ +THIRD_COLOR_MASK = THIRD_COLOR_MASK_##F; \ +ALPHA_BITS_MASK = ALPHA_BITS_MASK_##F; \ +FIRST_THIRD_COLOR_MASK = FIRST_COLOR_MASK | THIRD_COLOR_MASK; \ +TWO_LOW_BITS_MASK = RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1); \ +HIGH_BITS_SHIFTED_TWO_MASK = (( (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & \ + ~TWO_LOW_BITS_MASK ) >> 2); + +void RenderScreen (uint8 *Screen, bool8_32 sub, bool8_32 force_no_add, uint8 D) +{ + bool8_32 BG0; + bool8_32 BG1; + bool8_32 BG2; + bool8_32 BG3; + bool8_32 OB; + + GFX.S = Screen; + + if (!sub) + { + GFX.pCurrentClip = &IPPU.Clip [0]; + BG0 = ON_MAIN (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0); + BG1 = ON_MAIN (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1); + BG2 = ON_MAIN (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2); + BG3 = ON_MAIN (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3); + OB = ON_MAIN (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); + } + else + { + GFX.pCurrentClip = &IPPU.Clip [1]; + BG0 = ON_SUB (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0); + BG1 = ON_SUB (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1); + BG2 = ON_SUB (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2); + BG3 = ON_SUB (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3); + OB = ON_SUB (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); + } + +#ifdef __DEBUG__ + printf("Screen[y1,y2]:[%i,%i],Mode:%i, BG0:%i,BG1:%i,BG2:%i,BG3:%i,OBJ:%i\n", GFX.StartY, GFX.EndY, PPU.BGMode, BG0, BG1, BG2, BG3, OB); +#endif + + sub |= force_no_add; + + if (PPU.BGMode <= 1) + { + if (OB) + { +#ifndef __FAST_OBJS__ + SelectTileRenderer (sub || !SUB_OR_ADD(4), false); +#else + SelectTileRenderer (sub || !SUB_OR_ADD(4), true); +#endif + DrawOBJS (!sub, D); + } + if (BG0) + { + SelectTileRenderer (sub || !SUB_OR_ADD(0), false); + DrawBackground (PPU.BGMode, 0, D + 10, D + 14); + } + if (BG1) + { + SelectTileRenderer (sub || !SUB_OR_ADD(1), false); + DrawBackground (PPU.BGMode, 1, D + 9, D + 13); + } + if (BG2) + { + SelectTileRenderer (sub || !SUB_OR_ADD(2), false); + DrawBackground (PPU.BGMode, 2, D + 3, + PPU.BG3Priority ? D + 17 : D + 6); + } + if (BG3 && PPU.BGMode == 0) + { + SelectTileRenderer (sub || !SUB_OR_ADD(3), false); + DrawBackground (PPU.BGMode, 3, D + 2, D + 5); + } + } + else if (PPU.BGMode != 7) + { + if (OB) + { +#ifndef __FAST_OBJS__ + SelectTileRenderer (sub || !SUB_OR_ADD(4), false); +#else + SelectTileRenderer (sub || !SUB_OR_ADD(4), true); +#endif + DrawOBJS (!sub, D); + } + if (BG0) + { + SelectTileRenderer (sub || !SUB_OR_ADD(0), false); + DrawBackground (PPU.BGMode, 0, D + 5, D + 13); + } + if (PPU.BGMode != 6 && BG1) + { + SelectTileRenderer (sub || !SUB_OR_ADD(1), false); + DrawBackground (PPU.BGMode, 1, D + 2, D + 9); + } + } + else + { + if (OB && ((SNESGameFixes.Mode7Hack && D) || !SNESGameFixes.Mode7Hack)) + { + SelectTileRenderer (sub || !SUB_OR_ADD(4), true); + DrawOBJS (!sub, D); + } + if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1)) + { + int bg; + + if ((Memory.FillRAM [0x2133] & 0x40)&&BG1) + { + Mode7Depths [0] = (BG0?5:1) + D; + Mode7Depths [1] = 9 + D; + bg = 1; + if (sub || !SUB_OR_ADD(0)) + { + DrawBGMode7Background16Prio (Screen, bg); + } + else + { + if (GFX.r2131 & 0x80) + { + if (GFX.r2131 & 0x40) + { + DrawBGMode7Background16PrioSub1_2 (Screen, bg); + } + else + { + DrawBGMode7Background16PrioSub (Screen, bg); + } + } + else + { + if (GFX.r2131 & 0x40) + { + DrawBGMode7Background16PrioAdd1_2 (Screen, bg); + } + else + { + DrawBGMode7Background16PrioAdd (Screen, bg); + } + } + } + } + else + { + bg = 0; + if (sub || !SUB_OR_ADD(0)) + { + if (D || !SNESGameFixes.Mode7Hack) DrawBGMode7Background16 (Screen, bg, D+5); + else DrawBGMode7Background16New (Screen); + } + else + { + if (GFX.r2131 & 0x80) + { + if (GFX.r2131 & 0x40) + { + DrawBGMode7Background16Sub1_2 (Screen, bg, D+5); + } + else + { + DrawBGMode7Background16Sub (Screen, bg, D+5); + } + } + else + { + if (GFX.r2131 & 0x40) + { + DrawBGMode7Background16Add1_2 (Screen, bg, D+5); + } + else + { + DrawBGMode7Background16Add (Screen, bg, D+5); + } + } + } + } + } + if (OB && SNESGameFixes.Mode7Hack && D==0) + { +#ifndef __FAST_OBJS__ + SelectTileRenderer (sub || !SUB_OR_ADD(4), false); +#else + SelectTileRenderer (sub || !SUB_OR_ADD(4), true); +#endif + DrawOBJS (!sub, D); + } + } +} + +#include "font.h" + +void DisplayChar (uint8 *Screen, uint8 c) +{ + int line = (((c & 0x7f) - 32) >> 4) * font_height; + int offset = (((c & 0x7f) - 32) & 15) * font_width; + int h, w; + uint16 *s = (uint16 *) Screen; + for (h = 0; h < font_height; h++, line++, + s += GFX_PPL - font_width) + { + for (w = 0; w < font_width; w++, s++) + { + uint8 p = font [line][offset + w]; + + if (p == '#') + *s = 0xffff; + else + if (p == '.') + *s = BLACK; + } + } +} + +static void S9xDisplayFrameRate () +{ + uint8 *Screen = GFX.Screen + 2 + + (IPPU.RenderedScreenHeight - font_height - 1) * GFX_PITCH; + char string [10]; + int len = 5; + + sprintf (string, "%02d/%02d", IPPU.DisplayedRenderedFrameCount, + (int) Memory.ROMFramesPerSecond); + + int i; + for (i = 0; i < len; i++) + { + DisplayChar (Screen, string [i]); + Screen += (font_width - 1) * sizeof (uint16); + } +} + +static void S9xDisplayString (const char *string) +{ + uint8 *Screen = GFX.Screen + 2 + + (IPPU.RenderedScreenHeight - font_height * 5) * GFX_PITCH; + int len = strlen (string); + int max_chars = IPPU.RenderedScreenWidth / (font_width - 1); + int char_count = 0; + int i; + + for (i = 0; i < len; i++, char_count++) + { + if (char_count >= max_chars || string [i] < 32) + { + Screen -= (font_width - 1) * sizeof (uint16) * max_chars; + Screen += font_height * GFX_PITCH; + if (Screen >= GFX.Screen + GFX_PITCH * IPPU.RenderedScreenHeight) + break; + char_count -= max_chars; + } + if (string [i] < 32) + continue; + DisplayChar (Screen, string [i]); + Screen += (font_width - 1) * sizeof (uint16); + } +} + +// -x- + +static void S9xUpdateScreenTransparency () // ~30-50ms! (called from FLUSH_REDRAW()) +{ + uint32 starty = GFX.StartY; + uint32 endy = GFX.EndY; + uint32 black = BLACK | (BLACK << 16); + + + if (GFX.Pseudo) + { + GFX.r2131 = 0x5f; //0101 1111 - enable addition/subtraction on all BGS and sprites and "1/2 OF COLOR DATA" DESIGNATION + GFX.r212c &= (GFX.r212d_s | 0xf0); + GFX.r212d |= (GFX.r212c_s & 0x0f); + GFX.r2130 |= 2; // enable ADDITION/SUBTRACTION FOR SUB SCREEN + } + + // Check to see if any transparency effects are currently in use + if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING && + (GFX.r2130 & 0x30) != 0x30 && + !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0)) + { + DBG("Transparency in use\n"); + // transparency effects in use, so lets get busy! + ClipData *pClip; + uint32 fixedColour; + GFX.FixedColour = BUILD_PIXEL (IPPU.XB[PPU.FixedColourRed], IPPU.XB[PPU.FixedColourGreen] , IPPU.XB[PPU.FixedColourBlue]); + fixedColour = (GFX.FixedColour<<16|GFX.FixedColour); + // Clear the z-buffer, marking areas 'covered' by the fixed + // colour as depth 1. + pClip = &IPPU.Clip [1]; + + // Clear the z-buffer + + if (pClip->Count [5]) + { + + DBG("Colour window enabled. Clearing...\n"); + + // Colour window enabled. + // loop around all of the lines being updated + for (uint32 y = starty; y <= endy; y++) + { + // Clear the subZbuffer + memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH),0, (256>>2)); + // Clear the Zbuffer + memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, (256>>2)); + if (IPPU.Clip[0].Count [5]) { + // if there is clipping then clear subscreen to a black color + memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), black, (256>>1)); + } + + // loop through all window clippings + for (uint32 c = 0; c < pClip->Count [5]; c++) + { + int width = pClip->Right [c][5] - pClip->Left [c][5]; + if (width > 0) { + + //if (pClip->Right [c][5] > pClip->Left [c][5]) + //{ + memset (GFX.SubZBuffer + y * GFX_ZPITCH + pClip->Left [c][5], + 1, width); //pClip->Right [c][5] - pClip->Left [c][5]); + + if (IPPU.Clip [0].Count [5]) + { + DBG("Clearing sub-screen. Clipping effects in use.\n"); + // Blast, have to clear the sub-screen to the fixed-colour + // because there is a colour window in effect clipping + // the main screen that will allow the sub-screen + // 'underneath' to show through. + + __asm__ volatile ( + " mov r0, %[fixedcolour] \n" + " subs %[width], %[width], #8 \n" + " bmi 2f \n" + " mov r1, r0 \n" + " mov r2, r0 \n" + + "1: \n" + " subs %[width], %[width], #8 \n" + " stmia %[p]!, {r0, r1, r2, %[fixedcolour]}\n" + " bpl 1b \n" + + "2: \n" + " tst %[width], #1 \n" + " strneh %[fixedcolour], [%[p]], #2 \n" + + " tst %[width], #2 \n" + " strne %[fixedcolour], [%[p]], #4 \n" + + " tst %[width], #4 \n" + " stmia %[p]!, {r0, %[fixedcolour]}\n" + + : [width] "+r" (width) + : [fixedcolour] "r" (fixedColour), + [p] "r" (((uint16 *) (GFX.SubScreen + y * GFX_PITCH)) + pClip->Left [c][5]) + : "r0", "r1", "r2", "cc" + ); + //} + } + } + } + } + + } + else + { + DBG("No windows clipping the main screen.\n"); + + // No windows are clipping the main screen + // this simplifies the screen clearing process + // loop through all of the lines to be updated + for (uint32 y = starty; y <= endy; y++) { + // Clear the Zbuffer + memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, (256>>2)); + // clear the sub Zbuffer to 1 + memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH), 0x01010101, (256>>2)); + + if (IPPU.Clip [0].Count [5]) { + // Blast, have to clear the sub-screen to the fixed-colour + // because there is a colour window in effect clipping + // the main screen that will allow the sub-screen + // 'underneath' to show through. + memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), fixedColour, (256>>1)); + } + } + } + + if (ANYTHING_ON_SUB) + { + DBG("Rendering SubScreen...\n"); + GFX.DB = GFX.SubZBuffer; + RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH); + } + + if (IPPU.Clip [0].Count [5]) + { + DBG("Copying from SubScreen to the Main Screen\n"); + + __asm__ volatile ( + "1: \n" + " mov r1, #(256 >> 2) \n" + + "2: \n" + // four pixels at once + " ldrb r0, [%[d]], #1 \n" + " ldrb r3, [%[d]], #1 \n" + + " bics r0, r0, #1 \n" + " ldrneh r0, [%[p], %[delta]] \n" + + " bics r3, r3, #1 \n" + " ldrneh r3, [%[p], %[delta2]] \n" + + " strh r0, [%[p]], #2 \n" + " ldrb r0, [%[d]], #1 \n" + " strh r3, [%[p]], #2 \n" + " ldrb r3, [%[d]], #1 \n" + + " bics r0, r0, #1 \n" + " ldrneh r0, [%[p], %[delta]] \n" + + " bics r3, r3, #1 \n" + " ldrneh r3, [%[p], %[delta2]] \n" + + " strh r0, [%[p]], #2 \n" + " strh r3, [%[p]], #2 \n" + + " subs r1, r1, #1 \n" + " bne 2b \n" + "3: \n" + " subs %[lines], %[lines], #1 \n" + " addne %[p], %[p], #(640 - 512) \n" + " addne %[d], %[d], #(320 - 256) \n" + " bne 1b \n" + "4: \n" + + : + : [p] "r" ((uint16 *) (GFX.Screen + starty * GFX_PITCH)), + [d] "r" (GFX.SubZBuffer + starty * GFX_ZPITCH), + [delta] "r" (GFX.Delta << 1), + [delta2] "r" ((GFX.Delta << 1) + 2), + [lines] "r" (endy - starty + 1) + : "r0", "r1", "r3", "cc" + ); + } + + DBG("Rendering the Main Screen...\n"); + + GFX.DB = GFX.ZBuffer; + RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH); + + if (SUB_OR_ADD(5)) + { + uint32 back = IPPU.ScreenColors [0]; + uint32 Left = 0; + uint32 Right = 256; + uint32 Count; + + DBG("Addition/Substraction in use...\n"); + + pClip = &IPPU.Clip [0]; + + // some initial values + unsigned int fixedcolour_c; + if (GFX.r2131 & 0x80) { + fixedcolour_c = COLOR_SUB(back, GFX.FixedColour); + } else { + fixedcolour_c = COLOR_ADD(back, GFX.FixedColour); + } + + if (!(Count = pClip->Count [5])) Count = 1; + for (uint32 y = starty; y <= endy; y++) + { + + for (uint32 b = 0; b < Count; b++) + { + if (pClip->Count [5]) + { + Left = pClip->Left [b][5]; + Right = pClip->Right [b][5]; + if (Right <= Left) + continue; + } +#define _ROP_ADD1_2 \ + " mov r0, %[back] \n"\ + ROP_ADD1_2(r0, r1) \ + " strh r0, [%[p]] \n" + +// Arguments can be exchanged on addition, so early exit on back == 0 is possible +#define _ROP_ADD \ + ROP_ADD(r1, %[back]) \ + " strh r1, [%[p]] \n" + + +#define _ROP_SUB1_2 \ + " mov r0, %[back] \n"\ + ROP_SUB1_2(r0, r1) \ + " strh r0, [%[p]] \n" + +#define _ROP_SUB \ +" mov r0, %[back] \n"\ + ROP_SUB(r0, r1) \ + " strh r0, [%[p]] \n" + +#define SUBSCREEN_BG(rop, half) \ +\ +__asm__ volatile (\ +" ldrb r0, [%[d]] \n"\ +"71: \n"\ +\ +" movs r0, r0 \n"\ +" ldreqb r1, [%[d], %[zdelta]] \n"\ +" bne 72f \n"\ +\ +" cmp r1, #1 \n"\ +" ldrhih r1, [%[p], %[delta]] \n"\ +" bls 74f \n"\ +\ +_ROP_##rop##half \ +\ +"72: \n"\ +" add %[p], %[p], #2 \n"\ +" subs %[c], %[c], #1 \n"\ +" ldrneb r0, [%[d], #1]! \n"\ +" bne 71b \n"\ +" b 75f \n"\ +"74: \n"\ +" streqh %[fixedcolour], [%[p]], #2 \n"\ +" strloh %[back], [%[p]], #2 \n"\ +" subs %[c], %[c], #1 \n"\ +" ldrneb r0, [%[d], #1]! \n"\ +" bne 71b \n"\ +"75: \n"\ +:\ +:[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left),\ + [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left),\ + [zdelta] "r" (GFX.DepthDelta),\ + [back] "r" (back),\ + [delta] "r" (GFX.Delta << 1),\ + [fixedcolour] "r" (fixedcolour_c),\ + [c] "r" (Right - Left) \ +: "r0", "r1", "cc"\ +); + if (GFX.r2131 & 0x80) + { + if (GFX.r2131 & 0x40) + { + SUBSCREEN_BG(SUB, 1_2) + } + else + { + SUBSCREEN_BG(SUB, ) + + } + } + else + if (GFX.r2131 & 0x40) + { + SUBSCREEN_BG(ADD, 1_2) + } + else if (back != 0) { + SUBSCREEN_BG(ADD, ) + } + else + { + + if (!pClip->Count [5]) + { + DBG("Copying line with no effect...\n"); + // The backdrop has not been cleared yet - so + // copy the sub-screen to the main screen + // or fill it with the back-drop colour if the + // sub-screen is clear. + __asm__ volatile ( + " ldrb r0, [%[d]] \n" + "31: \n" + + " movs r0, r0 \n" + " ldreqb r1, [%[d], %[zdelta]] \n" + " bne 32f \n" + + " cmp r1, #1 \n" + " ldrhih r0, [%[p], %[delta]] \n" + " strloh %[back], [%[p]] \n" + " streqh %[fixedcolour], [%[p]] \n" + " strhih r0, [%[p]] \n" + + "32: \n" + " subs %[c], %[c], #1 \n" + " add %[p], %[p], #2 \n" + " ldrneb r0, [%[d], #1]! \n" + " bne 31b \n" + " \n" + : + :[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left), + [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left), + [zdelta] "r" (GFX.DepthDelta), + [back] "r" (back), + [delta] "r" (GFX.Delta << 1), + [fixedcolour] "r" (GFX.FixedColour), + [c] "r" (Right - Left) + : "r0", "r1", "cc" + + ); + + } + } + } + } + + } + else + { + + // Subscreen not being added to back + DBG("No addition/substraction in use...\n"); + uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); + pClip = &IPPU.Clip [0]; + + if (pClip->Count [5]) + { + + DBG("Copying subscreen with clipping...\n"); + + for (uint32 y = starty; y <= endy; y++) + { + for (uint32 b = 0; b < pClip->Count [5]; b++) + { + uint32 Left = pClip->Left [b][5]; + uint32 Right = pClip->Right [b][5]; + if (Left >= Right) continue; + __asm__ volatile ( + + " tst %[c], #1 \n" + " bne 21f \n" + + " ldrb r0, [%[d]], #1 \n" + " add %[p], %[p], #2 \n" + " movs r0, r0 \n" + " streqh %[back], [%[p], #-2] \n" + " subs %[c], %[c], #1 \n" + " beq 22f \n" + + "21: \n" + + " ldrb r0, [%[d]], #1 \n" + " ldrb r1, [%[d]], #1 \n" + " add %[p], %[p], #4 \n" + + " movs r0, r0 \n" + " streqh %[back], [%[p], #-4] \n" + + " movs r1, r1 \n" + " streqh %[back], [%[p], #-2] \n" + + " subs %[c], %[c], #2 \n" + " bhi 21b \n" + "22: \n" + : + :[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left), + [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left), + [back] "r" (back), + [c] "r" (Right - Left) + : "r0", "r1", "cc" + + ); + } + } + } + else + { + DBG("Copying SubScreen with no clipping...\n"); + + __asm__ volatile ( + "@ -- SubScreen clear \n" + "1113: \n" + " mov r1, #(256/8) \n" + "1112: \n" + " ldr r0, [%[d]], #4 \n" + + " add %[p], %[p], #8 \n" + + " tst r0, #0x0ff \n" + " streqh %[back], [%[p], #-8] \n" + + " tst r0, #0x0ff00 \n" + " streqh %[back], [%[p], #-6] \n" + + " tst r0, #0x0ff0000 \n" + " streqh %[back], [%[p], #-4] \n" + + " tst r0, #0x0ff000000 \n" + " streqh %[back], [%[p], #-2] \n" + + " ldr r0, [%[d]], #4 \n" + + " add %[p], %[p], #8 \n" + + " tst r0, #0x0ff \n" + " streqh %[back], [%[p], #-8] \n" + + " tst r0, #0x0ff00 \n" + " streqh %[back], [%[p], #-6] \n" + + " tst r0, #0x0ff0000 \n" + " streqh %[back], [%[p], #-4] \n" + + " tst r0, #0x0ff000000 \n" + " streqh %[back], [%[p], #-2] \n" + + " subs r1, r1, #1 \n" + " bne 1112b \n" + + " subs %[lines], %[lines], #1 \n" + " add %[p], %[p], #(640-512) \n" + " add %[d], %[d], #(320-256) \n" + " bne 1113b \n" + "1114:" + : + :[p] "r" (GFX.Screen + starty * GFX_PITCH), + [d] "r" (GFX.ZBuffer + starty * GFX_ZPITCH), + [back] "r" (back), + [lines] "r" (endy - starty + 1) + : "r0", "r1", "cc" + ); + } + } + + } + else + { + DBG("No transparency effects in use.\n"); + + // 16bit and transparency but currently no transparency effects in + // operation. + + // get the back colour of the current screen + uint32 back = IPPU.ScreenColors [0] | + (IPPU.ScreenColors [0] << 16); + + // if forceblanking in use then use black instead of the back color + if (PPU.ForcedBlanking) + back = black; + + // not sure what Clip is used for yet + // could be a check to see if there is any clipping present? + if (IPPU.Clip [0].Count[5]) + { + DBG("Clearing background with clipping...\n"); + + // loop through all of the lines that are going to be updated as part of this screen update + for (uint32 y = starty; y <= endy; y++) + { + memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), black, + IPPU.RenderedScreenWidth>>1); + + if (black!=back) + { + for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++) + { + //if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5]) + //{ + register int width = IPPU.Clip [0].Right [c][5] - IPPU.Clip [0].Left [c][5]; + if (width <= 0) continue; + + __asm__ volatile ( + " mov r0, %[back] \n" + " subs %[width], %[width], #8 \n" + " bmi 2f \n" + " mov r1, r0 \n" + " mov r2, r0 \n" + + "1: \n" + " subs %[width], %[width], #8 \n" + " stmia %[p]!, {r0, r1, r2, %[back]}\n" + " bpl 1b \n" + + "2: \n" + " tst %[width], #1 \n" + " strneh %[back], [%[p]], #2 \n" + + " tst %[width], #2 \n" + " strne %[back], [%[p]], #4 \n" + + " tst %[width], #4 \n" + " stmia %[p]!, {r0, %[back]}\n" + + : [width] "+r" (width) + : [back] "r" (back | (back << 16)), + [p] "r" (((uint16 *) (GFX.SubScreen + y * GFX_PITCH)) + IPPU.Clip [0].Left [c][5]) + : "r0", "r1", "r2", "cc" + ); + //} + } + } + } + + } + else + { + DBG("Clearing background with no clipping...\n"); + + // there is no clipping to worry about so just fill with the back colour + for (uint32 y = starty; y <= endy; y++) { + memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back, (256>>1)); + } + + } + + // If Forced blanking is not in effect + if (!PPU.ForcedBlanking) + { + DBG("Forced Blanking not in use. Clearing ZBuffer ... !!\n"); + // Clear the Zbuffer for each of the lines which are going to be updated + for (uint32 y = starty; y <= endy; y++) { + memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0, (256>>2)); + } + DBG("Rendering screen !!\n"); + GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object + RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH); + + } + } + IPPU.PreviousLine = IPPU.CurrentLine; +} + +static void S9xUpdateScreenNoTransparency () // ~30-50ms! (called from FLUSH_REDRAW()) +{ + uint32 starty = GFX.StartY; + uint32 endy = GFX.EndY; + + uint32 black = BLACK | (BLACK << 16); + + // get back colour to be used in clearing the screen + register uint32 back; + if (!(GFX.r2131 & 0x80) && (GFX.r2131 & 0x20) && + (PPU.FixedColourRed || PPU.FixedColourGreen || PPU.FixedColourBlue)) + { + back = (PPU.FixedColourRed << 11) | (PPU.FixedColourGreen << 6) | (1 << 5) | (PPU.FixedColourBlue); + back = (back << 16) | back; + } + else + { + back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); + } + + // if Forcedblanking in use then back colour becomes black + if (PPU.ForcedBlanking) + back = black; + else + { + SelectTileRenderer (TRUE, false); //selects the tile renderers to be used + // TRUE means to use the default + // FALSE means use best renderer based on current + // graphics register settings + } + + // now clear all graphics lines which are being updated using the back colour + for (register uint32 y = starty; y <= endy; y++) + { + memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back, + IPPU.RenderedScreenWidth>>1); + } + + if (!PPU.ForcedBlanking) + { + // Loop through all lines being updated and clear the + // zbuffer for each of the lines + for (uint32 y = starty; y <= endy; y++) + { + memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0, + IPPU.RenderedScreenWidth>>2); + } + GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object + GFX.pCurrentClip = &IPPU.Clip [0]; + +// Define an inline function to handle clipping +#define FIXCLIP(n) \ +if (GFX.r212c & (1 << (n))) \ + GFX.pCurrentClip = &IPPU.Clip [0]; \ +else \ + GFX.pCurrentClip = &IPPU.Clip [1] + +// Define an inline function to handle which BGs are being displayed +#define DISPLAY(n) ((GFX.r212c & n) || ((GFX.r212d & n) && subadd)) + + uint8 subadd = GFX.r2131 & 0x3f; + + // go through all BGS are check if they need to be displayed + bool8_32 BG0 = DISPLAY(1) && !(Settings.os9x_hack & GFX_IGNORE_BG0); + bool8_32 BG1 = DISPLAY(2) && !(Settings.os9x_hack & GFX_IGNORE_BG1); + bool8_32 BG2 = DISPLAY(4) && !(Settings.os9x_hack & GFX_IGNORE_BG2); + bool8_32 BG3 = DISPLAY(8) && !(Settings.os9x_hack & GFX_IGNORE_BG3); + bool8_32 OB = DISPLAY(16) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); + + if (PPU.BGMode <= 1) + { + // screen modes 0 and 1 + if (OB) + { + FIXCLIP(4); + DrawOBJS (FALSE, 0); + } + if (BG0) + { + FIXCLIP(0); + DrawBackground (PPU.BGMode, 0, 10, 14); + } + if (BG1) + { + FIXCLIP(1); + DrawBackground (PPU.BGMode, 1, 9, 13); + } + if (BG2) + { + FIXCLIP(2); + DrawBackground (PPU.BGMode, 2, 3, + PPU.BG3Priority ? 17 : 6); + } + if (BG3 && PPU.BGMode == 0) + { + FIXCLIP(3); + DrawBackground (PPU.BGMode, 3, 2, 5); + } + } + else if (PPU.BGMode != 7) + { + // screen modes 2 and up but not mode 7 + if (OB) + { + FIXCLIP(4); + DrawOBJS (FALSE, 0); + } + if (BG0) + { + FIXCLIP(0); + DrawBackground (PPU.BGMode, 0, 5, 13); + } + if (BG1 && PPU.BGMode != 6) + { + FIXCLIP(1); + DrawBackground (PPU.BGMode, 1, 2, 9); + } + } + else + { + // screen mode 7 + DrawBGMode7Background16New (GFX.Screen); + if (OB) + { + FIXCLIP(4); + DrawOBJS (FALSE, 0); + } + } + } + IPPU.PreviousLine = IPPU.CurrentLine; +} + +#ifdef __OLD_RASTER_FX__ +static void S9xUpdateScreen_delayedRasterFx () // ~30-50ms! (called from FLUSH_REDRAW()) +#else +void S9xUpdateScreen () // ~30-50ms! (called from FLUSH_REDRAW()) +#endif +{ + int StartY, EndY, CurrentLine, CurrentROp; + + StartY = IPPU.PreviousLine; + if ((EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) EndY = PPU.ScreenHeight - 1; + + GFX.S = GFX.Screen; + + CurrentROp = 0; + CurrentLine = StartY; +#ifdef __DEBUG__ + printf("Start screen update. ROPCount: %d, StartY: %d, EndY: %d\n", ROpCount, StartY, EndY); +#endif + do { + while ((CurrentROp < ROpCount) && ((rops[CurrentROp].line == CurrentLine) || (!wouldRasterAlterStatus(&rops[CurrentROp])))) { + #ifdef __DEBUG__ + printf("Processing ROP %d/%d. Line: %d\n", CurrentROp, ROpCount, CurrentLine); + #endif + doRaster(&rops[CurrentROp]); + CurrentROp++; + } + + GFX.StartY = CurrentLine; + if ((CurrentROp < ROpCount) && ((rops[CurrentROp].line - 1) <= EndY)) GFX.EndY = rops[CurrentROp].line - 1; + else GFX.EndY = EndY; + + #ifdef __DEBUG__ + printf("Partial screen update. ROPCount: %d, StartY: %d, EndY: %d\n", ROpCount, GFX.StartY, GFX.EndY); + #endif + + // get local copies of vid registers to be used later + GFX.r2131 = GFX.r2131_s; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN + GFX.r212c = GFX.r212c_s; // MAIN SCREEN, DESIGNATION - used to enable BGS + GFX.r212d = GFX.r212d_s; // SUB SCREEN DESIGNATION - used to enable sub BGS + GFX.r2130 = GFX.r2130_s; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION + + // If external sync is off and + // main screens have not been configured the same as the sub screen and + // color addition and subtraction has been disabled then + // Pseudo is 1 + // anything else it is 0 + GFX.Pseudo = (Memory.FillRAM[0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION? + (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens? + (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS? + + // If sprite data has been changed then go through and + // refresh the sprites. + if (IPPU.OBJChanged) { + #ifdef __DEBUG__ + printf("Objects changed !! setting up Objects...\n"); + #endif + S9xSetupOBJ(); + } + + if (PPU.RecomputeClipWindows) { + #ifdef __DEBUG__ + printf("Clipping changed !! recalculating clipping...\n"); + #endif + ComputeClipWindows(); + } + + if (Settings.Transparency) S9xUpdateScreenTransparency(); + else S9xUpdateScreenNoTransparency(); + CurrentLine = GFX.EndY + 1; + + #ifdef __DEBUG__ + printf("Finished partial screen update.\n", ROpCount, StartY, EndY); + #endif + + + } while ((CurrentROp < ROpCount) && (CurrentLine <= EndY)); + +#ifdef __DEBUG__ + printf("End screen update. ROPCount: %d, CurrentROp: %d, StartY: %d, EndY: %d\n", ROpCount, CurrentROp, StartY, EndY); +#endif + + RESET_ROPS(CurrentROp); + +#ifdef __DEBUG__ + printf("ROps cleaned\n"); +#endif + + PPU.BG[0].OffsetsChanged = 0; + PPU.BG[1].OffsetsChanged = 0; + PPU.BG[2].OffsetsChanged = 0; + PPU.BG[3].OffsetsChanged = 0; +} + +#ifdef __OLD_RASTER_FX__ + +static void S9xUpdateScreen_normalRasterFx () // ~30-50ms! (called from FLUSH_REDRAW()) +{ + GFX.StartY = IPPU.PreviousLine; + if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) GFX.EndY = PPU.ScreenHeight - 1; + + GFX.S = GFX.Screen; + +#ifdef __DEBUG__ + printf("Start screen update. StartY: %d, EndY: %d\n", GFX.StartY, GFX.EndY); +#endif + // get local copies of vid registers to be used later + GFX.r2131 = GFX.r2131_s; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN + GFX.r212c = GFX.r212c_s; // MAIN SCREEN, DESIGNATION - used to enable BGS + GFX.r212d = GFX.r212d_s; // SUB SCREEN DESIGNATION - used to enable sub BGS + GFX.r2130 = GFX.r2130_s; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION + + // If external sync is off and + // main screens have not been configured the same as the sub screen and + // color addition and subtraction has been disabled then + // Pseudo is 1 + // anything else it is 0 + GFX.Pseudo = (Memory.FillRAM[0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION? + (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens? + (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS? + + // If sprite data has been changed then go through and + // refresh the sprites. + if (IPPU.OBJChanged) { + #ifdef __DEBUG__ + printf("Objects changed !! setting up Objects...\n"); + #endif + S9xSetupOBJ(); + } + + if (PPU.RecomputeClipWindows) { + #ifdef __DEBUG__ + printf("Clipping changed !! recalculating clipping...\n"); + #endif + ComputeClipWindows(); + } + + if (Settings.Transparency) S9xUpdateScreenTransparency(); + else S9xUpdateScreenNoTransparency(); + +#ifdef __DEBUG__ + printf("End screen update. StartY: %d, EndY: %d\n", GFX.StartY, GFX.EndY); +#endif + PPU.BG[0].OffsetsChanged = 0; + PPU.BG[1].OffsetsChanged = 0; + PPU.BG[2].OffsetsChanged = 0; + PPU.BG[3].OffsetsChanged = 0; +} + +void S9xUpdateScreen() +{ + if (snesMenuOptions.delayedRasterFX) S9xUpdateScreen_delayedRasterFx(); + else S9xUpdateScreen_normalRasterFx (); +} +#endif + +// -x- + +#ifdef GFX_MULTI_FORMAT + +#define _BUILD_PIXEL(F) \ +uint32 BuildPixel##F(uint32 R, uint32 G, uint32 B) \ +{ \ + return (BUILD_PIXEL_##F(R,G,B)); \ +}\ +uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \ +{ \ + return (BUILD_PIXEL2_##F(R,G,B)); \ +} \ +void DecomposePixel##F(uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \ +{ \ + DECOMPOSE_PIXEL_##F(pixel,R,G,B); \ +} + +_BUILD_PIXEL(RGB565) +_BUILD_PIXEL(RGB555) +_BUILD_PIXEL(BGR565) +_BUILD_PIXEL(BGR555) +_BUILD_PIXEL(GBR565) +_BUILD_PIXEL(GBR555) +_BUILD_PIXEL(RGB5551) + +bool8_32 S9xSetRenderPixelFormat (int format) +{ + extern uint32 current_graphic_format; + + current_graphic_format = format; + + switch (format) + { + case RGB565: + _BUILD_SETUP(RGB565) + return (TRUE); + case RGB555: + _BUILD_SETUP(RGB555) + return (TRUE); + case BGR565: + _BUILD_SETUP(BGR565) + return (TRUE); + case BGR555: + _BUILD_SETUP(BGR555) + return (TRUE); + case GBR565: + _BUILD_SETUP(GBR565) + return (TRUE); + case GBR555: + _BUILD_SETUP(GBR555) + return (TRUE); + case RGB5551: + _BUILD_SETUP(RGB5551) + return (TRUE); + default: + break; + } + return (FALSE); +} +#endif diff --git a/src/gfx16.cpp b/src/gfx16.cpp deleted file mode 100644 index 3ac95ca..0000000 --- a/src/gfx16.cpp +++ /dev/null @@ -1,3443 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include "snes9x.h" - -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "display.h" -#include "gfx.h" -#include "apu.h" -#include "cheats.h" -#include -#include "asmmemfuncs.h" -#include "mode7.h" -#include "rops.h" -#include "tile16.h" -uint32 TileBlank; - -//#define __DEBUG__ - -#ifdef __DEBUG__ - #define DBG(b) printf(b) -#else - #define DBG(b) -#endif - - -const int tx_table[16] = { -// t1 = 16, t2 = 0 - // FLIP = 0x00 - 16 + 0, // 0x00 - 16 + 1, // 0x01 - - // FLIP = 0x01 - 16 + 1 - 0, // 0x02 - 16 + 1 - 1, // 0x03 - - // FLIP = 0x02 - 0 + 0, // 0x04 - 0 + 1, // 0x05 - - // FLIP = 0x03 - 0 + 1 - 0, // 0x06 - 0 + 1 - 1, // 0x07 - -// t1 = 0, t2 = 16 - // FLIP = 0x00 - 0 + 0, // 0x08 - 0 + 1, // 0x09 - - // FLIP = 0x01 - 0 + 1 - 0, // 0x0A - 0 + 1 - 1, // 0x0B - - // FLIP = 0x02 - 16 + 0, // 0x0C - 16 + 1, // 0x0D - - // FLIP = 0x03 - 16 + 1 - 0, // 0x0E - 16 + 1 - 1 // 0x0F -}; - -#define M7 19 -#define M8 19 - -void ComputeClipWindows (); -static void S9xDisplayFrameRate (); -static void S9xDisplayString (const char *string); - -extern uint8 BitShifts[8][4]; -extern uint8 TileShifts[8][4]; -extern uint8 PaletteShifts[8][4]; -extern uint8 PaletteMasks[8][4]; -extern uint8 Depths[8][4]; -extern uint8 BGSizes [2]; - -extern NormalTileRenderer DrawTilePtr; -extern ClippedTileRenderer DrawClippedTilePtr; -extern NormalTileRenderer DrawHiResTilePtr; -extern ClippedTileRenderer DrawHiResClippedTilePtr; -extern LargePixelRenderer DrawLargePixelPtr; - -extern struct SBG BG; - -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; - -extern uint8 Mode7Depths [2]; - -#define ON_MAIN(N) (GFX.r212c & (1 << (N))) - -#define SUB_OR_ADD(N) \ -(GFX.r2131 & (1 << (N))) - -#define ON_SUB(N) \ -((GFX.r2130 & 0x30) != 0x30 && \ - (GFX.r2130 & 2) && \ - (GFX.r212d & (1 << N))) - -#define ANYTHING_ON_SUB \ -((GFX.r2130 & 0x30) != 0x30 && \ - (GFX.r2130 & 2) && \ - (GFX.r212d & 0x1f)) - -#define ADD_OR_SUB_ON_ANYTHING \ -(GFX.r2131 & 0x3f) - -#define BLACK BUILD_PIXEL(0,0,0) - -void DrawNoZTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount); -void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile16x2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); -void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); -void DrawLargePixel16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawNoZTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Add (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawNoZTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawNoZTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - - -void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Sub (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawNoZTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - - -void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount); - -void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Add (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Sub (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount); - -void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount); - -void DrawHiResTile16 (uint32 Tile, uint32 Offset, - uint32 StartLine, uint32 LineCount); - -bool8_32 S9xGraphicsInit () -{ - register uint32 PixelOdd = 1; - register uint32 PixelEven = 2; - -#ifdef GFX_MULTI_FORMAT - if (GFX.BuildPixel == NULL) - S9xSetRenderPixelFormat (RGB565); -#endif - - for (uint8 bitshift = 0; bitshift < 4; bitshift++) - { - for (register int i = 0; i < 16; i++) - { - register uint32 h = 0; - register uint32 l = 0; - -#if defined(LSB_FIRST) -// Wiz usa LSB_FIRST - if (i & 8) - h |= PixelOdd; - if (i & 4) - h |= PixelOdd << 8; - if (i & 2) - h |= PixelOdd << 16; - if (i & 1) - h |= PixelOdd << 24; - if (i & 8) - l |= PixelOdd; - if (i & 4) - l |= PixelOdd << 8; - if (i & 2) - l |= PixelOdd << 16; - if (i & 1) - l |= PixelOdd << 24; -#else - if (i & 8) - h |= (PixelOdd << 24); - if (i & 4) - h |= (PixelOdd << 16); - if (i & 2) - h |= (PixelOdd << 8); - if (i & 1) - h |= PixelOdd; - if (i & 8) - l |= (PixelOdd << 24); - if (i & 4) - l |= (PixelOdd << 16); - if (i & 2) - l |= (PixelOdd << 8); - if (i & 1) - l |= PixelOdd; -#endif - - odd_high[bitshift][i] = h; - odd_low[bitshift][i] = l; - h = l = 0; - -#if defined(LSB_FIRST) - if (i & 8) - h |= PixelEven; - if (i & 4) - h |= PixelEven << 8; - if (i & 2) - h |= PixelEven << 16; - if (i & 1) - h |= PixelEven << 24; - if (i & 8) - l |= PixelEven; - if (i & 4) - l |= PixelEven << 8; - if (i & 2) - l |= PixelEven << 16; - if (i & 1) - l |= PixelEven << 24; -#else - if (i & 8) - h |= (PixelEven << 24); - if (i & 4) - h |= (PixelEven << 16); - if (i & 2) - h |= (PixelEven << 8); - if (i & 1) - h |= PixelEven; - if (i & 8) - l |= (PixelEven << 24); - if (i & 4) - l |= (PixelEven << 16); - if (i & 2) - l |= (PixelEven << 8); - if (i & 1) - l |= PixelEven; -#endif - - even_high[bitshift][i] = h; - even_low[bitshift][i] = l; - } - PixelEven <<= 2; - PixelOdd <<= 2; - } - - GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; - GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; - //GFX.InfoStringTimeout = 0; - //GFX.InfoString = NULL; - - PPU.BG_Forced = 0; - IPPU.OBJChanged = TRUE; - - IPPU.DirectColourMapsNeedRebuild = TRUE; - DrawTilePtr = DrawTile16; - DrawClippedTilePtr = DrawClippedTile16; - DrawLargePixelPtr = DrawLargePixel16; - DrawHiResTilePtr= DrawHiResTile16; - DrawHiResClippedTilePtr = DrawHiResClippedTile16; - S9xFixColourBrightness (); - - if (!(GFX.X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000))) - return (FALSE); - - if (!(GFX.ZERO_OR_X2 = (uint16 *) malloc (sizeof (uint16) * 0x10000)) || - !(GFX.ZERO = (uint16 *) malloc (sizeof (uint16) * 0x10000))) - { - if (GFX.ZERO_OR_X2) - { - free ((char *) GFX.ZERO_OR_X2); - GFX.ZERO_OR_X2 = NULL; - } - if (GFX.X2) - { - free ((char *) GFX.X2); - GFX.X2 = NULL; - } - return (FALSE); - } - uint32 r, g, b; - - // Build a lookup table that multiplies a packed RGB value by 2 with - // saturation. - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r << 1; - if (r2 > MAX_RED) - r2 = MAX_RED; - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g << 1; - if (g2 > MAX_GREEN) - g2 = MAX_GREEN; - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b << 1; - if (b2 > MAX_BLUE) - b2 = MAX_BLUE; - GFX.X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); - GFX.X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); - } - } - } - ZeroMemory (GFX.ZERO, 0x10000 * sizeof (uint16)); - ZeroMemory (GFX.ZERO_OR_X2, 0x10000 * sizeof (uint16)); - // Build a lookup table that if the top bit of the color value is zero - // then the value is zero, otherwise multiply the value by 2. Used by - // the color subtraction code. - -#if defined(OLD_COLOUR_BLENDING) - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r; - if ((r2 & 0x10) == 0) - r2 = 0; - else - r2 = (r2 << 1) & MAX_RED; - - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g; - if ((g2 & GREEN_HI_BIT) == 0) - g2 = 0; - else - g2 = (g2 << 1) & MAX_GREEN; - - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b; - if ((b2 & 0x10) == 0) - b2 = 0; - else - b2 = (b2 << 1) & MAX_BLUE; - - GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); - GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); - } - } - } -#else - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r; - if ((r2 & 0x10) == 0) - r2 = 0; - else - r2 = (r2 << 1) & MAX_RED; - - if (r2 == 0) - r2 = 1; - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g; - if ((g2 & GREEN_HI_BIT) == 0) - g2 = 0; - else - g2 = (g2 << 1) & MAX_GREEN; - - if (g2 == 0) - g2 = 1; - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b; - if ((b2 & 0x10) == 0) - b2 = 0; - else - b2 = (b2 << 1) & MAX_BLUE; - - if (b2 == 0) - b2 = 1; - GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); - GFX.ZERO_OR_X2 [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); - } - } - } -#endif - - // Build a lookup table that if the top bit of the color value is zero - // then the value is zero, otherwise its just the value. - for (r = 0; r <= MAX_RED; r++) - { - uint32 r2 = r; - if ((r2 & 0x10) == 0) - r2 = 0; - else - r2 &= ~0x10; - - for (g = 0; g <= MAX_GREEN; g++) - { - uint32 g2 = g; - if ((g2 & GREEN_HI_BIT) == 0) - g2 = 0; - else - g2 &= ~GREEN_HI_BIT; - for (b = 0; b <= MAX_BLUE; b++) - { - uint32 b2 = b; - if ((b2 & 0x10) == 0) - b2 = 0; - else - b2 &= ~0x10; - - GFX.ZERO [BUILD_PIXEL2 (r, g, b)] = BUILD_PIXEL2 (r2, g2, b2); - GFX.ZERO [BUILD_PIXEL2 (r, g, b) & ~ALPHA_BITS_MASK] = BUILD_PIXEL2 (r2, g2, b2); - } - } - } - - return (TRUE); -} - -void S9xGraphicsDeinit (void) -{ - // Free any memory allocated in S9xGraphicsInit - if (GFX.X2) - { - free ((char *) GFX.X2); - GFX.X2 = NULL; - } - if (GFX.ZERO_OR_X2) - { - free ((char *) GFX.ZERO_OR_X2); - GFX.ZERO_OR_X2 = NULL; - } - if (GFX.ZERO) - { - free ((char *) GFX.ZERO); - GFX.ZERO = NULL; - } -} - -void S9xBuildDirectColourMaps () -{ - for (uint32 p = 0; p < 8; p++) - { - for (uint32 c = 0; c < 256; c++) - { -// XXX: Brightness - /* - DirectColourMaps [p][c] = BUILD_PIXEL (IPPU.XB[((c & 7) << 2) | ((p & 1) << 1)], - IPPU.XB[((c & 0x38) >> 1) | (p & 2)], - IPPU.XB[((c & 0xc0) >> 3) | (p & 4)]); - */ - DirectColourMaps [p][c] = BUILD_PIXEL (((c & 7) << 2) | ((p & 1) << 1), - ((c & 0x38) >> 1) | (p & 2), - ((c & 0xc0) >> 3) | (p & 4)); - - } - } - IPPU.DirectColourMapsNeedRebuild = FALSE; -} - -void S9xStartScreenRefresh () -{ - RESET_ROPS(0); - - if (IPPU.RenderThisFrame) - { - if (!S9xInitUpdate ()) - { - IPPU.RenderThisFrame = FALSE; - return; - } - IPPU.RenderedFramesCount++; - IPPU.PreviousLine = IPPU.CurrentLine = 0; - IPPU.MaxBrightness = PPU.Brightness; - IPPU.LatchedBlanking = PPU.ForcedBlanking; - IPPU.LatchedInterlace = (Memory.FillRAM[0x2133] & 1); - IPPU.RenderedScreenWidth = 256; - IPPU.RenderedScreenHeight = PPU.ScreenHeight; - IPPU.DoubleWidthPixels = FALSE; - - PPU.RecomputeClipWindows = TRUE; - PPU.BG[0].OffsetsChanged = 0; - PPU.BG[1].OffsetsChanged = 0; - PPU.BG[2].OffsetsChanged = 0; - PPU.BG[3].OffsetsChanged = 0; - GFX.DepthDelta = GFX.SubZBuffer - GFX.ZBuffer; - GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; - } - - if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) - { - IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; - IPPU.RenderedFramesCount = 0; - IPPU.FrameCount = 0; - } -} - -void RenderLine (uint8 C) -{ - if (IPPU.RenderThisFrame) - { - - LineData[C].BG[0].VOffset = PPU.BG[0].VOffset + 1; - LineData[C].BG[0].HOffset = PPU.BG[0].HOffset; - LineData[C].BG[1].VOffset = PPU.BG[1].VOffset + 1; - LineData[C].BG[1].HOffset = PPU.BG[1].HOffset; - - //if (PPU.BGMode == 7) - if ((Memory.FillRAM[0x2105] & 7) == 7) - { - struct SLineMatrixData *p = &LineMatrixData [C]; - p->MatrixA = PPU.MatrixA; - p->MatrixB = PPU.MatrixB; - p->MatrixC = PPU.MatrixC; - p->MatrixD = PPU.MatrixD; - p->CentreX = PPU.CentreX; - p->CentreY = PPU.CentreY; - } - else - { - if (Settings.StarfoxHack && PPU.BG[2].VOffset == 0 && - PPU.BG[2].HOffset == 0xe000) - { - LineData[C].BG[2].VOffset = 0xe1; - LineData[C].BG[2].HOffset = 0; - } - else - { - LineData[C].BG[2].VOffset = PPU.BG[2].VOffset + 1; - LineData[C].BG[2].HOffset = PPU.BG[2].HOffset; - LineData[C].BG[3].VOffset = PPU.BG[3].VOffset + 1; - LineData[C].BG[3].HOffset = PPU.BG[3].HOffset; - } - - } - IPPU.CurrentLine = C + 1; - } -} - - -void S9xEndScreenRefresh() -{ - IPPU.HDMAStarted = FALSE; - -//RC - if (IPPU.RenderThisFrame) - { - FLUSH_REDRAW (); - //if (IPPU.ColorsChanged) - //{ - IPPU.ColorsChanged = FALSE; - //} - - S9xDeinitUpdate (IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, - 1); - } -#ifndef RC_OPTIMIZED - S9xApplyCheats (); -#endif - - -#ifdef DEBUGGER - if (CPU.Flags & FRAME_ADVANCE_FLAG) - { - if (ICPU.FrameAdvanceCount) - { - ICPU.FrameAdvanceCount--; - IPPU.RenderThisFrame = TRUE; - IPPU.FrameSkip = 0; - } - else - { - CPU.Flags &= ~FRAME_ADVANCE_FLAG; - CPU.Flags |= DEBUG_MODE_FLAG; - } - } -#endif - -/* - if (CPU.SRAMModified) - { - if (!CPU.AutoSaveTimer) - { - if (!(CPU.AutoSaveTimer = Settings.AutoSaveDelay * Memory.ROMFramesPerSecond)) - CPU.SRAMModified = FALSE; - } - else - { - if (!--CPU.AutoSaveTimer) - { - S9xAutoSaveSRAM (); - CPU.SRAMModified = FALSE; - } - } - } -*/ -} - -void S9xSetInfoString (const char *string) -{ - } - - - -int TileRenderer; -TileRendererSet TileRenderers[] = { - {DrawTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 0 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 0 - {DrawTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 1 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 1 - {DrawTile16FixedAdd1_2, DrawClippedTile16FixedAdd1_2, DrawLargePixel16Add1_2}, // 2 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 0 - {DrawTile16Add1_2, DrawClippedTile16Add1_2, DrawLargePixel16Add1_2}, // 3 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 1 - {DrawTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 4 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 0 - {DrawTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 5 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 1 - {DrawTile16FixedSub1_2, DrawClippedTile16FixedSub1_2, DrawLargePixel16Sub1_2}, // 6 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 0 - {DrawTile16Sub1_2, DrawClippedTile16Sub1_2, DrawLargePixel16Sub1_2}, // 7 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 1 - {DrawTile16, DrawClippedTile16, DrawLargePixel16} // 8 -> normal - }; -#ifdef __FAST_OBJS__ -TileRendererSet TileRenderersNoZ[] = { - {DrawNoZTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 0 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 0 - {DrawNoZTile16Add, DrawClippedTile16Add, DrawLargePixel16Add}, // 1 -> GFX.r2131:7 = 0, GFX.r2131:6 = 0, GFX.r2130:1 = 1 - {DrawTile16FixedAdd1_2, DrawClippedTile16FixedAdd1_2, DrawLargePixel16Add1_2}, // 2 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 0 - {DrawNoZTile16Add1_2, DrawClippedTile16Add1_2, DrawLargePixel16Add1_2}, // 3 -> GFX.r2131:7 = 0, GFX.r2131:6 = 1, GFX.r2130:1 = 1 - {DrawNoZTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 4 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 0 - {DrawNoZTile16Sub, DrawClippedTile16Sub, DrawLargePixel16Sub}, // 5 -> GFX.r2131:7 = 1, GFX.r2131:6 = 0, GFX.r2130:1 = 1 - {DrawTile16FixedSub1_2, DrawClippedTile16FixedSub1_2, DrawLargePixel16Sub1_2}, // 6 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 0 - {DrawNoZTile16Sub1_2, DrawClippedTile16Sub1_2, DrawLargePixel16Sub1_2}, // 7 -> GFX.r2131:7 = 1, GFX.r2131:6 = 1, GFX.r2130:1 = 1 - {DrawNoZTile16, DrawClippedTile16, DrawLargePixel16} // 8 -> normal - }; -#endif -INLINE void SelectTileRenderer (bool8_32 normal, bool NoZ = false) -{ - if (normal) { - TileRenderer = 8; - } - else { - TileRenderer = (((GFX.r2131 >> 5) & 0x06) | ((GFX.r2130 >> 1) & 1)); - } - -#ifdef __DEBUG__ - char *TRName[] = { - "Add", "Add", "FixedAdd1_2", "Add1_2", - "Sub", "Sub", "FixedSub1_2", "Sub1_2", - "Normal" - }; - printf("SelectTileRenderer: %s\n", TRName[TileRenderer]); -#endif - -#ifdef __FAST_OBJS__ - if (NoZ) { - DrawTilePtr = TileRenderersNoZ[TileRenderer].Normal; - DrawClippedTilePtr = TileRenderersNoZ[TileRenderer].Clipped; - DrawLargePixelPtr = TileRenderersNoZ[TileRenderer].Large; - } - else { -#endif - DrawTilePtr = TileRenderers[TileRenderer].Normal; - DrawClippedTilePtr = TileRenderers[TileRenderer].Clipped; - DrawLargePixelPtr = TileRenderers[TileRenderer].Large; -#ifdef __FAST_OBJS__ - } -#endif -} - -void S9xSetupOBJ () -{ - int SmallSize; - int LargeSize; - - switch (PPU.OBJSizeSelect) - { - case 0: - SmallSize = 8; - LargeSize = 16; - break; - case 1: - SmallSize = 8; - LargeSize = 32; - break; - case 2: - SmallSize = 8; - LargeSize = 64; - break; - case 3: - SmallSize = 16; - LargeSize = 32; - break; - case 4: - SmallSize = 16; - LargeSize = 64; - break; - case 5: - default: - SmallSize = 32; - LargeSize = 64; - break; - } - - int C = 0; - - int FirstSprite = PPU.FirstSprite & 0x7f; - int S = FirstSprite; - do - { - int Size; - if (PPU.OBJ [S].Size) - Size = LargeSize; - else - Size = SmallSize; - - long VPos = PPU.OBJ [S].VPos; - - if (VPos >= PPU.ScreenHeight) - VPos -= 256; - if (PPU.OBJ [S].HPos < 256 && PPU.OBJ [S].HPos > -Size && - VPos < PPU.ScreenHeight && VPos > -Size) - { -#ifndef __FAST_OBJS__ - GFX.OBJList[C++] = S; -#else - int x = 0; - int a, b; - // -- Sort objects (from low to high priority) - while (x < C) { - a = GFX.OBJList[x]; - if (PPU.OBJ[a].Priority >= PPU.OBJ[S].Priority) break; - x++; - } - - GFX.OBJList[x] = S; - x++; C++; - - while (x < C) { - b = GFX.OBJList[x]; - GFX.OBJList[x] = a; - a = b; - x++; - } -#endif - // -- - GFX.Sizes[S] = Size; - GFX.VPositions[S] = VPos; - } - S = (S + 1) & 0x7f; - } while (S != FirstSprite); - - // Terminate the list - GFX.OBJList [C] = -1; - IPPU.OBJChanged = FALSE; -} - -void DrawOBJS (bool8_32 OnMain = FALSE, uint8 D = 0) -{ - int bg_ta_ns; - int bg_ta; - uint32 O; - uint32 BaseTile, Tile; - - CHECK_SOUND(); - - BG.BitShift = 4; - SelectConvertTile(); - BG.TileShift = 5; - //BG.TileAddress = PPU.OBJNameBase; - BG.StartPalette = 128; - BG.PaletteShift = 4; - BG.PaletteMask = 7; - BG.Buffer = IPPU.TileCache [TILE_4BIT]; - BG.Buffered = IPPU.TileCached [TILE_4BIT]; - //BG.NameSelect = PPU.OBJNameSelect; - BG.DirectColourMode = FALSE; - - SelectPalette(); - bg_ta = PPU.OBJNameBase; - bg_ta_ns = bg_ta + PPU.OBJNameSelect; - - GFX.Z1 = D + 2; - - DBG("Draw Objects.\n"); - - int I = 0; - for (int S = GFX.OBJList [I++]; S >= 0; S = GFX.OBJList [I++]) - { - int VPos = GFX.VPositions [S]; - int Size = GFX.Sizes[S]; - int TileInc = 1; - int Offset; - - if (VPos + Size <= (int) GFX.StartY || VPos > (int) GFX.EndY) - continue; - - if (OnMain && SUB_OR_ADD(4)) - { -#ifndef __FAST_OBJS__ - SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4, false); -#else - SelectTileRenderer (!GFX.Pseudo && PPU.OBJ [S].Palette < 4, true); -#endif - } - - BaseTile = PPU.OBJ[S].Name | (PPU.OBJ[S].Palette << 10); - - if (PPU.OBJ[S].HFlip) - { - BaseTile += ((Size >> 3) - 1) | H_FLIP; - TileInc = -1; - } - - if (PPU.OBJ[S].VFlip) BaseTile |= V_FLIP; - //BaseTile |= PPU.OBJ[S].VFlip << 15; - - int clipcount = GFX.pCurrentClip->Count [4]; - if (!clipcount) clipcount = 1; - - GFX.Z2 = (PPU.OBJ[S].Priority + 1) * 4 + D; - - for (int clip = 0; clip < clipcount; clip++) - { - int Left; - int Right; - if (!GFX.pCurrentClip->Count [4]) - { - Left = 0; - Right = 256; - } - else - { - Left = GFX.pCurrentClip->Left [clip][4]; - Right = GFX.pCurrentClip->Right [clip][4]; - } - - if (Right <= Left || PPU.OBJ[S].HPos + Size <= Left || - PPU.OBJ[S].HPos >= Right) - continue; - - for (int Y = 0; Y < Size; Y += 8) - { - if (VPos + Y + 7 >= (int) GFX.StartY && VPos + Y <= (int) GFX.EndY) - { - int StartLine; - int TileLine; - int LineCount; - int Last; - - if ((StartLine = VPos + Y) < (int) GFX.StartY) - { - StartLine = GFX.StartY - StartLine; - LineCount = 8 - StartLine; - } - else - { - StartLine = 0; - LineCount = 8; - } - if ((Last = VPos + Y + 7 - GFX.EndY) > 0) - if ((LineCount -= Last) <= 0) - break; - - TileLine = StartLine << 3; - - O = (VPos + Y + StartLine) * GFX_PPL; - if (!PPU.OBJ[S].VFlip) Tile = BaseTile + (Y << 1); - else Tile = BaseTile + ((Size - Y - 8) << 1); - - if (Tile & 0x100) BG.TileAddress = bg_ta_ns; - else BG.TileAddress = bg_ta; - - int Middle = Size >> 3; - if (PPU.OBJ[S].HPos < Left) - { - Tile += ((Left - PPU.OBJ[S].HPos) >> 3) * TileInc; - Middle -= (Left - PPU.OBJ[S].HPos) >> 3; - O += Left * GFX_PIXSIZE; - if ((Offset = (Left - PPU.OBJ[S].HPos) & 7)) - { - O -= Offset * GFX_PIXSIZE; - int W = 8 - Offset; - int Width = Right - Left; - if (W > Width) W = Width; - //if (Tile & 0x100) BG.TileAddress = bg_ta_ns; - //else BG.TileAddress = bg_ta; - (*DrawClippedTilePtr) (Tile, O, Offset, W, TileLine, LineCount); - - if (W >= Width) - continue; - Tile += TileInc; - Middle--; - O += 8 * GFX_PIXSIZE; - } - } - else - O += PPU.OBJ[S].HPos * GFX_PIXSIZE; - - if (PPU.OBJ[S].HPos + Size >= Right) - { - Middle -= ((PPU.OBJ[S].HPos + Size + 7) - - Right) >> 3; - Offset = (Right - (PPU.OBJ[S].HPos + Size)) & 7; - } - else - Offset = 0; - - for (int X = 0; X < Middle; X++, O += 8 * GFX_PIXSIZE, - Tile += TileInc) - { - //if (Tile & 0x100) BG.TileAddress = bg_ta_ns; - //else BG.TileAddress = bg_ta; - (*DrawTilePtr) (Tile, O, TileLine, LineCount); - } - if (Offset) - { - //if (Tile & 0x100) BG.TileAddress = bg_ta_ns; - //else BG.TileAddress = bg_ta; - (*DrawClippedTilePtr) (Tile, O, 0, Offset, TileLine, LineCount); - } - } - } - } - } -} -void DrawBackgroundMosaic (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ -#ifdef __DEBUG__ - printf("DrawBackgroundMosaic(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2); -#endif - CHECK_SOUND(); - - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint8 depths [2] = {Z1, Z2}; - - if (BGMode == 0) - BG.StartPalette = bg << 5; - else - BG.StartPalette = 0; - SelectPalette(); - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if (PPU.BG[bg].SCSize & 1) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if(((uint8*)SC1-Memory.VRAM)>=0x10000) - SC1-=0x08000; - - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - - if (PPU.BG[bg].SCSize & 1) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - - uint32 Lines; - uint32 OffsetMask; - uint32 OffsetShift; - - if (BG.TileSize == 16) - { - OffsetMask = 0x3ff; - OffsetShift = 4; - } - else - { - OffsetMask = 0x1ff; - OffsetShift = 3; - } - - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) - { - uint32 VOffset = LineData [Y].BG[bg].VOffset; - uint32 HOffset = LineData [Y].BG[bg].HOffset; - uint32 MosaicOffset = Y % PPU.Mosaic; - - for (Lines = 1; Lines < PPU.Mosaic - MosaicOffset; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) - break; - - uint32 MosaicLine = VOffset + Y - MosaicOffset; - - if (Y + Lines > GFX.EndY) - Lines = GFX.EndY + 1 - Y; - uint32 VirtAlign = (MosaicLine & 7) << 3; - - uint16 *b1; - uint16 *b2; - - uint32 ScreenLine = MosaicLine >> OffsetShift; - uint32 Rem16 = MosaicLine & 15; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - uint16 *t; - uint32 Left = 0; - uint32 Right = 256; - - uint32 ClipCount = GFX.pCurrentClip->Count [bg]; - uint32 HPos = HOffset; - uint32 PixWidth = PPU.Mosaic; - - if (!ClipCount) - ClipCount = 1; - - for (uint32 clip = 0; clip < ClipCount; clip++) - { - if (GFX.pCurrentClip->Count [bg]) - { - Left = GFX.pCurrentClip->Left [clip][bg]; - Right = GFX.pCurrentClip->Right [clip][bg]; - uint32 r = Left % PPU.Mosaic; - HPos = HOffset + Left; - PixWidth = PPU.Mosaic - r; - } - uint32 s = Y * GFX_PPL + Left * GFX_PIXSIZE; - for (uint32 x = Left; x < Right; x += PixWidth, - s += PixWidth * GFX_PIXSIZE, - HPos += PixWidth, PixWidth = PPU.Mosaic) - { - uint32 Quot = (HPos & OffsetMask) >> 3; - - if (x + PixWidth >= Right) - PixWidth = Right - x; - - if (BG.TileSize == 8) - { - if (Quot > 31) - t = b2 + (Quot & 0x1f); - else - t = b1 + Quot; - } - else - { - if (Quot > 63) - t = b2 + ((Quot >> 1) & 0x1f); - else - t = b1 + (Quot >> 1); - } - - Tile = READ_2BYTES (t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - // Draw tile... - if (BG.TileSize != 8) - { - if (Tile & H_FLIP) - { - // Horizontal flip, but what about vertical flip ? - if (Tile & V_FLIP) - { - // Both horzontal & vertical flip - if (Rem16 < 8) - { - (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - else - { - // Horizontal flip only - if (Rem16 > 7) - { - (*DrawLargePixelPtr) (Tile + 17 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + 1 - (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - } - else - { - // No horizontal flip, but is there a vertical flip ? - if (Tile & V_FLIP) - { - // Vertical flip only - if (Rem16 < 8) - { - (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - else - { - // Normal unflipped - if (Rem16 > 7) - { - (*DrawLargePixelPtr) (Tile + 16 + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - else - { - (*DrawLargePixelPtr) (Tile + (Quot & 1), s, - HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - } - } - else - (*DrawLargePixelPtr) (Tile, s, HPos & 7, PixWidth, - VirtAlign, Lines); - } - } - } -} - -void DrawBackgroundOffset (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ -#ifdef __DEBUG__ - printf("DrawBackgroundOffset(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2); -#endif - - CHECK_SOUND(); - - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint16 *BPS0; - uint16 *BPS1; - uint16 *BPS2; - uint16 *BPS3; - uint32 Width; - int VOffsetOffset = BGMode == 4 ? 0 : 32; - uint8 depths [2] = {Z1, Z2}; - - BG.StartPalette = 0; - SelectPalette(); - - BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; - - if (PPU.BG[2].SCSize & 1) - BPS1 = BPS0 + 1024; - else - BPS1 = BPS0; - - if (PPU.BG[2].SCSize & 2) - BPS2 = BPS1 + 1024; - else - BPS2 = BPS0; - - if (PPU.BG[2].SCSize & 1) - BPS3 = BPS2 + 1024; - else - BPS3 = BPS2; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if (PPU.BG[bg].SCSize & 1) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if(((uint8*)SC1-Memory.VRAM)>=0x10000) - SC1-=0x08000; - - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - - if (PPU.BG[bg].SCSize & 1) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - - static const int Lines = 1; - int OffsetMask; - int OffsetShift; - int OffsetEnableMask = 1 << (bg + 13); - - if (BG.TileSize == 16) - { - OffsetMask = 0x3ff; - OffsetShift = 4; - } - else - { - OffsetMask = 0x1ff; - OffsetShift = 3; - } - - TileBlank = 0xFFFFFFFF; - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++) - { - uint32 VOff = LineData [Y].BG[2].VOffset - 1; - uint32 HOff = LineData [Y].BG[2].HOffset; - int VirtAlign; - int ScreenLine = VOff >> 3; - uint16 *s0; - uint16 *s1; - uint16 *s2; -#ifdef __DEBUG__ - printf("Processing line: %d\n", Y); -#endif - if (ScreenLine & 0x20) - s1 = BPS2, s2 = BPS3; - else - s1 = BPS0, s2 = BPS1; - - s1 += (ScreenLine & 0x1f) << 5; - s2 += (ScreenLine & 0x1f) << 5; - - if(BGMode != 4) - { - if((ScreenLine & 0x1f) == 0x1f) - { - if(ScreenLine & 0x20) - VOffsetOffset = BPS0 - BPS2 - 0x1f*32; - else - VOffsetOffset = BPS2 - BPS0 - 0x1f*32; - } - else - { - VOffsetOffset = 32; - } - } - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) - clipcount = 1; - - for (int clip = 0; clip < clipcount; clip++) - { - uint32 Left; - uint32 Right; -#ifdef __DEBUG__ - printf("Processing clip: %d/%d\n", clip, clipcount); -#endif - - if (!GFX.pCurrentClip->Count [bg]) - { - Left = 0; - Right = 256; - } - else - { - Left = GFX.pCurrentClip->Left [clip][bg]; - Right = GFX.pCurrentClip->Right [clip][bg]; - - if (Right <= Left) - continue; - } - - uint32 VOffset; - uint32 HOffset; - uint32 LineHOffset=LineData [Y].BG[bg].HOffset; - uint32 Offset; - uint32 HPos; - uint32 Quot; - uint32 Count; - uint16 *t; - uint32 Quot2; - uint32 VCellOffset; - uint32 HCellOffset; - uint16 *b1; - uint16 *b2; - uint32 TotalCount = 0; - uint32 MaxCount = 8; - - uint32 s = Left * GFX_PIXSIZE + Y * GFX_PPL; - bool8_32 left_hand_edge = (Left == 0); - Width = Right - Left; - - if (Left & 7) - MaxCount = 8 - (Left & 7); - - while (Left < Right) - { -#ifdef __DEBUG__ - printf("Left: %d, Right: %d\n", Left, Right); -#endif - if (left_hand_edge) - { - // The SNES offset-per-tile background mode has a - // hardware limitation that the offsets cannot be set - // for the tile at the left-hand edge of the screen. - VOffset = LineData [Y].BG[bg].VOffset; - HOffset = LineHOffset; - left_hand_edge = FALSE; - } - else - { - // All subsequent offset tile data is shifted left by one, - // hence the - 1 below. - Quot2 = ((HOff + Left - 1) & OffsetMask) >> 3; - - if (Quot2 > 31) - s0 = s2 + (Quot2 & 0x1f); - else - s0 = s1 + Quot2; - - HCellOffset = READ_2BYTES (s0); - - if (BGMode == 4) - { - VOffset = LineData [Y].BG[bg].VOffset; - HOffset=LineHOffset; - if ((HCellOffset & OffsetEnableMask)) - { - if (HCellOffset & 0x8000) - VOffset = HCellOffset + 1; - else - HOffset = HCellOffset; - } - } - else - { - VCellOffset = READ_2BYTES (s0 + VOffsetOffset); - if ((VCellOffset & OffsetEnableMask)) - VOffset = VCellOffset + 1; - else - VOffset = LineData [Y].BG[bg].VOffset; - - if ((HCellOffset & OffsetEnableMask)) - HOffset = (HCellOffset & ~7)|(LineHOffset&7); - else - HOffset=LineHOffset; - } - } - VirtAlign = ((Y + VOffset) & 7) << 3; - ScreenLine = (VOffset + Y) >> OffsetShift; - - int tx_index; - tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - HPos = (HOffset + Left) & OffsetMask; - - Quot = HPos >> 3; - - if (BG.TileSize == 8) - { - if (Quot > 31) - t = b2 + (Quot & 0x1f); - else - t = b1 + Quot; - } - else - { - if (Quot > 63) - t = b2 + ((Quot >> 1) & 0x1f); - else - t = b1 + (Quot >> 1); - } - - if (MaxCount + TotalCount > Width) - MaxCount = Width - TotalCount; - - Offset = HPos & 7; - - Count = 8 - Offset; - if (Count > MaxCount) - Count = MaxCount; - - s -= Offset * GFX_PIXSIZE; - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - if (Tile != TileBlank) - if (BG.TileSize == 8) - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); - else - { - Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13) + (Quot & 1)]; - if (Tile != TileBlank){ - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); - } - } - - Left += Count; - TotalCount += Count; - s += (Offset + Count) * GFX_PIXSIZE; - MaxCount = 8; - } - } - } -} - -void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8 Z2) -{ -#ifdef __DEBUG__ - printf("DrawBackgroundMode5(?, %i, %i, %i)\n", bg, Z1, Z2); -#endif - - CHECK_SOUND(); - - uint8 depths [2] = {Z1, Z2}; - - uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint32 Width; - - BG.StartPalette = 0; - SelectPalette(); - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - if ((PPU.BG[bg].SCSize & 1)) - SC1 = SC0 + 1024; - else - SC1 = SC0; - - if((SC1-(unsigned short*)Memory.VRAM)>0x10000) - SC1=(uint16*)&Memory.VRAM[(((uint8*)SC1)-Memory.VRAM)%0x10000]; - - if ((PPU.BG[bg].SCSize & 2)) - SC2 = SC1 + 1024; - else SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) - SC2-=0x08000; - - if ((PPU.BG[bg].SCSize & 1)) - SC3 = SC2 + 1024; - else - SC3 = SC2; - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) - SC3-=0x08000; - int Lines; - int VOffsetMask; - int VOffsetShift; - - if (BG.TileSize == 16) - { - VOffsetMask = 0x3ff; - VOffsetShift = 4; - } - else - { - VOffsetMask = 0x1ff; - VOffsetShift = 3; - } - int endy = GFX.EndY; - - for (int Y = GFX.StartY; Y <= endy; Y += Lines) - { - //int y = Y; - uint32 VOffset = LineData [Y].BG[bg].VOffset; - uint32 HOffset = LineData [Y].BG[bg].HOffset; - int VirtAlign = (Y + VOffset) & 7; - - for (Lines = 1; Lines < 8 - VirtAlign; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) - break; - - HOffset <<= 1; - if (Y + Lines > endy) - Lines = endy + 1 - Y; - - int ScreenLine = (VOffset + Y) >> VOffsetShift; - int t1; - int t2; - if (((VOffset + Y) & 15) > 7) - { - t1 = 16; - t2 = 0; - } - else - { - t1 = 0; - t2 = 16; - } - uint16 *b1; - uint16 *b2; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) - clipcount = 1; - for (int clip = 0; clip < clipcount; clip++) - { - int Left; - int Right; - - if (!GFX.pCurrentClip->Count [bg]) - { - Left = 0; - Right = 512; - } - else - { - Left = GFX.pCurrentClip->Left [clip][bg] * 2; - Right = GFX.pCurrentClip->Right [clip][bg] * 2; - - if (Right <= Left) - continue; - } - - uint32 s = (Left>>1) * GFX_PIXSIZE + Y * GFX_PPL; - uint32 HPos = (HOffset + Left * GFX_PIXSIZE) & 0x3ff; - - uint32 Quot = HPos >> 3; - uint32 Count = 0; - - uint16 *t; - if (Quot > 63) - t = b2 + ((Quot >> 1) & 0x1f); - else - t = b1 + (Quot >> 1); - - Width = Right - Left; - // Left hand edge clipped tile - if (HPos & 7) - { - int Offset = (HPos & 7); - Count = 8 - Offset; - if (Count > Width) - Count = Width; - s -= (Offset>>1); - Tile = READ_2BYTES (t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - - if (BG.TileSize == 8) - { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), - s, Offset, Count, VirtAlign, Lines); - } - } - - t += Quot & 1; - if (Quot == 63) - t = b2; - else if (Quot == 127) - t = b1; - Quot++; - s += 4; - } - - // Middle, unclipped tiles - Count = Width - Count; - int Middle = Count >> 3; - Count &= 7; - for (int C = Middle; C > 0; s += 4, Quot++, C--) - { - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - if (BG.TileSize == 8) - { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResTilePtr) (Tile + (Quot & 1), - s, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResTilePtr) (Tile + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResTilePtr) (Tile + t1 + (Quot & 1), - s, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResTilePtr) (Tile + t2 + (Quot & 1), - s, VirtAlign, Lines); - } - } - - t += Quot & 1; - if (Quot == 63) - t = b2; - else - if (Quot == 127) - t = b1; - } - - // Right-hand edge clipped tiles - if (Count) - { - Tile = READ_2BYTES(t); - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - if (BG.TileSize == 8) - { - if (!(Tile & H_FLIP)) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - { - // H flip - (*DrawHiResClippedTilePtr) (Tile + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - } - else - { - if (!(Tile & (V_FLIP | H_FLIP))) - { - // Normal, unflipped - (*DrawHiResClippedTilePtr) (Tile + t1 + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - if (Tile & H_FLIP) - { - if (Tile & V_FLIP) - { - // H & V flip - (*DrawHiResClippedTilePtr) (Tile + t2 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - else - { - // H flip only - (*DrawHiResClippedTilePtr) (Tile + t1 + 1 - (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - } - else - { - // V flip only - (*DrawHiResClippedTilePtr) (Tile + t2 + (Quot & 1), - s, 0, Count, VirtAlign, Lines); - } - } - } - } - } -} - -void DrawBackground_8(uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ -#ifdef __DEBUG__ - printf("DrawBackground_8(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2); -#endif - //uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint32 depths [2] = {Z1, Z2}; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - SC1 = SC0 + ((PPU.BG[bg].SCSize & 1) << 10); - - if(SC1 >= (unsigned short*)(Memory.VRAM+0x10000)) SC1 = (uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0]) & 0xffff]; - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) SC2 -= 0x08000; - - SC3 = SC2 + ((PPU.BG[bg].SCSize & 1) << 10); - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) SC3 -= 0x08000; - - int Lines; - - int oc = PPU.BG[bg].OffsetsChanged; - uint32 VOffset, HOffset; - if (!oc) { - VOffset = LineData [GFX.StartY].BG[bg].VOffset; - HOffset = LineData [GFX.StartY].BG[bg].HOffset; - } - TileBlank = 0xFFFFFFFF; - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){ - int y_ppl = Y * GFX_PPL; - if (oc) { - VOffset = LineData [Y].BG[bg].VOffset; - HOffset = LineData [Y].BG[bg].HOffset; - } - int VirtAlign = (Y + VOffset) & 7; - - int maxLines = GFX.EndY - Y + 1; - if ((8 - VirtAlign) < maxLines) maxLines = (8 - VirtAlign); - - if (oc) { - for (Lines = 1; Lines < maxLines; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) - break; - } else Lines = maxLines; - - VirtAlign <<= 3; - - uint32 ScreenLine = (VOffset + Y) >> 3; - uint16 *b1; - uint16 *b2; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - uint32 Left; - uint32 Right; - int clip = 0; - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) { - Left = 0; - Right = 256; - } - - do { - if (clipcount) { - Left = GFX.pCurrentClip->Left [clip][bg]; - Right = GFX.pCurrentClip->Right [clip][bg]; - - if (Right <= Left) {clip++; continue;} - } - - uint32 s = Left + y_ppl; - uint32 HPos = (HOffset + Left) & 0x1ff; - uint32 Quot = HPos >> 3; - uint32 Count = 0; - uint16 *t; - uint16 *b; - - if (Quot > 31) { - t = b2 + (Quot & 0x1f); - b = b1; - Quot -= 32; - } - else { - t = b1 + Quot; - b = b2; - } - - uint32 Width = Right - Left; - - // Left hand edge clipped tile - uint32 Offset = (HPos & 7); - if (Offset){ - Count = 8 - Offset; - if (Count > Width) Count = Width; - s -= Offset; - //uint32 Tile = READ_2BYTES(t); - register uint32 Tile = *(t++); - if (Tile != TileBlank){ - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); - } - //t++; - if (Quot == 31) t = b; - //else if (Quot == 63) t = b1; - Quot++; - s += 8; - } - - // Middle, unclipped tiles - Count = Width - Count; - for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){ - //uint32 Tile = READ_2BYTES(t); - register uint32 Tile = *(t++); - if (Tile != TileBlank){ - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - (*DrawTilePtr) (Tile, s, VirtAlign, Lines); - } - - //t++; - if (Quot == 31) t = b; - //else if (Quot == 63) t = b1; - } - - // Right-hand edge clipped tiles - if (Count & 7){ - //uint32 Tile = READ_2BYTES(t); - register uint32 Tile = *t; - if (Tile != TileBlank){ - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines); - } - } - clip ++; - } while (clip < clipcount); - } -} - -void DrawBackground_16 (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ -#ifdef __DEBUG__ - printf("DrawBackground_16(%i, %i, %i, %i)\n", BGMode, bg, Z1, Z2); -#endif - //uint32 Tile; - uint16 *SC0; - uint16 *SC1; - uint16 *SC2; - uint16 *SC3; - uint32 depths [2] = {Z1, Z2}; - - SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; - - SC1 = SC0 + ((PPU.BG[bg].SCSize & 1) << 10); - - if(SC1 >= (unsigned short*)(Memory.VRAM+0x10000)) SC1 = (uint16*)&Memory.VRAM[((uint8*)SC1-&Memory.VRAM[0]) & 0xffff]; - - if (PPU.BG[bg].SCSize & 2) - SC2 = SC1 + 1024; - else - SC2 = SC0; - - if(((uint8*)SC2-Memory.VRAM)>=0x10000) SC2 -= 0x08000; - - SC3 = SC2 + ((PPU.BG[bg].SCSize & 1) << 10); - - if(((uint8*)SC3-Memory.VRAM)>=0x10000) SC3 -= 0x08000; - - int Lines; - - int oc = PPU.BG[bg].OffsetsChanged; - uint32 VOffset, HOffset; - if (!oc) { - VOffset = LineData [GFX.StartY].BG[bg].VOffset; - HOffset = LineData [GFX.StartY].BG[bg].HOffset; - } - - TileBlank = 0xFFFFFFFF; - unsigned int tb1 = 0xffffffff; - unsigned int tb2 = 0xffffffff; - for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines){ - int y_ppl = Y * GFX_PPL; - if (oc) { - VOffset = LineData [Y].BG[bg].VOffset; - HOffset = LineData [Y].BG[bg].HOffset; - } - int VirtAlign = (Y + VOffset) & 7; - - int maxLines = GFX.EndY - Y + 1; - if ((8 - VirtAlign) < maxLines) maxLines = (8 - VirtAlign); - - if (oc) { - for (Lines = 1; Lines < maxLines; Lines++) - if ((VOffset != LineData [Y + Lines].BG[bg].VOffset) || - (HOffset != LineData [Y + Lines].BG[bg].HOffset)) - break; - } else Lines = maxLines; - - VirtAlign <<= 3; - - uint32 ScreenLine = (VOffset + Y) >> 4; - int tx_index = ( ((VOffset + Y) & 15) <= 7 ) << 3; - uint16 *b1; - uint16 *b2; - - if (ScreenLine & 0x20) - b1 = SC2, b2 = SC3; - else - b1 = SC0, b2 = SC1; - - b1 += (ScreenLine & 0x1f) << 5; - b2 += (ScreenLine & 0x1f) << 5; - - uint32 Left; - uint32 Right; - int clip = 0; - int clipcount = GFX.pCurrentClip->Count [bg]; - if (!clipcount) { - Left = 0; - Right = 256; - } - - do { - if (clipcount) { - Left = GFX.pCurrentClip->Left [clip][bg]; - Right = GFX.pCurrentClip->Right [clip][bg]; - - if (Right <= Left) {clip++; continue;} - } - - uint32 s = Left + y_ppl; - uint32 HPos = (HOffset + Left) & 0x3ff; - uint32 Quot = HPos >> 3; - uint32 Count = 0; - uint16 *t; - uint16 *b; - - if (Quot > 63) { - t = b2 + ((Quot >> 1) & 0x1f); - b = b1; - Quot -= 64; - } - else { - t = b1 + (Quot >> 1); - b = b2; - } - - - uint32 Width = Right - Left; - - register uint32 Tile; - if (Quot & 1) { - Tile = *(t++); - Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13)]; - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - } - - // Left hand edge clipped tile - uint32 Offset = (HPos & 7); - if (Offset){ - Count = 8 - Offset; - if (Count > Width) Count = Width; - s -= Offset; - if (!(Quot & 1)) { - Tile = *(t++); - Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13)]; - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - if (Tile != tb1) { - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); - tb1 = TileBlank; - } - } - else { - if (Tile & H_FLIP) Tile--; - else Tile++; - if (Quot == 63) t = b; - if (Tile != tb2) { - (*DrawClippedTilePtr) (Tile, s, Offset, Count, VirtAlign, Lines); - tb2 = TileBlank; - } - } - Quot++; - s += 8; - } - - // Middle, unclipped tiles - Count = Width - Count; - for (int C = Count >> 3; C > 0; s += 8, Quot++, C--){ - if (!(Quot & 1)) { - Tile = *(t++); - Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13)]; - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - if (Tile != tb1){ - (*DrawTilePtr) (Tile, s, VirtAlign, Lines); - tb1 = TileBlank; - } - } - else { - if (Tile & H_FLIP) Tile--; - else Tile++; - if (Quot == 63) t = b; - if (Tile != tb2){ - (*DrawTilePtr) (Tile, s, VirtAlign, Lines); - tb2 = TileBlank; - } - } - } - - // Right-hand edge clipped tiles - if (Count & 7){ - if (!(Quot & 1)) { - Tile = *(t++); - Tile += tx_table[tx_index + ((Tile & (H_FLIP | V_FLIP)) >> 13)]; - GFX.Z1 = GFX.Z2 = depths [(Tile & 0x2000) >> 13]; - if (Tile != tb1) (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines); - } - else { - if (Tile & H_FLIP) Tile--; - else Tile++; - if (Tile != tb2) (*DrawClippedTilePtr) (Tile, s, 0, Count & 7, VirtAlign, Lines); - } - } - clip ++; - } while (clip < clipcount); - } -} - - -inline void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2) -{ -//StartAnalyze(); - - BG.TileSize = BGSizes [PPU.BG[bg].BGSize]; - BG.BitShift = BitShifts[BGMode][bg]; - SelectConvertTile(); - BG.TileShift = TileShifts[BGMode][bg]; - BG.TileAddress = PPU.BG[bg].NameBase << 1; - //BG.NameSelect = 0; - BG.Buffer = IPPU.TileCache [Depths [BGMode][bg]]; - BG.Buffered = IPPU.TileCached [Depths [BGMode][bg]]; - BG.PaletteShift = PaletteShifts[BGMode][bg]; - BG.PaletteMask = PaletteMasks[BGMode][bg]; - BG.DirectColourMode = (BGMode == 3 || BGMode == 4) && bg == 0 && (GFX.r2130 & 1); - - DBG("Draw Background.\n"); - - if (IPPU.DirectColourMapsNeedRebuild && BG.DirectColourMode) S9xBuildDirectColourMaps (); - - if (PPU.BGMosaic [bg] && PPU.Mosaic > 1){ - DrawBackgroundMosaic (BGMode, bg, Z1, Z2); - return; - - } - switch (BGMode) - { - case 2: - case 4: // Used by Puzzle Bobble - DrawBackgroundOffset (BGMode, bg, Z1, Z2); - break; - - case 5: - case 6: // XXX: is also offset per tile. - DrawBackgroundMode5 (BGMode, bg, Z1, Z2); - break; - case 0: - case 1: - case 3: - CHECK_SOUND(); - - if (BGMode == 0) BG.StartPalette = bg << 5; - else BG.StartPalette = 0; - SelectPalette(); - - if (BG.TileSize == 8) DrawBackground_8 (BGMode, bg, Z1, Z2); - else DrawBackground_16 (BGMode, bg, Z1, Z2); - break; - } -} - -#define _BUILD_SETUP(F) \ -GFX.BuildPixel = BuildPixel##F; \ -GFX.BuildPixel2 = BuildPixel2##F; \ -GFX.DecomposePixel = DecomposePixel##F; \ -RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_##F; \ -GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_##F; \ -BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_##F; \ -RED_HI_BIT_MASK = RED_HI_BIT_MASK_##F; \ -GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_##F; \ -BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_##F; \ -MAX_RED = MAX_RED_##F; \ -MAX_GREEN = MAX_GREEN_##F; \ -MAX_BLUE = MAX_BLUE_##F; \ -GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \ -SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \ -RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_##F | \ - GREEN_LOW_BIT_MASK_##F | \ - BLUE_LOW_BIT_MASK_##F); \ -RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_##F | \ - GREEN_HI_BIT_MASK_##F | \ - BLUE_HI_BIT_MASK_##F); \ -RGB_HI_BITS_MASKx2 = ((RED_HI_BIT_MASK_##F | \ - GREEN_HI_BIT_MASK_##F | \ - BLUE_HI_BIT_MASK_##F) << 1); \ -RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; \ -FIRST_COLOR_MASK = FIRST_COLOR_MASK_##F; \ -SECOND_COLOR_MASK = SECOND_COLOR_MASK_##F; \ -THIRD_COLOR_MASK = THIRD_COLOR_MASK_##F; \ -ALPHA_BITS_MASK = ALPHA_BITS_MASK_##F; \ -FIRST_THIRD_COLOR_MASK = FIRST_COLOR_MASK | THIRD_COLOR_MASK; \ -TWO_LOW_BITS_MASK = RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1); \ -HIGH_BITS_SHIFTED_TWO_MASK = (( (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & \ - ~TWO_LOW_BITS_MASK ) >> 2); - -void RenderScreen (uint8 *Screen, bool8_32 sub, bool8_32 force_no_add, uint8 D) -{ - bool8_32 BG0; - bool8_32 BG1; - bool8_32 BG2; - bool8_32 BG3; - bool8_32 OB; - - GFX.S = Screen; - - if (!sub) - { - GFX.pCurrentClip = &IPPU.Clip [0]; - BG0 = ON_MAIN (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0); - BG1 = ON_MAIN (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1); - BG2 = ON_MAIN (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2); - BG3 = ON_MAIN (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3); - OB = ON_MAIN (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); - } - else - { - GFX.pCurrentClip = &IPPU.Clip [1]; - BG0 = ON_SUB (0) && !(Settings.os9x_hack & GFX_IGNORE_BG0); - BG1 = ON_SUB (1) && !(Settings.os9x_hack & GFX_IGNORE_BG1); - BG2 = ON_SUB (2) && !(Settings.os9x_hack & GFX_IGNORE_BG2); - BG3 = ON_SUB (3) && !(Settings.os9x_hack & GFX_IGNORE_BG3); - OB = ON_SUB (4) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); - } - -#ifdef __DEBUG__ - printf("Screen[y1,y2]:[%i,%i],Mode:%i, BG0:%i,BG1:%i,BG2:%i,BG3:%i,OBJ:%i\n", GFX.StartY, GFX.EndY, PPU.BGMode, BG0, BG1, BG2, BG3, OB); -#endif - - sub |= force_no_add; - - if (PPU.BGMode <= 1) - { - if (OB) - { -#ifndef __FAST_OBJS__ - SelectTileRenderer (sub || !SUB_OR_ADD(4), false); -#else - SelectTileRenderer (sub || !SUB_OR_ADD(4), true); -#endif - DrawOBJS (!sub, D); - } - if (BG0) - { - SelectTileRenderer (sub || !SUB_OR_ADD(0), false); - DrawBackground (PPU.BGMode, 0, D + 10, D + 14); - } - if (BG1) - { - SelectTileRenderer (sub || !SUB_OR_ADD(1), false); - DrawBackground (PPU.BGMode, 1, D + 9, D + 13); - } - if (BG2) - { - SelectTileRenderer (sub || !SUB_OR_ADD(2), false); - DrawBackground (PPU.BGMode, 2, D + 3, - PPU.BG3Priority ? D + 17 : D + 6); - } - if (BG3 && PPU.BGMode == 0) - { - SelectTileRenderer (sub || !SUB_OR_ADD(3), false); - DrawBackground (PPU.BGMode, 3, D + 2, D + 5); - } - } - else if (PPU.BGMode != 7) - { - if (OB) - { -#ifndef __FAST_OBJS__ - SelectTileRenderer (sub || !SUB_OR_ADD(4), false); -#else - SelectTileRenderer (sub || !SUB_OR_ADD(4), true); -#endif - DrawOBJS (!sub, D); - } - if (BG0) - { - SelectTileRenderer (sub || !SUB_OR_ADD(0), false); - DrawBackground (PPU.BGMode, 0, D + 5, D + 13); - } - if (PPU.BGMode != 6 && BG1) - { - SelectTileRenderer (sub || !SUB_OR_ADD(1), false); - DrawBackground (PPU.BGMode, 1, D + 2, D + 9); - } - } - else - { - if (OB && ((SNESGameFixes.Mode7Hack && D) || !SNESGameFixes.Mode7Hack)) - { - SelectTileRenderer (sub || !SUB_OR_ADD(4), true); - DrawOBJS (!sub, D); - } - if (BG0 || ((Memory.FillRAM [0x2133] & 0x40) && BG1)) - { - int bg; - - if ((Memory.FillRAM [0x2133] & 0x40)&&BG1) - { - Mode7Depths [0] = (BG0?5:1) + D; - Mode7Depths [1] = 9 + D; - bg = 1; - if (sub || !SUB_OR_ADD(0)) - { - DrawBGMode7Background16Prio (Screen, bg); - } - else - { - if (GFX.r2131 & 0x80) - { - if (GFX.r2131 & 0x40) - { - DrawBGMode7Background16PrioSub1_2 (Screen, bg); - } - else - { - DrawBGMode7Background16PrioSub (Screen, bg); - } - } - else - { - if (GFX.r2131 & 0x40) - { - DrawBGMode7Background16PrioAdd1_2 (Screen, bg); - } - else - { - DrawBGMode7Background16PrioAdd (Screen, bg); - } - } - } - } - else - { - bg = 0; - if (sub || !SUB_OR_ADD(0)) - { - if (D || !SNESGameFixes.Mode7Hack) DrawBGMode7Background16 (Screen, bg, D+5); - else DrawBGMode7Background16New (Screen); - } - else - { - if (GFX.r2131 & 0x80) - { - if (GFX.r2131 & 0x40) - { - DrawBGMode7Background16Sub1_2 (Screen, bg, D+5); - } - else - { - DrawBGMode7Background16Sub (Screen, bg, D+5); - } - } - else - { - if (GFX.r2131 & 0x40) - { - DrawBGMode7Background16Add1_2 (Screen, bg, D+5); - } - else - { - DrawBGMode7Background16Add (Screen, bg, D+5); - } - } - } - } - } - if (OB && SNESGameFixes.Mode7Hack && D==0) - { -#ifndef __FAST_OBJS__ - SelectTileRenderer (sub || !SUB_OR_ADD(4), false); -#else - SelectTileRenderer (sub || !SUB_OR_ADD(4), true); -#endif - DrawOBJS (!sub, D); - } - } -} - -#include "font.h" - -void DisplayChar (uint8 *Screen, uint8 c) -{ - int line = (((c & 0x7f) - 32) >> 4) * font_height; - int offset = (((c & 0x7f) - 32) & 15) * font_width; - int h, w; - uint16 *s = (uint16 *) Screen; - for (h = 0; h < font_height; h++, line++, - s += GFX_PPL - font_width) - { - for (w = 0; w < font_width; w++, s++) - { - uint8 p = font [line][offset + w]; - - if (p == '#') - *s = 0xffff; - else - if (p == '.') - *s = BLACK; - } - } -} - -static void S9xDisplayFrameRate () -{ - uint8 *Screen = GFX.Screen + 2 + - (IPPU.RenderedScreenHeight - font_height - 1) * GFX_PITCH; - char string [10]; - int len = 5; - - sprintf (string, "%02d/%02d", IPPU.DisplayedRenderedFrameCount, - (int) Memory.ROMFramesPerSecond); - - int i; - for (i = 0; i < len; i++) - { - DisplayChar (Screen, string [i]); - Screen += (font_width - 1) * sizeof (uint16); - } -} - -static void S9xDisplayString (const char *string) -{ - uint8 *Screen = GFX.Screen + 2 + - (IPPU.RenderedScreenHeight - font_height * 5) * GFX_PITCH; - int len = strlen (string); - int max_chars = IPPU.RenderedScreenWidth / (font_width - 1); - int char_count = 0; - int i; - - for (i = 0; i < len; i++, char_count++) - { - if (char_count >= max_chars || string [i] < 32) - { - Screen -= (font_width - 1) * sizeof (uint16) * max_chars; - Screen += font_height * GFX_PITCH; - if (Screen >= GFX.Screen + GFX_PITCH * IPPU.RenderedScreenHeight) - break; - char_count -= max_chars; - } - if (string [i] < 32) - continue; - DisplayChar (Screen, string [i]); - Screen += (font_width - 1) * sizeof (uint16); - } -} - -// -x- - -static void S9xUpdateScreenTransparency () // ~30-50ms! (called from FLUSH_REDRAW()) -{ - uint32 starty = GFX.StartY; - uint32 endy = GFX.EndY; - uint32 black = BLACK | (BLACK << 16); - - - if (GFX.Pseudo) - { - GFX.r2131 = 0x5f; //0101 1111 - enable addition/subtraction on all BGS and sprites and "1/2 OF COLOR DATA" DESIGNATION - GFX.r212c &= (GFX.r212d_s | 0xf0); - GFX.r212d |= (GFX.r212c_s & 0x0f); - GFX.r2130 |= 2; // enable ADDITION/SUBTRACTION FOR SUB SCREEN - } - - // Check to see if any transparency effects are currently in use - if (!PPU.ForcedBlanking && ADD_OR_SUB_ON_ANYTHING && - (GFX.r2130 & 0x30) != 0x30 && - !((GFX.r2130 & 0x30) == 0x10 && IPPU.Clip[1].Count[5] == 0)) - { - DBG("Transparency in use\n"); - // transparency effects in use, so lets get busy! - struct ClipData *pClip; - uint32 fixedColour; - GFX.FixedColour = BUILD_PIXEL (IPPU.XB[PPU.FixedColourRed], IPPU.XB[PPU.FixedColourGreen] , IPPU.XB[PPU.FixedColourBlue]); - fixedColour = (GFX.FixedColour<<16|GFX.FixedColour); - // Clear the z-buffer, marking areas 'covered' by the fixed - // colour as depth 1. - pClip = &IPPU.Clip [1]; - - // Clear the z-buffer - - if (pClip->Count [5]) - { - - DBG("Colour window enabled. Clearing...\n"); - - // Colour window enabled. - // loop around all of the lines being updated - for (uint32 y = starty; y <= endy; y++) - { - // Clear the subZbuffer - memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH),0, (256>>2)); - // Clear the Zbuffer - memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, (256>>2)); - if (IPPU.Clip[0].Count [5]) { - // if there is clipping then clear subscreen to a black color - memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), black, (256>>1)); - } - - // loop through all window clippings - for (uint32 c = 0; c < pClip->Count [5]; c++) - { - int width = pClip->Right [c][5] - pClip->Left [c][5]; - if (width > 0) { - - //if (pClip->Right [c][5] > pClip->Left [c][5]) - //{ - memset (GFX.SubZBuffer + y * GFX_ZPITCH + pClip->Left [c][5], - 1, width); //pClip->Right [c][5] - pClip->Left [c][5]); - - if (IPPU.Clip [0].Count [5]) - { - DBG("Clearing sub-screen. Clipping effects in use.\n"); - // Blast, have to clear the sub-screen to the fixed-colour - // because there is a colour window in effect clipping - // the main screen that will allow the sub-screen - // 'underneath' to show through. - - asm volatile ( - " mov r0, %[fixedcolour] \n" - " subs %[width], %[width], #8 \n" - " bmi 2f \n" - " mov r1, r0 \n" - " mov r2, r0 \n" - - "1: \n" - " subs %[width], %[width], #8 \n" - " stmia %[p]!, {r0, r1, r2, %[fixedcolour]}\n" - " bpl 1b \n" - - "2: \n" - " tst %[width], #1 \n" - " strneh %[fixedcolour], [%[p]], #2 \n" - - " tst %[width], #2 \n" - " strne %[fixedcolour], [%[p]], #4 \n" - - " tst %[width], #4 \n" - " stmia %[p]!, {r0, %[fixedcolour]}\n" - - : [width] "+r" (width) - : [fixedcolour] "r" (fixedColour), - [p] "r" (((uint16 *) (GFX.SubScreen + y * GFX_PITCH)) + pClip->Left [c][5]) - : "r0", "r1", "r2", "cc" - ); - //} - } - } - } - } - - } - else - { - DBG("No windows clipping the main screen.\n"); - - // No windows are clipping the main screen - // this simplifies the screen clearing process - // loop through all of the lines to be updated - for (uint32 y = starty; y <= endy; y++) { - // Clear the Zbuffer - memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH),0, (256>>2)); - // clear the sub Zbuffer to 1 - memset32 ((uint32_t*)(GFX.SubZBuffer + y * GFX_ZPITCH), 0x01010101, (256>>2)); - - if (IPPU.Clip [0].Count [5]) { - // Blast, have to clear the sub-screen to the fixed-colour - // because there is a colour window in effect clipping - // the main screen that will allow the sub-screen - // 'underneath' to show through. - memset32 ((uint32_t*)(GFX.SubScreen + y * GFX_PITCH), fixedColour, (256>>1)); - } - } - } - - if (ANYTHING_ON_SUB) - { - DBG("Rendering SubScreen...\n"); - GFX.DB = GFX.SubZBuffer; - RenderScreen (GFX.SubScreen, TRUE, TRUE, SUB_SCREEN_DEPTH); - } - - if (IPPU.Clip [0].Count [5]) - { - DBG("Copying from SubScreen to the Main Screen\n"); - - asm volatile ( - "1: \n" - " mov r1, #(256 >> 2) \n" - - "2: \n" - // four pixels at once - " ldrb r0, [%[d]], #1 \n" - " ldrb r3, [%[d]], #1 \n" - - " bics r0, r0, #1 \n" - " ldrneh r0, [%[p], %[delta]] \n" - - " bics r3, r3, #1 \n" - " ldrneh r3, [%[p], %[delta2]] \n" - - " strh r0, [%[p]], #2 \n" - " ldrb r0, [%[d]], #1 \n" - " strh r3, [%[p]], #2 \n" - " ldrb r3, [%[d]], #1 \n" - - " bics r0, r0, #1 \n" - " ldrneh r0, [%[p], %[delta]] \n" - - " bics r3, r3, #1 \n" - " ldrneh r3, [%[p], %[delta2]] \n" - - " strh r0, [%[p]], #2 \n" - " strh r3, [%[p]], #2 \n" - - " subs r1, r1, #1 \n" - " bne 2b \n" - "3: \n" - " subs %[lines], %[lines], #1 \n" - " addne %[p], %[p], #(640 - 512) \n" - " addne %[d], %[d], #(320 - 256) \n" - " bne 1b \n" - "4: \n" - - : - : [p] "r" ((uint16 *) (GFX.Screen + starty * GFX_PITCH)), - [d] "r" (GFX.SubZBuffer + starty * GFX_ZPITCH), - [delta] "r" (GFX.Delta << 1), - [delta2] "r" ((GFX.Delta << 1) + 2), - [lines] "r" (endy - starty + 1) - : "r0", "r1", "r3", "cc" - ); - } - - DBG("Rendering the Main Screen...\n"); - - GFX.DB = GFX.ZBuffer; - RenderScreen (GFX.Screen, FALSE, FALSE, MAIN_SCREEN_DEPTH); - - if (SUB_OR_ADD(5)) - { - uint32 back = IPPU.ScreenColors [0]; - uint32 Left = 0; - uint32 Right = 256; - uint32 Count; - - DBG("Addition/Substraction in use...\n"); - - pClip = &IPPU.Clip [0]; - - // some initial values - unsigned int fixedcolour_c; - if (GFX.r2131 & 0x80) { - fixedcolour_c = COLOR_SUB(back, GFX.FixedColour); - } else { - fixedcolour_c = COLOR_ADD(back, GFX.FixedColour); - } - - if (!(Count = pClip->Count [5])) Count = 1; - for (uint32 y = starty; y <= endy; y++) - { - - for (uint32 b = 0; b < Count; b++) - { - if (pClip->Count [5]) - { - Left = pClip->Left [b][5]; - Right = pClip->Right [b][5]; - if (Right <= Left) - continue; - } -#define _ROP_ADD1_2 \ - " mov r0, %[back] \n"\ - ROP_ADD1_2(r0, r1) \ - " strh r0, [%[p]] \n" - -// Arguments can be exchanged on addition, so early exit on back == 0 is possible -#define _ROP_ADD \ - ROP_ADD(r1, %[back]) \ - " strh r1, [%[p]] \n" - - -#define _ROP_SUB1_2 \ - " mov r0, %[back] \n"\ - ROP_SUB1_2(r0, r1) \ - " strh r0, [%[p]] \n" - -#define _ROP_SUB \ -" mov r0, %[back] \n"\ - ROP_SUB(r0, r1) \ - " strh r0, [%[p]] \n" - -#define SUBSCREEN_BG(rop, half) \ -\ -asm volatile (\ -" ldrb r0, [%[d]] \n"\ -"71: \n"\ -\ -" movs r0, r0 \n"\ -" ldreqb r1, [%[d], %[zdelta]] \n"\ -" bne 72f \n"\ -\ -" cmp r1, #1 \n"\ -" ldrhih r1, [%[p], %[delta]] \n"\ -" bls 74f \n"\ -\ -_ROP_##rop##half \ -\ -"72: \n"\ -" add %[p], %[p], #2 \n"\ -" subs %[c], %[c], #1 \n"\ -" ldrneb r0, [%[d], #1]! \n"\ -" bne 71b \n"\ -" b 75f \n"\ -"74: \n"\ -" streqh %[fixedcolour], [%[p]], #2 \n"\ -" strloh %[back], [%[p]], #2 \n"\ -" subs %[c], %[c], #1 \n"\ -" ldrneb r0, [%[d], #1]! \n"\ -" bne 71b \n"\ -"75: \n"\ -:\ -:[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left),\ - [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left),\ - [zdelta] "r" (GFX.DepthDelta),\ - [back] "r" (back),\ - [delta] "r" (GFX.Delta << 1),\ - [fixedcolour] "r" (fixedcolour_c),\ - [c] "r" (Right - Left) \ -: "r0", "r1", "cc"\ -); - if (GFX.r2131 & 0x80) - { - if (GFX.r2131 & 0x40) - { - SUBSCREEN_BG(SUB, 1_2) - } - else - { - SUBSCREEN_BG(SUB, ) - - } - } - else - if (GFX.r2131 & 0x40) - { - SUBSCREEN_BG(ADD, 1_2) - } - else if (back != 0) { - SUBSCREEN_BG(ADD, ) - } - else - { - - if (!pClip->Count [5]) - { - DBG("Copying line with no effect...\n"); - // The backdrop has not been cleared yet - so - // copy the sub-screen to the main screen - // or fill it with the back-drop colour if the - // sub-screen is clear. - asm volatile ( - " ldrb r0, [%[d]] \n" - "31: \n" - - " movs r0, r0 \n" - " ldreqb r1, [%[d], %[zdelta]] \n" - " bne 32f \n" - - " cmp r1, #1 \n" - " ldrhih r0, [%[p], %[delta]] \n" - " strloh %[back], [%[p]] \n" - " streqh %[fixedcolour], [%[p]] \n" - " strhih r0, [%[p]] \n" - - "32: \n" - " subs %[c], %[c], #1 \n" - " add %[p], %[p], #2 \n" - " ldrneb r0, [%[d], #1]! \n" - " bne 31b \n" - " \n" - : - :[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left), - [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left), - [zdelta] "r" (GFX.DepthDelta), - [back] "r" (back), - [delta] "r" (GFX.Delta << 1), - [fixedcolour] "r" (GFX.FixedColour), - [c] "r" (Right - Left) - : "r0", "r1", "cc" - - ); - - } - } - } - } - - } - else - { - - // Subscreen not being added to back - DBG("No addition/substraction in use...\n"); - uint32 back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); - pClip = &IPPU.Clip [0]; - - if (pClip->Count [5]) - { - - DBG("Copying subscreen with clipping...\n"); - - for (uint32 y = starty; y <= endy; y++) - { - for (uint32 b = 0; b < pClip->Count [5]; b++) - { - uint32 Left = pClip->Left [b][5]; - uint32 Right = pClip->Right [b][5]; - if (Left >= Right) continue; - asm volatile ( - - " tst %[c], #1 \n" - " bne 21f \n" - - " ldrb r0, [%[d]], #1 \n" - " add %[p], %[p], #2 \n" - " movs r0, r0 \n" - " streqh %[back], [%[p], #-2] \n" - " subs %[c], %[c], #1 \n" - " beq 22f \n" - - "21: \n" - - " ldrb r0, [%[d]], #1 \n" - " ldrb r1, [%[d]], #1 \n" - " add %[p], %[p], #4 \n" - - " movs r0, r0 \n" - " streqh %[back], [%[p], #-4] \n" - - " movs r1, r1 \n" - " streqh %[back], [%[p], #-2] \n" - - " subs %[c], %[c], #2 \n" - " bhi 21b \n" - "22: \n" - : - :[p] "r" ((uint16 *) (GFX.Screen + y * GFX_PITCH) + Left), - [d] "r" (GFX.ZBuffer + y * GFX_ZPITCH + Left), - [back] "r" (back), - [c] "r" (Right - Left) - : "r0", "r1", "cc" - - ); - } - } - } - else - { - DBG("Copying SubScreen with no clipping...\n"); - - asm volatile ( - "@ -- SubScreen clear \n" - "1113: \n" - " mov r1, #(256/8) \n" - "1112: \n" - " ldr r0, [%[d]], #4 \n" - - " add %[p], %[p], #8 \n" - - " tst r0, #0x0ff \n" - " streqh %[back], [%[p], #-8] \n" - - " tst r0, #0x0ff00 \n" - " streqh %[back], [%[p], #-6] \n" - - " tst r0, #0x0ff0000 \n" - " streqh %[back], [%[p], #-4] \n" - - " tst r0, #0x0ff000000 \n" - " streqh %[back], [%[p], #-2] \n" - - " ldr r0, [%[d]], #4 \n" - - " add %[p], %[p], #8 \n" - - " tst r0, #0x0ff \n" - " streqh %[back], [%[p], #-8] \n" - - " tst r0, #0x0ff00 \n" - " streqh %[back], [%[p], #-6] \n" - - " tst r0, #0x0ff0000 \n" - " streqh %[back], [%[p], #-4] \n" - - " tst r0, #0x0ff000000 \n" - " streqh %[back], [%[p], #-2] \n" - - " subs r1, r1, #1 \n" - " bne 1112b \n" - - " subs %[lines], %[lines], #1 \n" - " add %[p], %[p], #(640-512) \n" - " add %[d], %[d], #(320-256) \n" - " bne 1113b \n" - "1114:" - : - :[p] "r" (GFX.Screen + starty * GFX_PITCH), - [d] "r" (GFX.ZBuffer + starty * GFX_ZPITCH), - [back] "r" (back), - [lines] "r" (endy - starty + 1) - : "r0", "r1", "cc" - ); - } - } - - } - else - { - DBG("No transparency effects in use.\n"); - - // 16bit and transparency but currently no transparency effects in - // operation. - - // get the back colour of the current screen - uint32 back = IPPU.ScreenColors [0] | - (IPPU.ScreenColors [0] << 16); - - // if forceblanking in use then use black instead of the back color - if (PPU.ForcedBlanking) - back = black; - - // not sure what Clip is used for yet - // could be a check to see if there is any clipping present? - if (IPPU.Clip [0].Count[5]) - { - DBG("Clearing background with clipping...\n"); - - // loop through all of the lines that are going to be updated as part of this screen update - for (uint32 y = starty; y <= endy; y++) - { - memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), black, - IPPU.RenderedScreenWidth>>1); - - if (black!=back) - { - for (uint32 c = 0; c < IPPU.Clip [0].Count [5]; c++) - { - //if (IPPU.Clip [0].Right [c][5] > IPPU.Clip [0].Left [c][5]) - //{ - register int width = IPPU.Clip [0].Right [c][5] - IPPU.Clip [0].Left [c][5]; - if (width <= 0) continue; - - asm volatile ( - " mov r0, %[back] \n" - " subs %[width], %[width], #8 \n" - " bmi 2f \n" - " mov r1, r0 \n" - " mov r2, r0 \n" - - "1: \n" - " subs %[width], %[width], #8 \n" - " stmia %[p]!, {r0, r1, r2, %[back]}\n" - " bpl 1b \n" - - "2: \n" - " tst %[width], #1 \n" - " strneh %[back], [%[p]], #2 \n" - - " tst %[width], #2 \n" - " strne %[back], [%[p]], #4 \n" - - " tst %[width], #4 \n" - " stmia %[p]!, {r0, %[back]}\n" - - : [width] "+r" (width) - : [back] "r" (back | (back << 16)), - [p] "r" (((uint16 *) (GFX.SubScreen + y * GFX_PITCH)) + IPPU.Clip [0].Left [c][5]) - : "r0", "r1", "r2", "cc" - ); - //} - } - } - } - - } - else - { - DBG("Clearing background with no clipping...\n"); - - // there is no clipping to worry about so just fill with the back colour - for (uint32 y = starty; y <= endy; y++) { - memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back, (256>>1)); - } - - } - - // If Forced blanking is not in effect - if (!PPU.ForcedBlanking) - { - DBG("Forced Blanking not in use. Clearing ZBuffer ... !!\n"); - // Clear the Zbuffer for each of the lines which are going to be updated - for (uint32 y = starty; y <= endy; y++) { - memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0, (256>>2)); - } - DBG("Rendering screen !!\n"); - GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object - RenderScreen (GFX.Screen, FALSE, TRUE, SUB_SCREEN_DEPTH); - - } - } - IPPU.PreviousLine = IPPU.CurrentLine; -} - -static void S9xUpdateScreenNoTransparency () // ~30-50ms! (called from FLUSH_REDRAW()) -{ - uint32 starty = GFX.StartY; - uint32 endy = GFX.EndY; - - uint32 black = BLACK | (BLACK << 16); - - // get back colour to be used in clearing the screen - register uint32 back; - if (!(GFX.r2131 & 0x80) && (GFX.r2131 & 0x20) && - (PPU.FixedColourRed || PPU.FixedColourGreen || PPU.FixedColourBlue)) - { - back = (PPU.FixedColourRed << 11) | (PPU.FixedColourGreen << 6) | (1 << 5) | (PPU.FixedColourBlue); - back = (back << 16) | back; - } - else - { - back = IPPU.ScreenColors [0] | (IPPU.ScreenColors [0] << 16); - } - - // if Forcedblanking in use then back colour becomes black - if (PPU.ForcedBlanking) - back = black; - else - { - SelectTileRenderer (TRUE, false); //selects the tile renderers to be used - // TRUE means to use the default - // FALSE means use best renderer based on current - // graphics register settings - } - - // now clear all graphics lines which are being updated using the back colour - for (register uint32 y = starty; y <= endy; y++) - { - memset32 ((uint32_t*)(GFX.Screen + y * GFX_PITCH), back, - IPPU.RenderedScreenWidth>>1); - } - - if (!PPU.ForcedBlanking) - { - // Loop through all lines being updated and clear the - // zbuffer for each of the lines - for (uint32 y = starty; y <= endy; y++) - { - memset32 ((uint32_t*)(GFX.ZBuffer + y * GFX_ZPITCH), 0, - IPPU.RenderedScreenWidth>>2); - } - GFX.DB = GFX.ZBuffer; // save pointer to Zbuffer in GFX object - GFX.pCurrentClip = &IPPU.Clip [0]; - -// Define an inline function to handle clipping -#define FIXCLIP(n) \ -if (GFX.r212c & (1 << (n))) \ - GFX.pCurrentClip = &IPPU.Clip [0]; \ -else \ - GFX.pCurrentClip = &IPPU.Clip [1] - -// Define an inline function to handle which BGs are being displayed -#define DISPLAY(n) ((GFX.r212c & n) || ((GFX.r212d & n) && subadd)) - - uint8 subadd = GFX.r2131 & 0x3f; - - // go through all BGS are check if they need to be displayed - bool8_32 BG0 = DISPLAY(1) && !(Settings.os9x_hack & GFX_IGNORE_BG0); - bool8_32 BG1 = DISPLAY(2) && !(Settings.os9x_hack & GFX_IGNORE_BG1); - bool8_32 BG2 = DISPLAY(4) && !(Settings.os9x_hack & GFX_IGNORE_BG2); - bool8_32 BG3 = DISPLAY(8) && !(Settings.os9x_hack & GFX_IGNORE_BG3); - bool8_32 OB = DISPLAY(16) && !(Settings.os9x_hack & GFX_IGNORE_OBJ); - - if (PPU.BGMode <= 1) - { - // screen modes 0 and 1 - if (OB) - { - FIXCLIP(4); - DrawOBJS (); - } - if (BG0) - { - FIXCLIP(0); - DrawBackground (PPU.BGMode, 0, 10, 14); - } - if (BG1) - { - FIXCLIP(1); - DrawBackground (PPU.BGMode, 1, 9, 13); - } - if (BG2) - { - FIXCLIP(2); - DrawBackground (PPU.BGMode, 2, 3, - PPU.BG3Priority ? 17 : 6); - } - if (BG3 && PPU.BGMode == 0) - { - FIXCLIP(3); - DrawBackground (PPU.BGMode, 3, 2, 5); - } - } - else if (PPU.BGMode != 7) - { - // screen modes 2 and up but not mode 7 - if (OB) - { - FIXCLIP(4); - DrawOBJS (); - } - if (BG0) - { - FIXCLIP(0); - DrawBackground (PPU.BGMode, 0, 5, 13); - } - if (BG1 && PPU.BGMode != 6) - { - FIXCLIP(1); - DrawBackground (PPU.BGMode, 1, 2, 9); - } - } - else - { - // screen mode 7 - DrawBGMode7Background16New (GFX.Screen); - if (OB) - { - FIXCLIP(4); - DrawOBJS (); - } - } - } - IPPU.PreviousLine = IPPU.CurrentLine; -} - -#ifdef __OLD_RASTER_FX__ -static void S9xUpdateScreen_delayedRasterFx () // ~30-50ms! (called from FLUSH_REDRAW()) -#else -void S9xUpdateScreen () // ~30-50ms! (called from FLUSH_REDRAW()) -#endif -{ - int StartY, EndY, CurrentLine, CurrentROp; - - StartY = IPPU.PreviousLine; - if ((EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) EndY = PPU.ScreenHeight - 1; - - GFX.S = GFX.Screen; - - CurrentROp = 0; - CurrentLine = StartY; -#ifdef __DEBUG__ - printf("Start screen update. ROPCount: %d, StartY: %d, EndY: %d\n", ROpCount, StartY, EndY); -#endif - do { - while ((CurrentROp < ROpCount) && ((rops[CurrentROp].line == CurrentLine) || (!wouldRasterAlterStatus(&rops[CurrentROp])))) { - #ifdef __DEBUG__ - printf("Processing ROP %d/%d. Line: %d\n", CurrentROp, ROpCount, CurrentLine); - #endif - doRaster(&rops[CurrentROp]); - CurrentROp++; - } - - GFX.StartY = CurrentLine; - if ((CurrentROp < ROpCount) && ((rops[CurrentROp].line - 1) <= EndY)) GFX.EndY = rops[CurrentROp].line - 1; - else GFX.EndY = EndY; - - #ifdef __DEBUG__ - printf("Partial screen update. ROPCount: %d, StartY: %d, EndY: %d\n", ROpCount, GFX.StartY, GFX.EndY); - #endif - - // get local copies of vid registers to be used later - GFX.r2131 = GFX.r2131_s; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN - GFX.r212c = GFX.r212c_s; // MAIN SCREEN, DESIGNATION - used to enable BGS - GFX.r212d = GFX.r212d_s; // SUB SCREEN DESIGNATION - used to enable sub BGS - GFX.r2130 = GFX.r2130_s; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION - - // If external sync is off and - // main screens have not been configured the same as the sub screen and - // color addition and subtraction has been disabled then - // Pseudo is 1 - // anything else it is 0 - GFX.Pseudo = (Memory.FillRAM[0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION? - (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens? - (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS? - - // If sprite data has been changed then go through and - // refresh the sprites. - if (IPPU.OBJChanged) { - #ifdef __DEBUG__ - printf("Objects changed !! setting up Objects...\n"); - #endif - S9xSetupOBJ(); - } - - if (PPU.RecomputeClipWindows) { - #ifdef __DEBUG__ - printf("Clipping changed !! recalculating clipping...\n"); - #endif - ComputeClipWindows(); - } - - if (Settings.Transparency) S9xUpdateScreenTransparency(); - else S9xUpdateScreenNoTransparency(); - CurrentLine = GFX.EndY + 1; - - #ifdef __DEBUG__ - printf("Finished partial screen update.\n", ROpCount, StartY, EndY); - #endif - - - } while ((CurrentROp < ROpCount) && (CurrentLine <= EndY)); - -#ifdef __DEBUG__ - printf("End screen update. ROPCount: %d, CurrentROp: %d, StartY: %d, EndY: %d\n", ROpCount, CurrentROp, StartY, EndY); -#endif - - RESET_ROPS(CurrentROp); - -#ifdef __DEBUG__ - printf("ROps cleaned\n"); -#endif - - PPU.BG[0].OffsetsChanged = 0; - PPU.BG[1].OffsetsChanged = 0; - PPU.BG[2].OffsetsChanged = 0; - PPU.BG[3].OffsetsChanged = 0; -} - -#ifdef __OLD_RASTER_FX__ - -static void S9xUpdateScreen_normalRasterFx () // ~30-50ms! (called from FLUSH_REDRAW()) -{ - GFX.StartY = IPPU.PreviousLine; - if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) GFX.EndY = PPU.ScreenHeight - 1; - - GFX.S = GFX.Screen; - -#ifdef __DEBUG__ - printf("Start screen update. StartY: %d, EndY: %d\n", GFX.StartY, GFX.EndY); -#endif - // get local copies of vid registers to be used later - GFX.r2131 = GFX.r2131_s; // ADDITION/SUBTRACTION & SUBTRACTION DESIGNATION FOR EACH SCREEN - GFX.r212c = GFX.r212c_s; // MAIN SCREEN, DESIGNATION - used to enable BGS - GFX.r212d = GFX.r212d_s; // SUB SCREEN DESIGNATION - used to enable sub BGS - GFX.r2130 = GFX.r2130_s; // INITIAL SETTINGS FOR FIXED COLOR ADDITION OR SCREEN ADDITION - - // If external sync is off and - // main screens have not been configured the same as the sub screen and - // color addition and subtraction has been disabled then - // Pseudo is 1 - // anything else it is 0 - GFX.Pseudo = (Memory.FillRAM[0x2133] & 8) != 0 && // Use EXTERNAL SYNCHRONIZATION? - (GFX.r212c & 15) != (GFX.r212d & 15) && // Are the main screens different from the sub screens? - (GFX.r2131 & 0x3f) == 0; // Is colour data addition/subtraction disabled on all BGS? - - // If sprite data has been changed then go through and - // refresh the sprites. - if (IPPU.OBJChanged) { - #ifdef __DEBUG__ - printf("Objects changed !! setting up Objects...\n"); - #endif - S9xSetupOBJ(); - } - - if (PPU.RecomputeClipWindows) { - #ifdef __DEBUG__ - printf("Clipping changed !! recalculating clipping...\n"); - #endif - ComputeClipWindows(); - } - - if (Settings.Transparency) S9xUpdateScreenTransparency(); - else S9xUpdateScreenNoTransparency(); - -#ifdef __DEBUG__ - printf("End screen update. StartY: %d, EndY: %d\n", GFX.StartY, GFX.EndY); -#endif - PPU.BG[0].OffsetsChanged = 0; - PPU.BG[1].OffsetsChanged = 0; - PPU.BG[2].OffsetsChanged = 0; - PPU.BG[3].OffsetsChanged = 0; -} - -void S9xUpdateScreen() -{ - if (snesMenuOptions.delayedRasterFX) S9xUpdateScreen_delayedRasterFx(); - else S9xUpdateScreen_normalRasterFx (); -} -#endif - -// -x- - -#ifdef GFX_MULTI_FORMAT - -#define _BUILD_PIXEL(F) \ -uint32 BuildPixel##F(uint32 R, uint32 G, uint32 B) \ -{ \ - return (BUILD_PIXEL_##F(R,G,B)); \ -}\ -uint32 BuildPixel2##F(uint32 R, uint32 G, uint32 B) \ -{ \ - return (BUILD_PIXEL2_##F(R,G,B)); \ -} \ -void DecomposePixel##F(uint32 pixel, uint32 &R, uint32 &G, uint32 &B) \ -{ \ - DECOMPOSE_PIXEL_##F(pixel,R,G,B); \ -} - -_BUILD_PIXEL(RGB565) -_BUILD_PIXEL(RGB555) -_BUILD_PIXEL(BGR565) -_BUILD_PIXEL(BGR555) -_BUILD_PIXEL(GBR565) -_BUILD_PIXEL(GBR555) -_BUILD_PIXEL(RGB5551) - -bool8_32 S9xSetRenderPixelFormat (int format) -{ - extern uint32 current_graphic_format; - - current_graphic_format = format; - - switch (format) - { - case RGB565: - _BUILD_SETUP(RGB565) - return (TRUE); - case RGB555: - _BUILD_SETUP(RGB555) - return (TRUE); - case BGR565: - _BUILD_SETUP(BGR565) - return (TRUE); - case BGR555: - _BUILD_SETUP(BGR555) - return (TRUE); - case GBR565: - _BUILD_SETUP(GBR565) - return (TRUE); - case GBR555: - _BUILD_SETUP(GBR555) - return (TRUE); - case RGB5551: - _BUILD_SETUP(RGB5551) - return (TRUE); - default: - break; - } - return (FALSE); -} -#endif diff --git a/src/globals.c b/src/globals.c new file mode 100644 index 0000000..89649cb --- /dev/null +++ b/src/globals.c @@ -0,0 +1,437 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +// START_EXTERN_C +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "dsp1.h" +#include "missing.h" +#include "cpuexec.h" +#include "apu.h" +#include "dma.h" +#include "fxemu.h" +#include "gfx.h" +#include "soundux.h" +#include "cheats.h" +#include "sa1.h" +// END_EXTERN_C + +START_EXTERN_C +char String[513]; + +int (*APUMainLoop)(int); + +Missing missing; + +SICPU ICPU; + +SCPUState CPU; + +//SRegisters Registers; + +SAPU APU; + +SIAPU IAPU; + +SAPURegisters APURegisters; + +SSettings Settings; + +SDSP1 DSP1; + +#ifdef USE_SA1 +SSA1Registers SA1Registers; + +SSA1 SA1; + +uint8 *SA1_Map [MEMMAP_NUM_BLOCKS]; +uint8 *SA1_WriteMap [MEMMAP_NUM_BLOCKS]; +#endif + +uint8 *SRAM = NULL; +uint8 *ROM = NULL; +uint8 *RegRAM = NULL; +uint8 *C4RAM = NULL; + +long OpAddress = 0; + +CMemory Memory; + +SSNESGameFixes SNESGameFixes; + +END_EXTERN_C + +#ifndef ZSNES_FX +FxInit_s SuperFX; +#else +START_EXTERN_C +uint8 *SFXPlotTable = NULL; +END_EXTERN_C +#endif + +SPPU PPU; +InternalPPU IPPU; + +SDMA DMA[8]; + +uint8 *HDMAMemPointers [8]; +uint8 *HDMABasePointers [8]; + +SBG BG; + +SGFX GFX; +SLineData LineData[240]; +SLineMatrixData LineMatrixData [240]; + +uint8 Mode7Depths [2]; +NormalTileRenderer DrawTilePtr = NULL; +ClippedTileRenderer DrawClippedTilePtr = NULL; +NormalTileRenderer DrawHiResTilePtr = NULL; +ClippedTileRenderer DrawHiResClippedTilePtr = NULL; +LargePixelRenderer DrawLargePixelPtr = NULL; + +uint32 odd_high[4][16]; +uint32 odd_low[4][16]; +uint32 even_high[4][16]; +uint32 even_low[4][16]; + +#ifdef GFX_MULTI_FORMAT + +uint32 RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_RGB565; +uint32 GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_RGB565; +uint32 BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_RGB565; +uint32 RED_HI_BIT_MASK = RED_HI_BIT_MASK_RGB565; +uint32 GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_RGB565; +uint32 BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_RGB565; +uint32 MAX_RED = MAX_RED_RGB565; +uint32 MAX_GREEN = MAX_GREEN_RGB565; +uint32 MAX_BLUE = MAX_BLUE_RGB565; +uint32 SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_RGB565; +uint32 GREEN_HI_BIT = (MAX_GREEN_RGB565 + 1) >> 1; +uint32 RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_RGB565 | + GREEN_LOW_BIT_MASK_RGB565 | + BLUE_LOW_BIT_MASK_RGB565); +uint32 RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_RGB565 | + GREEN_HI_BIT_MASK_RGB565 | + BLUE_HI_BIT_MASK_RGB565); +uint32 RGB_HI_BITS_MASKx2 = (RED_HI_BIT_MASK_RGB565 | + GREEN_HI_BIT_MASK_RGB565 | + BLUE_HI_BIT_MASK_RGB565) << 1; +uint32 RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; +uint32 FIRST_COLOR_MASK = FIRST_COLOR_MASK_RGB565; +uint32 SECOND_COLOR_MASK = SECOND_COLOR_MASK_RGB565; +uint32 THIRD_COLOR_MASK = THIRD_COLOR_MASK_RGB565; +uint32 ALPHA_BITS_MASK = ALPHA_BITS_MASK_RGB565; +uint32 FIRST_THIRD_COLOR_MASK = 0; +uint32 TWO_LOW_BITS_MASK = 0; +uint32 HIGH_BITS_SHIFTED_TWO_MASK = 0; + +uint32 current_graphic_format = RGB565; +#endif + +uint8 GetBank = 0; +SCheatData Cheat; + +SoundStatus so; +SSoundData SoundData; +int Echo [24000]; +int DummyEchoBuffer [SOUND_BUFFER_SIZE]; +int MixBuffer [SOUND_BUFFER_SIZE]; +int EchoBuffer [SOUND_BUFFER_SIZE]; +int FilterTaps [8]; +unsigned long Z = 0; +int Loop [16]; + +uint16 SignExtend [2] = { + 0x00, 0xff00 +}; + +int HDMA_ModeByteCounts [8] = { + 1, 2, 2, 4, 4, 0, 0, 0 +}; + +uint8 BitShifts[8][4] = +{ + {2, 2, 2, 2}, // 0 + {4, 4, 2, 0}, // 1 + {4, 4, 0, 0}, // 2 + {8, 4, 0, 0}, // 3 + {8, 2, 0, 0}, // 4 + {4, 2, 0, 0}, // 5 + {4, 0, 0, 0}, // 6 + {8, 0, 0, 0} // 7 +}; +uint8 TileShifts[8][4] = +{ + {4, 4, 4, 4}, // 0 + {5, 5, 4, 0}, // 1 + {5, 5, 0, 0}, // 2 + {6, 5, 0, 0}, // 3 + {6, 4, 0, 0}, // 4 + {5, 4, 0, 0}, // 5 + {5, 0, 0, 0}, // 6 + {6, 0, 0, 0} // 7 +}; +uint8 PaletteShifts[8][4] = +{ + {2, 2, 2, 2}, // 0 + {4, 4, 2, 0}, // 1 + {4, 4, 0, 0}, // 2 + {0, 4, 0, 0}, // 3 + {0, 2, 0, 0}, // 4 + {4, 2, 0, 0}, // 5 + {4, 0, 0, 0}, // 6 + {0, 0, 0, 0} // 7 +}; +uint8 PaletteMasks[8][4] = +{ + {7, 7, 7, 7}, // 0 + {7, 7, 7, 0}, // 1 + {7, 7, 0, 0}, // 2 + {0, 7, 0, 0}, // 3 + {0, 7, 0, 0}, // 4 + {7, 7, 0, 0}, // 5 + {7, 0, 0, 0}, // 6 + {0, 0, 0, 0} // 7 +}; +uint8 Depths[8][4] = +{ + {TILE_2BIT, TILE_2BIT, TILE_2BIT, TILE_2BIT}, // 0 + {TILE_4BIT, TILE_4BIT, TILE_2BIT, 0}, // 1 + {TILE_4BIT, TILE_4BIT, 0, 0}, // 2 + {TILE_8BIT, TILE_4BIT, 0, 0}, // 3 + {TILE_8BIT, TILE_2BIT, 0, 0}, // 4 + {TILE_4BIT, TILE_2BIT, 0, 0}, // 5 + {TILE_8BIT, 0, 0, 0}, // 6 + {0, 0, 0, 0} // 7 +}; +uint8 BGSizes [2] = { + 8, 16 +}; +uint32 DirectColourMaps [8][256]; + +long FilterValues[4][2] = +{ + {0, 0}, + {240, 0}, + {488, -240}, + {460, -208} +}; + +int NoiseFreq [32] = { + 0, 16, 21, 25, 31, 42, 50, 63, 84, 100, 125, 167, 200, 250, 333, + 400, 500, 667, 800, 1000, 1300, 1600, 2000, 2700, 3200, 4000, + 5300, 6400, 8000, 10700, 16000, 32000 +}; + +uint32 HeadMask [4] = { +#ifdef LSB_FIRST + 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000 +#else + 0xffffffff, 0x00ffffff, 0x0000ffff, 0x000000ff +#endif +}; + +uint32 TailMask [5] = { +#ifdef LSB_FIRST + 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff +#else + 0x00000000, 0xff000000, 0xffff0000, 0xffffff00, 0xffffffff +#endif +}; + +START_EXTERN_C +uint8 APUROM [64] = +{ + 0xCD,0xEF,0xBD,0xE8,0x00,0xC6,0x1D,0xD0,0xFC,0x8F,0xAA,0xF4,0x8F, + 0xBB,0xF5,0x78,0xCC,0xF4,0xD0,0xFB,0x2F,0x19,0xEB,0xF4,0xD0,0xFC, + 0x7E,0xF4,0xD0,0x0B,0xE4,0xF5,0xCB,0xF4,0xD7,0x00,0xFC,0xD0,0xF3, + 0xAB,0x01,0x10,0xEF,0x7E,0xF4,0x10,0xEB,0xBA,0xF6,0xDA,0x00,0xBA, + 0xF4,0xC4,0xF4,0xDD,0x5D,0xD0,0xDB,0x1F,0x00,0x00,0xC0,0xFF +}; + +#ifdef NETPLAY_SUPPORT +SNetPlay NetPlay; +#endif + +// Raw SPC700 instruction cycle lengths +int32 S9xAPUCycleLengths [256] = +{ + /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */ + /* 00 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8, + /* 10 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 4, 6, + /* 20 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 5, 4, + /* 30 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 3, 8, + /* 40 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 6, 6, + /* 50 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 4, 5, 2, 2, 4, 3, + /* 60 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 5, 5, + /* 70 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 6, + /* 80 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 2, 4, 5, + /* 90 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2,12, 5, + /* a0 */ 3, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 2, 4, 4, + /* b0 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 4, + /* c0 */ 3, 8, 4, 5, 4, 5, 4, 7, 2, 5, 6, 4, 5, 2, 4, 9, + /* d0 */ 2, 8, 4, 5, 5, 6, 6, 7, 4, 5, 4, 5, 2, 2, 6, 3, + /* e0 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3, + /* f0 */ 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3 +}; + +// Actual data used by CPU emulation, will be scaled by APUReset routine +// to be relative to the 65c816 instruction lengths. +int32 S9xAPUCycles [256] = +{ + /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */ + /* 00 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8, + /* 10 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 4, 6, + /* 20 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 5, 4, + /* 30 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 3, 8, + /* 40 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 6, 6, + /* 50 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 4, 5, 2, 2, 4, 3, + /* 60 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 5, 5, + /* 70 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 6, + /* 80 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 2, 4, 5, + /* 90 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2,12, 5, + /* a0 */ 3, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 2, 4, 4, + /* b0 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 4, + /* c0 */ 3, 8, 4, 5, 4, 5, 4, 7, 2, 5, 6, 4, 5, 2, 4, 9, + /* d0 */ 2, 8, 4, 5, 5, 6, 6, 7, 4, 5, 4, 5, 2, 2, 6, 3, + /* e0 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3, + /* f0 */ 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3 +}; + +#ifndef VAR_CYCLES +uint8 S9xE1M1X1 [256] = { + 8, 6, 8, 4, 5, 3, 5, 6, 3, 2, 2, 4, 6, 4, 6, 5, /* e=1, m=1, x=1 */ + 2, 5, 5, 7, 5, 4, 6, 6, 2, 4, 2, 2, 6, 4, 7, 5, + 6, 6, 8, 4, 3, 3, 5, 6, 4, 2, 2, 5, 4, 4, 6, 5, + 2, 5, 5, 7, 4, 4, 6, 6, 2, 4, 2, 2, 4, 4, 7, 5, + 7, 6, 2, 4, 0, 3, 5, 6, 3, 2, 2, 3, 3, 4, 6, 5, + 2, 5, 5, 7, 0, 4, 6, 6, 2, 4, 3, 2, 4, 4, 7, 5, + 6, 6, 6, 4, 3, 3, 5, 6, 4, 2, 2, 6, 5, 4, 6, 5, + 2, 5, 5, 7, 4, 4, 6, 6, 2, 4, 4, 2, 6, 4, 7, 5, + 2, 6, 3, 4, 3, 3, 3, 6, 2, 2, 2, 3, 4, 4, 4, 5, + 2, 5, 5, 7, 4, 4, 4, 6, 2, 4, 2, 2, 4, 4, 4, 5, + 2, 6, 2, 4, 3, 3, 3, 6, 2, 2, 2, 4, 4, 4, 4, 5, + 2, 5, 5, 7, 4, 4, 4, 6, 2, 4, 2, 2, 4, 4, 4, 5, + 2, 6, 3, 4, 3, 3, 5, 6, 2, 2, 2, 3, 4, 4, 6, 5, + 2, 5, 5, 7, 6, 4, 6, 6, 2, 4, 3, 3, 6, 4, 7, 5, + 2, 6, 3, 4, 3, 3, 5, 6, 2, 2, 2, 3, 4, 4, 6, 5, + 2, 5, 5, 7, 5, 4, 6, 6, 2, 4, 4, 2, 6, 4, 7, 5 +}; + +uint8 S9xE0M1X1 [256] = { + 8, 6, 8, 4, 5, 3, 5, 6, 3, 2, 2, 4, 6, 4, 6, 5, /* e=0, m=1, x=1 */ + 2, 5, 5, 7, 5, 4, 6, 6, 2, 4, 2, 2, 6, 4, 7, 5, + 6, 6, 8, 4, 3, 3, 5, 6, 4, 2, 2, 5, 4, 4, 6, 5, + 2, 5, 5, 7, 4, 4, 6, 6, 2, 4, 2, 2, 4, 4, 7, 5, + 7, 6, 2, 4, 0, 3, 5, 6, 3, 2, 2, 3, 3, 4, 6, 5, + 2, 5, 5, 7, 0, 4, 6, 6, 2, 4, 3, 2, 4, 4, 7, 5, + 6, 6, 6, 4, 3, 3, 5, 6, 4, 2, 2, 6, 5, 4, 6, 5, + 2, 5, 5, 7, 4, 4, 6, 6, 2, 4, 4, 2, 6, 4, 7, 5, + 2, 6, 3, 4, 3, 3, 3, 6, 2, 2, 2, 3, 4, 4, 4, 5, + 2, 5, 5, 7, 4, 4, 4, 6, 2, 4, 2, 2, 4, 4, 4, 5, + 2, 6, 2, 4, 3, 3, 3, 6, 2, 2, 2, 4, 4, 4, 4, 5, + 2, 5, 5, 7, 4, 4, 4, 6, 2, 4, 2, 2, 4, 4, 4, 5, + 2, 6, 3, 4, 3, 3, 5, 6, 2, 2, 2, 3, 4, 4, 6, 5, + 2, 5, 5, 7, 6, 4, 6, 6, 2, 4, 3, 3, 6, 4, 7, 5, + 2, 6, 3, 4, 3, 3, 5, 6, 2, 2, 2, 3, 4, 4, 6, 5, + 2, 5, 5, 7, 5, 4, 6, 6, 2, 4, 4, 2, 6, 4, 7, 5 +}; + +uint8 S9xE0M0X1 [256] = { + 8, 7, 8, 5, 7, 4, 7, 7, 3, 3, 2, 4, 8, 5, 8, 6, /* e=0, m=0, x=1 */ + 2, 6, 6, 8, 7, 5, 8, 7, 2, 5, 2, 2, 8, 5, 9, 6, + 6, 7, 8, 5, 4, 4, 7, 7, 4, 3, 2, 5, 5, 5, 8, 6, + 2, 6, 6, 8, 5, 5, 8, 7, 2, 5, 2, 2, 5, 5, 9, 6, + 7, 7, 2, 5, 0, 4, 7, 7, 4, 3, 2, 3, 3, 5, 8, 6, + 2, 6, 6, 8, 0, 5, 8, 7, 2, 5, 3, 2, 4, 5, 9, 6, + 6, 7, 6, 5, 4, 4, 7, 7, 5, 3, 2, 6, 5, 5, 8, 6, + 2, 6, 6, 8, 5, 5, 8, 7, 2, 5, 4, 2, 6, 5, 9, 6, + 2, 7, 3, 5, 3, 4, 3, 7, 2, 3, 2, 3, 4, 5, 4, 6, + 2, 6, 6, 8, 4, 5, 4, 7, 2, 5, 2, 2, 5, 5, 5, 6, + 2, 7, 2, 5, 3, 4, 3, 7, 2, 3, 2, 4, 4, 5, 4, 6, + 2, 6, 6, 8, 4, 5, 4, 7, 2, 5, 2, 2, 4, 5, 4, 6, + 2, 7, 3, 5, 3, 4, 7, 7, 2, 3, 2, 3, 4, 5, 8, 6, + 2, 6, 6, 8, 6, 5, 8, 7, 2, 5, 3, 3, 6, 5, 9, 6, + 2, 7, 3, 5, 3, 4, 7, 7, 2, 3, 2, 3, 4, 5, 8, 6, + 2, 6, 6, 8, 5, 5, 8, 7, 2, 5, 4, 2, 6, 5, 9, 6 +}; + +uint8 S9xE0M1X0 [256] = { + 8, 6, 8, 4, 5, 3, 5, 6, 3, 2, 2, 4, 6, 4, 6, 5, /* e=0, m=1, x=0 */ + 2, 6, 5, 7, 5, 4, 6, 6, 2, 5, 2, 2, 6, 5, 7, 5, + 6, 6, 8, 4, 3, 3, 5, 6, 4, 2, 2, 5, 4, 4, 6, 5, + 2, 6, 5, 7, 4, 4, 6, 6, 2, 5, 2, 2, 5, 5, 7, 5, + 7, 6, 2, 4, 0, 3, 5, 6, 4, 2, 2, 3, 3, 4, 6, 5, + 2, 6, 5, 7, 0, 4, 6, 6, 2, 5, 4, 2, 4, 5, 7, 5, + 6, 6, 6, 4, 3, 3, 5, 6, 5, 2, 2, 6, 5, 4, 6, 5, + 2, 6, 5, 7, 4, 4, 6, 6, 2, 5, 5, 2, 6, 5, 7, 5, + 2, 6, 3, 4, 4, 3, 4, 6, 2, 2, 2, 3, 5, 4, 5, 5, + 2, 6, 5, 7, 5, 4, 5, 6, 2, 5, 2, 2, 4, 5, 5, 5, + 3, 6, 3, 4, 4, 3, 4, 6, 2, 2, 2, 4, 5, 4, 5, 5, + 2, 6, 5, 7, 5, 4, 5, 6, 2, 5, 2, 2, 5, 5, 5, 5, + 3, 6, 3, 4, 4, 3, 6, 6, 2, 2, 2, 3, 5, 4, 6, 5, + 2, 6, 5, 7, 6, 4, 8, 6, 2, 5, 4, 3, 6, 5, 7, 5, + 3, 6, 3, 4, 4, 3, 6, 6, 2, 2, 2, 3, 5, 4, 6, 5, + 2, 6, 5, 7, 5, 4, 8, 6, 2, 5, 5, 2, 6, 5, 7, 5 +}; + +uint8 S9xE0M0X0 [256] = { + 8, 7, 8, 5, 7, 4, 7, 7, 3, 3, 2, 4, 8, 5, 8, 6, /* e=0, m=0, x=0 */ + 2, 7, 6, 8, 7, 5, 8, 7, 2, 6, 2, 2, 8, 6, 9, 6, + 6, 7, 8, 5, 4, 4, 7, 7, 4, 3, 2, 5, 5, 5, 8, 6, + 2, 7, 6, 8, 5, 5, 8, 7, 2, 6, 2, 2, 6, 6, 9, 6, + 7, 7, 2, 5, 0, 4, 7, 7, 3, 3, 2, 3, 3, 5, 8, 6, + 2, 7, 6, 8, 0, 5, 8, 7, 2, 6, 4, 2, 4, 6, 9, 6, + 6, 7, 6, 5, 4, 4, 7, 7, 4, 3, 2, 6, 5, 5, 8, 6, + 2, 7, 6, 8, 5, 5, 8, 7, 2, 6, 5, 2, 6, 6, 9, 6, + 2, 7, 3, 5, 4, 4, 4, 7, 2, 3, 2, 3, 5, 5, 5, 6, + 2, 7, 6, 8, 5, 5, 5, 7, 2, 6, 2, 2, 5, 6, 6, 6, + 3, 7, 3, 5, 4, 4, 4, 7, 2, 3, 2, 4, 5, 5, 5, 6, + 2, 7, 6, 8, 5, 5, 5, 7, 2, 6, 2, 2, 5, 6, 5, 6, + 3, 7, 3, 5, 4, 4, 7, 7, 2, 3, 2, 3, 5, 5, 8, 6, + 2, 7, 6, 8, 6, 5, 8, 7, 2, 6, 4, 3, 6, 6, 9, 6, + 3, 7, 3, 5, 4, 4, 7, 7, 2, 3, 2, 3, 5, 5, 8, 6, + 2, 7, 6, 8, 5, 5, 8, 7, 2, 6, 5, 2, 6, 6, 9, 6 +}; +#endif + +END_EXTERN_C diff --git a/src/globals.cpp b/src/globals.cpp deleted file mode 100644 index 9f9bbbd..0000000 --- a/src/globals.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - extern "C" { -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "dsp1.h" -#include "missing.h" -#include "cpuexec.h" -#include "apu.h" -#include "dma.h" -#include "fxemu.h" -#include "gfx.h" -#include "soundux.h" -#include "cheats.h" -#include "sa1.h" - } -START_EXTERN_C -char String[513]; - -int (*APUMainLoop)(int); - -struct Missing missing; - -struct SICPU ICPU; - -struct SCPUState CPU; - -//struct SRegisters Registers; - -struct SAPU APU; - -struct SIAPU IAPU; - -struct SAPURegisters APURegisters; - -struct SSettings Settings; - -struct SDSP1 DSP1; - -#ifdef USE_SA1 -struct SSA1Registers SA1Registers; - -struct SSA1 SA1; - -uint8 *SA1_Map [MEMMAP_NUM_BLOCKS]; -uint8 *SA1_WriteMap [MEMMAP_NUM_BLOCKS]; -#endif - -uint8 *SRAM = NULL; -uint8 *ROM = NULL; -uint8 *RegRAM = NULL; -uint8 *C4RAM = NULL; - -long OpAddress = 0; - -CMemory Memory; - -struct SSNESGameFixes SNESGameFixes; - -END_EXTERN_C - -#ifndef ZSNES_FX -struct FxInit_s SuperFX; -#else -START_EXTERN_C -uint8 *SFXPlotTable = NULL; -END_EXTERN_C -#endif - -struct SPPU PPU; -struct InternalPPU IPPU; - -struct SDMA DMA[8]; - -uint8 *HDMAMemPointers [8]; -uint8 *HDMABasePointers [8]; - -struct SBG BG; - -struct SGFX GFX; -struct SLineData LineData[240]; -struct SLineMatrixData LineMatrixData [240]; - -uint8 Mode7Depths [2]; -NormalTileRenderer DrawTilePtr = NULL; -ClippedTileRenderer DrawClippedTilePtr = NULL; -NormalTileRenderer DrawHiResTilePtr = NULL; -ClippedTileRenderer DrawHiResClippedTilePtr = NULL; -LargePixelRenderer DrawLargePixelPtr = NULL; - -uint32 odd_high[4][16]; -uint32 odd_low[4][16]; -uint32 even_high[4][16]; -uint32 even_low[4][16]; - -#ifdef GFX_MULTI_FORMAT - -uint32 RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_RGB565; -uint32 GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_RGB565; -uint32 BLUE_LOW_BIT_MASK = BLUE_LOW_BIT_MASK_RGB565; -uint32 RED_HI_BIT_MASK = RED_HI_BIT_MASK_RGB565; -uint32 GREEN_HI_BIT_MASK = GREEN_HI_BIT_MASK_RGB565; -uint32 BLUE_HI_BIT_MASK = BLUE_HI_BIT_MASK_RGB565; -uint32 MAX_RED = MAX_RED_RGB565; -uint32 MAX_GREEN = MAX_GREEN_RGB565; -uint32 MAX_BLUE = MAX_BLUE_RGB565; -uint32 SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_RGB565; -uint32 GREEN_HI_BIT = (MAX_GREEN_RGB565 + 1) >> 1; -uint32 RGB_LOW_BITS_MASK = (RED_LOW_BIT_MASK_RGB565 | - GREEN_LOW_BIT_MASK_RGB565 | - BLUE_LOW_BIT_MASK_RGB565); -uint32 RGB_HI_BITS_MASK = (RED_HI_BIT_MASK_RGB565 | - GREEN_HI_BIT_MASK_RGB565 | - BLUE_HI_BIT_MASK_RGB565); -uint32 RGB_HI_BITS_MASKx2 = (RED_HI_BIT_MASK_RGB565 | - GREEN_HI_BIT_MASK_RGB565 | - BLUE_HI_BIT_MASK_RGB565) << 1; -uint32 RGB_REMOVE_LOW_BITS_MASK = ~RGB_LOW_BITS_MASK; -uint32 FIRST_COLOR_MASK = FIRST_COLOR_MASK_RGB565; -uint32 SECOND_COLOR_MASK = SECOND_COLOR_MASK_RGB565; -uint32 THIRD_COLOR_MASK = THIRD_COLOR_MASK_RGB565; -uint32 ALPHA_BITS_MASK = ALPHA_BITS_MASK_RGB565; -uint32 FIRST_THIRD_COLOR_MASK = 0; -uint32 TWO_LOW_BITS_MASK = 0; -uint32 HIGH_BITS_SHIFTED_TWO_MASK = 0; - -uint32 current_graphic_format = RGB565; -#endif - -uint8 GetBank = 0; -struct SCheatData Cheat; - -SoundStatus so; -SSoundData SoundData; -int Echo [24000]; -int DummyEchoBuffer [SOUND_BUFFER_SIZE]; -int MixBuffer [SOUND_BUFFER_SIZE]; -int EchoBuffer [SOUND_BUFFER_SIZE]; -int FilterTaps [8]; -unsigned long Z = 0; -int Loop [16]; - -uint16 SignExtend [2] = { - 0x00, 0xff00 -}; - -int HDMA_ModeByteCounts [8] = { - 1, 2, 2, 4, 4, 0, 0, 0 -}; - -uint8 BitShifts[8][4] = -{ - {2, 2, 2, 2}, // 0 - {4, 4, 2, 0}, // 1 - {4, 4, 0, 0}, // 2 - {8, 4, 0, 0}, // 3 - {8, 2, 0, 0}, // 4 - {4, 2, 0, 0}, // 5 - {4, 0, 0, 0}, // 6 - {8, 0, 0, 0} // 7 -}; -uint8 TileShifts[8][4] = -{ - {4, 4, 4, 4}, // 0 - {5, 5, 4, 0}, // 1 - {5, 5, 0, 0}, // 2 - {6, 5, 0, 0}, // 3 - {6, 4, 0, 0}, // 4 - {5, 4, 0, 0}, // 5 - {5, 0, 0, 0}, // 6 - {6, 0, 0, 0} // 7 -}; -uint8 PaletteShifts[8][4] = -{ - {2, 2, 2, 2}, // 0 - {4, 4, 2, 0}, // 1 - {4, 4, 0, 0}, // 2 - {0, 4, 0, 0}, // 3 - {0, 2, 0, 0}, // 4 - {4, 2, 0, 0}, // 5 - {4, 0, 0, 0}, // 6 - {0, 0, 0, 0} // 7 -}; -uint8 PaletteMasks[8][4] = -{ - {7, 7, 7, 7}, // 0 - {7, 7, 7, 0}, // 1 - {7, 7, 0, 0}, // 2 - {0, 7, 0, 0}, // 3 - {0, 7, 0, 0}, // 4 - {7, 7, 0, 0}, // 5 - {7, 0, 0, 0}, // 6 - {0, 0, 0, 0} // 7 -}; -uint8 Depths[8][4] = -{ - {TILE_2BIT, TILE_2BIT, TILE_2BIT, TILE_2BIT}, // 0 - {TILE_4BIT, TILE_4BIT, TILE_2BIT, 0}, // 1 - {TILE_4BIT, TILE_4BIT, 0, 0}, // 2 - {TILE_8BIT, TILE_4BIT, 0, 0}, // 3 - {TILE_8BIT, TILE_2BIT, 0, 0}, // 4 - {TILE_4BIT, TILE_2BIT, 0, 0}, // 5 - {TILE_8BIT, 0, 0, 0}, // 6 - {0, 0, 0, 0} // 7 -}; -uint8 BGSizes [2] = { - 8, 16 -}; -uint32 DirectColourMaps [8][256]; - -long FilterValues[4][2] = -{ - {0, 0}, - {240, 0}, - {488, -240}, - {460, -208} -}; - -int NoiseFreq [32] = { - 0, 16, 21, 25, 31, 42, 50, 63, 84, 100, 125, 167, 200, 250, 333, - 400, 500, 667, 800, 1000, 1300, 1600, 2000, 2700, 3200, 4000, - 5300, 6400, 8000, 10700, 16000, 32000 -}; - -uint32 HeadMask [4] = { -#ifdef LSB_FIRST - 0xffffffff, 0xffffff00, 0xffff0000, 0xff000000 -#else - 0xffffffff, 0x00ffffff, 0x0000ffff, 0x000000ff -#endif -}; - -uint32 TailMask [5] = { -#ifdef LSB_FIRST - 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff -#else - 0x00000000, 0xff000000, 0xffff0000, 0xffffff00, 0xffffffff -#endif -}; - -START_EXTERN_C -uint8 APUROM [64] = -{ - 0xCD,0xEF,0xBD,0xE8,0x00,0xC6,0x1D,0xD0,0xFC,0x8F,0xAA,0xF4,0x8F, - 0xBB,0xF5,0x78,0xCC,0xF4,0xD0,0xFB,0x2F,0x19,0xEB,0xF4,0xD0,0xFC, - 0x7E,0xF4,0xD0,0x0B,0xE4,0xF5,0xCB,0xF4,0xD7,0x00,0xFC,0xD0,0xF3, - 0xAB,0x01,0x10,0xEF,0x7E,0xF4,0x10,0xEB,0xBA,0xF6,0xDA,0x00,0xBA, - 0xF4,0xC4,0xF4,0xDD,0x5D,0xD0,0xDB,0x1F,0x00,0x00,0xC0,0xFF -}; - -#ifdef NETPLAY_SUPPORT -struct SNetPlay NetPlay; -#endif - -// Raw SPC700 instruction cycle lengths -int32 S9xAPUCycleLengths [256] = -{ - /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */ - /* 00 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8, - /* 10 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 4, 6, - /* 20 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 5, 4, - /* 30 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 3, 8, - /* 40 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 6, 6, - /* 50 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 4, 5, 2, 2, 4, 3, - /* 60 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 5, 5, - /* 70 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 6, - /* 80 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 2, 4, 5, - /* 90 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2,12, 5, - /* a0 */ 3, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 2, 4, 4, - /* b0 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 4, - /* c0 */ 3, 8, 4, 5, 4, 5, 4, 7, 2, 5, 6, 4, 5, 2, 4, 9, - /* d0 */ 2, 8, 4, 5, 5, 6, 6, 7, 4, 5, 4, 5, 2, 2, 6, 3, - /* e0 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3, - /* f0 */ 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3 -}; - -// Actual data used by CPU emulation, will be scaled by APUReset routine -// to be relative to the 65c816 instruction lengths. -int32 S9xAPUCycles [256] = -{ - /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, */ - /* 00 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 6, 8, - /* 10 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 4, 6, - /* 20 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 4, 5, 4, - /* 30 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 6, 5, 2, 2, 3, 8, - /* 40 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 6, 6, - /* 50 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 4, 5, 2, 2, 4, 3, - /* 60 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 4, 5, 5, - /* 70 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 6, - /* 80 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 6, 5, 4, 5, 2, 4, 5, - /* 90 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2,12, 5, - /* a0 */ 3, 8, 4, 5, 3, 4, 3, 6, 2, 6, 4, 4, 5, 2, 4, 4, - /* b0 */ 2, 8, 4, 5, 4, 5, 5, 6, 5, 5, 5, 5, 2, 2, 3, 4, - /* c0 */ 3, 8, 4, 5, 4, 5, 4, 7, 2, 5, 6, 4, 5, 2, 4, 9, - /* d0 */ 2, 8, 4, 5, 5, 6, 6, 7, 4, 5, 4, 5, 2, 2, 6, 3, - /* e0 */ 2, 8, 4, 5, 3, 4, 3, 6, 2, 4, 5, 3, 4, 3, 4, 3, - /* f0 */ 2, 8, 4, 5, 4, 5, 5, 6, 3, 4, 5, 4, 2, 2, 4, 3 -}; - -#ifndef VAR_CYCLES -uint8 S9xE1M1X1 [256] = { - 8, 6, 8, 4, 5, 3, 5, 6, 3, 2, 2, 4, 6, 4, 6, 5, /* e=1, m=1, x=1 */ - 2, 5, 5, 7, 5, 4, 6, 6, 2, 4, 2, 2, 6, 4, 7, 5, - 6, 6, 8, 4, 3, 3, 5, 6, 4, 2, 2, 5, 4, 4, 6, 5, - 2, 5, 5, 7, 4, 4, 6, 6, 2, 4, 2, 2, 4, 4, 7, 5, - 7, 6, 2, 4, 0, 3, 5, 6, 3, 2, 2, 3, 3, 4, 6, 5, - 2, 5, 5, 7, 0, 4, 6, 6, 2, 4, 3, 2, 4, 4, 7, 5, - 6, 6, 6, 4, 3, 3, 5, 6, 4, 2, 2, 6, 5, 4, 6, 5, - 2, 5, 5, 7, 4, 4, 6, 6, 2, 4, 4, 2, 6, 4, 7, 5, - 2, 6, 3, 4, 3, 3, 3, 6, 2, 2, 2, 3, 4, 4, 4, 5, - 2, 5, 5, 7, 4, 4, 4, 6, 2, 4, 2, 2, 4, 4, 4, 5, - 2, 6, 2, 4, 3, 3, 3, 6, 2, 2, 2, 4, 4, 4, 4, 5, - 2, 5, 5, 7, 4, 4, 4, 6, 2, 4, 2, 2, 4, 4, 4, 5, - 2, 6, 3, 4, 3, 3, 5, 6, 2, 2, 2, 3, 4, 4, 6, 5, - 2, 5, 5, 7, 6, 4, 6, 6, 2, 4, 3, 3, 6, 4, 7, 5, - 2, 6, 3, 4, 3, 3, 5, 6, 2, 2, 2, 3, 4, 4, 6, 5, - 2, 5, 5, 7, 5, 4, 6, 6, 2, 4, 4, 2, 6, 4, 7, 5 -}; - -uint8 S9xE0M1X1 [256] = { - 8, 6, 8, 4, 5, 3, 5, 6, 3, 2, 2, 4, 6, 4, 6, 5, /* e=0, m=1, x=1 */ - 2, 5, 5, 7, 5, 4, 6, 6, 2, 4, 2, 2, 6, 4, 7, 5, - 6, 6, 8, 4, 3, 3, 5, 6, 4, 2, 2, 5, 4, 4, 6, 5, - 2, 5, 5, 7, 4, 4, 6, 6, 2, 4, 2, 2, 4, 4, 7, 5, - 7, 6, 2, 4, 0, 3, 5, 6, 3, 2, 2, 3, 3, 4, 6, 5, - 2, 5, 5, 7, 0, 4, 6, 6, 2, 4, 3, 2, 4, 4, 7, 5, - 6, 6, 6, 4, 3, 3, 5, 6, 4, 2, 2, 6, 5, 4, 6, 5, - 2, 5, 5, 7, 4, 4, 6, 6, 2, 4, 4, 2, 6, 4, 7, 5, - 2, 6, 3, 4, 3, 3, 3, 6, 2, 2, 2, 3, 4, 4, 4, 5, - 2, 5, 5, 7, 4, 4, 4, 6, 2, 4, 2, 2, 4, 4, 4, 5, - 2, 6, 2, 4, 3, 3, 3, 6, 2, 2, 2, 4, 4, 4, 4, 5, - 2, 5, 5, 7, 4, 4, 4, 6, 2, 4, 2, 2, 4, 4, 4, 5, - 2, 6, 3, 4, 3, 3, 5, 6, 2, 2, 2, 3, 4, 4, 6, 5, - 2, 5, 5, 7, 6, 4, 6, 6, 2, 4, 3, 3, 6, 4, 7, 5, - 2, 6, 3, 4, 3, 3, 5, 6, 2, 2, 2, 3, 4, 4, 6, 5, - 2, 5, 5, 7, 5, 4, 6, 6, 2, 4, 4, 2, 6, 4, 7, 5 -}; - -uint8 S9xE0M0X1 [256] = { - 8, 7, 8, 5, 7, 4, 7, 7, 3, 3, 2, 4, 8, 5, 8, 6, /* e=0, m=0, x=1 */ - 2, 6, 6, 8, 7, 5, 8, 7, 2, 5, 2, 2, 8, 5, 9, 6, - 6, 7, 8, 5, 4, 4, 7, 7, 4, 3, 2, 5, 5, 5, 8, 6, - 2, 6, 6, 8, 5, 5, 8, 7, 2, 5, 2, 2, 5, 5, 9, 6, - 7, 7, 2, 5, 0, 4, 7, 7, 4, 3, 2, 3, 3, 5, 8, 6, - 2, 6, 6, 8, 0, 5, 8, 7, 2, 5, 3, 2, 4, 5, 9, 6, - 6, 7, 6, 5, 4, 4, 7, 7, 5, 3, 2, 6, 5, 5, 8, 6, - 2, 6, 6, 8, 5, 5, 8, 7, 2, 5, 4, 2, 6, 5, 9, 6, - 2, 7, 3, 5, 3, 4, 3, 7, 2, 3, 2, 3, 4, 5, 4, 6, - 2, 6, 6, 8, 4, 5, 4, 7, 2, 5, 2, 2, 5, 5, 5, 6, - 2, 7, 2, 5, 3, 4, 3, 7, 2, 3, 2, 4, 4, 5, 4, 6, - 2, 6, 6, 8, 4, 5, 4, 7, 2, 5, 2, 2, 4, 5, 4, 6, - 2, 7, 3, 5, 3, 4, 7, 7, 2, 3, 2, 3, 4, 5, 8, 6, - 2, 6, 6, 8, 6, 5, 8, 7, 2, 5, 3, 3, 6, 5, 9, 6, - 2, 7, 3, 5, 3, 4, 7, 7, 2, 3, 2, 3, 4, 5, 8, 6, - 2, 6, 6, 8, 5, 5, 8, 7, 2, 5, 4, 2, 6, 5, 9, 6 -}; - -uint8 S9xE0M1X0 [256] = { - 8, 6, 8, 4, 5, 3, 5, 6, 3, 2, 2, 4, 6, 4, 6, 5, /* e=0, m=1, x=0 */ - 2, 6, 5, 7, 5, 4, 6, 6, 2, 5, 2, 2, 6, 5, 7, 5, - 6, 6, 8, 4, 3, 3, 5, 6, 4, 2, 2, 5, 4, 4, 6, 5, - 2, 6, 5, 7, 4, 4, 6, 6, 2, 5, 2, 2, 5, 5, 7, 5, - 7, 6, 2, 4, 0, 3, 5, 6, 4, 2, 2, 3, 3, 4, 6, 5, - 2, 6, 5, 7, 0, 4, 6, 6, 2, 5, 4, 2, 4, 5, 7, 5, - 6, 6, 6, 4, 3, 3, 5, 6, 5, 2, 2, 6, 5, 4, 6, 5, - 2, 6, 5, 7, 4, 4, 6, 6, 2, 5, 5, 2, 6, 5, 7, 5, - 2, 6, 3, 4, 4, 3, 4, 6, 2, 2, 2, 3, 5, 4, 5, 5, - 2, 6, 5, 7, 5, 4, 5, 6, 2, 5, 2, 2, 4, 5, 5, 5, - 3, 6, 3, 4, 4, 3, 4, 6, 2, 2, 2, 4, 5, 4, 5, 5, - 2, 6, 5, 7, 5, 4, 5, 6, 2, 5, 2, 2, 5, 5, 5, 5, - 3, 6, 3, 4, 4, 3, 6, 6, 2, 2, 2, 3, 5, 4, 6, 5, - 2, 6, 5, 7, 6, 4, 8, 6, 2, 5, 4, 3, 6, 5, 7, 5, - 3, 6, 3, 4, 4, 3, 6, 6, 2, 2, 2, 3, 5, 4, 6, 5, - 2, 6, 5, 7, 5, 4, 8, 6, 2, 5, 5, 2, 6, 5, 7, 5 -}; - -uint8 S9xE0M0X0 [256] = { - 8, 7, 8, 5, 7, 4, 7, 7, 3, 3, 2, 4, 8, 5, 8, 6, /* e=0, m=0, x=0 */ - 2, 7, 6, 8, 7, 5, 8, 7, 2, 6, 2, 2, 8, 6, 9, 6, - 6, 7, 8, 5, 4, 4, 7, 7, 4, 3, 2, 5, 5, 5, 8, 6, - 2, 7, 6, 8, 5, 5, 8, 7, 2, 6, 2, 2, 6, 6, 9, 6, - 7, 7, 2, 5, 0, 4, 7, 7, 3, 3, 2, 3, 3, 5, 8, 6, - 2, 7, 6, 8, 0, 5, 8, 7, 2, 6, 4, 2, 4, 6, 9, 6, - 6, 7, 6, 5, 4, 4, 7, 7, 4, 3, 2, 6, 5, 5, 8, 6, - 2, 7, 6, 8, 5, 5, 8, 7, 2, 6, 5, 2, 6, 6, 9, 6, - 2, 7, 3, 5, 4, 4, 4, 7, 2, 3, 2, 3, 5, 5, 5, 6, - 2, 7, 6, 8, 5, 5, 5, 7, 2, 6, 2, 2, 5, 6, 6, 6, - 3, 7, 3, 5, 4, 4, 4, 7, 2, 3, 2, 4, 5, 5, 5, 6, - 2, 7, 6, 8, 5, 5, 5, 7, 2, 6, 2, 2, 5, 6, 5, 6, - 3, 7, 3, 5, 4, 4, 7, 7, 2, 3, 2, 3, 5, 5, 8, 6, - 2, 7, 6, 8, 6, 5, 8, 7, 2, 6, 4, 3, 6, 6, 9, 6, - 3, 7, 3, 5, 4, 4, 7, 7, 2, 3, 2, 3, 5, 5, 8, 6, - 2, 7, 6, 8, 5, 5, 8, 7, 2, 6, 5, 2, 6, 6, 9, 6 -}; -#endif - -END_EXTERN_C diff --git a/src/memmap.c b/src/memmap.c new file mode 100644 index 0000000..df5dec1 --- /dev/null +++ b/src/memmap.c @@ -0,0 +1,2759 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include +#include + +#ifdef __linux +//#include +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "cpuexec.h" +#include "ppu.h" +#include "display.h" +#include "cheats.h" +#include "apu.h" +#include "sa1.h" +#include "srtc.h" +#include "sdd1.h" + +#ifndef ZSNES_FX +#include "fxemu.h" +extern FxInit_s SuperFX; +#else +START_EXTERN_C +extern uint8 *SFXPlotTable; +END_EXTERN_C +#endif + +static uint8 bytes0x2000 [0x2000]; + +extern bool8 ROMAPUEnabled; + +extern char *rom_filename; +extern bool8 LoadZip(const char* , int32 *, int32 *); + +bool8_32 AllASCII (uint8 *b, int size) +{ + for (int i = 0; i < size; i++) + { + if (b[i] < 32 || b[i] > 126) + return (FALSE); + } + return (TRUE); +} + +int ScoreHiROM (bool8_32 skip_header) +{ + int score = 0; + int o = skip_header ? 0xff00 + 0x200 : 0xff00; + + if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + + Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) + score += 2; + + if (Memory.ROM [o + 0xda] == 0x33) + score += 2; + if ((Memory.ROM [o + 0xd5] & 0xf) < 4) + score += 2; + if (!(Memory.ROM [o + 0xfd] & 0x80)) + score -= 4; + if (Memory.CalculatedSize > 1024 * 1024 * 3) + score += 4; + if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) + score -= 1; + if (!AllASCII (&Memory.ROM [o + 0xb0], 6)) + score -= 1; + if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1)) + score -= 1; + + return (score); +} + +int ScoreLoROM (bool8_32 skip_header) +{ + int score = 0; + int o = skip_header ? 0x7f00 + 0x200 : 0x7f00; + + if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + + Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) + score += 2; + + if (Memory.ROM [o + 0xda] == 0x33) + score += 2; + if ((Memory.ROM [o + 0xd5] & 0xf) < 4) + score += 2; + if (Memory.CalculatedSize <= 1024 * 1024 * 16) + score += 2; + if (!(Memory.ROM [o + 0xfd] & 0x80)) + score -= 4; + if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) + score -= 1; + if (!AllASCII (&Memory.ROM [o + 0xb0], 6)) + score -= 1; + if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1)) + score -= 1; + + return (score); +} + +char *Safe (const char *s) +{ + static char *safe = NULL; + static int safe_len = 0; + + int len = strlen (s); + if (!safe || len + 1 > safe_len) + { + if (safe) + free ((char *) safe); + safe = (char *) malloc (safe_len = len + 1); + } + + for (int i = 0; i < len; i++) + { + if (s [i] >= 32 && s [i] < 127) + safe [i] = s[i]; + else + safe [i] = '?'; + } + safe [len] = 0; + return (safe); +} + +/**********************************************************************************************/ +/* Init() */ +/* This function allocates all the memory needed by the emulator */ +/**********************************************************************************************/ +bool8_32 MemoryInit () +{ + Memory.RAM = (uint8 *) malloc (0x20000); + Memory.SRAM = (uint8 *) malloc (0x20000); + Memory.VRAM = (uint8 *) malloc (0x10000); + Memory.ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000); + Memory.FillRAM = NULL; + + IPPU.TileCache [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES * 128); + IPPU.TileCache [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES * 128); + IPPU.TileCache [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES * 128); + + IPPU.TileCached [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES); + IPPU.TileCached [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES); + IPPU.TileCached [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES); + + if (!Memory.RAM || !Memory.SRAM || !Memory.VRAM || !Memory.ROM || + !IPPU.TileCache [TILE_2BIT] || !IPPU.TileCache [TILE_4BIT] || + !IPPU.TileCache [TILE_8BIT] || !IPPU.TileCached [TILE_2BIT] || + !IPPU.TileCached [TILE_4BIT] || !IPPU.TileCached [TILE_8BIT]) + { + MemoryDeinit (); + return (FALSE); + } + + // FillRAM uses first 32K of ROM image area, otherwise space just + // wasted. Might be read by the SuperFX code. + + Memory.FillRAM = Memory.ROM; + + // Add 0x8000 to ROM image pointer to stop SuperFX code accessing + // unallocated memory (can cause crash on some ports). + Memory.ROM += 0x8000; + + Memory.C4RAM = Memory.ROM + 0x400000 + 8192 * 8; + ROM = Memory.ROM; + SRAM = Memory.SRAM; + RegRAM = Memory.FillRAM; + +#ifdef ZSNES_FX + SFXPlotTable = ROM + 0x400000; +#else + SuperFX.pvRegisters = &Memory.FillRAM [0x3000]; + SuperFX.nRamBanks = 1; + SuperFX.pvRam = SRAM; + SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); + SuperFX.pvRom = (uint8 *) Memory.ROM; +#endif + + ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES); + + Memory.SDD1Data = NULL; + Memory.SDD1Index = NULL; + + return (TRUE); +} + +void MemoryDeinit () +{ + if (Memory.RAM) + { + free ((char *) Memory.RAM); + Memory.RAM = NULL; + } + if (Memory.SRAM) + { + free ((char *) Memory.SRAM); + Memory.SRAM = NULL; + } + if (Memory.VRAM) + { + free ((char *) Memory.VRAM); + Memory.VRAM = NULL; + } + if (Memory.ROM) + { + Memory.ROM -= 0x8000; + free ((char *) Memory.ROM); + Memory.ROM = NULL; + } + + if (IPPU.TileCache [TILE_2BIT]) + { + free ((char *) IPPU.TileCache [TILE_2BIT]); + IPPU.TileCache [TILE_2BIT] = NULL; + } + if (IPPU.TileCache [TILE_4BIT]) + { + free ((char *) IPPU.TileCache [TILE_4BIT]); + IPPU.TileCache [TILE_4BIT] = NULL; + } + if (IPPU.TileCache [TILE_8BIT]) + { + free ((char *) IPPU.TileCache [TILE_8BIT]); + IPPU.TileCache [TILE_8BIT] = NULL; + } + + if (IPPU.TileCached [TILE_2BIT]) + { + free ((char *) IPPU.TileCached [TILE_2BIT]); + IPPU.TileCached [TILE_2BIT] = NULL; + } + if (IPPU.TileCached [TILE_4BIT]) + { + free ((char *) IPPU.TileCached [TILE_4BIT]); + IPPU.TileCached [TILE_4BIT] = NULL; + } + if (IPPU.TileCached [TILE_8BIT]) + { + free ((char *) IPPU.TileCached [TILE_8BIT]); + IPPU.TileCached [TILE_8BIT] = NULL; + } + + FreeSDD1Data (); +} + +void FreeSDD1Data () +{ + if (Memory.SDD1Index) + { + free ((char *) Memory.SDD1Index); + Memory.SDD1Index = NULL; + } + if (Memory.SDD1Data) + { + free ((char *) Memory.SDD1Data); + Memory.SDD1Data = NULL; + } +} + +/**********************************************************************************************/ +/* checkext() */ +/**********************************************************************************************/ +int checkzip( char * fn ) +{ + int cnt = strlen(fn); + if( ( (fn[cnt-1] == 'p') || (fn[cnt-1] == 'P') ) && + ( (fn[cnt-2] == 'i') || (fn[cnt-2] == 'I') ) && + ( (fn[cnt-3] == 'z') || (fn[cnt-3] == 'Z') ) ){ + return true; + + } + return false; +} + +/**********************************************************************************************/ +/* LoadROM() */ +/* This function loads a Snes-Backup image */ +/**********************************************************************************************/ +bool8_32 LoadROM (const char *filename) +{ + unsigned long FileSize = 0; + int retry_count = 0; + STREAM ROMFile; + bool8_32 Interleaved = FALSE; + bool8_32 Tales = FALSE; + char dir [_MAX_DIR + 1]; + char drive [_MAX_DRIVE + 1]; + char name [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + char fname [_MAX_PATH + 1]; + int i; + + memset (&SNESGameFixes, 0, sizeof(SNESGameFixes)); + SNESGameFixes.SRAMInitialValue = 0x60; + + memset (bytes0x2000, 0, 0x2000); + CPU.TriedInterleavedMode2 = FALSE; + + Memory.CalculatedSize = 0; +again: + _splitpath (filename, drive, dir, name, ext); + _makepath (fname, drive, dir, name, ext); + +#ifdef __WIN32__ + memmove (&ext [0], &ext[1], 4); +#endif + + int32 TotalFileSize = 0; + + { + if ((ROMFile = OPEN_STREAM (fname, "rb")) == NULL) + return (FALSE); + + strcpy (Memory.ROMFilename, fname); + + Memory.HeaderCount = 0; + uint8 *ptr = Memory.ROM; + bool8_32 more = FALSE; + + do + { + FileSize = READ_STREAM (ptr, MAX_ROM_SIZE + 0x200 - (ptr - Memory.ROM), ROMFile); + CLOSE_STREAM (ROMFile); + int calc_size = (FileSize / 0x2000) * 0x2000; + + if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || + Settings.ForceHeader) + { + memmove (ptr, ptr + 512, calc_size); + Memory.HeaderCount++; + FileSize -= 512; + } + ptr += FileSize; + TotalFileSize += FileSize; + + int len; + if (ptr - Memory.ROM < MAX_ROM_SIZE + 0x200 && + (isdigit (ext [0]) && ext [1] == 0 && ext [0] < '9')) + { + more = TRUE; + ext [0]++; +#ifdef __WIN32__ + memmove (&ext [1], &ext [0], 4); + ext [0] = '.'; +#endif + _makepath (fname, drive, dir, name, ext); + } + else + if (ptr - Memory.ROM < MAX_ROM_SIZE + 0x200 && + (((len = strlen (name)) == 7 || len == 8) && + strncasecmp (name, "sf", 2) == 0 && + isdigit (name [2]) && isdigit (name [3]) && isdigit (name [4]) && + isdigit (name [5]) && isalpha (name [len - 1]))) + { + more = TRUE; + name [len - 1]++; +#ifdef __WIN32__ + memmove (&ext [1], &ext [0], 4); + ext [0] = '.'; +#endif + _makepath (fname, drive, dir, name, ext); + } + else + more = FALSE; + } while (more && (ROMFile = OPEN_STREAM (fname, "rb")) != NULL); + } + + if (Memory.HeaderCount == 0) + S9xMessage (S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found."); + else + { + if (Memory.HeaderCount == 1) + S9xMessage (S9X_INFO, S9X_HEADERS_INFO, + "Found ROM file header (and ignored it)."); + else + S9xMessage (S9X_INFO, S9X_HEADERS_INFO, + "Found multiple ROM file headers (and ignored them)."); + } + + CheckForIPSPatch (filename, Memory.HeaderCount != 0, &TotalFileSize); + int orig_hi_score, orig_lo_score; + int hi_score, lo_score; + + orig_hi_score = hi_score = ScoreHiROM (FALSE); + orig_lo_score = lo_score = ScoreLoROM (FALSE); + + if (Memory.HeaderCount == 0 && !Settings.ForceNoHeader && + ((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) || + (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score))) + { + memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512); + TotalFileSize -= 512; + S9xMessage (S9X_INFO, S9X_HEADER_WARNING, + "Try specifying the -nhd command line option if the game doesn't work\n"); + } + + Memory.CalculatedSize = (TotalFileSize / 0x2000) * 0x2000; + ZeroMemory (Memory.ROM + Memory.CalculatedSize, MAX_ROM_SIZE - Memory.CalculatedSize); + + // Check for cherryroms.com DAIKAIJYUMONOGATARI2 + + if (Memory.CalculatedSize == 0x500000 && + strncmp ((const char *)&Memory.ROM [0x40ffc0], "DAIKAIJYUMONOGATARI2", 20) == 0 && + strncmp ((const char *)&Memory.ROM [0x40ffb0], "18AE6J", 6) == 0 && + memcmp (&Memory.ROM[0x40ffb0], &Memory.ROM [0xffb0], 0x30)) + { + memmove (&Memory.ROM[0x100000], Memory.ROM, 0x500000); + memmove (Memory.ROM, &Memory.ROM[0x500000], 0x100000); + } + + Interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2; + if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score)) + { + Memory.LoROM = TRUE; + Memory.HiROM = FALSE; + + // Ignore map type byte if not 0x2x or 0x3x + if ((Memory.ROM [0x7fd5] & 0xf0) == 0x20 || (Memory.ROM [0x7fd5] & 0xf0) == 0x30) + { + switch (Memory.ROM [0x7fd5] & 0xf) + { + case 1: + if (strncmp ((char *) &Memory.ROM [0x7fc0], "TREASURE HUNTER G", 17) != 0) + Interleaved = TRUE; + break; + case 2: +#if 0 + if (!Settings.ForceLoROM && + strncmp ((char *) &ROM [0x7fc0], "SUPER FORMATION SOCCE", 21) != 0 && + strncmp ((char *) &ROM [0x7fc0], "Star Ocean", 10) != 0) + { + LoROM = FALSE; + HiROM = TRUE; + } +#endif + break; + case 5: + Interleaved = TRUE; + Tales = TRUE; + break; + } + } + } + else + { + if ((Memory.ROM [0xffd5] & 0xf0) == 0x20 || (Memory.ROM [0xffd5] & 0xf0) == 0x30) + { + switch (Memory.ROM [0xffd5] & 0xf) + { + case 0: + case 3: + Interleaved = TRUE; + break; + } + } + Memory.LoROM = FALSE; + Memory.HiROM = TRUE; + } + + // More + if (!Settings.ForceHiROM && !Settings.ForceLoROM && + !Settings.ForceInterleaved && !Settings.ForceInterleaved2 && + !Settings.ForceNotInterleaved && !Settings.ForcePAL && + !Settings.ForceSuperFX && !Settings.ForceDSP1 && + !Settings.ForceSA1 && !Settings.ForceC4 && + !Settings.ForceSDD1) + { + if (strncmp ((char *) &Memory.ROM [0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0) + { + Memory.LoROM = TRUE; + Memory.HiROM = FALSE; + Interleaved = FALSE; + } + else + if (strncmp ((char *) &Memory.ROM [0x7fc0], "SP MOMOTAROU DENTETSU2", 22) == 0) + { + Memory.LoROM = TRUE; + Memory.HiROM = FALSE; + Interleaved = FALSE; + } + else + if (Memory.CalculatedSize == 0x100000 && + strncmp ((char *) &Memory.ROM [0xffc0], "WWF SUPER WRESTLEMANIA", 22) == 0) + { + int cvcount; + + memmove (&Memory.ROM[0x100000] , Memory.ROM, 0x100000); + for (cvcount = 0; cvcount < 16; cvcount++) + { + memmove (&Memory.ROM[0x8000 * cvcount], &Memory.ROM[0x10000 * cvcount + 0x100000 + 0x8000], 0x8000); + memmove (&Memory.ROM[0x8000 * cvcount + 0x80000], &Memory.ROM[0x10000 * cvcount + 0x100000], 0x8000); + } + Memory.LoROM = TRUE; + Memory.HiROM = FALSE; + ZeroMemory (Memory.ROM + Memory.CalculatedSize, MAX_ROM_SIZE - Memory.CalculatedSize); + } + } + + if (!Settings.ForceNotInterleaved && Interleaved) + { + CPU.TriedInterleavedMode2 = TRUE; + S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO, + "ROM image is in interleaved format - converting..."); + + int nblocks = Memory.CalculatedSize >> 16; +#if 0 + int step = 64; + + while (nblocks <= step) + step >>= 1; + + nblocks = step; +#endif + uint8 blocks [256]; + + if (Tales) + { + nblocks = 0x60; + for (i = 0; i < 0x40; i += 2) + { + blocks [i + 0] = (i >> 1) + 0x20; + blocks [i + 1] = (i >> 1) + 0x00; + } + for (i = 0; i < 0x80; i += 2) + { + blocks [i + 0x40] = (i >> 1) + 0x80; + blocks [i + 0x41] = (i >> 1) + 0x40; + } + Memory.LoROM = FALSE; + Memory.HiROM = TRUE; + } + else + if (Settings.ForceInterleaved2) + { + for (i = 0; i < nblocks * 2; i++) + { + blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) | + ((i & 8) >> 2) | ((i & 16) >> 2); + } + } + else + { + bool8_32 t = Memory.LoROM; + + Memory.LoROM = Memory.HiROM; + Memory.HiROM = t; + + for (i = 0; i < nblocks; i++) + { + blocks [i * 2] = i + nblocks; + blocks [i * 2 + 1] = i; + } + } + + uint8 *tmp = (uint8 *) malloc (0x8000); + if (tmp) + { + for (i = 0; i < nblocks * 2; i++) + { + for (int j = i; j < nblocks * 2; j++) + { + if (blocks [j] == i) + { + memmove (tmp, &Memory.ROM [blocks [j] * 0x8000], 0x8000); + memmove (&Memory.ROM [blocks [j] * 0x8000], + &Memory.ROM [blocks [i] * 0x8000], 0x8000); + memmove (&Memory.ROM [blocks [i] * 0x8000], tmp, 0x8000); + uint8 b = blocks [j]; + blocks [j] = blocks [i]; + blocks [i] = b; + break; + } + } + } + free ((char *) tmp); + } + + hi_score = ScoreHiROM (FALSE); + lo_score = ScoreLoROM (FALSE); + + if ((Memory.HiROM && + (lo_score >= hi_score || hi_score < 0)) || + (Memory.LoROM && + (hi_score > lo_score || lo_score < 0))) + { + if (retry_count == 0) + { + S9xMessage (S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, + "ROM lied about its type! Trying again."); + Settings.ForceNotInterleaved = TRUE; + Settings.ForceInterleaved = FALSE; + retry_count++; + goto again; + } + } + } + FreeSDD1Data (); + InitROM (Tales); + + S9xLoadCheatFile (S9xGetFilename(".cht")); + S9xInitCheatData (); + S9xApplyCheats (); + + S9xReset (); + + return (TRUE); +} + +void S9xDeinterleaveMode2 () +{ + S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO, + "ROM image is in interleaved format - converting..."); + + int nblocks = Memory.CalculatedSize >> 15; + int step = 64; + + while (nblocks <= step) + step >>= 1; + + nblocks = step; + uint8 blocks [256]; + int i; + + for (i = 0; i < nblocks * 2; i++) + { + blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) | + ((i & 8) >> 2) | ((i & 16) >> 2); + } + + uint8 *tmp = (uint8 *) malloc (0x8000); + + if (tmp) + { + for (i = 0; i < nblocks * 2; i++) + { + for (int j = i; j < nblocks * 2; j++) + { + if (blocks [j] == i) + { + memmove (tmp, &Memory.ROM [blocks [j] * 0x8000], 0x8000); + memmove (&Memory.ROM [blocks [j] * 0x8000], + &Memory.ROM [blocks [i] * 0x8000], 0x8000); + memmove (&Memory.ROM [blocks [i] * 0x8000], tmp, 0x8000); + uint8 b = blocks [j]; + blocks [j] = blocks [i]; + blocks [i] = b; + break; + } + } + } + free ((char *) tmp); + } + InitROM (FALSE); + S9xReset (); +} + +void InitROM (bool8_32 Interleaved) +{ +#ifndef ZSNES_FX + SuperFX.nRomBanks = Memory.CalculatedSize >> 15; +#endif + Settings.MultiPlayer5Master = Settings.MultiPlayer5; + Settings.MouseMaster = Settings.Mouse; + Settings.SuperScopeMaster = Settings.SuperScope; + Settings.DSP1Master = Settings.ForceDSP1; + Settings.SuperFX = FALSE; + Settings.SA1 = FALSE; + Settings.C4 = FALSE; + Settings.SDD1 = FALSE; + Settings.SRTC = FALSE; + + ZeroMemory (Memory.BlockIsRAM, MEMMAP_NUM_BLOCKS); + ZeroMemory (Memory.BlockIsROM, MEMMAP_NUM_BLOCKS); + + SRAM = Memory.SRAM; + memset (Memory.ROMId, 0, 5); + memset (Memory.CompanyId, 0, 3); + + if (Memory.HiROM) + { + Memory.SRAMSize = Memory.ROM [0xffd8]; + strncpy (Memory.ROMName, (char *) &Memory.ROM[0xffc0], ROM_NAME_LEN - 1); + Memory.ROMSpeed = Memory.ROM [0xffd5]; + Memory.ROMType = Memory.ROM [0xffd6]; + Memory.ROMSize = Memory.ROM [0xffd7]; + Memory.ROMChecksum = Memory.ROM [0xffde] + (Memory.ROM [0xffdf] << 8); + Memory.ROMComplementChecksum = Memory.ROM [0xffdc] + (Memory.ROM [0xffdd] << 8); + + memmove (Memory.ROMId, &Memory.ROM [0xffb2], 4); + memmove (Memory.CompanyId, &Memory.ROM [0xffb0], 2); + + // Try to auto-detect the DSP1 chip + if (!Settings.ForceNoDSP1 && + (Memory.ROMType & 0xf) >= 3 && (Memory.ROMType & 0xf0) == 0) + Settings.DSP1Master = TRUE; + + Settings.SDD1 = Settings.ForceSDD1; + if ((Memory.ROMType & 0xf0) == 0x40) + Settings.SDD1 = !Settings.ForceNoSDD1; + + if (Settings.BS) + BSHiROMMap (); + else + if ((Memory.ROMSpeed & ~0x10) == 0x25) + TalesROMMap (Interleaved); + else + if ((Memory.ROMSpeed & ~0x10) == 0x22 && + strncmp (Memory.ROMName, "Super Street Fighter", 20) != 0) + { + AlphaROMMap (); + } + else + HiROMMap (); + } + else + { + Memory.HiROM = FALSE; + Memory.SRAMSize = Memory.ROM [0x7fd8]; + Memory.ROMSpeed = Memory.ROM [0x7fd5]; + Memory.ROMType = Memory.ROM [0x7fd6]; + Memory.ROMSize = Memory.ROM [0x7fd7]; + Memory.ROMChecksum = Memory.ROM [0x7fde] + (Memory.ROM [0x7fdf] << 8); + Memory.ROMComplementChecksum = Memory.ROM [0x7fdc] + (Memory.ROM [0x7fdd] << 8); + memmove (Memory.ROMId, &Memory.ROM [0x7fb2], 4); + memmove (Memory.CompanyId, &Memory.ROM [0x7fb0], 2); + + strncpy (Memory.ROMName, (char *) &Memory.ROM[0x7fc0], ROM_NAME_LEN - 1); + Settings.SuperFX = Settings.ForceSuperFX; + + if ((Memory.ROMType & 0xf0) == 0x10) + Settings.SuperFX = !Settings.ForceNoSuperFX; + + // Try to auto-detect the DSP1 chip + if (!Settings.ForceNoDSP1 && + (Memory.ROMType & 0xf) >= 3 && (Memory.ROMType & 0xf0) == 0) + Settings.DSP1Master = TRUE; + + Settings.SDD1 = Settings.ForceSDD1; + if ((Memory.ROMType & 0xf0) == 0x40) + Settings.SDD1 = !Settings.ForceNoSDD1; + + if (Settings.SDD1) + S9xLoadSDD1Data (); + + Settings.C4 = Settings.ForceC4; + if ((Memory.ROMType & 0xf0) == 0xf0 && + (strncmp (Memory.ROMName, "MEGAMAN X", 9) == 0 || + strncmp (Memory.ROMName, "ROCKMAN X", 9) == 0)) + { + Settings.C4 = !Settings.ForceNoC4; + } + + if (Settings.SuperFX) + { + //SRAM = ROM + 1024 * 1024 * 4; + SuperFXROMMap (); + Settings.MultiPlayer5Master = FALSE; + //Settings.MouseMaster = FALSE; + //Settings.SuperScopeMaster = FALSE; + Settings.DSP1Master = FALSE; + Settings.SA1 = FALSE; + Settings.C4 = FALSE; + Settings.SDD1 = FALSE; + } + else + if (Settings.ForceSA1 || + (!Settings.ForceNoSA1 && (Memory.ROMSpeed & ~0x10) == 0x23 && + (Memory.ROMType & 0xf) > 3 && (Memory.ROMType & 0xf0) == 0x30)) + { + Settings.SA1 = TRUE; + Settings.MultiPlayer5Master = FALSE; + //Settings.MouseMaster = FALSE; + //Settings.SuperScopeMaster = FALSE; + Settings.DSP1Master = FALSE; + Settings.C4 = FALSE; + Settings.SDD1 = FALSE; + SA1ROMMap (); + } + else + if ((Memory.ROMSpeed & ~0x10) == 0x25) + TalesROMMap (Interleaved); + else + if (strncmp ((char *) &Memory.ROM [0x7fc0], "SOUND NOVEL-TCOOL", 17) == 0 || + strncmp ((char *) &Memory.ROM [0x7fc0], "DERBY STALLION 96", 17) == 0) + { + LoROM24MBSMap (); + Settings.DSP1Master = FALSE; + } + else + if (strncmp ((char *) &Memory.ROM [0x7fc0], "THOROUGHBRED BREEDER3", 21) == 0 || + strncmp ((char *) &Memory.ROM [0x7fc0], "RPG-TCOOL 2", 11) == 0) + { + SRAM512KLoROMMap (); + Settings.DSP1Master = FALSE; + } + else + if (strncmp ((char *) &Memory.ROM [0x7fc0], "DEZAEMON ", 10) == 0) + { + Settings.DSP1Master = FALSE; + SRAM1024KLoROMMap (); + } + else + if (strncmp ((char *) &Memory.ROM [0x7fc0], "ADD-ON BASE CASSETE", 19) == 0) + { + Settings.MultiPlayer5Master = FALSE; + Settings.MouseMaster = FALSE; + Settings.SuperScopeMaster = FALSE; + Settings.DSP1Master = FALSE; + SufamiTurboLoROMMap(); + Memory.SRAMSize = 3; + } + else + if ((Memory.ROMSpeed & ~0x10) == 0x22 && + strncmp (Memory.ROMName, "Super Street Fighter", 20) != 0) + { + AlphaROMMap (); + } + else + LoROMMap (); + } + + int power2 = 0; + int size = Memory.CalculatedSize; + + while (size >>= 1) + power2++; + + size = 1 << power2; + uint32 remainder = Memory.CalculatedSize - size; + + uint32 sum1 = 0; + uint32 sum2 = 0; + + int i; + + for (i = 0; i < size; i++) + sum1 += Memory.ROM [i]; + + for (i = 0; i < (int) remainder; i++) + sum2 += Memory.ROM [size + i]; + + if (remainder) + { + //for Tengai makyou + if (Memory.CalculatedSize == 0x500000 && Memory.HiROM && + strncmp ((const char *)&Memory.ROM[0xffb0], "18AZ", 4) == 0 && + !memcmp(&Memory.ROM[0xffd5], "\x3a\xf9\x0d\x03\x00\x33\x00", 7)) + sum1 += sum2; + else + sum1 += sum2 * (size / remainder); + } + + sum1 &= 0xffff; + + Memory.CalculatedChecksum = caCRC32(&Memory.ROM[0], Memory.CalculatedSize); + if (Settings.ForceNTSC) + Settings.PAL = FALSE; + else + if (Settings.ForcePAL) + Settings.PAL = TRUE; + else + if (Memory.HiROM) + // Country code + Settings.PAL = Memory.ROM [0xffd9] >= 2; + else + Settings.PAL = Memory.ROM [0x7fd9] >= 2; + + if (Settings.PAL) + { + Settings.FrameTime = Settings.FrameTimePAL; + Memory.ROMFramesPerSecond = 50; + } + else + { + Settings.FrameTime = Settings.FrameTimeNTSC; + Memory.ROMFramesPerSecond = 60; + } + + Memory.ROMName[ROM_NAME_LEN - 1] = 0; + if (strlen (Memory.ROMName)) + { + char *p = Memory.ROMName + strlen (Memory.ROMName) - 1; + + while (p > Memory.ROMName && *(p - 1) == ' ') + p--; + *p = 0; + } + + if (Settings.SuperFX) + { + CPU.Memory_SRAMMask = 0xffff; + Memory.SRAMSize = 16; + } + else + { + CPU.Memory_SRAMMask = Memory.SRAMSize ? + ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; + } + + IAPU.OneCycle = ONE_APU_CYCLE; + Settings.Shutdown = Settings.ShutdownMaster; + + SetDSP = &DSP1SetByte; + GetDSP = &DSP1GetByte; + + ApplyROMFixes (); + sprintf (Memory.ROMName, "%s", Safe (Memory.ROMName)); + sprintf (Memory.ROMId, "%s", Safe (Memory.ROMId)); + sprintf (Memory.CompanyId, "%s", Safe (Memory.CompanyId)); + + sprintf (String, "\"%s\" [%s] %s, %s, Type: %s, Mode: %s, TV: %s, S-RAM: %s, ROMId: %s Company: %2.2s", + Memory.ROMName, + (Memory.ROMChecksum + Memory.ROMComplementChecksum != 0xffff || + Memory.ROMChecksum != sum1) ? "bad checksum" : "checksum ok", + MapType (), + Size (), + KartContents (), + MapMode (), + TVStandard (), + StaticRAMSize (), + Memory.ROMId, + Memory.CompanyId); + + S9xMessage (S9X_INFO, S9X_ROM_INFO, String); +} + +bool8_32 LoadSRAM (const char *filename) +{ + int size = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + + memset (Memory.SRAM, SNESGameFixes.SRAMInitialValue, 0x20000); + + if (size > 0x20000) + size = 0x20000; + + if (size) + { + FILE *file; + if ((file = fopen(filename, "rb"))) + { + int len = fread ((char*) SRAM, 1, 0x20000, file); + fclose (file); + if (len - size == 512) + { + // S-RAM file has a header - remove it + memmove (SRAM, SRAM + 512, size); + } + if (len == size + SRTC_SRAM_PAD) + { + S9xSRTCPostLoadState (); + S9xResetSRTC (); + rtc.index = -1; + rtc.mode = MODE_READ; + } + else + S9xHardResetSRTC (); + + return (TRUE); + } + S9xHardResetSRTC (); + return (FALSE); + } + + return (TRUE); +} + +bool8_32 SaveSRAM (const char *filename) +{ + int size = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + if (Settings.SRTC) + { + size += SRTC_SRAM_PAD; + S9xSRTCPreSaveState (); + } + + + if (size > 0x20000) + size = 0x20000; + + if (size && *Memory.ROMFilename) + { + FILE *file; + if ((file = fopen (filename, "wb"))) + { + fwrite ((char *) SRAM, size, 1, file); + fclose (file); + //sync(); +#if defined(__linux) + //chown (filename, getuid (), getgid ()); +#endif + return (TRUE); + } + } + return (FALSE); +} + +void FixROMSpeed () +{ + int c; + + for (c = 0x800; c < 0x1000; c++) + { + if (Memory.BlockIsROM [c]) + Memory.MemorySpeed [c] = (uint8) CPU.FastROMSpeed; + } +} + +void WriteProtectROM () +{ + memmove ((void *) Memory.WriteMap, (void *) Memory.Map, sizeof (Memory.Map)); + for (int c = 0; c < 0x1000; c++) + { + if (Memory.BlockIsROM [c]) + Memory.WriteMap [c] = (uint8 *) MAP_NONE; + } +} + +void MapRAM () +{ + int c; + + // Banks 7e->7f, RAM + for (c = 0; c < 16; c++) + { + Memory.Map [c + 0x7e0] = Memory.RAM; + Memory.Map [c + 0x7f0] = Memory.RAM + 0x10000; + Memory.BlockIsRAM [c + 0x7e0] = TRUE; + Memory.BlockIsRAM [c + 0x7f0] = TRUE; + Memory.BlockIsROM [c + 0x7e0] = FALSE; + Memory.BlockIsROM [c + 0x7f0] = FALSE; + } + + // Banks 70->77, S-RAM + for (c = 0; c < 0x80; c++) + { + Memory.Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM; + Memory.BlockIsRAM [c + 0x700] = TRUE; + Memory.BlockIsROM [c + 0x700] = FALSE; + } +} + +void MapExtraRAM () +{ + int c; + + // Banks 7e->7f, RAM + for (c = 0; c < 16; c++) + { + Memory.Map [c + 0x7e0] = Memory.RAM; + Memory.Map [c + 0x7f0] = Memory.RAM + 0x10000; + Memory.BlockIsRAM [c + 0x7e0] = TRUE; + Memory.BlockIsRAM [c + 0x7f0] = TRUE; + Memory.BlockIsROM [c + 0x7e0] = FALSE; + Memory.BlockIsROM [c + 0x7f0] = FALSE; + } + + // Banks 70->73, S-RAM + for (c = 0; c < 16; c++) + { + Memory.Map [c + 0x700] = SRAM; + Memory.Map [c + 0x710] = SRAM + 0x8000; + Memory.Map [c + 0x720] = SRAM + 0x10000; + Memory.Map [c + 0x730] = SRAM + 0x18000; + + Memory.BlockIsRAM [c + 0x700] = TRUE; + Memory.BlockIsROM [c + 0x700] = FALSE; + Memory.BlockIsRAM [c + 0x710] = TRUE; + Memory.BlockIsROM [c + 0x710] = FALSE; + Memory.BlockIsRAM [c + 0x720] = TRUE; + Memory.BlockIsROM [c + 0x720] = FALSE; + Memory.BlockIsRAM [c + 0x730] = TRUE; + Memory.BlockIsROM [c + 0x730] = FALSE; + } +} + +void LoROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.RAM; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = (uint8 *) MAP_PPU; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + Memory.Map [c + 5] = Memory.Map [c + 0x805] = (uint8 *) MAP_CPU; + if (Settings.DSP1Master) + { + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_DSP; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_DSP; + } + else + if (Settings.C4) + { + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_C4; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_C4; + } + else + { + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000; + } + + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = &Memory.ROM [(c << 11) % Memory.CalculatedSize] - 0x8000; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + if (Settings.DSP1Master) + { + // Banks 30->3f and b0->bf + for (c = 0x300; c < 0x400; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = (uint8 *) MAP_DSP; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = FALSE; + } + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [(c << 11) % Memory.CalculatedSize]; + + for (i = c + 8; i < c + 16; i++) + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [((c << 11) + 0x200000) % Memory.CalculatedSize - 0x8000]; + + for (i = c; i < c + 16; i++) + { + Memory.MemorySpeed [i + 0x400] = Memory.MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [i + 0x400] = Memory.BlockIsROM [i + 0xc00] = TRUE; + } + } + + if (Settings.DSP1Master) + { + for (c = 0; c < 0x100; c++) + { + Memory.Map [c + 0xe00] = (uint8 *) MAP_DSP; + Memory.MemorySpeed [c + 0xe00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [c + 0xe00] = FALSE; + } + } + MapRAM (); + WriteProtectROM (); +} + +void HiROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = (uint8 *) MAP_PPU; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + Memory.Map [c + 5] = Memory.Map [c + 0x805] = (uint8 *) MAP_CPU; + if (Settings.DSP1Master) + { + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_DSP; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_DSP; + } + else + { + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_NONE; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_NONE; + } + + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = &Memory.ROM [(c << 12) % Memory.CalculatedSize]; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. + for (c = 0; c < 16; c++) + { + Memory.Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Memory.Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Memory.Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Memory.Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Memory.BlockIsRAM [0x306 + (c << 4)] = TRUE; + Memory.BlockIsRAM [0x307 + (c << 4)] = TRUE; + Memory.BlockIsRAM [0xb06 + (c << 4)] = TRUE; + Memory.BlockIsRAM [0xb07 + (c << 4)] = TRUE; + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [(c << 12) % Memory.CalculatedSize]; + Memory.MemorySpeed [i + 0x400] = Memory.MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [i + 0x400] = Memory.BlockIsROM [i + 0xc00] = TRUE; + } + } + + MapRAM (); + WriteProtectROM (); +} + +void TalesROMMap (bool8_32 Interleaved) +{ + int c; + int i; + + uint32 OFFSET0 = 0x400000; + uint32 OFFSET1 = 0x400000; + uint32 OFFSET2 = 0x000000; + + if (Interleaved) + { + OFFSET0 = 0x000000; + OFFSET1 = 0x000000; + OFFSET2 = 0x200000; + } + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.RAM; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = (uint8 *) MAP_PPU; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + Memory.Map [c + 5] = Memory.Map [c + 0x805] = (uint8 *) MAP_CPU; + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_NONE; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_NONE; + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = &Memory.ROM [((c << 12) + OFFSET0) % Memory.CalculatedSize]; + Memory.Map [i + 0x800] = &Memory.ROM [((c << 12) + OFFSET0) % Memory.CalculatedSize]; + Memory.BlockIsROM [i] = TRUE; + Memory.BlockIsROM [i + 0x800] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + // Banks 30->3f and b0->bf, address ranges 6000->7ffff is S-RAM. + for (c = 0; c < 16; c++) + { + Memory.Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Memory.Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Memory.Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Memory.Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; + Memory.BlockIsRAM [0x306 + (c << 4)] = TRUE; + Memory.BlockIsRAM [0x307 + (c << 4)] = TRUE; + Memory.BlockIsRAM [0xb06 + (c << 4)] = TRUE; + Memory.BlockIsRAM [0xb07 + (c << 4)] = TRUE; + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + { + Memory.Map [i + 0x400] = &Memory.ROM [((c << 12) + OFFSET1) % Memory.CalculatedSize]; + Memory.Map [i + 0x408] = &Memory.ROM [((c << 12) + OFFSET1) % Memory.CalculatedSize]; + Memory.Map [i + 0xc00] = &Memory.ROM [((c << 12) + OFFSET2) % Memory.CalculatedSize]; + Memory.Map [i + 0xc08] = &Memory.ROM [((c << 12) + OFFSET2) % Memory.CalculatedSize]; + Memory.BlockIsROM [i + 0x400] = TRUE; + Memory.BlockIsROM [i + 0x408] = TRUE; + Memory.BlockIsROM [i + 0xc00] = TRUE; + Memory.BlockIsROM [i + 0xc08] = TRUE; + Memory.MemorySpeed [i + 0x400] = Memory.MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; + Memory.MemorySpeed [i + 0x408] = Memory.MemorySpeed [i + 0xc08] = SLOW_ONE_CYCLE; + } + } + MapRAM (); + WriteProtectROM (); +} + +void AlphaROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.RAM; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = (uint8 *) MAP_PPU; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + Memory.Map [c + 5] = Memory.Map [c + 0x805] = (uint8 *) MAP_CPU; + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_DSP; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_DSP; + + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = &Memory.ROM [c << 11] - 0x8000; + Memory.BlockIsROM [i] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + // Banks 40->7f and c0->ff + + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Memory.Map [i + 0x400] = &Memory.ROM [(c << 12) % Memory.CalculatedSize]; + Memory.Map [i + 0xc00] = &Memory.ROM [(c << 12) % Memory.CalculatedSize]; + Memory.MemorySpeed [i + 0x400] = Memory.MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [i + 0x400] = Memory.BlockIsROM [i + 0xc00] = TRUE; + } + } + + MapRAM (); + WriteProtectROM (); +} + +void SuperFXROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.RAM; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = (uint8 *) MAP_PPU; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + Memory.Map [c + 5] = Memory.Map [c + 0x805] = (uint8 *) MAP_CPU; + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_DSP; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_DSP; + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = &Memory.ROM [c << 11] - 0x8000; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = TRUE; + } + + for (i = c; i < c + 8; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [(c << 12) % Memory.CalculatedSize]; + Memory.MemorySpeed [i + 0x400] = Memory.MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [i + 0x400] = Memory.BlockIsROM [i + 0xc00] = TRUE; + } + } + + // Banks 7e->7f, RAM + for (c = 0; c < 16; c++) + { + Memory.Map [c + 0x7e0] = Memory.RAM; + Memory.Map [c + 0x7f0] = Memory.RAM + 0x10000; + Memory.BlockIsRAM [c + 0x7e0] = TRUE; + Memory.BlockIsRAM [c + 0x7f0] = TRUE; + Memory.BlockIsROM [c + 0x7e0] = FALSE; + Memory.BlockIsROM [c + 0x7f0] = FALSE; + } + + // Banks 70->71, S-RAM + for (c = 0; c < 32; c++) + { + Memory.Map [c + 0x700] = SRAM + (((c >> 4) & 1) << 16); + Memory.BlockIsRAM [c + 0x700] = TRUE; + Memory.BlockIsROM [c + 0x700] = FALSE; + } + + // Banks 00->3f and 80->bf address ranges 6000->7fff is RAM. + for (c = 0; c < 0x40; c++) + { + Memory.Map [0x006 + (c << 4)] = (uint8 *) SRAM - 0x6000; + Memory.Map [0x007 + (c << 4)] = (uint8 *) SRAM - 0x6000; + Memory.Map [0x806 + (c << 4)] = (uint8 *) SRAM - 0x6000; + Memory.Map [0x807 + (c << 4)] = (uint8 *) SRAM - 0x6000; + Memory.BlockIsRAM [0x006 + (c << 4)] = TRUE; + Memory.BlockIsRAM [0x007 + (c << 4)] = TRUE; + Memory.BlockIsRAM [0x806 + (c << 4)] = TRUE; + Memory.BlockIsRAM [0x807 + (c << 4)] = TRUE; + } + // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K + // block is repeated twice in each 64K block. + for (c = 0; c < 64; c++) + { + memmove (&Memory.ROM [0x200000 + c * 0x10000], &Memory.ROM [c * 0x8000], 0x8000); + memmove (&Memory.ROM [0x208000 + c * 0x10000], &Memory.ROM [c * 0x8000], 0x8000); + } + + WriteProtectROM (); +} + +void SA1ROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.RAM; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + Memory.Map [c + 5] = Memory.Map [c + 0x805] = (uint8 *) MAP_CPU; + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_BWRAM; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_BWRAM; + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = &Memory.ROM [c << 11] - 0x8000; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + // Banks 40->7f + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + Memory.Map [i + 0x400] = (uint8 *) &Memory.SRAM [(c << 12) & 0x1ffff]; + + for (i = c; i < c + 16; i++) + { + Memory.MemorySpeed [i + 0x400] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [i + 0x400] = FALSE; + } + } + + // c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Memory.Map [i + 0xc00] = &Memory.ROM [(c << 12) % Memory.CalculatedSize]; + Memory.MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [i + 0xc00] = TRUE; + } + } + + for (c = 0; c < 16; c++) + { + Memory.Map [c + 0x7e0] = Memory.RAM; + Memory.Map [c + 0x7f0] = Memory.RAM + 0x10000; + Memory.BlockIsRAM [c + 0x7e0] = TRUE; + Memory.BlockIsRAM [c + 0x7f0] = TRUE; + Memory.BlockIsROM [c + 0x7e0] = FALSE; + Memory.BlockIsROM [c + 0x7f0] = FALSE; + } + WriteProtectROM (); + +#ifdef USE_SA1 + // Now copy the map and correct it for the SA1 CPU. + memmove ((void *) SA1_WriteMap, (void *) Memory.WriteMap, sizeof (Memory.WriteMap)); + memmove ((void *) SA1_Map, (void *) Memory.Map, sizeof (Memory.Map)); + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + SA1_Map [c + 0] = SA1_Map [c + 0x800] = &Memory.FillRAM [0x3000]; + SA1_Map [c + 1] = SA1_Map [c + 0x801] = (uint8 *) MAP_NONE; + SA1_WriteMap [c + 0] = SA1_WriteMap [c + 0x800] = &Memory.FillRAM [0x3000]; + SA1_WriteMap [c + 1] = SA1_WriteMap [c + 0x801] = (uint8 *) MAP_NONE; + } + + // Banks 60->6f + for (c = 0; c < 0x100; c++) + SA1_Map [c + 0x600] = SA1_WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP; +#endif // USE_SA1 + + Memory.BWRAM = Memory.SRAM; +} + +void LoROM24MBSMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.RAM; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = (uint8 *) MAP_PPU; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + Memory.Map [c + 5] = Memory.Map [c + 0x805] = (uint8 *) MAP_CPU; + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_NONE; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_NONE; + + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = &Memory.ROM [c << 11] - 0x8000; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x200; c += 16) + { + Memory.Map [c + 0x800] = Memory.RAM; + Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 0x803] = (uint8 *) MAP_PPU; + Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + Memory.Map [c + 0x805] = (uint8 *) MAP_CPU; + Memory.Map [c + 0x806] = (uint8 *) MAP_NONE; + Memory.Map [c + 0x807] = (uint8 *) MAP_NONE; + + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i + 0x800] = &Memory.ROM [c << 11] - 0x8000 + 0x200000; + Memory.BlockIsROM [i + 0x800] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [(c << 11) + 0x200000]; + + for (i = c + 8; i < c + 16; i++) + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [(c << 11) + 0x200000 - 0x8000]; + + for (i = c; i < c + 16; i++) + { + Memory.MemorySpeed [i + 0x400] = Memory.MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [i + 0x400] = Memory.BlockIsROM [i + 0xc00] = TRUE; + } + } + + MapExtraRAM (); + WriteProtectROM (); +} + +void SufamiTurboLoROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.RAM; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = (uint8 *) MAP_PPU; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + Memory.Map [c + 5] = Memory.Map [c + 0x805] = (uint8 *) MAP_CPU; + if (Settings.DSP1Master) + { + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_DSP; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_DSP; + } + else + { + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_NONE; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_NONE; + } + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = &Memory.ROM [c << 11] - 0x8000; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + if (Settings.DSP1Master) + { + // Banks 30->3f and b0->bf + for (c = 0x300; c < 0x400; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = (uint8 *) MAP_DSP; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = FALSE; + } + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [(c << 11) + 0x200000]; + + for (i = c + 8; i < c + 16; i++) + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [(c << 11) + 0x200000 - 0x8000]; + + for (i = c; i < c + 16; i++) + { + Memory.MemorySpeed [i + 0x400] = Memory.MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [i + 0x400] = Memory.BlockIsROM [i + 0xc00] = TRUE; + } + } + + if (Settings.DSP1Master) + { + for (c = 0; c < 0x100; c++) + { + Memory.Map [c + 0xe00] = (uint8 *) MAP_DSP; + Memory.MemorySpeed [c + 0xe00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [c + 0xe00] = FALSE; + } + } + + // Banks 7e->7f, RAM + for (c = 0; c < 16; c++) + { + Memory.Map [c + 0x7e0] = Memory.RAM; + Memory.Map [c + 0x7f0] = Memory.RAM + 0x10000; + Memory.BlockIsRAM [c + 0x7e0] = TRUE; + Memory.BlockIsRAM [c + 0x7f0] = TRUE; + Memory.BlockIsROM [c + 0x7e0] = FALSE; + Memory.BlockIsROM [c + 0x7f0] = FALSE; + } + + // Banks 60->67, S-RAM + for (c = 0; c < 0x80; c++) + { + Memory.Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM; + Memory.BlockIsRAM [c + 0x600] = TRUE; + Memory.BlockIsROM [c + 0x600] = FALSE; + } + + WriteProtectROM (); +} + +void SRAM512KLoROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.RAM; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = (uint8 *) MAP_PPU; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + Memory.Map [c + 5] = Memory.Map [c + 0x805] = (uint8 *) MAP_CPU; + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_NONE; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_NONE; + + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = &Memory.ROM [c << 11] - 0x8000; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 8; i++) + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [(c << 11) + 0x200000]; + + for (i = c + 8; i < c + 16; i++) + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [(c << 11) + 0x200000 - 0x8000]; + + for (i = c; i < c + 16; i++) + { + Memory.MemorySpeed [i + 0x400] = Memory.MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [i + 0x400] = Memory.BlockIsROM [i + 0xc00] = TRUE; + + + } + } + + MapExtraRAM (); + WriteProtectROM (); +} + +void SRAM1024KLoROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.Map [c + 0x400] = Memory.Map [c + 0xc00] = Memory.RAM; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.Map [c + 0x401] = Memory.Map [c + 0xc01] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = Memory.BlockIsRAM [c + 0x400] = Memory.BlockIsRAM [c + 0xc00] = TRUE; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = Memory.BlockIsRAM [c + 0x401] = Memory.BlockIsRAM [c + 0xc01] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = Memory.Map [c + 0x402] = Memory.Map [c + 0xc02] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = Memory.Map [c + 0x403] = Memory.Map [c + 0xc03] = (uint8 *) MAP_PPU; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = Memory.Map [c + 0x404] = Memory.Map [c + 0xc04] = (uint8 *) MAP_CPU; + Memory.Map [c + 5] = Memory.Map [c + 0x805] = Memory.Map [c + 0x405] = Memory.Map [c + 0xc05] = (uint8 *) MAP_CPU; + Memory.Map [c + 6] = Memory.Map [c + 0x806] = Memory.Map [c + 0x406] = Memory.Map [c + 0xc06] = (uint8 *) MAP_NONE; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = Memory.Map [c + 0x407] = Memory.Map [c + 0xc07] = (uint8 *) MAP_NONE; + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [c << 11] - 0x8000; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = Memory.BlockIsROM [i + 0x400] = Memory.BlockIsROM [i + 0xc00] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = Memory.MemorySpeed [i + 0x800] = + Memory.MemorySpeed [i + 0x400] = Memory.MemorySpeed [i + 0xc00] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + MapExtraRAM (); + WriteProtectROM (); +} + +void BSHiROMMap () +{ + int c; + int i; + + // Banks 00->3f and 80->bf + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 0] = Memory.Map [c + 0x800] = Memory.RAM; + Memory.BlockIsRAM [c + 0] = Memory.BlockIsRAM [c + 0x800] = TRUE; + Memory.Map [c + 1] = Memory.Map [c + 0x801] = Memory.RAM; + Memory.BlockIsRAM [c + 1] = Memory.BlockIsRAM [c + 0x801] = TRUE; + + Memory.Map [c + 2] = Memory.Map [c + 0x802] = (uint8 *) MAP_PPU; + Memory.Map [c + 3] = Memory.Map [c + 0x803] = (uint8 *) MAP_PPU; + Memory.Map [c + 4] = Memory.Map [c + 0x804] = (uint8 *) MAP_CPU; + // XXX: How large is SRAM?? + Memory.Map [c + 5] = Memory.Map [c + 0x805] = (uint8 *) Memory.SRAM; + Memory.BlockIsRAM [c + 5] = Memory.BlockIsRAM [c + 0x805] = TRUE; + Memory.Map [c + 6] = Memory.Map [c + 0x806] = (uint8 *) MAP_NONE; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = (uint8 *) MAP_NONE; + + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = Memory.Map [i + 0x800] = &Memory.ROM [(c << 12) % Memory.CalculatedSize]; + Memory.BlockIsROM [i] = Memory.BlockIsROM [i + 0x800] = TRUE; + } + + for (i = c; i < c + 16; i++) + { + int ppu = i & 15; + + Memory.MemorySpeed [i] = + Memory.MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; + } + } + + // Banks 60->7d offset 0000->7fff & 60->7f offset 8000->ffff PSRAM + // XXX: How large is PSRAM? + for (c = 0x600; c < 0x7e0; c += 16) + { + for (i = c; i < c + 8; i++) + { + Memory.Map [i] = &Memory.ROM [0x400000 + (c << 11)]; + Memory.BlockIsRAM [i] = TRUE; + } + for (i = c + 8; i < c + 16; i++) + { + Memory.Map [i] = &Memory.ROM [0x400000 + (c << 11) - 0x8000]; + Memory.BlockIsRAM [i] = TRUE; + } + } + + // Banks 40->7f and c0->ff + for (c = 0; c < 0x400; c += 16) + { + for (i = c; i < c + 16; i++) + { + Memory.Map [i + 0x400] = Memory.Map [i + 0xc00] = &Memory.ROM [(c << 12) % Memory.CalculatedSize]; + Memory.MemorySpeed [i + 0x400] = Memory.MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; + Memory.BlockIsROM [i + 0x400] = Memory.BlockIsROM [i + 0xc00] = TRUE; + } + } + + MapRAM (); + WriteProtectROM (); +} + +const char *TVStandard () +{ + return (Settings.PAL ? "PAL" : "NTSC"); +} + +const char *Speed () +{ + return (Memory.ROMSpeed & 0x10 ? "120ns" : "200ns"); +} + +const char *MapType () +{ + return (Memory.HiROM ? "HiROM" : "LoROM"); +} + +const char *StaticRAMSize () +{ + static char tmp [20]; + + if (Memory.SRAMSize > 16) + return ("Corrupt"); + sprintf (tmp, "%dKb", (CPU.Memory_SRAMMask + 1) / 1024); + return (tmp); +} + +const char *Size () +{ + static char tmp [20]; + + if (Memory.ROMSize < 7 || Memory.ROMSize - 7 > 23) + return ("Corrupt"); + sprintf (tmp, "%dMbits", 1 << (Memory.ROMSize - 7)); + return (tmp); +} + +const char *KartContents () +{ + static char tmp [30]; + static const char *CoPro [16] = { + "DSP1", "SuperFX", "OBC1", "SA-1", "S-DD1", "S-RTC", "CoPro#6", + "CoPro#7", "CoPro#8", "CoPro#9", "CoPro#10", "CoPro#11", "CoPro#12", + "CoPro#13", "CoPro#14", "CoPro-Custom" + }; + static const char *Contents [3] = { + "ROM", "ROM+RAM", "ROM+RAM+BAT" + }; + if (Memory.ROMType == 0) + return ("ROM only"); + + sprintf (tmp, "%s", Contents [(Memory.ROMType & 0xf) % 3]); + + if ((Memory.ROMType & 0xf) >= 3) + sprintf (tmp, "%s+%s", tmp, CoPro [(Memory.ROMType & 0xf0) >> 4]); + + return (tmp); +} + +const char *MapMode () +{ + static char tmp [4]; + sprintf (tmp, "%02x", Memory.ROMSpeed & ~0x10); + return (tmp); +} + +const char *ROMID () +{ + return (Memory.ROMId); +} + +void ApplyROMFixes () +{ + ROMAPUEnabled = 0; + DSP1.version = 0; + //Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; + if (strncmp(Memory.ROMName, "DUNGEON MASTER", 14) == 0) + { + DSP1.version = 1; + SetDSP=&DSP2SetByte; + GetDSP=&DSP2GetByte; + } + + //OAM hacks because we don't fully understand the + //behavior of the SNES. + + //possibly an RTO issue? + //part of Fred's club is drawn over his face. + if(strncmp(Memory.ROMName, "THE FLINTSTONES TTOSM", 21)==0) + { + SNESGameFixes.Flintstones=true; + } + + if(strncmp(Memory.ROMName, "SUPER MARIO KART", 16)==0 + || strncmp(Memory.ROMName, "F-ZERO", 6)==0) + { + SNESGameFixes.Mode7Hack=true; + } + + //Totally wacky display... + //seems to need a disproven behavior, so + //we're definitely overlooking some other bug? + if(strncmp(Memory.ROMName, "UNIRACERS", 9)==0) + SNESGameFixes.Uniracers=true; + + // Enable S-RTC (Real Time Clock) emulation for Dai Kaijyu Monogatari 2 + Settings.SRTC = ((Memory.ROMType & 0xf0) >> 4) == 5; + + Settings.StrikeGunnerOffsetHack = strcmp (Memory.ROMName, "STRIKE GUNNER") == 0 ? 7 : 0; + + CPU.NMITriggerPoint = 4; + if (strcmp (Memory.ROMName, "CACOMA KNIGHT") == 0) + CPU.NMITriggerPoint = 25; + + // These games complain if the multi-player adaptor is 'connected' + if (strcmp (Memory.ROMName, "TETRIS&Dr.MARIO") == 0 || + strcmp (Memory.ROMName, "JIGSAW PARTY") == 0 || + strcmp (Memory.ROMName, "SUPER PICROSS") == 0 || + strcmp (Memory.ROMName, "KIRBY NO KIRA KIZZU") == 0 || + strcmp (Memory.ROMName, "BLOCK") == 0 || + strncmp (Memory.ROMName, "SUPER BOMBLISS", 14) == 0 || + strcmp (Memory.ROMId, "ABOJ") == 0) + { + Settings.MultiPlayer5Master = FALSE; + Settings.MouseMaster = FALSE; + Settings.SuperScopeMaster = FALSE; + } + + // Games which spool sound samples between the SNES and sound CPU using + // H-DMA as the sample is playing. + if (strcmp (Memory.ROMName, "EARTHWORM JIM 2") == 0 || + strcmp (Memory.ROMName, "PRIMAL RAGE") == 0 || + strcmp (Memory.ROMName, "CLAY FIGHTER") == 0 || + strcmp (Memory.ROMName, "ClayFighter 2") == 0 || + strncasecmp (Memory.ROMName, "MADDEN", 6) == 0 || + strncmp (Memory.ROMName, "NHL", 3) == 0 || + strcmp (Memory.ROMName, "WEAPONLORD") == 0) + { + Settings.Shutdown = FALSE; + } + + + // Stunt Racer FX + if (strcmp (Memory.ROMId, "CQ ") == 0 || + // Illusion of Gaia + strncmp (Memory.ROMId, "JG", 2) == 0 || + strcmp (Memory.ROMName, "GAIA GENSOUKI 1 JPN") == 0) + { + IAPU.OneCycle = 13; + ROMAPUEnabled |= 2; + CPU.APU_APUExecuting |= 2; + } + + // RENDERING RANGER R2 + if (strcmp (Memory.ROMId, "AVCJ") == 0 || + // Star Ocean + strncmp (Memory.ROMId, "ARF", 3) == 0 || + // Tales of Phantasia + strncmp (Memory.ROMId, "ATV", 3) == 0 || + // Act Raiser 1 & 2 + strncasecmp (Memory.ROMName, "ACTRAISER", 9) == 0 || + strncasecmp (Memory.ROMName, "ActRaiser", 9) == 0 || // I kown both sentences are supposed to be equivalent each other but they aren't on my compiler + // Soulblazer + strcmp (Memory.ROMName, "SOULBLAZER - 1 USA") == 0 || + strcmp (Memory.ROMName, "SOULBLADER - 1") == 0 || + strncmp (Memory.ROMName, "SOULBLAZER 1",12) == 0 || + // Terranigma + strncmp (Memory.ROMId, "AQT", 3) == 0 || + // Robotrek + strncmp (Memory.ROMId, "E9 ", 3) == 0 || + strcmp (Memory.ROMName, "SLAP STICK 1 JPN") == 0 || + // ZENNIHON PURORESU2 + strncmp (Memory.ROMId, "APR", 3) == 0 || + // Bomberman 4 + strncmp (Memory.ROMId, "A4B", 3) == 0 || + // UFO KAMEN YAKISOBAN + strncmp (Memory.ROMId, "Y7 ", 3) == 0 || + strncmp (Memory.ROMId, "Y9 ", 3) == 0 || + // Panic Bomber World + strncmp (Memory.ROMId, "APB", 3) == 0 || + ((strncmp (Memory.ROMName, "Parlor", 6) == 0 || + strcmp (Memory.ROMName, "HEIWA PARLOR!MINI8") == 0 || + strncmp (Memory.ROMName, "SANKYO Fever! フィーバー!", 21) == 0) && + strcmp (Memory.CompanyId, "A0") == 0) || + strcmp (Memory.ROMName, "DARK KINGDOM") == 0 || + strcmp (Memory.ROMName, "ZAN3 SFC") == 0 || + strcmp (Memory.ROMName, "HIOUDEN") == 0 || + strcmp (Memory.ROMName, "テンシノウタ") == 0 || + strcmp (Memory.ROMName, "FORTUNE QUEST") == 0 || + strcmp (Memory.ROMName, "FISHING TO BASSING") == 0 || + strncmp (Memory.ROMName, "TOKYODOME '95BATTLE 7", 21) == 0 || + strcmp (Memory.ROMName, "OHMONO BLACKBASS") == 0) + { + IAPU.OneCycle = 15; + // notaz: strangely enough, these games work properly with my hack enabled + if (strcmp (Memory.ROMId, "AVCJ") != 0) + ROMAPUEnabled |= 2; + CPU.APU_APUExecuting |= 2; + } + + if (strcmp (Memory.ROMName, "BATMAN--REVENGE JOKER") == 0) + { + Memory.HiROM = FALSE; + Memory.LoROM = TRUE; + LoROMMap (); + } + Settings.StarfoxHack = strcmp (Memory.ROMName, "STAR FOX") == 0 || + strcmp (Memory.ROMName, "STAR WING") == 0; + Settings.WinterGold = strcmp (Memory.ROMName, "FX SKIING NINTENDO 96") == 0 || + strcmp (Memory.ROMName, "DIRT RACER") == 0 || + strcmp (Memory.ROMName, "Stunt Race FX") == 0 || + Settings.StarfoxHack; + Settings.ChuckRock = strcmp (Memory.ROMName, "CHUCK ROCK") == 0; + Settings.Dezaemon = strcmp (Memory.ROMName, "DEZAEMON") == 0; + + if (strcmp (Memory.ROMName, "RADICAL DREAMERS") == 0 || + strcmp (Memory.ROMName, "TREASURE CONFLIX") == 0) + { + int c; + + for (c = 0; c < 0x80; c++) + { + Memory.Map [c + 0x700] = Memory.ROM + 0x200000 + 0x1000 * (c & 0xf0); + Memory.BlockIsRAM [c + 0x700] = TRUE; + Memory.BlockIsROM [c + 0x700] = FALSE; + } + for (c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 5] = Memory.Map [c + 0x805] = Memory.ROM + 0x300000; + Memory.BlockIsRAM [c + 5] = Memory.BlockIsRAM [c + 0x805] = TRUE; + } + WriteProtectROM (); + } + + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * + Settings.CyclesPercentage) / 100; + + // A Couple of HDMA related hacks - Lantus + if ((strcmp(Memory.ROMName, "SFX SUPERBUTOUDEN2")==0) || + (strcmp(Memory.ROMName, "ALIEN vs. PREDATOR")==0) || + (strcmp(Memory.ROMName, "STONE PROTECTORS")==0) || + (strcmp(Memory.ROMName, "SUPER BATTLETANK 2")==0)) + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 130) / 100; + + if (strcmp (Memory.ROMId, "ASRJ") == 0 && Settings.CyclesPercentage == 100) + // Street Racer + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 95) / 100; + + // Power Rangers Fight + if (strncmp (Memory.ROMId, "A3R", 3) == 0 || + // Clock Tower + strncmp (Memory.ROMId, "AJE", 3) == 0) + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 103) / 100; + + if (strcmp (Memory.ROMId, "AWVP") == 0 || strcmp (Memory.ROMId, "AWVE") == 0 || + strcmp (Memory.ROMId, "AWVJ") == 0) + { + // Wrestlemania Arcade +#if 0 + if (Settings.CyclesPercentage == 100) + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 140) / 100; // Fixes sound +#endif + Settings.WrestlemaniaArcade = TRUE; + } + // Theme Park - disable offset-per-tile mode. + if (strcmp (Memory.ROMId, "ATQP") == 0) + Settings.WrestlemaniaArcade = TRUE; + + if (strncmp (Memory.ROMId, "A3M", 3) == 0 && Settings.CyclesPercentage == 100) + // Mortal Kombat 3. Fixes cut off speech sample + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100; + + if (strcmp (Memory.ROMName, "\x0bd\x0da\x0b2\x0d4\x0b0\x0bd\x0de") == 0 && + Settings.CyclesPercentage == 100) + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 101) / 100; + + if (strcmp (Memory.ROMName, "WILD TRAX") == 0 || + strcmp (Memory.ROMName, "YOSSY'S ISLAND") == 0 || + strcmp (Memory.ROMName, "YOSHI'S ISLAND") == 0) + CPU.TriedInterleavedMode2 = TRUE; + + // Start Trek: Deep Sleep 9 + if (strncmp (Memory.ROMId, "A9D", 3) == 0 && Settings.CyclesPercentage == 100) + Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100; + + Settings.APURAMInitialValue = 0xff; + + if (strcmp (Memory.ROMName, "キュウヤク・メガミテンセイ") == 0 || + strcmp (Memory.ROMName, "KENTOUOU WORLDCHAMPIO") == 0 || + strcmp (Memory.ROMName, "TKO SUPERCHAMPIONSHIP") == 0 || + strcmp (Memory.ROMName, "TKO SUPER CHAMPIONSHI") == 0 || + strcmp (Memory.ROMName, "IHATOVO STORY") == 0 || + strcmp (Memory.ROMName, "WANDERERS FROM YS") == 0 || + strcmp (Memory.ROMName, "SUPER GENTYOUHISHI") == 0 || + // Panic Bomber World + strncmp (Memory.ROMId, "APB", 3) == 0) + { + Settings.APURAMInitialValue = 0; + } + + Settings.DaffyDuck = strcmp (Memory.ROMName, "DAFFY DUCK: MARV MISS") == 0; + Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; + +#ifdef USE_SA1 + SA1.WaitAddress = NULL; + SA1.WaitByteAddress1 = NULL; + SA1.WaitByteAddress2 = NULL; + + /* Bass Fishing */ + if (strcmp (Memory.ROMId, "ZBPJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x0093f1 >> MEMMAP_SHIFT] + 0x93f1; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x304a; + } + /* DAISENRYAKU EXPERTWW2 */ + if (strcmp (Memory.ROMId, "AEVJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x0ed18d >> MEMMAP_SHIFT] + 0xd18d; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x3000; + } + /* debjk2 */ + if (strcmp (Memory.ROMId, "A2DJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x008b62 >> MEMMAP_SHIFT] + 0x8b62; + } + /* Dragon Ballz HD */ + if (strcmp (Memory.ROMId, "AZIJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x008083 >> MEMMAP_SHIFT] + 0x8083; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x3020; + } + /* SFC SDGUNDAMGNEXT */ + if (strcmp (Memory.ROMId, "ZX3J") == 0) + { + SA1.WaitAddress = SA1_Map [0x0087f2 >> MEMMAP_SHIFT] + 0x87f2; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x30c4; + } + /* ShougiNoHanamichi */ + if (strcmp (Memory.ROMId, "AARJ") == 0) + { + SA1.WaitAddress = SA1_Map [0xc1f85a >> MEMMAP_SHIFT] + 0xf85a; + SA1.WaitByteAddress1 = Memory.SRAM + 0x0c64; + SA1.WaitByteAddress2 = Memory.SRAM + 0x0c66; + } + /* KATO HIFUMI9DAN SYOGI */ + if (strcmp (Memory.ROMId, "A23J") == 0) + { + SA1.WaitAddress = SA1_Map [0xc25037 >> MEMMAP_SHIFT] + 0x5037; + SA1.WaitByteAddress1 = Memory.SRAM + 0x0c06; + SA1.WaitByteAddress2 = Memory.SRAM + 0x0c08; + } + /* idaten */ + if (strcmp (Memory.ROMId, "AIIJ") == 0) + { + SA1.WaitAddress = SA1_Map [0xc100be >> MEMMAP_SHIFT] + 0x00be; + SA1.WaitByteAddress1 = Memory.SRAM + 0x1002; + SA1.WaitByteAddress2 = Memory.SRAM + 0x1004; + } + /* igotais */ + if (strcmp (Memory.ROMId, "AITJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x0080b7 >> MEMMAP_SHIFT] + 0x80b7; + } + /* J96 DREAM STADIUM */ + if (strcmp (Memory.ROMId, "AJ6J") == 0) + { + SA1.WaitAddress = SA1_Map [0xc0f74a >> MEMMAP_SHIFT] + 0xf74a; + } + /* JumpinDerby */ + if (strcmp (Memory.ROMId, "AJUJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x00d926 >> MEMMAP_SHIFT] + 0xd926; + } + /* JKAKINOKI SHOUGI */ + if (strcmp (Memory.ROMId, "AKAJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x00f070 >> MEMMAP_SHIFT] + 0xf070; + } + /* HOSHI NO KIRBY 3 & KIRBY'S DREAM LAND 3 JAP & US */ + if (strcmp (Memory.ROMId, "AFJJ") == 0 || strcmp (Memory.ROMId, "AFJE") == 0) + { + SA1.WaitAddress = SA1_Map [0x0082d4 >> MEMMAP_SHIFT] + 0x82d4; + SA1.WaitByteAddress1 = Memory.SRAM + 0x72a4; + } + /* KIRBY SUPER DELUXE JAP */ + if (strcmp (Memory.ROMId, "AKFJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x008c93 >> MEMMAP_SHIFT] + 0x8c93; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x300a; + SA1.WaitByteAddress2 = Memory.FillRAM + 0x300e; + } + /* KIRBY SUPER DELUXE US */ + if (strcmp (Memory.ROMId, "AKFE") == 0) + { + SA1.WaitAddress = SA1_Map [0x008cb8 >> MEMMAP_SHIFT] + 0x8cb8; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x300a; + SA1.WaitByteAddress2 = Memory.FillRAM + 0x300e; + } + /* SUPER MARIO RPG JAP & US */ + if (strcmp (Memory.ROMId, "ARWJ") == 0 || strcmp (Memory.ROMId, "ARWE") == 0) + { + SA1.WaitAddress = SA1_Map [0xc0816f >> MEMMAP_SHIFT] + 0x816f; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x3000; + } + /* marvelous.zip */ + if (strcmp (Memory.ROMId, "AVRJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x0085f2 >> MEMMAP_SHIFT] + 0x85f2; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x3024; + } + /* AUGUSTA3 MASTERS NEW */ + if (strcmp (Memory.ROMId, "AO3J") == 0) + { + SA1.WaitAddress = SA1_Map [0x00dddb >> MEMMAP_SHIFT] + 0xdddb; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x37b4; + } + /* OSHABERI PARODIUS */ + if (strcmp (Memory.ROMId, "AJOJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x8084e5 >> MEMMAP_SHIFT] + 0x84e5; + } + /* PANIC BOMBER WORLD */ + if (strcmp (Memory.ROMId, "APBJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x00857a >> MEMMAP_SHIFT] + 0x857a; + } + /* PEBBLE BEACH NEW */ + if (strcmp (Memory.ROMId, "AONJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x00df33 >> MEMMAP_SHIFT] + 0xdf33; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x37b4; + } + /* PGA EUROPEAN TOUR */ + if (strcmp (Memory.ROMId, "AEPE") == 0) + { + SA1.WaitAddress = SA1_Map [0x003700 >> MEMMAP_SHIFT] + 0x3700; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x3102; + } + /* PGA TOUR 96 */ + if (strcmp (Memory.ROMId, "A3GE") == 0) + { + SA1.WaitAddress = SA1_Map [0x003700 >> MEMMAP_SHIFT] + 0x3700; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x3102; + } + /* POWER RANGERS 4 */ + if (strcmp (Memory.ROMId, "A4RE") == 0) + { + SA1.WaitAddress = SA1_Map [0x009899 >> MEMMAP_SHIFT] + 0x9899; + SA1.WaitByteAddress1 = Memory.FillRAM + 0x3000; + } + /* PACHISURO PALUSUPE */ + if (strcmp (Memory.ROMId, "AGFJ") == 0) + { + // Never seems to turn on the SA-1! + } + /* SD F1 GRAND PRIX */ + if (strcmp (Memory.ROMId, "AGFJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x0181bc >> MEMMAP_SHIFT] + 0x81bc; + } + /* SHOUGI MARJONG */ + if (strcmp (Memory.ROMId, "ASYJ") == 0) + { + SA1.WaitAddress = SA1_Map [0x00f2cc >> MEMMAP_SHIFT] + 0xf2cc; + SA1.WaitByteAddress1 = Memory.SRAM + 0x7ffe; + SA1.WaitByteAddress2 = Memory.SRAM + 0x7ffc; + } + /* shogisai2 */ + if (strcmp (Memory.ROMId, "AX2J") == 0) + { + SA1.WaitAddress = SA1_Map [0x00d675 >> MEMMAP_SHIFT] + 0xd675; + } + + /* SHINING SCORPION */ + if (strcmp (Memory.ROMId, "A4WJ") == 0) + { + SA1.WaitAddress = SA1_Map [0xc048be >> MEMMAP_SHIFT] + 0x48be; + } + /* SHIN SHOUGI CLUB */ + if (strcmp (Memory.ROMId, "AHJJ") == 0) + { + SA1.WaitAddress = SA1_Map [0xc1002a >> MEMMAP_SHIFT] + 0x002a; + SA1.WaitByteAddress1 = Memory.SRAM + 0x0806; + SA1.WaitByteAddress2 = Memory.SRAM + 0x0808; + } +#endif // USE_SA1 + + // Additional game fixes by sanmaiwashi ... + if (strcmp (Memory.ROMName, "SFX ナイトガンダムモノガタリ 1") == 0) + { + bytes0x2000 [0xb18] = 0x4c; + bytes0x2000 [0xb19] = 0x4b; + bytes0x2000 [0xb1a] = 0xea; + } + + if (strcmp (Memory.ROMName, "GOGO ACKMAN3") == 0 || + strcmp (Memory.ROMName, "HOME ALONE") == 0) + { + // Banks 00->3f and 80->bf + for (int c = 0; c < 0x400; c += 16) + { + Memory.Map [c + 6] = Memory.Map [c + 0x806] = Memory.SRAM; + Memory.Map [c + 7] = Memory.Map [c + 0x807] = Memory.SRAM; + Memory.BlockIsROM [c + 6] = Memory.BlockIsROM [c + 0x806] = FALSE; + Memory.BlockIsROM [c + 7] = Memory.BlockIsROM [c + 0x807] = FALSE; + Memory.BlockIsRAM [c + 6] = Memory.BlockIsRAM [c + 0x806] = TRUE; + Memory.BlockIsRAM [c + 7] = Memory.BlockIsRAM [c + 0x807] = TRUE; + } + WriteProtectROM (); + } + + if (strncmp (Memory.ROMName, "SWORD WORLD SFC", 15) == 0 || + strcmp (Memory.ROMName, "SFC カメンライダー") == 0) + { + IAPU.OneCycle = 15; + SNESGameFixes.NeedInit0x2137 = TRUE; + ROMAPUEnabled |= 2; + CPU.APU_APUExecuting |= 2; + } + + if (strncmp (Memory.ROMName, "SHIEN THE BLADE CHASE", 21) == 0) + SNESGameFixes.Old_Read0x4200 = TRUE; + + if (strcmp (Memory.ROMName, "ゴジラ カイジュウダイケッセン") == 0) + SNESGameFixes.NeedInit0x2137 = TRUE; + + if (strcmp (Memory.ROMName, "UMIHARAKAWASE") == 0) + SNESGameFixes.umiharakawaseFix = TRUE; + + if (strcmp (Memory.ROMName, "ALIENS vs. PREDATOR") == 0) + SNESGameFixes.alienVSpredetorFix = TRUE; + + if (strcmp (Memory.ROMName, "demon's blazon") == 0 || + strcmp (Memory.ROMName, "demon's crest") == 0 || + strcmp (Memory.ROMName, "ROCKMAN X") == 0 || + strcmp (Memory.ROMName, "MEGAMAN X") == 0) + { + + // CAPCOM's protect + // Banks 0x808000, 0x408000 are mirroring. + for (int c = 0; c < 8; c++) + Memory.Map [0x408 + c] = Memory.ROM - 0x8000; + } + + if (strcmp (Memory.ROMName, "スーパーファミスタ") == 0 || + strcmp (Memory.ROMName, "スーパーファミスタ 2") == 0 || + strcmp (Memory.ROMName, "ZENKI TENCHIMEIDOU") == 0 || + strcmp (Memory.ROMName, "GANBA LEAGUE") == 0) + { + SNESGameFixes.APU_OutPorts_ReturnValueFix = TRUE; + } + + // HITOMI3 + if (strcmp (Memory.ROMName, "HITOMI3") == 0) + { + Memory.SRAMSize = 1; + CPU.Memory_SRAMMask = Memory.SRAMSize ? + ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; + } + + if (strcmp (Memory.ROMName, "goemon 4") == 0) + SNESGameFixes.SRAMInitialValue = 0x00; + + if (strcmp (Memory.ROMName, "PACHISLO ケンキュウ") == 0) + SNESGameFixes._0x213E_ReturnValue = 1; + + if (strcmp (Memory.ROMName, "ザ マージャン トウハイデン") == 0) + SNESGameFixes.TouhaidenControllerFix = TRUE; + + if (strcmp (Memory.ROMName, "DRAGON KNIGHT 4") == 0) + { + // Banks 70->7e, S-RAM + for (int c = 0; c < 0xe0; c++) + { + Memory.Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM; + Memory.BlockIsRAM [c + 0x700] = TRUE; + Memory.BlockIsROM [c + 0x700] = FALSE; + } + WriteProtectROM (); + } + + if (strncmp (Memory.ROMName, "LETs PACHINKO(", 14) == 0) + { + IAPU.OneCycle = 15; + ROMAPUEnabled |= 2; + CPU.APU_APUExecuting |= 2; + if (!Settings.ForceNTSC && !Settings.ForcePAL) + { + Settings.PAL = FALSE; + Settings.FrameTime = Settings.FrameTimeNTSC; + Memory.ROMFramesPerSecond = 60; + } + } + + if (strcmp (Memory.ROMName, "FURAI NO SIREN") == 0) + SNESGameFixes.SoundEnvelopeHeightReading2 = TRUE; +#if 0 + if(strcmp (ROMName, "XBAND JAPANESE MODEM") == 0) + { + for (c = 0x200; c < 0x400; c += 16) + { + for (int i = c; i < c + 16; i++) + { + Map [i + 0x400] = Map [i + 0xc00] = &ROM[c * 0x1000]; + MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = 8; + BlockIsRAM [i + 0x400] = BlockIsRAM [i + 0xc00] = TRUE; + BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = FALSE; + } + } + WriteProtectROM (); + } +#endif + +#define RomPatch(adr,ov,nv) \ +if (ROM [adr] == ov) \ + ROM [adr] = nv + + // Love Quest + if (strcmp (Memory.ROMName, "LOVE QUEST") == 0) + { + RomPatch (0x1385ec, 0xd0, 0xea); + RomPatch (0x1385ed, 0xb2, 0xea); + } + + // Nangoku Syonen Papuwa Kun + if (strcmp (Memory.ROMName, "NANGOKUSYONEN PAPUWA") == 0) + RomPatch (0x1f0d1, 0xa0, 0x6b); + + // Tetsuwan Atom + if (strcmp (Memory.ROMName, "Tetsuwan Atom") == 0) + { + RomPatch (0xe24c5, 0x90, 0xea); + RomPatch (0xe24c6, 0xf3, 0xea); + } + + // Oda Nobunaga + if (strcmp (Memory.ROMName, "SFC ODA NOBUNAGA") == 0) + { + RomPatch (0x7497, 0x80, 0xea); + RomPatch (0x7498, 0xd5, 0xea); + } + + // Super Batter Up + if (strcmp (Memory.ROMName, "Super Batter Up") == 0) + { + RomPatch (0x27ae0, 0xd0, 0xea); + RomPatch (0x27ae1, 0xfa, 0xea); + } + + // Super Professional Baseball 2 + if (strcmp (Memory.ROMName, "SUPER PRO. BASE BALL2") == 0) + { + RomPatch (0x1e4, 0x50, 0xea); + RomPatch (0x1e5, 0xfb, 0xea); + } + +} + +// Read variable size MSB int from a file +static long ReadInt (FILE *f, unsigned nbytes) +{ + long v = 0; + while (nbytes--) + { + int c = fgetc(f); + if (c == EOF) + return -1; + v = (v << 8) | (c & 0xFF); + } + return (v); +} + +#define IPS_EOF 0x00454F46l + +void CheckForIPSPatch (const char *rom_filename, bool8_32 header, + int32* rom_size) +{ + char dir [_MAX_DIR + 1]; + char drive [_MAX_DRIVE + 1]; + char name [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + char fname [_MAX_PATH + 1]; + FILE *patch_file = NULL; + long offset = header ? 512 : 0; + + if (!(patch_file = fopen(S9xGetFilename (".ips"), "rb"))) return; + + if (fread (fname, 1, 5, patch_file) != 5 || strncmp (fname, "PATCH", 5) != 0) + { + fclose (patch_file); + return; + } + + int32 ofs; + + for (;;) + { + long len; + long rlen; + int rchar; + + ofs = ReadInt (patch_file, 3); + if (ofs == -1) + goto err_eof; + + if (ofs == IPS_EOF) + break; + + ofs -= offset; + + len = ReadInt (patch_file, 2); + if (len == -1) + goto err_eof; + + /* Apply patch block */ + if (len) + { + if (ofs + len > MAX_ROM_SIZE) + goto err_eof; + + while (len--) + { + rchar = fgetc (patch_file); + if (rchar == EOF) + goto err_eof; + Memory.ROM [ofs++] = (uint8) rchar; + } + if (ofs > *rom_size) + *rom_size = ofs; + } + else + { + rlen = ReadInt (patch_file, 2); + if (rlen == -1) + goto err_eof; + + + rchar = fgetc (patch_file); + if (rchar == EOF) + goto err_eof; + + if (ofs + rlen > MAX_ROM_SIZE) + goto err_eof; + + while (rlen--) + Memory.ROM [ofs++] = (uint8) rchar; + + if (ofs > *rom_size) + *rom_size = ofs; + } + } + + // Check if ROM image needs to be truncated + ofs = ReadInt (patch_file, 3); + if (ofs != -1 && ofs - offset < *rom_size) + { + // Need to truncate ROM image + *rom_size = ofs - offset; + } + fclose (patch_file); + return; + +err_eof: + if (patch_file) + fclose (patch_file); +} + +const uint32 crc32Table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +//CRC32 for char arrays +uint32 caCRC32(uint8 *array, uint32 size) { + register uint32 crc32 = 0xFFFFFFFF; + for (register uint32 i = 0; i < size; i++) { + crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF]; + } + return ~crc32; +} +#include "getset.h" diff --git a/src/memmap.cpp b/src/memmap.cpp deleted file mode 100644 index 4436fe3..0000000 --- a/src/memmap.cpp +++ /dev/null @@ -1,2758 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include -#include - -#ifdef __linux -//#include -#endif - -#include "snes9x.h" -#include "memmap.h" -#include "cpuexec.h" -#include "ppu.h" -#include "display.h" -#include "cheats.h" -#include "apu.h" -#include "sa1.h" -#include "srtc.h" -#include "sdd1.h" - -#ifndef ZSNES_FX -#include "fxemu.h" -extern struct FxInit_s SuperFX; -#else -START_EXTERN_C -extern uint8 *SFXPlotTable; -END_EXTERN_C -#endif - -static uint8 bytes0x2000 [0x2000]; - -extern bool8 ROMAPUEnabled; - -extern char *rom_filename; -extern bool8 LoadZip(const char* , int32 *, int32 *); - -bool8_32 CMemory::AllASCII (uint8 *b, int size) -{ - for (int i = 0; i < size; i++) - { - if (b[i] < 32 || b[i] > 126) - return (FALSE); - } - return (TRUE); -} - -int CMemory::ScoreHiROM (bool8_32 skip_header) -{ - int score = 0; - int o = skip_header ? 0xff00 + 0x200 : 0xff00; - - if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + - Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) - score += 2; - - if (Memory.ROM [o + 0xda] == 0x33) - score += 2; - if ((Memory.ROM [o + 0xd5] & 0xf) < 4) - score += 2; - if (!(Memory.ROM [o + 0xfd] & 0x80)) - score -= 4; - if (CalculatedSize > 1024 * 1024 * 3) - score += 4; - if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xb0], 6)) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1)) - score -= 1; - - return (score); -} - -int CMemory::ScoreLoROM (bool8_32 skip_header) -{ - int score = 0; - int o = skip_header ? 0x7f00 + 0x200 : 0x7f00; - - if ((Memory.ROM [o + 0xdc] + (Memory.ROM [o + 0xdd] << 8) + - Memory.ROM [o + 0xde] + (Memory.ROM [o + 0xdf] << 8)) == 0xffff) - score += 2; - - if (Memory.ROM [o + 0xda] == 0x33) - score += 2; - if ((Memory.ROM [o + 0xd5] & 0xf) < 4) - score += 2; - if (CalculatedSize <= 1024 * 1024 * 16) - score += 2; - if (!(Memory.ROM [o + 0xfd] & 0x80)) - score -= 4; - if ((1 << (Memory.ROM [o + 0xd7] - 7)) > 48) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xb0], 6)) - score -= 1; - if (!AllASCII (&Memory.ROM [o + 0xc0], ROM_NAME_LEN - 1)) - score -= 1; - - return (score); -} - -char *CMemory::Safe (const char *s) -{ - static char *safe = NULL; - static int safe_len = 0; - - int len = strlen (s); - if (!safe || len + 1 > safe_len) - { - if (safe) - free ((char *) safe); - safe = (char *) malloc (safe_len = len + 1); - } - - for (int i = 0; i < len; i++) - { - if (s [i] >= 32 && s [i] < 127) - safe [i] = s[i]; - else - safe [i] = '?'; - } - safe [len] = 0; - return (safe); -} - -/**********************************************************************************************/ -/* Init() */ -/* This function allocates all the memory needed by the emulator */ -/**********************************************************************************************/ -bool8_32 CMemory::Init () -{ - RAM = (uint8 *) malloc (0x20000); - SRAM = (uint8 *) malloc (0x20000); - VRAM = (uint8 *) malloc (0x10000); - ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000); - FillRAM = NULL; - - IPPU.TileCache [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES * 128); - IPPU.TileCache [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES * 128); - IPPU.TileCache [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES * 128); - - IPPU.TileCached [TILE_2BIT] = (uint8 *) malloc (MAX_2BIT_TILES); - IPPU.TileCached [TILE_4BIT] = (uint8 *) malloc (MAX_4BIT_TILES); - IPPU.TileCached [TILE_8BIT] = (uint8 *) malloc (MAX_8BIT_TILES); - - if (!RAM || !SRAM || !VRAM || !ROM || - !IPPU.TileCache [TILE_2BIT] || !IPPU.TileCache [TILE_4BIT] || - !IPPU.TileCache [TILE_8BIT] || !IPPU.TileCached [TILE_2BIT] || - !IPPU.TileCached [TILE_4BIT] || !IPPU.TileCached [TILE_8BIT]) - { - Deinit (); - return (FALSE); - } - - // FillRAM uses first 32K of ROM image area, otherwise space just - // wasted. Might be read by the SuperFX code. - - FillRAM = ROM; - - // Add 0x8000 to ROM image pointer to stop SuperFX code accessing - // unallocated memory (can cause crash on some ports). - ROM += 0x8000; - - C4RAM = ROM + 0x400000 + 8192 * 8; - ::ROM = ROM; - ::SRAM = SRAM; - ::RegRAM = FillRAM; - -#ifdef ZSNES_FX - SFXPlotTable = ROM + 0x400000; -#else - SuperFX.pvRegisters = &Memory.FillRAM [0x3000]; - SuperFX.nRamBanks = 1; - SuperFX.pvRam = ::SRAM; - SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); - SuperFX.pvRom = (uint8 *) ROM; -#endif - - ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES); - - SDD1Data = NULL; - SDD1Index = NULL; - - return (TRUE); -} - -void CMemory::Deinit () -{ - if (RAM) - { - free ((char *) RAM); - RAM = NULL; - } - if (SRAM) - { - free ((char *) SRAM); - SRAM = NULL; - } - if (VRAM) - { - free ((char *) VRAM); - VRAM = NULL; - } - if (ROM) - { - ROM -= 0x8000; - free ((char *) ROM); - ROM = NULL; - } - - if (IPPU.TileCache [TILE_2BIT]) - { - free ((char *) IPPU.TileCache [TILE_2BIT]); - IPPU.TileCache [TILE_2BIT] = NULL; - } - if (IPPU.TileCache [TILE_4BIT]) - { - free ((char *) IPPU.TileCache [TILE_4BIT]); - IPPU.TileCache [TILE_4BIT] = NULL; - } - if (IPPU.TileCache [TILE_8BIT]) - { - free ((char *) IPPU.TileCache [TILE_8BIT]); - IPPU.TileCache [TILE_8BIT] = NULL; - } - - if (IPPU.TileCached [TILE_2BIT]) - { - free ((char *) IPPU.TileCached [TILE_2BIT]); - IPPU.TileCached [TILE_2BIT] = NULL; - } - if (IPPU.TileCached [TILE_4BIT]) - { - free ((char *) IPPU.TileCached [TILE_4BIT]); - IPPU.TileCached [TILE_4BIT] = NULL; - } - if (IPPU.TileCached [TILE_8BIT]) - { - free ((char *) IPPU.TileCached [TILE_8BIT]); - IPPU.TileCached [TILE_8BIT] = NULL; - } - - FreeSDD1Data (); -} - -void CMemory::FreeSDD1Data () -{ - if (SDD1Index) - { - free ((char *) SDD1Index); - SDD1Index = NULL; - } - if (SDD1Data) - { - free ((char *) SDD1Data); - SDD1Data = NULL; - } -} - -/**********************************************************************************************/ -/* checkext() */ -/**********************************************************************************************/ -int checkzip( char * fn ) -{ - int cnt = strlen(fn); - if( ( (fn[cnt-1] == 'p') || (fn[cnt-1] == 'P') ) && - ( (fn[cnt-2] == 'i') || (fn[cnt-2] == 'I') ) && - ( (fn[cnt-3] == 'z') || (fn[cnt-3] == 'Z') ) ){ - return true; - - } - return false; -} - -/**********************************************************************************************/ -/* LoadROM() */ -/* This function loads a Snes-Backup image */ -/**********************************************************************************************/ -bool8_32 CMemory::LoadROM (const char *filename) -{ - unsigned long FileSize = 0; - int retry_count = 0; - STREAM ROMFile; - bool8_32 Interleaved = FALSE; - bool8_32 Tales = FALSE; - char dir [_MAX_DIR + 1]; - char drive [_MAX_DRIVE + 1]; - char name [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - char fname [_MAX_PATH + 1]; - int i; - - memset (&SNESGameFixes, 0, sizeof(SNESGameFixes)); - SNESGameFixes.SRAMInitialValue = 0x60; - - memset (bytes0x2000, 0, 0x2000); - CPU.TriedInterleavedMode2 = FALSE; - - CalculatedSize = 0; -again: - _splitpath (filename, drive, dir, name, ext); - _makepath (fname, drive, dir, name, ext); - -#ifdef __WIN32__ - memmove (&ext [0], &ext[1], 4); -#endif - - int32 TotalFileSize = 0; - - { - if ((ROMFile = OPEN_STREAM (fname, "rb")) == NULL) - return (FALSE); - - strcpy (ROMFilename, fname); - - HeaderCount = 0; - uint8 *ptr = ROM; - bool8_32 more = FALSE; - - do - { - FileSize = READ_STREAM (ptr, MAX_ROM_SIZE + 0x200 - (ptr - ROM), ROMFile); - CLOSE_STREAM (ROMFile); - int calc_size = (FileSize / 0x2000) * 0x2000; - - if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) || - Settings.ForceHeader) - { - memmove (ptr, ptr + 512, calc_size); - HeaderCount++; - FileSize -= 512; - } - ptr += FileSize; - TotalFileSize += FileSize; - - int len; - if (ptr - ROM < MAX_ROM_SIZE + 0x200 && - (isdigit (ext [0]) && ext [1] == 0 && ext [0] < '9')) - { - more = TRUE; - ext [0]++; -#ifdef __WIN32__ - memmove (&ext [1], &ext [0], 4); - ext [0] = '.'; -#endif - _makepath (fname, drive, dir, name, ext); - } - else - if (ptr - ROM < MAX_ROM_SIZE + 0x200 && - (((len = strlen (name)) == 7 || len == 8) && - strncasecmp (name, "sf", 2) == 0 && - isdigit (name [2]) && isdigit (name [3]) && isdigit (name [4]) && - isdigit (name [5]) && isalpha (name [len - 1]))) - { - more = TRUE; - name [len - 1]++; -#ifdef __WIN32__ - memmove (&ext [1], &ext [0], 4); - ext [0] = '.'; -#endif - _makepath (fname, drive, dir, name, ext); - } - else - more = FALSE; - } while (more && (ROMFile = OPEN_STREAM (fname, "rb")) != NULL); - } - - if (HeaderCount == 0) - S9xMessage (S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found."); - else - { - if (HeaderCount == 1) - S9xMessage (S9X_INFO, S9X_HEADERS_INFO, - "Found ROM file header (and ignored it)."); - else - S9xMessage (S9X_INFO, S9X_HEADERS_INFO, - "Found multiple ROM file headers (and ignored them)."); - } - - CheckForIPSPatch (filename, HeaderCount != 0, TotalFileSize); - int orig_hi_score, orig_lo_score; - int hi_score, lo_score; - - orig_hi_score = hi_score = ScoreHiROM (FALSE); - orig_lo_score = lo_score = ScoreLoROM (FALSE); - - if (HeaderCount == 0 && !Settings.ForceNoHeader && - ((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) || - (hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score))) - { - memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512); - TotalFileSize -= 512; - S9xMessage (S9X_INFO, S9X_HEADER_WARNING, - "Try specifying the -nhd command line option if the game doesn't work\n"); - } - - CalculatedSize = (TotalFileSize / 0x2000) * 0x2000; - ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize); - - // Check for cherryroms.com DAIKAIJYUMONOGATARI2 - - if (CalculatedSize == 0x500000 && - strncmp ((const char *)&ROM [0x40ffc0], "DAIKAIJYUMONOGATARI2", 20) == 0 && - strncmp ((const char *)&ROM [0x40ffb0], "18AE6J", 6) == 0 && - memcmp (&ROM[0x40ffb0], &ROM [0xffb0], 0x30)) - { - memmove (&ROM[0x100000], ROM, 0x500000); - memmove (ROM, &ROM[0x500000], 0x100000); - } - - Interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2; - if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score)) - { - LoROM = TRUE; - HiROM = FALSE; - - // Ignore map type byte if not 0x2x or 0x3x - if ((ROM [0x7fd5] & 0xf0) == 0x20 || (ROM [0x7fd5] & 0xf0) == 0x30) - { - switch (ROM [0x7fd5] & 0xf) - { - case 1: - if (strncmp ((char *) &ROM [0x7fc0], "TREASURE HUNTER G", 17) != 0) - Interleaved = TRUE; - break; - case 2: -#if 0 - if (!Settings.ForceLoROM && - strncmp ((char *) &ROM [0x7fc0], "SUPER FORMATION SOCCE", 21) != 0 && - strncmp ((char *) &ROM [0x7fc0], "Star Ocean", 10) != 0) - { - LoROM = FALSE; - HiROM = TRUE; - } -#endif - break; - case 5: - Interleaved = TRUE; - Tales = TRUE; - break; - } - } - } - else - { - if ((ROM [0xffd5] & 0xf0) == 0x20 || (ROM [0xffd5] & 0xf0) == 0x30) - { - switch (ROM [0xffd5] & 0xf) - { - case 0: - case 3: - Interleaved = TRUE; - break; - } - } - LoROM = FALSE; - HiROM = TRUE; - } - - // More - if (!Settings.ForceHiROM && !Settings.ForceLoROM && - !Settings.ForceInterleaved && !Settings.ForceInterleaved2 && - !Settings.ForceNotInterleaved && !Settings.ForcePAL && - !Settings.ForceSuperFX && !Settings.ForceDSP1 && - !Settings.ForceSA1 && !Settings.ForceC4 && - !Settings.ForceSDD1) - { - if (strncmp ((char *) &ROM [0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0) - { - LoROM = TRUE; - HiROM = FALSE; - Interleaved = FALSE; - } - else - if (strncmp ((char *) &ROM [0x7fc0], "SP MOMOTAROU DENTETSU2", 22) == 0) - { - LoROM = TRUE; - HiROM = FALSE; - Interleaved = FALSE; - } - else - if (CalculatedSize == 0x100000 && - strncmp ((char *) &ROM [0xffc0], "WWF SUPER WRESTLEMANIA", 22) == 0) - { - int cvcount; - - memmove (&ROM[0x100000] , ROM, 0x100000); - for (cvcount = 0; cvcount < 16; cvcount++) - { - memmove (&ROM[0x8000 * cvcount], &ROM[0x10000 * cvcount + 0x100000 + 0x8000], 0x8000); - memmove (&ROM[0x8000 * cvcount + 0x80000], &ROM[0x10000 * cvcount + 0x100000], 0x8000); - } - LoROM = TRUE; - HiROM = FALSE; - ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize); - } - } - - if (!Settings.ForceNotInterleaved && Interleaved) - { - CPU.TriedInterleavedMode2 = TRUE; - S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO, - "ROM image is in interleaved format - converting..."); - - int nblocks = CalculatedSize >> 16; -#if 0 - int step = 64; - - while (nblocks <= step) - step >>= 1; - - nblocks = step; -#endif - uint8 blocks [256]; - - if (Tales) - { - nblocks = 0x60; - for (i = 0; i < 0x40; i += 2) - { - blocks [i + 0] = (i >> 1) + 0x20; - blocks [i + 1] = (i >> 1) + 0x00; - } - for (i = 0; i < 0x80; i += 2) - { - blocks [i + 0x40] = (i >> 1) + 0x80; - blocks [i + 0x41] = (i >> 1) + 0x40; - } - LoROM = FALSE; - HiROM = TRUE; - } - else - if (Settings.ForceInterleaved2) - { - for (i = 0; i < nblocks * 2; i++) - { - blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) | - ((i & 8) >> 2) | ((i & 16) >> 2); - } - } - else - { - bool8_32 t = LoROM; - - LoROM = HiROM; - HiROM = t; - - for (i = 0; i < nblocks; i++) - { - blocks [i * 2] = i + nblocks; - blocks [i * 2 + 1] = i; - } - } - - uint8 *tmp = (uint8 *) malloc (0x8000); - if (tmp) - { - for (i = 0; i < nblocks * 2; i++) - { - for (int j = i; j < nblocks * 2; j++) - { - if (blocks [j] == i) - { - memmove (tmp, &ROM [blocks [j] * 0x8000], 0x8000); - memmove (&ROM [blocks [j] * 0x8000], - &ROM [blocks [i] * 0x8000], 0x8000); - memmove (&ROM [blocks [i] * 0x8000], tmp, 0x8000); - uint8 b = blocks [j]; - blocks [j] = blocks [i]; - blocks [i] = b; - break; - } - } - } - free ((char *) tmp); - } - - hi_score = ScoreHiROM (FALSE); - lo_score = ScoreLoROM (FALSE); - - if ((HiROM && - (lo_score >= hi_score || hi_score < 0)) || - (LoROM && - (hi_score > lo_score || lo_score < 0))) - { - if (retry_count == 0) - { - S9xMessage (S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, - "ROM lied about its type! Trying again."); - Settings.ForceNotInterleaved = TRUE; - Settings.ForceInterleaved = FALSE; - retry_count++; - goto again; - } - } - } - FreeSDD1Data (); - InitROM (Tales); - - S9xLoadCheatFile (S9xGetFilename(".cht")); - S9xInitCheatData (); - S9xApplyCheats (); - - S9xReset (); - - return (TRUE); -} - -void S9xDeinterleaveMode2 () -{ - S9xMessage (S9X_INFO, S9X_ROM_INTERLEAVED_INFO, - "ROM image is in interleaved format - converting..."); - - int nblocks = Memory.CalculatedSize >> 15; - int step = 64; - - while (nblocks <= step) - step >>= 1; - - nblocks = step; - uint8 blocks [256]; - int i; - - for (i = 0; i < nblocks * 2; i++) - { - blocks [i] = (i & ~0x1e) | ((i & 2) << 2) | ((i & 4) << 2) | - ((i & 8) >> 2) | ((i & 16) >> 2); - } - - uint8 *tmp = (uint8 *) malloc (0x8000); - - if (tmp) - { - for (i = 0; i < nblocks * 2; i++) - { - for (int j = i; j < nblocks * 2; j++) - { - if (blocks [j] == i) - { - memmove (tmp, &Memory.ROM [blocks [j] * 0x8000], 0x8000); - memmove (&Memory.ROM [blocks [j] * 0x8000], - &Memory.ROM [blocks [i] * 0x8000], 0x8000); - memmove (&Memory.ROM [blocks [i] * 0x8000], tmp, 0x8000); - uint8 b = blocks [j]; - blocks [j] = blocks [i]; - blocks [i] = b; - break; - } - } - } - free ((char *) tmp); - } - Memory.InitROM (FALSE); - S9xReset (); -} - -void CMemory::InitROM (bool8_32 Interleaved) -{ -#ifndef ZSNES_FX - SuperFX.nRomBanks = CalculatedSize >> 15; -#endif - Settings.MultiPlayer5Master = Settings.MultiPlayer5; - Settings.MouseMaster = Settings.Mouse; - Settings.SuperScopeMaster = Settings.SuperScope; - Settings.DSP1Master = Settings.ForceDSP1; - Settings.SuperFX = FALSE; - Settings.SA1 = FALSE; - Settings.C4 = FALSE; - Settings.SDD1 = FALSE; - Settings.SRTC = FALSE; - - ZeroMemory (BlockIsRAM, MEMMAP_NUM_BLOCKS); - ZeroMemory (BlockIsROM, MEMMAP_NUM_BLOCKS); - - ::SRAM = SRAM; - memset (ROMId, 0, 5); - memset (CompanyId, 0, 3); - - if (Memory.HiROM) - { - Memory.SRAMSize = ROM [0xffd8]; - strncpy (ROMName, (char *) &ROM[0xffc0], ROM_NAME_LEN - 1); - ROMSpeed = ROM [0xffd5]; - ROMType = ROM [0xffd6]; - ROMSize = ROM [0xffd7]; - ROMChecksum = ROM [0xffde] + (ROM [0xffdf] << 8); - ROMComplementChecksum = ROM [0xffdc] + (ROM [0xffdd] << 8); - - memmove (ROMId, &ROM [0xffb2], 4); - memmove (CompanyId, &ROM [0xffb0], 2); - - // Try to auto-detect the DSP1 chip - if (!Settings.ForceNoDSP1 && - (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0) - Settings.DSP1Master = TRUE; - - Settings.SDD1 = Settings.ForceSDD1; - if ((ROMType & 0xf0) == 0x40) - Settings.SDD1 = !Settings.ForceNoSDD1; - - if (Settings.BS) - BSHiROMMap (); - else - if ((ROMSpeed & ~0x10) == 0x25) - TalesROMMap (Interleaved); - else - if ((ROMSpeed & ~0x10) == 0x22 && - strncmp (ROMName, "Super Street Fighter", 20) != 0) - { - AlphaROMMap (); - } - else - HiROMMap (); - } - else - { - Memory.HiROM = FALSE; - Memory.SRAMSize = ROM [0x7fd8]; - ROMSpeed = ROM [0x7fd5]; - ROMType = ROM [0x7fd6]; - ROMSize = ROM [0x7fd7]; - ROMChecksum = ROM [0x7fde] + (ROM [0x7fdf] << 8); - ROMComplementChecksum = ROM [0x7fdc] + (ROM [0x7fdd] << 8); - memmove (ROMId, &ROM [0x7fb2], 4); - memmove (CompanyId, &ROM [0x7fb0], 2); - - strncpy (ROMName, (char *) &ROM[0x7fc0], ROM_NAME_LEN - 1); - Settings.SuperFX = Settings.ForceSuperFX; - - if ((ROMType & 0xf0) == 0x10) - Settings.SuperFX = !Settings.ForceNoSuperFX; - - // Try to auto-detect the DSP1 chip - if (!Settings.ForceNoDSP1 && - (ROMType & 0xf) >= 3 && (ROMType & 0xf0) == 0) - Settings.DSP1Master = TRUE; - - Settings.SDD1 = Settings.ForceSDD1; - if ((ROMType & 0xf0) == 0x40) - Settings.SDD1 = !Settings.ForceNoSDD1; - - if (Settings.SDD1) - S9xLoadSDD1Data (); - - Settings.C4 = Settings.ForceC4; - if ((ROMType & 0xf0) == 0xf0 && - (strncmp (ROMName, "MEGAMAN X", 9) == 0 || - strncmp (ROMName, "ROCKMAN X", 9) == 0)) - { - Settings.C4 = !Settings.ForceNoC4; - } - - if (Settings.SuperFX) - { - //::SRAM = ROM + 1024 * 1024 * 4; - SuperFXROMMap (); - Settings.MultiPlayer5Master = FALSE; - //Settings.MouseMaster = FALSE; - //Settings.SuperScopeMaster = FALSE; - Settings.DSP1Master = FALSE; - Settings.SA1 = FALSE; - Settings.C4 = FALSE; - Settings.SDD1 = FALSE; - } - else - if (Settings.ForceSA1 || - (!Settings.ForceNoSA1 && (ROMSpeed & ~0x10) == 0x23 && - (ROMType & 0xf) > 3 && (ROMType & 0xf0) == 0x30)) - { - Settings.SA1 = TRUE; - Settings.MultiPlayer5Master = FALSE; - //Settings.MouseMaster = FALSE; - //Settings.SuperScopeMaster = FALSE; - Settings.DSP1Master = FALSE; - Settings.C4 = FALSE; - Settings.SDD1 = FALSE; - SA1ROMMap (); - } - else - if ((ROMSpeed & ~0x10) == 0x25) - TalesROMMap (Interleaved); - else - if (strncmp ((char *) &Memory.ROM [0x7fc0], "SOUND NOVEL-TCOOL", 17) == 0 || - strncmp ((char *) &Memory.ROM [0x7fc0], "DERBY STALLION 96", 17) == 0) - { - LoROM24MBSMap (); - Settings.DSP1Master = FALSE; - } - else - if (strncmp ((char *) &Memory.ROM [0x7fc0], "THOROUGHBRED BREEDER3", 21) == 0 || - strncmp ((char *) &Memory.ROM [0x7fc0], "RPG-TCOOL 2", 11) == 0) - { - SRAM512KLoROMMap (); - Settings.DSP1Master = FALSE; - } - else - if (strncmp ((char *) &Memory.ROM [0x7fc0], "DEZAEMON ", 10) == 0) - { - Settings.DSP1Master = FALSE; - SRAM1024KLoROMMap (); - } - else - if (strncmp ((char *) &Memory.ROM [0x7fc0], "ADD-ON BASE CASSETE", 19) == 0) - { - Settings.MultiPlayer5Master = FALSE; - Settings.MouseMaster = FALSE; - Settings.SuperScopeMaster = FALSE; - Settings.DSP1Master = FALSE; - SufamiTurboLoROMMap(); - Memory.SRAMSize = 3; - } - else - if ((ROMSpeed & ~0x10) == 0x22 && - strncmp (ROMName, "Super Street Fighter", 20) != 0) - { - AlphaROMMap (); - } - else - LoROMMap (); - } - - int power2 = 0; - int size = CalculatedSize; - - while (size >>= 1) - power2++; - - size = 1 << power2; - uint32 remainder = CalculatedSize - size; - - uint32 sum1 = 0; - uint32 sum2 = 0; - - int i; - - for (i = 0; i < size; i++) - sum1 += ROM [i]; - - for (i = 0; i < (int) remainder; i++) - sum2 += ROM [size + i]; - - if (remainder) - { - //for Tengai makyou - if (CalculatedSize == 0x500000 && Memory.HiROM && - strncmp ((const char *)&ROM[0xffb0], "18AZ", 4) == 0 && - !memcmp(&ROM[0xffd5], "\x3a\xf9\x0d\x03\x00\x33\x00", 7)) - sum1 += sum2; - else - sum1 += sum2 * (size / remainder); - } - - sum1 &= 0xffff; - - CalculatedChecksum = caCRC32(&ROM[0], CalculatedSize); - if (Settings.ForceNTSC) - Settings.PAL = FALSE; - else - if (Settings.ForcePAL) - Settings.PAL = TRUE; - else - if (Memory.HiROM) - // Country code - Settings.PAL = ROM [0xffd9] >= 2; - else - Settings.PAL = ROM [0x7fd9] >= 2; - - if (Settings.PAL) - { - Settings.FrameTime = Settings.FrameTimePAL; - Memory.ROMFramesPerSecond = 50; - } - else - { - Settings.FrameTime = Settings.FrameTimeNTSC; - Memory.ROMFramesPerSecond = 60; - } - - ROMName[ROM_NAME_LEN - 1] = 0; - if (strlen (ROMName)) - { - char *p = ROMName + strlen (ROMName) - 1; - - while (p > ROMName && *(p - 1) == ' ') - p--; - *p = 0; - } - - if (Settings.SuperFX) - { - CPU.Memory_SRAMMask = 0xffff; - Memory.SRAMSize = 16; - } - else - { - CPU.Memory_SRAMMask = Memory.SRAMSize ? - ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; - } - - IAPU.OneCycle = ONE_APU_CYCLE; - Settings.Shutdown = Settings.ShutdownMaster; - - SetDSP = &DSP1SetByte; - GetDSP = &DSP1GetByte; - - ApplyROMFixes (); - sprintf (ROMName, "%s", Safe (ROMName)); - sprintf (ROMId, "%s", Safe (ROMId)); - sprintf (CompanyId, "%s", Safe (CompanyId)); - - sprintf (String, "\"%s\" [%s] %s, %s, Type: %s, Mode: %s, TV: %s, S-RAM: %s, ROMId: %s Company: %2.2s", - ROMName, - (ROMChecksum + ROMComplementChecksum != 0xffff || - ROMChecksum != sum1) ? "bad checksum" : "checksum ok", - MapType (), - Size (), - KartContents (), - MapMode (), - TVStandard (), - StaticRAMSize (), - ROMId, - CompanyId); - - S9xMessage (S9X_INFO, S9X_ROM_INFO, String); -} - -bool8_32 CMemory::LoadSRAM (const char *filename) -{ - int size = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; - - memset (SRAM, SNESGameFixes.SRAMInitialValue, 0x20000); - - if (size > 0x20000) - size = 0x20000; - - if (size) - { - FILE *file; - if ((file = fopen(filename, "rb"))) - { - int len = fread ((char*) ::SRAM, 1, 0x20000, file); - fclose (file); - if (len - size == 512) - { - // S-RAM file has a header - remove it - memmove (::SRAM, ::SRAM + 512, size); - } - if (len == size + SRTC_SRAM_PAD) - { - S9xSRTCPostLoadState (); - S9xResetSRTC (); - rtc.index = -1; - rtc.mode = MODE_READ; - } - else - S9xHardResetSRTC (); - - return (TRUE); - } - S9xHardResetSRTC (); - return (FALSE); - } - - return (TRUE); -} - -bool8_32 CMemory::SaveSRAM (const char *filename) -{ - int size = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; - if (Settings.SRTC) - { - size += SRTC_SRAM_PAD; - S9xSRTCPreSaveState (); - } - - - if (size > 0x20000) - size = 0x20000; - - if (size && *Memory.ROMFilename) - { - FILE *file; - if ((file = fopen (filename, "wb"))) - { - fwrite ((char *) ::SRAM, size, 1, file); - fclose (file); - //sync(); -#if defined(__linux) - //chown (filename, getuid (), getgid ()); -#endif - return (TRUE); - } - } - return (FALSE); -} - -void CMemory::FixROMSpeed () -{ - int c; - - for (c = 0x800; c < 0x1000; c++) - { - if (BlockIsROM [c]) - MemorySpeed [c] = (uint8) CPU.FastROMSpeed; - } -} - -void CMemory::WriteProtectROM () -{ - memmove ((void *) WriteMap, (void *) Map, sizeof (Map)); - for (int c = 0; c < 0x1000; c++) - { - if (BlockIsROM [c]) - WriteMap [c] = (uint8 *) MAP_NONE; - } -} - -void CMemory::MapRAM () -{ - int c; - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - // Banks 70->77, S-RAM - for (c = 0; c < 0x80; c++) - { - Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0x700] = FALSE; - } -} - -void CMemory::MapExtraRAM () -{ - int c; - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - // Banks 70->73, S-RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x700] = ::SRAM; - Map [c + 0x710] = ::SRAM + 0x8000; - Map [c + 0x720] = ::SRAM + 0x10000; - Map [c + 0x730] = ::SRAM + 0x18000; - - BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0x700] = FALSE; - BlockIsRAM [c + 0x710] = TRUE; - BlockIsROM [c + 0x710] = FALSE; - BlockIsRAM [c + 0x720] = TRUE; - BlockIsROM [c + 0x720] = FALSE; - BlockIsRAM [c + 0x730] = TRUE; - BlockIsROM [c + 0x730] = FALSE; - } -} - -void CMemory::LoROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - if (Settings.DSP1Master) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - } - else - if (Settings.C4) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_C4; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_C4; - } - else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) bytes0x2000 - 0x6000; - Map [c + 7] = Map [c + 0x807] = (uint8 *) bytes0x2000 - 0x6000; - } - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [(c << 11) % CalculatedSize] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - if (Settings.DSP1Master) - { - // Banks 30->3f and b0->bf - for (c = 0x300; c < 0x400; c += 16) - { - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP; - BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE; - } - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) % CalculatedSize]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [((c << 11) + 0x200000) % CalculatedSize - 0x8000]; - - for (i = c; i < c + 16; i++) - { - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - if (Settings.DSP1Master) - { - for (c = 0; c < 0x100; c++) - { - Map [c + 0xe00] = (uint8 *) MAP_DSP; - MemorySpeed [c + 0xe00] = SLOW_ONE_CYCLE; - BlockIsROM [c + 0xe00] = FALSE; - } - } - MapRAM (); - WriteProtectROM (); -} - -void CMemory::HiROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - if (Settings.DSP1Master) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - } - else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - } - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - // Banks 30->3f and b0->bf, address ranges 6000->7fff is S-RAM. - for (c = 0; c < 16; c++) - { - Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - BlockIsRAM [0x306 + (c << 4)] = TRUE; - BlockIsRAM [0x307 + (c << 4)] = TRUE; - BlockIsRAM [0xb06 + (c << 4)] = TRUE; - BlockIsRAM [0xb07 + (c << 4)] = TRUE; - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - MapRAM (); - WriteProtectROM (); -} - -void CMemory::TalesROMMap (bool8_32 Interleaved) -{ - int c; - int i; - - uint32 OFFSET0 = 0x400000; - uint32 OFFSET1 = 0x400000; - uint32 OFFSET2 = 0x000000; - - if (Interleaved) - { - OFFSET0 = 0x000000; - OFFSET1 = 0x000000; - OFFSET2 = 0x200000; - } - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = &ROM [((c << 12) + OFFSET0) % CalculatedSize]; - Map [i + 0x800] = &ROM [((c << 12) + OFFSET0) % CalculatedSize]; - BlockIsROM [i] = TRUE; - BlockIsROM [i + 0x800] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - // Banks 30->3f and b0->bf, address ranges 6000->7ffff is S-RAM. - for (c = 0; c < 16; c++) - { - Map [0x306 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0x307 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb06 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - Map [0xb07 + (c << 4)] = (uint8 *) MAP_HIROM_SRAM; - BlockIsRAM [0x306 + (c << 4)] = TRUE; - BlockIsRAM [0x307 + (c << 4)] = TRUE; - BlockIsRAM [0xb06 + (c << 4)] = TRUE; - BlockIsRAM [0xb07 + (c << 4)] = TRUE; - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - { - Map [i + 0x400] = &ROM [((c << 12) + OFFSET1) % CalculatedSize]; - Map [i + 0x408] = &ROM [((c << 12) + OFFSET1) % CalculatedSize]; - Map [i + 0xc00] = &ROM [((c << 12) + OFFSET2) % CalculatedSize]; - Map [i + 0xc08] = &ROM [((c << 12) + OFFSET2) % CalculatedSize]; - BlockIsROM [i + 0x400] = TRUE; - BlockIsROM [i + 0x408] = TRUE; - BlockIsROM [i + 0xc00] = TRUE; - BlockIsROM [i + 0xc08] = TRUE; - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; - MemorySpeed [i + 0x408] = MemorySpeed [i + 0xc08] = SLOW_ONE_CYCLE; - } - } - MapRAM (); - WriteProtectROM (); -} - -void CMemory::AlphaROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - // Banks 40->7f and c0->ff - - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = &ROM [(c << 12) % CalculatedSize]; - Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - MapRAM (); - WriteProtectROM (); -} - -void CMemory::SuperFXROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - - for (i = c; i < c + 8; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - // Banks 70->71, S-RAM - for (c = 0; c < 32; c++) - { - Map [c + 0x700] = ::SRAM + (((c >> 4) & 1) << 16); - BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0x700] = FALSE; - } - - // Banks 00->3f and 80->bf address ranges 6000->7fff is RAM. - for (c = 0; c < 0x40; c++) - { - Map [0x006 + (c << 4)] = (uint8 *) ::SRAM - 0x6000; - Map [0x007 + (c << 4)] = (uint8 *) ::SRAM - 0x6000; - Map [0x806 + (c << 4)] = (uint8 *) ::SRAM - 0x6000; - Map [0x807 + (c << 4)] = (uint8 *) ::SRAM - 0x6000; - BlockIsRAM [0x006 + (c << 4)] = TRUE; - BlockIsRAM [0x007 + (c << 4)] = TRUE; - BlockIsRAM [0x806 + (c << 4)] = TRUE; - BlockIsRAM [0x807 + (c << 4)] = TRUE; - } - // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K - // block is repeated twice in each 64K block. - for (c = 0; c < 64; c++) - { - memmove (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); - memmove (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000); - } - - WriteProtectROM (); -} - -void CMemory::SA1ROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) &Memory.FillRAM [0x3000] - 0x3000; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_BWRAM; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_BWRAM; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - // Banks 40->7f - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - Map [i + 0x400] = (uint8 *) &SRAM [(c << 12) & 0x1ffff]; - - for (i = c; i < c + 16; i++) - { - MemorySpeed [i + 0x400] = SLOW_ONE_CYCLE; - BlockIsROM [i + 0x400] = FALSE; - } - } - - // c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; - BlockIsROM [i + 0xc00] = TRUE; - } - } - - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - WriteProtectROM (); - -#ifdef USE_SA1 - // Now copy the map and correct it for the SA1 CPU. - memmove ((void *) SA1_WriteMap, (void *) WriteMap, sizeof (WriteMap)); - memmove ((void *) SA1_Map, (void *) Map, sizeof (Map)); - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - SA1_Map [c + 0] = SA1_Map [c + 0x800] = &Memory.FillRAM [0x3000]; - SA1_Map [c + 1] = SA1_Map [c + 0x801] = (uint8 *) MAP_NONE; - SA1_WriteMap [c + 0] = SA1_WriteMap [c + 0x800] = &Memory.FillRAM [0x3000]; - SA1_WriteMap [c + 1] = SA1_WriteMap [c + 0x801] = (uint8 *) MAP_NONE; - } - - // Banks 60->6f - for (c = 0; c < 0x100; c++) - SA1_Map [c + 0x600] = SA1_WriteMap [c + 0x600] = (uint8 *) MAP_BWRAM_BITMAP; -#endif // USE_SA1 - - BWRAM = SRAM; -} - -void CMemory::LoROM24MBSMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x200; c += 16) - { - Map [c + 0x800] = RAM; - Map [c + 0x801] = RAM; - BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i + 0x800] = &ROM [c << 11] - 0x8000 + 0x200000; - BlockIsROM [i + 0x800] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; - - for (i = c; i < c + 16; i++) - { - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - MapExtraRAM (); - WriteProtectROM (); -} - -void CMemory::SufamiTurboLoROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - if (Settings.DSP1Master) - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_DSP; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_DSP; - } - else - { - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - } - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - if (Settings.DSP1Master) - { - // Banks 30->3f and b0->bf - for (c = 0x300; c < 0x400; c += 16) - { - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = (uint8 *) MAP_DSP; - BlockIsROM [i] = BlockIsROM [i + 0x800] = FALSE; - } - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; - - for (i = c; i < c + 16; i++) - { - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - if (Settings.DSP1Master) - { - for (c = 0; c < 0x100; c++) - { - Map [c + 0xe00] = (uint8 *) MAP_DSP; - MemorySpeed [c + 0xe00] = SLOW_ONE_CYCLE; - BlockIsROM [c + 0xe00] = FALSE; - } - } - - // Banks 7e->7f, RAM - for (c = 0; c < 16; c++) - { - Map [c + 0x7e0] = RAM; - Map [c + 0x7f0] = RAM + 0x10000; - BlockIsRAM [c + 0x7e0] = TRUE; - BlockIsRAM [c + 0x7f0] = TRUE; - BlockIsROM [c + 0x7e0] = FALSE; - BlockIsROM [c + 0x7f0] = FALSE; - } - - // Banks 60->67, S-RAM - for (c = 0; c < 0x80; c++) - { - Map [c + 0x600] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c + 0x600] = TRUE; - BlockIsROM [c + 0x600] = FALSE; - } - - WriteProtectROM (); -} - -void CMemory::SRAM512KLoROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 8; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000]; - - for (i = c + 8; i < c + 16; i++) - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 11) + 0x200000 - 0x8000]; - - for (i = c; i < c + 16; i++) - { - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - - - } - } - - MapExtraRAM (); - WriteProtectROM (); -} - -void CMemory::SRAM1024KLoROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = Map [c + 0x400] = Map [c + 0xc00] = RAM; - Map [c + 1] = Map [c + 0x801] = Map [c + 0x401] = Map [c + 0xc01] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = BlockIsRAM [c + 0x400] = BlockIsRAM [c + 0xc00] = TRUE; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = BlockIsRAM [c + 0x401] = BlockIsRAM [c + 0xc01] = TRUE; - - Map [c + 2] = Map [c + 0x802] = Map [c + 0x402] = Map [c + 0xc02] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = Map [c + 0x403] = Map [c + 0xc03] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = Map [c + 0x404] = Map [c + 0xc04] = (uint8 *) MAP_CPU; - Map [c + 5] = Map [c + 0x805] = Map [c + 0x405] = Map [c + 0xc05] = (uint8 *) MAP_CPU; - Map [c + 6] = Map [c + 0x806] = Map [c + 0x406] = Map [c + 0xc06] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = Map [c + 0x407] = Map [c + 0xc07] = (uint8 *) MAP_NONE; - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = Map [i + 0x400] = Map [i + 0xc00] = &ROM [c << 11] - 0x8000; - BlockIsROM [i] = BlockIsROM [i + 0x800] = BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = MemorySpeed [i + 0x800] = - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - MapExtraRAM (); - WriteProtectROM (); -} - -void CMemory::BSHiROMMap () -{ - int c; - int i; - - // Banks 00->3f and 80->bf - for (c = 0; c < 0x400; c += 16) - { - Map [c + 0] = Map [c + 0x800] = RAM; - BlockIsRAM [c + 0] = BlockIsRAM [c + 0x800] = TRUE; - Map [c + 1] = Map [c + 0x801] = RAM; - BlockIsRAM [c + 1] = BlockIsRAM [c + 0x801] = TRUE; - - Map [c + 2] = Map [c + 0x802] = (uint8 *) MAP_PPU; - Map [c + 3] = Map [c + 0x803] = (uint8 *) MAP_PPU; - Map [c + 4] = Map [c + 0x804] = (uint8 *) MAP_CPU; - // XXX: How large is SRAM?? - Map [c + 5] = Map [c + 0x805] = (uint8 *) SRAM; - BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE; - Map [c + 6] = Map [c + 0x806] = (uint8 *) MAP_NONE; - Map [c + 7] = Map [c + 0x807] = (uint8 *) MAP_NONE; - - for (i = c + 8; i < c + 16; i++) - { - Map [i] = Map [i + 0x800] = &ROM [(c << 12) % CalculatedSize]; - BlockIsROM [i] = BlockIsROM [i + 0x800] = TRUE; - } - - for (i = c; i < c + 16; i++) - { - int ppu = i & 15; - - MemorySpeed [i] = - MemorySpeed [i + 0x800] = ppu >= 2 && ppu <= 3 ? ONE_CYCLE : SLOW_ONE_CYCLE; - } - } - - // Banks 60->7d offset 0000->7fff & 60->7f offset 8000->ffff PSRAM - // XXX: How large is PSRAM? - for (c = 0x600; c < 0x7e0; c += 16) - { - for (i = c; i < c + 8; i++) - { - Map [i] = &ROM [0x400000 + (c << 11)]; - BlockIsRAM [i] = TRUE; - } - for (i = c + 8; i < c + 16; i++) - { - Map [i] = &ROM [0x400000 + (c << 11) - 0x8000]; - BlockIsRAM [i] = TRUE; - } - } - - // Banks 40->7f and c0->ff - for (c = 0; c < 0x400; c += 16) - { - for (i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM [(c << 12) % CalculatedSize]; - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = SLOW_ONE_CYCLE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = TRUE; - } - } - - MapRAM (); - WriteProtectROM (); -} - -const char *CMemory::TVStandard () -{ - return (Settings.PAL ? "PAL" : "NTSC"); -} - -const char *CMemory::Speed () -{ - return (ROMSpeed & 0x10 ? "120ns" : "200ns"); -} - -const char *CMemory::MapType () -{ - return (HiROM ? "HiROM" : "LoROM"); -} - -const char *CMemory::StaticRAMSize () -{ - static char tmp [20]; - - if (Memory.SRAMSize > 16) - return ("Corrupt"); - sprintf (tmp, "%dKb", (CPU.Memory_SRAMMask + 1) / 1024); - return (tmp); -} - -const char *CMemory::Size () -{ - static char tmp [20]; - - if (ROMSize < 7 || ROMSize - 7 > 23) - return ("Corrupt"); - sprintf (tmp, "%dMbits", 1 << (ROMSize - 7)); - return (tmp); -} - -const char *CMemory::KartContents () -{ - static char tmp [30]; - static const char *CoPro [16] = { - "DSP1", "SuperFX", "OBC1", "SA-1", "S-DD1", "S-RTC", "CoPro#6", - "CoPro#7", "CoPro#8", "CoPro#9", "CoPro#10", "CoPro#11", "CoPro#12", - "CoPro#13", "CoPro#14", "CoPro-Custom" - }; - static const char *Contents [3] = { - "ROM", "ROM+RAM", "ROM+RAM+BAT" - }; - if (ROMType == 0) - return ("ROM only"); - - sprintf (tmp, "%s", Contents [(ROMType & 0xf) % 3]); - - if ((ROMType & 0xf) >= 3) - sprintf (tmp, "%s+%s", tmp, CoPro [(ROMType & 0xf0) >> 4]); - - return (tmp); -} - -const char *CMemory::MapMode () -{ - static char tmp [4]; - sprintf (tmp, "%02x", ROMSpeed & ~0x10); - return (tmp); -} - -const char *CMemory::ROMID () -{ - return (ROMId); -} - -void CMemory::ApplyROMFixes () -{ - ROMAPUEnabled = 0; - DSP1.version = 0; - //Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; - if (strncmp(ROMName, "DUNGEON MASTER", 14) == 0) - { - DSP1.version = 1; - SetDSP=&DSP2SetByte; - GetDSP=&DSP2GetByte; - } - - //OAM hacks because we don't fully understand the - //behavior of the SNES. - - //possibly an RTO issue? - //part of Fred's club is drawn over his face. - if(strncmp(ROMName, "THE FLINTSTONES TTOSM", 21)==0) - { - SNESGameFixes.Flintstones=true; - } - - if(strncmp(ROMName, "SUPER MARIO KART", 16)==0 - || strncmp(ROMName, "F-ZERO", 6)==0) - { - SNESGameFixes.Mode7Hack=true; - } - - //Totally wacky display... - //seems to need a disproven behavior, so - //we're definitely overlooking some other bug? - if(strncmp(ROMName, "UNIRACERS", 9)==0) - SNESGameFixes.Uniracers=true; - - // Enable S-RTC (Real Time Clock) emulation for Dai Kaijyu Monogatari 2 - Settings.SRTC = ((ROMType & 0xf0) >> 4) == 5; - - Settings.StrikeGunnerOffsetHack = strcmp (ROMName, "STRIKE GUNNER") == 0 ? 7 : 0; - - CPU.NMITriggerPoint = 4; - if (strcmp (ROMName, "CACOMA KNIGHT") == 0) - CPU.NMITriggerPoint = 25; - - // These games complain if the multi-player adaptor is 'connected' - if (strcmp (ROMName, "TETRIS&Dr.MARIO") == 0 || - strcmp (ROMName, "JIGSAW PARTY") == 0 || - strcmp (ROMName, "SUPER PICROSS") == 0 || - strcmp (ROMName, "KIRBY NO KIRA KIZZU") == 0 || - strcmp (ROMName, "BLOCK") == 0 || - strncmp (ROMName, "SUPER BOMBLISS", 14) == 0 || - strcmp (ROMId, "ABOJ") == 0) - { - Settings.MultiPlayer5Master = FALSE; - Settings.MouseMaster = FALSE; - Settings.SuperScopeMaster = FALSE; - } - - // Games which spool sound samples between the SNES and sound CPU using - // H-DMA as the sample is playing. - if (strcmp (ROMName, "EARTHWORM JIM 2") == 0 || - strcmp (ROMName, "PRIMAL RAGE") == 0 || - strcmp (ROMName, "CLAY FIGHTER") == 0 || - strcmp (ROMName, "ClayFighter 2") == 0 || - strncasecmp (ROMName, "MADDEN", 6) == 0 || - strncmp (ROMName, "NHL", 3) == 0 || - strcmp (ROMName, "WEAPONLORD") == 0) - { - Settings.Shutdown = FALSE; - } - - - // Stunt Racer FX - if (strcmp (ROMId, "CQ ") == 0 || - // Illusion of Gaia - strncmp (ROMId, "JG", 2) == 0 || - strcmp (ROMName, "GAIA GENSOUKI 1 JPN") == 0) - { - IAPU.OneCycle = 13; - ROMAPUEnabled |= 2; - CPU.APU_APUExecuting |= 2; - } - - // RENDERING RANGER R2 - if (strcmp (ROMId, "AVCJ") == 0 || - // Star Ocean - strncmp (ROMId, "ARF", 3) == 0 || - // Tales of Phantasia - strncmp (ROMId, "ATV", 3) == 0 || - // Act Raiser 1 & 2 - strncasecmp (ROMName, "ACTRAISER", 9) == 0 || - strncasecmp (ROMName, "ActRaiser", 9) == 0 || // I kown both sentences are supposed to be equivalent each other but they aren't on my compiler - // Soulblazer - strcmp (ROMName, "SOULBLAZER - 1 USA") == 0 || - strcmp (ROMName, "SOULBLADER - 1") == 0 || - strncmp (ROMName, "SOULBLAZER 1",12) == 0 || - // Terranigma - strncmp (ROMId, "AQT", 3) == 0 || - // Robotrek - strncmp (ROMId, "E9 ", 3) == 0 || - strcmp (ROMName, "SLAP STICK 1 JPN") == 0 || - // ZENNIHON PURORESU2 - strncmp (ROMId, "APR", 3) == 0 || - // Bomberman 4 - strncmp (ROMId, "A4B", 3) == 0 || - // UFO KAMEN YAKISOBAN - strncmp (ROMId, "Y7 ", 3) == 0 || - strncmp (ROMId, "Y9 ", 3) == 0 || - // Panic Bomber World - strncmp (ROMId, "APB", 3) == 0 || - ((strncmp (ROMName, "Parlor", 6) == 0 || - strcmp (ROMName, "HEIWA PARLOR!MINI8") == 0 || - strncmp (ROMName, "SANKYO Fever! フィーバー!", 21) == 0) && - strcmp (CompanyId, "A0") == 0) || - strcmp (ROMName, "DARK KINGDOM") == 0 || - strcmp (ROMName, "ZAN3 SFC") == 0 || - strcmp (ROMName, "HIOUDEN") == 0 || - strcmp (ROMName, "テンシノウタ") == 0 || - strcmp (ROMName, "FORTUNE QUEST") == 0 || - strcmp (ROMName, "FISHING TO BASSING") == 0 || - strncmp (ROMName, "TOKYODOME '95BATTLE 7", 21) == 0 || - strcmp (ROMName, "OHMONO BLACKBASS") == 0) - { - IAPU.OneCycle = 15; - // notaz: strangely enough, these games work properly with my hack enabled - if (strcmp (ROMId, "AVCJ") != 0) - ROMAPUEnabled |= 2; - CPU.APU_APUExecuting |= 2; - } - - if (strcmp (ROMName, "BATMAN--REVENGE JOKER") == 0) - { - Memory.HiROM = FALSE; - Memory.LoROM = TRUE; - LoROMMap (); - } - Settings.StarfoxHack = strcmp (ROMName, "STAR FOX") == 0 || - strcmp (ROMName, "STAR WING") == 0; - Settings.WinterGold = strcmp (ROMName, "FX SKIING NINTENDO 96") == 0 || - strcmp (ROMName, "DIRT RACER") == 0 || - strcmp (ROMName, "Stunt Race FX") == 0 || - Settings.StarfoxHack; - Settings.ChuckRock = strcmp (ROMName, "CHUCK ROCK") == 0; - Settings.Dezaemon = strcmp (ROMName, "DEZAEMON") == 0; - - if (strcmp (ROMName, "RADICAL DREAMERS") == 0 || - strcmp (ROMName, "TREASURE CONFLIX") == 0) - { - int c; - - for (c = 0; c < 0x80; c++) - { - Map [c + 0x700] = ROM + 0x200000 + 0x1000 * (c & 0xf0); - BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0x700] = FALSE; - } - for (c = 0; c < 0x400; c += 16) - { - Map [c + 5] = Map [c + 0x805] = ROM + 0x300000; - BlockIsRAM [c + 5] = BlockIsRAM [c + 0x805] = TRUE; - } - WriteProtectROM (); - } - - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * - Settings.CyclesPercentage) / 100; - - // A Couple of HDMA related hacks - Lantus - if ((strcmp(ROMName, "SFX SUPERBUTOUDEN2")==0) || - (strcmp(ROMName, "ALIEN vs. PREDATOR")==0) || - (strcmp(ROMName, "STONE PROTECTORS")==0) || - (strcmp(ROMName, "SUPER BATTLETANK 2")==0)) - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 130) / 100; - - if (strcmp (ROMId, "ASRJ") == 0 && Settings.CyclesPercentage == 100) - // Street Racer - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 95) / 100; - - // Power Rangers Fight - if (strncmp (ROMId, "A3R", 3) == 0 || - // Clock Tower - strncmp (ROMId, "AJE", 3) == 0) - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 103) / 100; - - if (strcmp (ROMId, "AWVP") == 0 || strcmp (ROMId, "AWVE") == 0 || - strcmp (ROMId, "AWVJ") == 0) - { - // Wrestlemania Arcade -#if 0 - if (Settings.CyclesPercentage == 100) - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 140) / 100; // Fixes sound -#endif - Settings.WrestlemaniaArcade = TRUE; - } - // Theme Park - disable offset-per-tile mode. - if (strcmp (ROMId, "ATQP") == 0) - Settings.WrestlemaniaArcade = TRUE; - - if (strncmp (ROMId, "A3M", 3) == 0 && Settings.CyclesPercentage == 100) - // Mortal Kombat 3. Fixes cut off speech sample - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100; - - if (strcmp (ROMName, "\x0bd\x0da\x0b2\x0d4\x0b0\x0bd\x0de") == 0 && - Settings.CyclesPercentage == 100) - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 101) / 100; - - if (strcmp (ROMName, "WILD TRAX") == 0 || - strcmp (ROMName, "YOSSY'S ISLAND") == 0 || - strcmp (ROMName, "YOSHI'S ISLAND") == 0) - CPU.TriedInterleavedMode2 = TRUE; - - // Start Trek: Deep Sleep 9 - if (strncmp (ROMId, "A9D", 3) == 0 && Settings.CyclesPercentage == 100) - Settings.H_Max = (SNES_CYCLES_PER_SCANLINE * 110) / 100; - - Settings.APURAMInitialValue = 0xff; - - if (strcmp (ROMName, "キュウヤク・メガミテンセイ") == 0 || - strcmp (ROMName, "KENTOUOU WORLDCHAMPIO") == 0 || - strcmp (ROMName, "TKO SUPERCHAMPIONSHIP") == 0 || - strcmp (ROMName, "TKO SUPER CHAMPIONSHI") == 0 || - strcmp (ROMName, "IHATOVO STORY") == 0 || - strcmp (ROMName, "WANDERERS FROM YS") == 0 || - strcmp (ROMName, "SUPER GENTYOUHISHI") == 0 || - // Panic Bomber World - strncmp (ROMId, "APB", 3) == 0) - { - Settings.APURAMInitialValue = 0; - } - - Settings.DaffyDuck = strcmp (ROMName, "DAFFY DUCK: MARV MISS") == 0; - Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX; - -#ifdef USE_SA1 - SA1.WaitAddress = NULL; - SA1.WaitByteAddress1 = NULL; - SA1.WaitByteAddress2 = NULL; - - /* Bass Fishing */ - if (strcmp (ROMId, "ZBPJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x0093f1 >> MEMMAP_SHIFT] + 0x93f1; - SA1.WaitByteAddress1 = FillRAM + 0x304a; - } - /* DAISENRYAKU EXPERTWW2 */ - if (strcmp (ROMId, "AEVJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x0ed18d >> MEMMAP_SHIFT] + 0xd18d; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - /* debjk2 */ - if (strcmp (ROMId, "A2DJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x008b62 >> MEMMAP_SHIFT] + 0x8b62; - } - /* Dragon Ballz HD */ - if (strcmp (ROMId, "AZIJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x008083 >> MEMMAP_SHIFT] + 0x8083; - SA1.WaitByteAddress1 = FillRAM + 0x3020; - } - /* SFC SDGUNDAMGNEXT */ - if (strcmp (ROMId, "ZX3J") == 0) - { - SA1.WaitAddress = SA1_Map [0x0087f2 >> MEMMAP_SHIFT] + 0x87f2; - SA1.WaitByteAddress1 = FillRAM + 0x30c4; - } - /* ShougiNoHanamichi */ - if (strcmp (ROMId, "AARJ") == 0) - { - SA1.WaitAddress = SA1_Map [0xc1f85a >> MEMMAP_SHIFT] + 0xf85a; - SA1.WaitByteAddress1 = SRAM + 0x0c64; - SA1.WaitByteAddress2 = SRAM + 0x0c66; - } - /* KATO HIFUMI9DAN SYOGI */ - if (strcmp (ROMId, "A23J") == 0) - { - SA1.WaitAddress = SA1_Map [0xc25037 >> MEMMAP_SHIFT] + 0x5037; - SA1.WaitByteAddress1 = SRAM + 0x0c06; - SA1.WaitByteAddress2 = SRAM + 0x0c08; - } - /* idaten */ - if (strcmp (ROMId, "AIIJ") == 0) - { - SA1.WaitAddress = SA1_Map [0xc100be >> MEMMAP_SHIFT] + 0x00be; - SA1.WaitByteAddress1 = SRAM + 0x1002; - SA1.WaitByteAddress2 = SRAM + 0x1004; - } - /* igotais */ - if (strcmp (ROMId, "AITJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x0080b7 >> MEMMAP_SHIFT] + 0x80b7; - } - /* J96 DREAM STADIUM */ - if (strcmp (ROMId, "AJ6J") == 0) - { - SA1.WaitAddress = SA1_Map [0xc0f74a >> MEMMAP_SHIFT] + 0xf74a; - } - /* JumpinDerby */ - if (strcmp (ROMId, "AJUJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x00d926 >> MEMMAP_SHIFT] + 0xd926; - } - /* JKAKINOKI SHOUGI */ - if (strcmp (ROMId, "AKAJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x00f070 >> MEMMAP_SHIFT] + 0xf070; - } - /* HOSHI NO KIRBY 3 & KIRBY'S DREAM LAND 3 JAP & US */ - if (strcmp (ROMId, "AFJJ") == 0 || strcmp (ROMId, "AFJE") == 0) - { - SA1.WaitAddress = SA1_Map [0x0082d4 >> MEMMAP_SHIFT] + 0x82d4; - SA1.WaitByteAddress1 = SRAM + 0x72a4; - } - /* KIRBY SUPER DELUXE JAP */ - if (strcmp (ROMId, "AKFJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x008c93 >> MEMMAP_SHIFT] + 0x8c93; - SA1.WaitByteAddress1 = FillRAM + 0x300a; - SA1.WaitByteAddress2 = FillRAM + 0x300e; - } - /* KIRBY SUPER DELUXE US */ - if (strcmp (ROMId, "AKFE") == 0) - { - SA1.WaitAddress = SA1_Map [0x008cb8 >> MEMMAP_SHIFT] + 0x8cb8; - SA1.WaitByteAddress1 = FillRAM + 0x300a; - SA1.WaitByteAddress2 = FillRAM + 0x300e; - } - /* SUPER MARIO RPG JAP & US */ - if (strcmp (ROMId, "ARWJ") == 0 || strcmp (ROMId, "ARWE") == 0) - { - SA1.WaitAddress = SA1_Map [0xc0816f >> MEMMAP_SHIFT] + 0x816f; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - /* marvelous.zip */ - if (strcmp (ROMId, "AVRJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x0085f2 >> MEMMAP_SHIFT] + 0x85f2; - SA1.WaitByteAddress1 = FillRAM + 0x3024; - } - /* AUGUSTA3 MASTERS NEW */ - if (strcmp (ROMId, "AO3J") == 0) - { - SA1.WaitAddress = SA1_Map [0x00dddb >> MEMMAP_SHIFT] + 0xdddb; - SA1.WaitByteAddress1 = FillRAM + 0x37b4; - } - /* OSHABERI PARODIUS */ - if (strcmp (ROMId, "AJOJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x8084e5 >> MEMMAP_SHIFT] + 0x84e5; - } - /* PANIC BOMBER WORLD */ - if (strcmp (ROMId, "APBJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x00857a >> MEMMAP_SHIFT] + 0x857a; - } - /* PEBBLE BEACH NEW */ - if (strcmp (ROMId, "AONJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x00df33 >> MEMMAP_SHIFT] + 0xdf33; - SA1.WaitByteAddress1 = FillRAM + 0x37b4; - } - /* PGA EUROPEAN TOUR */ - if (strcmp (ROMId, "AEPE") == 0) - { - SA1.WaitAddress = SA1_Map [0x003700 >> MEMMAP_SHIFT] + 0x3700; - SA1.WaitByteAddress1 = FillRAM + 0x3102; - } - /* PGA TOUR 96 */ - if (strcmp (ROMId, "A3GE") == 0) - { - SA1.WaitAddress = SA1_Map [0x003700 >> MEMMAP_SHIFT] + 0x3700; - SA1.WaitByteAddress1 = FillRAM + 0x3102; - } - /* POWER RANGERS 4 */ - if (strcmp (ROMId, "A4RE") == 0) - { - SA1.WaitAddress = SA1_Map [0x009899 >> MEMMAP_SHIFT] + 0x9899; - SA1.WaitByteAddress1 = FillRAM + 0x3000; - } - /* PACHISURO PALUSUPE */ - if (strcmp (ROMId, "AGFJ") == 0) - { - // Never seems to turn on the SA-1! - } - /* SD F1 GRAND PRIX */ - if (strcmp (ROMId, "AGFJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x0181bc >> MEMMAP_SHIFT] + 0x81bc; - } - /* SHOUGI MARJONG */ - if (strcmp (ROMId, "ASYJ") == 0) - { - SA1.WaitAddress = SA1_Map [0x00f2cc >> MEMMAP_SHIFT] + 0xf2cc; - SA1.WaitByteAddress1 = SRAM + 0x7ffe; - SA1.WaitByteAddress2 = SRAM + 0x7ffc; - } - /* shogisai2 */ - if (strcmp (ROMId, "AX2J") == 0) - { - SA1.WaitAddress = SA1_Map [0x00d675 >> MEMMAP_SHIFT] + 0xd675; - } - - /* SHINING SCORPION */ - if (strcmp (ROMId, "A4WJ") == 0) - { - SA1.WaitAddress = SA1_Map [0xc048be >> MEMMAP_SHIFT] + 0x48be; - } - /* SHIN SHOUGI CLUB */ - if (strcmp (ROMId, "AHJJ") == 0) - { - SA1.WaitAddress = SA1_Map [0xc1002a >> MEMMAP_SHIFT] + 0x002a; - SA1.WaitByteAddress1 = SRAM + 0x0806; - SA1.WaitByteAddress2 = SRAM + 0x0808; - } -#endif // USE_SA1 - - // Additional game fixes by sanmaiwashi ... - if (strcmp (ROMName, "SFX ナイトガンダムモノガタリ 1") == 0) - { - bytes0x2000 [0xb18] = 0x4c; - bytes0x2000 [0xb19] = 0x4b; - bytes0x2000 [0xb1a] = 0xea; - } - - if (strcmp (ROMName, "GOGO ACKMAN3") == 0 || - strcmp (ROMName, "HOME ALONE") == 0) - { - // Banks 00->3f and 80->bf - for (int c = 0; c < 0x400; c += 16) - { - Map [c + 6] = Map [c + 0x806] = SRAM; - Map [c + 7] = Map [c + 0x807] = SRAM; - BlockIsROM [c + 6] = BlockIsROM [c + 0x806] = FALSE; - BlockIsROM [c + 7] = BlockIsROM [c + 0x807] = FALSE; - BlockIsRAM [c + 6] = BlockIsRAM [c + 0x806] = TRUE; - BlockIsRAM [c + 7] = BlockIsRAM [c + 0x807] = TRUE; - } - WriteProtectROM (); - } - - if (strncmp (ROMName, "SWORD WORLD SFC", 15) == 0 || - strcmp (ROMName, "SFC カメンライダー") == 0) - { - IAPU.OneCycle = 15; - SNESGameFixes.NeedInit0x2137 = TRUE; - ROMAPUEnabled |= 2; - CPU.APU_APUExecuting |= 2; - } - - if (strncmp (ROMName, "SHIEN THE BLADE CHASE", 21) == 0) - SNESGameFixes.Old_Read0x4200 = TRUE; - - if (strcmp (ROMName, "ゴジラ カイジュウダイケッセン") == 0) - SNESGameFixes.NeedInit0x2137 = TRUE; - - if (strcmp (ROMName, "UMIHARAKAWASE") == 0) - SNESGameFixes.umiharakawaseFix = TRUE; - - if (strcmp (ROMName, "ALIENS vs. PREDATOR") == 0) - SNESGameFixes.alienVSpredetorFix = TRUE; - - if (strcmp (ROMName, "demon's blazon") == 0 || - strcmp (ROMName, "demon's crest") == 0 || - strcmp (ROMName, "ROCKMAN X") == 0 || - strcmp (ROMName, "MEGAMAN X") == 0) - { - - // CAPCOM's protect - // Banks 0x808000, 0x408000 are mirroring. - for (int c = 0; c < 8; c++) - Map [0x408 + c] = ROM - 0x8000; - } - - if (strcmp (ROMName, "スーパーファミスタ") == 0 || - strcmp (ROMName, "スーパーファミスタ 2") == 0 || - strcmp (ROMName, "ZENKI TENCHIMEIDOU") == 0 || - strcmp (ROMName, "GANBA LEAGUE") == 0) - { - SNESGameFixes.APU_OutPorts_ReturnValueFix = TRUE; - } - - // HITOMI3 - if (strcmp (ROMName, "HITOMI3") == 0) - { - Memory.SRAMSize = 1; - CPU.Memory_SRAMMask = Memory.SRAMSize ? - ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; - } - - if (strcmp (ROMName, "goemon 4") == 0) - SNESGameFixes.SRAMInitialValue = 0x00; - - if (strcmp (ROMName, "PACHISLO ケンキュウ") == 0) - SNESGameFixes._0x213E_ReturnValue = 1; - - if (strcmp (ROMName, "ザ マージャン トウハイデン") == 0) - SNESGameFixes.TouhaidenControllerFix = TRUE; - - if (strcmp (ROMName, "DRAGON KNIGHT 4") == 0) - { - // Banks 70->7e, S-RAM - for (int c = 0; c < 0xe0; c++) - { - Map [c + 0x700] = (uint8 *) MAP_LOROM_SRAM; - BlockIsRAM [c + 0x700] = TRUE; - BlockIsROM [c + 0x700] = FALSE; - } - WriteProtectROM (); - } - - if (strncmp (ROMName, "LETs PACHINKO(", 14) == 0) - { - IAPU.OneCycle = 15; - ROMAPUEnabled |= 2; - CPU.APU_APUExecuting |= 2; - if (!Settings.ForceNTSC && !Settings.ForcePAL) - { - Settings.PAL = FALSE; - Settings.FrameTime = Settings.FrameTimeNTSC; - Memory.ROMFramesPerSecond = 60; - } - } - - if (strcmp (ROMName, "FURAI NO SIREN") == 0) - SNESGameFixes.SoundEnvelopeHeightReading2 = TRUE; -#if 0 - if(strcmp (ROMName, "XBAND JAPANESE MODEM") == 0) - { - for (c = 0x200; c < 0x400; c += 16) - { - for (int i = c; i < c + 16; i++) - { - Map [i + 0x400] = Map [i + 0xc00] = &ROM[c * 0x1000]; - MemorySpeed [i + 0x400] = MemorySpeed [i + 0xc00] = 8; - BlockIsRAM [i + 0x400] = BlockIsRAM [i + 0xc00] = TRUE; - BlockIsROM [i + 0x400] = BlockIsROM [i + 0xc00] = FALSE; - } - } - WriteProtectROM (); - } -#endif - -#define RomPatch(adr,ov,nv) \ -if (ROM [adr] == ov) \ - ROM [adr] = nv - - // Love Quest - if (strcmp (ROMName, "LOVE QUEST") == 0) - { - RomPatch (0x1385ec, 0xd0, 0xea); - RomPatch (0x1385ed, 0xb2, 0xea); - } - - // Nangoku Syonen Papuwa Kun - if (strcmp (ROMName, "NANGOKUSYONEN PAPUWA") == 0) - RomPatch (0x1f0d1, 0xa0, 0x6b); - - // Tetsuwan Atom - if (strcmp (ROMName, "Tetsuwan Atom") == 0) - { - RomPatch (0xe24c5, 0x90, 0xea); - RomPatch (0xe24c6, 0xf3, 0xea); - } - - // Oda Nobunaga - if (strcmp (ROMName, "SFC ODA NOBUNAGA") == 0) - { - RomPatch (0x7497, 0x80, 0xea); - RomPatch (0x7498, 0xd5, 0xea); - } - - // Super Batter Up - if (strcmp (ROMName, "Super Batter Up") == 0) - { - RomPatch (0x27ae0, 0xd0, 0xea); - RomPatch (0x27ae1, 0xfa, 0xea); - } - - // Super Professional Baseball 2 - if (strcmp (ROMName, "SUPER PRO. BASE BALL2") == 0) - { - RomPatch (0x1e4, 0x50, 0xea); - RomPatch (0x1e5, 0xfb, 0xea); - } - -} - -// Read variable size MSB int from a file -static long ReadInt (FILE *f, unsigned nbytes) -{ - long v = 0; - while (nbytes--) - { - int c = fgetc(f); - if (c == EOF) - return -1; - v = (v << 8) | (c & 0xFF); - } - return (v); -} - -#define IPS_EOF 0x00454F46l - -void CMemory::CheckForIPSPatch (const char *rom_filename, bool8_32 header, - int32 &rom_size) -{ - char dir [_MAX_DIR + 1]; - char drive [_MAX_DRIVE + 1]; - char name [_MAX_FNAME + 1]; - char ext [_MAX_EXT + 1]; - char fname [_MAX_PATH + 1]; - FILE *patch_file = NULL; - long offset = header ? 512 : 0; - - if (!(patch_file = fopen(S9xGetFilename (".ips"), "rb"))) return; - - if (fread (fname, 1, 5, patch_file) != 5 || strncmp (fname, "PATCH", 5) != 0) - { - fclose (patch_file); - return; - } - - int32 ofs; - - for (;;) - { - long len; - long rlen; - int rchar; - - ofs = ReadInt (patch_file, 3); - if (ofs == -1) - goto err_eof; - - if (ofs == IPS_EOF) - break; - - ofs -= offset; - - len = ReadInt (patch_file, 2); - if (len == -1) - goto err_eof; - - /* Apply patch block */ - if (len) - { - if (ofs + len > MAX_ROM_SIZE) - goto err_eof; - - while (len--) - { - rchar = fgetc (patch_file); - if (rchar == EOF) - goto err_eof; - ROM [ofs++] = (uint8) rchar; - } - if (ofs > rom_size) - rom_size = ofs; - } - else - { - rlen = ReadInt (patch_file, 2); - if (rlen == -1) - goto err_eof; - - - rchar = fgetc (patch_file); - if (rchar == EOF) - goto err_eof; - - if (ofs + rlen > MAX_ROM_SIZE) - goto err_eof; - - while (rlen--) - ROM [ofs++] = (uint8) rchar; - - if (ofs > rom_size) - rom_size = ofs; - } - } - - // Check if ROM image needs to be truncated - ofs = ReadInt (patch_file, 3); - if (ofs != -1 && ofs - offset < rom_size) - { - // Need to truncate ROM image - rom_size = ofs - offset; - } - fclose (patch_file); - return; - -err_eof: - if (patch_file) - fclose (patch_file); -} - -const uint32 crc32Table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -//CRC32 for char arrays -uint32 CMemory::caCRC32(uint8 *array, uint32 size, register uint32 crc32) { - for (register uint32 i = 0; i < size; i++) { - crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF]; - } - return ~crc32; -} -#include "getset.h" diff --git a/src/memmap.h b/src/memmap.h index 96c5e50..6f82f0a 100644 --- a/src/memmap.h +++ b/src/memmap.h @@ -80,14 +80,12 @@ #define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1) #define MEMMAP_MAX_SDD1_LOGGED_ENTRIES (0x10000 / 8) -class CMemory { -public: bool8_32 LoadROM (const char *); void InitROM (bool8_32); bool8_32 LoadSRAM (const char *); bool8_32 SaveSRAM (const char *); - bool8_32 Init (); - void Deinit (); + bool8_32 MemoryInit (); + void MemoryDeinit (); void FreeSDD1Data (); void WriteProtectROM (); @@ -112,7 +110,7 @@ public: int ScoreLoROM (bool8_32 skip_header); void ApplyROMFixes (); void CheckForIPSPatch (const char *rom_filename, bool8_32 header, - int32 &rom_size); + int32 *rom_size); const char *TVStandard (); const char *Speed (); @@ -124,7 +122,7 @@ public: const char *Headers (); const char *ROMID (); const char *CompanyID (); - uint32 caCRC32(uint8 *array, uint32 size, register uint32 crc32= 0xFFFFFFFF); + uint32 caCRC32(uint8 *array, uint32 size); enum { MAP_PPU, MAP_CPU, MAP_DSP, MAP_LOROM_SRAM, MAP_HIROM_SRAM, @@ -132,7 +130,8 @@ public: MAP_BWRAM_BITMAP2, MAP_SA1RAM, MAP_LAST }; enum { MAX_ROM_SIZE = 0x600000 }; - +typedef struct { + uint8 *RAM; uint8 *ROM; uint8 *VRAM; @@ -168,7 +167,7 @@ public: uint32 SDD1LoggedDataCount; uint8 SDD1LoggedData [MEMMAP_MAX_SDD1_LOGGED_ENTRIES]; char ROMFilename [_MAX_PATH]; -}; +}CMemory; START_EXTERN_C extern CMemory Memory; diff --git a/src/missing.h b/src/missing.h index 804f8b5..3c0681b 100644 --- a/src/missing.h +++ b/src/missing.h @@ -41,7 +41,7 @@ #ifndef _MISSING_H_ #define _MISSING_H_ -struct HDMA +typedef struct { uint8 used; uint8 bbus_address; @@ -52,9 +52,9 @@ struct HDMA uint8 force_table_address_read; uint8 line_count_write; uint8 line_count_read; -}; +}HDMA; -struct Missing +typedef struct { uint8 emulate6502; uint8 decimal_mode; @@ -63,7 +63,7 @@ struct Missing uint8 interlace; uint8 lines_239; uint8 pseudo_512; - struct HDMA hdma [8]; + HDMA hdma [8]; uint8 modes [8]; uint8 mode7_fx; uint8 mode7_flip; @@ -108,7 +108,7 @@ struct Missing uint16 unknowncpu_write; uint16 unknowndsp_read; uint16 unknowndsp_write; -}; +}Missing; -EXTERN_C struct Missing missing; +EXTERN_C Missing missing; #endif diff --git a/src/mode7.c b/src/mode7.c new file mode 100644 index 0000000..9e2b47d --- /dev/null +++ b/src/mode7.c @@ -0,0 +1,572 @@ +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" +#include "display.h" +#include "gfx.h" +#include "apu.h" + +extern SLineData LineData[240]; +extern SLineMatrixData LineMatrixData [240]; +extern uint8 Mode7Depths [2]; + +#define M7 19 + +/* +void DrawBGMode7Background16 (uint8 *Screen, int bg, int depth) +{ + RENDER_BACKGROUND_MODE7ADDSUB (depth, GFX.ScreenColors [b & 0xff]); +} +*/ + +#ifdef __DEBUG__ + + #define DMSG(rop) printf("Rendering Mode7 w/prio, ROp: " rop ", R:%d, r2130: %d, bg: %d\n", PPU.Mode7Repeat, GFX.r2130 & 1, bg) +#else + #define DMSG(rop) +#endif + +void DrawBGMode7Background16R0 (uint8 *Screen, int bg, int depth); +void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg, int depth); +void DrawBGMode7Background16R3 (uint8 *Screen, int bg, int depth); + +void DrawBGMode7Background16 (uint8 *Screen, int bg, int depth) +{ + DMSG("opaque"); + CHECK_SOUND(); + + if (GFX.r2130 & 1) { + if (IPPU.DirectColourMapsNeedRebuild) S9xBuildDirectColourMaps (); + GFX.ScreenColors = DirectColourMaps [0]; + } else GFX.ScreenColors = IPPU.ScreenColors; + + switch (PPU.Mode7Repeat) { + case 0: + DrawBGMode7Background16R0(Screen, bg, depth); + return; + case 3: + DrawBGMode7Background16R3(Screen, bg, depth); + return; + default: + DrawBGMode7Background16R1R2(Screen, bg, depth); + return; + } +} + +#define M7C 0x1fff + +void DrawBGMode7Background16R3 (uint8 *Screen, int bg, int depth) +{ + + uint8 *VRAM1 = Memory.VRAM + 1; + int aa, cc; + int startx; + uint32 Left = 0; + uint32 Right = 256; + uint32 ClipCount = GFX.pCurrentClip->Count [0]; + + int32 HOffset; + int32 VOffset; + int32 CentreX; + int32 CentreY; + uint8 *d; + uint16 *p; + int dir; + int yy; + int xx; + int yy3; + int xx3; + int BB; + int DD; + uint32 Line; + uint32 clip; + uint8 b; + uint8 *Depth; + + if (!ClipCount) ClipCount = 1; + + Screen += GFX.StartY * GFX_PITCH; + Depth = GFX.DB + GFX.StartY * GFX_PPL; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + + for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { + HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; + VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; + + CentreX = ((int32) l->CentreX << M7) >> M7; + CentreY = ((int32) l->CentreY << M7) >> M7; + + if (PPU.Mode7VFlip) yy = 255 - (int) Line; + else yy = Line; + + yy += VOffset - CentreY; + xx = HOffset - CentreX; + + BB = l->MatrixB * yy + (CentreX << 8); + DD = l->MatrixD * yy + (CentreY << 8); + + yy3 = ((yy + CentreY) & 7) << 4; + + for (clip = 0; clip < ClipCount; clip++) + { + if (GFX.pCurrentClip->Count [0]){ + Left = GFX.pCurrentClip->Left [clip][0]; + Right = GFX.pCurrentClip->Right [clip][0]; + if (Right <= Left) continue; + } + p = (uint16 *) Screen + Left; + d = Depth + Left; + + if (PPU.Mode7HFlip) { + startx = Right - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + dir = -1; + } else { + startx = Left; + aa = l->MatrixA; + cc = l->MatrixC; + dir = 1; + } + + + xx3 = (startx + HOffset); + + if (dir == 1) + { + __asm__ volatile ( + "1: \n" + " ldrb r0, [%[d]] \n" + " mov r3, %[AA], asr #18 \n" + " cmp %[depth], r0 \n" + " bls 4f \n" + " orrs r3, r3, %[CC], asr #18 \n" + " bne 2f \n" + " \n" + " mov r3, %[CC], asr #11 \n" + " mov r1, %[AA], asr #11 \n" + " add r3, r1, r3, lsl #7 \n" + " mov r3, r3, lsl #1 \n" + " ldrb r3, [%[VRAM], r3] \n" + " \n" + " and r1, %[CC], #(7 << 8) \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " and r0, %[AA], #(7 << 8) \n" + " add r3, r3, r1, asr #4 \n" + " add r3, r3, r0, asr #7 \n" + " \n" + " ldr r1, %[daa] \n" + " ldrb r0, [r3, #1] \n" + " add %[AA], %[AA], r1 \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " add %[xx3], %[xx3], #1 \n" + " strneb %[depth], [%[d]] \n" + " ldr r0, %[dcc] \n" + " strneh r1, [%[p]] \n" + " \n" + " add %[CC], %[CC], r0 \n" + " add %[d], %[d], #1 \n" + " add %[p], %[p], #2 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + " b 3f \n" + "2: \n" + //" and r1, %[yy3], #7 \n" + " and r0, %[xx3], #7 \n" + //" mov r3, r1, lsl #4 \n" + " add r3, %[yy3], r0, lsl #1 \n" + " \n" + " add r3, %[VRAM], r3 \n" + " ldrb r0, [r3, #1] \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " strneb %[depth], [%[d]] \n" + " strneh r1, [%[p]] \n" + "4: \n" + " ldr r0, %[daa] \n" + " ldr r1, %[dcc] \n" + " add %[xx3], %[xx3], #1 \n" + " add %[AA], %[AA], r0 \n" + " add %[CC], %[CC], r1 \n" + " add %[p], %[p], #2 \n" + " add %[d], %[d], #1 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + "3: \n" + : + : [x] "r" (Right - Left), + [AA] "r" (l->MatrixA * (startx + xx) + BB), + [CC] "r" (l->MatrixC * (startx + xx) + DD), + [daa] "m" (aa), + [dcc] "m" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors), + [p] "r" (p), + [d] "r" (d), + [depth] "r" (depth), + //[dir] "r" (dir), + [yy3] "r" (yy3), + [xx3] "r" (xx3) + : "r0", "r1", "r3", "cc" + ); + } + else + { + __asm__ volatile ( + "1: \n" + " ldrb r0, [%[d]] \n" + " mov r3, %[AA], asr #18 \n" + " cmp %[depth], r0 \n" + " bls 4f \n" + " orrs r3, r3, %[CC], asr #18 \n" + " bne 2f \n" + " \n" + " mov r3, %[CC], asr #11 \n" + " mov r1, %[AA], asr #11 \n" + " add r3, r1, r3, lsl #7 \n" + " mov r3, r3, lsl #1 \n" + " ldrb r3, [%[VRAM], r3] \n" + " \n" + " and r1, %[CC], #(7 << 8) \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " and r0, %[AA], #(7 << 8) \n" + " add r3, r3, r1, asr #4 \n" + " add r3, r3, r0, asr #7 \n" + " \n" + " ldr r1, %[daa] \n" + " ldrb r0, [r3, #1] \n" + " add %[AA], %[AA], r1 \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " add %[xx3], %[xx3], #-1 \n" + " strneb %[depth], [%[d]] \n" + " ldr r0, %[dcc] \n" + " strneh r1, [%[p]] \n" + " \n" + " add %[CC], %[CC], r0 \n" + " add %[d], %[d], #1 \n" + " add %[p], %[p], #2 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + " b 3f \n" + "2: \n" + //" and r1, %[yy3], #7 \n" + " and r0, %[xx3], #7 \n" + //" mov r3, r1, lsl #4 \n" + " add r3, %[yy3], r0, lsl #1 \n" + " \n" + " add r3, %[VRAM], r3 \n" + " ldrb r0, [r3, #1] \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " strneb %[depth], [%[d]] \n" + " strneh r1, [%[p]] \n" + "4: \n" + " ldr r0, %[daa] \n" + " ldr r1, %[dcc] \n" + " add %[xx3], %[xx3], #-1 \n" + " add %[AA], %[AA], r0 \n" + " add %[CC], %[CC], r1 \n" + " add %[p], %[p], #2 \n" + " add %[d], %[d], #1 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + "3: \n" + : + : [x] "r" (Right - Left), + [AA] "r" (l->MatrixA * (startx + xx) + BB), + [CC] "r" (l->MatrixC * (startx + xx) + DD), + [daa] "m" (aa), + [dcc] "m" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors), + [p] "r" (p), + [d] "r" (d), + [depth] "r" (depth), + //[dir] "r" (dir), + [yy3] "r" (yy3), + [xx3] "r" (xx3) + : "r0", "r1", "r3", "cc" + ); + } + } + } + +} + +void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg, int depth) +{ + + int aa, cc; + int startx; + uint32 Left = 0; + uint32 Right = 256; + uint32 ClipCount = GFX.pCurrentClip->Count [0]; + + int32 HOffset; + int32 VOffset; + int32 CentreX; + int32 CentreY; + uint8 *d; + uint16 *p; + int yy; + int xx; + int BB; + int DD; + uint32 Line; + uint32 clip; + uint8 b; + uint32 AndByY; + uint32 AndByX = 0xffffffff; + if (Settings.Dezaemon && PPU.Mode7Repeat == 2) AndByX = 0x7ff; + AndByY = AndByX << 4; + AndByX = AndByX << 1; + uint8 *Depth; + + if (!ClipCount) ClipCount = 1; + + Screen += GFX.StartY * GFX_PITCH; + Depth = GFX.DB + GFX.StartY * GFX_PPL; + + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + + for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { + HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; + VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; + + CentreX = ((int32) l->CentreX << M7) >> M7; + CentreY = ((int32) l->CentreY << M7) >> M7; + + if (PPU.Mode7VFlip) yy = 255 - (int) Line; + else yy = Line; + + yy += VOffset - CentreY; + xx = HOffset - CentreX; + + BB = l->MatrixB * yy + (CentreX << 8); + DD = l->MatrixD * yy + (CentreY << 8); + + for (clip = 0; clip < ClipCount; clip++) { + if (GFX.pCurrentClip->Count [0]){ + Left = GFX.pCurrentClip->Left [clip][0]; + Right = GFX.pCurrentClip->Right [clip][0]; + if (Right <= Left) continue; + } + p = (uint16 *) Screen + Left; + d = Depth + Left; + + if (PPU.Mode7HFlip) { + startx = Right - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + } else { + startx = Left; + aa = l->MatrixA; + cc = l->MatrixC; + } + __asm__ volatile ( + "1: \n" + " ldrb r0, [%[d]] \n" + " mov r3, %[AA], asr #18 \n" + " cmp %[depth], r0 \n" + " bls 2f \n" + " orrs r3, r3, %[CC], asr #18 \n" + " bne 2f \n" + " \n" + " ldr r1, %[AndByY] \n" + " ldr r0, %[AndByX] \n" + " and r1, r1, %[CC], asr #4 \n" + " and r0, r0, %[AA], asr #7 \n" + " \n" + " and r3, r1, #0x7f \n" + " sub r3, r1, r3 \n" + " add r3, r3, r0, asr #4 \n" + " add r3, r3, r3 \n" + " ldrb r3, [%[VRAM], r3] \n" + " and r1, r1, #0x70 \n" + " \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " \n" + " and r0, r0, #14 \n" + " add r3, r3, r1 \n" + " add r3, r3, r0 \n" + " \n" + " ldrb r0, [r3, #1] \n" + " add %[AA], %[AA], %[daa] \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " strneb %[depth], [%[d]] \n" + " add %[CC], %[CC], %[dcc] \n" + " strneh r1, [%[p]] \n" + " add %[p], %[p], #2 \n" + " add %[d], %[d], #1 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + " b 3f \n" + "2: \n" + " add %[AA], %[AA], %[daa] \n" + " add %[CC], %[CC], %[dcc] \n" + " add %[p], %[p], #2 \n" + " add %[d], %[d], #1 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + "3: \n" + : + : [x] "r" (Right - Left), + [AA] "r" (l->MatrixA * (startx + xx) + BB), + [CC] "r" (l->MatrixC * (startx + xx) + DD), + [daa] "r" (aa), + [dcc] "r" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors), + [p] "r" (p), + [d] "r" (d), + [depth] "r" (depth), + [AndByX] "m" (AndByX), + [AndByY] "m" (AndByY) + : "r0", "r1", "r3", "cc" + ); + } + } +} + + +void DrawBGMode7Background16R0 (uint8 *Screen, int bg, int depth) +{ + uint8 *VRAM1 = Memory.VRAM + 1; + int aa, cc; + int startx; + uint32 Left; + uint32 Right; + uint32 ClipCount = GFX.pCurrentClip->Count [0]; + + int32 HOffset; + int32 VOffset; + int32 CentreX; + int32 CentreY; + uint16 *p; + uint8 *d; + int yy; + int xx; + int BB; + int DD; + uint32 Line; + uint32 clip; + SLineMatrixData *l; + uint8 *Depth; + + + Left = 0; + Right = 256; + + + if (!ClipCount) ClipCount = 1; + + + l = &LineMatrixData [GFX.StartY]; + Screen += GFX.StartY * GFX_PITCH; + Depth = GFX.DB + GFX.StartY * GFX_PPL; + + for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { + HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; + VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; + + CentreX = ((int32) l->CentreX << M7) >> M7; + CentreY = ((int32) l->CentreY << M7) >> M7; + + if (PPU.Mode7VFlip) yy = 255 - (int) Line; + else yy = Line; + + /*yy += (VOffset - CentreY) % 1023; + xx = (HOffset - CentreX) % 1023; +*/ + + yy += ((VOffset - CentreY) << (32-10+1)) >> (32-10+1) ; + xx = ((HOffset - CentreX) << (32-10+1)) >> (32-10+1); + + BB = l->MatrixB * yy + (CentreX << 8); + DD = l->MatrixD * yy + (CentreY << 8); + + for (clip = 0; clip < ClipCount; clip++) + { + if (GFX.pCurrentClip->Count [0]){ + Left = GFX.pCurrentClip->Left [clip][0]; + Right = GFX.pCurrentClip->Right [clip][0]; + if (Right <= Left) continue; + } + + p = (uint16 *) Screen + Left; + d = Depth + Left; + + if (PPU.Mode7HFlip) { + startx = Right - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + } else { + startx = Left; + aa = l->MatrixA; + cc = l->MatrixC; + } + __asm__ volatile ( + " b 1f \n" + //"7: \n" // AndByX + //" .word (0x3ff << 1) \n" + "8: \n" // AndByY + " .word (0x3ff << 4) \n" + " \n" + "1: \n" + " ldr r3, 8b \n" + " ldrb r0, [%[d]] \n" + " and r1, r3, %[CC], asr #4 \n" + " cmp %[depth], r0 \n" + " bls 2f \n" + //" ldr r0, 7b \n" + " mov r0, r3, asr #3 \n" + " and r3, r1, #0x7f \n" + " and r0, r0, %[AA], asr #7 \n" + " sub r3, r1, r3 \n" + " add r3, r3, r0, asr #4 \n" + " add r3, r3, r3 \n" + " ldrb r3, [%[VRAM], r3] \n" + " \n" + " and r1, r1, #0x70 \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " \n" + " and r0, r0, #14 \n" + " add r3, r3, r1 \n" + " add r3, r3, r0 \n" + " \n" + " ldrb r0, [r3, #1] \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " strneb %[depth], [%[d]] \n" + " strneh r1, [%[p]] \n" + " \n" + "2: \n" + " add %[AA], %[AA], %[daa] \n" + " add %[CC], %[CC], %[dcc] \n" + " add %[p], %[p], #2 \n" + " add %[d], %[d], #1 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + : + : [x] "r" (Right - Left), + [AA] "r" (l->MatrixA * (startx + xx) + BB), + [CC] "r" (l->MatrixC * (startx + xx) + DD), + [daa] "r" (aa), + [dcc] "r" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors), + [p] "r" (p), + [d] "r" (d), + [depth] "r" (depth) + : "r0", "r1", "r3", "cc" + ); + + } + } + +} + + diff --git a/src/mode7.cpp b/src/mode7.cpp deleted file mode 100644 index db65ab9..0000000 --- a/src/mode7.cpp +++ /dev/null @@ -1,572 +0,0 @@ -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "display.h" -#include "gfx.h" -#include "apu.h" - -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; -extern uint8 Mode7Depths [2]; - -#define M7 19 - -/* -void DrawBGMode7Background16 (uint8 *Screen, int bg, int depth) -{ - RENDER_BACKGROUND_MODE7ADDSUB (depth, GFX.ScreenColors [b & 0xff]); -} -*/ - -#ifdef __DEBUG__ - - #define DMSG(rop) printf("Rendering Mode7 w/prio, ROp: " rop ", R:%d, r2130: %d, bg: %d\n", PPU.Mode7Repeat, GFX.r2130 & 1, bg) -#else - #define DMSG(rop) -#endif - -void DrawBGMode7Background16R0 (uint8 *Screen, int bg, int depth); -void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg, int depth); -void DrawBGMode7Background16R3 (uint8 *Screen, int bg, int depth); - -void DrawBGMode7Background16 (uint8 *Screen, int bg, int depth) -{ - DMSG("opaque"); - CHECK_SOUND(); - - if (GFX.r2130 & 1) { - if (IPPU.DirectColourMapsNeedRebuild) S9xBuildDirectColourMaps (); - GFX.ScreenColors = DirectColourMaps [0]; - } else GFX.ScreenColors = IPPU.ScreenColors; - - switch (PPU.Mode7Repeat) { - case 0: - DrawBGMode7Background16R0(Screen, bg, depth); - return; - case 3: - DrawBGMode7Background16R3(Screen, bg, depth); - return; - default: - DrawBGMode7Background16R1R2(Screen, bg, depth); - return; - } -} - -#define M7C 0x1fff - -void DrawBGMode7Background16R3 (uint8 *Screen, int bg, int depth) -{ - - uint8 *VRAM1 = Memory.VRAM + 1; - int aa, cc; - int startx; - uint32 Left = 0; - uint32 Right = 256; - uint32 ClipCount = GFX.pCurrentClip->Count [0]; - - int32 HOffset; - int32 VOffset; - int32 CentreX; - int32 CentreY; - uint8 *d; - uint16 *p; - int dir; - int yy; - int xx; - int yy3; - int xx3; - int BB; - int DD; - uint32 Line; - uint32 clip; - uint8 b; - uint8 *Depth; - - if (!ClipCount) ClipCount = 1; - - Screen += GFX.StartY * GFX_PITCH; - Depth = GFX.DB + GFX.StartY * GFX_PPL; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; - - for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { - HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; - VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; - - CentreX = ((int32) l->CentreX << M7) >> M7; - CentreY = ((int32) l->CentreY << M7) >> M7; - - if (PPU.Mode7VFlip) yy = 255 - (int) Line; - else yy = Line; - - yy += VOffset - CentreY; - xx = HOffset - CentreX; - - BB = l->MatrixB * yy + (CentreX << 8); - DD = l->MatrixD * yy + (CentreY << 8); - - yy3 = ((yy + CentreY) & 7) << 4; - - for (clip = 0; clip < ClipCount; clip++) - { - if (GFX.pCurrentClip->Count [0]){ - Left = GFX.pCurrentClip->Left [clip][0]; - Right = GFX.pCurrentClip->Right [clip][0]; - if (Right <= Left) continue; - } - p = (uint16 *) Screen + Left; - d = Depth + Left; - - if (PPU.Mode7HFlip) { - startx = Right - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - dir = -1; - } else { - startx = Left; - aa = l->MatrixA; - cc = l->MatrixC; - dir = 1; - } - - - xx3 = (startx + HOffset); - - if (dir == 1) - { - asm volatile ( - "1: \n" - " ldrb r0, [%[d]] \n" - " mov r3, %[AA], asr #18 \n" - " cmp %[depth], r0 \n" - " bls 4f \n" - " orrs r3, r3, %[CC], asr #18 \n" - " bne 2f \n" - " \n" - " mov r3, %[CC], asr #11 \n" - " mov r1, %[AA], asr #11 \n" - " add r3, r1, r3, lsl #7 \n" - " mov r3, r3, lsl #1 \n" - " ldrb r3, [%[VRAM], r3] \n" - " \n" - " and r1, %[CC], #(7 << 8) \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " and r0, %[AA], #(7 << 8) \n" - " add r3, r3, r1, asr #4 \n" - " add r3, r3, r0, asr #7 \n" - " \n" - " ldr r1, %[daa] \n" - " ldrb r0, [r3, #1] \n" - " add %[AA], %[AA], r1 \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " add %[xx3], %[xx3], #1 \n" - " strneb %[depth], [%[d]] \n" - " ldr r0, %[dcc] \n" - " strneh r1, [%[p]] \n" - " \n" - " add %[CC], %[CC], r0 \n" - " add %[d], %[d], #1 \n" - " add %[p], %[p], #2 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - " b 3f \n" - "2: \n" - //" and r1, %[yy3], #7 \n" - " and r0, %[xx3], #7 \n" - //" mov r3, r1, lsl #4 \n" - " add r3, %[yy3], r0, lsl #1 \n" - " \n" - " add r3, %[VRAM], r3 \n" - " ldrb r0, [r3, #1] \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " strneb %[depth], [%[d]] \n" - " strneh r1, [%[p]] \n" - "4: \n" - " ldr r0, %[daa] \n" - " ldr r1, %[dcc] \n" - " add %[xx3], %[xx3], #1 \n" - " add %[AA], %[AA], r0 \n" - " add %[CC], %[CC], r1 \n" - " add %[p], %[p], #2 \n" - " add %[d], %[d], #1 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - "3: \n" - : - : [x] "r" (Right - Left), - [AA] "r" (l->MatrixA * (startx + xx) + BB), - [CC] "r" (l->MatrixC * (startx + xx) + DD), - [daa] "m" (aa), - [dcc] "m" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors), - [p] "r" (p), - [d] "r" (d), - [depth] "r" (depth), - //[dir] "r" (dir), - [yy3] "r" (yy3), - [xx3] "r" (xx3) - : "r0", "r1", "r3", "cc" - ); - } - else - { - asm volatile ( - "1: \n" - " ldrb r0, [%[d]] \n" - " mov r3, %[AA], asr #18 \n" - " cmp %[depth], r0 \n" - " bls 4f \n" - " orrs r3, r3, %[CC], asr #18 \n" - " bne 2f \n" - " \n" - " mov r3, %[CC], asr #11 \n" - " mov r1, %[AA], asr #11 \n" - " add r3, r1, r3, lsl #7 \n" - " mov r3, r3, lsl #1 \n" - " ldrb r3, [%[VRAM], r3] \n" - " \n" - " and r1, %[CC], #(7 << 8) \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " and r0, %[AA], #(7 << 8) \n" - " add r3, r3, r1, asr #4 \n" - " add r3, r3, r0, asr #7 \n" - " \n" - " ldr r1, %[daa] \n" - " ldrb r0, [r3, #1] \n" - " add %[AA], %[AA], r1 \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " add %[xx3], %[xx3], #-1 \n" - " strneb %[depth], [%[d]] \n" - " ldr r0, %[dcc] \n" - " strneh r1, [%[p]] \n" - " \n" - " add %[CC], %[CC], r0 \n" - " add %[d], %[d], #1 \n" - " add %[p], %[p], #2 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - " b 3f \n" - "2: \n" - //" and r1, %[yy3], #7 \n" - " and r0, %[xx3], #7 \n" - //" mov r3, r1, lsl #4 \n" - " add r3, %[yy3], r0, lsl #1 \n" - " \n" - " add r3, %[VRAM], r3 \n" - " ldrb r0, [r3, #1] \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " strneb %[depth], [%[d]] \n" - " strneh r1, [%[p]] \n" - "4: \n" - " ldr r0, %[daa] \n" - " ldr r1, %[dcc] \n" - " add %[xx3], %[xx3], #-1 \n" - " add %[AA], %[AA], r0 \n" - " add %[CC], %[CC], r1 \n" - " add %[p], %[p], #2 \n" - " add %[d], %[d], #1 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - "3: \n" - : - : [x] "r" (Right - Left), - [AA] "r" (l->MatrixA * (startx + xx) + BB), - [CC] "r" (l->MatrixC * (startx + xx) + DD), - [daa] "m" (aa), - [dcc] "m" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors), - [p] "r" (p), - [d] "r" (d), - [depth] "r" (depth), - //[dir] "r" (dir), - [yy3] "r" (yy3), - [xx3] "r" (xx3) - : "r0", "r1", "r3", "cc" - ); - } - } - } - -} - -void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg, int depth) -{ - - int aa, cc; - int startx; - uint32 Left = 0; - uint32 Right = 256; - uint32 ClipCount = GFX.pCurrentClip->Count [0]; - - int32 HOffset; - int32 VOffset; - int32 CentreX; - int32 CentreY; - uint8 *d; - uint16 *p; - int yy; - int xx; - int BB; - int DD; - uint32 Line; - uint32 clip; - uint8 b; - uint32 AndByY; - uint32 AndByX = 0xffffffff; - if (Settings.Dezaemon && PPU.Mode7Repeat == 2) AndByX = 0x7ff; - AndByY = AndByX << 4; - AndByX = AndByX << 1; - uint8 *Depth; - - if (!ClipCount) ClipCount = 1; - - Screen += GFX.StartY * GFX_PITCH; - Depth = GFX.DB + GFX.StartY * GFX_PPL; - - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; - - for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { - HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; - VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; - - CentreX = ((int32) l->CentreX << M7) >> M7; - CentreY = ((int32) l->CentreY << M7) >> M7; - - if (PPU.Mode7VFlip) yy = 255 - (int) Line; - else yy = Line; - - yy += VOffset - CentreY; - xx = HOffset - CentreX; - - BB = l->MatrixB * yy + (CentreX << 8); - DD = l->MatrixD * yy + (CentreY << 8); - - for (clip = 0; clip < ClipCount; clip++) { - if (GFX.pCurrentClip->Count [0]){ - Left = GFX.pCurrentClip->Left [clip][0]; - Right = GFX.pCurrentClip->Right [clip][0]; - if (Right <= Left) continue; - } - p = (uint16 *) Screen + Left; - d = Depth + Left; - - if (PPU.Mode7HFlip) { - startx = Right - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - } else { - startx = Left; - aa = l->MatrixA; - cc = l->MatrixC; - } - asm volatile ( - "1: \n" - " ldrb r0, [%[d]] \n" - " mov r3, %[AA], asr #18 \n" - " cmp %[depth], r0 \n" - " bls 2f \n" - " orrs r3, r3, %[CC], asr #18 \n" - " bne 2f \n" - " \n" - " ldr r1, %[AndByY] \n" - " ldr r0, %[AndByX] \n" - " and r1, r1, %[CC], asr #4 \n" - " and r0, r0, %[AA], asr #7 \n" - " \n" - " and r3, r1, #0x7f \n" - " sub r3, r1, r3 \n" - " add r3, r3, r0, asr #4 \n" - " add r3, r3, r3 \n" - " ldrb r3, [%[VRAM], r3] \n" - " and r1, r1, #0x70 \n" - " \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " \n" - " and r0, r0, #14 \n" - " add r3, r3, r1 \n" - " add r3, r3, r0 \n" - " \n" - " ldrb r0, [r3, #1] \n" - " add %[AA], %[AA], %[daa] \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " strneb %[depth], [%[d]] \n" - " add %[CC], %[CC], %[dcc] \n" - " strneh r1, [%[p]] \n" - " add %[p], %[p], #2 \n" - " add %[d], %[d], #1 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - " b 3f \n" - "2: \n" - " add %[AA], %[AA], %[daa] \n" - " add %[CC], %[CC], %[dcc] \n" - " add %[p], %[p], #2 \n" - " add %[d], %[d], #1 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - "3: \n" - : - : [x] "r" (Right - Left), - [AA] "r" (l->MatrixA * (startx + xx) + BB), - [CC] "r" (l->MatrixC * (startx + xx) + DD), - [daa] "r" (aa), - [dcc] "r" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors), - [p] "r" (p), - [d] "r" (d), - [depth] "r" (depth), - [AndByX] "m" (AndByX), - [AndByY] "m" (AndByY) - : "r0", "r1", "r3", "cc" - ); - } - } -} - - -void DrawBGMode7Background16R0 (uint8 *Screen, int bg, int depth) -{ - uint8 *VRAM1 = Memory.VRAM + 1; - int aa, cc; - int startx; - uint32 Left; - uint32 Right; - uint32 ClipCount = GFX.pCurrentClip->Count [0]; - - int32 HOffset; - int32 VOffset; - int32 CentreX; - int32 CentreY; - uint16 *p; - uint8 *d; - int yy; - int xx; - int BB; - int DD; - uint32 Line; - uint32 clip; - struct SLineMatrixData *l; - uint8 *Depth; - - - Left = 0; - Right = 256; - - - if (!ClipCount) ClipCount = 1; - - - l = &LineMatrixData [GFX.StartY]; - Screen += GFX.StartY * GFX_PITCH; - Depth = GFX.DB + GFX.StartY * GFX_PPL; - - for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { - HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; - VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; - - CentreX = ((int32) l->CentreX << M7) >> M7; - CentreY = ((int32) l->CentreY << M7) >> M7; - - if (PPU.Mode7VFlip) yy = 255 - (int) Line; - else yy = Line; - - /*yy += (VOffset - CentreY) % 1023; - xx = (HOffset - CentreX) % 1023; -*/ - - yy += ((VOffset - CentreY) << (32-10+1)) >> (32-10+1) ; - xx = ((HOffset - CentreX) << (32-10+1)) >> (32-10+1); - - BB = l->MatrixB * yy + (CentreX << 8); - DD = l->MatrixD * yy + (CentreY << 8); - - for (clip = 0; clip < ClipCount; clip++) - { - if (GFX.pCurrentClip->Count [0]){ - Left = GFX.pCurrentClip->Left [clip][0]; - Right = GFX.pCurrentClip->Right [clip][0]; - if (Right <= Left) continue; - } - - p = (uint16 *) Screen + Left; - d = Depth + Left; - - if (PPU.Mode7HFlip) { - startx = Right - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - } else { - startx = Left; - aa = l->MatrixA; - cc = l->MatrixC; - } - asm volatile ( - " b 1f \n" - //"7: \n" // AndByX - //" .word (0x3ff << 1) \n" - "8: \n" // AndByY - " .word (0x3ff << 4) \n" - " \n" - "1: \n" - " ldr r3, 8b \n" - " ldrb r0, [%[d]] \n" - " and r1, r3, %[CC], asr #4 \n" - " cmp %[depth], r0 \n" - " bls 2f \n" - //" ldr r0, 7b \n" - " mov r0, r3, asr #3 \n" - " and r3, r1, #0x7f \n" - " and r0, r0, %[AA], asr #7 \n" - " sub r3, r1, r3 \n" - " add r3, r3, r0, asr #4 \n" - " add r3, r3, r3 \n" - " ldrb r3, [%[VRAM], r3] \n" - " \n" - " and r1, r1, #0x70 \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " \n" - " and r0, r0, #14 \n" - " add r3, r3, r1 \n" - " add r3, r3, r0 \n" - " \n" - " ldrb r0, [r3, #1] \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " strneb %[depth], [%[d]] \n" - " strneh r1, [%[p]] \n" - " \n" - "2: \n" - " add %[AA], %[AA], %[daa] \n" - " add %[CC], %[CC], %[dcc] \n" - " add %[p], %[p], #2 \n" - " add %[d], %[d], #1 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - : - : [x] "r" (Right - Left), - [AA] "r" (l->MatrixA * (startx + xx) + BB), - [CC] "r" (l->MatrixC * (startx + xx) + DD), - [daa] "r" (aa), - [dcc] "r" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors), - [p] "r" (p), - [d] "r" (d), - [depth] "r" (depth) - : "r0", "r1", "r3", "cc" - ); - - } - } - -} - - diff --git a/src/mode7_t.h b/src/mode7_t.h index 5d67aa6..9a35c41 100644 --- a/src/mode7_t.h +++ b/src/mode7_t.h @@ -7,8 +7,8 @@ #include "gfx.h" #include "apu.h" -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; +extern SLineData LineData[240]; +extern SLineMatrixData LineMatrixData [240]; extern uint8 Mode7Depths [2]; #define M7 19 @@ -50,7 +50,7 @@ static void DrawBGMode7Background16R3 (uint8 *Screen, int bg, int depth) Screen += GFX.StartY * GFX_PITCH; Depth = GFX.DB + GFX.StartY * GFX_PPL; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; @@ -96,7 +96,7 @@ static void DrawBGMode7Background16R3 (uint8 *Screen, int bg, int depth) xx3 = (startx + HOffset); #define M7R3(dir) \ - asm volatile (\ + __asm__ volatile (\ "1: \n"\ " ldrb r0, [%[d], #1]! \n"\ " mov r3, %[AA], asr #18 \n"\ @@ -238,7 +238,7 @@ static void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg, int depth) Screen += GFX.StartY * GFX_PITCH; Depth = GFX.DB + GFX.StartY * GFX_PPL; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; @@ -279,7 +279,7 @@ static void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg, int depth) AA = (l->MatrixA * (startx + xx) + BB); CC = (l->MatrixC * (startx + xx) + DD); - asm volatile ( + __asm__ volatile ( "1: \n" " ldrb r0, [%[d], #1]! \n" " mov r3, %[AA], asr #18 \n" @@ -375,7 +375,7 @@ static void DrawBGMode7Background16R0 (uint8 *Screen, int bg, int depth) int DD; uint32 Line; uint32 clip; - struct SLineMatrixData *l; + SLineMatrixData *l; uint8 *Depth; unsigned int fixedColour = GFX.FixedColour; @@ -432,7 +432,7 @@ static void DrawBGMode7Background16R0 (uint8 *Screen, int bg, int depth) AA = (l->MatrixA * (startx + xx) + BB); CC = (l->MatrixC * (startx + xx) + DD); - asm volatile ( + __asm__ volatile ( " ldrb r0, [%[d], #1]! \n" "1: \n" " ldr r3, %[AndByY] \n" diff --git a/src/mode7_t.h.new b/src/mode7_t.h.new index f37e332..2ebfefe 100644 --- a/src/mode7_t.h.new +++ b/src/mode7_t.h.new @@ -7,8 +7,8 @@ #include "gfx.h" #include "apu.h" -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; +extern SLineData LineData[240]; +extern SLineMatrixData LineMatrixData [240]; extern uint8 Mode7Depths [2]; #define M7 19 @@ -50,7 +50,7 @@ static void DrawBGMode7Background16R3 (uint8 *Screen, int bg, int depth) Screen += GFX.StartY * GFX_PITCH; Depth = GFX.DB + GFX.StartY * GFX_PPL; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; @@ -96,7 +96,7 @@ static void DrawBGMode7Background16R3 (uint8 *Screen, int bg, int depth) xx3 = (startx + HOffset); #define M7R3(dir) \ - asm volatile (\ + __asm__ volatile (\ "1: \n"\ " ldrb r0, [%[d], #1]! \n"\ " mov r3, %[AA], asr #18 \n"\ @@ -237,7 +237,7 @@ static void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg, int depth) Screen += GFX.StartY * GFX_PITCH; Depth = GFX.DB + GFX.StartY * GFX_PPL; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; @@ -278,7 +278,7 @@ static void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg, int depth) AA = (l->MatrixA * (startx + xx) + BB); CC = (l->MatrixC * (startx + xx) + DD); - asm volatile ( + __asm__ volatile ( "1: \n" " ldrb r0, [%[d], #1]! \n" " mov r3, %[AA], asr #18 \n" @@ -373,7 +373,7 @@ static void DrawBGMode7Background16R0 (uint8 *Screen, int bg, int depth) int DD; uint32 Line; uint32 clip; - struct SLineMatrixData *l; + SLineMatrixData *l; uint8 *Depth; unsigned int fixedColour = GFX.FixedColour; @@ -430,7 +430,7 @@ static void DrawBGMode7Background16R0 (uint8 *Screen, int bg, int depth) AA = (l->MatrixA * (startx + xx) + BB); CC = (l->MatrixC * (startx + xx) + DD); - asm volatile ( + __asm__ volatile ( " ldrb r0, [%[d], #1]! \n" "1: \n" " ldr r3, %[AndByY] \n" diff --git a/src/mode7add.c b/src/mode7add.c new file mode 100644 index 0000000..0670b89 --- /dev/null +++ b/src/mode7add.c @@ -0,0 +1,5 @@ +#include "rops.h" +#define ROPNAME Add +#define ROP ROP_ADD(r1, r3) + +#include "mode7_t.h" diff --git a/src/mode7add.cpp b/src/mode7add.cpp deleted file mode 100644 index 0670b89..0000000 --- a/src/mode7add.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "rops.h" -#define ROPNAME Add -#define ROP ROP_ADD(r1, r3) - -#include "mode7_t.h" diff --git a/src/mode7add1_2.c b/src/mode7add1_2.c new file mode 100644 index 0000000..c01ef6f --- /dev/null +++ b/src/mode7add1_2.c @@ -0,0 +1,6 @@ +#include "rops.h" +#define ROPNAME Add1_2 +#define ROP ROP_ADD1_2(r1, r3) + +#include "mode7_t.h" + diff --git a/src/mode7add1_2.cpp b/src/mode7add1_2.cpp deleted file mode 100644 index c01ef6f..0000000 --- a/src/mode7add1_2.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "rops.h" -#define ROPNAME Add1_2 -#define ROP ROP_ADD1_2(r1, r3) - -#include "mode7_t.h" - diff --git a/src/mode7add1_2prio.c b/src/mode7add1_2prio.c new file mode 100644 index 0000000..0826461 --- /dev/null +++ b/src/mode7add1_2prio.c @@ -0,0 +1,8 @@ +#include "rops.h" +#define ROPNAME Add1_2 +#define ROP ROP_ADD1_2(r1, r3) + +#include "mode7prio_t.h" + + + diff --git a/src/mode7add1_2prio.cpp b/src/mode7add1_2prio.cpp deleted file mode 100644 index 0826461..0000000 --- a/src/mode7add1_2prio.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "rops.h" -#define ROPNAME Add1_2 -#define ROP ROP_ADD1_2(r1, r3) - -#include "mode7prio_t.h" - - - diff --git a/src/mode7addprio.c b/src/mode7addprio.c new file mode 100644 index 0000000..38cbdfd --- /dev/null +++ b/src/mode7addprio.c @@ -0,0 +1,5 @@ +#include "rops.h" +#define ROPNAME Add +#define ROP ROP_ADD(r1, r3) + +#include "mode7prio_t.h" diff --git a/src/mode7addprio.cpp b/src/mode7addprio.cpp deleted file mode 100644 index 38cbdfd..0000000 --- a/src/mode7addprio.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "rops.h" -#define ROPNAME Add -#define ROP ROP_ADD(r1, r3) - -#include "mode7prio_t.h" diff --git a/src/mode7new.c b/src/mode7new.c new file mode 100644 index 0000000..b09dc36 --- /dev/null +++ b/src/mode7new.c @@ -0,0 +1,506 @@ +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" +#include "display.h" +#include "gfx.h" +#include "apu.h" + +extern SLineData LineData[240]; +extern SLineMatrixData LineMatrixData [240]; +extern uint8 Mode7Depths [2]; + +#define M7 19 + +#ifdef __DEBUG__ + + #define DMSG(rop) printf("Rendering Mode7, ROp: " rop ", R:%d, r2130: %d\n", PPU.Mode7Repeat, GFX.r2130 & 1) +#else + #define DMSG(rop) +#endif + +void DrawBGMode7Background16NewR0 (uint8 *Screen); +void DrawBGMode7Background16NewR1R2 (uint8 *Screen); +void DrawBGMode7Background16NewR3 (uint8 *Screen); + +void DrawBGMode7Background16New (uint8 *Screen) +{ + DMSG("totally opaque"); + CHECK_SOUND(); + + if (GFX.r2130 & 1) { + if (IPPU.DirectColourMapsNeedRebuild) S9xBuildDirectColourMaps (); + GFX.ScreenColors = DirectColourMaps [0]; + } else GFX.ScreenColors = IPPU.ScreenColors; + + switch (PPU.Mode7Repeat) { + case 0: + DrawBGMode7Background16NewR0(Screen); + return; + case 3: + DrawBGMode7Background16NewR3(Screen); + return; + default: + DrawBGMode7Background16NewR1R2(Screen); + return; + } +} + +#define M7C 0x1fff + +void DrawBGMode7Background16NewR3 (uint8 *Screen) +{ + uint8 *VRAM1 = Memory.VRAM + 1; + int aa, cc; + int startx; + uint32 Left = 0; + uint32 Right = 256; + uint32 ClipCount = GFX.pCurrentClip->Count [0]; + + int HOffset; + int VOffset; + int CentreX; + int CentreY; + uint16 *p; + int dir; + int yy; + int xx; + int yy3; + int xx3; + int BB; + int DD; + int Line; + uint32 clip; + + //FILE *f = fopen("mode7.log", "a"); + + if (!ClipCount) ClipCount = 1; + + Screen += GFX.StartY * GFX_PITCH; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + + for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, l++) { + HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; + VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; + + CentreX = ((int32) l->CentreX << M7) >> M7; + CentreY = ((int32) l->CentreY << M7) >> M7; + + if (PPU.Mode7VFlip) yy = 255 - Line; + else yy = Line; + + yy += VOffset - CentreY; + xx = HOffset - CentreX; + + BB = l->MatrixB * yy + (CentreX << 8); + DD = l->MatrixD * yy + (CentreY << 8); + + yy3 = ((yy + CentreY) & 7) << 4; + + for (clip = 0; clip < ClipCount; clip++) + { + if (GFX.pCurrentClip->Count [0]){ + Left = GFX.pCurrentClip->Left [clip][0]; + Right = GFX.pCurrentClip->Right [clip][0]; + if (Right <= Left) continue; + } + p = (uint16 *) Screen + Left; + + if (PPU.Mode7HFlip) { + startx = Right - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + dir = -1; + } else { + startx = Left; + aa = l->MatrixA; + cc = l->MatrixC; + dir = 1; + } + + int AA = (l->MatrixA * (startx + xx) + BB); + int CC = (l->MatrixC * (startx + xx) + DD); + + int width = Right - Left; + xx3 = (startx + HOffset); + + //fprintf(f, "AA:%d, CC:%d, daa: %d, dcc: %d, MA: %d, MB: %d, MC: %d, MD: %d\n", AA, CC, aa, cc, l->MatrixA, l->MatrixB, l->MatrixC, l->MatrixD); + + + if (dir == 1) + { + __asm__ volatile ( + "1: \n" + " mov r3, %[AA], asr #18 \n" + " orrs r3, r3, %[CC], asr #18 \n" + " bne 2f \n" + " \n" + " mov r3, %[CC], asr #11 \n" + " mov r1, %[AA], asr #11 \n" + " add r3, r1, r3, lsl #7 \n" + " mov r3, r3, lsl #1 \n" + " ldrb r3, [%[VRAM], r3] \n" + " \n" + " and r1, %[CC], #(7 << 8) \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " and r0, %[AA], #(7 << 8) \n" + " add r3, r3, r1, asr #4 \n" + " add r3, r3, r0, asr #7 \n" + " \n" + " ldrb r0, [r3, #1] \n" + " add %[AA], %[AA], %[daa] \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " add %[xx3], %[xx3], #1 \n" + " strneh r1, [%[p]] \n" + " \n" + " add %[CC], %[CC], %[dcc] \n" + " add %[p], %[p], #2 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + " b 3f \n" + "2: \n" + " and r0, %[xx3], #7 \n" + " add r3, %[yy3], r0, lsl #1 \n" + " \n" + " add r3, %[VRAM], r3 \n" + " ldrb r0, [r3, #1] \n" + " add %[AA], %[AA], %[daa] \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " add %[xx3], %[xx3], #1 \n" + " strneh r1, [%[p]] \n" + " \n" + " add %[CC], %[CC], %[dcc] \n" + " add %[p], %[p], #2 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + "3: \n" + : [xx3] "+r" (xx3), + [x] "+r" (width), + [p] "+r" (p), + [AA] "+r" (AA), + [CC] "+r" (CC) + : [yy3] "r" (yy3), + [daa] "r" (aa), + [dcc] "r" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors) + //[dir] "r" (dir) + : "r0", "r1", "r3", "cc" + ); + } + else + { + __asm__ volatile ( + "1: \n" + " mov r3, %[AA], asr #18 \n" + " orrs r3, r3, %[CC], asr #18 \n" + " bne 2f \n" + " \n" + " mov r3, %[CC], asr #11 \n" + " mov r1, %[AA], asr #11 \n" + " add r3, r1, r3, lsl #7 \n" + " mov r3, r3, lsl #1 \n" + " ldrb r3, [%[VRAM], r3] \n" + " \n" + " and r1, %[CC], #(7 << 8) \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " and r0, %[AA], #(7 << 8) \n" + " add r3, r3, r1, asr #4 \n" + " add r3, r3, r0, asr #7 \n" + " \n" + " ldrb r0, [r3, #1] \n" + " add %[AA], %[AA], %[daa] \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " add %[xx3], %[xx3], #-1 \n" + " strneh r1, [%[p]] \n" + " \n" + " add %[CC], %[CC], %[dcc] \n" + " add %[p], %[p], #2 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + " b 3f \n" + "2: \n" + " and r0, %[xx3], #7 \n" + " add r3, %[yy3], r0, lsl #1 \n" + " \n" + " add r3, %[VRAM], r3 \n" + " ldrb r0, [r3, #1] \n" + " add %[AA], %[AA], %[daa] \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " add %[xx3], %[xx3], #-1 \n" + " strneh r1, [%[p]] \n" + " \n" + " add %[CC], %[CC], %[dcc] \n" + " add %[p], %[p], #2 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + "3: \n" + : [xx3] "+r" (xx3), + [x] "+r" (width), + [p] "+r" (p), + [AA] "+r" (AA), + [CC] "+r" (CC) + : [yy3] "r" (yy3), + [daa] "r" (aa), + [dcc] "r" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors) + //[dir] "r" (dir) + : "r0", "r1", "r3", "cc" + ); + } + } + } + + //fclose(f); + +} + +void DrawBGMode7Background16NewR1R2 (uint8 *Screen) +{ + int aa, cc; + int startx; + uint32 Left = 0; + uint32 Right = 256; + uint32 ClipCount = GFX.pCurrentClip->Count [0]; + + int32 HOffset; + int32 VOffset; + int32 CentreX; + int32 CentreY; + uint16 *p; + int yy; + int xx; + int BB; + int DD; + uint32 Line; + uint32 clip; + uint8 b; + uint32 AndByY; + uint32 AndByX = 0xffffffff; + if (Settings.Dezaemon && PPU.Mode7Repeat == 2) AndByX = 0x7ff; + AndByY = AndByX << 4; + AndByX = AndByX << 1; + + if (!ClipCount) ClipCount = 1; + + Screen += GFX.StartY * GFX_PITCH; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + + for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, l++) { + HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; + VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; + + CentreX = ((int32) l->CentreX << M7) >> M7; + CentreY = ((int32) l->CentreY << M7) >> M7; + + if (PPU.Mode7VFlip) yy = 255 - (int) Line; + else yy = Line; + + yy += VOffset - CentreY; + xx = HOffset - CentreX; + + BB = l->MatrixB * yy + (CentreX << 8); + DD = l->MatrixD * yy + (CentreY << 8); + + for (clip = 0; clip < ClipCount; clip++) { + if (GFX.pCurrentClip->Count [0]){ + Left = GFX.pCurrentClip->Left [clip][0]; + Right = GFX.pCurrentClip->Right [clip][0]; + if (Right <= Left) continue; + } + p = (uint16 *) Screen + Left; + + if (PPU.Mode7HFlip) { + startx = Right - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + } else { + startx = Left; + aa = l->MatrixA; + cc = l->MatrixC; + } + __asm__ volatile ( + "1: \n" + " mov r3, %[AA], asr #18 \n" + " orrs r3, r3, %[CC], asr #18 \n" + " bne 2f \n" + " \n" + " and r1, %[AndByY], %[CC], asr #4 \n" + " and r0, %[AndByX], %[AA], asr #7 \n" + " \n" + " and r3, r1, #0x7f \n" + " sub r3, r1, r3 \n" + " add r3, r3, r0, asr #4 \n" + " add r3, r3, r3 \n" + " ldrb r3, [%[VRAM], r3] \n" + " and r1, r1, #0x70 \n" + " \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " \n" + " and r0, r0, #14 \n" + " add r3, r3, r1 \n" + " add r3, r3, r0 \n" + " \n" + " ldrb r0, [r3, #1] \n" + " add %[AA], %[AA], %[daa] \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " add %[CC], %[CC], %[dcc] \n" + " strneh r1, [%[p]] \n" + " add %[p], %[p], #2 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + " b 3f \n" + "2: \n" + " add %[AA], %[AA], %[daa] \n" + " add %[CC], %[CC], %[dcc] \n" + " add %[p], %[p], #2 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + "3: \n" + : + : [x] "r" (Right - Left), + [AA] "r" (l->MatrixA * (startx + xx) + BB), + [CC] "r" (l->MatrixC * (startx + xx) + DD), + [daa] "r" (aa), + [dcc] "r" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors), + [p] "r" (p), + [AndByX] "r" (AndByX), + [AndByY] "r" (AndByY) + : "r0", "r1", "r3", "cc" + ); + } + } +} + + +void DrawBGMode7Background16NewR0 (uint8 *Screen) +{ + uint8 *VRAM1 = Memory.VRAM + 1; + int aa, cc; + int startx; + uint32 Left; + uint32 Right; + uint32 ClipCount = GFX.pCurrentClip->Count [0]; + + int32 HOffset; + int32 VOffset; + int32 CentreX; + int32 CentreY; + uint16 *p; +uint8 *z; + int yy; + int xx; + int BB; + int DD; + uint32 Line; + uint32 clip; + SLineMatrixData *l; + + + + Left = 0; + Right = 256; + + + if (!ClipCount) ClipCount = 1; + + + l = &LineMatrixData [GFX.StartY]; + Screen += GFX.StartY * GFX_PITCH; + + for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, l++) { + HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; + VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; + + CentreX = ((int32) l->CentreX << M7) >> M7; + CentreY = ((int32) l->CentreY << M7) >> M7; + + if (PPU.Mode7VFlip) yy = 255 - (int) Line; + else yy = Line; + + /*yy += (VOffset - CentreY) % 1023; + xx = (HOffset - CentreX) % 1023; +*/ + + yy += ((VOffset - CentreY) << (32-10+1)) >> (32-10+1) ; + xx = ((HOffset - CentreX) << (32-10+1)) >> (32-10+1); + + BB = l->MatrixB * yy + (CentreX << 8); + DD = l->MatrixD * yy + (CentreY << 8); + + for (clip = 0; clip < ClipCount; clip++) + { + if (GFX.pCurrentClip->Count [0]){ + Left = GFX.pCurrentClip->Left [clip][0]; + Right = GFX.pCurrentClip->Right [clip][0]; + if (Right <= Left) continue; + } + + p = (uint16 *) Screen + Left; + + + if (PPU.Mode7HFlip) { + startx = Right - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + } else { + startx = Left; + aa = l->MatrixA; + cc = l->MatrixC; + } + __asm__ volatile ( + " \n" + "1: \n" + " and r1, %[AndByY], %[CC], asr #4 \n" + " and r3, r1, #0x7f \n" + " and r0, %[AndByX], %[AA], asr #7 \n" + " sub r3, r1, r3 \n" + " add r3, r3, r0, asr #4 \n" + " add r3, r3, r3 \n" + " ldrb r3, [%[VRAM], r3] \n" + " \n" + " and r1, r1, #0x70 \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " \n" + " and r0, r0, #14 \n" + " add r3, r3, r1 \n" + " add r3, r3, r0 \n" + " \n" + " ldrb r0, [r3, #1] \n" + " add %[AA], %[AA], %[daa] \n" + " movs r0, r0, lsl #2 \n" + " add %[CC], %[CC], %[dcc] \n" + " ldrne r1, [%[colors], r0] \n" + " add %[p], %[p], #2 \n" + " strneh r1, [%[p]] \n" + " \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + : + : [x] "r" (Right - Left), + [AA] "r" (l->MatrixA * (startx + xx) + BB), + [CC] "r" (l->MatrixC * (startx + xx) + DD), + [daa] "r" (aa), + [dcc] "r" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors), + [p] "r" (p), + [AndByX] "r" (0x3ff << 1), + [AndByY] "r" (0x3ff << 4) + : "r0", "r1", "r3", "cc" + ); + + } + } + +} + + diff --git a/src/mode7new.cpp b/src/mode7new.cpp deleted file mode 100644 index b71e835..0000000 --- a/src/mode7new.cpp +++ /dev/null @@ -1,506 +0,0 @@ -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "display.h" -#include "gfx.h" -#include "apu.h" - -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; -extern uint8 Mode7Depths [2]; - -#define M7 19 - -#ifdef __DEBUG__ - - #define DMSG(rop) printf("Rendering Mode7, ROp: " rop ", R:%d, r2130: %d\n", PPU.Mode7Repeat, GFX.r2130 & 1) -#else - #define DMSG(rop) -#endif - -void DrawBGMode7Background16NewR0 (uint8 *Screen); -void DrawBGMode7Background16NewR1R2 (uint8 *Screen); -void DrawBGMode7Background16NewR3 (uint8 *Screen); - -void DrawBGMode7Background16New (uint8 *Screen) -{ - DMSG("totally opaque"); - CHECK_SOUND(); - - if (GFX.r2130 & 1) { - if (IPPU.DirectColourMapsNeedRebuild) S9xBuildDirectColourMaps (); - GFX.ScreenColors = DirectColourMaps [0]; - } else GFX.ScreenColors = IPPU.ScreenColors; - - switch (PPU.Mode7Repeat) { - case 0: - DrawBGMode7Background16NewR0(Screen); - return; - case 3: - DrawBGMode7Background16NewR3(Screen); - return; - default: - DrawBGMode7Background16NewR1R2(Screen); - return; - } -} - -#define M7C 0x1fff - -void DrawBGMode7Background16NewR3 (uint8 *Screen) -{ - uint8 *VRAM1 = Memory.VRAM + 1; - int aa, cc; - int startx; - uint32 Left = 0; - uint32 Right = 256; - uint32 ClipCount = GFX.pCurrentClip->Count [0]; - - int HOffset; - int VOffset; - int CentreX; - int CentreY; - uint16 *p; - int dir; - int yy; - int xx; - int yy3; - int xx3; - int BB; - int DD; - int Line; - uint32 clip; - - //FILE *f = fopen("mode7.log", "a"); - - if (!ClipCount) ClipCount = 1; - - Screen += GFX.StartY * GFX_PITCH; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; - - for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, l++) { - HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; - VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; - - CentreX = ((int32) l->CentreX << M7) >> M7; - CentreY = ((int32) l->CentreY << M7) >> M7; - - if (PPU.Mode7VFlip) yy = 255 - Line; - else yy = Line; - - yy += VOffset - CentreY; - xx = HOffset - CentreX; - - BB = l->MatrixB * yy + (CentreX << 8); - DD = l->MatrixD * yy + (CentreY << 8); - - yy3 = ((yy + CentreY) & 7) << 4; - - for (clip = 0; clip < ClipCount; clip++) - { - if (GFX.pCurrentClip->Count [0]){ - Left = GFX.pCurrentClip->Left [clip][0]; - Right = GFX.pCurrentClip->Right [clip][0]; - if (Right <= Left) continue; - } - p = (uint16 *) Screen + Left; - - if (PPU.Mode7HFlip) { - startx = Right - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - dir = -1; - } else { - startx = Left; - aa = l->MatrixA; - cc = l->MatrixC; - dir = 1; - } - - int AA = (l->MatrixA * (startx + xx) + BB); - int CC = (l->MatrixC * (startx + xx) + DD); - - int width = Right - Left; - xx3 = (startx + HOffset); - - //fprintf(f, "AA:%d, CC:%d, daa: %d, dcc: %d, MA: %d, MB: %d, MC: %d, MD: %d\n", AA, CC, aa, cc, l->MatrixA, l->MatrixB, l->MatrixC, l->MatrixD); - - - if (dir == 1) - { - asm volatile ( - "1: \n" - " mov r3, %[AA], asr #18 \n" - " orrs r3, r3, %[CC], asr #18 \n" - " bne 2f \n" - " \n" - " mov r3, %[CC], asr #11 \n" - " mov r1, %[AA], asr #11 \n" - " add r3, r1, r3, lsl #7 \n" - " mov r3, r3, lsl #1 \n" - " ldrb r3, [%[VRAM], r3] \n" - " \n" - " and r1, %[CC], #(7 << 8) \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " and r0, %[AA], #(7 << 8) \n" - " add r3, r3, r1, asr #4 \n" - " add r3, r3, r0, asr #7 \n" - " \n" - " ldrb r0, [r3, #1] \n" - " add %[AA], %[AA], %[daa] \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " add %[xx3], %[xx3], #1 \n" - " strneh r1, [%[p]] \n" - " \n" - " add %[CC], %[CC], %[dcc] \n" - " add %[p], %[p], #2 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - " b 3f \n" - "2: \n" - " and r0, %[xx3], #7 \n" - " add r3, %[yy3], r0, lsl #1 \n" - " \n" - " add r3, %[VRAM], r3 \n" - " ldrb r0, [r3, #1] \n" - " add %[AA], %[AA], %[daa] \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " add %[xx3], %[xx3], #1 \n" - " strneh r1, [%[p]] \n" - " \n" - " add %[CC], %[CC], %[dcc] \n" - " add %[p], %[p], #2 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - "3: \n" - : [xx3] "+r" (xx3), - [x] "+r" (width), - [p] "+r" (p), - [AA] "+r" (AA), - [CC] "+r" (CC) - : [yy3] "r" (yy3), - [daa] "r" (aa), - [dcc] "r" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors) - //[dir] "r" (dir) - : "r0", "r1", "r3", "cc" - ); - } - else - { - asm volatile ( - "1: \n" - " mov r3, %[AA], asr #18 \n" - " orrs r3, r3, %[CC], asr #18 \n" - " bne 2f \n" - " \n" - " mov r3, %[CC], asr #11 \n" - " mov r1, %[AA], asr #11 \n" - " add r3, r1, r3, lsl #7 \n" - " mov r3, r3, lsl #1 \n" - " ldrb r3, [%[VRAM], r3] \n" - " \n" - " and r1, %[CC], #(7 << 8) \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " and r0, %[AA], #(7 << 8) \n" - " add r3, r3, r1, asr #4 \n" - " add r3, r3, r0, asr #7 \n" - " \n" - " ldrb r0, [r3, #1] \n" - " add %[AA], %[AA], %[daa] \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " add %[xx3], %[xx3], #-1 \n" - " strneh r1, [%[p]] \n" - " \n" - " add %[CC], %[CC], %[dcc] \n" - " add %[p], %[p], #2 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - " b 3f \n" - "2: \n" - " and r0, %[xx3], #7 \n" - " add r3, %[yy3], r0, lsl #1 \n" - " \n" - " add r3, %[VRAM], r3 \n" - " ldrb r0, [r3, #1] \n" - " add %[AA], %[AA], %[daa] \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " add %[xx3], %[xx3], #-1 \n" - " strneh r1, [%[p]] \n" - " \n" - " add %[CC], %[CC], %[dcc] \n" - " add %[p], %[p], #2 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - "3: \n" - : [xx3] "+r" (xx3), - [x] "+r" (width), - [p] "+r" (p), - [AA] "+r" (AA), - [CC] "+r" (CC) - : [yy3] "r" (yy3), - [daa] "r" (aa), - [dcc] "r" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors) - //[dir] "r" (dir) - : "r0", "r1", "r3", "cc" - ); - } - } - } - - //fclose(f); - -} - -void DrawBGMode7Background16NewR1R2 (uint8 *Screen) -{ - int aa, cc; - int startx; - uint32 Left = 0; - uint32 Right = 256; - uint32 ClipCount = GFX.pCurrentClip->Count [0]; - - int32 HOffset; - int32 VOffset; - int32 CentreX; - int32 CentreY; - uint16 *p; - int yy; - int xx; - int BB; - int DD; - uint32 Line; - uint32 clip; - uint8 b; - uint32 AndByY; - uint32 AndByX = 0xffffffff; - if (Settings.Dezaemon && PPU.Mode7Repeat == 2) AndByX = 0x7ff; - AndByY = AndByX << 4; - AndByX = AndByX << 1; - - if (!ClipCount) ClipCount = 1; - - Screen += GFX.StartY * GFX_PITCH; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; - - for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, l++) { - HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; - VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; - - CentreX = ((int32) l->CentreX << M7) >> M7; - CentreY = ((int32) l->CentreY << M7) >> M7; - - if (PPU.Mode7VFlip) yy = 255 - (int) Line; - else yy = Line; - - yy += VOffset - CentreY; - xx = HOffset - CentreX; - - BB = l->MatrixB * yy + (CentreX << 8); - DD = l->MatrixD * yy + (CentreY << 8); - - for (clip = 0; clip < ClipCount; clip++) { - if (GFX.pCurrentClip->Count [0]){ - Left = GFX.pCurrentClip->Left [clip][0]; - Right = GFX.pCurrentClip->Right [clip][0]; - if (Right <= Left) continue; - } - p = (uint16 *) Screen + Left; - - if (PPU.Mode7HFlip) { - startx = Right - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - } else { - startx = Left; - aa = l->MatrixA; - cc = l->MatrixC; - } - asm volatile ( - "1: \n" - " mov r3, %[AA], asr #18 \n" - " orrs r3, r3, %[CC], asr #18 \n" - " bne 2f \n" - " \n" - " and r1, %[AndByY], %[CC], asr #4 \n" - " and r0, %[AndByX], %[AA], asr #7 \n" - " \n" - " and r3, r1, #0x7f \n" - " sub r3, r1, r3 \n" - " add r3, r3, r0, asr #4 \n" - " add r3, r3, r3 \n" - " ldrb r3, [%[VRAM], r3] \n" - " and r1, r1, #0x70 \n" - " \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " \n" - " and r0, r0, #14 \n" - " add r3, r3, r1 \n" - " add r3, r3, r0 \n" - " \n" - " ldrb r0, [r3, #1] \n" - " add %[AA], %[AA], %[daa] \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " add %[CC], %[CC], %[dcc] \n" - " strneh r1, [%[p]] \n" - " add %[p], %[p], #2 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - " b 3f \n" - "2: \n" - " add %[AA], %[AA], %[daa] \n" - " add %[CC], %[CC], %[dcc] \n" - " add %[p], %[p], #2 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - "3: \n" - : - : [x] "r" (Right - Left), - [AA] "r" (l->MatrixA * (startx + xx) + BB), - [CC] "r" (l->MatrixC * (startx + xx) + DD), - [daa] "r" (aa), - [dcc] "r" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors), - [p] "r" (p), - [AndByX] "r" (AndByX), - [AndByY] "r" (AndByY) - : "r0", "r1", "r3", "cc" - ); - } - } -} - - -void DrawBGMode7Background16NewR0 (uint8 *Screen) -{ - uint8 *VRAM1 = Memory.VRAM + 1; - int aa, cc; - int startx; - uint32 Left; - uint32 Right; - uint32 ClipCount = GFX.pCurrentClip->Count [0]; - - int32 HOffset; - int32 VOffset; - int32 CentreX; - int32 CentreY; - uint16 *p; -uint8 *z; - int yy; - int xx; - int BB; - int DD; - uint32 Line; - uint32 clip; - struct SLineMatrixData *l; - - - - Left = 0; - Right = 256; - - - if (!ClipCount) ClipCount = 1; - - - l = &LineMatrixData [GFX.StartY]; - Screen += GFX.StartY * GFX_PITCH; - - for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, l++) { - HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; - VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; - - CentreX = ((int32) l->CentreX << M7) >> M7; - CentreY = ((int32) l->CentreY << M7) >> M7; - - if (PPU.Mode7VFlip) yy = 255 - (int) Line; - else yy = Line; - - /*yy += (VOffset - CentreY) % 1023; - xx = (HOffset - CentreX) % 1023; -*/ - - yy += ((VOffset - CentreY) << (32-10+1)) >> (32-10+1) ; - xx = ((HOffset - CentreX) << (32-10+1)) >> (32-10+1); - - BB = l->MatrixB * yy + (CentreX << 8); - DD = l->MatrixD * yy + (CentreY << 8); - - for (clip = 0; clip < ClipCount; clip++) - { - if (GFX.pCurrentClip->Count [0]){ - Left = GFX.pCurrentClip->Left [clip][0]; - Right = GFX.pCurrentClip->Right [clip][0]; - if (Right <= Left) continue; - } - - p = (uint16 *) Screen + Left; - - - if (PPU.Mode7HFlip) { - startx = Right - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - } else { - startx = Left; - aa = l->MatrixA; - cc = l->MatrixC; - } - asm volatile ( - " \n" - "1: \n" - " and r1, %[AndByY], %[CC], asr #4 \n" - " and r3, r1, #0x7f \n" - " and r0, %[AndByX], %[AA], asr #7 \n" - " sub r3, r1, r3 \n" - " add r3, r3, r0, asr #4 \n" - " add r3, r3, r3 \n" - " ldrb r3, [%[VRAM], r3] \n" - " \n" - " and r1, r1, #0x70 \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " \n" - " and r0, r0, #14 \n" - " add r3, r3, r1 \n" - " add r3, r3, r0 \n" - " \n" - " ldrb r0, [r3, #1] \n" - " add %[AA], %[AA], %[daa] \n" - " movs r0, r0, lsl #2 \n" - " add %[CC], %[CC], %[dcc] \n" - " ldrne r1, [%[colors], r0] \n" - " add %[p], %[p], #2 \n" - " strneh r1, [%[p]] \n" - " \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - : - : [x] "r" (Right - Left), - [AA] "r" (l->MatrixA * (startx + xx) + BB), - [CC] "r" (l->MatrixC * (startx + xx) + DD), - [daa] "r" (aa), - [dcc] "r" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors), - [p] "r" (p), - [AndByX] "r" (0x3ff << 1), - [AndByY] "r" (0x3ff << 4) - : "r0", "r1", "r3", "cc" - ); - - } - } - -} - - diff --git a/src/mode7prio.c b/src/mode7prio.c new file mode 100644 index 0000000..2b9a3a2 --- /dev/null +++ b/src/mode7prio.c @@ -0,0 +1,603 @@ +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" +#include "display.h" +#include "gfx.h" +#include "apu.h" + +extern SLineData LineData[240]; +extern SLineMatrixData LineMatrixData [240]; +extern uint8 Mode7Depths [2]; + +#define M7 19 + +/* +void DrawBGMode7Background16Prio (uint8 *Screen, int bg) +{ + RENDER_BACKGROUND_MODE7PRIO (GFX.ScreenColors [b & 0x7f]); +} +*/ + + +#ifdef __DEBUG__ + + #define DMSG(rop) printf("Rendering Mode7 w/prio, ROp: " rop ", R:%d, r2130: %d, bg: %d\n", PPU.Mode7Repeat, GFX.r2130 & 1, bg) +#else + #define DMSG(rop) +#endif + +void DrawBGMode7Background16PrioR0 (uint8 *Screen, int bg); +void DrawBGMode7Background16PrioR1R2 (uint8 *Screen, int bg); +void DrawBGMode7Background16PrioR3 (uint8 *Screen, int bg); + +void DrawBGMode7Background16Prio (uint8 *Screen, int bg) +{ + DMSG("opaque"); + CHECK_SOUND(); + + if (GFX.r2130 & 1) { + if (IPPU.DirectColourMapsNeedRebuild) S9xBuildDirectColourMaps (); + GFX.ScreenColors = DirectColourMaps [0]; + } else GFX.ScreenColors = IPPU.ScreenColors; + + switch (PPU.Mode7Repeat) { + case 0: + DrawBGMode7Background16PrioR0(Screen, bg); + return; + case 3: + DrawBGMode7Background16PrioR3(Screen, bg); + return; + default: + DrawBGMode7Background16PrioR1R2(Screen, bg); + return; + } +} + +#define M7C 0x1fff + +void DrawBGMode7Background16PrioR3 (uint8 *Screen, int bg) +{ + + uint8 *VRAM1 = Memory.VRAM + 1; + int aa, cc; + int startx; + uint32 Left = 0; + uint32 Right = 256; + uint32 ClipCount = GFX.pCurrentClip->Count [0]; + + int32 HOffset; + int32 VOffset; + int32 CentreX; + int32 CentreY; + uint8 *d; + uint16 *p; + int dir; + int yy; + int xx; + int BB; + int DD; + uint32 Line; + uint32 clip; + uint8 b; + uint8 *Depth; + uint32 depth = Mode7Depths[0] | (Mode7Depths[1] << 8); + + if (!ClipCount) ClipCount = 1; + + Screen += GFX.StartY * GFX_PITCH; + Depth = GFX.DB + GFX.StartY * GFX_PPL; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + + for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { + HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; + VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; + + CentreX = ((int32) l->CentreX << M7) >> M7; + CentreY = ((int32) l->CentreY << M7) >> M7; + + if (PPU.Mode7VFlip) yy = 255 - (int) Line; + else yy = Line; + + yy += VOffset - CentreY; + xx = HOffset - CentreX; + + BB = l->MatrixB * yy + (CentreX << 8); + DD = l->MatrixD * yy + (CentreY << 8); + + for (clip = 0; clip < ClipCount; clip++) + { + if (GFX.pCurrentClip->Count [0]){ + Left = GFX.pCurrentClip->Left [clip][0]; + Right = GFX.pCurrentClip->Right [clip][0]; + if (Right <= Left) continue; + } + p = (uint16 *) Screen + Left; + d = Depth + Left; + + if (PPU.Mode7HFlip) { + startx = Right - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + dir = -1; + } else { + startx = Left; + aa = l->MatrixA; + cc = l->MatrixC; + dir = 1; + } + + if (dir == 1) + { + __asm__ volatile ( + "1: \n" + " mov r3, %[AA], lsr #18 \n" + " orrs r3, r3, %[CC], lsr #18 \n" + " bne 2f \n" + " \n" + " mov r3, %[CC], lsr #11 \n" + " mov r1, %[AA], lsr #11 \n" + " add r3, r1, r3, lsl #7 \n" + " mov r3, r3, lsl #1 \n" + " ldrb r3, [%[VRAM], r3] \n" + " \n" + " mov r1, %[CC], lsr #8 \n" + " mov r0, %[AA], lsr #8 \n" + " \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " \n" + " and r1, r1, #7 \n" + " and r0, r0, #7 \n" + " add r3, r3, r1, lsl #4 \n" + " add r3, r3, r0, lsl #1 \n" + " \n" + " ldrb r0, [r3, #1] \n" + " ldrb r3, [%[d]] \n" + " tst r0, #0x80 \n" + " andeq r1, %[depth], #0xff \n" + " mov r1, %[depth], lsr #8 \n" + " cmp r1, r3 \n" + " bls 4f \n" + + " ldr r1, %[daa] \n" + " movs r0, r0, lsl #2 \n" + " add %[AA], %[AA], r1 \n" + " ldrne r1, [%[colors], r0] \n" + " add %[xx3], %[xx3], #1 \n" + " strneb %[depth], [%[d]] \n" + " ldr r0, %[dcc] \n" + " strneh r1, [%[p]] \n" + " \n" + " add %[CC], %[CC], r0 \n" + " add %[d], %[d], #1 \n" + " add %[p], %[p], #2 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + " b 3f \n" + "2: \n" + " and r1, %[yy3], #7 \n" + " and r0, %[xx3], #7 \n" + " mov r3, r1, lsl #4 \n" + " add r3, r3, r0, lsl #1 \n" + " \n" + " add r3, %[VRAM], r3 \n" + + " ldrb r0, [r3, #1] \n" + " ldrb r3, [%[d]] \n" + " tst r0, #0x80 \n" + " andeq r1, %[depth], #0xff \n" + " mov r1, %[depth], lsr #8 \n" + " cmp r1, r3 \n" + " bls 4f \n" + + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " strneb %[depth], [%[d]] \n" + " strneh r1, [%[p]] \n" + "4: \n" + " ldr r0, %[daa] \n" + " ldr r1, %[dcc] \n" + " add %[xx3], %[xx3], #1 \n" + " add %[AA], %[AA], r0 \n" + " add %[CC], %[CC], r1 \n" + " add %[p], %[p], #2 \n" + " add %[d], %[d], #1 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + "3: \n" + : + : [x] "r" (Right - Left), + [AA] "r" (l->MatrixA * (startx + xx) + BB), + [CC] "r" (l->MatrixC * (startx + xx) + DD), + [daa] "m" (aa), + [dcc] "m" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors), + [p] "r" (p), + [d] "r" (d), + [depth] "r" (depth), + //[dir] "r" (dir), + [yy3] "r" (yy + CentreY), + [xx3] "r" (startx + HOffset) + : "r0", "r1", "r3", "cc" + ); + } + else + { + __asm__ volatile ( + "1: \n" + " mov r3, %[AA], lsr #18 \n" + " orrs r3, r3, %[CC], lsr #18 \n" + " bne 2f \n" + " \n" + " mov r3, %[CC], lsr #11 \n" + " mov r1, %[AA], lsr #11 \n" + " add r3, r1, r3, lsl #7 \n" + " mov r3, r3, lsl #1 \n" + " ldrb r3, [%[VRAM], r3] \n" + " \n" + " mov r1, %[CC], lsr #8 \n" + " mov r0, %[AA], lsr #8 \n" + " \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " \n" + " and r1, r1, #7 \n" + " and r0, r0, #7 \n" + " add r3, r3, r1, lsl #4 \n" + " add r3, r3, r0, lsl #1 \n" + " \n" + " ldrb r0, [r3, #1] \n" + " ldrb r3, [%[d]] \n" + " tst r0, #0x80 \n" + " andeq r1, %[depth], #0xff \n" + " mov r1, %[depth], lsr #8 \n" + " cmp r1, r3 \n" + " bls 4f \n" + + " ldr r1, %[daa] \n" + " movs r0, r0, lsl #2 \n" + " add %[AA], %[AA], r1 \n" + " ldrne r1, [%[colors], r0] \n" + " add %[xx3], %[xx3], #-1 \n" + " strneb %[depth], [%[d]] \n" + " ldr r0, %[dcc] \n" + " strneh r1, [%[p]] \n" + " \n" + " add %[CC], %[CC], r0 \n" + " add %[d], %[d], #1 \n" + " add %[p], %[p], #2 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + " b 3f \n" + "2: \n" + " and r1, %[yy3], #7 \n" + " and r0, %[xx3], #7 \n" + " mov r3, r1, lsl #4 \n" + " add r3, r3, r0, lsl #1 \n" + " \n" + " add r3, %[VRAM], r3 \n" + + " ldrb r0, [r3, #1] \n" + " ldrb r3, [%[d]] \n" + " tst r0, #0x80 \n" + " andeq r1, %[depth], #0xff \n" + " mov r1, %[depth], lsr #8 \n" + " cmp r1, r3 \n" + " bls 4f \n" + + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " strneb %[depth], [%[d]] \n" + " strneh r1, [%[p]] \n" + "4: \n" + " ldr r0, %[daa] \n" + " ldr r1, %[dcc] \n" + " add %[xx3], %[xx3], #-1 \n" + " add %[AA], %[AA], r0 \n" + " add %[CC], %[CC], r1 \n" + " add %[p], %[p], #2 \n" + " add %[d], %[d], #1 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + "3: \n" + : + : [x] "r" (Right - Left), + [AA] "r" (l->MatrixA * (startx + xx) + BB), + [CC] "r" (l->MatrixC * (startx + xx) + DD), + [daa] "m" (aa), + [dcc] "m" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors), + [p] "r" (p), + [d] "r" (d), + [depth] "r" (depth), + //[dir] "r" (dir), + [yy3] "r" (yy + CentreY), + [xx3] "r" (startx + HOffset) + : "r0", "r1", "r3", "cc" + ); + } + } + } + +} + +void DrawBGMode7Background16PrioR1R2 (uint8 *Screen, int bg) +{ + + int aa, cc; + int startx; + uint32 Left = 0; + uint32 Right = 256; + uint32 ClipCount = GFX.pCurrentClip->Count [0]; + + int32 HOffset; + int32 VOffset; + int32 CentreX; + int32 CentreY; + uint8 *d; + uint16 *p; + int yy; + int xx; + int BB; + int DD; + uint32 Line; + uint32 clip; + uint8 b; + uint32 AndByY; + uint32 AndByX = 0xffffffff; + if (Settings.Dezaemon && PPU.Mode7Repeat == 2) AndByX = 0x7ff; + AndByY = AndByX << 4; + AndByX = AndByX << 1; + uint8 *Depth; + uint32 depth = Mode7Depths[0] | (Mode7Depths[1] << 8); + + if (!ClipCount) ClipCount = 1; + + Screen += GFX.StartY * GFX_PITCH; + Depth = GFX.DB + GFX.StartY * GFX_PPL; + + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + + for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { + HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; + VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; + + CentreX = ((int32) l->CentreX << M7) >> M7; + CentreY = ((int32) l->CentreY << M7) >> M7; + + if (PPU.Mode7VFlip) yy = 255 - (int) Line; + else yy = Line; + + yy += VOffset - CentreY; + xx = HOffset - CentreX; + + BB = l->MatrixB * yy + (CentreX << 8); + DD = l->MatrixD * yy + (CentreY << 8); + + for (clip = 0; clip < ClipCount; clip++) { + if (GFX.pCurrentClip->Count [0]){ + Left = GFX.pCurrentClip->Left [clip][0]; + Right = GFX.pCurrentClip->Right [clip][0]; + if (Right <= Left) continue; + } + p = (uint16 *) Screen + Left; + d = Depth + Left; + + if (PPU.Mode7HFlip) { + startx = Right - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + } else { + startx = Left; + aa = l->MatrixA; + cc = l->MatrixC; + } + __asm__ volatile ( + "1: \n" + " mov r3, %[AA], lsr #18 \n" + " orrs r3, r3, %[CC], lsr #18 \n" + " bne 2f \n" + " \n" + " ldr r1, %[AndByY] \n" + " ldr r0, %[AndByX] \n" + " and r1, r1, %[CC], lsr #4 \n" + " and r0, r0, %[AA], lsr #7 \n" + " \n" + " and r3, r1, #0x7f \n" + " sub r3, r1, r3 \n" + " add r3, r3, r0, lsr #4 \n" + " add r3, r3, r3 \n" + " ldrb r3, [%[VRAM], r3] \n" + " and r1, r1, #0x70 \n" + " \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " \n" + " and r0, r0, #14 \n" + " add r3, r3, r1 \n" + " add r3, r3, r0 \n" + " \n" + " ldrb r0, [r3, #1] \n" + " ldrb r3, [%[d]] \n" + " tst r0, #0x80 \n" + " andeq r1, %[depth], #0xff \n" + " mov r1, %[depth], lsr #8 \n" + " cmp r1, r3 \n" + " bls 2f \n" + + " add %[AA], %[AA], %[daa] \n" + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " strneb %[depth], [%[d]] \n" + " add %[CC], %[CC], %[dcc] \n" + " strneh r1, [%[p]] \n" + " add %[p], %[p], #2 \n" + " add %[d], %[d], #1 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + " b 3f \n" + "2: \n" + " add %[AA], %[AA], %[daa] \n" + " add %[CC], %[CC], %[dcc] \n" + " add %[p], %[p], #2 \n" + " add %[d], %[d], #1 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + "3: \n" + : + : [x] "r" (Right - Left), + [AA] "r" (l->MatrixA * (startx + xx) + BB), + [CC] "r" (l->MatrixC * (startx + xx) + DD), + [daa] "r" (aa), + [dcc] "r" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors), + [p] "r" (p), + [d] "r" (d), + [depth] "r" (depth), + [AndByX] "m" (AndByX), + [AndByY] "m" (AndByY) + : "r0", "r1", "r3", "cc" + ); + } + } +} + + +void DrawBGMode7Background16PrioR0 (uint8 *Screen, int bg) +{ + uint8 *VRAM1 = Memory.VRAM + 1; + int aa, cc; + int startx; + uint32 Left; + uint32 Right; + uint32 ClipCount = GFX.pCurrentClip->Count [0]; + + int32 HOffset; + int32 VOffset; + int32 CentreX; + int32 CentreY; + uint16 *p; + uint8 *d; + int yy; + int xx; + int BB; + int DD; + uint32 Line; + uint32 clip; + SLineMatrixData *l; + uint8 *Depth; + uint32 depth = Mode7Depths[0] | (Mode7Depths[1] << 8); + + Left = 0; + Right = 256; + + + if (!ClipCount) ClipCount = 1; + + + l = &LineMatrixData [GFX.StartY]; + Screen += GFX.StartY * GFX_PITCH; + Depth = GFX.DB + GFX.StartY * GFX_PPL; + + for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { + HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; + VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; + + CentreX = ((int32) l->CentreX << M7) >> M7; + CentreY = ((int32) l->CentreY << M7) >> M7; + + if (PPU.Mode7VFlip) yy = 255 - (int) Line; + else yy = Line; + + yy += (VOffset - CentreY) % 1023; + xx = (HOffset - CentreX) % 1023; + + BB = l->MatrixB * yy + (CentreX << 8); + DD = l->MatrixD * yy + (CentreY << 8); + + for (clip = 0; clip < ClipCount; clip++) + { + if (GFX.pCurrentClip->Count [0]){ + Left = GFX.pCurrentClip->Left [clip][0]; + Right = GFX.pCurrentClip->Right [clip][0]; + if (Right <= Left) continue; + } + + p = (uint16 *) Screen + Left; + d = Depth + Left; + + if (PPU.Mode7HFlip) { + startx = Right - 1; + aa = -l->MatrixA; + cc = -l->MatrixC; + } else { + startx = Left; + aa = l->MatrixA; + cc = l->MatrixC; + } + __asm__ volatile ( + " b 1f \n" + "7: \n" // AndByX + " .word (0x3ff << 1) \n" + "8: \n" // AndByY + " .word (0x3ff << 4) \n" + " \n" + "1: \n" + " ldr r3, 8b \n" + " ldr r0, 7b \n" + " and r1, r3, %[CC], lsr #4 \n" + " and r3, r1, #0x7f \n" + " and r0, r0, %[AA], lsr #7 \n" + " sub r3, r1, r3 \n" + " add r3, r3, r0, lsr #4 \n" + " add r3, r3, r3 \n" + " ldrb r3, [%[VRAM], r3] \n" + " \n" + " and r1, r1, #0x70 \n" + " add r3, %[VRAM], r3, lsl #7 \n" + " \n" + " and r0, r0, #14 \n" + " add r3, r3, r1 \n" + " add r3, r3, r0 \n" + " \n" + " ldrb r0, [r3, #1] \n" + " ldrb r3, [%[d]] \n" + " tst r0, #0x80 \n" + " andeq r1, %[depth], #0xff \n" + " mov r1, %[depth], lsr #8 \n" + " cmp r1, r3 \n" + " bls 2f \n" + + " movs r0, r0, lsl #2 \n" + " ldrne r1, [%[colors], r0] \n" + " strneb %[depth], [%[d]] \n" + " strneh r1, [%[p]] \n" + " \n" + "2: \n" + " add %[AA], %[AA], %[daa] \n" + " add %[CC], %[CC], %[dcc] \n" + " add %[p], %[p], #2 \n" + " add %[d], %[d], #1 \n" + " subs %[x], %[x], #1 \n" + " bne 1b \n" + : + : [x] "r" (Right - Left), + [AA] "r" (l->MatrixA * (startx + xx) + BB), + [CC] "r" (l->MatrixC * (startx + xx) + DD), + [daa] "r" (aa), + [dcc] "r" (cc), + [VRAM] "r" (Memory.VRAM), + [colors] "r" (GFX.ScreenColors), + [p] "r" (p), + [d] "r" (d), + [depth] "r" (depth) + : "r0", "r1", "r3", "cc" + ); + + } + } + +} + + diff --git a/src/mode7prio.cpp b/src/mode7prio.cpp deleted file mode 100644 index c149eb5..0000000 --- a/src/mode7prio.cpp +++ /dev/null @@ -1,603 +0,0 @@ -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "display.h" -#include "gfx.h" -#include "apu.h" - -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; -extern uint8 Mode7Depths [2]; - -#define M7 19 - -/* -void DrawBGMode7Background16Prio (uint8 *Screen, int bg) -{ - RENDER_BACKGROUND_MODE7PRIO (GFX.ScreenColors [b & 0x7f]); -} -*/ - - -#ifdef __DEBUG__ - - #define DMSG(rop) printf("Rendering Mode7 w/prio, ROp: " rop ", R:%d, r2130: %d, bg: %d\n", PPU.Mode7Repeat, GFX.r2130 & 1, bg) -#else - #define DMSG(rop) -#endif - -void DrawBGMode7Background16PrioR0 (uint8 *Screen, int bg); -void DrawBGMode7Background16PrioR1R2 (uint8 *Screen, int bg); -void DrawBGMode7Background16PrioR3 (uint8 *Screen, int bg); - -void DrawBGMode7Background16Prio (uint8 *Screen, int bg) -{ - DMSG("opaque"); - CHECK_SOUND(); - - if (GFX.r2130 & 1) { - if (IPPU.DirectColourMapsNeedRebuild) S9xBuildDirectColourMaps (); - GFX.ScreenColors = DirectColourMaps [0]; - } else GFX.ScreenColors = IPPU.ScreenColors; - - switch (PPU.Mode7Repeat) { - case 0: - DrawBGMode7Background16PrioR0(Screen, bg); - return; - case 3: - DrawBGMode7Background16PrioR3(Screen, bg); - return; - default: - DrawBGMode7Background16PrioR1R2(Screen, bg); - return; - } -} - -#define M7C 0x1fff - -void DrawBGMode7Background16PrioR3 (uint8 *Screen, int bg) -{ - - uint8 *VRAM1 = Memory.VRAM + 1; - int aa, cc; - int startx; - uint32 Left = 0; - uint32 Right = 256; - uint32 ClipCount = GFX.pCurrentClip->Count [0]; - - int32 HOffset; - int32 VOffset; - int32 CentreX; - int32 CentreY; - uint8 *d; - uint16 *p; - int dir; - int yy; - int xx; - int BB; - int DD; - uint32 Line; - uint32 clip; - uint8 b; - uint8 *Depth; - uint32 depth = Mode7Depths[0] | (Mode7Depths[1] << 8); - - if (!ClipCount) ClipCount = 1; - - Screen += GFX.StartY * GFX_PITCH; - Depth = GFX.DB + GFX.StartY * GFX_PPL; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; - - for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { - HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; - VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; - - CentreX = ((int32) l->CentreX << M7) >> M7; - CentreY = ((int32) l->CentreY << M7) >> M7; - - if (PPU.Mode7VFlip) yy = 255 - (int) Line; - else yy = Line; - - yy += VOffset - CentreY; - xx = HOffset - CentreX; - - BB = l->MatrixB * yy + (CentreX << 8); - DD = l->MatrixD * yy + (CentreY << 8); - - for (clip = 0; clip < ClipCount; clip++) - { - if (GFX.pCurrentClip->Count [0]){ - Left = GFX.pCurrentClip->Left [clip][0]; - Right = GFX.pCurrentClip->Right [clip][0]; - if (Right <= Left) continue; - } - p = (uint16 *) Screen + Left; - d = Depth + Left; - - if (PPU.Mode7HFlip) { - startx = Right - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - dir = -1; - } else { - startx = Left; - aa = l->MatrixA; - cc = l->MatrixC; - dir = 1; - } - - if (dir == 1) - { - asm volatile ( - "1: \n" - " mov r3, %[AA], lsr #18 \n" - " orrs r3, r3, %[CC], lsr #18 \n" - " bne 2f \n" - " \n" - " mov r3, %[CC], lsr #11 \n" - " mov r1, %[AA], lsr #11 \n" - " add r3, r1, r3, lsl #7 \n" - " mov r3, r3, lsl #1 \n" - " ldrb r3, [%[VRAM], r3] \n" - " \n" - " mov r1, %[CC], lsr #8 \n" - " mov r0, %[AA], lsr #8 \n" - " \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " \n" - " and r1, r1, #7 \n" - " and r0, r0, #7 \n" - " add r3, r3, r1, lsl #4 \n" - " add r3, r3, r0, lsl #1 \n" - " \n" - " ldrb r0, [r3, #1] \n" - " ldrb r3, [%[d]] \n" - " tst r0, #0x80 \n" - " andeq r1, %[depth], #0xff \n" - " mov r1, %[depth], lsr #8 \n" - " cmp r1, r3 \n" - " bls 4f \n" - - " ldr r1, %[daa] \n" - " movs r0, r0, lsl #2 \n" - " add %[AA], %[AA], r1 \n" - " ldrne r1, [%[colors], r0] \n" - " add %[xx3], %[xx3], #1 \n" - " strneb %[depth], [%[d]] \n" - " ldr r0, %[dcc] \n" - " strneh r1, [%[p]] \n" - " \n" - " add %[CC], %[CC], r0 \n" - " add %[d], %[d], #1 \n" - " add %[p], %[p], #2 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - " b 3f \n" - "2: \n" - " and r1, %[yy3], #7 \n" - " and r0, %[xx3], #7 \n" - " mov r3, r1, lsl #4 \n" - " add r3, r3, r0, lsl #1 \n" - " \n" - " add r3, %[VRAM], r3 \n" - - " ldrb r0, [r3, #1] \n" - " ldrb r3, [%[d]] \n" - " tst r0, #0x80 \n" - " andeq r1, %[depth], #0xff \n" - " mov r1, %[depth], lsr #8 \n" - " cmp r1, r3 \n" - " bls 4f \n" - - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " strneb %[depth], [%[d]] \n" - " strneh r1, [%[p]] \n" - "4: \n" - " ldr r0, %[daa] \n" - " ldr r1, %[dcc] \n" - " add %[xx3], %[xx3], #1 \n" - " add %[AA], %[AA], r0 \n" - " add %[CC], %[CC], r1 \n" - " add %[p], %[p], #2 \n" - " add %[d], %[d], #1 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - "3: \n" - : - : [x] "r" (Right - Left), - [AA] "r" (l->MatrixA * (startx + xx) + BB), - [CC] "r" (l->MatrixC * (startx + xx) + DD), - [daa] "m" (aa), - [dcc] "m" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors), - [p] "r" (p), - [d] "r" (d), - [depth] "r" (depth), - //[dir] "r" (dir), - [yy3] "r" (yy + CentreY), - [xx3] "r" (startx + HOffset) - : "r0", "r1", "r3", "cc" - ); - } - else - { - asm volatile ( - "1: \n" - " mov r3, %[AA], lsr #18 \n" - " orrs r3, r3, %[CC], lsr #18 \n" - " bne 2f \n" - " \n" - " mov r3, %[CC], lsr #11 \n" - " mov r1, %[AA], lsr #11 \n" - " add r3, r1, r3, lsl #7 \n" - " mov r3, r3, lsl #1 \n" - " ldrb r3, [%[VRAM], r3] \n" - " \n" - " mov r1, %[CC], lsr #8 \n" - " mov r0, %[AA], lsr #8 \n" - " \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " \n" - " and r1, r1, #7 \n" - " and r0, r0, #7 \n" - " add r3, r3, r1, lsl #4 \n" - " add r3, r3, r0, lsl #1 \n" - " \n" - " ldrb r0, [r3, #1] \n" - " ldrb r3, [%[d]] \n" - " tst r0, #0x80 \n" - " andeq r1, %[depth], #0xff \n" - " mov r1, %[depth], lsr #8 \n" - " cmp r1, r3 \n" - " bls 4f \n" - - " ldr r1, %[daa] \n" - " movs r0, r0, lsl #2 \n" - " add %[AA], %[AA], r1 \n" - " ldrne r1, [%[colors], r0] \n" - " add %[xx3], %[xx3], #-1 \n" - " strneb %[depth], [%[d]] \n" - " ldr r0, %[dcc] \n" - " strneh r1, [%[p]] \n" - " \n" - " add %[CC], %[CC], r0 \n" - " add %[d], %[d], #1 \n" - " add %[p], %[p], #2 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - " b 3f \n" - "2: \n" - " and r1, %[yy3], #7 \n" - " and r0, %[xx3], #7 \n" - " mov r3, r1, lsl #4 \n" - " add r3, r3, r0, lsl #1 \n" - " \n" - " add r3, %[VRAM], r3 \n" - - " ldrb r0, [r3, #1] \n" - " ldrb r3, [%[d]] \n" - " tst r0, #0x80 \n" - " andeq r1, %[depth], #0xff \n" - " mov r1, %[depth], lsr #8 \n" - " cmp r1, r3 \n" - " bls 4f \n" - - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " strneb %[depth], [%[d]] \n" - " strneh r1, [%[p]] \n" - "4: \n" - " ldr r0, %[daa] \n" - " ldr r1, %[dcc] \n" - " add %[xx3], %[xx3], #-1 \n" - " add %[AA], %[AA], r0 \n" - " add %[CC], %[CC], r1 \n" - " add %[p], %[p], #2 \n" - " add %[d], %[d], #1 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - "3: \n" - : - : [x] "r" (Right - Left), - [AA] "r" (l->MatrixA * (startx + xx) + BB), - [CC] "r" (l->MatrixC * (startx + xx) + DD), - [daa] "m" (aa), - [dcc] "m" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors), - [p] "r" (p), - [d] "r" (d), - [depth] "r" (depth), - //[dir] "r" (dir), - [yy3] "r" (yy + CentreY), - [xx3] "r" (startx + HOffset) - : "r0", "r1", "r3", "cc" - ); - } - } - } - -} - -void DrawBGMode7Background16PrioR1R2 (uint8 *Screen, int bg) -{ - - int aa, cc; - int startx; - uint32 Left = 0; - uint32 Right = 256; - uint32 ClipCount = GFX.pCurrentClip->Count [0]; - - int32 HOffset; - int32 VOffset; - int32 CentreX; - int32 CentreY; - uint8 *d; - uint16 *p; - int yy; - int xx; - int BB; - int DD; - uint32 Line; - uint32 clip; - uint8 b; - uint32 AndByY; - uint32 AndByX = 0xffffffff; - if (Settings.Dezaemon && PPU.Mode7Repeat == 2) AndByX = 0x7ff; - AndByY = AndByX << 4; - AndByX = AndByX << 1; - uint8 *Depth; - uint32 depth = Mode7Depths[0] | (Mode7Depths[1] << 8); - - if (!ClipCount) ClipCount = 1; - - Screen += GFX.StartY * GFX_PITCH; - Depth = GFX.DB + GFX.StartY * GFX_PPL; - - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; - - for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { - HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; - VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; - - CentreX = ((int32) l->CentreX << M7) >> M7; - CentreY = ((int32) l->CentreY << M7) >> M7; - - if (PPU.Mode7VFlip) yy = 255 - (int) Line; - else yy = Line; - - yy += VOffset - CentreY; - xx = HOffset - CentreX; - - BB = l->MatrixB * yy + (CentreX << 8); - DD = l->MatrixD * yy + (CentreY << 8); - - for (clip = 0; clip < ClipCount; clip++) { - if (GFX.pCurrentClip->Count [0]){ - Left = GFX.pCurrentClip->Left [clip][0]; - Right = GFX.pCurrentClip->Right [clip][0]; - if (Right <= Left) continue; - } - p = (uint16 *) Screen + Left; - d = Depth + Left; - - if (PPU.Mode7HFlip) { - startx = Right - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - } else { - startx = Left; - aa = l->MatrixA; - cc = l->MatrixC; - } - asm volatile ( - "1: \n" - " mov r3, %[AA], lsr #18 \n" - " orrs r3, r3, %[CC], lsr #18 \n" - " bne 2f \n" - " \n" - " ldr r1, %[AndByY] \n" - " ldr r0, %[AndByX] \n" - " and r1, r1, %[CC], lsr #4 \n" - " and r0, r0, %[AA], lsr #7 \n" - " \n" - " and r3, r1, #0x7f \n" - " sub r3, r1, r3 \n" - " add r3, r3, r0, lsr #4 \n" - " add r3, r3, r3 \n" - " ldrb r3, [%[VRAM], r3] \n" - " and r1, r1, #0x70 \n" - " \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " \n" - " and r0, r0, #14 \n" - " add r3, r3, r1 \n" - " add r3, r3, r0 \n" - " \n" - " ldrb r0, [r3, #1] \n" - " ldrb r3, [%[d]] \n" - " tst r0, #0x80 \n" - " andeq r1, %[depth], #0xff \n" - " mov r1, %[depth], lsr #8 \n" - " cmp r1, r3 \n" - " bls 2f \n" - - " add %[AA], %[AA], %[daa] \n" - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " strneb %[depth], [%[d]] \n" - " add %[CC], %[CC], %[dcc] \n" - " strneh r1, [%[p]] \n" - " add %[p], %[p], #2 \n" - " add %[d], %[d], #1 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - " b 3f \n" - "2: \n" - " add %[AA], %[AA], %[daa] \n" - " add %[CC], %[CC], %[dcc] \n" - " add %[p], %[p], #2 \n" - " add %[d], %[d], #1 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - "3: \n" - : - : [x] "r" (Right - Left), - [AA] "r" (l->MatrixA * (startx + xx) + BB), - [CC] "r" (l->MatrixC * (startx + xx) + DD), - [daa] "r" (aa), - [dcc] "r" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors), - [p] "r" (p), - [d] "r" (d), - [depth] "r" (depth), - [AndByX] "m" (AndByX), - [AndByY] "m" (AndByY) - : "r0", "r1", "r3", "cc" - ); - } - } -} - - -void DrawBGMode7Background16PrioR0 (uint8 *Screen, int bg) -{ - uint8 *VRAM1 = Memory.VRAM + 1; - int aa, cc; - int startx; - uint32 Left; - uint32 Right; - uint32 ClipCount = GFX.pCurrentClip->Count [0]; - - int32 HOffset; - int32 VOffset; - int32 CentreX; - int32 CentreY; - uint16 *p; - uint8 *d; - int yy; - int xx; - int BB; - int DD; - uint32 Line; - uint32 clip; - struct SLineMatrixData *l; - uint8 *Depth; - uint32 depth = Mode7Depths[0] | (Mode7Depths[1] << 8); - - Left = 0; - Right = 256; - - - if (!ClipCount) ClipCount = 1; - - - l = &LineMatrixData [GFX.StartY]; - Screen += GFX.StartY * GFX_PITCH; - Depth = GFX.DB + GFX.StartY * GFX_PPL; - - for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { - HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; - VOffset = ((int32) LineData[Line].BG[0].VOffset << M7) >> M7; - - CentreX = ((int32) l->CentreX << M7) >> M7; - CentreY = ((int32) l->CentreY << M7) >> M7; - - if (PPU.Mode7VFlip) yy = 255 - (int) Line; - else yy = Line; - - yy += (VOffset - CentreY) % 1023; - xx = (HOffset - CentreX) % 1023; - - BB = l->MatrixB * yy + (CentreX << 8); - DD = l->MatrixD * yy + (CentreY << 8); - - for (clip = 0; clip < ClipCount; clip++) - { - if (GFX.pCurrentClip->Count [0]){ - Left = GFX.pCurrentClip->Left [clip][0]; - Right = GFX.pCurrentClip->Right [clip][0]; - if (Right <= Left) continue; - } - - p = (uint16 *) Screen + Left; - d = Depth + Left; - - if (PPU.Mode7HFlip) { - startx = Right - 1; - aa = -l->MatrixA; - cc = -l->MatrixC; - } else { - startx = Left; - aa = l->MatrixA; - cc = l->MatrixC; - } - asm volatile ( - " b 1f \n" - "7: \n" // AndByX - " .word (0x3ff << 1) \n" - "8: \n" // AndByY - " .word (0x3ff << 4) \n" - " \n" - "1: \n" - " ldr r3, 8b \n" - " ldr r0, 7b \n" - " and r1, r3, %[CC], lsr #4 \n" - " and r3, r1, #0x7f \n" - " and r0, r0, %[AA], lsr #7 \n" - " sub r3, r1, r3 \n" - " add r3, r3, r0, lsr #4 \n" - " add r3, r3, r3 \n" - " ldrb r3, [%[VRAM], r3] \n" - " \n" - " and r1, r1, #0x70 \n" - " add r3, %[VRAM], r3, lsl #7 \n" - " \n" - " and r0, r0, #14 \n" - " add r3, r3, r1 \n" - " add r3, r3, r0 \n" - " \n" - " ldrb r0, [r3, #1] \n" - " ldrb r3, [%[d]] \n" - " tst r0, #0x80 \n" - " andeq r1, %[depth], #0xff \n" - " mov r1, %[depth], lsr #8 \n" - " cmp r1, r3 \n" - " bls 2f \n" - - " movs r0, r0, lsl #2 \n" - " ldrne r1, [%[colors], r0] \n" - " strneb %[depth], [%[d]] \n" - " strneh r1, [%[p]] \n" - " \n" - "2: \n" - " add %[AA], %[AA], %[daa] \n" - " add %[CC], %[CC], %[dcc] \n" - " add %[p], %[p], #2 \n" - " add %[d], %[d], #1 \n" - " subs %[x], %[x], #1 \n" - " bne 1b \n" - : - : [x] "r" (Right - Left), - [AA] "r" (l->MatrixA * (startx + xx) + BB), - [CC] "r" (l->MatrixC * (startx + xx) + DD), - [daa] "r" (aa), - [dcc] "r" (cc), - [VRAM] "r" (Memory.VRAM), - [colors] "r" (GFX.ScreenColors), - [p] "r" (p), - [d] "r" (d), - [depth] "r" (depth) - : "r0", "r1", "r3", "cc" - ); - - } - } - -} - - diff --git a/src/mode7prio_t.h b/src/mode7prio_t.h index 8f1e7e4..889d8b9 100644 --- a/src/mode7prio_t.h +++ b/src/mode7prio_t.h @@ -6,8 +6,8 @@ #include "gfx.h" #include "apu.h" -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; +extern SLineData LineData[240]; +extern SLineMatrixData LineMatrixData [240]; extern uint8 Mode7Depths [2]; #define M7 19 @@ -48,7 +48,7 @@ static void DrawBGMode7Background16R3 (uint8 *Screen, int bg) Screen += GFX.StartY * GFX_PITCH; Depth = GFX.DB + GFX.StartY * GFX_PPL; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; @@ -93,7 +93,7 @@ static void DrawBGMode7Background16R3 (uint8 *Screen, int bg) xx3 = (startx + HOffset); - asm volatile ( + __asm__ volatile ( "1: \n" " mov r3, %[AA], asr #18 \n" " orrs r3, r3, %[CC], asr #18 \n" @@ -249,7 +249,7 @@ static void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg) Screen += GFX.StartY * GFX_PITCH; Depth = GFX.DB + GFX.StartY * GFX_PPL; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; @@ -285,7 +285,7 @@ static void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg) aa = l->MatrixA; cc = l->MatrixC; } - asm volatile ( + __asm__ volatile ( "1: \n" " mov r3, %[AA], asr #18 \n" " orrs r3, r3, %[CC], asr #18 \n" @@ -384,7 +384,7 @@ static void DrawBGMode7Background16R0 (uint8 *Screen, int bg) int DD; uint32 Line; uint32 clip; - struct SLineMatrixData *l; + SLineMatrixData *l; uint8 *Depth; unsigned int fixedColour = GFX.FixedColour; uint32 depth = Mode7Depths[0] | (Mode7Depths[1] << 8); @@ -437,7 +437,7 @@ static void DrawBGMode7Background16R0 (uint8 *Screen, int bg) aa = l->MatrixA; cc = l->MatrixC; } - asm volatile ( + __asm__ volatile ( " ldr r3, %[AndByY] \n" "1: \n" " and r1, r3, %[CC], asr #4 \n" diff --git a/src/mode7prio_t.h.last b/src/mode7prio_t.h.last index 444c1fd..d97e314 100644 --- a/src/mode7prio_t.h.last +++ b/src/mode7prio_t.h.last @@ -6,8 +6,8 @@ #include "gfx.h" #include "apu.h" -extern struct SLineData LineData[240]; -extern struct SLineMatrixData LineMatrixData [240]; +extern SLineData LineData[240]; +extern SLineMatrixData LineMatrixData [240]; extern uint8 Mode7Depths [2]; #define M7 19 @@ -48,7 +48,7 @@ static void DrawBGMode7Background16R3 (uint8 *Screen, int bg) Screen += GFX.StartY * GFX_PITCH; Depth = GFX.DB + GFX.StartY * GFX_PPL; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; @@ -93,7 +93,7 @@ static void DrawBGMode7Background16R3 (uint8 *Screen, int bg) xx3 = (startx + HOffset); - asm volatile ( + __asm__ volatile ( "1: \n" " mov r3, %[AA], asr #18 \n" " orrs r3, r3, %[CC], asr #18 \n" @@ -245,7 +245,7 @@ static void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg) Screen += GFX.StartY * GFX_PITCH; Depth = GFX.DB + GFX.StartY * GFX_PPL; - struct SLineMatrixData *l = &LineMatrixData [GFX.StartY]; + SLineMatrixData *l = &LineMatrixData [GFX.StartY]; for (Line = GFX.StartY; Line <= GFX.EndY; Line++, Screen += GFX_PITCH, Depth += GFX_PPL, l++) { HOffset = ((int32) LineData[Line].BG[0].HOffset << M7) >> M7; @@ -281,7 +281,7 @@ static void DrawBGMode7Background16R1R2 (uint8 *Screen, int bg) aa = l->MatrixA; cc = l->MatrixC; } - asm volatile ( + __asm__ volatile ( "1: \n" " mov r3, %[AA], asr #18 \n" " orrs r3, r3, %[CC], asr #18 \n" @@ -378,7 +378,7 @@ static void DrawBGMode7Background16R0 (uint8 *Screen, int bg) int DD; uint32 Line; uint32 clip; - struct SLineMatrixData *l; + SLineMatrixData *l; uint8 *Depth; unsigned int fixedColour = GFX.FixedColour; uint32 depth = Mode7Depths[0] | (Mode7Depths[1] << 8); @@ -431,7 +431,7 @@ static void DrawBGMode7Background16R0 (uint8 *Screen, int bg) aa = l->MatrixA; cc = l->MatrixC; } - asm volatile ( + __asm__ volatile ( //" b 1f \n" //"7: \n" // AndByX //" .word (0x3ff << 1) \n" diff --git a/src/mode7sub.c b/src/mode7sub.c new file mode 100644 index 0000000..2ba1209 --- /dev/null +++ b/src/mode7sub.c @@ -0,0 +1,6 @@ +#include "rops.h" +#define ROPNAME Sub +#define ROP ROP_SUB(r1, r3) + +#include "mode7_t.h" + diff --git a/src/mode7sub.cpp b/src/mode7sub.cpp deleted file mode 100644 index 2ba1209..0000000 --- a/src/mode7sub.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "rops.h" -#define ROPNAME Sub -#define ROP ROP_SUB(r1, r3) - -#include "mode7_t.h" - diff --git a/src/mode7sub1_2.c b/src/mode7sub1_2.c new file mode 100644 index 0000000..0b87cbf --- /dev/null +++ b/src/mode7sub1_2.c @@ -0,0 +1,6 @@ +#include "rops.h" +#define ROPNAME Sub1_2 +#define ROP ROP_SUB1_2(r1, r3) + +#include "mode7_t.h" + diff --git a/src/mode7sub1_2.cpp b/src/mode7sub1_2.cpp deleted file mode 100644 index 0b87cbf..0000000 --- a/src/mode7sub1_2.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "rops.h" -#define ROPNAME Sub1_2 -#define ROP ROP_SUB1_2(r1, r3) - -#include "mode7_t.h" - diff --git a/src/mode7sub1_2prio.c b/src/mode7sub1_2prio.c new file mode 100644 index 0000000..6da6869 --- /dev/null +++ b/src/mode7sub1_2prio.c @@ -0,0 +1,5 @@ +#include "rops.h" +#define ROPNAME Sub1_2 +#define ROP ROP_SUB1_2(r1, r3) + +#include "mode7prio_t.h" diff --git a/src/mode7sub1_2prio.cpp b/src/mode7sub1_2prio.cpp deleted file mode 100644 index 6da6869..0000000 --- a/src/mode7sub1_2prio.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "rops.h" -#define ROPNAME Sub1_2 -#define ROP ROP_SUB1_2(r1, r3) - -#include "mode7prio_t.h" diff --git a/src/mode7subprio.c b/src/mode7subprio.c new file mode 100644 index 0000000..61a3870 --- /dev/null +++ b/src/mode7subprio.c @@ -0,0 +1,6 @@ +#include "rops.h" +#define ROPNAME Sub +#define ROP ROP_SUB(r1, r3) + +#include "mode7prio_t.h" + diff --git a/src/mode7subprio.cpp b/src/mode7subprio.cpp deleted file mode 100644 index 61a3870..0000000 --- a/src/mode7subprio.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "rops.h" -#define ROPNAME Sub -#define ROP ROP_SUB(r1, r3) - -#include "mode7prio_t.h" - diff --git a/src/os9x_asm_cpu.c b/src/os9x_asm_cpu.c new file mode 100644 index 0000000..bfd2ec5 --- /dev/null +++ b/src/os9x_asm_cpu.c @@ -0,0 +1,255 @@ +#include "snes9x.h" +#include "apu.h" +#include "ppu.h" +#include "cpuexec.h" +//#include "cpuops.h" + +#include "os9x_asm_cpu.h" + +//#define __debug_c_irq__ +//#define __debug_c_nmi__ +//#define __debug_c_hblank__ +//#define __debug_c_io__ + +START_EXTERN_C + +void asm_S9xSetPCBase(uint32 Address) +{ +#ifdef __debug_c_setpc__ + printf("spcb\n"); +#endif + S9xSetPCBase(Address); +} + + +#ifdef _C_GW_ +#define PushW(w) \ + S9xSetWord (w, Registers.S.W - 1);\ + Registers.S.W -= 2; +#define PushB(b)\ + S9xSetByte (b, Registers.S.W--); + + +void asm_S9xMainLoop(void) +{ + //S9xPackStatus(); + //printf("asmMainLoop Enter(0x%08x).\n", CPU.Flags); + asmMainLoop(&CPU); + //printf("asmMainLoop Exit(0x%08x, %d).\n", CPU.PC - CPU.PCBase, CPU.Cycles); + //S9xUnpackStatus(); +} + +void asm_S9xDoHBlankProcessing(void) +{ +#ifdef __debug_c_hblank__ + printf("hblank\n"); +#endif +// S9xUnpackStatus(); // not needed + S9xDoHBlankProcessing(); +// S9xPackStatus(); +} + + +uint8 asm_S9xGetByte(uint32 Address) +{ +#ifdef __debug_c_io__ + printf("gb\n"); +#endif + return S9xGetByte(Address); +} + +uint16 asm_S9xGetWord(uint32 Address) +{ +#ifdef __debug_c_io__ + printf("gw\n"); +#endif + return S9xGetWord(Address); +} + + +void asm_S9xSetByte(uint32 Address,uint8 value) +{ +#ifdef __debug_c_io__ + printf("sb\n"); +#endif + S9xSetByte(value,Address); +} + +void asm_S9xSetWord(uint32 Address,uint16 value) +{ +#ifdef __debug_c_io__ + printf("sw\n"); +#endif + S9xSetWord(value,Address); +} + + +void asm_S9xOpcode_NMI(void) +{ +#ifdef __debug_c_nmi__ + printf("nmi\n"); +#endif +// S9xUnpackStatus(); // not needed + + if (!CheckEmulation()) + { + PushB (Registers.PB); + PushW (CPU.PC - CPU.PCBase); +// S9xPackStatus (); + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; +// c = 0; // unused +#ifdef USE_SA1 + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) + S9xSetPCBase (Memory.FillRAM [0x220c] | + (Memory.FillRAM [0x220d] << 8)); + else +#endif + S9xSetPCBase (S9xGetWord (0xFFEA)); +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#else + CPU.Cycles += 8; +#endif + } + else + { + PushW (CPU.PC - CPU.PCBase); +// S9xPackStatus (); // not needed + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; +// ICPU.ShiftedPB = 0; // unused +#ifdef USE_SA1 + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) + S9xSetPCBase (Memory.FillRAM [0x220c] | + (Memory.FillRAM [0x220d] << 8)); + else +#endif + S9xSetPCBase (S9xGetWord (0xFFFA)); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else + CPU.Cycles += 6; +#endif + } + +// S9xPackStatus(); // not needed +} + +void asm_S9xOpcode_IRQ(void) +{ +#ifdef __debug_c_irq__ + printf("irq\n"); +#endif +// S9xUnpackStatus(); // not needed + + if (!CheckEmulation()) + { + PushB (Registers.PB); + PushW (CPU.PC - CPU.PCBase); +// S9xPackStatus (); // not needed + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; +// ICPU.ShiftedPB = 0; // unused + +#ifdef USE_SA1 + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) + S9xSetPCBase (Memory.FillRAM [0x220e] | + (Memory.FillRAM [0x220f] << 8)); + else +#endif + S9xSetPCBase (S9xGetWord (0xFFEE)); +#ifdef VAR_CYCLES + CPU.Cycles += TWO_CYCLES; +#else + CPU.Cycles += 8; +#endif + } + else + { + PushW (CPU.PC - CPU.PCBase); +// S9xPackStatus (); // not needed + PushB (Registers.PL); + ClearDecimal (); + SetIRQ (); + + Registers.PB = 0; +// ICPU.ShiftedPB = 0; // unused + +#ifdef USE_SA1 + if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) + S9xSetPCBase (Memory.FillRAM [0x220e] | + (Memory.FillRAM [0x220f] << 8)); + else +#endif + S9xSetPCBase (S9xGetWord (0xFFFE)); +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#else + CPU.Cycles += 6; +#endif + } + +// S9xPackStatus(); // not needed +} +#endif + +/* +void asm_APU_EXECUTE(int Mode) +{ +#ifdef __debug_c_apuex__ + printf("apuexec\n"); +#endif + if(CPU.APU_APUExecuting != Mode) return; + + if (Settings.asmspc700) + { + if(CPU.APU_Cycles < CPU.Cycles) { + int cycles = CPU.Cycles - CPU.APU_Cycles; + CPU.APU_Cycles += cycles - spc700_execute(cycles); + } + } + else + { + while (CPU.APU_Cycles <= CPU.Cycles) + { + CPU.APU_Cycles += S9xAPUCycles [*IAPU.PC]; + (*S9xApuOpcodes[*IAPU.PC]) (); + } + } +} + + +void asm_APU_EXECUTE2(void) +{ + if(CPU.APU_APUExecuting != 1) return; + + //ICPU.CPUExecuting = FALSE; + if (Settings.asmspc700) + { + if(CPU.APU_Cycles < CPU.NextEvent) { + int cycles = CPU.NextEvent - CPU.APU_Cycles; + CPU.APU_Cycles += cycles - spc700_execute(cycles); + } + } + else + { + do + { + CPU.APU_Cycles += S9xAPUCycles [*IAPU.PC]; + (*S9xApuOpcodes[*IAPU.PC]) (); + } while (CPU.APU_Cycles < CPU.NextEvent); + } + //ICPU.CPUExecuting = TRUE; +}*/ + +END_EXTERN_C diff --git a/src/os9x_asm_cpu.cpp b/src/os9x_asm_cpu.cpp deleted file mode 100644 index bfd2ec5..0000000 --- a/src/os9x_asm_cpu.cpp +++ /dev/null @@ -1,255 +0,0 @@ -#include "snes9x.h" -#include "apu.h" -#include "ppu.h" -#include "cpuexec.h" -//#include "cpuops.h" - -#include "os9x_asm_cpu.h" - -//#define __debug_c_irq__ -//#define __debug_c_nmi__ -//#define __debug_c_hblank__ -//#define __debug_c_io__ - -START_EXTERN_C - -void asm_S9xSetPCBase(uint32 Address) -{ -#ifdef __debug_c_setpc__ - printf("spcb\n"); -#endif - S9xSetPCBase(Address); -} - - -#ifdef _C_GW_ -#define PushW(w) \ - S9xSetWord (w, Registers.S.W - 1);\ - Registers.S.W -= 2; -#define PushB(b)\ - S9xSetByte (b, Registers.S.W--); - - -void asm_S9xMainLoop(void) -{ - //S9xPackStatus(); - //printf("asmMainLoop Enter(0x%08x).\n", CPU.Flags); - asmMainLoop(&CPU); - //printf("asmMainLoop Exit(0x%08x, %d).\n", CPU.PC - CPU.PCBase, CPU.Cycles); - //S9xUnpackStatus(); -} - -void asm_S9xDoHBlankProcessing(void) -{ -#ifdef __debug_c_hblank__ - printf("hblank\n"); -#endif -// S9xUnpackStatus(); // not needed - S9xDoHBlankProcessing(); -// S9xPackStatus(); -} - - -uint8 asm_S9xGetByte(uint32 Address) -{ -#ifdef __debug_c_io__ - printf("gb\n"); -#endif - return S9xGetByte(Address); -} - -uint16 asm_S9xGetWord(uint32 Address) -{ -#ifdef __debug_c_io__ - printf("gw\n"); -#endif - return S9xGetWord(Address); -} - - -void asm_S9xSetByte(uint32 Address,uint8 value) -{ -#ifdef __debug_c_io__ - printf("sb\n"); -#endif - S9xSetByte(value,Address); -} - -void asm_S9xSetWord(uint32 Address,uint16 value) -{ -#ifdef __debug_c_io__ - printf("sw\n"); -#endif - S9xSetWord(value,Address); -} - - -void asm_S9xOpcode_NMI(void) -{ -#ifdef __debug_c_nmi__ - printf("nmi\n"); -#endif -// S9xUnpackStatus(); // not needed - - if (!CheckEmulation()) - { - PushB (Registers.PB); - PushW (CPU.PC - CPU.PCBase); -// S9xPackStatus (); - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; -// c = 0; // unused -#ifdef USE_SA1 - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) - S9xSetPCBase (Memory.FillRAM [0x220c] | - (Memory.FillRAM [0x220d] << 8)); - else -#endif - S9xSetPCBase (S9xGetWord (0xFFEA)); -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#else - CPU.Cycles += 8; -#endif - } - else - { - PushW (CPU.PC - CPU.PCBase); -// S9xPackStatus (); // not needed - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; -// ICPU.ShiftedPB = 0; // unused -#ifdef USE_SA1 - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x20)) - S9xSetPCBase (Memory.FillRAM [0x220c] | - (Memory.FillRAM [0x220d] << 8)); - else -#endif - S9xSetPCBase (S9xGetWord (0xFFFA)); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else - CPU.Cycles += 6; -#endif - } - -// S9xPackStatus(); // not needed -} - -void asm_S9xOpcode_IRQ(void) -{ -#ifdef __debug_c_irq__ - printf("irq\n"); -#endif -// S9xUnpackStatus(); // not needed - - if (!CheckEmulation()) - { - PushB (Registers.PB); - PushW (CPU.PC - CPU.PCBase); -// S9xPackStatus (); // not needed - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; -// ICPU.ShiftedPB = 0; // unused - -#ifdef USE_SA1 - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) - S9xSetPCBase (Memory.FillRAM [0x220e] | - (Memory.FillRAM [0x220f] << 8)); - else -#endif - S9xSetPCBase (S9xGetWord (0xFFEE)); -#ifdef VAR_CYCLES - CPU.Cycles += TWO_CYCLES; -#else - CPU.Cycles += 8; -#endif - } - else - { - PushW (CPU.PC - CPU.PCBase); -// S9xPackStatus (); // not needed - PushB (Registers.PL); - ClearDecimal (); - SetIRQ (); - - Registers.PB = 0; -// ICPU.ShiftedPB = 0; // unused - -#ifdef USE_SA1 - if (Settings.SA1 && (Memory.FillRAM [0x2209] & 0x40)) - S9xSetPCBase (Memory.FillRAM [0x220e] | - (Memory.FillRAM [0x220f] << 8)); - else -#endif - S9xSetPCBase (S9xGetWord (0xFFFE)); -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#else - CPU.Cycles += 6; -#endif - } - -// S9xPackStatus(); // not needed -} -#endif - -/* -void asm_APU_EXECUTE(int Mode) -{ -#ifdef __debug_c_apuex__ - printf("apuexec\n"); -#endif - if(CPU.APU_APUExecuting != Mode) return; - - if (Settings.asmspc700) - { - if(CPU.APU_Cycles < CPU.Cycles) { - int cycles = CPU.Cycles - CPU.APU_Cycles; - CPU.APU_Cycles += cycles - spc700_execute(cycles); - } - } - else - { - while (CPU.APU_Cycles <= CPU.Cycles) - { - CPU.APU_Cycles += S9xAPUCycles [*IAPU.PC]; - (*S9xApuOpcodes[*IAPU.PC]) (); - } - } -} - - -void asm_APU_EXECUTE2(void) -{ - if(CPU.APU_APUExecuting != 1) return; - - //ICPU.CPUExecuting = FALSE; - if (Settings.asmspc700) - { - if(CPU.APU_Cycles < CPU.NextEvent) { - int cycles = CPU.NextEvent - CPU.APU_Cycles; - CPU.APU_Cycles += cycles - spc700_execute(cycles); - } - } - else - { - do - { - CPU.APU_Cycles += S9xAPUCycles [*IAPU.PC]; - (*S9xApuOpcodes[*IAPU.PC]) (); - } while (CPU.APU_Cycles < CPU.NextEvent); - } - //ICPU.CPUExecuting = TRUE; -}*/ - -END_EXTERN_C diff --git a/src/port.h b/src/port.h index 04422e9..540ae2d 100644 --- a/src/port.h +++ b/src/port.h @@ -63,6 +63,7 @@ I can't take it anymore, it's too convoluted. So I've commented out the entire //#include #include #include +#include //Types Defined typedef unsigned char bool8; typedef unsigned char uint8; diff --git a/src/ppu.c b/src/ppu.c new file mode 100644 index 0000000..3f7a1c6 --- /dev/null +++ b/src/ppu.c @@ -0,0 +1,1416 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" +#include "missing.h" +#include "apu.h" +#include "dma.h" +#include "gfx.h" +#include "display.h" +#include "sa1.h" +#include "sdd1.h" +#include "srtc.h" + +#include "port.h" + +#ifndef ZSNES_FX +#include "fxemu.h" +#include "fxinst.h" +extern FxInit_s SuperFX; +extern FxRegs_s GSU; +#else +EXTERN_C void S9xSuperFXWriteReg (uint8, uint32); +EXTERN_C uint8 S9xSuperFXReadReg (uint32); +#endif +extern uint8 *HDMAMemPointers [8]; + +void S9xUpdateHTimer () +{ + if (PPU.HTimerEnabled) + { +#ifdef DEBUGGER + missing.hirq_pos = PPU.IRQHBeamPos; +#endif + PPU.HTimerPosition = PPU.IRQHBeamPos * Settings.H_Max / SNES_HCOUNTER_MAX; + if (PPU.HTimerPosition == Settings.H_Max || + PPU.HTimerPosition == Settings.HBlankStart) + { + PPU.HTimerPosition--; + } + + if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos) + { + if (PPU.HTimerPosition < CPU.Cycles) + { + // Missed the IRQ on this line already + if (CPU.WhichEvent == HBLANK_END_EVENT || + CPU.WhichEvent == HTIMER_AFTER_EVENT) + { + CPU.WhichEvent = HBLANK_END_EVENT; + CPU.NextEvent = Settings.H_Max; + } + else + { + CPU.WhichEvent = HBLANK_START_EVENT; + CPU.NextEvent = Settings.HBlankStart; + } + } + else + { + if (CPU.WhichEvent == HTIMER_BEFORE_EVENT || + CPU.WhichEvent == HBLANK_START_EVENT) + { + if (PPU.HTimerPosition > Settings.HBlankStart) + { + // HTimer was to trigger before h-blank start, + // now triggers after start of h-blank + CPU.NextEvent = Settings.HBlankStart; + CPU.WhichEvent = HBLANK_START_EVENT; + } + else + { + CPU.NextEvent = PPU.HTimerPosition; + CPU.WhichEvent = HTIMER_BEFORE_EVENT; + } + } + else + { + CPU.WhichEvent = HTIMER_AFTER_EVENT; + CPU.NextEvent = PPU.HTimerPosition; + } + } + } + } +} + +void S9xFixColourBrightness () +{ + IPPU.XB = mul_brightness [PPU.Brightness]; + if (Settings.SixteenBit) + { + unsigned int i; + for (i = 0; i < 256; i++) + { + //IPPU.Red [i] = IPPU.XB [PPU.CGDATA [i] & 0x1f]; + //IPPU.Green [i] = IPPU.XB [(PPU.CGDATA [i] >> 5) & 0x1f]; + //IPPU.Blue [i] = IPPU.XB [(PPU.CGDATA [i] >> 10) & 0x1f]; + IPPU.ScreenColors [i] = BUILD_PIXEL (IPPU.XB[IPPU.Red [i]], IPPU.XB[IPPU.Green [i]], IPPU.XB[IPPU.Blue [i]]); + } + } +} + +/**********************************************************************************************/ +/* S9xSetPPU() */ +/* This function sets a PPU Register to a specific byte */ +/**********************************************************************************************/ +#include "ppu_setppu.h" + +/**********************************************************************************************/ +/* S9xGetPPU() */ +/* This function retrieves a PPU Register */ +/**********************************************************************************************/ +#include "ppu_getppu.h" + +/**********************************************************************************************/ +/* S9xSetCPU() */ +/* This function sets a CPU/DMA Register to a specific byte */ +/**********************************************************************************************/ +void S9xSetCPU(uint8 byte, uint16 Address) +{ + int d; + + if (Address < 0x4200) + { +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + switch (Address) + { + case 0x4016 : + // S9xReset reading of old-style joypads + if ((byte & 1) && !(Memory.FillRAM[Address] & 1)) + { + PPU.Joypad1ButtonReadPos = 0; + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 0; + } + break; + case 0x4017 : + break; + default : +#ifdef DEBUGGER + missing.unknowncpu_write = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf(String, "Unknown register register write: $%02X->$%04X\n", byte, Address); + S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + break; + } + } + else + switch (Address) + { + case 0x4200 : + // NMI, V & H IRQ and joypad reading enable flags + if (byte & 0x20) + { + if (!PPU.VTimerEnabled) + { +#ifdef DEBUGGER + missing.virq = 1; + missing.virq_pos = PPU.IRQVBeamPos; +#endif + PPU.VTimerEnabled = TRUE; + if (PPU.HTimerEnabled) + S9xUpdateHTimer(); + else if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); + } + } + else + { + PPU.VTimerEnabled = FALSE; + } + + if (byte & 0x10) + { + if (!PPU.HTimerEnabled) + { +#ifdef DEBUGGER + missing.hirq = 1; + missing.hirq_pos = PPU.IRQHBeamPos; +#endif + PPU.HTimerEnabled = TRUE; + S9xUpdateHTimer(); + } + } + else + { + // No need to check for HTimer being disabled as the scanline + // event trigger code won't trigger an H-IRQ unless its enabled. + PPU.HTimerEnabled = FALSE; + PPU.HTimerPosition = Settings.H_Max + 1; + } + +#ifndef RC_OPTIMIZED + if (!Settings.DaffyDuck) + CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + + if ((byte & 0x80) + && !(Memory.FillRAM[0x4200] & 0x80) + && CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE + && CPU.V_Counter <= PPU.ScreenHeight + (SNESGameFixes.alienVSpredetorFix ? 25 : 15) + && //jyam 15->25 alien vs predetor + // Panic Bomberman clears the NMI pending flag @ scanline 230 before enabling + // NMIs again. The NMI routine crashes the CPU if it is called without the NMI + // pending flag being set... + (Memory.FillRAM[0x4210] & 0x80) && !CPU.NMIActive) + { + CPU.Flags |= NMI_FLAG; + CPU.NMIActive = TRUE; + CPU.NMICycleCount = CPU.NMITriggerPoint; + } +#endif + break; + case 0x4201 : + // I/O port output + case 0x4202 : + // Multiplier (for multply) + break; + case 0x4203 : + { + // Multiplicand + uint32 res = Memory.FillRAM[0x4202] * byte; + + Memory.FillRAM[0x4216] = (uint8) res; + Memory.FillRAM[0x4217] = (uint8) (res >> 8); + break; + } + case 0x4204 : + case 0x4205 : + // Low and high muliplier (for divide) + break; + case 0x4206 : + { + // Divisor + uint16 a = + Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); + uint16 div = byte ? a / byte : 0xffff; + uint16 rem = byte ? a % byte : a; + + Memory.FillRAM[0x4214] = (uint8) div; + Memory.FillRAM[0x4215] = div >> 8; + Memory.FillRAM[0x4216] = (uint8) rem; + Memory.FillRAM[0x4217] = rem >> 8; + break; + } + case 0x4207 : + d = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte; + + if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) + S9xUpdateHTimer(); + break; + + case 0x4208 : + d = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8); + + if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) + S9xUpdateHTimer(); + + break; + + case 0x4209 : + d = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF00) | byte; +#ifdef DEBUGGER + missing.virq_pos = PPU.IRQVBeamPos; +#endif + if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) + { + if (PPU.HTimerEnabled) + S9xUpdateHTimer(); + else + { + if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); + } + } + break; + + case 0x420A : + d = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF) | ((byte & 1) << 8); +#ifdef DEBUGGER + missing.virq_pos = PPU.IRQVBeamPos; +#endif + if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) + { + if (PPU.HTimerEnabled) + S9xUpdateHTimer(); + else + { + if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); + } + } + break; + + case 0x420B : +#ifdef DEBUGGER + missing.dma_this_frame = byte; + missing.dma_channels = byte; +#endif + if ((byte & 0x01) != 0) + S9xDoDMA(0); + if ((byte & 0x02) != 0) + S9xDoDMA(1); + if ((byte & 0x04) != 0) + S9xDoDMA(2); + if ((byte & 0x08) != 0) + S9xDoDMA(3); + if ((byte & 0x10) != 0) + S9xDoDMA(4); + if ((byte & 0x20) != 0) + S9xDoDMA(5); + if ((byte & 0x40) != 0) + S9xDoDMA(6); + if ((byte & 0x80) != 0) + S9xDoDMA(7); + break; + case 0x420C : +#ifdef DEBUGGER + missing.hdma_this_frame |= byte; + missing.hdma_channels |= byte; +#endif + //if (Settings.DisableHDMA) + // byte = 0; + Memory.FillRAM[0x420c] = byte; + IPPU.HDMA = byte; + break; + + case 0x420d : + // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) + if ((byte & 1) != (Memory.FillRAM[0x420d] & 1)) + { + if (byte & 1) + { + CPU.FastROMSpeed = ONE_CYCLE; +#ifdef DEBUGGER + missing.fast_rom = 1; +#endif + } + else + CPU.FastROMSpeed = SLOW_ONE_CYCLE; + + FixROMSpeed(); + } + /* FALL */ + case 0x420e : + case 0x420f : + // --->>> Unknown + break; + case 0x4210 : + // NMI ocurred flag (reset on read or write) + Memory.FillRAM[0x4210] = 0; + return; + case 0x4211 : + // IRQ ocurred flag (reset on read or write) + CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + break; + case 0x4212 : + // v-blank, h-blank and joypad being scanned flags (read-only) + case 0x4213 : + // I/O Port (read-only) + case 0x4214 : + case 0x4215 : + // Quotent of divide (read-only) + case 0x4216 : + case 0x4217 : + // Multiply product (read-only) + return; + case 0x4218 : + case 0x4219 : + case 0x421a : + case 0x421b : + case 0x421c : + case 0x421d : + case 0x421e : + case 0x421f : + // Joypad values (read-only) + return; + + case 0x4300 : + case 0x4310 : + case 0x4320 : + case 0x4330 : + case 0x4340 : + case 0x4350 : + case 0x4360 : + case 0x4370 : + d = (Address >> 4) & 0x7; + DMA[d].TransferDirection = (byte & 128) != 0 ? 1 : 0; + DMA[d].HDMAIndirectAddressing = (byte & 64) != 0 ? 1 : 0; + DMA[d].AAddressDecrement = (byte & 16) != 0 ? 1 : 0; + DMA[d].AAddressFixed = (byte & 8) != 0 ? 1 : 0; + DMA[d].TransferMode = (byte & 7); + break; + + case 0x4301 : + case 0x4311 : + case 0x4321 : + case 0x4331 : + case 0x4341 : + case 0x4351 : + case 0x4361 : + case 0x4371 : + DMA[((Address >> 4) & 0x7)].BAddress = byte; + break; + + case 0x4302 : + case 0x4312 : + case 0x4322 : + case 0x4332 : + case 0x4342 : + case 0x4352 : + case 0x4362 : + case 0x4372 : + d = (Address >> 4) & 0x7; + DMA[d].AAddress &= 0xFF00; + DMA[d].AAddress |= byte; + break; + + case 0x4303 : + case 0x4313 : + case 0x4323 : + case 0x4333 : + case 0x4343 : + case 0x4353 : + case 0x4363 : + case 0x4373 : + d = (Address >> 4) & 0x7; + DMA[d].AAddress &= 0xFF; + DMA[d].AAddress |= byte << 8; + break; + + case 0x4304 : + case 0x4314 : + case 0x4324 : + case 0x4334 : + case 0x4344 : + case 0x4354 : + case 0x4364 : + case 0x4374 : + DMA[((Address >> 4) & 0x7)].ABank = byte; + HDMAMemPointers[((Address >> 4) & 0x7)]=NULL; + break; + + case 0x4305 : + case 0x4315 : + case 0x4325 : + case 0x4335 : + case 0x4345 : + case 0x4355 : + case 0x4365 : + case 0x4375 : + d = (Address >> 4) & 0x7; + DMA[d].TransferBytes &= 0xFF00; + DMA[d].TransferBytes |= byte; + DMA[d].IndirectAddress &= 0xff00; + DMA[d].IndirectAddress |= byte; + HDMAMemPointers[d]=NULL; + break; + + case 0x4306 : + case 0x4316 : + case 0x4326 : + case 0x4336 : + case 0x4346 : + case 0x4356 : + case 0x4366 : + case 0x4376 : + d = (Address >> 4) & 0x7; + DMA[d].TransferBytes &= 0xFF; + DMA[d].TransferBytes |= byte << 8; + DMA[d].IndirectAddress &= 0xff; + DMA[d].IndirectAddress |= byte << 8; + HDMAMemPointers[d]=NULL; + break; + + case 0x4307 : + case 0x4317 : + case 0x4327 : + case 0x4337 : + case 0x4347 : + case 0x4357 : + case 0x4367 : + case 0x4377 : + DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; + HDMAMemPointers[d]=NULL; + break; + + case 0x4308 : + case 0x4318 : + case 0x4328 : + case 0x4338 : + case 0x4348 : + case 0x4358 : + case 0x4368 : + case 0x4378 : + d = (Address >> 4) & 7; + DMA[d].Address &= 0xff00; + DMA[d].Address |= byte; + HDMAMemPointers[d] = NULL; + break; + + case 0x4309 : + case 0x4319 : + case 0x4329 : + case 0x4339 : + case 0x4349 : + case 0x4359 : + case 0x4369 : + case 0x4379 : + d = (Address >> 4) & 0x7; + DMA[d].Address &= 0xff; + DMA[d].Address |= byte << 8; + HDMAMemPointers[d] = NULL; + break; + + case 0x430A : + case 0x431A : + case 0x432A : + case 0x433A : + case 0x434A : + case 0x435A : + case 0x436A : + case 0x437A : + d = (Address >> 4) & 0x7; + DMA[d].LineCount = byte & 0x7f; + DMA[d].Repeat = !(byte & 0x80); + break; + + case 0x430F: + case 0x431F: + case 0x432F: + case 0x433F: + case 0x434F: + case 0x435F: + case 0x436F: + case 0x437F: + Address &= ~4; // Convert 43xF to 43xB + /* fall through */ + case 0x430B: + case 0x431B: + case 0x432B: + case 0x433B: + case 0x434B: + case 0x435B: + case 0x436B: + case 0x437B: + + // Unknown, but they seem to be RAM-ish + break; + case 0x4800 : + case 0x4801 : + case 0x4802 : + case 0x4803 : + //printf ("%02x->%04x\n", byte, Address); + break; + + case 0x4804 : + case 0x4805 : + case 0x4806 : + case 0x4807 : + //printf ("%02x->%04x\n", byte, Address); + + S9xSetSDD1MemoryMap(Address - 0x4804, byte & 7); + break; + default : +#ifdef DEBUGGER + missing.unknowncpu_write = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf( + String, + "Unknown register write: $%02X->$%04X\n", + byte, + Address); + S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + break; + } + Memory.FillRAM[Address] = byte; +} + +/**********************************************************************************************/ +/* S9xGetCPU() */ +/* This function retrieves a CPU/DMA Register */ +/**********************************************************************************************/ +uint8 S9xGetCPU(uint16 Address) +{ + uint8 byte; + if(Address>=0x4800&&Address<=0x4807&&Settings.SDD1) + { + return Memory.FillRAM[Address]; + } + + if (Address < 0x4200) + { +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + switch (Address) + { + // Secret of the Evermore + case 0x4000 : + case 0x4001 : + return (0x40); + + case 0x4016 : + { + if (Memory.FillRAM[0x4016] & 1) + { + return (0); + } + + byte = IPPU.Joypads[0] >> (PPU.Joypad1ButtonReadPos ^ 15); + PPU.Joypad1ButtonReadPos++; + return (byte & 1); + } + case 0x4017 : + { + if (Memory.FillRAM[0x4016] & 1) + { + // MultiPlayer5 adaptor is only allowed to be plugged into port 2 + switch (IPPU.Controller) + { + case SNES_MULTIPLAYER5 : + return (2); + + case SNES_MOUSE : + if (++PPU.MouseSpeed[0] > 2) + PPU.MouseSpeed[0] = 0; + break; + } + return (0x00); + } + + if (IPPU.Controller == SNES_MULTIPLAYER5) + { + if (Memory.FillRAM[0x4201] & 0x80) + { + byte = + ((IPPU.Joypads[0] + >> (PPU.Joypad2ButtonReadPos ^ 15)) + & 1) + | (((IPPU.Joypads[2] + >> (PPU.Joypad2ButtonReadPos ^ 15)) + & 1) + << 1); + PPU.Joypad2ButtonReadPos++; + return (byte); + } + else + { + byte = + ((IPPU.Joypads[3] + >> (PPU.Joypad3ButtonReadPos ^ 15)) + & 1) + | (((IPPU.Joypads[4] + >> (PPU.Joypad3ButtonReadPos ^ 15)) + & 1) + << 1); + PPU.Joypad3ButtonReadPos++; + return (byte); + } + } + return ( + (IPPU.Joypads[1] + >> (PPU.Joypad2ButtonReadPos++ ^ 15)) + & 1); + } + default : +#ifdef DEBUGGER + missing.unknowncpu_read = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf(String, "Unknown register read: $%04X\n", Address); + S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + break; + } + return (Memory.FillRAM[Address]); + } + else + switch (Address) + { + // BS Dynami Tracer! needs to be able to check if NMIs are enabled + // already, otherwise the game locks up. + case 0x4200 : + // NMI, h & v timers and joypad reading enable + if (SNESGameFixes.Old_Read0x4200) + { +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + return (REGISTER_4212()); + } + case 0x4201 : + // I/O port (output - write only?) + case 0x4202 : + case 0x4203 : + // Multiplier and multiplicand (write) + case 0x4204 : + case 0x4205 : + case 0x4206 : + // Divisor and dividend (write) + return (Memory.FillRAM[Address]); + case 0x4207 : + return (uint8) (PPU.IRQHBeamPos); + case 0x4208 : + return (PPU.IRQHBeamPos >> 8); + case 0x4209 : + return (uint8) (PPU.IRQVBeamPos); + case 0x420a : + return (PPU.IRQVBeamPos >> 8); + case 0x420b : + // General purpose DMA enable + // Super Formation Soccer 95 della Serie A UCC Xaqua requires this + // register should not always return zero. + // .. But Aero 2 waits until this register goes zero.. + // Just keep toggling the value for now in the hope that it breaks + // the game out of its wait loop... + Memory.FillRAM[0x420b] = !Memory.FillRAM[0x420b]; + return (Memory.FillRAM[0x420b]); + case 0x420c : + // H-DMA enable + return (IPPU.HDMA); + case 0x420d : + // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) + return (Memory.FillRAM[Address]); + case 0x420e : + case 0x420f : + // --->>> Unknown + return (Memory.FillRAM[Address]); + case 0x4210 : +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + byte = Memory.FillRAM[0x4210]; + Memory.FillRAM[0x4210] = 0; + return (byte); + case 0x4211 : + byte = + (CPU.IRQActive + & (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE)) + ? 0x80 + : 0; + // Super Robot Wars Ex ROM bug requires this. + byte |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; + CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + return (byte); + case 0x4212 : + // V-blank, h-blank and joypads being read flags (read-only) +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + return (REGISTER_4212()); + case 0x4213 : + // I/O port input + case 0x4214 : + case 0x4215 : + // Quotient of divide result + case 0x4216 : + case 0x4217 : + // Multiplcation result (for multiply) or remainder of + // divison. + return (Memory.FillRAM[Address]); + case 0x4218 : + case 0x4219 : + case 0x421a : + case 0x421b : + case 0x421c : + case 0x421d : + case 0x421e : + case 0x421f : + // Joypads 1-4 button and direction state. + return (Memory.FillRAM[Address]); + + case 0x4300 : + case 0x4310 : + case 0x4320 : + case 0x4330 : + case 0x4340 : + case 0x4350 : + case 0x4360 : + case 0x4370 : + // DMA direction, address type, fixed flag, + return (Memory.FillRAM[Address]); + + case 0x4301 : + case 0x4311 : + case 0x4321 : + case 0x4331 : + case 0x4341 : + case 0x4351 : + case 0x4361 : + case 0x4371 : + return (Memory.FillRAM[Address]); + + case 0x4302 : + case 0x4312 : + case 0x4322 : + case 0x4332 : + case 0x4342 : + case 0x4352 : + case 0x4362 : + case 0x4372 : + return (Memory.FillRAM[Address]); + + case 0x4303 : + case 0x4313 : + case 0x4323 : + case 0x4333 : + case 0x4343 : + case 0x4353 : + case 0x4363 : + case 0x4373 : + return (Memory.FillRAM[Address]); + + case 0x4304 : + case 0x4314 : + case 0x4324 : + case 0x4334 : + case 0x4344 : + case 0x4354 : + case 0x4364 : + case 0x4374 : + return (Memory.FillRAM[Address]); + + case 0x4305 : + case 0x4315 : + case 0x4325 : + case 0x4335 : + case 0x4345 : + case 0x4355 : + case 0x4365 : + case 0x4375 : + return (Memory.FillRAM[Address]); + + case 0x4306 : + case 0x4316 : + case 0x4326 : + case 0x4336 : + case 0x4346 : + case 0x4356 : + case 0x4366 : + case 0x4376 : + return (Memory.FillRAM[Address]); + + case 0x4307 : + case 0x4317 : + case 0x4327 : + case 0x4337 : + case 0x4347 : + case 0x4357 : + case 0x4367 : + case 0x4377 : + return (DMA[(Address >> 4) & 7].IndirectBank); + + case 0x4308 : + case 0x4318 : + case 0x4328 : + case 0x4338 : + case 0x4348 : + case 0x4358 : + case 0x4368 : + case 0x4378 : + return (Memory.FillRAM[Address]); + + case 0x4309 : + case 0x4319 : + case 0x4329 : + case 0x4339 : + case 0x4349 : + case 0x4359 : + case 0x4369 : + case 0x4379 : + return (Memory.FillRAM[Address]); + + case 0x430A : + case 0x431A : + case 0x432A : + case 0x433A : + case 0x434A : + case 0x435A : + case 0x436A : + case 0x437A : + { + int d = (Address & 0x70) >> 4; + if (IPPU.HDMA & (1 << d)) + { + return (DMA[d].LineCount); + } + return (Memory.FillRAM[Address]); + } + case 0x430F: + case 0x431F: + case 0x432F: + case 0x433F: + case 0x434F: + case 0x435F: + case 0x436F: + case 0x437F: + Address &= ~4; // Convert 43xF to 43xB + /* fall through */ + case 0x430B: + case 0x431B: + case 0x432B: + case 0x433B: + case 0x434B: + case 0x435B: + case 0x436B: + case 0x437B: + + // Unknown, but they seem to be RAM-ish + return (Memory.FillRAM[Address]); + default : +#ifdef DEBUGGER + missing.unknowncpu_read = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf(String, "Unknown register read: $%04X\n", Address); + S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); + } + +#endif + break; + } + return (Memory.FillRAM[Address]); +} + +void S9xResetPPU() +{ + PPU.BGMode = 0; + PPU.BG3Priority = 0; + PPU.Brightness = 0; + PPU.VMA.High = 0; + PPU.VMA.Increment = 1; + PPU.VMA.Address = 0; + PPU.VMA.FullGraphicCount = 0; + PPU.VMA.Shift = 0; + + uint8 B; + for (B = 0; B != 4; B++) + { + PPU.BG[B].SCBase = 0; + PPU.BG[B].VOffset = 0; + PPU.BG[B].HOffset = 0; + PPU.BG[B].BGSize = 0; + PPU.BG[B].NameBase = 0; + PPU.BG[B].SCSize = 0; + + PPU.ClipCounts[B] = 0; + PPU.ClipWindowOverlapLogic[B] = CLIP_OR; + PPU.ClipWindow1Enable[B] = FALSE; + PPU.ClipWindow2Enable[B] = FALSE; + PPU.ClipWindow1Inside[B] = TRUE; + PPU.ClipWindow2Inside[B] = TRUE; + } + + PPU.ClipCounts[4] = 0; + PPU.ClipCounts[5] = 0; + PPU.ClipWindowOverlapLogic[4] = PPU.ClipWindowOverlapLogic[5] = CLIP_OR; + PPU.ClipWindow1Enable[4] = PPU.ClipWindow1Enable[5] = FALSE; + PPU.ClipWindow2Enable[4] = PPU.ClipWindow2Enable[5] = FALSE; + PPU.ClipWindow1Inside[4] = PPU.ClipWindow1Inside[5] = TRUE; + PPU.ClipWindow2Inside[4] = PPU.ClipWindow2Inside[5] = TRUE; + + PPU.CGFLIP = 0; + unsigned int c; + for (c = 0; c < 256; c++) + { + IPPU.Red[c] = (c & 7) << 2; + IPPU.Green[c] = ((c >> 3) & 7) << 2; + IPPU.Blue[c] = ((c >> 6) & 2) << 3; + PPU.CGDATA[c] = + IPPU.Red[c] | (IPPU.Green[c] << 5) | (IPPU.Blue[c] << 10); + } + + PPU.FirstSprite = 0; + PPU.LastSprite = 127; + int Sprite; + for (Sprite = 0; Sprite < 128; Sprite++) + { + PPU.OBJ[Sprite].HPos = 0; + PPU.OBJ[Sprite].VPos = 0; + PPU.OBJ[Sprite].VFlip = 0; + PPU.OBJ[Sprite].HFlip = 0; + PPU.OBJ[Sprite].Priority = 0; + PPU.OBJ[Sprite].Palette = 0; + PPU.OBJ[Sprite].Name = 0; + PPU.OBJ[Sprite].Size = 0; + } + PPU.OAMPriorityRotation = 0; + PPU.OAMWriteRegister = 0; + + PPU.OAMFlip = 0; + PPU.OAMTileAddress = 0; + PPU.OAMAddr = 0; + PPU.IRQVBeamPos = 0; + PPU.IRQHBeamPos = 0; + PPU.VBeamPosLatched = 0; + PPU.HBeamPosLatched = 0; + + PPU.HBeamFlip = 0; + PPU.VBeamFlip = 0; + PPU.HVBeamCounterLatched = 0; + + PPU.MatrixA = PPU.MatrixB = PPU.MatrixC = PPU.MatrixD = 0; + PPU.CentreX = PPU.CentreY = 0; + PPU.Joypad1ButtonReadPos = 0; + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 0; + + PPU.CGADD = 0; + PPU.FixedColourRed = PPU.FixedColourGreen = PPU.FixedColourBlue = 0; + PPU.SavedOAMAddr = 0; + PPU.SavedOAMAddr2 = 0; + PPU.ScreenHeight = SNES_HEIGHT; + PPU.WRAM = 0; + PPU.BG_Forced = 0; + PPU.ForcedBlanking = TRUE; + PPU.OBJThroughMain = FALSE; + PPU.OBJThroughSub = FALSE; + PPU.OBJSizeSelect = 0; + PPU.OBJNameSelect = 0; + PPU.OBJNameBase = 0; + PPU.OBJAddition = FALSE; + PPU.OAMReadFlip = 0; + PPU.BGnxOFSbyte = 0; + ZeroMemory(PPU.OAMData, 512 + 32); + + PPU.VTimerEnabled = FALSE; + PPU.HTimerEnabled = FALSE; + PPU.HTimerPosition = Settings.H_Max + 1; + PPU.Mosaic = 0; + PPU.BGMosaic[0] = PPU.BGMosaic[1] = FALSE; + PPU.BGMosaic[2] = PPU.BGMosaic[3] = FALSE; + PPU.Mode7HFlip = FALSE; + PPU.Mode7VFlip = FALSE; + PPU.Mode7Repeat = 0; + PPU.Window1Left = 1; + PPU.Window1Right = 0; + PPU.Window2Left = 1; + PPU.Window2Right = 0; + PPU.RecomputeClipWindows = TRUE; + PPU.CGFLIPRead = 0; + PPU.Need16x8Mulitply = FALSE; + PPU.MouseSpeed[0] = PPU.MouseSpeed[1] = 0; + + IPPU.ColorsChanged = TRUE; + IPPU.HDMA = 0; + IPPU.HDMAStarted = FALSE; + IPPU.MaxBrightness = 0; + IPPU.LatchedBlanking = 0; + IPPU.OBJChanged = TRUE; + IPPU.RenderThisFrame = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + IPPU.FrameCount = 0; + IPPU.RenderedFramesCount = 0; + IPPU.DisplayedRenderedFrameCount = 0; + IPPU.SkippedFrames = 0; + IPPU.FrameSkip = 0; + ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES); + IPPU.FirstVRAMRead = FALSE; + IPPU.LatchedInterlace = FALSE; + IPPU.DoubleWidthPixels = FALSE; + IPPU.RenderedScreenWidth = SNES_WIDTH; + IPPU.RenderedScreenHeight = SNES_HEIGHT; + IPPU.XB = NULL; + for (c = 0; c < 256; c++) + IPPU.ScreenColors[c] = c; + S9xFixColourBrightness(); + IPPU.PreviousLine = IPPU.CurrentLine = 0; + IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; + IPPU.Joypads[3] = IPPU.Joypads[4] = 0; + IPPU.SuperScope = 0; + IPPU.Mouse[0] = IPPU.Mouse[1] = 0; + IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; + IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; + + if (Settings.ControllerOption == 0) + IPPU.Controller = SNES_MAX_CONTROLLER_OPTIONS - 1; + else + IPPU.Controller = Settings.ControllerOption - 1; + S9xNextController(); + + for (c = 0; c < 2; c++) + memset(& IPPU.Clip[c], 0, sizeof(ClipData)); + + if (Settings.MouseMaster) + { + S9xProcessMouse(0); + S9xProcessMouse(1); + } + for (c = 0; c < 0x8000; c += 0x100) + memset(& Memory.FillRAM[c], c >> 8, 0x100); + + ZeroMemory(& Memory.FillRAM[0x2100], 0x100); + ZeroMemory(& Memory.FillRAM[0x4200], 0x100); + ZeroMemory(& Memory.FillRAM[0x4000], 0x100); + // For BS Suttehakkun 2... + ZeroMemory(& Memory.FillRAM[0x1000], 0x1000); + Memory.FillRAM[0x4201]=Memory.FillRAM[0x4213]=0xFF; + + PPU.BG[0].OffsetsChanged = 0; + PPU.BG[1].OffsetsChanged = 0; + PPU.BG[2].OffsetsChanged = 0; + PPU.BG[3].OffsetsChanged = 0; + ROpCount = 0; + ZeroMemory(&rops, MAX_ROPS); + GFX.r212c_s = 0; + GFX.r212d_s = 0; + GFX.r212e_s = 0; + GFX.r212f_s = 0; + GFX.r2130_s = 0; + GFX.r2131_s = 0; +} + +void S9xProcessMouse(int which1) +{ + int x, y; + uint32 buttons; + + if ((IPPU.Controller == SNES_MOUSE + || IPPU.Controller == SNES_MOUSE_SWAPPED) + && S9xReadMousePosition(which1, &x, &y, &buttons)) + { + int delta_x, delta_y; +#define MOUSE_SIGNATURE 0x1 + IPPU.Mouse[which1] = + MOUSE_SIGNATURE + | (PPU.MouseSpeed[which1] << 4) + | ((buttons & 1) << 6) + | ((buttons & 2) << 6); + + delta_x = x - IPPU.PrevMouseX[which1]; + delta_y = y - IPPU.PrevMouseY[which1]; + + if (delta_x > 63) + { + delta_x = 63; + IPPU.PrevMouseX[which1] += 63; + } + else if (delta_x < -63) + { + delta_x = -63; + IPPU.PrevMouseX[which1] -= 63; + } + else + IPPU.PrevMouseX[which1] = x; + + if (delta_y > 63) + { + delta_y = 63; + IPPU.PrevMouseY[which1] += 63; + } + else if (delta_y < -63) + { + delta_y = -63; + IPPU.PrevMouseY[which1] -= 63; + } + else + IPPU.PrevMouseY[which1] = y; + + if (delta_x < 0) + { + delta_x = -delta_x; + IPPU.Mouse[which1] |= (delta_x | 0x80) << 16; + } + else + IPPU.Mouse[which1] |= delta_x << 16; + + if (delta_y < 0) + { + delta_y = -delta_y; + IPPU.Mouse[which1] |= (delta_y | 0x80) << 24; + } + else + IPPU.Mouse[which1] |= delta_y << 24; + + if (IPPU.Controller == SNES_MOUSE_SWAPPED) + IPPU.Joypads[0] = IPPU.Mouse[which1]; + else + IPPU.Joypads[1] = IPPU.Mouse[which1]; + } +} + +void ProcessSuperScope() +{ + int x, y; + uint32 buttons; + + if (IPPU.Controller == SNES_SUPERSCOPE + && S9xReadSuperScopePosition(&x, &y, &buttons)) + { +#define SUPERSCOPE_SIGNATURE 0x00ff + uint32 scope; + + scope = + SUPERSCOPE_SIGNATURE + | ((buttons & 1) << (7 + 8)) + | ((buttons & 2) << (5 + 8)) + | ((buttons & 4) << (3 + 8)) + | ((buttons & 8) << (1 + 8)); + if (x > 255) + x = 255; + if (x < 0) + x = 0; + if (y > PPU.ScreenHeight - 1) + y = PPU.ScreenHeight - 1; + if (y < 0) + y = 0; + + PPU.VBeamPosLatched = (uint16) (y + 1); + PPU.HBeamPosLatched = (uint16) x; + PPU.HVBeamCounterLatched = TRUE; + Memory.FillRAM[0x213F] |= 0x40; + IPPU.Joypads[1] = scope; + } +} + +void S9xNextController() +{ + switch (IPPU.Controller) + { + case SNES_MULTIPLAYER5 : + IPPU.Controller = SNES_JOYPAD; + break; + case SNES_JOYPAD : + if (Settings.MouseMaster) + { + IPPU.Controller = SNES_MOUSE_SWAPPED; + break; + } + case SNES_MOUSE_SWAPPED : + if (Settings.MouseMaster) + { + IPPU.Controller = SNES_MOUSE; + break; + } + case SNES_MOUSE : + if (Settings.SuperScopeMaster) + { + IPPU.Controller = SNES_SUPERSCOPE; + break; + } + case SNES_SUPERSCOPE : + if (Settings.MultiPlayer5Master) + { + IPPU.Controller = SNES_MULTIPLAYER5; + break; + } + default : + IPPU.Controller = SNES_JOYPAD; + break; + } +} + +void S9xUpdateJoypads() +{ +#if defined (__WIZ__) + IPPU.Joypads[0] = S9xReadJoypad (0); + + if (IPPU.Joypads[0] & SNES_LEFT_MASK) + IPPU.Joypads[0] &= ~SNES_RIGHT_MASK; + if (IPPU.Joypads[0] & SNES_UP_MASK) + IPPU.Joypads[0] &= ~SNES_DOWN_MASK; + + if (Memory.FillRAM [0x4200] & 1) + { + PPU.Joypad1ButtonReadPos = 16; + + Memory.FillRAM [0x4218] = (uint8) IPPU.Joypads[0]; + Memory.FillRAM [0x4219] = (uint8) (IPPU.Joypads[0] >> 8); + if (Memory.FillRAM [0x4201] & 0x80) + { + Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads[0]; + Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads[0] >> 8); + } + } +#else + int i; + + for (i = 0; i < 5; i++) + { + IPPU.Joypads[i] = S9xReadJoypad(i); + if (IPPU.Joypads[i] & SNES_LEFT_MASK) + IPPU.Joypads[i] &= ~SNES_RIGHT_MASK; + if (IPPU.Joypads[i] & SNES_UP_MASK) + IPPU.Joypads[i] &= ~SNES_DOWN_MASK; + } + + if (IPPU.Controller == SNES_JOYPAD + || IPPU.Controller == SNES_MULTIPLAYER5) + { + for (i = 0; i < 5; i++) + { + if (IPPU.Joypads[i]) + IPPU.Joypads[i] |= 0xffff0000; + } + } + + // Read mouse position if enabled + if (Settings.MouseMaster) + { + for (i = 0; i < 2; i++) + S9xProcessMouse(i); + } + + // Read SuperScope if enabled + if (Settings.SuperScopeMaster) + ProcessSuperScope(); + + if (Memory.FillRAM[0x4200] & 1) + { + PPU.Joypad1ButtonReadPos = 16; + if (Memory.FillRAM[0x4201] & 0x80) + { + PPU.Joypad2ButtonReadPos = 16; + PPU.Joypad3ButtonReadPos = 0; + } + else + { + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 16; + } + + Memory.FillRAM[0x4218] = (uint8) IPPU.Joypads[0]; + Memory.FillRAM[0x4219] = (uint8) (IPPU.Joypads[0] >> 8); + Memory.FillRAM[0x421a] = (uint8) IPPU.Joypads[1]; + Memory.FillRAM[0x421b] = (uint8) (IPPU.Joypads[1] >> 8); + if (Memory.FillRAM[0x4201] & 0x80) + { + Memory.FillRAM[0x421c] = (uint8) IPPU.Joypads[0]; + Memory.FillRAM[0x421d] = (uint8) (IPPU.Joypads[0] >> 8); + Memory.FillRAM[0x421e] = (uint8) IPPU.Joypads[2]; + Memory.FillRAM[0x421f] = (uint8) (IPPU.Joypads[2] >> 8); + } + else + { + Memory.FillRAM[0x421c] = (uint8) IPPU.Joypads[3]; + Memory.FillRAM[0x421d] = (uint8) (IPPU.Joypads[3] >> 8); + Memory.FillRAM[0x421e] = (uint8) IPPU.Joypads[4]; + Memory.FillRAM[0x421f] = (uint8) (IPPU.Joypads[4] >> 8); + } + } +#endif +} + +void S9xSuperFXExec() +{ + if ((Memory.FillRAM[0x3000 + GSU_SFR] & FLG_G) + && (Memory.FillRAM[0x3000 + GSU_SCMR] & 0x18) == 0x18) + { + if (!Settings.WinterGold||Settings.StarfoxHack) + FxEmulate(~0); + else FxEmulate((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? 700 : 350); + int GSUStatus = Memory.FillRAM[0x3000 + + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8); + if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) + { + // Trigger a GSU IRQ. + S9xSetIRQ(GSU_IRQ_SOURCE); + } + } +} + diff --git a/src/ppu.cpp b/src/ppu.cpp deleted file mode 100644 index 54526cf..0000000 --- a/src/ppu.cpp +++ /dev/null @@ -1,1413 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "missing.h" -#include "apu.h" -#include "dma.h" -#include "gfx.h" -#include "display.h" -#include "sa1.h" -#include "sdd1.h" -#include "srtc.h" - -#include "port.h" - -#ifndef ZSNES_FX -#include "fxemu.h" -#include "fxinst.h" -extern struct FxInit_s SuperFX; -extern struct FxRegs_s GSU; -#else -EXTERN_C void S9xSuperFXWriteReg (uint8, uint32); -EXTERN_C uint8 S9xSuperFXReadReg (uint32); -#endif -extern uint8 *HDMAMemPointers [8]; - -void S9xUpdateHTimer () -{ - if (PPU.HTimerEnabled) - { -#ifdef DEBUGGER - missing.hirq_pos = PPU.IRQHBeamPos; -#endif - PPU.HTimerPosition = PPU.IRQHBeamPos * Settings.H_Max / SNES_HCOUNTER_MAX; - if (PPU.HTimerPosition == Settings.H_Max || - PPU.HTimerPosition == Settings.HBlankStart) - { - PPU.HTimerPosition--; - } - - if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos) - { - if (PPU.HTimerPosition < CPU.Cycles) - { - // Missed the IRQ on this line already - if (CPU.WhichEvent == HBLANK_END_EVENT || - CPU.WhichEvent == HTIMER_AFTER_EVENT) - { - CPU.WhichEvent = HBLANK_END_EVENT; - CPU.NextEvent = Settings.H_Max; - } - else - { - CPU.WhichEvent = HBLANK_START_EVENT; - CPU.NextEvent = Settings.HBlankStart; - } - } - else - { - if (CPU.WhichEvent == HTIMER_BEFORE_EVENT || - CPU.WhichEvent == HBLANK_START_EVENT) - { - if (PPU.HTimerPosition > Settings.HBlankStart) - { - // HTimer was to trigger before h-blank start, - // now triggers after start of h-blank - CPU.NextEvent = Settings.HBlankStart; - CPU.WhichEvent = HBLANK_START_EVENT; - } - else - { - CPU.NextEvent = PPU.HTimerPosition; - CPU.WhichEvent = HTIMER_BEFORE_EVENT; - } - } - else - { - CPU.WhichEvent = HTIMER_AFTER_EVENT; - CPU.NextEvent = PPU.HTimerPosition; - } - } - } - } -} - -void S9xFixColourBrightness () -{ - IPPU.XB = mul_brightness [PPU.Brightness]; - if (Settings.SixteenBit) - { - for (unsigned int i = 0; i < 256; i++) - { - //IPPU.Red [i] = IPPU.XB [PPU.CGDATA [i] & 0x1f]; - //IPPU.Green [i] = IPPU.XB [(PPU.CGDATA [i] >> 5) & 0x1f]; - //IPPU.Blue [i] = IPPU.XB [(PPU.CGDATA [i] >> 10) & 0x1f]; - IPPU.ScreenColors [i] = BUILD_PIXEL (IPPU.XB[IPPU.Red [i]], IPPU.XB[IPPU.Green [i]], IPPU.XB[IPPU.Blue [i]]); - } - } -} - -/**********************************************************************************************/ -/* S9xSetPPU() */ -/* This function sets a PPU Register to a specific byte */ -/**********************************************************************************************/ -#include "ppu_setppu.h" - -/**********************************************************************************************/ -/* S9xGetPPU() */ -/* This function retrieves a PPU Register */ -/**********************************************************************************************/ -#include "ppu_getppu.h" - -/**********************************************************************************************/ -/* S9xSetCPU() */ -/* This function sets a CPU/DMA Register to a specific byte */ -/**********************************************************************************************/ -void S9xSetCPU(uint8 byte, uint16 Address) -{ - int d; - - if (Address < 0x4200) - { -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - switch (Address) - { - case 0x4016 : - // S9xReset reading of old-style joypads - if ((byte & 1) && !(Memory.FillRAM[Address] & 1)) - { - PPU.Joypad1ButtonReadPos = 0; - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 0; - } - break; - case 0x4017 : - break; - default : -#ifdef DEBUGGER - missing.unknowncpu_write = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf(String, "Unknown register register write: $%02X->$%04X\n", byte, Address); - S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); - } -#endif - break; - } - } - else - switch (Address) - { - case 0x4200 : - // NMI, V & H IRQ and joypad reading enable flags - if (byte & 0x20) - { - if (!PPU.VTimerEnabled) - { -#ifdef DEBUGGER - missing.virq = 1; - missing.virq_pos = PPU.IRQVBeamPos; -#endif - PPU.VTimerEnabled = TRUE; - if (PPU.HTimerEnabled) - S9xUpdateHTimer(); - else if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); - } - } - else - { - PPU.VTimerEnabled = FALSE; - } - - if (byte & 0x10) - { - if (!PPU.HTimerEnabled) - { -#ifdef DEBUGGER - missing.hirq = 1; - missing.hirq_pos = PPU.IRQHBeamPos; -#endif - PPU.HTimerEnabled = TRUE; - S9xUpdateHTimer(); - } - } - else - { - // No need to check for HTimer being disabled as the scanline - // event trigger code won't trigger an H-IRQ unless its enabled. - PPU.HTimerEnabled = FALSE; - PPU.HTimerPosition = Settings.H_Max + 1; - } - -#ifndef RC_OPTIMIZED - if (!Settings.DaffyDuck) - CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - - if ((byte & 0x80) - && !(Memory.FillRAM[0x4200] & 0x80) - && CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE - && CPU.V_Counter <= PPU.ScreenHeight + (SNESGameFixes.alienVSpredetorFix ? 25 : 15) - && //jyam 15->25 alien vs predetor - // Panic Bomberman clears the NMI pending flag @ scanline 230 before enabling - // NMIs again. The NMI routine crashes the CPU if it is called without the NMI - // pending flag being set... - (Memory.FillRAM[0x4210] & 0x80) && !CPU.NMIActive) - { - CPU.Flags |= NMI_FLAG; - CPU.NMIActive = TRUE; - CPU.NMICycleCount = CPU.NMITriggerPoint; - } -#endif - break; - case 0x4201 : - // I/O port output - case 0x4202 : - // Multiplier (for multply) - break; - case 0x4203 : - { - // Multiplicand - uint32 res = Memory.FillRAM[0x4202] * byte; - - Memory.FillRAM[0x4216] = (uint8) res; - Memory.FillRAM[0x4217] = (uint8) (res >> 8); - break; - } - case 0x4204 : - case 0x4205 : - // Low and high muliplier (for divide) - break; - case 0x4206 : - { - // Divisor - uint16 a = - Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); - uint16 div = byte ? a / byte : 0xffff; - uint16 rem = byte ? a % byte : a; - - Memory.FillRAM[0x4214] = (uint8) div; - Memory.FillRAM[0x4215] = div >> 8; - Memory.FillRAM[0x4216] = (uint8) rem; - Memory.FillRAM[0x4217] = rem >> 8; - break; - } - case 0x4207 : - d = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte; - - if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) - S9xUpdateHTimer(); - break; - - case 0x4208 : - d = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8); - - if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) - S9xUpdateHTimer(); - - break; - - case 0x4209 : - d = PPU.IRQVBeamPos; - PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF00) | byte; -#ifdef DEBUGGER - missing.virq_pos = PPU.IRQVBeamPos; -#endif - if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) - { - if (PPU.HTimerEnabled) - S9xUpdateHTimer(); - else - { - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); - } - } - break; - - case 0x420A : - d = PPU.IRQVBeamPos; - PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF) | ((byte & 1) << 8); -#ifdef DEBUGGER - missing.virq_pos = PPU.IRQVBeamPos; -#endif - if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) - { - if (PPU.HTimerEnabled) - S9xUpdateHTimer(); - else - { - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ(PPU_V_BEAM_IRQ_SOURCE); - } - } - break; - - case 0x420B : -#ifdef DEBUGGER - missing.dma_this_frame = byte; - missing.dma_channels = byte; -#endif - if ((byte & 0x01) != 0) - S9xDoDMA(0); - if ((byte & 0x02) != 0) - S9xDoDMA(1); - if ((byte & 0x04) != 0) - S9xDoDMA(2); - if ((byte & 0x08) != 0) - S9xDoDMA(3); - if ((byte & 0x10) != 0) - S9xDoDMA(4); - if ((byte & 0x20) != 0) - S9xDoDMA(5); - if ((byte & 0x40) != 0) - S9xDoDMA(6); - if ((byte & 0x80) != 0) - S9xDoDMA(7); - break; - case 0x420C : -#ifdef DEBUGGER - missing.hdma_this_frame |= byte; - missing.hdma_channels |= byte; -#endif - //if (Settings.DisableHDMA) - // byte = 0; - Memory.FillRAM[0x420c] = byte; - IPPU.HDMA = byte; - break; - - case 0x420d : - // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) - if ((byte & 1) != (Memory.FillRAM[0x420d] & 1)) - { - if (byte & 1) - { - CPU.FastROMSpeed = ONE_CYCLE; -#ifdef DEBUGGER - missing.fast_rom = 1; -#endif - } - else - CPU.FastROMSpeed = SLOW_ONE_CYCLE; - - Memory.FixROMSpeed(); - } - /* FALL */ - case 0x420e : - case 0x420f : - // --->>> Unknown - break; - case 0x4210 : - // NMI ocurred flag (reset on read or write) - Memory.FillRAM[0x4210] = 0; - return; - case 0x4211 : - // IRQ ocurred flag (reset on read or write) - CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - break; - case 0x4212 : - // v-blank, h-blank and joypad being scanned flags (read-only) - case 0x4213 : - // I/O Port (read-only) - case 0x4214 : - case 0x4215 : - // Quotent of divide (read-only) - case 0x4216 : - case 0x4217 : - // Multiply product (read-only) - return; - case 0x4218 : - case 0x4219 : - case 0x421a : - case 0x421b : - case 0x421c : - case 0x421d : - case 0x421e : - case 0x421f : - // Joypad values (read-only) - return; - - case 0x4300 : - case 0x4310 : - case 0x4320 : - case 0x4330 : - case 0x4340 : - case 0x4350 : - case 0x4360 : - case 0x4370 : - d = (Address >> 4) & 0x7; - DMA[d].TransferDirection = (byte & 128) != 0 ? 1 : 0; - DMA[d].HDMAIndirectAddressing = (byte & 64) != 0 ? 1 : 0; - DMA[d].AAddressDecrement = (byte & 16) != 0 ? 1 : 0; - DMA[d].AAddressFixed = (byte & 8) != 0 ? 1 : 0; - DMA[d].TransferMode = (byte & 7); - break; - - case 0x4301 : - case 0x4311 : - case 0x4321 : - case 0x4331 : - case 0x4341 : - case 0x4351 : - case 0x4361 : - case 0x4371 : - DMA[((Address >> 4) & 0x7)].BAddress = byte; - break; - - case 0x4302 : - case 0x4312 : - case 0x4322 : - case 0x4332 : - case 0x4342 : - case 0x4352 : - case 0x4362 : - case 0x4372 : - d = (Address >> 4) & 0x7; - DMA[d].AAddress &= 0xFF00; - DMA[d].AAddress |= byte; - break; - - case 0x4303 : - case 0x4313 : - case 0x4323 : - case 0x4333 : - case 0x4343 : - case 0x4353 : - case 0x4363 : - case 0x4373 : - d = (Address >> 4) & 0x7; - DMA[d].AAddress &= 0xFF; - DMA[d].AAddress |= byte << 8; - break; - - case 0x4304 : - case 0x4314 : - case 0x4324 : - case 0x4334 : - case 0x4344 : - case 0x4354 : - case 0x4364 : - case 0x4374 : - DMA[((Address >> 4) & 0x7)].ABank = byte; - HDMAMemPointers[((Address >> 4) & 0x7)]=NULL; - break; - - case 0x4305 : - case 0x4315 : - case 0x4325 : - case 0x4335 : - case 0x4345 : - case 0x4355 : - case 0x4365 : - case 0x4375 : - d = (Address >> 4) & 0x7; - DMA[d].TransferBytes &= 0xFF00; - DMA[d].TransferBytes |= byte; - DMA[d].IndirectAddress &= 0xff00; - DMA[d].IndirectAddress |= byte; - HDMAMemPointers[d]=NULL; - break; - - case 0x4306 : - case 0x4316 : - case 0x4326 : - case 0x4336 : - case 0x4346 : - case 0x4356 : - case 0x4366 : - case 0x4376 : - d = (Address >> 4) & 0x7; - DMA[d].TransferBytes &= 0xFF; - DMA[d].TransferBytes |= byte << 8; - DMA[d].IndirectAddress &= 0xff; - DMA[d].IndirectAddress |= byte << 8; - HDMAMemPointers[d]=NULL; - break; - - case 0x4307 : - case 0x4317 : - case 0x4327 : - case 0x4337 : - case 0x4347 : - case 0x4357 : - case 0x4367 : - case 0x4377 : - DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; - HDMAMemPointers[d]=NULL; - break; - - case 0x4308 : - case 0x4318 : - case 0x4328 : - case 0x4338 : - case 0x4348 : - case 0x4358 : - case 0x4368 : - case 0x4378 : - d = (Address >> 4) & 7; - DMA[d].Address &= 0xff00; - DMA[d].Address |= byte; - HDMAMemPointers[d] = NULL; - break; - - case 0x4309 : - case 0x4319 : - case 0x4329 : - case 0x4339 : - case 0x4349 : - case 0x4359 : - case 0x4369 : - case 0x4379 : - d = (Address >> 4) & 0x7; - DMA[d].Address &= 0xff; - DMA[d].Address |= byte << 8; - HDMAMemPointers[d] = NULL; - break; - - case 0x430A : - case 0x431A : - case 0x432A : - case 0x433A : - case 0x434A : - case 0x435A : - case 0x436A : - case 0x437A : - d = (Address >> 4) & 0x7; - DMA[d].LineCount = byte & 0x7f; - DMA[d].Repeat = !(byte & 0x80); - break; - - case 0x430F: - case 0x431F: - case 0x432F: - case 0x433F: - case 0x434F: - case 0x435F: - case 0x436F: - case 0x437F: - Address &= ~4; // Convert 43xF to 43xB - /* fall through */ - case 0x430B: - case 0x431B: - case 0x432B: - case 0x433B: - case 0x434B: - case 0x435B: - case 0x436B: - case 0x437B: - - // Unknown, but they seem to be RAM-ish - break; - case 0x4800 : - case 0x4801 : - case 0x4802 : - case 0x4803 : - //printf ("%02x->%04x\n", byte, Address); - break; - - case 0x4804 : - case 0x4805 : - case 0x4806 : - case 0x4807 : - //printf ("%02x->%04x\n", byte, Address); - - S9xSetSDD1MemoryMap(Address - 0x4804, byte & 7); - break; - default : -#ifdef DEBUGGER - missing.unknowncpu_write = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf( - String, - "Unknown register write: $%02X->$%04X\n", - byte, - Address); - S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); - } -#endif - break; - } - Memory.FillRAM[Address] = byte; -} - -/**********************************************************************************************/ -/* S9xGetCPU() */ -/* This function retrieves a CPU/DMA Register */ -/**********************************************************************************************/ -uint8 S9xGetCPU(uint16 Address) -{ - uint8 byte; - if(Address>=0x4800&&Address<=0x4807&&Settings.SDD1) - { - return Memory.FillRAM[Address]; - } - - if (Address < 0x4200) - { -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - switch (Address) - { - // Secret of the Evermore - case 0x4000 : - case 0x4001 : - return (0x40); - - case 0x4016 : - { - if (Memory.FillRAM[0x4016] & 1) - { - return (0); - } - - byte = IPPU.Joypads[0] >> (PPU.Joypad1ButtonReadPos ^ 15); - PPU.Joypad1ButtonReadPos++; - return (byte & 1); - } - case 0x4017 : - { - if (Memory.FillRAM[0x4016] & 1) - { - // MultiPlayer5 adaptor is only allowed to be plugged into port 2 - switch (IPPU.Controller) - { - case SNES_MULTIPLAYER5 : - return (2); - - case SNES_MOUSE : - if (++PPU.MouseSpeed[0] > 2) - PPU.MouseSpeed[0] = 0; - break; - } - return (0x00); - } - - if (IPPU.Controller == SNES_MULTIPLAYER5) - { - if (Memory.FillRAM[0x4201] & 0x80) - { - byte = - ((IPPU.Joypads[0] - >> (PPU.Joypad2ButtonReadPos ^ 15)) - & 1) - | (((IPPU.Joypads[2] - >> (PPU.Joypad2ButtonReadPos ^ 15)) - & 1) - << 1); - PPU.Joypad2ButtonReadPos++; - return (byte); - } - else - { - byte = - ((IPPU.Joypads[3] - >> (PPU.Joypad3ButtonReadPos ^ 15)) - & 1) - | (((IPPU.Joypads[4] - >> (PPU.Joypad3ButtonReadPos ^ 15)) - & 1) - << 1); - PPU.Joypad3ButtonReadPos++; - return (byte); - } - } - return ( - (IPPU.Joypads[1] - >> (PPU.Joypad2ButtonReadPos++ ^ 15)) - & 1); - } - default : -#ifdef DEBUGGER - missing.unknowncpu_read = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf(String, "Unknown register read: $%04X\n", Address); - S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); - } -#endif - break; - } - return (Memory.FillRAM[Address]); - } - else - switch (Address) - { - // BS Dynami Tracer! needs to be able to check if NMIs are enabled - // already, otherwise the game locks up. - case 0x4200 : - // NMI, h & v timers and joypad reading enable - if (SNESGameFixes.Old_Read0x4200) - { -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - return (REGISTER_4212()); - } - case 0x4201 : - // I/O port (output - write only?) - case 0x4202 : - case 0x4203 : - // Multiplier and multiplicand (write) - case 0x4204 : - case 0x4205 : - case 0x4206 : - // Divisor and dividend (write) - return (Memory.FillRAM[Address]); - case 0x4207 : - return (uint8) (PPU.IRQHBeamPos); - case 0x4208 : - return (PPU.IRQHBeamPos >> 8); - case 0x4209 : - return (uint8) (PPU.IRQVBeamPos); - case 0x420a : - return (PPU.IRQVBeamPos >> 8); - case 0x420b : - // General purpose DMA enable - // Super Formation Soccer 95 della Serie A UCC Xaqua requires this - // register should not always return zero. - // .. But Aero 2 waits until this register goes zero.. - // Just keep toggling the value for now in the hope that it breaks - // the game out of its wait loop... - Memory.FillRAM[0x420b] = !Memory.FillRAM[0x420b]; - return (Memory.FillRAM[0x420b]); - case 0x420c : - // H-DMA enable - return (IPPU.HDMA); - case 0x420d : - // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) - return (Memory.FillRAM[Address]); - case 0x420e : - case 0x420f : - // --->>> Unknown - return (Memory.FillRAM[Address]); - case 0x4210 : -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - byte = Memory.FillRAM[0x4210]; - Memory.FillRAM[0x4210] = 0; - return (byte); - case 0x4211 : - byte = - (CPU.IRQActive - & (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE)) - ? 0x80 - : 0; - // Super Robot Wars Ex ROM bug requires this. - byte |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; - CLEAR_IRQ_SOURCE(PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - return (byte); - case 0x4212 : - // V-blank, h-blank and joypads being read flags (read-only) -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - return (REGISTER_4212()); - case 0x4213 : - // I/O port input - case 0x4214 : - case 0x4215 : - // Quotient of divide result - case 0x4216 : - case 0x4217 : - // Multiplcation result (for multiply) or remainder of - // divison. - return (Memory.FillRAM[Address]); - case 0x4218 : - case 0x4219 : - case 0x421a : - case 0x421b : - case 0x421c : - case 0x421d : - case 0x421e : - case 0x421f : - // Joypads 1-4 button and direction state. - return (Memory.FillRAM[Address]); - - case 0x4300 : - case 0x4310 : - case 0x4320 : - case 0x4330 : - case 0x4340 : - case 0x4350 : - case 0x4360 : - case 0x4370 : - // DMA direction, address type, fixed flag, - return (Memory.FillRAM[Address]); - - case 0x4301 : - case 0x4311 : - case 0x4321 : - case 0x4331 : - case 0x4341 : - case 0x4351 : - case 0x4361 : - case 0x4371 : - return (Memory.FillRAM[Address]); - - case 0x4302 : - case 0x4312 : - case 0x4322 : - case 0x4332 : - case 0x4342 : - case 0x4352 : - case 0x4362 : - case 0x4372 : - return (Memory.FillRAM[Address]); - - case 0x4303 : - case 0x4313 : - case 0x4323 : - case 0x4333 : - case 0x4343 : - case 0x4353 : - case 0x4363 : - case 0x4373 : - return (Memory.FillRAM[Address]); - - case 0x4304 : - case 0x4314 : - case 0x4324 : - case 0x4334 : - case 0x4344 : - case 0x4354 : - case 0x4364 : - case 0x4374 : - return (Memory.FillRAM[Address]); - - case 0x4305 : - case 0x4315 : - case 0x4325 : - case 0x4335 : - case 0x4345 : - case 0x4355 : - case 0x4365 : - case 0x4375 : - return (Memory.FillRAM[Address]); - - case 0x4306 : - case 0x4316 : - case 0x4326 : - case 0x4336 : - case 0x4346 : - case 0x4356 : - case 0x4366 : - case 0x4376 : - return (Memory.FillRAM[Address]); - - case 0x4307 : - case 0x4317 : - case 0x4327 : - case 0x4337 : - case 0x4347 : - case 0x4357 : - case 0x4367 : - case 0x4377 : - return (DMA[(Address >> 4) & 7].IndirectBank); - - case 0x4308 : - case 0x4318 : - case 0x4328 : - case 0x4338 : - case 0x4348 : - case 0x4358 : - case 0x4368 : - case 0x4378 : - return (Memory.FillRAM[Address]); - - case 0x4309 : - case 0x4319 : - case 0x4329 : - case 0x4339 : - case 0x4349 : - case 0x4359 : - case 0x4369 : - case 0x4379 : - return (Memory.FillRAM[Address]); - - case 0x430A : - case 0x431A : - case 0x432A : - case 0x433A : - case 0x434A : - case 0x435A : - case 0x436A : - case 0x437A : - { - int d = (Address & 0x70) >> 4; - if (IPPU.HDMA & (1 << d)) - { - return (DMA[d].LineCount); - } - return (Memory.FillRAM[Address]); - } - case 0x430F: - case 0x431F: - case 0x432F: - case 0x433F: - case 0x434F: - case 0x435F: - case 0x436F: - case 0x437F: - Address &= ~4; // Convert 43xF to 43xB - /* fall through */ - case 0x430B: - case 0x431B: - case 0x432B: - case 0x433B: - case 0x434B: - case 0x435B: - case 0x436B: - case 0x437B: - - // Unknown, but they seem to be RAM-ish - return (Memory.FillRAM[Address]); - default : -#ifdef DEBUGGER - missing.unknowncpu_read = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf(String, "Unknown register read: $%04X\n", Address); - S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String); - } - -#endif - break; - } - return (Memory.FillRAM[Address]); -} - -void S9xResetPPU() -{ - PPU.BGMode = 0; - PPU.BG3Priority = 0; - PPU.Brightness = 0; - PPU.VMA.High = 0; - PPU.VMA.Increment = 1; - PPU.VMA.Address = 0; - PPU.VMA.FullGraphicCount = 0; - PPU.VMA.Shift = 0; - - for (uint8 B = 0; B != 4; B++) - { - PPU.BG[B].SCBase = 0; - PPU.BG[B].VOffset = 0; - PPU.BG[B].HOffset = 0; - PPU.BG[B].BGSize = 0; - PPU.BG[B].NameBase = 0; - PPU.BG[B].SCSize = 0; - - PPU.ClipCounts[B] = 0; - PPU.ClipWindowOverlapLogic[B] = CLIP_OR; - PPU.ClipWindow1Enable[B] = FALSE; - PPU.ClipWindow2Enable[B] = FALSE; - PPU.ClipWindow1Inside[B] = TRUE; - PPU.ClipWindow2Inside[B] = TRUE; - } - - PPU.ClipCounts[4] = 0; - PPU.ClipCounts[5] = 0; - PPU.ClipWindowOverlapLogic[4] = PPU.ClipWindowOverlapLogic[5] = CLIP_OR; - PPU.ClipWindow1Enable[4] = PPU.ClipWindow1Enable[5] = FALSE; - PPU.ClipWindow2Enable[4] = PPU.ClipWindow2Enable[5] = FALSE; - PPU.ClipWindow1Inside[4] = PPU.ClipWindow1Inside[5] = TRUE; - PPU.ClipWindow2Inside[4] = PPU.ClipWindow2Inside[5] = TRUE; - - PPU.CGFLIP = 0; - unsigned int c; - for (c = 0; c < 256; c++) - { - IPPU.Red[c] = (c & 7) << 2; - IPPU.Green[c] = ((c >> 3) & 7) << 2; - IPPU.Blue[c] = ((c >> 6) & 2) << 3; - PPU.CGDATA[c] = - IPPU.Red[c] | (IPPU.Green[c] << 5) | (IPPU.Blue[c] << 10); - } - - PPU.FirstSprite = 0; - PPU.LastSprite = 127; - for (int Sprite = 0; Sprite < 128; Sprite++) - { - PPU.OBJ[Sprite].HPos = 0; - PPU.OBJ[Sprite].VPos = 0; - PPU.OBJ[Sprite].VFlip = 0; - PPU.OBJ[Sprite].HFlip = 0; - PPU.OBJ[Sprite].Priority = 0; - PPU.OBJ[Sprite].Palette = 0; - PPU.OBJ[Sprite].Name = 0; - PPU.OBJ[Sprite].Size = 0; - } - PPU.OAMPriorityRotation = 0; - PPU.OAMWriteRegister = 0; - - PPU.OAMFlip = 0; - PPU.OAMTileAddress = 0; - PPU.OAMAddr = 0; - PPU.IRQVBeamPos = 0; - PPU.IRQHBeamPos = 0; - PPU.VBeamPosLatched = 0; - PPU.HBeamPosLatched = 0; - - PPU.HBeamFlip = 0; - PPU.VBeamFlip = 0; - PPU.HVBeamCounterLatched = 0; - - PPU.MatrixA = PPU.MatrixB = PPU.MatrixC = PPU.MatrixD = 0; - PPU.CentreX = PPU.CentreY = 0; - PPU.Joypad1ButtonReadPos = 0; - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 0; - - PPU.CGADD = 0; - PPU.FixedColourRed = PPU.FixedColourGreen = PPU.FixedColourBlue = 0; - PPU.SavedOAMAddr = 0; - PPU.SavedOAMAddr2 = 0; - PPU.ScreenHeight = SNES_HEIGHT; - PPU.WRAM = 0; - PPU.BG_Forced = 0; - PPU.ForcedBlanking = TRUE; - PPU.OBJThroughMain = FALSE; - PPU.OBJThroughSub = FALSE; - PPU.OBJSizeSelect = 0; - PPU.OBJNameSelect = 0; - PPU.OBJNameBase = 0; - PPU.OBJAddition = FALSE; - PPU.OAMReadFlip = 0; - PPU.BGnxOFSbyte = 0; - ZeroMemory(PPU.OAMData, 512 + 32); - - PPU.VTimerEnabled = FALSE; - PPU.HTimerEnabled = FALSE; - PPU.HTimerPosition = Settings.H_Max + 1; - PPU.Mosaic = 0; - PPU.BGMosaic[0] = PPU.BGMosaic[1] = FALSE; - PPU.BGMosaic[2] = PPU.BGMosaic[3] = FALSE; - PPU.Mode7HFlip = FALSE; - PPU.Mode7VFlip = FALSE; - PPU.Mode7Repeat = 0; - PPU.Window1Left = 1; - PPU.Window1Right = 0; - PPU.Window2Left = 1; - PPU.Window2Right = 0; - PPU.RecomputeClipWindows = TRUE; - PPU.CGFLIPRead = 0; - PPU.Need16x8Mulitply = FALSE; - PPU.MouseSpeed[0] = PPU.MouseSpeed[1] = 0; - - IPPU.ColorsChanged = TRUE; - IPPU.HDMA = 0; - IPPU.HDMAStarted = FALSE; - IPPU.MaxBrightness = 0; - IPPU.LatchedBlanking = 0; - IPPU.OBJChanged = TRUE; - IPPU.RenderThisFrame = TRUE; - IPPU.DirectColourMapsNeedRebuild = TRUE; - IPPU.FrameCount = 0; - IPPU.RenderedFramesCount = 0; - IPPU.DisplayedRenderedFrameCount = 0; - IPPU.SkippedFrames = 0; - IPPU.FrameSkip = 0; - ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES); - ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES); - ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES); - IPPU.FirstVRAMRead = FALSE; - IPPU.LatchedInterlace = FALSE; - IPPU.DoubleWidthPixels = FALSE; - IPPU.RenderedScreenWidth = SNES_WIDTH; - IPPU.RenderedScreenHeight = SNES_HEIGHT; - IPPU.XB = NULL; - for (c = 0; c < 256; c++) - IPPU.ScreenColors[c] = c; - S9xFixColourBrightness(); - IPPU.PreviousLine = IPPU.CurrentLine = 0; - IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; - IPPU.Joypads[3] = IPPU.Joypads[4] = 0; - IPPU.SuperScope = 0; - IPPU.Mouse[0] = IPPU.Mouse[1] = 0; - IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; - IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; - - if (Settings.ControllerOption == 0) - IPPU.Controller = SNES_MAX_CONTROLLER_OPTIONS - 1; - else - IPPU.Controller = Settings.ControllerOption - 1; - S9xNextController(); - - for (c = 0; c < 2; c++) - memset(& IPPU.Clip[c], 0, sizeof(struct ClipData)); - - if (Settings.MouseMaster) - { - S9xProcessMouse(0); - S9xProcessMouse(1); - } - for (c = 0; c < 0x8000; c += 0x100) - memset(& Memory.FillRAM[c], c >> 8, 0x100); - - ZeroMemory(& Memory.FillRAM[0x2100], 0x100); - ZeroMemory(& Memory.FillRAM[0x4200], 0x100); - ZeroMemory(& Memory.FillRAM[0x4000], 0x100); - // For BS Suttehakkun 2... - ZeroMemory(& Memory.FillRAM[0x1000], 0x1000); - Memory.FillRAM[0x4201]=Memory.FillRAM[0x4213]=0xFF; - - PPU.BG[0].OffsetsChanged = 0; - PPU.BG[1].OffsetsChanged = 0; - PPU.BG[2].OffsetsChanged = 0; - PPU.BG[3].OffsetsChanged = 0; - ROpCount = 0; - ZeroMemory(&rops, MAX_ROPS); - GFX.r212c_s = 0; - GFX.r212d_s = 0; - GFX.r212e_s = 0; - GFX.r212f_s = 0; - GFX.r2130_s = 0; - GFX.r2131_s = 0; -} - -void S9xProcessMouse(int which1) -{ - int x, y; - uint32 buttons; - - if ((IPPU.Controller == SNES_MOUSE - || IPPU.Controller == SNES_MOUSE_SWAPPED) - && S9xReadMousePosition(which1, x, y, buttons)) - { - int delta_x, delta_y; -#define MOUSE_SIGNATURE 0x1 - IPPU.Mouse[which1] = - MOUSE_SIGNATURE - | (PPU.MouseSpeed[which1] << 4) - | ((buttons & 1) << 6) - | ((buttons & 2) << 6); - - delta_x = x - IPPU.PrevMouseX[which1]; - delta_y = y - IPPU.PrevMouseY[which1]; - - if (delta_x > 63) - { - delta_x = 63; - IPPU.PrevMouseX[which1] += 63; - } - else if (delta_x < -63) - { - delta_x = -63; - IPPU.PrevMouseX[which1] -= 63; - } - else - IPPU.PrevMouseX[which1] = x; - - if (delta_y > 63) - { - delta_y = 63; - IPPU.PrevMouseY[which1] += 63; - } - else if (delta_y < -63) - { - delta_y = -63; - IPPU.PrevMouseY[which1] -= 63; - } - else - IPPU.PrevMouseY[which1] = y; - - if (delta_x < 0) - { - delta_x = -delta_x; - IPPU.Mouse[which1] |= (delta_x | 0x80) << 16; - } - else - IPPU.Mouse[which1] |= delta_x << 16; - - if (delta_y < 0) - { - delta_y = -delta_y; - IPPU.Mouse[which1] |= (delta_y | 0x80) << 24; - } - else - IPPU.Mouse[which1] |= delta_y << 24; - - if (IPPU.Controller == SNES_MOUSE_SWAPPED) - IPPU.Joypads[0] = IPPU.Mouse[which1]; - else - IPPU.Joypads[1] = IPPU.Mouse[which1]; - } -} - -void ProcessSuperScope() -{ - int x, y; - uint32 buttons; - - if (IPPU.Controller == SNES_SUPERSCOPE - && S9xReadSuperScopePosition(x, y, buttons)) - { -#define SUPERSCOPE_SIGNATURE 0x00ff - uint32 scope; - - scope = - SUPERSCOPE_SIGNATURE - | ((buttons & 1) << (7 + 8)) - | ((buttons & 2) << (5 + 8)) - | ((buttons & 4) << (3 + 8)) - | ((buttons & 8) << (1 + 8)); - if (x > 255) - x = 255; - if (x < 0) - x = 0; - if (y > PPU.ScreenHeight - 1) - y = PPU.ScreenHeight - 1; - if (y < 0) - y = 0; - - PPU.VBeamPosLatched = (uint16) (y + 1); - PPU.HBeamPosLatched = (uint16) x; - PPU.HVBeamCounterLatched = TRUE; - Memory.FillRAM[0x213F] |= 0x40; - IPPU.Joypads[1] = scope; - } -} - -void S9xNextController() -{ - switch (IPPU.Controller) - { - case SNES_MULTIPLAYER5 : - IPPU.Controller = SNES_JOYPAD; - break; - case SNES_JOYPAD : - if (Settings.MouseMaster) - { - IPPU.Controller = SNES_MOUSE_SWAPPED; - break; - } - case SNES_MOUSE_SWAPPED : - if (Settings.MouseMaster) - { - IPPU.Controller = SNES_MOUSE; - break; - } - case SNES_MOUSE : - if (Settings.SuperScopeMaster) - { - IPPU.Controller = SNES_SUPERSCOPE; - break; - } - case SNES_SUPERSCOPE : - if (Settings.MultiPlayer5Master) - { - IPPU.Controller = SNES_MULTIPLAYER5; - break; - } - default : - IPPU.Controller = SNES_JOYPAD; - break; - } -} - -void S9xUpdateJoypads() -{ -#if defined (__WIZ__) - IPPU.Joypads[0] = S9xReadJoypad (0); - - if (IPPU.Joypads[0] & SNES_LEFT_MASK) - IPPU.Joypads[0] &= ~SNES_RIGHT_MASK; - if (IPPU.Joypads[0] & SNES_UP_MASK) - IPPU.Joypads[0] &= ~SNES_DOWN_MASK; - - if (Memory.FillRAM [0x4200] & 1) - { - PPU.Joypad1ButtonReadPos = 16; - - Memory.FillRAM [0x4218] = (uint8) IPPU.Joypads[0]; - Memory.FillRAM [0x4219] = (uint8) (IPPU.Joypads[0] >> 8); - if (Memory.FillRAM [0x4201] & 0x80) - { - Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads[0]; - Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads[0] >> 8); - } - } -#else - int i; - - for (i = 0; i < 5; i++) - { - IPPU.Joypads[i] = S9xReadJoypad(i); - if (IPPU.Joypads[i] & SNES_LEFT_MASK) - IPPU.Joypads[i] &= ~SNES_RIGHT_MASK; - if (IPPU.Joypads[i] & SNES_UP_MASK) - IPPU.Joypads[i] &= ~SNES_DOWN_MASK; - } - - if (IPPU.Controller == SNES_JOYPAD - || IPPU.Controller == SNES_MULTIPLAYER5) - { - for (i = 0; i < 5; i++) - { - if (IPPU.Joypads[i]) - IPPU.Joypads[i] |= 0xffff0000; - } - } - - // Read mouse position if enabled - if (Settings.MouseMaster) - { - for (i = 0; i < 2; i++) - S9xProcessMouse(i); - } - - // Read SuperScope if enabled - if (Settings.SuperScopeMaster) - ProcessSuperScope(); - - if (Memory.FillRAM[0x4200] & 1) - { - PPU.Joypad1ButtonReadPos = 16; - if (Memory.FillRAM[0x4201] & 0x80) - { - PPU.Joypad2ButtonReadPos = 16; - PPU.Joypad3ButtonReadPos = 0; - } - else - { - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 16; - } - - Memory.FillRAM[0x4218] = (uint8) IPPU.Joypads[0]; - Memory.FillRAM[0x4219] = (uint8) (IPPU.Joypads[0] >> 8); - Memory.FillRAM[0x421a] = (uint8) IPPU.Joypads[1]; - Memory.FillRAM[0x421b] = (uint8) (IPPU.Joypads[1] >> 8); - if (Memory.FillRAM[0x4201] & 0x80) - { - Memory.FillRAM[0x421c] = (uint8) IPPU.Joypads[0]; - Memory.FillRAM[0x421d] = (uint8) (IPPU.Joypads[0] >> 8); - Memory.FillRAM[0x421e] = (uint8) IPPU.Joypads[2]; - Memory.FillRAM[0x421f] = (uint8) (IPPU.Joypads[2] >> 8); - } - else - { - Memory.FillRAM[0x421c] = (uint8) IPPU.Joypads[3]; - Memory.FillRAM[0x421d] = (uint8) (IPPU.Joypads[3] >> 8); - Memory.FillRAM[0x421e] = (uint8) IPPU.Joypads[4]; - Memory.FillRAM[0x421f] = (uint8) (IPPU.Joypads[4] >> 8); - } - } -#endif -} - -void S9xSuperFXExec() -{ - if ((Memory.FillRAM[0x3000 + GSU_SFR] & FLG_G) - && (Memory.FillRAM[0x3000 + GSU_SCMR] & 0x18) == 0x18) - { - if (!Settings.WinterGold||Settings.StarfoxHack) - FxEmulate(~0); - else FxEmulate((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? 700 : 350); - int GSUStatus = Memory.FillRAM[0x3000 - + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8); - if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) - { - // Trigger a GSU IRQ. - S9xSetIRQ(GSU_IRQ_SOURCE); - } - } -} - diff --git a/src/ppu.h b/src/ppu.h index b0d1a47..255e690 100644 --- a/src/ppu.h +++ b/src/ppu.h @@ -62,13 +62,13 @@ extern uint16 SignExtend [2]; #define SA1_IRQ_SOURCE (1 << 7) #define SA1_DMA_IRQ_SOURCE (1 << 5) -struct ClipData { +typedef struct { uint32 Count [6]; uint32 Left [6][6]; uint32 Right [6][6]; -}; +}ClipData; -struct InternalPPU { +typedef struct{ bool8 ColorsChanged; uint8 HDMA; bool8 HDMAStarted; @@ -102,10 +102,10 @@ struct InternalPPU { uint32 Mouse[2]; int PrevMouseX[2]; int PrevMouseY[2]; - struct ClipData Clip [2]; -}; + ClipData Clip [2]; +}InternalPPU; -struct SOBJ +typedef struct { short HPos; uint16 VPos; @@ -115,9 +115,10 @@ struct SOBJ uint8 Priority; uint8 Palette; uint8 Size; -}; +}SOBJ; -struct SPPU { +typedef struct +{ uint8 BGMode; uint8 BG3Priority; uint8 Brightness; @@ -145,7 +146,7 @@ struct SPPU { uint16 CGDATA [256]; uint8 FirstSprite; uint8 LastSprite; - struct SOBJ OBJ [128]; + SOBJ OBJ [128]; uint8 OAMPriorityRotation; uint16 OAMAddr; @@ -212,14 +213,14 @@ struct SPPU { uint16 SavedOAMAddr2; uint16 OAMWriteRegister; uint8 BGnxOFSbyte; -}; +}SPPU; #define CLIP_OR 0 #define CLIP_AND 1 #define CLIP_XOR 2 #define CLIP_XNOR 3 -struct SDMA { +typedef struct { bool8 TransferDirection; bool8 AAddressFixed; bool8 AAddressDecrement; @@ -240,7 +241,7 @@ struct SDMA { uint8 Repeat; uint8 LineCount; uint8 FirstLine; -}; +}SDMA; START_EXTERN_C //void S9xUpdateScreen (); @@ -261,9 +262,9 @@ uint8 S9xGetC4 (uint16 Address); void S9xSetC4RAM (uint8 Byte, uint16 Address); uint8 S9xGetC4RAM (uint16 Address); -extern struct SPPU PPU; -extern struct SDMA DMA [8]; -extern struct InternalPPU IPPU; +extern SPPU PPU; +extern SDMA DMA [8]; +extern InternalPPU IPPU; END_EXTERN_C #include "gfx.h" @@ -309,7 +310,7 @@ STATIC INLINE void REGISTER_2104 (uint8 byte) IPPU.OBJChanged = TRUE; // X position high bit, and sprite size (x4) - struct SOBJ *pObj = &PPU.OBJ [(addr & 0x1f) * 4]; + SOBJ *pObj = &PPU.OBJ [(addr & 0x1f) * 4]; pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(byte >> 0) & 1]; pObj++->Size = byte & 2; diff --git a/src/ppu_.c b/src/ppu_.c new file mode 100644 index 0000000..e6cfecb --- /dev/null +++ b/src/ppu_.c @@ -0,0 +1,2486 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" +#include "missing.h" +#include "apu.h" +#include "dma.h" +#include "gfx.h" +#include "display.h" +#include "sa1.h" +#include "sdd1.h" +#include "srtc.h" + + +#ifndef ZSNES_FX +#include "fxemu.h" +#include "fxinst.h" +extern FxInit_s SuperFX; +extern FxRegs_s GSU; +#else +EXTERN_C void S9xSuperFXWriteReg (uint8, uint32); +EXTERN_C uint8 S9xSuperFXReadReg (uint32); +#endif + +void S9xUpdateHTimer () +{ + if (PPU.HTimerEnabled) + { +#ifdef DEBUGGER + missing.hirq_pos = PPU.IRQHBeamPos; +#endif + PPU.HTimerPosition = PPU.IRQHBeamPos * Settings.H_Max / SNES_HCOUNTER_MAX; + if (PPU.HTimerPosition == Settings.H_Max || + PPU.HTimerPosition == Settings.HBlankStart) + { + PPU.HTimerPosition--; + } + + if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos) + { + if (PPU.HTimerPosition < CPU.Cycles) + { + // Missed the IRQ on this line already + if (CPU.WhichEvent == HBLANK_END_EVENT || + CPU.WhichEvent == HTIMER_AFTER_EVENT) + { + CPU.WhichEvent = HBLANK_END_EVENT; + CPU.NextEvent = Settings.H_Max; + } + else + { + CPU.WhichEvent = HBLANK_START_EVENT; + CPU.NextEvent = Settings.HBlankStart; + } + } + else + { + if (CPU.WhichEvent == HTIMER_BEFORE_EVENT || + CPU.WhichEvent == HBLANK_START_EVENT) + { + if (PPU.HTimerPosition > Settings.HBlankStart) + { + // HTimer was to trigger before h-blank start, + // now triggers after start of h-blank + CPU.NextEvent = Settings.HBlankStart; + CPU.WhichEvent = HBLANK_START_EVENT; + } + else + { + CPU.NextEvent = PPU.HTimerPosition; + CPU.WhichEvent = HTIMER_BEFORE_EVENT; + } + } + else + { + CPU.WhichEvent = HTIMER_AFTER_EVENT; + CPU.NextEvent = PPU.HTimerPosition; + } + } + } + } +} + +void S9xFixColourBrightness () +{ + IPPU.XB = mul_brightness [PPU.Brightness]; + if (Settings.SixteenBit) + { + for (int i = 0; i < 256; i++) + { + IPPU.Red [i] = IPPU.XB [PPU.CGDATA [i] & 0x1f]; + IPPU.Green [i] = IPPU.XB [(PPU.CGDATA [i] >> 5) & 0x1f]; + IPPU.Blue [i] = IPPU.XB [(PPU.CGDATA [i] >> 10) & 0x1f]; + IPPU.ScreenColors [i] = BUILD_PIXEL (IPPU.Red [i], IPPU.Green [i], + IPPU.Blue [i]); + } + } +} + +/**********************************************************************************************/ +/* S9xSetPPU() */ +/* This function sets a PPU Register to a specific byte */ +/**********************************************************************************************/ +void S9xSetPPU (uint8 Byte, uint16 Address) +{ + if (Address <= 0x2183) + { + switch (Address) + { + case 0x2100: + // Brightness and screen blank bit + if (Byte != Memory.FillRAM [0x2100]) + { + FLUSH_REDRAW (); + if (PPU.Brightness != (Byte & 0xF)) + { + IPPU.ColorsChanged = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + PPU.Brightness = Byte & 0xF; + S9xFixColourBrightness (); + if (PPU.Brightness > IPPU.MaxBrightness) + IPPU.MaxBrightness = PPU.Brightness; + } + if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80)) + { + IPPU.ColorsChanged = TRUE; + PPU.ForcedBlanking = (Byte >> 7) & 1; + } + } + break; + + case 0x2101: + // Sprite (OBJ) tile address + if (Byte != Memory.FillRAM [0x2101]) + { + FLUSH_REDRAW (); + PPU.OBJNameBase = (Byte & 3) << 14; + PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13; + PPU.OBJSizeSelect = (Byte >> 5) & 7; + IPPU.OBJChanged = TRUE; + } + break; + + case 0x2102: + // Sprite write address (low) + PPU.OAMAddr = Byte; + PPU.OAMFlip = 2; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + if (PPU.OAMPriorityRotation) + { + PPU.FirstSprite = PPU.OAMAddr & 0x7f; +#ifdef DEBUGGER + missing.sprite_priority_rotation = 1; +#endif + } + break; + + case 0x2103: + // Sprite register write address (high), sprite priority rotation + // bit. + if ((PPU.OAMPriorityRotation = (Byte & 0x80) == 0 ? 0 : 1)) + { + PPU.FirstSprite = PPU.OAMAddr & 0x7f; +#ifdef DEBUGGER + missing.sprite_priority_rotation = 1; +#endif + } + // Only update the sprite write address top bit if the low byte has + // been written to first. + if (PPU.OAMFlip & 2) + { + PPU.OAMAddr &= 0x00FF; + PPU.OAMAddr |= (Byte & 1) << 8; + } + PPU.OAMFlip = 0; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + break; + + case 0x2104: + // Sprite register write + REGISTER_2104(Byte, &Memory, &IPPU, &PPU); + + break; + + case 0x2105: + // Screen mode (0 - 7), background tile sizes and background 3 + // priority + if (Byte != Memory.FillRAM [0x2105]) + { + FLUSH_REDRAW (); + PPU.BG3Priority = (Byte >> 3) & 1; + PPU.BG[0].BGSize = (Byte >> 4) & 1; + PPU.BG[1].BGSize = (Byte >> 5) & 1; + PPU.BG[2].BGSize = (Byte >> 6) & 1; + PPU.BG[3].BGSize = (Byte >> 7) & 1; + PPU.BGMode = Byte & 7; +#ifdef DEBUGGER + missing.modes[PPU.BGMode] = 1; +#endif + } + break; + + case 0x2106: + // Mosaic pixel size and enable + if (Byte != Memory.FillRAM [0x2106]) + { + FLUSH_REDRAW (); +#ifdef DEBUGGER + if ((Byte & 0xf0) && (Byte & 0x0f)) + missing.mosaic = 1; +#endif + PPU.Mosaic = (Byte >> 4) + 1; + PPU.BGMosaic [0] = (Byte & 1) && PPU.Mosaic > 1; + PPU.BGMosaic [1] = (Byte & 2) && PPU.Mosaic > 1; + PPU.BGMosaic [2] = (Byte & 4) && PPU.Mosaic > 1; + PPU.BGMosaic [3] = (Byte & 8) && PPU.Mosaic > 1; + } + break; + case 0x2107: // [BG0SC] + if (Byte != Memory.FillRAM [0x2107]) + { + FLUSH_REDRAW (); + PPU.BG[0].SCSize = Byte & 3; + PPU.BG[0].SCBase = (Byte & 0x7c) << 8; + } + break; + + case 0x2108: // [BG1SC] + if (Byte != Memory.FillRAM [0x2108]) + { + FLUSH_REDRAW (); + PPU.BG[1].SCSize = Byte & 3; + PPU.BG[1].SCBase = (Byte & 0x7c) << 8; + } + break; + + case 0x2109: // [BG2SC] + if (Byte != Memory.FillRAM [0x2109]) + { + FLUSH_REDRAW (); + PPU.BG[2].SCSize = Byte & 3; + PPU.BG[2].SCBase = (Byte & 0x7c) << 8; + } + break; + + case 0x210A: // [BG3SC] + if (Byte != Memory.FillRAM [0x210a]) + { + FLUSH_REDRAW (); + PPU.BG[3].SCSize = Byte & 3; + PPU.BG[3].SCBase = (Byte & 0x7c) << 8; + } + break; + + case 0x210B: // [BG01NBA] + if (Byte != Memory.FillRAM [0x210b]) + { + FLUSH_REDRAW (); + PPU.BG[0].NameBase = (Byte & 7) << 12; + PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12; + } + break; + + case 0x210C: // [BG23NBA] + if (Byte != Memory.FillRAM [0x210c]) + { + FLUSH_REDRAW (); + PPU.BG[2].NameBase = (Byte & 7) << 12; + PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12; + } + break; + + case 0x210D: + PPU.BG[0].HOffset = ((PPU.BG[0].HOffset >> 8) & 0xff) | + ((uint16) Byte << 8); + break; + + case 0x210E: + PPU.BG[0].VOffset = ((PPU.BG[0].VOffset >> 8) & 0xff) | + ((uint16) Byte << 8); + break; + case 0x210F: + PPU.BG[1].HOffset = ((PPU.BG[1].HOffset >> 8) & 0xff) | + ((uint16) Byte << 8); + break; + + case 0x2110: + PPU.BG[1].VOffset = ((PPU.BG[1].VOffset >> 8) & 0xff) | + ((uint16) Byte << 8); + break; + + case 0x2111: + PPU.BG[2].HOffset = ((PPU.BG[2].HOffset >> 8) & 0xff) | + ((uint16) Byte << 8); + break; + + case 0x2112: + PPU.BG[2].VOffset = ((PPU.BG[2].VOffset >> 8) & 0xff) | + ((uint16) Byte << 8); + break; + + case 0x2113: + PPU.BG[3].HOffset = ((PPU.BG[3].HOffset >> 8) & 0xff) | + ((uint16) Byte << 8); + break; + + case 0x2114: + PPU.BG[3].VOffset = ((PPU.BG[3].VOffset >> 8) & 0xff) | + ((uint16) Byte << 8); + break; + + case 0x2115: + // VRAM byte/word access flag and increment + PPU.VMA.High = (Byte & 0x80) == 0 ? FALSE : TRUE; + switch (Byte & 3) + { + case 0: + PPU.VMA.Increment = 1; + break; + case 1: + PPU.VMA.Increment = 32; + break; + case 2: + PPU.VMA.Increment = 128; + break; + case 3: + PPU.VMA.Increment = 128; + break; + } +#ifdef DEBUGGER + if ((Byte & 3) != 0) + missing.vram_inc = Byte & 3; +#endif + if (Byte & 0x0c) + { + static uint16 IncCount [4] = { 0, 32, 64, 128 }; + static uint16 Shift [4] = { 0, 5, 6, 7 }; +#ifdef DEBUGGER + missing.vram_full_graphic_inc = (Byte & 0x0c) >> 2; +#endif + PPU.VMA.Increment = 1; + uint8 i = (Byte & 0x0c) >> 2; + PPU.VMA.FullGraphicCount = IncCount [i]; + PPU.VMA.Mask1 = IncCount [i] * 8 - 1; + PPU.VMA.Shift = Shift [i]; + } + else + PPU.VMA.FullGraphicCount = 0; + break; + + case 0x2116: + // VRAM read/write address (low) + PPU.VMA.Address &= 0xFF00; + PPU.VMA.Address |= Byte; + IPPU.FirstVRAMRead = TRUE; + break; + + case 0x2117: + // VRAM read/write address (high) + PPU.VMA.Address &= 0x00FF; + PPU.VMA.Address |= Byte << 8; + IPPU.FirstVRAMRead = TRUE; + break; + + case 0x2118: + // VRAM write data (low) + IPPU.FirstVRAMRead = TRUE; + REGISTER_2118(Byte, &Memory, &IPPU, &PPU); + break; + + case 0x2119: + // VRAM write data (high) + IPPU.FirstVRAMRead = TRUE; + REGISTER_2119(Byte, &Memory, &IPPU, &PPU); + break; + + case 0x211a: + // Mode 7 outside rotation area display mode and flipping + if (Byte != Memory.FillRAM [0x211a]) + { + FLUSH_REDRAW (); + PPU.Mode7Repeat = Byte >> 6; + PPU.Mode7VFlip = (Byte & 2) >> 1; + PPU.Mode7HFlip = Byte & 1; + } + break; + case 0x211b: + // Mode 7 matrix A (low & high) + PPU.MatrixA = ((PPU.MatrixA >> 8) & 0xff) | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + break; + case 0x211c: + // Mode 7 matrix B (low & high) + PPU.MatrixB = ((PPU.MatrixB >> 8) & 0xff) | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + break; + case 0x211d: + // Mode 7 matrix C (low & high) + PPU.MatrixC = ((PPU.MatrixC >> 8) & 0xff) | (Byte << 8); + break; + case 0x211e: + // Mode 7 matrix D (low & high) + PPU.MatrixD = ((PPU.MatrixD >> 8) & 0xff) | (Byte << 8); + break; + case 0x211f: + // Mode 7 centre of rotation X (low & high) + PPU.CentreX = ((PPU.CentreX >> 8) & 0xff) | (Byte << 8); + break; + case 0x2120: + // Mode 7 centre of rotation Y (low & high) + PPU.CentreY = ((PPU.CentreY >> 8) & 0xff) | (Byte << 8); + break; + + case 0x2121: + // CG-RAM address + PPU.CGFLIP = 0; + PPU.CGFLIPRead = 0; + PPU.CGADD = Byte; + break; + + case 0x2122: + REGISTER_2122(Byte, &Memory, &IPPU, &PPU); + break; + + case 0x2123: + // Window 1 and 2 enable for backgrounds 1 and 2 + if (Byte != Memory.FillRAM [0x2123]) + { + FLUSH_REDRAW (); + + PPU.ClipWindow1Enable [0] = !!(Byte & 0x02); + PPU.ClipWindow1Enable [1] = !!(Byte & 0x20); + PPU.ClipWindow2Enable [0] = !!(Byte & 0x08); + PPU.ClipWindow2Enable [1] = !!(Byte & 0x80); + PPU.ClipWindow1Inside [0] = !(Byte & 0x01); + PPU.ClipWindow1Inside [1] = !(Byte & 0x10); + PPU.ClipWindow2Inside [0] = !(Byte & 0x04); + PPU.ClipWindow2Inside [1] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; +#ifdef DEBUGGER + if (Byte & 0x80) + missing.window2[1] = 1; + if (Byte & 0x20) + missing.window1[1] = 1; + if (Byte & 0x08) + missing.window2[0] = 1; + if (Byte & 0x02) + missing.window1[0] = 1; +#endif + } + break; + case 0x2124: + // Window 1 and 2 enable for backgrounds 3 and 4 + if (Byte != Memory.FillRAM [0x2124]) + { + FLUSH_REDRAW (); + + PPU.ClipWindow1Enable [2] = !!(Byte & 0x02); + PPU.ClipWindow1Enable [3] = !!(Byte & 0x20); + PPU.ClipWindow2Enable [2] = !!(Byte & 0x08); + PPU.ClipWindow2Enable [3] = !!(Byte & 0x80); + PPU.ClipWindow1Inside [2] = !(Byte & 0x01); + PPU.ClipWindow1Inside [3] = !(Byte & 0x10); + PPU.ClipWindow2Inside [2] = !(Byte & 0x04); + PPU.ClipWindow2Inside [3] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; +#ifdef DEBUGGER + if (Byte & 0x80) + missing.window2[3] = 1; + if (Byte & 0x20) + missing.window1[3] = 1; + if (Byte & 0x08) + missing.window2[2] = 1; + if (Byte & 0x02) + missing.window1[2] = 1; +#endif + } + break; + case 0x2125: + // Window 1 and 2 enable for objects and colour window + if (Byte != Memory.FillRAM [0x2125]) + { + FLUSH_REDRAW (); + + PPU.ClipWindow1Enable [4] = !!(Byte & 0x02); + PPU.ClipWindow1Enable [5] = !!(Byte & 0x20); + PPU.ClipWindow2Enable [4] = !!(Byte & 0x08); + PPU.ClipWindow2Enable [5] = !!(Byte & 0x80); + PPU.ClipWindow1Inside [4] = !(Byte & 0x01); + PPU.ClipWindow1Inside [5] = !(Byte & 0x10); + PPU.ClipWindow2Inside [4] = !(Byte & 0x04); + PPU.ClipWindow2Inside [5] = !(Byte & 0x40); + PPU.RecomputeClipWindows = TRUE; +#ifdef DEBUGGER + if (Byte & 0x80) + missing.window2[5] = 1; + if (Byte & 0x20) + missing.window1[5] = 1; + if (Byte & 0x08) + missing.window2[4] = 1; + if (Byte & 0x02) + missing.window1[4] = 1; +#endif + } + break; + case 0x2126: + // Window 1 left position + if (Byte != Memory.FillRAM [0x2126]) + { + FLUSH_REDRAW (); + + PPU.Window1Left = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2127: + // Window 1 right position + if (Byte != Memory.FillRAM [0x2127]) + { + FLUSH_REDRAW (); + + PPU.Window1Right = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2128: + // Window 2 left position + if (Byte != Memory.FillRAM [0x2128]) + { + FLUSH_REDRAW (); + + PPU.Window2Left = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2129: + // Window 2 right position + if (Byte != Memory.FillRAM [0x2129]) + { + FLUSH_REDRAW (); + + PPU.Window2Right = Byte; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212a: + // Windows 1 & 2 overlap logic for backgrounds 1 - 4 + if (Byte != Memory.FillRAM [0x212a]) + { + FLUSH_REDRAW (); + + PPU.ClipWindowOverlapLogic [0] = (Byte & 0x03); + PPU.ClipWindowOverlapLogic [1] = (Byte & 0x0c) >> 2; + PPU.ClipWindowOverlapLogic [2] = (Byte & 0x30) >> 4; + PPU.ClipWindowOverlapLogic [3] = (Byte & 0xc0) >> 6; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212b: + // Windows 1 & 2 overlap logic for objects and colour window + if (Byte != Memory.FillRAM [0x212b]) + { + FLUSH_REDRAW (); + + PPU.ClipWindowOverlapLogic [4] = Byte & 0x03; + PPU.ClipWindowOverlapLogic [5] = (Byte & 0x0c) >> 2; + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212c: + // Main screen designation (backgrounds 1 - 4 and objects) + if (Byte != Memory.FillRAM [0x212c]) + { + FLUSH_REDRAW (); + + PPU.RecomputeClipWindows = TRUE; + Memory.FillRAM [Address] = Byte; + return; + } + break; + case 0x212d: + // Sub-screen designation (backgrounds 1 - 4 and objects) + if (Byte != Memory.FillRAM [0x212d]) + { + FLUSH_REDRAW (); + +#ifdef DEBUGGER + if (Byte & 0x1f) + missing.subscreen = 1; +#endif + PPU.RecomputeClipWindows = TRUE; + Memory.FillRAM [Address] = Byte; + return; + } + break; + case 0x212e: + // Window mask designation for main screen ? + if (Byte != Memory.FillRAM [0x212e]) + { + FLUSH_REDRAW (); + + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x212f: + // Window mask designation for sub-screen ? + if (Byte != Memory.FillRAM [0x212f]) + { + FLUSH_REDRAW (); + + PPU.RecomputeClipWindows = TRUE; + } + break; + case 0x2130: + // Fixed colour addition or screen addition + if (Byte != Memory.FillRAM [0x2130]) + { + FLUSH_REDRAW (); + + PPU.RecomputeClipWindows = TRUE; +#ifdef DEBUGGER + if ((Byte & 1) && (PPU.BGMode == 3 || PPU.BGMode == 4 || PPU.BGMode == 7)) + missing.direct = 1; +#endif + } + break; + case 0x2131: + // Colour addition or subtraction select + if (Byte != Memory.FillRAM[0x2131]) + { + FLUSH_REDRAW (); + + // Backgrounds 1 - 4, objects and backdrop colour add/sub enable +#ifdef DEBUGGER + if (Byte & 0x80) + { + // Subtract + if (Memory.FillRAM[0x2130] & 0x02) + missing.subscreen_sub = 1; + else + missing.fixed_colour_sub = 1; + } + else + { + // Addition + if (Memory.FillRAM[0x2130] & 0x02) + missing.subscreen_add = 1; + else + missing.fixed_colour_add = 1; + } +#endif + Memory.FillRAM[0x2131] = Byte; + } + break; + case 0x2132: + if (Byte != Memory.FillRAM [0x2132]) + { + FLUSH_REDRAW (); + + // Colour data for fixed colour addition/subtraction + if (Byte & 0x80) + PPU.FixedColourBlue = Byte & 0x1f; + if (Byte & 0x40) + PPU.FixedColourGreen = Byte & 0x1f; + if (Byte & 0x20) + PPU.FixedColourRed = Byte & 0x1f; + } + break; + case 0x2133: + // Screen settings + if (Byte != Memory.FillRAM [0x2133]) + { +#ifdef DEBUGGER + if (Byte & 0x40) + missing.mode7_bgmode = 1; + if (Byte & 0x08) + missing.pseudo_512 = 1; +#endif + if (Byte & 0x04) + { + PPU.ScreenHeight = SNES_HEIGHT_EXTENDED; +#ifdef DEBUGGER + missing.lines_239 = 1; +#endif + } + else + PPU.ScreenHeight = SNES_HEIGHT; +#ifdef DEBUGGER + if (Byte & 0x02) + missing.sprite_double_height = 1; + + if (Byte & 1) + missing.interlace = 1; +#endif + } + break; + case 0x2134: + case 0x2135: + case 0x2136: + // Matrix 16bit x 8bit multiply result (read-only) + return; + + case 0x2137: + // Software latch for horizontal and vertical timers (read-only) + return; + case 0x2138: + // OAM read data (read-only) + return; + case 0x2139: + case 0x213a: + // VRAM read data (read-only) + return; + case 0x213b: + // CG-RAM read data (read-only) + return; + case 0x213c: + case 0x213d: + // Horizontal and vertical (low/high) read counter (read-only) + return; + case 0x213e: + // PPU status (time over and range over) + return; + case 0x213f: + // NTSC/PAL select and field (read-only) + return; + case 0x2140: case 0x2141: case 0x2142: case 0x2143: + case 0x2144: case 0x2145: case 0x2146: case 0x2147: + case 0x2148: case 0x2149: case 0x214a: case 0x214b: + case 0x214c: case 0x214d: case 0x214e: case 0x214f: + case 0x2150: case 0x2151: case 0x2152: case 0x2153: + case 0x2154: case 0x2155: case 0x2156: case 0x2157: + case 0x2158: case 0x2159: case 0x215a: case 0x215b: + case 0x215c: case 0x215d: case 0x215e: case 0x215f: + case 0x2160: case 0x2161: case 0x2162: case 0x2163: + case 0x2164: case 0x2165: case 0x2166: case 0x2167: + case 0x2168: case 0x2169: case 0x216a: case 0x216b: + case 0x216c: case 0x216d: case 0x216e: case 0x216f: + case 0x2170: case 0x2171: case 0x2172: case 0x2173: + case 0x2174: case 0x2175: case 0x2176: case 0x2177: + case 0x2178: case 0x2179: case 0x217a: case 0x217b: + case 0x217c: case 0x217d: case 0x217e: case 0x217f: +#ifdef SPCTOOL + _SPCInPB (Address & 3, Byte); +#else +// CPU.Flags |= DEBUG_MODE_FLAG; + Memory.FillRAM [Address] = Byte; + IAPU.RAM [(Address & 3) + 0xf4] = Byte; +#ifdef SPC700_SHUTDOWN + IAPU.APUExecuting = Settings.APUEnabled; + IAPU.WaitCounter++; +#endif +#endif // SPCTOOL + break; + case 0x2180: + REGISTER_2180(Byte, &Memory, &IPPU, &PPU); + break; + case 0x2181: + PPU.WRAM &= 0x1FF00; + PPU.WRAM |= Byte; + break; + case 0x2182: + PPU.WRAM &= 0x100FF; + PPU.WRAM |= Byte << 8; + break; + case 0x2183: + PPU.WRAM &= 0x0FFFF; + PPU.WRAM |= Byte << 16; + PPU.WRAM &= 0x1FFFF; + break; + } + } + else + { + if (Settings.SA1) + { + if (Address >= 0x2200 && Address <0x23ff) + S9xSetSA1 (Byte, Address); + else + Memory.FillRAM [Address] = Byte; + return; + } + else + // Dai Kaijyu Monogatari II + if (Address == 0x2801 && Settings.SRTC) + S9xSetSRTC (Byte, Address); + else + if (Address < 0x3000 || Address >= 0x3000 + 768) + { +#ifdef DEBUGGER + missing.unknownppu_write = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf (String, "Unknown register write: $%02X->$%04X\n", + Byte, Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + } + else + { + if (!Settings.SuperFX) + return; + + #ifdef ZSNES_FX + Memory.FillRAM [Address] = Byte; + if (Address < 0x3040) + S9xSuperFXWriteReg (Byte, Address); + #else + switch (Address) + { + case 0x3030: + if ((Memory.FillRAM [0x3030] ^ Byte) & FLG_G) + { + Memory.FillRAM [Address] = Byte; + // Go flag has been changed + if (Byte & FLG_G) + S9xSuperFXExec (); + else + FxFlushCache (&GSU); + } + else + Memory.FillRAM [Address] = Byte; + break; + + case 0x3031: + Memory.FillRAM [Address] = Byte; + break; + case 0x3033: + Memory.FillRAM [Address] = Byte; + break; + case 0x3034: + Memory.FillRAM [Address] = Byte & 0x7f; + break; + case 0x3036: + Memory.FillRAM [Address] = Byte & 0x7f; + break; + case 0x3037: + Memory.FillRAM [Address] = Byte; + break; + case 0x3038: + Memory.FillRAM [Address] = Byte; + break; + case 0x3039: + Memory.FillRAM [Address] = Byte; + break; + case 0x303a: + Memory.FillRAM [Address] = Byte; + break; + case 0x303b: + break; + case 0x303f: + Memory.FillRAM [Address] = Byte; + break; + case 0x301f: + Memory.FillRAM [Address] = Byte; + Memory.FillRAM [0x3000 + GSU_SFR] |= FLG_G; + S9xSuperFXExec (); + return; + + default: + Memory.FillRAM[Address] = Byte; + if (Address >= 0x3100) + { + FxCacheWriteAccess (Address, &GSU); + } + break; + } + #endif + return; + } + } + Memory.FillRAM[Address] = Byte; +} + +/**********************************************************************************************/ +/* S9xGetPPU() */ +/* This function retrieves a PPU Register */ +/**********************************************************************************************/ +uint8 S9xGetPPU (uint16 Address) +{ + uint8 byte = 0; + + if (Address <= 0x2190) + { + switch (Address) + { + case 0x2100: + case 0x2101: + return (Memory.FillRAM[Address]); + case 0x2102: +#ifdef DEBUGGER + missing.oam_address_read = 1; +#endif + return (uint8)(PPU.OAMAddr); + case 0x2103: + return (((PPU.OAMAddr >> 8) & 1) | (PPU.OAMPriorityRotation << 7)); + case 0x2104: + case 0x2105: + case 0x2106: + case 0x2107: + case 0x2108: + case 0x2109: + case 0x210a: + case 0x210b: + case 0x210c: + return (Memory.FillRAM[Address]); + case 0x210d: + case 0x210e: + case 0x210f: + case 0x2110: + case 0x2111: + case 0x2112: + case 0x2113: + case 0x2114: +#ifdef DEBUGGER + missing.bg_offset_read = 1; +#endif + return (Memory.FillRAM[Address]); + case 0x2115: + return (Memory.FillRAM[Address]); + case 0x2116: + return (uint8)(PPU.VMA.Address); + case 0x2117: + return (PPU.VMA.Address >> 8); + case 0x2118: + case 0x2119: + case 0x211a: + return (Memory.FillRAM[Address]); + case 0x211b: + case 0x211c: + case 0x211d: + case 0x211e: + case 0x211f: + case 0x2120: +#ifdef DEBUGGER + missing.matrix_read = 1; +#endif + return (Memory.FillRAM[Address]); + case 0x2121: + return (PPU.CGADD); + case 0x2122: + case 0x2123: + case 0x2124: + case 0x2125: + case 0x2126: + case 0x2127: + case 0x2128: + case 0x2129: + case 0x212a: + case 0x212b: + case 0x212c: + case 0x212d: + case 0x212e: + case 0x212f: + case 0x2130: + case 0x2131: + case 0x2132: + case 0x2133: + return (Memory.FillRAM[Address]); + + case 0x2134: + case 0x2135: + case 0x2136: + // 16bit x 8bit multiply read result. + if (PPU.Need16x8Mulitply) + { + int32 r = (int32) PPU.MatrixA * (int32) (PPU.MatrixB >> 8); + + Memory.FillRAM[0x2134] = (uint8) r; + Memory.FillRAM[0x2135] = (uint8)(r >> 8); + Memory.FillRAM[0x2136] = (uint8)(r >> 16); + PPU.Need16x8Mulitply = FALSE; + } +#ifdef DEBUGGER + missing.matrix_multiply = 1; +#endif + return (Memory.FillRAM[Address]); + case 0x2137: + // Latch h and v counters +#ifdef DEBUGGER + missing.h_v_latch = 1; +#endif +#if 0 +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif +#endif + PPU.HVBeamCounterLatched = 1; + PPU.VBeamPosLatched = (uint16) CPU.V_Counter; + PPU.HBeamPosLatched = (uint16) ((CPU.Cycles * SNES_HCOUNTER_MAX) / Settings.H_Max); + + // Causes screen flicker for Yoshi's Island if uncommented + //CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + + if (SNESGameFixes.NeedInit0x2137) + PPU.VBeamFlip = 0; //jyam sword world sfc2 & godzill + return (0); + case 0x2138: + // Read OAM (sprite) control data + if (!PPU.OAMReadFlip) + { + byte = PPU.OAMData [PPU.OAMAddr << 1]; + } + else + { + byte = PPU.OAMData [(PPU.OAMAddr << 1) + 1]; + if (++PPU.OAMAddr >= 0x110) + PPU.OAMAddr = 0; + + } + PPU.OAMReadFlip ^= 1; +#ifdef DEBUGGER + missing.oam_read = 1; +#endif + return (byte); + + case 0x2139: + // Read vram low byte +#ifdef DEBUGGER + missing.vram_read = 1; +#endif + if (IPPU.FirstVRAMRead) + byte = Memory.VRAM[PPU.VMA.Address << 1]; + else + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address - 1; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + byte = Memory.VRAM [((address << 1) - 2) & 0xFFFF]; + } + else + byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff]; + + if (!PPU.VMA.High) + { + PPU.VMA.Address += PPU.VMA.Increment; + IPPU.FirstVRAMRead = FALSE; + } + break; + case 0x213A: + // Read vram high byte +#ifdef DEBUGGER + missing.vram_read = 1; +#endif + if (IPPU.FirstVRAMRead) + byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff]; + else + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address - 1; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + + (rem >> PPU.VMA.Shift) + + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + byte = Memory.VRAM [((address << 1) - 1) & 0xFFFF]; + } + else + byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xFFFF]; + if (PPU.VMA.High) + { + PPU.VMA.Address += PPU.VMA.Increment; + IPPU.FirstVRAMRead = FALSE; + } + break; + + case 0x213B: + // Read palette data +#ifdef DEBUGGER + missing.cgram_read = 1; +#endif + if (PPU.CGFLIPRead) + byte = PPU.CGDATA [PPU.CGADD++] >> 8; + else + byte = PPU.CGDATA [PPU.CGADD] & 0xff; + + PPU.CGFLIPRead ^= 1; + return (byte); + + case 0x213C: + // Horizontal counter value 0-339 +#ifdef DEBUGGER + missing.h_counter_read = 1; +#endif + if (PPU.HBeamFlip) + byte = PPU.HBeamPosLatched >> 8; + else + byte = (uint8)PPU.HBeamPosLatched; + PPU.HBeamFlip ^= 1; + break; + case 0x213D: + // Vertical counter value 0-262 +#ifdef DEBUGGER + missing.v_counter_read = 1; +#endif + if (PPU.VBeamFlip) + byte = PPU.VBeamPosLatched >> 8; + else + byte = (uint8)PPU.VBeamPosLatched; + PPU.VBeamFlip ^= 1; + break; + case 0x213E: + // PPU time and range over flags + return (SNESGameFixes._0x213E_ReturnValue); + + case 0x213F: + // NTSC/PAL and which field flags + PPU.VBeamFlip = PPU.HBeamFlip = 0; + return ((Settings.PAL ? 0x10 : 0) | (Memory.FillRAM[0x213f] & 0xc0)); + + case 0x2140: case 0x2141: case 0x2142: case 0x2143: + case 0x2144: case 0x2145: case 0x2146: case 0x2147: + case 0x2148: case 0x2149: case 0x214a: case 0x214b: + case 0x214c: case 0x214d: case 0x214e: case 0x214f: + case 0x2150: case 0x2151: case 0x2152: case 0x2153: + case 0x2154: case 0x2155: case 0x2156: case 0x2157: + case 0x2158: case 0x2159: case 0x215a: case 0x215b: + case 0x215c: case 0x215d: case 0x215e: case 0x215f: + case 0x2160: case 0x2161: case 0x2162: case 0x2163: + case 0x2164: case 0x2165: case 0x2166: case 0x2167: + case 0x2168: case 0x2169: case 0x216a: case 0x216b: + case 0x216c: case 0x216d: case 0x216e: case 0x216f: + case 0x2170: case 0x2171: case 0x2172: case 0x2173: + case 0x2174: case 0x2175: case 0x2176: case 0x2177: + case 0x2178: case 0x2179: case 0x217a: case 0x217b: + case 0x217c: case 0x217d: case 0x217e: case 0x217f: +#ifdef SPCTOOL + return ((uint8) _SPCOutP [Address & 3]); +#else + // CPU.Flags |= DEBUG_MODE_FLAG; +#ifdef SPC700_SHUTDOWN + IAPU.APUExecuting = Settings.APUEnabled; + IAPU.WaitCounter++; +#endif + if (Settings.APUEnabled) + { +#ifdef CPU_SHUTDOWN +// CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + if (SNESGameFixes.APU_OutPorts_ReturnValueFix && + Address >= 0x2140 && Address <= 0x2143 && !CPU.V_Counter) + { + return (uint8)((Address & 1) ? ((rand() & 0xff00) >> 8) : + (rand() & 0xff)); + } + + return (APU.OutPorts [Address & 3]); + } + + switch (Settings.SoundSkipMethod) + { + case 0: + case 1: + CPU.BranchSkip = TRUE; + break; + case 2: + break; + case 3: + CPU.BranchSkip = TRUE; + break; + } + if (Address & 3 < 2) + { + int r = rand (); + if (r & 2) + { + if (r & 4) + return (Address & 3 == 1 ? 0xaa : 0xbb); + else + return ((r >> 3) & 0xff); + } + } + else + { + int r = rand (); + if (r & 2) + return ((r >> 3) & 0xff); + } + return (Memory.FillRAM[Address]); +#endif // SPCTOOL + + case 0x2180: + // Read WRAM +#ifdef DEBUGGER + missing.wram_read = 1; +#endif + byte = Memory.RAM [PPU.WRAM++]; + PPU.WRAM &= 0x1FFFF; + break; + case 0x2181: + case 0x2182: + case 0x2183: + return (Memory.FillRAM [Address]); + case 0x2190: + return (1); + } + } + else + { + if (Settings.SA1) + return (S9xGetSA1 (Address)); + + if (Address <= 0x2fff || Address >= 0x3000 + 768) + { + switch (Address) + { + case 0x21c2: + return (0x20); + case 0x21c3: + return (0); + case 0x2800: + // For Dai Kaijyu Monogatari II + if (Settings.SRTC) + return (S9xGetSRTC (Address)); + /*FALL*/ + + default: +#ifdef DEBUGGER + missing.unknownppu_read = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf (String, "Unknown register read: $%04X\n", Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + // XXX: + return (0); //Memory.FillRAM[Address]); + } + } + + if (!Settings.SuperFX) + return (0x30); +#ifdef ZSNES_FX + if (Address < 0x3040) + byte = S9xSuperFXReadReg (Address); + else + byte = Memory.FillRAM [Address]; + +#ifdef CPU_SHUTDOWN + if (Address == 0x3030) + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + if (Address == 0x3031) + CLEAR_IRQ_SOURCE (GSU_IRQ_SOURCE); +#else + byte = Memory.FillRAM [Address]; + +//if (Address != 0x3030 && Address != 0x3031) +//printf ("%04x\n", Address); +#ifdef CPU_SHUTDOWN + if (Address == 0x3030) + { + CPU.WaitAddress = CPU.PCAtOpcodeStart; + } + else +#endif + if (Address == 0x3031) + { + CLEAR_IRQ_SOURCE (GSU_IRQ_SOURCE); + Memory.FillRAM [0x3031] = byte & 0x7f; + } + return (byte); +#endif + } + + return (byte); +} + +/**********************************************************************************************/ +/* S9xSetCPU() */ +/* This function sets a CPU/DMA Register to a specific byte */ +/**********************************************************************************************/ +void S9xSetCPU (uint8 byte, uint16 Address) +{ + int d; + + if (Address < 0x4200) + { +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + switch (Address) + { + case 0x4016: + // S9xReset reading of old-style joypads + if ((byte & 1) && !(Memory.FillRAM [Address] & 1)) + { + PPU.Joypad1ButtonReadPos = 0; + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 0; + } + break; + case 0x4017: + break; + default: +#ifdef DEBUGGER + missing.unknowncpu_write = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf (String, "Unknown register register write: $%02X->$%04X\n", + byte, Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + break; + } + } + else + switch (Address) + { + case 0x4200: + // NMI, V & H IRQ and joypad reading enable flags + if ((byte & 0x20) && + (!SNESGameFixes.umiharakawaseFix || PPU.IRQVBeamPos < 209)) + { + if (!PPU.VTimerEnabled) + { +#ifdef DEBUGGER + missing.virq = 1; + missing.virq_pos = PPU.IRQVBeamPos; +#endif + PPU.VTimerEnabled = TRUE; + if (PPU.HTimerEnabled) + S9xUpdateHTimer (); + else + if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); + } + } + else + { + PPU.VTimerEnabled = FALSE; +#ifndef RC_OPTIMIZED + if (SNESGameFixes.umiharakawaseFix) + byte &= ~0x20; +#endif + } + + if (byte & 0x10) + { + if (!PPU.HTimerEnabled) + { +#ifdef DEBUGGER + missing.hirq = 1; + missing.hirq_pos = PPU.IRQHBeamPos; +#endif + PPU.HTimerEnabled = TRUE; + S9xUpdateHTimer (); + } + } + else + { + // No need to check for HTimer being disabled as the scanline + // event trigger code won't trigger an H-IRQ unless its enabled. + PPU.HTimerEnabled = FALSE; + PPU.HTimerPosition = Settings.H_Max + 1; + } + +#ifndef RC_OPTIMIZED + if (!Settings.DaffyDuck) + CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + + if ((byte & 0x80) && + !(Memory.FillRAM [0x4200] & 0x80) && + CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && + CPU.V_Counter <= PPU.ScreenHeight + + (SNESGameFixes.alienVSpredetorFix ? 25 : 15) && //jyam 15->25 alien vs predetor +// Panic Bomberman clears the NMI pending flag @ scanline 230 before enabling +// NMIs again. The NMI routine crashes the CPU if it is called without the NMI +// pending flag being set... + (Memory.FillRAM [0x4210] & 0x80) && + !CPU.NMIActive) + { + CPU.Flags |= NMI_FLAG; + CPU.NMIActive = TRUE; + CPU.NMICycleCount = CPU.NMITriggerPoint; + } +#endif + break; + case 0x4201: + // I/O port output + case 0x4202: + // Multiplier (for multply) + break; + case 0x4203: + { + // Multiplicand + uint32 res = Memory.FillRAM[0x4202] * byte; + + Memory.FillRAM[0x4216] = (uint8) res; + Memory.FillRAM[0x4217] = (uint8) (res >> 8); + break; + } + case 0x4204: + case 0x4205: + // Low and high muliplier (for divide) + break; + case 0x4206: + { + // Divisor + uint16 a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); + uint16 div = byte ? a / byte : 0xffff; + uint16 rem = byte ? a % byte : a; + + Memory.FillRAM[0x4214] = (uint8)div; + Memory.FillRAM[0x4215] = div >> 8; + Memory.FillRAM[0x4216] = (uint8)rem; + Memory.FillRAM[0x4217] = rem >> 8; + break; + } + case 0x4207: + d = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte; + + if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) + S9xUpdateHTimer (); + break; + + case 0x4208: + d = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8); + + if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) + S9xUpdateHTimer (); + + break; + + case 0x4209: + d = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF00) | byte; +#ifdef DEBUGGER + missing.virq_pos = PPU.IRQVBeamPos; +#endif + if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) + { + if (PPU.HTimerEnabled) + S9xUpdateHTimer (); + else + { + if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); + } + } + break; + + case 0x420A: + d = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF) | ((byte & 1) << 8); +#ifdef DEBUGGER + missing.virq_pos = PPU.IRQVBeamPos; +#endif + if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) + { + if (PPU.HTimerEnabled) + S9xUpdateHTimer (); + else + { + if (PPU.IRQVBeamPos == CPU.V_Counter) + S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); + } + } + break; + + case 0x420B: +#ifdef DEBUGGER + missing.dma_this_frame = byte; + missing.dma_channels = byte; +#endif + if ((byte & 0x01) != 0) + S9xDoDMA (0); + if ((byte & 0x02) != 0) + S9xDoDMA (1); + if ((byte & 0x04) != 0) + S9xDoDMA (2); + if ((byte & 0x08) != 0) + S9xDoDMA (3); + if ((byte & 0x10) != 0) + S9xDoDMA (4); + if ((byte & 0x20) != 0) + S9xDoDMA (5); + if ((byte & 0x40) != 0) + S9xDoDMA (6); + if ((byte & 0x80) != 0) + S9xDoDMA (7); + break; + case 0x420C: +#ifdef DEBUGGER + missing.hdma_this_frame |= byte; + missing.hdma_channels |= byte; +#endif + if (Settings.DisableHDMA) + byte = 0; + Memory.FillRAM[0x420c] = byte; + IPPU.HDMA = byte; + break; + + case 0x420d: + // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) + if ((byte & 1) != (Memory.FillRAM [0x420d] & 1)) + { + if (byte & 1) + { + CPU.FastROMSpeed = ONE_CYCLE; +#ifdef DEBUGGER + missing.fast_rom = 1; +#endif + } + else + CPU.FastROMSpeed = SLOW_ONE_CYCLE; + + Memory.FixROMSpeed (); + } + /* FALL */ + case 0x420e: + case 0x420f: + // --->>> Unknown + break; + case 0x4210: + // NMI ocurred flag (reset on read or write) + Memory.FillRAM[0x4210] = 0; + return; + case 0x4211: + // IRQ ocurred flag (reset on read or write) + CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + break; + case 0x4212: + // v-blank, h-blank and joypad being scanned flags (read-only) + case 0x4213: + // I/O Port (read-only) + case 0x4214: + case 0x4215: + // Quotent of divide (read-only) + case 0x4216: + case 0x4217: + // Multiply product (read-only) + return; + case 0x4218: + case 0x4219: + case 0x421a: + case 0x421b: + case 0x421c: + case 0x421d: + case 0x421e: + case 0x421f: + // Joypad values (read-only) + return; + + case 0x4300: + case 0x4310: + case 0x4320: + case 0x4330: + case 0x4340: + case 0x4350: + case 0x4360: + case 0x4370: + d = (Address >> 4) & 0x7; + DMA[d].TransferDirection = (byte & 128) != 0 ? 1 : 0; + DMA[d].HDMAIndirectAddressing = (byte & 64) != 0 ? 1 : 0; + DMA[d].AAddressDecrement = (byte & 16) != 0 ? 1 : 0; + DMA[d].AAddressFixed = (byte & 8) != 0 ? 1 : 0; + DMA[d].TransferMode = (byte & 7); + break; + + case 0x4301: + case 0x4311: + case 0x4321: + case 0x4331: + case 0x4341: + case 0x4351: + case 0x4361: + case 0x4371: + DMA[((Address >> 4) & 0x7)].BAddress = byte; + break; + + case 0x4302: + case 0x4312: + case 0x4322: + case 0x4332: + case 0x4342: + case 0x4352: + case 0x4362: + case 0x4372: + d = (Address >> 4) & 0x7; + DMA[d].AAddress &= 0xFF00; + DMA[d].AAddress |= byte; + break; + + case 0x4303: + case 0x4313: + case 0x4323: + case 0x4333: + case 0x4343: + case 0x4353: + case 0x4363: + case 0x4373: + d = (Address >> 4) & 0x7; + DMA[d].AAddress &= 0xFF; + DMA[d].AAddress |= byte << 8; + break; + + case 0x4304: + case 0x4314: + case 0x4324: + case 0x4334: + case 0x4344: + case 0x4354: + case 0x4364: + case 0x4374: + DMA[((Address >> 4) & 0x7)].ABank = byte; + break; + + case 0x4305: + case 0x4315: + case 0x4325: + case 0x4335: + case 0x4345: + case 0x4355: + case 0x4365: + case 0x4375: + d = (Address >> 4) & 0x7; + DMA[d].TransferBytes &= 0xFF00; + DMA[d].TransferBytes |= byte; + DMA[d].IndirectAddress &= 0xff00; + DMA[d].IndirectAddress |= byte; + break; + + case 0x4306: + case 0x4316: + case 0x4326: + case 0x4336: + case 0x4346: + case 0x4356: + case 0x4366: + case 0x4376: + d = (Address >> 4) & 0x7; + DMA[d].TransferBytes &= 0xFF; + DMA[d].TransferBytes |= byte << 8; + DMA[d].IndirectAddress &= 0xff; + DMA[d].IndirectAddress |= byte << 8; + break; + + case 0x4307: + case 0x4317: + case 0x4327: + case 0x4337: + case 0x4347: + case 0x4357: + case 0x4367: + case 0x4377: + DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; + break; + + case 0x4308: + case 0x4318: + case 0x4328: + case 0x4338: + case 0x4348: + case 0x4358: + case 0x4368: + case 0x4378: + d = (Address >> 4) & 7; + DMA[d].Address &= 0xff00; + DMA[d].Address |= byte; + break; + + case 0x4309: + case 0x4319: + case 0x4329: + case 0x4339: + case 0x4349: + case 0x4359: + case 0x4369: + case 0x4379: + d = (Address >> 4) & 0x7; + DMA[d].Address &= 0xff; + DMA[d].Address |= byte << 8; + break; + + case 0x430A: + case 0x431A: + case 0x432A: + case 0x433A: + case 0x434A: + case 0x435A: + case 0x436A: + case 0x437A: + d = (Address >> 4) & 0x7; + DMA[d].LineCount = byte & 0x7f; + DMA[d].Repeat = !(byte & 0x80); + break; + + case 0x4800: + case 0x4801: + case 0x4802: + case 0x4803: +//printf ("%02x->%04x\n", byte, Address); + break; + + case 0x4804: + case 0x4805: + case 0x4806: + case 0x4807: +//printf ("%02x->%04x\n", byte, Address); + + S9xSetSDD1MemoryMap (Address - 0x4804, byte & 7); + break; + default: +#ifdef DEBUGGER + missing.unknowncpu_write = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf (String, "Unknown register write: $%02X->$%04X\n", + byte, Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + break; + } + Memory.FillRAM [Address] = byte; +} + +/**********************************************************************************************/ +/* S9xGetCPU() */ +/* This function retrieves a CPU/DMA Register */ +/**********************************************************************************************/ +uint8 S9xGetCPU (uint16 Address) +{ + uint8 byte; + + if (Address < 0x4200) + { +#ifdef VAR_CYCLES + CPU.Cycles += ONE_CYCLE; +#endif + switch (Address) + { + // Secret of the Evermore + case 0x4000: + case 0x4001: + return (0x40); + + case 0x4016: + { + if (Memory.FillRAM [0x4016] & 1) + { + if ((!Settings.SwapJoypads && + IPPU.Controller == SNES_MOUSE_SWAPPED) || + (Settings.SwapJoypads && + IPPU.Controller == SNES_MOUSE)) + { + if (++PPU.MouseSpeed [0] > 2) + PPU.MouseSpeed [0] = 0; + } + return (0); + } + + int ind = Settings.SwapJoypads ? 1 : 0; + byte = IPPU.Joypads[ind] >> (PPU.Joypad1ButtonReadPos ^ 15); + PPU.Joypad1ButtonReadPos++; + return (byte & 1); + } + case 0x4017: + { + if (Memory.FillRAM [0x4016] & 1) + { + // MultiPlayer5 adaptor is only allowed to be plugged into port 2 + switch (IPPU.Controller) + { + case SNES_MULTIPLAYER5: + return (2); + case SNES_MOUSE_SWAPPED: + if (Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) + PPU.MouseSpeed [0] = 0; + break; + + case SNES_MOUSE: + if (!Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) + PPU.MouseSpeed [0] = 0; + break; + } + return (0x00); + } + + int ind = Settings.SwapJoypads ? 0 : 1; + + if (IPPU.Controller == SNES_MULTIPLAYER5) + { + if (Memory.FillRAM [0x4201] & 0x80) + { + byte = ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) | + (((IPPU.Joypads[2] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) << 1); + PPU.Joypad2ButtonReadPos++; + return (byte); + } + else + { + byte = ((IPPU.Joypads[3] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) | + (((IPPU.Joypads[4] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) << 1); + PPU.Joypad3ButtonReadPos++; + return (byte); + } + } + return ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos++ ^ 15)) & 1); + } + default: +#ifdef DEBUGGER + missing.unknowncpu_read = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf (String, "Unknown register read: $%04X\n", Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } +#endif + break; + } + return (Memory.FillRAM [Address]); + } + else + switch (Address) + { + // BS Dynami Tracer! needs to be able to check if NMIs are enabled + // already, otherwise the game locks up. + case 0x4200: + // NMI, h & v timers and joypad reading enable + if (SNESGameFixes.Old_Read0x4200) + { +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + return (REGISTER_4212()); + } + case 0x4201: + // I/O port (output - write only?) + case 0x4202: + case 0x4203: + // Multiplier and multiplicand (write) + case 0x4204: + case 0x4205: + case 0x4206: + // Divisor and dividend (write) + return (Memory.FillRAM[Address]); + case 0x4207: + return (uint8)(PPU.IRQHBeamPos); + case 0x4208: + return (PPU.IRQHBeamPos >> 8); + case 0x4209: + return (uint8)(PPU.IRQVBeamPos); + case 0x420a: + return (PPU.IRQVBeamPos >> 8); + case 0x420b: + // General purpose DMA enable + // Super Formation Soccer 95 della Serie A UCC Xaqua requires this + // register should not always return zero. + // .. But Aero 2 waits until this register goes zero.. + // Just keep toggling the value for now in the hope that it breaks + // the game out of its wait loop... + Memory.FillRAM [0x420b] = !Memory.FillRAM [0x420b]; + return (Memory.FillRAM [0x420b]); + case 0x420c: + // H-DMA enable + return (IPPU.HDMA); + case 0x420d: + // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) + return (Memory.FillRAM[Address]); + case 0x420e: + case 0x420f: + // --->>> Unknown + return (Memory.FillRAM[Address]); + case 0x4210: +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + byte = Memory.FillRAM[0x4210]; + Memory.FillRAM[0x4210] = 0; + return (byte); + case 0x4211: + byte = (CPU.IRQActive & (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE)) ? 0x80 : 0; + // Super Robot Wars Ex ROM bug requires this. + byte |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; + CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); + return (byte); + case 0x4212: + // V-blank, h-blank and joypads being read flags (read-only) +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; +#endif + return (REGISTER_4212()); + case 0x4213: + // I/O port input + case 0x4214: + case 0x4215: + // Quotient of divide result + case 0x4216: + case 0x4217: + // Multiplcation result (for multiply) or remainder of + // divison. + return (Memory.FillRAM[Address]); + case 0x4218: + case 0x4219: + case 0x421a: + case 0x421b: + case 0x421c: + case 0x421d: + case 0x421e: + case 0x421f: + // Joypads 1-4 button and direction state. + return (Memory.FillRAM [Address]); + + case 0x4300: + case 0x4310: + case 0x4320: + case 0x4330: + case 0x4340: + case 0x4350: + case 0x4360: + case 0x4370: + // DMA direction, address type, fixed flag, + return (Memory.FillRAM[Address]); + + case 0x4301: + case 0x4311: + case 0x4321: + case 0x4331: + case 0x4341: + case 0x4351: + case 0x4361: + case 0x4371: + return (Memory.FillRAM[Address]); + + case 0x4302: + case 0x4312: + case 0x4322: + case 0x4332: + case 0x4342: + case 0x4352: + case 0x4362: + case 0x4372: + return (Memory.FillRAM[Address]); + + case 0x4303: + case 0x4313: + case 0x4323: + case 0x4333: + case 0x4343: + case 0x4353: + case 0x4363: + case 0x4373: + return (Memory.FillRAM[Address]); + + case 0x4304: + case 0x4314: + case 0x4324: + case 0x4334: + case 0x4344: + case 0x4354: + case 0x4364: + case 0x4374: + return (Memory.FillRAM[Address]); + + case 0x4305: + case 0x4315: + case 0x4325: + case 0x4335: + case 0x4345: + case 0x4355: + case 0x4365: + case 0x4375: + return (Memory.FillRAM[Address]); + + case 0x4306: + case 0x4316: + case 0x4326: + case 0x4336: + case 0x4346: + case 0x4356: + case 0x4366: + case 0x4376: + return (Memory.FillRAM[Address]); + + case 0x4307: + case 0x4317: + case 0x4327: + case 0x4337: + case 0x4347: + case 0x4357: + case 0x4367: + case 0x4377: + return (DMA[(Address >> 4) & 7].IndirectBank); + + case 0x4308: + case 0x4318: + case 0x4328: + case 0x4338: + case 0x4348: + case 0x4358: + case 0x4368: + case 0x4378: + return (Memory.FillRAM[Address]); + + case 0x4309: + case 0x4319: + case 0x4329: + case 0x4339: + case 0x4349: + case 0x4359: + case 0x4369: + case 0x4379: + return (Memory.FillRAM[Address]); + + case 0x430A: + case 0x431A: + case 0x432A: + case 0x433A: + case 0x434A: + case 0x435A: + case 0x436A: + case 0x437A: + { + int d = (Address & 0x70) >> 4; + if (IPPU.HDMA & (1 << d)) + { + return (DMA[d].LineCount); + } + return (Memory.FillRAM[Address]); + } + default: +#ifdef DEBUGGER + missing.unknowncpu_read = Address; + if (Settings.TraceUnknownRegisters) + { + sprintf (String, "Unknown register read: $%04X\n", Address); + S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); + } + +#endif + break; + } + return (Memory.FillRAM[Address]); +} + +void S9xResetPPU () +{ + PPU.BGMode = 0; + PPU.BG3Priority = 0; + PPU.Brightness = 0; + PPU.VMA.High = 0; + PPU.VMA.Increment = 1; + PPU.VMA.Address = 0; + PPU.VMA.FullGraphicCount = 0; + PPU.VMA.Shift = 0; + + for (uint8 B = 0; B != 4; B++) + { + PPU.BG[B].SCBase = 0; + PPU.BG[B].VOffset = 0; + PPU.BG[B].HOffset = 0; + PPU.BG[B].BGSize = 0; + PPU.BG[B].NameBase = 0; + PPU.BG[B].SCSize = 0; + + PPU.ClipCounts[B] = 0; + PPU.ClipWindowOverlapLogic [B] = CLIP_OR; + PPU.ClipWindow1Enable[B] = FALSE; + PPU.ClipWindow2Enable[B] = FALSE; + PPU.ClipWindow1Inside[B] = TRUE; + PPU.ClipWindow2Inside[B] = TRUE; + } + + PPU.ClipCounts[4] = 0; + PPU.ClipCounts[5] = 0; + PPU.ClipWindowOverlapLogic[4] = PPU.ClipWindowOverlapLogic[5] = CLIP_OR; + PPU.ClipWindow1Enable[4] = PPU.ClipWindow1Enable[5] = FALSE; + PPU.ClipWindow2Enable[4] = PPU.ClipWindow2Enable[5] = FALSE; + PPU.ClipWindow1Inside[4] = PPU.ClipWindow1Inside[5] = TRUE; + PPU.ClipWindow2Inside[4] = PPU.ClipWindow2Inside[5] = TRUE; + + PPU.CGFLIP = 0; + int c; + for (c = 0; c < 256; c++) + { + IPPU.Red [c] = (c & 7) << 2; + IPPU.Green [c] = ((c >> 3) & 7) << 2; + IPPU.Blue [c] = ((c >> 6) & 2) << 3; + PPU.CGDATA [c] = IPPU.Red [c] | (IPPU.Green [c] << 5) | + (IPPU.Blue [c] << 10); + } + + PPU.FirstSprite = 0; + PPU.LastSprite = 127; + for (int Sprite = 0; Sprite < 128; Sprite++) + { + PPU.OBJ[Sprite].HPos = 0; + PPU.OBJ[Sprite].VPos = 0; + PPU.OBJ[Sprite].VFlip = 0; + PPU.OBJ[Sprite].HFlip = 0; + PPU.OBJ[Sprite].Priority = 0; + PPU.OBJ[Sprite].Palette = 0; + PPU.OBJ[Sprite].Name = 0; + PPU.OBJ[Sprite].Size = 0; + } + PPU.OAMPriorityRotation = 0; + + PPU.OAMFlip = 0; + PPU.OAMTileAddress = 0; + PPU.OAMAddr = 0; + PPU.IRQVBeamPos = 0; + PPU.IRQHBeamPos = 0; + PPU.VBeamPosLatched = 0; + PPU.HBeamPosLatched = 0; + + PPU.HBeamFlip = 0; + PPU.VBeamFlip = 0; + PPU.HVBeamCounterLatched = 0; + + PPU.MatrixA = PPU.MatrixB = PPU.MatrixC = PPU.MatrixD = 0; + PPU.CentreX = PPU.CentreY = 0; + PPU.Joypad1ButtonReadPos = 0; + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 0; + + PPU.CGADD = 0; + PPU.FixedColourRed = PPU.FixedColourGreen = PPU.FixedColourBlue = 0; + PPU.SavedOAMAddr = 0; + PPU.ScreenHeight = SNES_HEIGHT; + PPU.WRAM = 0; + PPU.BG_Forced = 0; + PPU.ForcedBlanking = TRUE; + PPU.OBJThroughMain = FALSE; + PPU.OBJThroughSub = FALSE; + PPU.OBJSizeSelect = 0; + PPU.OBJNameSelect = 0; + PPU.OBJNameBase = 0; + PPU.OBJAddition = FALSE; + PPU.OAMReadFlip = 0; + ZeroMemory (PPU.OAMData, 512 + 32); + + PPU.VTimerEnabled = FALSE; + PPU.HTimerEnabled = FALSE; + PPU.HTimerPosition = Settings.H_Max + 1; + PPU.Mosaic = 0; + PPU.BGMosaic [0] = PPU.BGMosaic [1] = FALSE; + PPU.BGMosaic [2] = PPU.BGMosaic [3] = FALSE; + PPU.Mode7HFlip = FALSE; + PPU.Mode7VFlip = FALSE; + PPU.Mode7Repeat = 0; + PPU.Window1Left = 1; + PPU.Window1Right = 0; + PPU.Window2Left = 1; + PPU.Window2Right = 0; + PPU.RecomputeClipWindows = TRUE; + PPU.CGFLIPRead = 0; + PPU.Need16x8Mulitply = FALSE; + PPU.MouseSpeed[0] = PPU.MouseSpeed[1] = 0; + + IPPU.ColorsChanged = TRUE; + IPPU.HDMA = 0; + IPPU.HDMAStarted = FALSE; + IPPU.MaxBrightness = 0; + IPPU.LatchedBlanking = 0; + IPPU.OBJChanged = TRUE; + IPPU.RenderThisFrame = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + IPPU.FrameCount = 0; + IPPU.RenderedFramesCount = 0; + IPPU.DisplayedRenderedFrameCount = 0; + IPPU.SkippedFrames = 0; + IPPU.FrameSkip = 0; + ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES); + IPPU.FirstVRAMRead = FALSE; + IPPU.LatchedInterlace = FALSE; + IPPU.DoubleWidthPixels = FALSE; + IPPU.RenderedScreenWidth = SNES_WIDTH; + IPPU.RenderedScreenHeight = SNES_HEIGHT; + IPPU.XB = NULL; + for (c = 0; c < 256; c++) + IPPU.ScreenColors [c] = c; + S9xFixColourBrightness (); + IPPU.PreviousLine = IPPU.CurrentLine = 0; + IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; + IPPU.Joypads[3] = IPPU.Joypads[4] = 0; + IPPU.SuperScope = 0; + IPPU.Mouse[0] = IPPU.Mouse[1] = 0; + IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; + IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; + + if (Settings.ControllerOption == 0) + IPPU.Controller = SNES_MAX_CONTROLLER_OPTIONS - 1; + else + IPPU.Controller = Settings.ControllerOption - 1; + S9xNextController (); + + for (c = 0; c < 2; c++) + memset (&IPPU.Clip [c], 0, sizeof (ClipData)); + + if (Settings.MouseMaster) + { + S9xProcessMouse (0); + S9xProcessMouse (1); + } + for (c = 0; c < 0x8000; c += 0x100) + memset (&Memory.FillRAM [c], c >> 8, 0x100); + + ZeroMemory (&Memory.FillRAM [0x2100], 0x100); + ZeroMemory (&Memory.FillRAM [0x4200], 0x100); + ZeroMemory (&Memory.FillRAM [0x4000], 0x100); + // For BS Suttehakkun 2... + ZeroMemory (&Memory.FillRAM [0x1000], 0x1000); +} + +void S9xProcessMouse (int which1) +{ + int x, y; + uint32 buttons; + + if ((IPPU.Controller == SNES_MOUSE || IPPU.Controller == SNES_MOUSE_SWAPPED) && + S9xReadMousePosition (which1, &x, &y, &buttons)) + { + int delta_x, delta_y; +#define MOUSE_SIGNATURE 0x1 + IPPU.Mouse [which1] = MOUSE_SIGNATURE | + (PPU.MouseSpeed [which1] << 4) | + ((buttons & 1) << 6) | ((buttons & 2) << 6); + + delta_x = x - IPPU.PrevMouseX[which1]; + delta_y = y - IPPU.PrevMouseY[which1]; + + if (delta_x > 63) + { + delta_x = 63; + IPPU.PrevMouseX[which1] += 63; + } + else + if (delta_x < -63) + { + delta_x = -63; + IPPU.PrevMouseX[which1] -= 63; + } + else + IPPU.PrevMouseX[which1] = x; + + if (delta_y > 63) + { + delta_y = 63; + IPPU.PrevMouseY[which1] += 63; + } + else + if (delta_y < -63) + { + delta_y = -63; + IPPU.PrevMouseY[which1] -= 63; + } + else + IPPU.PrevMouseY[which1] = y; + + if (delta_x < 0) + { + delta_x = -delta_x; + IPPU.Mouse [which1] |= (delta_x | 0x80) << 16; + } + else + IPPU.Mouse [which1] |= delta_x << 16; + + if (delta_y < 0) + { + delta_y = -delta_y; + IPPU.Mouse [which1] |= (delta_y | 0x80) << 24; + } + else + IPPU.Mouse [which1] |= delta_y << 24; + + if (IPPU.Controller == SNES_MOUSE_SWAPPED) + IPPU.Joypads [0] = IPPU.Mouse [which1]; + else + IPPU.Joypads [1] = IPPU.Mouse [which1]; + } +} + +void ProcessSuperScope () +{ + int x, y; + uint32 buttons; + + if (IPPU.Controller == SNES_SUPERSCOPE && + S9xReadSuperScopePosition (&x, &y, &buttons)) + { +#define SUPERSCOPE_SIGNATURE 0x00ff + uint32 scope; + + scope = SUPERSCOPE_SIGNATURE | ((buttons & 1) << (7 + 8)) | + ((buttons & 2) << (5 + 8)) | ((buttons & 4) << (3 + 8)) | + ((buttons & 8) << (1 + 8)); + if (x > 255) + x = 255; + if (x < 0) + x = 0; + if (y > PPU.ScreenHeight - 1) + y = PPU.ScreenHeight - 1; + if (y < 0) + y = 0; + + PPU.VBeamPosLatched = (uint16) (y + 1); + PPU.HBeamPosLatched = (uint16) x; + PPU.HVBeamCounterLatched = TRUE; + Memory.FillRAM [0x213F] |= 0x40; + IPPU.Joypads [1] = scope; + } +} + +void S9xNextController () +{ + switch (IPPU.Controller) + { + case SNES_MULTIPLAYER5: + IPPU.Controller = SNES_JOYPAD; + break; + case SNES_JOYPAD: + if (Settings.MouseMaster) + { + IPPU.Controller = SNES_MOUSE_SWAPPED; + break; + } + case SNES_MOUSE_SWAPPED: + if (Settings.MouseMaster) + { + IPPU.Controller = SNES_MOUSE; + break; + } + case SNES_MOUSE: + if (Settings.SuperScopeMaster) + { + IPPU.Controller = SNES_SUPERSCOPE; + break; + } + case SNES_SUPERSCOPE: + if (Settings.MultiPlayer5Master) + { + IPPU.Controller = SNES_MULTIPLAYER5; + break; + } + default: + IPPU.Controller = SNES_JOYPAD; + break; + } +} + +void S9xUpdateJoypads () +{ + int i; + + for (i = 0; i < 5; i++) + { + IPPU.Joypads [i] = S9xReadJoypad (i); + if (IPPU.Joypads [i] & SNES_LEFT_MASK) + IPPU.Joypads [i] &= ~SNES_RIGHT_MASK; + if (IPPU.Joypads [i] & SNES_UP_MASK) + IPPU.Joypads [i] &= ~SNES_DOWN_MASK; + } + + //touhaiden controller Fix + if (SNESGameFixes.TouhaidenControllerFix && + (IPPU.Controller == SNES_JOYPAD || IPPU.Controller == SNES_MULTIPLAYER5)) + { + for (i = 0; i < 5; i++) + { + if (IPPU.Joypads [i]) + IPPU.Joypads [i] |= 0xffff0000; + } + } + + // Read mouse position if enabled + if (Settings.MouseMaster) + { + for (i = 0; i < 2; i++) + S9xProcessMouse (i); + } + + // Read SuperScope if enabled + if (Settings.SuperScopeMaster) + ProcessSuperScope (); + + if (Memory.FillRAM [0x4200] & 1) + { + PPU.Joypad1ButtonReadPos = 16; + if (Memory.FillRAM [0x4201] & 0x80) + { + PPU.Joypad2ButtonReadPos = 16; + PPU.Joypad3ButtonReadPos = 0; + } + else + { + PPU.Joypad2ButtonReadPos = 0; + PPU.Joypad3ButtonReadPos = 16; + } + int ind = Settings.SwapJoypads ? 1 : 0; + + Memory.FillRAM [0x4218] = (uint8) IPPU.Joypads [ind]; + Memory.FillRAM [0x4219] = (uint8) (IPPU.Joypads [ind] >> 8); + Memory.FillRAM [0x421a] = (uint8) IPPU.Joypads [ind ^ 1]; + Memory.FillRAM [0x421b] = (uint8) (IPPU.Joypads [ind ^ 1] >> 8); + if (Memory.FillRAM [0x4201] & 0x80) + { + Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [ind]; + Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads [ind] >> 8); + Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [2]; + Memory.FillRAM [0x421f] = (uint8) (IPPU.Joypads [2] >> 8); + } + else + { + Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [3]; + Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads [3] >> 8); + Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [4]; + Memory.FillRAM [0x421f] = (uint8) (IPPU.Joypads [4] >> 8); + } + } +} + +#ifndef ZSNES_FX +void S9xSuperFXExec () +{ + if (Settings.SuperFX) + { + if ((Memory.FillRAM [0x3000 + GSU_SFR] & FLG_G) && + (Memory.FillRAM [0x3000 + GSU_SCMR] & 0x18) == 0x18) + { + if (!Settings.WinterGold) + FxEmulate (~0); + else + FxEmulate ((Memory.FillRAM [0x3000 + GSU_CLSR] & 1) ? 700 : 350); + int GSUStatus = Memory.FillRAM [0x3000 + GSU_SFR] | + (Memory.FillRAM [0x3000 + GSU_SFR + 1] << 8); + if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) + { + // Trigger a GSU IRQ. + S9xSetIRQ (GSU_IRQ_SOURCE); + } + } + } + +} +#endif diff --git a/src/ppu_.cpp b/src/ppu_.cpp deleted file mode 100644 index 1e29935..0000000 --- a/src/ppu_.cpp +++ /dev/null @@ -1,2486 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" -#include "missing.h" -#include "apu.h" -#include "dma.h" -#include "gfx.h" -#include "display.h" -#include "sa1.h" -#include "sdd1.h" -#include "srtc.h" - - -#ifndef ZSNES_FX -#include "fxemu.h" -#include "fxinst.h" -extern struct FxInit_s SuperFX; -extern struct FxRegs_s GSU; -#else -EXTERN_C void S9xSuperFXWriteReg (uint8, uint32); -EXTERN_C uint8 S9xSuperFXReadReg (uint32); -#endif - -void S9xUpdateHTimer () -{ - if (PPU.HTimerEnabled) - { -#ifdef DEBUGGER - missing.hirq_pos = PPU.IRQHBeamPos; -#endif - PPU.HTimerPosition = PPU.IRQHBeamPos * Settings.H_Max / SNES_HCOUNTER_MAX; - if (PPU.HTimerPosition == Settings.H_Max || - PPU.HTimerPosition == Settings.HBlankStart) - { - PPU.HTimerPosition--; - } - - if (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos) - { - if (PPU.HTimerPosition < CPU.Cycles) - { - // Missed the IRQ on this line already - if (CPU.WhichEvent == HBLANK_END_EVENT || - CPU.WhichEvent == HTIMER_AFTER_EVENT) - { - CPU.WhichEvent = HBLANK_END_EVENT; - CPU.NextEvent = Settings.H_Max; - } - else - { - CPU.WhichEvent = HBLANK_START_EVENT; - CPU.NextEvent = Settings.HBlankStart; - } - } - else - { - if (CPU.WhichEvent == HTIMER_BEFORE_EVENT || - CPU.WhichEvent == HBLANK_START_EVENT) - { - if (PPU.HTimerPosition > Settings.HBlankStart) - { - // HTimer was to trigger before h-blank start, - // now triggers after start of h-blank - CPU.NextEvent = Settings.HBlankStart; - CPU.WhichEvent = HBLANK_START_EVENT; - } - else - { - CPU.NextEvent = PPU.HTimerPosition; - CPU.WhichEvent = HTIMER_BEFORE_EVENT; - } - } - else - { - CPU.WhichEvent = HTIMER_AFTER_EVENT; - CPU.NextEvent = PPU.HTimerPosition; - } - } - } - } -} - -void S9xFixColourBrightness () -{ - IPPU.XB = mul_brightness [PPU.Brightness]; - if (Settings.SixteenBit) - { - for (int i = 0; i < 256; i++) - { - IPPU.Red [i] = IPPU.XB [PPU.CGDATA [i] & 0x1f]; - IPPU.Green [i] = IPPU.XB [(PPU.CGDATA [i] >> 5) & 0x1f]; - IPPU.Blue [i] = IPPU.XB [(PPU.CGDATA [i] >> 10) & 0x1f]; - IPPU.ScreenColors [i] = BUILD_PIXEL (IPPU.Red [i], IPPU.Green [i], - IPPU.Blue [i]); - } - } -} - -/**********************************************************************************************/ -/* S9xSetPPU() */ -/* This function sets a PPU Register to a specific byte */ -/**********************************************************************************************/ -void S9xSetPPU (uint8 Byte, uint16 Address) -{ - if (Address <= 0x2183) - { - switch (Address) - { - case 0x2100: - // Brightness and screen blank bit - if (Byte != Memory.FillRAM [0x2100]) - { - FLUSH_REDRAW (); - if (PPU.Brightness != (Byte & 0xF)) - { - IPPU.ColorsChanged = TRUE; - IPPU.DirectColourMapsNeedRebuild = TRUE; - PPU.Brightness = Byte & 0xF; - S9xFixColourBrightness (); - if (PPU.Brightness > IPPU.MaxBrightness) - IPPU.MaxBrightness = PPU.Brightness; - } - if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80)) - { - IPPU.ColorsChanged = TRUE; - PPU.ForcedBlanking = (Byte >> 7) & 1; - } - } - break; - - case 0x2101: - // Sprite (OBJ) tile address - if (Byte != Memory.FillRAM [0x2101]) - { - FLUSH_REDRAW (); - PPU.OBJNameBase = (Byte & 3) << 14; - PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13; - PPU.OBJSizeSelect = (Byte >> 5) & 7; - IPPU.OBJChanged = TRUE; - } - break; - - case 0x2102: - // Sprite write address (low) - PPU.OAMAddr = Byte; - PPU.OAMFlip = 2; - PPU.OAMReadFlip = 0; - PPU.SavedOAMAddr = PPU.OAMAddr; - if (PPU.OAMPriorityRotation) - { - PPU.FirstSprite = PPU.OAMAddr & 0x7f; -#ifdef DEBUGGER - missing.sprite_priority_rotation = 1; -#endif - } - break; - - case 0x2103: - // Sprite register write address (high), sprite priority rotation - // bit. - if ((PPU.OAMPriorityRotation = (Byte & 0x80) == 0 ? 0 : 1)) - { - PPU.FirstSprite = PPU.OAMAddr & 0x7f; -#ifdef DEBUGGER - missing.sprite_priority_rotation = 1; -#endif - } - // Only update the sprite write address top bit if the low byte has - // been written to first. - if (PPU.OAMFlip & 2) - { - PPU.OAMAddr &= 0x00FF; - PPU.OAMAddr |= (Byte & 1) << 8; - } - PPU.OAMFlip = 0; - PPU.OAMReadFlip = 0; - PPU.SavedOAMAddr = PPU.OAMAddr; - break; - - case 0x2104: - // Sprite register write - REGISTER_2104(Byte, &Memory, &IPPU, &PPU); - - break; - - case 0x2105: - // Screen mode (0 - 7), background tile sizes and background 3 - // priority - if (Byte != Memory.FillRAM [0x2105]) - { - FLUSH_REDRAW (); - PPU.BG3Priority = (Byte >> 3) & 1; - PPU.BG[0].BGSize = (Byte >> 4) & 1; - PPU.BG[1].BGSize = (Byte >> 5) & 1; - PPU.BG[2].BGSize = (Byte >> 6) & 1; - PPU.BG[3].BGSize = (Byte >> 7) & 1; - PPU.BGMode = Byte & 7; -#ifdef DEBUGGER - missing.modes[PPU.BGMode] = 1; -#endif - } - break; - - case 0x2106: - // Mosaic pixel size and enable - if (Byte != Memory.FillRAM [0x2106]) - { - FLUSH_REDRAW (); -#ifdef DEBUGGER - if ((Byte & 0xf0) && (Byte & 0x0f)) - missing.mosaic = 1; -#endif - PPU.Mosaic = (Byte >> 4) + 1; - PPU.BGMosaic [0] = (Byte & 1) && PPU.Mosaic > 1; - PPU.BGMosaic [1] = (Byte & 2) && PPU.Mosaic > 1; - PPU.BGMosaic [2] = (Byte & 4) && PPU.Mosaic > 1; - PPU.BGMosaic [3] = (Byte & 8) && PPU.Mosaic > 1; - } - break; - case 0x2107: // [BG0SC] - if (Byte != Memory.FillRAM [0x2107]) - { - FLUSH_REDRAW (); - PPU.BG[0].SCSize = Byte & 3; - PPU.BG[0].SCBase = (Byte & 0x7c) << 8; - } - break; - - case 0x2108: // [BG1SC] - if (Byte != Memory.FillRAM [0x2108]) - { - FLUSH_REDRAW (); - PPU.BG[1].SCSize = Byte & 3; - PPU.BG[1].SCBase = (Byte & 0x7c) << 8; - } - break; - - case 0x2109: // [BG2SC] - if (Byte != Memory.FillRAM [0x2109]) - { - FLUSH_REDRAW (); - PPU.BG[2].SCSize = Byte & 3; - PPU.BG[2].SCBase = (Byte & 0x7c) << 8; - } - break; - - case 0x210A: // [BG3SC] - if (Byte != Memory.FillRAM [0x210a]) - { - FLUSH_REDRAW (); - PPU.BG[3].SCSize = Byte & 3; - PPU.BG[3].SCBase = (Byte & 0x7c) << 8; - } - break; - - case 0x210B: // [BG01NBA] - if (Byte != Memory.FillRAM [0x210b]) - { - FLUSH_REDRAW (); - PPU.BG[0].NameBase = (Byte & 7) << 12; - PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12; - } - break; - - case 0x210C: // [BG23NBA] - if (Byte != Memory.FillRAM [0x210c]) - { - FLUSH_REDRAW (); - PPU.BG[2].NameBase = (Byte & 7) << 12; - PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12; - } - break; - - case 0x210D: - PPU.BG[0].HOffset = ((PPU.BG[0].HOffset >> 8) & 0xff) | - ((uint16) Byte << 8); - break; - - case 0x210E: - PPU.BG[0].VOffset = ((PPU.BG[0].VOffset >> 8) & 0xff) | - ((uint16) Byte << 8); - break; - case 0x210F: - PPU.BG[1].HOffset = ((PPU.BG[1].HOffset >> 8) & 0xff) | - ((uint16) Byte << 8); - break; - - case 0x2110: - PPU.BG[1].VOffset = ((PPU.BG[1].VOffset >> 8) & 0xff) | - ((uint16) Byte << 8); - break; - - case 0x2111: - PPU.BG[2].HOffset = ((PPU.BG[2].HOffset >> 8) & 0xff) | - ((uint16) Byte << 8); - break; - - case 0x2112: - PPU.BG[2].VOffset = ((PPU.BG[2].VOffset >> 8) & 0xff) | - ((uint16) Byte << 8); - break; - - case 0x2113: - PPU.BG[3].HOffset = ((PPU.BG[3].HOffset >> 8) & 0xff) | - ((uint16) Byte << 8); - break; - - case 0x2114: - PPU.BG[3].VOffset = ((PPU.BG[3].VOffset >> 8) & 0xff) | - ((uint16) Byte << 8); - break; - - case 0x2115: - // VRAM byte/word access flag and increment - PPU.VMA.High = (Byte & 0x80) == 0 ? FALSE : TRUE; - switch (Byte & 3) - { - case 0: - PPU.VMA.Increment = 1; - break; - case 1: - PPU.VMA.Increment = 32; - break; - case 2: - PPU.VMA.Increment = 128; - break; - case 3: - PPU.VMA.Increment = 128; - break; - } -#ifdef DEBUGGER - if ((Byte & 3) != 0) - missing.vram_inc = Byte & 3; -#endif - if (Byte & 0x0c) - { - static uint16 IncCount [4] = { 0, 32, 64, 128 }; - static uint16 Shift [4] = { 0, 5, 6, 7 }; -#ifdef DEBUGGER - missing.vram_full_graphic_inc = (Byte & 0x0c) >> 2; -#endif - PPU.VMA.Increment = 1; - uint8 i = (Byte & 0x0c) >> 2; - PPU.VMA.FullGraphicCount = IncCount [i]; - PPU.VMA.Mask1 = IncCount [i] * 8 - 1; - PPU.VMA.Shift = Shift [i]; - } - else - PPU.VMA.FullGraphicCount = 0; - break; - - case 0x2116: - // VRAM read/write address (low) - PPU.VMA.Address &= 0xFF00; - PPU.VMA.Address |= Byte; - IPPU.FirstVRAMRead = TRUE; - break; - - case 0x2117: - // VRAM read/write address (high) - PPU.VMA.Address &= 0x00FF; - PPU.VMA.Address |= Byte << 8; - IPPU.FirstVRAMRead = TRUE; - break; - - case 0x2118: - // VRAM write data (low) - IPPU.FirstVRAMRead = TRUE; - REGISTER_2118(Byte, &Memory, &IPPU, &PPU); - break; - - case 0x2119: - // VRAM write data (high) - IPPU.FirstVRAMRead = TRUE; - REGISTER_2119(Byte, &Memory, &IPPU, &PPU); - break; - - case 0x211a: - // Mode 7 outside rotation area display mode and flipping - if (Byte != Memory.FillRAM [0x211a]) - { - FLUSH_REDRAW (); - PPU.Mode7Repeat = Byte >> 6; - PPU.Mode7VFlip = (Byte & 2) >> 1; - PPU.Mode7HFlip = Byte & 1; - } - break; - case 0x211b: - // Mode 7 matrix A (low & high) - PPU.MatrixA = ((PPU.MatrixA >> 8) & 0xff) | (Byte << 8); - PPU.Need16x8Mulitply = TRUE; - break; - case 0x211c: - // Mode 7 matrix B (low & high) - PPU.MatrixB = ((PPU.MatrixB >> 8) & 0xff) | (Byte << 8); - PPU.Need16x8Mulitply = TRUE; - break; - case 0x211d: - // Mode 7 matrix C (low & high) - PPU.MatrixC = ((PPU.MatrixC >> 8) & 0xff) | (Byte << 8); - break; - case 0x211e: - // Mode 7 matrix D (low & high) - PPU.MatrixD = ((PPU.MatrixD >> 8) & 0xff) | (Byte << 8); - break; - case 0x211f: - // Mode 7 centre of rotation X (low & high) - PPU.CentreX = ((PPU.CentreX >> 8) & 0xff) | (Byte << 8); - break; - case 0x2120: - // Mode 7 centre of rotation Y (low & high) - PPU.CentreY = ((PPU.CentreY >> 8) & 0xff) | (Byte << 8); - break; - - case 0x2121: - // CG-RAM address - PPU.CGFLIP = 0; - PPU.CGFLIPRead = 0; - PPU.CGADD = Byte; - break; - - case 0x2122: - REGISTER_2122(Byte, &Memory, &IPPU, &PPU); - break; - - case 0x2123: - // Window 1 and 2 enable for backgrounds 1 and 2 - if (Byte != Memory.FillRAM [0x2123]) - { - FLUSH_REDRAW (); - - PPU.ClipWindow1Enable [0] = !!(Byte & 0x02); - PPU.ClipWindow1Enable [1] = !!(Byte & 0x20); - PPU.ClipWindow2Enable [0] = !!(Byte & 0x08); - PPU.ClipWindow2Enable [1] = !!(Byte & 0x80); - PPU.ClipWindow1Inside [0] = !(Byte & 0x01); - PPU.ClipWindow1Inside [1] = !(Byte & 0x10); - PPU.ClipWindow2Inside [0] = !(Byte & 0x04); - PPU.ClipWindow2Inside [1] = !(Byte & 0x40); - PPU.RecomputeClipWindows = TRUE; -#ifdef DEBUGGER - if (Byte & 0x80) - missing.window2[1] = 1; - if (Byte & 0x20) - missing.window1[1] = 1; - if (Byte & 0x08) - missing.window2[0] = 1; - if (Byte & 0x02) - missing.window1[0] = 1; -#endif - } - break; - case 0x2124: - // Window 1 and 2 enable for backgrounds 3 and 4 - if (Byte != Memory.FillRAM [0x2124]) - { - FLUSH_REDRAW (); - - PPU.ClipWindow1Enable [2] = !!(Byte & 0x02); - PPU.ClipWindow1Enable [3] = !!(Byte & 0x20); - PPU.ClipWindow2Enable [2] = !!(Byte & 0x08); - PPU.ClipWindow2Enable [3] = !!(Byte & 0x80); - PPU.ClipWindow1Inside [2] = !(Byte & 0x01); - PPU.ClipWindow1Inside [3] = !(Byte & 0x10); - PPU.ClipWindow2Inside [2] = !(Byte & 0x04); - PPU.ClipWindow2Inside [3] = !(Byte & 0x40); - PPU.RecomputeClipWindows = TRUE; -#ifdef DEBUGGER - if (Byte & 0x80) - missing.window2[3] = 1; - if (Byte & 0x20) - missing.window1[3] = 1; - if (Byte & 0x08) - missing.window2[2] = 1; - if (Byte & 0x02) - missing.window1[2] = 1; -#endif - } - break; - case 0x2125: - // Window 1 and 2 enable for objects and colour window - if (Byte != Memory.FillRAM [0x2125]) - { - FLUSH_REDRAW (); - - PPU.ClipWindow1Enable [4] = !!(Byte & 0x02); - PPU.ClipWindow1Enable [5] = !!(Byte & 0x20); - PPU.ClipWindow2Enable [4] = !!(Byte & 0x08); - PPU.ClipWindow2Enable [5] = !!(Byte & 0x80); - PPU.ClipWindow1Inside [4] = !(Byte & 0x01); - PPU.ClipWindow1Inside [5] = !(Byte & 0x10); - PPU.ClipWindow2Inside [4] = !(Byte & 0x04); - PPU.ClipWindow2Inside [5] = !(Byte & 0x40); - PPU.RecomputeClipWindows = TRUE; -#ifdef DEBUGGER - if (Byte & 0x80) - missing.window2[5] = 1; - if (Byte & 0x20) - missing.window1[5] = 1; - if (Byte & 0x08) - missing.window2[4] = 1; - if (Byte & 0x02) - missing.window1[4] = 1; -#endif - } - break; - case 0x2126: - // Window 1 left position - if (Byte != Memory.FillRAM [0x2126]) - { - FLUSH_REDRAW (); - - PPU.Window1Left = Byte; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2127: - // Window 1 right position - if (Byte != Memory.FillRAM [0x2127]) - { - FLUSH_REDRAW (); - - PPU.Window1Right = Byte; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2128: - // Window 2 left position - if (Byte != Memory.FillRAM [0x2128]) - { - FLUSH_REDRAW (); - - PPU.Window2Left = Byte; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2129: - // Window 2 right position - if (Byte != Memory.FillRAM [0x2129]) - { - FLUSH_REDRAW (); - - PPU.Window2Right = Byte; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x212a: - // Windows 1 & 2 overlap logic for backgrounds 1 - 4 - if (Byte != Memory.FillRAM [0x212a]) - { - FLUSH_REDRAW (); - - PPU.ClipWindowOverlapLogic [0] = (Byte & 0x03); - PPU.ClipWindowOverlapLogic [1] = (Byte & 0x0c) >> 2; - PPU.ClipWindowOverlapLogic [2] = (Byte & 0x30) >> 4; - PPU.ClipWindowOverlapLogic [3] = (Byte & 0xc0) >> 6; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x212b: - // Windows 1 & 2 overlap logic for objects and colour window - if (Byte != Memory.FillRAM [0x212b]) - { - FLUSH_REDRAW (); - - PPU.ClipWindowOverlapLogic [4] = Byte & 0x03; - PPU.ClipWindowOverlapLogic [5] = (Byte & 0x0c) >> 2; - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x212c: - // Main screen designation (backgrounds 1 - 4 and objects) - if (Byte != Memory.FillRAM [0x212c]) - { - FLUSH_REDRAW (); - - PPU.RecomputeClipWindows = TRUE; - Memory.FillRAM [Address] = Byte; - return; - } - break; - case 0x212d: - // Sub-screen designation (backgrounds 1 - 4 and objects) - if (Byte != Memory.FillRAM [0x212d]) - { - FLUSH_REDRAW (); - -#ifdef DEBUGGER - if (Byte & 0x1f) - missing.subscreen = 1; -#endif - PPU.RecomputeClipWindows = TRUE; - Memory.FillRAM [Address] = Byte; - return; - } - break; - case 0x212e: - // Window mask designation for main screen ? - if (Byte != Memory.FillRAM [0x212e]) - { - FLUSH_REDRAW (); - - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x212f: - // Window mask designation for sub-screen ? - if (Byte != Memory.FillRAM [0x212f]) - { - FLUSH_REDRAW (); - - PPU.RecomputeClipWindows = TRUE; - } - break; - case 0x2130: - // Fixed colour addition or screen addition - if (Byte != Memory.FillRAM [0x2130]) - { - FLUSH_REDRAW (); - - PPU.RecomputeClipWindows = TRUE; -#ifdef DEBUGGER - if ((Byte & 1) && (PPU.BGMode == 3 || PPU.BGMode == 4 || PPU.BGMode == 7)) - missing.direct = 1; -#endif - } - break; - case 0x2131: - // Colour addition or subtraction select - if (Byte != Memory.FillRAM[0x2131]) - { - FLUSH_REDRAW (); - - // Backgrounds 1 - 4, objects and backdrop colour add/sub enable -#ifdef DEBUGGER - if (Byte & 0x80) - { - // Subtract - if (Memory.FillRAM[0x2130] & 0x02) - missing.subscreen_sub = 1; - else - missing.fixed_colour_sub = 1; - } - else - { - // Addition - if (Memory.FillRAM[0x2130] & 0x02) - missing.subscreen_add = 1; - else - missing.fixed_colour_add = 1; - } -#endif - Memory.FillRAM[0x2131] = Byte; - } - break; - case 0x2132: - if (Byte != Memory.FillRAM [0x2132]) - { - FLUSH_REDRAW (); - - // Colour data for fixed colour addition/subtraction - if (Byte & 0x80) - PPU.FixedColourBlue = Byte & 0x1f; - if (Byte & 0x40) - PPU.FixedColourGreen = Byte & 0x1f; - if (Byte & 0x20) - PPU.FixedColourRed = Byte & 0x1f; - } - break; - case 0x2133: - // Screen settings - if (Byte != Memory.FillRAM [0x2133]) - { -#ifdef DEBUGGER - if (Byte & 0x40) - missing.mode7_bgmode = 1; - if (Byte & 0x08) - missing.pseudo_512 = 1; -#endif - if (Byte & 0x04) - { - PPU.ScreenHeight = SNES_HEIGHT_EXTENDED; -#ifdef DEBUGGER - missing.lines_239 = 1; -#endif - } - else - PPU.ScreenHeight = SNES_HEIGHT; -#ifdef DEBUGGER - if (Byte & 0x02) - missing.sprite_double_height = 1; - - if (Byte & 1) - missing.interlace = 1; -#endif - } - break; - case 0x2134: - case 0x2135: - case 0x2136: - // Matrix 16bit x 8bit multiply result (read-only) - return; - - case 0x2137: - // Software latch for horizontal and vertical timers (read-only) - return; - case 0x2138: - // OAM read data (read-only) - return; - case 0x2139: - case 0x213a: - // VRAM read data (read-only) - return; - case 0x213b: - // CG-RAM read data (read-only) - return; - case 0x213c: - case 0x213d: - // Horizontal and vertical (low/high) read counter (read-only) - return; - case 0x213e: - // PPU status (time over and range over) - return; - case 0x213f: - // NTSC/PAL select and field (read-only) - return; - case 0x2140: case 0x2141: case 0x2142: case 0x2143: - case 0x2144: case 0x2145: case 0x2146: case 0x2147: - case 0x2148: case 0x2149: case 0x214a: case 0x214b: - case 0x214c: case 0x214d: case 0x214e: case 0x214f: - case 0x2150: case 0x2151: case 0x2152: case 0x2153: - case 0x2154: case 0x2155: case 0x2156: case 0x2157: - case 0x2158: case 0x2159: case 0x215a: case 0x215b: - case 0x215c: case 0x215d: case 0x215e: case 0x215f: - case 0x2160: case 0x2161: case 0x2162: case 0x2163: - case 0x2164: case 0x2165: case 0x2166: case 0x2167: - case 0x2168: case 0x2169: case 0x216a: case 0x216b: - case 0x216c: case 0x216d: case 0x216e: case 0x216f: - case 0x2170: case 0x2171: case 0x2172: case 0x2173: - case 0x2174: case 0x2175: case 0x2176: case 0x2177: - case 0x2178: case 0x2179: case 0x217a: case 0x217b: - case 0x217c: case 0x217d: case 0x217e: case 0x217f: -#ifdef SPCTOOL - _SPCInPB (Address & 3, Byte); -#else -// CPU.Flags |= DEBUG_MODE_FLAG; - Memory.FillRAM [Address] = Byte; - IAPU.RAM [(Address & 3) + 0xf4] = Byte; -#ifdef SPC700_SHUTDOWN - IAPU.APUExecuting = Settings.APUEnabled; - IAPU.WaitCounter++; -#endif -#endif // SPCTOOL - break; - case 0x2180: - REGISTER_2180(Byte, &Memory, &IPPU, &PPU); - break; - case 0x2181: - PPU.WRAM &= 0x1FF00; - PPU.WRAM |= Byte; - break; - case 0x2182: - PPU.WRAM &= 0x100FF; - PPU.WRAM |= Byte << 8; - break; - case 0x2183: - PPU.WRAM &= 0x0FFFF; - PPU.WRAM |= Byte << 16; - PPU.WRAM &= 0x1FFFF; - break; - } - } - else - { - if (Settings.SA1) - { - if (Address >= 0x2200 && Address <0x23ff) - S9xSetSA1 (Byte, Address); - else - Memory.FillRAM [Address] = Byte; - return; - } - else - // Dai Kaijyu Monogatari II - if (Address == 0x2801 && Settings.SRTC) - S9xSetSRTC (Byte, Address); - else - if (Address < 0x3000 || Address >= 0x3000 + 768) - { -#ifdef DEBUGGER - missing.unknownppu_write = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf (String, "Unknown register write: $%02X->$%04X\n", - Byte, Address); - S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); - } -#endif - } - else - { - if (!Settings.SuperFX) - return; - - #ifdef ZSNES_FX - Memory.FillRAM [Address] = Byte; - if (Address < 0x3040) - S9xSuperFXWriteReg (Byte, Address); - #else - switch (Address) - { - case 0x3030: - if ((Memory.FillRAM [0x3030] ^ Byte) & FLG_G) - { - Memory.FillRAM [Address] = Byte; - // Go flag has been changed - if (Byte & FLG_G) - S9xSuperFXExec (); - else - FxFlushCache (&GSU); - } - else - Memory.FillRAM [Address] = Byte; - break; - - case 0x3031: - Memory.FillRAM [Address] = Byte; - break; - case 0x3033: - Memory.FillRAM [Address] = Byte; - break; - case 0x3034: - Memory.FillRAM [Address] = Byte & 0x7f; - break; - case 0x3036: - Memory.FillRAM [Address] = Byte & 0x7f; - break; - case 0x3037: - Memory.FillRAM [Address] = Byte; - break; - case 0x3038: - Memory.FillRAM [Address] = Byte; - break; - case 0x3039: - Memory.FillRAM [Address] = Byte; - break; - case 0x303a: - Memory.FillRAM [Address] = Byte; - break; - case 0x303b: - break; - case 0x303f: - Memory.FillRAM [Address] = Byte; - break; - case 0x301f: - Memory.FillRAM [Address] = Byte; - Memory.FillRAM [0x3000 + GSU_SFR] |= FLG_G; - S9xSuperFXExec (); - return; - - default: - Memory.FillRAM[Address] = Byte; - if (Address >= 0x3100) - { - FxCacheWriteAccess (Address, &GSU); - } - break; - } - #endif - return; - } - } - Memory.FillRAM[Address] = Byte; -} - -/**********************************************************************************************/ -/* S9xGetPPU() */ -/* This function retrieves a PPU Register */ -/**********************************************************************************************/ -uint8 S9xGetPPU (uint16 Address) -{ - uint8 byte = 0; - - if (Address <= 0x2190) - { - switch (Address) - { - case 0x2100: - case 0x2101: - return (Memory.FillRAM[Address]); - case 0x2102: -#ifdef DEBUGGER - missing.oam_address_read = 1; -#endif - return (uint8)(PPU.OAMAddr); - case 0x2103: - return (((PPU.OAMAddr >> 8) & 1) | (PPU.OAMPriorityRotation << 7)); - case 0x2104: - case 0x2105: - case 0x2106: - case 0x2107: - case 0x2108: - case 0x2109: - case 0x210a: - case 0x210b: - case 0x210c: - return (Memory.FillRAM[Address]); - case 0x210d: - case 0x210e: - case 0x210f: - case 0x2110: - case 0x2111: - case 0x2112: - case 0x2113: - case 0x2114: -#ifdef DEBUGGER - missing.bg_offset_read = 1; -#endif - return (Memory.FillRAM[Address]); - case 0x2115: - return (Memory.FillRAM[Address]); - case 0x2116: - return (uint8)(PPU.VMA.Address); - case 0x2117: - return (PPU.VMA.Address >> 8); - case 0x2118: - case 0x2119: - case 0x211a: - return (Memory.FillRAM[Address]); - case 0x211b: - case 0x211c: - case 0x211d: - case 0x211e: - case 0x211f: - case 0x2120: -#ifdef DEBUGGER - missing.matrix_read = 1; -#endif - return (Memory.FillRAM[Address]); - case 0x2121: - return (PPU.CGADD); - case 0x2122: - case 0x2123: - case 0x2124: - case 0x2125: - case 0x2126: - case 0x2127: - case 0x2128: - case 0x2129: - case 0x212a: - case 0x212b: - case 0x212c: - case 0x212d: - case 0x212e: - case 0x212f: - case 0x2130: - case 0x2131: - case 0x2132: - case 0x2133: - return (Memory.FillRAM[Address]); - - case 0x2134: - case 0x2135: - case 0x2136: - // 16bit x 8bit multiply read result. - if (PPU.Need16x8Mulitply) - { - int32 r = (int32) PPU.MatrixA * (int32) (PPU.MatrixB >> 8); - - Memory.FillRAM[0x2134] = (uint8) r; - Memory.FillRAM[0x2135] = (uint8)(r >> 8); - Memory.FillRAM[0x2136] = (uint8)(r >> 16); - PPU.Need16x8Mulitply = FALSE; - } -#ifdef DEBUGGER - missing.matrix_multiply = 1; -#endif - return (Memory.FillRAM[Address]); - case 0x2137: - // Latch h and v counters -#ifdef DEBUGGER - missing.h_v_latch = 1; -#endif -#if 0 -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif -#endif - PPU.HVBeamCounterLatched = 1; - PPU.VBeamPosLatched = (uint16) CPU.V_Counter; - PPU.HBeamPosLatched = (uint16) ((CPU.Cycles * SNES_HCOUNTER_MAX) / Settings.H_Max); - - // Causes screen flicker for Yoshi's Island if uncommented - //CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - - if (SNESGameFixes.NeedInit0x2137) - PPU.VBeamFlip = 0; //jyam sword world sfc2 & godzill - return (0); - case 0x2138: - // Read OAM (sprite) control data - if (!PPU.OAMReadFlip) - { - byte = PPU.OAMData [PPU.OAMAddr << 1]; - } - else - { - byte = PPU.OAMData [(PPU.OAMAddr << 1) + 1]; - if (++PPU.OAMAddr >= 0x110) - PPU.OAMAddr = 0; - - } - PPU.OAMReadFlip ^= 1; -#ifdef DEBUGGER - missing.oam_read = 1; -#endif - return (byte); - - case 0x2139: - // Read vram low byte -#ifdef DEBUGGER - missing.vram_read = 1; -#endif - if (IPPU.FirstVRAMRead) - byte = Memory.VRAM[PPU.VMA.Address << 1]; - else - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address - 1; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - byte = Memory.VRAM [((address << 1) - 2) & 0xFFFF]; - } - else - byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff]; - - if (!PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - IPPU.FirstVRAMRead = FALSE; - } - break; - case 0x213A: - // Read vram high byte -#ifdef DEBUGGER - missing.vram_read = 1; -#endif - if (IPPU.FirstVRAMRead) - byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff]; - else - if (PPU.VMA.FullGraphicCount) - { - uint32 addr = PPU.VMA.Address - 1; - uint32 rem = addr & PPU.VMA.Mask1; - uint32 address = (addr & ~PPU.VMA.Mask1) + - (rem >> PPU.VMA.Shift) + - ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); - byte = Memory.VRAM [((address << 1) - 1) & 0xFFFF]; - } - else - byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xFFFF]; - if (PPU.VMA.High) - { - PPU.VMA.Address += PPU.VMA.Increment; - IPPU.FirstVRAMRead = FALSE; - } - break; - - case 0x213B: - // Read palette data -#ifdef DEBUGGER - missing.cgram_read = 1; -#endif - if (PPU.CGFLIPRead) - byte = PPU.CGDATA [PPU.CGADD++] >> 8; - else - byte = PPU.CGDATA [PPU.CGADD] & 0xff; - - PPU.CGFLIPRead ^= 1; - return (byte); - - case 0x213C: - // Horizontal counter value 0-339 -#ifdef DEBUGGER - missing.h_counter_read = 1; -#endif - if (PPU.HBeamFlip) - byte = PPU.HBeamPosLatched >> 8; - else - byte = (uint8)PPU.HBeamPosLatched; - PPU.HBeamFlip ^= 1; - break; - case 0x213D: - // Vertical counter value 0-262 -#ifdef DEBUGGER - missing.v_counter_read = 1; -#endif - if (PPU.VBeamFlip) - byte = PPU.VBeamPosLatched >> 8; - else - byte = (uint8)PPU.VBeamPosLatched; - PPU.VBeamFlip ^= 1; - break; - case 0x213E: - // PPU time and range over flags - return (SNESGameFixes._0x213E_ReturnValue); - - case 0x213F: - // NTSC/PAL and which field flags - PPU.VBeamFlip = PPU.HBeamFlip = 0; - return ((Settings.PAL ? 0x10 : 0) | (Memory.FillRAM[0x213f] & 0xc0)); - - case 0x2140: case 0x2141: case 0x2142: case 0x2143: - case 0x2144: case 0x2145: case 0x2146: case 0x2147: - case 0x2148: case 0x2149: case 0x214a: case 0x214b: - case 0x214c: case 0x214d: case 0x214e: case 0x214f: - case 0x2150: case 0x2151: case 0x2152: case 0x2153: - case 0x2154: case 0x2155: case 0x2156: case 0x2157: - case 0x2158: case 0x2159: case 0x215a: case 0x215b: - case 0x215c: case 0x215d: case 0x215e: case 0x215f: - case 0x2160: case 0x2161: case 0x2162: case 0x2163: - case 0x2164: case 0x2165: case 0x2166: case 0x2167: - case 0x2168: case 0x2169: case 0x216a: case 0x216b: - case 0x216c: case 0x216d: case 0x216e: case 0x216f: - case 0x2170: case 0x2171: case 0x2172: case 0x2173: - case 0x2174: case 0x2175: case 0x2176: case 0x2177: - case 0x2178: case 0x2179: case 0x217a: case 0x217b: - case 0x217c: case 0x217d: case 0x217e: case 0x217f: -#ifdef SPCTOOL - return ((uint8) _SPCOutP [Address & 3]); -#else - // CPU.Flags |= DEBUG_MODE_FLAG; -#ifdef SPC700_SHUTDOWN - IAPU.APUExecuting = Settings.APUEnabled; - IAPU.WaitCounter++; -#endif - if (Settings.APUEnabled) - { -#ifdef CPU_SHUTDOWN -// CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - if (SNESGameFixes.APU_OutPorts_ReturnValueFix && - Address >= 0x2140 && Address <= 0x2143 && !CPU.V_Counter) - { - return (uint8)((Address & 1) ? ((rand() & 0xff00) >> 8) : - (rand() & 0xff)); - } - - return (APU.OutPorts [Address & 3]); - } - - switch (Settings.SoundSkipMethod) - { - case 0: - case 1: - CPU.BranchSkip = TRUE; - break; - case 2: - break; - case 3: - CPU.BranchSkip = TRUE; - break; - } - if (Address & 3 < 2) - { - int r = rand (); - if (r & 2) - { - if (r & 4) - return (Address & 3 == 1 ? 0xaa : 0xbb); - else - return ((r >> 3) & 0xff); - } - } - else - { - int r = rand (); - if (r & 2) - return ((r >> 3) & 0xff); - } - return (Memory.FillRAM[Address]); -#endif // SPCTOOL - - case 0x2180: - // Read WRAM -#ifdef DEBUGGER - missing.wram_read = 1; -#endif - byte = Memory.RAM [PPU.WRAM++]; - PPU.WRAM &= 0x1FFFF; - break; - case 0x2181: - case 0x2182: - case 0x2183: - return (Memory.FillRAM [Address]); - case 0x2190: - return (1); - } - } - else - { - if (Settings.SA1) - return (S9xGetSA1 (Address)); - - if (Address <= 0x2fff || Address >= 0x3000 + 768) - { - switch (Address) - { - case 0x21c2: - return (0x20); - case 0x21c3: - return (0); - case 0x2800: - // For Dai Kaijyu Monogatari II - if (Settings.SRTC) - return (S9xGetSRTC (Address)); - /*FALL*/ - - default: -#ifdef DEBUGGER - missing.unknownppu_read = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf (String, "Unknown register read: $%04X\n", Address); - S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); - } -#endif - // XXX: - return (0); //Memory.FillRAM[Address]); - } - } - - if (!Settings.SuperFX) - return (0x30); -#ifdef ZSNES_FX - if (Address < 0x3040) - byte = S9xSuperFXReadReg (Address); - else - byte = Memory.FillRAM [Address]; - -#ifdef CPU_SHUTDOWN - if (Address == 0x3030) - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - if (Address == 0x3031) - CLEAR_IRQ_SOURCE (GSU_IRQ_SOURCE); -#else - byte = Memory.FillRAM [Address]; - -//if (Address != 0x3030 && Address != 0x3031) -//printf ("%04x\n", Address); -#ifdef CPU_SHUTDOWN - if (Address == 0x3030) - { - CPU.WaitAddress = CPU.PCAtOpcodeStart; - } - else -#endif - if (Address == 0x3031) - { - CLEAR_IRQ_SOURCE (GSU_IRQ_SOURCE); - Memory.FillRAM [0x3031] = byte & 0x7f; - } - return (byte); -#endif - } - - return (byte); -} - -/**********************************************************************************************/ -/* S9xSetCPU() */ -/* This function sets a CPU/DMA Register to a specific byte */ -/**********************************************************************************************/ -void S9xSetCPU (uint8 byte, uint16 Address) -{ - int d; - - if (Address < 0x4200) - { -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - switch (Address) - { - case 0x4016: - // S9xReset reading of old-style joypads - if ((byte & 1) && !(Memory.FillRAM [Address] & 1)) - { - PPU.Joypad1ButtonReadPos = 0; - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 0; - } - break; - case 0x4017: - break; - default: -#ifdef DEBUGGER - missing.unknowncpu_write = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf (String, "Unknown register register write: $%02X->$%04X\n", - byte, Address); - S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); - } -#endif - break; - } - } - else - switch (Address) - { - case 0x4200: - // NMI, V & H IRQ and joypad reading enable flags - if ((byte & 0x20) && - (!SNESGameFixes.umiharakawaseFix || PPU.IRQVBeamPos < 209)) - { - if (!PPU.VTimerEnabled) - { -#ifdef DEBUGGER - missing.virq = 1; - missing.virq_pos = PPU.IRQVBeamPos; -#endif - PPU.VTimerEnabled = TRUE; - if (PPU.HTimerEnabled) - S9xUpdateHTimer (); - else - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - } - else - { - PPU.VTimerEnabled = FALSE; -#ifndef RC_OPTIMIZED - if (SNESGameFixes.umiharakawaseFix) - byte &= ~0x20; -#endif - } - - if (byte & 0x10) - { - if (!PPU.HTimerEnabled) - { -#ifdef DEBUGGER - missing.hirq = 1; - missing.hirq_pos = PPU.IRQHBeamPos; -#endif - PPU.HTimerEnabled = TRUE; - S9xUpdateHTimer (); - } - } - else - { - // No need to check for HTimer being disabled as the scanline - // event trigger code won't trigger an H-IRQ unless its enabled. - PPU.HTimerEnabled = FALSE; - PPU.HTimerPosition = Settings.H_Max + 1; - } - -#ifndef RC_OPTIMIZED - if (!Settings.DaffyDuck) - CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - - if ((byte & 0x80) && - !(Memory.FillRAM [0x4200] & 0x80) && - CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && - CPU.V_Counter <= PPU.ScreenHeight + - (SNESGameFixes.alienVSpredetorFix ? 25 : 15) && //jyam 15->25 alien vs predetor -// Panic Bomberman clears the NMI pending flag @ scanline 230 before enabling -// NMIs again. The NMI routine crashes the CPU if it is called without the NMI -// pending flag being set... - (Memory.FillRAM [0x4210] & 0x80) && - !CPU.NMIActive) - { - CPU.Flags |= NMI_FLAG; - CPU.NMIActive = TRUE; - CPU.NMICycleCount = CPU.NMITriggerPoint; - } -#endif - break; - case 0x4201: - // I/O port output - case 0x4202: - // Multiplier (for multply) - break; - case 0x4203: - { - // Multiplicand - uint32 res = Memory.FillRAM[0x4202] * byte; - - Memory.FillRAM[0x4216] = (uint8) res; - Memory.FillRAM[0x4217] = (uint8) (res >> 8); - break; - } - case 0x4204: - case 0x4205: - // Low and high muliplier (for divide) - break; - case 0x4206: - { - // Divisor - uint16 a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); - uint16 div = byte ? a / byte : 0xffff; - uint16 rem = byte ? a % byte : a; - - Memory.FillRAM[0x4214] = (uint8)div; - Memory.FillRAM[0x4215] = div >> 8; - Memory.FillRAM[0x4216] = (uint8)rem; - Memory.FillRAM[0x4217] = rem >> 8; - break; - } - case 0x4207: - d = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF00) | byte; - - if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) - S9xUpdateHTimer (); - break; - - case 0x4208: - d = PPU.IRQHBeamPos; - PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xFF) | ((byte & 1) << 8); - - if (PPU.HTimerEnabled && PPU.IRQHBeamPos != d) - S9xUpdateHTimer (); - - break; - - case 0x4209: - d = PPU.IRQVBeamPos; - PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF00) | byte; -#ifdef DEBUGGER - missing.virq_pos = PPU.IRQVBeamPos; -#endif - if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) - { - if (PPU.HTimerEnabled) - S9xUpdateHTimer (); - else - { - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - } - break; - - case 0x420A: - d = PPU.IRQVBeamPos; - PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xFF) | ((byte & 1) << 8); -#ifdef DEBUGGER - missing.virq_pos = PPU.IRQVBeamPos; -#endif - if (PPU.VTimerEnabled && PPU.IRQVBeamPos != d) - { - if (PPU.HTimerEnabled) - S9xUpdateHTimer (); - else - { - if (PPU.IRQVBeamPos == CPU.V_Counter) - S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE); - } - } - break; - - case 0x420B: -#ifdef DEBUGGER - missing.dma_this_frame = byte; - missing.dma_channels = byte; -#endif - if ((byte & 0x01) != 0) - S9xDoDMA (0); - if ((byte & 0x02) != 0) - S9xDoDMA (1); - if ((byte & 0x04) != 0) - S9xDoDMA (2); - if ((byte & 0x08) != 0) - S9xDoDMA (3); - if ((byte & 0x10) != 0) - S9xDoDMA (4); - if ((byte & 0x20) != 0) - S9xDoDMA (5); - if ((byte & 0x40) != 0) - S9xDoDMA (6); - if ((byte & 0x80) != 0) - S9xDoDMA (7); - break; - case 0x420C: -#ifdef DEBUGGER - missing.hdma_this_frame |= byte; - missing.hdma_channels |= byte; -#endif - if (Settings.DisableHDMA) - byte = 0; - Memory.FillRAM[0x420c] = byte; - IPPU.HDMA = byte; - break; - - case 0x420d: - // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) - if ((byte & 1) != (Memory.FillRAM [0x420d] & 1)) - { - if (byte & 1) - { - CPU.FastROMSpeed = ONE_CYCLE; -#ifdef DEBUGGER - missing.fast_rom = 1; -#endif - } - else - CPU.FastROMSpeed = SLOW_ONE_CYCLE; - - Memory.FixROMSpeed (); - } - /* FALL */ - case 0x420e: - case 0x420f: - // --->>> Unknown - break; - case 0x4210: - // NMI ocurred flag (reset on read or write) - Memory.FillRAM[0x4210] = 0; - return; - case 0x4211: - // IRQ ocurred flag (reset on read or write) - CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - break; - case 0x4212: - // v-blank, h-blank and joypad being scanned flags (read-only) - case 0x4213: - // I/O Port (read-only) - case 0x4214: - case 0x4215: - // Quotent of divide (read-only) - case 0x4216: - case 0x4217: - // Multiply product (read-only) - return; - case 0x4218: - case 0x4219: - case 0x421a: - case 0x421b: - case 0x421c: - case 0x421d: - case 0x421e: - case 0x421f: - // Joypad values (read-only) - return; - - case 0x4300: - case 0x4310: - case 0x4320: - case 0x4330: - case 0x4340: - case 0x4350: - case 0x4360: - case 0x4370: - d = (Address >> 4) & 0x7; - DMA[d].TransferDirection = (byte & 128) != 0 ? 1 : 0; - DMA[d].HDMAIndirectAddressing = (byte & 64) != 0 ? 1 : 0; - DMA[d].AAddressDecrement = (byte & 16) != 0 ? 1 : 0; - DMA[d].AAddressFixed = (byte & 8) != 0 ? 1 : 0; - DMA[d].TransferMode = (byte & 7); - break; - - case 0x4301: - case 0x4311: - case 0x4321: - case 0x4331: - case 0x4341: - case 0x4351: - case 0x4361: - case 0x4371: - DMA[((Address >> 4) & 0x7)].BAddress = byte; - break; - - case 0x4302: - case 0x4312: - case 0x4322: - case 0x4332: - case 0x4342: - case 0x4352: - case 0x4362: - case 0x4372: - d = (Address >> 4) & 0x7; - DMA[d].AAddress &= 0xFF00; - DMA[d].AAddress |= byte; - break; - - case 0x4303: - case 0x4313: - case 0x4323: - case 0x4333: - case 0x4343: - case 0x4353: - case 0x4363: - case 0x4373: - d = (Address >> 4) & 0x7; - DMA[d].AAddress &= 0xFF; - DMA[d].AAddress |= byte << 8; - break; - - case 0x4304: - case 0x4314: - case 0x4324: - case 0x4334: - case 0x4344: - case 0x4354: - case 0x4364: - case 0x4374: - DMA[((Address >> 4) & 0x7)].ABank = byte; - break; - - case 0x4305: - case 0x4315: - case 0x4325: - case 0x4335: - case 0x4345: - case 0x4355: - case 0x4365: - case 0x4375: - d = (Address >> 4) & 0x7; - DMA[d].TransferBytes &= 0xFF00; - DMA[d].TransferBytes |= byte; - DMA[d].IndirectAddress &= 0xff00; - DMA[d].IndirectAddress |= byte; - break; - - case 0x4306: - case 0x4316: - case 0x4326: - case 0x4336: - case 0x4346: - case 0x4356: - case 0x4366: - case 0x4376: - d = (Address >> 4) & 0x7; - DMA[d].TransferBytes &= 0xFF; - DMA[d].TransferBytes |= byte << 8; - DMA[d].IndirectAddress &= 0xff; - DMA[d].IndirectAddress |= byte << 8; - break; - - case 0x4307: - case 0x4317: - case 0x4327: - case 0x4337: - case 0x4347: - case 0x4357: - case 0x4367: - case 0x4377: - DMA[d = ((Address >> 4) & 0x7)].IndirectBank = byte; - break; - - case 0x4308: - case 0x4318: - case 0x4328: - case 0x4338: - case 0x4348: - case 0x4358: - case 0x4368: - case 0x4378: - d = (Address >> 4) & 7; - DMA[d].Address &= 0xff00; - DMA[d].Address |= byte; - break; - - case 0x4309: - case 0x4319: - case 0x4329: - case 0x4339: - case 0x4349: - case 0x4359: - case 0x4369: - case 0x4379: - d = (Address >> 4) & 0x7; - DMA[d].Address &= 0xff; - DMA[d].Address |= byte << 8; - break; - - case 0x430A: - case 0x431A: - case 0x432A: - case 0x433A: - case 0x434A: - case 0x435A: - case 0x436A: - case 0x437A: - d = (Address >> 4) & 0x7; - DMA[d].LineCount = byte & 0x7f; - DMA[d].Repeat = !(byte & 0x80); - break; - - case 0x4800: - case 0x4801: - case 0x4802: - case 0x4803: -//printf ("%02x->%04x\n", byte, Address); - break; - - case 0x4804: - case 0x4805: - case 0x4806: - case 0x4807: -//printf ("%02x->%04x\n", byte, Address); - - S9xSetSDD1MemoryMap (Address - 0x4804, byte & 7); - break; - default: -#ifdef DEBUGGER - missing.unknowncpu_write = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf (String, "Unknown register write: $%02X->$%04X\n", - byte, Address); - S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); - } -#endif - break; - } - Memory.FillRAM [Address] = byte; -} - -/**********************************************************************************************/ -/* S9xGetCPU() */ -/* This function retrieves a CPU/DMA Register */ -/**********************************************************************************************/ -uint8 S9xGetCPU (uint16 Address) -{ - uint8 byte; - - if (Address < 0x4200) - { -#ifdef VAR_CYCLES - CPU.Cycles += ONE_CYCLE; -#endif - switch (Address) - { - // Secret of the Evermore - case 0x4000: - case 0x4001: - return (0x40); - - case 0x4016: - { - if (Memory.FillRAM [0x4016] & 1) - { - if ((!Settings.SwapJoypads && - IPPU.Controller == SNES_MOUSE_SWAPPED) || - (Settings.SwapJoypads && - IPPU.Controller == SNES_MOUSE)) - { - if (++PPU.MouseSpeed [0] > 2) - PPU.MouseSpeed [0] = 0; - } - return (0); - } - - int ind = Settings.SwapJoypads ? 1 : 0; - byte = IPPU.Joypads[ind] >> (PPU.Joypad1ButtonReadPos ^ 15); - PPU.Joypad1ButtonReadPos++; - return (byte & 1); - } - case 0x4017: - { - if (Memory.FillRAM [0x4016] & 1) - { - // MultiPlayer5 adaptor is only allowed to be plugged into port 2 - switch (IPPU.Controller) - { - case SNES_MULTIPLAYER5: - return (2); - case SNES_MOUSE_SWAPPED: - if (Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) - PPU.MouseSpeed [0] = 0; - break; - - case SNES_MOUSE: - if (!Settings.SwapJoypads && ++PPU.MouseSpeed [0] > 2) - PPU.MouseSpeed [0] = 0; - break; - } - return (0x00); - } - - int ind = Settings.SwapJoypads ? 0 : 1; - - if (IPPU.Controller == SNES_MULTIPLAYER5) - { - if (Memory.FillRAM [0x4201] & 0x80) - { - byte = ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) | - (((IPPU.Joypads[2] >> (PPU.Joypad2ButtonReadPos ^ 15)) & 1) << 1); - PPU.Joypad2ButtonReadPos++; - return (byte); - } - else - { - byte = ((IPPU.Joypads[3] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) | - (((IPPU.Joypads[4] >> (PPU.Joypad3ButtonReadPos ^ 15)) & 1) << 1); - PPU.Joypad3ButtonReadPos++; - return (byte); - } - } - return ((IPPU.Joypads[ind] >> (PPU.Joypad2ButtonReadPos++ ^ 15)) & 1); - } - default: -#ifdef DEBUGGER - missing.unknowncpu_read = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf (String, "Unknown register read: $%04X\n", Address); - S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); - } -#endif - break; - } - return (Memory.FillRAM [Address]); - } - else - switch (Address) - { - // BS Dynami Tracer! needs to be able to check if NMIs are enabled - // already, otherwise the game locks up. - case 0x4200: - // NMI, h & v timers and joypad reading enable - if (SNESGameFixes.Old_Read0x4200) - { -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - return (REGISTER_4212()); - } - case 0x4201: - // I/O port (output - write only?) - case 0x4202: - case 0x4203: - // Multiplier and multiplicand (write) - case 0x4204: - case 0x4205: - case 0x4206: - // Divisor and dividend (write) - return (Memory.FillRAM[Address]); - case 0x4207: - return (uint8)(PPU.IRQHBeamPos); - case 0x4208: - return (PPU.IRQHBeamPos >> 8); - case 0x4209: - return (uint8)(PPU.IRQVBeamPos); - case 0x420a: - return (PPU.IRQVBeamPos >> 8); - case 0x420b: - // General purpose DMA enable - // Super Formation Soccer 95 della Serie A UCC Xaqua requires this - // register should not always return zero. - // .. But Aero 2 waits until this register goes zero.. - // Just keep toggling the value for now in the hope that it breaks - // the game out of its wait loop... - Memory.FillRAM [0x420b] = !Memory.FillRAM [0x420b]; - return (Memory.FillRAM [0x420b]); - case 0x420c: - // H-DMA enable - return (IPPU.HDMA); - case 0x420d: - // Cycle speed 0 - 2.68Mhz, 1 - 3.58Mhz (banks 0x80 +) - return (Memory.FillRAM[Address]); - case 0x420e: - case 0x420f: - // --->>> Unknown - return (Memory.FillRAM[Address]); - case 0x4210: -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - byte = Memory.FillRAM[0x4210]; - Memory.FillRAM[0x4210] = 0; - return (byte); - case 0x4211: - byte = (CPU.IRQActive & (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE)) ? 0x80 : 0; - // Super Robot Wars Ex ROM bug requires this. - byte |= CPU.Cycles >= Settings.HBlankStart ? 0x40 : 0; - CLEAR_IRQ_SOURCE (PPU_V_BEAM_IRQ_SOURCE | PPU_H_BEAM_IRQ_SOURCE); - return (byte); - case 0x4212: - // V-blank, h-blank and joypads being read flags (read-only) -#ifdef CPU_SHUTDOWN - CPU.WaitAddress = CPU.PCAtOpcodeStart; -#endif - return (REGISTER_4212()); - case 0x4213: - // I/O port input - case 0x4214: - case 0x4215: - // Quotient of divide result - case 0x4216: - case 0x4217: - // Multiplcation result (for multiply) or remainder of - // divison. - return (Memory.FillRAM[Address]); - case 0x4218: - case 0x4219: - case 0x421a: - case 0x421b: - case 0x421c: - case 0x421d: - case 0x421e: - case 0x421f: - // Joypads 1-4 button and direction state. - return (Memory.FillRAM [Address]); - - case 0x4300: - case 0x4310: - case 0x4320: - case 0x4330: - case 0x4340: - case 0x4350: - case 0x4360: - case 0x4370: - // DMA direction, address type, fixed flag, - return (Memory.FillRAM[Address]); - - case 0x4301: - case 0x4311: - case 0x4321: - case 0x4331: - case 0x4341: - case 0x4351: - case 0x4361: - case 0x4371: - return (Memory.FillRAM[Address]); - - case 0x4302: - case 0x4312: - case 0x4322: - case 0x4332: - case 0x4342: - case 0x4352: - case 0x4362: - case 0x4372: - return (Memory.FillRAM[Address]); - - case 0x4303: - case 0x4313: - case 0x4323: - case 0x4333: - case 0x4343: - case 0x4353: - case 0x4363: - case 0x4373: - return (Memory.FillRAM[Address]); - - case 0x4304: - case 0x4314: - case 0x4324: - case 0x4334: - case 0x4344: - case 0x4354: - case 0x4364: - case 0x4374: - return (Memory.FillRAM[Address]); - - case 0x4305: - case 0x4315: - case 0x4325: - case 0x4335: - case 0x4345: - case 0x4355: - case 0x4365: - case 0x4375: - return (Memory.FillRAM[Address]); - - case 0x4306: - case 0x4316: - case 0x4326: - case 0x4336: - case 0x4346: - case 0x4356: - case 0x4366: - case 0x4376: - return (Memory.FillRAM[Address]); - - case 0x4307: - case 0x4317: - case 0x4327: - case 0x4337: - case 0x4347: - case 0x4357: - case 0x4367: - case 0x4377: - return (DMA[(Address >> 4) & 7].IndirectBank); - - case 0x4308: - case 0x4318: - case 0x4328: - case 0x4338: - case 0x4348: - case 0x4358: - case 0x4368: - case 0x4378: - return (Memory.FillRAM[Address]); - - case 0x4309: - case 0x4319: - case 0x4329: - case 0x4339: - case 0x4349: - case 0x4359: - case 0x4369: - case 0x4379: - return (Memory.FillRAM[Address]); - - case 0x430A: - case 0x431A: - case 0x432A: - case 0x433A: - case 0x434A: - case 0x435A: - case 0x436A: - case 0x437A: - { - int d = (Address & 0x70) >> 4; - if (IPPU.HDMA & (1 << d)) - { - return (DMA[d].LineCount); - } - return (Memory.FillRAM[Address]); - } - default: -#ifdef DEBUGGER - missing.unknowncpu_read = Address; - if (Settings.TraceUnknownRegisters) - { - sprintf (String, "Unknown register read: $%04X\n", Address); - S9xMessage (S9X_TRACE, S9X_PPU_TRACE, String); - } - -#endif - break; - } - return (Memory.FillRAM[Address]); -} - -void S9xResetPPU () -{ - PPU.BGMode = 0; - PPU.BG3Priority = 0; - PPU.Brightness = 0; - PPU.VMA.High = 0; - PPU.VMA.Increment = 1; - PPU.VMA.Address = 0; - PPU.VMA.FullGraphicCount = 0; - PPU.VMA.Shift = 0; - - for (uint8 B = 0; B != 4; B++) - { - PPU.BG[B].SCBase = 0; - PPU.BG[B].VOffset = 0; - PPU.BG[B].HOffset = 0; - PPU.BG[B].BGSize = 0; - PPU.BG[B].NameBase = 0; - PPU.BG[B].SCSize = 0; - - PPU.ClipCounts[B] = 0; - PPU.ClipWindowOverlapLogic [B] = CLIP_OR; - PPU.ClipWindow1Enable[B] = FALSE; - PPU.ClipWindow2Enable[B] = FALSE; - PPU.ClipWindow1Inside[B] = TRUE; - PPU.ClipWindow2Inside[B] = TRUE; - } - - PPU.ClipCounts[4] = 0; - PPU.ClipCounts[5] = 0; - PPU.ClipWindowOverlapLogic[4] = PPU.ClipWindowOverlapLogic[5] = CLIP_OR; - PPU.ClipWindow1Enable[4] = PPU.ClipWindow1Enable[5] = FALSE; - PPU.ClipWindow2Enable[4] = PPU.ClipWindow2Enable[5] = FALSE; - PPU.ClipWindow1Inside[4] = PPU.ClipWindow1Inside[5] = TRUE; - PPU.ClipWindow2Inside[4] = PPU.ClipWindow2Inside[5] = TRUE; - - PPU.CGFLIP = 0; - int c; - for (c = 0; c < 256; c++) - { - IPPU.Red [c] = (c & 7) << 2; - IPPU.Green [c] = ((c >> 3) & 7) << 2; - IPPU.Blue [c] = ((c >> 6) & 2) << 3; - PPU.CGDATA [c] = IPPU.Red [c] | (IPPU.Green [c] << 5) | - (IPPU.Blue [c] << 10); - } - - PPU.FirstSprite = 0; - PPU.LastSprite = 127; - for (int Sprite = 0; Sprite < 128; Sprite++) - { - PPU.OBJ[Sprite].HPos = 0; - PPU.OBJ[Sprite].VPos = 0; - PPU.OBJ[Sprite].VFlip = 0; - PPU.OBJ[Sprite].HFlip = 0; - PPU.OBJ[Sprite].Priority = 0; - PPU.OBJ[Sprite].Palette = 0; - PPU.OBJ[Sprite].Name = 0; - PPU.OBJ[Sprite].Size = 0; - } - PPU.OAMPriorityRotation = 0; - - PPU.OAMFlip = 0; - PPU.OAMTileAddress = 0; - PPU.OAMAddr = 0; - PPU.IRQVBeamPos = 0; - PPU.IRQHBeamPos = 0; - PPU.VBeamPosLatched = 0; - PPU.HBeamPosLatched = 0; - - PPU.HBeamFlip = 0; - PPU.VBeamFlip = 0; - PPU.HVBeamCounterLatched = 0; - - PPU.MatrixA = PPU.MatrixB = PPU.MatrixC = PPU.MatrixD = 0; - PPU.CentreX = PPU.CentreY = 0; - PPU.Joypad1ButtonReadPos = 0; - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 0; - - PPU.CGADD = 0; - PPU.FixedColourRed = PPU.FixedColourGreen = PPU.FixedColourBlue = 0; - PPU.SavedOAMAddr = 0; - PPU.ScreenHeight = SNES_HEIGHT; - PPU.WRAM = 0; - PPU.BG_Forced = 0; - PPU.ForcedBlanking = TRUE; - PPU.OBJThroughMain = FALSE; - PPU.OBJThroughSub = FALSE; - PPU.OBJSizeSelect = 0; - PPU.OBJNameSelect = 0; - PPU.OBJNameBase = 0; - PPU.OBJAddition = FALSE; - PPU.OAMReadFlip = 0; - ZeroMemory (PPU.OAMData, 512 + 32); - - PPU.VTimerEnabled = FALSE; - PPU.HTimerEnabled = FALSE; - PPU.HTimerPosition = Settings.H_Max + 1; - PPU.Mosaic = 0; - PPU.BGMosaic [0] = PPU.BGMosaic [1] = FALSE; - PPU.BGMosaic [2] = PPU.BGMosaic [3] = FALSE; - PPU.Mode7HFlip = FALSE; - PPU.Mode7VFlip = FALSE; - PPU.Mode7Repeat = 0; - PPU.Window1Left = 1; - PPU.Window1Right = 0; - PPU.Window2Left = 1; - PPU.Window2Right = 0; - PPU.RecomputeClipWindows = TRUE; - PPU.CGFLIPRead = 0; - PPU.Need16x8Mulitply = FALSE; - PPU.MouseSpeed[0] = PPU.MouseSpeed[1] = 0; - - IPPU.ColorsChanged = TRUE; - IPPU.HDMA = 0; - IPPU.HDMAStarted = FALSE; - IPPU.MaxBrightness = 0; - IPPU.LatchedBlanking = 0; - IPPU.OBJChanged = TRUE; - IPPU.RenderThisFrame = TRUE; - IPPU.DirectColourMapsNeedRebuild = TRUE; - IPPU.FrameCount = 0; - IPPU.RenderedFramesCount = 0; - IPPU.DisplayedRenderedFrameCount = 0; - IPPU.SkippedFrames = 0; - IPPU.FrameSkip = 0; - ZeroMemory (IPPU.TileCached [TILE_2BIT], MAX_2BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_4BIT], MAX_4BIT_TILES); - ZeroMemory (IPPU.TileCached [TILE_8BIT], MAX_8BIT_TILES); - IPPU.FirstVRAMRead = FALSE; - IPPU.LatchedInterlace = FALSE; - IPPU.DoubleWidthPixels = FALSE; - IPPU.RenderedScreenWidth = SNES_WIDTH; - IPPU.RenderedScreenHeight = SNES_HEIGHT; - IPPU.XB = NULL; - for (c = 0; c < 256; c++) - IPPU.ScreenColors [c] = c; - S9xFixColourBrightness (); - IPPU.PreviousLine = IPPU.CurrentLine = 0; - IPPU.Joypads[0] = IPPU.Joypads[1] = IPPU.Joypads[2] = 0; - IPPU.Joypads[3] = IPPU.Joypads[4] = 0; - IPPU.SuperScope = 0; - IPPU.Mouse[0] = IPPU.Mouse[1] = 0; - IPPU.PrevMouseX[0] = IPPU.PrevMouseX[1] = 256 / 2; - IPPU.PrevMouseY[0] = IPPU.PrevMouseY[1] = 224 / 2; - - if (Settings.ControllerOption == 0) - IPPU.Controller = SNES_MAX_CONTROLLER_OPTIONS - 1; - else - IPPU.Controller = Settings.ControllerOption - 1; - S9xNextController (); - - for (c = 0; c < 2; c++) - memset (&IPPU.Clip [c], 0, sizeof (struct ClipData)); - - if (Settings.MouseMaster) - { - S9xProcessMouse (0); - S9xProcessMouse (1); - } - for (c = 0; c < 0x8000; c += 0x100) - memset (&Memory.FillRAM [c], c >> 8, 0x100); - - ZeroMemory (&Memory.FillRAM [0x2100], 0x100); - ZeroMemory (&Memory.FillRAM [0x4200], 0x100); - ZeroMemory (&Memory.FillRAM [0x4000], 0x100); - // For BS Suttehakkun 2... - ZeroMemory (&Memory.FillRAM [0x1000], 0x1000); -} - -void S9xProcessMouse (int which1) -{ - int x, y; - uint32 buttons; - - if ((IPPU.Controller == SNES_MOUSE || IPPU.Controller == SNES_MOUSE_SWAPPED) && - S9xReadMousePosition (which1, x, y, buttons)) - { - int delta_x, delta_y; -#define MOUSE_SIGNATURE 0x1 - IPPU.Mouse [which1] = MOUSE_SIGNATURE | - (PPU.MouseSpeed [which1] << 4) | - ((buttons & 1) << 6) | ((buttons & 2) << 6); - - delta_x = x - IPPU.PrevMouseX[which1]; - delta_y = y - IPPU.PrevMouseY[which1]; - - if (delta_x > 63) - { - delta_x = 63; - IPPU.PrevMouseX[which1] += 63; - } - else - if (delta_x < -63) - { - delta_x = -63; - IPPU.PrevMouseX[which1] -= 63; - } - else - IPPU.PrevMouseX[which1] = x; - - if (delta_y > 63) - { - delta_y = 63; - IPPU.PrevMouseY[which1] += 63; - } - else - if (delta_y < -63) - { - delta_y = -63; - IPPU.PrevMouseY[which1] -= 63; - } - else - IPPU.PrevMouseY[which1] = y; - - if (delta_x < 0) - { - delta_x = -delta_x; - IPPU.Mouse [which1] |= (delta_x | 0x80) << 16; - } - else - IPPU.Mouse [which1] |= delta_x << 16; - - if (delta_y < 0) - { - delta_y = -delta_y; - IPPU.Mouse [which1] |= (delta_y | 0x80) << 24; - } - else - IPPU.Mouse [which1] |= delta_y << 24; - - if (IPPU.Controller == SNES_MOUSE_SWAPPED) - IPPU.Joypads [0] = IPPU.Mouse [which1]; - else - IPPU.Joypads [1] = IPPU.Mouse [which1]; - } -} - -void ProcessSuperScope () -{ - int x, y; - uint32 buttons; - - if (IPPU.Controller == SNES_SUPERSCOPE && - S9xReadSuperScopePosition (x, y, buttons)) - { -#define SUPERSCOPE_SIGNATURE 0x00ff - uint32 scope; - - scope = SUPERSCOPE_SIGNATURE | ((buttons & 1) << (7 + 8)) | - ((buttons & 2) << (5 + 8)) | ((buttons & 4) << (3 + 8)) | - ((buttons & 8) << (1 + 8)); - if (x > 255) - x = 255; - if (x < 0) - x = 0; - if (y > PPU.ScreenHeight - 1) - y = PPU.ScreenHeight - 1; - if (y < 0) - y = 0; - - PPU.VBeamPosLatched = (uint16) (y + 1); - PPU.HBeamPosLatched = (uint16) x; - PPU.HVBeamCounterLatched = TRUE; - Memory.FillRAM [0x213F] |= 0x40; - IPPU.Joypads [1] = scope; - } -} - -void S9xNextController () -{ - switch (IPPU.Controller) - { - case SNES_MULTIPLAYER5: - IPPU.Controller = SNES_JOYPAD; - break; - case SNES_JOYPAD: - if (Settings.MouseMaster) - { - IPPU.Controller = SNES_MOUSE_SWAPPED; - break; - } - case SNES_MOUSE_SWAPPED: - if (Settings.MouseMaster) - { - IPPU.Controller = SNES_MOUSE; - break; - } - case SNES_MOUSE: - if (Settings.SuperScopeMaster) - { - IPPU.Controller = SNES_SUPERSCOPE; - break; - } - case SNES_SUPERSCOPE: - if (Settings.MultiPlayer5Master) - { - IPPU.Controller = SNES_MULTIPLAYER5; - break; - } - default: - IPPU.Controller = SNES_JOYPAD; - break; - } -} - -void S9xUpdateJoypads () -{ - int i; - - for (i = 0; i < 5; i++) - { - IPPU.Joypads [i] = S9xReadJoypad (i); - if (IPPU.Joypads [i] & SNES_LEFT_MASK) - IPPU.Joypads [i] &= ~SNES_RIGHT_MASK; - if (IPPU.Joypads [i] & SNES_UP_MASK) - IPPU.Joypads [i] &= ~SNES_DOWN_MASK; - } - - //touhaiden controller Fix - if (SNESGameFixes.TouhaidenControllerFix && - (IPPU.Controller == SNES_JOYPAD || IPPU.Controller == SNES_MULTIPLAYER5)) - { - for (i = 0; i < 5; i++) - { - if (IPPU.Joypads [i]) - IPPU.Joypads [i] |= 0xffff0000; - } - } - - // Read mouse position if enabled - if (Settings.MouseMaster) - { - for (i = 0; i < 2; i++) - S9xProcessMouse (i); - } - - // Read SuperScope if enabled - if (Settings.SuperScopeMaster) - ProcessSuperScope (); - - if (Memory.FillRAM [0x4200] & 1) - { - PPU.Joypad1ButtonReadPos = 16; - if (Memory.FillRAM [0x4201] & 0x80) - { - PPU.Joypad2ButtonReadPos = 16; - PPU.Joypad3ButtonReadPos = 0; - } - else - { - PPU.Joypad2ButtonReadPos = 0; - PPU.Joypad3ButtonReadPos = 16; - } - int ind = Settings.SwapJoypads ? 1 : 0; - - Memory.FillRAM [0x4218] = (uint8) IPPU.Joypads [ind]; - Memory.FillRAM [0x4219] = (uint8) (IPPU.Joypads [ind] >> 8); - Memory.FillRAM [0x421a] = (uint8) IPPU.Joypads [ind ^ 1]; - Memory.FillRAM [0x421b] = (uint8) (IPPU.Joypads [ind ^ 1] >> 8); - if (Memory.FillRAM [0x4201] & 0x80) - { - Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [ind]; - Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads [ind] >> 8); - Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [2]; - Memory.FillRAM [0x421f] = (uint8) (IPPU.Joypads [2] >> 8); - } - else - { - Memory.FillRAM [0x421c] = (uint8) IPPU.Joypads [3]; - Memory.FillRAM [0x421d] = (uint8) (IPPU.Joypads [3] >> 8); - Memory.FillRAM [0x421e] = (uint8) IPPU.Joypads [4]; - Memory.FillRAM [0x421f] = (uint8) (IPPU.Joypads [4] >> 8); - } - } -} - -#ifndef ZSNES_FX -void S9xSuperFXExec () -{ - if (Settings.SuperFX) - { - if ((Memory.FillRAM [0x3000 + GSU_SFR] & FLG_G) && - (Memory.FillRAM [0x3000 + GSU_SCMR] & 0x18) == 0x18) - { - if (!Settings.WinterGold) - FxEmulate (~0); - else - FxEmulate ((Memory.FillRAM [0x3000 + GSU_CLSR] & 1) ? 700 : 350); - int GSUStatus = Memory.FillRAM [0x3000 + GSU_SFR] | - (Memory.FillRAM [0x3000 + GSU_SFR + 1] << 8); - if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) - { - // Trigger a GSU IRQ. - S9xSetIRQ (GSU_IRQ_SOURCE); - } - } - } - -} -#endif diff --git a/src/rops.c b/src/rops.c new file mode 100644 index 0000000..e4eab04 --- /dev/null +++ b/src/rops.c @@ -0,0 +1,238 @@ +#include "snes9x.h" +#include "ppu.h" +#include "rops.h" + +ROPSTRUCT rops[MAX_ROPS]; +unsigned int ROpCount; + +void doRaster(ROPSTRUCT *rop) { + if (!rop) return; + switch (rop->rop) { + case ROP_NOP: + // NOP + break; + case ROP_FIXEDCOLOUR: + { + unsigned char col = rop->value & 0x1f; + // Colour data for fixed colour addition/subtraction + if (rop->value & 0x80) PPU.FixedColourBlue = col; + if (rop->value & 0x40) PPU.FixedColourGreen = col; + if (rop->value & 0x20) PPU.FixedColourRed = col; + } + break; + case ROP_PALETTE: + { + // Pallette, colors + unsigned char col = rop->value & 255; + IPPU.Blue[col] = (rop->value >> (16 + 10)) & 0x1f; + IPPU.Green[col] = (rop->value >> (16 + 5)) & 0x1f; + IPPU.Red[col] = (rop->value >> (16 + 0)) & 0x1f; + IPPU.ScreenColors[col] = (uint16) BUILD_PIXEL (IPPU.XB[IPPU.Red[col]], IPPU.XB[IPPU.Green[col]], IPPU.XB[IPPU.Blue[col]]); + IPPU.ColorsChanged = TRUE; + } + break; + case ROP_SCREEN_MODE: + // Screen mode (0 - 7), background tile sizes and background 3 priority + PPU.BG[0].BGSize = (rop->value >> 4) & 1; + PPU.BG[1].BGSize = (rop->value >> 5) & 1; + PPU.BG[2].BGSize = (rop->value >> 6) & 1; + PPU.BG[3].BGSize = (rop->value >> 7) & 1; + PPU.BGMode = rop->value & 7; + // BJ: BG3Priority only takes effect if BGMode==1 and the bit is set + PPU.BG3Priority = ((rop->value & 0x0f) == 0x09); + break; + case ROP_BRIGHTNESS: + PPU.Brightness = rop->value; + S9xFixColourBrightness(); + if (PPU.Brightness > IPPU.MaxBrightness) IPPU.MaxBrightness = PPU.Brightness; + IPPU.ColorsChanged = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + break; + case ROP_FORCE_BLANKING: + PPU.ForcedBlanking = rop->value; + IPPU.ColorsChanged = TRUE; + break; + case ROP_TILE_ADDRESS: + PPU.OBJNameBase = (rop->value & 3) << 14; + PPU.OBJNameSelect = ((rop->value >> 3) & 3) << 13; + PPU.OBJSizeSelect = (rop->value >> 5) & 7; + IPPU.OBJChanged = TRUE; + break; + case ROP_MOSAIC: + PPU.Mosaic = (rop->value >> 4) + 1; + PPU.BGMosaic[0] = (rop->value & 1) && PPU.Mosaic > 1; + PPU.BGMosaic[1] = (rop->value & 2) && PPU.Mosaic > 1; + PPU.BGMosaic[2] = (rop->value & 4) && PPU.Mosaic > 1; + PPU.BGMosaic[3] = (rop->value & 8) && PPU.Mosaic > 1; + break; + case ROP_BG_SCSIZE_SCBASE: + PPU.BG[rop->value >> 16].SCSize = rop->value & 3; + PPU.BG[rop->value >> 16].SCBase = (rop->value & 0x7c) << 8; + break; + case ROP_BG_NAMEBASE: + PPU.BG[(rop->value >> 16) + 0].NameBase = (rop->value & 7) << 12; + PPU.BG[(rop->value >> 16) + 1].NameBase = ((rop->value >> 4) & 7) << 12; + break; + case ROP_MODE7_ROTATION: + PPU.Mode7Repeat = rop->value >> 6; + if (PPU.Mode7Repeat == 1) PPU.Mode7Repeat = 0; + PPU.Mode7VFlip = (rop->value & 2) >> 1; + PPU.Mode7HFlip = rop->value & 1; + break; + case ROP_BG_WINDOW_ENABLE: + PPU.ClipWindow1Enable[(rop->value >> 16) + 0] = !!(rop->value & 0x02); + PPU.ClipWindow1Enable[(rop->value >> 16) + 1] = !!(rop->value & 0x20); + PPU.ClipWindow2Enable[(rop->value >> 16) + 0] = !!(rop->value & 0x08); + PPU.ClipWindow2Enable[(rop->value >> 16) + 1] = !!(rop->value & 0x80); + PPU.ClipWindow1Inside[(rop->value >> 16) + 0] = !(rop->value & 0x01); + PPU.ClipWindow1Inside[(rop->value >> 16) + 1] = !(rop->value & 0x10); + PPU.ClipWindow2Inside[(rop->value >> 16) + 0] = !(rop->value & 0x04); + PPU.ClipWindow2Inside[(rop->value >> 16) + 1] = !(rop->value & 0x40); + PPU.RecomputeClipWindows = TRUE; + break; + case ROP_WINDOW1_LEFT: + PPU.Window1Left = rop->value; + PPU.RecomputeClipWindows = TRUE; + break; + case ROP_WINDOW1_RIGHT: + PPU.Window1Right = rop->value; + PPU.RecomputeClipWindows = TRUE; + break; + case ROP_WINDOW2_LEFT: + PPU.Window2Left = rop->value; + PPU.RecomputeClipWindows = TRUE; + break; + case ROP_WINDOW2_RIGHT: + PPU.Window2Right = rop->value; + PPU.RecomputeClipWindows = TRUE; + break; + case ROP_BG_WINDOW_LOGIC: + PPU.ClipWindowOverlapLogic[0] = (rop->value & 0x03); + PPU.ClipWindowOverlapLogic[1] = (rop->value & 0x0c) >> 2; + PPU.ClipWindowOverlapLogic[2] = (rop->value & 0x30) >> 4; + PPU.ClipWindowOverlapLogic[3] = (rop->value & 0xc0) >> 6; + PPU.RecomputeClipWindows = TRUE; + break; + case ROP_OBJS_WINDOW_LOGIC: + PPU.ClipWindowOverlapLogic[4] = (rop->value & 0x03); + PPU.ClipWindowOverlapLogic[5] = (rop->value & 0x0c) >> 2; + PPU.RecomputeClipWindows = TRUE; + break; + case ROP_MAIN_SCREEN_DESIG: + // Main screen designation (backgrounds 1 - 4 and objects) + if ((GFX.r212c_s & GFX.r212e_s & 0x1f) != (GFX.r212e_s & rop->value & 0x1f)) PPU.RecomputeClipWindows = TRUE; + GFX.r212c_s = rop->value; + break; + case ROP_SUB_SCREEN_DESIG: + // Sub-screen designation (backgrounds 1 - 4 and objects) + if ((GFX.r212d_s & GFX.r212f_s & 0x1f) != (GFX.r212f_s & rop->value & 0x1f)) PPU.RecomputeClipWindows = TRUE; + GFX.r212d_s = rop->value; + break; + case ROP_MAIN_SCREEN_WMASK: + // Window mask designation for main screen ? + if ((GFX.r212c_s & GFX.r212e_s & 0x1f) != (GFX.r212c_s & rop->value & 0x1f)) PPU.RecomputeClipWindows = TRUE; + GFX.r212e_s = rop->value; + break; + case ROP_SUB_SCREEN_WMASK: + // Window mask designation for sub-sreen ? + if ((GFX.r212d_s & GFX.r212f_s & 0x1f) != (GFX.r212d_s & rop->value & 0x1f)) PPU.RecomputeClipWindows = TRUE; + GFX.r212f_s = rop->value; + break; + case ROP_FIXEDCOL_OR_SCREEN: + // Fixed colour addition or screen addition + if ((GFX.r2130_s & 0xf0) != (rop->value & 0xf0)) PPU.RecomputeClipWindows = TRUE; + GFX.r2130_s = rop->value; + break; + case ROP_ADD_OR_SUB_COLOR: + // Backgrounds 1 - 4, objects and backdrop colour add/sub enable + GFX.r2131_s = rop->value; + break; + } + rop->rop = 0; // Raster Operation already done, invalidate it +} + +bool wouldRasterAlterStatus(ROPSTRUCT *rop) { + if (!rop) return false; + switch (rop->rop) { + case ROP_NOP: + return false; + break; + case ROP_FIXEDCOLOUR: + { + unsigned char col = rop->value & 0x1f; + // Colour data for fixed colour addition/subtraction + if ((rop->value & 0x80) && (PPU.FixedColourBlue != col)) return true; + if ((rop->value & 0x40) && (PPU.FixedColourGreen != col)) return true; + if ((rop->value & 0x20) && (PPU.FixedColourRed != col)) return true; + return false; + } + break; + case ROP_PALETTE: + return true; + break; + case ROP_SCREEN_MODE: + return true; + break; + case ROP_BRIGHTNESS: + return true; + break; + case ROP_FORCE_BLANKING: + return true; + break; + case ROP_TILE_ADDRESS: + return true; + break; + case ROP_MOSAIC: + return true; + break; + case ROP_BG_SCSIZE_SCBASE: + return true; + break; + case ROP_BG_NAMEBASE: + return true; + break; + case ROP_MODE7_ROTATION: + return true; + break; + case ROP_BG_WINDOW_ENABLE: + return true; + break; + case ROP_WINDOW1_LEFT: + return true; + break; + case ROP_WINDOW1_RIGHT: + return true; + break; + case ROP_WINDOW2_LEFT: + return true; + break; + case ROP_WINDOW2_RIGHT: + return true; + break; + case ROP_BG_WINDOW_LOGIC: + return true; + break; + case ROP_OBJS_WINDOW_LOGIC: + return true; + break; + case ROP_MAIN_SCREEN_DESIG: + return true; + break; + case ROP_SUB_SCREEN_DESIG: + return true; + break; + case ROP_MAIN_SCREEN_WMASK: + return true; + break; + case ROP_SUB_SCREEN_WMASK: + return true; + break; + case ROP_FIXEDCOL_OR_SCREEN: + return true; + break; + case ROP_ADD_OR_SUB_COLOR: + return true; + break; + } + return true; +} diff --git a/src/rops.cpp b/src/rops.cpp deleted file mode 100644 index e4eab04..0000000 --- a/src/rops.cpp +++ /dev/null @@ -1,238 +0,0 @@ -#include "snes9x.h" -#include "ppu.h" -#include "rops.h" - -ROPSTRUCT rops[MAX_ROPS]; -unsigned int ROpCount; - -void doRaster(ROPSTRUCT *rop) { - if (!rop) return; - switch (rop->rop) { - case ROP_NOP: - // NOP - break; - case ROP_FIXEDCOLOUR: - { - unsigned char col = rop->value & 0x1f; - // Colour data for fixed colour addition/subtraction - if (rop->value & 0x80) PPU.FixedColourBlue = col; - if (rop->value & 0x40) PPU.FixedColourGreen = col; - if (rop->value & 0x20) PPU.FixedColourRed = col; - } - break; - case ROP_PALETTE: - { - // Pallette, colors - unsigned char col = rop->value & 255; - IPPU.Blue[col] = (rop->value >> (16 + 10)) & 0x1f; - IPPU.Green[col] = (rop->value >> (16 + 5)) & 0x1f; - IPPU.Red[col] = (rop->value >> (16 + 0)) & 0x1f; - IPPU.ScreenColors[col] = (uint16) BUILD_PIXEL (IPPU.XB[IPPU.Red[col]], IPPU.XB[IPPU.Green[col]], IPPU.XB[IPPU.Blue[col]]); - IPPU.ColorsChanged = TRUE; - } - break; - case ROP_SCREEN_MODE: - // Screen mode (0 - 7), background tile sizes and background 3 priority - PPU.BG[0].BGSize = (rop->value >> 4) & 1; - PPU.BG[1].BGSize = (rop->value >> 5) & 1; - PPU.BG[2].BGSize = (rop->value >> 6) & 1; - PPU.BG[3].BGSize = (rop->value >> 7) & 1; - PPU.BGMode = rop->value & 7; - // BJ: BG3Priority only takes effect if BGMode==1 and the bit is set - PPU.BG3Priority = ((rop->value & 0x0f) == 0x09); - break; - case ROP_BRIGHTNESS: - PPU.Brightness = rop->value; - S9xFixColourBrightness(); - if (PPU.Brightness > IPPU.MaxBrightness) IPPU.MaxBrightness = PPU.Brightness; - IPPU.ColorsChanged = TRUE; - IPPU.DirectColourMapsNeedRebuild = TRUE; - break; - case ROP_FORCE_BLANKING: - PPU.ForcedBlanking = rop->value; - IPPU.ColorsChanged = TRUE; - break; - case ROP_TILE_ADDRESS: - PPU.OBJNameBase = (rop->value & 3) << 14; - PPU.OBJNameSelect = ((rop->value >> 3) & 3) << 13; - PPU.OBJSizeSelect = (rop->value >> 5) & 7; - IPPU.OBJChanged = TRUE; - break; - case ROP_MOSAIC: - PPU.Mosaic = (rop->value >> 4) + 1; - PPU.BGMosaic[0] = (rop->value & 1) && PPU.Mosaic > 1; - PPU.BGMosaic[1] = (rop->value & 2) && PPU.Mosaic > 1; - PPU.BGMosaic[2] = (rop->value & 4) && PPU.Mosaic > 1; - PPU.BGMosaic[3] = (rop->value & 8) && PPU.Mosaic > 1; - break; - case ROP_BG_SCSIZE_SCBASE: - PPU.BG[rop->value >> 16].SCSize = rop->value & 3; - PPU.BG[rop->value >> 16].SCBase = (rop->value & 0x7c) << 8; - break; - case ROP_BG_NAMEBASE: - PPU.BG[(rop->value >> 16) + 0].NameBase = (rop->value & 7) << 12; - PPU.BG[(rop->value >> 16) + 1].NameBase = ((rop->value >> 4) & 7) << 12; - break; - case ROP_MODE7_ROTATION: - PPU.Mode7Repeat = rop->value >> 6; - if (PPU.Mode7Repeat == 1) PPU.Mode7Repeat = 0; - PPU.Mode7VFlip = (rop->value & 2) >> 1; - PPU.Mode7HFlip = rop->value & 1; - break; - case ROP_BG_WINDOW_ENABLE: - PPU.ClipWindow1Enable[(rop->value >> 16) + 0] = !!(rop->value & 0x02); - PPU.ClipWindow1Enable[(rop->value >> 16) + 1] = !!(rop->value & 0x20); - PPU.ClipWindow2Enable[(rop->value >> 16) + 0] = !!(rop->value & 0x08); - PPU.ClipWindow2Enable[(rop->value >> 16) + 1] = !!(rop->value & 0x80); - PPU.ClipWindow1Inside[(rop->value >> 16) + 0] = !(rop->value & 0x01); - PPU.ClipWindow1Inside[(rop->value >> 16) + 1] = !(rop->value & 0x10); - PPU.ClipWindow2Inside[(rop->value >> 16) + 0] = !(rop->value & 0x04); - PPU.ClipWindow2Inside[(rop->value >> 16) + 1] = !(rop->value & 0x40); - PPU.RecomputeClipWindows = TRUE; - break; - case ROP_WINDOW1_LEFT: - PPU.Window1Left = rop->value; - PPU.RecomputeClipWindows = TRUE; - break; - case ROP_WINDOW1_RIGHT: - PPU.Window1Right = rop->value; - PPU.RecomputeClipWindows = TRUE; - break; - case ROP_WINDOW2_LEFT: - PPU.Window2Left = rop->value; - PPU.RecomputeClipWindows = TRUE; - break; - case ROP_WINDOW2_RIGHT: - PPU.Window2Right = rop->value; - PPU.RecomputeClipWindows = TRUE; - break; - case ROP_BG_WINDOW_LOGIC: - PPU.ClipWindowOverlapLogic[0] = (rop->value & 0x03); - PPU.ClipWindowOverlapLogic[1] = (rop->value & 0x0c) >> 2; - PPU.ClipWindowOverlapLogic[2] = (rop->value & 0x30) >> 4; - PPU.ClipWindowOverlapLogic[3] = (rop->value & 0xc0) >> 6; - PPU.RecomputeClipWindows = TRUE; - break; - case ROP_OBJS_WINDOW_LOGIC: - PPU.ClipWindowOverlapLogic[4] = (rop->value & 0x03); - PPU.ClipWindowOverlapLogic[5] = (rop->value & 0x0c) >> 2; - PPU.RecomputeClipWindows = TRUE; - break; - case ROP_MAIN_SCREEN_DESIG: - // Main screen designation (backgrounds 1 - 4 and objects) - if ((GFX.r212c_s & GFX.r212e_s & 0x1f) != (GFX.r212e_s & rop->value & 0x1f)) PPU.RecomputeClipWindows = TRUE; - GFX.r212c_s = rop->value; - break; - case ROP_SUB_SCREEN_DESIG: - // Sub-screen designation (backgrounds 1 - 4 and objects) - if ((GFX.r212d_s & GFX.r212f_s & 0x1f) != (GFX.r212f_s & rop->value & 0x1f)) PPU.RecomputeClipWindows = TRUE; - GFX.r212d_s = rop->value; - break; - case ROP_MAIN_SCREEN_WMASK: - // Window mask designation for main screen ? - if ((GFX.r212c_s & GFX.r212e_s & 0x1f) != (GFX.r212c_s & rop->value & 0x1f)) PPU.RecomputeClipWindows = TRUE; - GFX.r212e_s = rop->value; - break; - case ROP_SUB_SCREEN_WMASK: - // Window mask designation for sub-sreen ? - if ((GFX.r212d_s & GFX.r212f_s & 0x1f) != (GFX.r212d_s & rop->value & 0x1f)) PPU.RecomputeClipWindows = TRUE; - GFX.r212f_s = rop->value; - break; - case ROP_FIXEDCOL_OR_SCREEN: - // Fixed colour addition or screen addition - if ((GFX.r2130_s & 0xf0) != (rop->value & 0xf0)) PPU.RecomputeClipWindows = TRUE; - GFX.r2130_s = rop->value; - break; - case ROP_ADD_OR_SUB_COLOR: - // Backgrounds 1 - 4, objects and backdrop colour add/sub enable - GFX.r2131_s = rop->value; - break; - } - rop->rop = 0; // Raster Operation already done, invalidate it -} - -bool wouldRasterAlterStatus(ROPSTRUCT *rop) { - if (!rop) return false; - switch (rop->rop) { - case ROP_NOP: - return false; - break; - case ROP_FIXEDCOLOUR: - { - unsigned char col = rop->value & 0x1f; - // Colour data for fixed colour addition/subtraction - if ((rop->value & 0x80) && (PPU.FixedColourBlue != col)) return true; - if ((rop->value & 0x40) && (PPU.FixedColourGreen != col)) return true; - if ((rop->value & 0x20) && (PPU.FixedColourRed != col)) return true; - return false; - } - break; - case ROP_PALETTE: - return true; - break; - case ROP_SCREEN_MODE: - return true; - break; - case ROP_BRIGHTNESS: - return true; - break; - case ROP_FORCE_BLANKING: - return true; - break; - case ROP_TILE_ADDRESS: - return true; - break; - case ROP_MOSAIC: - return true; - break; - case ROP_BG_SCSIZE_SCBASE: - return true; - break; - case ROP_BG_NAMEBASE: - return true; - break; - case ROP_MODE7_ROTATION: - return true; - break; - case ROP_BG_WINDOW_ENABLE: - return true; - break; - case ROP_WINDOW1_LEFT: - return true; - break; - case ROP_WINDOW1_RIGHT: - return true; - break; - case ROP_WINDOW2_LEFT: - return true; - break; - case ROP_WINDOW2_RIGHT: - return true; - break; - case ROP_BG_WINDOW_LOGIC: - return true; - break; - case ROP_OBJS_WINDOW_LOGIC: - return true; - break; - case ROP_MAIN_SCREEN_DESIG: - return true; - break; - case ROP_SUB_SCREEN_DESIG: - return true; - break; - case ROP_MAIN_SCREEN_WMASK: - return true; - break; - case ROP_SUB_SCREEN_WMASK: - return true; - break; - case ROP_FIXEDCOL_OR_SCREEN: - return true; - break; - case ROP_ADD_OR_SUB_COLOR: - return true; - break; - } - return true; -} diff --git a/src/rops.h b/src/rops.h index e751a58..e5d3c78 100644 --- a/src/rops.h +++ b/src/rops.h @@ -1,6 +1,8 @@ #ifndef __ROPS_H__ #define __ROPS_H__ +#include "stdbool.h" + /* Raster Operations macros */ diff --git a/src/sa1.c b/src/sa1.c new file mode 100644 index 0000000..54fd9b2 --- /dev/null +++ b/src/sa1.c @@ -0,0 +1,775 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +#ifdef USE_SA1 + +#include "snes9x.h" +#include "ppu.h" +#include "cpuexec.h" + +#include "sa1.h" + +static void S9xSA1CharConv2 (); +static void S9xSA1DMA (); +static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift); + +void S9xSA1Init () +{ + SA1.NMIActive = FALSE; + SA1.IRQActive = FALSE; + SA1.WaitingForInterrupt = FALSE; + SA1.Waiting = FALSE; + SA1.Flags = 0; + SA1.Executing = FALSE; + memset (&Memory.FillRAM [0x2200], 0, 0x200); + Memory.FillRAM [0x2200] = 0x20; + Memory.FillRAM [0x2220] = 0x00; + Memory.FillRAM [0x2221] = 0x01; + Memory.FillRAM [0x2222] = 0x02; + Memory.FillRAM [0x2223] = 0x03; + Memory.FillRAM [0x2228] = 0xff; + SA1.op1 = 0; + SA1.op2 = 0; + SA1.arithmetic_op = 0; + SA1.sum = 0; + SA1.overflow = FALSE; +} + +void S9xSA1Reset () +{ + SA1Registers.PB = 0; + SA1Registers.PC = Memory.FillRAM [0x2203] | + (Memory.FillRAM [0x2204] << 8); + SA1Registers.D.W = 0; + SA1Registers.DB = 0; + SA1Registers.SH = 1; + SA1Registers.SL = 0xFF; + SA1Registers.XH = 0; + SA1Registers.YH = 0; + SA1Registers.P.W = 0; + + SA1.ShiftedPB = 0; + SA1.ShiftedDB = 0; + SA1SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); + SA1ClearFlags (Decimal); + + SA1.WaitingForInterrupt = FALSE; + SA1.PC = NULL; + SA1.PCBase = NULL; + S9xSA1SetPCBase (SA1Registers.PC); + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + + S9xSA1UnpackStatus(); + S9xSA1FixCycles (); + SA1.Executing = TRUE; + SA1.BWRAM = Memory.SRAM; + Memory.FillRAM [0x2225] = 0; +} + +void S9xSA1SetBWRAMMemMap (uint8 val) +{ + int c; + + if (val & 0x80) + { + for (c = 0; c < 0x400; c += 16) + { + SA1_Map [c + 6] = SA1_Map [c + 0x806] = (uint8 *) MAP_BWRAM_BITMAP2; + SA1_Map [c + 7] = SA1_Map [c + 0x807] = (uint8 *) MAP_BWRAM_BITMAP2; + SA1_WriteMap [c + 6] = SA1_WriteMap [c + 0x806] = (uint8 *) MAP_BWRAM_BITMAP2; + SA1_WriteMap [c + 7] = SA1_WriteMap [c + 0x807] = (uint8 *) MAP_BWRAM_BITMAP2; + } + SA1.BWRAM = Memory.SRAM + (val & 0x7f) * 0x2000 / 4; + } + else + { + for (c = 0; c < 0x400; c += 16) + { + SA1_Map [c + 6] = SA1_Map [c + 0x806] = (uint8 *) MAP_BWRAM; + SA1_Map [c + 7] = SA1_Map [c + 0x807] = (uint8 *) MAP_BWRAM; + SA1_WriteMap [c + 6] = SA1_WriteMap [c + 0x806] = (uint8 *) MAP_BWRAM; + SA1_WriteMap [c + 7] = SA1_WriteMap [c + 0x807] = (uint8 *) MAP_BWRAM; + } + SA1.BWRAM = Memory.SRAM + (val & 7) * 0x2000; + } +} + +void S9xFixSA1AfterSnapshotLoad () +{ + SA1.ShiftedPB = (uint32) SA1Registers.PB << 16; + SA1.ShiftedDB = (uint32) SA1Registers.DB << 16; + + S9xSA1SetPCBase (SA1.ShiftedPB + SA1Registers.PC); + S9xSA1UnpackStatus (); + S9xSA1FixCycles (); + SA1.VirtualBitmapFormat = (Memory.FillRAM [0x223f] & 0x80) ? 2 : 4; + Memory.BWRAM = Memory.SRAM + (Memory.FillRAM [0x2224] & 7) * 0x2000; + S9xSA1SetBWRAMMemMap (Memory.FillRAM [0x2225]); + + SA1.Waiting = (Memory.FillRAM [0x2200] & 0x60) != 0; + SA1.Executing = !SA1.Waiting; +} + +// SA9xSA1GetByte --- begin +static uint8 S9xSA1GetByte_default (uint32 address) { +#ifdef DEBUGGER +// printf ("R(B) %06x\n", address); +#endif + return (0); +} +static uint8 S9xSA1GetByte_PPU (uint32 address) { + return (S9xGetSA1 (address & 0xffff)); +} +static uint8 S9xSA1GetByte_SA1RAM (uint32 address) { + return (*(Memory.SRAM + (address & 0xffff))); +} +static uint8 S9xSA1GetByte_BWRAM (uint32 address) { + return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000))); +} +static uint8 S9xSA1GetByte_BWRAM_BITMAP (uint32 address) { + address -= 0x600000; + if (SA1.VirtualBitmapFormat == 2) + return ((Memory.SRAM [(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); + else + return ((Memory.SRAM [(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); +} +static uint8 S9xSA1GetByte_BWRAM_BITMAP2 (uint32 address) { + address = (address & 0xffff) - 0x6000; + if (SA1.VirtualBitmapFormat == 2) + return ((SA1.BWRAM [(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); + else + return ((SA1.BWRAM [(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); +} + +// GetByte JumpTable for Memmory map modes +uint8 (*S9xSA1GetByte_JumpTable[(1 << (16 - 12))]) (uint32 address) = { + S9xSA1GetByte_PPU, // MAP_PPU + S9xSA1GetByte_default, // MAP_CPU + S9xSA1GetByte_default, // MAP_DSP + S9xSA1GetByte_SA1RAM, // MAP_LOROM_SRAM + S9xSA1GetByte_default, // MAP_HIROM_SRAM + S9xSA1GetByte_default, // MAP_NONE + S9xSA1GetByte_default, // MAP_DEBUG + S9xSA1GetByte_default, // MAP_C4 + S9xSA1GetByte_BWRAM, // MAP_BWRAM + S9xSA1GetByte_BWRAM_BITMAP, // MAP_BWRAM_BITMAP + S9xSA1GetByte_BWRAM_BITMAP2, // MAP_BWRAM_BITMAP2 + S9xSA1GetByte_SA1RAM, // MAP_SA1RAM + S9xSA1GetByte_default, // MAP_LAST + S9xSA1GetByte_default, // MAP_LAST+1 + S9xSA1GetByte_default, // MAP_LAST+2 + S9xSA1GetByte_default // MAP_LAST+3 +}; + +uint8 S9xSA1GetByte (uint32 address) +{ + uint8 *GetAddress = SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; + if (GetAddress >= (uint8 *) MAP_LAST) return (*(GetAddress + (address & 0xffff))); + return S9xSA1GetByte_JumpTable[(intptr_t) GetAddress](address); +// return (SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK] >= (uint8 *)MAP_LAST) ? +// (*((uint8 *)(SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]) + (address & 0xffff))) : +// S9xSA1GetByte_JumpTable[(int) SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]](address); +} + +/* +uint16 S9xSA1GetWord (uint32 address) +{ + uint8 *GetAddress = SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; + if (GetAddress >= (uint8 *) MAP_LAST) + return (*(GetAddress + (address & 0xffff))) | ((*(GetAddress + ((address+1) & 0xffff))) << 8); + return (S9xSA1GetByte_JumpTable[(int) GetAddress](address)) | ((S9xSA1GetByte_JumpTable[(int) GetAddress](address+1)) << 8); +} +*/ +// SA9xSA1SetByte --- begin +static void S9xSA1SetByte_default (uint8 byte, uint32 address) { +} +static void S9xSA1SetByte_PPU (uint8 byte, uint32 address) { + S9xSetSA1 (byte, address & 0xffff); +} +static void S9xSA1SetByte_SA1RAM (uint8 byte, uint32 address) { + *(Memory.SRAM + (address & 0xffff)) = byte; +} +static void S9xSA1SetByte_BWRAM (uint8 byte, uint32 address) { + *(SA1.BWRAM + ((address & 0x7fff) - 0x6000)) = byte; +} +static void S9xSA1SetByte_BWRAM_BITMAP (uint8 byte, uint32 address) { + uint8 *ptr; + address -= 0x600000; + if (SA1.VirtualBitmapFormat == 2) { + ptr = &Memory.SRAM [(address >> 2) & 0xffff]; + *ptr &= ~(3 << ((address & 3) << 1)); + *ptr |= (byte & 3) << ((address & 3) << 1); + } else { + ptr = &Memory.SRAM [(address >> 1) & 0xffff]; + *ptr &= ~(15 << ((address & 1) << 2)); + *ptr |= (byte & 15) << ((address & 1) << 2); + } + address -= 0x600000; +} +static void S9xSA1SetByte_BWRAM_BITMAP2 (uint8 byte, uint32 address) { + uint8 *ptr; + address = (address & 0xffff) - 0x6000; + if (SA1.VirtualBitmapFormat == 2) + { + ptr = &SA1.BWRAM [(address >> 2) & 0xffff]; + *ptr &= ~(3 << ((address & 3) << 1)); + *ptr |= (byte & 3) << ((address & 3) << 1); + } + else + { + ptr = &SA1.BWRAM [(address >> 1) & 0xffff]; + *ptr &= ~(15 << ((address & 1) << 2)); + *ptr |= (byte & 15) << ((address & 1) << 2); + } +} + +// SetByte JumpTable for Memmory map modes +void (*S9xSA1SetByte_JumpTable[(1 << (16 - 12))]) (uint8 byte, uint32 address) = { + S9xSA1SetByte_PPU, // MAP_PPU + S9xSA1SetByte_default, // MAP_CPU + S9xSA1SetByte_default, // MAP_DSP + S9xSA1SetByte_SA1RAM, // MAP_LOROM_SRAM + S9xSA1SetByte_default, // MAP_HIROM_SRAM + S9xSA1SetByte_default, // MAP_NONE + S9xSA1SetByte_default, // MAP_DEBUG + S9xSA1SetByte_default, // MAP_C4 + S9xSA1SetByte_BWRAM, // MAP_BWRAM + S9xSA1SetByte_BWRAM_BITMAP, // MAP_BWRAM_BITMAP + S9xSA1SetByte_BWRAM_BITMAP2, // MAP_BWRAM_BITMAP2 + S9xSA1SetByte_SA1RAM, // MAP_SA1RAM + S9xSA1SetByte_default, // MAP_LAST + S9xSA1SetByte_default, // MAP_LAST+1 + S9xSA1SetByte_default, // MAP_LAST+2 + S9xSA1SetByte_default // MAP_LAST+3 +}; + +void S9xSA1SetByte (uint8 byte, uint32 address) +{ + // MEMMAP_SHIFT 12 + // MEMMAP_MASK 0xFFF + + uint8 *Setaddress = SA1_WriteMap [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; + if (Setaddress >= (uint8 *) MAP_LAST) + { + *(Setaddress + (address & 0xffff)) = byte; + return; + } + S9xSA1SetByte_JumpTable[(intptr_t)Setaddress](byte, address); +} + +void S9xSA1SetPCBase (uint32 address) +{ + uint8 *GetAddress = SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; + if (GetAddress >= (uint8 *) MAP_LAST) + { + SA1.PCBase = GetAddress; + SA1.PC = GetAddress + (address & 0xffff); + return; + } + + switch ((intptr_t) GetAddress) + { + case MAP_PPU: + SA1.PCBase = Memory.FillRAM - 0x2000; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + + case MAP_CPU: + SA1.PCBase = Memory.FillRAM - 0x4000; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + + case MAP_DSP: + SA1.PCBase = Memory.FillRAM - 0x6000; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + + case MAP_SA1RAM: + case MAP_LOROM_SRAM: + SA1.PCBase = Memory.SRAM; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + + case MAP_BWRAM: + SA1.PCBase = SA1.BWRAM - 0x6000; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + case MAP_HIROM_SRAM: + SA1.PCBase = Memory.SRAM - 0x6000; + SA1.PC = SA1.PCBase + (address & 0xffff); + return; + + case MAP_DEBUG: +#ifdef DEBUGGER + printf ("SBP %06x\n", address); +#endif + + default: + case MAP_NONE: + SA1.PCBase = Memory.RAM; + SA1.PC = Memory.RAM + (address & 0xffff); + return; + } +} + +void S9xSA1ExecuteDuringSleep () +{ +} + +void S9xSetSA1MemMap (uint32 which1, uint8 map) +{ + int c; + int start = which1 * 0x100 + 0xc00; + int start2 = which1 * 0x200; + uint8 *block; + int i; + + if (which1 >= 2) + start2 += 0x400; + + for (c = 0; c < 0x100; c += 16) + { + block = &Memory.ROM [(map & 7) * 0x100000 + (c << 12)]; + for (i = c; i < c + 16; i++) + Memory.Map [start + i] = SA1_Map [start + i] = block; + } + + for (c = 0; c < 0x200; c += 16) + { + block = &Memory.ROM [(map & 7) * 0x100000 + (c << 11) - 0x8000]; + for (i = c + 8; i < c + 16; i++) + Memory.Map [start2 + i] = SA1_Map [start2 + i] = block; + } +} + +uint8 S9xGetSA1 (uint32 address) +{ + if ((address < 0x2300) && (address > 0x230d)) return (Memory.FillRAM [address]); + switch (address) + { + case 0x2300: + return ((uint8) ((Memory.FillRAM [0x2209] & 0x5f) | + (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)))); + case 0x2301: + return ((Memory.FillRAM [0x2200] & 0xf) | + (Memory.FillRAM [0x2301] & 0xf0)); + case 0x2306: + return ((uint8) SA1.sum); + case 0x2307: + return ((uint8) (SA1.sum >> 8)); + case 0x2308: + return ((uint8) (SA1.sum >> 16)); + case 0x2309: + return ((uint8) (SA1.sum >> 24)); + case 0x230a: + return ((uint8) (SA1.sum >> 32)); + case 0x230b: + return (Memory.FillRAM [address]); + case 0x230c: + return (Memory.FillRAM [0x230c]); + case 0x230d: + { + uint8 byte = Memory.FillRAM [0x230d]; + + if (Memory.FillRAM [0x2258] & 0x80) + { + S9xSA1ReadVariableLengthData (TRUE, FALSE); + } + return (byte); + } + } + +} + +void S9xSetSA1 (uint8 byte, uint32 address) +{ + + if (address < 0x2200 || address > 0x22ff) return; + + switch (address) + { + case 0x2200: + SA1.Waiting = (byte & 0x60) != 0; + + if (!(byte & 0x20) && (Memory.FillRAM [0x2200] & 0x20)) + { + S9xSA1Reset (); + } + if (byte & 0x80) + { + Memory.FillRAM [0x2301] |= 0x80; + if (Memory.FillRAM [0x220a] & 0x80) + { + SA1.Flags |= IRQ_PENDING_FLAG; + SA1.IRQActive |= SNES_IRQ_SOURCE; + SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; + } + } + if (byte & 0x10) + { + Memory.FillRAM [0x2301] |= 0x10; + } + break; + + case 0x2201: + if (((byte ^ Memory.FillRAM [0x2201]) & 0x80) && + (Memory.FillRAM [0x2300] & byte & 0x80)) + { + S9xSetIRQ (SA1_IRQ_SOURCE); + } + if (((byte ^ Memory.FillRAM [0x2201]) & 0x20) && + (Memory.FillRAM [0x2300] & byte & 0x20)) + { + S9xSetIRQ (SA1_DMA_IRQ_SOURCE); + } + break; + case 0x2202: + if (byte & 0x80) + { + Memory.FillRAM [0x2300] &= ~0x80; + S9xClearIRQ (SA1_IRQ_SOURCE); + } + if (byte & 0x20) + { + Memory.FillRAM [0x2300] &= ~0x20; + S9xClearIRQ (SA1_DMA_IRQ_SOURCE); + } + break; + + case 0x2209: + Memory.FillRAM [0x2209] = byte; + if (byte & 0x80) + Memory.FillRAM [0x2300] |= 0x80; + + if (byte & Memory.FillRAM [0x2201] & 0x80) + { + S9xSetIRQ (SA1_IRQ_SOURCE); + } + return; + case 0x220a: + if (((byte ^ Memory.FillRAM [0x220a]) & 0x80) && + (Memory.FillRAM [0x2301] & byte & 0x80)) + { + SA1.Flags |= IRQ_PENDING_FLAG; + SA1.IRQActive |= SNES_IRQ_SOURCE; + } + if (((byte ^ Memory.FillRAM [0x220a]) & 0x40) && + (Memory.FillRAM [0x2301] & byte & 0x40)) + { + SA1.Flags |= IRQ_PENDING_FLAG; + SA1.IRQActive |= TIMER_IRQ_SOURCE; + } + if (((byte ^ Memory.FillRAM [0x220a]) & 0x20) && + (Memory.FillRAM [0x2301] & byte & 0x20)) + { + SA1.Flags |= IRQ_PENDING_FLAG; + SA1.IRQActive |= DMA_IRQ_SOURCE; + } + if (((byte ^ Memory.FillRAM [0x220a]) & 0x10) && + (Memory.FillRAM [0x2301] & byte & 0x10)) + { + } + break; + case 0x220b: + if (byte & 0x80) + { + SA1.IRQActive &= ~SNES_IRQ_SOURCE; + Memory.FillRAM [0x2301] &= ~0x80; + } + if (byte & 0x40) + { + SA1.IRQActive &= ~TIMER_IRQ_SOURCE; + Memory.FillRAM [0x2301] &= ~0x40; + } + if (byte & 0x20) + { + SA1.IRQActive &= ~DMA_IRQ_SOURCE; + Memory.FillRAM [0x2301] &= ~0x20; + } + if (byte & 0x10) + { + // Clear NMI + Memory.FillRAM [0x2301] &= ~0x10; + } + if (!SA1.IRQActive) + SA1.Flags &= ~IRQ_PENDING_FLAG; + break; + case 0x2220: + case 0x2221: + case 0x2222: + case 0x2223: + S9xSetSA1MemMap (address - 0x2220, byte); + break; + case 0x2224: + Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; + break; + case 0x2225: + if (byte != Memory.FillRAM [address]) + S9xSA1SetBWRAMMemMap (byte); + break; + case 0x2231: + if (byte & 0x80) + SA1.in_char_dma = FALSE; + break; + case 0x2236: + Memory.FillRAM [address] = byte; + if ((Memory.FillRAM [0x2230] & 0xa4) == 0x80) + { + // Normal DMA to I-RAM + S9xSA1DMA (); + } + else + if ((Memory.FillRAM [0x2230] & 0xb0) == 0xb0) + { + Memory.FillRAM [0x2300] |= 0x20; + if (Memory.FillRAM [0x2201] & 0x20) + S9xSetIRQ (SA1_DMA_IRQ_SOURCE); + SA1.in_char_dma = TRUE; + } + return; + case 0x2237: + Memory.FillRAM [address] = byte; + if ((Memory.FillRAM [0x2230] & 0xa4) == 0x84) + { + // Normal DMA to BW-RAM + S9xSA1DMA (); + } + return; + case 0x223f: + SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; + break; + + case 0x224f: + Memory.FillRAM [address] = byte; + if ((Memory.FillRAM [0x2230] & 0xb0) == 0xa0) + { + // Char conversion 2 DMA enabled + memmove (&Memory.ROM [MAX_ROM_SIZE - 0x10000] + (SA1.in_char_dma << 4), + &Memory.FillRAM [0x2240], 16); + SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; + if ((SA1.in_char_dma & 3) == 0) + { + S9xSA1CharConv2 (); + } + } + return; + case 0x2250: + if (byte & 2) + SA1.sum = 0; + SA1.arithmetic_op = byte & 3; + break; + + case 0x2251: + SA1.op1 = (SA1.op1 & 0xff00) | byte; + break; + case 0x2252: + SA1.op1 = (SA1.op1 & 0xff) | (byte << 8); + break; + case 0x2253: + SA1.op2 = (SA1.op2 & 0xff00) | byte; + break; + case 0x2254: + SA1.op2 = (SA1.op2 & 0xff) | (byte << 8); + switch (SA1.arithmetic_op) + { + case 0: // multiply + SA1.sum = SA1.op1 * SA1.op2; + break; + case 1: // divide + if (SA1.op2 == 0) + SA1.sum = SA1.op1 << 16; + else + { + unsigned int x = (SA1.op1 / (int) ((uint16) SA1.op2)); + SA1.sum = x | ((SA1.op1 - (x * (uint16) SA1.op2)) << 16); + // SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | + //((SA1.op1 % (int) ((uint16) SA1.op2)) << 16); + } + break; + default: // cumulative sum + SA1.sum += SA1.op1 * SA1.op2; + if (SA1.sum & ((int64) 0xffffff << 32)) + SA1.overflow = TRUE; + break; + } + break; + case 0x2258: // Variable bit-field length/auto inc/start. + Memory.FillRAM [0x2258] = byte; + S9xSA1ReadVariableLengthData (TRUE, FALSE); + return; + case 0x2259: + case 0x225a: + case 0x225b: // Variable bit-field start address + Memory.FillRAM [address] = byte; + // XXX: ??? + SA1.variable_bit_pos = 0; + S9xSA1ReadVariableLengthData (FALSE, TRUE); + return; + } + if (address >= 0x2200 && address <= 0x22ff) + Memory.FillRAM [address] = byte; +} + +static void S9xSA1CharConv2 () +{ + uint32 dest = Memory.FillRAM [0x2235] | (Memory.FillRAM [0x2236] << 8); + uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; + int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : + (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; + int bytes_per_char = 8 * depth; + uint8 *p = &Memory.FillRAM [0x3000] + dest + offset * bytes_per_char; + uint8 *q = &Memory.ROM [MAX_ROM_SIZE - 0x10000] + offset * 64; + + if (depth == 8) + { + for (int l = 0; l < 8; l++, q += 8) + { + for (int b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); + *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); + *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); + *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); + } + p += 2; + } + } +} + +static void S9xSA1DMA () +{ + uint32 src = Memory.FillRAM [0x2232] | + (Memory.FillRAM [0x2233] << 8) | + (Memory.FillRAM [0x2234] << 16); + uint32 dst = Memory.FillRAM [0x2235] | + (Memory.FillRAM [0x2236] << 8) | + (Memory.FillRAM [0x2237] << 16); + uint32 len = Memory.FillRAM [0x2238] | + (Memory.FillRAM [0x2239] << 8); + + uint8 *s; + uint8 *d; + + switch (Memory.FillRAM [0x2230] & 3) + { + case 0: // ROM + s = SA1_Map [(src >> MEMMAP_SHIFT) & MEMMAP_MASK]; + if (s >= (uint8 *) MAP_LAST) + s += (src & 0xffff); + else + s = Memory.ROM + (src & 0xffff); + break; + case 1: // BW-RAM + src &= CPU.Memory_SRAMMask; + len &= CPU.Memory_SRAMMask; + s = Memory.SRAM + src; + break; + default: + case 2: + src &= 0x3ff; + len &= 0x3ff; + s = &Memory.FillRAM [0x3000] + src; + break; + } + + if (Memory.FillRAM [0x2230] & 4) + { + dst &= CPU.Memory_SRAMMask; + len &= CPU.Memory_SRAMMask; + d = Memory.SRAM + dst; + } + else + { + dst &= 0x3ff; + len &= 0x3ff; + d = &Memory.FillRAM [0x3000] + dst; + } + memmove (d, s, len); + Memory.FillRAM [0x2301] |= 0x20; + + if (Memory.FillRAM [0x220a] & 0x20) + { + SA1.Flags |= IRQ_PENDING_FLAG; + SA1.IRQActive |= DMA_IRQ_SOURCE; + } +} + +void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift) +{ + uint32 addr = Memory.FillRAM [0x2259] | + (Memory.FillRAM [0x225a] << 8) | + (Memory.FillRAM [0x225b] << 16); + uint8 shift = Memory.FillRAM [0x2258] & 15; + + if (no_shift) + shift = 0; + else + if (shift == 0) + shift = 16; + + uint8 s = shift + SA1.variable_bit_pos; + + if (s >= 16) + { + addr += (s >> 4) << 1; + s &= 15; + } + uint32 data = S9xSA1GetWord (addr) | + (S9xSA1GetWord (addr + 2) << 16); + + data >>= s; + Memory.FillRAM [0x230c] = (uint8) data; + Memory.FillRAM [0x230d] = (uint8) (data >> 8); + if (inc) + { + SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15; + Memory.FillRAM [0x2259] = (uint8) addr; + Memory.FillRAM [0x225a] = (uint8) (addr >> 8); + Memory.FillRAM [0x225b] = (uint8) (addr >> 16); + } +} + +#endif // USE_SA1 diff --git a/src/sa1.cpp b/src/sa1.cpp deleted file mode 100644 index 73b1fa4..0000000 --- a/src/sa1.cpp +++ /dev/null @@ -1,775 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -#ifdef USE_SA1 - -#include "snes9x.h" -#include "ppu.h" -#include "cpuexec.h" - -#include "sa1.h" - -static void S9xSA1CharConv2 (); -static void S9xSA1DMA (); -static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift); - -void S9xSA1Init () -{ - SA1.NMIActive = FALSE; - SA1.IRQActive = FALSE; - SA1.WaitingForInterrupt = FALSE; - SA1.Waiting = FALSE; - SA1.Flags = 0; - SA1.Executing = FALSE; - memset (&Memory.FillRAM [0x2200], 0, 0x200); - Memory.FillRAM [0x2200] = 0x20; - Memory.FillRAM [0x2220] = 0x00; - Memory.FillRAM [0x2221] = 0x01; - Memory.FillRAM [0x2222] = 0x02; - Memory.FillRAM [0x2223] = 0x03; - Memory.FillRAM [0x2228] = 0xff; - SA1.op1 = 0; - SA1.op2 = 0; - SA1.arithmetic_op = 0; - SA1.sum = 0; - SA1.overflow = FALSE; -} - -void S9xSA1Reset () -{ - SA1Registers.PB = 0; - SA1Registers.PC = Memory.FillRAM [0x2203] | - (Memory.FillRAM [0x2204] << 8); - SA1Registers.D.W = 0; - SA1Registers.DB = 0; - SA1Registers.SH = 1; - SA1Registers.SL = 0xFF; - SA1Registers.XH = 0; - SA1Registers.YH = 0; - SA1Registers.P.W = 0; - - SA1.ShiftedPB = 0; - SA1.ShiftedDB = 0; - SA1SetFlags (MemoryFlag | IndexFlag | IRQ | Emulation); - SA1ClearFlags (Decimal); - - SA1.WaitingForInterrupt = FALSE; - SA1.PC = NULL; - SA1.PCBase = NULL; - S9xSA1SetPCBase (SA1Registers.PC); - SA1.S9xOpcodes = S9xSA1OpcodesM1X1; - - S9xSA1UnpackStatus(); - S9xSA1FixCycles (); - SA1.Executing = TRUE; - SA1.BWRAM = Memory.SRAM; - Memory.FillRAM [0x2225] = 0; -} - -void S9xSA1SetBWRAMMemMap (uint8 val) -{ - int c; - - if (val & 0x80) - { - for (c = 0; c < 0x400; c += 16) - { - SA1_Map [c + 6] = SA1_Map [c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - SA1_Map [c + 7] = SA1_Map [c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - SA1_WriteMap [c + 6] = SA1_WriteMap [c + 0x806] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - SA1_WriteMap [c + 7] = SA1_WriteMap [c + 0x807] = (uint8 *) CMemory::MAP_BWRAM_BITMAP2; - } - SA1.BWRAM = Memory.SRAM + (val & 0x7f) * 0x2000 / 4; - } - else - { - for (c = 0; c < 0x400; c += 16) - { - SA1_Map [c + 6] = SA1_Map [c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; - SA1_Map [c + 7] = SA1_Map [c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; - SA1_WriteMap [c + 6] = SA1_WriteMap [c + 0x806] = (uint8 *) CMemory::MAP_BWRAM; - SA1_WriteMap [c + 7] = SA1_WriteMap [c + 0x807] = (uint8 *) CMemory::MAP_BWRAM; - } - SA1.BWRAM = Memory.SRAM + (val & 7) * 0x2000; - } -} - -void S9xFixSA1AfterSnapshotLoad () -{ - SA1.ShiftedPB = (uint32) SA1Registers.PB << 16; - SA1.ShiftedDB = (uint32) SA1Registers.DB << 16; - - S9xSA1SetPCBase (SA1.ShiftedPB + SA1Registers.PC); - S9xSA1UnpackStatus (); - S9xSA1FixCycles (); - SA1.VirtualBitmapFormat = (Memory.FillRAM [0x223f] & 0x80) ? 2 : 4; - Memory.BWRAM = Memory.SRAM + (Memory.FillRAM [0x2224] & 7) * 0x2000; - S9xSA1SetBWRAMMemMap (Memory.FillRAM [0x2225]); - - SA1.Waiting = (Memory.FillRAM [0x2200] & 0x60) != 0; - SA1.Executing = !SA1.Waiting; -} - -// SA9xSA1GetByte --- begin -static uint8 S9xSA1GetByte_default (uint32 address) { -#ifdef DEBUGGER -// printf ("R(B) %06x\n", address); -#endif - return (0); -} -static uint8 S9xSA1GetByte_PPU (uint32 address) { - return (S9xGetSA1 (address & 0xffff)); -} -static uint8 S9xSA1GetByte_SA1RAM (uint32 address) { - return (*(Memory.SRAM + (address & 0xffff))); -} -static uint8 S9xSA1GetByte_BWRAM (uint32 address) { - return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000))); -} -static uint8 S9xSA1GetByte_BWRAM_BITMAP (uint32 address) { - address -= 0x600000; - if (SA1.VirtualBitmapFormat == 2) - return ((Memory.SRAM [(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); - else - return ((Memory.SRAM [(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); -} -static uint8 S9xSA1GetByte_BWRAM_BITMAP2 (uint32 address) { - address = (address & 0xffff) - 0x6000; - if (SA1.VirtualBitmapFormat == 2) - return ((SA1.BWRAM [(address >> 2) & 0xffff] >> ((address & 3) << 1)) & 3); - else - return ((SA1.BWRAM [(address >> 1) & 0xffff] >> ((address & 1) << 2)) & 15); -} - -// GetByte JumpTable for Memmory map modes -uint8 (*S9xSA1GetByte_JumpTable[(1 << (16 - 12))]) (uint32 address) = { - S9xSA1GetByte_PPU, // MAP_PPU - S9xSA1GetByte_default, // MAP_CPU - S9xSA1GetByte_default, // MAP_DSP - S9xSA1GetByte_SA1RAM, // MAP_LOROM_SRAM - S9xSA1GetByte_default, // MAP_HIROM_SRAM - S9xSA1GetByte_default, // MAP_NONE - S9xSA1GetByte_default, // MAP_DEBUG - S9xSA1GetByte_default, // MAP_C4 - S9xSA1GetByte_BWRAM, // MAP_BWRAM - S9xSA1GetByte_BWRAM_BITMAP, // MAP_BWRAM_BITMAP - S9xSA1GetByte_BWRAM_BITMAP2, // MAP_BWRAM_BITMAP2 - S9xSA1GetByte_SA1RAM, // MAP_SA1RAM - S9xSA1GetByte_default, // MAP_LAST - S9xSA1GetByte_default, // MAP_LAST+1 - S9xSA1GetByte_default, // MAP_LAST+2 - S9xSA1GetByte_default // MAP_LAST+3 -}; - -uint8 S9xSA1GetByte (uint32 address) -{ - uint8 *GetAddress = SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) return (*(GetAddress + (address & 0xffff))); - return S9xSA1GetByte_JumpTable[(intptr_t) GetAddress](address); -// return (SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK] >= (uint8 *)CMemory::MAP_LAST) ? -// (*((uint8 *)(SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]) + (address & 0xffff))) : -// S9xSA1GetByte_JumpTable[(int) SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]](address); -} - -/* -uint16 S9xSA1GetWord (uint32 address) -{ - uint8 *GetAddress = SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - return (*(GetAddress + (address & 0xffff))) | ((*(GetAddress + ((address+1) & 0xffff))) << 8); - return (S9xSA1GetByte_JumpTable[(int) GetAddress](address)) | ((S9xSA1GetByte_JumpTable[(int) GetAddress](address+1)) << 8); -} -*/ -// SA9xSA1SetByte --- begin -static void S9xSA1SetByte_default (uint8 byte, uint32 address) { -} -static void S9xSA1SetByte_PPU (uint8 byte, uint32 address) { - S9xSetSA1 (byte, address & 0xffff); -} -static void S9xSA1SetByte_SA1RAM (uint8 byte, uint32 address) { - *(Memory.SRAM + (address & 0xffff)) = byte; -} -static void S9xSA1SetByte_BWRAM (uint8 byte, uint32 address) { - *(SA1.BWRAM + ((address & 0x7fff) - 0x6000)) = byte; -} -static void S9xSA1SetByte_BWRAM_BITMAP (uint8 byte, uint32 address) { - uint8 *ptr; - address -= 0x600000; - if (SA1.VirtualBitmapFormat == 2) { - ptr = &Memory.SRAM [(address >> 2) & 0xffff]; - *ptr &= ~(3 << ((address & 3) << 1)); - *ptr |= (byte & 3) << ((address & 3) << 1); - } else { - ptr = &Memory.SRAM [(address >> 1) & 0xffff]; - *ptr &= ~(15 << ((address & 1) << 2)); - *ptr |= (byte & 15) << ((address & 1) << 2); - } - address -= 0x600000; -} -static void S9xSA1SetByte_BWRAM_BITMAP2 (uint8 byte, uint32 address) { - uint8 *ptr; - address = (address & 0xffff) - 0x6000; - if (SA1.VirtualBitmapFormat == 2) - { - ptr = &SA1.BWRAM [(address >> 2) & 0xffff]; - *ptr &= ~(3 << ((address & 3) << 1)); - *ptr |= (byte & 3) << ((address & 3) << 1); - } - else - { - ptr = &SA1.BWRAM [(address >> 1) & 0xffff]; - *ptr &= ~(15 << ((address & 1) << 2)); - *ptr |= (byte & 15) << ((address & 1) << 2); - } -} - -// SetByte JumpTable for Memmory map modes -void (*S9xSA1SetByte_JumpTable[(1 << (16 - 12))]) (uint8 byte, uint32 address) = { - S9xSA1SetByte_PPU, // MAP_PPU - S9xSA1SetByte_default, // MAP_CPU - S9xSA1SetByte_default, // MAP_DSP - S9xSA1SetByte_SA1RAM, // MAP_LOROM_SRAM - S9xSA1SetByte_default, // MAP_HIROM_SRAM - S9xSA1SetByte_default, // MAP_NONE - S9xSA1SetByte_default, // MAP_DEBUG - S9xSA1SetByte_default, // MAP_C4 - S9xSA1SetByte_BWRAM, // MAP_BWRAM - S9xSA1SetByte_BWRAM_BITMAP, // MAP_BWRAM_BITMAP - S9xSA1SetByte_BWRAM_BITMAP2, // MAP_BWRAM_BITMAP2 - S9xSA1SetByte_SA1RAM, // MAP_SA1RAM - S9xSA1SetByte_default, // MAP_LAST - S9xSA1SetByte_default, // MAP_LAST+1 - S9xSA1SetByte_default, // MAP_LAST+2 - S9xSA1SetByte_default // MAP_LAST+3 -}; - -void S9xSA1SetByte (uint8 byte, uint32 address) -{ - // MEMMAP_SHIFT 12 - // MEMMAP_MASK 0xFFF - - uint8 *Setaddress = SA1_WriteMap [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; - if (Setaddress >= (uint8 *) CMemory::MAP_LAST) - { - *(Setaddress + (address & 0xffff)) = byte; - return; - } - S9xSA1SetByte_JumpTable[(intptr_t)Setaddress](byte, address); -} - -void S9xSA1SetPCBase (uint32 address) -{ - uint8 *GetAddress = SA1_Map [(address >> MEMMAP_SHIFT) & MEMMAP_MASK]; - if (GetAddress >= (uint8 *) CMemory::MAP_LAST) - { - SA1.PCBase = GetAddress; - SA1.PC = GetAddress + (address & 0xffff); - return; - } - - switch ((intptr_t) GetAddress) - { - case CMemory::MAP_PPU: - SA1.PCBase = Memory.FillRAM - 0x2000; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - - case CMemory::MAP_CPU: - SA1.PCBase = Memory.FillRAM - 0x4000; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - - case CMemory::MAP_DSP: - SA1.PCBase = Memory.FillRAM - 0x6000; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - - case CMemory::MAP_SA1RAM: - case CMemory::MAP_LOROM_SRAM: - SA1.PCBase = Memory.SRAM; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - - case CMemory::MAP_BWRAM: - SA1.PCBase = SA1.BWRAM - 0x6000; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - case CMemory::MAP_HIROM_SRAM: - SA1.PCBase = Memory.SRAM - 0x6000; - SA1.PC = SA1.PCBase + (address & 0xffff); - return; - - case CMemory::MAP_DEBUG: -#ifdef DEBUGGER - printf ("SBP %06x\n", address); -#endif - - default: - case CMemory::MAP_NONE: - SA1.PCBase = Memory.RAM; - SA1.PC = Memory.RAM + (address & 0xffff); - return; - } -} - -void S9xSA1ExecuteDuringSleep () -{ -} - -void S9xSetSA1MemMap (uint32 which1, uint8 map) -{ - int c; - int start = which1 * 0x100 + 0xc00; - int start2 = which1 * 0x200; - uint8 *block; - int i; - - if (which1 >= 2) - start2 += 0x400; - - for (c = 0; c < 0x100; c += 16) - { - block = &Memory.ROM [(map & 7) * 0x100000 + (c << 12)]; - for (i = c; i < c + 16; i++) - Memory.Map [start + i] = SA1_Map [start + i] = block; - } - - for (c = 0; c < 0x200; c += 16) - { - block = &Memory.ROM [(map & 7) * 0x100000 + (c << 11) - 0x8000]; - for (i = c + 8; i < c + 16; i++) - Memory.Map [start2 + i] = SA1_Map [start2 + i] = block; - } -} - -uint8 S9xGetSA1 (uint32 address) -{ - if ((address < 0x2300) && (address > 0x230d)) return (Memory.FillRAM [address]); - switch (address) - { - case 0x2300: - return ((uint8) ((Memory.FillRAM [0x2209] & 0x5f) | - (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE)))); - case 0x2301: - return ((Memory.FillRAM [0x2200] & 0xf) | - (Memory.FillRAM [0x2301] & 0xf0)); - case 0x2306: - return ((uint8) SA1.sum); - case 0x2307: - return ((uint8) (SA1.sum >> 8)); - case 0x2308: - return ((uint8) (SA1.sum >> 16)); - case 0x2309: - return ((uint8) (SA1.sum >> 24)); - case 0x230a: - return ((uint8) (SA1.sum >> 32)); - case 0x230b: - return (Memory.FillRAM [address]); - case 0x230c: - return (Memory.FillRAM [0x230c]); - case 0x230d: - { - uint8 byte = Memory.FillRAM [0x230d]; - - if (Memory.FillRAM [0x2258] & 0x80) - { - S9xSA1ReadVariableLengthData (TRUE, FALSE); - } - return (byte); - } - } - -} - -void S9xSetSA1 (uint8 byte, uint32 address) -{ - - if (address < 0x2200 || address > 0x22ff) return; - - switch (address) - { - case 0x2200: - SA1.Waiting = (byte & 0x60) != 0; - - if (!(byte & 0x20) && (Memory.FillRAM [0x2200] & 0x20)) - { - S9xSA1Reset (); - } - if (byte & 0x80) - { - Memory.FillRAM [0x2301] |= 0x80; - if (Memory.FillRAM [0x220a] & 0x80) - { - SA1.Flags |= IRQ_PENDING_FLAG; - SA1.IRQActive |= SNES_IRQ_SOURCE; - SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; - } - } - if (byte & 0x10) - { - Memory.FillRAM [0x2301] |= 0x10; - } - break; - - case 0x2201: - if (((byte ^ Memory.FillRAM [0x2201]) & 0x80) && - (Memory.FillRAM [0x2300] & byte & 0x80)) - { - S9xSetIRQ (SA1_IRQ_SOURCE); - } - if (((byte ^ Memory.FillRAM [0x2201]) & 0x20) && - (Memory.FillRAM [0x2300] & byte & 0x20)) - { - S9xSetIRQ (SA1_DMA_IRQ_SOURCE); - } - break; - case 0x2202: - if (byte & 0x80) - { - Memory.FillRAM [0x2300] &= ~0x80; - S9xClearIRQ (SA1_IRQ_SOURCE); - } - if (byte & 0x20) - { - Memory.FillRAM [0x2300] &= ~0x20; - S9xClearIRQ (SA1_DMA_IRQ_SOURCE); - } - break; - - case 0x2209: - Memory.FillRAM [0x2209] = byte; - if (byte & 0x80) - Memory.FillRAM [0x2300] |= 0x80; - - if (byte & Memory.FillRAM [0x2201] & 0x80) - { - S9xSetIRQ (SA1_IRQ_SOURCE); - } - return; - case 0x220a: - if (((byte ^ Memory.FillRAM [0x220a]) & 0x80) && - (Memory.FillRAM [0x2301] & byte & 0x80)) - { - SA1.Flags |= IRQ_PENDING_FLAG; - SA1.IRQActive |= SNES_IRQ_SOURCE; - } - if (((byte ^ Memory.FillRAM [0x220a]) & 0x40) && - (Memory.FillRAM [0x2301] & byte & 0x40)) - { - SA1.Flags |= IRQ_PENDING_FLAG; - SA1.IRQActive |= TIMER_IRQ_SOURCE; - } - if (((byte ^ Memory.FillRAM [0x220a]) & 0x20) && - (Memory.FillRAM [0x2301] & byte & 0x20)) - { - SA1.Flags |= IRQ_PENDING_FLAG; - SA1.IRQActive |= DMA_IRQ_SOURCE; - } - if (((byte ^ Memory.FillRAM [0x220a]) & 0x10) && - (Memory.FillRAM [0x2301] & byte & 0x10)) - { - } - break; - case 0x220b: - if (byte & 0x80) - { - SA1.IRQActive &= ~SNES_IRQ_SOURCE; - Memory.FillRAM [0x2301] &= ~0x80; - } - if (byte & 0x40) - { - SA1.IRQActive &= ~TIMER_IRQ_SOURCE; - Memory.FillRAM [0x2301] &= ~0x40; - } - if (byte & 0x20) - { - SA1.IRQActive &= ~DMA_IRQ_SOURCE; - Memory.FillRAM [0x2301] &= ~0x20; - } - if (byte & 0x10) - { - // Clear NMI - Memory.FillRAM [0x2301] &= ~0x10; - } - if (!SA1.IRQActive) - SA1.Flags &= ~IRQ_PENDING_FLAG; - break; - case 0x2220: - case 0x2221: - case 0x2222: - case 0x2223: - S9xSetSA1MemMap (address - 0x2220, byte); - break; - case 0x2224: - Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; - break; - case 0x2225: - if (byte != Memory.FillRAM [address]) - S9xSA1SetBWRAMMemMap (byte); - break; - case 0x2231: - if (byte & 0x80) - SA1.in_char_dma = FALSE; - break; - case 0x2236: - Memory.FillRAM [address] = byte; - if ((Memory.FillRAM [0x2230] & 0xa4) == 0x80) - { - // Normal DMA to I-RAM - S9xSA1DMA (); - } - else - if ((Memory.FillRAM [0x2230] & 0xb0) == 0xb0) - { - Memory.FillRAM [0x2300] |= 0x20; - if (Memory.FillRAM [0x2201] & 0x20) - S9xSetIRQ (SA1_DMA_IRQ_SOURCE); - SA1.in_char_dma = TRUE; - } - return; - case 0x2237: - Memory.FillRAM [address] = byte; - if ((Memory.FillRAM [0x2230] & 0xa4) == 0x84) - { - // Normal DMA to BW-RAM - S9xSA1DMA (); - } - return; - case 0x223f: - SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; - break; - - case 0x224f: - Memory.FillRAM [address] = byte; - if ((Memory.FillRAM [0x2230] & 0xb0) == 0xa0) - { - // Char conversion 2 DMA enabled - memmove (&Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + (SA1.in_char_dma << 4), - &Memory.FillRAM [0x2240], 16); - SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; - if ((SA1.in_char_dma & 3) == 0) - { - S9xSA1CharConv2 (); - } - } - return; - case 0x2250: - if (byte & 2) - SA1.sum = 0; - SA1.arithmetic_op = byte & 3; - break; - - case 0x2251: - SA1.op1 = (SA1.op1 & 0xff00) | byte; - break; - case 0x2252: - SA1.op1 = (SA1.op1 & 0xff) | (byte << 8); - break; - case 0x2253: - SA1.op2 = (SA1.op2 & 0xff00) | byte; - break; - case 0x2254: - SA1.op2 = (SA1.op2 & 0xff) | (byte << 8); - switch (SA1.arithmetic_op) - { - case 0: // multiply - SA1.sum = SA1.op1 * SA1.op2; - break; - case 1: // divide - if (SA1.op2 == 0) - SA1.sum = SA1.op1 << 16; - else - { - unsigned int x = (SA1.op1 / (int) ((uint16) SA1.op2)); - SA1.sum = x | ((SA1.op1 - (x * (uint16) SA1.op2)) << 16); - // SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | - //((SA1.op1 % (int) ((uint16) SA1.op2)) << 16); - } - break; - default: // cumulative sum - SA1.sum += SA1.op1 * SA1.op2; - if (SA1.sum & ((int64) 0xffffff << 32)) - SA1.overflow = TRUE; - break; - } - break; - case 0x2258: // Variable bit-field length/auto inc/start. - Memory.FillRAM [0x2258] = byte; - S9xSA1ReadVariableLengthData (TRUE, FALSE); - return; - case 0x2259: - case 0x225a: - case 0x225b: // Variable bit-field start address - Memory.FillRAM [address] = byte; - // XXX: ??? - SA1.variable_bit_pos = 0; - S9xSA1ReadVariableLengthData (FALSE, TRUE); - return; - } - if (address >= 0x2200 && address <= 0x22ff) - Memory.FillRAM [address] = byte; -} - -static void S9xSA1CharConv2 () -{ - uint32 dest = Memory.FillRAM [0x2235] | (Memory.FillRAM [0x2236] << 8); - uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; - int depth = (Memory.FillRAM [0x2231] & 3) == 0 ? 8 : - (Memory.FillRAM [0x2231] & 3) == 1 ? 4 : 2; - int bytes_per_char = 8 * depth; - uint8 *p = &Memory.FillRAM [0x3000] + dest + offset * bytes_per_char; - uint8 *q = &Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64; - - if (depth == 8) - { - for (int l = 0; l < 8; l++, q += 8) - { - for (int b = 0; b < 8; b++) - { - uint8 r = *(q + b); - *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); - *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); - *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); - *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); - *(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1); - *(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1); - *(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1); - *(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1); - } - p += 2; - } - } -} - -static void S9xSA1DMA () -{ - uint32 src = Memory.FillRAM [0x2232] | - (Memory.FillRAM [0x2233] << 8) | - (Memory.FillRAM [0x2234] << 16); - uint32 dst = Memory.FillRAM [0x2235] | - (Memory.FillRAM [0x2236] << 8) | - (Memory.FillRAM [0x2237] << 16); - uint32 len = Memory.FillRAM [0x2238] | - (Memory.FillRAM [0x2239] << 8); - - uint8 *s; - uint8 *d; - - switch (Memory.FillRAM [0x2230] & 3) - { - case 0: // ROM - s = SA1_Map [(src >> MEMMAP_SHIFT) & MEMMAP_MASK]; - if (s >= (uint8 *) CMemory::MAP_LAST) - s += (src & 0xffff); - else - s = Memory.ROM + (src & 0xffff); - break; - case 1: // BW-RAM - src &= CPU.Memory_SRAMMask; - len &= CPU.Memory_SRAMMask; - s = Memory.SRAM + src; - break; - default: - case 2: - src &= 0x3ff; - len &= 0x3ff; - s = &Memory.FillRAM [0x3000] + src; - break; - } - - if (Memory.FillRAM [0x2230] & 4) - { - dst &= CPU.Memory_SRAMMask; - len &= CPU.Memory_SRAMMask; - d = Memory.SRAM + dst; - } - else - { - dst &= 0x3ff; - len &= 0x3ff; - d = &Memory.FillRAM [0x3000] + dst; - } - memmove (d, s, len); - Memory.FillRAM [0x2301] |= 0x20; - - if (Memory.FillRAM [0x220a] & 0x20) - { - SA1.Flags |= IRQ_PENDING_FLAG; - SA1.IRQActive |= DMA_IRQ_SOURCE; - } -} - -void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift) -{ - uint32 addr = Memory.FillRAM [0x2259] | - (Memory.FillRAM [0x225a] << 8) | - (Memory.FillRAM [0x225b] << 16); - uint8 shift = Memory.FillRAM [0x2258] & 15; - - if (no_shift) - shift = 0; - else - if (shift == 0) - shift = 16; - - uint8 s = shift + SA1.variable_bit_pos; - - if (s >= 16) - { - addr += (s >> 4) << 1; - s &= 15; - } - uint32 data = S9xSA1GetWord (addr) | - (S9xSA1GetWord (addr + 2) << 16); - - data >>= s; - Memory.FillRAM [0x230c] = (uint8) data; - Memory.FillRAM [0x230d] = (uint8) (data >> 8); - if (inc) - { - SA1.variable_bit_pos = (SA1.variable_bit_pos + shift) & 15; - Memory.FillRAM [0x2259] = (uint8) addr; - Memory.FillRAM [0x225a] = (uint8) (addr >> 8); - Memory.FillRAM [0x225b] = (uint8) (addr >> 16); - } -} - -#endif // USE_SA1 diff --git a/src/sa1.h b/src/sa1.h index 3a297f5..fdcbf67 100644 --- a/src/sa1.h +++ b/src/sa1.h @@ -46,8 +46,10 @@ #define _sa1_h_ #include "memmap.h" +#include "cpuexec.h" -struct SSA1Registers { +typedef struct +{ uint8 PB; uint8 DB; pair P; @@ -57,10 +59,11 @@ struct SSA1Registers { pair X; pair Y; uint16 PC; -}; +}SSA1Registers ; -struct SSA1 { - struct SOpcodes *S9xOpcodes; +typedef struct +{ + SOpcodes *S9xOpcodes; uint8 _Carry; uint8 _Zero; uint8 _Negative; @@ -95,10 +98,10 @@ struct SSA1 { uint8 VirtualBitmapFormat; bool8 in_char_dma; uint8 variable_bit_pos; -}; +}SSA1; -extern struct SSA1Registers SA1Registers; -extern struct SSA1 SA1; +extern SSA1Registers SA1Registers; +extern SSA1 SA1; extern uint8 *SA1_Map [MEMMAP_NUM_BLOCKS]; extern uint8 *SA1_WriteMap [MEMMAP_NUM_BLOCKS]; @@ -120,7 +123,6 @@ extern uint8 *SA1_WriteMap [MEMMAP_NUM_BLOCKS]; #define SA1SetFlags(f) (SA1Registers.P.W |= (f)) #define SA1CheckFlag(f) (SA1Registers.PL & (f)) - START_EXTERN_C uint8 S9xSA1GetByte (uint32); //uint16 S9xSA1GetWord (uint32); @@ -132,10 +134,10 @@ void S9xSA1SetPCBase (uint32); uint8 S9xGetSA1 (uint32); void S9xSetSA1 (uint8, uint32); -extern struct SOpcodes S9xSA1OpcodesM1X1 [256]; -extern struct SOpcodes S9xSA1OpcodesM1X0 [256]; -extern struct SOpcodes S9xSA1OpcodesM0X1 [256]; -extern struct SOpcodes S9xSA1OpcodesM0X0 [256]; +extern SOpcodes S9xSA1OpcodesM1X1 [256]; +extern SOpcodes S9xSA1OpcodesM1X0 [256]; +extern SOpcodes S9xSA1OpcodesM0X1 [256]; +extern SOpcodes S9xSA1OpcodesM0X0 [256]; void S9xSA1MainLoop (); void S9xSA1Init (); diff --git a/src/sa1cpu.c b/src/sa1cpu.c new file mode 100644 index 0000000..eddccfb --- /dev/null +++ b/src/sa1cpu.c @@ -0,0 +1,125 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +#ifdef USE_SA1 + +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "cpuexec.h" + +#include "sa1.h" +#define CPU SA1 +#define ICPU SA1 + +#undef Registers + +#define Registers SA1Registers +#define S9xGetByte S9xSA1GetByte +#define S9xGetWord S9xSA1GetWord +#define S9xSetByte S9xSA1SetByte +#define S9xSetWord S9xSA1SetWord +#define S9xSetPCBase S9xSA1SetPCBase +#define S9xOpcodesM1X1 S9xSA1OpcodesM1X1 +#define S9xOpcodesM1X0 S9xSA1OpcodesM1X0 +#define S9xOpcodesM0X1 S9xSA1OpcodesM0X1 +#define S9xOpcodesM0X0 S9xSA1OpcodesM0X0 +#define S9xOpcode_IRQ S9xSA1Opcode_IRQ +#define S9xOpcode_NMI S9xSA1Opcode_NMI +#define S9xUnpackStatus S9xSA1UnpackStatus +#define S9xPackStatus S9xSA1PackStatus +#define S9xFixCycles S9xSA1FixCycles +#define Immediate8 SA1Immediate8 +#define Immediate16 SA1Immediate16 +#define Relative SA1Relative +#define RelativeLong SA1RelativeLong +#define AbsoluteIndexedIndirect SA1AbsoluteIndexedIndirect +#define AbsoluteIndirectLong SA1AbsoluteIndirectLong +#define AbsoluteIndirect SA1AbsoluteIndirect +#define Absolute SA1Absolute +#define AbsoluteLong SA1AbsoluteLong +#define Direct SA1Direct +#define DirectIndirectIndexed SA1DirectIndirectIndexed +#define DirectIndirectIndexedLong SA1DirectIndirectIndexedLong +#define DirectIndexedIndirect SA1DirectIndexedIndirect +#define DirectIndexedX SA1DirectIndexedX +#define DirectIndexedY SA1DirectIndexedY +#define AbsoluteIndexedX SA1AbsoluteIndexedX +#define AbsoluteIndexedY SA1AbsoluteIndexedY +#define AbsoluteLongIndexedX SA1AbsoluteLongIndexedX +#define DirectIndirect SA1DirectIndirect +#define DirectIndirectLong SA1DirectIndirectLong +#define StackRelative SA1StackRelative +#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed + +//#undef CPU_SHUTDOWN +#undef VAR_CYCLES +#define SA1_OPCODES + +#include "cpuops.c" + +void S9xSA1MainLoop () +{ + int i; + + if (SA1.Flags & IRQ_PENDING_FLAG) + { + if (SA1.IRQActive) + { + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1.PC++; + } + if (!SA1CheckFlag (IRQ)) + S9xSA1Opcode_IRQ (); + } + else + SA1.Flags &= ~IRQ_PENDING_FLAG; + } + + for (i = 0; i < 3 && SA1.Executing; i++) + { + (*SA1.S9xOpcodes [*SA1.PC++].S9xOpcode) (); + } +} + +#endif // USE_SA1 diff --git a/src/sa1cpu.cpp b/src/sa1cpu.cpp deleted file mode 100644 index 0e571cb..0000000 --- a/src/sa1cpu.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -#ifdef USE_SA1 - -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "cpuexec.h" - -#include "sa1.h" -#define CPU SA1 -#define ICPU SA1 - -#undef Registers - -#define Registers SA1Registers -#define S9xGetByte S9xSA1GetByte -#define S9xGetWord S9xSA1GetWord -#define S9xSetByte S9xSA1SetByte -#define S9xSetWord S9xSA1SetWord -#define S9xSetPCBase S9xSA1SetPCBase -#define S9xOpcodesM1X1 S9xSA1OpcodesM1X1 -#define S9xOpcodesM1X0 S9xSA1OpcodesM1X0 -#define S9xOpcodesM0X1 S9xSA1OpcodesM0X1 -#define S9xOpcodesM0X0 S9xSA1OpcodesM0X0 -#define S9xOpcode_IRQ S9xSA1Opcode_IRQ -#define S9xOpcode_NMI S9xSA1Opcode_NMI -#define S9xUnpackStatus S9xSA1UnpackStatus -#define S9xPackStatus S9xSA1PackStatus -#define S9xFixCycles S9xSA1FixCycles -#define Immediate8 SA1Immediate8 -#define Immediate16 SA1Immediate16 -#define Relative SA1Relative -#define RelativeLong SA1RelativeLong -#define AbsoluteIndexedIndirect SA1AbsoluteIndexedIndirect -#define AbsoluteIndirectLong SA1AbsoluteIndirectLong -#define AbsoluteIndirect SA1AbsoluteIndirect -#define Absolute SA1Absolute -#define AbsoluteLong SA1AbsoluteLong -#define Direct SA1Direct -#define DirectIndirectIndexed SA1DirectIndirectIndexed -#define DirectIndirectIndexedLong SA1DirectIndirectIndexedLong -#define DirectIndexedIndirect SA1DirectIndexedIndirect -#define DirectIndexedX SA1DirectIndexedX -#define DirectIndexedY SA1DirectIndexedY -#define AbsoluteIndexedX SA1AbsoluteIndexedX -#define AbsoluteIndexedY SA1AbsoluteIndexedY -#define AbsoluteLongIndexedX SA1AbsoluteLongIndexedX -#define DirectIndirect SA1DirectIndirect -#define DirectIndirectLong SA1DirectIndirectLong -#define StackRelative SA1StackRelative -#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed - -//#undef CPU_SHUTDOWN -#undef VAR_CYCLES -#define SA1_OPCODES - -#include "cpuops.cpp" - -void S9xSA1MainLoop () -{ - int i; - - if (SA1.Flags & IRQ_PENDING_FLAG) - { - if (SA1.IRQActive) - { - if (SA1.WaitingForInterrupt) - { - SA1.WaitingForInterrupt = FALSE; - SA1.PC++; - } - if (!SA1CheckFlag (IRQ)) - S9xSA1Opcode_IRQ (); - } - else - SA1.Flags &= ~IRQ_PENDING_FLAG; - } - - for (i = 0; i < 3 && SA1.Executing; i++) - { - (*SA1.S9xOpcodes [*SA1.PC++].S9xOpcode) (); - } -} - -#endif // USE_SA1 diff --git a/src/sar.h b/src/sar.h index 1c62aa0..390114b 100644 --- a/src/sar.h +++ b/src/sar.h @@ -96,31 +96,34 @@ typedef int int32; #endif #ifdef RIGHTSHIFT_IS_SAR -#define SAR(b, n) ((b)>>(n)) +#define SAR8(b, n) ((b)>>(n)) +#define SAR16(b, n) ((b)>>(n)) +#define SAR32(b, n) ((b)>>(n)) +#define SAR64(b, n) ((b)>>(n)) #else -static inline int8 SAR(const int8 b, const int n){ +static inline int8 SAR8(const int8 b, const int n){ #ifndef RIGHTSHIFT_INT8_IS_SAR if(b<0) return (b>>n)|(-1<<(8-n)); #endif return b>>n; } -static inline int16 SAR(const int16 b, const int n){ +static inline int16 SAR16(const int16 b, const int n){ #ifndef RIGHTSHIFT_INT16_IS_SAR if(b<0) return (b>>n)|(-1<<(16-n)); #endif return b>>n; } -static inline int32 SAR(const int32 b, const int n){ +static inline int32 SAR32(const int32 b, const int n){ #ifndef RIGHTSHIFT_INT32_IS_SAR if(b<0) return (b>>n)|(-1<<(32-n)); #endif return b>>n; } -static inline int64 SAR(const int64 b, const int n){ +static inline int64 SAR64(const int64 b, const int n){ #ifndef RIGHTSHIFT_INT64_IS_SAR if(b<0) return (b>>n)|(-1<<(64-n)); #endif diff --git a/src/sdd1.c b/src/sdd1.c new file mode 100644 index 0000000..878bf4c --- /dev/null +++ b/src/sdd1.c @@ -0,0 +1,131 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "sdd1.h" +#include "display.h" + +#ifdef __linux +//#include +#endif + +void S9xSetSDD1MemoryMap (uint32 bank, uint32 value) +{ + bank = 0xc00 + bank * 0x100; + value = value * 1024 * 1024; + + int c; + + for (c = 0; c < 0x100; c += 16) + { + uint8 *block = &Memory.ROM [value + (c << 12)]; + int i; + + for (i = c; i < c + 16; i++) + Memory.Map [i + bank] = block; + } +} + +void S9xResetSDD1 () +{ + memset (&Memory.FillRAM [0x4800], 0, 4); + for (int i = 0; i < 4; i++) + { + Memory.FillRAM [0x4804 + i] = i; + S9xSetSDD1MemoryMap (i, i); + } +} + +void S9xSDD1PostLoadState () +{ + for (int i = 0; i < 4; i++) + S9xSetSDD1MemoryMap (i, Memory.FillRAM [0x4804 + i]); +} + +static int S9xCompareSDD1LoggedDataEntries (const void *p1, const void *p2) +{ + uint8 *b1 = (uint8 *) p1; + uint8 *b2 = (uint8 *) p2; + uint32 a1 = (*b1 << 16) + (*(b1 + 1) << 8) + *(b1 + 2); + uint32 a2 = (*b2 << 16) + (*(b2 + 1) << 8) + *(b2 + 2); + + return (a1 - a2); +} + +void S9xSDD1SaveLoggedData () +{ + if (Memory.SDD1LoggedDataCount != Memory.SDD1LoggedDataCountPrev) + { + qsort (Memory.SDD1LoggedData, Memory.SDD1LoggedDataCount, 8, + S9xCompareSDD1LoggedDataEntries); + + FILE *fs = fopen (S9xGetFilename (".dat"), "wb"); + + if (fs) + { + fwrite (Memory.SDD1LoggedData, 8, + Memory.SDD1LoggedDataCount, fs); + fclose (fs); +#if defined(__linux) + //chown (S9xGetFilename (".dat"), getuid (), getgid ()); +#endif + } + Memory.SDD1LoggedDataCountPrev = Memory.SDD1LoggedDataCount; + } +} + +void S9xSDD1LoadLoggedData () +{ + FILE *fs = fopen (S9xGetFilename (".dat"), "rb"); + + Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = 0; + + if (fs) + { + int c = fread (Memory.SDD1LoggedData, 8, + MEMMAP_MAX_SDD1_LOGGED_ENTRIES, fs); + + if (c != EOF) + Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = c; + fclose (fs); + } +} diff --git a/src/sdd1.cpp b/src/sdd1.cpp deleted file mode 100644 index 878bf4c..0000000 --- a/src/sdd1.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include "snes9x.h" -#include "memmap.h" -#include "ppu.h" -#include "sdd1.h" -#include "display.h" - -#ifdef __linux -//#include -#endif - -void S9xSetSDD1MemoryMap (uint32 bank, uint32 value) -{ - bank = 0xc00 + bank * 0x100; - value = value * 1024 * 1024; - - int c; - - for (c = 0; c < 0x100; c += 16) - { - uint8 *block = &Memory.ROM [value + (c << 12)]; - int i; - - for (i = c; i < c + 16; i++) - Memory.Map [i + bank] = block; - } -} - -void S9xResetSDD1 () -{ - memset (&Memory.FillRAM [0x4800], 0, 4); - for (int i = 0; i < 4; i++) - { - Memory.FillRAM [0x4804 + i] = i; - S9xSetSDD1MemoryMap (i, i); - } -} - -void S9xSDD1PostLoadState () -{ - for (int i = 0; i < 4; i++) - S9xSetSDD1MemoryMap (i, Memory.FillRAM [0x4804 + i]); -} - -static int S9xCompareSDD1LoggedDataEntries (const void *p1, const void *p2) -{ - uint8 *b1 = (uint8 *) p1; - uint8 *b2 = (uint8 *) p2; - uint32 a1 = (*b1 << 16) + (*(b1 + 1) << 8) + *(b1 + 2); - uint32 a2 = (*b2 << 16) + (*(b2 + 1) << 8) + *(b2 + 2); - - return (a1 - a2); -} - -void S9xSDD1SaveLoggedData () -{ - if (Memory.SDD1LoggedDataCount != Memory.SDD1LoggedDataCountPrev) - { - qsort (Memory.SDD1LoggedData, Memory.SDD1LoggedDataCount, 8, - S9xCompareSDD1LoggedDataEntries); - - FILE *fs = fopen (S9xGetFilename (".dat"), "wb"); - - if (fs) - { - fwrite (Memory.SDD1LoggedData, 8, - Memory.SDD1LoggedDataCount, fs); - fclose (fs); -#if defined(__linux) - //chown (S9xGetFilename (".dat"), getuid (), getgid ()); -#endif - } - Memory.SDD1LoggedDataCountPrev = Memory.SDD1LoggedDataCount; - } -} - -void S9xSDD1LoadLoggedData () -{ - FILE *fs = fopen (S9xGetFilename (".dat"), "rb"); - - Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = 0; - - if (fs) - { - int c = fread (Memory.SDD1LoggedData, 8, - MEMMAP_MAX_SDD1_LOGGED_ENTRIES, fs); - - if (c != EOF) - Memory.SDD1LoggedDataCount = Memory.SDD1LoggedDataCountPrev = c; - fclose (fs); - } -} diff --git a/src/sdd1emu.c b/src/sdd1emu.c new file mode 100644 index 0000000..3f97ee2 --- /dev/null +++ b/src/sdd1emu.c @@ -0,0 +1,414 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and distribute Snes9x in both binary and + source form, for non-commercial purposes, is hereby granted without fee, + providing that this license information and copyright notice appear with + all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes + charging money for Snes9x or software derived from Snes9x. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +*******************************************************************************/ +/* S-DD1 decompressor + * + * Based on code and documentation by Andreas Naive, who deserves a great deal + * of thanks and credit for figuring this out. + * + * Andreas says: + * The author is greatly indebted with The Dumper, without whose help and + * patience providing him with real S-DD1 data the research had never been + * possible. He also wish to note that in the very beggining of his research, + * Neviksti had done some steps in the right direction. By last, the author is + * indirectly indebted to all the people that worked and contributed in the + * S-DD1 issue in the past. + */ + +#include +#include "port.h" +#include "sdd1emu.h" + +static int valid_bits; +static uint16 in_stream; +static uint8 *in_buf; +static uint8 bit_ctr[8]; +static uint8 context_states[32]; +static int context_MPS[32]; +static int bitplane_type; +static int high_context_bits; +static int low_context_bits; +static int prev_bits[8]; + +static struct { + uint8 code_size; + uint8 MPS_next; + uint8 LPS_next; +} evolution_table[] = { + /* 0 */ { 0,25,25}, + /* 1 */ { 0, 2, 1}, + /* 2 */ { 0, 3, 1}, + /* 3 */ { 0, 4, 2}, + /* 4 */ { 0, 5, 3}, + /* 5 */ { 1, 6, 4}, + /* 6 */ { 1, 7, 5}, + /* 7 */ { 1, 8, 6}, + /* 8 */ { 1, 9, 7}, + /* 9 */ { 2,10, 8}, + /* 10 */ { 2,11, 9}, + /* 11 */ { 2,12,10}, + /* 12 */ { 2,13,11}, + /* 13 */ { 3,14,12}, + /* 14 */ { 3,15,13}, + /* 15 */ { 3,16,14}, + /* 16 */ { 3,17,15}, + /* 17 */ { 4,18,16}, + /* 18 */ { 4,19,17}, + /* 19 */ { 5,20,18}, + /* 20 */ { 5,21,19}, + /* 21 */ { 6,22,20}, + /* 22 */ { 6,23,21}, + /* 23 */ { 7,24,22}, + /* 24 */ { 7,24,23}, + /* 25 */ { 0,26, 1}, + /* 26 */ { 1,27, 2}, + /* 27 */ { 2,28, 4}, + /* 28 */ { 3,29, 8}, + /* 29 */ { 4,30,12}, + /* 30 */ { 5,31,16}, + /* 31 */ { 6,32,18}, + /* 32 */ { 7,24,22} +}; + +static uint8 run_table[128] = { + 128, 64, 96, 32, 112, 48, 80, 16, 120, 56, 88, 24, 104, 40, 72, + 8, 124, 60, 92, 28, 108, 44, 76, 12, 116, 52, 84, 20, 100, 36, + 68, 4, 126, 62, 94, 30, 110, 46, 78, 14, 118, 54, 86, 22, 102, + 38, 70, 6, 122, 58, 90, 26, 106, 42, 74, 10, 114, 50, 82, 18, + 98, 34, 66, 2, 127, 63, 95, 31, 111, 47, 79, 15, 119, 55, 87, + 23, 103, 39, 71, 7, 123, 59, 91, 27, 107, 43, 75, 11, 115, 51, + 83, 19, 99, 35, 67, 3, 125, 61, 93, 29, 109, 45, 77, 13, 117, + 53, 85, 21, 101, 37, 69, 5, 121, 57, 89, 25, 105, 41, 73, 9, + 113, 49, 81, 17, 97, 33, 65, 1 +}; + +static inline uint8 GetCodeword(int bits){ + uint8 tmp; + + if(!valid_bits){ + in_stream|=*(in_buf++); + valid_bits=8; + } + in_stream<<=1; + valid_bits--; + in_stream^=0x8000; + if(in_stream&0x8000) return 0x80+(1<>8) | (0x7f>>bits); + in_stream<<=bits; + valid_bits-=bits; + if(valid_bits<0){ + in_stream |= (*(in_buf++))<<(-valid_bits); + valid_bits+=8; + } + return run_table[tmp]; +} + +static inline uint8 GolombGetBit(int code_size){ + if(!bit_ctr[code_size]) bit_ctr[code_size]=GetCodeword(code_size); + bit_ctr[code_size]--; + if(bit_ctr[code_size]==0x80){ + bit_ctr[code_size]=0; + return 2; /* secret code for 'last zero'. ones are always last. */ + } + return (bit_ctr[code_size]==0)?1:0; +} + +static inline uint8 ProbGetBit(uint8 context){ + uint8 state=context_states[context]; + uint8 bit=GolombGetBit(evolution_table[state].code_size); + + if(bit&1){ + context_states[context]=evolution_table[state].LPS_next; + if(state<2){ + context_MPS[context]^=1; + return context_MPS[context]; /* just inverted, so just return it */ + } else{ + return context_MPS[context]^1; /* we know bit is 1, so use a constant */ + } + } else if(bit){ + context_states[context]=evolution_table[state].MPS_next; + /* zero here, zero there, no difference so drop through. */ + } + return context_MPS[context]; /* we know bit is 0, so don't bother xoring */ +} + +static inline uint8 GetBit(uint8 cur_bitplane){ + uint8 bit; + + bit=ProbGetBit(((cur_bitplane&1)<<4) + | ((prev_bits[cur_bitplane]&high_context_bits)>>5) + | (prev_bits[cur_bitplane]&low_context_bits)); + + prev_bits[cur_bitplane] <<= 1; + prev_bits[cur_bitplane] |= bit; + return bit; +} + +void SDD1_decompress(uint8 *out, uint8 *in, int len){ + uint8 bit, i, plane; + uint8 byte1, byte2; + + if(len==0) len=0x10000; + + bitplane_type=in[0]>>6; + + switch(in[0]&0x30){ + case 0x00: + high_context_bits=0x01c0; + low_context_bits =0x0001; + break; + case 0x10: + high_context_bits=0x0180; + low_context_bits =0x0001; + break; + case 0x20: + high_context_bits=0x00c0; + low_context_bits =0x0001; + break; + case 0x30: + high_context_bits=0x0180; + low_context_bits =0x0003; + break; + } + + in_stream=(in[0]<<11) | (in[1]<<3); + valid_bits=5; + in_buf=in+2; + memset(bit_ctr, 0, sizeof(bit_ctr)); + memset(context_states, 0, sizeof(context_states)); + memset(context_MPS, 0, sizeof(context_MPS)); + memset(prev_bits, 0, sizeof(prev_bits)); + + switch(bitplane_type){ + case 0: + while(1) { + for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ + if(GetBit(0)) byte1 |= bit; + if(GetBit(1)) byte2 |= bit; + } + *(out++)=byte1; + if(!--len) return; + *(out++)=byte2; + if(!--len) return; + } + break; + case 1: + i=plane=0; + while(1) { + for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ + if(GetBit(plane)) byte1 |= bit; + if(GetBit(plane+1)) byte2 |= bit; + } + *(out++)=byte1; + if(!--len) return; + *(out++)=byte2; + if(!--len) return; + if(!(i+=32)) plane = (plane+2)&7; + } + break; + case 2: + i=plane=0; + while(1) { + for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ + if(GetBit(plane)) byte1 |= bit; + if(GetBit(plane+1)) byte2 |= bit; + } + *(out++)=byte1; + if(!--len) return; + *(out++)=byte2; + if(!--len) return; + if(!(i+=32)) plane ^= 2; + } + break; + case 3: + do { + for(byte1=plane=0, bit=1; bit; bit<<=1, plane++){ + if(GetBit(plane)) byte1 |= bit; + } + *(out++)=byte1; + } while(--len); + break; + } +} + +static uint8 cur_plane; +static uint8 num_bits; +static uint8 next_byte; + +void SDD1_init(uint8 *in){ + bitplane_type=in[0]>>6; + + switch(in[0]&0x30){ + case 0x00: + high_context_bits=0x01c0; + low_context_bits =0x0001; + break; + case 0x10: + high_context_bits=0x0180; + low_context_bits =0x0001; + break; + case 0x20: + high_context_bits=0x00c0; + low_context_bits =0x0001; + break; + case 0x30: + high_context_bits=0x0180; + low_context_bits =0x0003; + break; + } + + in_stream=(in[0]<<11) | (in[1]<<3); + valid_bits=5; + in_buf=in+2; + memset(bit_ctr, 0, sizeof(bit_ctr)); + memset(context_states, 0, sizeof(context_states)); + memset(context_MPS, 0, sizeof(context_MPS)); + memset(prev_bits, 0, sizeof(prev_bits)); + + cur_plane=0; + num_bits=0; +} + +uint8 SDD1_get_byte(void){ + uint8 bit; + uint8 byte=0; + + switch(bitplane_type){ + case 0: + num_bits+=16; + if(num_bits&16){ + next_byte=0; + for(bit=0x80; bit; bit>>=1){ + if(GetBit(0)) byte |= bit; + if(GetBit(1)) next_byte |= bit; + } + return byte; + } else { + return next_byte; + } + + case 1: + num_bits+=16; + if(num_bits&16){ + next_byte=0; + for(bit=0x80; bit; bit>>=1){ + if(GetBit(cur_plane)) byte |= bit; + if(GetBit(cur_plane+1)) next_byte |= bit; + } + return byte; + } else { + if(!num_bits) cur_plane = (cur_plane+2)&7; + return next_byte; + } + + case 2: + num_bits+=16; + if(num_bits&16){ + next_byte=0; + for(bit=0x80; bit; bit>>=1){ + if(GetBit(cur_plane)) byte |= bit; + if(GetBit(cur_plane+1)) next_byte |= bit; + } + return byte; + } else { + if(!num_bits) cur_plane ^= 2; + return next_byte; + } + + case 3: + for(cur_plane=0, bit=1; bit; bit<<=1, cur_plane++){ + if(GetBit(cur_plane)) byte |= bit; + } + return byte; + + default: + /* should never happen */ + return 0; + } +} + diff --git a/src/sdd1emu.cpp b/src/sdd1emu.cpp deleted file mode 100644 index 3f97ee2..0000000 --- a/src/sdd1emu.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ -/* S-DD1 decompressor - * - * Based on code and documentation by Andreas Naive, who deserves a great deal - * of thanks and credit for figuring this out. - * - * Andreas says: - * The author is greatly indebted with The Dumper, without whose help and - * patience providing him with real S-DD1 data the research had never been - * possible. He also wish to note that in the very beggining of his research, - * Neviksti had done some steps in the right direction. By last, the author is - * indirectly indebted to all the people that worked and contributed in the - * S-DD1 issue in the past. - */ - -#include -#include "port.h" -#include "sdd1emu.h" - -static int valid_bits; -static uint16 in_stream; -static uint8 *in_buf; -static uint8 bit_ctr[8]; -static uint8 context_states[32]; -static int context_MPS[32]; -static int bitplane_type; -static int high_context_bits; -static int low_context_bits; -static int prev_bits[8]; - -static struct { - uint8 code_size; - uint8 MPS_next; - uint8 LPS_next; -} evolution_table[] = { - /* 0 */ { 0,25,25}, - /* 1 */ { 0, 2, 1}, - /* 2 */ { 0, 3, 1}, - /* 3 */ { 0, 4, 2}, - /* 4 */ { 0, 5, 3}, - /* 5 */ { 1, 6, 4}, - /* 6 */ { 1, 7, 5}, - /* 7 */ { 1, 8, 6}, - /* 8 */ { 1, 9, 7}, - /* 9 */ { 2,10, 8}, - /* 10 */ { 2,11, 9}, - /* 11 */ { 2,12,10}, - /* 12 */ { 2,13,11}, - /* 13 */ { 3,14,12}, - /* 14 */ { 3,15,13}, - /* 15 */ { 3,16,14}, - /* 16 */ { 3,17,15}, - /* 17 */ { 4,18,16}, - /* 18 */ { 4,19,17}, - /* 19 */ { 5,20,18}, - /* 20 */ { 5,21,19}, - /* 21 */ { 6,22,20}, - /* 22 */ { 6,23,21}, - /* 23 */ { 7,24,22}, - /* 24 */ { 7,24,23}, - /* 25 */ { 0,26, 1}, - /* 26 */ { 1,27, 2}, - /* 27 */ { 2,28, 4}, - /* 28 */ { 3,29, 8}, - /* 29 */ { 4,30,12}, - /* 30 */ { 5,31,16}, - /* 31 */ { 6,32,18}, - /* 32 */ { 7,24,22} -}; - -static uint8 run_table[128] = { - 128, 64, 96, 32, 112, 48, 80, 16, 120, 56, 88, 24, 104, 40, 72, - 8, 124, 60, 92, 28, 108, 44, 76, 12, 116, 52, 84, 20, 100, 36, - 68, 4, 126, 62, 94, 30, 110, 46, 78, 14, 118, 54, 86, 22, 102, - 38, 70, 6, 122, 58, 90, 26, 106, 42, 74, 10, 114, 50, 82, 18, - 98, 34, 66, 2, 127, 63, 95, 31, 111, 47, 79, 15, 119, 55, 87, - 23, 103, 39, 71, 7, 123, 59, 91, 27, 107, 43, 75, 11, 115, 51, - 83, 19, 99, 35, 67, 3, 125, 61, 93, 29, 109, 45, 77, 13, 117, - 53, 85, 21, 101, 37, 69, 5, 121, 57, 89, 25, 105, 41, 73, 9, - 113, 49, 81, 17, 97, 33, 65, 1 -}; - -static inline uint8 GetCodeword(int bits){ - uint8 tmp; - - if(!valid_bits){ - in_stream|=*(in_buf++); - valid_bits=8; - } - in_stream<<=1; - valid_bits--; - in_stream^=0x8000; - if(in_stream&0x8000) return 0x80+(1<>8) | (0x7f>>bits); - in_stream<<=bits; - valid_bits-=bits; - if(valid_bits<0){ - in_stream |= (*(in_buf++))<<(-valid_bits); - valid_bits+=8; - } - return run_table[tmp]; -} - -static inline uint8 GolombGetBit(int code_size){ - if(!bit_ctr[code_size]) bit_ctr[code_size]=GetCodeword(code_size); - bit_ctr[code_size]--; - if(bit_ctr[code_size]==0x80){ - bit_ctr[code_size]=0; - return 2; /* secret code for 'last zero'. ones are always last. */ - } - return (bit_ctr[code_size]==0)?1:0; -} - -static inline uint8 ProbGetBit(uint8 context){ - uint8 state=context_states[context]; - uint8 bit=GolombGetBit(evolution_table[state].code_size); - - if(bit&1){ - context_states[context]=evolution_table[state].LPS_next; - if(state<2){ - context_MPS[context]^=1; - return context_MPS[context]; /* just inverted, so just return it */ - } else{ - return context_MPS[context]^1; /* we know bit is 1, so use a constant */ - } - } else if(bit){ - context_states[context]=evolution_table[state].MPS_next; - /* zero here, zero there, no difference so drop through. */ - } - return context_MPS[context]; /* we know bit is 0, so don't bother xoring */ -} - -static inline uint8 GetBit(uint8 cur_bitplane){ - uint8 bit; - - bit=ProbGetBit(((cur_bitplane&1)<<4) - | ((prev_bits[cur_bitplane]&high_context_bits)>>5) - | (prev_bits[cur_bitplane]&low_context_bits)); - - prev_bits[cur_bitplane] <<= 1; - prev_bits[cur_bitplane] |= bit; - return bit; -} - -void SDD1_decompress(uint8 *out, uint8 *in, int len){ - uint8 bit, i, plane; - uint8 byte1, byte2; - - if(len==0) len=0x10000; - - bitplane_type=in[0]>>6; - - switch(in[0]&0x30){ - case 0x00: - high_context_bits=0x01c0; - low_context_bits =0x0001; - break; - case 0x10: - high_context_bits=0x0180; - low_context_bits =0x0001; - break; - case 0x20: - high_context_bits=0x00c0; - low_context_bits =0x0001; - break; - case 0x30: - high_context_bits=0x0180; - low_context_bits =0x0003; - break; - } - - in_stream=(in[0]<<11) | (in[1]<<3); - valid_bits=5; - in_buf=in+2; - memset(bit_ctr, 0, sizeof(bit_ctr)); - memset(context_states, 0, sizeof(context_states)); - memset(context_MPS, 0, sizeof(context_MPS)); - memset(prev_bits, 0, sizeof(prev_bits)); - - switch(bitplane_type){ - case 0: - while(1) { - for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ - if(GetBit(0)) byte1 |= bit; - if(GetBit(1)) byte2 |= bit; - } - *(out++)=byte1; - if(!--len) return; - *(out++)=byte2; - if(!--len) return; - } - break; - case 1: - i=plane=0; - while(1) { - for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ - if(GetBit(plane)) byte1 |= bit; - if(GetBit(plane+1)) byte2 |= bit; - } - *(out++)=byte1; - if(!--len) return; - *(out++)=byte2; - if(!--len) return; - if(!(i+=32)) plane = (plane+2)&7; - } - break; - case 2: - i=plane=0; - while(1) { - for(byte1=byte2=0, bit=0x80; bit; bit>>=1){ - if(GetBit(plane)) byte1 |= bit; - if(GetBit(plane+1)) byte2 |= bit; - } - *(out++)=byte1; - if(!--len) return; - *(out++)=byte2; - if(!--len) return; - if(!(i+=32)) plane ^= 2; - } - break; - case 3: - do { - for(byte1=plane=0, bit=1; bit; bit<<=1, plane++){ - if(GetBit(plane)) byte1 |= bit; - } - *(out++)=byte1; - } while(--len); - break; - } -} - -static uint8 cur_plane; -static uint8 num_bits; -static uint8 next_byte; - -void SDD1_init(uint8 *in){ - bitplane_type=in[0]>>6; - - switch(in[0]&0x30){ - case 0x00: - high_context_bits=0x01c0; - low_context_bits =0x0001; - break; - case 0x10: - high_context_bits=0x0180; - low_context_bits =0x0001; - break; - case 0x20: - high_context_bits=0x00c0; - low_context_bits =0x0001; - break; - case 0x30: - high_context_bits=0x0180; - low_context_bits =0x0003; - break; - } - - in_stream=(in[0]<<11) | (in[1]<<3); - valid_bits=5; - in_buf=in+2; - memset(bit_ctr, 0, sizeof(bit_ctr)); - memset(context_states, 0, sizeof(context_states)); - memset(context_MPS, 0, sizeof(context_MPS)); - memset(prev_bits, 0, sizeof(prev_bits)); - - cur_plane=0; - num_bits=0; -} - -uint8 SDD1_get_byte(void){ - uint8 bit; - uint8 byte=0; - - switch(bitplane_type){ - case 0: - num_bits+=16; - if(num_bits&16){ - next_byte=0; - for(bit=0x80; bit; bit>>=1){ - if(GetBit(0)) byte |= bit; - if(GetBit(1)) next_byte |= bit; - } - return byte; - } else { - return next_byte; - } - - case 1: - num_bits+=16; - if(num_bits&16){ - next_byte=0; - for(bit=0x80; bit; bit>>=1){ - if(GetBit(cur_plane)) byte |= bit; - if(GetBit(cur_plane+1)) next_byte |= bit; - } - return byte; - } else { - if(!num_bits) cur_plane = (cur_plane+2)&7; - return next_byte; - } - - case 2: - num_bits+=16; - if(num_bits&16){ - next_byte=0; - for(bit=0x80; bit; bit>>=1){ - if(GetBit(cur_plane)) byte |= bit; - if(GetBit(cur_plane+1)) next_byte |= bit; - } - return byte; - } else { - if(!num_bits) cur_plane ^= 2; - return next_byte; - } - - case 3: - for(cur_plane=0, bit=1; bit; bit<<=1, cur_plane++){ - if(GetBit(cur_plane)) byte |= bit; - } - return byte; - - default: - /* should never happen */ - return 0; - } -} - diff --git a/src/sdd1emu.h b/src/sdd1emu.h index e9d4785..829ac4a 100644 --- a/src/sdd1emu.h +++ b/src/sdd1emu.h @@ -92,13 +92,13 @@ /* for START_EXTERN_C/END_EXTERN_C */ #include "port.h" -extern "C" { +START_EXTERN_C void SDD1_decompress(uint8 *out, uint8 *in, int output_length); void SDD1_init(uint8 *in); uint8 SDD1_get_byte(void); -} +END_EXTERN_C #endif diff --git a/src/seta.c b/src/seta.c new file mode 100644 index 0000000..0600a07 --- /dev/null +++ b/src/seta.c @@ -0,0 +1,107 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and distribute Snes9x in both binary and + source form, for non-commercial purposes, is hereby granted without fee, + providing that this license information and copyright notice appear with + all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes + charging money for Snes9x or software derived from Snes9x. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +*******************************************************************************/ +#include "port.h" +#include "seta.h" + + +void (*SetSETA)(uint32, uint8)=&S9xSetST010; +uint8 (*GetSETA)(uint32)=&S9xGetST010; + +extern "C"{ +uint8 S9xGetSetaDSP(uint32 Address) +{ + return GetSETA(Address); +} + +void S9xSetSetaDSP(uint8 Byte, uint32 Address) +{ + SetSETA(Address, Byte); +} +} + diff --git a/src/seta.cpp b/src/seta.cpp deleted file mode 100644 index 0600a07..0000000 --- a/src/seta.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ -#include "port.h" -#include "seta.h" - - -void (*SetSETA)(uint32, uint8)=&S9xSetST010; -uint8 (*GetSETA)(uint32)=&S9xGetST010; - -extern "C"{ -uint8 S9xGetSetaDSP(uint32 Address) -{ - return GetSETA(Address); -} - -void S9xSetSetaDSP(uint8 Byte, uint32 Address) -{ - SetSETA(Address, Byte); -} -} - diff --git a/src/seta010.c b/src/seta010.c new file mode 100644 index 0000000..c6dc266 --- /dev/null +++ b/src/seta010.c @@ -0,0 +1,751 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and distribute Snes9x in both binary and + source form, for non-commercial purposes, is hereby granted without fee, + providing that this license information and copyright notice appear with + all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes + charging money for Snes9x or software derived from Snes9x. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +*******************************************************************************/ +//#include "port.h" +#include "memmap.h" +#include "seta.h" + +// Mode 7 scaling constants for all raster lines +const int16 ST010_M7Scale[176] = { + 0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3, + 0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b, + 0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8, + 0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6, + 0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5, + 0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d, + 0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c, + 0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e, + 0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063, + 0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a, + 0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052, + 0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c, + 0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047, + 0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042, + 0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e, + 0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a, + 0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037, + 0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034, + 0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031, + 0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f, + 0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d, + 0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b +}; + +// H-DMA hack +bool seta_hack; + +//temporary Op04 requirement +#include + +#ifndef PI +#define PI 3.1415926535897932384626433832795 +#endif + +ST010_Regs ST010; + +uint8 S9xGetST010(uint32 Address) +{ + if(!(Address&0x80000)) + return 0x80; + + if((Address&0xFFF)==0x20) + return ST010.op_reg; + if ((Address&0xFFF)==0x21) + return ST010.execute; + return Memory.SRAM[Address&CPU.Memory_SRAMMask]; +} + +const int16 ST010_SinTable[256] = { + 0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2, + 0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, + 0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, + 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, + 0x5a82, 0x5cb3, 0x5ed7, 0x60eb, 0x62f1, 0x64e8, 0x66cf, 0x68a6, + 0x6a6d, 0x6c23, 0x6dc9, 0x6f5e, 0x70e2, 0x7254, 0x73b5, 0x7504, + 0x7641, 0x776b, 0x7884, 0x7989, 0x7a7c, 0x7b5c, 0x7c29, 0x7ce3, + 0x7d89, 0x7e1d, 0x7e9c, 0x7f09, 0x7f61, 0x7fa6, 0x7fd8, 0x7ff5, + 0x7fff, 0x7ff5, 0x7fd8, 0x7fa6, 0x7f61, 0x7f09, 0x7e9c, 0x7e1d, + 0x7d89, 0x7ce3, 0x7c29, 0x7b5c, 0x7a7c, 0x7989, 0x7884, 0x776b, + 0x7641, 0x7504, 0x73b5, 0x7254, 0x70e2, 0x6f5e, 0x6dc9, 0x6c23, + 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f1, 0x60eb, 0x5ed7, 0x5cb3, + 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, + 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33df, + 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f1a, 0x1c0b, + 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8c, 0x096a, 0x0648, 0x0324, + 0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2, + -0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, + -0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a, + -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, + -0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6, + -0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504, + -0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3, + -0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5, + -0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d, + -0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b, + -0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23, + -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3, + -0x5a82, -0x5842, -0x55f5, -0x539a, -0x5133, -0x4ebf, -0x4c3f, -0x49b3, + -0x471c, -0x447a, -0x41cd, -0x3f17, -0x3c56, -0x398c, -0x36b9, -0x33de, + -0x30fb, -0x2e10, -0x2b1f, -0x2826, -0x2527, -0x2223, -0x1f19, -0x1c0b, + -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324}; + +const unsigned char ST010_ArcTan[32][32] = { + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, + { 0x80, 0xa0, 0xad, 0xb3, 0xb6, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf}, + { 0x80, 0x93, 0xa0, 0xa8, 0xad, 0xb0, 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, + 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd}, + { 0x80, 0x8d, 0x98, 0xa0, 0xa6, 0xaa, 0xad, 0xb0, 0xb1, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb8, + 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc}, + { 0x80, 0x8a, 0x93, 0x9a, 0xa0, 0xa5, 0xa8, 0xab, 0xad, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xb5, 0xb5, + 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb}, + { 0x80, 0x88, 0x90, 0x96, 0x9b, 0xa0, 0xa4, 0xa7, 0xa9, 0xab, 0xad, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, + 0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9}, + { 0x80, 0x87, 0x8d, 0x93, 0x98, 0x9c, 0xa0, 0xa3, 0xa6, 0xa8, 0xaa, 0xac, 0xad, 0xae, 0xb0, 0xb0, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8}, + { 0x80, 0x86, 0x8b, 0x90, 0x95, 0x99, 0x9d, 0xa0, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xad, 0xae, + 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7}, + { 0x80, 0x85, 0x8a, 0x8f, 0x93, 0x97, 0x9a, 0x9d, 0xa0, 0xa2, 0xa5, 0xa6, 0xa8, 0xaa, 0xab, 0xac, + 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5}, + { 0x80, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x98, 0x9b, 0x9e, 0xa0, 0xa0, 0xa4, 0xa6, 0xa7, 0xa9, 0xaa, + 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4}, + { 0x80, 0x84, 0x88, 0x8c, 0x90, 0x93, 0x96, 0x99, 0x9b, 0x9e, 0xa0, 0xa2, 0xa4, 0xa5, 0xa7, 0xa8, + 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3}, + { 0x80, 0x84, 0x87, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, 0xa6, + 0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2}, + { 0x80, 0x83, 0x87, 0x8a, 0x8d, 0x90, 0x93, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1}, + { 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x94, 0x96, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa2, 0xa3, + 0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xb0}, + { 0x80, 0x83, 0x86, 0x89, 0x8b, 0x8e, 0x90, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa1, + 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf}, + { 0x80, 0x83, 0x85, 0x88, 0x8b, 0x8d, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9b, 0x9d, 0x9f, 0xa0, + 0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae}, + { 0x80, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9a, 0x9c, 0x9d, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xad}, + { 0x80, 0x82, 0x85, 0x87, 0x89, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97, 0x99, 0x9b, 0x9c, 0x9d, + 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac}, + { 0x80, 0x82, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x93, 0x95, 0x96, 0x98, 0x99, 0x9b, 0x9c, + 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab}, + { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x9a, 0x9b, + 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa}, + { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x99, 0x9a, + 0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9}, + { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8f, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x99, + 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8}, + { 0x80, 0x82, 0x84, 0x86, 0x87, 0x89, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x98, + 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7}, + { 0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98, + 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6}, + { 0x80, 0x82, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5}, + { 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4}, + { 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x95, + 0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4}, + { 0x80, 0x82, 0x83, 0x85, 0x86, 0x87, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x95, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3}, + { 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2}, + { 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa1}, + { 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, + 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1}, + { 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, + 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0}}; + +short ST010_Sin(short Theta) +{ + return ST010_SinTable[(Theta >> 8) & 0xff]; +} + +short ST010_Cos(short Theta) +{ + return ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff]; +} + +void ST010_OP01(short x0, short y0, short &x1, short &y1, short &Quadrant, short &Theta) +{ + if ((x0 < 0) && (y0 < 0)) + { + x1 = -x0; + y1 = -y0; + Quadrant = -0x8000; + } + else if (x0 < 0) + { + x1 = y0; + y1 = -x0; + Quadrant = -0x4000; + } + else if (y0 < 0) + { + x1 = -y0; + y1 = x0; + Quadrant = 0x4000; + } + else + { + x1 = x0; + y1 = y0; + Quadrant = 0x0000; + } + + while ((x1 > 0x1f) || (y1 > 0x1f)) + { + if (x1 > 1) x1 >>= 1; + if (y1 > 1) y1 >>= 1; + } + + if (y1 == 0) Quadrant += 0x4000; + + Theta = (ST010_ArcTan[y1][x1] << 8) ^ Quadrant; +} + +void ST010_Scale(short Multiplier, short X0, short Y0, int &X1, int &Y1) +{ + X1 = X0 * Multiplier << 1; + Y1 = Y0 * Multiplier << 1; +} + +void ST010_Multiply(short Multiplicand, short Multiplier, int &Product) +{ + Product = Multiplicand * Multiplier << 1; +} + +void ST010_Rotate(short Theta, short X0, short Y0, short &X1, short &Y1) +{ + X1 = (Y0 * ST010_Sin(Theta) >> 15) + (X0 * ST010_Cos(Theta) >> 15); + Y1 = (Y0 * ST010_Cos(Theta) >> 15) - (X0 * ST010_Sin(Theta) >> 15); +} + +void SETA_Distance(short Y0, short X0, short &Distance) +{ + if (X0 < 0) X0 = -X0; + if (Y0 < 0) Y0 = -Y0; + Distance = ((X0 * 0x7af0) + 0x4000) >> 15; +} + +void ST010_SortDrivers(uint16 Positions, uint16 Places[32], uint16 Drivers[32]) +{ + bool Sorted; + uint16 Temp; + + if (Positions > 1) + do { + Sorted = true; + for (int i = 0; i < Positions - 1; i++) + if (Places[i] < Places[i + 1]) + { + Temp = Places[i + 1]; + Places[i + 1] = Places[i]; + Places[i] = Temp; + + Temp = Drivers[i + 1]; + Drivers[i + 1] = Drivers[i]; + Drivers[i] = Temp; + + Sorted = false; + } + Positions--; + } while (!Sorted); +} + +#define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset] + +void S9xSetST010(uint32 Address, uint8 Byte) +{ + if(!(Address&0x80000)) + { + ST010.control_enable=TRUE; + return; + } + //printf("Write %06X:%02X\n", Address, Byte); + + if((Address &0xFFF) ==0x20 && ST010.control_enable) + ST010.op_reg=Byte; + if((Address &0xFFF) ==0x21 && ST010.control_enable) + ST010.execute=Byte; + else Memory.SRAM[Address&CPU.Memory_SRAMMask]=Byte; + + if(ST010.execute&0x80) + { + switch(ST010.op_reg) + { + // Sorts Driver Placements + // + // Input + // 0x0024-0x0025 : Positions + // 0x0040-0x007f : Places + // 0x0080-0x00ff : Drivers + // Output + // 0x0040-0x007f : Places + // 0x0080-0x00ff : Drivers + // + case 0x02: + { +#ifdef FAST_LSB_WORD_ACCESS + ST010_SortDrivers(*(short*)&SRAM[0x0024], (uint16*) (SRAM + 0x0040), (uint16*) (SRAM + 0x0080)); +#else + uint16 Places[32]; + uint16 Positions = ST010_WORD(0x0024); + int Pos, Offset; + + Offset = 0; + + for (Pos = 0; Pos < Positions; Pos++) + { + Places[Pos] = ST010_WORD(0x0040 + Offset); + Offset += 2; + } + + ST010_SortDrivers(Positions, Places, (uint16*) (SRAM + 0x0080)); + + Offset = 0; + + for (Pos = 0; Pos < Positions; Pos++) + { + SRAM[0x0040 + Offset]=(uint8)(Places[Pos]); + SRAM[0x0041 + Offset]=(uint8)(Places[Pos] >> 8); + Offset += 2; + } +#endif + break; + + } + + // Two Dimensional Coordinate Scale + // + // Input + // 0x0000-0x0001 : X0 (signed) + // 0x0002-0x0003 : Y0 (signed) + // 0x0004-0x0005 : Multiplier (signed) + // Output + // 0x0010-0x0013 : X1 (signed) + // 0x0014-0x0017 : Y1 (signed) + // + case 0x03: + { +#ifdef FAST_LSB_WORD_ACCESS + ST010_Scale(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], + (int&) Memory.SRAM[0x0010], (int&) Memory.SRAM[0x0014]); +#else + int x1, y1; + + ST010_Scale(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); + + Memory.SRAM[0x0010]=(uint8)(x1); + Memory.SRAM[0x0011]=(uint8)(x1 >> 8); + Memory.SRAM[0x0012]=(uint8)(x1 >> 16); + Memory.SRAM[0x0013]=(uint8)(x1 >> 24); + Memory.SRAM[0x0014]=(uint8)(y1); + Memory.SRAM[0x0015]=(uint8)(y1 >> 8); + Memory.SRAM[0x0016]=(uint8)(y1 >> 16); + Memory.SRAM[0x0017]=(uint8)(y1 >> 24); +#endif + break; + } + + // 16-bit Multiplication + // + // Input + // 0x0000-0x0001 : Multiplcand (signed) + // 0x0002-0x0003 : Multiplier (signed) + // Output + // 0x0010-0x0013 : Product (signed) + // + case 0x06: + { +#ifdef FAST_LSB_WORD_ACCESS + ST010_Multiply(*(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], (int&) Memory.SRAM[0x0010]); +#else + int Product; + + ST010_Multiply(ST010_WORD(0x0000), ST010_WORD(0x0002), Product); + + Memory.SRAM[0x0010]=(uint8)(Product); + Memory.SRAM[0x0011]=(uint8)(Product >> 8); + Memory.SRAM[0x0012]=(uint8)(Product >> 16); + Memory.SRAM[0x0013]=(uint8)(Product >> 24); +#endif + break; + } + + // Mode 7 Raster Data Calculation + // + // Input + // 0x0000-0x0001 : Angle (signed) + // Output + // 0x00f0-0x024f : Mode 7 Matrix A + // 0x0250-0x03af : Mode 7 Matrix B + // 0x03b0-0x050f : Mode 7 Matrix C + // 0x0510-0x066f : Mode 7 Matrix D + // + case 0x07: + { + int16 data; + int32 offset = 0; + int16 Theta = ST010_WORD(0x0000); + + for (int32 line = 0; line < 176; line++) + { + // Calculate Mode 7 Matrix A/D data + data = ST010_M7Scale[line] * ST010_Cos(Theta) >> 15; + + Memory.SRAM[0x00f0 + offset]=(uint8)(data); + Memory.SRAM[0x00f1 + offset]=(uint8)(data >> 8); + Memory.SRAM[0x0510 + offset]=(uint8)(data); + Memory.SRAM[0x0511 + offset]=(uint8)(data >> 8); + + // Calculate Mode 7 Matrix B/C data + data = ST010_M7Scale[line] * ST010_Sin(Theta) >> 15; + + Memory.SRAM[0x0250 + offset]=(uint8)(data); + Memory.SRAM[0x0251 + offset]=(uint8)(data >> 8); + + if (data) data = ~data; + + Memory.SRAM[0x03b0 + offset]=(uint8)(data); + Memory.SRAM[0x03b1 + offset]=(uint8)(data >> 8); + + offset += 2; + } + + // Shift Angle for use with Lookup table + Memory.SRAM[0x00] = Memory.SRAM[0x01]; + Memory.SRAM[0x01] = 0x00; + + break; + } + + // Two dimensional Coordinate Rotation + // + // Input + // 0x0000-0x0001 : X0 (signed) + // 0x0002-0x0003 : Y0 (signed) + // 0x0004-0x0005 : Angle (signed) + // Output + // 0x0010-0x0011 : X1 (signed) + // 0x0012-0x0013 : Y1 (signed) + // + case 0x08: + { +#ifdef FAST_LSB_WORD_ACCESS + ST010_Rotate(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], + (short&) Memory.SRAM[0x0010], (short&) Memory.SRAM[0x0012]); +#else + short x1, y1; + + ST010_Rotate(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); + + Memory.SRAM[0x0010]=(uint8)(x1); + Memory.SRAM[0x0011]=(uint8)(x1 >> 8); + Memory.SRAM[0x0012]=(uint8)(y1); + Memory.SRAM[0x0013]=(uint8)(y1 >> 8); +#endif + break; + } + + // Input + // 0x0000-0x0001 : DX (signed) + // 0x0002-0x0003 : DY (signed) + // Output + // 0x0010-0x0011 : Angle (signed) + // + case 0x01: + { + Memory.SRAM[0x0006] = Memory.SRAM[0x0002]; + Memory.SRAM[0x0007] = Memory.SRAM[0x0003]; + +#ifdef FAST_LSB_WORD_ACCESS + ST010_OP01(*(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], + (short&) Memory.SRAM[0x0000], (short&) Memory.SRAM[0x0002], + (short&) Memory.SRAM[0x0004], (short&) Memory.SRAM[0x0010]); +#else + short x1, y1, Quadrant, Theta; + + ST010_OP01(ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1, Quadrant, Theta); + + Memory.SRAM[0x0000]=(uint8)(x1); + Memory.SRAM[0x0001]=(uint8)(x1 >> 8); + Memory.SRAM[0x0002]=(uint8)(y1); + Memory.SRAM[0x0003]=(uint8)(y1 >> 8); + Memory.SRAM[0x0004]=(uint8)(Quadrant); + Memory.SRAM[0x0005]=(uint8)(Quadrant >> 8); + Memory.SRAM[0x0010]=(uint8)(Theta); + Memory.SRAM[0x0011]=(uint8)(Theta >> 8); +#endif + break; + } + + // calculate the vector length of (x,y) + case 0x04: + { + int16 square, x,y; +#ifdef FAST_LSB_WORD_ACCESS + x=*((int16*)Memory.SRAM); + y=*((int16*)&Memory.SRAM[2]); +#else + x=Memory.SRAM[0]|(Memory.SRAM[1]<<8); + y=Memory.SRAM[2]|(Memory.SRAM[3]<<8); +#endif + square=(int16)sqrt((double)(y*y+x*x)); + //SETA_Distance( x,y,square ); + +#ifdef FAST_LSB_WORD_ACCESS + *((int16*)&Memory.SRAM[0x10])=square; +#else + Memory.SRAM[0x10]=(uint8)(square); + Memory.SRAM[0x11]=(uint8)(square>>8); +#endif + break; + } + + // calculate AI orientation based on specific guidelines + case 0x05: + { + int dx,dy; + int16 a1,b1,c1; + uint16 o1; + + bool wrap=false; + + // target (x,y) coordinates + int16 ypos_max = ST010_WORD(0x00C0); + int16 xpos_max = ST010_WORD(0x00C2); + + // current coordinates and direction + int32 ypos = SRAM[0xC4]|(SRAM[0xC5]<<8)|(SRAM[0xC6]<<16)|(SRAM[0xC7]<<24); + int32 xpos = SRAM[0xC8]|(SRAM[0xC9]<<8)|(SRAM[0xCA]<<16)|(SRAM[0xCB]<<24); + uint16 rot = SRAM[0xCC]|(SRAM[0xCD]<<8); + + // physics + uint16 speed = ST010_WORD(0x00D4); + uint16 accel = ST010_WORD(0x00D6); + uint16 speed_max = ST010_WORD(0x00D8); + + // special condition acknowledgment + int16 system = ST010_WORD(0x00DA); + int16 flags = ST010_WORD(0x00DC); + + // new target coordinates + int16 ypos_new = ST010_WORD(0x00DE); + int16 xpos_new = ST010_WORD(0x00E0); + + // mask upper bit + xpos_new &= 0x7FFF; + + // get the current distance + dx = xpos_max-(xpos>>16); + dy = ypos_max-(ypos>>16); + + // quirk: clear and move in9 + SRAM[0xD2]=0xFF; + SRAM[0xD3]=0xFF; + SRAM[0xDA]=0; + SRAM[0xDB]=0; + + // grab the target angle + ST010_OP01(dy,dx,a1,b1,c1,(int16 &)o1); + + // check for wrapping + //if((o1<0x6000 && rot>0xA000) || + // (rot<0x6000 && o1>0xA000)) + //if(o10x8000) + { + o1+=0x8000; + rot+=0x8000; + wrap=true; + } + //o1=0x0000; + //rot=0xFF00; + + uint16 old_speed; + + old_speed = speed; + + // special case + if(abs(o1-rot)==0x8000) + { + speed = 0x100; + } + // slow down for sharp curves + else if(abs(o1-rot)>=0x1000) + { + uint32 slow = abs(o1-rot); + slow >>= 4; // scaling + speed -= slow; + } + // otherwise accelerate + else + { + speed += accel; + if(speed > speed_max) + { + // clip speed + speed = speed_max; + } + } + + // prevent negative/positive overflow + if(abs(old_speed-speed)>0x8000) { + if(old_speedrot && (o1-rot)>0x80) || + (o1=0x80) ) + { + if(o1rot) rot+=0x280; + } + + // turn off wrapping + if(wrap) rot-=0x8000; + + // now check the distances (store for later) + dx = (xpos_max<<16)-xpos; + dy = (ypos_max<<16)-ypos; + dx>>=16; + dy>>=16; + + // if we're in so many units of the target, signal it + if( ( system && (dy<=6 && dy>=-8) && (dx<=126 && dx>=-128)) || + (!system && (dx<=6 && dx>=-8) && (dy<=126 && dy>=-128)) ) + { + // announce our new destination and flag it + xpos_max = xpos_new&0x7FFF; + ypos_max = ypos_new; + flags |= 0x08; + } + + // update position + xpos -= (ST010_Cos(rot) * 0x400 >> 15) * (speed >> 8) << 1; + ypos -= (ST010_Sin(rot) * 0x400 >> 15) * (speed >> 8) << 1; + + // quirk: mask upper byte + xpos &= 0x1FFFFFFF; + ypos &= 0x1FFFFFFF; + + SRAM[0x00C0]=(uint8)(ypos_max); + SRAM[0x00C1]=(uint8)(ypos_max >> 8); + SRAM[0x00C2]=(uint8)(xpos_max); + SRAM[0x00C3]=(uint8)(xpos_max >> 8); + SRAM[0x00C4]=(uint8)(ypos); + SRAM[0x00C5]=(uint8)(ypos >> 8); + SRAM[0x00C6]=(uint8)(ypos >> 16); + SRAM[0x00C7]=(uint8)(ypos >> 24); + SRAM[0x00C8]=(uint8)(xpos); + SRAM[0x00C9]=(uint8)(xpos >> 8); + SRAM[0x00CA]=(uint8)(xpos >> 16); + SRAM[0x00CB]=(uint8)(xpos >> 24); + SRAM[0x00CC]=(uint8)(rot); + SRAM[0x00CD]=(uint8)(rot >> 8); + SRAM[0x00D4]=(uint8)(speed); + SRAM[0x00D5]=(uint8)(speed >> 8); + SRAM[0x00DC]=(uint8)(flags); + SRAM[0x00DD]=(uint8)(flags >> 8); + + break; + } + + default: + printf("Unknown Op\n"); + break; + } + + // lower signal: op processed + ST010.op_reg=0; + ST010.execute=0; + } +} + diff --git a/src/seta010.cpp b/src/seta010.cpp deleted file mode 100644 index c6dc266..0000000 --- a/src/seta010.cpp +++ /dev/null @@ -1,751 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ -//#include "port.h" -#include "memmap.h" -#include "seta.h" - -// Mode 7 scaling constants for all raster lines -const int16 ST010_M7Scale[176] = { - 0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3, - 0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b, - 0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8, - 0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6, - 0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5, - 0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d, - 0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c, - 0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e, - 0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063, - 0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a, - 0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052, - 0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c, - 0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047, - 0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042, - 0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e, - 0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a, - 0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037, - 0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034, - 0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031, - 0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f, - 0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d, - 0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b -}; - -// H-DMA hack -bool seta_hack; - -//temporary Op04 requirement -#include - -#ifndef PI -#define PI 3.1415926535897932384626433832795 -#endif - -ST010_Regs ST010; - -uint8 S9xGetST010(uint32 Address) -{ - if(!(Address&0x80000)) - return 0x80; - - if((Address&0xFFF)==0x20) - return ST010.op_reg; - if ((Address&0xFFF)==0x21) - return ST010.execute; - return Memory.SRAM[Address&CPU.Memory_SRAMMask]; -} - -const int16 ST010_SinTable[256] = { - 0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2, - 0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, - 0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, - 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, - 0x5a82, 0x5cb3, 0x5ed7, 0x60eb, 0x62f1, 0x64e8, 0x66cf, 0x68a6, - 0x6a6d, 0x6c23, 0x6dc9, 0x6f5e, 0x70e2, 0x7254, 0x73b5, 0x7504, - 0x7641, 0x776b, 0x7884, 0x7989, 0x7a7c, 0x7b5c, 0x7c29, 0x7ce3, - 0x7d89, 0x7e1d, 0x7e9c, 0x7f09, 0x7f61, 0x7fa6, 0x7fd8, 0x7ff5, - 0x7fff, 0x7ff5, 0x7fd8, 0x7fa6, 0x7f61, 0x7f09, 0x7e9c, 0x7e1d, - 0x7d89, 0x7ce3, 0x7c29, 0x7b5c, 0x7a7c, 0x7989, 0x7884, 0x776b, - 0x7641, 0x7504, 0x73b5, 0x7254, 0x70e2, 0x6f5e, 0x6dc9, 0x6c23, - 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f1, 0x60eb, 0x5ed7, 0x5cb3, - 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, - 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33df, - 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f1a, 0x1c0b, - 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8c, 0x096a, 0x0648, 0x0324, - 0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2, - -0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, - -0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a, - -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, - -0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6, - -0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504, - -0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3, - -0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5, - -0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d, - -0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b, - -0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23, - -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3, - -0x5a82, -0x5842, -0x55f5, -0x539a, -0x5133, -0x4ebf, -0x4c3f, -0x49b3, - -0x471c, -0x447a, -0x41cd, -0x3f17, -0x3c56, -0x398c, -0x36b9, -0x33de, - -0x30fb, -0x2e10, -0x2b1f, -0x2826, -0x2527, -0x2223, -0x1f19, -0x1c0b, - -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324}; - -const unsigned char ST010_ArcTan[32][32] = { - { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, - { 0x80, 0xa0, 0xad, 0xb3, 0xb6, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, - 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf}, - { 0x80, 0x93, 0xa0, 0xa8, 0xad, 0xb0, 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb, - 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd}, - { 0x80, 0x8d, 0x98, 0xa0, 0xa6, 0xaa, 0xad, 0xb0, 0xb1, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb8, - 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc}, - { 0x80, 0x8a, 0x93, 0x9a, 0xa0, 0xa5, 0xa8, 0xab, 0xad, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xb5, 0xb5, - 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb}, - { 0x80, 0x88, 0x90, 0x96, 0x9b, 0xa0, 0xa4, 0xa7, 0xa9, 0xab, 0xad, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, - 0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9}, - { 0x80, 0x87, 0x8d, 0x93, 0x98, 0x9c, 0xa0, 0xa3, 0xa6, 0xa8, 0xaa, 0xac, 0xad, 0xae, 0xb0, 0xb0, - 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8}, - { 0x80, 0x86, 0x8b, 0x90, 0x95, 0x99, 0x9d, 0xa0, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xad, 0xae, - 0xaf, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7}, - { 0x80, 0x85, 0x8a, 0x8f, 0x93, 0x97, 0x9a, 0x9d, 0xa0, 0xa2, 0xa5, 0xa6, 0xa8, 0xaa, 0xab, 0xac, - 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5}, - { 0x80, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x98, 0x9b, 0x9e, 0xa0, 0xa0, 0xa4, 0xa6, 0xa7, 0xa9, 0xaa, - 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4}, - { 0x80, 0x84, 0x88, 0x8c, 0x90, 0x93, 0x96, 0x99, 0x9b, 0x9e, 0xa0, 0xa2, 0xa4, 0xa5, 0xa7, 0xa8, - 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3}, - { 0x80, 0x84, 0x87, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, 0xa6, - 0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2}, - { 0x80, 0x83, 0x87, 0x8a, 0x8d, 0x90, 0x93, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1}, - { 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x94, 0x96, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa2, 0xa3, - 0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xb0}, - { 0x80, 0x83, 0x86, 0x89, 0x8b, 0x8e, 0x90, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa1, - 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf}, - { 0x80, 0x83, 0x85, 0x88, 0x8b, 0x8d, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9b, 0x9d, 0x9f, 0xa0, - 0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae}, - { 0x80, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9a, 0x9c, 0x9d, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xad}, - { 0x80, 0x82, 0x85, 0x87, 0x89, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97, 0x99, 0x9b, 0x9c, 0x9d, - 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac}, - { 0x80, 0x82, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x93, 0x95, 0x96, 0x98, 0x99, 0x9b, 0x9c, - 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab}, - { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x9a, 0x9b, - 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa}, - { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x99, 0x9a, - 0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9}, - { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8f, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x99, - 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8}, - { 0x80, 0x82, 0x84, 0x86, 0x87, 0x89, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x98, - 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7}, - { 0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98, - 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6}, - { 0x80, 0x82, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5}, - { 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4}, - { 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x95, - 0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4}, - { 0x80, 0x82, 0x83, 0x85, 0x86, 0x87, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x95, - 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3}, - { 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, - 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2}, - { 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, - 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa1}, - { 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, - 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1}, - { 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, - 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0}}; - -short ST010_Sin(short Theta) -{ - return ST010_SinTable[(Theta >> 8) & 0xff]; -} - -short ST010_Cos(short Theta) -{ - return ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff]; -} - -void ST010_OP01(short x0, short y0, short &x1, short &y1, short &Quadrant, short &Theta) -{ - if ((x0 < 0) && (y0 < 0)) - { - x1 = -x0; - y1 = -y0; - Quadrant = -0x8000; - } - else if (x0 < 0) - { - x1 = y0; - y1 = -x0; - Quadrant = -0x4000; - } - else if (y0 < 0) - { - x1 = -y0; - y1 = x0; - Quadrant = 0x4000; - } - else - { - x1 = x0; - y1 = y0; - Quadrant = 0x0000; - } - - while ((x1 > 0x1f) || (y1 > 0x1f)) - { - if (x1 > 1) x1 >>= 1; - if (y1 > 1) y1 >>= 1; - } - - if (y1 == 0) Quadrant += 0x4000; - - Theta = (ST010_ArcTan[y1][x1] << 8) ^ Quadrant; -} - -void ST010_Scale(short Multiplier, short X0, short Y0, int &X1, int &Y1) -{ - X1 = X0 * Multiplier << 1; - Y1 = Y0 * Multiplier << 1; -} - -void ST010_Multiply(short Multiplicand, short Multiplier, int &Product) -{ - Product = Multiplicand * Multiplier << 1; -} - -void ST010_Rotate(short Theta, short X0, short Y0, short &X1, short &Y1) -{ - X1 = (Y0 * ST010_Sin(Theta) >> 15) + (X0 * ST010_Cos(Theta) >> 15); - Y1 = (Y0 * ST010_Cos(Theta) >> 15) - (X0 * ST010_Sin(Theta) >> 15); -} - -void SETA_Distance(short Y0, short X0, short &Distance) -{ - if (X0 < 0) X0 = -X0; - if (Y0 < 0) Y0 = -Y0; - Distance = ((X0 * 0x7af0) + 0x4000) >> 15; -} - -void ST010_SortDrivers(uint16 Positions, uint16 Places[32], uint16 Drivers[32]) -{ - bool Sorted; - uint16 Temp; - - if (Positions > 1) - do { - Sorted = true; - for (int i = 0; i < Positions - 1; i++) - if (Places[i] < Places[i + 1]) - { - Temp = Places[i + 1]; - Places[i + 1] = Places[i]; - Places[i] = Temp; - - Temp = Drivers[i + 1]; - Drivers[i + 1] = Drivers[i]; - Drivers[i] = Temp; - - Sorted = false; - } - Positions--; - } while (!Sorted); -} - -#define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset] - -void S9xSetST010(uint32 Address, uint8 Byte) -{ - if(!(Address&0x80000)) - { - ST010.control_enable=TRUE; - return; - } - //printf("Write %06X:%02X\n", Address, Byte); - - if((Address &0xFFF) ==0x20 && ST010.control_enable) - ST010.op_reg=Byte; - if((Address &0xFFF) ==0x21 && ST010.control_enable) - ST010.execute=Byte; - else Memory.SRAM[Address&CPU.Memory_SRAMMask]=Byte; - - if(ST010.execute&0x80) - { - switch(ST010.op_reg) - { - // Sorts Driver Placements - // - // Input - // 0x0024-0x0025 : Positions - // 0x0040-0x007f : Places - // 0x0080-0x00ff : Drivers - // Output - // 0x0040-0x007f : Places - // 0x0080-0x00ff : Drivers - // - case 0x02: - { -#ifdef FAST_LSB_WORD_ACCESS - ST010_SortDrivers(*(short*)&SRAM[0x0024], (uint16*) (SRAM + 0x0040), (uint16*) (SRAM + 0x0080)); -#else - uint16 Places[32]; - uint16 Positions = ST010_WORD(0x0024); - int Pos, Offset; - - Offset = 0; - - for (Pos = 0; Pos < Positions; Pos++) - { - Places[Pos] = ST010_WORD(0x0040 + Offset); - Offset += 2; - } - - ST010_SortDrivers(Positions, Places, (uint16*) (SRAM + 0x0080)); - - Offset = 0; - - for (Pos = 0; Pos < Positions; Pos++) - { - SRAM[0x0040 + Offset]=(uint8)(Places[Pos]); - SRAM[0x0041 + Offset]=(uint8)(Places[Pos] >> 8); - Offset += 2; - } -#endif - break; - - } - - // Two Dimensional Coordinate Scale - // - // Input - // 0x0000-0x0001 : X0 (signed) - // 0x0002-0x0003 : Y0 (signed) - // 0x0004-0x0005 : Multiplier (signed) - // Output - // 0x0010-0x0013 : X1 (signed) - // 0x0014-0x0017 : Y1 (signed) - // - case 0x03: - { -#ifdef FAST_LSB_WORD_ACCESS - ST010_Scale(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], - (int&) Memory.SRAM[0x0010], (int&) Memory.SRAM[0x0014]); -#else - int x1, y1; - - ST010_Scale(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); - - Memory.SRAM[0x0010]=(uint8)(x1); - Memory.SRAM[0x0011]=(uint8)(x1 >> 8); - Memory.SRAM[0x0012]=(uint8)(x1 >> 16); - Memory.SRAM[0x0013]=(uint8)(x1 >> 24); - Memory.SRAM[0x0014]=(uint8)(y1); - Memory.SRAM[0x0015]=(uint8)(y1 >> 8); - Memory.SRAM[0x0016]=(uint8)(y1 >> 16); - Memory.SRAM[0x0017]=(uint8)(y1 >> 24); -#endif - break; - } - - // 16-bit Multiplication - // - // Input - // 0x0000-0x0001 : Multiplcand (signed) - // 0x0002-0x0003 : Multiplier (signed) - // Output - // 0x0010-0x0013 : Product (signed) - // - case 0x06: - { -#ifdef FAST_LSB_WORD_ACCESS - ST010_Multiply(*(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], (int&) Memory.SRAM[0x0010]); -#else - int Product; - - ST010_Multiply(ST010_WORD(0x0000), ST010_WORD(0x0002), Product); - - Memory.SRAM[0x0010]=(uint8)(Product); - Memory.SRAM[0x0011]=(uint8)(Product >> 8); - Memory.SRAM[0x0012]=(uint8)(Product >> 16); - Memory.SRAM[0x0013]=(uint8)(Product >> 24); -#endif - break; - } - - // Mode 7 Raster Data Calculation - // - // Input - // 0x0000-0x0001 : Angle (signed) - // Output - // 0x00f0-0x024f : Mode 7 Matrix A - // 0x0250-0x03af : Mode 7 Matrix B - // 0x03b0-0x050f : Mode 7 Matrix C - // 0x0510-0x066f : Mode 7 Matrix D - // - case 0x07: - { - int16 data; - int32 offset = 0; - int16 Theta = ST010_WORD(0x0000); - - for (int32 line = 0; line < 176; line++) - { - // Calculate Mode 7 Matrix A/D data - data = ST010_M7Scale[line] * ST010_Cos(Theta) >> 15; - - Memory.SRAM[0x00f0 + offset]=(uint8)(data); - Memory.SRAM[0x00f1 + offset]=(uint8)(data >> 8); - Memory.SRAM[0x0510 + offset]=(uint8)(data); - Memory.SRAM[0x0511 + offset]=(uint8)(data >> 8); - - // Calculate Mode 7 Matrix B/C data - data = ST010_M7Scale[line] * ST010_Sin(Theta) >> 15; - - Memory.SRAM[0x0250 + offset]=(uint8)(data); - Memory.SRAM[0x0251 + offset]=(uint8)(data >> 8); - - if (data) data = ~data; - - Memory.SRAM[0x03b0 + offset]=(uint8)(data); - Memory.SRAM[0x03b1 + offset]=(uint8)(data >> 8); - - offset += 2; - } - - // Shift Angle for use with Lookup table - Memory.SRAM[0x00] = Memory.SRAM[0x01]; - Memory.SRAM[0x01] = 0x00; - - break; - } - - // Two dimensional Coordinate Rotation - // - // Input - // 0x0000-0x0001 : X0 (signed) - // 0x0002-0x0003 : Y0 (signed) - // 0x0004-0x0005 : Angle (signed) - // Output - // 0x0010-0x0011 : X1 (signed) - // 0x0012-0x0013 : Y1 (signed) - // - case 0x08: - { -#ifdef FAST_LSB_WORD_ACCESS - ST010_Rotate(*(short*)&Memory.SRAM[0x0004], *(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], - (short&) Memory.SRAM[0x0010], (short&) Memory.SRAM[0x0012]); -#else - short x1, y1; - - ST010_Rotate(ST010_WORD(0x0004), ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1); - - Memory.SRAM[0x0010]=(uint8)(x1); - Memory.SRAM[0x0011]=(uint8)(x1 >> 8); - Memory.SRAM[0x0012]=(uint8)(y1); - Memory.SRAM[0x0013]=(uint8)(y1 >> 8); -#endif - break; - } - - // Input - // 0x0000-0x0001 : DX (signed) - // 0x0002-0x0003 : DY (signed) - // Output - // 0x0010-0x0011 : Angle (signed) - // - case 0x01: - { - Memory.SRAM[0x0006] = Memory.SRAM[0x0002]; - Memory.SRAM[0x0007] = Memory.SRAM[0x0003]; - -#ifdef FAST_LSB_WORD_ACCESS - ST010_OP01(*(short*)&Memory.SRAM[0x0000], *(short*)&Memory.SRAM[0x0002], - (short&) Memory.SRAM[0x0000], (short&) Memory.SRAM[0x0002], - (short&) Memory.SRAM[0x0004], (short&) Memory.SRAM[0x0010]); -#else - short x1, y1, Quadrant, Theta; - - ST010_OP01(ST010_WORD(0x0000), ST010_WORD(0x0002), x1, y1, Quadrant, Theta); - - Memory.SRAM[0x0000]=(uint8)(x1); - Memory.SRAM[0x0001]=(uint8)(x1 >> 8); - Memory.SRAM[0x0002]=(uint8)(y1); - Memory.SRAM[0x0003]=(uint8)(y1 >> 8); - Memory.SRAM[0x0004]=(uint8)(Quadrant); - Memory.SRAM[0x0005]=(uint8)(Quadrant >> 8); - Memory.SRAM[0x0010]=(uint8)(Theta); - Memory.SRAM[0x0011]=(uint8)(Theta >> 8); -#endif - break; - } - - // calculate the vector length of (x,y) - case 0x04: - { - int16 square, x,y; -#ifdef FAST_LSB_WORD_ACCESS - x=*((int16*)Memory.SRAM); - y=*((int16*)&Memory.SRAM[2]); -#else - x=Memory.SRAM[0]|(Memory.SRAM[1]<<8); - y=Memory.SRAM[2]|(Memory.SRAM[3]<<8); -#endif - square=(int16)sqrt((double)(y*y+x*x)); - //SETA_Distance( x,y,square ); - -#ifdef FAST_LSB_WORD_ACCESS - *((int16*)&Memory.SRAM[0x10])=square; -#else - Memory.SRAM[0x10]=(uint8)(square); - Memory.SRAM[0x11]=(uint8)(square>>8); -#endif - break; - } - - // calculate AI orientation based on specific guidelines - case 0x05: - { - int dx,dy; - int16 a1,b1,c1; - uint16 o1; - - bool wrap=false; - - // target (x,y) coordinates - int16 ypos_max = ST010_WORD(0x00C0); - int16 xpos_max = ST010_WORD(0x00C2); - - // current coordinates and direction - int32 ypos = SRAM[0xC4]|(SRAM[0xC5]<<8)|(SRAM[0xC6]<<16)|(SRAM[0xC7]<<24); - int32 xpos = SRAM[0xC8]|(SRAM[0xC9]<<8)|(SRAM[0xCA]<<16)|(SRAM[0xCB]<<24); - uint16 rot = SRAM[0xCC]|(SRAM[0xCD]<<8); - - // physics - uint16 speed = ST010_WORD(0x00D4); - uint16 accel = ST010_WORD(0x00D6); - uint16 speed_max = ST010_WORD(0x00D8); - - // special condition acknowledgment - int16 system = ST010_WORD(0x00DA); - int16 flags = ST010_WORD(0x00DC); - - // new target coordinates - int16 ypos_new = ST010_WORD(0x00DE); - int16 xpos_new = ST010_WORD(0x00E0); - - // mask upper bit - xpos_new &= 0x7FFF; - - // get the current distance - dx = xpos_max-(xpos>>16); - dy = ypos_max-(ypos>>16); - - // quirk: clear and move in9 - SRAM[0xD2]=0xFF; - SRAM[0xD3]=0xFF; - SRAM[0xDA]=0; - SRAM[0xDB]=0; - - // grab the target angle - ST010_OP01(dy,dx,a1,b1,c1,(int16 &)o1); - - // check for wrapping - //if((o1<0x6000 && rot>0xA000) || - // (rot<0x6000 && o1>0xA000)) - //if(o10x8000) - { - o1+=0x8000; - rot+=0x8000; - wrap=true; - } - //o1=0x0000; - //rot=0xFF00; - - uint16 old_speed; - - old_speed = speed; - - // special case - if(abs(o1-rot)==0x8000) - { - speed = 0x100; - } - // slow down for sharp curves - else if(abs(o1-rot)>=0x1000) - { - uint32 slow = abs(o1-rot); - slow >>= 4; // scaling - speed -= slow; - } - // otherwise accelerate - else - { - speed += accel; - if(speed > speed_max) - { - // clip speed - speed = speed_max; - } - } - - // prevent negative/positive overflow - if(abs(old_speed-speed)>0x8000) { - if(old_speedrot && (o1-rot)>0x80) || - (o1=0x80) ) - { - if(o1rot) rot+=0x280; - } - - // turn off wrapping - if(wrap) rot-=0x8000; - - // now check the distances (store for later) - dx = (xpos_max<<16)-xpos; - dy = (ypos_max<<16)-ypos; - dx>>=16; - dy>>=16; - - // if we're in so many units of the target, signal it - if( ( system && (dy<=6 && dy>=-8) && (dx<=126 && dx>=-128)) || - (!system && (dx<=6 && dx>=-8) && (dy<=126 && dy>=-128)) ) - { - // announce our new destination and flag it - xpos_max = xpos_new&0x7FFF; - ypos_max = ypos_new; - flags |= 0x08; - } - - // update position - xpos -= (ST010_Cos(rot) * 0x400 >> 15) * (speed >> 8) << 1; - ypos -= (ST010_Sin(rot) * 0x400 >> 15) * (speed >> 8) << 1; - - // quirk: mask upper byte - xpos &= 0x1FFFFFFF; - ypos &= 0x1FFFFFFF; - - SRAM[0x00C0]=(uint8)(ypos_max); - SRAM[0x00C1]=(uint8)(ypos_max >> 8); - SRAM[0x00C2]=(uint8)(xpos_max); - SRAM[0x00C3]=(uint8)(xpos_max >> 8); - SRAM[0x00C4]=(uint8)(ypos); - SRAM[0x00C5]=(uint8)(ypos >> 8); - SRAM[0x00C6]=(uint8)(ypos >> 16); - SRAM[0x00C7]=(uint8)(ypos >> 24); - SRAM[0x00C8]=(uint8)(xpos); - SRAM[0x00C9]=(uint8)(xpos >> 8); - SRAM[0x00CA]=(uint8)(xpos >> 16); - SRAM[0x00CB]=(uint8)(xpos >> 24); - SRAM[0x00CC]=(uint8)(rot); - SRAM[0x00CD]=(uint8)(rot >> 8); - SRAM[0x00D4]=(uint8)(speed); - SRAM[0x00D5]=(uint8)(speed >> 8); - SRAM[0x00DC]=(uint8)(flags); - SRAM[0x00DD]=(uint8)(flags >> 8); - - break; - } - - default: - printf("Unknown Op\n"); - break; - } - - // lower signal: op processed - ST010.op_reg=0; - ST010.execute=0; - } -} - diff --git a/src/seta011.c b/src/seta011.c new file mode 100644 index 0000000..364e9ef --- /dev/null +++ b/src/seta011.c @@ -0,0 +1,233 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and distribute Snes9x in both binary and + source form, for non-commercial purposes, is hereby granted without fee, + providing that this license information and copyright notice appear with + all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes + charging money for Snes9x or software derived from Snes9x. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +*******************************************************************************/ +#include +#include "port.h" +#include "seta.h" +#include "memmap.h" + +ST011_Regs ST011; + +// shougi playboard +uint8 board[9][9]; + +// debug +static int line = 0; + +uint8 S9xGetST011(uint32 Address) +{ + uint8 t; + uint16 address = (uint16) Address & 0xFFFF; + + // line counter + line++; + + // status check + if (address == 0x01) + { + t = 0xFF; + } + // read directly from s-ram + else + { + t = Memory.SRAM[address]; + } + + // debug +// if(address<0x150) +// printf( "ST011 R: %06X %02X\n", Address, t); + + return t; +} + +void S9xSetST011(uint32 Address, uint8 Byte) +{ + uint16 address = (uint16) Address & 0xFFFF; + static bool reset = false; + + // debug + line++; + + if(!reset) + { + // bootup values + ST011.waiting4command = true; + reset = true; + } + + // debug +// if(address<0x150) +// printf( "ST011 W: %06X %02X\n", Address, Byte ); + + Memory.SRAM[address]=Byte; + + // op commands/data goes through this address + if(address==0x00) + { + // check for new commands + if (ST011.waiting4command) + { + ST011.waiting4command = false; + ST011.command = Byte; + ST011.in_index = 0; + ST011.out_index = 0; + switch(ST011.command) + { + case 0x01: ST011.in_count = 12*10+8; break; + case 0x02: ST011.in_count = 4; break; + case 0x04: ST011.in_count = 0; break; + case 0x05: ST011.in_count = 0; break; + case 0x06: ST011.in_count = 0; break; + case 0x07: ST011.in_count = 0; break; + case 0x0E: ST011.in_count = 0; break; + default: ST011.waiting4command=true; break; + } + } + else + { + ST011.parameters [ST011.in_index] = Byte; + ST011.in_index++; + } + } + + if (ST011.in_count==ST011.in_index) + { + // Actually execute the command + ST011.waiting4command = true; + ST011.out_index = 0; + switch (ST011.command) + { + // unknown: download playboard + case 0x01: + { + // 9x9 board data: top to bottom, left to right + // Values represent piece types and ownership + for( int lcv=0; lcv<9; lcv++ ) + memcpy( board[lcv], ST011.parameters+lcv*10, 9*1 ); + } + break; + + // unknown + case 0x02: break; + + // unknown + case 0x04: + { + // outputs + Memory.SRAM[0x12C] = 0x00; + //Memory.SRAM[0x12D] = 0x00; + Memory.SRAM[0x12E] = 0x00; + } + break; + + // unknown + case 0x05: + { + // outputs + Memory.SRAM[0x12C] = 0x00; + //Memory.SRAM[0x12D] = 0x00; + Memory.SRAM[0x12E] = 0x00; + } + break; + + // unknown + case 0x06: break; + case 0x07: break; + + // unknown + case 0x0E: + { + // outputs + Memory.SRAM[0x12C] = 0x00; + Memory.SRAM[0x12D] = 0x00; + } + break; + } + } +} + diff --git a/src/seta011.cpp b/src/seta011.cpp deleted file mode 100644 index 364e9ef..0000000 --- a/src/seta011.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ -#include -#include "port.h" -#include "seta.h" -#include "memmap.h" - -ST011_Regs ST011; - -// shougi playboard -uint8 board[9][9]; - -// debug -static int line = 0; - -uint8 S9xGetST011(uint32 Address) -{ - uint8 t; - uint16 address = (uint16) Address & 0xFFFF; - - // line counter - line++; - - // status check - if (address == 0x01) - { - t = 0xFF; - } - // read directly from s-ram - else - { - t = Memory.SRAM[address]; - } - - // debug -// if(address<0x150) -// printf( "ST011 R: %06X %02X\n", Address, t); - - return t; -} - -void S9xSetST011(uint32 Address, uint8 Byte) -{ - uint16 address = (uint16) Address & 0xFFFF; - static bool reset = false; - - // debug - line++; - - if(!reset) - { - // bootup values - ST011.waiting4command = true; - reset = true; - } - - // debug -// if(address<0x150) -// printf( "ST011 W: %06X %02X\n", Address, Byte ); - - Memory.SRAM[address]=Byte; - - // op commands/data goes through this address - if(address==0x00) - { - // check for new commands - if (ST011.waiting4command) - { - ST011.waiting4command = false; - ST011.command = Byte; - ST011.in_index = 0; - ST011.out_index = 0; - switch(ST011.command) - { - case 0x01: ST011.in_count = 12*10+8; break; - case 0x02: ST011.in_count = 4; break; - case 0x04: ST011.in_count = 0; break; - case 0x05: ST011.in_count = 0; break; - case 0x06: ST011.in_count = 0; break; - case 0x07: ST011.in_count = 0; break; - case 0x0E: ST011.in_count = 0; break; - default: ST011.waiting4command=true; break; - } - } - else - { - ST011.parameters [ST011.in_index] = Byte; - ST011.in_index++; - } - } - - if (ST011.in_count==ST011.in_index) - { - // Actually execute the command - ST011.waiting4command = true; - ST011.out_index = 0; - switch (ST011.command) - { - // unknown: download playboard - case 0x01: - { - // 9x9 board data: top to bottom, left to right - // Values represent piece types and ownership - for( int lcv=0; lcv<9; lcv++ ) - memcpy( board[lcv], ST011.parameters+lcv*10, 9*1 ); - } - break; - - // unknown - case 0x02: break; - - // unknown - case 0x04: - { - // outputs - Memory.SRAM[0x12C] = 0x00; - //Memory.SRAM[0x12D] = 0x00; - Memory.SRAM[0x12E] = 0x00; - } - break; - - // unknown - case 0x05: - { - // outputs - Memory.SRAM[0x12C] = 0x00; - //Memory.SRAM[0x12D] = 0x00; - Memory.SRAM[0x12E] = 0x00; - } - break; - - // unknown - case 0x06: break; - case 0x07: break; - - // unknown - case 0x0E: - { - // outputs - Memory.SRAM[0x12C] = 0x00; - Memory.SRAM[0x12D] = 0x00; - } - break; - } - } -} - diff --git a/src/seta018.c b/src/seta018.c new file mode 100644 index 0000000..5390a35 --- /dev/null +++ b/src/seta018.c @@ -0,0 +1,255 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://www.snes9x.com + + Permission to use, copy, modify and distribute Snes9x in both binary and + source form, for non-commercial purposes, is hereby granted without fee, + providing that this license information and copyright notice appear with + all copies and any derived work. + + This software is provided 'as-is', without any express or implied + warranty. In no event shall the authors be held liable for any damages + arising from the use of this software. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes + charging money for Snes9x or software derived from Snes9x. + + The copyright holders request that bug fixes and improvements to the code + should be forwarded to them so everyone can benefit from the modifications + in future versions. + + Super NES and Super Nintendo Entertainment System are trademarks of + Nintendo Co., Limited and its subsidiary companies. +*******************************************************************************/ +#include "memmap.h" +#include "seta.h" +//#include "port.h" + +ST018_Regs ST018; + +static int line; // line counter + +extern "C"{ +uint8 S9xGetST018(uint32 Address) +{ + uint8 t = 0; + uint16 address = (uint16) Address & 0xFFFF; + + line++; + + // these roles may be flipped + // op output + if (address == 0x3804) + { + if (ST018.out_count) + { + t = (uint8) ST018.output [ST018.out_index]; + ST018.out_index++; + if (ST018.out_count==ST018.out_index) + ST018.out_count=0; + } + else + t = 0x81; + } + // status register + else if (address == 0x3800) + t = ST018.status; + + printf( "ST018 R: %06X %02X\n", Address, t); + + return t; +} + +void S9xSetST018(uint8 Byte, uint32 Address) +{ + uint16 address = (uint16) Address&0xFFFF; + static bool reset = false; + + printf( "ST018 W: %06X %02X\n", Address, Byte ); + + line++; + + if (!reset) + { + // bootup values + ST018.waiting4command = true; + ST018.part_command = 0; + reset = true; + } + + Memory.SRAM[address]=Byte; + + // default status for now + ST018.status = 0x00; + + // op data goes through this address + if (address==0x3804) + { + // check for new commands: 3 bytes length + if(ST018.waiting4command && ST018.part_command==2) + { + ST018.waiting4command = false; + ST018.command <<= 8; + ST018.command |= Byte; + ST018.in_index = 0; + ST018.out_index = 0; + ST018.part_command = 0; // 3-byte commands + ST018.pass = 0; // data streams into the chip + switch(ST018.command & 0xFFFFFF) + { + case 0x0100: ST018.in_count = 0; break; + case 0xFF00: ST018.in_count = 0; break; + default: ST018.waiting4command = true; break; + } + } + else if(ST018.waiting4command) + { + // 3-byte commands + ST018.part_command++; + ST018.command <<= 8; + ST018.command |= Byte; + } + } + // extra parameters + else if (address==0x3802) + { + ST018.parameters[ST018.in_index] = Byte; + ST018.in_index++; + } + + if (ST018.in_count==ST018.in_index) + { + // Actually execute the command + ST018.waiting4command = true; + ST018.in_index = 0; + ST018.out_index = 0; + switch (ST018.command) + { + // hardware check? + case 0x0100: + ST018.waiting4command = false; + ST018.pass++; + if (ST018.pass==1) + { + ST018.in_count = 1; + ST018.out_count = 2; + + // Overload's research + ST018.output[0x00] = 0x81; + ST018.output[0x01] = 0x81; + } + else + { + //ST018.in_count = 1; + ST018.out_count = 3; + + // no reason to change this + //ST018.output[0x00] = 0x81; + //ST018.output[0x01] = 0x81; + ST018.output[0x02] = 0x81; + + // done processing requests + if (ST018.pass==3) + ST018.waiting4command = true; + } + break; + + // unknown: feels like a security detection + // format identical to 0x0100 + case 0xFF00: + ST018.waiting4command = false; + ST018.pass++; + if (ST018.pass==1) + { + ST018.in_count = 1; + ST018.out_count = 2; + + // Overload's research + ST018.output[0x00] = 0x81; + ST018.output[0x01] = 0x81; + } + else + { + //ST018.in_count = 1; + ST018.out_count = 3; + + // no reason to change this + //ST018.output[0x00] = 0x81; + //ST018.output[0x01] = 0x81; + ST018.output[0x02] = 0x81; + + // done processing requests + if (ST018.pass==3) + ST018.waiting4command = true; + } + break; + } + } +} +} + diff --git a/src/seta018.cpp b/src/seta018.cpp deleted file mode 100644 index 5390a35..0000000 --- a/src/seta018.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ -#include "memmap.h" -#include "seta.h" -//#include "port.h" - -ST018_Regs ST018; - -static int line; // line counter - -extern "C"{ -uint8 S9xGetST018(uint32 Address) -{ - uint8 t = 0; - uint16 address = (uint16) Address & 0xFFFF; - - line++; - - // these roles may be flipped - // op output - if (address == 0x3804) - { - if (ST018.out_count) - { - t = (uint8) ST018.output [ST018.out_index]; - ST018.out_index++; - if (ST018.out_count==ST018.out_index) - ST018.out_count=0; - } - else - t = 0x81; - } - // status register - else if (address == 0x3800) - t = ST018.status; - - printf( "ST018 R: %06X %02X\n", Address, t); - - return t; -} - -void S9xSetST018(uint8 Byte, uint32 Address) -{ - uint16 address = (uint16) Address&0xFFFF; - static bool reset = false; - - printf( "ST018 W: %06X %02X\n", Address, Byte ); - - line++; - - if (!reset) - { - // bootup values - ST018.waiting4command = true; - ST018.part_command = 0; - reset = true; - } - - Memory.SRAM[address]=Byte; - - // default status for now - ST018.status = 0x00; - - // op data goes through this address - if (address==0x3804) - { - // check for new commands: 3 bytes length - if(ST018.waiting4command && ST018.part_command==2) - { - ST018.waiting4command = false; - ST018.command <<= 8; - ST018.command |= Byte; - ST018.in_index = 0; - ST018.out_index = 0; - ST018.part_command = 0; // 3-byte commands - ST018.pass = 0; // data streams into the chip - switch(ST018.command & 0xFFFFFF) - { - case 0x0100: ST018.in_count = 0; break; - case 0xFF00: ST018.in_count = 0; break; - default: ST018.waiting4command = true; break; - } - } - else if(ST018.waiting4command) - { - // 3-byte commands - ST018.part_command++; - ST018.command <<= 8; - ST018.command |= Byte; - } - } - // extra parameters - else if (address==0x3802) - { - ST018.parameters[ST018.in_index] = Byte; - ST018.in_index++; - } - - if (ST018.in_count==ST018.in_index) - { - // Actually execute the command - ST018.waiting4command = true; - ST018.in_index = 0; - ST018.out_index = 0; - switch (ST018.command) - { - // hardware check? - case 0x0100: - ST018.waiting4command = false; - ST018.pass++; - if (ST018.pass==1) - { - ST018.in_count = 1; - ST018.out_count = 2; - - // Overload's research - ST018.output[0x00] = 0x81; - ST018.output[0x01] = 0x81; - } - else - { - //ST018.in_count = 1; - ST018.out_count = 3; - - // no reason to change this - //ST018.output[0x00] = 0x81; - //ST018.output[0x01] = 0x81; - ST018.output[0x02] = 0x81; - - // done processing requests - if (ST018.pass==3) - ST018.waiting4command = true; - } - break; - - // unknown: feels like a security detection - // format identical to 0x0100 - case 0xFF00: - ST018.waiting4command = false; - ST018.pass++; - if (ST018.pass==1) - { - ST018.in_count = 1; - ST018.out_count = 2; - - // Overload's research - ST018.output[0x00] = 0x81; - ST018.output[0x01] = 0x81; - } - else - { - //ST018.in_count = 1; - ST018.out_count = 3; - - // no reason to change this - //ST018.output[0x00] = 0x81; - //ST018.output[0x01] = 0x81; - ST018.output[0x02] = 0x81; - - // done processing requests - if (ST018.pass==3) - ST018.waiting4command = true; - } - break; - } - } -} -} - diff --git a/src/snaporig.c b/src/snaporig.c new file mode 100644 index 0000000..3ede5af --- /dev/null +++ b/src/snaporig.c @@ -0,0 +1,411 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include +#include +#include + +#if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) +//#include +#include +#include +#endif + +#include "snapshot.h" +#include "snaporig.h" +#include "memmap.h" +#include "snes9x.h" +#include "65c816.h" +#include "ppu.h" +#include "cpuexec.h" +#include "display.h" +#include "apu.h" +#include "soundux.h" + +struct SOrigPPU OrigPPU; +struct SOrigDMA OrigDMA [8]; +struct SOrigRegisters OrigRegisters; +struct SOrigCPUState OrigCPU; +struct SOrigAPU OrigAPU; +SOrigSoundData OrigSoundData; +struct SOrigAPURegisters OrigAPURegisters; +char ROMFilename [1025]; + +static int ReadOrigSnapshot (STREAM); + +bool8_32 S9xLoadOrigSnapshot (const char *filename) +{ + STREAM snapshot = NULL; + if (S9xOpenSnapshotFile (filename, TRUE, &snapshot)) + { + int result; + if ((result = ReadOrigSnapshot (snapshot)) != SUCCESS) + { + S9xCloseSnapshotFile (snapshot); + return (FALSE); + } + S9xCloseSnapshotFile (snapshot); + return (TRUE); + } + return (FALSE); +} + +static int ReadBlock (const char *key, void *block, int max_len, STREAM snap) +{ + char buffer [20]; + int len = 0; + int rem = 0; + + if (READ_STREAM (buffer, 11, snap) != 11 || + strncmp (buffer, key, 4) != 0 || + (len = atoi (&buffer [4])) == 0) + return (WRONG_FORMAT); + + if (len > max_len) + { + rem = len - max_len; + len = max_len; + } + if (READ_STREAM (block, len, snap) != len) + return (WRONG_FORMAT); + + if (rem) + { + char *junk = new char [rem]; + READ_STREAM (junk, rem, snap); + delete junk; + } + + return (SUCCESS); +} + +static int ReadOrigSnapshot (STREAM snap) +{ + char buffer [_MAX_PATH]; + char rom_filename [_MAX_PATH]; + int result; + int i; + int j; + + int version; + int len = strlen (ORIG_SNAPSHOT_MAGIC) + 1 + 4 + 1; + if (READ_STREAM (buffer, len, snap) != len) + return (WRONG_FORMAT); + if (strncmp (buffer, ORIG_SNAPSHOT_MAGIC, strlen (ORIG_SNAPSHOT_MAGIC)) != 0) + return (WRONG_FORMAT); + if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > ORIG_SNAPSHOT_VERSION) + return (WRONG_VERSION); + + if ((result = ReadBlock ("NAM:", rom_filename, _MAX_PATH, snap)) != SUCCESS) + return (result); + + if ((result = ReadBlock ("HiR:", buffer, 0x41, snap)) != SUCCESS) + return (result); + + if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 && + strcasecmp (S9xBasename (rom_filename), S9xBasename (Memory.ROMFilename)) != 0) + { + S9xMessage (S9X_WARNING, S9X_FREEZE_ROM_NAME, + "Current loaded ROM image doesn't match that required by freeze-game file."); + } + + S9xReset (); + S9xSetSoundMute (TRUE); + if ((result = ReadBlock ("CPU:", &OrigCPU, sizeof (OrigCPU), snap)) != SUCCESS) + return (result); + OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old; + Memory.FixROMSpeed (); + if (version == 3) + { + OrigCPU.Cycles = OrigCPU.Cycles_old; + OrigCPU.NextEvent = OrigCPU.NextEvent_old; + OrigCPU.V_Counter = OrigCPU.V_Counter_old; + OrigCPU.MemSpeed = OrigCPU.MemSpeed_old; + OrigCPU.MemSpeedx2 = OrigCPU.MemSpeedx2_old; + OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old; + } + CPU.Flags = OrigCPU.Flags; + CPU.BranchSkip = OrigCPU.BranchSkip; + CPU.NMIActive = OrigCPU.NMIActive; + CPU.IRQActive = OrigCPU.IRQActive; + CPU.WaitingForInterrupt = OrigCPU.WaitingForInterrupt; + CPU.WhichEvent = OrigCPU.WhichEvent; + CPU.Cycles = OrigCPU.Cycles; + CPU.NextEvent = OrigCPU.NextEvent; + CPU.V_Counter = OrigCPU.V_Counter; + CPU.MemSpeed = OrigCPU.MemSpeed; + CPU.MemSpeedx2 = OrigCPU.MemSpeedx2; + CPU.FastROMSpeed = OrigCPU.FastROMSpeed; + + if ((result = ReadBlock ("REG:", &OrigRegisters, sizeof (OrigRegisters), snap)) != SUCCESS) + return (result); + + Registers = *(struct SRegisters *) &OrigRegisters; + + if ((result = ReadBlock ("PPU:", &OrigPPU, sizeof (OrigPPU), snap)) != SUCCESS) + return (result); + + if (version == 2) + { + OrigPPU.OBJNameSelect = OrigPPU.OBJNameSelect_old << 13; + OrigPPU.OBJNameBase <<= 1; + OrigPPU.OBJNameSelect <<= 13; + } + PPU.BGMode = OrigPPU.BGMode; + PPU.BG3Priority = OrigPPU.BG3Priority; + PPU.Brightness = OrigPPU.Brightness; + + PPU.VMA.High = OrigPPU.VMA.High; + PPU.VMA.Increment = OrigPPU.VMA.Increment; + PPU.VMA.Address = OrigPPU.VMA.Address; + PPU.VMA.Mask1 = OrigPPU.VMA.Mask1; + PPU.VMA.FullGraphicCount = OrigPPU.VMA.FullGraphicCount; + PPU.VMA.Shift = OrigPPU.VMA.Shift; + + for (i = 0; i < 4; i++) + { + PPU.BG[i].SCBase = OrigPPU.BG[i].SCBase; + PPU.BG[i].VOffset = OrigPPU.BG[i].VOffset; + PPU.BG[i].HOffset = OrigPPU.BG[i].HOffset; + PPU.BG[i].BGSize = OrigPPU.BG[i].BGSize; + PPU.BG[i].NameBase = OrigPPU.BG[i].NameBase; + PPU.BG[i].SCSize = OrigPPU.BG[i].SCSize; + } + + PPU.CGFLIP = OrigPPU.CGFLIP; + for (i = 0; i < 256; i++) + PPU.CGDATA [i] = OrigPPU.CGDATA [i]; + PPU.FirstSprite = OrigPPU.FirstSprite; + for (i = 0; i < 128; i++) + { + PPU.OBJ[i].HPos = OrigPPU.OBJ [i].HPos; + PPU.OBJ[i].VPos = OrigPPU.OBJ [i].VPos; + PPU.OBJ[i].Name = OrigPPU.OBJ [i].Name; + PPU.OBJ[i].VFlip = OrigPPU.OBJ [i].VFlip; + PPU.OBJ[i].HFlip = OrigPPU.OBJ [i].HFlip; + PPU.OBJ[i].Priority = OrigPPU.OBJ [i].Priority; + PPU.OBJ[i].Palette = OrigPPU.OBJ [i].Palette; + PPU.OBJ[i].Size = OrigPPU.OBJ [i].Size; + } + PPU.OAMPriorityRotation = OrigPPU.OAMPriorityRotation; + PPU.OAMAddr = OrigPPU.OAMAddr; + + PPU.OAMFlip = OrigPPU.OAMFlip; + PPU.OAMTileAddress = OrigPPU.OAMTileAddress; + PPU.IRQVBeamPos = OrigPPU.IRQVBeamPos; + PPU.IRQHBeamPos = OrigPPU.IRQHBeamPos; + PPU.VBeamPosLatched = OrigPPU.VBeamPosLatched; + PPU.HBeamPosLatched = OrigPPU.HBeamPosLatched; + + PPU.HBeamFlip = OrigPPU.HBeamFlip; + PPU.VBeamFlip = OrigPPU.VBeamFlip; + PPU.HVBeamCounterLatched = OrigPPU.HVBeamCounterLatched; + + PPU.MatrixA = OrigPPU.MatrixA; + PPU.MatrixB = OrigPPU.MatrixB; + PPU.MatrixC = OrigPPU.MatrixC; + PPU.MatrixD = OrigPPU.MatrixD; + PPU.CentreX = OrigPPU.CentreX; + PPU.CentreY = OrigPPU.CentreY; + PPU.Joypad1ButtonReadPos = OrigPPU.Joypad1ButtonReadPos; + PPU.Joypad2ButtonReadPos = OrigPPU.Joypad2ButtonReadPos; + PPU.Joypad3ButtonReadPos = OrigPPU.Joypad3ButtonReadPos; + + PPU.CGADD = OrigPPU.CGADD; + PPU.FixedColourRed = OrigPPU.FixedColourRed; + PPU.FixedColourGreen = OrigPPU.FixedColourGreen; + PPU.FixedColourBlue = OrigPPU.FixedColourBlue; + PPU.SavedOAMAddr = OrigPPU.SavedOAMAddr; + PPU.ScreenHeight = OrigPPU.ScreenHeight; + PPU.WRAM = OrigPPU.WRAM; + PPU.ForcedBlanking = OrigPPU.ForcedBlanking; + PPU.OBJNameSelect = OrigPPU.OBJNameSelect; + PPU.OBJSizeSelect = OrigPPU.OBJSizeSelect; + PPU.OBJNameBase = OrigPPU.OBJNameBase; + PPU.OAMReadFlip = OrigPPU.OAMReadFlip; + memmove (PPU.OAMData, OrigPPU.OAMData, sizeof (PPU.OAMData)); + PPU.VTimerEnabled = OrigPPU.VTimerEnabled; + PPU.HTimerEnabled = OrigPPU.HTimerEnabled; + PPU.HTimerPosition = OrigPPU.HTimerPosition; + PPU.Mosaic = OrigPPU.Mosaic; + memmove (PPU.BGMosaic, OrigPPU.BGMosaic, sizeof (PPU.BGMosaic)); + PPU.Mode7HFlip = OrigPPU.Mode7HFlip; + PPU.Mode7VFlip = OrigPPU.Mode7VFlip; + PPU.Mode7Repeat = OrigPPU.Mode7Repeat; + PPU.Window1Left = OrigPPU.Window1Left; + PPU.Window1Right = OrigPPU.Window1Right; + PPU.Window2Left = OrigPPU.Window2Left; + PPU.Window2Right = OrigPPU.Window2Right; + for (i = 0; i < 6; i++) + { + PPU.ClipWindowOverlapLogic [i] = OrigPPU.ClipWindowOverlapLogic [i]; + PPU.ClipWindow1Enable [i] = OrigPPU.ClipWindow1Enable [i]; + PPU.ClipWindow2Enable [i] = OrigPPU.ClipWindow2Enable [i]; + PPU.ClipWindow1Inside [i] = OrigPPU.ClipWindow1Inside [i]; + PPU.ClipWindow2Inside [i] = OrigPPU.ClipWindow2Inside [i]; + } + PPU.CGFLIPRead = OrigPPU.CGFLIPRead; + PPU.Need16x8Mulitply = OrigPPU.Need16x8Mulitply; + + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; + S9xFixColourBrightness (); + IPPU.RenderThisFrame = FALSE; + + if ((result = ReadBlock ("DMA:", OrigDMA, sizeof (OrigDMA), snap)) != SUCCESS) + return (result); + + for (i = 0; i < 8; i++) + { + DMA[i].TransferDirection = OrigDMA[i].TransferDirection; + DMA[i].AAddressFixed = OrigDMA[i].AAddressFixed; + DMA[i].AAddressDecrement = OrigDMA[i].AAddressDecrement; + DMA[i].TransferMode = OrigDMA[i].TransferMode; + DMA[i].ABank = OrigDMA[i].ABank; + DMA[i].AAddress = OrigDMA[i].AAddress; + DMA[i].Address = OrigDMA[i].Address; + DMA[i].BAddress = OrigDMA[i].BAddress; + DMA[i].TransferBytes = OrigDMA[i].TransferBytes; + DMA[i].HDMAIndirectAddressing = OrigDMA[i].HDMAIndirectAddressing; + DMA[i].IndirectAddress = OrigDMA[i].IndirectAddress; + DMA[i].IndirectBank = OrigDMA[i].IndirectBank; + DMA[i].Repeat = OrigDMA[i].Repeat; + DMA[i].LineCount = OrigDMA[i].LineCount; + DMA[i].FirstLine = OrigDMA[i].FirstLine; + } + + if ((result = ReadBlock ("VRA:", Memory.VRAM, 0x10000, snap)) != SUCCESS) + return (result); + if ((result = ReadBlock ("RAM:", Memory.RAM, 0x20000, snap)) != SUCCESS) + return (result); + if ((result = ReadBlock ("SRA:", SRAM, 0x10000, snap)) != SUCCESS) + return (result); + if ((result = ReadBlock ("FIL:", Memory.FillRAM, 0x8000, snap)) != SUCCESS) + return (result); + if (ReadBlock ("APU:", &OrigAPU, sizeof (OrigAPU), snap) == SUCCESS) + { + APU = *(struct SAPU *) &OrigAPU; + + if ((result = ReadBlock ("ARE:", &OrigAPURegisters, + sizeof (OrigAPURegisters), snap)) != SUCCESS) + return (result); + APURegisters = *(struct SAPURegisters *) &OrigAPURegisters; + if ((result = ReadBlock ("ARA:", IAPU.RAM, 0x10000, snap)) != SUCCESS) + return (result); + if ((result = ReadBlock ("SOU:", &OrigSoundData, + sizeof (SOrigSoundData), snap)) != SUCCESS) + return (result); + + SoundData.master_volume_left = OrigSoundData.master_volume_left; + SoundData.master_volume_right = OrigSoundData.master_volume_right; + SoundData.echo_volume_left = OrigSoundData.echo_volume_left; + SoundData.echo_volume_right = OrigSoundData.echo_volume_right; + SoundData.echo_enable = OrigSoundData.echo_enable; + SoundData.echo_feedback = OrigSoundData.echo_feedback; + SoundData.echo_ptr = OrigSoundData.echo_ptr; + SoundData.echo_buffer_size = OrigSoundData.echo_buffer_size; + SoundData.echo_write_enabled = OrigSoundData.echo_write_enabled; + SoundData.echo_channel_enable = OrigSoundData.echo_channel_enable; + SoundData.pitch_mod = OrigSoundData.pitch_mod; + + for (i = 0; i < 3; i++) + SoundData.dummy [i] = OrigSoundData.dummy [i]; + for (i = 0; i < NUM_CHANNELS; i++) + { + SoundData.channels [i].state = OrigSoundData.channels [i].state; + SoundData.channels [i].type = OrigSoundData.channels [i].type; + SoundData.channels [i].volume_left = OrigSoundData.channels [i].volume_left; + SoundData.channels [i].volume_right = OrigSoundData.channels [i].volume_right; + SoundData.channels [i].hertz = OrigSoundData.channels [i].frequency; + SoundData.channels [i].count = OrigSoundData.channels [i].count; + SoundData.channels [i].loop = OrigSoundData.channels [i].loop; + SoundData.channels [i].envx = OrigSoundData.channels [i].envx; + SoundData.channels [i].left_vol_level = OrigSoundData.channels [i].left_vol_level; + SoundData.channels [i].right_vol_level = OrigSoundData.channels [i].right_vol_level; + SoundData.channels [i].envx_target = OrigSoundData.channels [i].envx_target; + SoundData.channels [i].env_error = OrigSoundData.channels [i].env_error; + SoundData.channels [i].erate = OrigSoundData.channels [i].erate; + SoundData.channels [i].direction = OrigSoundData.channels [i].direction; + SoundData.channels [i].attack_rate = OrigSoundData.channels [i].attack_rate; + SoundData.channels [i].decay_rate = OrigSoundData.channels [i].decay_rate; + SoundData.channels [i].sustain_rate = OrigSoundData.channels [i].sustain_rate; + SoundData.channels [i].release_rate = OrigSoundData.channels [i].release_rate; + SoundData.channels [i].sustain_level = OrigSoundData.channels [i].sustain_level; + SoundData.channels [i].sample = OrigSoundData.channels [i].sample; + for (j = 0; j < 16; j++) + SoundData.channels [i].decoded [j] = OrigSoundData.channels [i].decoded [j]; + + for (j = 0; j < 2; j++) + SoundData.channels [i].previous [j] = OrigSoundData.channels [i].previous [j]; + + SoundData.channels [i].sample_number = OrigSoundData.channels [i].sample_number; + SoundData.channels [i].last_block = OrigSoundData.channels [i].last_block; + SoundData.channels [i].needs_decode = OrigSoundData.channels [i].needs_decode; + SoundData.channels [i].block_pointer = OrigSoundData.channels [i].block_pointer; + SoundData.channels [i].sample_pointer = OrigSoundData.channels [i].sample_pointer; + SoundData.channels [i].mode = OrigSoundData.channels [i].mode; + } + + S9xSetSoundMute (FALSE); + IAPU.PC = IAPU.RAM + IAPU.PC; + S9xAPUUnpackStatus (); + if (APUCheckDirectPage ()) + IAPU.DirectPage = IAPU.RAM + 0x100; + else + IAPU.DirectPage = IAPU.RAM; + Settings.APUEnabled = TRUE; + CPU.APU_APUExecuting = TRUE; + } + else + { + Settings.APUEnabled = FALSE; + CPU.APU_APUExecuting = FALSE; + S9xSetSoundMute (TRUE); + } + S9xFixSoundAfterSnapshotLoad (); + ICPU.ShiftedPB = Registers.PB << 16; + ICPU.ShiftedDB = Registers.DB << 16; + S9xSetPCBase (ICPU.ShiftedPB + Registers.PC, &CPU); + S9xUnpackStatus (); + S9xFixCycles (&Registers, &ICPU); + S9xReschedule (); + + return (SUCCESS); +} diff --git a/src/snaporig.cpp b/src/snaporig.cpp deleted file mode 100644 index 26ee8b7..0000000 --- a/src/snaporig.cpp +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include -#include -#include - -#if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) -//#include -#include -#include -#endif - -#include "snapshot.h" -#include "snaporig.h" -#include "memmap.h" -#include "snes9x.h" -#include "65c816.h" -#include "ppu.h" -#include "cpuexec.h" -#include "display.h" -#include "apu.h" -#include "soundux.h" - -struct SOrigPPU OrigPPU; -struct SOrigDMA OrigDMA [8]; -struct SOrigRegisters OrigRegisters; -struct SOrigCPUState OrigCPU; -struct SOrigAPU OrigAPU; -SOrigSoundData OrigSoundData; -struct SOrigAPURegisters OrigAPURegisters; -char ROMFilename [1025]; - -static int ReadOrigSnapshot (STREAM); - -bool8_32 S9xLoadOrigSnapshot (const char *filename) -{ - STREAM snapshot = NULL; - if (S9xOpenSnapshotFile (filename, TRUE, &snapshot)) - { - int result; - if ((result = ReadOrigSnapshot (snapshot)) != SUCCESS) - { - S9xCloseSnapshotFile (snapshot); - return (FALSE); - } - S9xCloseSnapshotFile (snapshot); - return (TRUE); - } - return (FALSE); -} - -static int ReadBlock (const char *key, void *block, int max_len, STREAM snap) -{ - char buffer [20]; - int len = 0; - int rem = 0; - - if (READ_STREAM (buffer, 11, snap) != 11 || - strncmp (buffer, key, 4) != 0 || - (len = atoi (&buffer [4])) == 0) - return (WRONG_FORMAT); - - if (len > max_len) - { - rem = len - max_len; - len = max_len; - } - if (READ_STREAM (block, len, snap) != len) - return (WRONG_FORMAT); - - if (rem) - { - char *junk = new char [rem]; - READ_STREAM (junk, rem, snap); - delete junk; - } - - return (SUCCESS); -} - -static int ReadOrigSnapshot (STREAM snap) -{ - char buffer [_MAX_PATH]; - char rom_filename [_MAX_PATH]; - int result; - int i; - int j; - - int version; - int len = strlen (ORIG_SNAPSHOT_MAGIC) + 1 + 4 + 1; - if (READ_STREAM (buffer, len, snap) != len) - return (WRONG_FORMAT); - if (strncmp (buffer, ORIG_SNAPSHOT_MAGIC, strlen (ORIG_SNAPSHOT_MAGIC)) != 0) - return (WRONG_FORMAT); - if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > ORIG_SNAPSHOT_VERSION) - return (WRONG_VERSION); - - if ((result = ReadBlock ("NAM:", rom_filename, _MAX_PATH, snap)) != SUCCESS) - return (result); - - if ((result = ReadBlock ("HiR:", buffer, 0x41, snap)) != SUCCESS) - return (result); - - if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 && - strcasecmp (S9xBasename (rom_filename), S9xBasename (Memory.ROMFilename)) != 0) - { - S9xMessage (S9X_WARNING, S9X_FREEZE_ROM_NAME, - "Current loaded ROM image doesn't match that required by freeze-game file."); - } - - S9xReset (); - S9xSetSoundMute (TRUE); - if ((result = ReadBlock ("CPU:", &OrigCPU, sizeof (OrigCPU), snap)) != SUCCESS) - return (result); - OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old; - Memory.FixROMSpeed (); - if (version == 3) - { - OrigCPU.Cycles = OrigCPU.Cycles_old; - OrigCPU.NextEvent = OrigCPU.NextEvent_old; - OrigCPU.V_Counter = OrigCPU.V_Counter_old; - OrigCPU.MemSpeed = OrigCPU.MemSpeed_old; - OrigCPU.MemSpeedx2 = OrigCPU.MemSpeedx2_old; - OrigCPU.FastROMSpeed = OrigCPU.FastROMSpeed_old; - } - CPU.Flags = OrigCPU.Flags; - CPU.BranchSkip = OrigCPU.BranchSkip; - CPU.NMIActive = OrigCPU.NMIActive; - CPU.IRQActive = OrigCPU.IRQActive; - CPU.WaitingForInterrupt = OrigCPU.WaitingForInterrupt; - CPU.WhichEvent = OrigCPU.WhichEvent; - CPU.Cycles = OrigCPU.Cycles; - CPU.NextEvent = OrigCPU.NextEvent; - CPU.V_Counter = OrigCPU.V_Counter; - CPU.MemSpeed = OrigCPU.MemSpeed; - CPU.MemSpeedx2 = OrigCPU.MemSpeedx2; - CPU.FastROMSpeed = OrigCPU.FastROMSpeed; - - if ((result = ReadBlock ("REG:", &OrigRegisters, sizeof (OrigRegisters), snap)) != SUCCESS) - return (result); - - Registers = *(struct SRegisters *) &OrigRegisters; - - if ((result = ReadBlock ("PPU:", &OrigPPU, sizeof (OrigPPU), snap)) != SUCCESS) - return (result); - - if (version == 2) - { - OrigPPU.OBJNameSelect = OrigPPU.OBJNameSelect_old << 13; - OrigPPU.OBJNameBase <<= 1; - OrigPPU.OBJNameSelect <<= 13; - } - PPU.BGMode = OrigPPU.BGMode; - PPU.BG3Priority = OrigPPU.BG3Priority; - PPU.Brightness = OrigPPU.Brightness; - - PPU.VMA.High = OrigPPU.VMA.High; - PPU.VMA.Increment = OrigPPU.VMA.Increment; - PPU.VMA.Address = OrigPPU.VMA.Address; - PPU.VMA.Mask1 = OrigPPU.VMA.Mask1; - PPU.VMA.FullGraphicCount = OrigPPU.VMA.FullGraphicCount; - PPU.VMA.Shift = OrigPPU.VMA.Shift; - - for (i = 0; i < 4; i++) - { - PPU.BG[i].SCBase = OrigPPU.BG[i].SCBase; - PPU.BG[i].VOffset = OrigPPU.BG[i].VOffset; - PPU.BG[i].HOffset = OrigPPU.BG[i].HOffset; - PPU.BG[i].BGSize = OrigPPU.BG[i].BGSize; - PPU.BG[i].NameBase = OrigPPU.BG[i].NameBase; - PPU.BG[i].SCSize = OrigPPU.BG[i].SCSize; - } - - PPU.CGFLIP = OrigPPU.CGFLIP; - for (i = 0; i < 256; i++) - PPU.CGDATA [i] = OrigPPU.CGDATA [i]; - PPU.FirstSprite = OrigPPU.FirstSprite; - for (i = 0; i < 128; i++) - { - PPU.OBJ[i].HPos = OrigPPU.OBJ [i].HPos; - PPU.OBJ[i].VPos = OrigPPU.OBJ [i].VPos; - PPU.OBJ[i].Name = OrigPPU.OBJ [i].Name; - PPU.OBJ[i].VFlip = OrigPPU.OBJ [i].VFlip; - PPU.OBJ[i].HFlip = OrigPPU.OBJ [i].HFlip; - PPU.OBJ[i].Priority = OrigPPU.OBJ [i].Priority; - PPU.OBJ[i].Palette = OrigPPU.OBJ [i].Palette; - PPU.OBJ[i].Size = OrigPPU.OBJ [i].Size; - } - PPU.OAMPriorityRotation = OrigPPU.OAMPriorityRotation; - PPU.OAMAddr = OrigPPU.OAMAddr; - - PPU.OAMFlip = OrigPPU.OAMFlip; - PPU.OAMTileAddress = OrigPPU.OAMTileAddress; - PPU.IRQVBeamPos = OrigPPU.IRQVBeamPos; - PPU.IRQHBeamPos = OrigPPU.IRQHBeamPos; - PPU.VBeamPosLatched = OrigPPU.VBeamPosLatched; - PPU.HBeamPosLatched = OrigPPU.HBeamPosLatched; - - PPU.HBeamFlip = OrigPPU.HBeamFlip; - PPU.VBeamFlip = OrigPPU.VBeamFlip; - PPU.HVBeamCounterLatched = OrigPPU.HVBeamCounterLatched; - - PPU.MatrixA = OrigPPU.MatrixA; - PPU.MatrixB = OrigPPU.MatrixB; - PPU.MatrixC = OrigPPU.MatrixC; - PPU.MatrixD = OrigPPU.MatrixD; - PPU.CentreX = OrigPPU.CentreX; - PPU.CentreY = OrigPPU.CentreY; - PPU.Joypad1ButtonReadPos = OrigPPU.Joypad1ButtonReadPos; - PPU.Joypad2ButtonReadPos = OrigPPU.Joypad2ButtonReadPos; - PPU.Joypad3ButtonReadPos = OrigPPU.Joypad3ButtonReadPos; - - PPU.CGADD = OrigPPU.CGADD; - PPU.FixedColourRed = OrigPPU.FixedColourRed; - PPU.FixedColourGreen = OrigPPU.FixedColourGreen; - PPU.FixedColourBlue = OrigPPU.FixedColourBlue; - PPU.SavedOAMAddr = OrigPPU.SavedOAMAddr; - PPU.ScreenHeight = OrigPPU.ScreenHeight; - PPU.WRAM = OrigPPU.WRAM; - PPU.ForcedBlanking = OrigPPU.ForcedBlanking; - PPU.OBJNameSelect = OrigPPU.OBJNameSelect; - PPU.OBJSizeSelect = OrigPPU.OBJSizeSelect; - PPU.OBJNameBase = OrigPPU.OBJNameBase; - PPU.OAMReadFlip = OrigPPU.OAMReadFlip; - memmove (PPU.OAMData, OrigPPU.OAMData, sizeof (PPU.OAMData)); - PPU.VTimerEnabled = OrigPPU.VTimerEnabled; - PPU.HTimerEnabled = OrigPPU.HTimerEnabled; - PPU.HTimerPosition = OrigPPU.HTimerPosition; - PPU.Mosaic = OrigPPU.Mosaic; - memmove (PPU.BGMosaic, OrigPPU.BGMosaic, sizeof (PPU.BGMosaic)); - PPU.Mode7HFlip = OrigPPU.Mode7HFlip; - PPU.Mode7VFlip = OrigPPU.Mode7VFlip; - PPU.Mode7Repeat = OrigPPU.Mode7Repeat; - PPU.Window1Left = OrigPPU.Window1Left; - PPU.Window1Right = OrigPPU.Window1Right; - PPU.Window2Left = OrigPPU.Window2Left; - PPU.Window2Right = OrigPPU.Window2Right; - for (i = 0; i < 6; i++) - { - PPU.ClipWindowOverlapLogic [i] = OrigPPU.ClipWindowOverlapLogic [i]; - PPU.ClipWindow1Enable [i] = OrigPPU.ClipWindow1Enable [i]; - PPU.ClipWindow2Enable [i] = OrigPPU.ClipWindow2Enable [i]; - PPU.ClipWindow1Inside [i] = OrigPPU.ClipWindow1Inside [i]; - PPU.ClipWindow2Inside [i] = OrigPPU.ClipWindow2Inside [i]; - } - PPU.CGFLIPRead = OrigPPU.CGFLIPRead; - PPU.Need16x8Mulitply = OrigPPU.Need16x8Mulitply; - - IPPU.ColorsChanged = TRUE; - IPPU.OBJChanged = TRUE; - S9xFixColourBrightness (); - IPPU.RenderThisFrame = FALSE; - - if ((result = ReadBlock ("DMA:", OrigDMA, sizeof (OrigDMA), snap)) != SUCCESS) - return (result); - - for (i = 0; i < 8; i++) - { - DMA[i].TransferDirection = OrigDMA[i].TransferDirection; - DMA[i].AAddressFixed = OrigDMA[i].AAddressFixed; - DMA[i].AAddressDecrement = OrigDMA[i].AAddressDecrement; - DMA[i].TransferMode = OrigDMA[i].TransferMode; - DMA[i].ABank = OrigDMA[i].ABank; - DMA[i].AAddress = OrigDMA[i].AAddress; - DMA[i].Address = OrigDMA[i].Address; - DMA[i].BAddress = OrigDMA[i].BAddress; - DMA[i].TransferBytes = OrigDMA[i].TransferBytes; - DMA[i].HDMAIndirectAddressing = OrigDMA[i].HDMAIndirectAddressing; - DMA[i].IndirectAddress = OrigDMA[i].IndirectAddress; - DMA[i].IndirectBank = OrigDMA[i].IndirectBank; - DMA[i].Repeat = OrigDMA[i].Repeat; - DMA[i].LineCount = OrigDMA[i].LineCount; - DMA[i].FirstLine = OrigDMA[i].FirstLine; - } - - if ((result = ReadBlock ("VRA:", Memory.VRAM, 0x10000, snap)) != SUCCESS) - return (result); - if ((result = ReadBlock ("RAM:", Memory.RAM, 0x20000, snap)) != SUCCESS) - return (result); - if ((result = ReadBlock ("SRA:", ::SRAM, 0x10000, snap)) != SUCCESS) - return (result); - if ((result = ReadBlock ("FIL:", Memory.FillRAM, 0x8000, snap)) != SUCCESS) - return (result); - if (ReadBlock ("APU:", &OrigAPU, sizeof (OrigAPU), snap) == SUCCESS) - { - APU = *(struct SAPU *) &OrigAPU; - - if ((result = ReadBlock ("ARE:", &OrigAPURegisters, - sizeof (OrigAPURegisters), snap)) != SUCCESS) - return (result); - APURegisters = *(struct SAPURegisters *) &OrigAPURegisters; - if ((result = ReadBlock ("ARA:", IAPU.RAM, 0x10000, snap)) != SUCCESS) - return (result); - if ((result = ReadBlock ("SOU:", &OrigSoundData, - sizeof (SOrigSoundData), snap)) != SUCCESS) - return (result); - - SoundData.master_volume_left = OrigSoundData.master_volume_left; - SoundData.master_volume_right = OrigSoundData.master_volume_right; - SoundData.echo_volume_left = OrigSoundData.echo_volume_left; - SoundData.echo_volume_right = OrigSoundData.echo_volume_right; - SoundData.echo_enable = OrigSoundData.echo_enable; - SoundData.echo_feedback = OrigSoundData.echo_feedback; - SoundData.echo_ptr = OrigSoundData.echo_ptr; - SoundData.echo_buffer_size = OrigSoundData.echo_buffer_size; - SoundData.echo_write_enabled = OrigSoundData.echo_write_enabled; - SoundData.echo_channel_enable = OrigSoundData.echo_channel_enable; - SoundData.pitch_mod = OrigSoundData.pitch_mod; - - for (i = 0; i < 3; i++) - SoundData.dummy [i] = OrigSoundData.dummy [i]; - for (i = 0; i < NUM_CHANNELS; i++) - { - SoundData.channels [i].state = OrigSoundData.channels [i].state; - SoundData.channels [i].type = OrigSoundData.channels [i].type; - SoundData.channels [i].volume_left = OrigSoundData.channels [i].volume_left; - SoundData.channels [i].volume_right = OrigSoundData.channels [i].volume_right; - SoundData.channels [i].hertz = OrigSoundData.channels [i].frequency; - SoundData.channels [i].count = OrigSoundData.channels [i].count; - SoundData.channels [i].loop = OrigSoundData.channels [i].loop; - SoundData.channels [i].envx = OrigSoundData.channels [i].envx; - SoundData.channels [i].left_vol_level = OrigSoundData.channels [i].left_vol_level; - SoundData.channels [i].right_vol_level = OrigSoundData.channels [i].right_vol_level; - SoundData.channels [i].envx_target = OrigSoundData.channels [i].envx_target; - SoundData.channels [i].env_error = OrigSoundData.channels [i].env_error; - SoundData.channels [i].erate = OrigSoundData.channels [i].erate; - SoundData.channels [i].direction = OrigSoundData.channels [i].direction; - SoundData.channels [i].attack_rate = OrigSoundData.channels [i].attack_rate; - SoundData.channels [i].decay_rate = OrigSoundData.channels [i].decay_rate; - SoundData.channels [i].sustain_rate = OrigSoundData.channels [i].sustain_rate; - SoundData.channels [i].release_rate = OrigSoundData.channels [i].release_rate; - SoundData.channels [i].sustain_level = OrigSoundData.channels [i].sustain_level; - SoundData.channels [i].sample = OrigSoundData.channels [i].sample; - for (j = 0; j < 16; j++) - SoundData.channels [i].decoded [j] = OrigSoundData.channels [i].decoded [j]; - - for (j = 0; j < 2; j++) - SoundData.channels [i].previous [j] = OrigSoundData.channels [i].previous [j]; - - SoundData.channels [i].sample_number = OrigSoundData.channels [i].sample_number; - SoundData.channels [i].last_block = OrigSoundData.channels [i].last_block; - SoundData.channels [i].needs_decode = OrigSoundData.channels [i].needs_decode; - SoundData.channels [i].block_pointer = OrigSoundData.channels [i].block_pointer; - SoundData.channels [i].sample_pointer = OrigSoundData.channels [i].sample_pointer; - SoundData.channels [i].mode = OrigSoundData.channels [i].mode; - } - - S9xSetSoundMute (FALSE); - IAPU.PC = IAPU.RAM + IAPU.PC; - S9xAPUUnpackStatus (); - if (APUCheckDirectPage ()) - IAPU.DirectPage = IAPU.RAM + 0x100; - else - IAPU.DirectPage = IAPU.RAM; - Settings.APUEnabled = TRUE; - CPU.APU_APUExecuting = TRUE; - } - else - { - Settings.APUEnabled = FALSE; - CPU.APU_APUExecuting = FALSE; - S9xSetSoundMute (TRUE); - } - S9xFixSoundAfterSnapshotLoad (); - ICPU.ShiftedPB = Registers.PB << 16; - ICPU.ShiftedDB = Registers.DB << 16; - S9xSetPCBase (ICPU.ShiftedPB + Registers.PC, &CPU); - S9xUnpackStatus (); - S9xFixCycles (&Registers, &ICPU); - S9xReschedule (); - - return (SUCCESS); -} diff --git a/src/snapshot.c b/src/snapshot.c new file mode 100644 index 0000000..c44610c --- /dev/null +++ b/src/snapshot.c @@ -0,0 +1,945 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +#ifndef __GP32__ +#include +#include +#include +#endif +#if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) +#include +#include +#include +#endif + +#include "snapshot.h" +//#include "snaporig.h" +#include "memmap.h" +#include "snes9x.h" +#include "65c816.h" +#include "ppu.h" +#include "cpuexec.h" +#include "display.h" +#include "apu.h" +#include "soundux.h" +#ifdef USE_SA1 +#include "sa1.h" +#endif +#include "srtc.h" +#include "sdd1.h" + + +// notaz: file i/o function pointers for states, +// changing funcs will allow to enable/disable gzipped saves +extern int (*statef_open)(const char *fname, const char *mode); +extern int (*statef_read)(void *p, int l); +extern int (*statef_write)(void *p, int l); +extern void (*statef_close)(); + +extern uint8 *SRAM; + +#ifdef ZSNES_FX +START_EXTERN_C +void S9xSuperFXPreSaveState (); +void S9xSuperFXPostSaveState (); +void S9xSuperFXPostLoadState (); +END_EXTERN_C +#endif + +//bool8 S9xUnfreezeZSNES (const char *filename); + +typedef struct { + int offset; + int size; + int type; +} FreezeData; + +enum { + INT_V, uint8_ARRAY_V, uint16_ARRAY_V, uint32_ARRAY_V +}; + +#define Offset(field,structure) \ + ((int) (((char *) (&(((structure)NULL)->field))) - ((char *) NULL))) + +#define COUNT(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0])) + +#undef OFFSET +#define OFFSET(f) Offset(f, SCPUState *) + +static FreezeData SnapCPU [] = { + {OFFSET (Flags), 4, INT_V}, + {OFFSET (BranchSkip), 1, INT_V}, + {OFFSET (NMIActive), 1, INT_V}, + {OFFSET (IRQActive), 1, INT_V}, + {OFFSET (WaitingForInterrupt), 1, INT_V}, + {OFFSET (WhichEvent), 1, INT_V}, + {OFFSET (Cycles), 4, INT_V}, + {OFFSET (NextEvent), 4, INT_V}, + {OFFSET (V_Counter), 4, INT_V}, + {OFFSET (MemSpeed), 4, INT_V}, + {OFFSET (MemSpeedx2), 4, INT_V}, + {OFFSET (FastROMSpeed), 4, INT_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f, SRegisters *) + +static FreezeData SnapRegisters [] = { + {OFFSET (PB), 1, INT_V}, + {OFFSET (DB), 1, INT_V}, + {OFFSET (P.W), 2, INT_V}, + {OFFSET (A.W), 2, INT_V}, + {OFFSET (D.W), 2, INT_V}, + {OFFSET (S.W), 2, INT_V}, + {OFFSET (X.W), 2, INT_V}, + {OFFSET (Y.W), 2, INT_V}, + {OFFSET (PC), 2, INT_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f, SPPU *) + +static FreezeData SnapPPU [] = { + {OFFSET (BGMode), 1, INT_V}, + {OFFSET (BG3Priority), 1, INT_V}, + {OFFSET (Brightness), 1, INT_V}, + {OFFSET (VMA.High), 1, INT_V}, + {OFFSET (VMA.Increment), 1, INT_V}, + {OFFSET (VMA.Address), 2, INT_V}, + {OFFSET (VMA.Mask1), 2, INT_V}, + {OFFSET (VMA.FullGraphicCount), 2, INT_V}, + {OFFSET (VMA.Shift), 2, INT_V}, + {OFFSET (BG[0].SCBase), 2, INT_V}, + {OFFSET (BG[0].VOffset), 2, INT_V}, + {OFFSET (BG[0].HOffset), 2, INT_V}, + {OFFSET (BG[0].BGSize), 1, INT_V}, + {OFFSET (BG[0].NameBase), 2, INT_V}, + {OFFSET (BG[0].SCSize), 2, INT_V}, + + {OFFSET (BG[1].SCBase), 2, INT_V}, + {OFFSET (BG[1].VOffset), 2, INT_V}, + {OFFSET (BG[1].HOffset), 2, INT_V}, + {OFFSET (BG[1].BGSize), 1, INT_V}, + {OFFSET (BG[1].NameBase), 2, INT_V}, + {OFFSET (BG[1].SCSize), 2, INT_V}, + + {OFFSET (BG[2].SCBase), 2, INT_V}, + {OFFSET (BG[2].VOffset), 2, INT_V}, + {OFFSET (BG[2].HOffset), 2, INT_V}, + {OFFSET (BG[2].BGSize), 1, INT_V}, + {OFFSET (BG[2].NameBase), 2, INT_V}, + {OFFSET (BG[2].SCSize), 2, INT_V}, + + {OFFSET (BG[3].SCBase), 2, INT_V}, + {OFFSET (BG[3].VOffset), 2, INT_V}, + {OFFSET (BG[3].HOffset), 2, INT_V}, + {OFFSET (BG[3].BGSize), 1, INT_V}, + {OFFSET (BG[3].NameBase), 2, INT_V}, + {OFFSET (BG[3].SCSize), 2, INT_V}, + + {OFFSET (CGFLIP), 1, INT_V}, + {OFFSET (CGDATA), 256, uint16_ARRAY_V}, + {OFFSET (FirstSprite), 1, INT_V}, +#define O(N) \ + {OFFSET (OBJ[N].HPos), 2, INT_V}, \ + {OFFSET (OBJ[N].VPos), 2, INT_V}, \ + {OFFSET (OBJ[N].Name), 2, INT_V}, \ + {OFFSET (OBJ[N].VFlip), 1, INT_V}, \ + {OFFSET (OBJ[N].HFlip), 1, INT_V}, \ + {OFFSET (OBJ[N].Priority), 1, INT_V}, \ + {OFFSET (OBJ[N].Palette), 1, INT_V}, \ + {OFFSET (OBJ[N].Size), 1, INT_V} + + O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), + O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), + O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), + O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31), + O( 32), O( 33), O( 34), O( 35), O( 36), O( 37), O( 38), O( 39), + O( 40), O( 41), O( 42), O( 43), O( 44), O( 45), O( 46), O( 47), + O( 48), O( 49), O( 50), O( 51), O( 52), O( 53), O( 54), O( 55), + O( 56), O( 57), O( 58), O( 59), O( 60), O( 61), O( 62), O( 63), + O( 64), O( 65), O( 66), O( 67), O( 68), O( 69), O( 70), O( 71), + O( 72), O( 73), O( 74), O( 75), O( 76), O( 77), O( 78), O( 79), + O( 80), O( 81), O( 82), O( 83), O( 84), O( 85), O( 86), O( 87), + O( 88), O( 89), O( 90), O( 91), O( 92), O( 93), O( 94), O( 95), + O( 96), O( 97), O( 98), O( 99), O(100), O(101), O(102), O(103), + O(104), O(105), O(106), O(107), O(108), O(109), O(110), O(111), + O(112), O(113), O(114), O(115), O(116), O(117), O(118), O(119), + O(120), O(121), O(122), O(123), O(124), O(125), O(126), O(127), +#undef O + {OFFSET (OAMPriorityRotation), 1, INT_V}, + {OFFSET (OAMAddr), 2, INT_V}, + {OFFSET (OAMFlip), 1, INT_V}, + {OFFSET (OAMTileAddress), 2, INT_V}, + {OFFSET (IRQVBeamPos), 2, INT_V}, + {OFFSET (IRQHBeamPos), 2, INT_V}, + {OFFSET (VBeamPosLatched), 2, INT_V}, + {OFFSET (HBeamPosLatched), 2, INT_V}, + {OFFSET (HBeamFlip), 1, INT_V}, + {OFFSET (VBeamFlip), 1, INT_V}, + {OFFSET (HVBeamCounterLatched), 1, INT_V}, + {OFFSET (MatrixA), 2, INT_V}, + {OFFSET (MatrixB), 2, INT_V}, + {OFFSET (MatrixC), 2, INT_V}, + {OFFSET (MatrixD), 2, INT_V}, + {OFFSET (CentreX), 2, INT_V}, + {OFFSET (CentreY), 2, INT_V}, + {OFFSET (Joypad1ButtonReadPos), 1, INT_V}, + {OFFSET (Joypad2ButtonReadPos), 1, INT_V}, + {OFFSET (Joypad3ButtonReadPos), 1, INT_V}, + {OFFSET (CGADD), 1, INT_V}, + {OFFSET (FixedColourRed), 1, INT_V}, + {OFFSET (FixedColourGreen), 1, INT_V}, + {OFFSET (FixedColourBlue), 1, INT_V}, + {OFFSET (SavedOAMAddr), 2, INT_V}, + {OFFSET (ScreenHeight), 2, INT_V}, + {OFFSET (WRAM), 4, INT_V}, + {OFFSET (ForcedBlanking), 1, INT_V}, + {OFFSET (OBJNameSelect), 2, INT_V}, + {OFFSET (OBJSizeSelect), 1, INT_V}, + {OFFSET (OBJNameBase), 2, INT_V}, + {OFFSET (OAMReadFlip), 1, INT_V}, + {OFFSET (VTimerEnabled), 1, INT_V}, + {OFFSET (HTimerEnabled), 1, INT_V}, + {OFFSET (HTimerPosition), 2, INT_V}, + {OFFSET (Mosaic), 1, INT_V}, + {OFFSET (Mode7HFlip), 1, INT_V}, + {OFFSET (Mode7VFlip), 1, INT_V}, + {OFFSET (Mode7Repeat), 1, INT_V}, + {OFFSET (Window1Left), 1, INT_V}, + {OFFSET (Window1Right), 1, INT_V}, + {OFFSET (Window2Left), 1, INT_V}, + {OFFSET (Window2Right), 1, INT_V}, +#define O(N) \ + {OFFSET (ClipWindowOverlapLogic[N]), 1, INT_V}, \ + {OFFSET (ClipWindow1Enable[N]), 1, INT_V}, \ + {OFFSET (ClipWindow2Enable[N]), 1, INT_V}, \ + {OFFSET (ClipWindow1Inside[N]), 1, INT_V}, \ + {OFFSET (ClipWindow2Inside[N]), 1, INT_V} + + O(0), O(1), O(2), O(3), O(4), O(5), + +#undef O + + {OFFSET (CGFLIPRead), 1, INT_V}, + {OFFSET (Need16x8Mulitply), 1, INT_V}, + {OFFSET (BGMosaic), 4, uint8_ARRAY_V}, + {OFFSET (OAMData), 512 + 32, uint8_ARRAY_V}, + {OFFSET (Need16x8Mulitply), 1, INT_V}, + {OFFSET (MouseSpeed), 2, uint8_ARRAY_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f, SDMA *) + +static FreezeData SnapDMA [] = { +#define O(N) \ + {OFFSET (TransferDirection) + N * sizeof ( SDMA), 1, INT_V}, \ + {OFFSET (AAddressFixed) + N * sizeof ( SDMA), 1, INT_V}, \ + {OFFSET (AAddressDecrement) + N * sizeof ( SDMA), 1, INT_V}, \ + {OFFSET (TransferMode) + N * sizeof ( SDMA), 1, INT_V}, \ + {OFFSET (ABank) + N * sizeof ( SDMA), 1, INT_V}, \ + {OFFSET (AAddress) + N * sizeof ( SDMA), 2, INT_V}, \ + {OFFSET (Address) + N * sizeof ( SDMA), 2, INT_V}, \ + {OFFSET (BAddress) + N * sizeof ( SDMA), 1, INT_V}, \ + {OFFSET (TransferBytes) + N * sizeof ( SDMA), 2, INT_V}, \ + {OFFSET (HDMAIndirectAddressing) + N * sizeof ( SDMA), 1, INT_V}, \ + {OFFSET (IndirectAddress) + N * sizeof ( SDMA), 2, INT_V}, \ + {OFFSET (IndirectBank) + N * sizeof ( SDMA), 1, INT_V}, \ + {OFFSET (Repeat) + N * sizeof ( SDMA), 1, INT_V}, \ + {OFFSET (LineCount) + N * sizeof ( SDMA), 1, INT_V}, \ + {OFFSET (FirstLine) + N * sizeof ( SDMA), 1, INT_V} + + O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) +#undef O +}; + +#undef OFFSET +#define OFFSET(f) Offset(f, SAPU *) + +static FreezeData SnapAPU [] = { + {OFFSET (Cycles), 4, INT_V}, + {OFFSET (ShowROM), 1, INT_V}, + {OFFSET (Flags), 1, INT_V}, + {OFFSET (KeyedChannels), 1, INT_V}, + {OFFSET (OutPorts), 4, uint8_ARRAY_V}, + {OFFSET (DSP), 0x80, uint8_ARRAY_V}, + {OFFSET (ExtraRAM), 64, uint8_ARRAY_V}, + {OFFSET (Timer), 3, uint16_ARRAY_V}, + {OFFSET (TimerTarget), 3, uint16_ARRAY_V}, + {OFFSET (TimerEnabled), 3, uint8_ARRAY_V}, + {OFFSET (TimerValueWritten), 3, uint8_ARRAY_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f, SAPURegisters *) + +static FreezeData SnapAPURegisters [] = { + {OFFSET (P) , 1, INT_V}, + {OFFSET (YA.W), 2, INT_V}, + {OFFSET (X) , 1, INT_V}, + {OFFSET (S) , 1, INT_V}, + {OFFSET (PC) , 2, INT_V} +}; + +#undef OFFSET +#undef OFFSET1 +#define OFFSET(f) Offset(f,SSoundData *) + +static FreezeData SnapSoundData [] = { + {OFFSET (master_volume_left), 2, INT_V}, + {OFFSET (master_volume_right), 2, INT_V}, + {OFFSET (echo_volume_left), 2, INT_V}, + {OFFSET (echo_volume_right), 2, INT_V}, + {OFFSET (echo_enable), 4, INT_V}, + {OFFSET (echo_feedback), 4, INT_V}, + {OFFSET (echo_ptr), 4, INT_V}, + {OFFSET (echo_buffer_size), 4, INT_V}, + {OFFSET (echo_write_enabled), 4, INT_V}, + {OFFSET (echo_channel_enable), 4, INT_V}, + {OFFSET (pitch_mod), 4, INT_V}, + {OFFSET (dummy), 3, uint32_ARRAY_V}, +#define O(N) \ + {OFFSET (channels [N].state), 4, INT_V}, \ + {OFFSET (channels [N].type), 4, INT_V}, \ + {OFFSET (channels [N].volume_left), 2, INT_V}, \ + {OFFSET (channels [N].volume_right), 2, INT_V}, \ + {OFFSET (channels [N].hertz), 4, INT_V}, \ + {OFFSET (channels [N].count), 4, INT_V}, \ + {OFFSET (channels [N].loop), 1, INT_V}, \ + {OFFSET (channels [N].envx), 4, INT_V}, \ + {OFFSET (channels [N].left_vol_level), 2, INT_V}, \ + {OFFSET (channels [N].right_vol_level), 2, INT_V}, \ + {OFFSET (channels [N].envx_target), 2, INT_V}, \ + {OFFSET (channels [N].env_error), 4, INT_V}, \ + {OFFSET (channels [N].erate), 4, INT_V}, \ + {OFFSET (channels [N].direction), 4, INT_V}, \ + {OFFSET (channels [N].attack_rate), 4, INT_V}, \ + {OFFSET (channels [N].decay_rate), 4, INT_V}, \ + {OFFSET (channels [N].sustain_rate), 4, INT_V}, \ + {OFFSET (channels [N].release_rate), 4, INT_V}, \ + {OFFSET (channels [N].sustain_level), 4, INT_V}, \ + {OFFSET (channels [N].sample), 2, INT_V}, \ + {OFFSET (channels [N].decoded), 16, uint16_ARRAY_V}, \ + {OFFSET (channels [N].previous16), 2, uint16_ARRAY_V}, \ + {OFFSET (channels [N].sample_number), 2, INT_V}, \ + {OFFSET (channels [N].last_block), 1, INT_V}, \ + {OFFSET (channels [N].needs_decode), 1, INT_V}, \ + {OFFSET (channels [N].block_pointer), 4, INT_V}, \ + {OFFSET (channels [N].sample_pointer), 4, INT_V}, \ + {OFFSET (channels [N].mode), 4, INT_V} + + O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) +#undef O +}; + +#ifdef USE_SA1 + +#undef OFFSET +#define OFFSET(f) Offset(f, SSA1Registers *) + +static FreezeData SnapSA1Registers [] = { + {OFFSET (PB), 1, INT_V}, + {OFFSET (DB), 1, INT_V}, + {OFFSET (P.W), 2, INT_V}, + {OFFSET (A.W), 2, INT_V}, + {OFFSET (D.W), 2, INT_V}, + {OFFSET (S.W), 2, INT_V}, + {OFFSET (X.W), 2, INT_V}, + {OFFSET (Y.W), 2, INT_V}, + {OFFSET (PC), 2, INT_V} +}; + +#undef OFFSET +#define OFFSET(f) Offset(f, SSA1 *) + +static FreezeData SnapSA1 [] = { + {OFFSET (Flags), 4, INT_V}, + {OFFSET (NMIActive), 1, INT_V}, + {OFFSET (IRQActive), 1, INT_V}, + {OFFSET (WaitingForInterrupt), 1, INT_V}, + {OFFSET (op1), 2, INT_V}, + {OFFSET (op2), 2, INT_V}, + {OFFSET (arithmetic_op), 4, INT_V}, + {OFFSET (sum), 8, INT_V}, + {OFFSET (overflow), 1, INT_V} +}; +#endif + +//static char ROMFilename [_MAX_PATH]; +//static char SnapshotFilename [_MAX_PATH]; + +static void Freeze (); +static int Unfreeze (); +void FreezeStruct (char *name, void *base, FreezeData *fields, + int num_fields); +void FreezeBlock (char *name, uint8 *block, int size); + +int UnfreezeStruct (char *name, void *base, FreezeData *fields, + int num_fields); +int UnfreezeBlock (char *name, uint8 *block, int size); + +bool8 Snapshot (const char *filename) +{ + return (S9xFreezeGame (filename)); +} + +bool8 S9xFreezeGame (const char *filename) +{ + if(statef_open(filename, "wb")) + { + Freeze(); + statef_close(); + return (TRUE); + } + return (FALSE); +} + + +bool8 S9xUnfreezeGame (const char *filename) +{ + if(statef_open(filename, "rb")) + { + int result; + if ((result = Unfreeze()) != SUCCESS) + { + switch (result) + { + case WRONG_FORMAT: + S9xMessage (S9X_ERROR, S9X_WRONG_FORMAT, + "File not in Snes9x freeze format"); + S9xReset(); + break; + case WRONG_VERSION: + S9xMessage (S9X_ERROR, S9X_WRONG_VERSION, + "Incompatable Snes9x freeze file format version"); + S9xReset(); + break; + default: + // should never happen + break; + } + statef_close(); + return (FALSE); + } + statef_close(); + return (TRUE); + } + + + return (FALSE); +} + +static void Freeze () +{ + char buffer[1024]; + int i; + + S9xSetSoundMute (TRUE); +#ifdef ZSNES_FX + if (Settings.SuperFX) + S9xSuperFXPreSaveState (); +#endif + + S9xSRTCPreSaveState (); + + for (i = 0; i < 8; i++) + { + SoundData.channels [i].previous16 [0] = (int16) SoundData.channels [i].previous [0]; + SoundData.channels [i].previous16 [1] = (int16) SoundData.channels [i].previous [1]; + } + sprintf (buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); + statef_write(buffer, strlen (buffer)); + sprintf (buffer, "NAM:%06d:%s%c", strlen (Memory.ROMFilename) + 1, + Memory.ROMFilename, 0); + statef_write(buffer, strlen (buffer) + 1); + FreezeStruct ("CPU", &CPU, SnapCPU, COUNT (SnapCPU)); + FreezeStruct ("REG", &Registers, SnapRegisters, COUNT (SnapRegisters)); + FreezeStruct ("PPU", &PPU, SnapPPU, COUNT (SnapPPU)); + FreezeStruct ("DMA", DMA, SnapDMA, COUNT (SnapDMA)); + +// RAM and VRAM + FreezeBlock ("VRA", Memory.VRAM, 0x10000); + FreezeBlock ("RAM", Memory.RAM, 0x20000); + FreezeBlock ("SRA", SRAM, 0x20000); + FreezeBlock ("FIL", Memory.FillRAM, 0x8000); + if (Settings.APUEnabled) + { +// APU + FreezeStruct ("APU", &APU, SnapAPU, COUNT (SnapAPU)); + // copy all SPC700 regs to savestate compatible struct + SAPURegisters spcregs; + spcregs.P = IAPU.P; + spcregs.YA.W = IAPU.YA.W; + spcregs.X = IAPU.X; + spcregs.S = IAPU.S; + spcregs.PC = IAPU.PC - IAPU.RAM; + FreezeStruct ("ARE", &spcregs, SnapAPURegisters, + COUNT (SnapAPURegisters)); + + FreezeBlock ("ARA", IAPU.RAM, 0x10000); + FreezeStruct ("SOU", &SoundData, SnapSoundData, + COUNT (SnapSoundData)); + } +#ifdef USE_SA1 + if (Settings.SA1) + { + SA1Registers.PC = SA1.PC - SA1.PCBase; + S9xSA1PackStatus (); + FreezeStruct ("SA1", &SA1, SnapSA1, COUNT (SnapSA1)); + FreezeStruct ("SAR", &SA1Registers, SnapSA1Registers, + COUNT (SnapSA1Registers)); + } +#endif + S9xSetSoundMute (FALSE); +#ifdef ZSNES_FX + if (Settings.SuperFX) + S9xSuperFXPostSaveState (); +#endif +} + +static int Unfreeze() +{ + // notaz: overflowing the damn Symbian stack again + char buffer [16]; + char rom_filename [512]; + int result; + + int version; + + unsigned int len = strlen (SNAPSHOT_MAGIC) + 1 + 4 + 1; + if (statef_read(buffer, len) != (int)len) + { + return (WRONG_FORMAT); + } + if (strncmp (buffer, SNAPSHOT_MAGIC, strlen (SNAPSHOT_MAGIC)) != 0) + { + return (WRONG_FORMAT); + } + if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > SNAPSHOT_VERSION) + return (WRONG_VERSION); + + if ((result = UnfreezeBlock("NAM", (uint8 *) rom_filename, 512)) != SUCCESS) + return (result); + + if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 && + strcasecmp (S9xBasename (rom_filename), S9xBasename (Memory.ROMFilename)) != 0) + { + S9xMessage (S9X_WARNING, S9X_FREEZE_ROM_NAME, + "Current loaded ROM image doesn't match that required by freeze-game file."); + } + + + + uint32 old_flags = CPU.Flags; +#ifdef USE_SA1 + uint32 sa1_old_flags = SA1.Flags; +#endif + S9xReset (); + S9xSetSoundMute (TRUE); + + if ((result = UnfreezeStruct("CPU", &CPU, SnapCPU, + COUNT (SnapCPU))) != SUCCESS) + return (result); + + + FixROMSpeed (); + CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | + SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); + if ((result = UnfreezeStruct("REG", &Registers, SnapRegisters, COUNT (SnapRegisters))) != SUCCESS) + return (result); + if ((result = UnfreezeStruct("PPU", &PPU, SnapPPU, COUNT (SnapPPU))) != SUCCESS) + return (result); + + + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; + CPU.InDMA = FALSE; + // Restore colors from PPU + for (unsigned int i = 0; i < 256; i++) { + IPPU.Red[i] = PPU.CGDATA[i] & 0x1f; + IPPU.Green[i] = (PPU.CGDATA[i] >> 5) & 0x1f; + IPPU.Blue[i] = (PPU.CGDATA[i] >> 10) & 0x1f; + } + + S9xFixColourBrightness (); + IPPU.RenderThisFrame = FALSE; + + if ((result = UnfreezeStruct ("DMA", DMA, SnapDMA, + COUNT (SnapDMA))) != SUCCESS) + return (result); + + if ((result = UnfreezeBlock ("VRA", Memory.VRAM, 0x10000)) != SUCCESS) + return (result); + + if ((result = UnfreezeBlock ("RAM", Memory.RAM, 0x20000)) != SUCCESS) + return (result); + + if ((result = UnfreezeBlock ("SRA", SRAM, 0x20000)) != SUCCESS) + return (result); + + if ((result = UnfreezeBlock ("FIL", Memory.FillRAM, 0x8000)) != SUCCESS) + return (result); + + // Restore graphics shadow registers + GFX.r212c_s = Memory.FillRAM[0x212c]; + GFX.r212d_s = Memory.FillRAM[0x212d]; + GFX.r212e_s = Memory.FillRAM[0x212e]; + GFX.r212f_s = Memory.FillRAM[0x212f]; + GFX.r2130_s = Memory.FillRAM[0x2130]; + GFX.r2131_s = Memory.FillRAM[0x2131]; + + if (UnfreezeStruct ("APU", &APU, SnapAPU, COUNT (SnapAPU)) == SUCCESS) + { + SAPURegisters spcregs; + if ((result = UnfreezeStruct ("ARE", &spcregs, SnapAPURegisters, + COUNT (SnapAPURegisters))) != SUCCESS) + return (result); + // reload all SPC700 regs from savestate compatible struct + IAPU.P = spcregs.P; + IAPU.YA.W = spcregs.YA.W; + IAPU.X = spcregs.X; + IAPU.S = spcregs.S; + IAPU.PC = IAPU.RAM + spcregs.PC; + + if ((result = UnfreezeBlock ("ARA", IAPU.RAM, 0x10000)) != SUCCESS) + return (result); + + if ((result = UnfreezeStruct ("SOU", &SoundData, SnapSoundData, + COUNT (SnapSoundData))) != SUCCESS) + return (result); + + // notaz: just to be sure + for(int u=0; u<8; u++) { + SoundData.channels[u].env_ind_attack &= 0xf; + SoundData.channels[u].env_ind_decay &= 0x7; + SoundData.channels[u].env_ind_sustain&= 0x1f; + } + + S9xSetSoundMute (FALSE); + S9xAPUUnpackStatus (); + if (APUCheckDirectPage ()) + IAPU.DirectPage = IAPU.RAM + 0x100; + else + IAPU.DirectPage = IAPU.RAM; + Settings.APUEnabled = TRUE; + /*IAPU.APUExecuting*/CPU.APU_APUExecuting = TRUE; + } + else + { + Settings.APUEnabled = FALSE; + /*IAPU.APUExecuting*/CPU.APU_APUExecuting = FALSE; + S9xSetSoundMute (TRUE); + } +#ifdef USE_SA1 + if ((result = UnfreezeStruct ("SA1", &SA1, SnapSA1, + COUNT(SnapSA1))) == SUCCESS) + { + if ((result = UnfreezeStruct ("SAR", &SA1Registers, + SnapSA1Registers, COUNT (SnapSA1Registers))) != SUCCESS) + return (result); + + S9xFixSA1AfterSnapshotLoad (); + SA1.Flags |= sa1_old_flags & (TRACE_FLAG); + } +#endif + S9xFixSoundAfterSnapshotLoad (); + ICPU.ShiftedPB = Registers.PB << 16; + ICPU.ShiftedDB = Registers.DB << 16; + S9xSetPCBase (ICPU.ShiftedPB + Registers.PC); + +#ifndef ASMCPU + S9xUnpackStatus (); // not needed + S9xFixCycles (); // also not needed? +#endif + S9xReschedule (); +#ifdef ZSNES_FX + if (Settings.SuperFX) + S9xSuperFXPostLoadState (); +#endif + + S9xSRTCPostLoadState (); + if (Settings.SDD1) S9xSDD1PostLoadState (); + + return (SUCCESS); +} + +int FreezeSize (int size, int type) +{ + switch (type) + { + case uint16_ARRAY_V: + return (size * 2); + case uint32_ARRAY_V: + return (size * 4); + default: + return (size); + } +} + +void FreezeStruct(char *name, void *base, FreezeData *fields, + int num_fields) +{ + // Work out the size of the required block + int len = 0; + int i; + int j; + + for (i = 0; i < num_fields; i++) + { + if (fields [i].offset + FreezeSize (fields [i].size, + fields [i].type) > len) + len = fields [i].offset + FreezeSize (fields [i].size, + fields [i].type); + } + +// uint8 *block = new uint8 [len]; + uint8 *block = (uint8*)malloc(len); + uint8 *ptr = block; + uint16 word; + uint32 dword; + int64 qword; + + // Build the block ready to be streamed out + for (i = 0; i < num_fields; i++) + { + switch (fields [i].type) + { + case INT_V: + switch (fields [i].size) + { + case 1: + *ptr++ = *((uint8 *) base + fields [i].offset); + break; + case 2: + word = *((uint16 *) ((uint8 *) base + fields [i].offset)); + *ptr++ = (uint8) (word >> 8); + *ptr++ = (uint8) word; + break; + case 4: + dword = *((uint32 *) ((uint8 *) base + fields [i].offset)); + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + break; + case 8: + qword = *((int64 *) ((uint8 *) base + fields [i].offset)); + *ptr++ = (uint8) (qword >> 56); + *ptr++ = (uint8) (qword >> 48); + *ptr++ = (uint8) (qword >> 40); + *ptr++ = (uint8) (qword >> 32); + *ptr++ = (uint8) (qword >> 24); + *ptr++ = (uint8) (qword >> 16); + *ptr++ = (uint8) (qword >> 8); + *ptr++ = (uint8) qword; + break; + } + break; + case uint8_ARRAY_V: + memmove (ptr, (uint8 *) base + fields [i].offset, fields [i].size); + ptr += fields [i].size; + break; + case uint16_ARRAY_V: + for (j = 0; j < fields [i].size; j++) + { + word = *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)); + *ptr++ = (uint8) (word >> 8); + *ptr++ = (uint8) word; + } + break; + case uint32_ARRAY_V: + for (j = 0; j < fields [i].size; j++) + { + dword = *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)); + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + } + break; + } + } + + FreezeBlock (name, block, len); + + free(block); +} + +void FreezeBlock (char *name, uint8 *block, int size) +{ + char buffer [512]; + sprintf (buffer, "%s:%06d:", name, size); + statef_write(buffer, strlen (buffer)); + statef_write(block, size); + +} + +int UnfreezeStruct (char *name, void *base, FreezeData *fields, + int num_fields) +{ + // Work out the size of the required block + int len = 0; + int i; + int j; + + for (i = 0; i < num_fields; i++) + { + if (fields [i].offset + FreezeSize (fields [i].size, + fields [i].type) > len) + len = fields [i].offset + FreezeSize (fields [i].size, + fields [i].type); + } + + uint8 *block = (uint8*)malloc(len); + uint8 *ptr = block; + uint16 word; + uint32 dword; + int64 qword; + int result; + + if ((result = UnfreezeBlock (name, block, len)) != SUCCESS) + { + free(block); + return (result); + } + + // Unpack the block of data into a C structure + for (i = 0; i < num_fields; i++) + { + switch (fields [i].type) + { + case INT_V: + switch (fields [i].size) + { + case 1: + *((uint8 *) base + fields [i].offset) = *ptr++; + break; + case 2: + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) ((uint8 *) base + fields [i].offset)) = word; + break; + case 4: + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) ((uint8 *) base + fields [i].offset)) = dword; + break; + case 8: + qword = (int64) *ptr++ << 56; + qword |= (int64) *ptr++ << 48; + qword |= (int64) *ptr++ << 40; + qword |= (int64) *ptr++ << 32; + qword |= (int64) *ptr++ << 24; + qword |= (int64) *ptr++ << 16; + qword |= (int64) *ptr++ << 8; + qword |= (int64) *ptr++; + *((int64 *) ((uint8 *) base + fields [i].offset)) = qword; + break; + } + break; + case uint8_ARRAY_V: + memmove ((uint8 *) base + fields [i].offset, ptr, fields [i].size); + ptr += fields [i].size; + break; + case uint16_ARRAY_V: + for (j = 0; j < fields [i].size; j++) + { + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)) = word; + } + break; + case uint32_ARRAY_V: + for (j = 0; j < fields [i].size; j++) + { + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)) = dword; + } + break; + } + } + +// delete block; + free(block); + return (result); +} + +int UnfreezeBlock(char *name, uint8 *block, int size) +{ + char buffer [20]; + int len = 0; + int rem = 0; + + if (statef_read(buffer, 11) != 11 || + strncmp (buffer, name, 3) != 0 || buffer [3] != ':' || + (len = atoi (&buffer [4])) == 0) + { + return (WRONG_FORMAT); + } + + if (len > size) + { + rem = len - size; + len = size; + } + + if (statef_read(block, len) != len) + { + return (WRONG_FORMAT); + } + + if (rem) + { + char *junk = (char*)malloc(rem); + statef_read(junk, rem); + free(junk); + } + + return (SUCCESS); +} + + diff --git a/src/snapshot.cpp b/src/snapshot.cpp deleted file mode 100644 index fbcf81f..0000000 --- a/src/snapshot.cpp +++ /dev/null @@ -1,945 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -#ifndef __GP32__ -#include -#include -#include -#endif -#if defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP) -#include -#include -#include -#endif - -#include "snapshot.h" -//#include "snaporig.h" -#include "memmap.h" -#include "snes9x.h" -#include "65c816.h" -#include "ppu.h" -#include "cpuexec.h" -#include "display.h" -#include "apu.h" -#include "soundux.h" -#ifdef USE_SA1 -#include "sa1.h" -#endif -#include "srtc.h" -#include "sdd1.h" - - -// notaz: file i/o function pointers for states, -// changing funcs will allow to enable/disable gzipped saves -extern int (*statef_open)(const char *fname, const char *mode); -extern int (*statef_read)(void *p, int l); -extern int (*statef_write)(void *p, int l); -extern void (*statef_close)(); - -extern uint8 *SRAM; - -#ifdef ZSNES_FX -START_EXTERN_C -void S9xSuperFXPreSaveState (); -void S9xSuperFXPostSaveState (); -void S9xSuperFXPostLoadState (); -END_EXTERN_C -#endif - -//bool8 S9xUnfreezeZSNES (const char *filename); - -typedef struct { - int offset; - int size; - int type; -} FreezeData; - -enum { - INT_V, uint8_ARRAY_V, uint16_ARRAY_V, uint32_ARRAY_V -}; - -#define Offset(field,structure) \ - ((int) (((char *) (&(((structure)NULL)->field))) - ((char *) NULL))) - -#define COUNT(ARRAY) (sizeof (ARRAY) / sizeof (ARRAY[0])) - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SCPUState *) - -static FreezeData SnapCPU [] = { - {OFFSET (Flags), 4, INT_V}, - {OFFSET (BranchSkip), 1, INT_V}, - {OFFSET (NMIActive), 1, INT_V}, - {OFFSET (IRQActive), 1, INT_V}, - {OFFSET (WaitingForInterrupt), 1, INT_V}, - {OFFSET (WhichEvent), 1, INT_V}, - {OFFSET (Cycles), 4, INT_V}, - {OFFSET (NextEvent), 4, INT_V}, - {OFFSET (V_Counter), 4, INT_V}, - {OFFSET (MemSpeed), 4, INT_V}, - {OFFSET (MemSpeedx2), 4, INT_V}, - {OFFSET (FastROMSpeed), 4, INT_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SRegisters *) - -static FreezeData SnapRegisters [] = { - {OFFSET (PB), 1, INT_V}, - {OFFSET (DB), 1, INT_V}, - {OFFSET (P.W), 2, INT_V}, - {OFFSET (A.W), 2, INT_V}, - {OFFSET (D.W), 2, INT_V}, - {OFFSET (S.W), 2, INT_V}, - {OFFSET (X.W), 2, INT_V}, - {OFFSET (Y.W), 2, INT_V}, - {OFFSET (PC), 2, INT_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SPPU *) - -static FreezeData SnapPPU [] = { - {OFFSET (BGMode), 1, INT_V}, - {OFFSET (BG3Priority), 1, INT_V}, - {OFFSET (Brightness), 1, INT_V}, - {OFFSET (VMA.High), 1, INT_V}, - {OFFSET (VMA.Increment), 1, INT_V}, - {OFFSET (VMA.Address), 2, INT_V}, - {OFFSET (VMA.Mask1), 2, INT_V}, - {OFFSET (VMA.FullGraphicCount), 2, INT_V}, - {OFFSET (VMA.Shift), 2, INT_V}, - {OFFSET (BG[0].SCBase), 2, INT_V}, - {OFFSET (BG[0].VOffset), 2, INT_V}, - {OFFSET (BG[0].HOffset), 2, INT_V}, - {OFFSET (BG[0].BGSize), 1, INT_V}, - {OFFSET (BG[0].NameBase), 2, INT_V}, - {OFFSET (BG[0].SCSize), 2, INT_V}, - - {OFFSET (BG[1].SCBase), 2, INT_V}, - {OFFSET (BG[1].VOffset), 2, INT_V}, - {OFFSET (BG[1].HOffset), 2, INT_V}, - {OFFSET (BG[1].BGSize), 1, INT_V}, - {OFFSET (BG[1].NameBase), 2, INT_V}, - {OFFSET (BG[1].SCSize), 2, INT_V}, - - {OFFSET (BG[2].SCBase), 2, INT_V}, - {OFFSET (BG[2].VOffset), 2, INT_V}, - {OFFSET (BG[2].HOffset), 2, INT_V}, - {OFFSET (BG[2].BGSize), 1, INT_V}, - {OFFSET (BG[2].NameBase), 2, INT_V}, - {OFFSET (BG[2].SCSize), 2, INT_V}, - - {OFFSET (BG[3].SCBase), 2, INT_V}, - {OFFSET (BG[3].VOffset), 2, INT_V}, - {OFFSET (BG[3].HOffset), 2, INT_V}, - {OFFSET (BG[3].BGSize), 1, INT_V}, - {OFFSET (BG[3].NameBase), 2, INT_V}, - {OFFSET (BG[3].SCSize), 2, INT_V}, - - {OFFSET (CGFLIP), 1, INT_V}, - {OFFSET (CGDATA), 256, uint16_ARRAY_V}, - {OFFSET (FirstSprite), 1, INT_V}, -#define O(N) \ - {OFFSET (OBJ[N].HPos), 2, INT_V}, \ - {OFFSET (OBJ[N].VPos), 2, INT_V}, \ - {OFFSET (OBJ[N].Name), 2, INT_V}, \ - {OFFSET (OBJ[N].VFlip), 1, INT_V}, \ - {OFFSET (OBJ[N].HFlip), 1, INT_V}, \ - {OFFSET (OBJ[N].Priority), 1, INT_V}, \ - {OFFSET (OBJ[N].Palette), 1, INT_V}, \ - {OFFSET (OBJ[N].Size), 1, INT_V} - - O( 0), O( 1), O( 2), O( 3), O( 4), O( 5), O( 6), O( 7), - O( 8), O( 9), O( 10), O( 11), O( 12), O( 13), O( 14), O( 15), - O( 16), O( 17), O( 18), O( 19), O( 20), O( 21), O( 22), O( 23), - O( 24), O( 25), O( 26), O( 27), O( 28), O( 29), O( 30), O( 31), - O( 32), O( 33), O( 34), O( 35), O( 36), O( 37), O( 38), O( 39), - O( 40), O( 41), O( 42), O( 43), O( 44), O( 45), O( 46), O( 47), - O( 48), O( 49), O( 50), O( 51), O( 52), O( 53), O( 54), O( 55), - O( 56), O( 57), O( 58), O( 59), O( 60), O( 61), O( 62), O( 63), - O( 64), O( 65), O( 66), O( 67), O( 68), O( 69), O( 70), O( 71), - O( 72), O( 73), O( 74), O( 75), O( 76), O( 77), O( 78), O( 79), - O( 80), O( 81), O( 82), O( 83), O( 84), O( 85), O( 86), O( 87), - O( 88), O( 89), O( 90), O( 91), O( 92), O( 93), O( 94), O( 95), - O( 96), O( 97), O( 98), O( 99), O(100), O(101), O(102), O(103), - O(104), O(105), O(106), O(107), O(108), O(109), O(110), O(111), - O(112), O(113), O(114), O(115), O(116), O(117), O(118), O(119), - O(120), O(121), O(122), O(123), O(124), O(125), O(126), O(127), -#undef O - {OFFSET (OAMPriorityRotation), 1, INT_V}, - {OFFSET (OAMAddr), 2, INT_V}, - {OFFSET (OAMFlip), 1, INT_V}, - {OFFSET (OAMTileAddress), 2, INT_V}, - {OFFSET (IRQVBeamPos), 2, INT_V}, - {OFFSET (IRQHBeamPos), 2, INT_V}, - {OFFSET (VBeamPosLatched), 2, INT_V}, - {OFFSET (HBeamPosLatched), 2, INT_V}, - {OFFSET (HBeamFlip), 1, INT_V}, - {OFFSET (VBeamFlip), 1, INT_V}, - {OFFSET (HVBeamCounterLatched), 1, INT_V}, - {OFFSET (MatrixA), 2, INT_V}, - {OFFSET (MatrixB), 2, INT_V}, - {OFFSET (MatrixC), 2, INT_V}, - {OFFSET (MatrixD), 2, INT_V}, - {OFFSET (CentreX), 2, INT_V}, - {OFFSET (CentreY), 2, INT_V}, - {OFFSET (Joypad1ButtonReadPos), 1, INT_V}, - {OFFSET (Joypad2ButtonReadPos), 1, INT_V}, - {OFFSET (Joypad3ButtonReadPos), 1, INT_V}, - {OFFSET (CGADD), 1, INT_V}, - {OFFSET (FixedColourRed), 1, INT_V}, - {OFFSET (FixedColourGreen), 1, INT_V}, - {OFFSET (FixedColourBlue), 1, INT_V}, - {OFFSET (SavedOAMAddr), 2, INT_V}, - {OFFSET (ScreenHeight), 2, INT_V}, - {OFFSET (WRAM), 4, INT_V}, - {OFFSET (ForcedBlanking), 1, INT_V}, - {OFFSET (OBJNameSelect), 2, INT_V}, - {OFFSET (OBJSizeSelect), 1, INT_V}, - {OFFSET (OBJNameBase), 2, INT_V}, - {OFFSET (OAMReadFlip), 1, INT_V}, - {OFFSET (VTimerEnabled), 1, INT_V}, - {OFFSET (HTimerEnabled), 1, INT_V}, - {OFFSET (HTimerPosition), 2, INT_V}, - {OFFSET (Mosaic), 1, INT_V}, - {OFFSET (Mode7HFlip), 1, INT_V}, - {OFFSET (Mode7VFlip), 1, INT_V}, - {OFFSET (Mode7Repeat), 1, INT_V}, - {OFFSET (Window1Left), 1, INT_V}, - {OFFSET (Window1Right), 1, INT_V}, - {OFFSET (Window2Left), 1, INT_V}, - {OFFSET (Window2Right), 1, INT_V}, -#define O(N) \ - {OFFSET (ClipWindowOverlapLogic[N]), 1, INT_V}, \ - {OFFSET (ClipWindow1Enable[N]), 1, INT_V}, \ - {OFFSET (ClipWindow2Enable[N]), 1, INT_V}, \ - {OFFSET (ClipWindow1Inside[N]), 1, INT_V}, \ - {OFFSET (ClipWindow2Inside[N]), 1, INT_V} - - O(0), O(1), O(2), O(3), O(4), O(5), - -#undef O - - {OFFSET (CGFLIPRead), 1, INT_V}, - {OFFSET (Need16x8Mulitply), 1, INT_V}, - {OFFSET (BGMosaic), 4, uint8_ARRAY_V}, - {OFFSET (OAMData), 512 + 32, uint8_ARRAY_V}, - {OFFSET (Need16x8Mulitply), 1, INT_V}, - {OFFSET (MouseSpeed), 2, uint8_ARRAY_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SDMA *) - -static FreezeData SnapDMA [] = { -#define O(N) \ - {OFFSET (TransferDirection) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (AAddressFixed) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (AAddressDecrement) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (TransferMode) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (ABank) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (AAddress) + N * sizeof (struct SDMA), 2, INT_V}, \ - {OFFSET (Address) + N * sizeof (struct SDMA), 2, INT_V}, \ - {OFFSET (BAddress) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (TransferBytes) + N * sizeof (struct SDMA), 2, INT_V}, \ - {OFFSET (HDMAIndirectAddressing) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (IndirectAddress) + N * sizeof (struct SDMA), 2, INT_V}, \ - {OFFSET (IndirectBank) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (Repeat) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (LineCount) + N * sizeof (struct SDMA), 1, INT_V}, \ - {OFFSET (FirstLine) + N * sizeof (struct SDMA), 1, INT_V} - - O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) -#undef O -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SAPU *) - -static FreezeData SnapAPU [] = { - {OFFSET (Cycles), 4, INT_V}, - {OFFSET (ShowROM), 1, INT_V}, - {OFFSET (Flags), 1, INT_V}, - {OFFSET (KeyedChannels), 1, INT_V}, - {OFFSET (OutPorts), 4, uint8_ARRAY_V}, - {OFFSET (DSP), 0x80, uint8_ARRAY_V}, - {OFFSET (ExtraRAM), 64, uint8_ARRAY_V}, - {OFFSET (Timer), 3, uint16_ARRAY_V}, - {OFFSET (TimerTarget), 3, uint16_ARRAY_V}, - {OFFSET (TimerEnabled), 3, uint8_ARRAY_V}, - {OFFSET (TimerValueWritten), 3, uint8_ARRAY_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SAPURegisters *) - -static FreezeData SnapAPURegisters [] = { - {OFFSET (P) , 1, INT_V}, - {OFFSET (YA.W), 2, INT_V}, - {OFFSET (X) , 1, INT_V}, - {OFFSET (S) , 1, INT_V}, - {OFFSET (PC) , 2, INT_V} -}; - -#undef OFFSET -#undef OFFSET1 -#define OFFSET(f) Offset(f,SSoundData *) - -static FreezeData SnapSoundData [] = { - {OFFSET (master_volume_left), 2, INT_V}, - {OFFSET (master_volume_right), 2, INT_V}, - {OFFSET (echo_volume_left), 2, INT_V}, - {OFFSET (echo_volume_right), 2, INT_V}, - {OFFSET (echo_enable), 4, INT_V}, - {OFFSET (echo_feedback), 4, INT_V}, - {OFFSET (echo_ptr), 4, INT_V}, - {OFFSET (echo_buffer_size), 4, INT_V}, - {OFFSET (echo_write_enabled), 4, INT_V}, - {OFFSET (echo_channel_enable), 4, INT_V}, - {OFFSET (pitch_mod), 4, INT_V}, - {OFFSET (dummy), 3, uint32_ARRAY_V}, -#define O(N) \ - {OFFSET (channels [N].state), 4, INT_V}, \ - {OFFSET (channels [N].type), 4, INT_V}, \ - {OFFSET (channels [N].volume_left), 2, INT_V}, \ - {OFFSET (channels [N].volume_right), 2, INT_V}, \ - {OFFSET (channels [N].hertz), 4, INT_V}, \ - {OFFSET (channels [N].count), 4, INT_V}, \ - {OFFSET (channels [N].loop), 1, INT_V}, \ - {OFFSET (channels [N].envx), 4, INT_V}, \ - {OFFSET (channels [N].left_vol_level), 2, INT_V}, \ - {OFFSET (channels [N].right_vol_level), 2, INT_V}, \ - {OFFSET (channels [N].envx_target), 2, INT_V}, \ - {OFFSET (channels [N].env_error), 4, INT_V}, \ - {OFFSET (channels [N].erate), 4, INT_V}, \ - {OFFSET (channels [N].direction), 4, INT_V}, \ - {OFFSET (channels [N].attack_rate), 4, INT_V}, \ - {OFFSET (channels [N].decay_rate), 4, INT_V}, \ - {OFFSET (channels [N].sustain_rate), 4, INT_V}, \ - {OFFSET (channels [N].release_rate), 4, INT_V}, \ - {OFFSET (channels [N].sustain_level), 4, INT_V}, \ - {OFFSET (channels [N].sample), 2, INT_V}, \ - {OFFSET (channels [N].decoded), 16, uint16_ARRAY_V}, \ - {OFFSET (channels [N].previous16), 2, uint16_ARRAY_V}, \ - {OFFSET (channels [N].sample_number), 2, INT_V}, \ - {OFFSET (channels [N].last_block), 1, INT_V}, \ - {OFFSET (channels [N].needs_decode), 1, INT_V}, \ - {OFFSET (channels [N].block_pointer), 4, INT_V}, \ - {OFFSET (channels [N].sample_pointer), 4, INT_V}, \ - {OFFSET (channels [N].mode), 4, INT_V} - - O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) -#undef O -}; - -#ifdef USE_SA1 - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SSA1Registers *) - -static FreezeData SnapSA1Registers [] = { - {OFFSET (PB), 1, INT_V}, - {OFFSET (DB), 1, INT_V}, - {OFFSET (P.W), 2, INT_V}, - {OFFSET (A.W), 2, INT_V}, - {OFFSET (D.W), 2, INT_V}, - {OFFSET (S.W), 2, INT_V}, - {OFFSET (X.W), 2, INT_V}, - {OFFSET (Y.W), 2, INT_V}, - {OFFSET (PC), 2, INT_V} -}; - -#undef OFFSET -#define OFFSET(f) Offset(f,struct SSA1 *) - -static FreezeData SnapSA1 [] = { - {OFFSET (Flags), 4, INT_V}, - {OFFSET (NMIActive), 1, INT_V}, - {OFFSET (IRQActive), 1, INT_V}, - {OFFSET (WaitingForInterrupt), 1, INT_V}, - {OFFSET (op1), 2, INT_V}, - {OFFSET (op2), 2, INT_V}, - {OFFSET (arithmetic_op), 4, INT_V}, - {OFFSET (sum), 8, INT_V}, - {OFFSET (overflow), 1, INT_V} -}; -#endif - -//static char ROMFilename [_MAX_PATH]; -//static char SnapshotFilename [_MAX_PATH]; - -static void Freeze (); -static int Unfreeze (); -void FreezeStruct (char *name, void *base, FreezeData *fields, - int num_fields); -void FreezeBlock (char *name, uint8 *block, int size); - -int UnfreezeStruct (char *name, void *base, FreezeData *fields, - int num_fields); -int UnfreezeBlock (char *name, uint8 *block, int size); - -bool8 Snapshot (const char *filename) -{ - return (S9xFreezeGame (filename)); -} - -bool8 S9xFreezeGame (const char *filename) -{ - if(statef_open(filename, "wb")) - { - Freeze(); - statef_close(); - return (TRUE); - } - return (FALSE); -} - - -bool8 S9xUnfreezeGame (const char *filename) -{ - if(statef_open(filename, "rb")) - { - int result; - if ((result = Unfreeze()) != SUCCESS) - { - switch (result) - { - case WRONG_FORMAT: - S9xMessage (S9X_ERROR, S9X_WRONG_FORMAT, - "File not in Snes9x freeze format"); - S9xReset(); - break; - case WRONG_VERSION: - S9xMessage (S9X_ERROR, S9X_WRONG_VERSION, - "Incompatable Snes9x freeze file format version"); - S9xReset(); - break; - default: - // should never happen - break; - } - statef_close(); - return (FALSE); - } - statef_close(); - return (TRUE); - } - - - return (FALSE); -} - -static void Freeze () -{ - char buffer[1024]; - int i; - - S9xSetSoundMute (TRUE); -#ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPreSaveState (); -#endif - - S9xSRTCPreSaveState (); - - for (i = 0; i < 8; i++) - { - SoundData.channels [i].previous16 [0] = (int16) SoundData.channels [i].previous [0]; - SoundData.channels [i].previous16 [1] = (int16) SoundData.channels [i].previous [1]; - } - sprintf (buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); - statef_write(buffer, strlen (buffer)); - sprintf (buffer, "NAM:%06d:%s%c", strlen (Memory.ROMFilename) + 1, - Memory.ROMFilename, 0); - statef_write(buffer, strlen (buffer) + 1); - FreezeStruct ("CPU", &CPU, SnapCPU, COUNT (SnapCPU)); - FreezeStruct ("REG", &Registers, SnapRegisters, COUNT (SnapRegisters)); - FreezeStruct ("PPU", &PPU, SnapPPU, COUNT (SnapPPU)); - FreezeStruct ("DMA", DMA, SnapDMA, COUNT (SnapDMA)); - -// RAM and VRAM - FreezeBlock ("VRA", Memory.VRAM, 0x10000); - FreezeBlock ("RAM", Memory.RAM, 0x20000); - FreezeBlock ("SRA", ::SRAM, 0x20000); - FreezeBlock ("FIL", Memory.FillRAM, 0x8000); - if (Settings.APUEnabled) - { -// APU - FreezeStruct ("APU", &APU, SnapAPU, COUNT (SnapAPU)); - // copy all SPC700 regs to savestate compatible struct - SAPURegisters spcregs; - spcregs.P = IAPU.P; - spcregs.YA.W = IAPU.YA.W; - spcregs.X = IAPU.X; - spcregs.S = IAPU.S; - spcregs.PC = IAPU.PC - IAPU.RAM; - FreezeStruct ("ARE", &spcregs, SnapAPURegisters, - COUNT (SnapAPURegisters)); - - FreezeBlock ("ARA", IAPU.RAM, 0x10000); - FreezeStruct ("SOU", &SoundData, SnapSoundData, - COUNT (SnapSoundData)); - } -#ifdef USE_SA1 - if (Settings.SA1) - { - SA1Registers.PC = SA1.PC - SA1.PCBase; - S9xSA1PackStatus (); - FreezeStruct ("SA1", &SA1, SnapSA1, COUNT (SnapSA1)); - FreezeStruct ("SAR", &SA1Registers, SnapSA1Registers, - COUNT (SnapSA1Registers)); - } -#endif - S9xSetSoundMute (FALSE); -#ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPostSaveState (); -#endif -} - -static int Unfreeze() -{ - // notaz: overflowing the damn Symbian stack again - char buffer [16]; - char rom_filename [512]; - int result; - - int version; - - unsigned int len = strlen (SNAPSHOT_MAGIC) + 1 + 4 + 1; - if (statef_read(buffer, len) != (int)len) - { - return (WRONG_FORMAT); - } - if (strncmp (buffer, SNAPSHOT_MAGIC, strlen (SNAPSHOT_MAGIC)) != 0) - { - return (WRONG_FORMAT); - } - if ((version = atoi (&buffer [strlen (SNAPSHOT_MAGIC) + 1])) > SNAPSHOT_VERSION) - return (WRONG_VERSION); - - if ((result = UnfreezeBlock("NAM", (uint8 *) rom_filename, 512)) != SUCCESS) - return (result); - - if (strcasecmp (rom_filename, Memory.ROMFilename) != 0 && - strcasecmp (S9xBasename (rom_filename), S9xBasename (Memory.ROMFilename)) != 0) - { - S9xMessage (S9X_WARNING, S9X_FREEZE_ROM_NAME, - "Current loaded ROM image doesn't match that required by freeze-game file."); - } - - - - uint32 old_flags = CPU.Flags; -#ifdef USE_SA1 - uint32 sa1_old_flags = SA1.Flags; -#endif - S9xReset (); - S9xSetSoundMute (TRUE); - - if ((result = UnfreezeStruct("CPU", &CPU, SnapCPU, - COUNT (SnapCPU))) != SUCCESS) - return (result); - - - Memory.FixROMSpeed (); - CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | - SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); - if ((result = UnfreezeStruct("REG", &Registers, SnapRegisters, COUNT (SnapRegisters))) != SUCCESS) - return (result); - if ((result = UnfreezeStruct("PPU", &PPU, SnapPPU, COUNT (SnapPPU))) != SUCCESS) - return (result); - - - IPPU.ColorsChanged = TRUE; - IPPU.OBJChanged = TRUE; - CPU.InDMA = FALSE; - // Restore colors from PPU - for (unsigned int i = 0; i < 256; i++) { - IPPU.Red[i] = PPU.CGDATA[i] & 0x1f; - IPPU.Green[i] = (PPU.CGDATA[i] >> 5) & 0x1f; - IPPU.Blue[i] = (PPU.CGDATA[i] >> 10) & 0x1f; - } - - S9xFixColourBrightness (); - IPPU.RenderThisFrame = FALSE; - - if ((result = UnfreezeStruct ("DMA", DMA, SnapDMA, - COUNT (SnapDMA))) != SUCCESS) - return (result); - - if ((result = UnfreezeBlock ("VRA", Memory.VRAM, 0x10000)) != SUCCESS) - return (result); - - if ((result = UnfreezeBlock ("RAM", Memory.RAM, 0x20000)) != SUCCESS) - return (result); - - if ((result = UnfreezeBlock ("SRA", ::SRAM, 0x20000)) != SUCCESS) - return (result); - - if ((result = UnfreezeBlock ("FIL", Memory.FillRAM, 0x8000)) != SUCCESS) - return (result); - - // Restore graphics shadow registers - GFX.r212c_s = Memory.FillRAM[0x212c]; - GFX.r212d_s = Memory.FillRAM[0x212d]; - GFX.r212e_s = Memory.FillRAM[0x212e]; - GFX.r212f_s = Memory.FillRAM[0x212f]; - GFX.r2130_s = Memory.FillRAM[0x2130]; - GFX.r2131_s = Memory.FillRAM[0x2131]; - - if (UnfreezeStruct ("APU", &APU, SnapAPU, COUNT (SnapAPU)) == SUCCESS) - { - SAPURegisters spcregs; - if ((result = UnfreezeStruct ("ARE", &spcregs, SnapAPURegisters, - COUNT (SnapAPURegisters))) != SUCCESS) - return (result); - // reload all SPC700 regs from savestate compatible struct - IAPU.P = spcregs.P; - IAPU.YA.W = spcregs.YA.W; - IAPU.X = spcregs.X; - IAPU.S = spcregs.S; - IAPU.PC = IAPU.RAM + spcregs.PC; - - if ((result = UnfreezeBlock ("ARA", IAPU.RAM, 0x10000)) != SUCCESS) - return (result); - - if ((result = UnfreezeStruct ("SOU", &SoundData, SnapSoundData, - COUNT (SnapSoundData))) != SUCCESS) - return (result); - - // notaz: just to be sure - for(int u=0; u<8; u++) { - SoundData.channels[u].env_ind_attack &= 0xf; - SoundData.channels[u].env_ind_decay &= 0x7; - SoundData.channels[u].env_ind_sustain&= 0x1f; - } - - S9xSetSoundMute (FALSE); - S9xAPUUnpackStatus (); - if (APUCheckDirectPage ()) - IAPU.DirectPage = IAPU.RAM + 0x100; - else - IAPU.DirectPage = IAPU.RAM; - Settings.APUEnabled = TRUE; - /*IAPU.APUExecuting*/CPU.APU_APUExecuting = TRUE; - } - else - { - Settings.APUEnabled = FALSE; - /*IAPU.APUExecuting*/CPU.APU_APUExecuting = FALSE; - S9xSetSoundMute (TRUE); - } -#ifdef USE_SA1 - if ((result = UnfreezeStruct ("SA1", &SA1, SnapSA1, - COUNT(SnapSA1))) == SUCCESS) - { - if ((result = UnfreezeStruct ("SAR", &SA1Registers, - SnapSA1Registers, COUNT (SnapSA1Registers))) != SUCCESS) - return (result); - - S9xFixSA1AfterSnapshotLoad (); - SA1.Flags |= sa1_old_flags & (TRACE_FLAG); - } -#endif - S9xFixSoundAfterSnapshotLoad (); - ICPU.ShiftedPB = Registers.PB << 16; - ICPU.ShiftedDB = Registers.DB << 16; - S9xSetPCBase (ICPU.ShiftedPB + Registers.PC); - -#ifndef ASMCPU - S9xUnpackStatus (); // not needed - S9xFixCycles (); // also not needed? -#endif - S9xReschedule (); -#ifdef ZSNES_FX - if (Settings.SuperFX) - S9xSuperFXPostLoadState (); -#endif - - S9xSRTCPostLoadState (); - if (Settings.SDD1) S9xSDD1PostLoadState (); - - return (SUCCESS); -} - -int FreezeSize (int size, int type) -{ - switch (type) - { - case uint16_ARRAY_V: - return (size * 2); - case uint32_ARRAY_V: - return (size * 4); - default: - return (size); - } -} - -void FreezeStruct(char *name, void *base, FreezeData *fields, - int num_fields) -{ - // Work out the size of the required block - int len = 0; - int i; - int j; - - for (i = 0; i < num_fields; i++) - { - if (fields [i].offset + FreezeSize (fields [i].size, - fields [i].type) > len) - len = fields [i].offset + FreezeSize (fields [i].size, - fields [i].type); - } - -// uint8 *block = new uint8 [len]; - uint8 *block = (uint8*)malloc(len); - uint8 *ptr = block; - uint16 word; - uint32 dword; - int64 qword; - - // Build the block ready to be streamed out - for (i = 0; i < num_fields; i++) - { - switch (fields [i].type) - { - case INT_V: - switch (fields [i].size) - { - case 1: - *ptr++ = *((uint8 *) base + fields [i].offset); - break; - case 2: - word = *((uint16 *) ((uint8 *) base + fields [i].offset)); - *ptr++ = (uint8) (word >> 8); - *ptr++ = (uint8) word; - break; - case 4: - dword = *((uint32 *) ((uint8 *) base + fields [i].offset)); - *ptr++ = (uint8) (dword >> 24); - *ptr++ = (uint8) (dword >> 16); - *ptr++ = (uint8) (dword >> 8); - *ptr++ = (uint8) dword; - break; - case 8: - qword = *((int64 *) ((uint8 *) base + fields [i].offset)); - *ptr++ = (uint8) (qword >> 56); - *ptr++ = (uint8) (qword >> 48); - *ptr++ = (uint8) (qword >> 40); - *ptr++ = (uint8) (qword >> 32); - *ptr++ = (uint8) (qword >> 24); - *ptr++ = (uint8) (qword >> 16); - *ptr++ = (uint8) (qword >> 8); - *ptr++ = (uint8) qword; - break; - } - break; - case uint8_ARRAY_V: - memmove (ptr, (uint8 *) base + fields [i].offset, fields [i].size); - ptr += fields [i].size; - break; - case uint16_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - word = *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)); - *ptr++ = (uint8) (word >> 8); - *ptr++ = (uint8) word; - } - break; - case uint32_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - dword = *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)); - *ptr++ = (uint8) (dword >> 24); - *ptr++ = (uint8) (dword >> 16); - *ptr++ = (uint8) (dword >> 8); - *ptr++ = (uint8) dword; - } - break; - } - } - - FreezeBlock (name, block, len); - - free(block); -} - -void FreezeBlock (char *name, uint8 *block, int size) -{ - char buffer [512]; - sprintf (buffer, "%s:%06d:", name, size); - statef_write(buffer, strlen (buffer)); - statef_write(block, size); - -} - -int UnfreezeStruct (char *name, void *base, FreezeData *fields, - int num_fields) -{ - // Work out the size of the required block - int len = 0; - int i; - int j; - - for (i = 0; i < num_fields; i++) - { - if (fields [i].offset + FreezeSize (fields [i].size, - fields [i].type) > len) - len = fields [i].offset + FreezeSize (fields [i].size, - fields [i].type); - } - - uint8 *block = (uint8*)malloc(len); - uint8 *ptr = block; - uint16 word; - uint32 dword; - int64 qword; - int result; - - if ((result = UnfreezeBlock (name, block, len)) != SUCCESS) - { - free(block); - return (result); - } - - // Unpack the block of data into a C structure - for (i = 0; i < num_fields; i++) - { - switch (fields [i].type) - { - case INT_V: - switch (fields [i].size) - { - case 1: - *((uint8 *) base + fields [i].offset) = *ptr++; - break; - case 2: - word = *ptr++ << 8; - word |= *ptr++; - *((uint16 *) ((uint8 *) base + fields [i].offset)) = word; - break; - case 4: - dword = *ptr++ << 24; - dword |= *ptr++ << 16; - dword |= *ptr++ << 8; - dword |= *ptr++; - *((uint32 *) ((uint8 *) base + fields [i].offset)) = dword; - break; - case 8: - qword = (int64) *ptr++ << 56; - qword |= (int64) *ptr++ << 48; - qword |= (int64) *ptr++ << 40; - qword |= (int64) *ptr++ << 32; - qword |= (int64) *ptr++ << 24; - qword |= (int64) *ptr++ << 16; - qword |= (int64) *ptr++ << 8; - qword |= (int64) *ptr++; - *((int64 *) ((uint8 *) base + fields [i].offset)) = qword; - break; - } - break; - case uint8_ARRAY_V: - memmove ((uint8 *) base + fields [i].offset, ptr, fields [i].size); - ptr += fields [i].size; - break; - case uint16_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - word = *ptr++ << 8; - word |= *ptr++; - *((uint16 *) ((uint8 *) base + fields [i].offset + j * 2)) = word; - } - break; - case uint32_ARRAY_V: - for (j = 0; j < fields [i].size; j++) - { - dword = *ptr++ << 24; - dword |= *ptr++ << 16; - dword |= *ptr++ << 8; - dword |= *ptr++; - *((uint32 *) ((uint8 *) base + fields [i].offset + j * 4)) = dword; - } - break; - } - } - -// delete block; - free(block); - return (result); -} - -int UnfreezeBlock(char *name, uint8 *block, int size) -{ - char buffer [20]; - int len = 0; - int rem = 0; - - if (statef_read(buffer, 11) != 11 || - strncmp (buffer, name, 3) != 0 || buffer [3] != ':' || - (len = atoi (&buffer [4])) == 0) - { - return (WRONG_FORMAT); - } - - if (len > size) - { - rem = len - size; - len = size; - } - - if (statef_read(block, len) != len) - { - return (WRONG_FORMAT); - } - - if (rem) - { - char *junk = (char*)malloc(rem); - statef_read(junk, rem); - free(junk); - } - - return (SUCCESS); -} - - diff --git a/src/snes9x.cpp b/src/snes9x.cpp deleted file mode 100644 index 36e3f44..0000000 --- a/src/snes9x.cpp +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include -#include - -#include "snes9x.h" -#include "memmap.h" -#include "display.h" -#include "cheats.h" - -#ifdef DEBUGGER -extern FILE *trace; -#endif - -void S9xUsage () -{ - S9xMessage (S9X_INFO, S9X_USAGE, "snes9x: S9xUsage: snes9x \n\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "Where can be:\n"); - - S9xMessage (S9X_INFO, S9X_USAGE, "\ --cycles or -h Percentage of CPU cycles to execute every scan line (default 90)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --frameskip or -f Screen update frame skip rate (default 2)\n"); - S9xExtraUsage (); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --forcehirom or -F or -FH Force Hi-ROM memory map, useful for hacked ROM imagess.\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --forcelorom or -FL Force Lo-ROM memory map, useful for hacked ROM images.\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --old or -o Enable old-style SNES joypad emulation\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --noold or -no Disbale old-style SNES joypad emulation\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --soundskip or -ss Sound CPU skip-waiting method, 0 - 3 (default 0)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --sound or -S Enable digital sound output (default: enabled)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --nosound or -NS Disable digital sound output\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --sound or -S Enable digital sound output (default: off)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --soundquality or -r Sound sample playback rate/quality, 0-7 (default 4)\n"); - -#ifdef __sgi -/* BS: changed the sample rate values to match the IRIX options */ - S9xMessage (S9X_INFO, S9X_USAGE, "\ - 0 - off, 1 - 8192, 2 - 11025, 3 - 16000,\n\ - 4 - 22050 (default), 5 - 32000, 6 - 44100,\n\ - 7 - 48000\n"); -#else - S9xMessage (S9X_INFO, S9X_USAGE, "\ - 0 - off, 1 - 8192, 2 - 11025, 3 - 16500,\n\ - 4 - 22050 (default), 5 - 29300, 6 - 36600,\n\ - 7 - 44000\n"); -#endif - - S9xMessage (S9X_INFO, S9X_USAGE, "\ --stereo Enable stereo sound (default: mono sound)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --mono Enable mono sound (default: mono sound)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --buffersize or -B Sound playback buffer size (default auto for playback rate)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --nospeedhacks or -N Disable some internal speed ups that break a few ROMs\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --speedhacks or -SH Enable some internal speed ups that break a few ROMs\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --loadsnapshot or -l \n\ - Load saved game position snapshot file & required ROM\n\ - image.\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --swapjoypads or -s Swap joypad 1 and 2 around\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --pal or -p Fool ROM into thinking that this is a PAL SNES system\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --ntsc or -n Fool ROM into thinking that this is a NTCS SNES system\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --interleaved or -i ROM image is in interleaved format.\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --interleaved2 or -i2 ROM image is in interleaved 2 format\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --nohdma or -H Disable H-DMA emulation (default: enabled)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --hdma or -NH Enable H-DMA emulation (default: enabled)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --layering or -L Swap some background priority levels - helps some games\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --graphicwindows Enable graphic window effects (default: enabled)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --nographicwindows or -nw Disable graphic window effects (default: enabled)\n"); -#ifdef DEBUGGER - S9xMessage (S9X_INFO, S9X_USAGE, "\ --noirq or -I Disable processor IRQ (for debugging)\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --debug or -d Enter debug mode once ROM has loaded\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --trace or -t Trace CPU instructions to file (WARNING: file gets very large!)\n"); -#endif - -#ifdef JOYSTICK_SUPPORT -#ifdef __linux - S9xMessage (S9X_INFO, S9X_USAGE, "\ --joydevX /dev/jsY Use joystick device /dev/jsY for emulation of gamepad X\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --joymapX 0 1 2 3 4 5 6 7 Joystick buttons which should be assigned to gamepad X - A B X Y TL TR Start and Select\n"); -#else - S9xMessage (S9X_INFO, S9X_USAGE, "\ --four or -4 Single standard PC joystick has four buttons\n"); - S9xMessage (S9X_INFO, S9X_USAGE, "\ --six or -6 Single standard PC joystick has six buttons\n"); -#endif - S9xMessage (S9X_INFO, S9X_USAGE, "\ --nojoy or -j Disable joystick support\n"); -#endif - - S9xMessage (S9X_INFO, S9X_USAGE, "\ -\nROM image needs to be in Super MagiCom (*.smc), Super FamiCom (*.sfc),\n\ -*.fig, or split (*.1, *.2, or sf32527a, sf32527b, etc) format and can be\n\ -compressed with gzip or compress.\n"); - - exit (1); -} - -#ifdef STORM -extern int dofps; -extern int hicolor; -extern int secondjoy; -extern int minimal; -int prelude=0; -extern int unit; -#endif - -char *S9xParseArgs (char **argv, int argc) -{ - char *rom_filename = NULL; - - for (int i = 1; i < argc; i++) - { - if (*argv[i] == '-') - { - if (strcasecmp (argv [i], "-so") == 0 || - strcasecmp (argv [i], "-sound") == 0) - { - Settings.NextAPUEnabled = TRUE; - } - else if (strcasecmp (argv [i], "-ns") == 0 || - strcasecmp (argv [i], "-nosound") == 0) - { - Settings.NextAPUEnabled = FALSE; - } - else if (strcasecmp (argv [i], "-soundskip") == 0 || - strcasecmp (argv [i], "-sk") == 0) - { - if (i + 1 < argc) - Settings.SoundSkipMethod = atoi (argv [++i]); - else - S9xUsage (); - } - else if (strcasecmp (argv [i], "-ra") == 0 || - strcasecmp (argv [i], "-ratio") == 0) - { - if (i + 1 < argc) - { - } - else - S9xUsage (); - } - else if (strcasecmp (argv [i], "-h") == 0 || - strcasecmp (argv [i], "-cycles") == 0) - { - if (i + 1 < argc) - { - int p = atoi (argv [++i]); - if (p > 0 && p < 200) - Settings.CyclesPercentage = p; - } - else - S9xUsage (); - } - else if (strcasecmp (argv [i], "-nh") == 0 || - strcasecmp (argv [i], "-nohdma") == 0) - { - Settings.DisableHDMA = TRUE; - } - else if (strcasecmp (argv [i], "-ha") == 0 || - strcasecmp (argv [i], "-hdma") == 0) - { - Settings.DisableHDMA = FALSE; - } - else if (strcasecmp (argv [i], "-n") == 0 || - strcasecmp (argv [i], "-nospeedhacks") == 0) - { - Settings.ShutdownMaster = FALSE; - } - else if (strcasecmp (argv [i], "-sh") == 0 || - strcasecmp (argv [i], "-speedhacks") == 0) - { - Settings.ShutdownMaster = TRUE; - } - else if (strcasecmp (argv [i], "-p") == 0 || - strcasecmp (argv [i], "-pal") == 0) - { - Settings.ForcePAL = TRUE; - } - else if (strcasecmp (argv [i], "-n") == 0 || - strcasecmp (argv [i], "-ntsc") == 0) - { - Settings.ForceNTSC = TRUE; - } - else if (strcasecmp (argv [i], "-f") == 0 || - strcasecmp (argv [i], "-frameskip") == 0) - { - if (i + 1 < argc) - Settings.SkipFrames = atoi (argv [++i]) + 1; - else - S9xUsage (); - } - else if (strcasecmp (argv [i], "-fh") == 0 || - strcasecmp (argv [i], "-hr") == 0 || - strcasecmp (argv [i], "-hirom") == 0) - Settings.ForceHiROM = TRUE; - else if (strcasecmp (argv [i], "-fl") == 0 || - strcasecmp (argv [i], "-lr") == 0 || - strcasecmp (argv [i], "-lorom") == 0) - Settings.ForceLoROM = TRUE; - else if (strcasecmp (argv [i], "-hd") == 0 || - strcasecmp (argv [i], "-header") == 0 || - strcasecmp (argv [i], "-he") == 0) - { - Settings.ForceHeader = TRUE; - } - else if (strcasecmp (argv [i], "-nhd") == 0 || - strcasecmp (argv [i], "-noheader") == 0) - { - Settings.ForceNoHeader = TRUE; - } - else if (strcasecmp (argv [i], "-bs") == 0) - { - Settings.BS = TRUE; - } -#ifdef DEBUGGER - else if (strcasecmp (argv [i], "-d") == 0 || - strcasecmp (argv [i], "-debug") == 0) - { - CPU.Flags |= DEBUG_MODE_FLAG; - } - else if (strcasecmp (argv [i], "-t") == 0 || - strcasecmp (argv [i], "-trace") == 0) - { - trace = fopen ("trace.log", "wb"); - CPU.Flags |= TRACE_FLAG; - } -#endif - else if (strcasecmp (argv [i], "-L") == 0 || - strcasecmp (argv [i], "-layering") == 0) - Settings.BGLayering = TRUE; - else if (strcasecmp (argv [i], "-nl") == 0 || - strcasecmp (argv [i], "-nolayering") == 0) - Settings.BGLayering = FALSE; - else if (strcasecmp (argv [i], "-O") == 0 || - strcasecmp (argv [i], "-tileredraw") == 0) - { - } - else if (strcasecmp (argv [i], "-no") == 0 || - strcasecmp (argv [i], "-lineredraw") == 0) - { - } - else if (strcasecmp (argv [i], "-tr") == 0 || - strcasecmp (argv [i], "-transparency") == 0) - { - Settings.ForceTransparency = TRUE; - Settings.ForceNoTransparency = FALSE; - } - else if (strcasecmp (argv [i], "-nt") == 0 || - strcasecmp (argv [i], "-notransparency") == 0) - { - Settings.ForceNoTransparency = TRUE; - Settings.ForceTransparency = FALSE; - } - else if (strcasecmp (argv [i], "-hi") == 0 || - strcasecmp (argv [i], "-hires") == 0) - { - Settings.SupportHiRes = TRUE; - } - else if (strcasecmp (argv [i], "-16") == 0 || - strcasecmp (argv [i], "-sixteen") == 0) - { - Settings.SixteenBit = TRUE; - } - else if (strcasecmp (argv [i], "-displayframerate") == 0 || - strcasecmp (argv [i], "-dfr") == 0) - { - Settings.DisplayFrameRate = TRUE; - } - else if (strcasecmp (argv [i], "-s") == 0 || - strcasecmp (argv [i], "-swapjoypads") == 0 || - strcasecmp (argv [i], "-sw") == 0) - Settings.SwapJoypads = TRUE; - else if (strcasecmp (argv [i], "-i") == 0 || - strcasecmp (argv [i], "-interleaved") == 0) - Settings.ForceInterleaved = TRUE; - else if (strcasecmp (argv [i], "-i2") == 0 || - strcasecmp (argv [i], "-interleaved2") == 0) - Settings.ForceInterleaved2 = TRUE; - else if (strcasecmp (argv [i], "-ni") == 0 || - strcasecmp (argv [i], "-nointerleave") == 0) - Settings.ForceNotInterleaved = TRUE; - else if (strcasecmp (argv [i], "-noirq") == 0) - Settings.DisableIRQ = TRUE; - else if (strcasecmp (argv [i], "-nw") == 0 || - strcasecmp (argv [i], "-nowindows") == 0) - { - Settings.DisableGraphicWindows = TRUE; - } - else if (strcasecmp (argv [i], "-windows") == 0) - { - Settings.DisableGraphicWindows = FALSE; - } - else if (strcasecmp (argv [i], "-im7") == 0) - { - Settings.Mode7Interpolate = TRUE; - } - else if (strcasecmp (argv [i], "-gg") == 0 || - strcasecmp (argv [i], "-gamegenie") == 0) - { - if (i + 1 < argc) - { - uint32 address; - uint8 byte; - const char *error; - if ((error = S9xGameGenieToRaw (argv [++i], address, byte)) == NULL) - S9xAddCheat (TRUE, FALSE, address, byte); - else - S9xMessage (S9X_ERROR, S9X_GAME_GENIE_CODE_ERROR, - error); - } - else - S9xUsage (); - } - else if (strcasecmp (argv [i], "-ar") == 0 || - strcasecmp (argv [i], "-actionreplay") == 0) - { - if (i + 1 < argc) - { - uint32 address; - uint8 byte; - const char *error; - if ((error = S9xProActionReplayToRaw (argv [++i], address, byte)) == NULL) - S9xAddCheat (TRUE, FALSE, address, byte); - else - S9xMessage (S9X_ERROR, S9X_ACTION_REPLY_CODE_ERROR, - error); - } - else - S9xUsage (); - } - else if (strcasecmp (argv [i], "-gf") == 0 || - strcasecmp (argv [i], "-goldfinger") == 0) - { - if (i + 1 < argc) - { - uint32 address; - uint8 bytes [3]; - bool8 sram; - uint8 num_bytes; - const char *error; - if ((error = S9xGoldFingerToRaw (argv [++i], address, sram, - num_bytes, bytes)) == NULL) - { - for (int c = 0; c < num_bytes; c++) - S9xAddCheat (TRUE, FALSE, address + c, bytes [c]); - } - else - S9xMessage (S9X_ERROR, S9X_GOLD_FINGER_CODE_ERROR, - error); - } - else - S9xUsage (); - } - else if (strcasecmp (argv[i], "-ft") == 0 || - strcasecmp (argv [i], "-frametime") == 0) - { - if (i + 1 < argc) - { - double ft; - if (sscanf (argv [++i], "%lf", &ft) == 1) - { -#ifdef __WIN32__ - Settings.FrameTimePAL = (int32) (ft * 1000); - Settings.FrameTimeNTSC = (int32) (ft * 1000); -#else - Settings.FrameTimePAL = (int32) ft; - Settings.FrameTimeNTSC = (int32) ft; -#endif - - } - } - else - S9xUsage (); - } - else if (strcasecmp (argv [i], "-e") == 0 || - strcasecmp (argv [i], "-echo") == 0) - Settings.DisableSoundEcho = FALSE; - else if (strcasecmp (argv [i], "-ne") == 0 || - strcasecmp (argv [i], "-noecho") == 0) - Settings.DisableSoundEcho = TRUE; - else if (strcasecmp (argv [i], "-r") == 0 || - strcasecmp (argv [i], "-soundquality") == 0 || - strcasecmp (argv [i], "-sq") == 0) - { - if (i + 1 < argc) - Settings.SoundPlaybackRate = atoi (argv [++i]) & 7; - else - S9xUsage (); - } - else if (strcasecmp (argv [i], "-stereo") == 0 || - strcasecmp (argv [i], "-st") == 0) - { - Settings.Stereo = TRUE; - Settings.APUEnabled = TRUE; - Settings.NextAPUEnabled = TRUE; - } - else if (strcasecmp (argv [i], "-mono") == 0) - { - Settings.Stereo = FALSE; - Settings.NextAPUEnabled = TRUE; - } - else if (strcasecmp (argv [i], "-envx") == 0 || - strcasecmp (argv [i], "-ex") == 0) - { - Settings.SoundEnvelopeHeightReading = TRUE; - } - else if (strcasecmp (argv [i], "-nosamplecaching") == 0 || - strcasecmp (argv [i], "-nsc") == 0 || - strcasecmp (argv [i], "-nc") == 0) - { - Settings.DisableSampleCaching = TRUE; - } - else if (strcasecmp (argv [i], "-nomastervolume") == 0 || - strcasecmp (argv [i], "-nmv") == 0) - { - Settings.DisableMasterVolume = TRUE; - } - else if (strcasecmp (argv [i], "-soundsync") == 0 || - strcasecmp (argv [i], "-sy") == 0) - { - Settings.SoundSync = TRUE; - Settings.SoundEnvelopeHeightReading = TRUE; - Settings.InterpolatedSound = TRUE; - } - else if (strcasecmp (argv [i], "-soundsync2") == 0 || - strcasecmp (argv [i], "-sy2") == 0) - { - Settings.SoundSync = 2; - Settings.SoundEnvelopeHeightReading = TRUE; - Settings.InterpolatedSound = TRUE; - } - else if (strcasecmp (argv [i], "-interpolatedsound") == 0 || - strcasecmp (argv [i], "-is") == 0) - { - Settings.InterpolatedSound = TRUE; - } -#ifdef USE_THREADS - else if (strcasecmp (argv [i], "-threadsound") == 0 || - strcasecmp (argv [i], "-ts") == 0) - { - Settings.ThreadSound = TRUE; - } -#endif - else if (strcasecmp (argv [i], "-alt") == 0 || - strcasecmp (argv [i], "-altsampledecode") == 0) - { - Settings.AltSampleDecode = 1; - } - else if (strcasecmp (argv [i], "-fix") == 0) - { - Settings.FixFrequency = 1; - } - else if (strcasecmp (argv [i], "-nosuperfx") == 0 || - strcasecmp (argv [i], "-nosfx") == 0) - Settings.ForceNoSuperFX = TRUE; - else if (strcasecmp (argv [i], "-superfx") == 0 || - strcasecmp (argv [i], "-sfx") == 0) - Settings.ForceSuperFX = TRUE; - else if (strcasecmp (argv [i], "-dsp1") == 0) - Settings.ForceDSP1 = TRUE; - else if (strcasecmp (argv [i], "-nodsp1") == 0) - Settings.ForceNoDSP1 = TRUE; - else if (strcasecmp (argv [i], "-nomultiplayer5") == 0 || - strcasecmp (argv [i], "-nmp") == 0) - Settings.MultiPlayer5 = FALSE; - else if (strcasecmp (argv [i], "-multiplayer5") == 0 || - strcasecmp (argv [i], "-mp") == 0) - { - Settings.MultiPlayer5 = TRUE; - Settings.ControllerOption = SNES_MULTIPLAYER5; - } - else if (strcasecmp (argv [i], "-mouse") == 0 || - strcasecmp (argv [i], "-mo") == 0) - { - Settings.ControllerOption = SNES_MOUSE_SWAPPED; - Settings.Mouse = TRUE; - } - else if (strcasecmp (argv [i], "-nomouse") == 0 || - strcasecmp (argv [i], "-nm") == 0) - { - Settings.Mouse = FALSE; - } - else if (strcasecmp (argv [i], "-superscope") == 0 || - strcasecmp (argv [i], "-ss") == 0) - { - Settings.SuperScope = TRUE; - Settings.ControllerOption = SNES_SUPERSCOPE; - } - else if (strcasecmp (argv [i], "-nosuperscope") == 0 || - strcasecmp (argv [i], "-nss") == 0) - { - Settings.SuperScope = FALSE; - } -#ifdef NETPLAY_SUPPORT - else if (strcasecmp (argv [i], "-port") == 0 || - strcasecmp (argv [i], "-po") == 0) - { - if (i + 1 < argc) - { - Settings.NetPlay = TRUE; - Settings.Port = -atoi (argv [++i]); - } - else - S9xUsage (); - } - else if (strcasecmp (argv [i], "-server") == 0 || - strcasecmp (argv [i], "-srv") == 0) - { - if (i + 1 < argc) - { - Settings.NetPlay = TRUE; - strncpy (Settings.ServerName, argv [++i], 127); - Settings.ServerName [127] = 0; - } - else - S9xUsage (); - } - else if (strcasecmp (argv [i], "-net") == 0) - { - Settings.NetPlay = TRUE; - } -#endif -#ifdef STORM - else if (strcasecmp(argv[i],"-nosecondjoy")==0){secondjoy=0;} - else if (strcasecmp(argv[i],"-showfps")==0){dofps=1;} - else if (strcasecmp(argv[i],"-hicolor")==0){hicolor=1;} - else if (strcasecmp(argv[i],"-minimal")==0){minimal=1;printf("Keyboard with exception of ESC switched off!\n");} - else if (strcasecmp(argv[i],"-ahiunit")==0) - { - if (i+1 status //uint8 DB; //9 //pair P; //10 @@ -254,7 +255,7 @@ struct SCPUState{ void *DSPGet; void *DSPSet; int32 rstatus; -}; +}SCPUState; #define HBLANK_START_EVENT 0 @@ -263,7 +264,8 @@ struct SCPUState{ #define HTIMER_AFTER_EVENT 3 #define NO_EVENT 4 -struct SSettings{ +typedef struct +{ // CPU options bool8 APUEnabled; bool8 Shutdown; @@ -398,9 +400,9 @@ struct SSettings{ #ifdef __WIN32__ int SoundDriver; #endif -}; +}SSettings; -struct SSNESGameFixes +typedef struct { uint8 NeedInit0x2137; uint8 umiharakawaseFix; @@ -414,12 +416,12 @@ struct SSNESGameFixes uint8 Uniracers; uint8 Flintstones; uint8 Mode7Hack; -}; +}SSNESGameFixes; START_EXTERN_C -extern struct SSettings Settings; -extern struct SCPUState CPU; -extern struct SSNESGameFixes SNESGameFixes; +extern SSettings Settings; +extern SCPUState CPU; +extern SSNESGameFixes SNESGameFixes; extern char String [513]; void S9xExit (); diff --git a/src/soundux.c b/src/soundux.c new file mode 100644 index 0000000..50b737b --- /dev/null +++ b/src/soundux.c @@ -0,0 +1,1196 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +#include +#include +#include +#include +#include +//#include + +#define CLIP16(v) \ +if ((v) < -32768) \ + (v) = -32768; \ +else \ +if ((v) > 32767) \ + (v) = 32767 + +#define CLIP16_latch(v,l) \ +if ((v) < -32768) \ +{ (v) = -32768; (l)++; }\ +else \ +if ((v) > 32767) \ +{ (v) = 32767; (l)++; } + +#define CLIP24(v) \ +if ((v) < -8388608) \ + (v) = -8388608; \ +else \ +if ((v) > 8388607) \ + (v) = 8388607 + +/* +#define CLIP8(v) \ +if ((v) < -128) \ + (v) = -128; \ +else \ +if ((v) > 127) \ + (v) = 127 +*/ + + +#include "snes9x.h" +#include "soundux.h" +#include "apu.h" +#include "memmap.h" +#include "cpuexec.h" +#include "asmmemfuncs.h" + + +static int wave[SOUND_BUFFER_SIZE]; + +//extern int Echo [24000]; +extern int MixBuffer [SOUND_BUFFER_SIZE]; +//extern int EchoBuffer [SOUND_BUFFER_SIZE]; +//extern int FilterTaps [8]; +extern unsigned long Z; +//extern int Loop [16]; + +extern long FilterValues[4][2]; +//extern int NoiseFreq [32]; + +//#define FIXED_POINT 0x10000UL +#define FIXED_POINT_REMAINDER 0xffffUL +#define FIXED_POINT_SHIFT 16 + +#define VOL_DIV8 0x8000 +#define VOL_DIV16 0x0080 +#define ENVX_SHIFT 24 + +void DecodeBlockAsm (int8 *, int16 *, int32 *, int32 *); + +// F is channel's current frequency and M is the 16-bit modulation waveform +// from the previous channel multiplied by the current envelope volume level. +#define PITCH_MOD(F,M) ((F) * ((((unsigned long) (M)) + 0x800000) >> 16) >> 7) +//#define PITCH_MOD(F,M) ((F) * ((((M) & 0x7fffff) >> 14) + 1) >> 8) + +#define LAST_SAMPLE 0xffffff +#define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE) + + +static inline void S9xAPUSetEndOfSample (int i, Channel *ch) +{ + ch->state = SOUND_SILENT; + ch->mode = MODE_NONE; + APU.DSP [APU_ENDX] |= 1 << i; + APU.DSP [APU_KON] &= ~(1 << i); + APU.DSP [APU_KOFF] &= ~(1 << i); + APU.KeyedChannels &= ~(1 << i); +} +#ifdef __DJGPP +END_OF_FUNCTION (S9xAPUSetEndOfSample) +#endif + +static inline void S9xAPUSetEndX (int ch) +{ + APU.DSP [APU_ENDX] |= 1 << ch; +} +#ifdef __DJGPP +END_OF_FUNCTION (S9xAPUSetEndX) +#endif + +void S9xSetEchoDelay (int delay) +{ + SoundData.echo_buffer_size = (512 * delay * so.playback_rate) >> 15; // notaz / 32000; + if (so.stereo) + SoundData.echo_buffer_size <<= 1; + if (SoundData.echo_buffer_size) { + while(SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr -= SoundData.echo_buffer_size; + } else + SoundData.echo_ptr = 0; + S9xSetEchoEnable (APU.DSP [APU_EON]); +} + +void S9xSetSoundKeyOff (int channel) +{ + Channel *ch = &SoundData.channels[channel]; + + if (ch->state != SOUND_SILENT) + { + ch->state = SOUND_RELEASE; + ch->mode = MODE_RELEASE; + S9xSetEnvRate (ch, 8, -1, 0, 5<<28); + } +} + +void S9xFixSoundAfterSnapshotLoad () +{ + SoundData.echo_write_enabled = !(APU.DSP [APU_FLG] & 0x20); + SoundData.echo_channel_enable = APU.DSP [APU_EON]; + S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf); + S9xSetEchoFeedback ((signed char) APU.DSP [APU_EFB]); + + S9xSetFilterCoefficient (0, (signed char) APU.DSP [APU_C0]); + S9xSetFilterCoefficient (1, (signed char) APU.DSP [APU_C1]); + S9xSetFilterCoefficient (2, (signed char) APU.DSP [APU_C2]); + S9xSetFilterCoefficient (3, (signed char) APU.DSP [APU_C3]); + S9xSetFilterCoefficient (4, (signed char) APU.DSP [APU_C4]); + S9xSetFilterCoefficient (5, (signed char) APU.DSP [APU_C5]); + S9xSetFilterCoefficient (6, (signed char) APU.DSP [APU_C6]); + S9xSetFilterCoefficient (7, (signed char) APU.DSP [APU_C7]); + + for (int i = 0; i < 8; i++) + { + SoundData.channels[i].needs_decode = TRUE; + S9xSetSoundFrequency (i, SoundData.channels[i].hertz); + SoundData.channels [i].envxx = SoundData.channels [i].envx << ENVX_SHIFT; + SoundData.channels [i].next_sample = 0; + SoundData.channels [i].previous [0] = (int32) SoundData.channels [i].previous16 [0]; + SoundData.channels [i].previous [1] = (int32) SoundData.channels [i].previous16 [1]; + } + SoundData.master_volume [0] = SoundData.master_volume_left; + SoundData.master_volume [1] = SoundData.master_volume_right; + SoundData.echo_volume [0] = SoundData.echo_volume_left; + SoundData.echo_volume [1] = SoundData.echo_volume_right; + IAPU.Scanline = 0; +} + +void S9xSetEnvelopeHeight (int channel, int level) +{ + Channel *ch = &SoundData.channels[channel]; + + ch->envx = level; + ch->envxx = level << ENVX_SHIFT; + + ch->left_vol_level = (level * ch->volume_left) / 128; + ch->right_vol_level = (level * ch->volume_right) / 128; + + if (ch->envx == 0 && ch->state != SOUND_SILENT && ch->state != SOUND_GAIN) + { + S9xAPUSetEndOfSample (channel, ch); + } +} + +#if 1 +void S9xSetSoundSample (int channel, uint16 sample_number) +{ +} +#else +void S9xSetSoundSample (int channel, uint16 sample_number) +{ + register Channel *ch = &SoundData.channels[channel]; + + if (ch->state != SOUND_SILENT && + sample_number != ch->sample_number) + { + int keep = ch->state; + ch->state = SOUND_SILENT; + ch->sample_number = sample_number; + ch->loop = FALSE; + ch->needs_decode = TRUE; + ch->last_block = FALSE; + ch->previous [0] = ch->previous[1] = 0; + ch->block_pointer = *S9xGetSampleAddress(sample_number); + ch->sample_pointer = 0; + ch->state = keep; + } +} +#endif + +static void DecodeBlock (Channel *ch) +{ + if (ch->block_pointer >= 0x10000 - 9) + { + ch->last_block = TRUE; + ch->loop = FALSE; + ch->block = ch->decoded; + memset32 ((uint32_t *) ch->decoded, 0, 8); + return; + } + signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; + + unsigned char filter = *compressed; + if ((ch->last_block = filter & 1)) + ch->loop = (filter & 2) != 0; + + int16 *raw = ch->block = ch->decoded; + +#ifdef ARM + DecodeBlockAsm (compressed, raw, &ch->previous [0], &ch->previous [1]); +#else + int32 out; + unsigned char shift; + signed char sample1, sample2; + unsigned int i; + + compressed++; + + int32 prev0 = ch->previous [0]; + int32 prev1 = ch->previous [1]; + shift = filter >> 4; + + switch ((filter >> 2) & 3) + { + case 0: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + *raw++ = ((int32) sample1 << shift); + *raw++ = ((int32) sample2 << shift); + } + prev1 = *(raw - 2); + prev0 = *(raw - 1); + break; + case 1: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + prev0 = (int16) prev0; + *raw++ = prev1 = ((int32) sample1 << shift) + prev0 - (prev0 >> 4); + prev1 = (int16) prev1; + *raw++ = prev0 = ((int32) sample2 << shift) + prev1 - (prev1 >> 4); + } + break; + case 2: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + + out = (sample1 << shift) - prev1 + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - + (prev0 >> 4); + + out = (sample2 << shift) - prev1 + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - + (prev0 >> 4); + } + break; + case 3: + for (i = 8; i != 0; i--) + { + sample1 = *compressed++; + sample2 = sample1 << 4; + sample2 >>= 4; + sample1 >>= 4; + out = (sample1 << shift); + + out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - + (prev0 >> 4) - (prev1 >> 6); + + out = (sample2 << shift); + out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); + prev1 = (int16) prev0; + prev0 &= ~3; + *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - + (prev0 >> 4) - (prev1 >> 6); + } + break; + } + ch->previous [0] = prev0; + ch->previous [1] = prev1; + +#endif + ch->block_pointer += 9; +} + + +static void MixStereo (int sample_count) +{ + int pitch_mod = SoundData.pitch_mod & (0xFFFFFFFF^APU.DSP[APU_NON]);//~APU.DSP[APU_NON]; + + for (uint32 J = 0; J < NUM_CHANNELS; J++) + { + int32 VL, VR; + Channel *ch = &SoundData.channels[J]; + unsigned long freq0 = ch->frequency; + + if (ch->state == SOUND_SILENT) + continue; + +// freq0 = (unsigned long) ((double) freq0 * 0.985);//uncommented by jonathan gevaryahu, as it is necessary for most cards in linux + + bool8 mod = pitch_mod & (1 << J); + + if (ch->needs_decode) + { + DecodeBlock(ch); + ch->needs_decode = FALSE; + ch->sample = ch->block[0]; + ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT; + if (ch->sample_pointer == 0) + ch->sample_pointer = 1; + if (ch->sample_pointer > SOUND_DECODE_LENGTH) + ch->sample_pointer = SOUND_DECODE_LENGTH - 1; + + ch->next_sample = ch->block[ch->sample_pointer]; + } + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; + + for (uint32 I = 0; I < (uint32) sample_count; I += 2) + { + unsigned long freq = freq0; + + if (mod) + freq = PITCH_MOD(freq, wave [I / 2]); + + ch->env_error += ch->erate; + if (ch->env_error >= FIXED_POINT) + { + uint32 step = ch->env_error >> FIXED_POINT_SHIFT; + + switch (ch->state) + { + case SOUND_ATTACK: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_DECAY; + if (ch->sustain_level != 8) + { + S9xSetEnvRate (ch, ch->decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28); + break; + } + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28); + } + break; + + case SOUND_DECAY: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= ch->envx_target) + { + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28); + } + break; + + case SOUND_SUSTAIN: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_RELEASE: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_INCREASE_LINEAR: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, -1, 0, 0); + } + break; + + case SOUND_INCREASE_BENT_LINE: + if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4) + { + while (ch->env_error >= FIXED_POINT) + { + ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + } + else + { + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + } + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, -1, 0, 0); + } + break; + + case SOUND_DECREASE_LINEAR: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx -= step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_DECREASE_EXPONENTIAL: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + break; + + case SOUND_GAIN: + S9xSetEnvRate (ch, 0, -1, 0, 0); + break; + } + ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; + ch->right_vol_level = (ch->envx * ch->volume_right) / 128; + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; + } + + ch->count += freq; + if (ch->count >= FIXED_POINT) + { + VL = ch->count >> FIXED_POINT_SHIFT; + ch->sample_pointer += VL; + ch->count &= FIXED_POINT_REMAINDER; + + ch->sample = ch->next_sample; + if (ch->sample_pointer >= SOUND_DECODE_LENGTH) + { + if (JUST_PLAYED_LAST_SAMPLE(ch)) + { + S9xAPUSetEndOfSample (J, ch); + goto stereo_exit; + } + do + { + ch->sample_pointer -= SOUND_DECODE_LENGTH; + if (ch->last_block) + { + if (!ch->loop) + { + ch->sample_pointer = LAST_SAMPLE; + ch->next_sample = ch->sample; + break; + } + else + { + S9xAPUSetEndX (J); + ch->last_block = FALSE; + uint16 *dir = S9xGetSampleAddress (ch->sample_number); + ch->block_pointer = *(dir + 1); + } + } + DecodeBlock (ch); + } while (ch->sample_pointer >= SOUND_DECODE_LENGTH); + if (!JUST_PLAYED_LAST_SAMPLE (ch)) + ch->next_sample = ch->block [ch->sample_pointer]; + } + else + ch->next_sample = ch->block [ch->sample_pointer]; + + if (ch->type != SOUND_SAMPLE) + { + for (;VL > 0; VL--) + if ((so.noise_gen <<= 1) & 0x80000000L) + so.noise_gen ^= 0x0040001L; + ch->sample = (so.noise_gen << 17) >> 17; + } + + VL = (ch->sample * ch-> left_vol_level) / 128; + VR = (ch->sample * ch->right_vol_level) / 128; + } + + if (pitch_mod & (1 << (J + 1))) + wave [I / 2] = ch->sample * ch->envx; + + MixBuffer [I] += VL; + MixBuffer [I+1] += VR; + if (ch->echo_buf_ptr) + { + ch->echo_buf_ptr [I] += VL; + ch->echo_buf_ptr [I+1] += VR; + } + } +stereo_exit: ; + } +} + +static void MixMono (int sample_count) +{ + int pitch_mod = SoundData.pitch_mod & (0xFFFFFFFF^APU.DSP[APU_NON]); + + for (uint32 J = 0; J < NUM_CHANNELS; J++) + { + Channel *ch = &SoundData.channels[J]; + unsigned long freq0 = ch->frequency; + + if (ch->state == SOUND_SILENT) + continue; + +// freq0 = (unsigned long) ((double) freq0 * 0.985); + + bool8 mod = pitch_mod & (1 << J); + + if (ch->needs_decode) + { + DecodeBlock(ch); + ch->needs_decode = FALSE; + ch->sample = ch->block[0]; + ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT; + if (ch->sample_pointer == 0) + ch->sample_pointer = 1; + if (ch->sample_pointer > SOUND_DECODE_LENGTH) + ch->sample_pointer = SOUND_DECODE_LENGTH - 1; + ch->next_sample = ch->block[ch->sample_pointer]; + + } + int32 V = (ch->sample * ch->left_vol_level) / 128; + + for (uint32 I = 0; I < (uint32) sample_count; I++) + { + unsigned long freq = freq0; + + if (mod) + freq = PITCH_MOD(freq, wave [I]); + + ch->env_error += ch->erate; + if (ch->env_error >= FIXED_POINT) + { + uint32 step = ch->env_error >> FIXED_POINT_SHIFT; + + switch (ch->state) + { + case SOUND_ATTACK: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_DECAY; + if (ch->sustain_level != 8) + { + S9xSetEnvRate (ch, ch->decay_rate, -1, + (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28); + break; + } + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28); + } + break; + + case SOUND_DECAY: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= ch->envx_target) + { + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + ch->state = SOUND_SUSTAIN; + S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28); + } + break; + + case SOUND_SUSTAIN: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + break; + + case SOUND_RELEASE: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + break; + + case SOUND_INCREASE_LINEAR: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, -1, 0, 0); + } + break; + + case SOUND_INCREASE_BENT_LINE: + if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4) + { + while (ch->env_error >= FIXED_POINT) + { + ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + } + else + { + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx += step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + } + + if (ch->envx >= 126) + { + ch->envx = 127; + ch->envxx = 127 << ENVX_SHIFT; + ch->state = SOUND_GAIN; + ch->mode = MODE_GAIN; + S9xSetEnvRate (ch, 0, -1, 0, 0); + } + break; + + case SOUND_DECREASE_LINEAR: + ch->env_error &= FIXED_POINT_REMAINDER; + ch->envx -= step << 1; + ch->envxx = ch->envx << ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + break; + + case SOUND_DECREASE_EXPONENTIAL: + while (ch->env_error >= FIXED_POINT) + { + ch->envxx = (ch->envxx >> 8) * 255; + ch->env_error -= FIXED_POINT; + } + ch->envx = ch->envxx >> ENVX_SHIFT; + if (ch->envx <= 0) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + break; + + case SOUND_GAIN: + S9xSetEnvRate (ch, 0, -1, 0, 0); + break; + } + ch->left_vol_level = (ch->envx * ch->volume_left) / 128; + V = (ch->sample * ch->left_vol_level) / 128; + } + + ch->count += freq; + if (ch->count >= FIXED_POINT) + { + V = ch->count >> FIXED_POINT_SHIFT; + ch->sample_pointer += V; + ch->count &= FIXED_POINT_REMAINDER; + + ch->sample = ch->next_sample; + if (ch->sample_pointer >= SOUND_DECODE_LENGTH) + { + if (JUST_PLAYED_LAST_SAMPLE(ch)) + { + S9xAPUSetEndOfSample (J, ch); + goto mono_exit; + } + do + { + ch->sample_pointer -= SOUND_DECODE_LENGTH; + if (ch->last_block) + { + if (!ch->loop) + { + ch->sample_pointer = LAST_SAMPLE; + ch->next_sample = ch->sample; + break; + } + else + { + ch->last_block = FALSE; + uint16 *dir = S9xGetSampleAddress (ch->sample_number); + ch->block_pointer = *(dir + 1); + S9xAPUSetEndX (J); + } + } + DecodeBlock (ch); + } while (ch->sample_pointer >= SOUND_DECODE_LENGTH); + if (!JUST_PLAYED_LAST_SAMPLE (ch)) + ch->next_sample = ch->block [ch->sample_pointer]; + } + else + ch->next_sample = ch->block [ch->sample_pointer]; + + if (ch->type != SOUND_SAMPLE) + { + for (;V > 0; V--) + if ((so.noise_gen <<= 1) & 0x80000000L) + so.noise_gen ^= 0x0040001L; + ch->sample = (so.noise_gen << 17) >> 17; + } + V = (ch->sample * ch-> left_vol_level) / 128; + } + + MixBuffer [I] += V; + if (ch->echo_buf_ptr) + ch->echo_buf_ptr [I] += V; + + if (pitch_mod & (1 << (J + 1))) + wave [I] = ch->sample * ch->envx; + } +mono_exit: ; + } +} + + +// For backwards compatibility with older port specific code +void S9xMixSamples (signed short *buffer, int sample_count) +{ + S9xMixSamplesO (buffer, sample_count, 0); +} + + +void S9xMixSamplesO (signed short *buffer, int sample_count, int sample_offset) +{ + // 16-bit sound only + int J; + + buffer += sample_offset; + + if (so.mute_sound) + { + memset16((uint16_t*)buffer, 0, sample_count); + return; + } + + memset32 ((uint32_t*)MixBuffer, 0, sample_count); + if (SoundData.echo_enable) + memset32 ((uint32_t*)EchoBuffer, 0, sample_count); + + if (so.stereo) + MixStereo (sample_count); + else + MixMono (sample_count); + + /* Mix and convert waveforms */ + if (SoundData.echo_enable && SoundData.echo_buffer_size) + { + if (so.stereo) + { + int l, r; + int master_vol_l = SoundData.master_volume[0]; + int master_vol_r = SoundData.master_volume[1]; + int echo_vol_l = SoundData.echo_volume[0]; + int echo_vol_r = SoundData.echo_volume[1]; + + // 16-bit stereo sound with echo enabled ... + if (SoundData.no_filter) + { + // ... but no filter defined. + for (J = 0; J < sample_count; J+=2) + { + int E = Echo [SoundData.echo_ptr]; + + Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J]; + Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J+1]; + + if (SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + l = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16; + r = (MixBuffer[J+1] * master_vol_r + E * echo_vol_r) / VOL_DIV16; + + CLIP16(l); + CLIP16(r); + buffer[J] = l; + buffer[J+1] = r; + } + } + else + { + // ... with filter defined. + for (J = 0; J < sample_count; J+=2) + { + register int E = Echo [SoundData.echo_ptr]; + + Loop [(Z - 0) & 15] = E; + + + + E = E * FilterTaps [0]; + E += Loop [(Z - 2) & 15] * FilterTaps [1]; + E += Loop [(Z - 4) & 15] * FilterTaps [2]; + E += Loop [(Z - 6) & 15] * FilterTaps [3]; + E += Loop [(Z - 8) & 15] * FilterTaps [4]; + E += Loop [(Z - 10) & 15] * FilterTaps [5]; + E += Loop [(Z - 12) & 15] * FilterTaps [6]; + E += Loop [(Z - 14) & 15] * FilterTaps [7]; + E /= 128; + Z++; + + Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J]; + Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J+1]; + + if (SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + l = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16; + r = (MixBuffer[J+1] * master_vol_r + E * echo_vol_r) / VOL_DIV16; + + CLIP16(l); + CLIP16(r); + buffer[J] = l; + buffer[J+1] = r; + } + } + } + else + { + int I; + int master_vol_l = SoundData.master_volume[0]; + int echo_vol_l = SoundData.echo_volume[0]; + + // 16-bit mono sound with echo enabled... + if (SoundData.no_filter) + { + // ... no filter defined + for (J = 0; J < sample_count; J++) + { + int E = Echo [SoundData.echo_ptr]; + + Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J]; + + if (SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16; + CLIP16(I); + buffer[J] = I; + } + } + else + { + // ... with filter defined + for (J = 0; J < sample_count; J++) + { + register int E = Echo [SoundData.echo_ptr]; + + Loop [(Z - 0) & 7] = E; + E = E * FilterTaps [0]; + E += Loop [(Z - 1) & 7] * FilterTaps [1]; + E += Loop [(Z - 2) & 7] * FilterTaps [2]; + E += Loop [(Z - 3) & 7] * FilterTaps [3]; + E += Loop [(Z - 4) & 7] * FilterTaps [4]; + E += Loop [(Z - 5) & 7] * FilterTaps [5]; + E += Loop [(Z - 6) & 7] * FilterTaps [6]; + E += Loop [(Z - 7) & 7] * FilterTaps [7]; + E /= 128; + Z++; + + Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J]; + + if (SoundData.echo_ptr >= SoundData.echo_buffer_size) + SoundData.echo_ptr = 0; + + I = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16; + CLIP16(I); + buffer[J] = I; + } + } + } + } + else + { + int l, master_vol_l = SoundData.master_volume[0]; + + if (so.stereo) + { + int r, master_vol_r = SoundData.master_volume[1]; + + // 16-bit stereo sound, no echo + for (J = 0; J < sample_count; J+=2) + { + l = (MixBuffer[J] * master_vol_l) / VOL_DIV16; + r = (MixBuffer[J+1] * master_vol_r) / VOL_DIV16; + + CLIP16(l); + CLIP16(r); + buffer[J] = l; + buffer[J+1] = r; + } + } + else + { + // 16-bit mono sound, no echo + for (J = 0; J < sample_count; J++) + { + l = (MixBuffer[J] * master_vol_l) / VOL_DIV16; + + CLIP16(l); + buffer[J] = l; + } + } + } +} + +#ifdef __DJGPP +END_OF_FUNCTION(S9xMixSamplesO); +#endif + +void S9xResetSound (bool8 full) +{ + for (int i = 0; i < 8; i++) + { + SoundData.channels[i].state = SOUND_SILENT; + SoundData.channels[i].mode = MODE_NONE; + SoundData.channels[i].type = SOUND_SAMPLE; + SoundData.channels[i].volume_left = 0; + SoundData.channels[i].volume_right = 0; + SoundData.channels[i].hertz = 0; + SoundData.channels[i].count = 0; + SoundData.channels[i].loop = FALSE; + SoundData.channels[i].envx_target = 0; + SoundData.channels[i].env_error = 0; + SoundData.channels[i].erate = 0; + SoundData.channels[i].envx = 0; + SoundData.channels[i].envxx = 0; + SoundData.channels[i].left_vol_level = 0; + SoundData.channels[i].right_vol_level = 0; + SoundData.channels[i].direction = 0; + SoundData.channels[i].attack_rate = 0; + SoundData.channels[i].decay_rate = 0; + SoundData.channels[i].sustain_rate = 0; + SoundData.channels[i].release_rate = 0; + SoundData.channels[i].sustain_level = 0; + // notaz + SoundData.channels[i].env_ind_attack = 0; + SoundData.channels[i].env_ind_decay = 0; + SoundData.channels[i].env_ind_sustain = 0; + SoundData.echo_ptr = 0; + SoundData.echo_feedback = 0; + SoundData.echo_buffer_size = 1; + } + FilterTaps [0] = 127; + FilterTaps [1] = 0; + FilterTaps [2] = 0; + FilterTaps [3] = 0; + FilterTaps [4] = 0; + FilterTaps [5] = 0; + FilterTaps [6] = 0; + FilterTaps [7] = 0; + so.mute_sound = TRUE; + so.noise_gen = 1; + + if (full) + { + SoundData.master_volume_left = 0; + SoundData.master_volume_right = 0; + SoundData.echo_volume_left = 0; + SoundData.echo_volume_right = 0; + SoundData.echo_enable = 0; + SoundData.echo_write_enabled = 0; + SoundData.echo_channel_enable = 0; + SoundData.pitch_mod = 0; + SoundData.dummy[0] = 0; + SoundData.dummy[1] = 0; + SoundData.dummy[2] = 0; + SoundData.master_volume[0] = 0; + SoundData.master_volume[1] = 0; + SoundData.echo_volume[0] = 0; + SoundData.echo_volume[1] = 0; + SoundData.noise_hertz = 0; + } + + SoundData.master_volume_left = 127; + SoundData.master_volume_right = 127; + SoundData.master_volume [0] = SoundData.master_volume [1] = 127; + SoundData.no_filter = TRUE; +} + + + +extern unsigned long AttackRate [16]; +extern unsigned long DecayRate [8]; +extern unsigned long SustainRate [32]; +extern unsigned long IncreaseRate [32]; +extern unsigned long DecreaseRateExp [32]; + + +void S9xSetPlaybackRate (uint32 playback_rate) +{ + so.playback_rate = playback_rate; + + if(playback_rate) { + // notaz: calclulate a value (let's call it freqbase) to simplify channel freq calculations later. + so.freqbase = (FIXED_POINT<<11) / (playback_rate * 33 / 32); + // now precalculate env rates for S9xSetEnvRate + static int steps [] = + { + //0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238 + 0, 64, 619, 619, 128, 1, 64, 55, 64, 619 + }; + int i, u; + for(i=0; i < 16; i++) + for(u=0; u < 10; u++) + AttackERate[i][u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / + (AttackRate[i] * playback_rate)); + for(i=0; i < 8; i++) + for(u=0; u < 10; u++) + DecayERate[i][u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / + (DecayRate[i] * playback_rate)); + + for(i=0; i < 32; i++) + for(u=0; u < 10; u++) + SustainERate[i][u]= (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / + (SustainRate[i] * playback_rate)); + + for(i=0; i < 32; i++) + for(u=0; u < 10; u++) + IncreaseERate[i][u]=(unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / + (IncreaseRate[i] * playback_rate)); + + for(i=0; i < 32; i++) + for(u=0; u < 10; u++) + DecreaseERateExp[i][u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / + (DecreaseRateExp[i] / 2 * playback_rate)); + + for(u=0; u < 10; u++) + KeyOffERate[u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / + (8 * playback_rate)); + } + + S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf); + for (int i = 0; i < 8; i++) + S9xSetSoundFrequency (i, SoundData.channels [i].hertz); +} + +bool8 S9xInitSound (void) +{ + so.playback_rate = 0; + so.stereo = 0; + + S9xResetSound (TRUE); + S9xSetSoundMute (TRUE); + + return (1); +} + diff --git a/src/soundux.cpp b/src/soundux.cpp deleted file mode 100644 index d4b7cb9..0000000 --- a/src/soundux.cpp +++ /dev/null @@ -1,1196 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -#include -#include -#include -#include -#include -//#include - -#define CLIP16(v) \ -if ((v) < -32768) \ - (v) = -32768; \ -else \ -if ((v) > 32767) \ - (v) = 32767 - -#define CLIP16_latch(v,l) \ -if ((v) < -32768) \ -{ (v) = -32768; (l)++; }\ -else \ -if ((v) > 32767) \ -{ (v) = 32767; (l)++; } - -#define CLIP24(v) \ -if ((v) < -8388608) \ - (v) = -8388608; \ -else \ -if ((v) > 8388607) \ - (v) = 8388607 - -/* -#define CLIP8(v) \ -if ((v) < -128) \ - (v) = -128; \ -else \ -if ((v) > 127) \ - (v) = 127 -*/ - - -#include "snes9x.h" -#include "soundux.h" -#include "apu.h" -#include "memmap.h" -#include "cpuexec.h" -#include "asmmemfuncs.h" - - -static int wave[SOUND_BUFFER_SIZE]; - -//extern int Echo [24000]; -extern int MixBuffer [SOUND_BUFFER_SIZE]; -//extern int EchoBuffer [SOUND_BUFFER_SIZE]; -//extern int FilterTaps [8]; -extern unsigned long Z; -//extern int Loop [16]; - -extern long FilterValues[4][2]; -//extern int NoiseFreq [32]; - -//#define FIXED_POINT 0x10000UL -#define FIXED_POINT_REMAINDER 0xffffUL -#define FIXED_POINT_SHIFT 16 - -#define VOL_DIV8 0x8000 -#define VOL_DIV16 0x0080 -#define ENVX_SHIFT 24 - -extern "C" void DecodeBlockAsm (int8 *, int16 *, int32 *, int32 *); - -// F is channel's current frequency and M is the 16-bit modulation waveform -// from the previous channel multiplied by the current envelope volume level. -#define PITCH_MOD(F,M) ((F) * ((((unsigned long) (M)) + 0x800000) >> 16) >> 7) -//#define PITCH_MOD(F,M) ((F) * ((((M) & 0x7fffff) >> 14) + 1) >> 8) - -#define LAST_SAMPLE 0xffffff -#define JUST_PLAYED_LAST_SAMPLE(c) ((c)->sample_pointer >= LAST_SAMPLE) - - -static inline void S9xAPUSetEndOfSample (int i, Channel *ch) -{ - ch->state = SOUND_SILENT; - ch->mode = MODE_NONE; - APU.DSP [APU_ENDX] |= 1 << i; - APU.DSP [APU_KON] &= ~(1 << i); - APU.DSP [APU_KOFF] &= ~(1 << i); - APU.KeyedChannels &= ~(1 << i); -} -#ifdef __DJGPP -END_OF_FUNCTION (S9xAPUSetEndOfSample) -#endif - -static inline void S9xAPUSetEndX (int ch) -{ - APU.DSP [APU_ENDX] |= 1 << ch; -} -#ifdef __DJGPP -END_OF_FUNCTION (S9xAPUSetEndX) -#endif - -void S9xSetEchoDelay (int delay) -{ - SoundData.echo_buffer_size = (512 * delay * so.playback_rate) >> 15; // notaz / 32000; - if (so.stereo) - SoundData.echo_buffer_size <<= 1; - if (SoundData.echo_buffer_size) { - while(SoundData.echo_ptr >= SoundData.echo_buffer_size) - SoundData.echo_ptr -= SoundData.echo_buffer_size; - } else - SoundData.echo_ptr = 0; - S9xSetEchoEnable (APU.DSP [APU_EON]); -} - -void S9xSetSoundKeyOff (int channel) -{ - Channel *ch = &SoundData.channels[channel]; - - if (ch->state != SOUND_SILENT) - { - ch->state = SOUND_RELEASE; - ch->mode = MODE_RELEASE; - S9xSetEnvRate (ch, 8, -1, 0, 5<<28); - } -} - -void S9xFixSoundAfterSnapshotLoad () -{ - SoundData.echo_write_enabled = !(APU.DSP [APU_FLG] & 0x20); - SoundData.echo_channel_enable = APU.DSP [APU_EON]; - S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf); - S9xSetEchoFeedback ((signed char) APU.DSP [APU_EFB]); - - S9xSetFilterCoefficient (0, (signed char) APU.DSP [APU_C0]); - S9xSetFilterCoefficient (1, (signed char) APU.DSP [APU_C1]); - S9xSetFilterCoefficient (2, (signed char) APU.DSP [APU_C2]); - S9xSetFilterCoefficient (3, (signed char) APU.DSP [APU_C3]); - S9xSetFilterCoefficient (4, (signed char) APU.DSP [APU_C4]); - S9xSetFilterCoefficient (5, (signed char) APU.DSP [APU_C5]); - S9xSetFilterCoefficient (6, (signed char) APU.DSP [APU_C6]); - S9xSetFilterCoefficient (7, (signed char) APU.DSP [APU_C7]); - - for (int i = 0; i < 8; i++) - { - SoundData.channels[i].needs_decode = TRUE; - S9xSetSoundFrequency (i, SoundData.channels[i].hertz); - SoundData.channels [i].envxx = SoundData.channels [i].envx << ENVX_SHIFT; - SoundData.channels [i].next_sample = 0; - SoundData.channels [i].previous [0] = (int32) SoundData.channels [i].previous16 [0]; - SoundData.channels [i].previous [1] = (int32) SoundData.channels [i].previous16 [1]; - } - SoundData.master_volume [0] = SoundData.master_volume_left; - SoundData.master_volume [1] = SoundData.master_volume_right; - SoundData.echo_volume [0] = SoundData.echo_volume_left; - SoundData.echo_volume [1] = SoundData.echo_volume_right; - IAPU.Scanline = 0; -} - -void S9xSetEnvelopeHeight (int channel, int level) -{ - Channel *ch = &SoundData.channels[channel]; - - ch->envx = level; - ch->envxx = level << ENVX_SHIFT; - - ch->left_vol_level = (level * ch->volume_left) / 128; - ch->right_vol_level = (level * ch->volume_right) / 128; - - if (ch->envx == 0 && ch->state != SOUND_SILENT && ch->state != SOUND_GAIN) - { - S9xAPUSetEndOfSample (channel, ch); - } -} - -#if 1 -void S9xSetSoundSample (int, uint16) -{ -} -#else -void S9xSetSoundSample (int channel, uint16 sample_number) -{ - register Channel *ch = &SoundData.channels[channel]; - - if (ch->state != SOUND_SILENT && - sample_number != ch->sample_number) - { - int keep = ch->state; - ch->state = SOUND_SILENT; - ch->sample_number = sample_number; - ch->loop = FALSE; - ch->needs_decode = TRUE; - ch->last_block = FALSE; - ch->previous [0] = ch->previous[1] = 0; - ch->block_pointer = *S9xGetSampleAddress(sample_number); - ch->sample_pointer = 0; - ch->state = keep; - } -} -#endif - -static void DecodeBlock (Channel *ch) -{ - if (ch->block_pointer >= 0x10000 - 9) - { - ch->last_block = TRUE; - ch->loop = FALSE; - ch->block = ch->decoded; - memset32 ((uint32_t *) ch->decoded, 0, 8); - return; - } - signed char *compressed = (signed char *) &IAPU.RAM [ch->block_pointer]; - - unsigned char filter = *compressed; - if ((ch->last_block = filter & 1)) - ch->loop = (filter & 2) != 0; - - int16 *raw = ch->block = ch->decoded; - -#ifdef ARM - DecodeBlockAsm (compressed, raw, &ch->previous [0], &ch->previous [1]); -#else - int32 out; - unsigned char shift; - signed char sample1, sample2; - unsigned int i; - - compressed++; - - int32 prev0 = ch->previous [0]; - int32 prev1 = ch->previous [1]; - shift = filter >> 4; - - switch ((filter >> 2) & 3) - { - case 0: - for (i = 8; i != 0; i--) - { - sample1 = *compressed++; - sample2 = sample1 << 4; - sample2 >>= 4; - sample1 >>= 4; - *raw++ = ((int32) sample1 << shift); - *raw++ = ((int32) sample2 << shift); - } - prev1 = *(raw - 2); - prev0 = *(raw - 1); - break; - case 1: - for (i = 8; i != 0; i--) - { - sample1 = *compressed++; - sample2 = sample1 << 4; - sample2 >>= 4; - sample1 >>= 4; - prev0 = (int16) prev0; - *raw++ = prev1 = ((int32) sample1 << shift) + prev0 - (prev0 >> 4); - prev1 = (int16) prev1; - *raw++ = prev0 = ((int32) sample2 << shift) + prev1 - (prev1 >> 4); - } - break; - case 2: - for (i = 8; i != 0; i--) - { - sample1 = *compressed++; - sample2 = sample1 << 4; - sample2 >>= 4; - sample1 >>= 4; - - out = (sample1 << shift) - prev1 + (prev1 >> 4); - prev1 = (int16) prev0; - prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - - (prev0 >> 4); - - out = (sample2 << shift) - prev1 + (prev1 >> 4); - prev1 = (int16) prev0; - prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 5) - - (prev0 >> 4); - } - break; - case 3: - for (i = 8; i != 0; i--) - { - sample1 = *compressed++; - sample2 = sample1 << 4; - sample2 >>= 4; - sample1 >>= 4; - out = (sample1 << shift); - - out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); - prev1 = (int16) prev0; - prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - - (prev0 >> 4) - (prev1 >> 6); - - out = (sample2 << shift); - out = out - prev1 + (prev1 >> 3) + (prev1 >> 4); - prev1 = (int16) prev0; - prev0 &= ~3; - *raw++ = prev0 = out + (prev0 << 1) - (prev0 >> 3) - - (prev0 >> 4) - (prev1 >> 6); - } - break; - } - ch->previous [0] = prev0; - ch->previous [1] = prev1; - -#endif - ch->block_pointer += 9; -} - - -static void MixStereo (int sample_count) -{ - int pitch_mod = SoundData.pitch_mod & (0xFFFFFFFF^APU.DSP[APU_NON]);//~APU.DSP[APU_NON]; - - for (uint32 J = 0; J < NUM_CHANNELS; J++) - { - int32 VL, VR; - Channel *ch = &SoundData.channels[J]; - unsigned long freq0 = ch->frequency; - - if (ch->state == SOUND_SILENT) - continue; - -// freq0 = (unsigned long) ((double) freq0 * 0.985);//uncommented by jonathan gevaryahu, as it is necessary for most cards in linux - - bool8 mod = pitch_mod & (1 << J); - - if (ch->needs_decode) - { - DecodeBlock(ch); - ch->needs_decode = FALSE; - ch->sample = ch->block[0]; - ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT; - if (ch->sample_pointer == 0) - ch->sample_pointer = 1; - if (ch->sample_pointer > SOUND_DECODE_LENGTH) - ch->sample_pointer = SOUND_DECODE_LENGTH - 1; - - ch->next_sample = ch->block[ch->sample_pointer]; - } - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; - - for (uint32 I = 0; I < (uint32) sample_count; I += 2) - { - unsigned long freq = freq0; - - if (mod) - freq = PITCH_MOD(freq, wave [I / 2]); - - ch->env_error += ch->erate; - if (ch->env_error >= FIXED_POINT) - { - uint32 step = ch->env_error >> FIXED_POINT_SHIFT; - - switch (ch->state) - { - case SOUND_ATTACK: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_DECAY; - if (ch->sustain_level != 8) - { - S9xSetEnvRate (ch, ch->decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28); - break; - } - ch->state = SOUND_SUSTAIN; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28); - } - break; - - case SOUND_DECAY: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= ch->envx_target) - { - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - ch->state = SOUND_SUSTAIN; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28); - } - break; - - case SOUND_SUSTAIN: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_RELEASE: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_INCREASE_LINEAR: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_GAIN; - ch->mode = MODE_GAIN; - S9xSetEnvRate (ch, 0, -1, 0, 0); - } - break; - - case SOUND_INCREASE_BENT_LINE: - if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4) - { - while (ch->env_error >= FIXED_POINT) - { - ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - } - else - { - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - } - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_GAIN; - ch->mode = MODE_GAIN; - S9xSetEnvRate (ch, 0, -1, 0, 0); - } - break; - - case SOUND_DECREASE_LINEAR: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx -= step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_DECREASE_EXPONENTIAL: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - break; - - case SOUND_GAIN: - S9xSetEnvRate (ch, 0, -1, 0, 0); - break; - } - ch-> left_vol_level = (ch->envx * ch->volume_left) / 128; - ch->right_vol_level = (ch->envx * ch->volume_right) / 128; - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; - } - - ch->count += freq; - if (ch->count >= FIXED_POINT) - { - VL = ch->count >> FIXED_POINT_SHIFT; - ch->sample_pointer += VL; - ch->count &= FIXED_POINT_REMAINDER; - - ch->sample = ch->next_sample; - if (ch->sample_pointer >= SOUND_DECODE_LENGTH) - { - if (JUST_PLAYED_LAST_SAMPLE(ch)) - { - S9xAPUSetEndOfSample (J, ch); - goto stereo_exit; - } - do - { - ch->sample_pointer -= SOUND_DECODE_LENGTH; - if (ch->last_block) - { - if (!ch->loop) - { - ch->sample_pointer = LAST_SAMPLE; - ch->next_sample = ch->sample; - break; - } - else - { - S9xAPUSetEndX (J); - ch->last_block = FALSE; - uint16 *dir = S9xGetSampleAddress (ch->sample_number); - ch->block_pointer = *(dir + 1); - } - } - DecodeBlock (ch); - } while (ch->sample_pointer >= SOUND_DECODE_LENGTH); - if (!JUST_PLAYED_LAST_SAMPLE (ch)) - ch->next_sample = ch->block [ch->sample_pointer]; - } - else - ch->next_sample = ch->block [ch->sample_pointer]; - - if (ch->type != SOUND_SAMPLE) - { - for (;VL > 0; VL--) - if ((so.noise_gen <<= 1) & 0x80000000L) - so.noise_gen ^= 0x0040001L; - ch->sample = (so.noise_gen << 17) >> 17; - } - - VL = (ch->sample * ch-> left_vol_level) / 128; - VR = (ch->sample * ch->right_vol_level) / 128; - } - - if (pitch_mod & (1 << (J + 1))) - wave [I / 2] = ch->sample * ch->envx; - - MixBuffer [I] += VL; - MixBuffer [I+1] += VR; - if (ch->echo_buf_ptr) - { - ch->echo_buf_ptr [I] += VL; - ch->echo_buf_ptr [I+1] += VR; - } - } -stereo_exit: ; - } -} - -static void MixMono (int sample_count) -{ - int pitch_mod = SoundData.pitch_mod & (0xFFFFFFFF^APU.DSP[APU_NON]); - - for (uint32 J = 0; J < NUM_CHANNELS; J++) - { - Channel *ch = &SoundData.channels[J]; - unsigned long freq0 = ch->frequency; - - if (ch->state == SOUND_SILENT) - continue; - -// freq0 = (unsigned long) ((double) freq0 * 0.985); - - bool8 mod = pitch_mod & (1 << J); - - if (ch->needs_decode) - { - DecodeBlock(ch); - ch->needs_decode = FALSE; - ch->sample = ch->block[0]; - ch->sample_pointer = freq0 >> FIXED_POINT_SHIFT; - if (ch->sample_pointer == 0) - ch->sample_pointer = 1; - if (ch->sample_pointer > SOUND_DECODE_LENGTH) - ch->sample_pointer = SOUND_DECODE_LENGTH - 1; - ch->next_sample = ch->block[ch->sample_pointer]; - - } - int32 V = (ch->sample * ch->left_vol_level) / 128; - - for (uint32 I = 0; I < (uint32) sample_count; I++) - { - unsigned long freq = freq0; - - if (mod) - freq = PITCH_MOD(freq, wave [I]); - - ch->env_error += ch->erate; - if (ch->env_error >= FIXED_POINT) - { - uint32 step = ch->env_error >> FIXED_POINT_SHIFT; - - switch (ch->state) - { - case SOUND_ATTACK: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_DECAY; - if (ch->sustain_level != 8) - { - S9xSetEnvRate (ch, ch->decay_rate, -1, - (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28); - break; - } - ch->state = SOUND_SUSTAIN; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28); - } - break; - - case SOUND_DECAY: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= ch->envx_target) - { - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto mono_exit; - } - ch->state = SOUND_SUSTAIN; - S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28); - } - break; - - case SOUND_SUSTAIN: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto mono_exit; - } - break; - - case SOUND_RELEASE: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx -= (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto mono_exit; - } - break; - - case SOUND_INCREASE_LINEAR: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_GAIN; - ch->mode = MODE_GAIN; - S9xSetEnvRate (ch, 0, -1, 0, 0); - } - break; - - case SOUND_INCREASE_BENT_LINE: - if (ch->envx >= (MAX_ENVELOPE_HEIGHT * 3) / 4) - { - while (ch->env_error >= FIXED_POINT) - { - ch->envxx += (MAX_ENVELOPE_HEIGHT << ENVX_SHIFT) / 256; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - } - else - { - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx += step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - } - - if (ch->envx >= 126) - { - ch->envx = 127; - ch->envxx = 127 << ENVX_SHIFT; - ch->state = SOUND_GAIN; - ch->mode = MODE_GAIN; - S9xSetEnvRate (ch, 0, -1, 0, 0); - } - break; - - case SOUND_DECREASE_LINEAR: - ch->env_error &= FIXED_POINT_REMAINDER; - ch->envx -= step << 1; - ch->envxx = ch->envx << ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto mono_exit; - } - break; - - case SOUND_DECREASE_EXPONENTIAL: - while (ch->env_error >= FIXED_POINT) - { - ch->envxx = (ch->envxx >> 8) * 255; - ch->env_error -= FIXED_POINT; - } - ch->envx = ch->envxx >> ENVX_SHIFT; - if (ch->envx <= 0) - { - S9xAPUSetEndOfSample (J, ch); - goto mono_exit; - } - break; - - case SOUND_GAIN: - S9xSetEnvRate (ch, 0, -1, 0, 0); - break; - } - ch->left_vol_level = (ch->envx * ch->volume_left) / 128; - V = (ch->sample * ch->left_vol_level) / 128; - } - - ch->count += freq; - if (ch->count >= FIXED_POINT) - { - V = ch->count >> FIXED_POINT_SHIFT; - ch->sample_pointer += V; - ch->count &= FIXED_POINT_REMAINDER; - - ch->sample = ch->next_sample; - if (ch->sample_pointer >= SOUND_DECODE_LENGTH) - { - if (JUST_PLAYED_LAST_SAMPLE(ch)) - { - S9xAPUSetEndOfSample (J, ch); - goto mono_exit; - } - do - { - ch->sample_pointer -= SOUND_DECODE_LENGTH; - if (ch->last_block) - { - if (!ch->loop) - { - ch->sample_pointer = LAST_SAMPLE; - ch->next_sample = ch->sample; - break; - } - else - { - ch->last_block = FALSE; - uint16 *dir = S9xGetSampleAddress (ch->sample_number); - ch->block_pointer = *(dir + 1); - S9xAPUSetEndX (J); - } - } - DecodeBlock (ch); - } while (ch->sample_pointer >= SOUND_DECODE_LENGTH); - if (!JUST_PLAYED_LAST_SAMPLE (ch)) - ch->next_sample = ch->block [ch->sample_pointer]; - } - else - ch->next_sample = ch->block [ch->sample_pointer]; - - if (ch->type != SOUND_SAMPLE) - { - for (;V > 0; V--) - if ((so.noise_gen <<= 1) & 0x80000000L) - so.noise_gen ^= 0x0040001L; - ch->sample = (so.noise_gen << 17) >> 17; - } - V = (ch->sample * ch-> left_vol_level) / 128; - } - - MixBuffer [I] += V; - if (ch->echo_buf_ptr) - ch->echo_buf_ptr [I] += V; - - if (pitch_mod & (1 << (J + 1))) - wave [I] = ch->sample * ch->envx; - } -mono_exit: ; - } -} - - -// For backwards compatibility with older port specific code -void S9xMixSamples (signed short *buffer, int sample_count) -{ - S9xMixSamplesO (buffer, sample_count, 0); -} - - -void S9xMixSamplesO (signed short *buffer, int sample_count, int sample_offset) -{ - // 16-bit sound only - int J; - - buffer += sample_offset; - - if (so.mute_sound) - { - memset16((uint16_t*)buffer, 0, sample_count); - return; - } - - memset32 ((uint32_t*)MixBuffer, 0, sample_count); - if (SoundData.echo_enable) - memset32 ((uint32_t*)EchoBuffer, 0, sample_count); - - if (so.stereo) - MixStereo (sample_count); - else - MixMono (sample_count); - - /* Mix and convert waveforms */ - if (SoundData.echo_enable && SoundData.echo_buffer_size) - { - if (so.stereo) - { - int l, r; - int master_vol_l = SoundData.master_volume[0]; - int master_vol_r = SoundData.master_volume[1]; - int echo_vol_l = SoundData.echo_volume[0]; - int echo_vol_r = SoundData.echo_volume[1]; - - // 16-bit stereo sound with echo enabled ... - if (SoundData.no_filter) - { - // ... but no filter defined. - for (J = 0; J < sample_count; J+=2) - { - int E = Echo [SoundData.echo_ptr]; - - Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J]; - Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J+1]; - - if (SoundData.echo_ptr >= SoundData.echo_buffer_size) - SoundData.echo_ptr = 0; - - l = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16; - r = (MixBuffer[J+1] * master_vol_r + E * echo_vol_r) / VOL_DIV16; - - CLIP16(l); - CLIP16(r); - buffer[J] = l; - buffer[J+1] = r; - } - } - else - { - // ... with filter defined. - for (J = 0; J < sample_count; J+=2) - { - register int E = Echo [SoundData.echo_ptr]; - - Loop [(Z - 0) & 15] = E; - - - - E = E * FilterTaps [0]; - E += Loop [(Z - 2) & 15] * FilterTaps [1]; - E += Loop [(Z - 4) & 15] * FilterTaps [2]; - E += Loop [(Z - 6) & 15] * FilterTaps [3]; - E += Loop [(Z - 8) & 15] * FilterTaps [4]; - E += Loop [(Z - 10) & 15] * FilterTaps [5]; - E += Loop [(Z - 12) & 15] * FilterTaps [6]; - E += Loop [(Z - 14) & 15] * FilterTaps [7]; - E /= 128; - Z++; - - Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J]; - Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J+1]; - - if (SoundData.echo_ptr >= SoundData.echo_buffer_size) - SoundData.echo_ptr = 0; - - l = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16; - r = (MixBuffer[J+1] * master_vol_r + E * echo_vol_r) / VOL_DIV16; - - CLIP16(l); - CLIP16(r); - buffer[J] = l; - buffer[J+1] = r; - } - } - } - else - { - int I; - int master_vol_l = SoundData.master_volume[0]; - int echo_vol_l = SoundData.echo_volume[0]; - - // 16-bit mono sound with echo enabled... - if (SoundData.no_filter) - { - // ... no filter defined - for (J = 0; J < sample_count; J++) - { - int E = Echo [SoundData.echo_ptr]; - - Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J]; - - if (SoundData.echo_ptr >= SoundData.echo_buffer_size) - SoundData.echo_ptr = 0; - - I = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16; - CLIP16(I); - buffer[J] = I; - } - } - else - { - // ... with filter defined - for (J = 0; J < sample_count; J++) - { - register int E = Echo [SoundData.echo_ptr]; - - Loop [(Z - 0) & 7] = E; - E = E * FilterTaps [0]; - E += Loop [(Z - 1) & 7] * FilterTaps [1]; - E += Loop [(Z - 2) & 7] * FilterTaps [2]; - E += Loop [(Z - 3) & 7] * FilterTaps [3]; - E += Loop [(Z - 4) & 7] * FilterTaps [4]; - E += Loop [(Z - 5) & 7] * FilterTaps [5]; - E += Loop [(Z - 6) & 7] * FilterTaps [6]; - E += Loop [(Z - 7) & 7] * FilterTaps [7]; - E /= 128; - Z++; - - Echo[SoundData.echo_ptr++] = (E * SoundData.echo_feedback) / 128 + EchoBuffer[J]; - - if (SoundData.echo_ptr >= SoundData.echo_buffer_size) - SoundData.echo_ptr = 0; - - I = (MixBuffer[J] * master_vol_l + E * echo_vol_l) / VOL_DIV16; - CLIP16(I); - buffer[J] = I; - } - } - } - } - else - { - int l, master_vol_l = SoundData.master_volume[0]; - - if (so.stereo) - { - int r, master_vol_r = SoundData.master_volume[1]; - - // 16-bit stereo sound, no echo - for (J = 0; J < sample_count; J+=2) - { - l = (MixBuffer[J] * master_vol_l) / VOL_DIV16; - r = (MixBuffer[J+1] * master_vol_r) / VOL_DIV16; - - CLIP16(l); - CLIP16(r); - buffer[J] = l; - buffer[J+1] = r; - } - } - else - { - // 16-bit mono sound, no echo - for (J = 0; J < sample_count; J++) - { - l = (MixBuffer[J] * master_vol_l) / VOL_DIV16; - - CLIP16(l); - buffer[J] = l; - } - } - } -} - -#ifdef __DJGPP -END_OF_FUNCTION(S9xMixSamplesO); -#endif - -void S9xResetSound (bool8 full) -{ - for (int i = 0; i < 8; i++) - { - SoundData.channels[i].state = SOUND_SILENT; - SoundData.channels[i].mode = MODE_NONE; - SoundData.channels[i].type = SOUND_SAMPLE; - SoundData.channels[i].volume_left = 0; - SoundData.channels[i].volume_right = 0; - SoundData.channels[i].hertz = 0; - SoundData.channels[i].count = 0; - SoundData.channels[i].loop = FALSE; - SoundData.channels[i].envx_target = 0; - SoundData.channels[i].env_error = 0; - SoundData.channels[i].erate = 0; - SoundData.channels[i].envx = 0; - SoundData.channels[i].envxx = 0; - SoundData.channels[i].left_vol_level = 0; - SoundData.channels[i].right_vol_level = 0; - SoundData.channels[i].direction = 0; - SoundData.channels[i].attack_rate = 0; - SoundData.channels[i].decay_rate = 0; - SoundData.channels[i].sustain_rate = 0; - SoundData.channels[i].release_rate = 0; - SoundData.channels[i].sustain_level = 0; - // notaz - SoundData.channels[i].env_ind_attack = 0; - SoundData.channels[i].env_ind_decay = 0; - SoundData.channels[i].env_ind_sustain = 0; - SoundData.echo_ptr = 0; - SoundData.echo_feedback = 0; - SoundData.echo_buffer_size = 1; - } - FilterTaps [0] = 127; - FilterTaps [1] = 0; - FilterTaps [2] = 0; - FilterTaps [3] = 0; - FilterTaps [4] = 0; - FilterTaps [5] = 0; - FilterTaps [6] = 0; - FilterTaps [7] = 0; - so.mute_sound = TRUE; - so.noise_gen = 1; - - if (full) - { - SoundData.master_volume_left = 0; - SoundData.master_volume_right = 0; - SoundData.echo_volume_left = 0; - SoundData.echo_volume_right = 0; - SoundData.echo_enable = 0; - SoundData.echo_write_enabled = 0; - SoundData.echo_channel_enable = 0; - SoundData.pitch_mod = 0; - SoundData.dummy[0] = 0; - SoundData.dummy[1] = 0; - SoundData.dummy[2] = 0; - SoundData.master_volume[0] = 0; - SoundData.master_volume[1] = 0; - SoundData.echo_volume[0] = 0; - SoundData.echo_volume[1] = 0; - SoundData.noise_hertz = 0; - } - - SoundData.master_volume_left = 127; - SoundData.master_volume_right = 127; - SoundData.master_volume [0] = SoundData.master_volume [1] = 127; - SoundData.no_filter = TRUE; -} - - - -extern unsigned long AttackRate [16]; -extern unsigned long DecayRate [8]; -extern unsigned long SustainRate [32]; -extern unsigned long IncreaseRate [32]; -extern unsigned long DecreaseRateExp [32]; - - -void S9xSetPlaybackRate (uint32 playback_rate) -{ - so.playback_rate = playback_rate; - - if(playback_rate) { - // notaz: calclulate a value (let's call it freqbase) to simplify channel freq calculations later. - so.freqbase = (FIXED_POINT<<11) / (playback_rate * 33 / 32); - // now precalculate env rates for S9xSetEnvRate - static int steps [] = - { - //0, 64, 1238, 1238, 256, 1, 64, 109, 64, 1238 - 0, 64, 619, 619, 128, 1, 64, 55, 64, 619 - }; - int i, u; - for(i=0; i < 16; i++) - for(u=0; u < 10; u++) - AttackERate[i][u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / - (AttackRate[i] * playback_rate)); - for(i=0; i < 8; i++) - for(u=0; u < 10; u++) - DecayERate[i][u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / - (DecayRate[i] * playback_rate)); - - for(i=0; i < 32; i++) - for(u=0; u < 10; u++) - SustainERate[i][u]= (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / - (SustainRate[i] * playback_rate)); - - for(i=0; i < 32; i++) - for(u=0; u < 10; u++) - IncreaseERate[i][u]=(unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / - (IncreaseRate[i] * playback_rate)); - - for(i=0; i < 32; i++) - for(u=0; u < 10; u++) - DecreaseERateExp[i][u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / - (DecreaseRateExp[i] / 2 * playback_rate)); - - for(u=0; u < 10; u++) - KeyOffERate[u] = (unsigned long) (((int64) FIXED_POINT * 1000 * steps[u]) / - (8 * playback_rate)); - } - - S9xSetEchoDelay (APU.DSP [APU_EDL] & 0xf); - for (int i = 0; i < 8; i++) - S9xSetSoundFrequency (i, SoundData.channels [i].hertz); -} - -bool8 S9xInitSound (void) -{ - so.playback_rate = 0; - so.stereo = 0; - - S9xResetSound (TRUE); - S9xSetSoundMute (TRUE); - - return (1); -} - diff --git a/src/soundux.h b/src/soundux.h index 4b313df..9d084bd 100644 --- a/src/soundux.h +++ b/src/soundux.h @@ -270,6 +270,7 @@ static inline void S9xSetEnvRate (Channel *ch, unsigned long rate, int direction static inline void S9xSetEchoEnable (uint8 byte) { + int i; SoundData.echo_channel_enable = byte; if (!SoundData.echo_write_enabled || Settings.DisableSoundEcho) byte = 0; @@ -280,7 +281,7 @@ static inline void S9xSetEchoEnable (uint8 byte) } SoundData.echo_enable = byte; - for (int i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { if (byte & (1 << i)) SoundData.channels [i].echo_buf_ptr = EchoBuffer; diff --git a/src/spc700.c b/src/spc700.c new file mode 100644 index 0000000..8fd1230 --- /dev/null +++ b/src/spc700.c @@ -0,0 +1,2509 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +#include "snes9x.h" +#include "memmap.h" +#include "display.h" +#include "cpuexec.h" +#include "apu.h" +#include "spc700.h" + +// SPC700/Sound DSP chips have a 24.57MHz crystal on their PCB. + +// we only need the memhandlers +#undef INLINE +#define INLINE +#include "apumem.h" + +#define OP1 (*(IAPU.PC + 1)) +#define OP2 (*(IAPU.PC + 2)) + +#ifdef SPC700_SHUTDOWN +#define APUShutdown() \ + if (Settings.Shutdown && (IAPU.PC == IAPU.WaitAddress1 || IAPU.PC == IAPU.WaitAddress2)) \ + { \ + if (IAPU.WaitCounter == 0) \ + { \ + if (!ICPU.CPUExecuting) \ + CPU.APU_Cycles = CPU.Cycles = CPU.NextEvent; \ + else \ + CPU.APU_APUExecuting = FALSE; \ + } \ + else \ + if (IAPU.WaitCounter >= 2) \ + IAPU.WaitCounter = 1; \ + else \ + IAPU.WaitCounter--; \ + } +#else +#define APUShutdown() +#endif + +#define APUSetZN8(b)\ + IAPU._Zero = (b); + +#define APUSetZN16(w)\ + IAPU._Zero = ((w) != 0) | ((w) >> 8); + +void STOP (char *s) +{ + char buffer[100]; + +#ifdef DEBUGGER + S9xAPUOPrint (buffer, IAPU.PC - IAPU.RAM); +#endif + + sprintf (String, "Sound CPU in unknown state executing %s at %04lX\n%s\n", s, IAPU.PC - IAPU.RAM, buffer); + S9xMessage (S9X_ERROR, S9X_APU_STOPPED, String); + APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE; + CPU.APU_APUExecuting = FALSE; + +#ifdef DEBUGGER + CPU.Flags |= DEBUG_MODE_FLAG; +#else + S9xExit (); +#endif +} + +#define TCALL(n)\ +{\ + PushW ((IAPU.PC - IAPU.RAM + 1)); \ + IAPU.PC = IAPU.RAM + (APU.ExtraRAM [((15 - n) << 1)] + \ + (APU.ExtraRAM [((15 - n) << 1) + 1] << 8)); \ +} + +// XXX: HalfCarry - BJ fixed? +#define SBC(a,b)\ +short Int16 = (short) (a) - (short) (b) + (short) (APUCheckCarry ()) - 1;\ +IAPU._Carry = Int16 >= 0;\ +if ((((a) ^ (b)) & 0x80) && (((a) ^ (uint8) Int16) & 0x80))\ + APUSetOverflow ();\ +else \ + APUClearOverflow (); \ +APUSetHalfCarry ();\ +if(((a) ^ (b) ^ (uint8) Int16) & 0x10)\ + APUClearHalfCarry ();\ +(a) = (uint8) Int16;\ +APUSetZN8 ((uint8) Int16); + +// XXX: HalfCarry - BJ fixed? +#define ADC(a,b)\ +uint16 Work16 = (a) + (b) + APUCheckCarry();\ +IAPU._Carry = Work16 >= 0x100; \ +if (~((a) ^ (b)) & ((b) ^ (uint8) Work16) & 0x80)\ + APUSetOverflow ();\ +else \ + APUClearOverflow (); \ +APUClearHalfCarry ();\ +/*if(((a) ^ (b) ^ (uint8) Int16) & 0x10) notaz: Int16!? */\ +if(((a) ^ (b) ^ (uint8) Work16) & 0x10)\ + APUSetHalfCarry ();\ +(a) = (uint8) Work16;\ +APUSetZN8 ((uint8) Work16); + +#define CMP(a,b)\ +short Int16 = (short) (a) - (short) (b);\ +IAPU._Carry = Int16 >= 0;\ +APUSetZN8 ((uint8) Int16); + +#define ASL(b)\ + IAPU._Carry = ((b) & 0x80) != 0; \ + (b) <<= 1;\ + APUSetZN8 (b); +#define LSR(b)\ + IAPU._Carry = (b) & 1;\ + (b) >>= 1;\ + APUSetZN8 (b); +#define ROL(b)\ + uint16 Work16 = ((b) << 1) | APUCheckCarry (); \ + IAPU._Carry = Work16 >= 0x100; \ + (b) = (uint8) Work16; \ + APUSetZN8 (b); +#define ROR(b)\ + uint16 Work16 = (b) | ((uint16) APUCheckCarry () << 8); \ + IAPU._Carry = (uint8) Work16 & 1; \ + Work16 >>= 1; \ + (b) = (uint8) Work16; \ + APUSetZN8 (b); + +#define Push(b)\ + *(IAPU.RAM + 0x100 + IAPU.S) = b;\ + IAPU.S--; + +#define Pop(b)\ + IAPU.S++;\ + (b) = *(IAPU.RAM + 0x100 + IAPU.S); + +#ifdef FAST_LSB_WORD_ACCESS +#define PushW(w)\ + *(uint16 *) (IAPU.RAM + 0xff + IAPU.S) = w;\ + IAPU.S -= 2; +#define PopW(w)\ + IAPU.S += 2;\ + w = *(uint16 *) (IAPU.RAM + 0xff + IAPU.S); +#else +#define PushW(w)\ + *(IAPU.RAM + 0xff + IAPU.S) = w;\ + *(IAPU.RAM + 0x100 + IAPU.S) = (w >> 8);\ + IAPU.S -= 2; +#define PopW(w)\ + IAPU.S += 2; \ + (w) = *(IAPU.RAM + 0xff + IAPU.S) + (*(IAPU.RAM + 0x100 + IAPU.S) << 8); +#endif + +#define Relative()\ + signed char Int8 = OP1;\ + short Int16 = (int) (IAPU.PC + 2 - IAPU.RAM) + Int8; + +#define Relative2()\ + signed char Int8 = OP2;\ + short Int16 = (int) (IAPU.PC + 3 - IAPU.RAM) + Int8; + +#ifdef FAST_LSB_WORD_ACCESS +#define IndexedXIndirect()\ + IAPU.Address = *(uint16 *) (IAPU.DirectPage + ((OP1 + IAPU.X) & 0xff)); + +#define Absolute()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1); + +#define AbsoluteX()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1) + IAPU.X; + +#define AbsoluteY()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1) + IAPU.YA.B.Y; + +#define MemBit()\ + IAPU.Address = *(uint16 *) (IAPU.PC + 1);\ + IAPU.Bit = (uint8)(IAPU.Address >> 13);\ + IAPU.Address &= 0x1fff; + +#define IndirectIndexedY()\ + IAPU.Address = *(uint16 *) (IAPU.DirectPage + OP1) + IAPU.YA.B.Y; +#else +#define IndexedXIndirect()\ + IAPU.Address = *(IAPU.DirectPage + ((OP1 + IAPU.X) & 0xff)) + \ + (*(IAPU.DirectPage + ((OP1 + IAPU.X + 1) & 0xff)) << 8); +#define Absolute()\ + IAPU.Address = OP1 + (OP2 << 8); + +#define AbsoluteX()\ + IAPU.Address = OP1 + (OP2 << 8) + IAPU.X; + +#define AbsoluteY()\ + IAPU.Address = OP1 + (OP2 << 8) + IAPU.YA.B.Y; + +#define MemBit()\ + IAPU.Address = OP1 + (OP2 << 8);\ + IAPU.Bit = (int8) (IAPU.Address >> 13);\ + IAPU.Address &= 0x1fff; + +#define IndirectIndexedY()\ + IAPU.Address = *(IAPU.DirectPage + OP1) + \ + (*(IAPU.DirectPage + OP1 + 1) << 8) + \ + IAPU.YA.B.Y; +#endif + +void Apu00 () +{ +// NOP + IAPU.PC++; +} + +void Apu01 () { TCALL (0) } + +void Apu11 () { TCALL (1) } + +void Apu21 () { TCALL (2) } + +void Apu31 () { TCALL (3) } + +void Apu41 () { TCALL (4) } + +void Apu51 () { TCALL (5) } + +void Apu61 () { TCALL (6) } + +void Apu71 () { TCALL (7) } + +void Apu81 () { TCALL (8) } + +void Apu91 () { TCALL (9) } + +void ApuA1 () { TCALL (10) } + +void ApuB1 () { TCALL (11) } + +void ApuC1 () { TCALL (12) } + +void ApuD1 () { TCALL (13) } + +void ApuE1 () { TCALL (14) } + +void ApuF1 () { TCALL (15) } + +void Apu3F () // CALL absolute +{ + Absolute (); + // 0xB6f for Star Fox 2 + PushW ((IAPU.PC + 3 - IAPU.RAM)); + IAPU.PC = IAPU.RAM + IAPU.Address; +} + +void Apu4F () // PCALL $XX +{ + uint8 Work8 = OP1; + PushW ((IAPU.PC + 2 - IAPU.RAM)); + IAPU.PC = IAPU.RAM + 0xff00 + Work8; +} + +#define SET(b) \ +S9xAPUSetByteZ ((uint8) (S9xAPUGetByteZ (OP1 ) | (1 << (b))), OP1); \ +IAPU.PC += 2 + +void Apu02 () +{ + SET (0); +} + +void Apu22 () +{ + SET (1); +} + +void Apu42 () +{ + SET (2); +} + +void Apu62 () +{ + SET (3); +} + + + +void Apu82 () +{ + + + SET (4); +} + +void ApuA2 () +{ + SET (5); +} + +void ApuC2 () +{ + SET (6); +} + +void ApuE2 () +{ + SET (7); +} + +#define CLR(b) \ +S9xAPUSetByteZ ((uint8) (S9xAPUGetByteZ (OP1) & ~(1 << (b))), OP1); \ +IAPU.PC += 2; + +void Apu12 () +{ + CLR (0); +} + +void Apu32 () +{ + CLR (1); +} + +void Apu52 () +{ + CLR (2); +} + +void Apu72 () +{ + CLR (3); +} + +void Apu92 () +{ + CLR (4); +} + +void ApuB2 () +{ + CLR (5); +} + +void ApuD2 () +{ + CLR (6); +} + +void ApuF2 () +{ + CLR (7); +} + +#define BBS(b) \ +uint8 Work8 = OP1; \ +Relative2 (); \ +if (S9xAPUGetByteZ (Work8) & (1 << (b))) \ +{ \ + IAPU.PC = IAPU.RAM + (uint16) Int16; \ + CPU.APU_Cycles += IAPU.TwoCycles; \ +} \ +else \ + IAPU.PC += 3 + +void Apu03 () +{ + BBS (0); +} + +void Apu23 () +{ + BBS (1); +} + +void Apu43 () +{ + BBS (2); +} + +void Apu63 () +{ + BBS (3); +} + +void Apu83 () +{ + BBS (4); +} + +void ApuA3 () +{ + BBS (5); +} + +void ApuC3 () +{ + BBS (6); +} + +void ApuE3 () +{ + BBS (7); +} + +#define BBC(b) \ +uint8 Work8 = OP1; \ +Relative2 (); \ +if (!(S9xAPUGetByteZ (Work8) & (1 << (b)))) \ +{ \ + IAPU.PC = IAPU.RAM + (uint16) Int16; \ + CPU.APU_Cycles += IAPU.TwoCycles; \ +} \ +else \ + IAPU.PC += 3 + +void Apu13 () +{ + BBC (0); +} + +void Apu33 () +{ + BBC (1); +} + +void Apu53 () +{ + BBC (2); +} + +void Apu73 () +{ + BBC (3); +} + +void Apu93 () +{ + BBC (4); +} + +void ApuB3 () +{ + BBC (5); +} + +void ApuD3 () +{ + BBC (6); +} + +void ApuF3 () +{ + BBC (7); +} + +void Apu04 () +{ +// OR A,dp + IAPU.YA.B.A |= S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu05 () +{ +// OR A,abs + Absolute (); + IAPU.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void Apu06 () +{ +// OR A,(X) + IAPU.YA.B.A |= S9xAPUGetByteZ (IAPU.X); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void Apu07 () +{ +// OR A,(dp+X) + IndexedXIndirect (); + IAPU.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu08 () +{ +// OR A,#00 + IAPU.YA.B.A |= OP1; + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu09 () +{ +// OR dp(dest),dp(src) + uint8 Work8 = S9xAPUGetByteZ (OP1); + Work8 |= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu14 () +{ +// OR A,dp+X + IAPU.YA.B.A |= S9xAPUGetByteZ (OP1 + IAPU.X); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu15 () +{ +// OR A,abs+X + AbsoluteX (); + IAPU.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void Apu16 () +{ +// OR A,abs+Y + AbsoluteY (); + IAPU.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void Apu17 () +{ +// OR A,(dp)+Y + IndirectIndexedY (); + IAPU.YA.B.A |= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu18 () +{ +// OR dp,#00 + uint8 Work8 = OP1; + Work8 |= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu19 () +{ +// OR (X),(Y) + uint8 Work8 = S9xAPUGetByteZ (IAPU.X) | S9xAPUGetByteZ (IAPU.YA.B.Y); + APUSetZN8 (Work8); + S9xAPUSetByteZ (Work8, IAPU.X); + IAPU.PC++; +} + +void Apu0A () +{ +// OR1 C,membit + MemBit (); + if (!APUCheckCarry ()) + { + if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) + APUSetCarry (); + } + IAPU.PC += 3; +} + +void Apu2A () +{ +// OR1 C,not membit + MemBit (); + if (!APUCheckCarry ()) + { + if (!(S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) + APUSetCarry (); + } + IAPU.PC += 3; +} + +void Apu4A () +{ +// AND1 C,membit + MemBit (); + if (APUCheckCarry ()) + { + if (!(S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) + APUClearCarry (); + } + IAPU.PC += 3; +} + +void Apu6A () +{ +// AND1 C, not membit + MemBit (); + if (APUCheckCarry ()) + { + if ((S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) + APUClearCarry (); + } + IAPU.PC += 3; +} + +void Apu8A () +{ +// EOR1 C, membit + MemBit (); + if (APUCheckCarry ()) + { + if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) + APUClearCarry (); + } + else + { + if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) + APUSetCarry (); + } + IAPU.PC += 3; +} + +void ApuAA () +{ +// MOV1 C,membit + MemBit (); + if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) + APUSetCarry (); + else + APUClearCarry (); + IAPU.PC += 3; +} + +void ApuCA () +{ +// MOV1 membit,C + MemBit (); + if (APUCheckCarry ()) + { + S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) | (1 << IAPU.Bit), IAPU.Address); + } + else + { + S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) & ~(1 << IAPU.Bit), IAPU.Address); + } + IAPU.PC += 3; +} + +void ApuEA () +{ +// NOT1 membit + MemBit (); + S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) ^ (1 << IAPU.Bit), IAPU.Address); + IAPU.PC += 3; +} + +void Apu0B () +{ +// ASL dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + ASL (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu0C () +{ +// ASL abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + ASL (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu1B () +{ +// ASL dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); + ASL (Work8); + S9xAPUSetByteZ (Work8, OP1 + IAPU.X); + IAPU.PC += 2; +} + +void Apu1C () +{ +// ASL A + ASL (IAPU.YA.B.A); + IAPU.PC++; +} + +void Apu0D () +{ +// PUSH PSW + S9xAPUPackStatus (); + Push (IAPU.P); + IAPU.PC++; +} + +void Apu2D () +{ +// PUSH A + Push (IAPU.YA.B.A); + IAPU.PC++; +} + +void Apu4D () +{ +// PUSH X + Push (IAPU.X); + IAPU.PC++; +} + +void Apu6D () +{ +// PUSH Y + Push (IAPU.YA.B.Y); + IAPU.PC++; +} + +void Apu8E () +{ +// POP PSW + Pop (IAPU.P); + S9xAPUUnpackStatus (); + if (APUCheckDirectPage ()) + IAPU.DirectPage = IAPU.RAM + 0x100; + else + IAPU.DirectPage = IAPU.RAM; + IAPU.PC++; +} + +void ApuAE () +{ +// POP A + Pop (IAPU.YA.B.A); + IAPU.PC++; +} + +void ApuCE () +{ +// POP X + Pop (IAPU.X); + IAPU.PC++; +} + +void ApuEE () +{ +// POP Y + Pop (IAPU.YA.B.Y); + IAPU.PC++; +} + +void Apu0E () +{ +// TSET1 abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + S9xAPUSetByte (Work8 | IAPU.YA.B.A, IAPU.Address); + Work8 &= IAPU.YA.B.A; + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu4E () +{ +// TCLR1 abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + S9xAPUSetByte (Work8 & ~IAPU.YA.B.A, IAPU.Address); + Work8 &= IAPU.YA.B.A; + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu0F () +{ +// BRK + +#if 0 + STOP ("BRK"); +#else + PushW ((IAPU.PC + 1 - IAPU.RAM)); + S9xAPUPackStatus (); + Push (IAPU.P); + APUSetBreak (); + APUClearInterrupt (); +// XXX:Where is the BRK vector ??? + IAPU.PC = IAPU.RAM + APU.ExtraRAM[0x20] + (APU.ExtraRAM[0x21] << 8); +#endif +} + +void ApuEF () +{ +// SLEEP + // XXX: sleep + // STOP ("SLEEP"); + CPU.APU_APUExecuting = FALSE; + IAPU.PC++; +} + +void ApuFF () +{ +// STOP + // STOP ("STOP"); + CPU.APU_APUExecuting = FALSE; + IAPU.PC++; +} + +void Apu10 () +{ +// BPL + Relative (); + if (!APUCheckNegative ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void Apu30 () +{ +// BMI + Relative (); + if (APUCheckNegative ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void Apu90 () +{ +// BCC + Relative (); + if (!APUCheckCarry ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void ApuB0 () +{ +// BCS + Relative (); + if (APUCheckCarry ()) + { + + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void ApuD0 () +{ +// BNE + Relative (); + if (!APUCheckZero ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void ApuF0 () +{ +// BEQ + Relative (); + if (APUCheckZero ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 2; +} + +void Apu50 () +{ +// BVC + Relative (); + if (!APUCheckOverflow ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + } + else + IAPU.PC += 2; +} + +void Apu70 () +{ +// BVS + Relative (); + if (APUCheckOverflow ()) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + } + else + IAPU.PC += 2; +} + +void Apu2F () +{ +// BRA + Relative (); + IAPU.PC = IAPU.RAM + (uint16) Int16; +} + +void Apu80 () +{ +// SETC + APUSetCarry (); + IAPU.PC++; +} + +void ApuED () +{ +// NOTC + IAPU._Carry ^= 1; + IAPU.PC++; +} + +void Apu40 () +{ +// SETP + APUSetDirectPage (); + IAPU.DirectPage = IAPU.RAM + 0x100; + IAPU.PC++; +} + +void Apu1A () +{ +// DECW dp + uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + Work16--; + S9xAPUSetByteZ ((uint8) Work16, OP1); + S9xAPUSetByteZ (Work16 >> 8, OP1 + 1); + APUSetZN16 (Work16); + IAPU.PC += 2; +} + +void Apu5A () +{ +// CMPW YA,dp + uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + long Int32 = (long) IAPU.YA.W - (long) Work16; + IAPU._Carry = Int32 >= 0; + APUSetZN16 ((uint16) Int32); + IAPU.PC += 2; +} + +void Apu3A () +{ +// INCW dp + uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + Work16++; + S9xAPUSetByteZ ((uint8) Work16, OP1); + S9xAPUSetByteZ (Work16 >> 8, OP1 + 1); + APUSetZN16 (Work16); + IAPU.PC += 2; +} + +// XXX: HalfCarry - BJ Fixed? Or is it between bits 7 and 8 for ADDW/SUBW? +void Apu7A () +{ +// ADDW YA,dp + uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + uint32 Work32 = (uint32) IAPU.YA.W + Work16; + IAPU._Carry = Work32 >= 0x10000; + if (~(IAPU.YA.W ^ Work16) & (Work16 ^ (uint16) Work32) & 0x8000) + APUSetOverflow (); + else + APUClearOverflow (); + APUClearHalfCarry (); + if((IAPU.YA.W ^ Work16 ^ (uint16) Work32) & 0x10) + APUSetHalfCarry (); + IAPU.YA.W = (uint16) Work32; + APUSetZN16 (IAPU.YA.W); + IAPU.PC += 2; +} + +// XXX: BJ: i think the old HalfCarry behavior was wrong... +// XXX: Or is it between bits 7 and 8 for ADDW/SUBW? +void Apu9A () +{ +// SUBW YA,dp + uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); + long Int32 = (long) IAPU.YA.W - (long) Work16; + APUClearHalfCarry (); + IAPU._Carry = Int32 >= 0; + if (((IAPU.YA.W ^ Work16) & 0x8000) && + ((IAPU.YA.W ^ (uint16) Int32) & 0x8000)) + APUSetOverflow (); + else + APUClearOverflow (); +// if (((IAPU.YA.W ^ Work16) & 0x0080) && +// ((IAPU.YA.W ^ (uint16) Int32) & 0x0080)) +// APUSetHalfCarry (); // notaz: strange here + APUSetHalfCarry (); +// if((IAPU.YA.W ^ Work16 ^ (uint16) Work32) & 0x10) // notaz: Work32?! + if((IAPU.YA.W ^ Work16 ^ (uint16) Int32) & 0x10) + APUClearHalfCarry (); + IAPU.YA.W = (uint16) Int32; + APUSetZN16 (IAPU.YA.W); + IAPU.PC += 2; +} + +void ApuBA () +{ +// MOVW YA,dp + IAPU.YA.B.A = S9xAPUGetByteZ (OP1); + IAPU.YA.B.Y = S9xAPUGetByteZ (OP1 + 1); + APUSetZN16 (IAPU.YA.W); + IAPU.PC += 2; +} + +void ApuDA () +{ +// MOVW dp,YA + S9xAPUSetByteZ (IAPU.YA.B.A, OP1); + S9xAPUSetByteZ (IAPU.YA.B.Y, OP1 + 1); + IAPU.PC += 2; +} + +void Apu64 () +{ +// CMP A,dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + CMP (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu65 () +{ +// CMP A,abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu66 () +{ +// CMP A,(X) + uint8 Work8 = S9xAPUGetByteZ (IAPU.X); + CMP (IAPU.YA.B.A, Work8); + IAPU.PC++; +} + +void Apu67 () +{ +// CMP A,(dp+X) + IndexedXIndirect (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + CMP (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu68 () +{ +// CMP A,#00 + uint8 Work8 = OP1; + CMP (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu69 () +{ +// CMP dp(dest), dp(src) + uint8 W1 = S9xAPUGetByteZ (OP1); + uint8 Work8 = S9xAPUGetByteZ (OP2); + CMP (Work8, W1); + IAPU.PC += 3; +} + +void Apu74 () +{ +// CMP A, dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); + CMP (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu75 () +{ +// CMP A,abs+X + AbsoluteX (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu76 () +{ +// CMP A, abs+Y + AbsoluteY (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu77 () +{ +// CMP A,(dp)+Y + IndirectIndexedY (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu78 () +{ +// CMP dp,#00 + uint8 Work8 = OP1; + uint8 W1 = S9xAPUGetByteZ (OP2); + CMP (W1, Work8); + IAPU.PC += 3; +} + +void Apu79 () +{ +// CMP (X),(Y) + uint8 W1 = S9xAPUGetByteZ (IAPU.X); + uint8 Work8 = S9xAPUGetByteZ (IAPU.YA.B.Y); + CMP (W1, Work8); + IAPU.PC++; +} + +void Apu1E () +{ +// CMP X,abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address); + CMP (IAPU.X, Work8); + IAPU.PC += 3; +} + +void Apu3E () +{ +// CMP X,dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + CMP (IAPU.X, Work8); + IAPU.PC += 2; +} + +void ApuC8 () +{ +// CMP X,#00 + CMP (IAPU.X, OP1); + IAPU.PC += 2; +} + +void Apu5E () +{ +// CMP Y,abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + CMP (IAPU.YA.B.Y, Work8); + IAPU.PC += 3; +} + +void Apu7E () +{ +// CMP Y,dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + CMP (IAPU.YA.B.Y, Work8); + IAPU.PC += 2; +} + +void ApuAD () +{ +// CMP Y,#00 + uint8 Work8 = OP1; + CMP (IAPU.YA.B.Y, Work8); + IAPU.PC += 2; +} + +void Apu1F () +{ +// JMP (abs+X) + Absolute (); + IAPU.PC = IAPU.RAM + S9xAPUGetByte (IAPU.Address + IAPU.X) + + (S9xAPUGetByte (IAPU.Address + IAPU.X + 1) << 8); +// XXX: HERE: + // APU.Flags |= TRACE_FLAG; +} + +void Apu5F () +{ +// JMP abs + Absolute (); + IAPU.PC = IAPU.RAM + IAPU.Address; +} + +void Apu20 () +{ +// CLRP + APUClearDirectPage (); + IAPU.DirectPage = IAPU.RAM; + IAPU.PC++; +} + +void Apu60 () +{ +// CLRC + APUClearCarry (); + IAPU.PC++; +} + +void ApuE0 () +{ +// CLRV + APUClearHalfCarry (); + APUClearOverflow (); + IAPU.PC++; +} + +void Apu24 () +{ +// AND A,dp + IAPU.YA.B.A &= S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu25 () +{ +// AND A,abs + Absolute (); + IAPU.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void Apu26 () +{ +// AND A,(X) + IAPU.YA.B.A &= S9xAPUGetByteZ (IAPU.X); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void Apu27 () +{ +// AND A,(dp+X) + IndexedXIndirect (); + IAPU.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu28 () +{ +// AND A,#00 + IAPU.YA.B.A &= OP1; + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu29 () +{ +// AND dp(dest),dp(src) + uint8 Work8 = S9xAPUGetByteZ (OP1); + Work8 &= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu34 () +{ +// AND A,dp+X + IAPU.YA.B.A &= S9xAPUGetByteZ (OP1 + IAPU.X); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu35 () +{ +// AND A,abs+X + AbsoluteX (); + IAPU.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void Apu36 () +{ +// AND A,abs+Y + AbsoluteY (); + IAPU.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void Apu37 () +{ +// AND A,(dp)+Y + IndirectIndexedY (); + IAPU.YA.B.A &= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu38 () +{ +// AND dp,#00 + uint8 Work8 = OP1; + Work8 &= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu39 () +{ +// AND (X),(Y) + uint8 Work8 = S9xAPUGetByteZ (IAPU.X) & S9xAPUGetByteZ (IAPU.YA.B.Y); + APUSetZN8 (Work8); + S9xAPUSetByteZ (Work8, IAPU.X); + IAPU.PC++; +} + +void Apu2B () +{ +// ROL dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + ROL (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu2C () +{ +// ROL abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + ROL (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu3B () +{ +// ROL dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); + ROL (Work8); + S9xAPUSetByteZ (Work8, OP1 + IAPU.X); + IAPU.PC += 2; +} + +void Apu3C () +{ +// ROL A + ROL (IAPU.YA.B.A); + IAPU.PC++; +} + +void Apu2E () +{ +// CBNE dp,rel + uint8 Work8 = OP1; + Relative2 (); + + if (S9xAPUGetByteZ (Work8) != IAPU.YA.B.A) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 3; +} + +void ApuDE () +{ +// CBNE dp+X,rel + uint8 Work8 = OP1 + IAPU.X; + Relative2 (); + + if (S9xAPUGetByteZ (Work8) != IAPU.YA.B.A) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + APUShutdown (); + } + else + IAPU.PC += 3; +} + +void Apu3D () +{ +// INC X + IAPU.X++; + APUSetZN8 (IAPU.X); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void ApuFC () +{ +// INC Y + IAPU.YA.B.Y++; + APUSetZN8 (IAPU.YA.B.Y); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void Apu1D () +{ +// DEC X + IAPU.X--; + APUSetZN8 (IAPU.X); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void ApuDC () +{ +// DEC Y + IAPU.YA.B.Y--; + APUSetZN8 (IAPU.YA.B.Y); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void ApuAB () +{ +// INC dp + uint8 Work8 = S9xAPUGetByteZ (OP1) + 1; + S9xAPUSetByteZ (Work8, OP1); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void ApuAC () +{ +// INC abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (IAPU.Address) + 1; + S9xAPUSetByte (Work8, IAPU.Address); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 3; +} + +void ApuBB () +{ +// INC dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X) + 1; + S9xAPUSetByteZ (Work8, OP1 + IAPU.X); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void ApuBC () +{ +// INC A + IAPU.YA.B.A++; + APUSetZN8 (IAPU.YA.B.A); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void Apu8B () +{ +// DEC dp + uint8 Work8 = S9xAPUGetByteZ (OP1) - 1; + S9xAPUSetByteZ (Work8, OP1); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void Apu8C () +{ +// DEC abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))) - 1; + S9xAPUSetByte (Work8, IAPU.Address); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 3; +} + +void Apu9B () +{ +// DEC dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X) - 1; + S9xAPUSetByteZ (Work8, OP1 + IAPU.X); + APUSetZN8 (Work8); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC += 2; +} + +void Apu9C () +{ +// DEC A + IAPU.YA.B.A--; + APUSetZN8 (IAPU.YA.B.A); + +#ifdef SPC700_SHUTDOWN + IAPU.WaitCounter++; +#endif + + IAPU.PC++; +} + +void Apu44 () +{ +// EOR A,dp + IAPU.YA.B.A ^= S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu45 () +{ +// EOR A,abs + Absolute (); + IAPU.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void Apu46 () +{ +// EOR A,(X) + IAPU.YA.B.A ^= S9xAPUGetByteZ (IAPU.X); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void Apu47 () +{ +// EOR A,(dp+X) + IndexedXIndirect (); + IAPU.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu48 () +{ +// EOR A,#00 + IAPU.YA.B.A ^= OP1; + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu49 () +{ +// EOR dp(dest),dp(src) + uint8 Work8 = S9xAPUGetByteZ (OP1); + Work8 ^= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu54 () +{ +// EOR A,dp+X + IAPU.YA.B.A ^= S9xAPUGetByteZ (OP1 + IAPU.X); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu55 () +{ +// EOR A,abs+X + AbsoluteX (); + IAPU.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void Apu56 () +{ +// EOR A,abs+Y + AbsoluteY (); + IAPU.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void Apu57 () +{ +// EOR A,(dp)+Y + IndirectIndexedY (); + IAPU.YA.B.A ^= S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void Apu58 () +{ +// EOR dp,#00 + uint8 Work8 = OP1; + Work8 ^= S9xAPUGetByteZ (OP2); + S9xAPUSetByteZ (Work8, OP2); + APUSetZN8 (Work8); + IAPU.PC += 3; +} + +void Apu59 () +{ +// EOR (X),(Y) + uint8 Work8 = S9xAPUGetByteZ (IAPU.X) ^ S9xAPUGetByteZ (IAPU.YA.B.Y); + APUSetZN8 (Work8); + S9xAPUSetByteZ (Work8, IAPU.X); + IAPU.PC++; +} + +void Apu4B () +{ +// LSR dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + LSR (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu4C () +{ +// LSR abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + LSR (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu5B () +{ +// LSR dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); + LSR (Work8); + S9xAPUSetByteZ (Work8, OP1 + IAPU.X); + IAPU.PC += 2; +} + +void Apu5C () +{ +// LSR A + LSR (IAPU.YA.B.A); + IAPU.PC++; +} + +void Apu7D () +{ +// MOV A,X + IAPU.YA.B.A = IAPU.X; + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void ApuDD () +{ +// MOV A,Y + IAPU.YA.B.A = IAPU.YA.B.Y; + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void Apu5D () +{ +// MOV X,A + IAPU.X = IAPU.YA.B.A; + APUSetZN8 (IAPU.X); + IAPU.PC++; +} + +void ApuFD () +{ +// MOV Y,A + IAPU.YA.B.Y = IAPU.YA.B.A; + APUSetZN8 (IAPU.YA.B.Y); + IAPU.PC++; +} + +void Apu9D () +{ +//MOV X,SP + IAPU.X = IAPU.S; + APUSetZN8 (IAPU.X); + IAPU.PC++; +} + +void ApuBD () +{ +// MOV SP,X + IAPU.S = IAPU.X; + IAPU.PC++; +} + +void Apu6B () +{ +// ROR dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + ROR (Work8); + S9xAPUSetByteZ (Work8, OP1); + IAPU.PC += 2; +} + +void Apu6C () +{ +// ROR abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + ROR (Work8); + S9xAPUSetByte (Work8, IAPU.Address); + IAPU.PC += 3; +} + +void Apu7B () +{ +// ROR dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); + ROR (Work8); + S9xAPUSetByteZ (Work8, OP1 + IAPU.X); + IAPU.PC += 2; +} + +void Apu7C () +{ +// ROR A + ROR (IAPU.YA.B.A); + IAPU.PC++; +} + +void Apu6E () +{ +// DBNZ dp,rel + uint8 Work8 = OP1; + Relative2 (); + uint8 W1 = S9xAPUGetByteZ (Work8) - 1; + S9xAPUSetByteZ (W1, Work8); + if (W1 != 0) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + } + else + IAPU.PC += 3; +} + +void ApuFE () +{ +// DBNZ Y,rel + Relative (); + IAPU.YA.B.Y--; + if (IAPU.YA.B.Y != 0) + { + IAPU.PC = IAPU.RAM + (uint16) Int16; + CPU.APU_Cycles += IAPU.TwoCycles; + } + else + IAPU.PC += 2; +} + +void Apu6F () +{ +// RET + uint16 Work16; + PopW (Work16); + IAPU.PC = IAPU.RAM + Work16; +} + +void Apu7F () +{ +// RETI + // STOP ("RETI"); + uint16 Work16; + Pop (IAPU.P); + S9xAPUUnpackStatus (); + PopW (Work16); + IAPU.PC = IAPU.RAM + Work16; +} + +void Apu84 () +{ +// ADC A,dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + ADC (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu85 () +{ +// ADC A, abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + ADC (IAPU.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu86 () +{ +// ADC A,(X) + uint8 Work8 = S9xAPUGetByteZ (IAPU.X); + ADC (IAPU.YA.B.A, Work8); + IAPU.PC++; +} + +void Apu87 () +{ +// ADC A,(dp+X) + IndexedXIndirect (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + ADC (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu88 () +{ +// ADC A,#00 + uint8 Work8 = OP1; + ADC (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu89 () +{ +// ADC dp(dest),dp(src) + uint8 Work8 = S9xAPUGetByteZ (OP1); + uint8 W1 = S9xAPUGetByteZ (OP2); + ADC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void Apu94 () +{ +// ADC A,dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); + ADC (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu95 () +{ +// ADC A, abs+X + AbsoluteX (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + ADC (IAPU.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu96 () +{ +// ADC A, abs+Y + AbsoluteY (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + ADC (IAPU.YA.B.A, Work8); + IAPU.PC += 3; +} + +void Apu97 () +{ +// ADC A, (dp)+Y + IndirectIndexedY (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + ADC (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void Apu98 () +{ +// ADC dp,#00 + uint8 Work8 = OP1; + uint8 W1 = S9xAPUGetByteZ (OP2); + ADC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void Apu99 () +{ +// ADC (X),(Y) + uint8 W1 = S9xAPUGetByteZ (IAPU.X); + uint8 Work8 = S9xAPUGetByteZ (IAPU.YA.B.Y); + ADC (W1, Work8); + S9xAPUSetByteZ (W1, IAPU.X); + IAPU.PC++; +} + +void Apu8D () +{ +// MOV Y,#00 + IAPU.YA.B.Y = OP1; + APUSetZN8 (IAPU.YA.B.Y); + IAPU.PC += 2; +} + +void Apu8F () +{ +// MOV dp,#00 + uint8 Work8 = OP1; + S9xAPUSetByteZ (Work8, OP2); + IAPU.PC += 3; +} + +void Apu9E () +{ +// DIV YA,X + if (IAPU.X == 0) + { + APUSetOverflow (); + IAPU.YA.B.Y = 0xff; + IAPU.YA.B.A = 0xff; + } + else + { + APUClearOverflow (); + uint8 Work8 = IAPU.YA.W / IAPU.X; + IAPU.YA.B.Y = IAPU.YA.W % IAPU.X; + IAPU.YA.B.A = Work8; + } +// XXX How should Overflow, Half Carry, Zero and Negative flags be set?? + // APUSetZN16 (IAPU.YA.W); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void Apu9F () +{ +// XCN A + IAPU.YA.B.A = (IAPU.YA.B.A >> 4) | (IAPU.YA.B.A << 4); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void ApuA4 () +{ +// SBC A, dp + uint8 Work8 = S9xAPUGetByteZ (OP1); + SBC (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuA5 () +{ +// SBC A, abs + Absolute (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + SBC (IAPU.YA.B.A, Work8); + IAPU.PC += 3; +} + +void ApuA6 () +{ +// SBC A, (X) + uint8 Work8 = S9xAPUGetByteZ (IAPU.X); + SBC (IAPU.YA.B.A, Work8); + IAPU.PC++; +} + +void ApuA7 () +{ +// SBC A,(dp+X) + IndexedXIndirect (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + SBC (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuA8 () +{ +// SBC A,#00 + uint8 Work8 = OP1; + SBC (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuA9 () +{ +// SBC dp(dest), dp(src) + uint8 Work8 = S9xAPUGetByteZ (OP1); + uint8 W1 = S9xAPUGetByteZ (OP2); + SBC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void ApuB4 () +{ +// SBC A, dp+X + uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); + SBC (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuB5 () +{ +// SBC A,abs+X + AbsoluteX (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + SBC (IAPU.YA.B.A, Work8); + IAPU.PC += 3; +} + +void ApuB6 () +{ +// SBC A,abs+Y + AbsoluteY (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + SBC (IAPU.YA.B.A, Work8); + IAPU.PC += 3; +} + +void ApuB7 () +{ +// SBC A,(dp)+Y + IndirectIndexedY (); + uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); + SBC (IAPU.YA.B.A, Work8); + IAPU.PC += 2; +} + +void ApuB8 () +{ +// SBC dp,#00 + uint8 Work8 = OP1; + uint8 W1 = S9xAPUGetByteZ (OP2); + SBC (W1, Work8); + S9xAPUSetByteZ (W1, OP2); + IAPU.PC += 3; +} + +void ApuB9 () +{ +// SBC (X),(Y) + uint8 W1 = S9xAPUGetByteZ (IAPU.X); + uint8 Work8 = S9xAPUGetByteZ (IAPU.YA.B.Y); + SBC (W1, Work8); + S9xAPUSetByteZ (W1, IAPU.X); + IAPU.PC++; +} + +void ApuAF () +{ +// MOV (X)+, A + S9xAPUSetByteZ (IAPU.YA.B.A, IAPU.X++); + IAPU.PC++; +} + +void ApuBE () +{ +// DAS + if ((IAPU.YA.B.A & 0x0f) > 9 || !APUCheckHalfCarry()) + { + IAPU.YA.B.A -= 6; + } + if (IAPU.YA.B.A > 0x9f || !IAPU._Carry) + { + IAPU.YA.B.A -= 0x60; + APUClearCarry (); + } + else { APUSetCarry (); } + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void ApuBF () +{ +// MOV A,(X)+ + IAPU.YA.B.A = S9xAPUGetByteZ (IAPU.X++); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void ApuC0 () +{ +// DI + APUClearInterrupt (); + IAPU.PC++; +} + +void ApuA0 () +{ +// EI + APUSetInterrupt (); + IAPU.PC++; +} + +void ApuC4 () +{ +// MOV dp,A + S9xAPUSetByteZ (IAPU.YA.B.A, OP1); + IAPU.PC += 2; +} + +void ApuC5 () +{ +// MOV abs,A + Absolute (); + S9xAPUSetByte (IAPU.YA.B.A, IAPU.Address); + IAPU.PC += 3; +} + +void ApuC6 () +{ +// MOV (X), A + S9xAPUSetByteZ (IAPU.YA.B.A, IAPU.X); + IAPU.PC++; +} + +void ApuC7 () +{ +// MOV (dp+X),A + IndexedXIndirect (); + S9xAPUSetByte (IAPU.YA.B.A, IAPU.Address); + IAPU.PC += 2; +} + +void ApuC9 () +{ +// MOV abs,X + Absolute (); + S9xAPUSetByte (IAPU.X, IAPU.Address); + IAPU.PC += 3; +} + +void ApuCB () +{ +// MOV dp,Y + S9xAPUSetByteZ (IAPU.YA.B.Y, OP1); + IAPU.PC += 2; +} + +void ApuCC () +{ +// MOV abs,Y + Absolute (); + S9xAPUSetByte (IAPU.YA.B.Y, IAPU.Address); + IAPU.PC += 3; +} + +void ApuCD () +{ +// MOV X,#00 + IAPU.X = OP1; + APUSetZN8 (IAPU.X); + IAPU.PC += 2; +} + +void ApuCF () +{ +// MUL YA + IAPU.YA.W = (uint16) IAPU.YA.B.A * IAPU.YA.B.Y; + APUSetZN16 (IAPU.YA.W); + IAPU.PC++; +} + +void ApuD4 () +{ +// MOV dp+X, A + S9xAPUSetByteZ (IAPU.YA.B.A, OP1 + IAPU.X); + IAPU.PC += 2; +} + +void ApuD5 () +{ +// MOV abs+X,A + AbsoluteX (); + S9xAPUSetByte (IAPU.YA.B.A, IAPU.Address); + IAPU.PC += 3; +} + +void ApuD6 () +{ +// MOV abs+Y,A + AbsoluteY (); + S9xAPUSetByte (IAPU.YA.B.A, IAPU.Address); + IAPU.PC += 3; +} + +void ApuD7 () +{ +// MOV (dp)+Y,A + IndirectIndexedY (); + S9xAPUSetByte (IAPU.YA.B.A, IAPU.Address); + IAPU.PC += 2; +} + +void ApuD8 () +{ +// MOV dp,X + S9xAPUSetByteZ (IAPU.X, OP1); + IAPU.PC += 2; +} + +void ApuD9 () +{ +// MOV dp+Y,X + S9xAPUSetByteZ (IAPU.X, OP1 + IAPU.YA.B.Y); + IAPU.PC += 2; +} + +void ApuDB () +{ +// MOV dp+X,Y + S9xAPUSetByteZ (IAPU.YA.B.Y, OP1 + IAPU.X); + IAPU.PC += 2; +} + +void ApuDF () +{ +// DAA + if ((IAPU.YA.B.A & 0x0f) > 9 || APUCheckHalfCarry()) + { + if(IAPU.YA.B.A > 0xf0) APUSetCarry (); + IAPU.YA.B.A += 6; + //APUSetHalfCarry (); Intel procs do this, but this is a Sony proc... + } + //else { APUClearHalfCarry (); } ditto as above + if (IAPU.YA.B.A > 0x9f || IAPU._Carry) + { + IAPU.YA.B.A += 0x60; + APUSetCarry (); + } + else { APUClearCarry (); } + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void ApuE4 () +{ +// MOV A, dp + IAPU.YA.B.A = S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void ApuE5 () +{ +// MOV A,abs + Absolute (); + IAPU.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void ApuE6 () +{ +// MOV A,(X) + IAPU.YA.B.A = S9xAPUGetByteZ (IAPU.X); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC++; +} + +void ApuE7 () +{ +// MOV A,(dp+X) + IndexedXIndirect (); + IAPU.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void ApuE8 () +{ +// MOV A,#00 + IAPU.YA.B.A = OP1; + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void ApuE9 () +{ +// MOV X, abs + Absolute (); + IAPU.X = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.X); + IAPU.PC += 3; +} + +void ApuEB () +{ +// MOV Y,dp + IAPU.YA.B.Y = S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.YA.B.Y); + IAPU.PC += 2; +} + +void ApuEC () +{ +// MOV Y,abs + Absolute (); + IAPU.YA.B.Y = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.Y); + IAPU.PC += 3; +} + +void ApuF4 () +{ +// MOV A, dp+X + IAPU.YA.B.A = S9xAPUGetByteZ (OP1 + IAPU.X); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void ApuF5 () +{ +// MOV A, abs+X + AbsoluteX (); + IAPU.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void ApuF6 () +{ +// MOV A, abs+Y + AbsoluteY (); + IAPU.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 3; +} + +void ApuF7 () +{ +// MOV A, (dp)+Y + IndirectIndexedY (); + IAPU.YA.B.A = S9xAPUGetByte (IAPU.Address); + APUSetZN8 (IAPU.YA.B.A); + IAPU.PC += 2; +} + +void ApuF8 () +{ +// MOV X,dp + IAPU.X = S9xAPUGetByteZ (OP1); + APUSetZN8 (IAPU.X); + IAPU.PC += 2; +} + +void ApuF9 () +{ +// MOV X,dp+Y + IAPU.X = S9xAPUGetByteZ (OP1 + IAPU.YA.B.Y); + APUSetZN8 (IAPU.X); + IAPU.PC += 2; +} + +void ApuFA () +{ +// MOV dp(dest),dp(src) + S9xAPUSetByteZ (S9xAPUGetByteZ (OP1), OP2); + IAPU.PC += 3; +} + +void ApuFB () +{ +// MOV Y,dp+X + IAPU.YA.B.Y = S9xAPUGetByteZ (OP1 + IAPU.X); + APUSetZN8 (IAPU.YA.B.Y); + IAPU.PC += 2; +} + +#if defined(NO_INLINE_SET_GET) +#undef INLINE +#define INLINE +#include "apumem.h" +#endif + + +void (*S9xApuOpcodes[256]) (void) = +{ + Apu00, Apu01, Apu02, Apu03, Apu04, Apu05, Apu06, Apu07, + Apu08, Apu09, Apu0A, Apu0B, Apu0C, Apu0D, Apu0E, Apu0F, + Apu10, Apu11, Apu12, Apu13, Apu14, Apu15, Apu16, Apu17, + Apu18, Apu19, Apu1A, Apu1B, Apu1C, Apu1D, Apu1E, Apu1F, + Apu20, Apu21, Apu22, Apu23, Apu24, Apu25, Apu26, Apu27, + Apu28, Apu29, Apu2A, Apu2B, Apu2C, Apu2D, Apu2E, Apu2F, + Apu30, Apu31, Apu32, Apu33, Apu34, Apu35, Apu36, Apu37, + Apu38, Apu39, Apu3A, Apu3B, Apu3C, Apu3D, Apu3E, Apu3F, + Apu40, Apu41, Apu42, Apu43, Apu44, Apu45, Apu46, Apu47, + Apu48, Apu49, Apu4A, Apu4B, Apu4C, Apu4D, Apu4E, Apu4F, + Apu50, Apu51, Apu52, Apu53, Apu54, Apu55, Apu56, Apu57, + Apu58, Apu59, Apu5A, Apu5B, Apu5C, Apu5D, Apu5E, Apu5F, + Apu60, Apu61, Apu62, Apu63, Apu64, Apu65, Apu66, Apu67, + Apu68, Apu69, Apu6A, Apu6B, Apu6C, Apu6D, Apu6E, Apu6F, + Apu70, Apu71, Apu72, Apu73, Apu74, Apu75, Apu76, Apu77, + Apu78, Apu79, Apu7A, Apu7B, Apu7C, Apu7D, Apu7E, Apu7F, + Apu80, Apu81, Apu82, Apu83, Apu84, Apu85, Apu86, Apu87, + Apu88, Apu89, Apu8A, Apu8B, Apu8C, Apu8D, Apu8E, Apu8F, + Apu90, Apu91, Apu92, Apu93, Apu94, Apu95, Apu96, Apu97, + Apu98, Apu99, Apu9A, Apu9B, Apu9C, Apu9D, Apu9E, Apu9F, + ApuA0, ApuA1, ApuA2, ApuA3, ApuA4, ApuA5, ApuA6, ApuA7, + ApuA8, ApuA9, ApuAA, ApuAB, ApuAC, ApuAD, ApuAE, ApuAF, + ApuB0, ApuB1, ApuB2, ApuB3, ApuB4, ApuB5, ApuB6, ApuB7, + ApuB8, ApuB9, ApuBA, ApuBB, ApuBC, ApuBD, ApuBE, ApuBF, + ApuC0, ApuC1, ApuC2, ApuC3, ApuC4, ApuC5, ApuC6, ApuC7, + ApuC8, ApuC9, ApuCA, ApuCB, ApuCC, ApuCD, ApuCE, ApuCF, + ApuD0, ApuD1, ApuD2, ApuD3, ApuD4, ApuD5, ApuD6, ApuD7, + ApuD8, ApuD9, ApuDA, ApuDB, ApuDC, ApuDD, ApuDE, ApuDF, + ApuE0, ApuE1, ApuE2, ApuE3, ApuE4, ApuE5, ApuE6, ApuE7, + ApuE8, ApuE9, ApuEA, ApuEB, ApuEC, ApuED, ApuEE, ApuEF, + ApuF0, ApuF1, ApuF2, ApuF3, ApuF4, ApuF5, ApuF6, ApuF7, + ApuF8, ApuF9, ApuFA, ApuFB, ApuFC, ApuFD, ApuFE, ApuFF +}; + + diff --git a/src/spc700.cpp b/src/spc700.cpp deleted file mode 100644 index 637d2db..0000000 --- a/src/spc700.cpp +++ /dev/null @@ -1,2509 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -#include "snes9x.h" -#include "memmap.h" -#include "display.h" -#include "cpuexec.h" -#include "apu.h" -#include "spc700.h" - -// SPC700/Sound DSP chips have a 24.57MHz crystal on their PCB. - -// we only need the memhandlers -#undef INLINE -#define INLINE extern "C" -#include "apumem.h" - -#define OP1 (*(IAPU.PC + 1)) -#define OP2 (*(IAPU.PC + 2)) - -#ifdef SPC700_SHUTDOWN -#define APUShutdown() \ - if (Settings.Shutdown && (IAPU.PC == IAPU.WaitAddress1 || IAPU.PC == IAPU.WaitAddress2)) \ - { \ - if (IAPU.WaitCounter == 0) \ - { \ - if (!ICPU.CPUExecuting) \ - CPU.APU_Cycles = CPU.Cycles = CPU.NextEvent; \ - else \ - CPU.APU_APUExecuting = FALSE; \ - } \ - else \ - if (IAPU.WaitCounter >= 2) \ - IAPU.WaitCounter = 1; \ - else \ - IAPU.WaitCounter--; \ - } -#else -#define APUShutdown() -#endif - -#define APUSetZN8(b)\ - IAPU._Zero = (b); - -#define APUSetZN16(w)\ - IAPU._Zero = ((w) != 0) | ((w) >> 8); - -void STOP (char *s) -{ - char buffer[100]; - -#ifdef DEBUGGER - S9xAPUOPrint (buffer, IAPU.PC - IAPU.RAM); -#endif - - sprintf (String, "Sound CPU in unknown state executing %s at %04lX\n%s\n", s, IAPU.PC - IAPU.RAM, buffer); - S9xMessage (S9X_ERROR, S9X_APU_STOPPED, String); - APU.TimerEnabled[0] = APU.TimerEnabled[1] = APU.TimerEnabled[2] = FALSE; - CPU.APU_APUExecuting = FALSE; - -#ifdef DEBUGGER - CPU.Flags |= DEBUG_MODE_FLAG; -#else - S9xExit (); -#endif -} - -#define TCALL(n)\ -{\ - PushW ((IAPU.PC - IAPU.RAM + 1)); \ - IAPU.PC = IAPU.RAM + (APU.ExtraRAM [((15 - n) << 1)] + \ - (APU.ExtraRAM [((15 - n) << 1) + 1] << 8)); \ -} - -// XXX: HalfCarry - BJ fixed? -#define SBC(a,b)\ -short Int16 = (short) (a) - (short) (b) + (short) (APUCheckCarry ()) - 1;\ -IAPU._Carry = Int16 >= 0;\ -if ((((a) ^ (b)) & 0x80) && (((a) ^ (uint8) Int16) & 0x80))\ - APUSetOverflow ();\ -else \ - APUClearOverflow (); \ -APUSetHalfCarry ();\ -if(((a) ^ (b) ^ (uint8) Int16) & 0x10)\ - APUClearHalfCarry ();\ -(a) = (uint8) Int16;\ -APUSetZN8 ((uint8) Int16); - -// XXX: HalfCarry - BJ fixed? -#define ADC(a,b)\ -uint16 Work16 = (a) + (b) + APUCheckCarry();\ -IAPU._Carry = Work16 >= 0x100; \ -if (~((a) ^ (b)) & ((b) ^ (uint8) Work16) & 0x80)\ - APUSetOverflow ();\ -else \ - APUClearOverflow (); \ -APUClearHalfCarry ();\ -/*if(((a) ^ (b) ^ (uint8) Int16) & 0x10) notaz: Int16!? */\ -if(((a) ^ (b) ^ (uint8) Work16) & 0x10)\ - APUSetHalfCarry ();\ -(a) = (uint8) Work16;\ -APUSetZN8 ((uint8) Work16); - -#define CMP(a,b)\ -short Int16 = (short) (a) - (short) (b);\ -IAPU._Carry = Int16 >= 0;\ -APUSetZN8 ((uint8) Int16); - -#define ASL(b)\ - IAPU._Carry = ((b) & 0x80) != 0; \ - (b) <<= 1;\ - APUSetZN8 (b); -#define LSR(b)\ - IAPU._Carry = (b) & 1;\ - (b) >>= 1;\ - APUSetZN8 (b); -#define ROL(b)\ - uint16 Work16 = ((b) << 1) | APUCheckCarry (); \ - IAPU._Carry = Work16 >= 0x100; \ - (b) = (uint8) Work16; \ - APUSetZN8 (b); -#define ROR(b)\ - uint16 Work16 = (b) | ((uint16) APUCheckCarry () << 8); \ - IAPU._Carry = (uint8) Work16 & 1; \ - Work16 >>= 1; \ - (b) = (uint8) Work16; \ - APUSetZN8 (b); - -#define Push(b)\ - *(IAPU.RAM + 0x100 + IAPU.S) = b;\ - IAPU.S--; - -#define Pop(b)\ - IAPU.S++;\ - (b) = *(IAPU.RAM + 0x100 + IAPU.S); - -#ifdef FAST_LSB_WORD_ACCESS -#define PushW(w)\ - *(uint16 *) (IAPU.RAM + 0xff + IAPU.S) = w;\ - IAPU.S -= 2; -#define PopW(w)\ - IAPU.S += 2;\ - w = *(uint16 *) (IAPU.RAM + 0xff + IAPU.S); -#else -#define PushW(w)\ - *(IAPU.RAM + 0xff + IAPU.S) = w;\ - *(IAPU.RAM + 0x100 + IAPU.S) = (w >> 8);\ - IAPU.S -= 2; -#define PopW(w)\ - IAPU.S += 2; \ - (w) = *(IAPU.RAM + 0xff + IAPU.S) + (*(IAPU.RAM + 0x100 + IAPU.S) << 8); -#endif - -#define Relative()\ - signed char Int8 = OP1;\ - short Int16 = (int) (IAPU.PC + 2 - IAPU.RAM) + Int8; - -#define Relative2()\ - signed char Int8 = OP2;\ - short Int16 = (int) (IAPU.PC + 3 - IAPU.RAM) + Int8; - -#ifdef FAST_LSB_WORD_ACCESS -#define IndexedXIndirect()\ - IAPU.Address = *(uint16 *) (IAPU.DirectPage + ((OP1 + IAPU.X) & 0xff)); - -#define Absolute()\ - IAPU.Address = *(uint16 *) (IAPU.PC + 1); - -#define AbsoluteX()\ - IAPU.Address = *(uint16 *) (IAPU.PC + 1) + IAPU.X; - -#define AbsoluteY()\ - IAPU.Address = *(uint16 *) (IAPU.PC + 1) + IAPU.YA.B.Y; - -#define MemBit()\ - IAPU.Address = *(uint16 *) (IAPU.PC + 1);\ - IAPU.Bit = (uint8)(IAPU.Address >> 13);\ - IAPU.Address &= 0x1fff; - -#define IndirectIndexedY()\ - IAPU.Address = *(uint16 *) (IAPU.DirectPage + OP1) + IAPU.YA.B.Y; -#else -#define IndexedXIndirect()\ - IAPU.Address = *(IAPU.DirectPage + ((OP1 + IAPU.X) & 0xff)) + \ - (*(IAPU.DirectPage + ((OP1 + IAPU.X + 1) & 0xff)) << 8); -#define Absolute()\ - IAPU.Address = OP1 + (OP2 << 8); - -#define AbsoluteX()\ - IAPU.Address = OP1 + (OP2 << 8) + IAPU.X; - -#define AbsoluteY()\ - IAPU.Address = OP1 + (OP2 << 8) + IAPU.YA.B.Y; - -#define MemBit()\ - IAPU.Address = OP1 + (OP2 << 8);\ - IAPU.Bit = (int8) (IAPU.Address >> 13);\ - IAPU.Address &= 0x1fff; - -#define IndirectIndexedY()\ - IAPU.Address = *(IAPU.DirectPage + OP1) + \ - (*(IAPU.DirectPage + OP1 + 1) << 8) + \ - IAPU.YA.B.Y; -#endif - -void Apu00 () -{ -// NOP - IAPU.PC++; -} - -void Apu01 () { TCALL (0) } - -void Apu11 () { TCALL (1) } - -void Apu21 () { TCALL (2) } - -void Apu31 () { TCALL (3) } - -void Apu41 () { TCALL (4) } - -void Apu51 () { TCALL (5) } - -void Apu61 () { TCALL (6) } - -void Apu71 () { TCALL (7) } - -void Apu81 () { TCALL (8) } - -void Apu91 () { TCALL (9) } - -void ApuA1 () { TCALL (10) } - -void ApuB1 () { TCALL (11) } - -void ApuC1 () { TCALL (12) } - -void ApuD1 () { TCALL (13) } - -void ApuE1 () { TCALL (14) } - -void ApuF1 () { TCALL (15) } - -void Apu3F () // CALL absolute -{ - Absolute (); - // 0xB6f for Star Fox 2 - PushW ((IAPU.PC + 3 - IAPU.RAM)); - IAPU.PC = IAPU.RAM + IAPU.Address; -} - -void Apu4F () // PCALL $XX -{ - uint8 Work8 = OP1; - PushW ((IAPU.PC + 2 - IAPU.RAM)); - IAPU.PC = IAPU.RAM + 0xff00 + Work8; -} - -#define SET(b) \ -S9xAPUSetByteZ ((uint8) (S9xAPUGetByteZ (OP1 ) | (1 << (b))), OP1); \ -IAPU.PC += 2 - -void Apu02 () -{ - SET (0); -} - -void Apu22 () -{ - SET (1); -} - -void Apu42 () -{ - SET (2); -} - -void Apu62 () -{ - SET (3); -} - - - -void Apu82 () -{ - - - SET (4); -} - -void ApuA2 () -{ - SET (5); -} - -void ApuC2 () -{ - SET (6); -} - -void ApuE2 () -{ - SET (7); -} - -#define CLR(b) \ -S9xAPUSetByteZ ((uint8) (S9xAPUGetByteZ (OP1) & ~(1 << (b))), OP1); \ -IAPU.PC += 2; - -void Apu12 () -{ - CLR (0); -} - -void Apu32 () -{ - CLR (1); -} - -void Apu52 () -{ - CLR (2); -} - -void Apu72 () -{ - CLR (3); -} - -void Apu92 () -{ - CLR (4); -} - -void ApuB2 () -{ - CLR (5); -} - -void ApuD2 () -{ - CLR (6); -} - -void ApuF2 () -{ - CLR (7); -} - -#define BBS(b) \ -uint8 Work8 = OP1; \ -Relative2 (); \ -if (S9xAPUGetByteZ (Work8) & (1 << (b))) \ -{ \ - IAPU.PC = IAPU.RAM + (uint16) Int16; \ - CPU.APU_Cycles += IAPU.TwoCycles; \ -} \ -else \ - IAPU.PC += 3 - -void Apu03 () -{ - BBS (0); -} - -void Apu23 () -{ - BBS (1); -} - -void Apu43 () -{ - BBS (2); -} - -void Apu63 () -{ - BBS (3); -} - -void Apu83 () -{ - BBS (4); -} - -void ApuA3 () -{ - BBS (5); -} - -void ApuC3 () -{ - BBS (6); -} - -void ApuE3 () -{ - BBS (7); -} - -#define BBC(b) \ -uint8 Work8 = OP1; \ -Relative2 (); \ -if (!(S9xAPUGetByteZ (Work8) & (1 << (b)))) \ -{ \ - IAPU.PC = IAPU.RAM + (uint16) Int16; \ - CPU.APU_Cycles += IAPU.TwoCycles; \ -} \ -else \ - IAPU.PC += 3 - -void Apu13 () -{ - BBC (0); -} - -void Apu33 () -{ - BBC (1); -} - -void Apu53 () -{ - BBC (2); -} - -void Apu73 () -{ - BBC (3); -} - -void Apu93 () -{ - BBC (4); -} - -void ApuB3 () -{ - BBC (5); -} - -void ApuD3 () -{ - BBC (6); -} - -void ApuF3 () -{ - BBC (7); -} - -void Apu04 () -{ -// OR A,dp - IAPU.YA.B.A |= S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu05 () -{ -// OR A,abs - Absolute (); - IAPU.YA.B.A |= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void Apu06 () -{ -// OR A,(X) - IAPU.YA.B.A |= S9xAPUGetByteZ (IAPU.X); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void Apu07 () -{ -// OR A,(dp+X) - IndexedXIndirect (); - IAPU.YA.B.A |= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu08 () -{ -// OR A,#00 - IAPU.YA.B.A |= OP1; - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu09 () -{ -// OR dp(dest),dp(src) - uint8 Work8 = S9xAPUGetByteZ (OP1); - Work8 |= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu14 () -{ -// OR A,dp+X - IAPU.YA.B.A |= S9xAPUGetByteZ (OP1 + IAPU.X); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu15 () -{ -// OR A,abs+X - AbsoluteX (); - IAPU.YA.B.A |= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void Apu16 () -{ -// OR A,abs+Y - AbsoluteY (); - IAPU.YA.B.A |= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void Apu17 () -{ -// OR A,(dp)+Y - IndirectIndexedY (); - IAPU.YA.B.A |= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu18 () -{ -// OR dp,#00 - uint8 Work8 = OP1; - Work8 |= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu19 () -{ -// OR (X),(Y) - uint8 Work8 = S9xAPUGetByteZ (IAPU.X) | S9xAPUGetByteZ (IAPU.YA.B.Y); - APUSetZN8 (Work8); - S9xAPUSetByteZ (Work8, IAPU.X); - IAPU.PC++; -} - -void Apu0A () -{ -// OR1 C,membit - MemBit (); - if (!APUCheckCarry ()) - { - if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) - APUSetCarry (); - } - IAPU.PC += 3; -} - -void Apu2A () -{ -// OR1 C,not membit - MemBit (); - if (!APUCheckCarry ()) - { - if (!(S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) - APUSetCarry (); - } - IAPU.PC += 3; -} - -void Apu4A () -{ -// AND1 C,membit - MemBit (); - if (APUCheckCarry ()) - { - if (!(S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) - APUClearCarry (); - } - IAPU.PC += 3; -} - -void Apu6A () -{ -// AND1 C, not membit - MemBit (); - if (APUCheckCarry ()) - { - if ((S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit))) - APUClearCarry (); - } - IAPU.PC += 3; -} - -void Apu8A () -{ -// EOR1 C, membit - MemBit (); - if (APUCheckCarry ()) - { - if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) - APUClearCarry (); - } - else - { - if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) - APUSetCarry (); - } - IAPU.PC += 3; -} - -void ApuAA () -{ -// MOV1 C,membit - MemBit (); - if (S9xAPUGetByte (IAPU.Address) & (1 << IAPU.Bit)) - APUSetCarry (); - else - APUClearCarry (); - IAPU.PC += 3; -} - -void ApuCA () -{ -// MOV1 membit,C - MemBit (); - if (APUCheckCarry ()) - { - S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) | (1 << IAPU.Bit), IAPU.Address); - } - else - { - S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) & ~(1 << IAPU.Bit), IAPU.Address); - } - IAPU.PC += 3; -} - -void ApuEA () -{ -// NOT1 membit - MemBit (); - S9xAPUSetByte (S9xAPUGetByte (IAPU.Address) ^ (1 << IAPU.Bit), IAPU.Address); - IAPU.PC += 3; -} - -void Apu0B () -{ -// ASL dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - ASL (Work8); - S9xAPUSetByteZ (Work8, OP1); - IAPU.PC += 2; -} - -void Apu0C () -{ -// ASL abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - ASL (Work8); - S9xAPUSetByte (Work8, IAPU.Address); - IAPU.PC += 3; -} - -void Apu1B () -{ -// ASL dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); - ASL (Work8); - S9xAPUSetByteZ (Work8, OP1 + IAPU.X); - IAPU.PC += 2; -} - -void Apu1C () -{ -// ASL A - ASL (IAPU.YA.B.A); - IAPU.PC++; -} - -void Apu0D () -{ -// PUSH PSW - S9xAPUPackStatus (); - Push (IAPU.P); - IAPU.PC++; -} - -void Apu2D () -{ -// PUSH A - Push (IAPU.YA.B.A); - IAPU.PC++; -} - -void Apu4D () -{ -// PUSH X - Push (IAPU.X); - IAPU.PC++; -} - -void Apu6D () -{ -// PUSH Y - Push (IAPU.YA.B.Y); - IAPU.PC++; -} - -void Apu8E () -{ -// POP PSW - Pop (IAPU.P); - S9xAPUUnpackStatus (); - if (APUCheckDirectPage ()) - IAPU.DirectPage = IAPU.RAM + 0x100; - else - IAPU.DirectPage = IAPU.RAM; - IAPU.PC++; -} - -void ApuAE () -{ -// POP A - Pop (IAPU.YA.B.A); - IAPU.PC++; -} - -void ApuCE () -{ -// POP X - Pop (IAPU.X); - IAPU.PC++; -} - -void ApuEE () -{ -// POP Y - Pop (IAPU.YA.B.Y); - IAPU.PC++; -} - -void Apu0E () -{ -// TSET1 abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - S9xAPUSetByte (Work8 | IAPU.YA.B.A, IAPU.Address); - Work8 &= IAPU.YA.B.A; - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu4E () -{ -// TCLR1 abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - S9xAPUSetByte (Work8 & ~IAPU.YA.B.A, IAPU.Address); - Work8 &= IAPU.YA.B.A; - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu0F () -{ -// BRK - -#if 0 - STOP ("BRK"); -#else - PushW ((IAPU.PC + 1 - IAPU.RAM)); - S9xAPUPackStatus (); - Push (IAPU.P); - APUSetBreak (); - APUClearInterrupt (); -// XXX:Where is the BRK vector ??? - IAPU.PC = IAPU.RAM + APU.ExtraRAM[0x20] + (APU.ExtraRAM[0x21] << 8); -#endif -} - -void ApuEF () -{ -// SLEEP - // XXX: sleep - // STOP ("SLEEP"); - CPU.APU_APUExecuting = FALSE; - IAPU.PC++; -} - -void ApuFF () -{ -// STOP - // STOP ("STOP"); - CPU.APU_APUExecuting = FALSE; - IAPU.PC++; -} - -void Apu10 () -{ -// BPL - Relative (); - if (!APUCheckNegative ()) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - APUShutdown (); - } - else - IAPU.PC += 2; -} - -void Apu30 () -{ -// BMI - Relative (); - if (APUCheckNegative ()) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - APUShutdown (); - } - else - IAPU.PC += 2; -} - -void Apu90 () -{ -// BCC - Relative (); - if (!APUCheckCarry ()) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - APUShutdown (); - } - else - IAPU.PC += 2; -} - -void ApuB0 () -{ -// BCS - Relative (); - if (APUCheckCarry ()) - { - - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - APUShutdown (); - } - else - IAPU.PC += 2; -} - -void ApuD0 () -{ -// BNE - Relative (); - if (!APUCheckZero ()) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - APUShutdown (); - } - else - IAPU.PC += 2; -} - -void ApuF0 () -{ -// BEQ - Relative (); - if (APUCheckZero ()) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - APUShutdown (); - } - else - IAPU.PC += 2; -} - -void Apu50 () -{ -// BVC - Relative (); - if (!APUCheckOverflow ()) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - } - else - IAPU.PC += 2; -} - -void Apu70 () -{ -// BVS - Relative (); - if (APUCheckOverflow ()) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - } - else - IAPU.PC += 2; -} - -void Apu2F () -{ -// BRA - Relative (); - IAPU.PC = IAPU.RAM + (uint16) Int16; -} - -void Apu80 () -{ -// SETC - APUSetCarry (); - IAPU.PC++; -} - -void ApuED () -{ -// NOTC - IAPU._Carry ^= 1; - IAPU.PC++; -} - -void Apu40 () -{ -// SETP - APUSetDirectPage (); - IAPU.DirectPage = IAPU.RAM + 0x100; - IAPU.PC++; -} - -void Apu1A () -{ -// DECW dp - uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); - Work16--; - S9xAPUSetByteZ ((uint8) Work16, OP1); - S9xAPUSetByteZ (Work16 >> 8, OP1 + 1); - APUSetZN16 (Work16); - IAPU.PC += 2; -} - -void Apu5A () -{ -// CMPW YA,dp - uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); - long Int32 = (long) IAPU.YA.W - (long) Work16; - IAPU._Carry = Int32 >= 0; - APUSetZN16 ((uint16) Int32); - IAPU.PC += 2; -} - -void Apu3A () -{ -// INCW dp - uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); - Work16++; - S9xAPUSetByteZ ((uint8) Work16, OP1); - S9xAPUSetByteZ (Work16 >> 8, OP1 + 1); - APUSetZN16 (Work16); - IAPU.PC += 2; -} - -// XXX: HalfCarry - BJ Fixed? Or is it between bits 7 and 8 for ADDW/SUBW? -void Apu7A () -{ -// ADDW YA,dp - uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); - uint32 Work32 = (uint32) IAPU.YA.W + Work16; - IAPU._Carry = Work32 >= 0x10000; - if (~(IAPU.YA.W ^ Work16) & (Work16 ^ (uint16) Work32) & 0x8000) - APUSetOverflow (); - else - APUClearOverflow (); - APUClearHalfCarry (); - if((IAPU.YA.W ^ Work16 ^ (uint16) Work32) & 0x10) - APUSetHalfCarry (); - IAPU.YA.W = (uint16) Work32; - APUSetZN16 (IAPU.YA.W); - IAPU.PC += 2; -} - -// XXX: BJ: i think the old HalfCarry behavior was wrong... -// XXX: Or is it between bits 7 and 8 for ADDW/SUBW? -void Apu9A () -{ -// SUBW YA,dp - uint16 Work16 = S9xAPUGetByteZ (OP1) + (S9xAPUGetByteZ (OP1 + 1) << 8); - long Int32 = (long) IAPU.YA.W - (long) Work16; - APUClearHalfCarry (); - IAPU._Carry = Int32 >= 0; - if (((IAPU.YA.W ^ Work16) & 0x8000) && - ((IAPU.YA.W ^ (uint16) Int32) & 0x8000)) - APUSetOverflow (); - else - APUClearOverflow (); -// if (((IAPU.YA.W ^ Work16) & 0x0080) && -// ((IAPU.YA.W ^ (uint16) Int32) & 0x0080)) -// APUSetHalfCarry (); // notaz: strange here - APUSetHalfCarry (); -// if((IAPU.YA.W ^ Work16 ^ (uint16) Work32) & 0x10) // notaz: Work32?! - if((IAPU.YA.W ^ Work16 ^ (uint16) Int32) & 0x10) - APUClearHalfCarry (); - IAPU.YA.W = (uint16) Int32; - APUSetZN16 (IAPU.YA.W); - IAPU.PC += 2; -} - -void ApuBA () -{ -// MOVW YA,dp - IAPU.YA.B.A = S9xAPUGetByteZ (OP1); - IAPU.YA.B.Y = S9xAPUGetByteZ (OP1 + 1); - APUSetZN16 (IAPU.YA.W); - IAPU.PC += 2; -} - -void ApuDA () -{ -// MOVW dp,YA - S9xAPUSetByteZ (IAPU.YA.B.A, OP1); - S9xAPUSetByteZ (IAPU.YA.B.Y, OP1 + 1); - IAPU.PC += 2; -} - -void Apu64 () -{ -// CMP A,dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - CMP (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu65 () -{ -// CMP A,abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu66 () -{ -// CMP A,(X) - uint8 Work8 = S9xAPUGetByteZ (IAPU.X); - CMP (IAPU.YA.B.A, Work8); - IAPU.PC++; -} - -void Apu67 () -{ -// CMP A,(dp+X) - IndexedXIndirect (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - CMP (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu68 () -{ -// CMP A,#00 - uint8 Work8 = OP1; - CMP (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu69 () -{ -// CMP dp(dest), dp(src) - uint8 W1 = S9xAPUGetByteZ (OP1); - uint8 Work8 = S9xAPUGetByteZ (OP2); - CMP (Work8, W1); - IAPU.PC += 3; -} - -void Apu74 () -{ -// CMP A, dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); - CMP (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu75 () -{ -// CMP A,abs+X - AbsoluteX (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu76 () -{ -// CMP A, abs+Y - AbsoluteY (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu77 () -{ -// CMP A,(dp)+Y - IndirectIndexedY (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu78 () -{ -// CMP dp,#00 - uint8 Work8 = OP1; - uint8 W1 = S9xAPUGetByteZ (OP2); - CMP (W1, Work8); - IAPU.PC += 3; -} - -void Apu79 () -{ -// CMP (X),(Y) - uint8 W1 = S9xAPUGetByteZ (IAPU.X); - uint8 Work8 = S9xAPUGetByteZ (IAPU.YA.B.Y); - CMP (W1, Work8); - IAPU.PC++; -} - -void Apu1E () -{ -// CMP X,abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address); - CMP (IAPU.X, Work8); - IAPU.PC += 3; -} - -void Apu3E () -{ -// CMP X,dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - CMP (IAPU.X, Work8); - IAPU.PC += 2; -} - -void ApuC8 () -{ -// CMP X,#00 - CMP (IAPU.X, OP1); - IAPU.PC += 2; -} - -void Apu5E () -{ -// CMP Y,abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - CMP (IAPU.YA.B.Y, Work8); - IAPU.PC += 3; -} - -void Apu7E () -{ -// CMP Y,dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - CMP (IAPU.YA.B.Y, Work8); - IAPU.PC += 2; -} - -void ApuAD () -{ -// CMP Y,#00 - uint8 Work8 = OP1; - CMP (IAPU.YA.B.Y, Work8); - IAPU.PC += 2; -} - -void Apu1F () -{ -// JMP (abs+X) - Absolute (); - IAPU.PC = IAPU.RAM + S9xAPUGetByte (IAPU.Address + IAPU.X) + - (S9xAPUGetByte (IAPU.Address + IAPU.X + 1) << 8); -// XXX: HERE: - // APU.Flags |= TRACE_FLAG; -} - -void Apu5F () -{ -// JMP abs - Absolute (); - IAPU.PC = IAPU.RAM + IAPU.Address; -} - -void Apu20 () -{ -// CLRP - APUClearDirectPage (); - IAPU.DirectPage = IAPU.RAM; - IAPU.PC++; -} - -void Apu60 () -{ -// CLRC - APUClearCarry (); - IAPU.PC++; -} - -void ApuE0 () -{ -// CLRV - APUClearHalfCarry (); - APUClearOverflow (); - IAPU.PC++; -} - -void Apu24 () -{ -// AND A,dp - IAPU.YA.B.A &= S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu25 () -{ -// AND A,abs - Absolute (); - IAPU.YA.B.A &= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void Apu26 () -{ -// AND A,(X) - IAPU.YA.B.A &= S9xAPUGetByteZ (IAPU.X); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void Apu27 () -{ -// AND A,(dp+X) - IndexedXIndirect (); - IAPU.YA.B.A &= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu28 () -{ -// AND A,#00 - IAPU.YA.B.A &= OP1; - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu29 () -{ -// AND dp(dest),dp(src) - uint8 Work8 = S9xAPUGetByteZ (OP1); - Work8 &= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu34 () -{ -// AND A,dp+X - IAPU.YA.B.A &= S9xAPUGetByteZ (OP1 + IAPU.X); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu35 () -{ -// AND A,abs+X - AbsoluteX (); - IAPU.YA.B.A &= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void Apu36 () -{ -// AND A,abs+Y - AbsoluteY (); - IAPU.YA.B.A &= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void Apu37 () -{ -// AND A,(dp)+Y - IndirectIndexedY (); - IAPU.YA.B.A &= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu38 () -{ -// AND dp,#00 - uint8 Work8 = OP1; - Work8 &= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu39 () -{ -// AND (X),(Y) - uint8 Work8 = S9xAPUGetByteZ (IAPU.X) & S9xAPUGetByteZ (IAPU.YA.B.Y); - APUSetZN8 (Work8); - S9xAPUSetByteZ (Work8, IAPU.X); - IAPU.PC++; -} - -void Apu2B () -{ -// ROL dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - ROL (Work8); - S9xAPUSetByteZ (Work8, OP1); - IAPU.PC += 2; -} - -void Apu2C () -{ -// ROL abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - ROL (Work8); - S9xAPUSetByte (Work8, IAPU.Address); - IAPU.PC += 3; -} - -void Apu3B () -{ -// ROL dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); - ROL (Work8); - S9xAPUSetByteZ (Work8, OP1 + IAPU.X); - IAPU.PC += 2; -} - -void Apu3C () -{ -// ROL A - ROL (IAPU.YA.B.A); - IAPU.PC++; -} - -void Apu2E () -{ -// CBNE dp,rel - uint8 Work8 = OP1; - Relative2 (); - - if (S9xAPUGetByteZ (Work8) != IAPU.YA.B.A) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - APUShutdown (); - } - else - IAPU.PC += 3; -} - -void ApuDE () -{ -// CBNE dp+X,rel - uint8 Work8 = OP1 + IAPU.X; - Relative2 (); - - if (S9xAPUGetByteZ (Work8) != IAPU.YA.B.A) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - APUShutdown (); - } - else - IAPU.PC += 3; -} - -void Apu3D () -{ -// INC X - IAPU.X++; - APUSetZN8 (IAPU.X); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void ApuFC () -{ -// INC Y - IAPU.YA.B.Y++; - APUSetZN8 (IAPU.YA.B.Y); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void Apu1D () -{ -// DEC X - IAPU.X--; - APUSetZN8 (IAPU.X); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void ApuDC () -{ -// DEC Y - IAPU.YA.B.Y--; - APUSetZN8 (IAPU.YA.B.Y); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void ApuAB () -{ -// INC dp - uint8 Work8 = S9xAPUGetByteZ (OP1) + 1; - S9xAPUSetByteZ (Work8, OP1); - APUSetZN8 (Work8); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC += 2; -} - -void ApuAC () -{ -// INC abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (IAPU.Address) + 1; - S9xAPUSetByte (Work8, IAPU.Address); - APUSetZN8 (Work8); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC += 3; -} - -void ApuBB () -{ -// INC dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X) + 1; - S9xAPUSetByteZ (Work8, OP1 + IAPU.X); - APUSetZN8 (Work8); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC += 2; -} - -void ApuBC () -{ -// INC A - IAPU.YA.B.A++; - APUSetZN8 (IAPU.YA.B.A); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void Apu8B () -{ -// DEC dp - uint8 Work8 = S9xAPUGetByteZ (OP1) - 1; - S9xAPUSetByteZ (Work8, OP1); - APUSetZN8 (Work8); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC += 2; -} - -void Apu8C () -{ -// DEC abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))) - 1; - S9xAPUSetByte (Work8, IAPU.Address); - APUSetZN8 (Work8); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC += 3; -} - -void Apu9B () -{ -// DEC dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X) - 1; - S9xAPUSetByteZ (Work8, OP1 + IAPU.X); - APUSetZN8 (Work8); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC += 2; -} - -void Apu9C () -{ -// DEC A - IAPU.YA.B.A--; - APUSetZN8 (IAPU.YA.B.A); - -#ifdef SPC700_SHUTDOWN - IAPU.WaitCounter++; -#endif - - IAPU.PC++; -} - -void Apu44 () -{ -// EOR A,dp - IAPU.YA.B.A ^= S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu45 () -{ -// EOR A,abs - Absolute (); - IAPU.YA.B.A ^= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void Apu46 () -{ -// EOR A,(X) - IAPU.YA.B.A ^= S9xAPUGetByteZ (IAPU.X); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void Apu47 () -{ -// EOR A,(dp+X) - IndexedXIndirect (); - IAPU.YA.B.A ^= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu48 () -{ -// EOR A,#00 - IAPU.YA.B.A ^= OP1; - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu49 () -{ -// EOR dp(dest),dp(src) - uint8 Work8 = S9xAPUGetByteZ (OP1); - Work8 ^= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu54 () -{ -// EOR A,dp+X - IAPU.YA.B.A ^= S9xAPUGetByteZ (OP1 + IAPU.X); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu55 () -{ -// EOR A,abs+X - AbsoluteX (); - IAPU.YA.B.A ^= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void Apu56 () -{ -// EOR A,abs+Y - AbsoluteY (); - IAPU.YA.B.A ^= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void Apu57 () -{ -// EOR A,(dp)+Y - IndirectIndexedY (); - IAPU.YA.B.A ^= S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void Apu58 () -{ -// EOR dp,#00 - uint8 Work8 = OP1; - Work8 ^= S9xAPUGetByteZ (OP2); - S9xAPUSetByteZ (Work8, OP2); - APUSetZN8 (Work8); - IAPU.PC += 3; -} - -void Apu59 () -{ -// EOR (X),(Y) - uint8 Work8 = S9xAPUGetByteZ (IAPU.X) ^ S9xAPUGetByteZ (IAPU.YA.B.Y); - APUSetZN8 (Work8); - S9xAPUSetByteZ (Work8, IAPU.X); - IAPU.PC++; -} - -void Apu4B () -{ -// LSR dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - LSR (Work8); - S9xAPUSetByteZ (Work8, OP1); - IAPU.PC += 2; -} - -void Apu4C () -{ -// LSR abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - LSR (Work8); - S9xAPUSetByte (Work8, IAPU.Address); - IAPU.PC += 3; -} - -void Apu5B () -{ -// LSR dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); - LSR (Work8); - S9xAPUSetByteZ (Work8, OP1 + IAPU.X); - IAPU.PC += 2; -} - -void Apu5C () -{ -// LSR A - LSR (IAPU.YA.B.A); - IAPU.PC++; -} - -void Apu7D () -{ -// MOV A,X - IAPU.YA.B.A = IAPU.X; - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void ApuDD () -{ -// MOV A,Y - IAPU.YA.B.A = IAPU.YA.B.Y; - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void Apu5D () -{ -// MOV X,A - IAPU.X = IAPU.YA.B.A; - APUSetZN8 (IAPU.X); - IAPU.PC++; -} - -void ApuFD () -{ -// MOV Y,A - IAPU.YA.B.Y = IAPU.YA.B.A; - APUSetZN8 (IAPU.YA.B.Y); - IAPU.PC++; -} - -void Apu9D () -{ -//MOV X,SP - IAPU.X = IAPU.S; - APUSetZN8 (IAPU.X); - IAPU.PC++; -} - -void ApuBD () -{ -// MOV SP,X - IAPU.S = IAPU.X; - IAPU.PC++; -} - -void Apu6B () -{ -// ROR dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - ROR (Work8); - S9xAPUSetByteZ (Work8, OP1); - IAPU.PC += 2; -} - -void Apu6C () -{ -// ROR abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - ROR (Work8); - S9xAPUSetByte (Work8, IAPU.Address); - IAPU.PC += 3; -} - -void Apu7B () -{ -// ROR dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); - ROR (Work8); - S9xAPUSetByteZ (Work8, OP1 + IAPU.X); - IAPU.PC += 2; -} - -void Apu7C () -{ -// ROR A - ROR (IAPU.YA.B.A); - IAPU.PC++; -} - -void Apu6E () -{ -// DBNZ dp,rel - uint8 Work8 = OP1; - Relative2 (); - uint8 W1 = S9xAPUGetByteZ (Work8) - 1; - S9xAPUSetByteZ (W1, Work8); - if (W1 != 0) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - } - else - IAPU.PC += 3; -} - -void ApuFE () -{ -// DBNZ Y,rel - Relative (); - IAPU.YA.B.Y--; - if (IAPU.YA.B.Y != 0) - { - IAPU.PC = IAPU.RAM + (uint16) Int16; - CPU.APU_Cycles += IAPU.TwoCycles; - } - else - IAPU.PC += 2; -} - -void Apu6F () -{ -// RET - uint16 Work16; - PopW (Work16); - IAPU.PC = IAPU.RAM + Work16; -} - -void Apu7F () -{ -// RETI - // STOP ("RETI"); - uint16 Work16; - Pop (IAPU.P); - S9xAPUUnpackStatus (); - PopW (Work16); - IAPU.PC = IAPU.RAM + Work16; -} - -void Apu84 () -{ -// ADC A,dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - ADC (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu85 () -{ -// ADC A, abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - ADC (IAPU.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu86 () -{ -// ADC A,(X) - uint8 Work8 = S9xAPUGetByteZ (IAPU.X); - ADC (IAPU.YA.B.A, Work8); - IAPU.PC++; -} - -void Apu87 () -{ -// ADC A,(dp+X) - IndexedXIndirect (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - ADC (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu88 () -{ -// ADC A,#00 - uint8 Work8 = OP1; - ADC (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu89 () -{ -// ADC dp(dest),dp(src) - uint8 Work8 = S9xAPUGetByteZ (OP1); - uint8 W1 = S9xAPUGetByteZ (OP2); - ADC (W1, Work8); - S9xAPUSetByteZ (W1, OP2); - IAPU.PC += 3; -} - -void Apu94 () -{ -// ADC A,dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); - ADC (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu95 () -{ -// ADC A, abs+X - AbsoluteX (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - ADC (IAPU.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu96 () -{ -// ADC A, abs+Y - AbsoluteY (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - ADC (IAPU.YA.B.A, Work8); - IAPU.PC += 3; -} - -void Apu97 () -{ -// ADC A, (dp)+Y - IndirectIndexedY (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - ADC (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void Apu98 () -{ -// ADC dp,#00 - uint8 Work8 = OP1; - uint8 W1 = S9xAPUGetByteZ (OP2); - ADC (W1, Work8); - S9xAPUSetByteZ (W1, OP2); - IAPU.PC += 3; -} - -void Apu99 () -{ -// ADC (X),(Y) - uint8 W1 = S9xAPUGetByteZ (IAPU.X); - uint8 Work8 = S9xAPUGetByteZ (IAPU.YA.B.Y); - ADC (W1, Work8); - S9xAPUSetByteZ (W1, IAPU.X); - IAPU.PC++; -} - -void Apu8D () -{ -// MOV Y,#00 - IAPU.YA.B.Y = OP1; - APUSetZN8 (IAPU.YA.B.Y); - IAPU.PC += 2; -} - -void Apu8F () -{ -// MOV dp,#00 - uint8 Work8 = OP1; - S9xAPUSetByteZ (Work8, OP2); - IAPU.PC += 3; -} - -void Apu9E () -{ -// DIV YA,X - if (IAPU.X == 0) - { - APUSetOverflow (); - IAPU.YA.B.Y = 0xff; - IAPU.YA.B.A = 0xff; - } - else - { - APUClearOverflow (); - uint8 Work8 = IAPU.YA.W / IAPU.X; - IAPU.YA.B.Y = IAPU.YA.W % IAPU.X; - IAPU.YA.B.A = Work8; - } -// XXX How should Overflow, Half Carry, Zero and Negative flags be set?? - // APUSetZN16 (IAPU.YA.W); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void Apu9F () -{ -// XCN A - IAPU.YA.B.A = (IAPU.YA.B.A >> 4) | (IAPU.YA.B.A << 4); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void ApuA4 () -{ -// SBC A, dp - uint8 Work8 = S9xAPUGetByteZ (OP1); - SBC (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void ApuA5 () -{ -// SBC A, abs - Absolute (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - SBC (IAPU.YA.B.A, Work8); - IAPU.PC += 3; -} - -void ApuA6 () -{ -// SBC A, (X) - uint8 Work8 = S9xAPUGetByteZ (IAPU.X); - SBC (IAPU.YA.B.A, Work8); - IAPU.PC++; -} - -void ApuA7 () -{ -// SBC A,(dp+X) - IndexedXIndirect (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - SBC (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void ApuA8 () -{ -// SBC A,#00 - uint8 Work8 = OP1; - SBC (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void ApuA9 () -{ -// SBC dp(dest), dp(src) - uint8 Work8 = S9xAPUGetByteZ (OP1); - uint8 W1 = S9xAPUGetByteZ (OP2); - SBC (W1, Work8); - S9xAPUSetByteZ (W1, OP2); - IAPU.PC += 3; -} - -void ApuB4 () -{ -// SBC A, dp+X - uint8 Work8 = S9xAPUGetByteZ (OP1 + IAPU.X); - SBC (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void ApuB5 () -{ -// SBC A,abs+X - AbsoluteX (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - SBC (IAPU.YA.B.A, Work8); - IAPU.PC += 3; -} - -void ApuB6 () -{ -// SBC A,abs+Y - AbsoluteY (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - SBC (IAPU.YA.B.A, Work8); - IAPU.PC += 3; -} - -void ApuB7 () -{ -// SBC A,(dp)+Y - IndirectIndexedY (); - uint8 Work8 = S9xAPUGetByte (((IAPU.Address))); - SBC (IAPU.YA.B.A, Work8); - IAPU.PC += 2; -} - -void ApuB8 () -{ -// SBC dp,#00 - uint8 Work8 = OP1; - uint8 W1 = S9xAPUGetByteZ (OP2); - SBC (W1, Work8); - S9xAPUSetByteZ (W1, OP2); - IAPU.PC += 3; -} - -void ApuB9 () -{ -// SBC (X),(Y) - uint8 W1 = S9xAPUGetByteZ (IAPU.X); - uint8 Work8 = S9xAPUGetByteZ (IAPU.YA.B.Y); - SBC (W1, Work8); - S9xAPUSetByteZ (W1, IAPU.X); - IAPU.PC++; -} - -void ApuAF () -{ -// MOV (X)+, A - S9xAPUSetByteZ (IAPU.YA.B.A, IAPU.X++); - IAPU.PC++; -} - -void ApuBE () -{ -// DAS - if ((IAPU.YA.B.A & 0x0f) > 9 || !APUCheckHalfCarry()) - { - IAPU.YA.B.A -= 6; - } - if (IAPU.YA.B.A > 0x9f || !IAPU._Carry) - { - IAPU.YA.B.A -= 0x60; - APUClearCarry (); - } - else { APUSetCarry (); } - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void ApuBF () -{ -// MOV A,(X)+ - IAPU.YA.B.A = S9xAPUGetByteZ (IAPU.X++); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void ApuC0 () -{ -// DI - APUClearInterrupt (); - IAPU.PC++; -} - -void ApuA0 () -{ -// EI - APUSetInterrupt (); - IAPU.PC++; -} - -void ApuC4 () -{ -// MOV dp,A - S9xAPUSetByteZ (IAPU.YA.B.A, OP1); - IAPU.PC += 2; -} - -void ApuC5 () -{ -// MOV abs,A - Absolute (); - S9xAPUSetByte (IAPU.YA.B.A, IAPU.Address); - IAPU.PC += 3; -} - -void ApuC6 () -{ -// MOV (X), A - S9xAPUSetByteZ (IAPU.YA.B.A, IAPU.X); - IAPU.PC++; -} - -void ApuC7 () -{ -// MOV (dp+X),A - IndexedXIndirect (); - S9xAPUSetByte (IAPU.YA.B.A, IAPU.Address); - IAPU.PC += 2; -} - -void ApuC9 () -{ -// MOV abs,X - Absolute (); - S9xAPUSetByte (IAPU.X, IAPU.Address); - IAPU.PC += 3; -} - -void ApuCB () -{ -// MOV dp,Y - S9xAPUSetByteZ (IAPU.YA.B.Y, OP1); - IAPU.PC += 2; -} - -void ApuCC () -{ -// MOV abs,Y - Absolute (); - S9xAPUSetByte (IAPU.YA.B.Y, IAPU.Address); - IAPU.PC += 3; -} - -void ApuCD () -{ -// MOV X,#00 - IAPU.X = OP1; - APUSetZN8 (IAPU.X); - IAPU.PC += 2; -} - -void ApuCF () -{ -// MUL YA - IAPU.YA.W = (uint16) IAPU.YA.B.A * IAPU.YA.B.Y; - APUSetZN16 (IAPU.YA.W); - IAPU.PC++; -} - -void ApuD4 () -{ -// MOV dp+X, A - S9xAPUSetByteZ (IAPU.YA.B.A, OP1 + IAPU.X); - IAPU.PC += 2; -} - -void ApuD5 () -{ -// MOV abs+X,A - AbsoluteX (); - S9xAPUSetByte (IAPU.YA.B.A, IAPU.Address); - IAPU.PC += 3; -} - -void ApuD6 () -{ -// MOV abs+Y,A - AbsoluteY (); - S9xAPUSetByte (IAPU.YA.B.A, IAPU.Address); - IAPU.PC += 3; -} - -void ApuD7 () -{ -// MOV (dp)+Y,A - IndirectIndexedY (); - S9xAPUSetByte (IAPU.YA.B.A, IAPU.Address); - IAPU.PC += 2; -} - -void ApuD8 () -{ -// MOV dp,X - S9xAPUSetByteZ (IAPU.X, OP1); - IAPU.PC += 2; -} - -void ApuD9 () -{ -// MOV dp+Y,X - S9xAPUSetByteZ (IAPU.X, OP1 + IAPU.YA.B.Y); - IAPU.PC += 2; -} - -void ApuDB () -{ -// MOV dp+X,Y - S9xAPUSetByteZ (IAPU.YA.B.Y, OP1 + IAPU.X); - IAPU.PC += 2; -} - -void ApuDF () -{ -// DAA - if ((IAPU.YA.B.A & 0x0f) > 9 || APUCheckHalfCarry()) - { - if(IAPU.YA.B.A > 0xf0) APUSetCarry (); - IAPU.YA.B.A += 6; - //APUSetHalfCarry (); Intel procs do this, but this is a Sony proc... - } - //else { APUClearHalfCarry (); } ditto as above - if (IAPU.YA.B.A > 0x9f || IAPU._Carry) - { - IAPU.YA.B.A += 0x60; - APUSetCarry (); - } - else { APUClearCarry (); } - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void ApuE4 () -{ -// MOV A, dp - IAPU.YA.B.A = S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void ApuE5 () -{ -// MOV A,abs - Absolute (); - IAPU.YA.B.A = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void ApuE6 () -{ -// MOV A,(X) - IAPU.YA.B.A = S9xAPUGetByteZ (IAPU.X); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC++; -} - -void ApuE7 () -{ -// MOV A,(dp+X) - IndexedXIndirect (); - IAPU.YA.B.A = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void ApuE8 () -{ -// MOV A,#00 - IAPU.YA.B.A = OP1; - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void ApuE9 () -{ -// MOV X, abs - Absolute (); - IAPU.X = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.X); - IAPU.PC += 3; -} - -void ApuEB () -{ -// MOV Y,dp - IAPU.YA.B.Y = S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.YA.B.Y); - IAPU.PC += 2; -} - -void ApuEC () -{ -// MOV Y,abs - Absolute (); - IAPU.YA.B.Y = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.Y); - IAPU.PC += 3; -} - -void ApuF4 () -{ -// MOV A, dp+X - IAPU.YA.B.A = S9xAPUGetByteZ (OP1 + IAPU.X); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void ApuF5 () -{ -// MOV A, abs+X - AbsoluteX (); - IAPU.YA.B.A = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void ApuF6 () -{ -// MOV A, abs+Y - AbsoluteY (); - IAPU.YA.B.A = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 3; -} - -void ApuF7 () -{ -// MOV A, (dp)+Y - IndirectIndexedY (); - IAPU.YA.B.A = S9xAPUGetByte (IAPU.Address); - APUSetZN8 (IAPU.YA.B.A); - IAPU.PC += 2; -} - -void ApuF8 () -{ -// MOV X,dp - IAPU.X = S9xAPUGetByteZ (OP1); - APUSetZN8 (IAPU.X); - IAPU.PC += 2; -} - -void ApuF9 () -{ -// MOV X,dp+Y - IAPU.X = S9xAPUGetByteZ (OP1 + IAPU.YA.B.Y); - APUSetZN8 (IAPU.X); - IAPU.PC += 2; -} - -void ApuFA () -{ -// MOV dp(dest),dp(src) - S9xAPUSetByteZ (S9xAPUGetByteZ (OP1), OP2); - IAPU.PC += 3; -} - -void ApuFB () -{ -// MOV Y,dp+X - IAPU.YA.B.Y = S9xAPUGetByteZ (OP1 + IAPU.X); - APUSetZN8 (IAPU.YA.B.Y); - IAPU.PC += 2; -} - -#if defined(NO_INLINE_SET_GET) -#undef INLINE -#define INLINE -#include "apumem.h" -#endif - - -void (*S9xApuOpcodes[256]) (void) = -{ - Apu00, Apu01, Apu02, Apu03, Apu04, Apu05, Apu06, Apu07, - Apu08, Apu09, Apu0A, Apu0B, Apu0C, Apu0D, Apu0E, Apu0F, - Apu10, Apu11, Apu12, Apu13, Apu14, Apu15, Apu16, Apu17, - Apu18, Apu19, Apu1A, Apu1B, Apu1C, Apu1D, Apu1E, Apu1F, - Apu20, Apu21, Apu22, Apu23, Apu24, Apu25, Apu26, Apu27, - Apu28, Apu29, Apu2A, Apu2B, Apu2C, Apu2D, Apu2E, Apu2F, - Apu30, Apu31, Apu32, Apu33, Apu34, Apu35, Apu36, Apu37, - Apu38, Apu39, Apu3A, Apu3B, Apu3C, Apu3D, Apu3E, Apu3F, - Apu40, Apu41, Apu42, Apu43, Apu44, Apu45, Apu46, Apu47, - Apu48, Apu49, Apu4A, Apu4B, Apu4C, Apu4D, Apu4E, Apu4F, - Apu50, Apu51, Apu52, Apu53, Apu54, Apu55, Apu56, Apu57, - Apu58, Apu59, Apu5A, Apu5B, Apu5C, Apu5D, Apu5E, Apu5F, - Apu60, Apu61, Apu62, Apu63, Apu64, Apu65, Apu66, Apu67, - Apu68, Apu69, Apu6A, Apu6B, Apu6C, Apu6D, Apu6E, Apu6F, - Apu70, Apu71, Apu72, Apu73, Apu74, Apu75, Apu76, Apu77, - Apu78, Apu79, Apu7A, Apu7B, Apu7C, Apu7D, Apu7E, Apu7F, - Apu80, Apu81, Apu82, Apu83, Apu84, Apu85, Apu86, Apu87, - Apu88, Apu89, Apu8A, Apu8B, Apu8C, Apu8D, Apu8E, Apu8F, - Apu90, Apu91, Apu92, Apu93, Apu94, Apu95, Apu96, Apu97, - Apu98, Apu99, Apu9A, Apu9B, Apu9C, Apu9D, Apu9E, Apu9F, - ApuA0, ApuA1, ApuA2, ApuA3, ApuA4, ApuA5, ApuA6, ApuA7, - ApuA8, ApuA9, ApuAA, ApuAB, ApuAC, ApuAD, ApuAE, ApuAF, - ApuB0, ApuB1, ApuB2, ApuB3, ApuB4, ApuB5, ApuB6, ApuB7, - ApuB8, ApuB9, ApuBA, ApuBB, ApuBC, ApuBD, ApuBE, ApuBF, - ApuC0, ApuC1, ApuC2, ApuC3, ApuC4, ApuC5, ApuC6, ApuC7, - ApuC8, ApuC9, ApuCA, ApuCB, ApuCC, ApuCD, ApuCE, ApuCF, - ApuD0, ApuD1, ApuD2, ApuD3, ApuD4, ApuD5, ApuD6, ApuD7, - ApuD8, ApuD9, ApuDA, ApuDB, ApuDC, ApuDD, ApuDE, ApuDF, - ApuE0, ApuE1, ApuE2, ApuE3, ApuE4, ApuE5, ApuE6, ApuE7, - ApuE8, ApuE9, ApuEA, ApuEB, ApuEC, ApuED, ApuEE, ApuEF, - ApuF0, ApuF1, ApuF2, ApuF3, ApuF4, ApuF5, ApuF6, ApuF7, - ApuF8, ApuF9, ApuFA, ApuFB, ApuFC, ApuFD, ApuFE, ApuFF -}; - - diff --git a/src/spc700.h b/src/spc700.h index 6b73f44..66ef814 100644 --- a/src/spc700.h +++ b/src/spc700.h @@ -95,13 +95,14 @@ typedef union uint32 _padder; // make sure this whole thing takes 4 bytes } YAndA; -struct SAPURegisters{ +typedef struct +{ uint8 P; YAndA YA; uint8 X; uint8 S; uint16 PC; -}; +}SAPURegisters; //EXTERN_C struct SAPURegisters APURegisters; diff --git a/src/srtc.c b/src/srtc.c new file mode 100644 index 0000000..be390f0 --- /dev/null +++ b/src/srtc.c @@ -0,0 +1,528 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include +#include "snes9x.h" +#include "srtc.h" +#include "memmap.h" + +/*** The format of the rtc_data structure is: + +Index Description Range (nibble) +----- -------------- --------------------------------------- + + 0 Seconds low 0-9 + 1 Seconds high 0-5 + + 2 Minutes low 0-9 + 3 Minutes high 0-5 + + 4 Hour low 0-9 + 5 Hour high 0-2 + + 6 Day low 0-9 + 7 Day high 0-3 + + 8 Month 1-C (0xC is December, 12th month) + + 9 Year ones 0-9 + A Year tens 0-9 + B Year High 9-B (9=19xx, A=20xx, B=21xx) + + C Day of week 0-6 (0=Sunday, 1=Monday,...,6=Saturday) + +***/ + +SRTC_DATA rtc; + + +static int month_keys[12] = { 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6 }; + + +/********************************************************************************************* + * + * Note, if you are doing a save state for this game: + * + * On save: + * + * Call S9xUpdateSrtcTime and save the rtc data structure. + * + * On load: + * + * restore the rtc data structure + * rtc.system_timestamp = time (NULL); + * + * + *********************************************************************************************/ + + +void S9xResetSRTC () +{ + rtc.index = -1; + rtc.mode = MODE_READ; +} + +void S9xHardResetSRTC () +{ + ZeroMemory (&rtc, sizeof (rtc)); + rtc.index = -1; + rtc.mode = MODE_READ; + rtc.count_enable = FALSE; + rtc.needs_init = TRUE; + + // Get system timestamp + rtc.system_timestamp = time (NULL); +} + +/**********************************************************************************************/ +/* S9xSRTCComputeDayOfWeek() */ +/* Return 0-6 for Sunday-Saturday */ +/**********************************************************************************************/ +unsigned int S9xSRTCComputeDayOfWeek () +{ + unsigned year = rtc.data[10]*10 + rtc.data[9]; + unsigned month = rtc.data[8]; + unsigned day = rtc.data[7]*10 + rtc.data[6]; + unsigned day_of_week; + + year += (rtc.data[11] - 9) * 100; + + // Range check the month for valid array indicies + if ( month > 12 ) + month = 1; + + day_of_week = year + (year / 4) + month_keys[month-1] + day - 1; + + if(( year % 4 == 0 ) && ( month <= 2 ) ) + day_of_week--; + + day_of_week %= 7; + + return day_of_week; +} + + +/**********************************************************************************************/ +/* S9xSRTCDaysInMonth() */ +/* Return the number of days in a specific month for a certain year */ +/**********************************************************************************************/ +int S9xSRTCDaysInMmonth( int month, int year ) +{ + int mdays; + + switch ( month ) + { + case 2: + if ( ( year % 4 == 0 ) ) // DKJM2 only uses 199x - 22xx + mdays = 29; + else + mdays = 28; + break; + + case 4: + case 6: + case 9: + case 11: + mdays = 30; + break; + + default: // months 1,3,5,7,8,10,12 + mdays = 31; + break; + } + + return mdays; +} + + +#define DAYTICKS (60*60*24) +#define HOURTICKS (60*60) +#define MINUTETICKS 60 + + +/**********************************************************************************************/ +/* S9xUpdateSrtcTime() */ +/* Advance the S-RTC time if counting is enabled */ +/**********************************************************************************************/ +void S9xUpdateSrtcTime () +{ + time_t cur_systime; + long time_diff; + + // Keep track of game time by computing the number of seconds that pass on the system + // clock and adding the same number of seconds to the S-RTC clock structure. + // I originally tried using mktime and localtime library functions to keep track + // of time but some of the GNU time functions fail when the year goes to 2099 + // (and maybe less) and this would have caused a bug with DKJM2 so I'm doing + // it this way to get around that problem. + + // Note: Dai Kaijyu Monogatari II only allows dates in the range 1996-21xx. + + if (rtc.count_enable && !rtc.needs_init) + { + cur_systime = time (NULL); + + // This method assumes one time_t clock tick is one second + // which should work on PCs and GNU systems. + // If your tick interval is different adjust the + // DAYTICK, HOURTICK, and MINUTETICK defines + + time_diff = (long) (cur_systime - rtc.system_timestamp); + rtc.system_timestamp = cur_systime; + + if ( time_diff > 0 ) + { + int seconds; + int minutes; + int hours; + int days; + int month; + int year; + int temp_days; + + int year_hundreds; + int year_tens; + int year_ones; + + + if ( time_diff > DAYTICKS ) + { + days = time_diff / DAYTICKS; + time_diff = time_diff - days * DAYTICKS; + } + else + { + days = 0; + } + + if ( time_diff > HOURTICKS ) + { + hours = time_diff / HOURTICKS; + time_diff = time_diff - hours * HOURTICKS; + } + else + { + hours = 0; + } + + if ( time_diff > MINUTETICKS ) + { + minutes = time_diff / MINUTETICKS; + time_diff = time_diff - minutes * MINUTETICKS; + } + else + { + minutes = 0; + } + + if ( time_diff > 0 ) + { + seconds = time_diff; + } + else + { + seconds = 0; + } + + + seconds += (rtc.data[1]*10 + rtc.data[0]); + if ( seconds >= 60 ) + { + seconds -= 60; + minutes += 1; + } + + minutes += (rtc.data[3]*10 + rtc.data[2]); + if ( minutes >= 60 ) + { + minutes -= 60; + hours += 1; + } + + hours += (rtc.data[5]*10 + rtc.data[4]); + if ( hours >= 24 ) + { + hours -= 24; + days += 1; + } + + if ( days > 0 ) + { + year = rtc.data[10]*10 + rtc.data[9]; + year += ( 1000 + rtc.data[11] * 100 ); + + month = rtc.data[8]; + days += (rtc.data[7]*10 + rtc.data[6]); + while ( days > (temp_days = S9xSRTCDaysInMmonth( month, year )) ) + { + days -= temp_days; + month += 1; + if ( month > 12 ) + { + year += 1; + month = 1; + } + } + + year_tens = year % 100; + year_ones = year_tens % 10; + year_tens /= 10; + year_hundreds = (year - 1000) / 100; + + rtc.data[6] = days % 10; + rtc.data[7] = days / 10; + rtc.data[8] = month; + rtc.data[9] = year_ones; + rtc.data[10] = year_tens; + rtc.data[11] = year_hundreds; + rtc.data[12] = S9xSRTCComputeDayOfWeek (); + } + + rtc.data[0] = seconds % 10; + rtc.data[1] = seconds / 10; + rtc.data[2] = minutes % 10; + rtc.data[3] = minutes / 10; + rtc.data[4] = hours % 10; + rtc.data[5] = hours / 10; + + return; + } + } +} + + +/**********************************************************************************************/ +/* S9xSetSRTC() */ +/* This function sends data to the S-RTC used in Dai Kaijyu Monogatari II */ +/**********************************************************************************************/ +void S9xSetSRTC (uint8 data, uint16 Address) +{ + + data &= 0x0F; // Data is only 4-bits, mask out unused bits. + + if( data >= 0xD ) + { + // It's an RTC command + + switch ( data ) + { + case 0xD: + rtc.mode = MODE_READ; + rtc.index = -1; + break; + + case 0xE: + rtc.mode = MODE_COMMAND; + break; + + default: + // Ignore the write if it's an 0xF ??? + // Probably should switch back to read mode -- but this + // sequence never occurs in DKJM2 + break; + } + + return; + } + + if ( rtc.mode == MODE_LOAD_RTC ) + { + if ( (rtc.index >= 0) || (rtc.index < MAX_RTC_INDEX) ) + { + rtc.data[rtc.index++] = data; + + if ( rtc.index == MAX_RTC_INDEX ) + { + // We have all the data for the RTC load + + rtc.system_timestamp = time (NULL); // Get local system time + + // Get the day of the week + rtc.data[rtc.index++] = S9xSRTCComputeDayOfWeek (); + + // Start RTC counting again + rtc.count_enable = TRUE; + rtc.needs_init = FALSE; + } + + return; + } + else + { + // Attempting to write too much data + // error(); // ignore?? + } + } + else if ( rtc.mode == MODE_COMMAND ) + { + switch( data ) + { + case COMMAND_CLEAR_RTC: + // Disable RTC counter + rtc.count_enable = FALSE; + + ZeroMemory (rtc.data, MAX_RTC_INDEX+1); + rtc.index = -1; + rtc.mode = MODE_COMMAND_DONE; + break; + + case COMMAND_LOAD_RTC: + // Disable RTC counter + rtc.count_enable = FALSE; + + rtc.index = 0; // Setup for writing + rtc.mode = MODE_LOAD_RTC; + break; + + default: + rtc.mode = MODE_COMMAND_DONE; + // unrecognized command - need to implement. + } + + return; + } + else + { + if ( rtc.mode == MODE_READ ) + { + // Attempting to write while in read mode. Ignore. + } + + if ( rtc.mode == MODE_COMMAND_DONE ) + { + // Maybe this isn't an error. Maybe we should kick off + // a new E command. But is this valid? + } + } +} + +/**********************************************************************************************/ +/* S9xGetSRTC() */ +/* This function retrieves data from the S-RTC */ +/**********************************************************************************************/ +uint8 S9xGetSRTC (uint16 Address) +{ + if ( rtc.mode == MODE_READ ) + { + if ( rtc.index < 0 ) + { + S9xUpdateSrtcTime (); // Only update it if the game reads it + rtc.index++; + return ( 0x0f ); // Send start marker. + } + else if (rtc.index > MAX_RTC_INDEX) + { + rtc.index = -1; // Setup for next set of reads + return ( 0x0f ); // Data done marker. + } + else + { + // Feed out the data + return rtc.data[rtc.index++]; + } + } + else + { + return 0x0; + } +} + +void S9xSRTCPreSaveState () +{ + if (Settings.SRTC) + { + S9xUpdateSrtcTime (); + + int s = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + if (s > 0x20000) + s = 0x20000; + + SRAM [s + 0] = rtc.needs_init; + SRAM [s + 1] = rtc.count_enable; + memmove (&SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1); + SRAM [s + 3 + MAX_RTC_INDEX] = rtc.index; + SRAM [s + 4 + MAX_RTC_INDEX] = rtc.mode; + +#ifdef LSB_FIRST + memmove (&SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8); +#else + SRAM [s + 5 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 0); + SRAM [s + 6 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 8); + SRAM [s + 7 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 16); + SRAM [s + 8 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 24); + SRAM [s + 9 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 32); + SRAM [s + 10 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 40); + SRAM [s + 11 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 48); + SRAM [s + 12 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 56); +#endif + } +} + +void S9xSRTCPostLoadState () +{ + if (Settings.SRTC) + { + int s = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + if (s > 0x20000) + s = 0x20000; + + rtc.needs_init = SRAM [s + 0]; + rtc.count_enable = SRAM [s + 1]; + memmove (rtc.data, &SRAM [s + 2], MAX_RTC_INDEX + 1); + rtc.index = SRAM [s + 3 + MAX_RTC_INDEX]; + rtc.mode = SRAM [s + 4 + MAX_RTC_INDEX]; + +#ifdef LSB_FIRST + memmove (&rtc.system_timestamp, &SRAM [s + 5 + MAX_RTC_INDEX], 8); +#else + rtc.system_timestamp |= (SRAM [s + 5 + MAX_RTC_INDEX] << 0); + rtc.system_timestamp |= (SRAM [s + 6 + MAX_RTC_INDEX] << 8); + rtc.system_timestamp |= (SRAM [s + 7 + MAX_RTC_INDEX] << 16); + rtc.system_timestamp |= (SRAM [s + 8 + MAX_RTC_INDEX] << 24); + rtc.system_timestamp |= (SRAM [s + 9 + MAX_RTC_INDEX] << 32); + rtc.system_timestamp |= (SRAM [s + 10 + MAX_RTC_INDEX] << 40); + rtc.system_timestamp |= (SRAM [s + 11 + MAX_RTC_INDEX] << 48); + rtc.system_timestamp |= (SRAM [s + 12 + MAX_RTC_INDEX] << 56); +#endif + S9xUpdateSrtcTime (); + } +} diff --git a/src/srtc.cpp b/src/srtc.cpp deleted file mode 100644 index be390f0..0000000 --- a/src/srtc.cpp +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include -#include "snes9x.h" -#include "srtc.h" -#include "memmap.h" - -/*** The format of the rtc_data structure is: - -Index Description Range (nibble) ------ -------------- --------------------------------------- - - 0 Seconds low 0-9 - 1 Seconds high 0-5 - - 2 Minutes low 0-9 - 3 Minutes high 0-5 - - 4 Hour low 0-9 - 5 Hour high 0-2 - - 6 Day low 0-9 - 7 Day high 0-3 - - 8 Month 1-C (0xC is December, 12th month) - - 9 Year ones 0-9 - A Year tens 0-9 - B Year High 9-B (9=19xx, A=20xx, B=21xx) - - C Day of week 0-6 (0=Sunday, 1=Monday,...,6=Saturday) - -***/ - -SRTC_DATA rtc; - - -static int month_keys[12] = { 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6 }; - - -/********************************************************************************************* - * - * Note, if you are doing a save state for this game: - * - * On save: - * - * Call S9xUpdateSrtcTime and save the rtc data structure. - * - * On load: - * - * restore the rtc data structure - * rtc.system_timestamp = time (NULL); - * - * - *********************************************************************************************/ - - -void S9xResetSRTC () -{ - rtc.index = -1; - rtc.mode = MODE_READ; -} - -void S9xHardResetSRTC () -{ - ZeroMemory (&rtc, sizeof (rtc)); - rtc.index = -1; - rtc.mode = MODE_READ; - rtc.count_enable = FALSE; - rtc.needs_init = TRUE; - - // Get system timestamp - rtc.system_timestamp = time (NULL); -} - -/**********************************************************************************************/ -/* S9xSRTCComputeDayOfWeek() */ -/* Return 0-6 for Sunday-Saturday */ -/**********************************************************************************************/ -unsigned int S9xSRTCComputeDayOfWeek () -{ - unsigned year = rtc.data[10]*10 + rtc.data[9]; - unsigned month = rtc.data[8]; - unsigned day = rtc.data[7]*10 + rtc.data[6]; - unsigned day_of_week; - - year += (rtc.data[11] - 9) * 100; - - // Range check the month for valid array indicies - if ( month > 12 ) - month = 1; - - day_of_week = year + (year / 4) + month_keys[month-1] + day - 1; - - if(( year % 4 == 0 ) && ( month <= 2 ) ) - day_of_week--; - - day_of_week %= 7; - - return day_of_week; -} - - -/**********************************************************************************************/ -/* S9xSRTCDaysInMonth() */ -/* Return the number of days in a specific month for a certain year */ -/**********************************************************************************************/ -int S9xSRTCDaysInMmonth( int month, int year ) -{ - int mdays; - - switch ( month ) - { - case 2: - if ( ( year % 4 == 0 ) ) // DKJM2 only uses 199x - 22xx - mdays = 29; - else - mdays = 28; - break; - - case 4: - case 6: - case 9: - case 11: - mdays = 30; - break; - - default: // months 1,3,5,7,8,10,12 - mdays = 31; - break; - } - - return mdays; -} - - -#define DAYTICKS (60*60*24) -#define HOURTICKS (60*60) -#define MINUTETICKS 60 - - -/**********************************************************************************************/ -/* S9xUpdateSrtcTime() */ -/* Advance the S-RTC time if counting is enabled */ -/**********************************************************************************************/ -void S9xUpdateSrtcTime () -{ - time_t cur_systime; - long time_diff; - - // Keep track of game time by computing the number of seconds that pass on the system - // clock and adding the same number of seconds to the S-RTC clock structure. - // I originally tried using mktime and localtime library functions to keep track - // of time but some of the GNU time functions fail when the year goes to 2099 - // (and maybe less) and this would have caused a bug with DKJM2 so I'm doing - // it this way to get around that problem. - - // Note: Dai Kaijyu Monogatari II only allows dates in the range 1996-21xx. - - if (rtc.count_enable && !rtc.needs_init) - { - cur_systime = time (NULL); - - // This method assumes one time_t clock tick is one second - // which should work on PCs and GNU systems. - // If your tick interval is different adjust the - // DAYTICK, HOURTICK, and MINUTETICK defines - - time_diff = (long) (cur_systime - rtc.system_timestamp); - rtc.system_timestamp = cur_systime; - - if ( time_diff > 0 ) - { - int seconds; - int minutes; - int hours; - int days; - int month; - int year; - int temp_days; - - int year_hundreds; - int year_tens; - int year_ones; - - - if ( time_diff > DAYTICKS ) - { - days = time_diff / DAYTICKS; - time_diff = time_diff - days * DAYTICKS; - } - else - { - days = 0; - } - - if ( time_diff > HOURTICKS ) - { - hours = time_diff / HOURTICKS; - time_diff = time_diff - hours * HOURTICKS; - } - else - { - hours = 0; - } - - if ( time_diff > MINUTETICKS ) - { - minutes = time_diff / MINUTETICKS; - time_diff = time_diff - minutes * MINUTETICKS; - } - else - { - minutes = 0; - } - - if ( time_diff > 0 ) - { - seconds = time_diff; - } - else - { - seconds = 0; - } - - - seconds += (rtc.data[1]*10 + rtc.data[0]); - if ( seconds >= 60 ) - { - seconds -= 60; - minutes += 1; - } - - minutes += (rtc.data[3]*10 + rtc.data[2]); - if ( minutes >= 60 ) - { - minutes -= 60; - hours += 1; - } - - hours += (rtc.data[5]*10 + rtc.data[4]); - if ( hours >= 24 ) - { - hours -= 24; - days += 1; - } - - if ( days > 0 ) - { - year = rtc.data[10]*10 + rtc.data[9]; - year += ( 1000 + rtc.data[11] * 100 ); - - month = rtc.data[8]; - days += (rtc.data[7]*10 + rtc.data[6]); - while ( days > (temp_days = S9xSRTCDaysInMmonth( month, year )) ) - { - days -= temp_days; - month += 1; - if ( month > 12 ) - { - year += 1; - month = 1; - } - } - - year_tens = year % 100; - year_ones = year_tens % 10; - year_tens /= 10; - year_hundreds = (year - 1000) / 100; - - rtc.data[6] = days % 10; - rtc.data[7] = days / 10; - rtc.data[8] = month; - rtc.data[9] = year_ones; - rtc.data[10] = year_tens; - rtc.data[11] = year_hundreds; - rtc.data[12] = S9xSRTCComputeDayOfWeek (); - } - - rtc.data[0] = seconds % 10; - rtc.data[1] = seconds / 10; - rtc.data[2] = minutes % 10; - rtc.data[3] = minutes / 10; - rtc.data[4] = hours % 10; - rtc.data[5] = hours / 10; - - return; - } - } -} - - -/**********************************************************************************************/ -/* S9xSetSRTC() */ -/* This function sends data to the S-RTC used in Dai Kaijyu Monogatari II */ -/**********************************************************************************************/ -void S9xSetSRTC (uint8 data, uint16 Address) -{ - - data &= 0x0F; // Data is only 4-bits, mask out unused bits. - - if( data >= 0xD ) - { - // It's an RTC command - - switch ( data ) - { - case 0xD: - rtc.mode = MODE_READ; - rtc.index = -1; - break; - - case 0xE: - rtc.mode = MODE_COMMAND; - break; - - default: - // Ignore the write if it's an 0xF ??? - // Probably should switch back to read mode -- but this - // sequence never occurs in DKJM2 - break; - } - - return; - } - - if ( rtc.mode == MODE_LOAD_RTC ) - { - if ( (rtc.index >= 0) || (rtc.index < MAX_RTC_INDEX) ) - { - rtc.data[rtc.index++] = data; - - if ( rtc.index == MAX_RTC_INDEX ) - { - // We have all the data for the RTC load - - rtc.system_timestamp = time (NULL); // Get local system time - - // Get the day of the week - rtc.data[rtc.index++] = S9xSRTCComputeDayOfWeek (); - - // Start RTC counting again - rtc.count_enable = TRUE; - rtc.needs_init = FALSE; - } - - return; - } - else - { - // Attempting to write too much data - // error(); // ignore?? - } - } - else if ( rtc.mode == MODE_COMMAND ) - { - switch( data ) - { - case COMMAND_CLEAR_RTC: - // Disable RTC counter - rtc.count_enable = FALSE; - - ZeroMemory (rtc.data, MAX_RTC_INDEX+1); - rtc.index = -1; - rtc.mode = MODE_COMMAND_DONE; - break; - - case COMMAND_LOAD_RTC: - // Disable RTC counter - rtc.count_enable = FALSE; - - rtc.index = 0; // Setup for writing - rtc.mode = MODE_LOAD_RTC; - break; - - default: - rtc.mode = MODE_COMMAND_DONE; - // unrecognized command - need to implement. - } - - return; - } - else - { - if ( rtc.mode == MODE_READ ) - { - // Attempting to write while in read mode. Ignore. - } - - if ( rtc.mode == MODE_COMMAND_DONE ) - { - // Maybe this isn't an error. Maybe we should kick off - // a new E command. But is this valid? - } - } -} - -/**********************************************************************************************/ -/* S9xGetSRTC() */ -/* This function retrieves data from the S-RTC */ -/**********************************************************************************************/ -uint8 S9xGetSRTC (uint16 Address) -{ - if ( rtc.mode == MODE_READ ) - { - if ( rtc.index < 0 ) - { - S9xUpdateSrtcTime (); // Only update it if the game reads it - rtc.index++; - return ( 0x0f ); // Send start marker. - } - else if (rtc.index > MAX_RTC_INDEX) - { - rtc.index = -1; // Setup for next set of reads - return ( 0x0f ); // Data done marker. - } - else - { - // Feed out the data - return rtc.data[rtc.index++]; - } - } - else - { - return 0x0; - } -} - -void S9xSRTCPreSaveState () -{ - if (Settings.SRTC) - { - S9xUpdateSrtcTime (); - - int s = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; - if (s > 0x20000) - s = 0x20000; - - SRAM [s + 0] = rtc.needs_init; - SRAM [s + 1] = rtc.count_enable; - memmove (&SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1); - SRAM [s + 3 + MAX_RTC_INDEX] = rtc.index; - SRAM [s + 4 + MAX_RTC_INDEX] = rtc.mode; - -#ifdef LSB_FIRST - memmove (&SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8); -#else - SRAM [s + 5 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 0); - SRAM [s + 6 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 8); - SRAM [s + 7 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 16); - SRAM [s + 8 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 24); - SRAM [s + 9 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 32); - SRAM [s + 10 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 40); - SRAM [s + 11 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 48); - SRAM [s + 12 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 56); -#endif - } -} - -void S9xSRTCPostLoadState () -{ - if (Settings.SRTC) - { - int s = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; - if (s > 0x20000) - s = 0x20000; - - rtc.needs_init = SRAM [s + 0]; - rtc.count_enable = SRAM [s + 1]; - memmove (rtc.data, &SRAM [s + 2], MAX_RTC_INDEX + 1); - rtc.index = SRAM [s + 3 + MAX_RTC_INDEX]; - rtc.mode = SRAM [s + 4 + MAX_RTC_INDEX]; - -#ifdef LSB_FIRST - memmove (&rtc.system_timestamp, &SRAM [s + 5 + MAX_RTC_INDEX], 8); -#else - rtc.system_timestamp |= (SRAM [s + 5 + MAX_RTC_INDEX] << 0); - rtc.system_timestamp |= (SRAM [s + 6 + MAX_RTC_INDEX] << 8); - rtc.system_timestamp |= (SRAM [s + 7 + MAX_RTC_INDEX] << 16); - rtc.system_timestamp |= (SRAM [s + 8 + MAX_RTC_INDEX] << 24); - rtc.system_timestamp |= (SRAM [s + 9 + MAX_RTC_INDEX] << 32); - rtc.system_timestamp |= (SRAM [s + 10 + MAX_RTC_INDEX] << 40); - rtc.system_timestamp |= (SRAM [s + 11 + MAX_RTC_INDEX] << 48); - rtc.system_timestamp |= (SRAM [s + 12 + MAX_RTC_INDEX] << 56); -#endif - S9xUpdateSrtcTime (); - } -} diff --git a/src/tile.c b/src/tile.c new file mode 100644 index 0000000..b1e53d1 --- /dev/null +++ b/src/tile.c @@ -0,0 +1,1346 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ +#include "snes9x.h" + +#include "memmap.h" +#include "ppu.h" +#include "display.h" +#include "gfx.h" +#include "tile.h" + +extern uint32 HeadMask [4]; +extern uint32 TailMask [5]; + +uint8 ConvertTile (uint8 *pCache, uint32 TileAddr) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + uint32 p1; + uint32 p2; + register uint8 pix; + + switch (BG.BitShift) + { + case 8: + for (line = 8; line != 0; line--, tp += 2) + { + p1 = p2 = 0; + if ((pix = *(tp + 0))) + { + p1 |= odd_high[0][pix >> 4]; + p2 |= odd_low[0][pix & 0xf]; + } + if ((pix = *(tp + 1))) + { + p1 |= even_high[0][pix >> 4]; + p2 |= even_low[0][pix & 0xf]; + } + if ((pix = *(tp + 16))) + { + p1 |= odd_high[1][pix >> 4]; + p2 |= odd_low[1][pix & 0xf]; + } + if ((pix = *(tp + 17))) + { + p1 |= even_high[1][pix >> 4]; + p2 |= even_low[1][pix & 0xf]; + } + if ((pix = *(tp + 32))) + { + p1 |= odd_high[2][pix >> 4]; + p2 |= odd_low[2][pix & 0xf]; + } + if ((pix = *(tp + 33))) + { + p1 |= even_high[2][pix >> 4]; + p2 |= even_low[2][pix & 0xf]; + } + if ((pix = *(tp + 48))) + { + p1 |= odd_high[3][pix >> 4]; + p2 |= odd_low[3][pix & 0xf]; + } + if ((pix = *(tp + 49))) + { + p1 |= even_high[3][pix >> 4]; + p2 |= even_low[3][pix & 0xf]; + } + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + break; + + case 4: + for (line = 8; line != 0; line--, tp += 2) + { + p1 = p2 = 0; + if ((pix = *(tp + 0))) + { + p1 |= odd_high[0][pix >> 4]; + p2 |= odd_low[0][pix & 0xf]; + } + if ((pix = *(tp + 1))) + { + p1 |= even_high[0][pix >> 4]; + p2 |= even_low[0][pix & 0xf]; + } + if ((pix = *(tp + 16))) + { + p1 |= odd_high[1][pix >> 4]; + p2 |= odd_low[1][pix & 0xf]; + } + if ((pix = *(tp + 17))) + { + p1 |= even_high[1][pix >> 4]; + p2 |= even_low[1][pix & 0xf]; + } + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + break; + + case 2: + for (line = 8; line != 0; line--, tp += 2) + { + p1 = p2 = 0; + if ((pix = *(tp + 0))) + { + p1 |= odd_high[0][pix >> 4]; + p2 |= odd_low[0][pix & 0xf]; + } + if ((pix = *(tp + 1))) + { + p1 |= even_high[0][pix >> 4]; + p2 |= even_low[0][pix & 0xf]; + } + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + break; + } + return (non_zero ? TRUE : BLANK_TILE); +} + +static INLINE void WRITE_4PIXELS (uint32 Offset, uint8 *Pixels) +{ + register uint8 Pixel; + uint8 *Screen = GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ + { \ + Screen [N] = (uint8) GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS_FLIPPED (uint32 Offset, uint8 *Pixels) +{ + register uint8 Pixel; + uint8 *Screen = GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ + { \ + Screen [N] = (uint8) GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +inline void WRITE_4PIXELSHI16 (uint32 Offset, uint8 *Pixels) +{ + uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[2*N])) \ + { \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +inline void WRITE_4PIXELSHI16_FLIPPED (uint32 Offset, uint8 *Pixels) +{ + uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[6 - 2*N])) \ + { \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELSx2 (uint32 Offset, uint8 *Pixels) +{ + register uint8 Pixel; + uint8 *Screen = GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [0] && (Pixel = Pixels[N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS_FLIPPEDx2 (uint32 Offset, uint8 *Pixels) +{ + register uint8 Pixel; + uint8 *Screen = GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELSx2x2 (uint32 Offset, uint8 *Pixels) +{ + register uint8 Pixel; + uint8 *Screen = GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = Screen [GFX_PITCH + N * 2] = \ + Screen [GFX_PITCH + N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = Depth [GFX_PITCH + N * 2] = \ + Depth [GFX_PITCH + N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS_FLIPPEDx2x2 (uint32 Offset, uint8 *Pixels) +{ + register uint8 Pixel; + uint8 *Screen = GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = Screen [GFX_PITCH + N * 2] = \ + Screen [GFX_PITCH + N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = Depth [GFX_PITCH + N * 2] = \ + Depth [GFX_PITCH + N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +void DrawTile (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS, WRITE_4PIXELS_FLIPPED, 4) +} + +void DrawClippedTile (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS, WRITE_4PIXELS_FLIPPED, 4) +} + +void DrawTilex2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELSx2, WRITE_4PIXELS_FLIPPEDx2, 8) +} + +void DrawClippedTilex2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELSx2, WRITE_4PIXELS_FLIPPEDx2, 8) +} + +void DrawTilex2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELSx2x2, WRITE_4PIXELS_FLIPPEDx2x2, 8) +} + +void DrawClippedTilex2x2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELSx2x2, WRITE_4PIXELS_FLIPPEDx2x2, 8) +} + +void DrawLargePixel (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint8 *sp = GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + uint8 pixel; +#define PLOT_PIXEL(screen, pixel) (pixel) + + RENDER_TILE_LARGE (((uint8) GFX.ScreenColors [pixel]), PLOT_PIXEL) +} + +static INLINE void WRITE_4PIXELS16 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ + { \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPED (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ + { \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS16x2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPEDx2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS16x2x2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX_PITCH >> 1) + N * 2] = \ + Screen [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX_PITCH >> 1) + N * 2] = \ + Depth [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPEDx2x2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX_PITCH >> 1) + N * 2] = \ + Screen [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX_PITCH >> 1) + N * 2] = \ + Depth [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +void DrawTile16_OBJ (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) +{ +// TILE_PREAMBLE + + uint8 *pCache; + uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << 5); + if (Tile & 0x100){ + TileAddr += BG.NameSelect; + } + + TileAddr &= 0xffff; + + uint32 TileNumber; + pCache = &BG.Buffer[(TileNumber = (TileAddr >> 5)) << 6]; + + if (!BG.Buffered [TileNumber]){ + BG.Buffered[TileNumber] = ConvertTile (pCache, TileAddr); + } + + if (BG.Buffered [TileNumber] == BLANK_TILE){ + TileBlank = Tile & 0xFFFFFFFF; + return; + } + + GFX.ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & 7) << 4) + 128]; + + register uint8* bp; + register int inc; + + if (Tile & V_FLIP){ + bp = pCache + 56 - StartLine; + inc = -8; + } else { + bp = pCache + StartLine; + inc = 8; + } + + uint16* Screen = (uint16 *) GFX.S + Offset; + uint16* Colors = GFX.ScreenColors; + uint8* Depth = GFX.DB + Offset; + int GFX_Z1 = GFX.Z1; + int GFX_Z2 = GFX.Z2; + + if (!(Tile & H_FLIP)){ +#define FN(N) \ + if (GFX_Z1 > Depth[N] && bp[N]){ \ + Screen[N] = Colors[bp[N]]; \ + Depth[N] = GFX_Z2; \ + } + while ( LineCount-- ){ + if ( *(uint32*)bp ){ + FN(0); FN(1); FN(2); FN(3); + } + + if ( *(uint32 *)(bp + 4) ){ + FN(4); FN(5); FN(6); FN(7); + } + bp += inc; + Screen += GFX_PPL; + Depth += GFX_PPL; + } +#undef FN + } else { +#define FN(N, B) \ + if (GFX_Z1 > Depth[N] && bp[B]){ \ + Screen[N] = Colors[bp[B]]; \ + Depth[N] = GFX_Z2; \ + } + while ( LineCount-- ){ + if ( *(uint32 *)(bp + 4) ){ + FN(0, 7); FN(1, 6); FN(2, 5); FN(3, 4); + } + + if ( *(uint32*)bp ){ + FN(4, 3); FN(5, 2); FN(6, 1); FN(7, 0); + } + bp += inc; + Screen += GFX_PPL; + Depth += GFX_PPL; + } +#undef FN + } +} + +void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) +{ +// TILE_PREAMBLE + + uint8 *pCache; + uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); + + TileAddr &= 0xffff; + + uint32 TileNumber; + pCache = &BG.Buffer[(TileNumber = (TileAddr >> BG.TileShift)) << 6]; + + if (!BG.Buffered [TileNumber]){ + BG.Buffered[TileNumber] = ConvertTile (pCache, TileAddr); + } + + if (BG.Buffered [TileNumber] == BLANK_TILE) + { + TileBlank = Tile & 0xFFFFFFFF; + return; + } + + if (BG.DirectColourMode){ + if (IPPU.DirectColourMapsNeedRebuild){ + S9xBuildDirectColourMaps (); + } + GFX.ScreenColors = DirectColourMaps [(Tile >> 10) & BG.PaletteMask]; + } else { + GFX.ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & BG.PaletteMask) << BG.PaletteShift) + BG.StartPalette]; + } + + register uint8* bp; + register int inc; + + if (Tile & V_FLIP){ + bp = pCache + 56 - StartLine; + inc = -8; + } else { + bp = pCache + StartLine; + inc = 8; + } + + uint16* Screen = (uint16 *) GFX.S + Offset; + uint16* Colors = GFX.ScreenColors; + uint8* Depth = GFX.DB + Offset; + int GFX_Z1 = GFX.Z1; +// int GFX_Z2 = GFX.Z2; + + if (!(Tile & H_FLIP)){ +#define FN(N) \ + if (GFX_Z1 > Depth[N] && bp[N]){ \ + Screen[N] = Colors[bp[N]]; \ + Depth[N] = GFX_Z1; \ + } + while ( LineCount-- ){ + if ( *(uint32*)bp ){ + FN(0); FN(1); FN(2); FN(3); + } + + if ( *(uint32 *)(bp + 4) ){ + FN(4); FN(5); FN(6); FN(7); + } + bp += inc; + Screen += GFX_PPL; + Depth += GFX_PPL; + } +#undef FN + } else { +#define FN(N, B) \ + if (GFX_Z1 > Depth[N] && bp[B]){ \ + Screen[N] = Colors[bp[B]]; \ + Depth[N] = GFX_Z1; \ + } + while ( LineCount-- ){ + if ( *(uint32 *)(bp + 4) ){ + FN(0, 7); FN(1, 6); FN(2, 5); FN(3, 4); + } + + if ( *(uint32*)bp ){ + FN(4, 3); FN(5, 2); FN(6, 1); FN(7, 0); + } + bp += inc; + Screen += GFX_PPL; + Depth += GFX_PPL; + } +#undef FN + } +} + +void DrawClippedTile16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4) +} + +void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) +} + +void DrawClippedTile16x2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) +} + +void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) +} + +void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) +} + +void DrawLargePixel16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + uint16 pixel; + + RENDER_TILE_LARGE (GFX.ScreenColors [pixel], PLOT_PIXEL) +} + +static INLINE void WRITE_4PIXELS16_ADD (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ + { \ + if (SubDepth [N]) \ + { \ + if (SubDepth [N] != 1) \ + Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ + Screen [GFX.Delta + N]); \ + else \ + Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ + GFX.FixedColour); \ + } \ + else \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPED_ADD (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ + { \ + if (SubDepth [N]) \ + { \ + if (SubDepth [N] != 1) \ + Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ + Screen [GFX.Delta + N]); \ + else \ + Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ + GFX.FixedColour); \ + } \ + else \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +static INLINE void WRITE_4PIXELS16_ADD1_2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ + { \ + if (SubDepth [N]) \ + { \ + if (SubDepth [N] != 1) \ + Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \ + Screen [GFX.Delta + N])); \ + else \ + Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ + GFX.FixedColour); \ + } \ + else \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPED_ADD1_2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ + { \ + if (SubDepth [N]) \ + { \ + if (SubDepth [N] != 1) \ + Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \ + Screen [GFX.Delta + N])); \ + else \ + Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ + GFX.FixedColour); \ + } \ + else \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +static INLINE void WRITE_4PIXELS16_SUB (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ + { \ + if (SubDepth [N]) \ + { \ + if (SubDepth [N] != 1) \ + Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ + Screen [GFX.Delta + N]); \ + else \ + Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ + GFX.FixedColour); \ + } \ + else \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPED_SUB (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ + { \ + if (SubDepth [N]) \ + { \ + if (SubDepth [N] != 1) \ + Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ + Screen [GFX.Delta + N]); \ + else \ + Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ + GFX.FixedColour); \ + } \ + else \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +static INLINE void WRITE_4PIXELS16_SUB1_2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ + { \ + if (SubDepth [N]) \ + { \ + if (SubDepth [N] != 1) \ + Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \ + Screen [GFX.Delta + N]); \ + else \ + Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ + GFX.FixedColour); \ + } \ + else \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPED_SUB1_2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ + { \ + if (SubDepth [N]) \ + { \ + if (SubDepth [N] != 1) \ + Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \ + Screen [GFX.Delta + N]); \ + else \ + Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ + GFX.FixedColour); \ + } \ + else \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + + +void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4) +} + +void DrawClippedTile16Add (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4) +} + +void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4) +} + +void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4) +} + +void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4) +} + +void DrawClippedTile16Sub (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4) +} + +void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4) +} + +void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4) +} + +static INLINE void WRITE_4PIXELS16_ADDF1_2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ + { \ + if (SubDepth [N] == 1) \ + Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \ + GFX.FixedColour)); \ + else \ + Screen [N] = GFX.ScreenColors [Pixel];\ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPED_ADDF1_2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ + { \ + if (SubDepth [N] == 1) \ + Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \ + GFX.FixedColour)); \ + else \ + Screen [N] = GFX.ScreenColors [Pixel];\ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +static INLINE void WRITE_4PIXELS16_SUBF1_2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ + { \ + if (SubDepth [N] == 1) \ + Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \ + GFX.FixedColour); \ + else \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPED_SUBF1_2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint8 *SubDepth = GFX.SubZBuffer + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ + { \ + if (SubDepth [N] == 1) \ + Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \ + GFX.FixedColour); \ + else \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) + +#undef FN +} + +void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4) +} + +void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADDF1_2, + WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4) +} + +void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) +} + +void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, + WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) +} + +void DrawLargePixel16Add (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + register uint16 pixel; + +#define LARGE_ADD_PIXEL(s, p) \ +(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_ADD (p, *(s + GFX.Delta)) : \ + COLOR_ADD (p, GFX.FixedColour)) \ + : p) + + RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL) +} + +void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + register uint16 pixel; + +#define LARGE_ADD_PIXEL1_2(s, p) \ +((uint16) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_ADD1_2 (p, *(s + GFX.Delta)) : \ + COLOR_ADD (p, GFX.FixedColour)) \ + : p)) + + RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL1_2) +} + +void DrawLargePixel16Sub (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + register uint16 pixel; + +#define LARGE_SUB_PIXEL(s, p) \ +(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_SUB (p, *(s + GFX.Delta)) : \ + COLOR_SUB (p, GFX.FixedColour)) \ + : p) + + RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL) +} + +void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint16 pixel; + +#define LARGE_SUB_PIXEL1_2(s, p) \ +(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_SUB1_2 (p, *(s + GFX.Delta)) : \ + COLOR_SUB (p, GFX.FixedColour)) \ + : p) + + RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL1_2) +} + +void DrawHiResTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4) +} + +void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4) +} diff --git a/src/tile.cpp b/src/tile.cpp deleted file mode 100644 index 34735a7..0000000 --- a/src/tile.cpp +++ /dev/null @@ -1,1346 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ -#include "snes9x.h" - -#include "memmap.h" -#include "ppu.h" -#include "display.h" -#include "gfx.h" -#include "tile.h" - -extern uint32 HeadMask [4]; -extern uint32 TailMask [5]; - -uint8 ConvertTile (uint8 *pCache, uint32 TileAddr) -{ - register uint8 *tp = &Memory.VRAM[TileAddr]; - uint32 *p = (uint32 *) pCache; - uint32 non_zero = 0; - uint8 line; - uint32 p1; - uint32 p2; - register uint8 pix; - - switch (BG.BitShift) - { - case 8: - for (line = 8; line != 0; line--, tp += 2) - { - p1 = p2 = 0; - if ((pix = *(tp + 0))) - { - p1 |= odd_high[0][pix >> 4]; - p2 |= odd_low[0][pix & 0xf]; - } - if ((pix = *(tp + 1))) - { - p1 |= even_high[0][pix >> 4]; - p2 |= even_low[0][pix & 0xf]; - } - if ((pix = *(tp + 16))) - { - p1 |= odd_high[1][pix >> 4]; - p2 |= odd_low[1][pix & 0xf]; - } - if ((pix = *(tp + 17))) - { - p1 |= even_high[1][pix >> 4]; - p2 |= even_low[1][pix & 0xf]; - } - if ((pix = *(tp + 32))) - { - p1 |= odd_high[2][pix >> 4]; - p2 |= odd_low[2][pix & 0xf]; - } - if ((pix = *(tp + 33))) - { - p1 |= even_high[2][pix >> 4]; - p2 |= even_low[2][pix & 0xf]; - } - if ((pix = *(tp + 48))) - { - p1 |= odd_high[3][pix >> 4]; - p2 |= odd_low[3][pix & 0xf]; - } - if ((pix = *(tp + 49))) - { - p1 |= even_high[3][pix >> 4]; - p2 |= even_low[3][pix & 0xf]; - } - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - break; - - case 4: - for (line = 8; line != 0; line--, tp += 2) - { - p1 = p2 = 0; - if ((pix = *(tp + 0))) - { - p1 |= odd_high[0][pix >> 4]; - p2 |= odd_low[0][pix & 0xf]; - } - if ((pix = *(tp + 1))) - { - p1 |= even_high[0][pix >> 4]; - p2 |= even_low[0][pix & 0xf]; - } - if ((pix = *(tp + 16))) - { - p1 |= odd_high[1][pix >> 4]; - p2 |= odd_low[1][pix & 0xf]; - } - if ((pix = *(tp + 17))) - { - p1 |= even_high[1][pix >> 4]; - p2 |= even_low[1][pix & 0xf]; - } - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - break; - - case 2: - for (line = 8; line != 0; line--, tp += 2) - { - p1 = p2 = 0; - if ((pix = *(tp + 0))) - { - p1 |= odd_high[0][pix >> 4]; - p2 |= odd_low[0][pix & 0xf]; - } - if ((pix = *(tp + 1))) - { - p1 |= even_high[0][pix >> 4]; - p2 |= even_low[0][pix & 0xf]; - } - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - break; - } - return (non_zero ? TRUE : BLANK_TILE); -} - -INLINE void WRITE_4PIXELS (uint32 Offset, uint8 *Pixels) -{ - register uint8 Pixel; - uint8 *Screen = GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ - { \ - Screen [N] = (uint8) GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS_FLIPPED (uint32 Offset, uint8 *Pixels) -{ - register uint8 Pixel; - uint8 *Screen = GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ - { \ - Screen [N] = (uint8) GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -inline void WRITE_4PIXELSHI16 (uint32 Offset, uint8 *Pixels) -{ - uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[2*N])) \ - { \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -inline void WRITE_4PIXELSHI16_FLIPPED (uint32 Offset, uint8 *Pixels) -{ - uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[6 - 2*N])) \ - { \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELSx2 (uint32 Offset, uint8 *Pixels) -{ - register uint8 Pixel; - uint8 *Screen = GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [0] && (Pixel = Pixels[N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS_FLIPPEDx2 (uint32 Offset, uint8 *Pixels) -{ - register uint8 Pixel; - uint8 *Screen = GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELSx2x2 (uint32 Offset, uint8 *Pixels) -{ - register uint8 Pixel; - uint8 *Screen = GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = Screen [GFX_PITCH + N * 2] = \ - Screen [GFX_PITCH + N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = Depth [GFX_PITCH + N * 2] = \ - Depth [GFX_PITCH + N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS_FLIPPEDx2x2 (uint32 Offset, uint8 *Pixels) -{ - register uint8 Pixel; - uint8 *Screen = GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = Screen [GFX_PITCH + N * 2] = \ - Screen [GFX_PITCH + N * 2 + 1] = (uint8) GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = Depth [GFX_PITCH + N * 2] = \ - Depth [GFX_PITCH + N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -void DrawTile (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS, WRITE_4PIXELS_FLIPPED, 4) -} - -void DrawClippedTile (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS, WRITE_4PIXELS_FLIPPED, 4) -} - -void DrawTilex2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELSx2, WRITE_4PIXELS_FLIPPEDx2, 8) -} - -void DrawClippedTilex2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELSx2, WRITE_4PIXELS_FLIPPEDx2, 8) -} - -void DrawTilex2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELSx2x2, WRITE_4PIXELS_FLIPPEDx2x2, 8) -} - -void DrawClippedTilex2x2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELSx2x2, WRITE_4PIXELS_FLIPPEDx2x2, 8) -} - -void DrawLargePixel (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint8 *sp = GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - uint8 pixel; -#define PLOT_PIXEL(screen, pixel) (pixel) - - RENDER_TILE_LARGE (((uint8) GFX.ScreenColors [pixel]), PLOT_PIXEL) -} - -INLINE void WRITE_4PIXELS16 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ - { \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPED (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ - { \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS16x2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPEDx2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS16x2x2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX_PITCH >> 1) + N * 2] = \ - Screen [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX_PITCH >> 1) + N * 2] = \ - Depth [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPEDx2x2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX_PITCH >> 1) + N * 2] = \ - Screen [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX_PITCH >> 1) + N * 2] = \ - Depth [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -void DrawTile16_OBJ (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) -{ -// TILE_PREAMBLE - - uint8 *pCache; - uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << 5); - if (Tile & 0x100){ - TileAddr += BG.NameSelect; - } - - TileAddr &= 0xffff; - - uint32 TileNumber; - pCache = &BG.Buffer[(TileNumber = (TileAddr >> 5)) << 6]; - - if (!BG.Buffered [TileNumber]){ - BG.Buffered[TileNumber] = ConvertTile (pCache, TileAddr); - } - - if (BG.Buffered [TileNumber] == BLANK_TILE){ - TileBlank = Tile & 0xFFFFFFFF; - return; - } - - GFX.ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & 7) << 4) + 128]; - - register uint8* bp; - register int inc; - - if (Tile & V_FLIP){ - bp = pCache + 56 - StartLine; - inc = -8; - } else { - bp = pCache + StartLine; - inc = 8; - } - - uint16* Screen = (uint16 *) GFX.S + Offset; - uint16* Colors = GFX.ScreenColors; - uint8* Depth = GFX.DB + Offset; - int GFX_Z1 = GFX.Z1; - int GFX_Z2 = GFX.Z2; - - if (!(Tile & H_FLIP)){ -#define FN(N) \ - if (GFX_Z1 > Depth[N] && bp[N]){ \ - Screen[N] = Colors[bp[N]]; \ - Depth[N] = GFX_Z2; \ - } - while ( LineCount-- ){ - if ( *(uint32*)bp ){ - FN(0); FN(1); FN(2); FN(3); - } - - if ( *(uint32 *)(bp + 4) ){ - FN(4); FN(5); FN(6); FN(7); - } - bp += inc; - Screen += GFX_PPL; - Depth += GFX_PPL; - } -#undef FN - } else { -#define FN(N, B) \ - if (GFX_Z1 > Depth[N] && bp[B]){ \ - Screen[N] = Colors[bp[B]]; \ - Depth[N] = GFX_Z2; \ - } - while ( LineCount-- ){ - if ( *(uint32 *)(bp + 4) ){ - FN(0, 7); FN(1, 6); FN(2, 5); FN(3, 4); - } - - if ( *(uint32*)bp ){ - FN(4, 3); FN(5, 2); FN(6, 1); FN(7, 0); - } - bp += inc; - Screen += GFX_PPL; - Depth += GFX_PPL; - } -#undef FN - } -} - -void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) -{ -// TILE_PREAMBLE - - uint8 *pCache; - uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); - - TileAddr &= 0xffff; - - uint32 TileNumber; - pCache = &BG.Buffer[(TileNumber = (TileAddr >> BG.TileShift)) << 6]; - - if (!BG.Buffered [TileNumber]){ - BG.Buffered[TileNumber] = ConvertTile (pCache, TileAddr); - } - - if (BG.Buffered [TileNumber] == BLANK_TILE) - { - TileBlank = Tile & 0xFFFFFFFF; - return; - } - - if (BG.DirectColourMode){ - if (IPPU.DirectColourMapsNeedRebuild){ - S9xBuildDirectColourMaps (); - } - GFX.ScreenColors = DirectColourMaps [(Tile >> 10) & BG.PaletteMask]; - } else { - GFX.ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & BG.PaletteMask) << BG.PaletteShift) + BG.StartPalette]; - } - - register uint8* bp; - register int inc; - - if (Tile & V_FLIP){ - bp = pCache + 56 - StartLine; - inc = -8; - } else { - bp = pCache + StartLine; - inc = 8; - } - - uint16* Screen = (uint16 *) GFX.S + Offset; - uint16* Colors = GFX.ScreenColors; - uint8* Depth = GFX.DB + Offset; - int GFX_Z1 = GFX.Z1; -// int GFX_Z2 = GFX.Z2; - - if (!(Tile & H_FLIP)){ -#define FN(N) \ - if (GFX_Z1 > Depth[N] && bp[N]){ \ - Screen[N] = Colors[bp[N]]; \ - Depth[N] = GFX_Z1; \ - } - while ( LineCount-- ){ - if ( *(uint32*)bp ){ - FN(0); FN(1); FN(2); FN(3); - } - - if ( *(uint32 *)(bp + 4) ){ - FN(4); FN(5); FN(6); FN(7); - } - bp += inc; - Screen += GFX_PPL; - Depth += GFX_PPL; - } -#undef FN - } else { -#define FN(N, B) \ - if (GFX_Z1 > Depth[N] && bp[B]){ \ - Screen[N] = Colors[bp[B]]; \ - Depth[N] = GFX_Z1; \ - } - while ( LineCount-- ){ - if ( *(uint32 *)(bp + 4) ){ - FN(0, 7); FN(1, 6); FN(2, 5); FN(3, 4); - } - - if ( *(uint32*)bp ){ - FN(4, 3); FN(5, 2); FN(6, 1); FN(7, 0); - } - bp += inc; - Screen += GFX_PPL; - Depth += GFX_PPL; - } -#undef FN - } -} - -void DrawClippedTile16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4) -} - -void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) -} - -void DrawClippedTile16x2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) -} - -void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) -} - -void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) -} - -void DrawLargePixel16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - uint16 pixel; - - RENDER_TILE_LARGE (GFX.ScreenColors [pixel], PLOT_PIXEL) -} - -INLINE void WRITE_4PIXELS16_ADD (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ - { \ - if (SubDepth [N]) \ - { \ - if (SubDepth [N] != 1) \ - Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ - Screen [GFX.Delta + N]); \ - else \ - Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ - GFX.FixedColour); \ - } \ - else \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPED_ADD (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ - { \ - if (SubDepth [N]) \ - { \ - if (SubDepth [N] != 1) \ - Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ - Screen [GFX.Delta + N]); \ - else \ - Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ - GFX.FixedColour); \ - } \ - else \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -INLINE void WRITE_4PIXELS16_ADD1_2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ - { \ - if (SubDepth [N]) \ - { \ - if (SubDepth [N] != 1) \ - Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \ - Screen [GFX.Delta + N])); \ - else \ - Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ - GFX.FixedColour); \ - } \ - else \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPED_ADD1_2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ - { \ - if (SubDepth [N]) \ - { \ - if (SubDepth [N] != 1) \ - Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \ - Screen [GFX.Delta + N])); \ - else \ - Screen [N] = COLOR_ADD (GFX.ScreenColors [Pixel], \ - GFX.FixedColour); \ - } \ - else \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -INLINE void WRITE_4PIXELS16_SUB (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ - { \ - if (SubDepth [N]) \ - { \ - if (SubDepth [N] != 1) \ - Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ - Screen [GFX.Delta + N]); \ - else \ - Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ - GFX.FixedColour); \ - } \ - else \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPED_SUB (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ - { \ - if (SubDepth [N]) \ - { \ - if (SubDepth [N] != 1) \ - Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ - Screen [GFX.Delta + N]); \ - else \ - Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ - GFX.FixedColour); \ - } \ - else \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -INLINE void WRITE_4PIXELS16_SUB1_2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ - { \ - if (SubDepth [N]) \ - { \ - if (SubDepth [N] != 1) \ - Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \ - Screen [GFX.Delta + N]); \ - else \ - Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ - GFX.FixedColour); \ - } \ - else \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPED_SUB1_2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ - { \ - if (SubDepth [N]) \ - { \ - if (SubDepth [N] != 1) \ - Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \ - Screen [GFX.Delta + N]); \ - else \ - Screen [N] = (uint16) COLOR_SUB (GFX.ScreenColors [Pixel], \ - GFX.FixedColour); \ - } \ - else \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - - -void DrawTile16Add (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4) -} - -void DrawClippedTile16Add (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD, WRITE_4PIXELS16_FLIPPED_ADD, 4) -} - -void DrawTile16Add1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4) -} - -void DrawClippedTile16Add1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADD1_2, WRITE_4PIXELS16_FLIPPED_ADD1_2, 4) -} - -void DrawTile16Sub (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4) -} - -void DrawClippedTile16Sub (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB, WRITE_4PIXELS16_FLIPPED_SUB, 4) -} - -void DrawTile16Sub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4) -} - -void DrawClippedTile16Sub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUB1_2, WRITE_4PIXELS16_FLIPPED_SUB1_2, 4) -} - -INLINE void WRITE_4PIXELS16_ADDF1_2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ - { \ - if (SubDepth [N] == 1) \ - Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \ - GFX.FixedColour)); \ - else \ - Screen [N] = GFX.ScreenColors [Pixel];\ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPED_ADDF1_2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ - { \ - if (SubDepth [N] == 1) \ - Screen [N] = (uint16) (COLOR_ADD1_2 (GFX.ScreenColors [Pixel], \ - GFX.FixedColour)); \ - else \ - Screen [N] = GFX.ScreenColors [Pixel];\ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -INLINE void WRITE_4PIXELS16_SUBF1_2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[N])) \ - { \ - if (SubDepth [N] == 1) \ - Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \ - GFX.FixedColour); \ - else \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPED_SUBF1_2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint8 *SubDepth = GFX.SubZBuffer + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[3 - N])) \ - { \ - if (SubDepth [N] == 1) \ - Screen [N] = (uint16) COLOR_SUB1_2 (GFX.ScreenColors [Pixel], \ - GFX.FixedColour); \ - else \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) - -#undef FN -} - -void DrawTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_ADDF1_2, WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4) -} - -void DrawClippedTile16FixedAdd1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_ADDF1_2, - WRITE_4PIXELS16_FLIPPED_ADDF1_2, 4) -} - -void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) -} - -void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, - WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) -} - -void DrawLargePixel16Add (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - register uint16 pixel; - -#define LARGE_ADD_PIXEL(s, p) \ -(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_ADD (p, *(s + GFX.Delta)) : \ - COLOR_ADD (p, GFX.FixedColour)) \ - : p) - - RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL) -} - -void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - register uint16 pixel; - -#define LARGE_ADD_PIXEL1_2(s, p) \ -((uint16) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_ADD1_2 (p, *(s + GFX.Delta)) : \ - COLOR_ADD (p, GFX.FixedColour)) \ - : p)) - - RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL1_2) -} - -void DrawLargePixel16Sub (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - register uint16 pixel; - -#define LARGE_SUB_PIXEL(s, p) \ -(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_SUB (p, *(s + GFX.Delta)) : \ - COLOR_SUB (p, GFX.FixedColour)) \ - : p) - - RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL) -} - -void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint16 pixel; - -#define LARGE_SUB_PIXEL1_2(s, p) \ -(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_SUB1_2 (p, *(s + GFX.Delta)) : \ - COLOR_SUB (p, GFX.FixedColour)) \ - : p) - - RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL1_2) -} - -void DrawHiResTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4) -} - -void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4) -} diff --git a/src/tile16.c b/src/tile16.c new file mode 100644 index 0000000..c2825df --- /dev/null +++ b/src/tile16.c @@ -0,0 +1,1858 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +// ARM V5 Assembly by bitrider + +#include "snes9x.h" + +#include "memmap.h" +#include "ppu.h" +#include "display.h" +#include "gfx.h" +#include "tile16.h" + +extern uint32 HeadMask [4]; +extern uint32 TailMask [5]; + +#ifdef ARM_ASM + +#define f(from, to_lo, to_hi, pix) \ + " movs " #from ", " #from ", lsl #(17) \n" \ + " addcs " #to_hi ", " #to_hi ", #(1 << ( 0 + 1 + " #pix ")) \n" \ + " addmi " #to_hi ", " #to_hi ", #(1 << ( 8 + 1 + " #pix ")) \n" \ + " movs " #from ", " #from ", lsl #2 \n" \ + " addcs " #to_hi ", " #to_hi ", #(1 << (16 + 1 + " #pix ")) \n" \ + " addmi " #to_hi ", " #to_hi ", #(1 << (24 + 1 + " #pix ")) \n" \ + " movs " #from ", " #from ", lsl #2 \n"\ + " addcs " #to_lo ", " #to_lo ", #(1 << ( 0 + 1 + " #pix ")) \n" \ + " addmi " #to_lo ", " #to_lo ", #(1 << ( 8 + 1 + " #pix ")) \n" \ + " movs " #from ", " #from ", lsl #2 \n" \ + " addcs " #to_lo ", " #to_lo ", #(1 << (16 + 1 + " #pix ")) \n" \ + " addmi " #to_lo ", " #to_lo ", #(1 << (24 + 1 + " #pix ")) \n" \ + \ + " movs " #from ", " #from ", lsl #2 \n"\ + " addcs " #to_hi ", " #to_hi ", #(1 << ( 0 + " #pix ")) \n"\ + " addmi " #to_hi ", " #to_hi ", #(1 << ( 8 + " #pix ")) \n" \ + " movs " #from ", " #from ", lsl #2 \n"\ + " addcs " #to_hi ", " #to_hi ", #(1 << (16 + " #pix ")) \n" \ + " addmi " #to_hi ", " #to_hi ", #(1 << (24 + " #pix ")) \n"\ + " movs " #from ", " #from ", lsl #2 \n"\ + " addcs " #to_lo ", " #to_lo ", #(1 << ( 0 + " #pix ")) \n"\ + " addmi " #to_lo ", " #to_lo ", #(1 << ( 8 + " #pix ")) \n" \ + " movs " #from ", " #from ", lsl #2 \n"\ + " addcs " #to_lo ", " #to_lo ", #(1 << (16 + " #pix ")) \n" \ + " addmi " #to_lo ", " #to_lo ", #(1 << (24 + " #pix ")) \n" + +uint8 ConvertTile8bpp (uint8 *pCache, uint32 TileAddr) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + register uint32 *p = (uint32 *) pCache; + register uint32 non_zero; + + __asm__ volatile ( + " mov r0, #8 \n" + " mov %[non_zero], #0 \n" + + "1: \n" + + " mov r1, #0 \n" + " mov r2, #0 \n" + + " ldrh r3, [%[tp], #16] \n" + " ldrh r4, [%[tp], #32] \n" + + f(r3, r2, r1, 2) + f(r4, r2, r1, 4) + + " ldrh r3, [%[tp], #48] \n" + " ldrh r4, [%[tp]], #2 \n" + + f(r3, r2, r1, 6) + f(r4, r2, r1, 0) + + " stmia %[p]!, {r1, r2} \n" + + " orr %[non_zero], %[non_zero], r1 \n" + " orr %[non_zero], %[non_zero], r2 \n" + + " subs r0, r0, #1 \n" + " bne 1b \n" + + : [non_zero] "+r" (non_zero), + [tp] "+r" (tp), + [p] "+r" (p) + : + : "r0", "r1", "r2", "r3", "r4", "cc" + ); + + return (non_zero ? TRUE : BLANK_TILE); +} + +uint8 ConvertTile4bpp (uint8 *pCache, uint32 TileAddr) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + register uint32 *p = (uint32 *) pCache; + register uint32 non_zero; + + __asm__ volatile ( + " mov r0, #8 \n" + " mov %[non_zero], #0 \n" + "1: \n" + + " mov r1, #0 \n" + " mov r2, #0 \n" + + " ldrh r3, [%[tp], #16]\n" + " ldrh r4, [%[tp]], #2 \n" + + f(r3, r2, r1, 2) + f(r4, r2, r1, 0) + + " stmia %[p]!, {r1, r2} \n" + + " orr %[non_zero], %[non_zero], r1 \n" + " orr %[non_zero], %[non_zero], r2 \n" + + " subs r0, r0, #1 \n" + " bne 1b \n" + + : [non_zero] "+r" (non_zero), + [tp] "+r" (tp), + [p] "+r" (p) + : + : "r0", "r1", "r2", "r3", "r4", "cc" + ); + + return (non_zero ? TRUE : BLANK_TILE); +} + +uint8 ConvertTile2bpp (uint8 *pCache, uint32 TileAddr) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + register uint32 *p = (uint32 *) pCache; + register uint32 non_zero; + + __asm__ volatile ( + " mov r0, #8 \n" + " mov %[non_zero], #0 \n" + "1: \n" + + " ldrh r3, [%[tp]], #2 \n" + + " mov r1, #0 \n" + " mov r2, #0 \n" + + f(r3, r2, r1, 0) + + " stmia %[p]!, {r1, r2} \n" + + " orr %[non_zero], %[non_zero], r1 \n" + " orr %[non_zero], %[non_zero], r2 \n" + + " subs r0, r0, #1 \n" + " bne 1b \n" + + : [non_zero] "+r" (non_zero), + [tp] "+r" (tp), + [p] "+r" (p) + : + : "r0", "r1", "r2", "r3", "cc" + ); + + return (non_zero ? TRUE : BLANK_TILE); +} + + +uint8 (*ConvertTile) (uint8 *pCache, uint32 TileAddr); +void SelectConvertTile() { + switch (BG.BitShift) + { + + case 8: + ConvertTile = &ConvertTile8bpp; + break; + case 4: + ConvertTile = &ConvertTile4bpp; + break; + case 2: + ConvertTile = &ConvertTile2bpp; + break; + } +} +#else +uint8 ConvertTile (uint8 *pCache, uint32 TileAddr) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + switch (BG.BitShift) + { + case 8: + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + if ((pix = *(tp + 0))) + { + p1 |= odd_high[0][pix >> 4]; + p2 |= odd_low[0][pix & 0xf]; + } + if ((pix = *(tp + 1))) + { + p1 |= even_high[0][pix >> 4]; + p2 |= even_low[0][pix & 0xf]; + } + if ((pix = *(tp + 16))) + { + p1 |= odd_high[1][pix >> 4]; + p2 |= odd_low[1][pix & 0xf]; + } + if ((pix = *(tp + 17))) + { + p1 |= even_high[1][pix >> 4]; + p2 |= even_low[1][pix & 0xf]; + } + if ((pix = *(tp + 32))) + { + p1 |= odd_high[2][pix >> 4]; + p2 |= odd_low[2][pix & 0xf]; + } + if ((pix = *(tp + 33))) + { + p1 |= even_high[2][pix >> 4]; + p2 |= even_low[2][pix & 0xf]; + } + if ((pix = *(tp + 48))) + { + p1 |= odd_high[3][pix >> 4]; + p2 |= odd_low[3][pix & 0xf]; + } + if ((pix = *(tp + 49))) + { + p1 |= even_high[3][pix >> 4]; + p2 |= even_low[3][pix & 0xf]; + } + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + break; + + case 4: + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + if ((pix = *(tp + 0))) + { + p1 |= odd_high[0][pix >> 4]; + p2 |= odd_low[0][pix & 0xf]; + } + if ((pix = *(tp + 1))) + { + p1 |= even_high[0][pix >> 4]; + p2 |= even_low[0][pix & 0xf]; + } + if ((pix = *(tp + 16))) + { + p1 |= odd_high[1][pix >> 4]; + p2 |= odd_low[1][pix & 0xf]; + } + if ((pix = *(tp + 17))) + { + p1 |= even_high[1][pix >> 4]; + p2 |= even_low[1][pix & 0xf]; + } + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + break; + + case 2: + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + if ((pix = *(tp + 0))) + { + p1 |= odd_high[0][pix >> 4]; + p2 |= odd_low[0][pix & 0xf]; + } + if ((pix = *(tp + 1))) + { + p1 |= even_high[0][pix >> 4]; + p2 |= even_low[0][pix & 0xf]; + } + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + break; + } + return (non_zero ? TRUE : BLANK_TILE); +} +#endif + +void SelectPalette() { + // GFX.ScreenColors = &GFX.ScreenColorsPre[(Tile & GFX.PaletteMask) >> GFX.PaletteShift]; + if (BG.DirectColourMode) { + // GFX.ScreenColors = DirectColourMaps [(Tile >> 10) & BG.PaletteMask]; + + GFX.ScreenColorsPre = DirectColourMaps[0]; + GFX.PaletteMask = BG.PaletteMask << 10; + GFX.PaletteShift = 10; + } else { + // GFX.ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & BG.PaletteMask) << BG.PaletteShift) + BG.StartPalette]; + + GFX.ScreenColorsPre = &IPPU.ScreenColors[BG.StartPalette]; + GFX.PaletteMask = BG.PaletteMask << 10; + GFX.PaletteShift = 10 - BG.PaletteShift; + } + +} + +static inline void WRITE_4PIXELSHI16 (uint32 Offset, uint8 *Pixels) +{ + uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[2*N])) \ + { \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static inline void WRITE_4PIXELSHI16_FLIPPED (uint32 Offset, uint8 *Pixels) +{ + uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N] && (Pixel = Pixels[6 - 2*N])) \ + { \ + Screen [N] = GFX.ScreenColors [Pixel]; \ + Depth [N] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS16x2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPEDx2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS16x2x2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX_PITCH >> 1) + N * 2] = \ + Screen [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX_PITCH >> 1) + N * 2] = \ + Depth [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +static INLINE void WRITE_4PIXELS16_FLIPPEDx2x2 (uint32 Offset, uint8 *Pixels) +{ + register uint32 Pixel; + uint16 *Screen = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + +#define FN(N) \ + if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ + { \ + Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX_PITCH >> 1) + N * 2] = \ + Screen [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.ScreenColors [Pixel]; \ + Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX_PITCH >> 1) + N * 2] = \ + Depth [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.Z2; \ + } + + FN(0) + FN(1) + FN(2) + FN(3) +#undef FN +} + +#ifdef __FAST_OBJS__ +// DrawNoZTile16 ----------------------------------------- +void DrawNoZTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) +{ + + TILE_PREAMBLE +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" +#define FN(p) \ + " ldrb r1, [%[bp], #" #p "] \n"\ + " ldrb r0, [%[bp], #(" #p " + 1)] \n"\ + " movs r1, r1, lsl #2 \n"\ + " ldrne r1, [%[colors], r1] \n"\ + " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ + " strneh r1, [%[screen], #(" #p " * 2)] \n"\ + "3: \n"\ + " movs r1, r0, lsl #2 \n"\ + " ldrne r1, [%[colors], r1] \n"\ + " strneb %[gfx_z2], [%[depth], #(" #p " + 1)] \n"\ + " strneh r1, [%[screen], #((" #p " + 1) * 2)] \n"\ + "3: \n" + + FN(0) + FN(2) + FN(4) + FN(6) + // Loop + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : [lcount] "+r" (LineCount) + // input + : [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + 56 - StartLine) + // clobbered + : "r0", "r1", "cc" // r8 & flags + ); + } else { + __asm__ volatile ( + "2: \n" +#define FN1(p) \ + " ldrb r1, [%[bp], #( 7 - " #p ")] \n"\ + " ldrb r0, [%[bp], #(7 - " #p " - 1)] \n"\ + " movs r1, r1, lsl #2 \n"\ + " ldrne r1, [%[colors], r1] \n"\ + " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ + " strneh r1, [%[screen], #(" #p " * 2)] \n"\ + "3: \n"\ + " movs r1, r0, lsl #2 \n"\ + " ldrne r1, [%[colors], r1] \n"\ + " strneb %[gfx_z2], [%[depth], #(" #p " + 1)] \n"\ + " strneh r1, [%[screen], #((" #p " + 1) * 2 )] \n"\ + "3: \n" + + FN1(0) + FN1(2) + FN1(4) + FN1(6) + // Loop + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : [lcount] "+r" (LineCount) + // input + : [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + 56 - StartLine) + // clobbered + : "r0", "r1", "cc" // r8 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN(0) + FN(2) + FN(4) + FN(6) + // Loop + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : [lcount] "+r" (LineCount) + // input + : [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + StartLine) + // clobbered + : "r0", "r1", "cc" // r8 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1(0) + FN1(2) + FN1(4) + FN1(6) + // Loop + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : [lcount] "+r" (LineCount) + // input + : [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + StartLine) + // clobbered + : "r0", "r1", "cc" // r8 & flags + ); + + } + } +#undef FN +#undef FN1 + +} +#endif // #ifdef __FAST_OBJS__ + +// DrawTile16 ----------------------------------------- +void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" +#define FN(p) \ + " ldrb r9, [%[depth], #" #p "] \n"\ + " ldrb r8, [%[depth], #(" #p " + 1)] \n"\ + " cmp %[gfx_z1], r9 \n"\ + " ldrhib r9, [%[bp], #" #p "] \n"\ + " bls 3f \n"\ + " movs r9, r9, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ + " strneh r9, [%[screen], #(" #p " * 2)] \n"\ + "3: \n"\ + " cmp %[gfx_z1], r8 \n"\ + " ldrhib r9, [%[bp], #(" #p " + 1)] \n"\ + " bls 3f \n"\ + " movs r9, r9, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #(" #p " + 1)] \n"\ + " strneh r9, [%[screen], #((" #p " + 1) * 2)] \n"\ + "3: \n" + + FN(0) + FN(2) + FN(4) + FN(6) + // Loop + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : [lcount] "+r" (LineCount) + // input + : [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + 56 - StartLine) + // clobbered + : "r9", "r8", "cc" // r8 & flags + ); + } else { + __asm__ volatile ( + "2: \n" +#define FN1(p) \ + " ldrb r9, [%[depth], #" #p "] \n"\ + " ldrb r8, [%[depth], #(" #p " + 1)] \n"\ + " cmp %[gfx_z1], r9 \n"\ + " ldrhib r9, [%[bp], #( 7 - " #p ")] \n"\ + " bls 3f \n"\ + " movs r9, r9, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ + " strneh r9, [%[screen], #(" #p " * 2)] \n"\ + "3: \n"\ + " cmp %[gfx_z1], r8 \n"\ + " ldrhib r9, [%[bp], #(7 - " #p " - 1)] \n"\ + " bls 3f \n"\ + " movs r9, r9, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #(" #p " + 1)] \n"\ + " strneh r9, [%[screen], #((" #p " + 1) * 2 )] \n"\ + "3: \n" + + FN1(0) + FN1(2) + FN1(4) + FN1(6) + // Loop + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : [lcount] "+r" (LineCount) + // input + : [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + 56 - StartLine) + // clobbered + : "r9", "r8", "cc" // r8 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN(0) + FN(2) + FN(4) + FN(6) + // Loop + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : [lcount] "+r" (LineCount) + // input + : [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + StartLine) + // clobbered + : "r9", "r8", "cc" // r8 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1(0) + FN1(2) + FN1(4) + FN1(6) + // Loop + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : [lcount] "+r" (LineCount) + // input + : [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + StartLine) + // clobbered + : "r9", "r8", "cc" // r8, r9 & flags + ); + + } + } +#undef FN +#undef FN1 + +} + +// DrawClippedTile16 ----------------------------------------- +void DrawClippedTile16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ +if (Width == 0) return; +if (Width == 8) { + DrawTile16 (Tile, Offset, StartLine, LineCount); + return; + } + + TILE_PREAMBLE +Offset += StartPixel; + +#define FN(p) \ + " ldrb r8, [%[depth], #" #p "] \n"\ + " ldrb r9, [%[bp], #" #p "] \n"\ + " cmp %[gfx_z1], r8 \n"\ + " bls 3f \n"\ + " movs r9, r9, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ + " strneh r9, [%[screen], #(" #p " * 2)] \n"\ + "3: \n" + +#define FN1(p) \ + " ldrb r8, [%[depth], #" #p "] \n"\ + " ldrb r9, [%[bp], #(7 - " #p ")] \n"\ + " cmp %[gfx_z1], r8 \n"\ + " bls 3f \n"\ + " movs r9, r9, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ + " strneh r9, [%[screen], #(" #p " * 2)] \n"\ + "3: \n"\ + +switch(Width) { + case 1: +// -- Width = 1 ------ +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN(0) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1(0) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN(0) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1(0) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + + } + } + break; + case 2: +// -- Width = 2 ------ +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + + FN(0) + FN(1) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + + FN1(0) + FN1(1) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN(0) + FN(1) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1(0) + FN1(1) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + + } + } + + break; + case 3: +// -- Width = 3 ------ +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + + FN(0) + FN(1) + FN(2) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + + FN1(0) + FN1(1) + FN1(2) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN(0) + FN(1) + FN(2) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1(0) + FN1(1) + FN1(2) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + + } + } + + break; + case 4: +// -- Width = 4 ------ +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + + FN(0) + FN(1) + FN(2) + FN(3) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + + FN1(0) + FN1(1) + FN1(2) + FN1(3) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN(0) + FN(1) + FN(2) + FN(3) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1(0) + FN1(1) + FN1(2) + FN1(3) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + + } + } + + break; + case 5: +// -- Width = 5 ------ +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + + FN(0) + FN(1) + FN(2) + FN(3) + FN(4) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + + FN1(0) + FN1(1) + FN1(2) + FN1(3) + FN1(4) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN(0) + FN(1) + FN(2) + FN(3) + FN(4) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1(0) + FN1(1) + FN1(2) + FN1(3) + FN1(4) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + + } + } + + break; + case 6: +// -- Width = 6 ------ +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + + FN(0) + FN(1) + FN(2) + FN(3) + FN(4) + FN(5) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + + FN1(0) + FN1(1) + FN1(2) + FN1(3) + FN1(4) + FN1(5) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN(0) + FN(1) + FN(2) + FN(3) + FN(4) + FN(5) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1(0) + FN1(1) + FN1(2) + FN1(3) + FN1(4) + FN1(5) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + + } + } + + break; + case 7: +// -- Width = 7 ------ +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + + FN(0) + FN(1) + FN(2) + FN(3) + FN(4) + FN(5) + FN(6) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + + FN1(0) + FN1(1) + FN1(2) + FN1(3) + FN1(4) + FN1(5) + FN1(6) + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN(0) + FN(1) + FN(2) + FN(3) + FN(4) + FN(5) + FN(6) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine + StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1(0) + FN1(1) + FN1(2) + FN1(3) + FN1(4) + FN1(5) + FN1(6) + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine - StartPixel) + // clobbered + : "r9", "r8", "cc" // r9 & flags + ); + + } + } + + break; + } + + + + + +#undef FN +#undef FN1 +#undef C + +} + +void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + uint32 l; + + RENDER_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) +} + +void DrawClippedTile16x2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + uint32 l; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) +} + +void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + uint32 l; + + RENDER_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) +} + +void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + uint32 l; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) +} + +void DrawLargePixel16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + uint32 l; + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.DB + Offset; + uint16 pixel; + +#define PLOT_PIXEL(screen, pixel) (pixel) + + RENDER_TILE_LARGE (GFX.ScreenColors [pixel], PLOT_PIXEL) +} + + +void DrawLargePixel16Add (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + uint32 l; + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + register uint16 pixel; + +#define LARGE_ADD_PIXEL(s, p) \ +(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_ADD (p, *(s + GFX.Delta)) : \ + COLOR_ADD (p, GFX.FixedColour)) \ + : p) + + RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL) +} + +void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + uint32 l; + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + register uint16 pixel; + +#define LARGE_ADD_PIXEL1_2(s, p) \ +((uint16) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_ADD1_2 (p, *(s + GFX.Delta)) : \ + COLOR_ADD (p, GFX.FixedColour)) \ + : p)) + + RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL1_2) +} + +void DrawLargePixel16Sub (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + uint32 l; + + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + register uint16 pixel; + +#define LARGE_SUB_PIXEL(s, p) \ +(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_SUB (p, *(s + GFX.Delta)) : \ + COLOR_SUB (p, GFX.FixedColour)) \ + : p) + + RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL) +} + +void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Pixels, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + uint32 l; + + register uint16 *sp = (uint16 *) GFX.S + Offset; + uint8 *Depth = GFX.ZBuffer + Offset; + uint16 pixel; + +#define LARGE_SUB_PIXEL1_2(s, p) \ +(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ + COLOR_SUB1_2 (p, *(s + GFX.Delta)) : \ + COLOR_SUB (p, GFX.FixedColour)) \ + : p) + + RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL1_2) +} + +void DrawHiResTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + uint32 l; + + register uint8 *bp; + + RENDER_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4) +} + +void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + uint32 l; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4) +} diff --git a/src/tile16.cpp b/src/tile16.cpp deleted file mode 100644 index 3dc6e2a..0000000 --- a/src/tile16.cpp +++ /dev/null @@ -1,1858 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -// ARM V5 Assembly by bitrider - -#include "snes9x.h" - -#include "memmap.h" -#include "ppu.h" -#include "display.h" -#include "gfx.h" -#include "tile16.h" - -extern uint32 HeadMask [4]; -extern uint32 TailMask [5]; - -#ifdef ARM_ASM - -#define f(from, to_lo, to_hi, pix) \ - " movs " #from ", " #from ", lsl #(17) \n" \ - " addcs " #to_hi ", " #to_hi ", #(1 << ( 0 + 1 + " #pix ")) \n" \ - " addmi " #to_hi ", " #to_hi ", #(1 << ( 8 + 1 + " #pix ")) \n" \ - " movs " #from ", " #from ", lsl #2 \n" \ - " addcs " #to_hi ", " #to_hi ", #(1 << (16 + 1 + " #pix ")) \n" \ - " addmi " #to_hi ", " #to_hi ", #(1 << (24 + 1 + " #pix ")) \n" \ - " movs " #from ", " #from ", lsl #2 \n"\ - " addcs " #to_lo ", " #to_lo ", #(1 << ( 0 + 1 + " #pix ")) \n" \ - " addmi " #to_lo ", " #to_lo ", #(1 << ( 8 + 1 + " #pix ")) \n" \ - " movs " #from ", " #from ", lsl #2 \n" \ - " addcs " #to_lo ", " #to_lo ", #(1 << (16 + 1 + " #pix ")) \n" \ - " addmi " #to_lo ", " #to_lo ", #(1 << (24 + 1 + " #pix ")) \n" \ - \ - " movs " #from ", " #from ", lsl #2 \n"\ - " addcs " #to_hi ", " #to_hi ", #(1 << ( 0 + " #pix ")) \n"\ - " addmi " #to_hi ", " #to_hi ", #(1 << ( 8 + " #pix ")) \n" \ - " movs " #from ", " #from ", lsl #2 \n"\ - " addcs " #to_hi ", " #to_hi ", #(1 << (16 + " #pix ")) \n" \ - " addmi " #to_hi ", " #to_hi ", #(1 << (24 + " #pix ")) \n"\ - " movs " #from ", " #from ", lsl #2 \n"\ - " addcs " #to_lo ", " #to_lo ", #(1 << ( 0 + " #pix ")) \n"\ - " addmi " #to_lo ", " #to_lo ", #(1 << ( 8 + " #pix ")) \n" \ - " movs " #from ", " #from ", lsl #2 \n"\ - " addcs " #to_lo ", " #to_lo ", #(1 << (16 + " #pix ")) \n" \ - " addmi " #to_lo ", " #to_lo ", #(1 << (24 + " #pix ")) \n" - -uint8 ConvertTile8bpp (uint8 *pCache, uint32 TileAddr) -{ - register uint8 *tp = &Memory.VRAM[TileAddr]; - register uint32 *p = (uint32 *) pCache; - register uint32 non_zero; - - asm volatile ( - " mov r0, #8 \n" - " mov %[non_zero], #0 \n" - - "1: \n" - - " mov r1, #0 \n" - " mov r2, #0 \n" - - " ldrh r3, [%[tp], #16] \n" - " ldrh r4, [%[tp], #32] \n" - - f(r3, r2, r1, 2) - f(r4, r2, r1, 4) - - " ldrh r3, [%[tp], #48] \n" - " ldrh r4, [%[tp]], #2 \n" - - f(r3, r2, r1, 6) - f(r4, r2, r1, 0) - - " stmia %[p]!, {r1, r2} \n" - - " orr %[non_zero], %[non_zero], r1 \n" - " orr %[non_zero], %[non_zero], r2 \n" - - " subs r0, r0, #1 \n" - " bne 1b \n" - - : [non_zero] "+r" (non_zero), - [tp] "+r" (tp), - [p] "+r" (p) - : - : "r0", "r1", "r2", "r3", "r4", "cc" - ); - - return (non_zero ? TRUE : BLANK_TILE); -} - -uint8 ConvertTile4bpp (uint8 *pCache, uint32 TileAddr) -{ - register uint8 *tp = &Memory.VRAM[TileAddr]; - register uint32 *p = (uint32 *) pCache; - register uint32 non_zero; - - asm volatile ( - " mov r0, #8 \n" - " mov %[non_zero], #0 \n" - "1: \n" - - " mov r1, #0 \n" - " mov r2, #0 \n" - - " ldrh r3, [%[tp], #16]\n" - " ldrh r4, [%[tp]], #2 \n" - - f(r3, r2, r1, 2) - f(r4, r2, r1, 0) - - " stmia %[p]!, {r1, r2} \n" - - " orr %[non_zero], %[non_zero], r1 \n" - " orr %[non_zero], %[non_zero], r2 \n" - - " subs r0, r0, #1 \n" - " bne 1b \n" - - : [non_zero] "+r" (non_zero), - [tp] "+r" (tp), - [p] "+r" (p) - : - : "r0", "r1", "r2", "r3", "r4", "cc" - ); - - return (non_zero ? TRUE : BLANK_TILE); -} - -uint8 ConvertTile2bpp (uint8 *pCache, uint32 TileAddr) -{ - register uint8 *tp = &Memory.VRAM[TileAddr]; - register uint32 *p = (uint32 *) pCache; - register uint32 non_zero; - - asm volatile ( - " mov r0, #8 \n" - " mov %[non_zero], #0 \n" - "1: \n" - - " ldrh r3, [%[tp]], #2 \n" - - " mov r1, #0 \n" - " mov r2, #0 \n" - - f(r3, r2, r1, 0) - - " stmia %[p]!, {r1, r2} \n" - - " orr %[non_zero], %[non_zero], r1 \n" - " orr %[non_zero], %[non_zero], r2 \n" - - " subs r0, r0, #1 \n" - " bne 1b \n" - - : [non_zero] "+r" (non_zero), - [tp] "+r" (tp), - [p] "+r" (p) - : - : "r0", "r1", "r2", "r3", "cc" - ); - - return (non_zero ? TRUE : BLANK_TILE); -} - - -uint8 (*ConvertTile) (uint8 *pCache, uint32 TileAddr); -void SelectConvertTile() { - switch (BG.BitShift) - { - - case 8: - ConvertTile = &ConvertTile8bpp; - break; - case 4: - ConvertTile = &ConvertTile4bpp; - break; - case 2: - ConvertTile = &ConvertTile2bpp; - break; - } -} -#else -uint8 ConvertTile (uint8 *pCache, uint32 TileAddr) -{ - register uint8 *tp = &Memory.VRAM[TileAddr]; - uint32 *p = (uint32 *) pCache; - uint32 non_zero = 0; - uint8 line; - - switch (BG.BitShift) - { - case 8: - for (line = 8; line != 0; line--, tp += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - - if ((pix = *(tp + 0))) - { - p1 |= odd_high[0][pix >> 4]; - p2 |= odd_low[0][pix & 0xf]; - } - if ((pix = *(tp + 1))) - { - p1 |= even_high[0][pix >> 4]; - p2 |= even_low[0][pix & 0xf]; - } - if ((pix = *(tp + 16))) - { - p1 |= odd_high[1][pix >> 4]; - p2 |= odd_low[1][pix & 0xf]; - } - if ((pix = *(tp + 17))) - { - p1 |= even_high[1][pix >> 4]; - p2 |= even_low[1][pix & 0xf]; - } - if ((pix = *(tp + 32))) - { - p1 |= odd_high[2][pix >> 4]; - p2 |= odd_low[2][pix & 0xf]; - } - if ((pix = *(tp + 33))) - { - p1 |= even_high[2][pix >> 4]; - p2 |= even_low[2][pix & 0xf]; - } - if ((pix = *(tp + 48))) - { - p1 |= odd_high[3][pix >> 4]; - p2 |= odd_low[3][pix & 0xf]; - } - if ((pix = *(tp + 49))) - { - p1 |= even_high[3][pix >> 4]; - p2 |= even_low[3][pix & 0xf]; - } - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - break; - - case 4: - for (line = 8; line != 0; line--, tp += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - if ((pix = *(tp + 0))) - { - p1 |= odd_high[0][pix >> 4]; - p2 |= odd_low[0][pix & 0xf]; - } - if ((pix = *(tp + 1))) - { - p1 |= even_high[0][pix >> 4]; - p2 |= even_low[0][pix & 0xf]; - } - if ((pix = *(tp + 16))) - { - p1 |= odd_high[1][pix >> 4]; - p2 |= odd_low[1][pix & 0xf]; - } - if ((pix = *(tp + 17))) - { - p1 |= even_high[1][pix >> 4]; - p2 |= even_low[1][pix & 0xf]; - } - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - break; - - case 2: - for (line = 8; line != 0; line--, tp += 2) - { - uint32 p1 = 0; - uint32 p2 = 0; - register uint8 pix; - if ((pix = *(tp + 0))) - { - p1 |= odd_high[0][pix >> 4]; - p2 |= odd_low[0][pix & 0xf]; - } - if ((pix = *(tp + 1))) - { - p1 |= even_high[0][pix >> 4]; - p2 |= even_low[0][pix & 0xf]; - } - *p++ = p1; - *p++ = p2; - non_zero |= p1 | p2; - } - break; - } - return (non_zero ? TRUE : BLANK_TILE); -} -#endif - -void SelectPalette() { - // GFX.ScreenColors = &GFX.ScreenColorsPre[(Tile & GFX.PaletteMask) >> GFX.PaletteShift]; - if (BG.DirectColourMode) { - // GFX.ScreenColors = DirectColourMaps [(Tile >> 10) & BG.PaletteMask]; - - GFX.ScreenColorsPre = DirectColourMaps[0]; - GFX.PaletteMask = BG.PaletteMask << 10; - GFX.PaletteShift = 10; - } else { - // GFX.ScreenColors = &IPPU.ScreenColors [(((Tile >> 10) & BG.PaletteMask) << BG.PaletteShift) + BG.StartPalette]; - - GFX.ScreenColorsPre = &IPPU.ScreenColors[BG.StartPalette]; - GFX.PaletteMask = BG.PaletteMask << 10; - GFX.PaletteShift = 10 - BG.PaletteShift; - } - -} - -inline void WRITE_4PIXELSHI16 (uint32 Offset, uint8 *Pixels) -{ - uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[2*N])) \ - { \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -inline void WRITE_4PIXELSHI16_FLIPPED (uint32 Offset, uint8 *Pixels) -{ - uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N] && (Pixel = Pixels[6 - 2*N])) \ - { \ - Screen [N] = GFX.ScreenColors [Pixel]; \ - Depth [N] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS16x2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPEDx2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS16x2x2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX_PITCH >> 1) + N * 2] = \ - Screen [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX_PITCH >> 1) + N * 2] = \ - Depth [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -INLINE void WRITE_4PIXELS16_FLIPPEDx2x2 (uint32 Offset, uint8 *Pixels) -{ - register uint32 Pixel; - uint16 *Screen = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - -#define FN(N) \ - if (GFX.Z1 > Depth [N * 2] && (Pixel = Pixels[3 - N])) \ - { \ - Screen [N * 2] = Screen [N * 2 + 1] = Screen [(GFX_PITCH >> 1) + N * 2] = \ - Screen [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.ScreenColors [Pixel]; \ - Depth [N * 2] = Depth [N * 2 + 1] = Depth [(GFX_PITCH >> 1) + N * 2] = \ - Depth [(GFX_PITCH >> 1) + N * 2 + 1] = GFX.Z2; \ - } - - FN(0) - FN(1) - FN(2) - FN(3) -#undef FN -} - -#ifdef __FAST_OBJS__ -// DrawNoZTile16 ----------------------------------------- -void DrawNoZTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) -{ - - TILE_PREAMBLE -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" -#define FN(p) \ - " ldrb r1, [%[bp], #" #p "] \n"\ - " ldrb r0, [%[bp], #(" #p " + 1)] \n"\ - " movs r1, r1, lsl #2 \n"\ - " ldrne r1, [%[colors], r1] \n"\ - " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ - " strneh r1, [%[screen], #(" #p " * 2)] \n"\ - "3: \n"\ - " movs r1, r0, lsl #2 \n"\ - " ldrne r1, [%[colors], r1] \n"\ - " strneb %[gfx_z2], [%[depth], #(" #p " + 1)] \n"\ - " strneh r1, [%[screen], #((" #p " + 1) * 2)] \n"\ - "3: \n" - - FN(0) - FN(2) - FN(4) - FN(6) - // Loop - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : [lcount] "+r" (LineCount) - // input - : [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + 56 - StartLine) - // clobbered - : "r0", "r1", "cc" // r8 & flags - ); - } else { - asm volatile ( - "2: \n" -#define FN1(p) \ - " ldrb r1, [%[bp], #( 7 - " #p ")] \n"\ - " ldrb r0, [%[bp], #(7 - " #p " - 1)] \n"\ - " movs r1, r1, lsl #2 \n"\ - " ldrne r1, [%[colors], r1] \n"\ - " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ - " strneh r1, [%[screen], #(" #p " * 2)] \n"\ - "3: \n"\ - " movs r1, r0, lsl #2 \n"\ - " ldrne r1, [%[colors], r1] \n"\ - " strneb %[gfx_z2], [%[depth], #(" #p " + 1)] \n"\ - " strneh r1, [%[screen], #((" #p " + 1) * 2 )] \n"\ - "3: \n" - - FN1(0) - FN1(2) - FN1(4) - FN1(6) - // Loop - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : [lcount] "+r" (LineCount) - // input - : [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + 56 - StartLine) - // clobbered - : "r0", "r1", "cc" // r8 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN(0) - FN(2) - FN(4) - FN(6) - // Loop - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : [lcount] "+r" (LineCount) - // input - : [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + StartLine) - // clobbered - : "r0", "r1", "cc" // r8 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1(0) - FN1(2) - FN1(4) - FN1(6) - // Loop - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : [lcount] "+r" (LineCount) - // input - : [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + StartLine) - // clobbered - : "r0", "r1", "cc" // r8 & flags - ); - - } - } -#undef FN -#undef FN1 - -} -#endif // #ifdef __FAST_OBJS__ - -// DrawTile16 ----------------------------------------- -void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" -#define FN(p) \ - " ldrb r9, [%[depth], #" #p "] \n"\ - " ldrb r8, [%[depth], #(" #p " + 1)] \n"\ - " cmp %[gfx_z1], r9 \n"\ - " ldrhib r9, [%[bp], #" #p "] \n"\ - " bls 3f \n"\ - " movs r9, r9, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ - " strneh r9, [%[screen], #(" #p " * 2)] \n"\ - "3: \n"\ - " cmp %[gfx_z1], r8 \n"\ - " ldrhib r9, [%[bp], #(" #p " + 1)] \n"\ - " bls 3f \n"\ - " movs r9, r9, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #(" #p " + 1)] \n"\ - " strneh r9, [%[screen], #((" #p " + 1) * 2)] \n"\ - "3: \n" - - FN(0) - FN(2) - FN(4) - FN(6) - // Loop - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : [lcount] "+r" (LineCount) - // input - : [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + 56 - StartLine) - // clobbered - : "r9", "r8", "cc" // r8 & flags - ); - } else { - asm volatile ( - "2: \n" -#define FN1(p) \ - " ldrb r9, [%[depth], #" #p "] \n"\ - " ldrb r8, [%[depth], #(" #p " + 1)] \n"\ - " cmp %[gfx_z1], r9 \n"\ - " ldrhib r9, [%[bp], #( 7 - " #p ")] \n"\ - " bls 3f \n"\ - " movs r9, r9, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ - " strneh r9, [%[screen], #(" #p " * 2)] \n"\ - "3: \n"\ - " cmp %[gfx_z1], r8 \n"\ - " ldrhib r9, [%[bp], #(7 - " #p " - 1)] \n"\ - " bls 3f \n"\ - " movs r9, r9, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #(" #p " + 1)] \n"\ - " strneh r9, [%[screen], #((" #p " + 1) * 2 )] \n"\ - "3: \n" - - FN1(0) - FN1(2) - FN1(4) - FN1(6) - // Loop - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : [lcount] "+r" (LineCount) - // input - : [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + 56 - StartLine) - // clobbered - : "r9", "r8", "cc" // r8 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN(0) - FN(2) - FN(4) - FN(6) - // Loop - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : [lcount] "+r" (LineCount) - // input - : [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + StartLine) - // clobbered - : "r9", "r8", "cc" // r8 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1(0) - FN1(2) - FN1(4) - FN1(6) - // Loop - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : [lcount] "+r" (LineCount) - // input - : [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + StartLine) - // clobbered - : "r9", "r8", "cc" // r8, r9 & flags - ); - - } - } -#undef FN -#undef FN1 - -} - -// DrawClippedTile16 ----------------------------------------- -void DrawClippedTile16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ -if (Width == 0) return; -if (Width == 8) { - DrawTile16 (Tile, Offset, StartLine, LineCount); - return; - } - - TILE_PREAMBLE -Offset += StartPixel; - -#define FN(p) \ - " ldrb r8, [%[depth], #" #p "] \n"\ - " ldrb r9, [%[bp], #" #p "] \n"\ - " cmp %[gfx_z1], r8 \n"\ - " bls 3f \n"\ - " movs r9, r9, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ - " strneh r9, [%[screen], #(" #p " * 2)] \n"\ - "3: \n" - -#define FN1(p) \ - " ldrb r8, [%[depth], #" #p "] \n"\ - " ldrb r9, [%[bp], #(7 - " #p ")] \n"\ - " cmp %[gfx_z1], r8 \n"\ - " bls 3f \n"\ - " movs r9, r9, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #" #p "] \n"\ - " strneh r9, [%[screen], #(" #p " * 2)] \n"\ - "3: \n"\ - -switch(Width) { - case 1: -// -- Width = 1 ------ -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN(0) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1(0) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN(0) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1(0) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - - } - } - break; - case 2: -// -- Width = 2 ------ -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - - FN(0) - FN(1) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - - FN1(0) - FN1(1) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN(0) - FN(1) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1(0) - FN1(1) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - - } - } - - break; - case 3: -// -- Width = 3 ------ -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - - FN(0) - FN(1) - FN(2) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - - FN1(0) - FN1(1) - FN1(2) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN(0) - FN(1) - FN(2) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1(0) - FN1(1) - FN1(2) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - - } - } - - break; - case 4: -// -- Width = 4 ------ -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - - FN(0) - FN(1) - FN(2) - FN(3) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - - FN1(0) - FN1(1) - FN1(2) - FN1(3) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN(0) - FN(1) - FN(2) - FN(3) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1(0) - FN1(1) - FN1(2) - FN1(3) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - - } - } - - break; - case 5: -// -- Width = 5 ------ -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - - FN(0) - FN(1) - FN(2) - FN(3) - FN(4) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - - FN1(0) - FN1(1) - FN1(2) - FN1(3) - FN1(4) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN(0) - FN(1) - FN(2) - FN(3) - FN(4) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1(0) - FN1(1) - FN1(2) - FN1(3) - FN1(4) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - - } - } - - break; - case 6: -// -- Width = 6 ------ -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - - FN(0) - FN(1) - FN(2) - FN(3) - FN(4) - FN(5) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - - FN1(0) - FN1(1) - FN1(2) - FN1(3) - FN1(4) - FN1(5) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN(0) - FN(1) - FN(2) - FN(3) - FN(4) - FN(5) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1(0) - FN1(1) - FN1(2) - FN1(3) - FN1(4) - FN1(5) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - - } - } - - break; - case 7: -// -- Width = 7 ------ -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - - FN(0) - FN(1) - FN(2) - FN(3) - FN(4) - FN(5) - FN(6) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - - FN1(0) - FN1(1) - FN1(2) - FN1(3) - FN1(4) - FN1(5) - FN1(6) - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN(0) - FN(1) - FN(2) - FN(3) - FN(4) - FN(5) - FN(6) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine + StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1(0) - FN1(1) - FN1(2) - FN1(3) - FN1(4) - FN1(5) - FN1(6) - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine - StartPixel) - // clobbered - : "r9", "r8", "cc" // r9 & flags - ); - - } - } - - break; - } - - - - - -#undef FN -#undef FN1 -#undef C - -} - -void DrawTile16x2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - uint32 l; - - RENDER_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) -} - -void DrawClippedTile16x2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - uint32 l; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2, WRITE_4PIXELS16_FLIPPEDx2, 8) -} - -void DrawTile16x2x2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - uint32 l; - - RENDER_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) -} - -void DrawClippedTile16x2x2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - uint32 l; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16x2x2, WRITE_4PIXELS16_FLIPPEDx2x2, 8) -} - -void DrawLargePixel16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - uint32 l; - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.DB + Offset; - uint16 pixel; - -#define PLOT_PIXEL(screen, pixel) (pixel) - - RENDER_TILE_LARGE (GFX.ScreenColors [pixel], PLOT_PIXEL) -} - - -void DrawLargePixel16Add (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - uint32 l; - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - register uint16 pixel; - -#define LARGE_ADD_PIXEL(s, p) \ -(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_ADD (p, *(s + GFX.Delta)) : \ - COLOR_ADD (p, GFX.FixedColour)) \ - : p) - - RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL) -} - -void DrawLargePixel16Add1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - uint32 l; - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - register uint16 pixel; - -#define LARGE_ADD_PIXEL1_2(s, p) \ -((uint16) (Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_ADD1_2 (p, *(s + GFX.Delta)) : \ - COLOR_ADD (p, GFX.FixedColour)) \ - : p)) - - RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_ADD_PIXEL1_2) -} - -void DrawLargePixel16Sub (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - uint32 l; - - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - register uint16 pixel; - -#define LARGE_SUB_PIXEL(s, p) \ -(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_SUB (p, *(s + GFX.Delta)) : \ - COLOR_SUB (p, GFX.FixedColour)) \ - : p) - - RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL) -} - -void DrawLargePixel16Sub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Pixels, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - uint32 l; - - register uint16 *sp = (uint16 *) GFX.S + Offset; - uint8 *Depth = GFX.ZBuffer + Offset; - uint16 pixel; - -#define LARGE_SUB_PIXEL1_2(s, p) \ -(Depth [z + GFX.DepthDelta] ? (Depth [z + GFX.DepthDelta] != 1 ? \ - COLOR_SUB1_2 (p, *(s + GFX.Delta)) : \ - COLOR_SUB (p, GFX.FixedColour)) \ - : p) - - RENDER_TILE_LARGE (GFX.ScreenColors [pixel], LARGE_SUB_PIXEL1_2) -} - -void DrawHiResTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - uint32 l; - - register uint8 *bp; - - RENDER_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4) -} - -void DrawHiResClippedTile16 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - uint32 l; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILEHI(WRITE_4PIXELSHI16, WRITE_4PIXELSHI16_FLIPPED, 4) -} diff --git a/src/tile16.cpp.bak b/src/tile16.cpp.bak index 3d199ff..76c6eb7 100644 --- a/src/tile16.cpp.bak +++ b/src/tile16.cpp.bak @@ -209,7 +209,7 @@ inline void WRITE_4PIXELSHI16_FLIPPED (uint32 Offset, uint8 *Pixels) #undef FN } -INLINE void WRITE_4PIXELS16x2 (uint32 Offset, uint8 *Pixels) +static INLINE void WRITE_4PIXELS16x2 (uint32 Offset, uint8 *Pixels) { register uint32 Pixel; uint16 *Screen = (uint16 *) GFX.S + Offset; @@ -229,7 +229,7 @@ INLINE void WRITE_4PIXELS16x2 (uint32 Offset, uint8 *Pixels) #undef FN } -INLINE void WRITE_4PIXELS16_FLIPPEDx2 (uint32 Offset, uint8 *Pixels) +static INLINE void WRITE_4PIXELS16_FLIPPEDx2 (uint32 Offset, uint8 *Pixels) { register uint32 Pixel; uint16 *Screen = (uint16 *) GFX.S + Offset; @@ -249,7 +249,7 @@ INLINE void WRITE_4PIXELS16_FLIPPEDx2 (uint32 Offset, uint8 *Pixels) #undef FN } -INLINE void WRITE_4PIXELS16x2x2 (uint32 Offset, uint8 *Pixels) +static INLINE void WRITE_4PIXELS16x2x2 (uint32 Offset, uint8 *Pixels) { register uint32 Pixel; uint16 *Screen = (uint16 *) GFX.S + Offset; @@ -271,7 +271,7 @@ INLINE void WRITE_4PIXELS16x2x2 (uint32 Offset, uint8 *Pixels) #undef FN } -INLINE void WRITE_4PIXELS16_FLIPPEDx2x2 (uint32 Offset, uint8 *Pixels) +static INLINE void WRITE_4PIXELS16_FLIPPEDx2x2 (uint32 Offset, uint8 *Pixels) { register uint32 Pixel; uint16 *Screen = (uint16 *) GFX.S + Offset; @@ -300,7 +300,7 @@ void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) if (Tile & V_FLIP){ if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" #define FN(p, p2, p3, p4) \ " ldrb r9, [%[depth], #" p "] \n"\ @@ -346,7 +346,7 @@ if (Tile & V_FLIP){ : "r9", "r8", "cc" // r8 & flags ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" #define FN1(p, p2, p3, p4, p5, p6) \ " ldrb r9, [%[depth], #" p "] \n"\ @@ -394,7 +394,7 @@ if (Tile & V_FLIP){ } } else { if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" FN("0", "0", "1", "2") FN("2", "4", "3", "6") @@ -420,7 +420,7 @@ if (Tile & V_FLIP){ : "r9", "r8", "cc" // r8 & flags ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" FN1("0", "0", "7", "1", "2", "6") FN1("2", "4", "5", "3", "6", "4") @@ -466,7 +466,7 @@ Offset = Offset + StartPixel; if (Tile & V_FLIP){ if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" #define FN(p) \ " ldrb r9, [%[depth], #" p "] \n"\ @@ -519,7 +519,7 @@ if (Tile & V_FLIP){ : "r9", "cc" // r8 & flags ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" #define FN1(p) \ " ldrb r9, [%[depth], #" p "] \n"\ @@ -571,7 +571,7 @@ if (Tile & V_FLIP){ } } else { if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" FN("0") C("0") @@ -610,7 +610,7 @@ if (Tile & V_FLIP){ : "r9", "cc" // r8 & flags ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" FN1("0") C("0") diff --git a/src/tile16_t.h b/src/tile16_t.h index f4a0a57..cda914f 100644 --- a/src/tile16_t.h +++ b/src/tile16_t.h @@ -80,7 +80,7 @@ DEC_DRAWNOZ(ROPNAME) if (Tile & V_FLIP){ if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" ROW("#8") @@ -106,7 +106,7 @@ DEC_DRAWNOZ(ROPNAME) : "r8", "r9", "r10", "cc" ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" ROW1("#8") @@ -132,7 +132,7 @@ DEC_DRAWNOZ(ROPNAME) } } else { if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" ROW("#8") @@ -156,7 +156,7 @@ DEC_DRAWNOZ(ROPNAME) : "r8", "r9", "r10", "cc" ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" ROW1("#8") @@ -268,7 +268,7 @@ DEC_DRAW(ROPNAME) if (Tile & V_FLIP){ if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" ROW("#8") @@ -294,7 +294,7 @@ DEC_DRAW(ROPNAME) : "r8", "r9", "r10", "cc" ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" ROW1("#8") @@ -320,7 +320,7 @@ DEC_DRAW(ROPNAME) } } else { if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" ROW("#8") @@ -344,7 +344,7 @@ DEC_DRAW(ROPNAME) : "r8", "r9", "r10", "cc" ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" ROW1("#8") @@ -384,7 +384,7 @@ if (Width == 0) return; Offset = Offset + StartPixel; if (Tile & V_FLIP){ if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" ROW("%[width]") @@ -418,7 +418,7 @@ if (Tile & V_FLIP){ : "r8", "r9", "r10", "cc" ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" ROW1("%[width]") // Loop @@ -452,7 +452,7 @@ if (Tile & V_FLIP){ } } else { if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" ROW("%[width]") // Loop @@ -484,7 +484,7 @@ if (Tile & V_FLIP){ : "r8", "r9", "r10", "cc" ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" ROW1("%[width]") // Loop diff --git a/src/tile16add.c b/src/tile16add.c new file mode 100644 index 0000000..2211644 --- /dev/null +++ b/src/tile16add.c @@ -0,0 +1,48 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +// ARM V5 Assembly by bitrider + +#include "rops.h" +#define ROPNAME Add +#define ROP ROP_ADD(r9, r8) + +#include "tile16_t.h" diff --git a/src/tile16add.cpp b/src/tile16add.cpp deleted file mode 100644 index 2211644..0000000 --- a/src/tile16add.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -// ARM V5 Assembly by bitrider - -#include "rops.h" -#define ROPNAME Add -#define ROP ROP_ADD(r9, r8) - -#include "tile16_t.h" diff --git a/src/tile16add1_2.c b/src/tile16add1_2.c new file mode 100644 index 0000000..ad52769 --- /dev/null +++ b/src/tile16add1_2.c @@ -0,0 +1,48 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +// ARM V5 Assembly by bitrider + +#include "rops.h" +#define ROPNAME Add1_2 +#define ROP ROP_ADD1_2(r9, r8) + +#include "tile16_t.h" diff --git a/src/tile16add1_2.cpp b/src/tile16add1_2.cpp deleted file mode 100644 index ad52769..0000000 --- a/src/tile16add1_2.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -// ARM V5 Assembly by bitrider - -#include "rops.h" -#define ROPNAME Add1_2 -#define ROP ROP_ADD1_2(r9, r8) - -#include "tile16_t.h" diff --git a/src/tile16f_t.h b/src/tile16f_t.h index 493f76f..5aac300 100644 --- a/src/tile16f_t.h +++ b/src/tile16f_t.h @@ -87,7 +87,7 @@ DEC_DRAW(ROPNAME) if (Tile & V_FLIP){ if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" ROW("#8") @@ -113,7 +113,7 @@ DEC_DRAW(ROPNAME) : "r8", "r9", "r10", "cc" ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" ROW1("#8") @@ -139,7 +139,7 @@ DEC_DRAW(ROPNAME) } } else { if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" ROW("#8") @@ -163,7 +163,7 @@ DEC_DRAW(ROPNAME) : "r8", "r9", "r10", "cc" ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" ROW1("#8") @@ -203,7 +203,7 @@ if (Width == 0) return; Offset = Offset + StartPixel; if (Tile & V_FLIP){ if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" ROW("%[width]") @@ -237,7 +237,7 @@ if (Tile & V_FLIP){ : "r8", "r9", "r10", "cc" ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" ROW1("%[width]") // Loop @@ -271,7 +271,7 @@ if (Tile & V_FLIP){ } } else { if (!(Tile & H_FLIP)){ - asm volatile ( + __asm__ volatile ( "2: \n" ROW("%[width]") // Loop @@ -303,7 +303,7 @@ if (Tile & V_FLIP){ : "r8", "r9", "r10", "cc" ); } else { - asm volatile ( + __asm__ volatile ( "2: \n" ROW1("%[width]") // Loop diff --git a/src/tile16fadd1_2.c b/src/tile16fadd1_2.c new file mode 100644 index 0000000..752416b --- /dev/null +++ b/src/tile16fadd1_2.c @@ -0,0 +1,61 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +// ARM V5 Assembly by bitrider + +#define FIXEDCOLOUR (GFX.FixedColour & (~0x01860)) + +#define ROPNAME FixedAdd1_2 + +#define ROP \ + " bic r9, r9, #0b00000100000100000 \n"\ + " bic r9, r9, #0b00001000001000000 \n"\ + " add r9, r9, %[fixedcolour] \n"\ + " mov r9, r9, lsr #1 \n"\ + " tst r9, #0b00000000000100000 \n"\ + " orrne r9, r9, #0b00000000000011111 \n"\ + " tst r9, #0b00000100000000000 \n"\ + " orrne r9, r9, #0b00000011111100000 \n"\ + " tst r9, #0b10000000000000000 \n"\ + " orrne r9, r9, #0b01111100000000000 \n" + + +#include "tile16f_t.h" diff --git a/src/tile16fadd1_2.cpp b/src/tile16fadd1_2.cpp deleted file mode 100644 index 752416b..0000000 --- a/src/tile16fadd1_2.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -// ARM V5 Assembly by bitrider - -#define FIXEDCOLOUR (GFX.FixedColour & (~0x01860)) - -#define ROPNAME FixedAdd1_2 - -#define ROP \ - " bic r9, r9, #0b00000100000100000 \n"\ - " bic r9, r9, #0b00001000001000000 \n"\ - " add r9, r9, %[fixedcolour] \n"\ - " mov r9, r9, lsr #1 \n"\ - " tst r9, #0b00000000000100000 \n"\ - " orrne r9, r9, #0b00000000000011111 \n"\ - " tst r9, #0b00000100000000000 \n"\ - " orrne r9, r9, #0b00000011111100000 \n"\ - " tst r9, #0b10000000000000000 \n"\ - " orrne r9, r9, #0b01111100000000000 \n" - - -#include "tile16f_t.h" diff --git a/src/tile16fsub1_2.c b/src/tile16fsub1_2.c new file mode 100644 index 0000000..b7f2adb --- /dev/null +++ b/src/tile16fsub1_2.c @@ -0,0 +1,87 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +#ifdef ARM_ASM +/* ARM V5 Assembly by bitrider */ + +#define FIXEDCOLOUR ((GFX.FixedColour >> 1) & (~0x0C30)) +#define ROPNAME FixedSub1_2 +#define ROP \ + " mov r9, r9, lsr #1 \n"\ + " bic r9, r9, #0b00000010000010000 \n"\ + \ + " bic r8, r8, #0b00000100000100000 \n"\ + " orr r9, r9, #0b00000100000100000 \n"\ + " orr r9, r9, #0b10000000000000000 \n"\ + " sub r9, r9, %[fixedcolour] \n"\ + " tst r9, #0b00000000000100000 \n"\ + " biceq r9, r9, #0b00000000000011111 \n"\ + " tst r9, #0b00000100000000000 \n"\ + " biceq r9, r9, #0b00000011111100000 \n"\ + " tst r9, #0b10000000000000000 \n"\ + " biceq r9, r9, #0b01111100000000000 \n"\ + + +#include "tile16f_t.h" + +#else + +void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, + uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) +} + +void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + register uint8 *bp; + + TILE_CLIP_PREAMBLE + RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, + WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) +} +#endif diff --git a/src/tile16fsub1_2.cpp b/src/tile16fsub1_2.cpp deleted file mode 100644 index b7f2adb..0000000 --- a/src/tile16fsub1_2.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -#ifdef ARM_ASM -/* ARM V5 Assembly by bitrider */ - -#define FIXEDCOLOUR ((GFX.FixedColour >> 1) & (~0x0C30)) -#define ROPNAME FixedSub1_2 -#define ROP \ - " mov r9, r9, lsr #1 \n"\ - " bic r9, r9, #0b00000010000010000 \n"\ - \ - " bic r8, r8, #0b00000100000100000 \n"\ - " orr r9, r9, #0b00000100000100000 \n"\ - " orr r9, r9, #0b10000000000000000 \n"\ - " sub r9, r9, %[fixedcolour] \n"\ - " tst r9, #0b00000000000100000 \n"\ - " biceq r9, r9, #0b00000000000011111 \n"\ - " tst r9, #0b00000100000000000 \n"\ - " biceq r9, r9, #0b00000011111100000 \n"\ - " tst r9, #0b10000000000000000 \n"\ - " biceq r9, r9, #0b01111100000000000 \n"\ - - -#include "tile16f_t.h" - -#else - -void DrawTile16FixedSub1_2 (uint32 Tile, uint32 Offset, uint32 StartLine, - uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - RENDER_TILE(WRITE_4PIXELS16_SUBF1_2, WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) -} - -void DrawClippedTile16FixedSub1_2 (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - register uint8 *bp; - - TILE_CLIP_PREAMBLE - RENDER_CLIPPED_TILE(WRITE_4PIXELS16_SUBF1_2, - WRITE_4PIXELS16_FLIPPED_SUBF1_2, 4) -} -#endif diff --git a/src/tile16noprio.c b/src/tile16noprio.c new file mode 100644 index 0000000..4f3eabe --- /dev/null +++ b/src/tile16noprio.c @@ -0,0 +1,403 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +// ARM V5 Assembly by bitrider + + +#include "snes9x.h" + +#include "memmap.h" +#include "ppu.h" +#include "display.h" + #include "gfx.h" +#include "tile16.h" + +extern uint32 HeadMask [4]; +extern uint32 TailMask [5]; + +extern uint8 ConvertTile (uint8 *pCache, uint32 TileAddr); + +// DrawTile16 ----------------------------------------- +void DrawTile16NoPrio (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) +{ + TILE_PREAMBLE + +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" +#define FN(p, p2, p3, p4) \ + " ldrb r9, [%[bp], #" p "] \n"\ + " ldrb r8, [%[bp], #" p3 "] \n"\ + " movs r9, r9, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #" p "] \n"\ + " strneh r9, [%[screen], #" p2 "] \n"\ + "3: \n"\ + " movs r9, r8, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #" p3 "] \n"\ + " strneh r9, [%[screen], #" p4 "] \n"\ + "3: \n" + + FN("0", "0", "1", "2") + FN("2", "4", "3", "6") + FN("4", "8", "5", "10") + FN("6", "12", "7", "14") + // Loop + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + 56 - StartLine) + // clobbered + : "r9", "r8", "cc" // r8 & flags + ); + } else { + __asm__ volatile ( + "2: \n" +#define FN1(p, p2, p3, p4, p5, p6) \ + " ldrb r9, [%[bp], #" p3 "] \n"\ + " ldrb r8, [%[bp], #" p6 "] \n"\ + " movs r9, r9, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #" p "] \n"\ + " strneh r9, [%[screen], #" p2 "] \n"\ + "3: \n"\ + " movs r9, r8, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #" p4 "] \n"\ + " strneh r9, [%[screen], #" p5 "] \n"\ + "3: \n" + + FN1("0", "0", "7", "1", "2", "6") + FN1("2", "4", "5", "3", "6", "4") + FN1("4", "8", "3", "5", "10", "2") + FN1("6", "12", "1", "7", "14", "0") + // Loop + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + 56 - StartLine) + // clobbered + : "r9", "r8", "cc" // r8 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN("0", "0", "1", "2") + FN("2", "4", "3", "6") + FN("4", "8", "5", "10") + FN("6", "12", "7", "14") + // Loop + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + StartLine) + // clobbered + : "r9", "r8", "cc" // r8 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1("0", "0", "7", "1", "2", "6") + FN1("2", "4", "5", "3", "6", "4") + FN1("4", "8", "3", "5", "10", "2") + FN1("6", "12", "1", "7", "14", "0") + // Loop + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [bp] "r" (pCache + StartLine) + // clobbered + : "r9", "r8", "cc" // r8 & flags + ); + + } + } +#undef FN +#undef FN1 + +} + +// DrawClippedTile16NoPrio ----------------------------------------- +void DrawClippedTile16NoPrio (uint32 Tile, uint32 Offset, + uint32 StartPixel, uint32 Width, + uint32 StartLine, uint32 LineCount) +{ +if (Width == 0) return; + + TILE_PREAMBLE + +Offset = Offset + StartPixel; + +if (Tile & V_FLIP){ + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" +#define FN(p) \ + " ldrb r9, [%[bp], #" p "] \n"\ + " movs r9, r9, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #" p "] \n"\ + " strneh r9, [%[screen], #(" p " * 2)] \n"\ + "3: \n" + +#define C(p) " cmp %[width], #(" p " + 1) \n"\ + " beq 1f \n" + + FN("0") + C("0") + FN("1") + C("1") + FN("2") + C("2") + FN("3") + C("3") + FN("4") + C("4") + FN("5") + C("5") + FN("6") + C("6") + FN("7") + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine + StartPixel) + // clobbered + : "r9", "cc" // r8 & flags + ); + } else { + __asm__ volatile ( + "2: \n" +#define FN1(p) \ + " ldrb r9, [%[bp], #(7 - " p ")] \n"\ + " movs r9, r9, lsl #2 \n"\ + " ldrne r9, [%[colors], r9] \n"\ + " strneb %[gfx_z2], [%[depth], #" p "] \n"\ + " strneh r9, [%[screen], #(" p " * 2)] \n"\ + "3: \n"\ + + FN1("0") + C("0") + FN1("1") + C("1") + FN1("2") + C("2") + FN1("3") + C("3") + FN1("4") + C("4") + FN1("5") + C("5") + FN1("6") + C("6") + FN1("7") + // Loop + "1: \n" + " sub %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + 56 - StartLine - StartPixel) + // clobbered + : "r9", "cc" // r8 & flags + ); + } +} else { + if (!(Tile & H_FLIP)){ + __asm__ volatile ( + "2: \n" + FN("0") + C("0") + FN("1") + C("1") + FN("2") + C("2") + FN("3") + C("3") + FN("4") + C("4") + FN("5") + C("5") + FN("6") + C("6") + FN("7") + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine + StartPixel) + // clobbered + : "r9", "cc" // r8 & flags + ); + } else { + __asm__ volatile ( + "2: \n" + FN1("0") + C("0") + FN1("1") + C("1") + FN1("2") + C("2") + FN1("3") + C("3") + FN1("4") + C("4") + FN1("5") + C("5") + FN1("6") + C("6") + FN1("7") + // Loop + "1: \n" + " add %[bp], %[bp], #8 \n" + " add %[screen], %[screen], #640 \n" + " add %[depth], %[depth], #320 \n" + " subs %[lcount], %[lcount], #1 \n" + " bne 2b" + // output + : // none + // input + : [lcount] "r" (LineCount), + [gfx_z1] "r" (GFX.Z1), + [gfx_z2] "r" (GFX.Z2), + [screen] "r" ((uint16 *) GFX.S + Offset), + [colors] "r" (GFX.ScreenColors), + [depth] "r" (GFX.DB + Offset), + [width] "r" (Width), + [bp] "r" (pCache + StartLine - StartPixel) + // clobbered + : "r9", "cc" // r8 & flags + ); + + } + } +#undef FN +#undef FN1 +#undef C + +} + diff --git a/src/tile16noprio.cpp b/src/tile16noprio.cpp deleted file mode 100644 index 00da0dc..0000000 --- a/src/tile16noprio.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -// ARM V5 Assembly by bitrider - - -#include "snes9x.h" - -#include "memmap.h" -#include "ppu.h" -#include "display.h" - #include "gfx.h" -#include "tile16.h" - -extern uint32 HeadMask [4]; -extern uint32 TailMask [5]; - -extern uint8 ConvertTile (uint8 *pCache, uint32 TileAddr); - -// DrawTile16 ----------------------------------------- -void DrawTile16NoPrio (uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount) -{ - TILE_PREAMBLE - -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" -#define FN(p, p2, p3, p4) \ - " ldrb r9, [%[bp], #" p "] \n"\ - " ldrb r8, [%[bp], #" p3 "] \n"\ - " movs r9, r9, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #" p "] \n"\ - " strneh r9, [%[screen], #" p2 "] \n"\ - "3: \n"\ - " movs r9, r8, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #" p3 "] \n"\ - " strneh r9, [%[screen], #" p4 "] \n"\ - "3: \n" - - FN("0", "0", "1", "2") - FN("2", "4", "3", "6") - FN("4", "8", "5", "10") - FN("6", "12", "7", "14") - // Loop - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + 56 - StartLine) - // clobbered - : "r9", "r8", "cc" // r8 & flags - ); - } else { - asm volatile ( - "2: \n" -#define FN1(p, p2, p3, p4, p5, p6) \ - " ldrb r9, [%[bp], #" p3 "] \n"\ - " ldrb r8, [%[bp], #" p6 "] \n"\ - " movs r9, r9, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #" p "] \n"\ - " strneh r9, [%[screen], #" p2 "] \n"\ - "3: \n"\ - " movs r9, r8, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #" p4 "] \n"\ - " strneh r9, [%[screen], #" p5 "] \n"\ - "3: \n" - - FN1("0", "0", "7", "1", "2", "6") - FN1("2", "4", "5", "3", "6", "4") - FN1("4", "8", "3", "5", "10", "2") - FN1("6", "12", "1", "7", "14", "0") - // Loop - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + 56 - StartLine) - // clobbered - : "r9", "r8", "cc" // r8 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN("0", "0", "1", "2") - FN("2", "4", "3", "6") - FN("4", "8", "5", "10") - FN("6", "12", "7", "14") - // Loop - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + StartLine) - // clobbered - : "r9", "r8", "cc" // r8 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1("0", "0", "7", "1", "2", "6") - FN1("2", "4", "5", "3", "6", "4") - FN1("4", "8", "3", "5", "10", "2") - FN1("6", "12", "1", "7", "14", "0") - // Loop - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [bp] "r" (pCache + StartLine) - // clobbered - : "r9", "r8", "cc" // r8 & flags - ); - - } - } -#undef FN -#undef FN1 - -} - -// DrawClippedTile16NoPrio ----------------------------------------- -void DrawClippedTile16NoPrio (uint32 Tile, uint32 Offset, - uint32 StartPixel, uint32 Width, - uint32 StartLine, uint32 LineCount) -{ -if (Width == 0) return; - - TILE_PREAMBLE - -Offset = Offset + StartPixel; - -if (Tile & V_FLIP){ - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" -#define FN(p) \ - " ldrb r9, [%[bp], #" p "] \n"\ - " movs r9, r9, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #" p "] \n"\ - " strneh r9, [%[screen], #(" p " * 2)] \n"\ - "3: \n" - -#define C(p) " cmp %[width], #(" p " + 1) \n"\ - " beq 1f \n" - - FN("0") - C("0") - FN("1") - C("1") - FN("2") - C("2") - FN("3") - C("3") - FN("4") - C("4") - FN("5") - C("5") - FN("6") - C("6") - FN("7") - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine + StartPixel) - // clobbered - : "r9", "cc" // r8 & flags - ); - } else { - asm volatile ( - "2: \n" -#define FN1(p) \ - " ldrb r9, [%[bp], #(7 - " p ")] \n"\ - " movs r9, r9, lsl #2 \n"\ - " ldrne r9, [%[colors], r9] \n"\ - " strneb %[gfx_z2], [%[depth], #" p "] \n"\ - " strneh r9, [%[screen], #(" p " * 2)] \n"\ - "3: \n"\ - - FN1("0") - C("0") - FN1("1") - C("1") - FN1("2") - C("2") - FN1("3") - C("3") - FN1("4") - C("4") - FN1("5") - C("5") - FN1("6") - C("6") - FN1("7") - // Loop - "1: \n" - " sub %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + 56 - StartLine - StartPixel) - // clobbered - : "r9", "cc" // r8 & flags - ); - } -} else { - if (!(Tile & H_FLIP)){ - asm volatile ( - "2: \n" - FN("0") - C("0") - FN("1") - C("1") - FN("2") - C("2") - FN("3") - C("3") - FN("4") - C("4") - FN("5") - C("5") - FN("6") - C("6") - FN("7") - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine + StartPixel) - // clobbered - : "r9", "cc" // r8 & flags - ); - } else { - asm volatile ( - "2: \n" - FN1("0") - C("0") - FN1("1") - C("1") - FN1("2") - C("2") - FN1("3") - C("3") - FN1("4") - C("4") - FN1("5") - C("5") - FN1("6") - C("6") - FN1("7") - // Loop - "1: \n" - " add %[bp], %[bp], #8 \n" - " add %[screen], %[screen], #640 \n" - " add %[depth], %[depth], #320 \n" - " subs %[lcount], %[lcount], #1 \n" - " bne 2b" - // output - : // none - // input - : [lcount] "r" (LineCount), - [gfx_z1] "r" (GFX.Z1), - [gfx_z2] "r" (GFX.Z2), - [screen] "r" ((uint16 *) GFX.S + Offset), - [colors] "r" (GFX.ScreenColors), - [depth] "r" (GFX.DB + Offset), - [width] "r" (Width), - [bp] "r" (pCache + StartLine - StartPixel) - // clobbered - : "r9", "cc" // r8 & flags - ); - - } - } -#undef FN -#undef FN1 -#undef C - -} - diff --git a/src/tile16sub.c b/src/tile16sub.c new file mode 100644 index 0000000..9066e23 --- /dev/null +++ b/src/tile16sub.c @@ -0,0 +1,48 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +// ARM V5 Assembly by bitrider + +#include "rops.h" +#define ROPNAME Sub +#define ROP ROP_SUB(r9, r8) + +#include "tile16_t.h" diff --git a/src/tile16sub.cpp b/src/tile16sub.cpp deleted file mode 100644 index 9066e23..0000000 --- a/src/tile16sub.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -// ARM V5 Assembly by bitrider - -#include "rops.h" -#define ROPNAME Sub -#define ROP ROP_SUB(r9, r8) - -#include "tile16_t.h" diff --git a/src/tile16sub1_2.c b/src/tile16sub1_2.c new file mode 100644 index 0000000..0adaa0c --- /dev/null +++ b/src/tile16sub1_2.c @@ -0,0 +1,50 @@ +/* + * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + * + * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and + * Jerremy Koot (jkoot@snes9x.com) + * + * Super FX C emulator code + * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and + * Gary Henderson. + * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. + * + * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. + * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. + * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). + * + * DOS port code contains the works of other authors. See headers in + * individual files. + * + * Snes9x homepage: http://www.snes9x.com + * + * Permission to use, copy, modify and distribute Snes9x in both binary and + * source form, for non-commercial purposes, is hereby granted without fee, + * providing that this license information and copyright notice appear with + * all copies and any derived work. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event shall the authors be held liable for any damages + * arising from the use of this software. + * + * Snes9x is freeware for PERSONAL USE only. Commercial users should + * seek permission of the copyright holders first. Commercial use includes + * charging money for Snes9x or software derived from Snes9x. + * + * The copyright holders request that bug fixes and improvements to the code + * should be forwarded to them so everyone can benefit from the modifications + * in future versions. + * + * Super NES and Super Nintendo Entertainment System are trademarks of + * Nintendo Co., Limited and its subsidiary companies. + */ + +// ARM V5 Assembly by bitrider + +#include "rops.h" +#define ROPNAME Sub1_2 +#define ROP ROP_SUB1_2(r9, r8) + +#include "tile16_t.h" + + diff --git a/src/tile16sub1_2.cpp b/src/tile16sub1_2.cpp deleted file mode 100644 index 0adaa0c..0000000 --- a/src/tile16sub1_2.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - * - * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and - * Jerremy Koot (jkoot@snes9x.com) - * - * Super FX C emulator code - * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and - * Gary Henderson. - * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. - * - * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. - * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. - * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). - * - * DOS port code contains the works of other authors. See headers in - * individual files. - * - * Snes9x homepage: http://www.snes9x.com - * - * Permission to use, copy, modify and distribute Snes9x in both binary and - * source form, for non-commercial purposes, is hereby granted without fee, - * providing that this license information and copyright notice appear with - * all copies and any derived work. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event shall the authors be held liable for any damages - * arising from the use of this software. - * - * Snes9x is freeware for PERSONAL USE only. Commercial users should - * seek permission of the copyright holders first. Commercial use includes - * charging money for Snes9x or software derived from Snes9x. - * - * The copyright holders request that bug fixes and improvements to the code - * should be forwarded to them so everyone can benefit from the modifications - * in future versions. - * - * Super NES and Super Nintendo Entertainment System are trademarks of - * Nintendo Co., Limited and its subsidiary companies. - */ - -// ARM V5 Assembly by bitrider - -#include "rops.h" -#define ROPNAME Sub1_2 -#define ROP ROP_SUB1_2(r9, r8) - -#include "tile16_t.h" - - -- cgit v1.2.3