commit d1666860e082aa4e5f2f72420f98c8be528f29b6 Author: OV2 Date: Sat Sep 25 17:46:12 2010 +0200 Initial 1.52 import diff --git a/65c816.h b/65c816.h new file mode 100644 index 00000000..995fcbbb --- /dev/null +++ b/65c816.h @@ -0,0 +1,276 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _65C816_H_ +#define _65C816_H_ + +#define Carry 1 +#define Zero 2 +#define IRQ 4 +#define Decimal 8 +#define IndexFlag 16 +#define MemoryFlag 32 +#define Overflow 64 +#define Negative 128 +#define Emulation 256 + +#define SetCarry() (ICPU._Carry = 1) +#define ClearCarry() (ICPU._Carry = 0) +#define SetZero() (ICPU._Zero = 0) +#define ClearZero() (ICPU._Zero = 1) +#define SetIRQ() (Registers.PL |= IRQ) +#define ClearIRQ() (Registers.PL &= ~IRQ) +#define SetDecimal() (Registers.PL |= Decimal) +#define ClearDecimal() (Registers.PL &= ~Decimal) +#define SetIndex() (Registers.PL |= IndexFlag) +#define ClearIndex() (Registers.PL &= ~IndexFlag) +#define SetMemory() (Registers.PL |= MemoryFlag) +#define ClearMemory() (Registers.PL &= ~MemoryFlag) +#define SetOverflow() (ICPU._Overflow = 1) +#define ClearOverflow() (ICPU._Overflow = 0) +#define SetNegative() (ICPU._Negative = 0x80) +#define ClearNegative() (ICPU._Negative = 0) + +#define CheckCarry() (ICPU._Carry) +#define CheckZero() (ICPU._Zero == 0) +#define CheckIRQ() (Registers.PL & IRQ) +#define CheckDecimal() (Registers.PL & Decimal) +#define CheckIndex() (Registers.PL & IndexFlag) +#define CheckMemory() (Registers.PL & MemoryFlag) +#define CheckOverflow() (ICPU._Overflow) +#define CheckNegative() (ICPU._Negative & 0x80) +#define CheckEmulation() (Registers.P.W & Emulation) + +#define SetFlags(f) (Registers.P.W |= (f)) +#define ClearFlags(f) (Registers.P.W &= ~(f)) +#define CheckFlag(f) (Registers.PL & (f)) + +typedef union +{ +#ifdef LSB_FIRST + struct { uint8 l, h; } B; +#else + struct { uint8 h, l; } B; +#endif + uint16 W; +} pair; + +typedef union +{ +#ifdef LSB_FIRST + struct { uint8 xPCl, xPCh, xPB, z; } B; + struct { uint16 xPC, d; } W; +#else + struct { uint8 z, xPB, xPCh, xPCl; } B; + struct { uint16 d, xPC; } W; +#endif + uint32 xPBPC; +} PC_t; + +struct SRegisters +{ + uint8 DB; + pair P; + pair A; + pair D; + pair S; + pair X; + pair Y; + PC_t PC; +}; + +#define AL A.B.l +#define AH A.B.h +#define XL X.B.l +#define XH X.B.h +#define YL Y.B.l +#define YH Y.B.h +#define SL S.B.l +#define SH S.B.h +#define DL D.B.l +#define DH D.B.h +#define PL P.B.l +#define PH P.B.h +#define PBPC PC.xPBPC +#define PCw PC.W.xPC +#define PCh PC.B.xPCh +#define PCl PC.B.xPCl +#define PB PC.B.xPB + +extern struct SRegisters Registers; + +#endif diff --git a/apu/SNES_SPC.cpp b/apu/SNES_SPC.cpp new file mode 100644 index 00000000..7f4f9b7d --- /dev/null +++ b/apu/SNES_SPC.cpp @@ -0,0 +1,564 @@ +// Core SPC emulation: CPU, timers, SMP registers, memory + +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "SNES_SPC.h" + +#include + +/* Copyright (C) 2004-2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +#define RAM (m.ram.ram) +#define REGS (m.smp_regs [0]) +#define REGS_IN (m.smp_regs [1]) + +// (n ? n : 256) +#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) + +// Note: SPC_MORE_ACCURACY exists mainly so I can run my validation tests, which +// do crazy echo buffer accesses. +#ifndef SPC_MORE_ACCURACY + #define SPC_MORE_ACCURACY 0 +#endif + +#ifdef BLARGG_ENABLE_OPTIMIZER + #include BLARGG_ENABLE_OPTIMIZER +#endif + + +//// Timers + +#if SPC_DISABLE_TEMPO + #define TIMER_DIV( t, n ) ((n) >> t->prescaler) + #define TIMER_MUL( t, n ) ((n) << t->prescaler) +#else + #define TIMER_DIV( t, n ) ((n) / t->prescaler) + #define TIMER_MUL( t, n ) ((n) * t->prescaler) +#endif + +SNES_SPC::Timer* SNES_SPC::run_timer_( Timer* t, rel_time_t time ) +{ + int elapsed = TIMER_DIV( t, time - t->next_time ) + 1; + t->next_time += TIMER_MUL( t, elapsed ); + + if ( t->enabled ) + { + int remain = IF_0_THEN_256( t->period - t->divider ); + int divider = t->divider + elapsed; + int over = elapsed - remain; + if ( over >= 0 ) + { + int n = over / t->period; + t->counter = (t->counter + 1 + n) & 0x0F; + divider = over - n * t->period; + } + t->divider = (uint8_t) divider; + } + return t; +} + +inline SNES_SPC::Timer* SNES_SPC::run_timer( Timer* t, rel_time_t time ) +{ + if ( time >= t->next_time ) + t = run_timer_( t, time ); + return t; +} + + +//// ROM + +void SNES_SPC::enable_rom( int enable ) +{ + if ( m.rom_enabled != enable ) + { + m.rom_enabled = enable; + if ( enable ) + memcpy( m.hi_ram, &RAM [rom_addr], sizeof m.hi_ram ); + memcpy( &RAM [rom_addr], (enable ? m.rom : m.hi_ram), rom_size ); + // TODO: ROM can still get overwritten when DSP writes to echo buffer + } +} + + +//// DSP + +#if SPC_LESS_ACCURATE + int const max_reg_time = 29; + + signed char const SNES_SPC::reg_times_ [256] = + { + -1, 0,-11,-10,-15,-11, -2, -2, 4, 3, 14, 14, 26, 26, 14, 22, + 2, 3, 0, 1,-12, 0, 1, 1, 7, 6, 14, 14, 27, 14, 14, 23, + 5, 6, 3, 4, -1, 3, 4, 4, 10, 9, 14, 14, 26, -5, 14, 23, + 8, 9, 6, 7, 2, 6, 7, 7, 13, 12, 14, 14, 27, -4, 14, 24, + 11, 12, 9, 10, 5, 9, 10, 10, 16, 15, 14, 14, -2, -4, 14, 24, + 14, 15, 12, 13, 8, 12, 13, 13, 19, 18, 14, 14, -2,-36, 14, 24, + 17, 18, 15, 16, 11, 15, 16, 16, 22, 21, 14, 14, 28, -3, 14, 25, + 20, 21, 18, 19, 14, 18, 19, 19, 25, 24, 14, 14, 14, 29, 14, 25, + + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + }; + + #define RUN_DSP( time, offset ) \ + int count = (time) - (offset) - m.dsp_time;\ + if ( count >= 0 )\ + {\ + int clock_count = (count & ~(clocks_per_sample - 1)) + clocks_per_sample;\ + m.dsp_time += clock_count;\ + dsp.run( clock_count );\ + } +#else + #define RUN_DSP( time, offset ) \ + {\ + int count = (time) - m.dsp_time;\ + if ( !SPC_MORE_ACCURACY || count )\ + {\ + assert( count > 0 );\ + m.dsp_time = (time);\ + dsp.run( count );\ + }\ + } +#endif + +int SNES_SPC::dsp_read( rel_time_t time ) +{ + RUN_DSP( time, reg_times [REGS [r_dspaddr] & 0x7F] ); + + int result = dsp.read( REGS [r_dspaddr] & 0x7F ); + + #ifdef SPC_DSP_READ_HOOK + SPC_DSP_READ_HOOK( spc_time + time, (REGS [r_dspaddr] & 0x7F), result ); + #endif + + return result; +} + +inline void SNES_SPC::dsp_write( int data, rel_time_t time ) +{ + RUN_DSP( time, reg_times [REGS [r_dspaddr]] ) + #if SPC_LESS_ACCURATE + else if ( m.dsp_time == skipping_time ) + { + int r = REGS [r_dspaddr]; + if ( r == SPC_DSP::r_kon ) + m.skipped_kon |= data & ~dsp.read( SPC_DSP::r_koff ); + + if ( r == SPC_DSP::r_koff ) + { + m.skipped_koff |= data; + m.skipped_kon &= ~data; + } + } + #endif + + #ifdef SPC_DSP_WRITE_HOOK + SPC_DSP_WRITE_HOOK( m.spc_time + time, REGS [r_dspaddr], (uint8_t) data ); + #endif + + if ( REGS [r_dspaddr] <= 0x7F ) + dsp.write( REGS [r_dspaddr], data ); + else if ( !SPC_MORE_ACCURACY ) + dprintf( "SPC wrote to DSP register > $7F\n" ); +} + + +//// Memory access extras + +#if SPC_MORE_ACCURACY + #define MEM_ACCESS( time, addr ) \ + {\ + if ( time >= m.dsp_time )\ + {\ + RUN_DSP( time, max_reg_time );\ + }\ + } +#elif !defined (NDEBUG) + // Debug-only check for read/write within echo buffer, since this might result in + // inaccurate emulation due to the DSP not being caught up to the present. + + bool SNES_SPC::check_echo_access( int addr ) + { + if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) + { + int start = 0x100 * dsp.read( SPC_DSP::r_esa ); + int size = 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F); + int end = start + (size ? size : 4); + if ( start <= addr && addr < end ) + { + if ( !m.echo_accessed ) + { + m.echo_accessed = 1; + return true; + } + } + } + return false; + } + + #define MEM_ACCESS( time, addr ) check( !check_echo_access( (uint16_t) addr ) ); +#else + #define MEM_ACCESS( time, addr ) +#endif + + +//// CPU write + +#if SPC_MORE_ACCURACY +static unsigned char const glitch_probs [3] [256] = +{ + 0xC3,0x92,0x5B,0x1C,0xD1,0x92,0x5B,0x1C,0xDB,0x9C,0x72,0x18,0xCD,0x5C,0x38,0x0B, + 0xE1,0x9C,0x74,0x17,0xCF,0x75,0x45,0x0C,0xCF,0x6E,0x4A,0x0D,0xA3,0x3A,0x1D,0x08, + 0xDB,0xA0,0x82,0x19,0xD9,0x73,0x3C,0x0E,0xCB,0x76,0x52,0x0B,0xA5,0x46,0x1D,0x09, + 0xDA,0x74,0x55,0x0F,0xA2,0x3F,0x21,0x05,0x9A,0x40,0x20,0x07,0x63,0x1E,0x10,0x01, + 0xDF,0xA9,0x85,0x1D,0xD3,0x84,0x4B,0x0E,0xCF,0x6F,0x49,0x0F,0xB3,0x48,0x1E,0x05, + 0xD8,0x77,0x52,0x12,0xB7,0x49,0x23,0x06,0xAA,0x45,0x28,0x07,0x7D,0x28,0x0F,0x07, + 0xCC,0x7B,0x4A,0x0E,0xB2,0x4F,0x24,0x07,0xAD,0x43,0x2C,0x06,0x86,0x29,0x11,0x07, + 0xAE,0x48,0x1F,0x0A,0x76,0x21,0x19,0x05,0x76,0x21,0x14,0x05,0x44,0x11,0x0B,0x01, + 0xE7,0xAD,0x96,0x23,0xDC,0x86,0x59,0x0E,0xDC,0x7C,0x5F,0x15,0xBB,0x53,0x2E,0x09, + 0xD6,0x7C,0x4A,0x16,0xBB,0x4A,0x25,0x08,0xB3,0x4F,0x28,0x0B,0x8E,0x23,0x15,0x08, + 0xCF,0x7F,0x57,0x11,0xB5,0x4A,0x23,0x0A,0xAA,0x42,0x28,0x05,0x7D,0x22,0x12,0x03, + 0xA6,0x49,0x28,0x09,0x82,0x2B,0x0D,0x04,0x7A,0x20,0x0F,0x04,0x3D,0x0F,0x09,0x03, + 0xD1,0x7C,0x4C,0x0F,0xAF,0x4E,0x21,0x09,0xA8,0x46,0x2A,0x07,0x85,0x1F,0x0E,0x07, + 0xA6,0x3F,0x26,0x07,0x7C,0x24,0x14,0x07,0x78,0x22,0x16,0x04,0x46,0x12,0x0A,0x02, + 0xA6,0x41,0x2C,0x0A,0x7E,0x28,0x11,0x05,0x73,0x1B,0x14,0x05,0x3D,0x11,0x0A,0x02, + 0x70,0x22,0x17,0x05,0x48,0x13,0x08,0x03,0x3C,0x07,0x0D,0x07,0x26,0x07,0x06,0x01, + + 0xE0,0x9F,0xDA,0x7C,0x4F,0x18,0x28,0x0D,0xE9,0x9F,0xDA,0x7C,0x4F,0x18,0x1F,0x07, + 0xE6,0x97,0xD8,0x72,0x64,0x13,0x26,0x09,0xDC,0x67,0xA9,0x38,0x21,0x07,0x15,0x06, + 0xE9,0x91,0xD2,0x6B,0x63,0x14,0x2B,0x0E,0xD6,0x61,0xB7,0x41,0x2B,0x0E,0x10,0x09, + 0xCF,0x59,0xB0,0x2F,0x35,0x08,0x0F,0x07,0xB6,0x30,0x7A,0x21,0x17,0x07,0x09,0x03, + 0xE7,0xA3,0xE5,0x6B,0x65,0x1F,0x34,0x09,0xD8,0x6B,0xBE,0x45,0x27,0x07,0x10,0x07, + 0xDA,0x54,0xB1,0x39,0x2E,0x0E,0x17,0x08,0xA9,0x3C,0x86,0x22,0x16,0x06,0x07,0x03, + 0xD4,0x51,0xBC,0x3D,0x38,0x0A,0x13,0x06,0xB2,0x37,0x79,0x1C,0x17,0x05,0x0E,0x06, + 0xA7,0x31,0x74,0x1C,0x11,0x06,0x0C,0x02,0x6D,0x1A,0x38,0x10,0x0B,0x05,0x06,0x03, + 0xEB,0x9A,0xE1,0x7A,0x6F,0x13,0x34,0x0E,0xE6,0x75,0xC5,0x45,0x3E,0x0B,0x1A,0x05, + 0xD8,0x63,0xC1,0x40,0x3C,0x1B,0x19,0x06,0xB3,0x42,0x83,0x29,0x18,0x0A,0x08,0x04, + 0xD4,0x58,0xBA,0x43,0x3F,0x0A,0x1F,0x09,0xB1,0x33,0x8A,0x1F,0x1F,0x06,0x0D,0x05, + 0xAF,0x3C,0x7A,0x1F,0x16,0x08,0x0A,0x01,0x72,0x1B,0x52,0x0D,0x0B,0x09,0x06,0x01, + 0xCF,0x63,0xB7,0x47,0x40,0x10,0x14,0x06,0xC0,0x41,0x96,0x20,0x1C,0x09,0x10,0x05, + 0xA6,0x35,0x82,0x1A,0x20,0x0C,0x0E,0x04,0x80,0x1F,0x53,0x0F,0x0B,0x02,0x06,0x01, + 0xA6,0x31,0x81,0x1B,0x1D,0x01,0x08,0x08,0x7B,0x20,0x4D,0x19,0x0E,0x05,0x07,0x03, + 0x6B,0x17,0x49,0x07,0x0E,0x03,0x0A,0x05,0x37,0x0B,0x1F,0x06,0x04,0x02,0x07,0x01, + + 0xF0,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x47,0x1E,0x6E,0x1B,0x32,0x0A, + 0xF0,0xD6,0xEA,0xA4,0xED,0xC4,0xDE,0x82,0x98,0x1F,0x50,0x13,0x52,0x15,0x2A,0x0A, + 0xF1,0xD1,0xEB,0xA2,0xEB,0xB7,0xD8,0x69,0xA2,0x1F,0x5B,0x18,0x55,0x18,0x2C,0x0A, + 0xED,0xB5,0xDE,0x7E,0xE6,0x85,0xD3,0x59,0x59,0x0F,0x2C,0x09,0x24,0x07,0x15,0x09, + 0xF1,0xD6,0xEA,0xA0,0xEC,0xBB,0xDA,0x77,0xA9,0x23,0x58,0x14,0x5D,0x12,0x2F,0x09, + 0xF1,0xC1,0xE3,0x86,0xE4,0x87,0xD2,0x4E,0x68,0x15,0x26,0x0B,0x27,0x09,0x15,0x02, + 0xEE,0xA6,0xE0,0x5C,0xE0,0x77,0xC3,0x41,0x67,0x1B,0x3C,0x07,0x2A,0x06,0x19,0x07, + 0xE4,0x75,0xC6,0x43,0xCC,0x50,0x95,0x23,0x35,0x09,0x14,0x04,0x15,0x05,0x0B,0x04, + 0xEE,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x56,0x14,0x5A,0x12,0x26,0x0A, + 0xEE,0xBB,0xE7,0x7E,0xE9,0x8D,0xCB,0x49,0x67,0x11,0x34,0x07,0x2B,0x0B,0x14,0x07, + 0xED,0xA7,0xE5,0x76,0xE3,0x7E,0xC4,0x4B,0x77,0x14,0x34,0x08,0x27,0x07,0x14,0x04, + 0xE7,0x8B,0xD2,0x4C,0xCA,0x56,0x9E,0x31,0x36,0x0C,0x11,0x07,0x14,0x04,0x0A,0x02, + 0xF0,0x9B,0xEA,0x6F,0xE5,0x81,0xC4,0x43,0x74,0x10,0x30,0x0B,0x2D,0x08,0x1B,0x06, + 0xE6,0x83,0xCA,0x48,0xD9,0x56,0xA7,0x23,0x3B,0x09,0x12,0x09,0x15,0x07,0x0A,0x03, + 0xE5,0x5F,0xCB,0x3C,0xCF,0x48,0x91,0x22,0x31,0x0A,0x17,0x08,0x15,0x04,0x0D,0x02, + 0xD1,0x43,0x91,0x20,0xA9,0x2D,0x54,0x12,0x17,0x07,0x09,0x02,0x0C,0x04,0x05,0x03, +}; +#endif + +// divided into multiple functions to keep rarely-used functionality separate +// so often-used functionality can be optimized better by compiler + +// If write isn't preceded by read, data has this added to it +int const no_read_before_write = 0x2000; + +void SNES_SPC::cpu_write_smp_reg_( int data, rel_time_t time, int addr ) +{ + switch ( addr ) + { + case r_t0target: + case r_t1target: + case r_t2target: { + Timer* t = &m.timers [addr - r_t0target]; + int period = IF_0_THEN_256( data ); + if ( t->period != period ) + { + t = run_timer( t, time ); + #if SPC_MORE_ACCURACY + // Insane behavior when target is written just after counter is + // clocked and counter matches new period and new period isn't 1, 2, 4, or 8 + if ( t->divider == (period & 0xFF) && + t->next_time == time + TIMER_MUL( t, 1 ) && + ((period - 1) | ~0x0F) & period ) + { + //dprintf( "SPC pathological timer target write\n" ); + + // If the period is 3, 5, or 9, there's a probability this behavior won't occur, + // based on the previous period + int prob = 0xFF; + int old_period = t->period & 0xFF; + if ( period == 3 ) prob = glitch_probs [0] [old_period]; + if ( period == 5 ) prob = glitch_probs [1] [old_period]; + if ( period == 9 ) prob = glitch_probs [2] [old_period]; + + // The glitch suppresses incrementing of one of the counter bits, based on + // the lowest set bit in the new period + int b = 1; + while ( !(period & b) ) + b <<= 1; + + if ( (rand() >> 4 & 0xFF) <= prob ) + t->divider = (t->divider - b) & 0xFF; + } + #endif + t->period = period; + } + break; + } + + case r_t0out: + case r_t1out: + case r_t2out: + if ( !SPC_MORE_ACCURACY ) + dprintf( "SPC wrote to counter %d\n", (int) addr - r_t0out ); + + if ( data < no_read_before_write / 2 ) + run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0; + break; + + // Registers that act like RAM + case 0x8: + case 0x9: + REGS_IN [addr] = (uint8_t) data; + break; + + case r_test: + if ( (uint8_t) data != 0x0A ) + dprintf( "SPC wrote to test register\n" ); + break; + + case r_control: + // port clears + if ( data & 0x10 ) + { + REGS_IN [r_cpuio0] = 0; + REGS_IN [r_cpuio1] = 0; + } + if ( data & 0x20 ) + { + REGS_IN [r_cpuio2] = 0; + REGS_IN [r_cpuio3] = 0; + } + + // timers + { + for ( int i = 0; i < timer_count; i++ ) + { + Timer* t = &m.timers [i]; + int enabled = data >> i & 1; + if ( t->enabled != enabled ) + { + t = run_timer( t, time ); + t->enabled = enabled; + if ( enabled ) + { + t->divider = 0; + t->counter = 0; + } + } + } + } + enable_rom( data & 0x80 ); + break; + } +} + +void SNES_SPC::cpu_write_smp_reg( int data, rel_time_t time, int addr ) +{ + if ( addr == r_dspdata ) // 99% + dsp_write( data, time ); + else + cpu_write_smp_reg_( data, time, addr ); +} + +void SNES_SPC::cpu_write_high( int data, int i, rel_time_t time ) +{ + if ( i < rom_size ) + { + m.hi_ram [i] = (uint8_t) data; + if ( m.rom_enabled ) + RAM [i + rom_addr] = m.rom [i]; // restore overwritten ROM + } + else + { + assert( *(&(RAM [0]) + i + rom_addr) == (uint8_t) data ); + *(&(RAM [0]) + i + rom_addr) = cpu_pad_fill; // restore overwritten padding + cpu_write( data, i + rom_addr - 0x10000, time ); + } +} + +int const bits_in_int = CHAR_BIT * sizeof (int); + +void SNES_SPC::cpu_write( int data, int addr, rel_time_t time ) +{ + MEM_ACCESS( time, addr ) + + // RAM + RAM [addr] = (uint8_t) data; + int reg = addr - 0xF0; + if ( reg >= 0 ) // 64% + { + // $F0-$FF + if ( reg < reg_count ) // 87% + { + REGS [reg] = (uint8_t) data; + + // Ports + #ifdef SPC_PORT_WRITE_HOOK + if ( (unsigned) (reg - r_cpuio0) < port_count ) + SPC_PORT_WRITE_HOOK( m.spc_time + time, (reg - r_cpuio0), + (uint8_t) data, ®S [r_cpuio0] ); + #endif + + // Registers other than $F2 and $F4-$F7 + //if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 ) + // TODO: this is a bit on the fragile side + if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36% + cpu_write_smp_reg( data, time, reg ); + } + // High mem/address wrap-around + else + { + reg -= rom_addr - 0xF0; + if ( reg >= 0 ) // 1% in IPL ROM area or address wrapped around + cpu_write_high( data, reg, time ); + } + } +} + + +//// CPU read + +inline int SNES_SPC::cpu_read_smp_reg( int reg, rel_time_t time ) +{ + int result = REGS_IN [reg]; + reg -= r_dspaddr; + // DSP addr and data + if ( (unsigned) reg <= 1 ) // 4% 0xF2 and 0xF3 + { + result = REGS [r_dspaddr]; + if ( (unsigned) reg == 1 ) + result = dsp_read( time ); // 0xF3 + } + return result; +} + +int SNES_SPC::cpu_read( int addr, rel_time_t time ) +{ + MEM_ACCESS( time, addr ) + + // RAM + int result = RAM [addr]; + int reg = addr - 0xF0; + if ( reg >= 0 ) // 40% + { + reg -= 0x10; + if ( (unsigned) reg >= 0xFF00 ) // 21% + { + reg += 0x10 - r_t0out; + + // Timers + if ( (unsigned) reg < timer_count ) // 90% + { + Timer* t = &m.timers [reg]; + if ( time >= t->next_time ) + t = run_timer_( t, time ); + result = t->counter; + t->counter = 0; + } + // Other registers + else if ( reg < 0 ) // 10% + { + result = cpu_read_smp_reg( reg + r_t0out, time ); + } + else // 1% + { + assert( reg + (r_t0out + 0xF0 - 0x10000) < 0x100 ); + result = cpu_read( reg + (r_t0out + 0xF0 - 0x10000), time ); + } + } + } + + return result; +} + + +//// Run + +// Prefix and suffix for CPU emulator function +#define SPC_CPU_RUN_FUNC \ +BOOST::uint8_t* SNES_SPC::run_until_( time_t end_time )\ +{\ + rel_time_t rel_time = m.spc_time - end_time;\ + assert( rel_time <= 0 );\ + m.spc_time = end_time;\ + m.dsp_time += rel_time;\ + m.timers [0].next_time += rel_time;\ + m.timers [1].next_time += rel_time;\ + m.timers [2].next_time += rel_time; + +#define SPC_CPU_RUN_FUNC_END \ + m.spc_time += rel_time;\ + m.dsp_time -= rel_time;\ + m.timers [0].next_time -= rel_time;\ + m.timers [1].next_time -= rel_time;\ + m.timers [2].next_time -= rel_time;\ + assert( m.spc_time <= end_time );\ + return ®S [r_cpuio0];\ +} + +int const cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks + +void SNES_SPC::end_frame( time_t end_time ) +{ + // Catch CPU up to as close to end as possible. If final instruction + // would exceed end, does NOT execute it and leaves m.spc_time < end. + if ( end_time > m.spc_time ) + run_until_( end_time ); + + m.spc_time -= end_time; + m.extra_clocks += end_time; + + // Greatest number of clocks early that emulation can stop early due to + // not being able to execute current instruction without going over + // allowed time. + assert( -cpu_lag_max <= m.spc_time && m.spc_time <= 0 ); + + // Catch timers up to CPU + for ( int i = 0; i < timer_count; i++ ) + run_timer( &m.timers [i], 0 ); + + // Catch DSP up to CPU + if ( m.dsp_time < 0 ) + { + RUN_DSP( 0, max_reg_time ); + } + + // Save any extra samples beyond what should be generated + if ( m.buf_begin ) + save_extra(); +} + +// Inclusion here allows static memory access functions and better optimization +#include "SPC_CPU.h" diff --git a/apu/SNES_SPC.h b/apu/SNES_SPC.h new file mode 100644 index 00000000..a0868693 --- /dev/null +++ b/apu/SNES_SPC.h @@ -0,0 +1,288 @@ +// SNES SPC-700 APU emulator + +// snes_spc 0.9.0 +#ifndef SNES_SPC_H +#define SNES_SPC_H + +#include "SPC_DSP.h" +#include "blargg_endian.h" + +struct SNES_SPC { +public: + typedef BOOST::uint8_t uint8_t; + + // Must be called once before using + blargg_err_t init(); + + // Sample pairs generated per second + enum { sample_rate = 32000 }; + +// Emulator use + + // Sets IPL ROM data. Library does not include ROM data. Most SPC music files + // don't need ROM, but a full emulator must provide this. + enum { rom_size = 0x40 }; + void init_rom( uint8_t const rom [rom_size] ); + + // Sets destination for output samples + typedef short sample_t; + void set_output( sample_t* out, int out_size ); + + // Number of samples written to output since last set + int sample_count() const; + + // Resets SPC to power-on state. This resets your output buffer, so you must + // call set_output() after this. + void reset(); + + // Emulates pressing reset switch on SNES. This resets your output buffer, so + // you must call set_output() after this. + void soft_reset(); + + // 1024000 SPC clocks per second, sample pair every 32 clocks + typedef int time_t; + enum { clock_rate = 1024000 }; + enum { clocks_per_sample = 32 }; + + // Emulated port read/write at specified time + enum { port_count = 4 }; + int read_port ( time_t, int port ); + void write_port( time_t, int port, int data ); + + // Runs SPC to end_time and starts a new time frame at 0 + void end_frame( time_t end_time ); + +// Sound control + + // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). + // Reduces emulation accuracy. + enum { voice_count = 8 }; + void mute_voices( int mask ); + + // If true, prevents channels and global volumes from being phase-negated. + // Only supported by fast DSP. + void disable_surround( bool disable = true ); + + // Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc. + enum { tempo_unit = 0x100 }; + void set_tempo( int ); + +// SPC music files + + // Loads SPC data into emulator + enum { spc_min_file_size = 0x10180 }; + enum { spc_file_size = 0x10200 }; + blargg_err_t load_spc( void const* in, long size ); + + // Clears echo region. Useful after loading an SPC as many have garbage in echo. + void clear_echo(); + + // Plays for count samples and write samples to out. Discards samples if out + // is NULL. Count must be a multiple of 2 since output is stereo. + blargg_err_t play( int count, sample_t* out ); + + // Skips count samples. Several times faster than play() when using fast DSP. + blargg_err_t skip( int count ); + +// State save/load (only available with accurate DSP) + +#if !SPC_NO_COPY_STATE_FUNCS + // Saves/loads state + enum { state_size = 68 * 1024L }; // maximum space needed when saving + typedef SPC_DSP::copy_func_t copy_func_t; + void copy_state( unsigned char** io, copy_func_t ); + + // Writes minimal header to spc_out + static void init_header( void* spc_out ); + + // Saves emulator state as SPC file data. Writes spc_file_size bytes to spc_out. + // Does not set up SPC header; use init_header() for that. + void save_spc( void* spc_out ); + + // Returns true if new key-on events occurred since last check. Useful for + // trimming silence while saving an SPC. + bool check_kon(); +#endif + +//// Snes9x Accessor + + void dsp_set_spc_snapshot_callback( void (*callback) (void) ); + void dsp_dump_spc_snapshot( void ); + void dsp_set_stereo_switch( int ); + uint8_t dsp_reg_value( int, int ); + int dsp_envx_value( int ); + +public: + BLARGG_DISABLE_NOTHROW + + typedef BOOST::uint16_t uint16_t; + + // Time relative to m_spc_time. Speeds up code a bit by eliminating need to + // constantly add m_spc_time to time from CPU. CPU uses time that ends at + // 0 to eliminate reloading end time every instruction. It pays off. + typedef int rel_time_t; + + struct Timer + { + rel_time_t next_time; // time of next event + int prescaler; + int period; + int divider; + int enabled; + int counter; + }; + enum { reg_count = 0x10 }; + enum { timer_count = 3 }; + enum { extra_size = SPC_DSP::extra_size }; + + enum { signature_size = 35 }; + +private: + SPC_DSP dsp; + + #if SPC_LESS_ACCURATE + static signed char const reg_times_ [256]; + signed char reg_times [256]; + #endif + + struct state_t + { + Timer timers [timer_count]; + + uint8_t smp_regs [2] [reg_count]; + + struct + { + int pc; + int a; + int x; + int y; + int psw; + int sp; + } cpu_regs; + + rel_time_t dsp_time; + time_t spc_time; + bool echo_accessed; + + int tempo; + int skipped_kon; + int skipped_koff; + const char* cpu_error; + + int extra_clocks; + sample_t* buf_begin; + sample_t const* buf_end; + sample_t* extra_pos; + sample_t extra_buf [extra_size]; + + int rom_enabled; + uint8_t rom [rom_size]; + uint8_t hi_ram [rom_size]; + + unsigned char cycle_table [256]; + + struct + { + // padding to neutralize address overflow + union { + uint8_t padding1 [0x100]; + uint16_t align; // makes compiler align data for 16-bit access + } padding1 [1]; + uint8_t ram [0x10000]; + uint8_t padding2 [0x100]; + } ram; + }; + state_t m; + + enum { rom_addr = 0xFFC0 }; + + enum { skipping_time = 127 }; + + // Value that padding should be filled with + enum { cpu_pad_fill = 0xFF }; + + enum { + r_test = 0x0, r_control = 0x1, + r_dspaddr = 0x2, r_dspdata = 0x3, + r_cpuio0 = 0x4, r_cpuio1 = 0x5, + r_cpuio2 = 0x6, r_cpuio3 = 0x7, + r_f8 = 0x8, r_f9 = 0x9, + r_t0target = 0xA, r_t1target = 0xB, r_t2target = 0xC, + r_t0out = 0xD, r_t1out = 0xE, r_t2out = 0xF + }; + + void timers_loaded(); + void enable_rom( int enable ); + void reset_buf(); + void save_extra(); + void load_regs( uint8_t const in [reg_count] ); + void ram_loaded(); + void regs_loaded(); + void reset_time_regs(); + void reset_common( int timer_counter_init ); + + Timer* run_timer_ ( Timer* t, rel_time_t ); + Timer* run_timer ( Timer* t, rel_time_t ); + int dsp_read ( rel_time_t ); + void dsp_write ( int data, rel_time_t ); + void cpu_write_smp_reg_( int data, rel_time_t, int addr ); + void cpu_write_smp_reg ( int data, rel_time_t, int addr ); + void cpu_write_high ( int data, int i, rel_time_t ); + void cpu_write ( int data, int addr, rel_time_t ); + int cpu_read_smp_reg ( int i, rel_time_t ); + int cpu_read ( int addr, rel_time_t ); + unsigned CPU_mem_bit ( uint8_t const* pc, rel_time_t ); + + bool check_echo_access ( int addr ); + uint8_t* run_until_( time_t end_time ); + + struct spc_file_t + { + char signature [signature_size]; + uint8_t has_id666; + uint8_t version; + uint8_t pcl, pch; + uint8_t a; + uint8_t x; + uint8_t y; + uint8_t psw; + uint8_t sp; + char text [212]; + uint8_t ram [0x10000]; + uint8_t dsp [128]; + uint8_t unused [0x40]; + uint8_t ipl_rom [0x40]; + }; + + static char const signature [signature_size + 1]; + + void save_regs( uint8_t out [reg_count] ); +}; + +#include + +inline int SNES_SPC::sample_count() const { return (m.extra_clocks >> 5) * 2; } + +inline int SNES_SPC::read_port( time_t t, int port ) +{ + assert( (unsigned) port < port_count ); + return run_until_( t ) [port]; +} + +inline void SNES_SPC::write_port( time_t t, int port, int data ) +{ + assert( (unsigned) port < port_count ); + run_until_( t ) [0x10 + port] = data; + m.ram.ram [0xF4 + port] = data; +} + +inline void SNES_SPC::mute_voices( int mask ) { dsp.mute_voices( mask ); } + +inline void SNES_SPC::disable_surround( bool disable ) { dsp.disable_surround( disable ); } + +#if !SPC_NO_COPY_STATE_FUNCS +inline bool SNES_SPC::check_kon() { return dsp.check_kon(); } +#endif + +#endif diff --git a/apu/SNES_SPC_misc.cpp b/apu/SNES_SPC_misc.cpp new file mode 100644 index 00000000..659377ae --- /dev/null +++ b/apu/SNES_SPC_misc.cpp @@ -0,0 +1,413 @@ +// SPC emulation support: init, sample buffering, reset, SPC loading + +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "SNES_SPC.h" + +#include + +/* Copyright (C) 2004-2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +#define RAM (m.ram.ram) +#define REGS (m.smp_regs [0]) +#define REGS_IN (m.smp_regs [1]) + +// (n ? n : 256) +#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) + + +//// Init + +blargg_err_t SNES_SPC::init() +{ + memset( &m, 0, sizeof m ); + dsp.init( RAM ); + + m.tempo = tempo_unit; + + // Most SPC music doesn't need ROM, and almost all the rest only rely + // on these two bytes + m.rom [0x3E] = 0xFF; + m.rom [0x3F] = 0xC0; + + static unsigned char const cycle_table [128] = + {// 01 23 45 67 89 AB CD EF + 0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x68, // 0 + 0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x46, // 1 + 0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x74, // 2 + 0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x38, // 3 + 0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x66, // 4 + 0x48,0x47,0x45,0x56,0x55,0x45,0x22,0x43, // 5 + 0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x75, // 6 + 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x36, // 7 + 0x28,0x47,0x34,0x36,0x26,0x54,0x52,0x45, // 8 + 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0xC5, // 9 + 0x38,0x47,0x34,0x36,0x26,0x44,0x52,0x44, // A + 0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x34, // B + 0x38,0x47,0x45,0x47,0x25,0x64,0x52,0x49, // C + 0x48,0x47,0x56,0x67,0x45,0x55,0x22,0x83, // D + 0x28,0x47,0x34,0x36,0x24,0x53,0x43,0x40, // E + 0x48,0x47,0x45,0x56,0x34,0x54,0x22,0x60, // F + }; + + // unpack cycle table + for ( int i = 0; i < 128; i++ ) + { + int n = cycle_table [i]; + m.cycle_table [i * 2 + 0] = n >> 4; + m.cycle_table [i * 2 + 1] = n & 0x0F; + } + + #if SPC_LESS_ACCURATE + memcpy( reg_times, reg_times_, sizeof reg_times ); + #endif + + reset(); + return 0; +} + +void SNES_SPC::init_rom( uint8_t const in [rom_size] ) +{ + memcpy( m.rom, in, sizeof m.rom ); +} + +void SNES_SPC::set_tempo( int t ) +{ + m.tempo = t; + int const timer2_shift = 4; // 64 kHz + int const other_shift = 3; // 8 kHz + + #if SPC_DISABLE_TEMPO + m.timers [2].prescaler = timer2_shift; + m.timers [1].prescaler = timer2_shift + other_shift; + m.timers [0].prescaler = timer2_shift + other_shift; + #else + if ( !t ) + t = 1; + int const timer2_rate = 1 << timer2_shift; + int rate = (timer2_rate * tempo_unit + (t >> 1)) / t; + if ( rate < timer2_rate / 4 ) + rate = timer2_rate / 4; // max 4x tempo + m.timers [2].prescaler = rate; + m.timers [1].prescaler = rate << other_shift; + m.timers [0].prescaler = rate << other_shift; + #endif +} + +// Timer registers have been loaded. Applies these to the timers. Does not +// reset timer prescalers or dividers. +void SNES_SPC::timers_loaded() +{ + int i; + for ( i = 0; i < timer_count; i++ ) + { + Timer* t = &m.timers [i]; + t->period = IF_0_THEN_256( REGS [r_t0target + i] ); + t->enabled = REGS [r_control] >> i & 1; + t->counter = REGS_IN [r_t0out + i] & 0x0F; + } + + set_tempo( m.tempo ); +} + +// Loads registers from unified 16-byte format +void SNES_SPC::load_regs( uint8_t const in [reg_count] ) +{ + memcpy( REGS, in, reg_count ); + memcpy( REGS_IN, REGS, reg_count ); + + // These always read back as 0 + REGS_IN [r_test ] = 0; + REGS_IN [r_control ] = 0; + REGS_IN [r_t0target] = 0; + REGS_IN [r_t1target] = 0; + REGS_IN [r_t2target] = 0; +} + +// RAM was just loaded from SPC, with $F0-$FF containing SMP registers +// and timer counts. Copies these to proper registers. +void SNES_SPC::ram_loaded() +{ + m.rom_enabled = 0; + load_regs( &RAM [0xF0] ); + + // Put STOP instruction around memory to catch PC underflow/overflow + memset( m.ram.padding1, cpu_pad_fill, sizeof m.ram.padding1 ); + memset( m.ram.padding2, cpu_pad_fill, sizeof m.ram.padding2 ); +} + +// Registers were just loaded. Applies these new values. +void SNES_SPC::regs_loaded() +{ + enable_rom( REGS [r_control] & 0x80 ); + timers_loaded(); +} + +void SNES_SPC::reset_time_regs() +{ + m.cpu_error = 0; + m.echo_accessed = 0; + m.spc_time = 0; + m.dsp_time = 0; + #if SPC_LESS_ACCURATE + m.dsp_time = clocks_per_sample + 1; + #endif + + for ( int i = 0; i < timer_count; i++ ) + { + Timer* t = &m.timers [i]; + t->next_time = 1; + t->divider = 0; + } + + regs_loaded(); + + m.extra_clocks = 0; + reset_buf(); +} + +void SNES_SPC::reset_common( int timer_counter_init ) +{ + int i; + for ( i = 0; i < timer_count; i++ ) + REGS_IN [r_t0out + i] = timer_counter_init; + + // Run IPL ROM + memset( &m.cpu_regs, 0, sizeof m.cpu_regs ); + m.cpu_regs.pc = rom_addr; + + REGS [r_test ] = 0x0A; + REGS [r_control] = 0xB0; // ROM enabled, clear ports + for ( i = 0; i < port_count; i++ ) + REGS_IN [r_cpuio0 + i] = 0; + + reset_time_regs(); +} + +void SNES_SPC::soft_reset() +{ + reset_common( 0 ); + dsp.soft_reset(); +} + +void SNES_SPC::reset() +{ + m.cpu_regs.pc = 0xFFC0; + m.cpu_regs.a = 0x00; + m.cpu_regs.x = 0x00; + m.cpu_regs.y = 0x00; + m.cpu_regs.psw = 0x02; + m.cpu_regs.sp = 0xEF; + memset( RAM, 0x00, 0x10000 ); + ram_loaded(); + reset_common( 0x0F ); + dsp.reset(); +} + +char const SNES_SPC::signature [signature_size + 1] = + "SNES-SPC700 Sound File Data v0.30\x1A\x1A"; + +blargg_err_t SNES_SPC::load_spc( void const* data, long size ) +{ + spc_file_t const* const spc = (spc_file_t const*) data; + + // be sure compiler didn't insert any padding into fle_t + assert( sizeof (spc_file_t) == spc_min_file_size + 0x80 ); + + // Check signature and file size + if ( size < signature_size || memcmp( spc, signature, 27 ) ) + return "Not an SPC file"; + + if ( size < spc_min_file_size ) + return "Corrupt SPC file"; + + // CPU registers + m.cpu_regs.pc = spc->pch * 0x100 + spc->pcl; + m.cpu_regs.a = spc->a; + m.cpu_regs.x = spc->x; + m.cpu_regs.y = spc->y; + m.cpu_regs.psw = spc->psw; + m.cpu_regs.sp = spc->sp; + + // RAM and registers + memcpy( RAM, spc->ram, 0x10000 ); + ram_loaded(); + + // DSP registers + dsp.load( spc->dsp ); + + reset_time_regs(); + + return 0; +} + +void SNES_SPC::clear_echo() +{ + if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) ) + { + int addr = 0x100 * dsp.read( SPC_DSP::r_esa ); + int end = addr + 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F); + if ( end > 0x10000 ) + end = 0x10000; + memset( &RAM [addr], 0xFF, end - addr ); + } +} + + +//// Sample output + +void SNES_SPC::reset_buf() +{ + // Start with half extra buffer of silence + sample_t* out = m.extra_buf; + while ( out < &m.extra_buf [extra_size / 2] ) + *out++ = 0; + + m.extra_pos = out; + m.buf_begin = 0; + + dsp.set_output( 0, 0 ); +} + +void SNES_SPC::set_output( sample_t* out, int size ) +{ + require( (size & 1) == 0 ); // size must be even + + m.extra_clocks &= clocks_per_sample - 1; + if ( out ) + { + sample_t const* out_end = out + size; + m.buf_begin = out; + m.buf_end = out_end; + + // Copy extra to output + sample_t const* in = m.extra_buf; + while ( in < m.extra_pos && out < out_end ) + *out++ = *in++; + + // Handle output being full already + if ( out >= out_end ) + { + // Have DSP write to remaining extra space + out = dsp.extra(); + out_end = &dsp.extra() [extra_size]; + + // Copy any remaining extra samples as if DSP wrote them + while ( in < m.extra_pos ) + *out++ = *in++; + assert( out <= out_end ); + } + + dsp.set_output( out, out_end - out ); + } + else + { + reset_buf(); + } +} + +void SNES_SPC::save_extra() +{ + // Get end pointers + sample_t const* main_end = m.buf_end; // end of data written to buf + sample_t const* dsp_end = dsp.out_pos(); // end of data written to dsp.extra() + if ( m.buf_begin <= dsp_end && dsp_end <= main_end ) + { + main_end = dsp_end; + dsp_end = dsp.extra(); // nothing in DSP's extra + } + + // Copy any extra samples at these ends into extra_buf + sample_t* out = m.extra_buf; + sample_t const* in; + for ( in = m.buf_begin + sample_count(); in < main_end; in++ ) + *out++ = *in; + for ( in = dsp.extra(); in < dsp_end ; in++ ) + *out++ = *in; + + m.extra_pos = out; + assert( out <= &m.extra_buf [extra_size] ); +} + +blargg_err_t SNES_SPC::play( int count, sample_t* out ) +{ + require( (count & 1) == 0 ); // must be even + if ( count ) + { + set_output( out, count ); + end_frame( count * (clocks_per_sample / 2) ); + } + + const char* err = m.cpu_error; + m.cpu_error = 0; + return err; +} + +blargg_err_t SNES_SPC::skip( int count ) +{ + #if SPC_LESS_ACCURATE + if ( count > 2 * sample_rate * 2 ) + { + set_output( 0, 0 ); + + // Skip a multiple of 4 samples + time_t end = count; + count = (count & 3) + 1 * sample_rate * 2; + end = (end - count) * (clocks_per_sample / 2); + + m.skipped_kon = 0; + m.skipped_koff = 0; + + // Preserve DSP and timer synchronization + // TODO: verify that this really preserves it + int old_dsp_time = m.dsp_time + m.spc_time; + m.dsp_time = end - m.spc_time + skipping_time; + end_frame( end ); + m.dsp_time = m.dsp_time - skipping_time + old_dsp_time; + + dsp.write( SPC_DSP::r_koff, m.skipped_koff & ~m.skipped_kon ); + dsp.write( SPC_DSP::r_kon , m.skipped_kon ); + clear_echo(); + } + #endif + + return play( count, 0 ); +} + +//// Snes9x Accessor + +void SNES_SPC::dsp_set_spc_snapshot_callback( void (*callback) (void) ) +{ + dsp.set_spc_snapshot_callback( callback ); +} + +void SNES_SPC::dsp_dump_spc_snapshot( void ) +{ + dsp.dump_spc_snapshot(); +} + +void SNES_SPC::dsp_set_stereo_switch( int value ) +{ + dsp.set_stereo_switch( value ); +} + +SNES_SPC::uint8_t SNES_SPC::dsp_reg_value( int ch, int addr ) +{ + return dsp.reg_value( ch, addr ); +} + +int SNES_SPC::dsp_envx_value( int ch ) +{ + return dsp.envx_value( ch ); +} diff --git a/apu/SNES_SPC_state.cpp b/apu/SNES_SPC_state.cpp new file mode 100644 index 00000000..3d9d3f3a --- /dev/null +++ b/apu/SNES_SPC_state.cpp @@ -0,0 +1,142 @@ +// SPC emulation state save/load: copy_state(), save_spc() +// Separate file to avoid linking in unless needed + +// snes_spc 0.9.0. http://www.slack.net/‾ant/ + +#include "SNES_SPC.h" + +#if !SPC_NO_COPY_STATE_FUNCS + +#include + +/* Copyright (C) 2004-2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include +#include "blargg_source.h" + +#define RAM (m.ram.ram) +#define REGS (m.smp_regs [0]) +#define REGS_IN (m.smp_regs [1]) + +void SNES_SPC::save_regs( uint8_t out [reg_count] ) +{ + // Use current timer counter values + for ( int i = 0; i < timer_count; i++ ) + out [r_t0out + i] = m.timers [i].counter; + + // Last written values + memcpy( out, REGS, r_t0out ); +} + +void SNES_SPC::init_header( void* spc_out ) +{ + spc_file_t* const spc = (spc_file_t*) spc_out; + + spc->has_id666 = 26; // has none + spc->version = 30; + memcpy( spc, signature, sizeof spc->signature ); + memset( spc->text, 0, sizeof spc->text ); +} + +void SNES_SPC::save_spc( void* spc_out ) +{ + spc_file_t* const spc = (spc_file_t*) spc_out; + + // CPU + spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0); + spc->pch = (uint8_t) (m.cpu_regs.pc >> 8); + spc->a = m.cpu_regs.a; + spc->x = m.cpu_regs.x; + spc->y = m.cpu_regs.y; + spc->psw = m.cpu_regs.psw; + spc->sp = m.cpu_regs.sp; + + // RAM, ROM + memcpy( spc->ram, RAM, sizeof spc->ram ); + if ( m.rom_enabled ) + memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram ); + memset( spc->unused, 0, sizeof spc->unused ); + memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom ); + + // SMP registers + save_regs( &spc->ram [0xF0] ); + int i; + for ( i = 0; i < port_count; i++ ) + spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i]; + + // DSP registers + for ( i = 0; i < SPC_DSP::register_count; i++ ) + spc->dsp [i] = dsp.read( i ); +} + +#undef IF_0_THEN_256 +#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1) +void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy ) +{ + SPC_State_Copier copier( io, copy ); + + // Make state data more readable by putting 64K RAM, 16 SMP registers, + // then DSP (with its 128 registers) first + + // RAM + enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below + copier.copy( RAM, 0x10000 ); + + { + // SMP registers + uint8_t regs [reg_count]; + uint8_t regs_in [reg_count]; + + memcpy( regs, REGS, reg_count ); + memcpy( regs_in, REGS_IN, reg_count ); + + copier.copy( regs, sizeof regs ); + copier.copy( regs_in, sizeof regs_in ); + + memcpy( REGS, regs, reg_count); + memcpy( REGS_IN, regs_in, reg_count ); + + enable_rom( REGS [r_control] & 0x80 ); + } + + // CPU registers + SPC_COPY( uint16_t, m.cpu_regs.pc ); + SPC_COPY( uint8_t, m.cpu_regs.a ); + SPC_COPY( uint8_t, m.cpu_regs.x ); + SPC_COPY( uint8_t, m.cpu_regs.y ); + SPC_COPY( uint8_t, m.cpu_regs.psw ); + SPC_COPY( uint8_t, m.cpu_regs.sp ); + copier.extra(); + + SPC_COPY( int16_t, m.spc_time ); + SPC_COPY( int16_t, m.dsp_time ); + + // DSP + dsp.copy_state( io, copy ); + + // Timers + for ( int i = 0; i < timer_count; i++ ) + { + Timer* t = &m.timers [i]; + t->period = IF_0_THEN_256( REGS [r_t0target + i] ); + t->enabled = REGS [r_control] >> i & 1; + SPC_COPY( int16_t, t->next_time ); + SPC_COPY( uint8_t, t->divider ); + SPC_COPY( uint8_t, t->counter ); + copier.extra(); + } + + set_tempo( m.tempo ); + + copier.extra(); +} +#endif diff --git a/apu/SPC_CPU.h b/apu/SPC_CPU.h new file mode 100644 index 00000000..664fc488 --- /dev/null +++ b/apu/SPC_CPU.h @@ -0,0 +1,1220 @@ +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +/* Copyright (C) 2004-2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +//// Memory access + +#if SPC_MORE_ACCURACY + #define SUSPICIOUS_OPCODE( name ) ((void) 0) +#else + #define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" ) +#endif + +#define CPU_READ( time, offset, addr )\ + cpu_read( addr, time + offset ) + +#define CPU_WRITE( time, offset, addr, data )\ + cpu_write( data, addr, time + offset ) + +#if SPC_MORE_ACCURACY + #define CPU_READ_TIMER( time, offset, addr, out )\ + { out = CPU_READ( time, offset, addr ); } + +#else + // timers are by far the most common thing read from dp + #define CPU_READ_TIMER( time, offset, addr_, out )\ + {\ + rel_time_t adj_time = time + offset;\ + int dp_addr = addr_;\ + int ti = dp_addr - (r_t0out + 0xF0);\ + if ( (unsigned) ti < timer_count )\ + {\ + Timer* t = &m.timers [ti];\ + if ( adj_time >= t->next_time )\ + t = run_timer_( t, adj_time );\ + out = t->counter;\ + t->counter = 0;\ + }\ + else\ + {\ + out = ram [dp_addr];\ + int i = dp_addr - 0xF0;\ + if ( (unsigned) i < 0x10 )\ + out = cpu_read_smp_reg( i, adj_time );\ + }\ + } +#endif + +#define TIME_ADJ( n ) (n) + +#define READ_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), (addr), out ) +#define READ( time, addr ) CPU_READ ( rel_time, TIME_ADJ(time), (addr) ) +#define WRITE( time, addr, data ) CPU_WRITE( rel_time, TIME_ADJ(time), (addr), (data) ) + +#define DP_ADDR( addr ) (dp + (addr)) + +#define READ_DP_TIMER( time, addr, out ) CPU_READ_TIMER( rel_time, TIME_ADJ(time), DP_ADDR( addr ), out ) +#define READ_DP( time, addr ) READ ( time, DP_ADDR( addr ) ) +#define WRITE_DP( time, addr, data ) WRITE( time, DP_ADDR( addr ), data ) + +#define READ_PROG16( addr ) GET_LE16( ram + (addr) ) + +#define SET_PC( n ) (pc = ram + (n)) +#define GET_PC() (pc - ram) +#define READ_PC( pc ) (*(pc)) +#define READ_PC16( pc ) GET_LE16( pc ) + +// TODO: remove non-wrapping versions? +#define SPC_NO_SP_WRAPAROUND 0 + +#define SET_SP( v ) (sp = ram + 0x101 + (v)) +#define GET_SP() (sp - 0x101 - ram) + +#if SPC_NO_SP_WRAPAROUND +#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v )) +#define PUSH( v ) (void) (*--sp = (uint8_t) (v)) +#define POP( out ) (void) ((out) = *sp++) + +#else +#define PUSH16( data )\ +{\ + int addr = (sp -= 2) - ram;\ + if ( addr > 0x100 )\ + {\ + SET_LE16( sp, data );\ + }\ + else\ + {\ + ram [(uint8_t) addr + 0x100] = (uint8_t) data;\ + sp [1] = (uint8_t) (data >> 8);\ + sp += 0x100;\ + }\ +} + +#define PUSH( data )\ +{\ + *--sp = (uint8_t) (data);\ + if ( sp - ram == 0x100 )\ + sp += 0x100;\ +} + +#define POP( out )\ +{\ + out = *sp++;\ + if ( sp - ram == 0x201 )\ + {\ + out = sp [-0x101];\ + sp -= 0x100;\ + }\ +} + +#endif + +#define MEM_BIT( rel ) CPU_mem_bit( pc, rel_time + rel ) + +unsigned SNES_SPC::CPU_mem_bit( uint8_t const* pc, rel_time_t rel_time ) +{ + unsigned addr = READ_PC16( pc ); + unsigned t = READ( 0, addr & 0x1FFF ) >> (addr >> 13); + return t << 8 & 0x100; +} + +//// Status flag handling + +// Hex value in name to clarify code and bit shifting. +// Flag stored in indicated variable during emulation +int const n80 = 0x80; // nz +int const v40 = 0x40; // psw +int const p20 = 0x20; // dp +int const b10 = 0x10; // psw +int const h08 = 0x08; // psw +int const i04 = 0x04; // psw +int const z02 = 0x02; // nz +int const c01 = 0x01; // c + +int const nz_neg_mask = 0x880; // either bit set indicates N flag set + +#define GET_PSW( out )\ +{\ + out = psw & ~(n80 | p20 | z02 | c01);\ + out |= c >> 8 & c01;\ + out |= dp >> 3 & p20;\ + out |= ((nz >> 4) | nz) & n80;\ + if ( !(uint8_t) nz ) out |= z02;\ +} + +#define SET_PSW( in )\ +{\ + psw = in;\ + c = in << 8;\ + dp = in << 3 & 0x100;\ + nz = (in << 4 & 0x800) | (~in & z02);\ +} + +SPC_CPU_RUN_FUNC +{ + uint8_t* const ram = RAM; + int a = m.cpu_regs.a; + int x = m.cpu_regs.x; + int y = m.cpu_regs.y; + uint8_t const* pc; + uint8_t* sp; + int psw; + int c; + int nz; + int dp; + + SET_PC( m.cpu_regs.pc ); + SET_SP( m.cpu_regs.sp ); + SET_PSW( m.cpu_regs.psw ); + + goto loop; + + + // Main loop + +cbranch_taken_loop: + pc += *(BOOST::int8_t const*) pc; +inc_pc_loop: + pc++; +loop: +{ + unsigned opcode; + unsigned data; + + check( (unsigned) a < 0x100 ); + check( (unsigned) x < 0x100 ); + check( (unsigned) y < 0x100 ); + + opcode = *pc; + if ( (rel_time += m.cycle_table [opcode]) > 0 ) + goto out_of_time; + + #ifdef SPC_CPU_OPCODE_HOOK + SPC_CPU_OPCODE_HOOK( GET_PC(), opcode ); + #endif + /* + //SUB_CASE_COUNTER( 1 ); + #define PROFILE_TIMER_LOOP( op, addr, len )\ + if ( opcode == op )\ + {\ + int cond = (unsigned) ((addr) - 0xFD) < 3 &&\ + pc [len] == 0xF0 && pc [len+1] == 0xFE - len;\ + SUB_CASE_COUNTER( op && cond );\ + } + + PROFILE_TIMER_LOOP( 0xEC, GET_LE16( pc + 1 ), 3 ); + PROFILE_TIMER_LOOP( 0xEB, pc [1], 2 ); + PROFILE_TIMER_LOOP( 0xE4, pc [1], 2 ); + */ + + // TODO: if PC is at end of memory, this will get wrong operand (very obscure) + data = *++pc; + switch ( opcode ) + { + +// Common instructions + +#define BRANCH( cond )\ +{\ + pc++;\ + pc += (BOOST::int8_t) data;\ + if ( cond )\ + goto loop;\ + pc -= (BOOST::int8_t) data;\ + rel_time -= 2;\ + goto loop;\ +} + + case 0xF0: // BEQ + BRANCH( !(uint8_t) nz ) // 89% taken + + case 0xD0: // BNE + BRANCH( (uint8_t) nz ) + + case 0x3F:{// CALL + int old_addr = GET_PC() + 2; + SET_PC( READ_PC16( pc ) ); + PUSH16( old_addr ); + goto loop; + } + + case 0x6F:// RET + #if SPC_NO_SP_WRAPAROUND + { + SET_PC( GET_LE16( sp ) ); + sp += 2; + } + #else + { + int addr = sp - ram; + SET_PC( GET_LE16( sp ) ); + sp += 2; + if ( addr < 0x1FF ) + goto loop; + + SET_PC( sp [-0x101] * 0x100 + ram [(uint8_t) addr + 0x100] ); + sp -= 0x100; + } + #endif + goto loop; + + case 0xE4: // MOV a,dp + ++pc; + // 80% from timer + READ_DP_TIMER( 0, data, a = nz ); + goto loop; + + case 0xFA:{// MOV dp,dp + int temp; + READ_DP_TIMER( -2, data, temp ); + data = temp + no_read_before_write ; + } + // fall through + case 0x8F:{// MOV dp,#imm + int temp = READ_PC( pc + 1 ); + pc += 2; + + #if !SPC_MORE_ACCURACY + { + int i = dp + temp; + ram [i] = (uint8_t) data; + i -= 0xF0; + if ( (unsigned) i < 0x10 ) // 76% + { + REGS [i] = (uint8_t) data; + + // Registers other than $F2 and $F4-$F7 + //if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 ) + if ( ((~0x2F00 << (bits_in_int - 16)) << i) < 0 ) // 12% + cpu_write_smp_reg( data, rel_time, i ); + } + } + #else + WRITE_DP( 0, temp, data ); + #endif + goto loop; + } + + case 0xC4: // MOV dp,a + ++pc; + #if !SPC_MORE_ACCURACY + { + int i = dp + data; + ram [i] = (uint8_t) a; + i -= 0xF0; + if ( (unsigned) i < 0x10 ) // 39% + { + unsigned sel = i - 2; + REGS [i] = (uint8_t) a; + + if ( sel == 1 ) // 51% $F3 + dsp_write( a, rel_time ); + else if ( sel > 1 ) // 1% not $F2 or $F3 + cpu_write_smp_reg_( a, rel_time, i ); + } + } + #else + WRITE_DP( 0, data, a ); + #endif + goto loop; + +#define CASE( n ) case n: + +// Define common address modes based on opcode for immediate mode. Execution +// ends with data set to the address of the operand. +#define ADDR_MODES_( op )\ + CASE( op - 0x02 ) /* (X) */\ + data = x + dp;\ + pc--;\ + goto end_##op;\ + CASE( op + 0x0F ) /* (dp)+Y */\ + data = READ_PROG16( data + dp ) + y;\ + goto end_##op;\ + CASE( op - 0x01 ) /* (dp+X) */\ + data = READ_PROG16( ((uint8_t) (data + x)) + dp );\ + goto end_##op;\ + CASE( op + 0x0E ) /* abs+Y */\ + data += y;\ + goto abs_##op;\ + CASE( op + 0x0D ) /* abs+X */\ + data += x;\ + CASE( op - 0x03 ) /* abs */\ + abs_##op:\ + data += 0x100 * READ_PC( ++pc );\ + goto end_##op;\ + CASE( op + 0x0C ) /* dp+X */\ + data = (uint8_t) (data + x); + +#define ADDR_MODES_NO_DP( op )\ + ADDR_MODES_( op )\ + data += dp;\ + end_##op: + +#define ADDR_MODES( op )\ + ADDR_MODES_( op )\ + CASE( op - 0x04 ) /* dp */\ + data += dp;\ + end_##op: + +// 1. 8-bit Data Transmission Commands. Group I + + ADDR_MODES_NO_DP( 0xE8 ) // MOV A,addr + a = nz = READ( 0, data ); + goto inc_pc_loop; + + case 0xBF:{// MOV A,(X)+ + int temp = x + dp; + x = (uint8_t) (x + 1); + a = nz = READ( -1, temp ); + goto loop; + } + + case 0xE8: // MOV A,imm + a = data; + nz = data; + goto inc_pc_loop; + + case 0xF9: // MOV X,dp+Y + data = (uint8_t) (data + y); + case 0xF8: // MOV X,dp + READ_DP_TIMER( 0, data, x = nz ); + goto inc_pc_loop; + + case 0xE9: // MOV X,abs + data = READ_PC16( pc ); + ++pc; + data = READ( 0, data ); + case 0xCD: // MOV X,imm + x = data; + nz = data; + goto inc_pc_loop; + + case 0xFB: // MOV Y,dp+X + data = (uint8_t) (data + x); + case 0xEB: // MOV Y,dp + // 70% from timer + pc++; + READ_DP_TIMER( 0, data, y = nz ); + goto loop; + + case 0xEC:{// MOV Y,abs + int temp = READ_PC16( pc ); + pc += 2; + READ_TIMER( 0, temp, y = nz ); + //y = nz = READ( 0, temp ); + goto loop; + } + + case 0x8D: // MOV Y,imm + y = data; + nz = data; + goto inc_pc_loop; + +// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2 + + ADDR_MODES_NO_DP( 0xC8 ) // MOV addr,A + WRITE( 0, data, a ); + goto inc_pc_loop; + + { + int temp; + case 0xCC: // MOV abs,Y + temp = y; + goto mov_abs_temp; + case 0xC9: // MOV abs,X + temp = x; + mov_abs_temp: + WRITE( 0, READ_PC16( pc ), temp ); + pc += 2; + goto loop; + } + + case 0xD9: // MOV dp+Y,X + data = (uint8_t) (data + y); + case 0xD8: // MOV dp,X + WRITE( 0, data + dp, x ); + goto inc_pc_loop; + + case 0xDB: // MOV dp+X,Y + data = (uint8_t) (data + x); + case 0xCB: // MOV dp,Y + WRITE( 0, data + dp, y ); + goto inc_pc_loop; + +// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3. + + case 0x7D: // MOV A,X + a = x; + nz = x; + goto loop; + + case 0xDD: // MOV A,Y + a = y; + nz = y; + goto loop; + + case 0x5D: // MOV X,A + x = a; + nz = a; + goto loop; + + case 0xFD: // MOV Y,A + y = a; + nz = a; + goto loop; + + case 0x9D: // MOV X,SP + x = nz = GET_SP(); + goto loop; + + case 0xBD: // MOV SP,X + SET_SP( x ); + goto loop; + + //case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2) + + case 0xAF: // MOV (X)+,A + WRITE_DP( 0, x, a + no_read_before_write ); + x++; + goto loop; + +// 5. 8-BIT LOGIC OPERATION COMMANDS + +#define LOGICAL_OP( op, func )\ + ADDR_MODES( op ) /* addr */\ + data = READ( 0, data );\ + case op: /* imm */\ + nz = a func##= data;\ + goto inc_pc_loop;\ + { unsigned addr;\ + case op + 0x11: /* X,Y */\ + data = READ_DP( -2, y );\ + addr = x + dp;\ + goto addr_##op;\ + case op + 0x01: /* dp,dp */\ + data = READ_DP( -3, data );\ + case op + 0x10:{/*dp,imm*/\ + uint8_t const* addr2 = pc + 1;\ + pc += 2;\ + addr = READ_PC( addr2 ) + dp;\ + }\ + addr_##op:\ + nz = data func READ( -1, addr );\ + WRITE( 0, addr, nz );\ + goto loop;\ + } + + LOGICAL_OP( 0x28, & ); // AND + + LOGICAL_OP( 0x08, | ); // OR + + LOGICAL_OP( 0x48, ^ ); // EOR + +// 4. 8-BIT ARITHMETIC OPERATION COMMANDS + + ADDR_MODES( 0x68 ) // CMP addr + data = READ( 0, data ); + case 0x68: // CMP imm + nz = a - data; + c = ~nz; + nz &= 0xFF; + goto inc_pc_loop; + + case 0x79: // CMP (X),(Y) + data = READ_DP( -2, y ); + nz = READ_DP( -1, x ) - data; + c = ~nz; + nz &= 0xFF; + goto loop; + + case 0x69: // CMP dp,dp + data = READ_DP( -3, data ); + case 0x78: // CMP dp,imm + nz = READ_DP( -1, READ_PC( ++pc ) ) - data; + c = ~nz; + nz &= 0xFF; + goto inc_pc_loop; + + case 0x3E: // CMP X,dp + data += dp; + goto cmp_x_addr; + case 0x1E: // CMP X,abs + data = READ_PC16( pc ); + pc++; + cmp_x_addr: + data = READ( 0, data ); + case 0xC8: // CMP X,imm + nz = x - data; + c = ~nz; + nz &= 0xFF; + goto inc_pc_loop; + + case 0x7E: // CMP Y,dp + data += dp; + goto cmp_y_addr; + case 0x5E: // CMP Y,abs + data = READ_PC16( pc ); + pc++; + cmp_y_addr: + data = READ( 0, data ); + case 0xAD: // CMP Y,imm + nz = y - data; + c = ~nz; + nz &= 0xFF; + goto inc_pc_loop; + + { + int addr; + case 0xB9: // SBC (x),(y) + case 0x99: // ADC (x),(y) + pc--; // compensate for inc later + data = READ_DP( -2, y ); + addr = x + dp; + goto adc_addr; + case 0xA9: // SBC dp,dp + case 0x89: // ADC dp,dp + data = READ_DP( -3, data ); + case 0xB8: // SBC dp,imm + case 0x98: // ADC dp,imm + addr = READ_PC( ++pc ) + dp; + adc_addr: + nz = READ( -1, addr ); + goto adc_data; + +// catch ADC and SBC together, then decode later based on operand +#undef CASE +#define CASE( n ) case n: case (n) + 0x20: + ADDR_MODES( 0x88 ) // ADC/SBC addr + data = READ( 0, data ); + case 0xA8: // SBC imm + case 0x88: // ADC imm + addr = -1; // A + nz = a; + adc_data: { + int flags; + if ( opcode >= 0xA0 ) // SBC + data ^= 0xFF; + + flags = data ^ nz; + nz += data + (c >> 8 & 1); + flags ^= nz; + + psw = (psw & ~(v40 | h08)) | + (flags >> 1 & h08) | + ((flags + 0x80) >> 2 & v40); + c = nz; + if ( addr < 0 ) + { + a = (uint8_t) nz; + goto inc_pc_loop; + } + WRITE( 0, addr, /*(uint8_t)*/ nz ); + goto inc_pc_loop; + } + + } + +// 6. ADDITION & SUBTRACTION COMMANDS + +#define INC_DEC_REG( reg, op )\ + nz = reg op;\ + reg = (uint8_t) nz;\ + goto loop; + + case 0xBC: INC_DEC_REG( a, + 1 ) // INC A + case 0x3D: INC_DEC_REG( x, + 1 ) // INC X + case 0xFC: INC_DEC_REG( y, + 1 ) // INC Y + + case 0x9C: INC_DEC_REG( a, - 1 ) // DEC A + case 0x1D: INC_DEC_REG( x, - 1 ) // DEC X + case 0xDC: INC_DEC_REG( y, - 1 ) // DEC Y + + case 0x9B: // DEC dp+X + case 0xBB: // INC dp+X + data = (uint8_t) (data + x); + case 0x8B: // DEC dp + case 0xAB: // INC dp + data += dp; + goto inc_abs; + case 0x8C: // DEC abs + case 0xAC: // INC abs + data = READ_PC16( pc ); + pc++; + inc_abs: + nz = (opcode >> 4 & 2) - 1; + nz += READ( -1, data ); + WRITE( 0, data, /*(uint8_t)*/ nz ); + goto inc_pc_loop; + +// 7. SHIFT, ROTATION COMMANDS + + case 0x5C: // LSR A + c = 0; + case 0x7C:{// ROR A + nz = (c >> 1 & 0x80) | (a >> 1); + c = a << 8; + a = nz; + goto loop; + } + + case 0x1C: // ASL A + c = 0; + case 0x3C:{// ROL A + int temp = c >> 8 & 1; + c = a << 1; + nz = c | temp; + a = (uint8_t) nz; + goto loop; + } + + case 0x0B: // ASL dp + c = 0; + data += dp; + goto rol_mem; + case 0x1B: // ASL dp+X + c = 0; + case 0x3B: // ROL dp+X + data = (uint8_t) (data + x); + case 0x2B: // ROL dp + data += dp; + goto rol_mem; + case 0x0C: // ASL abs + c = 0; + case 0x2C: // ROL abs + data = READ_PC16( pc ); + pc++; + rol_mem: + nz = c >> 8 & 1; + nz |= (c = READ( -1, data ) << 1); + WRITE( 0, data, /*(uint8_t)*/ nz ); + goto inc_pc_loop; + + case 0x4B: // LSR dp + c = 0; + data += dp; + goto ror_mem; + case 0x5B: // LSR dp+X + c = 0; + case 0x7B: // ROR dp+X + data = (uint8_t) (data + x); + case 0x6B: // ROR dp + data += dp; + goto ror_mem; + case 0x4C: // LSR abs + c = 0; + case 0x6C: // ROR abs + data = READ_PC16( pc ); + pc++; + ror_mem: { + int temp = READ( -1, data ); + nz = (c >> 1 & 0x80) | (temp >> 1); + c = temp << 8; + WRITE( 0, data, nz ); + goto inc_pc_loop; + } + + case 0x9F: // XCN + nz = a = (a >> 4) | (uint8_t) (a << 4); + goto loop; + +// 8. 16-BIT TRANSMISION COMMANDS + + case 0xBA: // MOVW YA,dp + a = READ_DP( -2, data ); + nz = (a & 0x7F) | (a >> 1); + y = READ_DP( 0, (uint8_t) (data + 1) ); + nz |= y; + goto inc_pc_loop; + + case 0xDA: // MOVW dp,YA + WRITE_DP( -1, data, a ); + WRITE_DP( 0, (uint8_t) (data + 1), y + no_read_before_write ); + goto inc_pc_loop; + +// 9. 16-BIT OPERATION COMMANDS + + case 0x3A: // INCW dp + case 0x1A:{// DECW dp + int temp; + // low byte + data += dp; + temp = READ( -3, data ); + temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW + nz = ((temp >> 1) | temp) & 0x7F; + WRITE( -2, data, /*(uint8_t)*/ temp ); + + // high byte + data = (uint8_t) (data + 1) + dp; + temp = (uint8_t) ((temp >> 8) + READ( -1, data )); + nz |= temp; + WRITE( 0, data, temp ); + + goto inc_pc_loop; + } + + case 0x7A: // ADDW YA,dp + case 0x9A:{// SUBW YA,dp + int lo = READ_DP( -2, data ); + int hi = READ_DP( 0, (uint8_t) (data + 1) ); + int result; + int flags; + + if ( opcode == 0x9A ) // SUBW + { + lo = (lo ^ 0xFF) + 1; + hi ^= 0xFF; + } + + lo += a; + result = y + hi + (lo >> 8); + flags = hi ^ y ^ result; + + psw = (psw & ~(v40 | h08)) | + (flags >> 1 & h08) | + ((flags + 0x80) >> 2 & v40); + c = result; + a = (uint8_t) lo; + result = (uint8_t) result; + y = result; + nz = (((lo >> 1) | lo) & 0x7F) | result; + + goto inc_pc_loop; + } + + case 0x5A: { // CMPW YA,dp + int temp = a - READ_DP( -1, data ); + nz = ((temp >> 1) | temp) & 0x7F; + temp = y + (temp >> 8); + temp -= READ_DP( 0, (uint8_t) (data + 1) ); + nz |= temp; + c = ~temp; + nz &= 0xFF; + goto inc_pc_loop; + } + +// 10. MULTIPLICATION & DIVISON COMMANDS + + case 0xCF: { // MUL YA + unsigned temp = y * a; + a = (uint8_t) temp; + nz = ((temp >> 1) | temp) & 0x7F; + y = temp >> 8; + nz |= y; + goto loop; + } + + case 0x9E: // DIV YA,X + { + unsigned ya = y * 0x100 + a; + + psw &= ~(h08 | v40); + + if ( y >= x ) + psw |= v40; + + if ( (y & 15) >= (x & 15) ) + psw |= h08; + + if ( y < x * 2 ) + { + a = ya / x; + y = ya - a * x; + } + else + { + a = 255 - (ya - x * 0x200) / (256 - x); + y = x + (ya - x * 0x200) % (256 - x); + } + + nz = (uint8_t) a; + a = (uint8_t) a; + + goto loop; + } + +// 11. DECIMAL COMPENSATION COMMANDS + + case 0xDF: // DAA + SUSPICIOUS_OPCODE( "DAA" ); + if ( a > 0x99 || c & 0x100 ) + { + a += 0x60; + c = 0x100; + } + + if ( (a & 0x0F) > 9 || psw & h08 ) + a += 0x06; + + nz = a; + a = (uint8_t) a; + goto loop; + + case 0xBE: // DAS + SUSPICIOUS_OPCODE( "DAS" ); + if ( a > 0x99 || !(c & 0x100) ) + { + a -= 0x60; + c = 0; + } + + if ( (a & 0x0F) > 9 || !(psw & h08) ) + a -= 0x06; + + nz = a; + a = (uint8_t) a; + goto loop; + +// 12. BRANCHING COMMANDS + + case 0x2F: // BRA rel + pc += (BOOST::int8_t) data; + goto inc_pc_loop; + + case 0x30: // BMI + BRANCH( (nz & nz_neg_mask) ) + + case 0x10: // BPL + BRANCH( !(nz & nz_neg_mask) ) + + case 0xB0: // BCS + BRANCH( c & 0x100 ) + + case 0x90: // BCC + BRANCH( !(c & 0x100) ) + + case 0x70: // BVS + BRANCH( psw & v40 ) + + case 0x50: // BVC + BRANCH( !(psw & v40) ) + + #define CBRANCH( cond )\ + {\ + pc++;\ + if ( cond )\ + goto cbranch_taken_loop;\ + rel_time -= 2;\ + goto inc_pc_loop;\ + } + + case 0x03: // BBS dp.bit,rel + case 0x23: + case 0x43: + case 0x63: + case 0x83: + case 0xA3: + case 0xC3: + case 0xE3: + CBRANCH( READ_DP( -4, data ) >> (opcode >> 5) & 1 ) + + case 0x13: // BBC dp.bit,rel + case 0x33: + case 0x53: + case 0x73: + case 0x93: + case 0xB3: + case 0xD3: + case 0xF3: + CBRANCH( !(READ_DP( -4, data ) >> (opcode >> 5) & 1) ) + + case 0xDE: // CBNE dp+X,rel + data = (uint8_t) (data + x); + // fall through + case 0x2E:{// CBNE dp,rel + int temp; + // 61% from timer + READ_DP_TIMER( -4, data, temp ); + CBRANCH( temp != a ) + } + + case 0x6E: { // DBNZ dp,rel + unsigned temp = READ_DP( -4, data ) - 1; + WRITE_DP( -3, (uint8_t) data, /*(uint8_t)*/ temp + no_read_before_write ); + CBRANCH( temp ) + } + + case 0xFE: // DBNZ Y,rel + y = (uint8_t) (y - 1); + BRANCH( y ) + + case 0x1F: // JMP [abs+X] + SET_PC( READ_PC16( pc ) + x ); + // fall through + case 0x5F: // JMP abs + SET_PC( READ_PC16( pc ) ); + goto loop; + +// 13. SUB-ROUTINE CALL RETURN COMMANDS + + case 0x0F:{// BRK + int temp; + int ret_addr = GET_PC(); + SUSPICIOUS_OPCODE( "BRK" ); + SET_PC( READ_PROG16( 0xFFDE ) ); // vector address verified + PUSH16( ret_addr ); + GET_PSW( temp ); + psw = (psw | b10) & ~i04; + PUSH( temp ); + goto loop; + } + + case 0x4F:{// PCALL offset + int ret_addr = GET_PC() + 1; + SET_PC( 0xFF00 | data ); + PUSH16( ret_addr ); + goto loop; + } + + case 0x01: // TCALL n + case 0x11: + case 0x21: + case 0x31: + case 0x41: + case 0x51: + case 0x61: + case 0x71: + case 0x81: + case 0x91: + case 0xA1: + case 0xB1: + case 0xC1: + case 0xD1: + case 0xE1: + case 0xF1: { + int ret_addr = GET_PC(); + SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) ); + PUSH16( ret_addr ); + goto loop; + } + +// 14. STACK OPERATION COMMANDS + + { + int temp; + case 0x7F: // RET1 + temp = *sp; + SET_PC( GET_LE16( sp + 1 ) ); + sp += 3; + goto set_psw; + case 0x8E: // POP PSW + POP( temp ); + set_psw: + SET_PSW( temp ); + goto loop; + } + + case 0x0D: { // PUSH PSW + int temp; + GET_PSW( temp ); + PUSH( temp ); + goto loop; + } + + case 0x2D: // PUSH A + PUSH( a ); + goto loop; + + case 0x4D: // PUSH X + PUSH( x ); + goto loop; + + case 0x6D: // PUSH Y + PUSH( y ); + goto loop; + + case 0xAE: // POP A + POP( a ); + goto loop; + + case 0xCE: // POP X + POP( x ); + goto loop; + + case 0xEE: // POP Y + POP( y ); + goto loop; + +// 15. BIT OPERATION COMMANDS + + case 0x02: // SET1 + case 0x22: + case 0x42: + case 0x62: + case 0x82: + case 0xA2: + case 0xC2: + case 0xE2: + case 0x12: // CLR1 + case 0x32: + case 0x52: + case 0x72: + case 0x92: + case 0xB2: + case 0xD2: + case 0xF2: { + int bit = 1 << (opcode >> 5); + int mask = ~bit; + if ( opcode & 0x10 ) + bit = 0; + data += dp; + WRITE( 0, data, (READ( -1, data ) & mask) | bit ); + goto inc_pc_loop; + } + + case 0x0E: // TSET1 abs + case 0x4E: // TCLR1 abs + data = READ_PC16( pc ); + pc += 2; + { + unsigned temp = READ( -2, data ); + nz = (uint8_t) (a - temp); + temp &= ~a; + if ( opcode == 0x0E ) + temp |= a; + WRITE( 0, data, temp ); + } + goto loop; + + case 0x4A: // AND1 C,mem.bit + c &= MEM_BIT( 0 ); + pc += 2; + goto loop; + + case 0x6A: // AND1 C,/mem.bit + c &= ~MEM_BIT( 0 ); + pc += 2; + goto loop; + + case 0x0A: // OR1 C,mem.bit + c |= MEM_BIT( -1 ); + pc += 2; + goto loop; + + case 0x2A: // OR1 C,/mem.bit + c |= ~MEM_BIT( -1 ); + pc += 2; + goto loop; + + case 0x8A: // EOR1 C,mem.bit + c ^= MEM_BIT( -1 ); + pc += 2; + goto loop; + + case 0xEA: // NOT1 mem.bit + data = READ_PC16( pc ); + pc += 2; + { + unsigned temp = READ( -1, data & 0x1FFF ); + temp ^= 1 << (data >> 13); + WRITE( 0, data & 0x1FFF, temp ); + } + goto loop; + + case 0xCA: // MOV1 mem.bit,C + data = READ_PC16( pc ); + pc += 2; + { + unsigned temp = READ( -2, data & 0x1FFF ); + unsigned bit = data >> 13; + temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit); + WRITE( 0, data & 0x1FFF, temp + no_read_before_write ); + } + goto loop; + + case 0xAA: // MOV1 C,mem.bit + c = MEM_BIT( 0 ); + pc += 2; + goto loop; + +// 16. PROGRAM PSW FLAG OPERATION COMMANDS + + case 0x60: // CLRC + c = 0; + goto loop; + + case 0x80: // SETC + c = ~0; + goto loop; + + case 0xED: // NOTC + c ^= 0x100; + goto loop; + + case 0xE0: // CLRV + psw &= ~(v40 | h08); + goto loop; + + case 0x20: // CLRP + dp = 0; + goto loop; + + case 0x40: // SETP + dp = 0x100; + goto loop; + + case 0xA0: // EI + SUSPICIOUS_OPCODE( "EI" ); + psw |= i04; + goto loop; + + case 0xC0: // DI + SUSPICIOUS_OPCODE( "DI" ); + psw &= ~i04; + goto loop; + +// 17. OTHER COMMANDS + + case 0x00: // NOP + goto loop; + + case 0xFF:{// STOP + // handle PC wrap-around + unsigned addr = GET_PC() - 1; + if ( addr >= 0x10000 ) + { + addr &= 0xFFFF; + SET_PC( addr ); + dprintf( "SPC: PC wrapped around\n" ); + goto loop; + } + } + // fall through + case 0xEF: // SLEEP + SUSPICIOUS_OPCODE( "STOP/SLEEP" ); + --pc; + rel_time = 0; + m.cpu_error = "SPC emulation error"; + goto stop; + } // switch + + assert( 0 ); // catch any unhandled instructions +} +out_of_time: + rel_time -= m.cycle_table [*pc]; // undo partial execution of opcode +stop: + + // Uncache registers + if ( GET_PC() >= 0x10000 ) + dprintf( "SPC: PC wrapped around\n" ); + m.cpu_regs.pc = (uint16_t) GET_PC(); + m.cpu_regs.sp = ( uint8_t) GET_SP(); + m.cpu_regs.a = ( uint8_t) a; + m.cpu_regs.x = ( uint8_t) x; + m.cpu_regs.y = ( uint8_t) y; + { + int temp; + GET_PSW( temp ); + m.cpu_regs.psw = (uint8_t) temp; + } +} +SPC_CPU_RUN_FUNC_END diff --git a/apu/SPC_DSP.cpp b/apu/SPC_DSP.cpp new file mode 100644 index 00000000..621d73fc --- /dev/null +++ b/apu/SPC_DSP.cpp @@ -0,0 +1,1062 @@ +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "SPC_DSP.h" + +#include "blargg_endian.h" +#include + +/* Copyright (C) 2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +#ifdef BLARGG_ENABLE_OPTIMIZER + #include BLARGG_ENABLE_OPTIMIZER +#endif + +#if INT_MAX < 0x7FFFFFFF + #error "Requires that int type have at least 32 bits" +#endif + +// TODO: add to blargg_endian.h +#define GET_LE16SA( addr ) ((BOOST::int16_t) GET_LE16( addr )) +#define GET_LE16A( addr ) GET_LE16( addr ) +#define SET_LE16A( addr, data ) SET_LE16( addr, data ) + +static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] = +{ + 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80, + 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF, + 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A, + 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF, + 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67, + 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x9C,0x4E,0x7B,0xFF, + 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F, + 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF +}; + +// if ( io < -32768 ) io = -32768; +// if ( io > 32767 ) io = 32767; +#define CLAMP16( io )\ +{\ + if ( (int16_t) io != io )\ + io = (io >> 31) ^ 0x7FFF;\ +} + +// Access global DSP register +#define REG(n) m.regs [r_##n] + +// Access voice DSP register +#define VREG(r,n) r [v_##n] + +#define WRITE_SAMPLES( l, r, out ) \ +{\ + out [0] = l;\ + out [1] = r;\ + out += 2;\ + if ( out >= m.out_end )\ + {\ + check( out == m.out_end );\ + check( m.out_end != &m.extra [extra_size] || \ + (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\ + out = m.extra;\ + m.out_end = &m.extra [extra_size];\ + }\ +}\ + +void SPC_DSP::set_output( sample_t* out, int size ) +{ + require( (size & 1) == 0 ); // must be even + if ( !out ) + { + out = m.extra; + size = extra_size; + } + m.out_begin = out; + m.out = out; + m.out_end = out + size; +} + +// Volume registers and efb are signed! Easy to forget int8_t cast. +// Prefixes are to avoid accidental use of locals with same names. + +// Gaussian interpolation + +static short const gauss [512] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, + 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, + 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17, + 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27, + 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + 58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77, + 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102, + 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132, + 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168, + 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210, + 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257, + 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311, + 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370, + 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434, + 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504, + 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577, + 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654, + 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732, + 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811, + 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889, + 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965, + 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036, +1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102, +1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160, +1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210, +1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251, +1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280, +1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298, +1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, +}; + +inline int SPC_DSP::interpolate( voice_t const* v ) +{ + // Make pointers into gaussian based on fractional position between samples + int offset = v->interp_pos >> 4 & 0xFF; + short const* fwd = gauss + 255 - offset; + short const* rev = gauss + offset; // mirror left half of gaussian + + int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos]; + int out; + out = (fwd [ 0] * in [0]) >> 11; + out += (fwd [256] * in [1]) >> 11; + out += (rev [256] * in [2]) >> 11; + out = (int16_t) out; + out += (rev [ 0] * in [3]) >> 11; + + CLAMP16( out ); + out &= ~1; + return out; +} + + +//// Counters + +int const simple_counter_range = 2048 * 5 * 3; // 30720 + +static unsigned const counter_rates [32] = +{ + simple_counter_range + 1, // never fires + 2048, 1536, + 1280, 1024, 768, + 640, 512, 384, + 320, 256, 192, + 160, 128, 96, + 80, 64, 48, + 40, 32, 24, + 20, 16, 12, + 10, 8, 6, + 5, 4, 3, + 2, + 1 +}; + +static unsigned const counter_offsets [32] = +{ + 1, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 536, 0, 1040, + 0, + 0 +}; + +inline void SPC_DSP::init_counter() +{ + m.counter = 0; +} + +inline void SPC_DSP::run_counters() +{ + if ( --m.counter < 0 ) + m.counter = simple_counter_range - 1; +} + +inline unsigned SPC_DSP::read_counter( int rate ) +{ + return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate]; +} + + +//// Envelope + +inline void SPC_DSP::run_envelope( voice_t* const v ) +{ + int env = v->env; + if ( v->env_mode == env_release ) // 60% + { + if ( (env -= 0x8) < 0 ) + env = 0; + v->env = env; + } + else + { + int rate; + int env_data = VREG(v->regs,adsr1); + if ( m.t_adsr0 & 0x80 ) // 99% ADSR + { + if ( v->env_mode >= env_decay ) // 99% + { + env--; + env -= env >> 8; + rate = env_data & 0x1F; + if ( v->env_mode == env_decay ) // 1% + rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10; + } + else // env_attack + { + rate = (m.t_adsr0 & 0x0F) * 2 + 1; + env += rate < 31 ? 0x20 : 0x400; + } + } + else // GAIN + { + int mode; + env_data = VREG(v->regs,gain); + mode = env_data >> 5; + if ( mode < 4 ) // direct + { + env = env_data * 0x10; + rate = 31; + } + else + { + rate = env_data & 0x1F; + if ( mode == 4 ) // 4: linear decrease + { + env -= 0x20; + } + else if ( mode < 6 ) // 5: exponential decrease + { + env--; + env -= env >> 8; + } + else // 6,7: linear increase + { + env += 0x20; + if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 ) + env += 0x8 - 0x20; // 7: two-slope linear increase + } + } + } + + // Sustain level + if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay ) + v->env_mode = env_sustain; + + v->hidden_env = env; + + // unsigned cast because linear decrease going negative also triggers this + if ( (unsigned) env > 0x7FF ) + { + env = (env < 0 ? 0 : 0x7FF); + if ( v->env_mode == env_attack ) + v->env_mode = env_decay; + } + + if ( !read_counter( rate ) ) + v->env = env; // nothing else is controlled by the counter + } +} + + +//// BRR Decoding + +inline void SPC_DSP::decode_brr( voice_t* v ) +{ + // Arrange the four input nybbles in 0xABCD order for easy decoding + int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF]; + + int const header = m.t_brr_header; + + // Write to next four samples in circular buffer + int* pos = &v->buf [v->buf_pos]; + int* end; + if ( (v->buf_pos += 4) >= brr_buf_size ) + v->buf_pos = 0; + + // Decode four samples + for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 ) + { + // Extract nybble and sign-extend + int s = (int16_t) nybbles >> 12; + + // Shift sample based on header + int const shift = header >> 4; + s = (s << shift) >> 1; + if ( shift >= 0xD ) // handle invalid range + s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0) + + // Apply IIR filter (8 is the most commonly used) + int const filter = header & 0x0C; + int const p1 = pos [brr_buf_size - 1]; + int const p2 = pos [brr_buf_size - 2] >> 1; + if ( filter >= 8 ) + { + s += p1; + s -= p2; + if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875 + { + s += p2 >> 4; + s += (p1 * -3) >> 6; + } + else // s += p1 * 0.8984375 - p2 * 0.40625 + { + s += (p1 * -13) >> 7; + s += (p2 * 3) >> 4; + } + } + else if ( filter ) // s += p1 * 0.46875 + { + s += p1 >> 1; + s += (-p1) >> 5; + } + + // Adjust and write sample + CLAMP16( s ); + s = (int16_t) (s * 2); + pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around + } +} + + +//// Misc + +#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n() + +MISC_CLOCK( 27 ) +{ + m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON +} +MISC_CLOCK( 28 ) +{ + m.t_non = REG(non); + m.t_eon = REG(eon); + m.t_dir = REG(dir); +} +MISC_CLOCK( 29 ) +{ + if ( (m.every_other_sample ^= 1) != 0 ) + m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read +} +MISC_CLOCK( 30 ) +{ + if ( m.every_other_sample ) + { + m.kon = m.new_kon; + m.t_koff = REG(koff) | m.mute_mask; + } + + run_counters(); + + // Noise + if ( !read_counter( REG(flg) & 0x1F ) ) + { + int feedback = (m.noise << 13) ^ (m.noise << 14); + m.noise = (feedback & 0x4000) ^ (m.noise >> 1); + } +} + + +//// Voices + +#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v ) + +inline VOICE_CLOCK( V1 ) +{ + m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4; + m.t_srcn = VREG(v->regs,srcn); +} +inline VOICE_CLOCK( V2 ) +{ + // Read sample pointer (ignored if not needed) + uint8_t const* entry = &m.ram [m.t_dir_addr]; + if ( !v->kon_delay ) + entry += 2; + m.t_brr_next_addr = GET_LE16A( entry ); + + m.t_adsr0 = VREG(v->regs,adsr0); + + // Read pitch, spread over two clocks + m.t_pitch = VREG(v->regs,pitchl); +} +inline VOICE_CLOCK( V3a ) +{ + m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8; +} +inline VOICE_CLOCK( V3b ) +{ + // Read BRR header and byte + m.t_brr_byte = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF]; + m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking +} +VOICE_CLOCK( V3c ) +{ + // Pitch modulation using previous voice's output + if ( m.t_pmon & v->vbit ) + m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10; + + if ( v->kon_delay ) + { + // Get ready to start BRR decoding on next sample + if ( v->kon_delay == 5 ) + { + v->brr_addr = m.t_brr_next_addr; + v->brr_offset = 1; + v->buf_pos = 0; + m.t_brr_header = 0; // header is ignored on this sample + m.kon_check = true; + + if (take_spc_snapshot) + { + take_spc_snapshot = 0; + if (spc_snapshot_callback) + spc_snapshot_callback(); + } + } + + // Envelope is never run during KON + v->env = 0; + v->hidden_env = 0; + + // Disable BRR decoding until last three samples + v->interp_pos = 0; + if ( --v->kon_delay & 3 ) + v->interp_pos = 0x4000; + + // Pitch is never added during KON + m.t_pitch = 0; + } + + // Gaussian interpolation + { + int output = interpolate( v ); + + // Noise + if ( m.t_non & v->vbit ) + output = (int16_t) (m.noise * 2); + + // Apply envelope + m.t_output = (output * v->env) >> 11 & ~1; + v->t_envx_out = (uint8_t) (v->env >> 4); + } + + // Immediate silence due to end of sample or soft reset + if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 ) + { + v->env_mode = env_release; + v->env = 0; + } + + if ( m.every_other_sample ) + { + // KOFF + if ( m.t_koff & v->vbit ) + v->env_mode = env_release; + + // KON + if ( m.kon & v->vbit ) + { + v->kon_delay = 5; + v->env_mode = env_attack; + } + } + + // Run envelope for next sample + if ( !v->kon_delay ) + run_envelope( v ); +} + +inline void SPC_DSP::voice_output( voice_t const* v, int ch ) +{ + // Apply left/right volume + int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7; + amp *= ((stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0); + + // Add to output total + m.t_main_out [ch] += amp; + CLAMP16( m.t_main_out [ch] ); + + // Optionally add to echo total + if ( m.t_eon & v->vbit ) + { + m.t_echo_out [ch] += amp; + CLAMP16( m.t_echo_out [ch] ); + } +} +VOICE_CLOCK( V4 ) +{ + // Decode BRR + m.t_looped = 0; + if ( v->interp_pos >= 0x4000 ) + { + decode_brr( v ); + + if ( (v->brr_offset += 2) >= brr_block_size ) + { + // Start decoding next BRR block + assert( v->brr_offset == brr_block_size ); + v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF; + if ( m.t_brr_header & 1 ) + { + v->brr_addr = m.t_brr_next_addr; + m.t_looped = v->vbit; + } + v->brr_offset = 1; + } + } + + // Apply pitch + v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch; + + // Keep from getting too far ahead (when using pitch modulation) + if ( v->interp_pos > 0x7FFF ) + v->interp_pos = 0x7FFF; + + // Output left + voice_output( v, 0 ); +} +inline VOICE_CLOCK( V5 ) +{ + // Output right + voice_output( v, 1 ); + + // ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier + int endx_buf = REG(endx) | m.t_looped; + + // Clear bit in ENDX if KON just began + if ( v->kon_delay == 5 ) + endx_buf &= ~v->vbit; + m.endx_buf = (uint8_t) endx_buf; +} +inline VOICE_CLOCK( V6 ) +{ + (void) v; // avoid compiler warning about unused v + m.outx_buf = (uint8_t) (m.t_output >> 8); +} +inline VOICE_CLOCK( V7 ) +{ + // Update ENDX + REG(endx) = m.endx_buf; + + m.envx_buf = v->t_envx_out; +} +inline VOICE_CLOCK( V8 ) +{ + // Update OUTX + VREG(v->regs,outx) = m.outx_buf; +} +inline VOICE_CLOCK( V9 ) +{ + // Update ENVX + VREG(v->regs,envx) = m.envx_buf; +} + +// Most voices do all these in one clock, so make a handy composite +inline VOICE_CLOCK( V3 ) +{ + voice_V3a( v ); + voice_V3b( v ); + voice_V3c( v ); +} + +// Common combinations of voice steps on different voices. This greatly reduces +// code size and allows everything to be inlined in these functions. +VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); } +VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); } +VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); } + + +//// Echo + +// Current echo buffer pointer for left/right channel +#define ECHO_PTR( ch ) (&m.ram [m.t_echo_ptr + ch * 2]) + +// Sample in echo history buffer, where 0 is the oldest +#define ECHO_FIR( i ) (m.echo_hist_pos [i]) + +// Calculate FIR point for left/right channel +#define CALC_FIR( i, ch ) ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6) + +#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n() + +inline void SPC_DSP::echo_read( int ch ) +{ + int s = GET_LE16SA( ECHO_PTR( ch ) ); + // second copy simplifies wrap-around handling + ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1; +} + +ECHO_CLOCK( 22 ) +{ + // History + if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] ) + m.echo_hist_pos = m.echo_hist; + + m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF; + echo_read( 0 ); + + // FIR (using l and r temporaries below helps compiler optimize) + int l = CALC_FIR( 0, 0 ); + int r = CALC_FIR( 0, 1 ); + + m.t_echo_in [0] = l; + m.t_echo_in [1] = r; +} +ECHO_CLOCK( 23 ) +{ + int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 ); + int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 ); + + m.t_echo_in [0] += l; + m.t_echo_in [1] += r; + + echo_read( 1 ); +} +ECHO_CLOCK( 24 ) +{ + int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 ); + int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 ); + + m.t_echo_in [0] += l; + m.t_echo_in [1] += r; +} +ECHO_CLOCK( 25 ) +{ + int l = m.t_echo_in [0] + CALC_FIR( 6, 0 ); + int r = m.t_echo_in [1] + CALC_FIR( 6, 1 ); + + l = (int16_t) l; + r = (int16_t) r; + + l += (int16_t) CALC_FIR( 7, 0 ); + r += (int16_t) CALC_FIR( 7, 1 ); + + CLAMP16( l ); + CLAMP16( r ); + + m.t_echo_in [0] = l & ~1; + m.t_echo_in [1] = r & ~1; +} +inline int SPC_DSP::echo_output( int ch ) +{ + int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) + + (int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7); + CLAMP16( out ); + return out; +} +ECHO_CLOCK( 26 ) +{ + // Left output volumes + // (save sample for next clock so we can output both together) + m.t_main_out [0] = echo_output( 0 ); + + // Echo feedback + int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7); + int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7); + + CLAMP16( l ); + CLAMP16( r ); + + m.t_echo_out [0] = l & ~1; + m.t_echo_out [1] = r & ~1; +} +ECHO_CLOCK( 27 ) +{ + // Output + int l = m.t_main_out [0]; + int r = echo_output( 1 ); + m.t_main_out [0] = 0; + m.t_main_out [1] = 0; + + // TODO: global muting isn't this simple (turns DAC on and off + // or something, causing small ~37-sample pulse when first muted) + if ( REG(flg) & 0x40 ) + { + l = 0; + r = 0; + } + + // Output sample to DAC + #ifdef SPC_DSP_OUT_HOOK + SPC_DSP_OUT_HOOK( l, r ); + #else + sample_t* out = m.out; + WRITE_SAMPLES( l, r, out ); + m.out = out; + #endif +} +ECHO_CLOCK( 28 ) +{ + m.t_echo_enabled = REG(flg); +} +inline void SPC_DSP::echo_write( int ch ) +{ + if ( !(m.t_echo_enabled & 0x20) ) + SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] ); + m.t_echo_out [ch] = 0; +} +ECHO_CLOCK( 29 ) +{ + m.t_esa = REG(esa); + + if ( !m.echo_offset ) + m.echo_length = (REG(edl) & 0x0F) * 0x800; + + m.echo_offset += 4; + if ( m.echo_offset >= m.echo_length ) + m.echo_offset = 0; + + // Write left echo + echo_write( 0 ); + + m.t_echo_enabled = REG(flg); +} +ECHO_CLOCK( 30 ) +{ + // Write right echo + echo_write( 1 ); +} + + +//// Timing + +// Execute clock for a particular voice +#define V( clock, voice ) voice_##clock( &m.voices [voice] ); + +/* The most common sequence of clocks uses composite operations +for efficiency. For example, the following are equivalent to the +individual steps on the right: + +V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5) +V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4) +V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */ + +// Voice 0 1 2 3 4 5 6 7 +#define GEN_DSP_TIMING \ +PHASE( 0) V(V5,0)V(V2,1)\ +PHASE( 1) V(V6,0)V(V3,1)\ +PHASE( 2) V(V7_V4_V1,0)\ +PHASE( 3) V(V8_V5_V2,0)\ +PHASE( 4) V(V9_V6_V3,0)\ +PHASE( 5) V(V7_V4_V1,1)\ +PHASE( 6) V(V8_V5_V2,1)\ +PHASE( 7) V(V9_V6_V3,1)\ +PHASE( 8) V(V7_V4_V1,2)\ +PHASE( 9) V(V8_V5_V2,2)\ +PHASE(10) V(V9_V6_V3,2)\ +PHASE(11) V(V7_V4_V1,3)\ +PHASE(12) V(V8_V5_V2,3)\ +PHASE(13) V(V9_V6_V3,3)\ +PHASE(14) V(V7_V4_V1,4)\ +PHASE(15) V(V8_V5_V2,4)\ +PHASE(16) V(V9_V6_V3,4)\ +PHASE(17) V(V1,0) V(V7,5)V(V4,6)\ +PHASE(18) V(V8_V5_V2,5)\ +PHASE(19) V(V9_V6_V3,5)\ +PHASE(20) V(V1,1) V(V7,6)V(V4,7)\ +PHASE(21) V(V8,6)V(V5,7) V(V2,0) /* t_brr_next_addr order dependency */\ +PHASE(22) V(V3a,0) V(V9,6)V(V6,7) echo_22();\ +PHASE(23) V(V7,7) echo_23();\ +PHASE(24) V(V8,7) echo_24();\ +PHASE(25) V(V3b,0) V(V9,7) echo_25();\ +PHASE(26) echo_26();\ +PHASE(27) misc_27(); echo_27();\ +PHASE(28) misc_28(); echo_28();\ +PHASE(29) misc_29(); echo_29();\ +PHASE(30) misc_30();V(V3c,0) echo_30();\ +PHASE(31) V(V4,0) V(V1,2)\ + +#if !SPC_DSP_CUSTOM_RUN + +void SPC_DSP::run( int clocks_remain ) +{ + require( clocks_remain > 0 ); + + int const phase = m.phase; + m.phase = (phase + clocks_remain) & 31; + switch ( phase ) + { + loop: + + #define PHASE( n ) if ( n && !--clocks_remain ) break; case n: + GEN_DSP_TIMING + #undef PHASE + + if ( --clocks_remain ) + goto loop; + } +} + +#endif + + +//// Setup + +void SPC_DSP::init( void* ram_64k ) +{ + m.ram = (uint8_t*) ram_64k; + mute_voices( 0 ); + disable_surround( false ); + set_output( 0, 0 ); + reset(); + + stereo_switch = 0xffff; + take_spc_snapshot = 0; + spc_snapshot_callback = 0; + + #ifndef NDEBUG + // be sure this sign-extends + assert( (int16_t) 0x8000 == -0x8000 ); + + // be sure right shift preserves sign + assert( (-1 >> 1) == -1 ); + + // check clamp macro + int i; + i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF ); + i = -0x8001; CLAMP16( i ); assert( i == -0x8000 ); + + blargg_verify_byte_order(); + #endif +} + +void SPC_DSP::soft_reset_common() +{ + require( m.ram ); // init() must have been called already + + m.noise = 0x4000; + m.echo_hist_pos = m.echo_hist; + m.every_other_sample = 1; + m.echo_offset = 0; + m.phase = 0; + + init_counter(); + + for (int i = 0; i < voice_count; i++) + m.voices[i].voice_number = i; +} + +void SPC_DSP::soft_reset() +{ + REG(flg) = 0xE0; + soft_reset_common(); +} + +void SPC_DSP::load( uint8_t const regs [register_count] ) +{ + memcpy( m.regs, regs, sizeof m.regs ); + memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count ); + + // Internal state + for ( int i = voice_count; --i >= 0; ) + { + voice_t* v = &m.voices [i]; + v->brr_offset = 1; + v->vbit = 1 << i; + v->regs = &m.regs [i * 0x10]; + } + m.new_kon = REG(kon); + m.t_dir = REG(dir); + m.t_esa = REG(esa); + + soft_reset_common(); +} + +void SPC_DSP::reset() { load( initial_regs ); } + + +//// State save/load + +#if !SPC_NO_COPY_STATE_FUNCS + +void SPC_State_Copier::copy( void* state, size_t size ) +{ + func( buf, state, size ); +} + +int SPC_State_Copier::copy_int( int state, int size ) +{ + BOOST::uint8_t s [2]; + SET_LE16( s, state ); + func( buf, &s, size ); + return GET_LE16( s ); +} + +void SPC_State_Copier::skip( int count ) +{ + if ( count > 0 ) + { + char temp [64]; + memset( temp, 0, sizeof temp ); + do + { + int n = sizeof temp; + if ( n > count ) + n = count; + count -= n; + func( buf, temp, n ); + } + while ( count ); + } +} + +void SPC_State_Copier::extra() +{ + int n = 0; + SPC_State_Copier& copier = *this; + SPC_COPY( uint8_t, n ); + skip( n ); +} + +void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy ) +{ + SPC_State_Copier copier( io, copy ); + + // DSP registers + copier.copy( m.regs, register_count ); + + // Internal state + + // Voices + int i; + for ( i = 0; i < voice_count; i++ ) + { + voice_t* v = &m.voices [i]; + + // BRR buffer + int i; + for ( i = 0; i < brr_buf_size; i++ ) + { + int s = v->buf [i]; + SPC_COPY( int16_t, s ); + v->buf [i] = v->buf [i + brr_buf_size] = s; + } + + SPC_COPY( uint16_t, v->interp_pos ); + SPC_COPY( uint16_t, v->brr_addr ); + SPC_COPY( uint16_t, v->env ); + SPC_COPY( int16_t, v->hidden_env ); + SPC_COPY( uint8_t, v->buf_pos ); + SPC_COPY( uint8_t, v->brr_offset ); + SPC_COPY( uint8_t, v->kon_delay ); + { + int m = v->env_mode; + SPC_COPY( uint8_t, m ); + v->env_mode = (enum env_mode_t) m; + } + SPC_COPY( uint8_t, v->t_envx_out ); + + copier.extra(); + } + + // Echo history + for ( i = 0; i < echo_hist_size; i++ ) + { + int j; + for ( j = 0; j < 2; j++ ) + { + int s = m.echo_hist_pos [i] [j]; + SPC_COPY( int16_t, s ); + m.echo_hist [i] [j] = s; // write back at offset 0 + } + } + m.echo_hist_pos = m.echo_hist; + memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] ); + + // Misc + SPC_COPY( uint8_t, m.every_other_sample ); + SPC_COPY( uint8_t, m.kon ); + + SPC_COPY( uint16_t, m.noise ); + SPC_COPY( uint16_t, m.counter ); + SPC_COPY( uint16_t, m.echo_offset ); + SPC_COPY( uint16_t, m.echo_length ); + SPC_COPY( uint8_t, m.phase ); + + SPC_COPY( uint8_t, m.new_kon ); + SPC_COPY( uint8_t, m.endx_buf ); + SPC_COPY( uint8_t, m.envx_buf ); + SPC_COPY( uint8_t, m.outx_buf ); + + SPC_COPY( uint8_t, m.t_pmon ); + SPC_COPY( uint8_t, m.t_non ); + SPC_COPY( uint8_t, m.t_eon ); + SPC_COPY( uint8_t, m.t_dir ); + SPC_COPY( uint8_t, m.t_koff ); + + SPC_COPY( uint16_t, m.t_brr_next_addr ); + SPC_COPY( uint8_t, m.t_adsr0 ); + SPC_COPY( uint8_t, m.t_brr_header ); + SPC_COPY( uint8_t, m.t_brr_byte ); + SPC_COPY( uint8_t, m.t_srcn ); + SPC_COPY( uint8_t, m.t_esa ); + SPC_COPY( uint8_t, m.t_echo_enabled ); + + SPC_COPY( int16_t, m.t_main_out [0] ); + SPC_COPY( int16_t, m.t_main_out [1] ); + SPC_COPY( int16_t, m.t_echo_out [0] ); + SPC_COPY( int16_t, m.t_echo_out [1] ); + SPC_COPY( int16_t, m.t_echo_in [0] ); + SPC_COPY( int16_t, m.t_echo_in [1] ); + + SPC_COPY( uint16_t, m.t_dir_addr ); + SPC_COPY( uint16_t, m.t_pitch ); + SPC_COPY( int16_t, m.t_output ); + SPC_COPY( uint16_t, m.t_echo_ptr ); + SPC_COPY( uint8_t, m.t_looped ); + + copier.extra(); +} +#endif + + +//// Snes9x Accessor + +void SPC_DSP::set_spc_snapshot_callback( void (*callback) (void) ) +{ + spc_snapshot_callback = callback; +} + +void SPC_DSP::dump_spc_snapshot( void ) +{ + take_spc_snapshot = 1; +} + +void SPC_DSP::set_stereo_switch( int value ) +{ + stereo_switch = value; +} + +SPC_DSP::uint8_t SPC_DSP::reg_value( int ch, int addr ) +{ + return m.voices[ch].regs[addr]; +} + +int SPC_DSP::envx_value( int ch ) +{ + return m.voices[ch].env; +} diff --git a/apu/SPC_DSP.h b/apu/SPC_DSP.h new file mode 100644 index 00000000..6705a490 --- /dev/null +++ b/apu/SPC_DSP.h @@ -0,0 +1,317 @@ +// Highly accurate SNES SPC-700 DSP emulator + +// snes_spc 0.9.0 +#ifndef SPC_DSP_H +#define SPC_DSP_H + +#include "blargg_common.h" + +extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); } + +class SPC_DSP { +public: + typedef BOOST::uint8_t uint8_t; + +// Setup + + // Initializes DSP and has it use the 64K RAM provided + void init( void* ram_64k ); + + // Sets destination for output samples. If out is NULL or out_size is 0, + // doesn't generate any. + typedef short sample_t; + void set_output( sample_t* out, int out_size ); + + // Number of samples written to output since it was last set, always + // a multiple of 2. Undefined if more samples were generated than + // output buffer could hold. + int sample_count() const; + +// Emulation + + // Resets DSP to power-on state + void reset(); + + // Emulates pressing reset switch on SNES + void soft_reset(); + + // Reads/writes DSP registers. For accuracy, you must first call run() + // to catch the DSP up to present. + int read ( int addr ) const; + void write( int addr, int data ); + + // Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks + // a pair of samples is be generated. + void run( int clock_count ); + +// Sound control + + // Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events). + // Reduces emulation accuracy. + enum { voice_count = 8 }; + void mute_voices( int mask ); + +// State + + // Resets DSP and uses supplied values to initialize registers + enum { register_count = 128 }; + void load( uint8_t const regs [register_count] ); + + // Saves/loads exact emulator state + enum { state_size = 640 }; // maximum space needed when saving + typedef dsp_copy_func_t copy_func_t; + void copy_state( unsigned char** io, copy_func_t ); + + // Returns non-zero if new key-on events occurred since last call + bool check_kon(); + +// Snes9x Accessor + + int stereo_switch; + int take_spc_snapshot; + void (*spc_snapshot_callback) (void); + + void set_spc_snapshot_callback( void (*callback) (void) ); + void dump_spc_snapshot( void ); + void set_stereo_switch( int ); + uint8_t reg_value( int, int ); + int envx_value( int ); + +// DSP register addresses + + // Global registers + enum { + r_mvoll = 0x0C, r_mvolr = 0x1C, + r_evoll = 0x2C, r_evolr = 0x3C, + r_kon = 0x4C, r_koff = 0x5C, + r_flg = 0x6C, r_endx = 0x7C, + r_efb = 0x0D, r_pmon = 0x2D, + r_non = 0x3D, r_eon = 0x4D, + r_dir = 0x5D, r_esa = 0x6D, + r_edl = 0x7D, + r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F + }; + + // Voice registers + enum { + v_voll = 0x00, v_volr = 0x01, + v_pitchl = 0x02, v_pitchh = 0x03, + v_srcn = 0x04, v_adsr0 = 0x05, + v_adsr1 = 0x06, v_gain = 0x07, + v_envx = 0x08, v_outx = 0x09 + }; + +public: + enum { extra_size = 16 }; + sample_t* extra() { return m.extra; } + sample_t const* out_pos() const { return m.out; } + void disable_surround( bool ) { } // not supported +public: + BLARGG_DISABLE_NOTHROW + + typedef BOOST::int8_t int8_t; + typedef BOOST::int16_t int16_t; + + enum { echo_hist_size = 8 }; + + enum env_mode_t { env_release, env_attack, env_decay, env_sustain }; + enum { brr_buf_size = 12 }; + struct voice_t + { + int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling) + int buf_pos; // place in buffer where next samples will be decoded + int interp_pos; // relative fractional position in sample (0x1000 = 1.0) + int brr_addr; // address of current BRR block + int brr_offset; // current decoding offset in BRR block + uint8_t* regs; // pointer to voice's DSP registers + int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc. + int kon_delay; // KON delay/current setup phase + env_mode_t env_mode; + int env; // current envelope level + int hidden_env; // used by GAIN mode 7, very obscure quirk + uint8_t t_envx_out; + int voice_number; + }; +private: + enum { brr_block_size = 9 }; + + struct state_t + { + uint8_t regs [register_count]; + + // Echo history keeps most recent 8 samples (twice the size to simplify wrap handling) + int echo_hist [echo_hist_size * 2] [2]; + int (*echo_hist_pos) [2]; // &echo_hist [0 to 7] + + int every_other_sample; // toggles every sample + int kon; // KON value when last checked + int noise; + int counter; + int echo_offset; // offset from ESA in echo buffer + int echo_length; // number of bytes that echo_offset will stop at + int phase; // next clock cycle to run (0-31) + bool kon_check; // set when a new KON occurs + + // Hidden registers also written to when main register is written to + int new_kon; + uint8_t endx_buf; + uint8_t envx_buf; + uint8_t outx_buf; + + // Temporary state between clocks + + // read once per sample + int t_pmon; + int t_non; + int t_eon; + int t_dir; + int t_koff; + + // read a few clocks ahead then used + int t_brr_next_addr; + int t_adsr0; + int t_brr_header; + int t_brr_byte; + int t_srcn; + int t_esa; + int t_echo_enabled; + + // internal state that is recalculated every sample + int t_dir_addr; + int t_pitch; + int t_output; + int t_looped; + int t_echo_ptr; + + // left/right sums + int t_main_out [2]; + int t_echo_out [2]; + int t_echo_in [2]; + + voice_t voices [voice_count]; + + // non-emulation state + uint8_t* ram; // 64K shared RAM between DSP and SMP + int mute_mask; + sample_t* out; + sample_t* out_end; + sample_t* out_begin; + sample_t extra [extra_size]; + }; + state_t m; + + void init_counter(); + void run_counters(); + unsigned read_counter( int rate ); + + int interpolate( voice_t const* v ); + void run_envelope( voice_t* const v ); + void decode_brr( voice_t* v ); + + void misc_27(); + void misc_28(); + void misc_29(); + void misc_30(); + + void voice_output( voice_t const* v, int ch ); + void voice_V1( voice_t* const ); + void voice_V2( voice_t* const ); + void voice_V3( voice_t* const ); + void voice_V3a( voice_t* const ); + void voice_V3b( voice_t* const ); + void voice_V3c( voice_t* const ); + void voice_V4( voice_t* const ); + void voice_V5( voice_t* const ); + void voice_V6( voice_t* const ); + void voice_V7( voice_t* const ); + void voice_V8( voice_t* const ); + void voice_V9( voice_t* const ); + void voice_V7_V4_V1( voice_t* const ); + void voice_V8_V5_V2( voice_t* const ); + void voice_V9_V6_V3( voice_t* const ); + + void echo_read( int ch ); + int echo_output( int ch ); + void echo_write( int ch ); + void echo_22(); + void echo_23(); + void echo_24(); + void echo_25(); + void echo_26(); + void echo_27(); + void echo_28(); + void echo_29(); + void echo_30(); + + void soft_reset_common(); +}; + +#include + +inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; } + +inline int SPC_DSP::read( int addr ) const +{ + assert( (unsigned) addr < register_count ); + return m.regs [addr]; +} + +inline void SPC_DSP::write( int addr, int data ) +{ + assert( (unsigned) addr < register_count ); + + m.regs [addr] = (uint8_t) data; + switch ( addr & 0x0F ) + { + case v_envx: + m.envx_buf = (uint8_t) data; + break; + + case v_outx: + m.outx_buf = (uint8_t) data; + break; + + case 0x0C: + if ( addr == r_kon ) + m.new_kon = (uint8_t) data; + + if ( addr == r_endx ) // always cleared, regardless of data written + { + m.endx_buf = 0; + m.regs [r_endx] = 0; + } + break; + } +} + +inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; } + +inline bool SPC_DSP::check_kon() +{ + bool old = m.kon_check; + m.kon_check = 0; + return old; +} + +#if !SPC_NO_COPY_STATE_FUNCS + +class SPC_State_Copier { + SPC_DSP::copy_func_t func; + unsigned char** buf; +public: + SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; } + void copy( void* state, size_t size ); + int copy_int( int state, int size ); + void skip( int count ); + void extra(); +}; + +#define SPC_COPY( type, state )\ +{\ + state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\ + assert( (BOOST::type) state == state );\ +} + +#endif + +#endif diff --git a/apu/SPC_Filter.cpp b/apu/SPC_Filter.cpp new file mode 100644 index 00000000..b3d57708 --- /dev/null +++ b/apu/SPC_Filter.cpp @@ -0,0 +1,68 @@ +// snes_spc 0.9.0. http://www.slack.net/~ant/ + +#include "SPC_Filter.h" + +#include + +/* Copyright (C) 2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "blargg_source.h" + +void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); } + +SPC_Filter::SPC_Filter() +{ + gain = gain_unit; + bass = bass_norm; + clear(); +} + +void SPC_Filter::run( short* io, int count ) +{ + require( (count & 1) == 0 ); // must be even + + int const gain = this->gain; + int const bass = this->bass; + chan_t* c = &ch [2]; + do + { + // cache in registers + int sum = (--c)->sum; + int pp1 = c->pp1; + int p1 = c->p1; + + for ( int i = 0; i < count; i += 2 ) + { + // Low-pass filter (two point FIR with coeffs 0.25, 0.75) + int f = io [i] + p1; + p1 = io [i] * 3; + + // High-pass filter ("leaky integrator") + int delta = f - pp1; + pp1 = f; + int s = sum >> (gain_bits + 2); + sum += (delta * gain) - (sum >> bass); + + // Clamp to 16 bits + if ( (short) s != s ) + s = (s >> 31) ^ 0x7FFF; + + io [i] = (short) s; + } + + c->p1 = p1; + c->pp1 = pp1; + c->sum = sum; + ++io; + } + while ( c != ch ); +} diff --git a/apu/SPC_Filter.h b/apu/SPC_Filter.h new file mode 100644 index 00000000..d5c83cb8 --- /dev/null +++ b/apu/SPC_Filter.h @@ -0,0 +1,47 @@ +// Simple low-pass and high-pass filter to better match sound output of a SNES + +// snes_spc 0.9.0 +#ifndef SPC_FILTER_H +#define SPC_FILTER_H + +#include "blargg_common.h" + +struct SPC_Filter { +public: + + // Filters count samples of stereo sound in place. Count must be a multiple of 2. + typedef short sample_t; + void run( sample_t* io, int count ); + +// Optional features + + // Clears filter to silence + void clear(); + + // Sets gain (volume), where gain_unit is normal. Gains greater than gain_unit + // are fine, since output is clamped to 16-bit sample range. + enum { gain_unit = 0x100 }; + void set_gain( int gain ); + + // Sets amount of bass (logarithmic scale) + enum { bass_none = 0 }; + enum { bass_norm = 8 }; // normal amount + enum { bass_max = 31 }; + void set_bass( int bass ); + +public: + SPC_Filter(); + BLARGG_DISABLE_NOTHROW +private: + enum { gain_bits = 8 }; + int gain; + int bass; + struct chan_t { int p1, pp1, sum; }; + chan_t ch [2]; +}; + +inline void SPC_Filter::set_gain( int g ) { gain = g; } + +inline void SPC_Filter::set_bass( int b ) { bass = b; } + +#endif diff --git a/apu/apu.cpp b/apu/apu.cpp new file mode 100644 index 00000000..e5143ff3 --- /dev/null +++ b/apu/apu.cpp @@ -0,0 +1,654 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "apu.h" +#include "snapshot.h" +#include "display.h" +#include "resampler.h" + +#define APU_DEFAULT_INPUT_RATE 32000 +#define APU_MINIMUM_SAMPLE_COUNT 512 +#define APU_MINIMUM_SAMPLE_BLOCK 128 +#define APU_NUMERATOR_NTSC 5632 +#define APU_DENOMINATOR_NTSC 118125 +#define APU_NUMERATOR_PAL 102400 +#define APU_DENOMINATOR_PAL 2128137 + +SNES_SPC *spc_core = NULL; + +static 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 +}; + +namespace spc +{ + static apu_callback sa_callback = NULL; + static void *extra_data = NULL; + + static bool8 sound_in_sync = TRUE; + static bool8 sound_enabled = FALSE; + + static int buffer_size; + static int lag_master = 0; + static int lag = 0; + + static uint8 *landing_buffer = NULL; + static uint8 *shrink_buffer = NULL; + + static Resampler *resampler = NULL; + + static int32 reference_time; + static uint32 remainder; + + static const int32 timing_hack_numerator = SNES_SPC::tempo_unit; + static int32 timing_hack_denominator = SNES_SPC::tempo_unit; +} + +static void EightBitize (uint8 *, int); +static void DeStereo (uint8 *, int); +static void ReverseStereo (uint8 *, int); +static void UpdatePlaybackRate (void); +static void from_apu_to_state (uint8 **, void *, size_t); +static void to_apu_from_state (uint8 **, void *, size_t); +static void SPCSnapshotCallback (void); +static inline int S9xAPUGetClock (int32); +static inline int S9xAPUGetClockRemainder (int32); + + +static void EightBitize (uint8 *buffer, int sample_count) +{ + uint8 *buf8 = (uint8 *) buffer; + int16 *buf16 = (int16 *) buffer; + + for (int i = 0; i < sample_count; i++) + buf8[i] = (uint8) ((buf16[i] / 256) + 128); +} + +static void DeStereo (uint8 *buffer, int sample_count) +{ + int16 *buf = (int16 *) buffer; + int32 s1, s2; + + for (int i = 0; i < sample_count >> 1; i++) + { + s1 = (int32) buf[2 * i]; + s2 = (int32) buf[2 * i + 1]; + buf[i] = (int16) ((s1 + s2) >> 1); + } +} + +static void ReverseStereo (uint8 *src_buffer, int sample_count) +{ + int16 *buffer = (int16 *) src_buffer; + + for (int i = 0; i < sample_count; i += 2) + { + buffer[i + 1] ^= buffer[i]; + buffer[i] ^= buffer[i + 1]; + buffer[i + 1] ^= buffer[i]; + } +} + +bool8 S9xMixSamples (uint8 *buffer, int sample_count) +{ + static int shrink_buffer_size = -1; + uint8 *dest; + + if (!Settings.SixteenBitSound || !Settings.Stereo) + { + /* We still need both stereo samples for generating the mono sample */ + if (!Settings.Stereo) + sample_count <<= 1; + + /* We still have to generate 16-bit samples for bit-dropping, too */ + if (shrink_buffer_size < (sample_count << 1)) + { + delete[] spc::shrink_buffer; + spc::shrink_buffer = new uint8[sample_count << 1]; + shrink_buffer_size = sample_count << 1; + } + + dest = spc::shrink_buffer; + } + else + dest = buffer; + + if (Settings.Mute) + { + memset(dest, 0, sample_count << 1); + spc::resampler->clear(); + + return (FALSE); + } + else + { + if (spc::resampler->avail() >= (sample_count + spc::lag)) + { + spc::resampler->read((short *) dest, sample_count); + if (spc::lag == spc::lag_master) + spc::lag = 0; + } + else + { + memset(buffer, (Settings.SixteenBitSound ? 0 : 128), (sample_count << (Settings.SixteenBitSound ? 1 : 0)) >> (Settings.Stereo ? 0 : 1)); + if (spc::lag == 0) + spc::lag = spc::lag_master; + + return (FALSE); + } + } + + if (Settings.ReverseStereo && Settings.Stereo) + ReverseStereo(dest, sample_count); + + if (!Settings.Stereo || !Settings.SixteenBitSound) + { + if (!Settings.Stereo) + { + DeStereo(dest, sample_count); + sample_count >>= 1; + } + + if (!Settings.SixteenBitSound) + EightBitize(dest, sample_count); + + memcpy(buffer, dest, (sample_count << (Settings.SixteenBitSound ? 1 : 0))); + } + + return (TRUE); +} + +int S9xGetSampleCount (void) +{ + return (spc::resampler->avail() >> (Settings.Stereo ? 0 : 1)); +} + +void S9xFinalizeSamples (void) +{ + if (!Settings.Mute) + { + if (!spc::resampler->push((short *) spc::landing_buffer, spc_core->sample_count())) + { + /* We weren't able to process the entire buffer. Potential overrun. */ + spc::sound_in_sync = FALSE; + + if (Settings.SoundSync && !Settings.TurboMode) + return; + } + } + + if (!Settings.SoundSync || Settings.TurboMode || Settings.Mute) + spc::sound_in_sync = TRUE; + else + if (spc::resampler->space_empty() >= spc::resampler->space_filled()) + spc::sound_in_sync = TRUE; + else + spc::sound_in_sync = FALSE; + + spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); +} + +void S9xLandSamples (void) +{ + if (spc::sa_callback != NULL) + spc::sa_callback(spc::extra_data); + else + S9xFinalizeSamples(); +} + +void S9xClearSamples (void) +{ + spc::resampler->clear(); + spc::lag = spc::lag_master; +} + +bool8 S9xSyncSound (void) +{ + if (!Settings.SoundSync || spc::sound_in_sync) + return (TRUE); + + S9xLandSamples(); + + return (spc::sound_in_sync); +} + +void S9xSetSamplesAvailableCallback (apu_callback callback, void *data) +{ + spc::sa_callback = callback; + spc::extra_data = data; +} + +static void UpdatePlaybackRate (void) +{ + if (Settings.SoundInputRate == 0) + Settings.SoundInputRate = APU_DEFAULT_INPUT_RATE; + + double time_ratio = (double) Settings.SoundInputRate * spc::timing_hack_numerator / (Settings.SoundPlaybackRate * spc::timing_hack_denominator); + spc::resampler->time_ratio(time_ratio); +} + +bool8 S9xInitSound (int buffer_ms, int lag_ms) +{ + // buffer_ms : buffer size given in millisecond + // lag_ms : allowable time-lag given in millisecond + + int sample_count = buffer_ms * 32000 / 1000; + int lag_sample_count = lag_ms * 32000 / 1000; + + spc::lag_master = lag_sample_count; + if (Settings.Stereo) + spc::lag_master <<= 1; + spc::lag = spc::lag_master; + + if (sample_count < APU_MINIMUM_SAMPLE_COUNT) + sample_count = APU_MINIMUM_SAMPLE_COUNT; + + spc::buffer_size = sample_count; + if (Settings.Stereo) + spc::buffer_size <<= 1; + if (Settings.SixteenBitSound) + spc::buffer_size <<= 1; + + printf("Sound buffer size: %d (%d samples)\n", spc::buffer_size, sample_count); + + if (spc::landing_buffer) + delete[] spc::landing_buffer; + spc::landing_buffer = new uint8[spc::buffer_size * 2]; + if (!spc::landing_buffer) + return (FALSE); + + /* The resampler and spc unit use samples (16-bit short) as + arguments. Use 2x in the resampler for buffer leveling with SoundSync */ + if (!spc::resampler) + { + spc::resampler = new Resampler(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); + if (!spc::resampler) + { + delete[] spc::landing_buffer; + return (FALSE); + } + } + else + spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); + + spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + + UpdatePlaybackRate(); + + spc::sound_enabled = S9xOpenSoundDevice(); + + return (spc::sound_enabled); +} + +void S9xSetSoundControl (uint8 voice_switch) +{ + spc_core->dsp_set_stereo_switch(voice_switch << 8 | voice_switch); +} + +void S9xSetSoundMute (bool8 mute) +{ + Settings.Mute = mute; + if (!spc::sound_enabled) + Settings.Mute = TRUE; +} + +void S9xDumpSPCSnapshot (void) +{ + spc_core->dsp_dump_spc_snapshot(); +} + +static void SPCSnapshotCallback (void) +{ + S9xSPCDump(S9xGetFilenameInc((".spc"), SPC_DIR)); + printf("Dumped key-on triggered spc snapshot.\n"); +} + +bool8 S9xInitAPU (void) +{ + spc_core = new SNES_SPC; + if (!spc_core) + return (FALSE); + + spc_core->init(); + spc_core->init_rom(APUROM); + + spc_core->dsp_set_spc_snapshot_callback(SPCSnapshotCallback); + + spc::landing_buffer = NULL; + spc::shrink_buffer = NULL; + spc::resampler = NULL; + + return (TRUE); +} + +void S9xDeinitAPU (void) +{ + if (spc_core) + { + delete spc_core; + spc_core = NULL; + } + + if (spc::resampler) + { + delete spc::resampler; + spc::resampler = NULL; + } + + if (spc::landing_buffer) + { + delete[] spc::landing_buffer; + spc::landing_buffer = NULL; + } + + if (spc::shrink_buffer) + { + delete[] spc::shrink_buffer; + spc::shrink_buffer = NULL; + } +} + +static inline int S9xAPUGetClock (int32 cpucycles) +{ + if (Settings.PAL) + return ((int) floor(((double) APU_NUMERATOR_PAL * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder) / + ((double) APU_DENOMINATOR_PAL * spc::timing_hack_denominator))); + else + return (APU_NUMERATOR_NTSC * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder) / + (APU_DENOMINATOR_NTSC * spc::timing_hack_denominator); +} + +static inline int S9xAPUGetClockRemainder (int32 cpucycles) +{ + if (Settings.PAL) + return ((int) fmod (((double) APU_NUMERATOR_PAL * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder), + ((double) APU_DENOMINATOR_PAL * spc::timing_hack_denominator))); + else + return (APU_NUMERATOR_NTSC * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder) % + (APU_DENOMINATOR_NTSC * spc::timing_hack_denominator); +} + +uint8 S9xAPUReadPort (int port) +{ + return ((uint8) spc_core->read_port(S9xAPUGetClock(CPU.Cycles), port)); +} + +void S9xAPUWritePort (int port, uint8 byte) +{ + spc_core->write_port(S9xAPUGetClock(CPU.Cycles), port, byte); +} + +void S9xAPUSetReferenceTime (int32 cpucycles) +{ + spc::reference_time = cpucycles; +} + +void S9xAPUExecute (void) +{ + /* Accumulate partial APU cycles */ + spc_core->end_frame(S9xAPUGetClock(CPU.Cycles)); + + spc::remainder = S9xAPUGetClockRemainder(CPU.Cycles); + + S9xAPUSetReferenceTime(CPU.Cycles); +} + +void S9xAPUEndScanline (void) +{ + S9xAPUExecute(); + + if (spc_core->sample_count() >= APU_MINIMUM_SAMPLE_BLOCK || !spc::sound_in_sync) + S9xLandSamples(); +} + +void S9xAPUTimingSetSpeedup (int ticks) +{ + if (ticks != 0) + printf("APU speedup hack: %d\n", ticks); + + spc_core->set_tempo(SNES_SPC::tempo_unit - ticks); + + spc::timing_hack_denominator = SNES_SPC::tempo_unit - ticks; + + UpdatePlaybackRate(); +} + +void S9xResetAPU (void) +{ + spc::reference_time = 0; + spc::remainder = 0; + spc_core->reset(); + spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + + spc::resampler->clear(); +} + +void S9xSoftResetAPU (void) +{ + spc::reference_time = 0; + spc::remainder = 0; + spc_core->soft_reset(); + spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1); + + spc::resampler->clear(); +} + +static void from_apu_to_state (uint8 **buf, void *var, size_t size) +{ + memcpy(*buf, var, size); + *buf += size; +} + +static void to_apu_from_state (uint8 **buf, void *var, size_t size) +{ + memcpy(var, *buf, size); + *buf += size; +} + +void S9xAPUSaveState (uint8 *block) +{ + uint8 *ptr = block; + + spc_core->copy_state(&ptr, from_apu_to_state); + + SET_LE32(ptr, spc::reference_time); + ptr += sizeof(int32); + SET_LE32(ptr, spc::remainder); +} + +void S9xAPULoadState (uint8 *block) +{ + uint8 *ptr = block; + + S9xResetAPU(); + + spc_core->copy_state(&ptr, to_apu_from_state); + + spc::reference_time = GET_LE32(ptr); + ptr += sizeof(int32); + spc::remainder = GET_LE32(ptr); +} diff --git a/apu/apu.h b/apu/apu.h new file mode 100644 index 00000000..a8ed9db9 --- /dev/null +++ b/apu/apu.h @@ -0,0 +1,217 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _APU_H_ +#define _APU_H_ + +#include "snes9x.h" +#include "SNES_SPC.h" + +typedef void (*apu_callback) (void *); + +#define SPC_SAVE_STATE_BLOCK_SIZE (SNES_SPC::state_size + 8) + +bool8 S9xInitAPU (void); +void S9xDeinitAPU (void); +void S9xResetAPU (void); +void S9xSoftResetAPU (void); +uint8 S9xAPUReadPort (int); +void S9xAPUWritePort (int, uint8); +void S9xAPUExecute (void); +void S9xAPUEndScanline (void); +void S9xAPUSetReferenceTime (int32); +void S9xAPUTimingSetSpeedup (int); +void S9xAPULoadState (uint8 *); +void S9xAPUSaveState (uint8 *); +void S9xDumpSPCSnapshot (void); + +bool8 S9xInitSound (int, int); +bool8 S9xOpenSoundDevice (void); + +bool8 S9xSyncSound (void); +int S9xGetSampleCount (void); +void S9xSetSoundControl (uint8); +void S9xSetSoundMute (bool8); +void S9xLandSamples (void); +void S9xFinalizeSamples (void); +void S9xClearSamples (void); +bool8 S9xMixSamples (uint8 *, int); +void S9xSetSamplesAvailableCallback (apu_callback, void *); + +extern SNES_SPC *spc_core; + +#endif diff --git a/apu/blargg_common.h b/apu/blargg_common.h new file mode 100644 index 00000000..75edff39 --- /dev/null +++ b/apu/blargg_common.h @@ -0,0 +1,186 @@ +// Sets up common environment for Shay Green's libraries. +// To change configuration options, modify blargg_config.h, not this file. + +// snes_spc 0.9.0 +#ifndef BLARGG_COMMON_H +#define BLARGG_COMMON_H + +#include +#include +#include +#include + +#undef BLARGG_COMMON_H +// allow blargg_config.h to #include blargg_common.h +#include "blargg_config.h" +#ifndef BLARGG_COMMON_H +#define BLARGG_COMMON_H + +// BLARGG_RESTRICT: equivalent to restrict, where supported +#if defined (__GNUC__) || _MSC_VER >= 1100 + #define BLARGG_RESTRICT __restrict +#else + #define BLARGG_RESTRICT +#endif + +// STATIC_CAST(T,expr): Used in place of static_cast (expr) +#ifndef STATIC_CAST + #define STATIC_CAST(T,expr) ((T) (expr)) +#endif + +// blargg_err_t (0 on success, otherwise error string) +#ifndef blargg_err_t + typedef const char* blargg_err_t; +#endif + +// blargg_vector - very lightweight vector of POD types (no constructor/destructor) +template +class blargg_vector { + T* begin_; + size_t size_; +public: + blargg_vector() : begin_( 0 ), size_( 0 ) { } + ~blargg_vector() { free( begin_ ); } + size_t size() const { return size_; } + T* begin() const { return begin_; } + T* end() const { return begin_ + size_; } + blargg_err_t resize( size_t n ) + { + // TODO: blargg_common.cpp to hold this as an outline function, ugh + void* p = realloc( begin_, n * sizeof (T) ); + if ( p ) + begin_ = (T*) p; + else if ( n > size_ ) // realloc failure only a problem if expanding + return "Out of memory"; + size_ = n; + return 0; + } + void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); } + T& operator [] ( size_t n ) const + { + assert( n <= size_ ); // <= to allow past-the-end value + return begin_ [n]; + } +}; + +#ifndef BLARGG_DISABLE_NOTHROW + // throw spec mandatory in ISO C++ if operator new can return NULL + #if __cplusplus >= 199711 || defined (__GNUC__) + #define BLARGG_THROWS( spec ) throw spec + #else + #define BLARGG_THROWS( spec ) + #endif + #define BLARGG_DISABLE_NOTHROW \ + void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ + void operator delete ( void* p ) { free( p ); } + #define BLARGG_NEW new +#else + #include + #define BLARGG_NEW new (std::nothrow) +#endif + +// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant) +#define BLARGG_4CHAR( a, b, c, d ) \ + ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF)) + +// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. +#ifndef BOOST_STATIC_ASSERT + #ifdef _MSC_VER + // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified + #define BOOST_STATIC_ASSERT( expr ) \ + void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) + #else + // Some other compilers fail when declaring same function multiple times in class, + // so differentiate them by line + #define BOOST_STATIC_ASSERT( expr ) \ + void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) + #endif +#endif + +// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, +// compiler is assumed to support bool. If undefined, availability is determined. +#ifndef BLARGG_COMPILER_HAS_BOOL + #if defined (__MWERKS__) + #if !__option(bool) + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + #elif defined (_MSC_VER) + #if _MSC_VER < 1100 + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + #elif defined (__GNUC__) + // supports bool + #elif __cplusplus < 199711 + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif +#endif +#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL + // If you get errors here, modify your blargg_config.h file + typedef int bool; + const bool true = 1; + const bool false = 0; +#endif + +// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough + +#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF + typedef long blargg_long; +#else + typedef int blargg_long; +#endif + +#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF + typedef unsigned long blargg_ulong; +#else + typedef unsigned blargg_ulong; +#endif + +// BOOST::int8_t etc. + +// HAVE_STDINT_H: If defined, use for int8_t etc. +#if defined (HAVE_STDINT_H) + #include + #define BOOST + +// HAVE_INTTYPES_H: If defined, use for int8_t etc. +#elif defined (HAVE_INTTYPES_H) + #include + #define BOOST + +#else + struct BOOST + { + #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F + typedef signed char int8_t; + typedef unsigned char uint8_t; + #else + // No suitable 8-bit type available + typedef struct see_blargg_common_h int8_t; + typedef struct see_blargg_common_h uint8_t; + #endif + + #if USHRT_MAX == 0xFFFF + typedef short int16_t; + typedef unsigned short uint16_t; + #else + // No suitable 16-bit type available + typedef struct see_blargg_common_h int16_t; + typedef struct see_blargg_common_h uint16_t; + #endif + + #if ULONG_MAX == 0xFFFFFFFF + typedef long int32_t; + typedef unsigned long uint32_t; + #elif UINT_MAX == 0xFFFFFFFF + typedef int int32_t; + typedef unsigned int uint32_t; + #else + // No suitable 32-bit type available + typedef struct see_blargg_common_h int32_t; + typedef struct see_blargg_common_h uint32_t; + #endif + }; +#endif + +#endif +#endif diff --git a/apu/blargg_config.h b/apu/blargg_config.h new file mode 100644 index 00000000..9dc69db8 --- /dev/null +++ b/apu/blargg_config.h @@ -0,0 +1,24 @@ +// snes_spc 0.9.0 user configuration file. Don't replace when updating library. + +// snes_spc 0.9.0 +#ifndef BLARGG_CONFIG_H +#define BLARGG_CONFIG_H + +// Uncomment to disable debugging checks +//#define NDEBUG 1 + +// Uncomment to enable platform-specific (and possibly non-portable) optimizations +//#define BLARGG_NONPORTABLE 1 + +// Uncomment if automatic byte-order determination doesn't work +//#define BLARGG_BIG_ENDIAN 1 + +// Uncomment if you get errors in the bool section of blargg_common.h +//#define BLARGG_COMPILER_HAS_BOOL 1 + +// Use standard config.h if present +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#endif diff --git a/apu/blargg_endian.h b/apu/blargg_endian.h new file mode 100644 index 00000000..f2daca64 --- /dev/null +++ b/apu/blargg_endian.h @@ -0,0 +1,185 @@ +// CPU Byte Order Utilities + +// snes_spc 0.9.0 +#ifndef BLARGG_ENDIAN +#define BLARGG_ENDIAN + +#include "blargg_common.h" + +// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) +#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ + defined (__x86_64__) || defined (__ia64__) || defined (__i386__) + #define BLARGG_CPU_X86 1 + #define BLARGG_CPU_CISC 1 +#endif + +#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc) + #define BLARGG_CPU_POWERPC 1 + #define BLARGG_CPU_RISC 1 +#endif + +// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only +// one may be #defined to 1. Only needed if something actually depends on byte order. +#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) +#ifdef __GLIBC__ + // GCC handles this for us + #include + #if __BYTE_ORDER == __LITTLE_ENDIAN + #define BLARGG_LITTLE_ENDIAN 1 + #elif __BYTE_ORDER == __BIG_ENDIAN + #define BLARGG_BIG_ENDIAN 1 + #endif +#else + +#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ + (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) + #define BLARGG_LITTLE_ENDIAN 1 +#endif + +#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ + defined (__sparc__) || BLARGG_CPU_POWERPC || \ + (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) + #define BLARGG_BIG_ENDIAN 1 +#elif !defined (__mips__) + // No endian specified; assume little-endian, since it's most common + #define BLARGG_LITTLE_ENDIAN 1 +#endif +#endif +#endif + +#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN + #undef BLARGG_LITTLE_ENDIAN + #undef BLARGG_BIG_ENDIAN +#endif + +inline void blargg_verify_byte_order() +{ + #ifndef NDEBUG + #if BLARGG_BIG_ENDIAN + volatile int i = 1; + assert( *(volatile char*) &i == 0 ); + #elif BLARGG_LITTLE_ENDIAN + volatile int i = 1; + assert( *(volatile char*) &i != 0 ); + #endif + #endif +} + +inline unsigned get_le16( void const* p ) +{ + return (unsigned) ((unsigned char const*) p) [1] << 8 | + (unsigned) ((unsigned char const*) p) [0]; +} + +inline unsigned get_be16( void const* p ) +{ + return (unsigned) ((unsigned char const*) p) [0] << 8 | + (unsigned) ((unsigned char const*) p) [1]; +} + +inline blargg_ulong get_le32( void const* p ) +{ + return (blargg_ulong) ((unsigned char const*) p) [3] << 24 | + (blargg_ulong) ((unsigned char const*) p) [2] << 16 | + (blargg_ulong) ((unsigned char const*) p) [1] << 8 | + (blargg_ulong) ((unsigned char const*) p) [0]; +} + +inline blargg_ulong get_be32( void const* p ) +{ + return (blargg_ulong) ((unsigned char const*) p) [0] << 24 | + (blargg_ulong) ((unsigned char const*) p) [1] << 16 | + (blargg_ulong) ((unsigned char const*) p) [2] << 8 | + (blargg_ulong) ((unsigned char const*) p) [3]; +} + +inline void set_le16( void* p, unsigned n ) +{ + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [0] = (unsigned char) n; +} + +inline void set_be16( void* p, unsigned n ) +{ + ((unsigned char*) p) [0] = (unsigned char) (n >> 8); + ((unsigned char*) p) [1] = (unsigned char) n; +} + +inline void set_le32( void* p, blargg_ulong n ) +{ + ((unsigned char*) p) [0] = (unsigned char) n; + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [2] = (unsigned char) (n >> 16); + ((unsigned char*) p) [3] = (unsigned char) (n >> 24); +} + +inline void set_be32( void* p, blargg_ulong n ) +{ + ((unsigned char*) p) [3] = (unsigned char) n; + ((unsigned char*) p) [2] = (unsigned char) (n >> 8); + ((unsigned char*) p) [1] = (unsigned char) (n >> 16); + ((unsigned char*) p) [0] = (unsigned char) (n >> 24); +} + +#if BLARGG_NONPORTABLE + // Optimized implementation if byte order is known + #if BLARGG_LITTLE_ENDIAN + #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr)) + #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr)) + #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) + #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) + #elif BLARGG_BIG_ENDIAN + #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr)) + #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) + #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) + #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) + + #if BLARGG_CPU_POWERPC + // PowerPC has special byte-reversed instructions + #if defined (__MWERKS__) + #define GET_LE16( addr ) (__lhbrx( addr, 0 )) + #define GET_LE32( addr ) (__lwbrx( addr, 0 )) + #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) + #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) + #elif defined (__GNUC__) + #define GET_LE16( addr ) ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;}) + #define GET_LE32( addr ) ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;}) + #define SET_LE16( addr, in ) ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );}) + #define SET_LE32( addr, in ) ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );}) + #endif + #endif + #endif +#endif + +#ifndef GET_LE16 + #define GET_LE16( addr ) get_le16( addr ) + #define SET_LE16( addr, data ) set_le16( addr, data ) +#endif + +#ifndef GET_LE32 + #define GET_LE32( addr ) get_le32( addr ) + #define SET_LE32( addr, data ) set_le32( addr, data ) +#endif + +#ifndef GET_BE16 + #define GET_BE16( addr ) get_be16( addr ) + #define SET_BE16( addr, data ) set_be16( addr, data ) +#endif + +#ifndef GET_BE32 + #define GET_BE32( addr ) get_be32( addr ) + #define SET_BE32( addr, data ) set_be32( addr, data ) +#endif + +// auto-selecting versions + +inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } +inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); } +inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } +inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); } +inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); } +inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); } +inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); } +inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); } + +#endif diff --git a/apu/blargg_source.h b/apu/blargg_source.h new file mode 100644 index 00000000..5e45c4fb --- /dev/null +++ b/apu/blargg_source.h @@ -0,0 +1,100 @@ +/* Included at the beginning of library source files, after all other #include lines. +Sets up helpful macros and services used in my source code. They don't need +module an annoying module prefix on their names since they are defined after +all other #include lines. */ + +// snes_spc 0.9.0 +#ifndef BLARGG_SOURCE_H +#define BLARGG_SOURCE_H + +// If debugging is enabled, abort program if expr is false. Meant for checking +// internal state and consistency. A failed assertion indicates a bug in the module. +// void assert( bool expr ); +#include + +// If debugging is enabled and expr is false, abort program. Meant for checking +// caller-supplied parameters and operations that are outside the control of the +// module. A failed requirement indicates a bug outside the module. +// void require( bool expr ); +#undef require +#define require( expr ) assert( expr ) + +// Like printf() except output goes to debug log file. Might be defined to do +// nothing (not even evaluate its arguments). +// void dprintf( const char* format, ... ); +static inline void blargg_dprintf_( const char*, ... ) { } +#undef dprintf +#define dprintf (1) ? (void) 0 : blargg_dprintf_ + +// If enabled, evaluate expr and if false, make debug log entry with source file +// and line. Meant for finding situations that should be examined further, but that +// don't indicate a problem. In all cases, execution continues normally. +#undef check +#define check( expr ) ((void) 0) + +// If expr yields error string, return it from current function, otherwise continue. +#undef RETURN_ERR +#define RETURN_ERR( expr ) do { \ + blargg_err_t blargg_return_err_ = (expr); \ + if ( blargg_return_err_ ) return blargg_return_err_; \ + } while ( 0 ) + +// If ptr is 0, return out of memory error string. +#undef CHECK_ALLOC +#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) + +// Avoid any macros which evaluate their arguments multiple times +#undef min +#undef max + +#define DEF_MIN_MAX( type ) \ + static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\ + static inline type max( type x, type y ) { if ( y < x ) return x; return y; } + +DEF_MIN_MAX( int ) +DEF_MIN_MAX( unsigned ) +DEF_MIN_MAX( long ) +DEF_MIN_MAX( unsigned long ) +DEF_MIN_MAX( float ) +DEF_MIN_MAX( double ) + +#undef DEF_MIN_MAX + +/* +// using const references generates crappy code, and I am currenly only using these +// for built-in types, so they take arguments by value + +// TODO: remove +inline int min( int x, int y ) +template +inline T min( T x, T y ) +{ + if ( x < y ) + return x; + return y; +} + +template +inline T max( T x, T y ) +{ + if ( x < y ) + return y; + return x; +} +*/ + +// TODO: good idea? bad idea? +#undef byte +#define byte byte_ +typedef unsigned char byte; + +// deprecated +#define BLARGG_CHECK_ALLOC CHECK_ALLOC +#define BLARGG_RETURN_ERR RETURN_ERR + +// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check +#ifdef BLARGG_SOURCE_BEGIN + #include BLARGG_SOURCE_BEGIN +#endif + +#endif diff --git a/apu/license.txt b/apu/license.txt new file mode 100644 index 00000000..5ab7695a --- /dev/null +++ b/apu/license.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/apu/resampler.h b/apu/resampler.h new file mode 100644 index 00000000..51a32266 --- /dev/null +++ b/apu/resampler.h @@ -0,0 +1,162 @@ +/* Simple resampler based on bsnes's ruby audio library */ + +#ifndef __RESAMPLER_H +#define __RESAMPLER_H + +#include "ring_buffer.h" + +#undef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#undef CLAMP +#undef short_clamp +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#define short_clamp(n) ((short) CLAMP((n), -32768, 32767)) + +class Resampler : public ring_buffer +{ + protected: + + double r_step; + double r_frac; + int r_left[4], r_right[4]; + + double + hermite (double mu1, double a, double b, double c, double d) + { + const double tension = 0.0; //-1 = low, 0 = normal, 1 = high + const double bias = 0.0; //-1 = left, 0 = even, 1 = right + + double mu2, mu3, m0, m1, a0, a1, a2, a3; + + mu2 = mu1 * mu1; + mu3 = mu2 * mu1; + + m0 = (b - a) * (1 + bias) * (1 - tension) / 2; + m0 += (c - b) * (1 - bias) * (1 - tension) / 2; + m1 = (c - b) * (1 + bias) * (1 - tension) / 2; + m1 += (d - c) * (1 - bias) * (1 - tension) / 2; + + a0 = +2 * mu3 - 3 * mu2 + 1; + a1 = mu3 - 2 * mu2 + mu1; + a2 = mu3 - mu2; + a3 = -2 * mu3 + 3 * mu2; + + return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); + } + + public: + Resampler (int num_samples) : ring_buffer (num_samples << 1) + { + r_frac = 0.0; + } + + ~Resampler () + { + } + + void + time_ratio (double ratio) + { + r_step = ratio; + clear (); + } + + void + clear (void) + { + ring_buffer::clear (); + r_frac = 0; + r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0; + r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0; + } + + void + read (short *data, int num_samples) + { + int i_position = start >> 1; + short *internal_buffer = (short *) buffer; + int o_position = 0; + int consumed = 0; + + while (o_position < num_samples && consumed < buffer_size) + { + int s_left = internal_buffer[i_position]; + int s_right = internal_buffer[i_position + 1]; + const double margin_of_error = 1.0e-10; + + if (fabs(r_step - 1.0) < margin_of_error) + { + data[o_position] = (short) s_left; + data[o_position + 1] = (short) s_right; + + o_position += 2; + i_position = (i_position + 2) % (buffer_size >> 1); + consumed += 2; + + continue; + } + + r_left [0] = r_left [1]; + r_left [1] = r_left [2]; + r_left [2] = r_left [3]; + r_left [3] = s_left; + + r_right[0] = r_right[1]; + r_right[1] = r_right[2]; + r_right[2] = r_right[3]; + r_right[3] = s_right; + + while (r_frac <= 1.0 && o_position < num_samples) + { + data[o_position] = short_clamp (hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3])); + data[o_position + 1] = short_clamp (hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3])); + + o_position += 2; + + r_frac += r_step; + } + + if (r_frac > 1.0) + { + r_frac -= 1.0; + i_position = (i_position + 2) % (buffer_size >> 1); + consumed += 2; + } + } + + size -= consumed << 1; + start = (start + (consumed << 1)) % buffer_size; + } + + bool + push (short *src, int num_samples) + { + if (max_write () < num_samples) + return false; + + ring_buffer::push ((unsigned char *) src, num_samples << 1); + + return true; + } + + int + max_write (void) + { + return space_empty () >> 1; + } + + void + resize (int num_samples) + { + ring_buffer::resize (num_samples << 1); + } + + int + avail (void) + { + return (int) floor (((size >> 2) - r_frac) / r_step) * 2; + } +}; + +#endif /* __RESAMPLER_H */ diff --git a/apu/ring_buffer.h b/apu/ring_buffer.h new file mode 100644 index 00000000..b743c471 --- /dev/null +++ b/apu/ring_buffer.h @@ -0,0 +1,111 @@ +/* Simple byte-based ring buffer. Licensed under public domain (C) BearOso. */ + +#ifndef __RING_BUFFER_H +#define __RING_BUFFER_H + +#include + +#undef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +class ring_buffer +{ +protected: + int size; + int buffer_size; + int start; + unsigned char *buffer; + +public: + ring_buffer (int buffer_size) + { + this->buffer_size = buffer_size; + buffer = new unsigned char[this->buffer_size]; + memset (buffer, 0, this->buffer_size); + + size = 0; + start = 0; + } + + ~ring_buffer (void) + { + delete[] buffer; + } + + bool + push (unsigned char *src, int bytes) + { + if (space_empty () < bytes) + return false; + + int end = (start + size) % buffer_size; + int first_write_size = MIN (bytes, buffer_size - end); + + memcpy (buffer + end, src, first_write_size); + + if (bytes > first_write_size) + memcpy (buffer, src + first_write_size, bytes - first_write_size); + + size += bytes; + + return true; + } + + bool + pull (unsigned char *dst, int bytes) + { + if (space_filled () < bytes) + return false; + + memcpy (dst, buffer + start, MIN (bytes, buffer_size - start)); + + if (bytes > (buffer_size - start)) + memcpy (dst + (buffer_size - start), buffer, bytes - (buffer_size - start)); + + start = (start + bytes) % buffer_size; + size -= bytes; + + return true; + } + + inline int + space_empty (void) + { + return buffer_size - size; + } + + inline int + space_filled (void) + { + return size; + } + + void + clear (void) + { + start = 0; + size = 0; + memset (buffer, 0, buffer_size); + } + + void + resize (int size) + { + delete[] buffer; + buffer_size = size; + buffer = new unsigned char[buffer_size]; + memset (buffer, 0, this->buffer_size); + + size = 0; + start = 0; + } + + inline void + cache_silence (void) + { + clear (); + size = buffer_size; + } +}; + +#endif diff --git a/bsx.cpp b/bsx.cpp new file mode 100644 index 00000000..c6d6b369 --- /dev/null +++ b/bsx.cpp @@ -0,0 +1,1202 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +// Dreamer Nom wrote: +// Large thanks to John Weidman for all his initial research +// Thanks to Seph3 for his modem notes + + +#include "snes9x.h" +#include "memmap.h" +#include "display.h" + +//#define BSX_DEBUG + +#define BIOS_SIZE 0x100000 +#define FLASH_SIZE 0x200000 +#define PSRAM_SIZE 0x80000 + +#define Map Memory.Map +#define BlockIsRAM Memory.BlockIsRAM +#define BlockIsROM Memory.BlockIsROM +#define RAM Memory.RAM +#define SRAM Memory.SRAM +#define PSRAM Memory.BSRAM +#define BIOSROM Memory.BIOSROM +#define MAP_BSX Memory.MAP_BSX +#define MAP_CPU Memory.MAP_CPU +#define MAP_PPU Memory.MAP_PPU +#define MAP_NONE Memory.MAP_NONE + +#define BSXPPUBASE 0x2180 + +struct SBSX_RTC +{ + int hours; + int minutes; + int seconds; + int ticks; +}; + +static struct SBSX_RTC BSX_RTC; + +// flash card vendor information +static const uint8 flashcard[20] = +{ + 0x4D, 0x00, 0x50, 0x00, // vendor id + 0x00, 0x00, // ? + 0x2B, 0x00, // 2MB Flash (1MB = 0x2A) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8 init2192[32] = // FIXME +{ + 00, 00, 00, 00, 00, // unknown + 01, 01, 00, 00, 00, + 00, // seconds (?) + 00, // minutes + 00, // hours + 10, 10, 10, 10, 10, // unknown + 10, 10, 10, 10, 10, // dummy + 00, 00, 00, 00, 00, 00, 00, 00, 00 +}; + +static bool8 FlashMode; +static uint32 FlashSize; +static uint8 *MapROM, *FlashROM; + +static void BSX_Map_SNES (void); +static void BSX_Map_LoROM (void); +static void BSX_Map_HiROM (void); +static void BSX_Map_MMC (void); +static void BSX_Map_FlashIO (void); +static void BSX_Map_SRAM (void); +static void BSX_Map_PSRAM (void); +static void BSX_Map_BIOS (void); +static void BSX_Map_RAM (void); +static void BSX_Map_Dirty (void); +static void BSX_Map (void); +static void BSX_Set_Bypass_FlashIO (uint16, uint8); +static uint8 BSX_Get_Bypass_FlashIO (uint16); +static bool8 BSX_LoadBIOS (void); +static void map_psram_mirror_sub (uint32); +static int is_bsx (unsigned char *); + + +static void BSX_Map_SNES (void) +{ + // These maps will be partially overwritten + + int c; + + // 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; + } +} + +static void BSX_Map_LoROM (void) +{ + // These maps will be partially overwritten + + int i, c; + + // Banks 00->3F and 80->BF + for (c = 0; c < 0x400; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i] = Map[i + 0x800] = &MapROM[(c << 11) % FlashSize] - 0x8000; + BlockIsRAM[i] = BlockIsRAM[i + 0x800] = BSX.write_enable; + BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; + } + } + + // 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] = &MapROM[(c << 11) % FlashSize]; + + for (i = c + 8; i < c + 16; i++) + Map[i + 0x400] = Map[i + 0xC00] = &MapROM[(c << 11) % FlashSize] - 0x8000; + + for (i = c; i < c + 16; i++) + { + BlockIsRAM[i + 0x400] = BlockIsRAM[i + 0xC00] = BSX.write_enable; + BlockIsROM[i + 0x400] = BlockIsROM[i + 0xC00] = !BSX.write_enable; + } + } +} + +static void BSX_Map_HiROM (void) +{ + // These maps will be partially overwritten + + int i, c; + + // Banks 00->3F and 80->BF + for (c = 0; c < 0x400; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i] = Map[i + 0x800] = &MapROM[(c << 12) % FlashSize]; + BlockIsRAM[i] = BlockIsRAM[i + 0x800] = BSX.write_enable; + BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; + } + } + + // 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] = &MapROM[(c << 12) % FlashSize]; + BlockIsRAM[i + 0x400] = BlockIsRAM[i + 0xC00] = BSX.write_enable; + BlockIsROM[i + 0x400] = BlockIsROM[i + 0xC00] = !BSX.write_enable; + } + } +} + +static void BSX_Map_MMC (void) +{ + int c; + + // Banks 01->0E:5000-5FFF + for (c = 0x010; c < 0x0F0; c += 16) + { + Map[c + 5] = (uint8 *) MAP_BSX; + BlockIsRAM[c + 5] = BlockIsROM[c + 5] = FALSE; + } +} + +static void BSX_Map_FlashIO (void) +{ + int c; + + if (BSX.MMC[0x0C] || BSX.MMC[0x0D]) + { + // Bank C0:0000, 2AAA, 5555, FF00-FF1F + for (c = 0; c < 16; c++) + { + Map[c + 0xC00] = (uint8 *) MAP_BSX; + BlockIsRAM[c + 0xC00] = TRUE; + BlockIsROM[c + 0xC00] = FALSE; + } + } +} + +static void BSX_Map_SRAM (void) +{ + int c; + + // Banks 10->17:5000-5FFF + for (c = 0x100; c < 0x180; c += 16) + { + Map[c + 5] = (uint8 *) SRAM + ((c & 0x70) << 8) - 0x5000; + BlockIsRAM[c + 5] = TRUE; + BlockIsROM[c + 5] = FALSE; + } +} + +static void map_psram_mirror_sub (uint32 bank) +{ + int i, c; + + bank <<= 4; + + if (BSX.MMC[0x02]) + { + for (c = 0; c < 0x100; c += 16) + { + for (i = c; i < c + 16; i++) + { + Map[i + bank] = &PSRAM[(c << 12) % PSRAM_SIZE]; + BlockIsRAM[i + bank] = TRUE; + BlockIsROM[i + bank] = FALSE; + } + } + } + else + { + for (c = 0; c < 0x100; c += 16) + { + for (i = c; i < c + 8; i++) + Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE]; + + for (i = c + 8; i < c + 16; i++) + Map[i + bank] = &PSRAM[(c << 11) % PSRAM_SIZE] - 0x8000; + + for (i = c; i < c + 16; i++) + { + BlockIsRAM[i + bank] = TRUE; + BlockIsROM[i + bank] = FALSE; + } + } + } +} + +static void BSX_Map_PSRAM (void) +{ + int c; + + // Banks 70->77:0000-FFFF + // FIXME: could be toggled by $03 + for (c = 0; c < 0x80; c++) + { + Map[c + 0x700] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; + BlockIsRAM[c + 0x700] = TRUE; + BlockIsROM[c + 0x700] = FALSE; + } + + // Banks 20->3F:6000-7FFF mirrors 70->77:6000-7FFF + for (c = 0x200; c < 0x400; c += 16) + { + Map[c + 6] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; + Map[c + 7] = &PSRAM[((c & 0x70) << 12) % PSRAM_SIZE]; + BlockIsRAM[c + 6] = TRUE; + BlockIsRAM[c + 7] = TRUE; + BlockIsROM[c + 6] = FALSE; + BlockIsROM[c + 7] = FALSE; + } + + if (!BSX.MMC[0x05]) + // Banks 40->4F:0000-FFFF mirrors 70->77:0000-7FFF + map_psram_mirror_sub(0x40); + + if (!BSX.MMC[0x06]) + // Banks 50->5F:0000-FFFF mirrors 70->77:0000-7FFF + map_psram_mirror_sub(0x50); + + // FIXME + if (!BSX.MMC[0x03]) + // Banks 60->6F:0000-FFFF mirrors 70->77:0000-7FFF (?) + map_psram_mirror_sub(0x60); +} + +static void BSX_Map_BIOS (void) +{ + int i,c; + + // Banks 00->1F:8000-FFFF + if (BSX.MMC[0x07]) + { + for (c = 0; c < 0x200; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i] = &BIOSROM[(c << 11) % BIOS_SIZE] - 0x8000; + BlockIsRAM[i] = FALSE; + BlockIsROM[i] = TRUE; + } + } + } + + // Banks 80->9F:8000-FFFF + if (BSX.MMC[0x08]) + { + for (c = 0; c < 0x200; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i + 0x800] = &BIOSROM[(c << 11) % BIOS_SIZE] - 0x8000; + BlockIsRAM[i + 0x800] = FALSE; + BlockIsROM[i + 0x800] = TRUE; + } + } + } +} + +static void BSX_Map_RAM (void) +{ + int c; + + // Banks 7E->7F + 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; + } +} + +static void BSX_Map_Dirty (void) +{ + // for the quick bank change + + int i, c; + + // Banks 00->1F and 80->9F:8000-FFFF + if (BSX.MMC[0x02]) + { + for (c = 0; c < 0x200; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i] = Map[i + 0x800] = &MapROM[(c << 12) % FlashSize]; + BlockIsRAM[i] = BlockIsRAM[i + 0x800] = BSX.write_enable; + BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; + } + } + } + else + { + for (c = 0; c < 0x200; c += 16) + { + for (i = c + 8; i < c + 16; i++) + { + Map[i] = Map[i + 0x800] = &MapROM[(c << 11) % FlashSize] - 0x8000; + BlockIsRAM[i] = BlockIsRAM[i + 0x800] = BSX.write_enable; + BlockIsROM[i] = BlockIsROM[i + 0x800] = !BSX.write_enable; + } + } + } +} + +static void BSX_Map (void) +{ +#ifdef BSX_DEBUG + printf("BS: Remapping\n"); + for (int i = 0; i < 32; i++) + printf("BS: MMC %02X: %d\n", i, BSX.MMC[i]); +#endif + + memcpy(BSX.prevMMC, BSX.MMC, sizeof(BSX.MMC)); + + // Do a quick bank change + if (BSX.dirty2 && !BSX.dirty) + { + BSX_Map_Dirty(); + BSX_Map_BIOS(); + + BSX.dirty2 = FALSE; + + Memory.map_WriteProtectROM(); + return; + } + + if (BSX.MMC[0x01]) + { + MapROM = PSRAM; + FlashSize = PSRAM_SIZE; + } + else + { + MapROM = FlashROM; + FlashSize = FLASH_SIZE; + } + + BSX_Map_SNES(); + + if (BSX.MMC[0x02]) + BSX_Map_HiROM(); + else + BSX_Map_LoROM(); + + BSX_Map_PSRAM(); + BSX_Map_SRAM(); + BSX_Map_RAM(); + + BSX_Map_BIOS(); + BSX_Map_FlashIO(); + BSX_Map_MMC(); + + // Monitor new register changes + BSX.dirty = FALSE; + BSX.dirty2 = FALSE; + + Memory.map_WriteProtectROM(); +} + +static uint8 BSX_Get_Bypass_FlashIO (uint16 offset) +{ + if (BSX.MMC[0x02]) + return (MapROM[offset]); + else + { + if (offset < 0x8000) + return (MapROM[offset]); + else + return (MapROM[offset - 0x8000]); + } +} + +static void BSX_Set_Bypass_FlashIO (uint16 offset, uint8 byte) +{ + if (BSX.MMC[0x02]) + MapROM[offset] = byte; + else + { + if (offset < 0x8000) + MapROM[offset] = byte; + else + MapROM[offset - 0x8000] = byte; + } +} + +uint8 S9xGetBSX (uint32 address) +{ + uint8 bank = (address >> 16) & 0xFF; + uint16 offset = address & 0xFFFF; + uint8 t = 0; + + // MMC + if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000)) + return (BSX.MMC[bank]); + + // Flash IO + if (bank == 0xC0) + { + // default: read-through mode + t = BSX_Get_Bypass_FlashIO(offset); + + // note: may be more registers, purposes unknown + switch (offset) + { + case 0x0002: + if (BSX.flash_enable) + t = 0x80; // status register? + break; + + case 0x5555: + if (BSX.flash_enable) + t = 0x80; // ??? + break; + + case 0xFF00: + case 0xFF02: + case 0xFF04: + case 0xFF06: + case 0xFF08: + case 0xFF0A: + case 0xFF0C: + case 0xFF0E: + case 0xFF10: + case 0xFF12: + // return flash vendor information + if (BSX.read_enable) + t = flashcard[offset - 0xFF00]; + break; + } + } + + return (t); +} + +void S9xSetBSX (uint8 byte, uint32 address) +{ + uint8 bank = (address >> 16) & 0xFF; + uint16 offset = address & 0xFFFF; + + // MMC + if ((bank >= 0x01 && bank <= 0x0E) && (offset == 0x5000)) + { + switch (bank) + { + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + if (BSX.MMC[bank] != byte) + { + BSX.MMC[bank] = byte; + BSX.dirty = TRUE; + } + break; + + case 0x07: + case 0x08: + if (BSX.MMC[bank] != byte) + { + BSX.MMC[bank] = byte; + BSX.dirty2 = TRUE; + } + break; + + case 0x0E: + BSX.MMC[bank] = byte; + if (byte && (BSX.dirty || BSX.dirty2)) + BSX_Map(); + break; + } + } + + // Flash IO + if (bank == 0xC0) + { + BSX.old_write = BSX.new_write; + BSX.new_write = address; + + // ???: double writes to the desired address will bypass + // flash registers + if (BSX.old_write == BSX.new_write && BSX.write_enable) + { + BSX_Set_Bypass_FlashIO(offset, byte); + return; + } + + // flash command handling + // note: incomplete + switch (offset) + { + case 0x0000: + BSX.flash_command <<= 8; + BSX.flash_command |= byte; + if ((BSX.flash_command & 0xFFFF) == 0x38D0) + { + // retrieve information about the flash card + BSX.flash_enable = TRUE; + BSX.read_enable = TRUE; + } + break; + + case 0x2AAA: + BSX.flash_command <<= 8; + BSX.flash_command |= byte; + break; + + case 0x5555: + BSX.flash_command <<= 8; + BSX.flash_command |= byte; + + switch (BSX.flash_command & 0xFFFFFF) + { + case 0xAA55F0: + // turn off flash i/o + BSX.flash_enable = FALSE; + BSX.write_enable = FALSE; + BSX.read_enable = FALSE; + break; + + case 0xAA55A0: + // enable writing to flash + BSX.old_write = 0; + BSX.new_write = 0; + BSX.flash_enable = TRUE; + BSX.write_enable = TRUE; + BSX_Map(); + break; + + case 0xAA5570: + // turn on write-protection + BSX.write_enable = FALSE; + BSX_Map(); + break; + + case 0xAA5580: + case 0xAA5510: + // ??? + break; + + } + + break; + } + } +} + +uint8 S9xGetBSXPPU (uint16 address) +{ + uint8 t; + + // known read registers + switch (address) + { + // Test register low? (r/w) + case 0x2188: + t = BSX.PPU[0x2188 - BSXPPUBASE]; + break; + + // Test register high? (r/w) + case 0x2189: + t = BSX.PPU[0x2189 - BSXPPUBASE]; + break; + + case 0x218A: + t = BSX.PPU[0x218A - BSXPPUBASE]; + break; + + case 0x218C: + t = BSX.PPU[0x218C - BSXPPUBASE]; + break; + + // Transmission number low? (r/w) + case 0x218E: + t = BSX.PPU[0x218E - BSXPPUBASE]; + break; + + // Transmission number high? (r/w) + case 0x218F: + t = BSX.PPU[0x218F - BSXPPUBASE]; + break; + + // Status register? (r) + case 0x2190: + t = BSX.PPU[0x2190 - BSXPPUBASE]; + break; + + // Data register? (r/w) + case 0x2192: + t = BSX.PPU[0x2192 - BSXPPUBASE]; + + // test + t = BSX.test2192[BSX.out_index++]; + if (BSX.out_index == 32) + BSX.out_index = 0; + + BSX_RTC.ticks++; + if (BSX_RTC.ticks >= 1000) + { + BSX_RTC.ticks = 0; + BSX_RTC.seconds++; + } + if (BSX_RTC.seconds >= 60) + { + BSX_RTC.seconds = 0; + BSX_RTC.minutes++; + } + if (BSX_RTC.minutes >= 60) + { + BSX_RTC.minutes = 0; + BSX_RTC.hours++; + } + if (BSX_RTC.hours >= 24) + BSX_RTC.hours = 0; + + BSX.test2192[10] = BSX_RTC.seconds; + BSX.test2192[11] = BSX_RTC.minutes; + BSX.test2192[12] = BSX_RTC.hours; + + break; + + // Transmission status? (r/w) + case 0x2193: + // Data ready when bits 2/3 clear? + t = BSX.PPU[0x2193 - BSXPPUBASE] & ~0x0C; + break; + + // Reset? (r/w) + case 0x2194: + t = BSX.PPU[0x2194 - BSXPPUBASE]; + break; + + // Unknown (r) + case 0x2196: + t = BSX.PPU[0x2196 - BSXPPUBASE]; + break; + + // Unknown (r/w) + case 0x2197: + t = BSX.PPU[0x2197 - BSXPPUBASE]; + break; + + // Modem protocol? (r/w) + case 0x2199: + t = BSX.PPU[0x2199 - BSXPPUBASE]; + break; + + default: + t = OpenBus; + break; + } + + return (t); +} + +void S9xSetBSXPPU (uint8 byte, uint16 address) +{ + // known write registers + switch (address) + { + // Test register low? (r/w) + case 0x2188: + BSX.PPU[0x2188 - BSXPPUBASE] = byte; + break; + + // Test register high? (r/w) + case 0x2189: + BSX.PPU[0x2189 - BSXPPUBASE] = byte; + break; + + case 0x218A: + BSX.PPU[0x218A - BSXPPUBASE] = byte; + break; + + case 0x218B: + BSX.PPU[0x218B - BSXPPUBASE] = byte; + break; + + case 0x218C: + BSX.PPU[0x218C - BSXPPUBASE] = byte; + break; + + // Transmission number low? (r/w) + case 0x218E: + BSX.PPU[0x218E - BSXPPUBASE] = byte; + break; + + // Transmission number high? (r/w) + case 0x218F: + BSX.PPU[0x218F - BSXPPUBASE] = byte; + + // ? + BSX.PPU[0x218E - BSXPPUBASE] >>= 1; + BSX.PPU[0x218E - BSXPPUBASE] = BSX.PPU[0x218F - BSXPPUBASE] - BSX.PPU[0x218E - BSXPPUBASE]; + BSX.PPU[0x218F - BSXPPUBASE] >>= 1; + + BSX.PPU[0x2190 - BSXPPUBASE] = 0x80; // ? + break; + + // Strobe assert? (w) + case 0x2191: + BSX.PPU[0x2191 - BSXPPUBASE] = byte; + BSX.out_index = 0; + break; + + // Data register? (r/w) + case 0x2192: + BSX.PPU[0x2192 - BSXPPUBASE] = 0x01; // ? + BSX.PPU[0x2190 - BSXPPUBASE] = 0x80; // ? + break; + + // Transmission status? (r/w) + case 0x2193: + BSX.PPU[0x2193 - BSXPPUBASE] = byte; + break; + + // Reset? (r/w) + case 0x2194: + BSX.PPU[0x2194 - BSXPPUBASE] = byte; + break; + + // Unknown (r/w) + case 0x2197: + BSX.PPU[0x2197 - BSXPPUBASE] = byte; + break; + + // Modem protocol? (r/w) + case 0x2199: + // Lots of modem strings written here when + // connection is lost or no uplink established + BSX.PPU[0x2199 - BSXPPUBASE] = byte; + break; + } +} + +uint8 * S9xGetBasePointerBSX (uint32 address) +{ + return (MapROM); +} + +static bool8 BSX_LoadBIOS (void) +{ + FILE *fp; + char path[PATH_MAX + 1], name[PATH_MAX + 1]; + bool8 r = FALSE; + + strcpy(path, S9xGetDirectory(BIOS_DIR)); + strcat(path, SLASH_STR); + strcpy(name, path); + strcat(name, "BS-X.bin"); + + fp = fopen(name, "rb"); + if (!fp) + { + strcpy(name, path); + strcat(name, "BS-X.bios"); + fp = fopen(name, "rb"); + } + + if (fp) + { + size_t size; + + size = fread((void *) BIOSROM, 1, BIOS_SIZE, fp); + fclose(fp); + if (size == BIOS_SIZE) + r = TRUE; + } + +#ifdef BSX_DEBUG + if (r) + printf("BS: BIOS found.\n"); + else + printf("BS: BIOS not found!\n"); +#endif + + return (r); +} + +void S9xInitBSX (void) +{ + Settings.BS = FALSE; + + if (!memcmp(&Memory.ROM[0x7FC0], "Satellaview BS-X ", 21)) + { + // BS-X itself + + Settings.BS = TRUE; + Settings.BSXItself = TRUE; + + Memory.LoROM = TRUE; + Memory.HiROM = FALSE; + + memmove(BIOSROM, Memory.ROM, BIOS_SIZE); + + FlashMode = FALSE; + FlashSize = FLASH_SIZE; + + BSX.bootup = TRUE; + } + else + { + Settings.BSXItself = FALSE; + + int r1, r2; + + r1 = (is_bsx(Memory.ROM + 0x7FC0) == 1); + r2 = (is_bsx(Memory.ROM + 0xFFC0) == 1); + Settings.BS = (r1 | r2) ? TRUE : FALSE; + + if (Settings.BS) + { + // BS games + + Memory.LoROM = r1 ? TRUE : FALSE; + Memory.HiROM = r2 ? TRUE : FALSE; + + uint8 *header = r1 ? Memory.ROM + 0x7FC0 : Memory.ROM + 0xFFC0; + + FlashMode = (header[0x18] & 0xEF) == 0x20 ? FALSE : TRUE; + FlashSize = (header[0x19] & 0x20) ? PSRAM_SIZE : FLASH_SIZE; + +#ifdef BSX_DEBUG + for (int i = 0; i <= 0x1F; i++) + printf("BS: ROM Header %02X: %02X\n", i, header[i]); + printf("BS: FlashMode: %d, FlashSize: %x\n", FlashMode, FlashSize); +#endif + + BSX.bootup = Settings.BSXBootup; + + if (!BSX_LoadBIOS()) + { + BSX.bootup = FALSE; + memset(BIOSROM, 0, BIOS_SIZE); + } + } + } + + if (Settings.BS) + { + MapROM = NULL; + FlashROM = Memory.ROM; + + time_t t; + struct tm *tmr; + + time(&t); + tmr = localtime(&t); + + BSX_RTC.ticks = 0; + memcpy(BSX.test2192, init2192, sizeof(init2192)); + BSX.test2192[10] = BSX_RTC.seconds = tmr->tm_sec; + BSX.test2192[11] = BSX_RTC.minutes = tmr->tm_min; + BSX.test2192[12] = BSX_RTC.hours = tmr->tm_hour; +#ifdef BSX_DEBUG + printf("BS: Current Time: %02d:%02d:%02d\n", BSX_RTC.hours, BSX_RTC.minutes, BSX_RTC.seconds); +#endif + SNESGameFixes.SRAMInitialValue = 0x00; + } +} + +void S9xResetBSX (void) +{ + if (Settings.BSXItself) + memset(Memory.ROM, 0, FLASH_SIZE); + + memset(BSX.PPU, 0, sizeof(BSX.PPU)); + memset(BSX.MMC, 0, sizeof(BSX.MMC)); + memset(BSX.prevMMC, 0, sizeof(BSX.prevMMC)); + + BSX.dirty = FALSE; + BSX.dirty2 = FALSE; + BSX.flash_enable = FALSE; + BSX.write_enable = FALSE; + BSX.read_enable = FALSE; + BSX.flash_command = 0; + BSX.old_write = 0; + BSX.new_write = 0; + + BSX.out_index = 0; + memset(BSX.output, 0, sizeof(BSX.output)); + + // starting from the bios + if (BSX.bootup) + BSX.MMC[0x07] = BSX.MMC[0x08] = 0x80; + else + { + BSX.MMC[0x02] = FlashMode ? 0x80: 0; + + // per bios: run from psram or flash card + if (FlashSize == PSRAM_SIZE) + { + memcpy(PSRAM, FlashROM, PSRAM_SIZE); + + BSX.MMC[0x01] = 0x80; + BSX.MMC[0x03] = 0x80; + BSX.MMC[0x04] = 0x80; + BSX.MMC[0x0C] = 0x80; + BSX.MMC[0x0D] = 0x80; + } + else + { + BSX.MMC[0x03] = 0x80; + BSX.MMC[0x05] = 0x80; + BSX.MMC[0x06] = 0x80; + } + + BSX.MMC[0x0E] = 0x80; + } + + BSX_Map(); +} + +void S9xBSXPostLoadState (void) +{ + uint8 temp[16]; + bool8 pd1, pd2; + + pd1 = BSX.dirty; + pd2 = BSX.dirty2; + memcpy(temp, BSX.MMC, sizeof(BSX.MMC)); + + memcpy(BSX.MMC, BSX.prevMMC, sizeof(BSX.MMC)); + BSX_Map(); + + memcpy(BSX.MMC, temp, sizeof(BSX.MMC)); + BSX.dirty = pd1; + BSX.dirty2 = pd2; +} + +static bool valid_normal_bank (unsigned char bankbyte) +{ + switch (bankbyte) + { + case 32: case 33: case 48: case 49: + return (true); + break; + } + + return (false); +} + +static int is_bsx (unsigned char *p) +{ + if ((p[26] == 0x33 || p[26] == 0xFF) && (!p[21] || (p[21] & 131) == 128) && valid_normal_bank(p[24])) + { + unsigned char m = p[22]; + + if (!m && !p[23]) + return (2); + + if ((m == 0xFF && p[23] == 0xFF) || (!(m & 0xF) && ((m >> 4) - 1 < 12))) + return (1); + } + + return (0); +} diff --git a/bsx.h b/bsx.h new file mode 100644 index 00000000..d88bb193 --- /dev/null +++ b/bsx.h @@ -0,0 +1,211 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _BSX_H_ +#define _BSX_H_ + +struct SBSX +{ + bool8 dirty; // Changed register values + bool8 dirty2; // Changed register values + bool8 bootup; // Start in bios mapping + bool8 flash_enable; // Flash state + bool8 write_enable; // ROM write protection + bool8 read_enable; // Allow card vendor reading + uint32 flash_command; // Flash command + uint32 old_write; // Previous flash write address + uint32 new_write; // Current flash write address + uint8 out_index; + uint8 output[32]; + uint8 PPU[32]; + uint8 MMC[16]; + uint8 prevMMC[16]; + uint8 test2192[32]; +}; + +extern struct SBSX BSX; + +uint8 S9xGetBSX (uint32); +void S9xSetBSX (uint8, uint32); +uint8 S9xGetBSXPPU (uint16); +void S9xSetBSXPPU (uint8, uint16); +uint8 * S9xGetBasePointerBSX (uint32); +void S9xInitBSX (void); +void S9xResetBSX (void); +void S9xBSXPostLoadState (void); + +#endif diff --git a/c4.cpp b/c4.cpp new file mode 100644 index 00000000..ce406822 --- /dev/null +++ b/c4.cpp @@ -0,0 +1,341 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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" + +#define C4_PI 3.14159265 + +int16 C4WFXVal; +int16 C4WFYVal; +int16 C4WFZVal; +int16 C4WFX2Val; +int16 C4WFY2Val; +int16 C4WFDist; +int16 C4WFScale; +int16 C41FXVal; +int16 C41FYVal; +int16 C41FAngleRes; +int16 C41FDist; +int16 C41FDistVal; + +static double tanval; +static double c4x, c4y, c4z; +static double c4x2, c4y2, c4z2; + + +void C4TransfWireFrame (void) +{ + c4x = (double) C4WFXVal; + c4y = (double) C4WFYVal; + c4z = (double) C4WFZVal - 0x95; + + // Rotate X + tanval = -(double) C4WFX2Val * C4_PI * 2 / 128; + c4y2 = c4y * cos(tanval) - c4z * sin(tanval); + c4z2 = c4y * sin(tanval) + c4z * cos(tanval); + + // Rotate Y + tanval = -(double) C4WFY2Val * C4_PI * 2 / 128; + c4x2 = c4x * cos(tanval) + c4z2 * sin(tanval); + c4z = c4x * -sin(tanval) + c4z2 * cos(tanval); + + // Rotate Z + tanval = -(double) C4WFDist * C4_PI * 2 / 128; + c4x = c4x2 * cos(tanval) - c4y2 * sin(tanval); + c4y = c4x2 * sin(tanval) + c4y2 * cos(tanval); + + // Scale + C4WFXVal = (int16) (c4x * (double) C4WFScale / (0x90 * (c4z + 0x95)) * 0x95); + C4WFYVal = (int16) (c4y * (double) C4WFScale / (0x90 * (c4z + 0x95)) * 0x95); +} + +void C4TransfWireFrame2 (void) +{ + c4x = (double) C4WFXVal; + c4y = (double) C4WFYVal; + c4z = (double) C4WFZVal; + + // Rotate X + tanval = -(double) C4WFX2Val * C4_PI * 2 / 128; + c4y2 = c4y * cos(tanval) - c4z * sin(tanval); + c4z2 = c4y * sin(tanval) + c4z * cos(tanval); + + // Rotate Y + tanval = -(double) C4WFY2Val * C4_PI * 2 / 128; + c4x2 = c4x * cos(tanval) + c4z2 * sin(tanval); + c4z = c4x * -sin(tanval) + c4z2 * cos(tanval); + + // Rotate Z + tanval = -(double) C4WFDist * C4_PI * 2 / 128; + c4x = c4x2 * cos(tanval) - c4y2 * sin(tanval); + c4y = c4x2 * sin(tanval) + c4y2 * cos(tanval); + + // Scale + C4WFXVal = (int16) (c4x * (double) C4WFScale / 0x100); + C4WFYVal = (int16) (c4y * (double) C4WFScale / 0x100); +} + +void C4CalcWireFrame (void) +{ + C4WFXVal = C4WFX2Val - C4WFXVal; + C4WFYVal = C4WFY2Val - C4WFYVal; + + if (abs(C4WFXVal) > abs(C4WFYVal)) + { + C4WFDist = abs(C4WFXVal) + 1; + C4WFYVal = (int16) (256 * (double) C4WFYVal / abs(C4WFXVal)); + if (C4WFXVal < 0) + C4WFXVal = -256; + else + C4WFXVal = 256; + } + else + { + if (C4WFYVal != 0) + { + C4WFDist = abs(C4WFYVal) + 1; + C4WFXVal = (int16) (256 * (double) C4WFXVal / abs(C4WFYVal)); + if (C4WFYVal < 0) + C4WFYVal = -256; + else + C4WFYVal = 256; + } + else + C4WFDist = 0; + } +} + +void C4Op1F (void) +{ + if (C41FXVal == 0) + { + if (C41FYVal > 0) + C41FAngleRes = 0x80; + else + C41FAngleRes = 0x180; + } + else + { + tanval = (double) C41FYVal / C41FXVal; + C41FAngleRes = (int16) (atan(tanval) / (C4_PI * 2) * 512); + C41FAngleRes = C41FAngleRes; + if (C41FXVal< 0) + C41FAngleRes += 0x100; + C41FAngleRes &= 0x1FF; + } +} + +void C4Op15 (void) +{ + tanval = sqrt((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + C41FDist = (int16) tanval; +} + +void C4Op0D (void) +{ + tanval = sqrt((double) C41FYVal * C41FYVal + (double) C41FXVal * C41FXVal); + tanval = C41FDistVal / tanval; + C41FYVal = (int16) (C41FYVal * tanval * 0.99); + C41FXVal = (int16) (C41FXVal * tanval * 0.98); +} + +uint8 * S9xGetBasePointerC4 (uint16 Address) +{ + if (Address >= 0x7f40 && Address <= 0x7f5e) + return (NULL); + return (Memory.C4RAM - 0x6000); +} + +uint8 * S9xGetMemPointerC4 (uint16 Address) +{ + if (Address >= 0x7f40 && Address <= 0x7f5e) + return (NULL); + return (Memory.C4RAM - 0x6000 + (Address & 0xffff)); +} + +#ifdef ZSNES_C4 +START_EXTERN_C + +void C4LoaDMem (char *C4RAM) +{ + memmove(C4RAM + (READ_WORD(C4RAM + 0x1f45) & 0x1fff), C4GetMemPointer(READ_3WORD(C4RAM + 0x1f40)), READ_WORD(C4RAM + 0x1f43)); +} + +END_EXTERN_C +#endif diff --git a/c4.h b/c4.h new file mode 100644 index 00000000..649d8bb3 --- /dev/null +++ b/c4.h @@ -0,0 +1,224 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _C4_H_ +#define _C4_H_ + +#ifdef ZSNES_C4 +START_EXTERN_C +#endif + +extern int16 C4WFXVal; +extern int16 C4WFYVal; +extern int16 C4WFZVal; +extern int16 C4WFX2Val; +extern int16 C4WFY2Val; +extern int16 C4WFDist; +extern int16 C4WFScale; +extern int16 C41FXVal; +extern int16 C41FYVal; +extern int16 C41FAngleRes; +extern int16 C41FDist; +extern int16 C41FDistVal; + +#ifdef ZSNES_C4 +extern uint8 *C4Ram; +#endif + +void C4TransfWireFrame (void); +void C4TransfWireFrame2 (void); +void C4CalcWireFrame (void); +void C4Op0D (void); +void C4Op15 (void); +void C4Op1F (void); +void S9xInitC4 (void); +void S9xSetC4 (uint8, uint16); +uint8 S9xGetC4 (uint16); + +#ifdef ZSNES_C4 +END_EXTERN_C +#endif + +uint8 * S9xGetBasePointerC4 (uint16); +uint8 * S9xGetMemPointerC4 (uint16); + +static inline uint8 * C4GetMemPointer (uint32 Address) +{ + return (Memory.ROM + ((Address & 0xff0000) >> 1) + (Address & 0x7fff)); +} + +#endif diff --git a/c4emu.cpp b/c4emu.cpp new file mode 100644 index 00000000..a7c009cb --- /dev/null +++ b/c4emu.cpp @@ -0,0 +1,1238 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "sar.h" + +static 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 +}; + +static 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 +}; + +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); +static void C4DoScaleRotate (int); +static void C4DrawLine (int32, int32, int16, int32, int32, int16, uint8); +static void C4DrawWireFrame (void); +static void C4TransformLines (void); +static void C4BitPlaneWave (void); +static void C4SprDisintegrate (void); +static void C4ProcessSprites (void); + + +static void C4ConvOAM (void) +{ + uint8 *OAMptr = Memory.C4RAM + (Memory.C4RAM[0x626] << 2); + for (uint8 *i = Memory.C4RAM + 0x1fd; i > OAMptr; i -= 4) + *i = 0xe0; // Clear OAM-to-be + + uint8 *OAMptr2; + uint16 globalX, globalY; + 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); + +#ifdef DEBUGGER + if (Memory.C4RAM[0x625] != 0) + printf("$6625=%02x, expected 00\n", Memory.C4RAM[0x625]); + if ((Memory.C4RAM[0x626] >> 2) != Memory.C4RAM[0x629]) + printf("$6629=%02x, expected %02x\n", Memory.C4RAM[0x629], (Memory.C4RAM[0x626] >> 2)); + if (((uint16) Memory.C4RAM[0x626] << 2) != READ_WORD(Memory.C4RAM + 0x627)) + printf("$6627=%04x, expected %04x\n", READ_WORD(Memory.C4RAM + 0x627), ((uint16) Memory.C4RAM[0x626] << 2)); +#endif + + 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) + X = -X - ((sprptr[0] & 0x20) ? 16 : 8); // flip X + 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 << offset); + if (X & 0x100) + *OAMptr2 |= 1 << offset; + if (sprptr[0] & 0x20) + *OAMptr2 |= 2 << offset; + + OAMptr += 4; + SprCount--; + + offset = (offset + 2) & 6; + if (offset == 0) + OAMptr2++; + } + } + } + } + else + if (SprCount > 0) + { + // XXX: Should we be testing -16<=SprX<=272 and -16<=SprY<=224? + OAMptr[0] = (uint8) SprX; + OAMptr[1] = (uint8) SprY; + OAMptr[2] = SprName; + OAMptr[3] = SprAttr; + + *OAMptr2 &= ~(3 << offset); + if (SprX & 0x100) + *OAMptr2 |= 3 << offset; + else + *OAMptr2 |= 2 << offset; + + OAMptr += 4; + SprCount--; + + offset = (offset + 2) & 6; + if (offset == 0) + OAMptr2++; + } + } + } +} + +static void C4DoScaleRotate (int row_padding) +{ + int16 A, B, C, D; + + // Calculate matrix + int32 XScale = READ_WORD(Memory.C4RAM + 0x1f8f); + if (XScale & 0x8000) + XScale = 0x7fff; + + int32 YScale = READ_WORD(Memory.C4RAM + 0x1f92); + if (YScale & 0x8000) + YScale = 0x7fff; + + if (READ_WORD(Memory.C4RAM + 0x1f80) == 0) // no rotation + { + // XXX: only do this for C and D? + // XXX: and then only when YScale is 0x1000? + A = (int16) XScale; + B = 0; + C = 0; + D = (int16) YScale; + } + else + if (READ_WORD(Memory.C4RAM + 0x1f80) == 128) // 90 degree rotation + { + // XXX: Really do this? + A = 0; + B = (int16) (-YScale); + C = (int16) XScale; + D = 0; + } + else + if (READ_WORD(Memory.C4RAM + 0x1f80) == 256) // 180 degree rotation + { + // XXX: Really do this? + A = (int16) (-XScale); + B = 0; + C = 0; + D = (int16) (-YScale); + } + else + if (READ_WORD(Memory.C4RAM + 0x1f80) == 384) // 270 degree rotation + { + // XXX: Really do this? + A = 0; + B = (int16) YScale; + C = (int16) (-XScale); + D = 0; + } + else + { + A = (int16) SAR(C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * XScale, 15); + B = (int16) (-SAR(C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * YScale, 15)); + C = (int16) SAR(C4SinTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * XScale, 15); + D = (int16) SAR(C4CosTable[READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff] * YScale, 15); + } + + // Calculate Pixel Resolution + uint8 w = Memory.C4RAM[0x1f89] & ~7; + uint8 h = Memory.C4RAM[0x1f8c] & ~7; + + //printf("%dx%d XScale=%04x YScale=%04x angle=%03x\n", w, h, XScale, YScale, READ_WORD(Memory.C4RAM + 0x1f80) & 0x1ff); + //printf("Matrix: [%10g %10g] [%04x %04x]\n", A / 4096.0, B / 4096.0, A & 0xffff, B & 0xffff); + //printf(" [%10g %10g] [%04x %04x]\n", C / 4096.0, D / 4096.0, C & 0xffff, D & 0xffff); + + // Clear the output RAM + memset(Memory.C4RAM, 0, (w + row_padding / 4) * h / 2); + + int32 Cx = (int16) READ_WORD(Memory.C4RAM + 0x1f83); + int32 Cy = (int16) READ_WORD(Memory.C4RAM + 0x1f86); + +#ifdef DEBUGGER + if (Memory.C4RAM[0x1f97] != 0) + printf("$7f97=%02x, expected 00\n", Memory.C4RAM[0x1f97]); + if ((Cx & ~1) != w / 2 || (Cy & ~1) != h / 2) + printf("Center is not middle of image! (%d, %d) != (%d, %d)\n", Cx, Cy, w / 2, h / 2); +#endif + + // Calculate start position (i.e. (Ox, Oy) = (0, 0)) + // The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in the function. + // We do Cx*A etc normally because the matrix parameters already have the fractional parts. + int32 LineX = (Cx << 12) - Cx * A - Cx * B; + int32 LineY = (Cy << 12) - Cy * C - Cy * D; + + // Start loop + uint32 X, Y; + uint8 byte; + int outidx = 0; + uint8 bit = 0x80; + + for (int y = 0; y < h; y++) + { + X = LineX; + Y = LineY; + + for (int x = 0; x < w; x++) + { + if ((X >> 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 = (int16) X1; + C4WFYVal = (int16) 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 = (int16) X2; + C4WFYVal = (int16) Y2; + C4WFZVal = Z2; + C4TransfWireFrame2(); + X2 = (C4WFXVal + 48) << 8; + Y2 = (C4WFYVal + 48) << 8; + + // Get line info + C4WFXVal = (int16) (X1 >> 8); + C4WFYVal = (int16) (Y1 >> 8); + C4WFX2Val = (int16) (X2 >> 8); + C4WFY2Val = (int16) (Y2 >> 8); + C4CalcWireFrame(); + X2 = (int16) C4WFXVal; + Y2 = (int16) C4WFYVal; + + // Render line + for (int i = C4WFDist ? C4WFDist : 1; i > 0; i--) + { + if (X1 > 0xff && Y1 > 0xff && X1 < 0x6000 && Y1 < 0x6000) + { + uint16 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; + +#ifdef DEBUGGER + if (READ_3WORD(Memory.C4RAM + 0x1f8f) & 0xff00ff) + printf("wireframe: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8f)); + if (READ_3WORD(Memory.C4RAM + 0x1fa4) != 0x001000) + printf("wireframe: Unexpected value in $7fa4: %06x\n", READ_3WORD(Memory.C4RAM + 0x1fa4)); +#endif + + 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]; + +#ifdef DEBUGGER + if (Memory.C4RAM[0x1f8a] != 0x90) + printf("lines: $7f8a = %02x, expected 90\n", READ_WORD(Memory.C4RAM + 0x1f8a)); +#endif + + // 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 (void) +{ + 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; + +#ifdef DEBUGGER + if (READ_3WORD(Memory.C4RAM + 0x1f80) != Memory.C4RAM[waveptr + 0xb00]) + printf("$7f80=%06x, expected %02x\n", READ_3WORD(Memory.C4RAM + 0x1f80), Memory.C4RAM[waveptr + 0xb00]); +#endif + + 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 (void) +{ + uint8 *src; + uint8 width, height; + uint32 StartX, StartY; + 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); + +#ifdef DEBUGGER + if ((Cx & ~1) != width / 2 || (Cy & ~1) != height / 2) + printf("Center is not middle of image for disintegrate! (%d, %d) != (%d, %d)\n", Cx, Cy, width / 2, height / 2); +#endif + + 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 < height; i++, y += scaleY) + { + for (uint32 x = StartX, j = 0; j < width; j++, x += scaleX) + { + if ((x >> 8) < width && (y >> 8) < height && (y >> 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 C4ProcessSprites (void) +{ + switch (Memory.C4RAM[0x1f4d]) + { + case 0x00: // Build OAM + #ifdef DEBUGGER + //printf("00 00 Build OAM!\n"); + #endif + C4ConvOAM(); + break; + + case 0x03: // Scale/Rotate + #ifdef DEBUGGER + //printf("00 03 Scale/Rotate!\n"); + #endif + C4DoScaleRotate(0); + break; + + case 0x05: // Transform Lines + #ifdef DEBUGGER + //printf("00 05 Transform Lines!\n"); + #endif + C4TransformLines(); + break; + + case 0x07: // Scale/Rotate + #ifdef DEBUGGER + //printf("00 07 Scale/Rotate!\n"); + #endif + C4DoScaleRotate(64); + break; + + case 0x08: // Draw wireframe + #ifdef DEBUGGER + //printf("00 08 Draw wireframe!\n"); + #endif + C4DrawWireFrame(); + break; + + case 0x0b: // Disintegrate + #ifdef DEBUGGER + //printf("00 0b Disintegrate!\n"); + #endif + C4SprDisintegrate(); + break; + + case 0x0c: // Wave + #ifdef DEBUGGER + //printf("00 0b Wave!\n"); + #endif + C4BitPlaneWave(); + break; + + default: + #ifdef DEBUGGER + printf("Unknown C4 sprite command (%02x)\n", Memory.C4RAM[0x1f4d]); + #endif + break; + } +} + +void S9xInitC4 (void) +{ + // 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]); +} + +void S9xSetC4 (uint8 byte, uint16 Address) +{ + Memory.C4RAM[Address - 0x6000] = byte; + + if (Address == 0x7f4f) + { + if (Memory.C4RAM[0x1f4d] == 0x0e && byte < 0x40 && (byte & 3) == 0) + { + #ifdef DEBUGGER + printf("Test command %02x 0e used!\n", byte); + #endif + Memory.C4RAM[0x1f80] = byte >> 2; + } + else + { + switch (byte) + { + case 0x00: // Sprite + #ifdef DEBUGGER + //printf("00 Sprite!\n"); + #endif + C4ProcessSprites(); + break; + + case 0x01: // Draw wireframe + #ifdef DEBUGGER + //printf("01 Draw wireframe!\n"); + if (Memory.C4RAM[0x1f4d] != 8) + printf("$7f4d=%02x, expected 08 for command 01 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + memset(Memory.C4RAM + 0x300, 0, 16 * 12 * 3 * 4); + C4DrawWireFrame(); + break; + + case 0x05: // Propulsion (?) + { + #ifdef DEBUGGER + //printf("05 Propulsion (?)!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 05 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + 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 + #ifdef DEBUGGER + //printf("0d Set vector length!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 0d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + 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 + { + #ifdef DEBUGGER + //printf("10 Polar->Rect!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 10 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + int32 tmp; + 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 + { + #ifdef DEBUGGER + //printf("13 Polar->Rect!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 13 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + int32 tmp; + 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 + #ifdef DEBUGGER + //printf("15 Pythagorean!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 15 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80); + C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83); + //C4Op15(); // optimized to: + C41FDist = (int16) sqrt((double) C41FXVal * C41FXVal + (double) C41FYVal * C41FYVal); + WRITE_WORD(Memory.C4RAM + 0x1f80, C41FDist); + break; + + case 0x1f: // atan + #ifdef DEBUGGER + //printf("1f atan!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 1f %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + C41FXVal = READ_WORD(Memory.C4RAM + 0x1f80); + C41FYVal = READ_WORD(Memory.C4RAM + 0x1f83); + C4Op1F(); + WRITE_WORD(Memory.C4RAM + 0x1f86, C41FAngleRes); + break; + + case 0x22: // Trapezoid + { + #ifdef DEBUGGER + //printf("22 Trapezoid!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 22 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + int16 angle1 = READ_WORD(Memory.C4RAM + 0x1f8c) & 0x1ff; + int16 angle2 = READ_WORD(Memory.C4RAM + 0x1f8f) & 0x1ff; + + #ifdef DEBUGGER + if (C4CosTable[angle1] == 0) + fprintf(stderr, "22 Trapezoid: Invalid tangent! angle1=%d\n", angle1); + if (C4CosTable[angle2] == 0) + fprintf(stderr, "22 Trapezoid: Invalid tangent! angle2=%d\n", angle2); + #endif + + 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 + { + #ifdef DEBUGGER + //printf("25 Multiply!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 25 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + 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 + #ifdef DEBUGGER + //printf("2d Transform Coords!\n"); + if (Memory.C4RAM[0x1f4d] != 2) + printf("$7f4d=%02x, expected 02 for command 2d %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + if (READ_3WORD(Memory.C4RAM + 0x1f8f) & 0xff00ff) + printf("2d transform coords: Unexpected value in $7f8f: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8f)); + if (READ_3WORD(Memory.C4RAM + 0x1f8c) != 0x001000) + printf("0d transform coords: Unexpected value in $7f8c: %06x\n", READ_3WORD(Memory.C4RAM + 0x1f8c)); + #endif + 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 + { + #ifdef DEBUGGER + //printf("40 Sum!\n"); + if (Memory.C4RAM[0x1f4d] != 0x0e) + printf("$7f4d=%02x, expected 0e for command 40 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + uint16 sum = 0; + for (int i = 0; i < 0x800; sum += Memory.C4RAM[i++]) ; + WRITE_WORD(Memory.C4RAM + 0x1f80, sum); + break; + } + + case 0x54: // Square + { + #ifdef DEBUGGER + //printf("54 Square!\n"); + if (Memory.C4RAM[0x1f4d] != 0x0e) + printf("$7f4d=%02x, expected 0e for command 54 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + 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 + #ifdef DEBUGGER + //printf("5c Immediate Reg!\n"); + if (Memory.C4RAM[0x1f4d] != 0x0e) + printf("$7f4d=%02x, expected 0e for command 5c %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + for (int i = 0; i < 12 * 4; i++) + Memory.C4RAM[i] = C4TestPattern[i]; + break; + + case 0x89: // Immediate ROM + #ifdef DEBUGGER + //printf("89 Immediate ROM!\n"); + if (Memory.C4RAM[0x1f4d] != 0x0e) + printf("$7f4d=%02x, expected 0e for command 89 %02x\n", Memory.C4RAM[0x1f4d], Memory.C4RAM[0x1f4d]); + #endif + Memory.C4RAM[0x1f80] = 0x36; + Memory.C4RAM[0x1f81] = 0x43; + Memory.C4RAM[0x1f82] = 0x05; + break; + + default: + #ifdef DEBUGGER + printf("Unknown C4 command (%02x)\n", byte); + #endif + break; + } + } + } + else + if (Address == 0x7f47) + { + #ifdef DEBUGGER + //printf("C4 load memory %06x => %04x, %04x bytes\n", READ_3WORD(Memory.C4RAM + 0x1f40), READ_WORD(Memory.C4RAM + 0x1f45), READ_WORD(Memory.C4RAM + 0x1f43)); + if (byte != 0) + printf("C4 load: non-0 written to $7f47! Wrote %02x\n", byte); + if (READ_WORD(Memory.C4RAM + 0x1f45) < 0x6000 || (READ_WORD(Memory.C4RAM + 0x1f45) + READ_WORD(Memory.C4RAM + 0x1f43)) > 0x6c00) + printf("C4 load: Dest unusual! It's %04x\n", READ_WORD(Memory.C4RAM + 0x1f45)); + #endif + memmove(Memory.C4RAM + (READ_WORD(Memory.C4RAM + 0x1f45) & 0x1fff), C4GetMemPointer(READ_3WORD(Memory.C4RAM + 0x1f40)), READ_WORD(Memory.C4RAM + 0x1f43)); + } +} diff --git a/cheats.cpp b/cheats.cpp new file mode 100644 index 00000000..e4d648d0 --- /dev/null +++ b/cheats.cpp @@ -0,0 +1,578 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "cheats.h" + +#define WRAM_BITS ALL_BITS +#define SRAM_BITS ALL_BITS + (0x20000 >> 5) +#define IRAM_BITS ALL_BITS + (0x30000 >> 5) + +#define BIT_CLEAR(a, v) (a)[(v) >> 5] &= ~(1 << ((v) & 31)) + +#define TEST_BIT(a, v) ((a)[(v) >> 5] & (1 << ((v) & 31))) + +#define _S9XCHTC(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 _S9XCHTD(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 _S9XCHTDS(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)))) + +static bool8 S9xAllHex (const char *, int); + + +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]; + int i; + + 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."); + + for (i = 0; i < 3; i++) + { + unsigned int byte; + + strncpy(tmp, code + 5 + i * 2, 2); + tmp[2] = 0; + 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 const char *real_hex = "0123456789ABCDEF"; + static const 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->ALL_BITS, 0xff, 0x32000 >> 3); +} + +void S9xSearchForChange (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, bool8 is_signed, bool8 update) +{ + int l, i; + + 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; + } + + if (is_signed) + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(size, d->RAM, i), _S9XCHTDS(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) && _S9XCHTC(cmp, _S9XCHTDS(size, d->SRAM, i), _S9XCHTDS(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) && _S9XCHTC(cmp, _S9XCHTDS(size, d->FillRAM + 0x3000, i), _S9XCHTDS(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) && _S9XCHTC(cmp, _S9XCHTD(size, d->RAM, i), _S9XCHTD(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) && _S9XCHTC(cmp, _S9XCHTD(size, d->SRAM, i), _S9XCHTD(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) && _S9XCHTC(cmp, _S9XCHTD(size, d->FillRAM + 0x3000, i), _S9XCHTD(size, d->CIRAM, i))) + { + if (update) + d->CIRAM[i] = d->FillRAM[i + 0x3000]; + } + else + BIT_CLEAR(d->IRAM_BITS, i); + } + } + + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR(d->WRAM_BITS, i); + + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR(d->SRAM_BITS, i); +} + +void S9xSearchForValue (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, uint32 value, bool8 is_signed, bool8 update) +{ + int l, i; + + 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; + } + + if (is_signed) + { + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, _S9XCHTDS(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) && _S9XCHTC(cmp, _S9XCHTDS(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) && _S9XCHTC(cmp, _S9XCHTDS(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) && _S9XCHTC(cmp, _S9XCHTD(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) && _S9XCHTC(cmp, _S9XCHTD(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) && _S9XCHTC(cmp, _S9XCHTD(size, d->FillRAM + 0x3000, i), value)) + { + if (update) + d->CIRAM[i] = d->FillRAM[i + 0x3000]; + } + else + BIT_CLEAR(d->IRAM_BITS, i); + } + } + + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR(d->WRAM_BITS, i); + + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR(d->SRAM_BITS, i); +} + +void S9xSearchForAddress (SCheatData *d, S9xCheatComparisonType cmp, S9xCheatDataSize size, uint32 value, bool8 update) +{ + int l, i; + + 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; + } + + for (i = 0; i < 0x20000 - l; i++) + { + if (TEST_BIT(d->WRAM_BITS, i) && _S9XCHTC(cmp, 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) && _S9XCHTC(cmp, i + 0x20000, (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) && _S9XCHTC(cmp, i + 0x30000, (int32) value)) + { + if (update) + d->CIRAM[i] = d->FillRAM[i + 0x3000]; + } + else + BIT_CLEAR(d->IRAM_BITS, i); + } + + for (i = 0x20000 - l; i < 0x20000; i++) + BIT_CLEAR(d->WRAM_BITS, i); + + for (i = 0x10000 - l; i < 0x10000; i++) + BIT_CLEAR(d->SRAM_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/cheats.h b/cheats.h new file mode 100644 index 00000000..51ed71fb --- /dev/null +++ b/cheats.h @@ -0,0 +1,262 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _CHEATS_H_ +#define _CHEATS_H_ + +#define MAX_CHEATS 150 + +struct SCheat +{ + uint32 address; + uint8 byte; + uint8 saved_byte; + bool8 enabled; + bool8 saved; + char name[22]; +}; + +struct SCheatData +{ + struct SCheat c[MAX_CHEATS]; + uint32 num_cheats; + uint8 CWRAM[0x20000]; + uint8 CSRAM[0x10000]; + uint8 CIRAM[0x2000]; + uint8 *RAM; + uint8 *FillRAM; + uint8 *SRAM; + uint32 ALL_BITS[0x32000 >> 5]; + uint8 CWatchRAM[0x32000]; +}; + +struct Watch +{ + bool on; + int size; + int format; + uint32 address; + char buf[12]; + char desc[32]; +}; + +typedef enum +{ + S9X_LESS_THAN, + S9X_GREATER_THAN, + S9X_LESS_THAN_OR_EQUAL, + S9X_GREATER_THAN_OR_EQUAL, + S9X_EQUAL, + S9X_NOT_EQUAL +} S9xCheatComparisonType; + +typedef enum +{ + S9X_8_BITS, + S9X_16_BITS, + S9X_24_BITS, + S9X_32_BITS +} S9xCheatDataSize; + +extern SCheatData Cheat; +extern Watch watches[16]; + +void S9xApplyCheat (uint32); +void S9xApplyCheats (void); +void S9xRemoveCheat (uint32); +void S9xRemoveCheats (void); +void S9xDeleteCheat (uint32); +void S9xDeleteCheats (void); +void S9xEnableCheat (uint32); +void S9xDisableCheat (uint32); +void S9xAddCheat (bool8, bool8, uint32, uint8); +void S9xInitCheatData (void); +void S9xInitWatchedAddress (void); +bool8 S9xLoadCheatFile (const char *); +bool8 S9xSaveCheatFile (const char *); + +void S9xStartCheatSearch (SCheatData *); +void S9xSearchForChange (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, bool8, bool8); +void S9xSearchForValue (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8, bool8); +void S9xSearchForAddress (SCheatData *, S9xCheatComparisonType, S9xCheatDataSize, uint32, bool8); +void S9xOutputCheatSearchResults (SCheatData *); + +const char * S9xGameGenieToRaw (const char *, uint32 &, uint8 &); +const char * S9xProActionReplayToRaw (const char *, uint32 &, uint8 &); +const char * S9xGoldFingerToRaw (const char *, uint32 &, bool8 &, uint8 &, uint8 bytes[3]); + +#endif diff --git a/cheats2.cpp b/cheats2.cpp new file mode 100644 index 00000000..d174c5cf --- /dev/null +++ b/cheats2.cpp @@ -0,0 +1,406 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "cheats.h" + +static uint8 S9xGetByteFree (uint32); +static void S9xSetByteFree (uint8, uint32); + + +static uint8 S9xGetByteFree (uint32 address) +{ + uint32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + uint8 byte; + + byte = S9xGetByte(address); + + CPU.WaitAddress = WaitAddress; + CPU.Cycles = Cycles; + + return (byte); +} + +static void S9xSetByteFree (uint8 byte, uint32 address) +{ + uint32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + + S9xSetByte(byte, address); + + CPU.WaitAddress = WaitAddress; + CPU.Cycles = Cycles; +} + +void S9xInitWatchedAddress (void) +{ + for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++) + watches[i].on = false; + +} + +void S9xInitCheatData (void) +{ + Cheat.RAM = Memory.RAM; + Cheat.SRAM = Memory.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 = enable; + + if (save_current_value) + { + Cheat.c[Cheat.num_cheats].saved_byte = S9xGetByteFree(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--; + } +} + +void S9xDeleteCheats (void) +{ + S9xRemoveCheats(); + Cheat.num_cheats = 0; +} + +void S9xRemoveCheat (uint32 which1) +{ + if (Cheat.c[which1].saved) + { + uint32 address = Cheat.c[which1].address; + + int block = (address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *ptr = Memory.Map[block]; + + if (ptr >= (uint8 *) CMemory::MAP_LAST) + *(ptr + (address & 0xffff)) = Cheat.c[which1].saved_byte; + else + S9xSetByteFree(Cheat.c[which1].saved_byte, address); + } +} + +void S9xRemoveCheats (void) +{ + for (uint32 i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c[i].enabled) + S9xRemoveCheat(i); +} + +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 S9xApplyCheat (uint32 which1) +{ + uint32 address = Cheat.c[which1].address; + + if (!Cheat.c[which1].saved) + { + Cheat.c[which1].saved_byte = S9xGetByteFree(address); + Cheat.c[which1].saved = TRUE; + } + + int block = (address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *ptr = Memory.Map[block]; + + if (ptr >= (uint8 *) CMemory::MAP_LAST) + *(ptr + (address & 0xffff)) = Cheat.c[which1].byte; + else + S9xSetByteFree(Cheat.c[which1].byte, address); +} + +void S9xApplyCheats (void) +{ + if (Settings.ApplyCheats) + { + for (uint32 i = 0; i < Cheat.num_cheats; i++) + if (Cheat.c[i].enabled) + S9xApplyCheat(i); + } +} + +bool8 S9xLoadCheatFile (const char *filename) +{ + FILE *fs; + uint8 data[28]; + + Cheat.num_cheats = 0; + + fs = fopen(filename, "rb"); + 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) + { + remove(filename); + return (TRUE); + } + + FILE *fs; + uint8 data[28]; + + fs = fopen(filename, "wb"); + if (!fs) + return (FALSE); + + for (uint32 i = 0; i < Cheat.num_cheats; i++) + { + ZeroMemory(data, 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 >> 0); + 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/clip.cpp b/clip.cpp new file mode 100644 index 00000000..8e6baa35 --- /dev/null +++ b/clip.cpp @@ -0,0 +1,405 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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" + +static uint8 region_map[6][6] = +{ + { 0, 0x01, 0x03, 0x07, 0x0f, 0x1f }, + { 0, 0, 0x02, 0x06, 0x0e, 0x1e }, + { 0, 0, 0, 0x04, 0x0c, 0x1c }, + { 0, 0, 0, 0, 0x08, 0x18 }, + { 0, 0, 0, 0, 0, 0x10 } +}; + +static inline uint8 CalcWindowMask (int, uint8, uint8); +static inline void StoreWindowRegions (uint8, struct ClipData *, int, int16 *, uint8 *, bool8, bool8 s = FALSE); + + +static inline uint8 CalcWindowMask (int i, uint8 W1, uint8 W2) +{ + if (!PPU.ClipWindow1Enable[i]) + { + if (!PPU.ClipWindow2Enable[i]) + return (0); + else + { + if (!PPU.ClipWindow2Inside[i]) + return (~W2); + return (W2); + } + } + else + { + if (!PPU.ClipWindow2Enable[i]) + { + if (!PPU.ClipWindow1Inside[i]) + return (~W1); + return (W1); + } + else + { + if (!PPU.ClipWindow1Inside[i]) + W1 = ~W1; + if (!PPU.ClipWindow2Inside[i]) + W2 = ~W2; + + switch (PPU.ClipWindowOverlapLogic[i]) + { + case 0: // OR + return (W1 | W2); + + case 1: // AND + return (W1 & W2); + + case 2: // XOR + return (W1 ^ W2); + + case 3: // XNOR + return (~(W1 ^ W2)); + } + } + } + + // Never get here + return (0); +} + +static inline void StoreWindowRegions (uint8 Mask, struct ClipData *Clip, int n_regions, int16 *windows, uint8 *drawing_modes, bool8 sub, bool8 StoreMode0) +{ + int ct = 0; + + for (int j = 0; j < n_regions; j++) + { + int DrawMode = drawing_modes[j]; + if (sub) + DrawMode |= 1; + if (Mask & (1 << j)) + DrawMode = 0; + + if (!StoreMode0 && !DrawMode) + continue; + + if (ct > 0 && Clip->Right[ct - 1] == windows[j] && Clip->DrawMode[ct - 1] == DrawMode) + Clip->Right[ct - 1] = windows[j + 1]; // This region borders with and has the same drawing mode as the previous region: merge them. + else + { + // Add a new region to the BG + Clip->Left[ct] = windows[j]; + Clip->Right[ct] = windows[j + 1]; + Clip->DrawMode[ct] = DrawMode; + ct++; + } + } + + Clip->Count = ct; +} + +void S9xComputeClipWindows (void) +{ + int16 windows[6] = { 0, 256, 256, 256, 256, 256 }; + uint8 drawing_modes[5] = { 0, 0, 0, 0, 0 }; + int n_regions = 1; + int i, j; + + // Calculate window regions. We have at most 5 regions, because we have 6 control points + // (screen edges, window 1 left & right, and window 2 left & right). + + if (PPU.Window1Left <= PPU.Window1Right) + { + if (PPU.Window1Left > 0) + { + windows[2] = 256; + windows[1] = PPU.Window1Left; + n_regions = 2; + } + + if (PPU.Window1Right < 255) + { + windows[n_regions + 1] = 256; + windows[n_regions] = PPU.Window1Right + 1; + n_regions++; + } + } + + if (PPU.Window2Left <= PPU.Window2Right) + { + for (i = 0; i <= n_regions; i++) + { + if (PPU.Window2Left == windows[i]) + break; + + if (PPU.Window2Left < windows[i]) + { + for (j = n_regions; j >= i; j--) + windows[j + 1] = windows[j]; + + windows[i] = PPU.Window2Left; + n_regions++; + break; + } + } + + for (; i <= n_regions; i++) + { + if (PPU.Window2Right + 1 == windows[i]) + break; + + if (PPU.Window2Right + 1 < windows[i]) + { + for (j = n_regions; j >= i; j--) + windows[j + 1] = windows[j]; + + windows[i] = PPU.Window2Right + 1; + n_regions++; + break; + } + } + } + + // Get a bitmap of which regions correspond to each window. + + uint8 W1, W2; + + if (PPU.Window1Left <= PPU.Window1Right) + { + for (i = 0; windows[i] != PPU.Window1Left; i++) ; + for (j = i; windows[j] != PPU.Window1Right + 1; j++) ; + W1 = region_map[i][j]; + } + else + W1 = 0; + + if (PPU.Window2Left <= PPU.Window2Right) + { + for (i = 0; windows[i] != PPU.Window2Left; i++) ; + for (j = i; windows[j] != PPU.Window2Right + 1; j++) ; + W2 = region_map[i][j]; + } + else + W2 = 0; + + // Color Window affects the drawing mode for each region. + // Modes are: 3=Draw as normal, 2=clip color (math only), 1=no math (draw only), 0=nothing. + + uint8 CW_color = 0, CW_math = 0; + uint8 CW = CalcWindowMask(5, W1, W2); + + switch (Memory.FillRAM[0x2130] & 0xc0) + { + case 0x00: CW_color = 0; break; + case 0x40: CW_color = ~CW; break; + case 0x80: CW_color = CW; break; + case 0xc0: CW_color = 0xff; break; + } + + switch (Memory.FillRAM[0x2130] & 0x30) + { + case 0x00: CW_math = 0; break; + case 0x10: CW_math = ~CW; break; + case 0x20: CW_math = CW; break; + case 0x30: CW_math = 0xff; break; + } + + for (i = 0; i < n_regions; i++) + { + if (!(CW_color & (1 << i))) + drawing_modes[i] |= 1; + if (!(CW_math & (1 << i))) + drawing_modes[i] |= 2; + } + + // Store backdrop clip window (draw everywhere color window allows) + + StoreWindowRegions(0, &IPPU.Clip[0][5], n_regions, windows, drawing_modes, FALSE, TRUE); + StoreWindowRegions(0, &IPPU.Clip[1][5], n_regions, windows, drawing_modes, TRUE, TRUE); + + // Store per-BG and OBJ clip windows + + for (j = 0; j < 5; j++) + { + uint8 W = Settings.DisableGraphicWindows ? 0 : CalcWindowMask(j, W1, W2); + for (int sub = 0; sub < 2; sub++) + { + if (Memory.FillRAM[sub + 0x212e] & (1 << j)) + StoreWindowRegions(W, &IPPU.Clip[sub][j], n_regions, windows, drawing_modes, sub); + else + StoreWindowRegions(0, &IPPU.Clip[sub][j], n_regions, windows, drawing_modes, sub); + } + } +} diff --git a/conffile.cpp b/conffile.cpp new file mode 100644 index 00000000..daa38551 --- /dev/null +++ b/conffile.cpp @@ -0,0 +1,653 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "conffile.h" + +#ifdef __WIN32__ +#define snprintf _snprintf // needs ANSI compliant name +#endif + +#ifndef MAX +# define MAX(a,b) ((a) > (b)? (a) : (b)) +# define MIN(a,b) ((a) < (b)? (a) : (b)) +#endif + +#define SORT_SECTIONS_BY_SIZE // output + +using namespace std; + +bool ConfigFile::defaultAutoAdd = false; +bool ConfigFile::niceAlignment = false; +bool ConfigFile::showComments = true; +bool ConfigFile::alphaSort = true; +bool ConfigFile::timeSort = false; +static ConfigFile* curConfigFile = NULL; // for section_then_key_less + +ConfigFile::ConfigFile(void) { + Clear(); +} + +void ConfigFile::Clear(void){ + data.clear(); + linectr = 0; +} + +bool ConfigFile::LoadFile(const char *filename){ + STREAM s; + bool ret=false; + const char *n, *n2; + + if((s=OPEN_STREAM(filename, "r"))){ + n=filename; + n2=strrchr(n, '/'); if(n2!=NULL) n=n2+1; + n2=strrchr(n, '\\'); if(n2!=NULL) n=n2+1; + LoadFile(new fReader(s), n); + CLOSE_STREAM(s); + ret = true; + } else { + fprintf(stderr, "Couldn't open conffile "); + perror(filename); + } + return ret; +} + + +void ConfigFile::LoadFile(Reader *r, const char *name){ + curConfigFile = this; + string l, key, val; + string section; + string comment; + int i, line, line2; + bool eof; + + line=line2=0; + section.clear(); + do { + line=line2++; + l=r->getline(eof); + ConfigEntry::trim(l); + if(l.size()==0) continue; + + if(l[0]=='#' || l[0]==';'){ + // comment + continue; + } + + if(l[0]=='['){ + if(*l.rbegin()!=']'){ + if(name) fprintf(stderr, "%s:", name); + fprintf(stderr, "[%d]: Ignoring invalid section header\n", line); + continue; + } + section.assign(l, 1, l.size()-2); + continue; + } + + while(*l.rbegin()=='\\'){ + l.erase(l.size()-1); + line2++; + val=r->getline(eof); + if(eof){ + fprintf(stderr, "Unexpected EOF reading config file"); + if(name) fprintf(stderr, " '%s'", name); + fprintf(stderr, "\n"); + return; + } + ConfigEntry::trim(val); + l+=val; + } + i=l.find('='); + if(i<0){ + if(name) fprintf(stderr, "%s:", name); + fprintf(stderr, "[%d]: Ignoring invalid entry\n", line); + continue; + } + key=l.substr(0,i); ConfigEntry::trim(key); + val=l.substr(i+1); comment = ConfigEntry::trimCommented(val); + if(val[0]=='"' && *val.rbegin()=='"') val=val.substr(1, val.size()-2); + + ConfigEntry e(line, section, key, val); + e.comment = comment; + data.erase(e); + data.insert(e); + } while(!eof); + curConfigFile = NULL; +} + +bool ConfigFile::SaveTo(const char *filename){ + string section; + FILE *fp; + + if((fp=fopen(filename, "w"))==NULL){ + fprintf(stderr, "Couldn't write conffile "); + perror(filename); + return false; + } + + curConfigFile = this; + section.clear(); + set tmp; + fprintf(fp, "# Config file output by snes9x\n"); + time_t t=time(NULL); + fprintf(fp, "# %s", ctime(&t)); + +#ifdef SORT_SECTIONS_BY_SIZE + std::set data2; + for(set::iterator k=data.begin(); k!=data.end(); k++){ + ConfigEntry e (k->line, k->section, k->key, k->val); e.comment = k->comment; + data2.insert(e); + } +#else + #define data2 data + #define section_then_key_less key_less +#endif + + for(set::iterator j=data2.begin(); ; j++){ + if(j==data2.end() || j->section!=section){ + if(!tmp.empty()){ + fprintf(fp, "\n[%s]\n", section.c_str()); + unsigned int maxKeyLen=0, maxValLen=0; int maxLeftDiv=0; int maxRightDiv=-1; + if(niceAlignment){ + for(set::iterator i=tmp.begin(); i!=tmp.end(); i++){ + int len3 = i->key.find_last_of(':'); + maxRightDiv = MAX(maxRightDiv, len3); + len3 = i->key.length() - len3; + maxLeftDiv = MAX(maxLeftDiv, len3); + maxKeyLen = MAX(maxKeyLen, i->key.length()+3); + if(showComments){ + string o=i->val; ConfigEntry::trim(o); + unsigned int len = o.length(); + for(signed int j=len-1;j>=0;j--) if(o.at(j)=='#') len++; + if(o!=i->val) len+=2; + maxValLen = MAX(maxValLen, len); + } + } + if(maxValLen>48) maxValLen=48; // limit spacing + } + + for(set::iterator i=tmp.begin(); i!=tmp.end(); i++){ + string o=i->val; ConfigEntry::trim(o); + if(o!=i->val) o="\""+i->val+"\""; + int off=0, len3=0; + for(;;){ + int k=o.find('#',off); + if(k>=0){ + o.insert(k,1,'#'); // re-double any comment characters + off=k+2; + if(off<(int)o.length()) continue; + } + break; + } + if(niceAlignment){ + len3=i->key.find_last_of(':'); + int len3sub=0; + if(len3 < maxRightDiv){ + for(int j=len3;jkey.length(); + for(unsigned int j=i->key.length()+len3+3;jkey.c_str()); + for(int j=0;jkey.c_str(), o.c_str()); + + if(showComments && !i->comment.empty()){ + if(niceAlignment) for(unsigned int j=o.length();jcomment.c_str()); + } + fprintf(fp, "\n"); + } + } + if(j==data2.end()) break; + section=j->section; + tmp.clear(); + } + tmp.insert(*j); + } + curConfigFile = NULL; + + #undef data2 + #undef section_then_key_less + + if(ferror(fp)) + { + fp = fp; + } + + fclose(fp); + return true; +} + + +/***********************************************/ + +string ConfigFile::Get(const char *key){ + set::iterator i; + i=data.find(ConfigEntry(key)); + i->used=true; + return i->val; +} +bool ConfigFile::Has(const char *key){ + return data.find(ConfigEntry(key))!=data.end(); +} + +// exists and isn't completely empty (any side-effects are intentional) +bool ConfigFile::Exists(const char *key){ + const char* val = GetString(key, NULL); + return val && *val; +} + + +string ConfigFile::GetString(const char *key, string def){ + if(!Exists(key)) + return def; + return Get(key); +} + +char *ConfigFile::GetString(const char *key, char *out, uint32 outlen){ + if(!Exists(key)) return NULL; + ZeroMemory(out, outlen); + string o=Get(key); + if(outlen>0){ + outlen--; + if(o.size()::iterator i; + i=data.find(ConfigEntry(key)); + if(i==data.end()) + { + if(defaultAutoAdd) SetString(key,""); //SetString(key, def?def:""); + return def; + } + i->used=true; + // This should be OK, until this key gets removed + const std::string &iVal = i->val; + return iVal.c_str(); +} + +char *ConfigFile::GetStringDup(const char *key, const char *def){ + const char *c=GetString(key, def); + if(c==NULL) return NULL; + return strdup(c); +} + +bool ConfigFile::SetString(const char *key, string val, const char *comment){ + set::iterator i; + bool ret=false; + + ConfigEntry e(key, val); + if(comment && *comment) e.comment = comment; + e.used=true; + + i=data.find(e); + if(i!=data.end()){ + e.line=i->line; + data.erase(e); + ret=true; + } + if((i==data.end() && (!alphaSort || timeSort)) || (!alphaSort && timeSort)) + e.line = linectr++; + + data.insert(e); + return ret; +} + +int32 ConfigFile::GetInt(const char *key, int32 def, bool *bad){ + if(bad) *bad=false; + if(!Exists(key)) + return def; + char *c; + int32 i; + string o=Get(key); + i=strtol(o.c_str(), &c, 10); + if(c!=NULL && *c!='\0'){ + i=def; + if(bad) *bad=true; + } + return i; +} + +bool ConfigFile::SetInt(const char *key, int32 val, const char *comment){ + char buf[20]; + snprintf(buf, sizeof(buf), "%d", (int)val); + return SetString(key, buf, comment); +} + +uint32 ConfigFile::GetUInt(const char *key, uint32 def, int base, bool *bad){ + if(bad) *bad=false; + if(!Exists(key)) + return def; + if(base!=8 && base!=10 && base!=16) base=0; + char *c; + uint32 i; + string o=Get(key); + i=strtol(o.c_str(), &c, base); + if(c!=NULL && *c!='\0'){ + i=def; + if(bad) *bad=true; + } + return i; +} + +bool ConfigFile::SetUInt(const char *key, uint32 val, int base, const char *comment){ + char buf[20]; + switch(base){ + case 10: + default: + snprintf(buf, sizeof(buf), "%u", (unsigned int)val); + break; + case 8: + snprintf(buf, sizeof(buf), "%#o", (unsigned int)val); + break; + case 16: + snprintf(buf, sizeof(buf), "%#x", (unsigned int)val); + break; + } + return SetString(key, buf, comment); +} + +bool ConfigFile::GetBool(const char *key, bool def, bool *bad){ + if(bad) *bad=false; + if(!Exists(key)) + return def; + string o=Get(key); + const char *c=o.c_str(); + if(!strcasecmp(c, "true") || !strcasecmp(c, "1") || !strcasecmp(c, "yes") || !strcasecmp(c, "on")) return true; + if(!strcasecmp(c, "false") || !strcasecmp(c, "0") || !strcasecmp(c, "no") || !strcasecmp(c, "off")) return false; + if(bad) *bad=true; + return def; +} + +bool ConfigFile::SetBool(const char *key, bool val, const char *true_val, const char *false_val, const char *comment){ + return SetString(key, val?true_val:false_val, comment); +} + +const char* ConfigFile::GetComment(const char *key) +{ + set::iterator i; + i=data.find(ConfigEntry(key)); + if(i==data.end()) + return NULL; + + // This should be OK, until this key gets removed + const std::string &iCom = i->comment; + return iCom.c_str(); +} + +bool ConfigFile::DeleteKey(const char *key){ + return (data.erase(ConfigEntry(key))>0); +} + +/***********************************************/ + +bool ConfigFile::DeleteSection(const char *section){ + set::iterator s, e; + + for(s=data.begin(); s!=data.end() && s->section!=section; s++) ; + if(s==data.end()) return false; + for(e=s; e!=data.end() && e->section==section; e++) ; + data.erase(s, e); + return true; +} + +ConfigFile::secvec_t ConfigFile::GetSection(const char *section){ + secvec_t v; + set::iterator i; + + v.clear(); + for(i=data.begin(); i!=data.end(); i++){ + if(i->section!=section) continue; + v.push_back(std::pair(i->key, i->val)); + } + return v; +} + +int ConfigFile::GetSectionSize(const char *section){ + int count=0; + const unsigned int seclen=strlen(section); + set::iterator i; + for(i=data.begin(); i!=data.end(); i++) + if(i->section==section || !strncasecmp(section,i->section.c_str(),MIN(seclen,i->section.size()))) count++; + return count; +} + +// Clears all key-value pairs that didn't receive a "Get" or "Exists" command +void ConfigFile::ClearUnused() +{ + set::iterator i; +again: + for(i=data.begin(); i!=data.end(); i++){ + if(!i->used){ + data.erase(i); + goto again; + } + } +} + +void ConfigFile::ClearLines() +{ + set::iterator i; + for(i=data.begin(); i!=data.end(); i++){ + *(const_cast(&i->line)) = -1; + } +} + +bool ConfigFile::ConfigEntry::section_then_key_less::operator()(const ConfigEntry &a, const ConfigEntry &b) { + if(curConfigFile && a.section!=b.section){ + const int sva = curConfigFile->GetSectionSize(a.section.c_str()); + const int svb = curConfigFile->GetSectionSize(b.section.c_str()); + if(svasvb) return false; + return a.section +#include +#include + +#ifdef UNZIP_SUPPORT +#include "unzip/unzip.h" +#endif +#include "snes9x.h" +#include "reader.h" + +class ConfigFile { + public: + ConfigFile(void); + + void Clear(void); + + // return false on failure + bool LoadFile(const char *filename); + void LoadFile(Reader *r, const char *name=NULL); + + // return false if key does not exist or is empty + bool Exists(const char *key); + + // return the value / default + std::string GetString(const char *key, std::string def); + char *GetString(const char *key, char *out, uint32 outlen); // return NULL if it doesn't exist, out not affected + const char *GetString(const char *key, const char *def=NULL); // NOTE: returned pointer becomes invalid when key is deleted/modified, or the ConfigFile is Clear()ed or deleted. + char *GetStringDup(const char *key, const char *def=NULL); // Much like "strdup(GetString(key, def))" + int32 GetInt(const char *key, int32 def=-1, bool *bad=NULL); + uint32 GetUInt(const char *key, uint32 def=0, int base=0, bool *bad=NULL); // base = 0, 8, 10, or 16 + bool GetBool(const char *key, bool def=false, bool *bad=NULL); + const char* GetComment(const char *key); // NOTE: returned pointer becomes invalid when key is deleted/modified, or the ConfigFile is Clear()ed or deleted. + + // return true if the key existed prior to setting + bool SetString(const char *key, std::string val, const char *comment=""); + bool SetInt(const char *key, int32 val, const char *comment=""); + bool SetUInt(const char *key, uint32 val, int base=10, const char *comment=""); // base = 8, 10, or 16 + bool SetBool(const char *key, bool val, const char *true_val="TRUE", const char *false_val="FALSE", const char *comment=""); + bool DeleteKey(const char *key); + + // Operation on entire sections + bool DeleteSection(const char *section); + typedef std::vector > secvec_t; + secvec_t GetSection(const char *section); + int GetSectionSize(const char *section); + + // Clears all key-value pairs that didn't receive a Set command, or a Get command with autoAdd on + void ClearUnused(void); + + // Clears all stored line numbers + void ClearLines(void); + + bool SaveTo(const char *filename); + + static void SetDefaultAutoAdd(bool autoAdd); + static void SetNiceAlignment(bool align); + static void SetShowComments(bool show); + static void SetAlphaSort(bool sort); + static void SetTimeSort(bool sort); + + private: + std::string Get(const char *key); + bool Has(const char *key); + + class ConfigEntry { + protected: + int line; + std::string section; + std::string key; + std::string val; + std::string comment; + mutable bool used; + + struct section_then_key_less { + bool operator()(const ConfigEntry &a, const ConfigEntry &b); + }; + + struct key_less { + bool operator()(const ConfigEntry &a, const ConfigEntry &b) const{ + if(a.section!=b.section) return a.section0) s.erase(0, i); // erase leading whitespace + i=s.find_last_not_of(" \f\n\r\t\v"); + if(i!=-1) s.erase(i+1); // erase trailing whitespace + return; + } + + // trims comments and leading/trailing whitespace from s, and returns any trimmed comments + // make sure not to call this more than once on the same string + static std::string trimCommented(std::string &s){ + std::string cmt; + int i; + i=s.find_first_not_of(" \f\n\r\t\v"); + if(i==-1){ + s.clear(); + return cmt; + } + if(i>0) s.erase(0, i); // erase leading whitespace + int off=0; + for(;;){ + i=s.find('#',off); // find trailing comment + if(i>=0) + { + if((int)s.length()>i+1 && s.at(i+1) == '#') { + s.erase(i,1); // ignore ## and change to # + off = i+1; + continue; + } else { + int j=s.find_first_not_of(" \f\n\r\t\v",i+1); + if(j!=-1) cmt = s.substr(j); // store + s.erase(i); // erase trailing comment + } + } + break; + } + i=s.find_last_not_of(" \f\n\r\t\v"); + if(i!=-1) s.erase(i+1); // erase trailing whitespace + return cmt; + } + + public: + ConfigEntry(int l, const std::string &s, const std::string &k, const std::string &v) : + line(l), section(s), key(k), val(v) { + trim(section); + trim(key); + used=false; + } + + void parse_key(const std::string &k){ + int i=k.find("::"); + if(i==-1){ + section="Uncategorized"; key=k; + } else { + section=k.substr(0,i); key=k.substr(i+2); + } + trim(section); + trim(key); + used=false; + } + + ConfigEntry(const std::string k){ + parse_key(k); + } + + ConfigEntry(const std::string k, const std::string &v) : line(-1), val(v) { + parse_key(k); + } + + friend class ConfigFile; + friend struct key_less; + friend struct line_less; + }; + std::set data; + int linectr; + static bool defaultAutoAdd; + static bool niceAlignment; + static bool showComments; + static bool alphaSort; + static bool timeSort; +}; + +/* Config file format: + * + * Comments are any lines whose first non-whitespace character is ';' or '#'. + * Note that comments can also follow a value, on the same line. + * To intentionally have a '#' character in the value, use ## + * + * All parameters fall into sections. To name a section, the first + * non-whitespace character on the line will be '[', and the last will be ']'. + * + * Parameters are simple key=value pairs. Whitespace around the '=', and at the + * beginning or end of the line is ignored. Key names may not contain '=' nor + * begin with '[', however values can. If the last character of the value is + * '\', the next line (sans leading/trailing whitespace) is considered part of + * the value as well. Programmatically, the key "K" in section "S" is referred + * to as "S::K", much like C++ namespaces. For example: + * [Section1] + * # this is a comment + * foo = bar \ + * baz\ + * quux \ + * ## this is not a comment! # this IS a comment + * means the value of "Section1::foo" is "bar bazquux # this is not a comment!" + * + * Parameters may be of several types: + * String - Bare characters. If the first and last characters are both '"', + * they are removed (so just double them if you really want quotes + * there) + * Int - A decimal number from -2147483648 to 2147483647 + * UInt - A number in decimal, hex, or octal from 0 to 4294967295 (or + * 0xffffffff, or 037777777777) + * Bool - true/false, 0/1, on/off, yes/no + * + * Of course, the actual accepted values for a parameter may be further + * restricted ;) + */ + + +/* You must write this for your port */ +void S9xParsePortConfig(ConfigFile &, int pass); + +/* This may or may not be useful to you */ +const char *S9xParseDisplayConfig(ConfigFile &, int pass); + +#endif diff --git a/controls.cpp b/controls.cpp new file mode 100644 index 00000000..b34bf95b --- /dev/null +++ b/controls.cpp @@ -0,0 +1,3697 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 + +#include "snes9x.h" +#include "memmap.h" +#include "apu/apu.h" +#include "snapshot.h" +#include "controls.h" +#include "crosshairs.h" +#include "movie.h" +#include "display.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif + +using namespace std; + +#define NONE (-2) +#define MP5 (-1) +#define JOYPAD0 0 +#define JOYPAD1 1 +#define JOYPAD2 2 +#define JOYPAD3 3 +#define JOYPAD4 4 +#define JOYPAD5 5 +#define JOYPAD6 6 +#define JOYPAD7 7 +#define MOUSE0 8 +#define MOUSE1 9 +#define SUPERSCOPE 10 +#define ONE_JUSTIFIER 11 +#define TWO_JUSTIFIERS 12 +#define NUMCTLS 13 // This must be LAST + +#define POLL_ALL NUMCTLS + +#define SUPERSCOPE_FIRE 0x80 +#define SUPERSCOPE_CURSOR 0x40 +#define SUPERSCOPE_TURBO 0x20 +#define SUPERSCOPE_PAUSE 0x10 +#define SUPERSCOPE_OFFSCREEN 0x02 + +#define JUSTIFIER_TRIGGER 0x80 +#define JUSTIFIER_START 0x20 +#define JUSTIFIER_SELECT 0x08 + +#define MAP_UNKNOWN (-1) +#define MAP_NONE 0 +#define MAP_BUTTON 1 +#define MAP_AXIS 2 +#define MAP_POINTER 3 + +#define FLAG_IOBIT0 (Memory.FillRAM[0x4213] & 0x40) +#define FLAG_IOBIT1 (Memory.FillRAM[0x4213] & 0x80) +#define FLAG_IOBIT(n) ((n) ? (FLAG_IOBIT1) : (FLAG_IOBIT0)) + +bool8 pad_read = 0, pad_read_last = 0; +uint8 read_idx[2 /* ports */][2 /* per port */]; + +struct exemulti +{ + int32 pos; + bool8 data1; + s9xcommand_t *script; +}; + +struct crosshair +{ + uint8 set; + uint8 img; + uint8 fg, bg; +}; + +static struct +{ + int16 x, y; + int16 V_adj; + bool8 V_var; + int16 H_adj; + bool8 H_var; + bool8 mapped; +} pseudopointer[8]; + +static struct +{ + uint16 buttons; + uint16 turbos; + uint16 toggleturbo; + uint16 togglestick; + uint8 turbo_ct; +} joypad[8]; + +static struct +{ + uint8 delta_x, delta_y; + int16 old_x, old_y; + int16 cur_x, cur_y; + uint8 buttons; + uint32 ID; + struct crosshair crosshair; +} mouse[2]; + +static struct +{ + int16 x, y; + uint8 phys_buttons; + uint8 next_buttons; + uint8 read_buttons; + uint32 ID; + struct crosshair crosshair; +} superscope; + +static struct +{ + int16 x[2], y[2]; + uint8 buttons; + bool8 offscreen[2]; + uint32 ID[2]; + struct crosshair crosshair[2]; +} justifier; + +static struct +{ + int8 pads[4]; +} mp5[2]; + +static set exemultis; +static set pollmap[NUMCTLS + 1]; +static map keymap; +static vector multis; +static uint8 turbo_time; +static uint8 pseudobuttons[256]; +static bool8 FLAG_LATCH = FALSE; +static int32 curcontrollers[2] = { NONE, NONE }; +static int32 newcontrollers[2] = { JOYPAD0, NONE }; +static char buf[256]; + +static const char *color_names[32] = +{ + "Trans", + "Black", + "25Grey", + "50Grey", + "75Grey", + "White", + "Red", + "Orange", + "Yellow", + "Green", + "Cyan", + "Sky", + "Blue", + "Violet", + "MagicPink", + "Purple", + NULL, + "tBlack", + "t25Grey", + "t50Grey", + "t75Grey", + "tWhite", + "tRed", + "tOrange", + "tYellow", + "tGreen", + "tCyan", + "tSky", + "tBlue", + "tViolet", + "tMagicPink", + "tPurple" +}; + +static const char *speed_names[4] = +{ + "Var", + "Slow", + "Med", + "Fast" +}; + +static const int ptrspeeds[4] = { 1, 1, 4, 8 }; + +// Note: these should be in asciibetical order! +#define THE_COMMANDS \ + S(BeginRecordingMovie), \ + S(ClipWindows), \ + S(Debugger), \ + S(DecEmuTurbo), \ + S(DecFrameRate), \ + S(DecFrameTime), \ + S(DecTurboSpeed), \ + S(EmuTurbo), \ + S(EndRecordingMovie), \ + S(ExitEmu), \ + S(IncEmuTurbo), \ + S(IncFrameRate), \ + S(IncFrameTime), \ + S(IncTurboSpeed), \ + S(LoadFreezeFile), \ + S(LoadMovie), \ + S(LoadOopsFile), \ + S(Pause), \ + S(QuickLoad000), \ + S(QuickLoad001), \ + S(QuickLoad002), \ + S(QuickLoad003), \ + S(QuickLoad004), \ + S(QuickLoad005), \ + S(QuickLoad006), \ + S(QuickLoad007), \ + S(QuickLoad008), \ + S(QuickLoad009), \ + S(QuickLoad010), \ + S(QuickSave000), \ + S(QuickSave001), \ + S(QuickSave002), \ + S(QuickSave003), \ + S(QuickSave004), \ + S(QuickSave005), \ + S(QuickSave006), \ + S(QuickSave007), \ + S(QuickSave008), \ + S(QuickSave009), \ + S(QuickSave010), \ + S(Reset), \ + S(SaveFreezeFile), \ + S(SaveSPC), \ + S(Screenshot), \ + S(SeekToFrame), \ + S(SoftReset), \ + S(SoundChannel0), \ + S(SoundChannel1), \ + S(SoundChannel2), \ + S(SoundChannel3), \ + S(SoundChannel4), \ + S(SoundChannel5), \ + S(SoundChannel6), \ + S(SoundChannel7), \ + S(SoundChannelsOn), \ + S(SwapJoypads), \ + S(ToggleBG0), \ + S(ToggleBG1), \ + S(ToggleBG2), \ + S(ToggleBG3), \ + S(ToggleEmuTurbo), \ + S(ToggleHDMA), \ + S(ToggleSprites), \ + S(ToggleTransparency) \ + +#define S(x) x + +enum command_numbers +{ + THE_COMMANDS, + LAST_COMMAND +}; + +#undef S +#define S(x) #x + +static const char *command_names[LAST_COMMAND + 1] = +{ + THE_COMMANDS, + NULL +}; + +#undef S +#undef THE_COMMANDS + +static void DisplayStateChange (const char *, bool8); +static void DoGunLatch (int, int); +static int maptype (int); +static bool strless (const char *, const char *); +static int findstr (const char *, const char **, int); +static int get_threshold (const char **); +static const char * maptypename (int); +static int32 ApplyMulti (s9xcommand_t *, int32, int16); +static void do_polling (int); +static void UpdatePolledMouse (int); + + +static string& operator += (string &s, int i) +{ + snprintf(buf, sizeof(buf), "%d", i); + s.append(buf); + return (s); +} + +static string& operator += (string &s, double d) +{ + snprintf(buf, sizeof(buf), "%g", d); + s.append(buf); + return (s); +} + +static void DisplayStateChange (const char *str, bool8 on) +{ + snprintf(buf, sizeof(buf), "%s: %s", str, on ? "on":"off"); + S9xSetInfoString(buf); +} + +static void DoGunLatch (int x, int y) +{ + x += 40; + + if (x > 295) + x = 295; + else + if (x < 40) + x = 40; + + if (y > PPU.ScreenHeight - 1) + y = PPU.ScreenHeight - 1; + else + if (y < 0) + y = 0; + + PPU.GunVLatch = (uint16) (y + 1); + PPU.GunHLatch = (uint16) x; +} + +static int maptype (int t) +{ + switch (t) + { + case S9xNoMapping: + return (MAP_NONE); + + case S9xButtonJoypad: + case S9xButtonMouse: + case S9xButtonSuperscope: + case S9xButtonJustifier: + case S9xButtonCommand: + case S9xButtonPseudopointer: + case S9xButtonPort: + case S9xButtonMulti: + return (MAP_BUTTON); + + case S9xAxisJoypad: + case S9xAxisPseudopointer: + case S9xAxisPseudobuttons: + case S9xAxisPort: + return (MAP_AXIS); + + case S9xPointer: + case S9xPointerPort: + return (MAP_POINTER); + + default: + return (MAP_UNKNOWN); + } +} + +void S9xControlsReset (void) +{ + S9xControlsSoftReset(); + mouse[0].buttons &= ~0x30; + mouse[1].buttons &= ~0x30; + justifier.buttons &= ~JUSTIFIER_SELECT; +} + +void S9xControlsSoftReset (void) +{ + for (set::iterator it = exemultis.begin(); it != exemultis.end(); it++) + delete *it; + exemultis.clear(); + + for (int i = 0; i < 2; i++) + for (int j = 0; j < 2; j++) + read_idx[i][j]=0; + + FLAG_LATCH = FALSE; +} + +void S9xUnmapAllControls (void) +{ + S9xControlsReset(); + + keymap.clear(); + + for (int i = 0; i < (int) multis.size(); i++) + free(multis[i]); + multis.clear(); + + for (int i = 0; i < NUMCTLS + 1; i++) + pollmap[i].clear(); + + for (int i = 0; i < 8; i++) + { + pseudopointer[i].x = 0; + pseudopointer[i].y = 0; + pseudopointer[i].H_adj = 0; + pseudopointer[i].V_adj = 0; + pseudopointer[i].H_var = 0; + pseudopointer[i].V_var = 0; + pseudopointer[i].mapped = false; + + joypad[i].buttons = 0; + joypad[i].turbos = 0; + joypad[i].turbo_ct = 0; + } + + for (int i = 0; i < 2; i++) + { + mouse[i].old_x = mouse[i].old_y = 0; + mouse[i].cur_x = mouse[i].cur_y = 0; + mouse[i].buttons = 1; + mouse[i].ID = InvalidControlID; + + if (!(mouse[i].crosshair.set & 1)) + mouse[i].crosshair.img = 0; // no image for mouse because its only logical position is game-specific, not known by the emulator + if (!(mouse[i].crosshair.set & 2)) + mouse[i].crosshair.fg = 5; + if (!(mouse[i].crosshair.set & 4)) + mouse[i].crosshair.bg = 1; + + justifier.x[i] = justifier.y[i] = 0; + justifier.offscreen[i] = 0; + justifier.ID[i] = InvalidControlID; + + if (!(justifier.crosshair[i].set & 1)) + justifier.crosshair[i].img = 4; + if (!(justifier.crosshair[i].set & 2)) + justifier.crosshair[i].fg = i ? 14 : 12; + if (!(justifier.crosshair[i].set & 4)) + justifier.crosshair[i].bg = 1; + } + + justifier.buttons = 0; + + superscope.x = superscope.y = 0; + superscope.phys_buttons = 0; + superscope.next_buttons = 0; + superscope.read_buttons = 0; + superscope.ID = InvalidControlID; + + if (!(superscope.crosshair.set & 1)) + superscope.crosshair.img = 2; + if (!(superscope.crosshair.set & 2)) + superscope.crosshair.fg = 5; + if (!(superscope.crosshair.set & 4)) + superscope.crosshair.bg = 1; + + ZeroMemory(pseudobuttons, sizeof(pseudobuttons)); + + turbo_time = 1; +} + +void S9xSetController (int port, enum controllers controller, int8 id1, int8 id2, int8 id3, int8 id4) +{ + if (port < 0 || port > 1) + return; + + switch (controller) + { + case CTL_NONE: + break; + + case CTL_JOYPAD: + if (id1 < 0 || id1 > 7) + break; + + newcontrollers[port] = JOYPAD0 + id1; + return; + + case CTL_MOUSE: + if (id1 < 0 || id1 > 1) + break; + if (!Settings.MouseMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Mouse: MouseMaster disabled"); + break; + } + + newcontrollers[port] = MOUSE0 + id1; + return; + + case CTL_SUPERSCOPE: + if (!Settings.SuperScopeMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Superscope: SuperScopeMaster disabled"); + break; + } + + newcontrollers[port] = SUPERSCOPE; + return; + + case CTL_JUSTIFIER: + if (id1 < 0 || id1 > 1) + break; + if (!Settings.JustifierMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select Konami Justifier: JustifierMaster disabled"); + break; + } + + newcontrollers[port] = ONE_JUSTIFIER + id1; + return; + + case CTL_MP5: + if (id1 < -1 || id1 > 7) + break; + if (id2 < -1 || id2 > 7) + break; + if (id3 < -1 || id3 > 7) + break; + if (id4 < -1 || id4 > 7) + break; + if (!Settings.MultiPlayer5Master) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select MP5: MultiPlayer5Master disabled"); + break; + } + + newcontrollers[port] = MP5; + mp5[port].pads[0] = (id1 < 0) ? NONE : JOYPAD0 + id1; + mp5[port].pads[1] = (id2 < 0) ? NONE : JOYPAD0 + id2; + mp5[port].pads[2] = (id3 < 0) ? NONE : JOYPAD0 + id3; + mp5[port].pads[3] = (id4 < 0) ? NONE : JOYPAD0 + id4; + return; + + default: + fprintf(stderr, "Unknown controller type %d\n", controller); + break; + } + + newcontrollers[port] = NONE; +} + +bool S9xVerifyControllers (void) +{ + bool ret = false; + int port, i, used[NUMCTLS]; + + for (i = 0; i < NUMCTLS; used[i++] = 0) ; + + for (port = 0; port < 2; port++) + { + switch (i = newcontrollers[port]) + { + case MOUSE0: + case MOUSE1: + if (!Settings.MouseMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Mouse: MouseMaster disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } + + if (used[i]++ > 0) + { + snprintf(buf, sizeof(buf), "Mouse%d used more than once! Disabling extra instances", i - MOUSE0 + 1); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port] = NONE; + ret = true; + break; + } + + break; + + case SUPERSCOPE: + if (!Settings.SuperScopeMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select SNES Superscope: SuperScopeMaster disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } + + if (used[i]++ > 0) + { + snprintf(buf, sizeof(buf), "Superscope used more than once! Disabling extra instances"); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port] = NONE; + ret = true; + break; + } + + break; + + case ONE_JUSTIFIER: + case TWO_JUSTIFIERS: + if (!Settings.JustifierMaster) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select Konami Justifier: JustifierMaster disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } + + if (used[ONE_JUSTIFIER]++ > 0) + { + snprintf(buf, sizeof(buf), "Justifier used more than once! Disabling extra instances"); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port] = NONE; + ret = true; + break; + } + + break; + + case MP5: + if (!Settings.MultiPlayer5Master) + { + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, "Cannot select MP5: MultiPlayer5Master disabled"); + newcontrollers[port] = NONE; + ret = true; + break; + } + + for (i = 0; i < 4; i++) + { + if (mp5[port].pads[i] != NONE) + { + if (used[mp5[port].pads[i] - JOYPAD0]++ > 0) + { + snprintf(buf, sizeof(buf), "Joypad%d used more than once! Disabling extra instances", mp5[port].pads[i] - JOYPAD0 + 1); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + mp5[port].pads[i] = NONE; + ret = true; + break; + } + } + } + + break; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + if (used[i - JOYPAD0]++ > 0) + { + snprintf(buf, sizeof(buf), "Joypad%d used more than once! Disabling extra instances", i - JOYPAD0 + 1); + S9xMessage(S9X_CONFIG_INFO, S9X_ERROR, buf); + newcontrollers[port] = NONE; + ret = true; + break; + } + + break; + + default: + break; + } + } + + return (ret); +} + +void S9xGetController (int port, enum controllers *controller, int8 *id1, int8 *id2, int8 *id3, int8 *id4) +{ + int i; + + *controller = CTL_NONE; + *id1 = *id2 = *id3 = *id4 = -1; + + if (port < 0 || port > 1) + return; + + switch (i = newcontrollers[port]) + { + case MP5: + *controller = CTL_MP5; + *id1 = (mp5[port].pads[0] == NONE) ? -1 : mp5[port].pads[0] - JOYPAD0; + *id2 = (mp5[port].pads[1] == NONE) ? -1 : mp5[port].pads[1] - JOYPAD0; + *id3 = (mp5[port].pads[2] == NONE) ? -1 : mp5[port].pads[2] - JOYPAD0; + *id4 = (mp5[port].pads[3] == NONE) ? -1 : mp5[port].pads[3] - JOYPAD0; + return; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + *controller = CTL_JOYPAD; + *id1 = i - JOYPAD0; + return; + + case MOUSE0: + case MOUSE1: + *controller = CTL_MOUSE; + *id1 = i - MOUSE0; + return; + + case SUPERSCOPE: + *controller = CTL_SUPERSCOPE; + *id1 = 1; + return; + + case ONE_JUSTIFIER: + case TWO_JUSTIFIERS: + *controller = CTL_JUSTIFIER; + *id1 = i - ONE_JUSTIFIER; + return; + } +} + +void S9xReportControllers (void) +{ + static char mes[128]; + char *c = mes; + + S9xVerifyControllers(); + + for (int port = 0; port < 2; port++) + { + c += sprintf(c, "Port %d: ", port + 1); + + switch (newcontrollers[port]) + { + case NONE: + c += sprintf(c, ". "); + break; + + case MP5: + c += sprintf(c, "MP5 with pads"); + for (int i = 0; i < 4; i++) + { + if (mp5[port].pads[i] == NONE) + c += sprintf(c, " . "); + else + c += sprintf(c, " #%d. ", mp5[port].pads[i] + 1 - JOYPAD0); + } + + break; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + c += sprintf(c, "Pad #%d. ", (int) (newcontrollers[port] - JOYPAD0 + 1)); + break; + + case MOUSE0: + case MOUSE1: + c += sprintf(c, "Mouse #%d. ", (int) (newcontrollers[port] - MOUSE0 + 1)); + break; + + case SUPERSCOPE: + if (port == 0) + c += sprintf(c, "Superscope (cannot fire). "); + else + c += sprintf(c, "Superscope. "); + break; + + case ONE_JUSTIFIER: + if (port == 0) + c += sprintf(c, "Blue Justifier (cannot fire). "); + else + c += sprintf(c, "Blue Justifier. "); + break; + + case TWO_JUSTIFIERS: + if (port == 0) + c += sprintf(c, "Blue and Pink Justifiers (cannot fire). "); + else + c += sprintf(c, "Blue and Pink Justifiers. "); + break; + } + } + + S9xMessage(S9X_INFO, S9X_CONFIG_INFO, mes); +} + +char * S9xGetCommandName (s9xcommand_t command) +{ + string s; + char c; + + switch (command.type) + { + case S9xButtonJoypad: + if (command.button.joypad.buttons == 0) + return (strdup("None")); + if (command.button.joypad.buttons & 0x000f) + return (strdup("None")); + + s = "Joypad"; + s += command.button.joypad.idx + 1; + + c = ' '; + if (command.button.joypad.toggle) { if (c) s += c; s += "Toggle"; c = 0; } + if (command.button.joypad.sticky) { if (c) s += c; s += "Sticky"; c = 0; } + if (command.button.joypad.turbo ) { if (c) s += c; s += "Turbo"; c = 0; } + + c = ' '; + if (command.button.joypad.buttons & SNES_UP_MASK ) { s += c; s += "Up"; c = '+'; } + if (command.button.joypad.buttons & SNES_DOWN_MASK ) { s += c; s += "Down"; c = '+'; } + if (command.button.joypad.buttons & SNES_LEFT_MASK ) { s += c; s += "Left"; c = '+'; } + if (command.button.joypad.buttons & SNES_RIGHT_MASK ) { s += c; s += "Right"; c = '+'; } + if (command.button.joypad.buttons & SNES_A_MASK ) { s += c; s += "A"; c = '+'; } + if (command.button.joypad.buttons & SNES_B_MASK ) { s += c; s += "B"; c = '+'; } + if (command.button.joypad.buttons & SNES_X_MASK ) { s += c; s += "X"; c = '+'; } + if (command.button.joypad.buttons & SNES_Y_MASK ) { s += c; s += "Y"; c = '+'; } + if (command.button.joypad.buttons & SNES_TL_MASK ) { s += c; s += "L"; c = '+'; } + if (command.button.joypad.buttons & SNES_TR_MASK ) { s += c; s += "R"; c = '+'; } + if (command.button.joypad.buttons & SNES_START_MASK ) { s += c; s += "Start"; c = '+'; } + if (command.button.joypad.buttons & SNES_SELECT_MASK) { s += c; s += "Select"; c = '+'; } + + break; + + case S9xButtonMouse: + if (!command.button.mouse.left && !command.button.mouse.right) + return (strdup("None")); + + s = "Mouse"; + s += command.button.mouse.idx + 1; + s += " "; + + if (command.button.mouse.left ) s += "L"; + if (command.button.mouse.right) s += "R"; + + break; + + case S9xButtonSuperscope: + if (!command.button.scope.fire && !command.button.scope.cursor && !command.button.scope.turbo && !command.button.scope.pause && !command.button.scope.aim_offscreen) + return (strdup("None")); + + s = "Superscope"; + + if (command.button.scope.aim_offscreen) s += " AimOffscreen"; + + c = ' '; + if (command.button.scope.fire ) { s += c; s += "Fire"; c = '+'; } + if (command.button.scope.cursor) { s += c; s += "Cursor"; c = '+'; } + if (command.button.scope.turbo ) { s += c; s += "ToggleTurbo"; c = '+'; } + if (command.button.scope.pause ) { s += c; s += "Pause"; c = '+'; } + + break; + + case S9xButtonJustifier: + if (!command.button.justifier.trigger && !command.button.justifier.start && !command.button.justifier.aim_offscreen) + return (strdup("None")); + + s = "Justifier"; + s += command.button.justifier.idx + 1; + + if (command.button.justifier.aim_offscreen) s += " AimOffscreen"; + + c = ' '; + if (command.button.justifier.trigger) { s += c; s += "Trigger"; c = '+'; } + if (command.button.justifier.start ) { s += c; s += "Start"; c = '+'; } + + break; + + case S9xButtonCommand: + if (command.button.command >= LAST_COMMAND) + return (strdup("None")); + + return (strdup(command_names[command.button.command])); + + case S9xPointer: + if (!command.pointer.aim_mouse0 && !command.pointer.aim_mouse1 && !command.pointer.aim_scope && !command.pointer.aim_justifier0 && !command.pointer.aim_justifier1) + return (strdup("None")); + + s = "Pointer"; + + c = ' '; + if (command.pointer.aim_mouse0 ) { s += c; s += "Mouse1"; c = '+'; } + if (command.pointer.aim_mouse1 ) { s += c; s += "Mouse2"; c = '+'; } + if (command.pointer.aim_scope ) { s += c; s += "Superscope"; c = '+'; } + if (command.pointer.aim_justifier0) { s += c; s += "Justifier1"; c = '+'; } + if (command.pointer.aim_justifier1) { s += c; s += "Justifier2"; c = '+'; } + + break; + + case S9xButtonPseudopointer: + if (!command.button.pointer.UD && !command.button.pointer.LR) + return (strdup("None")); + if (command.button.pointer.UD == -2 || command.button.pointer.LR == -2) + return (strdup("None")); + + s = "ButtonToPointer "; + s += command.button.pointer.idx + 1; + + if (command.button.pointer.UD) s += (command.button.pointer.UD == 1) ? 'd' : 'u'; + if (command.button.pointer.LR) s += (command.button.pointer.LR == 1) ? 'r' : 'l'; + + s += " "; + s += speed_names[command.button.pointer.speed_type]; + + break; + + case S9xAxisJoypad: + s = "Joypad"; + s += command.axis.joypad.idx + 1; + s += " Axis "; + + switch (command.axis.joypad.axis) + { + case 0: s += (command.axis.joypad.invert ? "Right/Left" : "Left/Right"); break; + case 1: s += (command.axis.joypad.invert ? "Down/Up" : "Up/Down" ); break; + case 2: s += (command.axis.joypad.invert ? "A/Y" : "Y/A" ); break; + case 3: s += (command.axis.joypad.invert ? "B/X" : "X/B" ); break; + case 4: s += (command.axis.joypad.invert ? "R/L" : "L/R" ); break; + default: return (strdup("None")); + } + + s += " T="; + s += int((command.axis.joypad.threshold + 1) * 1000 / 256) / 10.0; + s += "%"; + + break; + + case S9xAxisPseudopointer: + s = "AxisToPointer "; + s += command.axis.pointer.idx + 1; + s += command.axis.pointer.HV ? 'v' : 'h'; + s += " "; + + if (command.axis.pointer.invert) s += "-"; + + s += speed_names[command.axis.pointer.speed_type]; + + break; + + case S9xAxisPseudobuttons: + s = "AxisToButtons "; + s += command.axis.button.negbutton; + s += "/"; + s += command.axis.button.posbutton; + s += " T="; + s += int((command.axis.button.threshold + 1) * 1000 / 256) / 10.0; + s += "%"; + + break; + + case S9xButtonPort: + case S9xAxisPort: + case S9xPointerPort: + return (strdup("BUG: Port should have handled this instead of calling S9xGetCommandName()")); + + case S9xNoMapping: + return (strdup("None")); + + case S9xButtonMulti: + { + if (command.button.multi_idx >= (int) multis.size()) + return (strdup("None")); + + s = "{"; + if (multis[command.button.multi_idx]->multi_press) s = "+{"; + + bool sep = false; + + for (s9xcommand_t *m = multis[command.button.multi_idx]; m->multi_press != 3; m++) + { + if (m->type == S9xNoMapping) + { + s += ";"; + sep = false; + } + else + { + if (sep) s += ","; + if (m->multi_press == 1) s += "+"; + if (m->multi_press == 2) s += "-"; + + s += S9xGetCommandName(*m); + sep = true; + } + } + + s += "}"; + + break; + } + + default: + return (strdup("BUG: Unknown command type")); + } + + return (strdup(s.c_str())); +} + +static bool strless (const char *a, const char *b) +{ + return (strcmp(a, b) < 0); +} + +static int findstr (const char *needle, const char **haystack, int numstr) +{ + const char **r; + + r = lower_bound(haystack, haystack + numstr, needle, strless); + if (r >= haystack + numstr || strcmp(needle, *r)) + return (-1); + + return (r - haystack); +} + +static int get_threshold (const char **ss) +{ + const char *s = *ss; + int i; + + if (s[0] != 'T' || s[1] != '=') + return (-1); + + s += 2; + i = 0; + + if (s[0] == '0') + { + if (s[1] != '.') + return (-1); + + s++; + } + else + { + do + { + if (*s < '0' || *s > '9') + return (-1); + + i = i * 10 + 10 * (*s - '0'); + if (i > 1000) + return (-1); + + s++; + } + while (*s != '.' && *s != '%'); + } + + if (*s == '.') + { + if (s[1] < '0' || s[1] > '9' || s[2] != '%') + return (-1); + + i += s[1] - '0'; + } + + if (i > 1000) + return (-1); + + *ss = s; + + return (i); +} + +s9xcommand_t S9xGetCommandT (const char *name) +{ + s9xcommand_t cmd; + int i, j; + const char *s; + + ZeroMemory(&cmd, sizeof(cmd)); + cmd.type = S9xBadMapping; + cmd.multi_press = 0; + cmd.button_norpt = 0; + + if (!strcmp(name, "None")) + cmd.type = S9xNoMapping; + else + if (!strncmp(name, "Joypad", 6)) + { + if (name[6] < '1' || name[6] > '8' || name[7] != ' ') + return (cmd); + + if (!strncmp(name + 8, "Axis ", 5)) + { + cmd.axis.joypad.idx = name[6] - '1'; + s = name + 13; + + if (!strncmp(s, "Left/Right ", 11)) { j = 0; i = 0; s += 11; } + else + if (!strncmp(s, "Right/Left ", 11)) { j = 0; i = 1; s += 11; } + else + if (!strncmp(s, "Up/Down ", 8)) { j = 1; i = 0; s += 8; } + else + if (!strncmp(s, "Down/Up ", 8)) { j = 1; i = 1; s += 8; } + else + if (!strncmp(s, "Y/A ", 4)) { j = 2; i = 0; s += 4; } + else + if (!strncmp(s, "A/Y ", 4)) { j = 2; i = 1; s += 4; } + else + if (!strncmp(s, "X/B ", 4)) { j = 3; i = 0; s += 4; } + else + if (!strncmp(s, "B/X ", 4)) { j = 3; i = 1; s += 4; } + else + if (!strncmp(s, "L/R ", 4)) { j = 4; i = 0; s += 4; } + else + if (!strncmp(s, "R/L ", 4)) { j = 4; i = 1; s += 4; } + else + return (cmd); + + cmd.axis.joypad.axis = j; + cmd.axis.joypad.invert = i; + i = get_threshold(&s); + if (i < 0) + return (cmd); + cmd.axis.joypad.threshold = (i - 1) * 256 / 1000; + + cmd.type = S9xAxisJoypad; + } + else + { + cmd.button.joypad.idx = name[6] - '1'; + s = name + 8; + i = 0; + + if ((cmd.button.joypad.toggle = strncmp(s, "Toggle", 6) ? 0 : 1)) s += i = 6; + if ((cmd.button.joypad.sticky = strncmp(s, "Sticky", 6) ? 0 : 1)) s += i = 6; + if ((cmd.button.joypad.turbo = strncmp(s, "Turbo", 5) ? 0 : 1)) s += i = 5; + + if (cmd.button.joypad.toggle && !(cmd.button.joypad.sticky || cmd.button.joypad.turbo)) + return (cmd); + + if (i) + { + if (*s != ' ') + return (cmd); + s++; + } + + i = 0; + + if (!strncmp(s, "Up", 2)) { i |= SNES_UP_MASK; s += 2; if (*s == '+') s++; } + if (!strncmp(s, "Down", 4)) { i |= SNES_DOWN_MASK; s += 4; if (*s == '+') s++; } + if (!strncmp(s, "Left", 4)) { i |= SNES_LEFT_MASK; s += 4; if (*s == '+') s++; } + if (!strncmp(s, "Right", 5)) { i |= SNES_RIGHT_MASK; s += 5; if (*s == '+') s++; } + + if (*s == 'A') { i |= SNES_A_MASK; s++; if (*s == '+') s++; } + if (*s == 'B') { i |= SNES_B_MASK; s++; if (*s == '+') s++; } + if (*s == 'X') { i |= SNES_X_MASK; s++; if (*s == '+') s++; } + if (*s == 'Y') { i |= SNES_Y_MASK; s++; if (*s == '+') s++; } + if (*s == 'L') { i |= SNES_TL_MASK; s++; if (*s == '+') s++; } + if (*s == 'R') { i |= SNES_TR_MASK; s++; if (*s == '+') s++; } + + if (!strncmp(s, "Start", 5)) { i |= SNES_START_MASK; s += 5; if (*s == '+') s++; } + if (!strncmp(s, "Select", 6)) { i |= SNES_SELECT_MASK; s += 6; } + + if (i == 0 || *s != 0 || *(s - 1) == '+') + return (cmd); + + cmd.button.joypad.buttons = i; + + cmd.type = S9xButtonJoypad; + } + } + else + if (!strncmp(name, "Mouse", 5)) + { + if (name[5] < '1' || name[5] > '2' || name[6] != ' ') + return (cmd); + + cmd.button.mouse.idx = name[5] - '1'; + s = name + 7; + i = 0; + + if ((cmd.button.mouse.left = (*s == 'L'))) s += i = 1; + if ((cmd.button.mouse.right = (*s == 'R'))) s += i = 1; + + if (i == 0 || *s != 0) + return (cmd); + + cmd.type = S9xButtonMouse; + } + else + if (!strncmp(name, "Superscope ", 11)) + { + s = name + 11; + i = 0; + + if ((cmd.button.scope.aim_offscreen = strncmp(s, "AimOffscreen", 12) ? 0 : 1)) { s += i = 12; if (*s == ' ') s++; else if (*s != 0) return (cmd); } + if ((cmd.button.scope.fire = strncmp(s, "Fire", 4) ? 0 : 1)) { s += i = 4; if (*s == '+') s++; } + if ((cmd.button.scope.cursor = strncmp(s, "Cursor", 6) ? 0 : 1)) { s += i = 6; if (*s == '+') s++; } + if ((cmd.button.scope.turbo = strncmp(s, "ToggleTurbo", 11) ? 0 : 1)) { s += i = 11; if (*s == '+') s++; } + if ((cmd.button.scope.pause = strncmp(s, "Pause", 5) ? 0 : 1)) { s += i = 5; } + + if (i == 0 || *s != 0 || *(s - 1) == '+') + return (cmd); + + cmd.type = S9xButtonSuperscope; + } + else + if (!strncmp(name, "Justifier", 9)) + { + if (name[9] < '1' || name[9] > '2' || name[10] != ' ') + return (cmd); + + cmd.button.justifier.idx = name[9] - '1'; + s = name + 11; + i = 0; + + if ((cmd.button.justifier.aim_offscreen = strncmp(s, "AimOffscreen", 12) ? 0 : 1)) { s += i = 12; if (*s == ' ') s++; else if (*s != 0) return (cmd); } + if ((cmd.button.justifier.trigger = strncmp(s, "Trigger", 7) ? 0 : 1)) { s += i = 7; if (*s == '+') s++; } + if ((cmd.button.justifier.start = strncmp(s, "Start", 5) ? 0 : 1)) { s += i = 5; } + + if (i == 0 || *s != 0 || *(s - 1) == '+') + return (cmd); + + cmd.type = S9xButtonJustifier; + } + else + if (!strncmp(name, "Pointer ", 8)) + { + s = name + 8; + i = 0; + + if ((cmd.pointer.aim_mouse0 = strncmp(s, "Mouse1", 6) ? 0 : 1)) { s += i = 6; if (*s == '+') s++; } + if ((cmd.pointer.aim_mouse1 = strncmp(s, "Mouse2", 6) ? 0 : 1)) { s += i = 6; if (*s == '+') s++; } + if ((cmd.pointer.aim_scope = strncmp(s, "Superscope", 10) ? 0 : 1)) { s += i = 10; if (*s == '+') s++; } + if ((cmd.pointer.aim_justifier0 = strncmp(s, "Justifier1", 10) ? 0 : 1)) { s += i = 10; if (*s == '+') s++; } + if ((cmd.pointer.aim_justifier1 = strncmp(s, "Justifier2", 10) ? 0 : 1)) { s += i = 10; } + + if (i == 0 || *s != 0 || *(s - 1) == '+') + return (cmd); + + cmd.type = S9xPointer; + } + else + if (!strncmp(name, "ButtonToPointer ", 16)) + { + if (name[16] < '1' || name[16] > '8') + return (cmd); + + cmd.button.pointer.idx = name[16] - '1'; + s = name + 17; + i = 0; + + if ((cmd.button.pointer.UD = (*s == 'u' ? -1 : (*s == 'd' ? 1 : 0)))) s += i = 1; + if ((cmd.button.pointer.LR = (*s == 'l' ? -1 : (*s == 'r' ? 1 : 0)))) s += i = 1; + + if (i == 0 || *(s++) != ' ') + return (cmd); + + for (i = 0; i < 4; i++) + if (!strcmp(s, speed_names[i])) + break; + if (i > 3) + return (cmd); + + cmd.button.pointer.speed_type = i; + + cmd.type = S9xButtonPseudopointer; + } + else + if (!strncmp(name, "AxisToPointer ", 14)) + { + if (name[14] < '1' || name[14] > '8') + return (cmd); + + cmd.axis.pointer.idx = name[14] - '1'; + s= name + 15; + i = 0; + + if (*s == 'h') + cmd.axis.pointer.HV = 0; + else + if (*s == 'v') + cmd.axis.pointer.HV = 1; + else + return (cmd); + + if (s[1] != ' ') + return (cmd); + + s += 2; + if ((cmd.axis.pointer.invert = *s == '-')) + s++; + + for (i = 0; i < 4; i++) + if (!strcmp(s, speed_names[i])) + break; + if (i > 3) + return (cmd); + + cmd.axis.pointer.speed_type = i; + + cmd.type = S9xAxisPseudopointer; + } + else + if (!strncmp(name, "AxisToButtons ", 14)) + { + s = name + 14; + + if (s[0] == '0') + { + if (s[1] != '/') + return (cmd); + + cmd.axis.button.negbutton = 0; + s += 2; + } + else + { + i = 0; + do + { + if (*s < '0' || *s > '9') + return (cmd); + + i = i * 10 + *s - '0'; + if (i > 255) + return (cmd); + } + while (*++s != '/'); + + cmd.axis.button.negbutton = i; + s++; + } + + if (s[0] == '0') + { + if (s[1] != ' ') + return (cmd); + + cmd.axis.button.posbutton = 0; + s += 2; + } + else + { + i = 0; + do + { + if (*s < '0' || *s > '9') + return (cmd); + + i = i * 10 + *s - '0'; + if (i > 255) + return (cmd); + } + while (*++s != ' '); + + cmd.axis.button.posbutton = i; + s++; + } + + i = get_threshold(&s); + if (i < 0) + return (cmd); + cmd.axis.button.threshold = (i - 1) * 256 / 1000; + + cmd.type = S9xAxisPseudobuttons; + } + else + if (!strncmp(name, "MULTI#", 6)) + { + i = strtol(name + 6, (char **) &s, 10); + if (s != NULL && *s != '\0') + return (cmd); + if (i >= (int) multis.size()) + return (cmd); + + cmd.button.multi_idx = i; + cmd.type = S9xButtonMulti; + } + else + if (((name[0] == '+' && name[1] == '{') || name[0] == '{') && name[strlen(name) - 1] == '}') + { + if (multis.size() > 2147483640) + { + fprintf(stderr, "Too many multis!"); + return (cmd); + } + + string x; + int n; + + j = 2; + for (i = (name[0] == '+') ? 2 : 1; name[i] != '\0'; i++) + { + if (name[i] == ',' || name[i] == ';') + { + if (name[i] == ';') + j++; + if (++j > 2147483640) + { + fprintf(stderr, "Multi too long!"); + return (cmd); + } + } + + if (name[i] == '{') + return (cmd); + } + + s9xcommand_t *c = (s9xcommand_t *) calloc(j, sizeof(s9xcommand_t)); + if (c == NULL) + { + perror("malloc error while parsing multi"); + return (cmd); + } + + n = 0; + i = (name[0] == '+') ? 2 : 1; + + do + { + if (name[i] == ';') + { + c[n].type = S9xNoMapping; + c[n].multi_press = 0; + c[n].button_norpt = 0; + + j = i; + } + else + if (name[i] == ',') + { + free(c); + return (cmd); + } + else + { + uint8 press = 0; + + if (name[0] == '+') + { + if (name[i] == '+') + press = 1; + else + if (name[i] == '-') + press = 2; + else + { + free(c); + return (cmd); + } + + i++; + } + + for (j = i; name[j] != ';' && name[j] != ',' && name[j] != '}'; j++) ; + + x.assign(name + i, j - i); + c[n] = S9xGetCommandT(x.c_str()); + c[n].multi_press = press; + + if (maptype(c[n].type) != MAP_BUTTON) + { + free(c); + return (cmd); + } + + if (name[j] == ';') + j--; + } + + i = j + 1; + n++; + } + while (name[i] != '\0'); + + c[n].type = S9xNoMapping; + c[n].multi_press = 3; + + multis.push_back(c); + + cmd.button.multi_idx = multis.size() - 1; + cmd.type = S9xButtonMulti; + } + else + { + i = findstr(name, command_names, LAST_COMMAND); + if (i < 0) + return (cmd); + + cmd.type = S9xButtonCommand; + cmd.button.command = i; + } + + return (cmd); +} + +const char ** S9xGetAllSnes9xCommands (void) +{ + return (command_names); +} + +s9xcommand_t S9xGetMapping (uint32 id) +{ + if (keymap.count(id) == 0) + { + s9xcommand_t cmd; + cmd.type = S9xNoMapping; + return (cmd); + } + else + return (keymap[id]); +} + +static const char * maptypename (int t) +{ + switch (t) + { + case MAP_NONE: return ("unmapped"); + case MAP_BUTTON: return ("button"); + case MAP_AXIS: return ("axis"); + case MAP_POINTER: return ("pointer"); + default: return ("unknown"); + } +} + +void S9xUnmapID (uint32 id) +{ + for (int i = 0; i < NUMCTLS + 1; i++) + pollmap[i].erase(id); + + if (mouse[0].ID == id) mouse[0].ID = InvalidControlID; + if (mouse[1].ID == id) mouse[1].ID = InvalidControlID; + if (superscope.ID == id) superscope.ID = InvalidControlID; + if (justifier.ID[0] == id) justifier.ID[0] = InvalidControlID; + if (justifier.ID[1] == id) justifier.ID[1] = InvalidControlID; + + if (id >= PseudoPointerBase) + pseudopointer[id - PseudoPointerBase].mapped = false; + + keymap.erase(id); +} + +bool S9xMapButton (uint32 id, s9xcommand_t mapping, bool poll) +{ + int t; + + if (id == InvalidControlID) + { + fprintf(stderr, "Cannot map InvalidControlID\n"); + return (false); + } + + t = maptype(mapping.type); + + if (t == MAP_NONE) + { + S9xUnmapID(id); + return (true); + } + + if (t != MAP_BUTTON) + return (false); + + t = maptype(S9xGetMapping(id).type); + + if (t != MAP_NONE && t != MAP_BUTTON) + fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to button\n", id, maptypename(t)); + + if (id >= PseudoPointerBase) + { + fprintf(stderr, "ERROR: Refusing to map pseudo-pointer #%d as a button\n", id - PseudoPointerBase); + return (false); + } + + t = -1; + + if (poll) + { + if (id >= PseudoButtonBase) + fprintf(stderr, "INFO: Ignoring attempt to set pseudo-button #%d to polling\n", id - PseudoButtonBase); + else + { + switch (mapping.type) + { + case S9xButtonJoypad: + t = JOYPAD0 + mapping.button.joypad.idx; + break; + + case S9xButtonMouse: + t = MOUSE0 + mapping.button.mouse.idx; + break; + + case S9xButtonSuperscope: + t = SUPERSCOPE; + break; + + case S9xButtonJustifier: + t = ONE_JUSTIFIER + mapping.button.justifier.idx; + break; + + case S9xButtonCommand: + case S9xButtonPseudopointer: + case S9xButtonPort: + case S9xButtonMulti: + t = POLL_ALL; + break; + } + } + } + + S9xUnmapID(id); + + keymap[id] = mapping; + + if (t >= 0) + pollmap[t].insert(id); + + return (true); +} + +void S9xReportButton (uint32 id, bool pressed) +{ + if (keymap.count(id) == 0) + return; + + if (keymap[id].type == S9xNoMapping) + return; + + if (maptype(keymap[id].type) != MAP_BUTTON) + { + fprintf(stderr, "ERROR: S9xReportButton called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); + return; + } + + if (keymap[id].type == S9xButtonCommand) // skips the "already-pressed check" unless it's a command, as a hack to work around the following problem: + if (keymap[id].button_norpt == pressed) // FIXME: this makes the controls "stick" after loading a savestate while recording a movie and holding any button + return; + + keymap[id].button_norpt = pressed; + + S9xApplyCommand(keymap[id], pressed, 0); +} + +bool S9xMapPointer (uint32 id, s9xcommand_t mapping, bool poll) +{ + int t; + + if (id == InvalidControlID) + { + fprintf(stderr, "Cannot map InvalidControlID\n"); + return (false); + } + + t = maptype(mapping.type); + + if (t == MAP_NONE) + { + S9xUnmapID(id); + return (true); + } + + if (t != MAP_POINTER) + return (false); + + t = maptype(S9xGetMapping(id).type); + + if (t != MAP_NONE && t != MAP_POINTER) + fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to pointer\n", id, maptypename(t)); + + if (id < PseudoPointerBase && id >= PseudoButtonBase) + { + fprintf(stderr, "ERROR: Refusing to map pseudo-button #%d as a pointer\n", id - PseudoButtonBase); + return (false); + } + + if (mapping.type == S9xPointer) + { + if (mapping.pointer.aim_mouse0 && mouse[0].ID != InvalidControlID && mouse[0].ID != id) + { + fprintf(stderr, "ERROR: Rejecting attempt to control Mouse1 with two pointers\n"); + return (false); + } + + if (mapping.pointer.aim_mouse1 && mouse[1].ID != InvalidControlID && mouse[1].ID != id) + { + fprintf(stderr, "ERROR: Rejecting attempt to control Mouse2 with two pointers\n"); + return (false); + } + + if (mapping.pointer.aim_scope && superscope.ID != InvalidControlID && superscope.ID != id) + { + fprintf(stderr, "ERROR: Rejecting attempt to control SuperScope with two pointers\n"); + return (false); + } + + if (mapping.pointer.aim_justifier0 && justifier.ID[0] != InvalidControlID && justifier.ID[0] != id) + { + fprintf(stderr, "ERROR: Rejecting attempt to control Justifier1 with two pointers\n"); + return (false); + } + + if (mapping.pointer.aim_justifier1 && justifier.ID[1] != InvalidControlID && justifier.ID[1] != id) + { + fprintf(stderr, "ERROR: Rejecting attempt to control Justifier2 with two pointers\n"); + return (false); + } + } + + S9xUnmapID(id); + + if (poll) + { + if (id >= PseudoPointerBase) + fprintf(stderr, "INFO: Ignoring attempt to set pseudo-pointer #%d to polling\n", id - PseudoPointerBase); + else + { + switch (mapping.type) + { + case S9xPointer: + if (mapping.pointer.aim_mouse0 ) pollmap[MOUSE0 ].insert(id); + if (mapping.pointer.aim_mouse1 ) pollmap[MOUSE1 ].insert(id); + if (mapping.pointer.aim_scope ) pollmap[SUPERSCOPE ].insert(id); + if (mapping.pointer.aim_justifier0) pollmap[ONE_JUSTIFIER ].insert(id); + if (mapping.pointer.aim_justifier1) pollmap[TWO_JUSTIFIERS].insert(id); + break; + + case S9xPointerPort: + pollmap[POLL_ALL].insert(id); + break; + } + } + } + + if (id >= PseudoPointerBase) + pseudopointer[id - PseudoPointerBase].mapped = true; + + keymap[id] = mapping; + + if (mapping.pointer.aim_mouse0 ) mouse[0].ID = id; + if (mapping.pointer.aim_mouse1 ) mouse[1].ID = id; + if (mapping.pointer.aim_scope ) superscope.ID = id; + if (mapping.pointer.aim_justifier0) justifier.ID[0] = id; + if (mapping.pointer.aim_justifier1) justifier.ID[1] = id; + + return (true); +} + +void S9xReportPointer (uint32 id, int16 x, int16 y) +{ + if (keymap.count(id) == 0) + return; + + if (keymap[id].type == S9xNoMapping) + return; + + if (maptype(keymap[id].type) != MAP_POINTER) + { + fprintf(stderr, "ERROR: S9xReportPointer called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); + return; + } + + S9xApplyCommand(keymap[id], x, y); +} + +bool S9xMapAxis (uint32 id, s9xcommand_t mapping, bool poll) +{ + int t; + + if (id == InvalidControlID) + { + fprintf(stderr, "Cannot map InvalidControlID\n"); + return (false); + } + + t = maptype(mapping.type); + + if (t == MAP_NONE) + { + S9xUnmapID(id); + return (true); + } + + if (t != MAP_AXIS) + return (false); + + t = maptype(S9xGetMapping(id).type); + + if (t != MAP_NONE && t != MAP_AXIS) + fprintf(stderr, "WARNING: Remapping ID 0x%08x from %s to axis\n", id, maptypename(t)); + + if (id >= PseudoPointerBase) + { + fprintf(stderr, "ERROR: Refusing to map pseudo-pointer #%d as an axis\n", id - PseudoPointerBase); + return (false); + } + + t = -1; + + if (poll) + { + switch (mapping.type) + { + case S9xAxisJoypad: + t = JOYPAD0 + mapping.axis.joypad.idx; + break; + + case S9xAxisPseudopointer: + case S9xAxisPseudobuttons: + case S9xAxisPort: + t=POLL_ALL; + break; + } + } + + S9xUnmapID(id); + + keymap[id] = mapping; + + if (t >= 0) + pollmap[t].insert(id); + + return (true); +} + +void S9xReportAxis (uint32 id, int16 value) +{ + if (keymap.count(id) == 0) + return; + + if (keymap[id].type == S9xNoMapping) + return; + + if (maptype(keymap[id].type) != MAP_AXIS) + { + fprintf(stderr, "ERROR: S9xReportAxis called on %s ID 0x%08x\n", maptypename(maptype(keymap[id].type)), id); + return; + } + + S9xApplyCommand(keymap[id], value, 0); +} + +static int32 ApplyMulti (s9xcommand_t *multi, int32 pos, int16 data1) +{ + while (1) + { + if (multi[pos].multi_press == 3) + return (-1); + + if (multi[pos].type == S9xNoMapping) + break; + + if (multi[pos].multi_press) + S9xApplyCommand(multi[pos], multi[pos].multi_press == 1, 0); + else + S9xApplyCommand(multi[pos], data1, 0); + + pos++; + } + + return (pos + 1); +} + +void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2) +{ + int i; + + switch (cmd.type) + { + case S9xNoMapping: + return; + + case S9xButtonJoypad: + if (cmd.button.joypad.toggle) + { + if (!data1) + return; + + uint16 r = cmd.button.joypad.buttons; + + if (cmd.button.joypad.turbo) joypad[cmd.button.joypad.idx].toggleturbo ^= r; + if (cmd.button.joypad.sticky) joypad[cmd.button.joypad.idx].togglestick ^= r; + } + else + { + uint16 r, s, t, st; + + s = t = st = 0; + r = cmd.button.joypad.buttons; + st = r & joypad[cmd.button.joypad.idx].togglestick & joypad[cmd.button.joypad.idx].toggleturbo; + r ^= st; + t = r & joypad[cmd.button.joypad.idx].toggleturbo; + r ^= t; + s = r & joypad[cmd.button.joypad.idx].togglestick; + r ^= s; + + if (cmd.button.joypad.turbo && cmd.button.joypad.sticky) + { + uint16 x = r; r = st; st = x; + x = s; s = t; t = x; + } + else + if (cmd.button.joypad.turbo) + { + uint16 x = r; r = t; t = x; + x = s; s = st; st = x; + } + else + if (cmd.button.joypad.sticky) + { + uint16 x = r; r = s; s = x; + x = t; t = st; st = x; + } + + if (data1) + { + if (!Settings.UpAndDown && !S9xMoviePlaying()) // if up+down isn't allowed AND we are NOT playing a movie, + { + if (cmd.button.joypad.buttons & (SNES_LEFT_MASK | SNES_RIGHT_MASK)) + { + // if we're pressing left or right, then unpress and unturbo them both first + // so we don't end up hittnig left AND right accidentally. + // Note though that the user can still do it on purpose, if Settings.UpAndDown = true. + // This is a feature, look up glitches in tLoZ:aLttP to find out why. + joypad[cmd.button.joypad.idx].buttons &= ~(SNES_LEFT_MASK | SNES_RIGHT_MASK); + joypad[cmd.button.joypad.idx].turbos &= ~(SNES_LEFT_MASK | SNES_RIGHT_MASK); + } + + if (cmd.button.joypad.buttons & (SNES_UP_MASK | SNES_DOWN_MASK)) + { + // and ditto for up/down + joypad[cmd.button.joypad.idx].buttons &= ~(SNES_UP_MASK | SNES_DOWN_MASK); + joypad[cmd.button.joypad.idx].turbos &= ~(SNES_UP_MASK | SNES_DOWN_MASK); + } + } + + joypad[cmd.button.joypad.idx].buttons |= r; + joypad[cmd.button.joypad.idx].turbos |= t; + joypad[cmd.button.joypad.idx].buttons ^= s; + joypad[cmd.button.joypad.idx].buttons &= ~(joypad[cmd.button.joypad.idx].turbos & st); + joypad[cmd.button.joypad.idx].turbos ^= st; + } + else + { + joypad[cmd.button.joypad.idx].buttons &= ~r; + joypad[cmd.button.joypad.idx].buttons &= ~(joypad[cmd.button.joypad.idx].turbos & t); + joypad[cmd.button.joypad.idx].turbos &= ~t; + } + } + + return; + + case S9xButtonMouse: + i = 0; + if (cmd.button.mouse.left ) i |= 0x40; + if (cmd.button.mouse.right) i |= 0x80; + + if (data1) + mouse[cmd.button.mouse.idx].buttons |= i; + else + mouse[cmd.button.mouse.idx].buttons &= ~i; + + return; + + case S9xButtonSuperscope: + i = 0; + if (cmd.button.scope.fire ) i |= SUPERSCOPE_FIRE; + if (cmd.button.scope.cursor ) i |= SUPERSCOPE_CURSOR; + if (cmd.button.scope.pause ) i |= SUPERSCOPE_PAUSE; + if (cmd.button.scope.aim_offscreen) i |= SUPERSCOPE_OFFSCREEN; + + if (data1) + { + superscope.phys_buttons |= i; + + if (cmd.button.scope.turbo) + { + superscope.phys_buttons ^= SUPERSCOPE_TURBO; + + if (superscope.phys_buttons & SUPERSCOPE_TURBO) + superscope.next_buttons |= superscope.phys_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR); + else + superscope.next_buttons &= ~(SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR); + } + + superscope.next_buttons |= i & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR | SUPERSCOPE_PAUSE); + + if (!S9xMovieActive()) // PPU modification during non-recordable command screws up movie synchronization + if ((superscope.next_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR)) && curcontrollers[1] == SUPERSCOPE && !(superscope.phys_buttons & SUPERSCOPE_OFFSCREEN)) + DoGunLatch(superscope.x, superscope.y); + } + else + { + superscope.phys_buttons &= ~i; + superscope.next_buttons &= SUPERSCOPE_OFFSCREEN | ~i; + } + + return; + + case S9xButtonJustifier: + i = 0; + if (cmd.button.justifier.trigger) i |= JUSTIFIER_TRIGGER; + if (cmd.button.justifier.start ) i |= JUSTIFIER_START; + if (cmd.button.justifier.aim_offscreen) justifier.offscreen[cmd.button.justifier.idx] = data1 ? 1 : 0; + i >>= cmd.button.justifier.idx; + + if (data1) + justifier.buttons |= i; + else + justifier.buttons &= ~i; + + return; + + case S9xButtonCommand: + if (((enum command_numbers) cmd.button.command) >= LAST_COMMAND) + { + fprintf(stderr, "Unknown command %04x\n", cmd.button.command); + return; + } + + if (!data1) + { + switch (i = cmd.button.command) + { + case EmuTurbo: + Settings.TurboMode = FALSE; + break; + } + } + else + { + switch ((enum command_numbers) (i = cmd.button.command)) + { + case ExitEmu: + S9xExit(); + break; + + case Reset: + S9xReset(); + break; + + case SoftReset: + S9xMovieUpdateOnReset(); + if (S9xMoviePlaying()) + S9xMovieStop(TRUE); + S9xSoftReset(); + break; + + case EmuTurbo: + Settings.TurboMode = TRUE; + break; + + case ToggleEmuTurbo: + Settings.TurboMode = !Settings.TurboMode; + DisplayStateChange("Turbo mode", Settings.TurboMode); + break; + + case ClipWindows: + Settings.DisableGraphicWindows = !Settings.DisableGraphicWindows; + DisplayStateChange("Graphic clip windows", !Settings.DisableGraphicWindows); + break; + + case Debugger: + #ifdef DEBUGGER + CPU.Flags |= DEBUG_MODE_FLAG; + #endif + break; + + case IncFrameRate: + if (Settings.SkipFrames == AUTO_FRAMERATE) + Settings.SkipFrames = 1; + else + if (Settings.SkipFrames < 10) + Settings.SkipFrames++; + + if (Settings.SkipFrames == AUTO_FRAMERATE) + S9xSetInfoString("Auto frame skip"); + else + { + sprintf(buf, "Frame skip: %d", Settings.SkipFrames - 1); + S9xSetInfoString(buf); + } + + break; + + case DecFrameRate: + if (Settings.SkipFrames <= 1) + Settings.SkipFrames = AUTO_FRAMERATE; + else + if (Settings.SkipFrames != AUTO_FRAMERATE) + Settings.SkipFrames--; + + if (Settings.SkipFrames == AUTO_FRAMERATE) + S9xSetInfoString("Auto frame skip"); + else + { + sprintf(buf, "Frame skip: %d", Settings.SkipFrames - 1); + S9xSetInfoString(buf); + } + + break; + + case IncEmuTurbo: + if (Settings.TurboSkipFrames < 20) + Settings.TurboSkipFrames += 1; + else + if (Settings.TurboSkipFrames < 200) + Settings.TurboSkipFrames += 5; + sprintf(buf, "Turbo frame skip: %d", Settings.TurboSkipFrames); + S9xSetInfoString(buf); + break; + + case DecEmuTurbo: + if (Settings.TurboSkipFrames > 20) + Settings.TurboSkipFrames -= 5; + else + if (Settings.TurboSkipFrames > 0) + Settings.TurboSkipFrames -= 1; + sprintf(buf, "Turbo frame skip: %d", Settings.TurboSkipFrames); + S9xSetInfoString(buf); + break; + + case IncFrameTime: // Increase emulated frame time by 1ms + Settings.FrameTime += 1000; + sprintf(buf, "Emulated frame time: %dms", Settings.FrameTime / 1000); + S9xSetInfoString(buf); + break; + + case DecFrameTime: // Decrease emulated frame time by 1ms + if (Settings.FrameTime >= 1000) + Settings.FrameTime -= 1000; + sprintf(buf, "Emulated frame time: %dms", Settings.FrameTime / 1000); + S9xSetInfoString(buf); + break; + + case IncTurboSpeed: + if (turbo_time >= 120) + break; + turbo_time++; + sprintf(buf, "Turbo speed: %d", turbo_time); + S9xSetInfoString(buf); + break; + + case DecTurboSpeed: + if (turbo_time <= 1) + break; + turbo_time--; + sprintf(buf, "Turbo speed: %d", turbo_time); + S9xSetInfoString(buf); + break; + + case LoadFreezeFile: + S9xUnfreezeGame(S9xChooseFilename(TRUE)); + break; + + case SaveFreezeFile: + S9xFreezeGame(S9xChooseFilename(FALSE)); + break; + + case LoadOopsFile: + { + char filename[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + snprintf(filename, PATH_MAX + 1, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops"); + + if (S9xUnfreezeGame(filename)) + { + sprintf(buf, "%s.%.*s loaded", def, _MAX_EXT - 1, "oops"); + S9xSetInfoString (buf); + } + else + S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, "Oops file not found"); + + break; + } + + case Pause: + Settings.Paused = !Settings.Paused; + DisplayStateChange("Pause", Settings.Paused); + #if defined(NETPLAY_SUPPORT) && !defined(__WIN32__) + S9xNPSendPause(Settings.Paused); + #endif + break; + + case QuickLoad000: + case QuickLoad001: + case QuickLoad002: + case QuickLoad003: + case QuickLoad004: + case QuickLoad005: + case QuickLoad006: + case QuickLoad007: + case QuickLoad008: + case QuickLoad009: + case QuickLoad010: + { + char filename[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickLoad000); + + if (S9xUnfreezeGame(filename)) + { + sprintf(buf, "%s.%03d loaded", def, i - QuickLoad000); + S9xSetInfoString(buf); + } + else + S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, "Freeze file not found"); + + break; + } + + case QuickSave000: + case QuickSave001: + case QuickSave002: + case QuickSave003: + case QuickSave004: + case QuickSave005: + case QuickSave006: + case QuickSave007: + case QuickSave008: + case QuickSave009: + case QuickSave010: + { + char filename[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + snprintf(filename, PATH_MAX + 1, "%s%s%s.%03d", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, i - QuickSave000); + + sprintf(buf, "%s.%03d saved", def, i - QuickSave000); + S9xSetInfoString(buf); + + S9xFreezeGame(filename); + break; + } + + case SaveSPC: + S9xDumpSPCSnapshot(); + break; + + case Screenshot: + Settings.TakeScreenshot = TRUE; + break; + + case SoundChannel0: + case SoundChannel1: + case SoundChannel2: + case SoundChannel3: + case SoundChannel4: + case SoundChannel5: + case SoundChannel6: + case SoundChannel7: + S9xToggleSoundChannel(i - SoundChannel0); + sprintf(buf, "Sound channel %d toggled", i - SoundChannel0); + S9xSetInfoString(buf); + break; + + case SoundChannelsOn: + S9xToggleSoundChannel(8); + S9xSetInfoString("All sound channels on"); + break; + + case ToggleBG0: + Settings.BG_Forced ^= 1; + DisplayStateChange("BG#0", !(Settings.BG_Forced & 1)); + break; + + case ToggleBG1: + Settings.BG_Forced ^= 2; + DisplayStateChange("BG#1", !(Settings.BG_Forced & 2)); + break; + + case ToggleBG2: + Settings.BG_Forced ^= 4; + DisplayStateChange("BG#2", !(Settings.BG_Forced & 4)); + break; + + case ToggleBG3: + Settings.BG_Forced ^= 8; + DisplayStateChange("BG#3", !(Settings.BG_Forced & 8)); + break; + + case ToggleSprites: + Settings.BG_Forced ^= 16; + DisplayStateChange("Sprites", !(Settings.BG_Forced & 16)); + break; + + case ToggleHDMA: + Settings.DisableHDMA = !Settings.DisableHDMA; + DisplayStateChange("HDMA emulation", !Settings.DisableHDMA); + break; + + case ToggleTransparency: + Settings.Transparency = !Settings.Transparency; + DisplayStateChange("Transparency effects", Settings.Transparency); + break; + + case BeginRecordingMovie: + if (S9xMovieActive()) + S9xMovieStop(FALSE); + S9xMovieCreate(S9xChooseMovieFilename(FALSE), 0xFF, MOVIE_OPT_FROM_RESET, NULL, 0); + break; + + case LoadMovie: + if (S9xMovieActive()) + S9xMovieStop(FALSE); + S9xMovieOpen(S9xChooseMovieFilename(TRUE), FALSE); + break; + + case EndRecordingMovie: + if (S9xMovieActive()) + S9xMovieStop(FALSE); + break; + + case SwapJoypads: + if ((curcontrollers[0] != NONE && !(curcontrollers[0] >= JOYPAD0 && curcontrollers[0] <= JOYPAD7))) + { + S9xSetInfoString("Cannot swap pads: port 1 is not a joypad"); + break; + } + + if ((curcontrollers[1] != NONE && !(curcontrollers[1] >= JOYPAD0 && curcontrollers[1] <= JOYPAD7))) + { + S9xSetInfoString("Cannot swap pads: port 2 is not a joypad"); + break; + } + + newcontrollers[1] = curcontrollers[0]; + newcontrollers[0] = curcontrollers[1]; + + strcpy(buf, "Swap pads: P1="); + i = 14; + if (newcontrollers[0] == NONE) + { + strcpy(buf + i, ""); + i += 6; + } + else + { + sprintf(buf + i, "Joypad%d", newcontrollers[0] - JOYPAD0 + 1); + i += 7; + } + + strcpy(buf + i, " P2="); + i += 4; + if (newcontrollers[1] == NONE) + strcpy(buf + i, ""); + else + sprintf(buf + i, "Joypad%d", newcontrollers[1] - JOYPAD0 + 1); + + S9xSetInfoString(buf); + break; + + case SeekToFrame: + if (S9xMovieActive()) + { + sprintf(buf, "Select frame number (current: %d)", S9xMovieGetFrameCounter()); + const char *frameno = S9xStringInput(buf); + if (!frameno) + return; + + int frameDest = atoi(frameno); + if (frameDest > 0 && frameDest > (int) S9xMovieGetFrameCounter()) + { + int distance = frameDest - S9xMovieGetFrameCounter(); + Settings.HighSpeedSeek = distance; + } + } + + break; + + case LAST_COMMAND: + break; + } + } + + return; + + case S9xPointer: + if (cmd.pointer.aim_mouse0) + { + mouse[0].cur_x = data1; + mouse[0].cur_y = data2; + } + + if (cmd.pointer.aim_mouse1) + { + mouse[1].cur_x = data1; + mouse[1].cur_y = data2; + } + + if (cmd.pointer.aim_scope) + { + superscope.x = data1; + superscope.y = data2; + } + + if (cmd.pointer.aim_justifier0) + { + justifier.x[0] = data1; + justifier.y[0] = data2; + } + + if (cmd.pointer.aim_justifier1) + { + justifier.x[1] = data1; + justifier.y[1] = data2; + } + + return; + + case S9xButtonPseudopointer: + if (data1) + { + if (cmd.button.pointer.UD) + { + if (!pseudopointer[cmd.button.pointer.idx].V_adj) + pseudopointer[cmd.button.pointer.idx].V_adj = cmd.button.pointer.UD * ptrspeeds[cmd.button.pointer.speed_type]; + pseudopointer[cmd.button.pointer.idx].V_var = (cmd.button.pointer.speed_type == 0); + } + + if (cmd.button.pointer.LR) + { + if (!pseudopointer[cmd.button.pointer.idx].H_adj) + pseudopointer[cmd.button.pointer.idx].H_adj = cmd.button.pointer.LR * ptrspeeds[cmd.button.pointer.speed_type]; + pseudopointer[cmd.button.pointer.idx].H_var = (cmd.button.pointer.speed_type == 0); + } + } + else + { + if (cmd.button.pointer.UD) + { + pseudopointer[cmd.button.pointer.idx].V_adj = 0; + pseudopointer[cmd.button.pointer.idx].V_var = false; + } + + if (cmd.button.pointer.LR) + { + pseudopointer[cmd.button.pointer.idx].H_adj = 0; + pseudopointer[cmd.button.pointer.idx].H_var = false; + } + } + + return; + + case S9xAxisJoypad: + { + uint16 pos, neg; + + switch (cmd.axis.joypad.axis) + { + case 0: neg = SNES_LEFT_MASK; pos = SNES_RIGHT_MASK; break; + case 1: neg = SNES_UP_MASK; pos = SNES_DOWN_MASK; break; + case 2: neg = SNES_Y_MASK; pos = SNES_A_MASK; break; + case 3: neg = SNES_X_MASK; pos = SNES_B_MASK; break; + case 4: neg = SNES_TL_MASK; pos = SNES_TR_MASK; break; + default: return; + } + + if (cmd.axis.joypad.invert) + data1 = -data1; + + uint16 p, r; + + p = r = 0; + if (data1 > ((cmd.axis.joypad.threshold + 1) * 127)) + p |= pos; + else + r |= pos; + + if (data1 <= ((cmd.axis.joypad.threshold + 1) * -127)) + p |= neg; + else + r |= neg; + + joypad[cmd.axis.joypad.idx].buttons |= p; + joypad[cmd.axis.joypad.idx].buttons &= ~r; + joypad[cmd.axis.joypad.idx].turbos &= ~(p | r); + + return; + } + + case S9xAxisPseudopointer: + if (data1 == 0) + { + if (cmd.axis.pointer.HV) + { + pseudopointer[cmd.axis.pointer.idx].V_adj = 0; + pseudopointer[cmd.axis.pointer.idx].V_var = false; + } + else + { + pseudopointer[cmd.axis.pointer.idx].H_adj = 0; + pseudopointer[cmd.axis.pointer.idx].H_var = false; + } + } + else + { + if (cmd.axis.pointer.invert) + data1 = -data1; + + if (cmd.axis.pointer.HV) + { + if (!pseudopointer[cmd.axis.pointer.idx].V_adj) + pseudopointer[cmd.axis.pointer.idx].V_adj = (int16) ((int32) data1 * ptrspeeds[cmd.axis.pointer.speed_type] / 32767); + pseudopointer[cmd.axis.pointer.idx].V_var = (cmd.axis.pointer.speed_type == 0); + } + else + { + if (!pseudopointer[cmd.axis.pointer.idx].H_adj) + pseudopointer[cmd.axis.pointer.idx].H_adj = (int16) ((int32) data1 * ptrspeeds[cmd.axis.pointer.speed_type] / 32767); + pseudopointer[cmd.axis.pointer.idx].H_var = (cmd.axis.pointer.speed_type == 0); + } + } + + return; + + case S9xAxisPseudobuttons: + if (data1 > ((cmd.axis.button.threshold + 1) * 127)) + { + if (!pseudobuttons[cmd.axis.button.posbutton]) + { + pseudobuttons[cmd.axis.button.posbutton] = 1; + S9xReportButton(PseudoButtonBase + cmd.axis.button.posbutton, true); + } + } + else + { + if (pseudobuttons[cmd.axis.button.posbutton]) + { + pseudobuttons[cmd.axis.button.posbutton] = 0; + S9xReportButton(PseudoButtonBase + cmd.axis.button.posbutton, false); + } + } + + if (data1 <= ((cmd.axis.button.threshold + 1) * -127)) + { + if (!pseudobuttons[cmd.axis.button.negbutton]) + { + pseudobuttons[cmd.axis.button.negbutton] = 1; + S9xReportButton(PseudoButtonBase + cmd.axis.button.negbutton, true); + } + } + else + { + if (pseudobuttons[cmd.axis.button.negbutton]) + { + pseudobuttons[cmd.axis.button.negbutton] = 0; + S9xReportButton(PseudoButtonBase + cmd.axis.button.negbutton, false); + } + } + + return; + + case S9xButtonPort: + case S9xAxisPort: + case S9xPointerPort: + S9xHandlePortCommand(cmd, data1, data2); + return; + + case S9xButtonMulti: + if (cmd.button.multi_idx >= (int) multis.size()) + return; + + if (multis[cmd.button.multi_idx]->multi_press && !data1) + return; + + i = ApplyMulti(multis[cmd.button.multi_idx], 0, data1); + if (i >= 0) + { + struct exemulti *e = new struct exemulti; + e->pos = i; + e->data1 = data1 != 0; + e->script = multis[cmd.button.multi_idx]; + exemultis.insert(e); + } + + return; + + default: + fprintf(stderr, "WARNING: Unknown command type %d\n", cmd.type); + return; + } +} + +static void do_polling (int mp) +{ + set::iterator itr; + + if (S9xMoviePlaying()) + return; + + if (pollmap[mp].empty()) + return; + + for (itr = pollmap[mp].begin(); itr != pollmap[mp].end(); itr++) + { + switch (maptype(keymap[*itr].type)) + { + case MAP_BUTTON: + { + bool pressed; + if (S9xPollButton(*itr, &pressed)) + S9xReportButton(*itr, pressed); + break; + } + + case MAP_AXIS: + { + int16 value; + if (S9xPollAxis(*itr, &value)) + S9xReportAxis(*itr, value); + break; + } + + case MAP_POINTER: + { + int16 x, y; + if (S9xPollPointer(*itr, &x, &y)) + S9xReportPointer(*itr, x, y); + break; + } + + default: + break; + } + } +} + +static void UpdatePolledMouse (int i) +{ + int16 j; + + j = mouse[i - MOUSE0].cur_x - mouse[i - MOUSE0].old_x; + + if (j < -127) + { + mouse[i - MOUSE0].delta_x = 0xff; + mouse[i - MOUSE0].old_x -= 127; + } + else + if (j < 0) + { + mouse[i - MOUSE0].delta_x = 0x80 | -j; + mouse[i - MOUSE0].old_x = mouse[i - MOUSE0].cur_x; + } + else + if (j > 127) + { + mouse[i - MOUSE0].delta_x = 0x7f; + mouse[i - MOUSE0].old_x += 127; + } + else + { + mouse[i - MOUSE0].delta_x = (uint8) j; + mouse[i - MOUSE0].old_x = mouse[i - MOUSE0].cur_x; + } + + j = mouse[i - MOUSE0].cur_y - mouse[i - MOUSE0].old_y; + + if (j < -127) + { + mouse[i - MOUSE0].delta_y = 0xff; + mouse[i - MOUSE0].old_y -= 127; + } + else + if (j < 0) + { + mouse[i - MOUSE0].delta_y = 0x80 | -j; + mouse[i - MOUSE0].old_y = mouse[i - MOUSE0].cur_y; + } + else + if (j > 127) + { + mouse[i - MOUSE0].delta_y = 0x7f; + mouse[i - MOUSE0].old_y += 127; + } + else + { + mouse[i - MOUSE0].delta_y = (uint8) j; + mouse[i - MOUSE0].old_y = mouse[i - MOUSE0].cur_y; + } +} + +void S9xSetJoypadLatch (bool latch) +{ + if (!latch && FLAG_LATCH) + { + // 1 written, 'plug in' new controllers now + curcontrollers[0] = newcontrollers[0]; + curcontrollers[1] = newcontrollers[1]; + } + + if (latch && !FLAG_LATCH) + { + int i; + + for (int n = 0; n < 2; n++) + { + for (int j = 0; j < 2; j++) + read_idx[n][j] = 0; + + switch (i = curcontrollers[n]) + { + case MP5: + for (int j = 0, k = mp5[n].pads[j]; j < 4; k = mp5[n].pads[++j]) + { + if (k == NONE) + continue; + do_polling(k); + } + + break; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + do_polling(i); + break; + + case MOUSE0: + case MOUSE1: + do_polling(i); + if (!S9xMoviePlaying()) + UpdatePolledMouse(i); + break; + + case SUPERSCOPE: + if (superscope.next_buttons & SUPERSCOPE_FIRE) + { + superscope.next_buttons &= ~SUPERSCOPE_TURBO; + superscope.next_buttons |= superscope.phys_buttons & SUPERSCOPE_TURBO; + } + + if (superscope.next_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR)) + { + superscope.next_buttons &= ~SUPERSCOPE_OFFSCREEN; + superscope.next_buttons |= superscope.phys_buttons & SUPERSCOPE_OFFSCREEN; + } + + superscope.read_buttons = superscope.next_buttons; + + superscope.next_buttons &= ~SUPERSCOPE_PAUSE; + if (!(superscope.phys_buttons & SUPERSCOPE_TURBO)) + superscope.next_buttons &= ~(SUPERSCOPE_CURSOR | SUPERSCOPE_FIRE); + + do_polling(i); + break; + + case TWO_JUSTIFIERS: + do_polling(TWO_JUSTIFIERS); + // fall through + + case ONE_JUSTIFIER: + justifier.buttons ^= JUSTIFIER_SELECT; + do_polling(ONE_JUSTIFIER); + break; + + default: + break; + } + } + } + + FLAG_LATCH = latch; +} + +uint8 S9xReadJOYSERn (int n) +{ + int i, j, r; + + if (n > 1) + n -= 0x4016; + assert(n == 0 || n == 1); + + uint8 bits = (OpenBus & ~3) | ((n == 1) ? 0x1c : 0); + + if (FLAG_LATCH) + { + switch (i = curcontrollers[n]) + { + case MP5: + return (bits | 2); + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + return (bits | ((joypad[i - JOYPAD0].buttons & 0x8000) ? 1 : 0)); + + case MOUSE0: + case MOUSE1: + mouse[i - MOUSE0].buttons += 0x10; + if ((mouse[i - MOUSE0].buttons & 0x30) == 0x30) + mouse[i - MOUSE0].buttons &= 0xcf; + return (bits); + + case SUPERSCOPE: + return (bits | ((superscope.read_buttons & 0x80) ? 1 : 0)); + + case ONE_JUSTIFIER: + case TWO_JUSTIFIERS: + return (bits); + + default: + return (bits); + } + } + else + { + switch (i = curcontrollers[n]) + { + case MP5: + r = read_idx[n][FLAG_IOBIT(n) ? 0 : 1]++; + j = FLAG_IOBIT(n) ? 0 : 2; + + for (i = 0; i < 2; i++, j++) + { + if (mp5[n].pads[j] == NONE) + continue; + if (r >= 16) + bits |= 1 << i; + else + bits |= ((joypad[mp5[n].pads[j] - JOYPAD0].buttons & (0x8000 >> r)) ? 1 : 0) << i; + } + + return (bits); + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + if (read_idx[n][0] >= 16) + { + read_idx[n][0]++; + return (bits | 1); + } + else + return (bits | ((joypad[i - JOYPAD0].buttons & (0x8000 >> read_idx[n][0]++)) ? 1 : 0)); + + case MOUSE0: + case MOUSE1: + if (read_idx[n][0] < 8) + { + read_idx[n][0]++; + return (bits); + } + else + if (read_idx[n][0] < 16) + return (bits | ((mouse[i - MOUSE0].buttons & (0x8000 >> read_idx[n][0]++)) ? 1 : 0)); + else + if (read_idx[n][0] < 24) + return (bits | ((mouse[i - MOUSE0].delta_y & (0x800000 >> read_idx[n][0]++)) ? 1 : 0)); + else + if (read_idx[n][0] < 32) + return (bits | ((mouse[i - MOUSE0].delta_x & (0x80000000 >> read_idx[n][0]++)) ? 1 : 0)); + else + { + read_idx[n][0]++; + return (bits | 1); + } + + case SUPERSCOPE: + if (read_idx[n][0] < 8) + return (bits | ((superscope.read_buttons & (0x80 >> read_idx[n][0]++)) ? 1 : 0)); + else + { + read_idx[n][0]++; + return (bits | 1); + } + + case ONE_JUSTIFIER: + if (read_idx[n][0] < 24) + return (bits | ((0xaa7000 >> read_idx[n][0]++) & 1)); + else + if (read_idx[n][0] < 32) + return (bits | ((justifier.buttons & (JUSTIFIER_TRIGGER | JUSTIFIER_START | JUSTIFIER_SELECT) & (0x80000000 >> read_idx[n][0]++)) ? 1 : 0)); + else + { + read_idx[n][0]++; + return (bits | 1); + } + + case TWO_JUSTIFIERS: + if (read_idx[n][0] < 24) + return (bits | ((0xaa7000 >> read_idx[n][0]++) & 1)); + else + if (read_idx[n][0] < 32) + return (bits | ((justifier.buttons & (0x80000000 >> read_idx[n][0]++)) ? 1 : 0)); + else + { + read_idx[n][0]++; + return (bits | 1); + } + + default: + read_idx[n][0]++; + return (bits); + } + } +} + +void S9xDoAutoJoypad (void) +{ + int i, j; + + S9xSetJoypadLatch(1); + S9xSetJoypadLatch(0); + + S9xMovieUpdate(false); + + for (int n = 0; n < 2; n++) + { + switch (i = curcontrollers[n]) + { + case MP5: + j = FLAG_IOBIT(n) ? 0 : 2; + for (i = 0; i < 2; i++, j++) + { + if (mp5[n].pads[j] == NONE) + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2 + i * 4, 0); + else + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2 + i * 4, joypad[mp5[n].pads[j] - JOYPAD0].buttons); + } + + read_idx[n][FLAG_IOBIT(n) ? 0 : 1] = 16; + break; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + read_idx[n][0] = 16; + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, joypad[i - JOYPAD0].buttons); + WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); + break; + + case MOUSE0: + case MOUSE1: + read_idx[n][0] = 16; + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, mouse[i - MOUSE0].buttons); + WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); + break; + + case SUPERSCOPE: + read_idx[n][0] = 16; + Memory.FillRAM[0x4218 + n * 2] = 0xff; + Memory.FillRAM[0x4219 + n * 2] = superscope.read_buttons; + WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); + break; + + case ONE_JUSTIFIER: + case TWO_JUSTIFIERS: + read_idx[n][0] = 16; + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, 0x000e); + WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); + break; + + default: + WRITE_WORD(Memory.FillRAM + 0x4218 + n * 2, 0); + WRITE_WORD(Memory.FillRAM + 0x421c + n * 2, 0); + break; + } + } +} + +void S9xControlEOF (void) +{ + struct crosshair *c; + int i, j; + + PPU.GunVLatch = 1000; // i.e., never latch + PPU.GunHLatch = 0; + + for (int n = 0; n < 2; n++) + { + switch (i = curcontrollers[n]) + { + case MP5: + for (j = 0, i = mp5[n].pads[j]; j < 4; i = mp5[n].pads[++j]) + { + if (i == NONE) + continue; + + if (++joypad[i - JOYPAD0].turbo_ct >= turbo_time) + { + joypad[i - JOYPAD0].turbo_ct = 0; + joypad[i - JOYPAD0].buttons ^= joypad[i - JOYPAD0].turbos; + } + } + + break; + + case JOYPAD0: + case JOYPAD1: + case JOYPAD2: + case JOYPAD3: + case JOYPAD4: + case JOYPAD5: + case JOYPAD6: + case JOYPAD7: + if (++joypad[i - JOYPAD0].turbo_ct >= turbo_time) + { + joypad[i - JOYPAD0].turbo_ct = 0; + joypad[i - JOYPAD0].buttons ^= joypad[i - JOYPAD0].turbos; + } + + break; + + case MOUSE0: + case MOUSE1: + c = &mouse[i - MOUSE0].crosshair; + if (IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, mouse[i - MOUSE0].cur_x, mouse[i - MOUSE0].cur_y); + break; + + case SUPERSCOPE: + if (n == 1 && !(superscope.phys_buttons & SUPERSCOPE_OFFSCREEN)) + { + if (superscope.next_buttons & (SUPERSCOPE_FIRE | SUPERSCOPE_CURSOR)) + DoGunLatch(superscope.x, superscope.y); + + c = &superscope.crosshair; + if (IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, superscope.x, superscope.y); + } + + break; + + case TWO_JUSTIFIERS: + if (n == 1 && !justifier.offscreen[1]) + { + c = &justifier.crosshair[1]; + if (IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, justifier.x[1], justifier.y[1]); + } + + i = (justifier.buttons & JUSTIFIER_SELECT) ? 1 : 0; + goto do_justifier; + + case ONE_JUSTIFIER: + i = (justifier.buttons & JUSTIFIER_SELECT) ? -1 : 0; + + do_justifier: + if (n == 1) + { + if (i >= 0 && !justifier.offscreen[i]) + DoGunLatch(justifier.x[i], justifier.y[i]); + + if (!justifier.offscreen[0]) + { + c = &justifier.crosshair[0]; + if (IPPU.RenderThisFrame) + S9xDrawCrosshair(S9xGetCrosshair(c->img), c->fg, c->bg, justifier.x[0], justifier.y[0]); + } + } + + break; + + default: + break; + } + } + + for (int n = 0; n < 8; n++) + { + if (!pseudopointer[n].mapped) + continue; + + if (pseudopointer[n].H_adj) + { + pseudopointer[n].x += pseudopointer[n].H_adj; + if (pseudopointer[n].x < 0) + pseudopointer[n].x = 0; + else + if (pseudopointer[n].x > 255) + pseudopointer[n].x = 255; + + if (pseudopointer[n].H_var) + { + if (pseudopointer[n].H_adj < 0) + { + if (pseudopointer[n].H_adj > -ptrspeeds[3]) + pseudopointer[n].H_adj--; + } + else + { + if (pseudopointer[n].H_adj < ptrspeeds[3]) + pseudopointer[n].H_adj++; + } + } + } + + if (pseudopointer[n].V_adj) + { + pseudopointer[n].y += pseudopointer[n].V_adj; + if (pseudopointer[n].y < 0) + pseudopointer[n].y = 0; + else + if (pseudopointer[n].y > PPU.ScreenHeight - 1) + pseudopointer[n].y = PPU.ScreenHeight - 1; + + if (pseudopointer[n].V_var) + { + if (pseudopointer[n].V_adj < 0) + { + if (pseudopointer[n].V_adj > -ptrspeeds[3]) + pseudopointer[n].V_adj--; + } + else + { + if (pseudopointer[n].V_adj < ptrspeeds[3]) + pseudopointer[n].V_adj++; + } + } + } + + S9xReportPointer(PseudoPointerBase + n, pseudopointer[n].x, pseudopointer[n].y); + } + + set::iterator it, jt; + + for (it = exemultis.begin(); it != exemultis.end(); it++) + { + i = ApplyMulti((*it)->script, (*it)->pos, (*it)->data1); + + if (i >= 0) + (*it)->pos = i; + else + { + jt = it; + it--; + delete *jt; + exemultis.erase(jt); + } + } + + do_polling(POLL_ALL); + + S9xMovieUpdate(); + + pad_read_last = pad_read; + pad_read = false; +} + +void S9xSetControllerCrosshair (enum crosscontrols ctl, int8 idx, const char *fg, const char *bg) +{ + struct crosshair *c; + int8 fgcolor = -1, bgcolor = -1; + int i, j; + + if (idx < -1 || idx > 31) + { + fprintf(stderr, "S9xSetControllerCrosshair() called with invalid index\n"); + return; + } + + switch (ctl) + { + case X_MOUSE1: c = &mouse[0].crosshair; break; + case X_MOUSE2: c = &mouse[1].crosshair; break; + case X_SUPERSCOPE: c = &superscope.crosshair; break; + case X_JUSTIFIER1: c = &justifier.crosshair[0]; break; + case X_JUSTIFIER2: c = &justifier.crosshair[1]; break; + default: + fprintf(stderr, "S9xSetControllerCrosshair() called with an invalid controller ID %d\n", ctl); + return; + } + + if (fg) + { + fgcolor = 0; + if (*fg == 't') + { + fg++; + fgcolor = 16; + } + + for (i = 0; i < 16; i++) + { + for (j = 0; color_names[i][j] && fg[j] == color_names[i][j]; j++) ; + if (isalnum(fg[j])) + continue; + + if (!color_names[i][j]) + break; + } + + fgcolor |= i; + if (i > 15 || fgcolor == 16) + { + fprintf(stderr, "S9xSetControllerCrosshair() called with invalid fgcolor\n"); + return; + } + } + + if (bg) + { + bgcolor = 0; + if (*bg == 't') + { + bg++; + bgcolor = 16; + } + + for (i = 0; i < 16; i++) + { + for (j = 0; color_names[i][j] && bg[j] == color_names[i][j]; j++) ; + if (isalnum(bg[j])) + continue; + + if (!color_names[i][j]) + break; + } + + bgcolor |= i; + if (i > 15 || bgcolor == 16) + { + fprintf(stderr, "S9xSetControllerCrosshair() called with invalid bgcolor\n"); + return; + } + } + + if (idx != -1) + { + c->set |= 1; + c->img = idx; + } + + if (fgcolor != -1) + { + c->set |= 2; + c->fg = fgcolor; + } + + if (bgcolor != -1) + { + c->set |= 4; + c->bg = bgcolor; + } +} + +void S9xGetControllerCrosshair (enum crosscontrols ctl, int8 *idx, const char **fg, const char **bg) +{ + struct crosshair *c; + + switch (ctl) + { + case X_MOUSE1: c = &mouse[0].crosshair; break; + case X_MOUSE2: c = &mouse[1].crosshair; break; + case X_SUPERSCOPE: c = &superscope.crosshair; break; + case X_JUSTIFIER1: c = &justifier.crosshair[0]; break; + case X_JUSTIFIER2: c = &justifier.crosshair[1]; break; + default: + fprintf(stderr, "S9xGetControllerCrosshair() called with an invalid controller ID %d\n", ctl); + return; + } + + if (idx) + *idx = c->img; + + if (fg) + *fg = color_names[c->fg]; + + if (bg) + *bg = color_names[c->bg]; +} + +void S9xControlPreSaveState (struct SControlSnapshot *s) +{ + ZeroMemory(s, sizeof(*s)); + s->ver = 3; + + for (int j = 0; j < 2; j++) + { + s->port1_read_idx[j] = read_idx[0][j]; + s->port2_read_idx[j] = read_idx[1][j]; + } + + for (int j = 0; j < 2; j++) + s->mouse_speed[j] = (mouse[j].buttons & 0x30) >> 4; + + s->justifier_select = ((justifier.buttons & JUSTIFIER_SELECT) ? 1 : 0); + +#define COPY(x) { memcpy((char *) s->internal + i, &(x), sizeof(x)); i += sizeof(x); } + + int i = 0; + + for (int j = 0; j < 8; j++) + COPY(joypad[j].buttons); + + for (int j = 0; j < 2; j++) + { + COPY(mouse[j].delta_x); + COPY(mouse[j].delta_y); + COPY(mouse[j].old_x); + COPY(mouse[j].old_y); + COPY(mouse[j].cur_x); + COPY(mouse[j].cur_y); + COPY(mouse[j].buttons); + } + + COPY(superscope.x); + COPY(superscope.y); + COPY(superscope.phys_buttons); + COPY(superscope.next_buttons); + COPY(superscope.read_buttons); + + for (int j = 0; j < 2; j++) + COPY(justifier.x[j]); + for (int j = 0; j < 2; j++) + COPY(justifier.y[j]); + COPY(justifier.buttons); + for (int j = 0; j < 2; j++) + COPY(justifier.offscreen[j]); + + for (int j = 0; j < 2; j++) + for (int k = 0; k < 2; k++) + COPY(mp5[j].pads[k]); + + assert(i == sizeof(s->internal)); + +#undef COPY + + s->pad_read = pad_read; + s->pad_read_last = pad_read_last; +} + +void S9xControlPostLoadState (struct SControlSnapshot *s) +{ + if (curcontrollers[0] == MP5 && s->ver < 1) + { + // Crap. Old snes9x didn't support this. + S9xMessage(S9X_WARNING, S9X_FREEZE_FILE_INFO, "Old savestate has no support for MP5 in port 1."); + newcontrollers[0] = curcontrollers[0]; + curcontrollers[0] = mp5[0].pads[0]; + } + + for (int j = 0; j < 2; j++) + { + read_idx[0][j] = s->port1_read_idx[j]; + read_idx[1][j] = s->port2_read_idx[j]; + } + + for (int j = 0; j < 2; j++) + mouse[j].buttons |= (s->mouse_speed[j] & 3) << 4; + + if (s->justifier_select & 1) + justifier.buttons |= JUSTIFIER_SELECT; + else + justifier.buttons &= ~JUSTIFIER_SELECT; + + FLAG_LATCH = (Memory.FillRAM[0x4016] & 1) == 1; + + if (s->ver > 1) + { + #define COPY(x) { memcpy(&(x), (char *) s->internal + i, sizeof(x)); i += sizeof(x); } + + int i = 0; + + for (int j = 0; j < 8; j++) + COPY(joypad[j].buttons); + + for (int j = 0; j < 2; j++) + { + COPY(mouse[j].delta_x); + COPY(mouse[j].delta_y); + COPY(mouse[j].old_x); + COPY(mouse[j].old_y); + COPY(mouse[j].cur_x); + COPY(mouse[j].cur_y); + COPY(mouse[j].buttons); + } + + COPY(superscope.x); + COPY(superscope.y); + COPY(superscope.phys_buttons); + COPY(superscope.next_buttons); + COPY(superscope.read_buttons); + + for (int j = 0; j < 2; j++) + COPY(justifier.x[j]); + for (int j = 0; j < 2; j++) + COPY(justifier.y[j]); + COPY(justifier.buttons); + for (int j = 0; j < 2; j++) + COPY(justifier.offscreen[j]); + for (int j = 0; j < 2; j++) + for (int k = 0; k < 2; k++) + COPY(mp5[j].pads[k]); + + assert(i == sizeof(s->internal)); + + #undef COPY + } + + if (s->ver > 2) + { + pad_read = s->pad_read; + pad_read_last = s->pad_read_last; + } +} + +uint16 MovieGetJoypad (int i) +{ + if (i < 0 || i > 7) + return (0); + + return (joypad[i].buttons); +} + +void MovieSetJoypad (int i, uint16 buttons) +{ + if (i < 0 || i > 7) + return; + + joypad[i].buttons = buttons; +} + +bool MovieGetMouse (int i, uint8 out[5]) +{ + if (i < 0 || i > 1 || (curcontrollers[i] != MOUSE0 && curcontrollers[i] != MOUSE1)) + return (false); + + int n = curcontrollers[i] - MOUSE0; + uint8 *ptr = out; + + WRITE_WORD(ptr, mouse[n].cur_x); ptr += 2; + WRITE_WORD(ptr, mouse[n].cur_y); ptr += 2; + *ptr = mouse[n].buttons; + + return (true); +} + +void MovieSetMouse (int i, uint8 in[5], bool inPolling) +{ + if (i < 0 || i > 1 || (curcontrollers[i] != MOUSE0 && curcontrollers[i] != MOUSE1)) + return; + + int n = curcontrollers[i] - MOUSE0; + uint8 *ptr = in; + + mouse[n].cur_x = READ_WORD(ptr); ptr += 2; + mouse[n].cur_y = READ_WORD(ptr); ptr += 2; + mouse[n].buttons = *ptr; + + if (inPolling) + UpdatePolledMouse(curcontrollers[i]); +} + +bool MovieGetScope (int i, uint8 out[6]) +{ + if (i < 0 || i > 1 || curcontrollers[i] != SUPERSCOPE) + return (false); + + uint8 *ptr = out; + + WRITE_WORD(ptr, superscope.x); ptr += 2; + WRITE_WORD(ptr, superscope.y); ptr += 2; + *ptr++ = superscope.phys_buttons; + *ptr = superscope.next_buttons; + + return (true); +} + +void MovieSetScope (int i, uint8 in[6]) +{ + if (i < 0 || i > 1 || curcontrollers[i] != SUPERSCOPE) + return; + + uint8 *ptr = in; + + superscope.x = READ_WORD(ptr); ptr += 2; + superscope.y = READ_WORD(ptr); ptr += 2; + superscope.phys_buttons = *ptr++; + superscope.next_buttons = *ptr; +} + +bool MovieGetJustifier (int i, uint8 out[11]) +{ + if (i < 0 || i > 1 || (curcontrollers[i] != ONE_JUSTIFIER && curcontrollers[i] != TWO_JUSTIFIERS)) + return (false); + + uint8 *ptr = out; + + WRITE_WORD(ptr, justifier.x[0]); ptr += 2; + WRITE_WORD(ptr, justifier.x[1]); ptr += 2; + WRITE_WORD(ptr, justifier.y[0]); ptr += 2; + WRITE_WORD(ptr, justifier.y[1]); ptr += 2; + *ptr++ = justifier.buttons; + *ptr++ = justifier.offscreen[0]; + *ptr = justifier.offscreen[1]; + + return (true); +} + +void MovieSetJustifier (int i, uint8 in[11]) +{ + if (i < 0 || i > 1 || (curcontrollers[i] != ONE_JUSTIFIER && curcontrollers[i] != TWO_JUSTIFIERS)) + return; + + uint8 *ptr = in; + + justifier.x[0] = READ_WORD(ptr); ptr += 2; + justifier.x[1] = READ_WORD(ptr); ptr += 2; + justifier.y[0] = READ_WORD(ptr); ptr += 2; + justifier.y[1] = READ_WORD(ptr); ptr += 2; + justifier.buttons = *ptr++; + justifier.offscreen[0] = *ptr++; + justifier.offscreen[1] = *ptr; +} diff --git a/controls.h b/controls.h new file mode 100644 index 00000000..8772f62c --- /dev/null +++ b/controls.h @@ -0,0 +1,453 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _CONTROLS_H_ +#define _CONTROLS_H_ + +#define S9xNoMapping 0 +#define S9xButtonJoypad 1 +#define S9xButtonMouse 2 +#define S9xButtonSuperscope 3 +#define S9xButtonJustifier 4 +#define S9xButtonCommand 5 +#define S9xButtonMulti 6 +#define S9xAxisJoypad 7 +#define S9xPointer 8 + +#define S9xButtonPseudopointer 254 +#define S9xAxisPseudopointer 253 +#define S9xAxisPseudobuttons 252 + +// These are automatically kicked out to the S9xHandlePortCommand function. +// If your port wants to define port-specific commands or whatever, use these values for the s9xcommand_t type field. + +#define S9xButtonPort 251 +#define S9xAxisPort 250 +#define S9xPointerPort 249 + +#define S9xBadMapping 255 +#define InvalidControlID ((uint32) -1) + +// S9xButtonPseudopointer and S9xAxisPseudopointer will report pointer motion using IDs PseudoPointerBase through PseudoPointerBase+7. +// S9xAxisPseudopointer command types. S9xAxisPseudobuttons will report buttons with IDs PseudoButtonBase to PseudoButtonBase+255. + +#define PseudoPointerBase (InvalidControlID - 8) +#define PseudoButtonBase (PseudoPointerBase - 256) + +typedef struct +{ + uint8 type; + uint8 multi_press:2; + uint8 button_norpt:1; + + union + { + union + { + struct + { + uint8 idx:3; // Pad number 0-7 + uint8 toggle:1; // If set, toggle turbo/sticky for the button + uint8 turbo:1; // If set, be a 'turbo' button + uint8 sticky:1; // If set, toggle button state (on/turbo or off) when pressed and do nothing on release + uint16 buttons; // Which buttons to actuate. Use SNES_*_MASK constants from snes9x.h + } joypad; + + struct + { + uint8 idx:1; // Mouse number 0-1 + uint8 left:1; // buttons + uint8 right:1; + } mouse; + + struct + { + uint8 fire:1; + uint8 cursor:1; + uint8 turbo:1; + uint8 pause:1; + uint8 aim_offscreen:1; // Pretend we're pointing the gun offscreen (ignore the pointer) + } scope; + + struct + { + uint8 idx:3; // Pseudo-pointer number 0-7 + uint8 speed_type:2; // 0=variable, 1=slow, 2=med, 3=fast + int8 UD:2; // -1=up, 1=down, 0=no vertical motion + int8 LR:2; // -1=left, 1=right, 0=no horizontal motion + } pointer; + + struct + { + uint8 idx:1; // Justifier number 0-1 + uint8 trigger:1; // buttons + uint8 start:1; + uint8 aim_offscreen:1; // Pretend we're pointing the gun offscreen (ignore the pointer) + } justifier; + + int32 multi_idx; + uint16 command; + } button; + + union + { + struct + { + uint8 idx:3; // Pad number 0-7 + uint8 invert:1; // 1 = positive is Left/Up/Y/X/L + uint8 axis:3; // 0=Left/Right, 1=Up/Down, 2=Y/A, 3=X/B, 4=L/R + uint8 threshold; // (threshold+1)/256% deflection is a button press + } joypad; + + struct + { + uint8 idx:3; // Pseudo-pointer number 0-7 + uint8 speed_type:2; // 0=variable, 1=slow, 2=med, 3=fast + uint8 invert:1; // 1 = invert axis, so positive is up/left + uint8 HV:1; // 0=horizontal, 1=vertical + } pointer; + + struct + { + uint8 threshold; // (threshold+1)/256% deflection is a button press + uint8 negbutton; // Button ID for negative deflection + uint8 posbutton; // Button ID for positive deflection + } button; + } axis; + + struct // Which SNES-pointers to control with this pointer + { + uint16 aim_mouse0:1; + uint16 aim_mouse1:1; + uint16 aim_scope:1; + uint16 aim_justifier0:1; + uint16 aim_justifier1:1; + } pointer; + + uint8 port[4]; + }; +} s9xcommand_t; + +// Starting out... + +void S9xUnmapAllControls (void); + +// Setting which controllers are plugged in. + +enum controllers +{ + CTL_NONE, // all ids ignored + CTL_JOYPAD, // use id1 to specify 0-7 + CTL_MOUSE, // use id1 to specify 0-1 + CTL_SUPERSCOPE, + CTL_JUSTIFIER, // use id1: 0=one justifier, 1=two justifiers + CTL_MP5 // use id1-id4 to specify pad 0-7 (or -1) +}; + +void S9xSetController (int port, enum controllers controller, int8 id1, int8 id2, int8 id3, int8 id4); // port=0-1 +void S9xGetController (int port, enum controllers *controller, int8 *id1, int8 *id2, int8 *id3, int8 *id4); +void S9xReportControllers (void); + +// Call this when you're done with S9xSetController, or if you change any of the controller Settings.*Master flags. +// Returns true if something was disabled. + +bool S9xVerifyControllers (void); + +// Functions for translation s9xcommand_t's into strings, and vice versa. +// free() the returned string after you're done with it. + +char * S9xGetCommandName (s9xcommand_t command); +s9xcommand_t S9xGetCommandT (const char *name); + +// Returns an array of strings naming all the snes9x commands. +// Note that this is only the strings for S9xButtonCommand! +// The idea is that this would be used for a pull-down list in a config GUI. DO NOT free() the returned value. + +const char ** S9xGetAllSnes9xCommands (void); + +// Generic mapping functions + +s9xcommand_t S9xGetMapping (uint32 id); +void S9xUnmapID (uint32 id); + +// Button mapping functions. +// If a button is mapped with poll=TRUE, then S9xPollButton will be called whenever snes9x feels a need for that mapping. +// Otherwise, snes9x will assume you will call S9xReportButton() whenever the button state changes. +// S9xMapButton() will fail and return FALSE if mapping.type isn't an S9xButton* type. + +bool S9xMapButton (uint32 id, s9xcommand_t mapping, bool poll); +void S9xReportButton (uint32 id, bool pressed); + +// Pointer mapping functions. +// If a pointer is mapped with poll=TRUE, then S9xPollPointer will be called whenever snes9x feels a need for that mapping. +// Otherwise, snes9x will assume you will call S9xReportPointer() whenever the pointer position changes. +// S9xMapPointer() will fail and return FALSE if mapping.type isn't an S9xPointer* type. + +// Note that position [0,0] is considered the upper-left corner of the 'screen', +// and either [255,223] or [255,239] is the lower-right. +// Note that the SNES mouse doesn't aim at a particular point, +// so the SNES's idea of where the mouse pointer is will probably differ from your OS's idea. + +bool S9xMapPointer (uint32 id, s9xcommand_t mapping, bool poll); +void S9xReportPointer (uint32 id, int16 x, int16 y); + +// Axis mapping functions. +// If an axis is mapped with poll=TRUE, then S9xPollAxis will be called whenever snes9x feels a need for that mapping. +// Otherwise, snes9x will assume you will call S9xReportAxis() whenever the axis deflection changes. +// S9xMapAxis() will fail and return FALSE if mapping.type isn't an S9xAxis* type. + +// Note that value is linear -32767 through 32767 with 0 being no deflection. +// If your axis reports differently you should transform the value before passing it to S9xReportAxis(). + +bool S9xMapAxis (uint32 id, s9xcommand_t mapping, bool poll); +void S9xReportAxis (uint32 id, int16 value); + +// Do whatever the s9xcommand_t says to do. +// If cmd.type is a button type, data1 should be TRUE (non-0) or FALSE (0) to indicate whether the 'button' is pressed or released. +// If cmd.type is an axis, data1 holds the deflection value. +// If cmd.type is a pointer, data1 and data2 are the positions of the pointer. + +void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2); + +////////// +// These functions are called by snes9x into your port, so each port should implement them. + +// If something was mapped with poll=TRUE, these functions will be called when snes9x needs the button/axis/pointer state. +// Fill in the reference options as appropriate. + +bool S9xPollButton (uint32 id, bool *pressed); +bool S9xPollPointer (uint32 id, int16 *x, int16 *y); +bool S9xPollAxis (uint32 id, int16 *value); + +// These are called when snes9x tries to apply a command with a S9x*Port type. +// data1 and data2 are filled in like S9xApplyCommand. + +void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2); + +// Called before already-read SNES joypad data is being used by the game if your port defines SNES_JOY_READ_CALLBACKS. + +#ifdef SNES_JOY_READ_CALLBACKS +void S9xOnSNESPadRead (void); +#endif + +// These are for your use. + +s9xcommand_t S9xGetPortCommandT (const char *name); +char * S9xGetPortCommandName (s9xcommand_t command); +void S9xSetupDefaultKeymap (void); +bool8 S9xMapInput (const char *name, s9xcommand_t *cmd); + +////////// +// These functions are called from snes9x into this subsystem. No need to use them from a port. + +// Use when resetting snes9x. + +void S9xControlsReset (void); +void S9xControlsSoftReset (void); + +// Use when writing to $4016. + +void S9xSetJoypadLatch (bool latch); + +// Use when reading $4016/7 (JOYSER0 and JOYSER1). + +uint8 S9xReadJOYSERn (int n); + +// End-Of-Frame processing. Sets gun latch variables and tries to draw crosshairs + +void S9xControlEOF (void); + +// Functions and a structure for snapshot. + +struct SControlSnapshot +{ + uint8 ver; + uint8 port1_read_idx[2]; + uint8 dummy1[4]; // for future expansion + uint8 port2_read_idx[2]; + uint8 dummy2[4]; + uint8 mouse_speed[2]; + uint8 justifier_select; + uint8 dummy3[8]; + bool8 pad_read, pad_read_last; + uint8 internal[60]; // yes, we need to save this! +}; + +void S9xControlPreSaveState (struct SControlSnapshot *s); +void S9xControlPostLoadState (struct SControlSnapshot *s); + +#endif diff --git a/cpu.cpp b/cpu.cpp new file mode 100644 index 00000000..91c986cf --- /dev/null +++ b/cpu.cpp @@ -0,0 +1,339 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "dma.h" +#include "apu/apu.h" +#include "fxemu.h" +#include "sdd1.h" +#include "srtc.h" +#include "snapshot.h" +#include "cheats.h" +#include "logger.h" +#ifdef DEBUGGER +#include "debug.h" +#endif + +static void S9xResetCPU (void); +static void S9xSoftResetCPU (void); + + +static void S9xResetCPU (void) +{ + S9xSoftResetCPU(); + Registers.SL = 0xff; + Registers.P.W = 0; + Registers.A.W = 0; + Registers.X.W = 0; + Registers.Y.W = 0; + SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); + ClearFlags(Decimal); +} + +static void S9xSoftResetCPU (void) +{ + Registers.PBPC = 0; + Registers.PB = 0; + Registers.PCw = S9xGetWord(0xfffc); + OpenBus = Registers.PCh; + Registers.D.W = 0; + Registers.DB = 0; + Registers.SH = 1; + Registers.SL -= 3; + Registers.XH = 0; + Registers.YH = 0; + + ICPU.ShiftedPB = 0; + ICPU.ShiftedDB = 0; + SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); + ClearFlags(Decimal); + + CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector. + CPU.PrevCycles = -1; + CPU.V_Counter = 0; + CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); + CPU.PCBase = NULL; + CPU.IRQActive = FALSE; + CPU.IRQPending = 0; + CPU.MemSpeed = SLOW_ONE_CYCLE; + CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2; + CPU.FastROMSpeed = SLOW_ONE_CYCLE; + CPU.InDMA = FALSE; + CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + CPU.InWRAMDMAorHDMA = FALSE; + CPU.HDMARanInDMA = 0; + CPU.CurrentDMAorHDMAChannel = -1; + CPU.WhichEvent = HC_RENDER_EVENT; + CPU.NextEvent = Timings.RenderPos; + CPU.WaitingForInterrupt = FALSE; + CPU.WaitAddress = 0xffffffff; + CPU.WaitCounter = 0; + CPU.PBPCAtOpcodeStart = 0xffffffff; + CPU.AutoSaveTimer = 0; + CPU.SRAMModified = FALSE; + + Timings.InterlaceField = FALSE; + Timings.H_Max = Timings.H_Max_Master; + Timings.V_Max = Timings.V_Max_Master; + Timings.NMITriggerPos = 0xffff; + if (Model->_5A22 == 2) + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; + else + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1; + + S9xSetPCBase(Registers.PBPC); + + ICPU.S9xOpcodes = S9xOpcodesE1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + ICPU.CPUExecuting = TRUE; + + S9xUnpackStatus(); +} + +void S9xReset (void) +{ + S9xResetSaveTimer(FALSE); + S9xResetLogger(); + + memset(Memory.RAM, 0x55, 0x20000); + memset(Memory.VRAM, 0x00, 0x10000); + ZeroMemory(Memory.FillRAM, 0x8000); + + if (Settings.BS) + S9xResetBSX(); + + S9xResetCPU(); + S9xResetPPU(); + S9xResetDMA(); + S9xResetAPU(); + + if (Settings.DSP) + S9xResetDSP(); + if (Settings.SuperFX) + S9xResetSuperFX(); + if (Settings.SA1) + S9xSA1Init(); + if (Settings.SDD1) + S9xResetSDD1(); + if (Settings.SPC7110) + S9xResetSPC7110(); + if (Settings.C4) + S9xInitC4(); + if (Settings.OBC1) + S9xResetOBC1(); + if (Settings.SRTC) + S9xResetSRTC(); + + S9xInitCheatData(); +} + +void S9xSoftReset (void) +{ + S9xResetSaveTimer(FALSE); + + memset(Memory.VRAM, 0x00, 0x10000); + ZeroMemory(Memory.FillRAM, 0x8000); + + if (Settings.BS) + S9xResetBSX(); + + S9xSoftResetCPU(); + S9xSoftResetPPU(); + S9xResetDMA(); + S9xSoftResetAPU(); + + if (Settings.DSP) + S9xResetDSP(); + if (Settings.SuperFX) + S9xResetSuperFX(); + if (Settings.SA1) + S9xSA1Init(); + if (Settings.SDD1) + S9xResetSDD1(); + if (Settings.SPC7110) + S9xResetSPC7110(); + if (Settings.C4) + S9xInitC4(); + if (Settings.OBC1) + S9xResetOBC1(); + if (Settings.SRTC) + S9xResetSRTC(); + + S9xInitCheatData(); +} diff --git a/cpuaddr.h b/cpuaddr.h new file mode 100644 index 00000000..3ae55c41 --- /dev/null +++ b/cpuaddr.h @@ -0,0 +1,690 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _CPUADDR_H_ +#define _CPUADDR_H_ + +typedef enum +{ + NONE = 0, + READ = 1, + WRITE = 2, + MODIFY = 3, + JUMP = 5, + JSR = 8 +} AccessMode; + +static inline uint8 Immediate8Slow (AccessMode a) +{ + uint8 val = S9xGetByte(Registers.PBPC); + if (a & READ) + OpenBus = val; + Registers.PCw++; + + return (val); +} + +static inline uint8 Immediate8 (AccessMode a) +{ + uint8 val = CPU.PCBase[Registers.PCw]; + if (a & READ) + OpenBus = val; + AddCycles(CPU.MemSpeed); + Registers.PCw++; + + return (val); +} + +static inline uint16 Immediate16Slow (AccessMode a) +{ + uint16 val = S9xGetWord(Registers.PBPC, WRAP_BANK); + if (a & READ) + OpenBus = (uint8) (val >> 8); + Registers.PCw += 2; + + return (val); +} + +static inline uint16 Immediate16 (AccessMode a) +{ + uint16 val = READ_WORD(CPU.PCBase + Registers.PCw); + if (a & READ) + OpenBus = (uint8) (val >> 8); + AddCycles(CPU.MemSpeedx2); + Registers.PCw += 2; + + return (val); +} + +static inline uint32 RelativeSlow (AccessMode a) // branch $xx +{ + int8 offset = Immediate8Slow(a); + + return ((int16) Registers.PCw + offset) & 0xffff; +} + +static inline uint32 Relative (AccessMode a) // branch $xx +{ + int8 offset = Immediate8(a); + + return ((int16) Registers.PCw + offset) & 0xffff; +} + +static inline uint32 RelativeLongSlow (AccessMode a) // BRL $xxxx +{ + int16 offset = Immediate16Slow(a); + + return ((int32) Registers.PCw + offset) & 0xffff; +} + +static inline uint32 RelativeLong (AccessMode a) // BRL $xxxx +{ + int16 offset = Immediate16(a); + + return ((int32) Registers.PCw + offset) & 0xffff; +} + +static inline uint32 AbsoluteIndexedIndirectSlow (AccessMode a) // (a,X) +{ + uint16 addr; + + if (a & JSR) + { + // JSR (a,X) pushes the old address in the middle of loading the new. + // OpenBus needs to be set to account for this. + addr = Immediate8Slow(READ); + if (a == JSR) + OpenBus = Registers.PCl; + addr |= Immediate8Slow(READ) << 8; + } + else + addr = Immediate16Slow(READ); + + AddCycles(ONE_CYCLE); + addr += Registers.X.W; + + // Address load wraps within the bank + uint16 addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK); + OpenBus = addr2 >> 8; + + return (addr2); +} + +static inline uint32 AbsoluteIndexedIndirect (AccessMode a) // (a,X) +{ + uint16 addr = Immediate16Slow(READ); + addr += Registers.X.W; + + // Address load wraps within the bank + uint16 addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK); + OpenBus = addr2 >> 8; + + return (addr2); +} + +static inline uint32 AbsoluteIndirectLongSlow (AccessMode a) // [a] +{ + uint16 addr = Immediate16Slow(READ); + + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint32 addr2 = S9xGetWord(addr); + OpenBus = addr2 >> 8; + addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; + + return (addr2); +} + +static inline uint32 AbsoluteIndirectLong (AccessMode a) // [a] +{ + uint16 addr = Immediate16(READ); + + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint32 addr2 = S9xGetWord(addr); + OpenBus = addr2 >> 8; + addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; + + return (addr2); +} + +static inline uint32 AbsoluteIndirectSlow (AccessMode a) // (a) +{ + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint16 addr2 = S9xGetWord(Immediate16Slow(READ)); + OpenBus = addr2 >> 8; + + return (addr2); +} + +static inline uint32 AbsoluteIndirect (AccessMode a) // (a) +{ + // No info on wrapping, but it doesn't matter anyway due to mirroring + uint16 addr2 = S9xGetWord(Immediate16(READ)); + OpenBus = addr2 >> 8; + + return (addr2); +} + +static inline uint32 AbsoluteSlow (AccessMode a) // a +{ + return (ICPU.ShiftedDB | Immediate16Slow(a)); +} + +static inline uint32 Absolute (AccessMode a) // a +{ + return (ICPU.ShiftedDB | Immediate16(a)); +} + +static inline uint32 AbsoluteLongSlow (AccessMode a) // l +{ + uint32 addr = Immediate16Slow(READ); + + // JSR l pushes the old bank in the middle of loading the new. + // OpenBus needs to be set to account for this. + if (a == JSR) + OpenBus = Registers.PB; + + addr |= Immediate8Slow(a) << 16; + + return (addr); +} + +static inline uint32 AbsoluteLong (AccessMode a) // l +{ + uint32 addr = READ_3WORD(CPU.PCBase + Registers.PCw); + AddCycles(CPU.MemSpeedx2 + CPU.MemSpeed); + if (a & READ) + OpenBus = addr >> 16; + Registers.PCw += 3; + + return (addr); +} + +static inline uint32 DirectSlow (AccessMode a) // d +{ + uint16 addr = Immediate8Slow(a) + Registers.D.W; + if (Registers.DL != 0) + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 Direct (AccessMode a) // d +{ + uint16 addr = Immediate8(a) + Registers.D.W; + if (Registers.DL != 0) + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 DirectIndirectSlow (AccessMode a) // (d) +{ + uint32 addr = S9xGetWord(DirectSlow(READ), (!CheckEmulation() || Registers.DL) ? WRAP_BANK : WRAP_PAGE); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + addr |= ICPU.ShiftedDB; + + return (addr); +} + +static inline uint32 DirectIndirectE0 (AccessMode a) // (d) +{ + uint32 addr = S9xGetWord(Direct(READ)); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + addr |= ICPU.ShiftedDB; + + return (addr); +} + +static inline uint32 DirectIndirectE1 (AccessMode a) // (d) +{ + uint32 addr = S9xGetWord(DirectSlow(READ), Registers.DL ? WRAP_BANK : WRAP_PAGE); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + addr |= ICPU.ShiftedDB; + + return (addr); +} + +static inline uint32 DirectIndirectIndexedSlow (AccessMode a) // (d),Y +{ + uint32 addr = DirectIndirectSlow(a); + if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.YL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 DirectIndirectIndexedE0X0 (AccessMode a) // (d),Y +{ + uint32 addr = DirectIndirectE0(a); + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 DirectIndirectIndexedE0X1 (AccessMode a) // (d),Y +{ + uint32 addr = DirectIndirectE0(a); + if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 DirectIndirectIndexedE1 (AccessMode a) // (d),Y +{ + uint32 addr = DirectIndirectE1(a); + if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 DirectIndirectLongSlow (AccessMode a) // [d] +{ + uint16 addr = DirectSlow(READ); + uint32 addr2 = S9xGetWord(addr); + OpenBus = addr2 >> 8; + addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; + + return (addr2); +} + +static inline uint32 DirectIndirectLong (AccessMode a) // [d] +{ + uint16 addr = Direct(READ); + uint32 addr2 = S9xGetWord(addr); + OpenBus = addr2 >> 8; + addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16; + + return (addr2); +} + +static inline uint32 DirectIndirectIndexedLongSlow (AccessMode a) // [d],Y +{ + return (DirectIndirectLongSlow(a) + Registers.Y.W); +} + +static inline uint32 DirectIndirectIndexedLong (AccessMode a) // [d],Y +{ + return (DirectIndirectLong(a) + Registers.Y.W); +} + +static inline uint32 DirectIndexedXSlow (AccessMode a) // d,X +{ + pair addr; + addr.W = DirectSlow(a); + if (!CheckEmulation() || Registers.DL) + addr.W += Registers.X.W; + else + addr.B.l += Registers.XL; + + AddCycles(ONE_CYCLE); + + return (addr.W); +} + +static inline uint32 DirectIndexedXE0 (AccessMode a) // d,X +{ + uint16 addr = Direct(a) + Registers.X.W; + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 DirectIndexedXE1 (AccessMode a) // d,X +{ + if (Registers.DL) + return (DirectIndexedXE0(a)); + else + { + pair addr; + addr.W = Direct(a); + addr.B.l += Registers.XL; + AddCycles(ONE_CYCLE); + + return (addr.W); + } +} + +static inline uint32 DirectIndexedYSlow (AccessMode a) // d,Y +{ + pair addr; + addr.W = DirectSlow(a); + if (!CheckEmulation() || Registers.DL) + addr.W += Registers.Y.W; + else + addr.B.l += Registers.YL; + + AddCycles(ONE_CYCLE); + + return (addr.W); +} + +static inline uint32 DirectIndexedYE0 (AccessMode a) // d,Y +{ + uint16 addr = Direct(a) + Registers.Y.W; + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 DirectIndexedYE1 (AccessMode a) // d,Y +{ + if (Registers.DL) + return (DirectIndexedYE0(a)); + else + { + pair addr; + addr.W = Direct(a); + addr.B.l += Registers.YL; + AddCycles(ONE_CYCLE); + + return (addr.W); + } +} + +static inline uint32 DirectIndexedIndirectSlow (AccessMode a) // (d,X) +{ + uint32 addr = S9xGetWord(DirectIndexedXSlow(READ), (!CheckEmulation() || Registers.DL) ? WRAP_BANK : WRAP_PAGE); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + + return (ICPU.ShiftedDB | addr); +} + +static inline uint32 DirectIndexedIndirectE0 (AccessMode a) // (d,X) +{ + uint32 addr = S9xGetWord(DirectIndexedXE0(READ)); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + + return (ICPU.ShiftedDB | addr); +} + +static inline uint32 DirectIndexedIndirectE1 (AccessMode a) // (d,X) +{ + uint32 addr = S9xGetWord(DirectIndexedXE1(READ), Registers.DL ? WRAP_BANK : WRAP_PAGE); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + + return (ICPU.ShiftedDB | addr); +} + +static inline uint32 AbsoluteIndexedXSlow (AccessMode a) // a,X +{ + uint32 addr = AbsoluteSlow(a); + if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.XL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.X.W); +} + +static inline uint32 AbsoluteIndexedXX0 (AccessMode a) // a,X +{ + uint32 addr = Absolute(a); + AddCycles(ONE_CYCLE); + + return (addr + Registers.X.W); +} + +static inline uint32 AbsoluteIndexedXX1 (AccessMode a) // a,X +{ + uint32 addr = Absolute(a); + if (a & WRITE || (addr & 0xff) + Registers.XL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.X.W); +} + +static inline uint32 AbsoluteIndexedYSlow (AccessMode a) // a,Y +{ + uint32 addr = AbsoluteSlow(a); + if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.YL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 AbsoluteIndexedYX0 (AccessMode a) // a,Y +{ + uint32 addr = Absolute(a); + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 AbsoluteIndexedYX1 (AccessMode a) // a,Y +{ + uint32 addr = Absolute(a); + if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100) + AddCycles(ONE_CYCLE); + + return (addr + Registers.Y.W); +} + +static inline uint32 AbsoluteLongIndexedXSlow (AccessMode a) // l,X +{ + return (AbsoluteLongSlow(a) + Registers.X.W); +} + +static inline uint32 AbsoluteLongIndexedX (AccessMode a) // l,X +{ + return (AbsoluteLong(a) + Registers.X.W); +} + +static inline uint32 StackRelativeSlow (AccessMode a) // d,S +{ + uint16 addr = Immediate8Slow(a) + Registers.S.W; + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 StackRelative (AccessMode a) // d,S +{ + uint16 addr = Immediate8(a) + Registers.S.W; + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 StackRelativeIndirectIndexedSlow (AccessMode a) // (d,S),Y +{ + uint32 addr = S9xGetWord(StackRelativeSlow(READ)); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + addr = (addr + Registers.Y.W + ICPU.ShiftedDB) & 0xffffff; + AddCycles(ONE_CYCLE); + + return (addr); +} + +static inline uint32 StackRelativeIndirectIndexed (AccessMode a) // (d,S),Y +{ + uint32 addr = S9xGetWord(StackRelative(READ)); + if (a & READ) + OpenBus = (uint8) (addr >> 8); + addr = (addr + Registers.Y.W + ICPU.ShiftedDB) & 0xffffff; + AddCycles(ONE_CYCLE); + + return (addr); +} + +#endif diff --git a/cpuexec.cpp b/cpuexec.cpp new file mode 100644 index 00000000..d7f22db9 --- /dev/null +++ b/cpuexec.cpp @@ -0,0 +1,565 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "dma.h" +#include "apu/apu.h" +#include "fxemu.h" +#include "snapshot.h" +#ifdef DEBUGGER +#include "debug.h" +#include "missing.h" +#endif + + +void S9xMainLoop (void) +{ + for (;;) + { + if (CPU.Flags) + { + if (CPU.Flags & NMI_FLAG) + { + if (Timings.NMITriggerPos <= CPU.Cycles) + { + CPU.Flags &= ~NMI_FLAG; + Timings.NMITriggerPos = 0xffff; + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + Registers.PCw++; + } + + S9xOpcode_NMI(); + } + } + + #ifdef DEBUGGER + if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG)) + { + for (int Break = 0; Break != 6; Break++) + { + if (S9xBreakpoint[Break].Enabled && + S9xBreakpoint[Break].Bank == Registers.PB && + S9xBreakpoint[Break].Address == Registers.PCw) + { + if (S9xBreakpoint[Break].Enabled == 2) + S9xBreakpoint[Break].Enabled = TRUE; + else + CPU.Flags |= DEBUG_MODE_FLAG; + } + } + } + #endif + + if (CPU.Flags & IRQ_FLAG) + { + if (CPU.IRQPending) + // FIXME: In case of IRQ during WRAM refresh + CPU.IRQPending--; + else + { + if (CPU.WaitingForInterrupt) + { + CPU.WaitingForInterrupt = FALSE; + Registers.PCw++; + } + + if (CPU.IRQActive && !Settings.DisableIRQ) + { + if (!CheckFlag(IRQ)) + // in IRQ handler $4211 is supposed to be read, so IRQ_FLAG should be cleared. + S9xOpcode_IRQ(); + } + else + CPU.Flags &= ~IRQ_FLAG; + } + } + + if (CPU.Flags & SCAN_KEYS_FLAG) + break; + + #ifdef DEBUGGER + if (CPU.Flags & DEBUG_MODE_FLAG) + break; + + if (CPU.Flags & TRACE_FLAG) + S9xTrace(); + + if (CPU.Flags & SINGLE_STEP_FLAG) + { + CPU.Flags &= ~SINGLE_STEP_FLAG; + CPU.Flags |= DEBUG_MODE_FLAG; + } + #endif + } + + #ifdef CPU_SHUTDOWN + CPU.PBPCAtOpcodeStart = Registers.PBPC; + #endif + + register uint8 Op; + register struct SOpcodes *Opcodes; + + CPU.PrevCycles = CPU.Cycles; + + if (CPU.PCBase) + { + Op = CPU.PCBase[Registers.PCw]; + CPU.Cycles += CPU.MemSpeed; + Opcodes = ICPU.S9xOpcodes; + } + else + { + Op = S9xGetByte(Registers.PBPC); + OpenBus = Op; + Opcodes = S9xOpcodesSlow; + } + + if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) + { + uint8 *oldPCBase = CPU.PCBase; + + CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16) (Registers.PCw + 4))); + if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK)) + Opcodes = S9xOpcodesSlow; + } + + Registers.PCw++; + (*Opcodes[Op].S9xOpcode)(); + + if (SA1.Executing) + S9xSA1MainLoop(); + + while (CPU.Cycles >= CPU.NextEvent) + S9xDoHEventProcessing(); + } + + S9xPackStatus(); + + if (CPU.Flags & SCAN_KEYS_FLAG) + { + #ifdef DEBUGGER + if (!(CPU.Flags & FRAME_ADVANCE_FLAG)) + #endif + S9xSyncSpeed(); + CPU.Flags &= ~SCAN_KEYS_FLAG; + } +} + +void S9xSetIRQ (uint32 source) +{ + CPU.IRQActive |= source; + CPU.IRQPending = Timings.IRQPendCount; + CPU.Flags |= IRQ_FLAG; + + if (CPU.WaitingForInterrupt) + { + // Force IRQ to trigger immediately after WAI - + // Final Fantasy Mystic Quest crashes without this. + CPU.WaitingForInterrupt = FALSE; + Registers.PCw++; + } + +#ifdef DEBUGGER + S9xTraceMessage("--- /IRQ low"); +#endif +} + +void S9xClearIRQ (uint32 source) +{ + CPU.IRQActive &= ~source; + if (!CPU.IRQActive) + CPU.Flags &= ~IRQ_FLAG; + +#ifdef DEBUGGER + S9xTraceMessage("--- /IRQ high"); +#endif +} + +void S9xDoHEventProcessing (void) +{ +#ifdef DEBUGGER + if (Settings.TraceHCEvent) + S9xTraceFormattedMessage("--- HC event processing (%02d) expected HC:%04d executed HC:%04d", + CPU.WhichEvent, CPU.NextEvent, CPU.Cycles); +#endif + +#ifdef CPU_SHUTDOWN + CPU.WaitCounter++; +#endif + + switch (CPU.WhichEvent) + { + case HC_HBLANK_START_EVENT: + S9xCheckMissingHTimerPosition(Timings.HBlankStart); + + break; + + case HC_HDMA_START_EVENT: + if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) + { + #ifdef DEBUGGER + S9xTraceFormattedMessage("*** HDMA HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); + #endif + PPU.HDMA = S9xDoHDMA(PPU.HDMA); + } + + S9xCheckMissingHTimerPosition(Timings.HDMAStart); + + break; + + case HC_HCOUNTER_MAX_EVENT: + #ifndef ZSNES_FX + if (Settings.SuperFX) + { + if (!SuperFX.oneLineDone) + S9xSuperFXExec(); + SuperFX.oneLineDone = FALSE; + } + #else + S9xSuperFXExec(); + #endif + + S9xAPUEndScanline(); + CPU.Cycles -= Timings.H_Max; + S9xAPUSetReferenceTime(CPU.Cycles); + + if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max)) + Timings.NMITriggerPos -= Timings.H_Max; + + CPU.V_Counter++; + if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1 + { + CPU.V_Counter = 0; + Timings.InterlaceField ^= 1; + + // From byuu: + // [NTSC] + // interlace mode has 525 scanlines: 263 on the even frame, and 262 on the odd. + // non-interlace mode has 524 scanlines: 262 scanlines on both even and odd frames. + // [PAL] + // interlace mode has 625 scanlines: 313 on the even frame, and 312 on the odd. + // non-interlace mode has 624 scanlines: 312 scanlines on both even and odd frames. + if (IPPU.Interlace && !Timings.InterlaceField) + Timings.V_Max = Timings.V_Max_Master + 1; // 263 (NTSC), 313?(PAL) + else + Timings.V_Max = Timings.V_Max_Master; // 262 (NTSC), 312?(PAL) + + Memory.FillRAM[0x213F] ^= 0x80; + PPU.RangeTimeOver = 0; + + // FIXME: reading $4210 will wait 2 cycles, then perform reading, then wait 4 more cycles. + Memory.FillRAM[0x4210] = Model->_5A22; + CPU.Flags &= ~NMI_FLAG; + Timings.NMITriggerPos = 0xffff; + + ICPU.Frame++; + PPU.HVBeamCounterLatched = 0; + CPU.Flags |= SCAN_KEYS_FLAG; + } + + // From byuu: + // In non-interlace mode, there are 341 dots per scanline, and 262 scanlines per frame. + // On odd frames, scanline 240 is one dot short. + // In interlace mode, there are always 341 dots per scanline. Even frames have 263 scanlines, + // and odd frames have 262 scanlines. + // Interlace mode scanline 240 on odd frames is not missing a dot. + if (CPU.V_Counter == 240 && !IPPU.Interlace && Timings.InterlaceField) // V=240 + Timings.H_Max = Timings.H_Max_Master - ONE_DOT_CYCLE; // HC=1360 + else + Timings.H_Max = Timings.H_Max_Master; // HC=1364 + + if (Model->_5A22 == 2) + { + if (CPU.V_Counter != 240 || IPPU.Interlace || !Timings.InterlaceField) // V=240 + { + if (Timings.WRAMRefreshPos == SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE) // HC=534 + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; // HC=538 + else + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE; // HC=534 + } + } + else + Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1; + + S9xCheckMissingHTimerPosition(0); + + if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240). + { + S9xEndScreenRefresh(); + PPU.HDMA = 0; + // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU. + #ifdef DEBUGGER + missing.dma_this_frame = 0; + #endif + IPPU.MaxBrightness = PPU.Brightness; + PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; + + if (!PPU.ForcedBlanking) + { + PPU.OAMAddr = PPU.SavedOAMAddr; + + uint8 tmp = 0; + + if (PPU.OAMPriorityRotation) + tmp = (PPU.OAMAddr & 0xFE) >> 1; + if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp) + { + PPU.FirstSprite = tmp; + IPPU.OBJChanged = TRUE; + } + + PPU.OAMFlip = 0; + } + + // FIXME: writing to $4210 will wait 6 cycles. + Memory.FillRAM[0x4210] = 0x80 | Model->_5A22; + if (Memory.FillRAM[0x4200] & 0x80) + { + // FIXME: triggered at HC=6, checked just before the final CPU cycle, + // then, when to call S9xOpcode_NMI()? + CPU.Flags |= NMI_FLAG; + Timings.NMITriggerPos = 6 + 6; + } + + } + + if (CPU.V_Counter == PPU.ScreenHeight + 3) // FIXME: not true + { + if (Memory.FillRAM[0x4200] & 1) + S9xDoAutoJoypad(); + } + + if (CPU.V_Counter == FIRST_VISIBLE_LINE) // V=1 + S9xStartScreenRefresh(); + + CPU.NextEvent = -1; + + break; + + case HC_HDMA_INIT_EVENT: + if (CPU.V_Counter == 0) + S9xStartHDMA(); + + S9xCheckMissingHTimerPosition(Timings.HDMAInit); + + break; + + case HC_RENDER_EVENT: + if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter <= PPU.ScreenHeight) + RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE)); + + S9xCheckMissingHTimerPosition(Timings.RenderPos); + + break; + + case HC_WRAM_REFRESH_EVENT: + #ifdef DEBUGGER + S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles); + #endif + S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES); + CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; + + S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos); + + break; + + case HC_IRQ_1_3_EVENT: + case HC_IRQ_3_5_EVENT: + case HC_IRQ_5_7_EVENT: + case HC_IRQ_7_9_EVENT: + case HC_IRQ_9_A_EVENT: + case HC_IRQ_A_1_EVENT: + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) + S9xSetIRQ(PPU_IRQ_SOURCE); + else + if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) + S9xSetIRQ(PPU_IRQ_SOURCE); + + break; + } + + S9xReschedule(); + +#ifdef DEBUGGER + if (Settings.TraceHCEvent) + S9xTraceFormattedMessage("--- HC event rescheduled (%02d) expected HC:%04d", CPU.WhichEvent, CPU.NextEvent); +#endif +} diff --git a/cpuexec.h b/cpuexec.h new file mode 100644 index 00000000..b11cff61 --- /dev/null +++ b/cpuexec.h @@ -0,0 +1,353 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _CPUEXEC_H_ +#define _CPUEXEC_H_ + +#include "ppu.h" + +struct SOpcodes +{ + void (*S9xOpcode) (void); +}; + +struct SICPU +{ + struct SOpcodes *S9xOpcodes; + uint8 *S9xOpLengths; + uint8 _Carry; + uint8 _Zero; + uint8 _Negative; + uint8 _Overflow; + bool8 CPUExecuting; + uint32 ShiftedPB; + uint32 ShiftedDB; + uint32 Frame; + uint32 FrameAdvanceCount; +}; + +extern struct SICPU ICPU; + +extern struct SOpcodes S9xOpcodesE1[256]; +extern struct SOpcodes S9xOpcodesM1X1[256]; +extern struct SOpcodes S9xOpcodesM1X0[256]; +extern struct SOpcodes S9xOpcodesM0X1[256]; +extern struct SOpcodes S9xOpcodesM0X0[256]; +extern struct SOpcodes S9xOpcodesSlow[256]; +extern uint8 S9xOpLengthsM1X1[256]; +extern uint8 S9xOpLengthsM1X0[256]; +extern uint8 S9xOpLengthsM0X1[256]; +extern uint8 S9xOpLengthsM0X0[256]; + +void S9xMainLoop (void); +void S9xReset (void); +void S9xSoftReset (void); +void S9xDoHEventProcessing (void); +void S9xClearIRQ (uint32); +void S9xSetIRQ (uint32); + +static inline void S9xUnpackStatus (void) +{ + ICPU._Zero = (Registers.PL & Zero) == 0; + ICPU._Negative = (Registers.PL & Negative); + ICPU._Carry = (Registers.PL & Carry); + ICPU._Overflow = (Registers.PL & Overflow) >> 6; +} + +static inline void S9xPackStatus (void) +{ + Registers.PL &= ~(Zero | Negative | Carry | Overflow); + Registers.PL |= ICPU._Carry | ((ICPU._Zero == 0) << 1) | (ICPU._Negative & 0x80) | (ICPU._Overflow << 6); +} + +static inline void S9xFixCycles (void) +{ + if (CheckEmulation()) + { + ICPU.S9xOpcodes = S9xOpcodesE1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + } + else + if (CheckMemory()) + { + if (CheckIndex()) + { + ICPU.S9xOpcodes = S9xOpcodesM1X1; + ICPU.S9xOpLengths = S9xOpLengthsM1X1; + } + else + { + ICPU.S9xOpcodes = S9xOpcodesM1X0; + ICPU.S9xOpLengths = S9xOpLengthsM1X0; + } + } + else + { + if (CheckIndex()) + { + ICPU.S9xOpcodes = S9xOpcodesM0X1; + ICPU.S9xOpLengths = S9xOpLengthsM0X1; + } + else + { + ICPU.S9xOpcodes = S9xOpcodesM0X0; + ICPU.S9xOpLengths = S9xOpLengthsM0X0; + } + } +} + +static inline void S9xReschedule (void) +{ + uint8 next = 0; + int32 hpos = 0; + + switch (CPU.WhichEvent) + { + case HC_HBLANK_START_EVENT: + case HC_IRQ_1_3_EVENT: + next = HC_HDMA_START_EVENT; + hpos = Timings.HDMAStart; + break; + + case HC_HDMA_START_EVENT: + case HC_IRQ_3_5_EVENT: + next = HC_HCOUNTER_MAX_EVENT; + hpos = Timings.H_Max; + break; + + case HC_HCOUNTER_MAX_EVENT: + case HC_IRQ_5_7_EVENT: + next = HC_HDMA_INIT_EVENT; + hpos = Timings.HDMAInit; + break; + + case HC_HDMA_INIT_EVENT: + case HC_IRQ_7_9_EVENT: + next = HC_RENDER_EVENT; + hpos = Timings.RenderPos; + break; + + case HC_RENDER_EVENT: + case HC_IRQ_9_A_EVENT: + next = HC_WRAM_REFRESH_EVENT; + hpos = Timings.WRAMRefreshPos; + break; + + case HC_WRAM_REFRESH_EVENT: + case HC_IRQ_A_1_EVENT: + next = HC_HBLANK_START_EVENT; + hpos = Timings.HBlankStart; + break; + } + + if (((int32) PPU.HTimerPosition > CPU.NextEvent) && ((int32) PPU.HTimerPosition < hpos)) + { + hpos = (int32) PPU.HTimerPosition; + + switch (next) + { + case HC_HDMA_START_EVENT: + next = HC_IRQ_1_3_EVENT; + break; + + case HC_HCOUNTER_MAX_EVENT: + next = HC_IRQ_3_5_EVENT; + break; + + case HC_HDMA_INIT_EVENT: + next = HC_IRQ_5_7_EVENT; + break; + + case HC_RENDER_EVENT: + next = HC_IRQ_7_9_EVENT; + break; + + case HC_WRAM_REFRESH_EVENT: + next = HC_IRQ_9_A_EVENT; + break; + + case HC_HBLANK_START_EVENT: + next = HC_IRQ_A_1_EVENT; + break; + } + } + + CPU.NextEvent = hpos; + CPU.WhichEvent = next; +} + +#endif diff --git a/cpumacro.h b/cpumacro.h new file mode 100644 index 00000000..9b1fc4cb --- /dev/null +++ b/cpumacro.h @@ -0,0 +1,904 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _CPUMACRO_H_ +#define _CPUMACRO_H_ + +#define rOP8(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + uint8 val = OpenBus = S9xGetByte(ADDR(READ)); \ + FUNC(val); \ +} + +#define rOP16(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + uint16 val = S9xGetWord(ADDR(READ), WRAP); \ + OpenBus = (uint8) (val >> 8); \ + FUNC(val); \ +} + +#define rOPC(OP, COND, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + if (Check##COND()) \ + { \ + uint8 val = OpenBus = S9xGetByte(ADDR(READ)); \ + FUNC(val); \ + } \ + else \ + { \ + uint16 val = S9xGetWord(ADDR(READ), WRAP); \ + OpenBus = (uint8) (val >> 8); \ + FUNC(val); \ + } \ +} + +#define rOPM(OP, ADDR, WRAP, FUNC) \ +rOPC(OP, Memory, ADDR, WRAP, FUNC) + +#define rOPX(OP, ADDR, WRAP, FUNC) \ +rOPC(OP, Index, ADDR, WRAP, FUNC) + +#define wOP8(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + FUNC##8(ADDR(WRITE)); \ +} + +#define wOP16(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + FUNC##16(ADDR(WRITE), WRAP); \ +} + +#define wOPC(OP, COND, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + if (Check##COND()) \ + FUNC##8(ADDR(WRITE)); \ + else \ + FUNC##16(ADDR(WRITE), WRAP); \ +} + +#define wOPM(OP, ADDR, WRAP, FUNC) \ +wOPC(OP, Memory, ADDR, WRAP, FUNC) + +#define wOPX(OP, ADDR, WRAP, FUNC) \ +wOPC(OP, Index, ADDR, WRAP, FUNC) + +#define mOP8(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + FUNC##8(ADDR(MODIFY)); \ +} + +#define mOP16(OP, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + FUNC##16(ADDR(MODIFY), WRAP); \ +} + +#define mOPC(OP, COND, ADDR, WRAP, FUNC) \ +static void Op##OP (void) \ +{ \ + if (Check##COND()) \ + FUNC##8(ADDR(MODIFY)); \ + else \ + FUNC##16(ADDR(MODIFY), WRAP); \ +} + +#define mOPM(OP, ADDR, WRAP, FUNC) \ +mOPC(OP, Memory, ADDR, WRAP, FUNC) + +#define bOP(OP, REL, COND, CHK, E) \ +static void Op##OP (void) \ +{ \ + pair newPC; \ + newPC.W = REL(JUMP); \ + if (COND) \ + { \ + AddCycles(ONE_CYCLE); \ + if (E && Registers.PCh != newPC.B.h) \ + AddCycles(ONE_CYCLE); \ + if ((Registers.PCw & ~MEMMAP_MASK) != (newPC.W & ~MEMMAP_MASK)) \ + S9xSetPCBase(ICPU.ShiftedPB + newPC.W); \ + else \ + Registers.PCw = newPC.W; \ + CPUShutdown(); \ + } \ +} + + +static inline void SetZN (uint16 Work16) +{ + ICPU._Zero = Work16 != 0; + ICPU._Negative = (uint8) (Work16 >> 8); +} + +static inline void SetZN (uint8 Work8) +{ + ICPU._Zero = Work8; + ICPU._Negative = Work8; +} + +static inline void ADC (uint16 Work16) +{ + if (CheckDecimal()) + { + uint16 A1 = Registers.A.W & 0x000F; + uint16 A2 = Registers.A.W & 0x00F0; + uint16 A3 = Registers.A.W & 0x0F00; + uint32 A4 = Registers.A.W & 0xF000; + uint16 W1 = Work16 & 0x000F; + uint16 W2 = Work16 & 0x00F0; + uint16 W3 = Work16 & 0x0F00; + uint16 W4 = Work16 & 0xF000; + + A1 += W1 + CheckCarry(); + if (A1 > 0x0009) + { + A1 -= 0x000A; + A1 &= 0x000F; + A2 += 0x0010; + } + + A2 += W2; + if (A2 > 0x0090) + { + A2 -= 0x00A0; + A2 &= 0x00F0; + A3 += 0x0100; + } + + A3 += W3; + if (A3 > 0x0900) + { + A3 -= 0x0A00; + A3 &= 0x0F00; + A4 += 0x1000; + } + + A4 += W4; + if (A4 > 0x9000) + { + A4 -= 0xA000; + A4 &= 0xF000; + SetCarry(); + } + else + ClearCarry(); + + uint16 Ans16 = A4 | A3 | A2 | A1; + + if (~(Registers.A.W ^ Work16) & (Work16 ^ Ans16) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + + Registers.A.W = Ans16; + SetZN(Registers.A.W); + } + else + { + uint32 Ans32 = Registers.A.W + Work16 + CheckCarry(); + + ICPU._Carry = Ans32 >= 0x10000; + + if (~(Registers.A.W ^ Work16) & (Work16 ^ (uint16) Ans32) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + + Registers.A.W = (uint16) Ans32; + SetZN(Registers.A.W); + } +} + +static inline void ADC (uint8 Work8) +{ + if (CheckDecimal()) + { + uint8 A1 = Registers.A.W & 0x0F; + uint16 A2 = Registers.A.W & 0xF0; + uint8 W1 = Work8 & 0x0F; + uint8 W2 = Work8 & 0xF0; + + A1 += W1 + CheckCarry(); + if (A1 > 0x09) + { + A1 -= 0x0A; + A1 &= 0x0F; + A2 += 0x10; + } + + A2 += W2; + if (A2 > 0x90) + { + A2 -= 0xA0; + A2 &= 0xF0; + SetCarry(); + } + else + ClearCarry(); + + uint8 Ans8 = A2 | A1; + + if (~(Registers.AL ^ Work8) & (Work8 ^ Ans8) & 0x80) + SetOverflow(); + else + ClearOverflow(); + + Registers.AL = Ans8; + SetZN(Registers.AL); + } + else + { + uint16 Ans16 = Registers.AL + Work8 + CheckCarry(); + + ICPU._Carry = Ans16 >= 0x100; + + if (~(Registers.AL ^ Work8) & (Work8 ^ (uint8) Ans16) & 0x80) + SetOverflow(); + else + ClearOverflow(); + + Registers.AL = (uint8) Ans16; + SetZN(Registers.AL); + } +} + +static inline void AND (uint16 Work16) +{ + Registers.A.W &= Work16; + SetZN(Registers.A.W); +} + +static inline void AND (uint8 Work8) +{ + Registers.AL &= Work8; + SetZN(Registers.AL); +} + +static inline void ASL16 (uint32 OpAddress, s9xwrap_t w) +{ + uint16 Work16 = S9xGetWord(OpAddress, w); + ICPU._Carry = (Work16 & 0x8000) != 0; + Work16 <<= 1; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; + SetZN(Work16); +} + +static inline void ASL8 (uint32 OpAddress) +{ + uint8 Work8 = S9xGetByte(OpAddress); + ICPU._Carry = (Work8 & 0x80) != 0; + Work8 <<= 1; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; + SetZN(Work8); +} + +static inline void BIT (uint16 Work16) +{ + ICPU._Overflow = (Work16 & 0x4000) != 0; + ICPU._Negative = (uint8) (Work16 >> 8); + ICPU._Zero = (Work16 & Registers.A.W) != 0; +} + +static inline void BIT (uint8 Work8) +{ + ICPU._Overflow = (Work8 & 0x40) != 0; + ICPU._Negative = Work8; + ICPU._Zero = Work8 & Registers.AL; +} + +static inline void CMP (uint16 val) +{ + int32 Int32 = (int32) Registers.A.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static inline void CMP (uint8 val) +{ + int16 Int16 = (int16) Registers.AL - (int16) val; + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static inline void CPX (uint16 val) +{ + int32 Int32 = (int32) Registers.X.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static inline void CPX (uint8 val) +{ + int16 Int16 = (int16) Registers.XL - (int16) val; + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static inline void CPY (uint16 val) +{ + int32 Int32 = (int32) Registers.Y.W - (int32) val; + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static inline void CPY (uint8 val) +{ + int16 Int16 = (int16) Registers.YL - (int16) val; + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static inline void DEC16 (uint32 OpAddress, s9xwrap_t w) +{ +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + uint16 Work16 = S9xGetWord(OpAddress, w) - 1; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; + SetZN(Work16); +} + +static inline void DEC8 (uint32 OpAddress) +{ +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + uint8 Work8 = S9xGetByte(OpAddress) - 1; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; + SetZN(Work8); +} + +static inline void EOR (uint16 val) +{ + Registers.A.W ^= val; + SetZN(Registers.A.W); +} + +static inline void EOR (uint8 val) +{ + Registers.AL ^= val; + SetZN(Registers.AL); +} + +static inline void INC16 (uint32 OpAddress, s9xwrap_t w) +{ +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + uint16 Work16 = S9xGetWord(OpAddress, w) + 1; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; + SetZN(Work16); +} + +static inline void INC8 (uint32 OpAddress) +{ +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + uint8 Work8 = S9xGetByte(OpAddress) + 1; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; + SetZN(Work8); +} + +static inline void LDA (uint16 val) +{ + Registers.A.W = val; + SetZN(Registers.A.W); +} + +static inline void LDA (uint8 val) +{ + Registers.AL = val; + SetZN(Registers.AL); +} + +static inline void LDX (uint16 val) +{ + Registers.X.W = val; + SetZN(Registers.X.W); +} + +static inline void LDX (uint8 val) +{ + Registers.XL = val; + SetZN(Registers.XL); +} + +static inline void LDY (uint16 val) +{ + Registers.Y.W = val; + SetZN(Registers.Y.W); +} + +static inline void LDY (uint8 val) +{ + Registers.YL = val; + SetZN(Registers.YL); +} + +static inline void LSR16 (uint32 OpAddress, s9xwrap_t w) +{ + uint16 Work16 = S9xGetWord(OpAddress, w); + ICPU._Carry = Work16 & 1; + Work16 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; + SetZN(Work16); +} + +static inline void LSR8 (uint32 OpAddress) +{ + uint8 Work8 = S9xGetByte(OpAddress); + ICPU._Carry = Work8 & 1; + Work8 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; + SetZN(Work8); +} + +static inline void ORA (uint16 val) +{ + Registers.A.W |= val; + SetZN(Registers.A.W); +} + +static inline void ORA (uint8 val) +{ + Registers.AL |= val; + SetZN(Registers.AL); +} + +static inline void ROL16 (uint32 OpAddress, s9xwrap_t w) +{ + uint32 Work32 = (((uint32) S9xGetWord(OpAddress, w)) << 1) | CheckCarry(); + ICPU._Carry = Work32 >= 0x10000; + AddCycles(ONE_CYCLE); + S9xSetWord((uint16) Work32, OpAddress, w, WRITE_10); + OpenBus = Work32 & 0xff; + SetZN((uint16) Work32); +} + +static inline void ROL8 (uint32 OpAddress) +{ + uint16 Work16 = (((uint16) S9xGetByte(OpAddress)) << 1) | CheckCarry(); + ICPU._Carry = Work16 >= 0x100; + AddCycles(ONE_CYCLE); + S9xSetByte((uint8) Work16, OpAddress); + OpenBus = Work16 & 0xff; + SetZN((uint8) Work16); +} + +static inline void ROR16 (uint32 OpAddress, s9xwrap_t w) +{ + uint32 Work32 = ((uint32) S9xGetWord(OpAddress, w)) | (((uint32) CheckCarry()) << 16); + ICPU._Carry = Work32 & 1; + Work32 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetWord((uint16) Work32, OpAddress, w, WRITE_10); + OpenBus = Work32 & 0xff; + SetZN((uint16) Work32); +} + +static inline void ROR8 (uint32 OpAddress) +{ + uint16 Work16 = ((uint16) S9xGetByte(OpAddress)) | (((uint16) CheckCarry()) << 8); + ICPU._Carry = Work16 & 1; + Work16 >>= 1; + AddCycles(ONE_CYCLE); + S9xSetByte((uint8) Work16, OpAddress); + OpenBus = Work16 & 0xff; + SetZN((uint8) Work16); +} + +static inline void SBC (uint16 Work16) +{ + if (CheckDecimal()) + { + uint16 A1 = Registers.A.W & 0x000F; + uint16 A2 = Registers.A.W & 0x00F0; + uint16 A3 = Registers.A.W & 0x0F00; + uint32 A4 = Registers.A.W & 0xF000; + uint16 W1 = Work16 & 0x000F; + uint16 W2 = Work16 & 0x00F0; + uint16 W3 = Work16 & 0x0F00; + uint16 W4 = Work16 & 0xF000; + + A1 -= W1 + !CheckCarry(); + A2 -= W2; + A3 -= W3; + A4 -= W4; + + if (A1 > 0x000F) + { + A1 += 0x000A; + A1 &= 0x000F; + A2 -= 0x0010; + } + + if (A2 > 0x00F0) + { + A2 += 0x00A0; + A2 &= 0x00F0; + A3 -= 0x0100; + } + + if (A3 > 0x0F00) + { + A3 += 0x0A00; + A3 &= 0x0F00; + A4 -= 0x1000; + } + + if (A4 > 0xF000) + { + A4 += 0xA000; + A4 &= 0xF000; + ClearCarry(); + } + else + SetCarry(); + + uint16 Ans16 = A4 | A3 | A2 | A1; + + if ((Registers.A.W ^ Work16) & (Registers.A.W ^ Ans16) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + + Registers.A.W = Ans16; + SetZN(Registers.A.W); + } + else + { + int32 Int32 = (int32) Registers.A.W - (int32) Work16 + (int32) CheckCarry() - 1; + + ICPU._Carry = Int32 >= 0; + + if ((Registers.A.W ^ Work16) & (Registers.A.W ^ (uint16) Int32) & 0x8000) + SetOverflow(); + else + ClearOverflow(); + + Registers.A.W = (uint16) Int32; + SetZN(Registers.A.W); + } +} + +static inline void SBC (uint8 Work8) +{ + if (CheckDecimal()) + { + uint8 A1 = Registers.A.W & 0x0F; + uint16 A2 = Registers.A.W & 0xF0; + uint8 W1 = Work8 & 0x0F; + uint8 W2 = Work8 & 0xF0; + + A1 -= W1 + !CheckCarry(); + A2 -= W2; + + if (A1 > 0x0F) + { + A1 += 0x0A; + A1 &= 0x0F; + A2 -= 0x10; + } + + if (A2 > 0xF0) + { + A2 += 0xA0; + A2 &= 0xF0; + ClearCarry(); + } + else + SetCarry(); + + uint8 Ans8 = A2 | A1; + + if ((Registers.AL ^ Work8) & (Registers.AL ^ Ans8) & 0x80) + SetOverflow(); + else + ClearOverflow(); + + Registers.AL = Ans8; + SetZN(Registers.AL); + } + else + { + int16 Int16 = (int16) Registers.AL - (int16) Work8 + (int16) CheckCarry() - 1; + + ICPU._Carry = Int16 >= 0; + + if ((Registers.AL ^ Work8) & (Registers.AL ^ (uint8) Int16) & 0x80) + SetOverflow(); + else + ClearOverflow(); + + Registers.AL = (uint8) Int16; + SetZN(Registers.AL); + } +} + +static inline void STA16 (uint32 OpAddress, enum s9xwrap_t w) +{ + S9xSetWord(Registers.A.W, OpAddress, w); + OpenBus = Registers.AH; +} + +static inline void STA8 (uint32 OpAddress) +{ + S9xSetByte(Registers.AL, OpAddress); + OpenBus = Registers.AL; +} + +static inline void STX16 (uint32 OpAddress, enum s9xwrap_t w) +{ + S9xSetWord(Registers.X.W, OpAddress, w); + OpenBus = Registers.XH; +} + +static inline void STX8 (uint32 OpAddress) +{ + S9xSetByte(Registers.XL, OpAddress); + OpenBus = Registers.XL; +} + +static inline void STY16 (uint32 OpAddress, enum s9xwrap_t w) +{ + S9xSetWord(Registers.Y.W, OpAddress, w); + OpenBus = Registers.YH; +} + +static inline void STY8 (uint32 OpAddress) +{ + S9xSetByte(Registers.YL, OpAddress); + OpenBus = Registers.YL; +} + +static inline void STZ16 (uint32 OpAddress, enum s9xwrap_t w) +{ + S9xSetWord(0, OpAddress, w); + OpenBus = 0; +} + +static inline void STZ8 (uint32 OpAddress) +{ + S9xSetByte(0, OpAddress); + OpenBus = 0; +} + +static inline void TSB16 (uint32 OpAddress, enum s9xwrap_t w) +{ + uint16 Work16 = S9xGetWord(OpAddress, w); + ICPU._Zero = (Work16 & Registers.A.W) != 0; + Work16 |= Registers.A.W; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; +} + +static inline void TSB8 (uint32 OpAddress) +{ + uint8 Work8 = S9xGetByte(OpAddress); + ICPU._Zero = Work8 & Registers.AL; + Work8 |= Registers.AL; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; +} + +static inline void TRB16 (uint32 OpAddress, enum s9xwrap_t w) +{ + uint16 Work16 = S9xGetWord(OpAddress, w); + ICPU._Zero = (Work16 & Registers.A.W) != 0; + Work16 &= ~Registers.A.W; + AddCycles(ONE_CYCLE); + S9xSetWord(Work16, OpAddress, w, WRITE_10); + OpenBus = Work16 & 0xff; +} + +static inline void TRB8 (uint32 OpAddress) +{ + uint8 Work8 = S9xGetByte(OpAddress); + ICPU._Zero = Work8 & Registers.AL; + Work8 &= ~Registers.AL; + AddCycles(ONE_CYCLE); + S9xSetByte(Work8, OpAddress); + OpenBus = Work8; +} + +#endif diff --git a/cpuops.cpp b/cpuops.cpp new file mode 100644 index 00000000..c10a0c09 --- /dev/null +++ b/cpuops.cpp @@ -0,0 +1,4014 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "apu/apu.h" + +// for "Magic WDM" features +#ifdef DEBUGGER +#include "snapshot.h" +#include "display.h" +#include "debug.h" +#include "missing.h" +#endif + +#ifdef SA1_OPCODES +#define AddCycles(n) { } +#else +#define AddCycles(n) CPU.Cycles += n +#endif + +#include "cpuaddr.h" +#include "cpuops.h" +#include "cpumacro.h" + + +/* ADC ********************************************************************* */ + +static void Op69M1 (void) +{ + ADC(Immediate8(READ)); +} + +static void Op69M0 (void) +{ + ADC(Immediate16(READ)); +} + +static void Op69Slow (void) +{ + if (CheckMemory()) + ADC(Immediate8Slow(READ)); + else + ADC(Immediate16Slow(READ)); +} + +rOP8 (65M1, Direct, WRAP_BANK, ADC) +rOP16(65M0, Direct, WRAP_BANK, ADC) +rOPM (65Slow, DirectSlow, WRAP_BANK, ADC) + +rOP8 (75E1, DirectIndexedXE1, WRAP_BANK, ADC) +rOP8 (75E0M1, DirectIndexedXE0, WRAP_BANK, ADC) +rOP16(75E0M0, DirectIndexedXE0, WRAP_BANK, ADC) +rOPM (75Slow, DirectIndexedXSlow, WRAP_BANK, ADC) + +rOP8 (72E1, DirectIndirectE1, WRAP_NONE, ADC) +rOP8 (72E0M1, DirectIndirectE0, WRAP_NONE, ADC) +rOP16(72E0M0, DirectIndirectE0, WRAP_NONE, ADC) +rOPM (72Slow, DirectIndirectSlow, WRAP_NONE, ADC) + +rOP8 (61E1, DirectIndexedIndirectE1, WRAP_NONE, ADC) +rOP8 (61E0M1, DirectIndexedIndirectE0, WRAP_NONE, ADC) +rOP16(61E0M0, DirectIndexedIndirectE0, WRAP_NONE, ADC) +rOPM (61Slow, DirectIndexedIndirectSlow, WRAP_NONE, ADC) + +rOP8 (71E1, DirectIndirectIndexedE1, WRAP_NONE, ADC) +rOP8 (71E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) +rOP16(71E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ADC) +rOP8 (71E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) +rOP16(71E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ADC) +rOPM (71Slow, DirectIndirectIndexedSlow, WRAP_NONE, ADC) + +rOP8 (67M1, DirectIndirectLong, WRAP_NONE, ADC) +rOP16(67M0, DirectIndirectLong, WRAP_NONE, ADC) +rOPM (67Slow, DirectIndirectLongSlow, WRAP_NONE, ADC) + +rOP8 (77M1, DirectIndirectIndexedLong, WRAP_NONE, ADC) +rOP16(77M0, DirectIndirectIndexedLong, WRAP_NONE, ADC) +rOPM (77Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ADC) + +rOP8 (6DM1, Absolute, WRAP_NONE, ADC) +rOP16(6DM0, Absolute, WRAP_NONE, ADC) +rOPM (6DSlow, AbsoluteSlow, WRAP_NONE, ADC) + +rOP8 (7DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) +rOP16(7DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ADC) +rOP8 (7DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) +rOP16(7DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ADC) +rOPM (7DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ADC) + +rOP8 (79M1X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) +rOP16(79M0X1, AbsoluteIndexedYX1, WRAP_NONE, ADC) +rOP8 (79M1X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) +rOP16(79M0X0, AbsoluteIndexedYX0, WRAP_NONE, ADC) +rOPM (79Slow, AbsoluteIndexedYSlow, WRAP_NONE, ADC) + +rOP8 (6FM1, AbsoluteLong, WRAP_NONE, ADC) +rOP16(6FM0, AbsoluteLong, WRAP_NONE, ADC) +rOPM (6FSlow, AbsoluteLongSlow, WRAP_NONE, ADC) + +rOP8 (7FM1, AbsoluteLongIndexedX, WRAP_NONE, ADC) +rOP16(7FM0, AbsoluteLongIndexedX, WRAP_NONE, ADC) +rOPM (7FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ADC) + +rOP8 (63M1, StackRelative, WRAP_NONE, ADC) +rOP16(63M0, StackRelative, WRAP_NONE, ADC) +rOPM (63Slow, StackRelativeSlow, WRAP_NONE, ADC) + +rOP8 (73M1, StackRelativeIndirectIndexed, WRAP_NONE, ADC) +rOP16(73M0, StackRelativeIndirectIndexed, WRAP_NONE, ADC) +rOPM (73Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ADC) + +/* AND ********************************************************************* */ + +static void Op29M1 (void) +{ + Registers.AL &= Immediate8(READ); + SetZN(Registers.AL); +} + +static void Op29M0 (void) +{ + Registers.A.W &= Immediate16(READ); + SetZN(Registers.A.W); +} + +static void Op29Slow (void) +{ + if (CheckMemory()) + { + Registers.AL &= Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W &= Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (25M1, Direct, WRAP_BANK, AND) +rOP16(25M0, Direct, WRAP_BANK, AND) +rOPM (25Slow, DirectSlow, WRAP_BANK, AND) + +rOP8 (35E1, DirectIndexedXE1, WRAP_BANK, AND) +rOP8 (35E0M1, DirectIndexedXE0, WRAP_BANK, AND) +rOP16(35E0M0, DirectIndexedXE0, WRAP_BANK, AND) +rOPM (35Slow, DirectIndexedXSlow, WRAP_BANK, AND) + +rOP8 (32E1, DirectIndirectE1, WRAP_NONE, AND) +rOP8 (32E0M1, DirectIndirectE0, WRAP_NONE, AND) +rOP16(32E0M0, DirectIndirectE0, WRAP_NONE, AND) +rOPM (32Slow, DirectIndirectSlow, WRAP_NONE, AND) + +rOP8 (21E1, DirectIndexedIndirectE1, WRAP_NONE, AND) +rOP8 (21E0M1, DirectIndexedIndirectE0, WRAP_NONE, AND) +rOP16(21E0M0, DirectIndexedIndirectE0, WRAP_NONE, AND) +rOPM (21Slow, DirectIndexedIndirectSlow, WRAP_NONE, AND) + +rOP8 (31E1, DirectIndirectIndexedE1, WRAP_NONE, AND) +rOP8 (31E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) +rOP16(31E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, AND) +rOP8 (31E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) +rOP16(31E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, AND) +rOPM (31Slow, DirectIndirectIndexedSlow, WRAP_NONE, AND) + +rOP8 (27M1, DirectIndirectLong, WRAP_NONE, AND) +rOP16(27M0, DirectIndirectLong, WRAP_NONE, AND) +rOPM (27Slow, DirectIndirectLongSlow, WRAP_NONE, AND) + +rOP8 (37M1, DirectIndirectIndexedLong, WRAP_NONE, AND) +rOP16(37M0, DirectIndirectIndexedLong, WRAP_NONE, AND) +rOPM (37Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, AND) + +rOP8 (2DM1, Absolute, WRAP_NONE, AND) +rOP16(2DM0, Absolute, WRAP_NONE, AND) +rOPM (2DSlow, AbsoluteSlow, WRAP_NONE, AND) + +rOP8 (3DM1X1, AbsoluteIndexedXX1, WRAP_NONE, AND) +rOP16(3DM0X1, AbsoluteIndexedXX1, WRAP_NONE, AND) +rOP8 (3DM1X0, AbsoluteIndexedXX0, WRAP_NONE, AND) +rOP16(3DM0X0, AbsoluteIndexedXX0, WRAP_NONE, AND) +rOPM (3DSlow, AbsoluteIndexedXSlow, WRAP_NONE, AND) + +rOP8 (39M1X1, AbsoluteIndexedYX1, WRAP_NONE, AND) +rOP16(39M0X1, AbsoluteIndexedYX1, WRAP_NONE, AND) +rOP8 (39M1X0, AbsoluteIndexedYX0, WRAP_NONE, AND) +rOP16(39M0X0, AbsoluteIndexedYX0, WRAP_NONE, AND) +rOPM (39Slow, AbsoluteIndexedYSlow, WRAP_NONE, AND) + +rOP8 (2FM1, AbsoluteLong, WRAP_NONE, AND) +rOP16(2FM0, AbsoluteLong, WRAP_NONE, AND) +rOPM (2FSlow, AbsoluteLongSlow, WRAP_NONE, AND) + +rOP8 (3FM1, AbsoluteLongIndexedX, WRAP_NONE, AND) +rOP16(3FM0, AbsoluteLongIndexedX, WRAP_NONE, AND) +rOPM (3FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, AND) + +rOP8 (23M1, StackRelative, WRAP_NONE, AND) +rOP16(23M0, StackRelative, WRAP_NONE, AND) +rOPM (23Slow, StackRelativeSlow, WRAP_NONE, AND) + +rOP8 (33M1, StackRelativeIndirectIndexed, WRAP_NONE, AND) +rOP16(33M0, StackRelativeIndirectIndexed, WRAP_NONE, AND) +rOPM (33Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, AND) + +/* ASL ********************************************************************* */ + +static void Op0AM1 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = (Registers.AL & 0x80) != 0; + Registers.AL <<= 1; + SetZN(Registers.AL); +} + +static void Op0AM0 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = (Registers.AH & 0x80) != 0; + Registers.A.W <<= 1; + SetZN(Registers.A.W); +} + +static void Op0ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + ICPU._Carry = (Registers.AL & 0x80) != 0; + Registers.AL <<= 1; + SetZN(Registers.AL); + } + else + { + ICPU._Carry = (Registers.AH & 0x80) != 0; + Registers.A.W <<= 1; + SetZN(Registers.A.W); + } +} + +mOP8 (06M1, Direct, WRAP_BANK, ASL) +mOP16(06M0, Direct, WRAP_BANK, ASL) +mOPM (06Slow, DirectSlow, WRAP_BANK, ASL) + +mOP8 (16E1, DirectIndexedXE1, WRAP_BANK, ASL) +mOP8 (16E0M1, DirectIndexedXE0, WRAP_BANK, ASL) +mOP16(16E0M0, DirectIndexedXE0, WRAP_BANK, ASL) +mOPM (16Slow, DirectIndexedXSlow, WRAP_BANK, ASL) + +mOP8 (0EM1, Absolute, WRAP_NONE, ASL) +mOP16(0EM0, Absolute, WRAP_NONE, ASL) +mOPM (0ESlow, AbsoluteSlow, WRAP_NONE, ASL) + +mOP8 (1EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) +mOP16(1EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ASL) +mOP8 (1EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) +mOP16(1EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ASL) +mOPM (1ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ASL) + +/* BIT ********************************************************************* */ + +static void Op89M1 (void) +{ + ICPU._Zero = Registers.AL & Immediate8(READ); +} + +static void Op89M0 (void) +{ + ICPU._Zero = (Registers.A.W & Immediate16(READ)) != 0; +} + +static void Op89Slow (void) +{ + if (CheckMemory()) + ICPU._Zero = Registers.AL & Immediate8Slow(READ); + else + ICPU._Zero = (Registers.A.W & Immediate16Slow(READ)) != 0; +} + +rOP8 (24M1, Direct, WRAP_BANK, BIT) +rOP16(24M0, Direct, WRAP_BANK, BIT) +rOPM (24Slow, DirectSlow, WRAP_BANK, BIT) + +rOP8 (34E1, DirectIndexedXE1, WRAP_BANK, BIT) +rOP8 (34E0M1, DirectIndexedXE0, WRAP_BANK, BIT) +rOP16(34E0M0, DirectIndexedXE0, WRAP_BANK, BIT) +rOPM (34Slow, DirectIndexedXSlow, WRAP_BANK, BIT) + +rOP8 (2CM1, Absolute, WRAP_NONE, BIT) +rOP16(2CM0, Absolute, WRAP_NONE, BIT) +rOPM (2CSlow, AbsoluteSlow, WRAP_NONE, BIT) + +rOP8 (3CM1X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) +rOP16(3CM0X1, AbsoluteIndexedXX1, WRAP_NONE, BIT) +rOP8 (3CM1X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) +rOP16(3CM0X0, AbsoluteIndexedXX0, WRAP_NONE, BIT) +rOPM (3CSlow, AbsoluteIndexedXSlow, WRAP_NONE, BIT) + +/* CMP ********************************************************************* */ + +static void OpC9M1 (void) +{ + int16 Int16 = (int16) Registers.AL - (int16) Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static void OpC9M0 (void) +{ + int32 Int32 = (int32) Registers.A.W - (int32) Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static void OpC9Slow (void) +{ + if (CheckMemory()) + { + int16 Int16 = (int16) Registers.AL - (int16) Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); + } + else + { + int32 Int32 = (int32) Registers.A.W - (int32) Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); + } +} + +rOP8 (C5M1, Direct, WRAP_BANK, CMP) +rOP16(C5M0, Direct, WRAP_BANK, CMP) +rOPM (C5Slow, DirectSlow, WRAP_BANK, CMP) + +rOP8 (D5E1, DirectIndexedXE1, WRAP_BANK, CMP) +rOP8 (D5E0M1, DirectIndexedXE0, WRAP_BANK, CMP) +rOP16(D5E0M0, DirectIndexedXE0, WRAP_BANK, CMP) +rOPM (D5Slow, DirectIndexedXSlow, WRAP_BANK, CMP) + +rOP8 (D2E1, DirectIndirectE1, WRAP_NONE, CMP) +rOP8 (D2E0M1, DirectIndirectE0, WRAP_NONE, CMP) +rOP16(D2E0M0, DirectIndirectE0, WRAP_NONE, CMP) +rOPM (D2Slow, DirectIndirectSlow, WRAP_NONE, CMP) + +rOP8 (C1E1, DirectIndexedIndirectE1, WRAP_NONE, CMP) +rOP8 (C1E0M1, DirectIndexedIndirectE0, WRAP_NONE, CMP) +rOP16(C1E0M0, DirectIndexedIndirectE0, WRAP_NONE, CMP) +rOPM (C1Slow, DirectIndexedIndirectSlow, WRAP_NONE, CMP) + +rOP8 (D1E1, DirectIndirectIndexedE1, WRAP_NONE, CMP) +rOP8 (D1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) +rOP16(D1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, CMP) +rOP8 (D1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) +rOP16(D1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, CMP) +rOPM (D1Slow, DirectIndirectIndexedSlow, WRAP_NONE, CMP) + +rOP8 (C7M1, DirectIndirectLong, WRAP_NONE, CMP) +rOP16(C7M0, DirectIndirectLong, WRAP_NONE, CMP) +rOPM (C7Slow, DirectIndirectLongSlow, WRAP_NONE, CMP) + +rOP8 (D7M1, DirectIndirectIndexedLong, WRAP_NONE, CMP) +rOP16(D7M0, DirectIndirectIndexedLong, WRAP_NONE, CMP) +rOPM (D7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, CMP) + +rOP8 (CDM1, Absolute, WRAP_NONE, CMP) +rOP16(CDM0, Absolute, WRAP_NONE, CMP) +rOPM (CDSlow, AbsoluteSlow, WRAP_NONE, CMP) + +rOP8 (DDM1X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) +rOP16(DDM0X1, AbsoluteIndexedXX1, WRAP_NONE, CMP) +rOP8 (DDM1X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) +rOP16(DDM0X0, AbsoluteIndexedXX0, WRAP_NONE, CMP) +rOPM (DDSlow, AbsoluteIndexedXSlow, WRAP_NONE, CMP) + +rOP8 (D9M1X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) +rOP16(D9M0X1, AbsoluteIndexedYX1, WRAP_NONE, CMP) +rOP8 (D9M1X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) +rOP16(D9M0X0, AbsoluteIndexedYX0, WRAP_NONE, CMP) +rOPM (D9Slow, AbsoluteIndexedYSlow, WRAP_NONE, CMP) + +rOP8 (CFM1, AbsoluteLong, WRAP_NONE, CMP) +rOP16(CFM0, AbsoluteLong, WRAP_NONE, CMP) +rOPM (CFSlow, AbsoluteLongSlow, WRAP_NONE, CMP) + +rOP8 (DFM1, AbsoluteLongIndexedX, WRAP_NONE, CMP) +rOP16(DFM0, AbsoluteLongIndexedX, WRAP_NONE, CMP) +rOPM (DFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, CMP) + +rOP8 (C3M1, StackRelative, WRAP_NONE, CMP) +rOP16(C3M0, StackRelative, WRAP_NONE, CMP) +rOPM (C3Slow, StackRelativeSlow, WRAP_NONE, CMP) + +rOP8 (D3M1, StackRelativeIndirectIndexed, WRAP_NONE, CMP) +rOP16(D3M0, StackRelativeIndirectIndexed, WRAP_NONE, CMP) +rOPM (D3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, CMP) + +/* CPX ********************************************************************* */ + +static void OpE0X1 (void) +{ + int16 Int16 = (int16) Registers.XL - (int16) Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static void OpE0X0 (void) +{ + int32 Int32 = (int32) Registers.X.W - (int32) Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static void OpE0Slow (void) +{ + if (CheckIndex()) + { + int16 Int16 = (int16) Registers.XL - (int16) Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); + } + else + { + int32 Int32 = (int32) Registers.X.W - (int32) Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); + } +} + +rOP8 (E4X1, Direct, WRAP_BANK, CPX) +rOP16(E4X0, Direct, WRAP_BANK, CPX) +rOPX (E4Slow, DirectSlow, WRAP_BANK, CPX) + +rOP8 (ECX1, Absolute, WRAP_NONE, CPX) +rOP16(ECX0, Absolute, WRAP_NONE, CPX) +rOPX (ECSlow, AbsoluteSlow, WRAP_NONE, CPX) + +/* CPY ********************************************************************* */ + +static void OpC0X1 (void) +{ + int16 Int16 = (int16) Registers.YL - (int16) Immediate8(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); +} + +static void OpC0X0 (void) +{ + int32 Int32 = (int32) Registers.Y.W - (int32) Immediate16(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); +} + +static void OpC0Slow (void) +{ + if (CheckIndex()) + { + int16 Int16 = (int16) Registers.YL - (int16) Immediate8Slow(READ); + ICPU._Carry = Int16 >= 0; + SetZN((uint8) Int16); + } + else + { + int32 Int32 = (int32) Registers.Y.W - (int32) Immediate16Slow(READ); + ICPU._Carry = Int32 >= 0; + SetZN((uint16) Int32); + } +} + +rOP8 (C4X1, Direct, WRAP_BANK, CPY) +rOP16(C4X0, Direct, WRAP_BANK, CPY) +rOPX (C4Slow, DirectSlow, WRAP_BANK, CPY) + +rOP8 (CCX1, Absolute, WRAP_NONE, CPY) +rOP16(CCX0, Absolute, WRAP_NONE, CPY) +rOPX (CCSlow, AbsoluteSlow, WRAP_NONE, CPY) + +/* DEC ********************************************************************* */ + +static void Op3AM1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.AL--; + SetZN(Registers.AL); +} + +static void Op3AM0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.A.W--; + SetZN(Registers.A.W); +} + +static void Op3ASlow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckMemory()) + { + Registers.AL--; + SetZN(Registers.AL); + } + else + { + Registers.A.W--; + SetZN(Registers.A.W); + } +} + +mOP8 (C6M1, Direct, WRAP_BANK, DEC) +mOP16(C6M0, Direct, WRAP_BANK, DEC) +mOPM (C6Slow, DirectSlow, WRAP_BANK, DEC) + +mOP8 (D6E1, DirectIndexedXE1, WRAP_BANK, DEC) +mOP8 (D6E0M1, DirectIndexedXE0, WRAP_BANK, DEC) +mOP16(D6E0M0, DirectIndexedXE0, WRAP_BANK, DEC) +mOPM (D6Slow, DirectIndexedXSlow, WRAP_BANK, DEC) + +mOP8 (CEM1, Absolute, WRAP_NONE, DEC) +mOP16(CEM0, Absolute, WRAP_NONE, DEC) +mOPM (CESlow, AbsoluteSlow, WRAP_NONE, DEC) + +mOP8 (DEM1X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) +mOP16(DEM0X1, AbsoluteIndexedXX1, WRAP_NONE, DEC) +mOP8 (DEM1X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) +mOP16(DEM0X0, AbsoluteIndexedXX0, WRAP_NONE, DEC) +mOPM (DESlow, AbsoluteIndexedXSlow, WRAP_NONE, DEC) + +/* EOR ********************************************************************* */ + +static void Op49M1 (void) +{ + Registers.AL ^= Immediate8(READ); + SetZN(Registers.AL); +} + +static void Op49M0 (void) +{ + Registers.A.W ^= Immediate16(READ); + SetZN(Registers.A.W); +} + +static void Op49Slow (void) +{ + if (CheckMemory()) + { + Registers.AL ^= Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W ^= Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (45M1, Direct, WRAP_BANK, EOR) +rOP16(45M0, Direct, WRAP_BANK, EOR) +rOPM (45Slow, DirectSlow, WRAP_BANK, EOR) + +rOP8 (55E1, DirectIndexedXE1, WRAP_BANK, EOR) +rOP8 (55E0M1, DirectIndexedXE0, WRAP_BANK, EOR) +rOP16(55E0M0, DirectIndexedXE0, WRAP_BANK, EOR) +rOPM (55Slow, DirectIndexedXSlow, WRAP_BANK, EOR) + +rOP8 (52E1, DirectIndirectE1, WRAP_NONE, EOR) +rOP8 (52E0M1, DirectIndirectE0, WRAP_NONE, EOR) +rOP16(52E0M0, DirectIndirectE0, WRAP_NONE, EOR) +rOPM (52Slow, DirectIndirectSlow, WRAP_NONE, EOR) + +rOP8 (41E1, DirectIndexedIndirectE1, WRAP_NONE, EOR) +rOP8 (41E0M1, DirectIndexedIndirectE0, WRAP_NONE, EOR) +rOP16(41E0M0, DirectIndexedIndirectE0, WRAP_NONE, EOR) +rOPM (41Slow, DirectIndexedIndirectSlow, WRAP_NONE, EOR) + +rOP8 (51E1, DirectIndirectIndexedE1, WRAP_NONE, EOR) +rOP8 (51E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) +rOP16(51E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, EOR) +rOP8 (51E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) +rOP16(51E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, EOR) +rOPM (51Slow, DirectIndirectIndexedSlow, WRAP_NONE, EOR) + +rOP8 (47M1, DirectIndirectLong, WRAP_NONE, EOR) +rOP16(47M0, DirectIndirectLong, WRAP_NONE, EOR) +rOPM (47Slow, DirectIndirectLongSlow, WRAP_NONE, EOR) + +rOP8 (57M1, DirectIndirectIndexedLong, WRAP_NONE, EOR) +rOP16(57M0, DirectIndirectIndexedLong, WRAP_NONE, EOR) +rOPM (57Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, EOR) + +rOP8 (4DM1, Absolute, WRAP_NONE, EOR) +rOP16(4DM0, Absolute, WRAP_NONE, EOR) +rOPM (4DSlow, AbsoluteSlow, WRAP_NONE, EOR) + +rOP8 (5DM1X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) +rOP16(5DM0X1, AbsoluteIndexedXX1, WRAP_NONE, EOR) +rOP8 (5DM1X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) +rOP16(5DM0X0, AbsoluteIndexedXX0, WRAP_NONE, EOR) +rOPM (5DSlow, AbsoluteIndexedXSlow, WRAP_NONE, EOR) + +rOP8 (59M1X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) +rOP16(59M0X1, AbsoluteIndexedYX1, WRAP_NONE, EOR) +rOP8 (59M1X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) +rOP16(59M0X0, AbsoluteIndexedYX0, WRAP_NONE, EOR) +rOPM (59Slow, AbsoluteIndexedYSlow, WRAP_NONE, EOR) + +rOP8 (4FM1, AbsoluteLong, WRAP_NONE, EOR) +rOP16(4FM0, AbsoluteLong, WRAP_NONE, EOR) +rOPM (4FSlow, AbsoluteLongSlow, WRAP_NONE, EOR) + +rOP8 (5FM1, AbsoluteLongIndexedX, WRAP_NONE, EOR) +rOP16(5FM0, AbsoluteLongIndexedX, WRAP_NONE, EOR) +rOPM (5FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, EOR) + +rOP8 (43M1, StackRelative, WRAP_NONE, EOR) +rOP16(43M0, StackRelative, WRAP_NONE, EOR) +rOPM (43Slow, StackRelativeSlow, WRAP_NONE, EOR) + +rOP8 (53M1, StackRelativeIndirectIndexed, WRAP_NONE, EOR) +rOP16(53M0, StackRelativeIndirectIndexed, WRAP_NONE, EOR) +rOPM (53Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, EOR) + +/* INC ********************************************************************* */ + +static void Op1AM1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.AL++; + SetZN(Registers.AL); +} + +static void Op1AM0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.A.W++; + SetZN(Registers.A.W); +} + +static void Op1ASlow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckMemory()) + { + Registers.AL++; + SetZN(Registers.AL); + } + else + { + Registers.A.W++; + SetZN(Registers.A.W); + } +} + +mOP8 (E6M1, Direct, WRAP_BANK, INC) +mOP16(E6M0, Direct, WRAP_BANK, INC) +mOPM (E6Slow, DirectSlow, WRAP_BANK, INC) + +mOP8 (F6E1, DirectIndexedXE1, WRAP_BANK, INC) +mOP8 (F6E0M1, DirectIndexedXE0, WRAP_BANK, INC) +mOP16(F6E0M0, DirectIndexedXE0, WRAP_BANK, INC) +mOPM (F6Slow, DirectIndexedXSlow, WRAP_BANK, INC) + +mOP8 (EEM1, Absolute, WRAP_NONE, INC) +mOP16(EEM0, Absolute, WRAP_NONE, INC) +mOPM (EESlow, AbsoluteSlow, WRAP_NONE, INC) + +mOP8 (FEM1X1, AbsoluteIndexedXX1, WRAP_NONE, INC) +mOP16(FEM0X1, AbsoluteIndexedXX1, WRAP_NONE, INC) +mOP8 (FEM1X0, AbsoluteIndexedXX0, WRAP_NONE, INC) +mOP16(FEM0X0, AbsoluteIndexedXX0, WRAP_NONE, INC) +mOPM (FESlow, AbsoluteIndexedXSlow, WRAP_NONE, INC) + +/* LDA ********************************************************************* */ + +static void OpA9M1 (void) +{ + Registers.AL = Immediate8(READ); + SetZN(Registers.AL); +} + +static void OpA9M0 (void) +{ + Registers.A.W = Immediate16(READ); + SetZN(Registers.A.W); +} + +static void OpA9Slow (void) +{ + if (CheckMemory()) + { + Registers.AL = Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W = Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (A5M1, Direct, WRAP_BANK, LDA) +rOP16(A5M0, Direct, WRAP_BANK, LDA) +rOPM (A5Slow, DirectSlow, WRAP_BANK, LDA) + +rOP8 (B5E1, DirectIndexedXE1, WRAP_BANK, LDA) +rOP8 (B5E0M1, DirectIndexedXE0, WRAP_BANK, LDA) +rOP16(B5E0M0, DirectIndexedXE0, WRAP_BANK, LDA) +rOPM (B5Slow, DirectIndexedXSlow, WRAP_BANK, LDA) + +rOP8 (B2E1, DirectIndirectE1, WRAP_NONE, LDA) +rOP8 (B2E0M1, DirectIndirectE0, WRAP_NONE, LDA) +rOP16(B2E0M0, DirectIndirectE0, WRAP_NONE, LDA) +rOPM (B2Slow, DirectIndirectSlow, WRAP_NONE, LDA) + +rOP8 (A1E1, DirectIndexedIndirectE1, WRAP_NONE, LDA) +rOP8 (A1E0M1, DirectIndexedIndirectE0, WRAP_NONE, LDA) +rOP16(A1E0M0, DirectIndexedIndirectE0, WRAP_NONE, LDA) +rOPM (A1Slow, DirectIndexedIndirectSlow, WRAP_NONE, LDA) + +rOP8 (B1E1, DirectIndirectIndexedE1, WRAP_NONE, LDA) +rOP8 (B1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) +rOP16(B1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, LDA) +rOP8 (B1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) +rOP16(B1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, LDA) +rOPM (B1Slow, DirectIndirectIndexedSlow, WRAP_NONE, LDA) + +rOP8 (A7M1, DirectIndirectLong, WRAP_NONE, LDA) +rOP16(A7M0, DirectIndirectLong, WRAP_NONE, LDA) +rOPM (A7Slow, DirectIndirectLongSlow, WRAP_NONE, LDA) + +rOP8 (B7M1, DirectIndirectIndexedLong, WRAP_NONE, LDA) +rOP16(B7M0, DirectIndirectIndexedLong, WRAP_NONE, LDA) +rOPM (B7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, LDA) + +rOP8 (ADM1, Absolute, WRAP_NONE, LDA) +rOP16(ADM0, Absolute, WRAP_NONE, LDA) +rOPM (ADSlow, AbsoluteSlow, WRAP_NONE, LDA) + +rOP8 (BDM1X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) +rOP16(BDM0X1, AbsoluteIndexedXX1, WRAP_NONE, LDA) +rOP8 (BDM1X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) +rOP16(BDM0X0, AbsoluteIndexedXX0, WRAP_NONE, LDA) +rOPM (BDSlow, AbsoluteIndexedXSlow, WRAP_NONE, LDA) + +rOP8 (B9M1X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) +rOP16(B9M0X1, AbsoluteIndexedYX1, WRAP_NONE, LDA) +rOP8 (B9M1X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) +rOP16(B9M0X0, AbsoluteIndexedYX0, WRAP_NONE, LDA) +rOPM (B9Slow, AbsoluteIndexedYSlow, WRAP_NONE, LDA) + +rOP8 (AFM1, AbsoluteLong, WRAP_NONE, LDA) +rOP16(AFM0, AbsoluteLong, WRAP_NONE, LDA) +rOPM (AFSlow, AbsoluteLongSlow, WRAP_NONE, LDA) + +rOP8 (BFM1, AbsoluteLongIndexedX, WRAP_NONE, LDA) +rOP16(BFM0, AbsoluteLongIndexedX, WRAP_NONE, LDA) +rOPM (BFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, LDA) + +rOP8 (A3M1, StackRelative, WRAP_NONE, LDA) +rOP16(A3M0, StackRelative, WRAP_NONE, LDA) +rOPM (A3Slow, StackRelativeSlow, WRAP_NONE, LDA) + +rOP8 (B3M1, StackRelativeIndirectIndexed, WRAP_NONE, LDA) +rOP16(B3M0, StackRelativeIndirectIndexed, WRAP_NONE, LDA) +rOPM (B3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, LDA) + +/* LDX ********************************************************************* */ + +static void OpA2X1 (void) +{ + Registers.XL = Immediate8(READ); + SetZN(Registers.XL); +} + +static void OpA2X0 (void) +{ + Registers.X.W = Immediate16(READ); + SetZN(Registers.X.W); +} + +static void OpA2Slow (void) +{ + if (CheckIndex()) + { + Registers.XL = Immediate8Slow(READ); + SetZN(Registers.XL); + } + else + { + Registers.X.W = Immediate16Slow(READ); + SetZN(Registers.X.W); + } +} + +rOP8 (A6X1, Direct, WRAP_BANK, LDX) +rOP16(A6X0, Direct, WRAP_BANK, LDX) +rOPX (A6Slow, DirectSlow, WRAP_BANK, LDX) + +rOP8 (B6E1, DirectIndexedYE1, WRAP_BANK, LDX) +rOP8 (B6E0X1, DirectIndexedYE0, WRAP_BANK, LDX) +rOP16(B6E0X0, DirectIndexedYE0, WRAP_BANK, LDX) +rOPX (B6Slow, DirectIndexedYSlow, WRAP_BANK, LDX) + +rOP8 (AEX1, Absolute, WRAP_BANK, LDX) +rOP16(AEX0, Absolute, WRAP_BANK, LDX) +rOPX (AESlow, AbsoluteSlow, WRAP_BANK, LDX) + +rOP8 (BEX1, AbsoluteIndexedYX1, WRAP_BANK, LDX) +rOP16(BEX0, AbsoluteIndexedYX0, WRAP_BANK, LDX) +rOPX (BESlow, AbsoluteIndexedYSlow, WRAP_BANK, LDX) + +/* LDY ********************************************************************* */ + +static void OpA0X1 (void) +{ + Registers.YL = Immediate8(READ); + SetZN(Registers.YL); +} + +static void OpA0X0 (void) +{ + Registers.Y.W = Immediate16(READ); + SetZN(Registers.Y.W); +} + +static void OpA0Slow (void) +{ + if (CheckIndex()) + { + Registers.YL = Immediate8Slow(READ); + SetZN(Registers.YL); + } + else + { + Registers.Y.W = Immediate16Slow(READ); + SetZN(Registers.Y.W); + } +} + +rOP8 (A4X1, Direct, WRAP_BANK, LDY) +rOP16(A4X0, Direct, WRAP_BANK, LDY) +rOPX (A4Slow, DirectSlow, WRAP_BANK, LDY) + +rOP8 (B4E1, DirectIndexedXE1, WRAP_BANK, LDY) +rOP8 (B4E0X1, DirectIndexedXE0, WRAP_BANK, LDY) +rOP16(B4E0X0, DirectIndexedXE0, WRAP_BANK, LDY) +rOPX (B4Slow, DirectIndexedXSlow, WRAP_BANK, LDY) + +rOP8 (ACX1, Absolute, WRAP_BANK, LDY) +rOP16(ACX0, Absolute, WRAP_BANK, LDY) +rOPX (ACSlow, AbsoluteSlow, WRAP_BANK, LDY) + +rOP8 (BCX1, AbsoluteIndexedXX1, WRAP_BANK, LDY) +rOP16(BCX0, AbsoluteIndexedXX0, WRAP_BANK, LDY) +rOPX (BCSlow, AbsoluteIndexedXSlow, WRAP_BANK, LDY) + +/* LSR ********************************************************************* */ + +static void Op4AM1 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = Registers.AL & 1; + Registers.AL >>= 1; + SetZN(Registers.AL); +} + +static void Op4AM0 (void) +{ + AddCycles(ONE_CYCLE); + ICPU._Carry = Registers.A.W & 1; + Registers.A.W >>= 1; + SetZN(Registers.A.W); +} + +static void Op4ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + ICPU._Carry = Registers.AL & 1; + Registers.AL >>= 1; + SetZN(Registers.AL); + } + else + { + ICPU._Carry = Registers.A.W & 1; + Registers.A.W >>= 1; + SetZN(Registers.A.W); + } +} + +mOP8 (46M1, Direct, WRAP_BANK, LSR) +mOP16(46M0, Direct, WRAP_BANK, LSR) +mOPM (46Slow, DirectSlow, WRAP_BANK, LSR) + +mOP8 (56E1, DirectIndexedXE1, WRAP_BANK, LSR) +mOP8 (56E0M1, DirectIndexedXE0, WRAP_BANK, LSR) +mOP16(56E0M0, DirectIndexedXE0, WRAP_BANK, LSR) +mOPM (56Slow, DirectIndexedXSlow, WRAP_BANK, LSR) + +mOP8 (4EM1, Absolute, WRAP_NONE, LSR) +mOP16(4EM0, Absolute, WRAP_NONE, LSR) +mOPM (4ESlow, AbsoluteSlow, WRAP_NONE, LSR) + +mOP8 (5EM1X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) +mOP16(5EM0X1, AbsoluteIndexedXX1, WRAP_NONE, LSR) +mOP8 (5EM1X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) +mOP16(5EM0X0, AbsoluteIndexedXX0, WRAP_NONE, LSR) +mOPM (5ESlow, AbsoluteIndexedXSlow, WRAP_NONE, LSR) + +/* ORA ********************************************************************* */ + +static void Op09M1 (void) +{ + Registers.AL |= Immediate8(READ); + SetZN(Registers.AL); +} + +static void Op09M0 (void) +{ + Registers.A.W |= Immediate16(READ); + SetZN(Registers.A.W); +} + +static void Op09Slow (void) +{ + if (CheckMemory()) + { + Registers.AL |= Immediate8Slow(READ); + SetZN(Registers.AL); + } + else + { + Registers.A.W |= Immediate16Slow(READ); + SetZN(Registers.A.W); + } +} + +rOP8 (05M1, Direct, WRAP_BANK, ORA) +rOP16(05M0, Direct, WRAP_BANK, ORA) +rOPM (05Slow, DirectSlow, WRAP_BANK, ORA) + +rOP8 (15E1, DirectIndexedXE1, WRAP_BANK, ORA) +rOP8 (15E0M1, DirectIndexedXE0, WRAP_BANK, ORA) +rOP16(15E0M0, DirectIndexedXE0, WRAP_BANK, ORA) +rOPM (15Slow, DirectIndexedXSlow, WRAP_BANK, ORA) + +rOP8 (12E1, DirectIndirectE1, WRAP_NONE, ORA) +rOP8 (12E0M1, DirectIndirectE0, WRAP_NONE, ORA) +rOP16(12E0M0, DirectIndirectE0, WRAP_NONE, ORA) +rOPM (12Slow, DirectIndirectSlow, WRAP_NONE, ORA) + +rOP8 (01E1, DirectIndexedIndirectE1, WRAP_NONE, ORA) +rOP8 (01E0M1, DirectIndexedIndirectE0, WRAP_NONE, ORA) +rOP16(01E0M0, DirectIndexedIndirectE0, WRAP_NONE, ORA) +rOPM (01Slow, DirectIndexedIndirectSlow, WRAP_NONE, ORA) + +rOP8 (11E1, DirectIndirectIndexedE1, WRAP_NONE, ORA) +rOP8 (11E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) +rOP16(11E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, ORA) +rOP8 (11E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) +rOP16(11E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, ORA) +rOPM (11Slow, DirectIndirectIndexedSlow, WRAP_NONE, ORA) + +rOP8 (07M1, DirectIndirectLong, WRAP_NONE, ORA) +rOP16(07M0, DirectIndirectLong, WRAP_NONE, ORA) +rOPM (07Slow, DirectIndirectLongSlow, WRAP_NONE, ORA) + +rOP8 (17M1, DirectIndirectIndexedLong, WRAP_NONE, ORA) +rOP16(17M0, DirectIndirectIndexedLong, WRAP_NONE, ORA) +rOPM (17Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, ORA) + +rOP8 (0DM1, Absolute, WRAP_NONE, ORA) +rOP16(0DM0, Absolute, WRAP_NONE, ORA) +rOPM (0DSlow, AbsoluteSlow, WRAP_NONE, ORA) + +rOP8 (1DM1X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) +rOP16(1DM0X1, AbsoluteIndexedXX1, WRAP_NONE, ORA) +rOP8 (1DM1X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) +rOP16(1DM0X0, AbsoluteIndexedXX0, WRAP_NONE, ORA) +rOPM (1DSlow, AbsoluteIndexedXSlow, WRAP_NONE, ORA) + +rOP8 (19M1X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) +rOP16(19M0X1, AbsoluteIndexedYX1, WRAP_NONE, ORA) +rOP8 (19M1X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) +rOP16(19M0X0, AbsoluteIndexedYX0, WRAP_NONE, ORA) +rOPM (19Slow, AbsoluteIndexedYSlow, WRAP_NONE, ORA) + +rOP8 (0FM1, AbsoluteLong, WRAP_NONE, ORA) +rOP16(0FM0, AbsoluteLong, WRAP_NONE, ORA) +rOPM (0FSlow, AbsoluteLongSlow, WRAP_NONE, ORA) + +rOP8 (1FM1, AbsoluteLongIndexedX, WRAP_NONE, ORA) +rOP16(1FM0, AbsoluteLongIndexedX, WRAP_NONE, ORA) +rOPM (1FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, ORA) + +rOP8 (03M1, StackRelative, WRAP_NONE, ORA) +rOP16(03M0, StackRelative, WRAP_NONE, ORA) +rOPM (03Slow, StackRelativeSlow, WRAP_NONE, ORA) + +rOP8 (13M1, StackRelativeIndirectIndexed, WRAP_NONE, ORA) +rOP16(13M0, StackRelativeIndirectIndexed, WRAP_NONE, ORA) +rOPM (13Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, ORA) + +/* ROL ********************************************************************* */ + +static void Op2AM1 (void) +{ + AddCycles(ONE_CYCLE); + uint16 w = (((uint16) Registers.AL) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x100; + Registers.AL = (uint8) w; + SetZN(Registers.AL); +} + +static void Op2AM0 (void) +{ + AddCycles(ONE_CYCLE); + uint32 w = (((uint32) Registers.A.W) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x10000; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); +} + +static void Op2ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + uint16 w = (((uint16) Registers.AL) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x100; + Registers.AL = (uint8) w; + SetZN(Registers.AL); + } + else + { + uint32 w = (((uint32) Registers.A.W) << 1) | CheckCarry(); + ICPU._Carry = w >= 0x10000; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); + } +} + +mOP8 (26M1, Direct, WRAP_BANK, ROL) +mOP16(26M0, Direct, WRAP_BANK, ROL) +mOPM (26Slow, DirectSlow, WRAP_BANK, ROL) + +mOP8 (36E1, DirectIndexedXE1, WRAP_BANK, ROL) +mOP8 (36E0M1, DirectIndexedXE0, WRAP_BANK, ROL) +mOP16(36E0M0, DirectIndexedXE0, WRAP_BANK, ROL) +mOPM (36Slow, DirectIndexedXSlow, WRAP_BANK, ROL) + +mOP8 (2EM1, Absolute, WRAP_NONE, ROL) +mOP16(2EM0, Absolute, WRAP_NONE, ROL) +mOPM (2ESlow, AbsoluteSlow, WRAP_NONE, ROL) + +mOP8 (3EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) +mOP16(3EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROL) +mOP8 (3EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) +mOP16(3EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROL) +mOPM (3ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROL) + +/* ROR ********************************************************************* */ + +static void Op6AM1 (void) +{ + AddCycles(ONE_CYCLE); + uint16 w = ((uint16) Registers.AL) | (((uint16) CheckCarry()) << 8); + ICPU._Carry = w & 1; + w >>= 1; + Registers.AL = (uint8) w; + SetZN(Registers.AL); +} + +static void Op6AM0 (void) +{ + AddCycles(ONE_CYCLE); + uint32 w = ((uint32) Registers.A.W) | (((uint32) CheckCarry()) << 16); + ICPU._Carry = w & 1; + w >>= 1; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); +} + +static void Op6ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + uint16 w = ((uint16) Registers.AL) | (((uint16) CheckCarry()) << 8); + ICPU._Carry = w & 1; + w >>= 1; + Registers.AL = (uint8) w; + SetZN(Registers.AL); + } + else + { + uint32 w = ((uint32) Registers.A.W) | (((uint32) CheckCarry()) << 16); + ICPU._Carry = w & 1; + w >>= 1; + Registers.A.W = (uint16) w; + SetZN(Registers.A.W); + } +} + +mOP8 (66M1, Direct, WRAP_BANK, ROR) +mOP16(66M0, Direct, WRAP_BANK, ROR) +mOPM (66Slow, DirectSlow, WRAP_BANK, ROR) + +mOP8 (76E1, DirectIndexedXE1, WRAP_BANK, ROR) +mOP8 (76E0M1, DirectIndexedXE0, WRAP_BANK, ROR) +mOP16(76E0M0, DirectIndexedXE0, WRAP_BANK, ROR) +mOPM (76Slow, DirectIndexedXSlow, WRAP_BANK, ROR) + +mOP8 (6EM1, Absolute, WRAP_NONE, ROR) +mOP16(6EM0, Absolute, WRAP_NONE, ROR) +mOPM (6ESlow, AbsoluteSlow, WRAP_NONE, ROR) + +mOP8 (7EM1X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) +mOP16(7EM0X1, AbsoluteIndexedXX1, WRAP_NONE, ROR) +mOP8 (7EM1X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) +mOP16(7EM0X0, AbsoluteIndexedXX0, WRAP_NONE, ROR) +mOPM (7ESlow, AbsoluteIndexedXSlow, WRAP_NONE, ROR) + +/* SBC ********************************************************************* */ + +static void OpE9M1 (void) +{ + SBC(Immediate8(READ)); +} + +static void OpE9M0 (void) +{ + SBC(Immediate16(READ)); +} + +static void OpE9Slow (void) +{ + if (CheckMemory()) + SBC(Immediate8Slow(READ)); + else + SBC(Immediate16Slow(READ)); +} + +rOP8 (E5M1, Direct, WRAP_BANK, SBC) +rOP16(E5M0, Direct, WRAP_BANK, SBC) +rOPM (E5Slow, DirectSlow, WRAP_BANK, SBC) + +rOP8 (F5E1, DirectIndexedXE1, WRAP_BANK, SBC) +rOP8 (F5E0M1, DirectIndexedXE0, WRAP_BANK, SBC) +rOP16(F5E0M0, DirectIndexedXE0, WRAP_BANK, SBC) +rOPM (F5Slow, DirectIndexedXSlow, WRAP_BANK, SBC) + +rOP8 (F2E1, DirectIndirectE1, WRAP_NONE, SBC) +rOP8 (F2E0M1, DirectIndirectE0, WRAP_NONE, SBC) +rOP16(F2E0M0, DirectIndirectE0, WRAP_NONE, SBC) +rOPM (F2Slow, DirectIndirectSlow, WRAP_NONE, SBC) + +rOP8 (E1E1, DirectIndexedIndirectE1, WRAP_NONE, SBC) +rOP8 (E1E0M1, DirectIndexedIndirectE0, WRAP_NONE, SBC) +rOP16(E1E0M0, DirectIndexedIndirectE0, WRAP_NONE, SBC) +rOPM (E1Slow, DirectIndexedIndirectSlow, WRAP_NONE, SBC) + +rOP8 (F1E1, DirectIndirectIndexedE1, WRAP_NONE, SBC) +rOP8 (F1E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) +rOP16(F1E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, SBC) +rOP8 (F1E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) +rOP16(F1E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, SBC) +rOPM (F1Slow, DirectIndirectIndexedSlow, WRAP_NONE, SBC) + +rOP8 (E7M1, DirectIndirectLong, WRAP_NONE, SBC) +rOP16(E7M0, DirectIndirectLong, WRAP_NONE, SBC) +rOPM (E7Slow, DirectIndirectLongSlow, WRAP_NONE, SBC) + +rOP8 (F7M1, DirectIndirectIndexedLong, WRAP_NONE, SBC) +rOP16(F7M0, DirectIndirectIndexedLong, WRAP_NONE, SBC) +rOPM (F7Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, SBC) + +rOP8 (EDM1, Absolute, WRAP_NONE, SBC) +rOP16(EDM0, Absolute, WRAP_NONE, SBC) +rOPM (EDSlow, AbsoluteSlow, WRAP_NONE, SBC) + +rOP8 (FDM1X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) +rOP16(FDM0X1, AbsoluteIndexedXX1, WRAP_NONE, SBC) +rOP8 (FDM1X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) +rOP16(FDM0X0, AbsoluteIndexedXX0, WRAP_NONE, SBC) +rOPM (FDSlow, AbsoluteIndexedXSlow, WRAP_NONE, SBC) + +rOP8 (F9M1X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) +rOP16(F9M0X1, AbsoluteIndexedYX1, WRAP_NONE, SBC) +rOP8 (F9M1X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) +rOP16(F9M0X0, AbsoluteIndexedYX0, WRAP_NONE, SBC) +rOPM (F9Slow, AbsoluteIndexedYSlow, WRAP_NONE, SBC) + +rOP8 (EFM1, AbsoluteLong, WRAP_NONE, SBC) +rOP16(EFM0, AbsoluteLong, WRAP_NONE, SBC) +rOPM (EFSlow, AbsoluteLongSlow, WRAP_NONE, SBC) + +rOP8 (FFM1, AbsoluteLongIndexedX, WRAP_NONE, SBC) +rOP16(FFM0, AbsoluteLongIndexedX, WRAP_NONE, SBC) +rOPM (FFSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, SBC) + +rOP8 (E3M1, StackRelative, WRAP_NONE, SBC) +rOP16(E3M0, StackRelative, WRAP_NONE, SBC) +rOPM (E3Slow, StackRelativeSlow, WRAP_NONE, SBC) + +rOP8 (F3M1, StackRelativeIndirectIndexed, WRAP_NONE, SBC) +rOP16(F3M0, StackRelativeIndirectIndexed, WRAP_NONE, SBC) +rOPM (F3Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, SBC) + +/* STA ********************************************************************* */ + +wOP8 (85M1, Direct, WRAP_BANK, STA) +wOP16(85M0, Direct, WRAP_BANK, STA) +wOPM (85Slow, DirectSlow, WRAP_BANK, STA) + +wOP8 (95E1, DirectIndexedXE1, WRAP_BANK, STA) +wOP8 (95E0M1, DirectIndexedXE0, WRAP_BANK, STA) +wOP16(95E0M0, DirectIndexedXE0, WRAP_BANK, STA) +wOPM (95Slow, DirectIndexedXSlow, WRAP_BANK, STA) + +wOP8 (92E1, DirectIndirectE1, WRAP_NONE, STA) +wOP8 (92E0M1, DirectIndirectE0, WRAP_NONE, STA) +wOP16(92E0M0, DirectIndirectE0, WRAP_NONE, STA) +wOPM (92Slow, DirectIndirectSlow, WRAP_NONE, STA) + +wOP8 (81E1, DirectIndexedIndirectE1, WRAP_NONE, STA) +wOP8 (81E0M1, DirectIndexedIndirectE0, WRAP_NONE, STA) +wOP16(81E0M0, DirectIndexedIndirectE0, WRAP_NONE, STA) +wOPM (81Slow, DirectIndexedIndirectSlow, WRAP_NONE, STA) + +wOP8 (91E1, DirectIndirectIndexedE1, WRAP_NONE, STA) +wOP8 (91E0M1X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) +wOP16(91E0M0X1, DirectIndirectIndexedE0X1, WRAP_NONE, STA) +wOP8 (91E0M1X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) +wOP16(91E0M0X0, DirectIndirectIndexedE0X0, WRAP_NONE, STA) +wOPM (91Slow, DirectIndirectIndexedSlow, WRAP_NONE, STA) + +wOP8 (87M1, DirectIndirectLong, WRAP_NONE, STA) +wOP16(87M0, DirectIndirectLong, WRAP_NONE, STA) +wOPM (87Slow, DirectIndirectLongSlow, WRAP_NONE, STA) + +wOP8 (97M1, DirectIndirectIndexedLong, WRAP_NONE, STA) +wOP16(97M0, DirectIndirectIndexedLong, WRAP_NONE, STA) +wOPM (97Slow, DirectIndirectIndexedLongSlow, WRAP_NONE, STA) + +wOP8 (8DM1, Absolute, WRAP_NONE, STA) +wOP16(8DM0, Absolute, WRAP_NONE, STA) +wOPM (8DSlow, AbsoluteSlow, WRAP_NONE, STA) + +wOP8 (9DM1X1, AbsoluteIndexedXX1, WRAP_NONE, STA) +wOP16(9DM0X1, AbsoluteIndexedXX1, WRAP_NONE, STA) +wOP8 (9DM1X0, AbsoluteIndexedXX0, WRAP_NONE, STA) +wOP16(9DM0X0, AbsoluteIndexedXX0, WRAP_NONE, STA) +wOPM (9DSlow, AbsoluteIndexedXSlow, WRAP_NONE, STA) + +wOP8 (99M1X1, AbsoluteIndexedYX1, WRAP_NONE, STA) +wOP16(99M0X1, AbsoluteIndexedYX1, WRAP_NONE, STA) +wOP8 (99M1X0, AbsoluteIndexedYX0, WRAP_NONE, STA) +wOP16(99M0X0, AbsoluteIndexedYX0, WRAP_NONE, STA) +wOPM (99Slow, AbsoluteIndexedYSlow, WRAP_NONE, STA) + +wOP8 (8FM1, AbsoluteLong, WRAP_NONE, STA) +wOP16(8FM0, AbsoluteLong, WRAP_NONE, STA) +wOPM (8FSlow, AbsoluteLongSlow, WRAP_NONE, STA) + +wOP8 (9FM1, AbsoluteLongIndexedX, WRAP_NONE, STA) +wOP16(9FM0, AbsoluteLongIndexedX, WRAP_NONE, STA) +wOPM (9FSlow, AbsoluteLongIndexedXSlow, WRAP_NONE, STA) + +wOP8 (83M1, StackRelative, WRAP_NONE, STA) +wOP16(83M0, StackRelative, WRAP_NONE, STA) +wOPM (83Slow, StackRelativeSlow, WRAP_NONE, STA) + +wOP8 (93M1, StackRelativeIndirectIndexed, WRAP_NONE, STA) +wOP16(93M0, StackRelativeIndirectIndexed, WRAP_NONE, STA) +wOPM (93Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, STA) + +/* STX ********************************************************************* */ + +wOP8 (86X1, Direct, WRAP_BANK, STX) +wOP16(86X0, Direct, WRAP_BANK, STX) +wOPX (86Slow, DirectSlow, WRAP_BANK, STX) + +wOP8 (96E1, DirectIndexedYE1, WRAP_BANK, STX) +wOP8 (96E0X1, DirectIndexedYE0, WRAP_BANK, STX) +wOP16(96E0X0, DirectIndexedYE0, WRAP_BANK, STX) +wOPX (96Slow, DirectIndexedYSlow, WRAP_BANK, STX) + +wOP8 (8EX1, Absolute, WRAP_BANK, STX) +wOP16(8EX0, Absolute, WRAP_BANK, STX) +wOPX (8ESlow, AbsoluteSlow, WRAP_BANK, STX) + +/* STY ********************************************************************* */ + +wOP8 (84X1, Direct, WRAP_BANK, STY) +wOP16(84X0, Direct, WRAP_BANK, STY) +wOPX (84Slow, DirectSlow, WRAP_BANK, STY) + +wOP8 (94E1, DirectIndexedXE1, WRAP_BANK, STY) +wOP8 (94E0X1, DirectIndexedXE0, WRAP_BANK, STY) +wOP16(94E0X0, DirectIndexedXE0, WRAP_BANK, STY) +wOPX (94Slow, DirectIndexedXSlow, WRAP_BANK, STY) + +wOP8 (8CX1, Absolute, WRAP_BANK, STY) +wOP16(8CX0, Absolute, WRAP_BANK, STY) +wOPX (8CSlow, AbsoluteSlow, WRAP_BANK, STY) + +/* STZ ********************************************************************* */ + +wOP8 (64M1, Direct, WRAP_BANK, STZ) +wOP16(64M0, Direct, WRAP_BANK, STZ) +wOPM (64Slow, DirectSlow, WRAP_BANK, STZ) + +wOP8 (74E1, DirectIndexedXE1, WRAP_BANK, STZ) +wOP8 (74E0M1, DirectIndexedXE0, WRAP_BANK, STZ) +wOP16(74E0M0, DirectIndexedXE0, WRAP_BANK, STZ) +wOPM (74Slow, DirectIndexedXSlow, WRAP_BANK, STZ) + +wOP8 (9CM1, Absolute, WRAP_NONE, STZ) +wOP16(9CM0, Absolute, WRAP_NONE, STZ) +wOPM (9CSlow, AbsoluteSlow, WRAP_NONE, STZ) + +wOP8 (9EM1X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) +wOP16(9EM0X1, AbsoluteIndexedXX1, WRAP_NONE, STZ) +wOP8 (9EM1X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) +wOP16(9EM0X0, AbsoluteIndexedXX0, WRAP_NONE, STZ) +wOPM (9ESlow, AbsoluteIndexedXSlow, WRAP_NONE, STZ) + +/* TRB ********************************************************************* */ + +mOP8 (14M1, Direct, WRAP_BANK, TRB) +mOP16(14M0, Direct, WRAP_BANK, TRB) +mOPM (14Slow, DirectSlow, WRAP_BANK, TRB) + +mOP8 (1CM1, Absolute, WRAP_BANK, TRB) +mOP16(1CM0, Absolute, WRAP_BANK, TRB) +mOPM (1CSlow, AbsoluteSlow, WRAP_BANK, TRB) + +/* TSB ********************************************************************* */ + +mOP8 (04M1, Direct, WRAP_BANK, TSB) +mOP16(04M0, Direct, WRAP_BANK, TSB) +mOPM (04Slow, DirectSlow, WRAP_BANK, TSB) + +mOP8 (0CM1, Absolute, WRAP_BANK, TSB) +mOP16(0CM0, Absolute, WRAP_BANK, TSB) +mOPM (0CSlow, AbsoluteSlow, WRAP_BANK, TSB) + +/* Branch Instructions ***************************************************** */ + +#ifdef CPU_SHUTDOWN + +#ifndef SA1_OPCODES + +inline void CPUShutdown (void) +{ + if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) + { + // Don't skip cycles with a pending NMI or IRQ - could cause delayed interrupt. + if (CPU.WaitCounter == 0 && !(CPU.Flags & (IRQ_FLAG | NMI_FLAG))) + { + CPU.WaitAddress = 0xffffffff; + if (Settings.SA1) + S9xSA1ExecuteDuringSleep(); + CPU.Cycles = CPU.NextEvent; + ICPU.CPUExecuting = FALSE; + S9xAPUExecute(); + ICPU.CPUExecuting = TRUE; + } + else + if (CPU.WaitCounter >= 2) + CPU.WaitCounter = 1; + else + CPU.WaitCounter--; + } +} + +#else + +inline void CPUShutdown (void) +{ + if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress) + { + if (CPU.WaitCounter >= 1) + SA1.Executing = FALSE; + else + CPU.WaitCounter++; + } +} + +#endif + +#else + +#define CPUShutdown() + +#endif + +// BCC +bOP(90E0, Relative, !CheckCarry(), 0, 0) +bOP(90E1, Relative, !CheckCarry(), 0, 1) +bOP(90Slow, RelativeSlow, !CheckCarry(), 0, CheckEmulation()) + +// BCS +bOP(B0E0, Relative, CheckCarry(), 0, 0) +bOP(B0E1, Relative, CheckCarry(), 0, 1) +bOP(B0Slow, RelativeSlow, CheckCarry(), 0, CheckEmulation()) + +// BEQ +bOP(F0E0, Relative, CheckZero(), 2, 0) +bOP(F0E1, Relative, CheckZero(), 2, 1) +bOP(F0Slow, RelativeSlow, CheckZero(), 2, CheckEmulation()) + +// BMI +bOP(30E0, Relative, CheckNegative(), 1, 0) +bOP(30E1, Relative, CheckNegative(), 1, 1) +bOP(30Slow, RelativeSlow, CheckNegative(), 1, CheckEmulation()) + +// BNE +bOP(D0E0, Relative, !CheckZero(), 1, 0) +bOP(D0E1, Relative, !CheckZero(), 1, 1) +bOP(D0Slow, RelativeSlow, !CheckZero(), 1, CheckEmulation()) + +// BPL +bOP(10E0, Relative, !CheckNegative(), 1, 0) +bOP(10E1, Relative, !CheckNegative(), 1, 1) +bOP(10Slow, RelativeSlow, !CheckNegative(), 1, CheckEmulation()) + +// BRA +bOP(80E0, Relative, 1, X, 0) +bOP(80E1, Relative, 1, X, 1) +bOP(80Slow, RelativeSlow, 1, X, CheckEmulation()) + +// BVC +bOP(50E0, Relative, !CheckOverflow(), 0, 0) +bOP(50E1, Relative, !CheckOverflow(), 0, 1) +bOP(50Slow, RelativeSlow, !CheckOverflow(), 0, CheckEmulation()) + +// BVS +bOP(70E0, Relative, CheckOverflow(), 0, 0) +bOP(70E1, Relative, CheckOverflow(), 0, 1) +bOP(70Slow, RelativeSlow, CheckOverflow(), 0, CheckEmulation()) + +// BRL +static void Op82 (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP)); +} + +static void Op82Slow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP)); +} + +/* Flag Instructions ******************************************************* */ + +// CLC +static void Op18 (void) +{ + ClearCarry(); + AddCycles(ONE_CYCLE); +} + +// SEC +static void Op38 (void) +{ + SetCarry(); + AddCycles(ONE_CYCLE); +} + +// CLD +static void OpD8 (void) +{ + ClearDecimal(); + AddCycles(ONE_CYCLE); +} + +// SED +static void OpF8 (void) +{ + SetDecimal(); + AddCycles(ONE_CYCLE); +#ifdef DEBUGGER + missing.decimal_mode = 1; +#endif +} + +// CLI +static void Op58 (void) +{ + ClearIRQ(); + AddCycles(ONE_CYCLE); + //CHECK_FOR_IRQ(); +} + +// SEI +static void Op78 (void) +{ + SetIRQ(); + AddCycles(ONE_CYCLE); +} + +// CLV +static void OpB8 (void) +{ + ClearOverflow(); + AddCycles(ONE_CYCLE); +} + +/* DEX/DEY ***************************************************************** */ + +static void OpCAX1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.XL--; + SetZN(Registers.XL); +} + +static void OpCAX0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.X.W--; + SetZN(Registers.X.W); +} + +static void OpCASlow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckIndex()) + { + Registers.XL--; + SetZN(Registers.XL); + } + else + { + Registers.X.W--; + SetZN(Registers.X.W); + } +} + +static void Op88X1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.YL--; + SetZN(Registers.YL); +} + +static void Op88X0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.Y.W--; + SetZN(Registers.Y.W); +} + +static void Op88Slow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckIndex()) + { + Registers.YL--; + SetZN(Registers.YL); + } + else + { + Registers.Y.W--; + SetZN(Registers.Y.W); + } +} + +/* INX/INY ***************************************************************** */ + +static void OpE8X1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.XL++; + SetZN(Registers.XL); +} + +static void OpE8X0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.X.W++; + SetZN(Registers.X.W); +} + +static void OpE8Slow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckIndex()) + { + Registers.XL++; + SetZN(Registers.XL); + } + else + { + Registers.X.W++; + SetZN(Registers.X.W); + } +} + +static void OpC8X1 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.YL++; + SetZN(Registers.YL); +} + +static void OpC8X0 (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + Registers.Y.W++; + SetZN(Registers.Y.W); +} + +static void OpC8Slow (void) +{ + AddCycles(ONE_CYCLE); +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + if (CheckIndex()) + { + Registers.YL--; + SetZN(Registers.YL); + } + else + { + Registers.Y.W--; + SetZN(Registers.Y.W); + } +} + +/* NOP ********************************************************************* */ + +static void OpEA (void) +{ + AddCycles(ONE_CYCLE); +} + +/* PUSH Instructions ******************************************************* */ + +#define PushW(w) \ + S9xSetWord(w, Registers.S.W - 1, WRAP_BANK, WRITE_10); \ + Registers.S.W -= 2; + +#define PushWE(w) \ + Registers.SL--; \ + S9xSetWord(w, Registers.S.W, WRAP_PAGE, WRITE_10); \ + Registers.SL--; + +#define PushB(b) \ + S9xSetByte(b, Registers.S.W--); + +#define PushBE(b) \ + S9xSetByte(b, Registers.S.W); \ + Registers.SL--; + +// PEA +static void OpF4E0 (void) +{ + uint16 val = (uint16) Absolute(NONE); + PushW(val); + OpenBus = val & 0xff; +} + +static void OpF4E1 (void) +{ + // Note: PEA is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 val = (uint16) Absolute(NONE); + PushW(val); + OpenBus = val & 0xff; + Registers.SH = 1; +} + +static void OpF4Slow (void) +{ + uint16 val = (uint16) AbsoluteSlow(NONE); + PushW(val); + OpenBus = val & 0xff; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PEI +static void OpD4E0 (void) +{ + uint16 val = (uint16) DirectIndirectE0(NONE); + PushW(val); + OpenBus = val & 0xff; +} + +static void OpD4E1 (void) +{ + // Note: PEI is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 val = (uint16) DirectIndirectE1(NONE); + PushW(val); + OpenBus = val & 0xff; + Registers.SH = 1; +} + +static void OpD4Slow (void) +{ + uint16 val = (uint16) DirectIndirectSlow(NONE); + PushW(val); + OpenBus = val & 0xff; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PER +static void Op62E0 (void) +{ + uint16 val = (uint16) RelativeLong(NONE); + PushW(val); + OpenBus = val & 0xff; +} + +static void Op62E1 (void) +{ + // Note: PER is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 val = (uint16) RelativeLong(NONE); + PushW(val); + OpenBus = val & 0xff; + Registers.SH = 1; +} + +static void Op62Slow (void) +{ + uint16 val = (uint16) RelativeLongSlow(NONE); + PushW(val); + OpenBus = val & 0xff; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PHA +static void Op48E1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op48E0M1 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op48E0M0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.A.W); + OpenBus = Registers.AL; +} + +static void Op48Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.AL); + } + else + if (CheckMemory()) + { + PushB(Registers.AL); + } + else + { + PushW(Registers.A.W); + } + + OpenBus = Registers.AL; +} + +// PHB +static void Op8BE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.DB); + OpenBus = Registers.DB; +} + +static void Op8BE0 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.DB); + OpenBus = Registers.DB; +} + +static void Op8BSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.DB); + } + else + { + PushB(Registers.DB); + } + + OpenBus = Registers.DB; +} + +// PHD +static void Op0BE0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.D.W); + OpenBus = Registers.DL; +} + +static void Op0BE1 (void) +{ + // Note: PHD is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + AddCycles(ONE_CYCLE); + PushW(Registers.D.W); + OpenBus = Registers.DL; + Registers.SH = 1; +} + +static void Op0BSlow (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.D.W); + OpenBus = Registers.DL; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PHK +static void Op4BE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.PB); + OpenBus = Registers.PB; +} + +static void Op4BE0 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.PB); + OpenBus = Registers.PB; +} + +static void Op4BSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.PB); + } + else + { + PushB(Registers.PB); + } + + OpenBus = Registers.PB; +} + +// PHP +static void Op08E0 (void) +{ + S9xPackStatus(); + AddCycles(ONE_CYCLE); + PushB(Registers.PL); + OpenBus = Registers.PL; +} + +static void Op08E1 (void) +{ + S9xPackStatus(); + AddCycles(ONE_CYCLE); + PushBE(Registers.PL); + OpenBus = Registers.PL; +} + +static void Op08Slow (void) +{ + S9xPackStatus(); + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.PL); + } + else + { + PushB(Registers.PL); + } + + OpenBus = Registers.PL; +} + +// PHX +static void OpDAE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpDAE0X1 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpDAE0X0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.X.W); + OpenBus = Registers.XL; +} + +static void OpDASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.XL); + } + else + if (CheckIndex()) + { + PushB(Registers.XL); + } + else + { + PushW(Registers.X.W); + } + + OpenBus = Registers.XL; +} + +// PHY +static void Op5AE1 (void) +{ + AddCycles(ONE_CYCLE); + PushBE(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op5AE0X1 (void) +{ + AddCycles(ONE_CYCLE); + PushB(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op5AE0X0 (void) +{ + AddCycles(ONE_CYCLE); + PushW(Registers.Y.W); + OpenBus = Registers.YL; +} + +static void Op5ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushBE(Registers.YL); + } + else + if (CheckIndex()) + { + PushB(Registers.YL); + } + else + { + PushW(Registers.Y.W); + } + + OpenBus = Registers.YL; +} + +/* PULL Instructions ******************************************************* */ + +#define PullW(w) \ + w = S9xGetWord(Registers.S.W + 1, WRAP_BANK); \ + Registers.S.W += 2; + +#define PullWE(w) \ + Registers.SL++; \ + w = S9xGetWord(Registers.S.W, WRAP_PAGE); \ + Registers.SL++; + +#define PullB(b) \ + b = S9xGetByte(++Registers.S.W); + +#define PullBE(b) \ + Registers.SL++; \ + b = S9xGetByte(Registers.S.W); + +// PLA +static void Op68E1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op68E0M1 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; +} + +static void Op68E0M0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.A.W); + SetZN(Registers.A.W); + OpenBus = Registers.AH; +} + +static void Op68Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; + } + else + if (CheckMemory()) + { + PullB(Registers.AL); + SetZN(Registers.AL); + OpenBus = Registers.AL; + } + else + { + PullW(Registers.A.W); + SetZN(Registers.A.W); + OpenBus = Registers.AH; + } +} + +// PLB +static void OpABE1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.DB); + SetZN(Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; +} + +static void OpABE0 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.DB); + SetZN(Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; +} + +static void OpABSlow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.DB); + } + else + { + PullB(Registers.DB); + } + + SetZN(Registers.DB); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = Registers.DB; +} + +// PLD +static void Op2BE0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.D.W); + SetZN(Registers.D.W); + OpenBus = Registers.DH; +} + +static void Op2BE1 (void) +{ + // Note: PLD is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + AddCycles(TWO_CYCLES); + PullW(Registers.D.W); + SetZN(Registers.D.W); + OpenBus = Registers.DH; + Registers.SH = 1; +} + +static void Op2BSlow (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.D.W); + SetZN(Registers.D.W); + OpenBus = Registers.DH; + if (CheckEmulation()) + Registers.SH = 1; +} + +// PLP +static void Op28E1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.PL); + OpenBus = Registers.PL; + SetFlags(MemoryFlag | IndexFlag); + S9xUnpackStatus(); + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +static void Op28E0 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.PL); + OpenBus = Registers.PL; + S9xUnpackStatus(); + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +static void Op28Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.PL); + OpenBus = Registers.PL; + SetFlags(MemoryFlag | IndexFlag); + } + else + { + PullB(Registers.PL); + OpenBus = Registers.PL; + } + + S9xUnpackStatus(); + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +// PLX +static void OpFAE1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpFAE0X1 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; +} + +static void OpFAE0X0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.X.W); + SetZN(Registers.X.W); + OpenBus = Registers.XH; +} + +static void OpFASlow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; + } + else + if (CheckIndex()) + { + PullB(Registers.XL); + SetZN(Registers.XL); + OpenBus = Registers.XL; + } + else + { + PullW(Registers.X.W); + SetZN(Registers.X.W); + OpenBus = Registers.XH; + } +} + +// PLY +static void Op7AE1 (void) +{ + AddCycles(TWO_CYCLES); + PullBE(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op7AE0X1 (void) +{ + AddCycles(TWO_CYCLES); + PullB(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; +} + +static void Op7AE0X0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.Y.W); + SetZN(Registers.Y.W); + OpenBus = Registers.YH; +} + +static void Op7ASlow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullBE(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; + } + else + if (CheckIndex()) + { + PullB(Registers.YL); + SetZN(Registers.YL); + OpenBus = Registers.YL; + } + else + { + PullW(Registers.Y.W); + SetZN(Registers.Y.W); + OpenBus = Registers.YH; + } +} + +/* Transfer Instructions *************************************************** */ + +// TAX +static void OpAAX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL = Registers.AL; + SetZN(Registers.XL); +} + +static void OpAAX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.A.W; + SetZN(Registers.X.W); +} + +static void OpAASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL = Registers.AL; + SetZN(Registers.XL); + } + else + { + Registers.X.W = Registers.A.W; + SetZN(Registers.X.W); + } +} + +// TAY +static void OpA8X1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.YL = Registers.AL; + SetZN(Registers.YL); +} + +static void OpA8X0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.Y.W = Registers.A.W; + SetZN(Registers.Y.W); +} + +static void OpA8Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.YL = Registers.AL; + SetZN(Registers.YL); + } + else + { + Registers.Y.W = Registers.A.W; + SetZN(Registers.Y.W); + } +} + +// TCD +static void Op5B (void) +{ + AddCycles(ONE_CYCLE); + Registers.D.W = Registers.A.W; + SetZN(Registers.D.W); +} + +// TCS +static void Op1B (void) +{ + AddCycles(ONE_CYCLE); + Registers.S.W = Registers.A.W; + if (CheckEmulation()) + Registers.SH = 1; +} + +// TDC +static void Op7B (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.D.W; + SetZN(Registers.A.W); +} + +// TSC +static void Op3B (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.S.W; + SetZN(Registers.A.W); +} + +// TSX +static void OpBAX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL = Registers.SL; + SetZN(Registers.XL); +} + +static void OpBAX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.S.W; + SetZN(Registers.X.W); +} + +static void OpBASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL = Registers.SL; + SetZN(Registers.XL); + } + else + { + Registers.X.W = Registers.S.W; + SetZN(Registers.X.W); + } +} + +// TXA +static void Op8AM1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.AL = Registers.XL; + SetZN(Registers.AL); +} + +static void Op8AM0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.X.W; + SetZN(Registers.A.W); +} + +static void Op8ASlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + Registers.AL = Registers.XL; + SetZN(Registers.AL); + } + else + { + Registers.A.W = Registers.X.W; + SetZN(Registers.A.W); + } +} + +// TXS +static void Op9A (void) +{ + AddCycles(ONE_CYCLE); + Registers.S.W = Registers.X.W; + if (CheckEmulation()) + Registers.SH = 1; +} + +// TXY +static void Op9BX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.YL = Registers.XL; + SetZN(Registers.YL); +} + +static void Op9BX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.Y.W = Registers.X.W; + SetZN(Registers.Y.W); +} + +static void Op9BSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.YL = Registers.XL; + SetZN(Registers.YL); + } + else + { + Registers.Y.W = Registers.X.W; + SetZN(Registers.Y.W); + } +} + +// TYA +static void Op98M1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.AL = Registers.YL; + SetZN(Registers.AL); +} + +static void Op98M0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.A.W = Registers.Y.W; + SetZN(Registers.A.W); +} + +static void Op98Slow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckMemory()) + { + Registers.AL = Registers.YL; + SetZN(Registers.AL); + } + else + { + Registers.A.W = Registers.Y.W; + SetZN(Registers.A.W); + } +} + +// TYX +static void OpBBX1 (void) +{ + AddCycles(ONE_CYCLE); + Registers.XL = Registers.YL; + SetZN(Registers.XL); +} + +static void OpBBX0 (void) +{ + AddCycles(ONE_CYCLE); + Registers.X.W = Registers.Y.W; + SetZN(Registers.X.W); +} + +static void OpBBSlow (void) +{ + AddCycles(ONE_CYCLE); + + if (CheckIndex()) + { + Registers.XL = Registers.YL; + SetZN(Registers.XL); + } + else + { + Registers.X.W = Registers.Y.W; + SetZN(Registers.X.W); + } +} + +/* XCE ********************************************************************* */ + +static void OpFB (void) +{ + AddCycles(ONE_CYCLE); + + uint8 A1 = ICPU._Carry; + uint8 A2 = Registers.PH; + + ICPU._Carry = A2 & 1; + Registers.PH = A1; + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + Registers.SH = 1; + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); +} + +/* BRK ********************************************************************* */ + +static void Op00 (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage("*** BRK"); +#endif + + AddCycles(CPU.MemSpeed); + + uint16 addr; + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw + 1); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFE6); + } + else + { + PushWE(Registers.PCw + 1); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFFE); + } + + S9xSetPCBase(addr); + OpenBus = addr >> 8; +} + +/* IRQ ********************************************************************* */ + +void S9xOpcode_IRQ (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage("*** IRQ"); +#endif + + // IRQ and NMI do an opcode fetch as their first "IO" cycle. + AddCycles(CPU.MemSpeed + ONE_CYCLE); + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2208]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40)) + { + OpenBus = Memory.FillRAM[0x220f]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFEE); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } + else + { + PushWE(Registers.PCw); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2208]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40)) + { + OpenBus = Memory.FillRAM[0x220f]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFFE); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } +} + +/* NMI ********************************************************************* */ + +void S9xOpcode_NMI (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage("*** NMI"); +#endif + + // IRQ and NMI do an opcode fetch as their first "IO" cycle. + AddCycles(CPU.MemSpeed + ONE_CYCLE); + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2206]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x20)) + { + OpenBus = Memory.FillRAM[0x220d]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFEA); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } + else + { + PushWE(Registers.PCw); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + #ifdef SA1_OPCODES + OpenBus = Memory.FillRAM[0x2206]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8)); + #else + if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x20)) + { + OpenBus = Memory.FillRAM[0x220d]; + AddCycles(2 * SLOW_ONE_CYCLE); + S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8)); + } + else + { + uint16 addr = S9xGetWord(0xFFFA); + OpenBus = addr >> 8; + S9xSetPCBase(addr); + } + #endif + } +} + +/* COP ********************************************************************* */ + +static void Op02 (void) +{ +#ifdef DEBUGGER + if (CPU.Flags & TRACE_FLAG) + S9xTraceMessage("*** COP"); +#endif + + AddCycles(CPU.MemSpeed); + + uint16 addr; + + if (!CheckEmulation()) + { + PushB(Registers.PB); + PushW(Registers.PCw + 1); + S9xPackStatus(); + PushB(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFE4); + } + else + { + PushWE(Registers.PCw + 1); + S9xPackStatus(); + PushBE(Registers.PL); + OpenBus = Registers.PL; + ClearDecimal(); + SetIRQ(); + + addr = S9xGetWord(0xFFF4); + } + + S9xSetPCBase(addr); + OpenBus = addr >> 8; +} + +/* JML ********************************************************************* */ + +static void OpDC (void) +{ + S9xSetPCBase(AbsoluteIndirectLong(JUMP)); +} + +static void OpDCSlow (void) +{ + S9xSetPCBase(AbsoluteIndirectLongSlow(JUMP)); +} + +static void Op5C (void) +{ + S9xSetPCBase(AbsoluteLong(JUMP)); +} + +static void Op5CSlow (void) +{ + S9xSetPCBase(AbsoluteLongSlow(JUMP)); +} + +/* JMP ********************************************************************* */ + +static void Op4C (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) Absolute(JUMP))); +#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) + CPUShutdown(); +#endif +} + +static void Op4CSlow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteSlow(JUMP))); +#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES) + CPUShutdown(); +#endif +} + +static void Op6C (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndirect(JUMP))); +} + +static void Op6CSlow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndirectSlow(JUMP))); +} + +static void Op7C (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndexedIndirect(JUMP))); +} + +static void Op7CSlow (void) +{ + S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteIndexedIndirectSlow(JUMP))); +} + +/* JSL/RTL ***************************************************************** */ + +static void Op22E1 (void) +{ + // Note: JSL is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint32 addr = AbsoluteLong(JSR); + PushB(Registers.PB); + PushW(Registers.PCw - 1); + Registers.SH = 1; + S9xSetPCBase(addr); +} + +static void Op22E0 (void) +{ + uint32 addr = AbsoluteLong(JSR); + PushB(Registers.PB); + PushW(Registers.PCw - 1); + S9xSetPCBase(addr); +} + +static void Op22Slow (void) +{ + uint32 addr = AbsoluteLongSlow(JSR); + PushB(Registers.PB); + PushW(Registers.PCw - 1); + if (CheckEmulation()) + Registers.SH = 1; + S9xSetPCBase(addr); +} + +static void Op6BE1 (void) +{ + // Note: RTL is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + PullB(Registers.PB); + Registers.SH = 1; + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op6BE0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + PullB(Registers.PB); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op6BSlow (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + PullB(Registers.PB); + if (CheckEmulation()) + Registers.SH = 1; + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +/* JSR/RTS ***************************************************************** */ + +static void Op20E1 (void) +{ + uint16 addr = Absolute(JSR); + AddCycles(ONE_CYCLE); + PushWE(Registers.PCw - 1); + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void Op20E0 (void) +{ + uint16 addr = Absolute(JSR); + AddCycles(ONE_CYCLE); + PushW(Registers.PCw - 1); + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void Op20Slow (void) +{ + uint16 addr = AbsoluteSlow(JSR); + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + PushWE(Registers.PCw - 1); + } + else + { + PushW(Registers.PCw - 1); + } + + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void OpFCE1 (void) +{ + // Note: JSR (a,X) is a new instruction, + // and so doesn't respect the emu-mode stack bounds. + uint16 addr = AbsoluteIndexedIndirect(JSR); + PushW(Registers.PCw - 1); + Registers.SH = 1; + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void OpFCE0 (void) +{ + uint16 addr = AbsoluteIndexedIndirect(JSR); + PushW(Registers.PCw - 1); + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void OpFCSlow (void) +{ + uint16 addr = AbsoluteIndexedIndirectSlow(JSR); + PushW(Registers.PCw - 1); + if (CheckEmulation()) + Registers.SH = 1; + S9xSetPCBase(ICPU.ShiftedPB + addr); +} + +static void Op60E1 (void) +{ + AddCycles(TWO_CYCLES); + PullWE(Registers.PCw); + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op60E0 (void) +{ + AddCycles(TWO_CYCLES); + PullW(Registers.PCw); + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +static void Op60Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (CheckEmulation()) + { + PullWE(Registers.PCw); + } + else + { + PullW(Registers.PCw); + } + + AddCycles(ONE_CYCLE); + Registers.PCw++; + S9xSetPCBase(Registers.PBPC); +} + +/* MVN/MVP ***************************************************************** */ + +static void Op54X1 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + Registers.XL++; + Registers.YL++; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op54X0 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = 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) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op54Slow (void) +{ + uint32 SrcBank; + + OpenBus = Registers.DB = Immediate8Slow(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8Slow(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + if (CheckIndex()) + { + Registers.XL++; + Registers.YL++; + } + else + { + Registers.X.W++; + Registers.Y.W++; + } + + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op44X1 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + Registers.XL--; + Registers.YL--; + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op44X0 (void) +{ + uint32 SrcBank; + + Registers.DB = Immediate8(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8(NONE); + + S9xSetByte(OpenBus = 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) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +static void Op44Slow (void) +{ + uint32 SrcBank; + + OpenBus = Registers.DB = Immediate8Slow(NONE); + ICPU.ShiftedDB = Registers.DB << 16; + OpenBus = SrcBank = Immediate8Slow(NONE); + + S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W); + + if (CheckIndex()) + { + Registers.XL--; + Registers.YL--; + } + else + { + Registers.X.W--; + Registers.Y.W--; + } + + Registers.A.W--; + if (Registers.A.W != 0xffff) + Registers.PCw -= 3; + + AddCycles(TWO_CYCLES); +} + +/* REP/SEP ***************************************************************** */ + +static void OpC2 (void) +{ + uint8 Work8 = ~Immediate8(READ); + Registers.PL &= Work8; + ICPU._Carry &= Work8; + ICPU._Overflow &= (Work8 >> 6); + ICPU._Negative &= Work8; + ICPU._Zero |= ~Work8 & Zero; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +static void OpC2Slow (void) +{ + uint8 Work8 = ~Immediate8Slow(READ); + Registers.PL &= Work8; + ICPU._Carry &= Work8; + ICPU._Overflow &= (Work8 >> 6); + ICPU._Negative &= Work8; + ICPU._Zero |= ~Work8 & Zero; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +static void OpE2 (void) +{ + uint8 Work8 = Immediate8(READ); + Registers.PL |= Work8; + ICPU._Carry |= Work8 & 1; + ICPU._Overflow |= (Work8 >> 6) & 1; + ICPU._Negative |= Work8; + if (Work8 & Zero) + ICPU._Zero = 0; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); +} + +static void OpE2Slow (void) +{ + uint8 Work8 = Immediate8Slow(READ); + Registers.PL |= Work8; + ICPU._Carry |= Work8 & 1; + ICPU._Overflow |= (Work8 >> 6) & 1; + ICPU._Negative |= Work8; + if (Work8 & Zero) + ICPU._Zero = 0; + + AddCycles(ONE_CYCLE); + + if (CheckEmulation()) + { + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + 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; + SetZN(Registers.AL); + AddCycles(TWO_CYCLES); +} + +/* RTI ********************************************************************* */ + +static void Op40Slow (void) +{ + AddCycles(TWO_CYCLES); + + if (!CheckEmulation()) + { + PullB(Registers.PL); + S9xUnpackStatus(); + PullW(Registers.PCw); + PullB(Registers.PB); + OpenBus = Registers.PB; + ICPU.ShiftedPB = Registers.PB << 16; + } + else + { + PullBE(Registers.PL); + S9xUnpackStatus(); + PullWE(Registers.PCw); + OpenBus = Registers.PCh; + SetFlags(MemoryFlag | IndexFlag); + #ifdef DEBUGGER + missing.emulate6502 = 1; + #endif + } + + S9xSetPCBase(Registers.PBPC); + + if (CheckIndex()) + { + Registers.XH = 0; + Registers.YH = 0; + } + + S9xFixCycles(); + //CHECK_FOR_IRQ(); +} + +/* STP/WAI ***************************************************************** */ + +// WAI +static void OpCB (void) +{ + // Ok, let's just C-ify the ASM versions separately. +#ifdef SA1_OPCODES + SA1.WaitingForInterrupt = TRUE; + Registers.PCw--; +#if 0 + // XXX: FIXME + if (Settings.Shutdown) + { + SA1.Cycles = SA1.NextEvent; + SA1.Executing = FALSE; + //S9xAPUExecute(); // FIXME + SA1.Executing = TRUE; + } +#endif +#else // SA1_OPCODES +#if 0 + if (CPU.IRQActive) + AddCycles(TWO_CYCLES); + else +#endif + { + CPU.WaitingForInterrupt = TRUE; + Registers.PCw--; + #ifdef CPU_SHUTDOWN + if (Settings.Shutdown) + { + CPU.Cycles = CPU.NextEvent; + ICPU.CPUExecuting = FALSE; + S9xAPUExecute(); + ICPU.CPUExecuting = TRUE; + } + else + AddCycles(TWO_CYCLES); + #else + AddCycles(TWO_CYCLES); +#endif + } +#endif // SA1_OPCODES +} + +// STP +static void OpDB (void) +{ + Registers.PCw--; + CPU.Flags |= DEBUG_MODE_FLAG | HALTED_FLAG; +} + +/* WDM (Reserved S9xOpcode) ************************************************ */ + +#ifdef DEBUGGER +extern FILE *trace, *trace2; +#endif + +static void Op42 (void) +{ +#ifdef DEBUGGER + uint8 byte = (uint8) S9xGetWord(Registers.PBPC); +#else + S9xGetWord(Registers.PBPC); +#endif + Registers.PCw++; + +#ifdef DEBUGGER + // Hey, let's use this to trigger debug modes. + switch (byte) + { + case 0xdb: // "STP" = Enter debug mode + CPU.Flags |= DEBUG_MODE_FLAG; + break; + + #ifndef SA1_OPCODES + case 0xe2: // "SEP" = Trace on + if (!(CPU.Flags & TRACE_FLAG)) + { + char buf[25]; + CPU.Flags |= TRACE_FLAG; + snprintf(buf, 25, "WDM trace on at $%02X:%04X", Registers.PB, Registers.PCw); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); + if (trace != NULL) + fclose(trace); + trace = fopen("WDMtrace.log", "ab"); + } + + break; + + case 0xc2: // "REP" = Trace off + if (CPU.Flags & TRACE_FLAG) + { + char buf[26]; + CPU.Flags &= ~TRACE_FLAG; + snprintf(buf, 26, "WDM trace off at $%02X:%04X", Registers.PB, Registers.PCw); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf); + if (trace != NULL) + fclose(trace); + trace = NULL; + } + + break; + #endif + + case 0x42: // "WDM" = Snapshot + char filename[PATH_MAX + 1], drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[PATH_MAX + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + snprintf(filename, PATH_MAX, "%s%s%s-%06X.wdm", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, Registers.PBPC & 0xffffff); + sprintf(def, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename); + S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, def); + S9xFreezeGame(filename); + + break; + + default: + break; + } +#endif +} + +/* CPU-S9xOpcodes Definitions ************************************************/ + +struct SOpcodes S9xOpcodesM1X1[256] = +{ + { Op00 }, { Op01E0M1 }, { Op02 }, { Op03M1 }, { Op04M1 }, + { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E0 }, { Op09M1 }, + { Op0AM1 }, { Op0BE0 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, + { Op0FM1 }, { Op10E0 }, { Op11E0M1X1 }, { Op12E0M1 }, { Op13M1 }, + { Op14M1 }, { Op15E0M1 }, { Op16E0M1 }, { Op17M1 }, { Op18 }, + { Op19M1X1 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X1 }, + { Op1EM1X1 }, { Op1FM1 }, { Op20E0 }, { Op21E0M1 }, { Op22E0 }, + { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, + { Op28E0 }, { Op29M1 }, { Op2AM1 }, { Op2BE0 }, { Op2CM1 }, + { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E0 }, { Op31E0M1X1 }, + { Op32E0M1 }, { Op33M1 }, { Op34E0M1 }, { Op35E0M1 }, { Op36E0M1 }, + { Op37M1 }, { Op38 }, { Op39M1X1 }, { Op3AM1 }, { Op3B }, + { Op3CM1X1 }, { Op3DM1X1 }, { Op3EM1X1 }, { Op3FM1 }, { Op40Slow }, + { Op41E0M1 }, { Op42 }, { Op43M1 }, { Op44X1 }, { Op45M1 }, + { Op46M1 }, { Op47M1 }, { Op48E0M1 }, { Op49M1 }, { Op4AM1 }, + { Op4BE0 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, + { Op50E0 }, { Op51E0M1X1 }, { Op52E0M1 }, { Op53M1 }, { Op54X1 }, + { Op55E0M1 }, { Op56E0M1 }, { Op57M1 }, { Op58 }, { Op59M1X1 }, + { Op5AE0X1 }, { Op5B }, { Op5C }, { Op5DM1X1 }, { Op5EM1X1 }, + { Op5FM1 }, { Op60E0 }, { Op61E0M1 }, { Op62E0 }, { Op63M1 }, + { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E0M1 }, + { Op69M1 }, { Op6AM1 }, { Op6BE0 }, { Op6C }, { Op6DM1 }, + { Op6EM1 }, { Op6FM1 }, { Op70E0 }, { Op71E0M1X1 }, { Op72E0M1 }, + { Op73M1 }, { Op74E0M1 }, { Op75E0M1 }, { Op76E0M1 }, { Op77M1 }, + { Op78 }, { Op79M1X1 }, { Op7AE0X1 }, { Op7B }, { Op7C }, + { Op7DM1X1 }, { Op7EM1X1 }, { Op7FM1 }, { Op80E0 }, { Op81E0M1 }, + { Op82 }, { Op83M1 }, { Op84X1 }, { Op85M1 }, { Op86X1 }, + { Op87M1 }, { Op88X1 }, { Op89M1 }, { Op8AM1 }, { Op8BE0 }, + { Op8CX1 }, { Op8DM1 }, { Op8EX1 }, { Op8FM1 }, { Op90E0 }, + { Op91E0M1X1 }, { Op92E0M1 }, { Op93M1 }, { Op94E0X1 }, { Op95E0M1 }, + { Op96E0X1 }, { Op97M1 }, { Op98M1 }, { Op99M1X1 }, { Op9A }, + { Op9BX1 }, { Op9CM1 }, { Op9DM1X1 }, { Op9EM1X1 }, { Op9FM1 }, + { OpA0X1 }, { OpA1E0M1 }, { OpA2X1 }, { OpA3M1 }, { OpA4X1 }, + { OpA5M1 }, { OpA6X1 }, { OpA7M1 }, { OpA8X1 }, { OpA9M1 }, + { OpAAX1 }, { OpABE0 }, { OpACX1 }, { OpADM1 }, { OpAEX1 }, + { OpAFM1 }, { OpB0E0 }, { OpB1E0M1X1 }, { OpB2E0M1 }, { OpB3M1 }, + { OpB4E0X1 }, { OpB5E0M1 }, { OpB6E0X1 }, { OpB7M1 }, { OpB8 }, + { OpB9M1X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM1X1 }, + { OpBEX1 }, { OpBFM1 }, { OpC0X1 }, { OpC1E0M1 }, { OpC2 }, + { OpC3M1 }, { OpC4X1 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, + { OpC8X1 }, { OpC9M1 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, + { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E0 }, { OpD1E0M1X1 }, + { OpD2E0M1 }, { OpD3M1 }, { OpD4E0 }, { OpD5E0M1 }, { OpD6E0M1 }, + { OpD7M1 }, { OpD8 }, { OpD9M1X1 }, { OpDAE0X1 }, { OpDB }, + { OpDC }, { OpDDM1X1 }, { OpDEM1X1 }, { OpDFM1 }, { OpE0X1 }, + { OpE1E0M1 }, { OpE2 }, { OpE3M1 }, { OpE4X1 }, { OpE5M1 }, + { OpE6M1 }, { OpE7M1 }, { OpE8X1 }, { OpE9M1 }, { OpEA }, + { OpEB }, { OpECX1 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, + { OpF0E0 }, { OpF1E0M1X1 }, { OpF2E0M1 }, { OpF3M1 }, { OpF4E0 }, + { OpF5E0M1 }, { OpF6E0M1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X1 }, + { OpFAE0X1 }, { OpFB }, { OpFCE0 }, { OpFDM1X1 }, { OpFEM1X1 }, + { OpFFM1 } +}; + +struct SOpcodes S9xOpcodesE1[256] = +{ + { Op00 }, { Op01E1 }, { Op02 }, { Op03M1 }, { Op04M1 }, + { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E1 }, { Op09M1 }, + { Op0AM1 }, { Op0BE1 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, + { Op0FM1 }, { Op10E1 }, { Op11E1 }, { Op12E1 }, { Op13M1 }, + { Op14M1 }, { Op15E1 }, { Op16E1 }, { Op17M1 }, { Op18 }, + { Op19M1X1 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X1 }, + { Op1EM1X1 }, { Op1FM1 }, { Op20E1 }, { Op21E1 }, { Op22E1 }, + { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, + { Op28E1 }, { Op29M1 }, { Op2AM1 }, { Op2BE1 }, { Op2CM1 }, + { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E1 }, { Op31E1 }, + { Op32E1 }, { Op33M1 }, { Op34E1 }, { Op35E1 }, { Op36E1 }, + { Op37M1 }, { Op38 }, { Op39M1X1 }, { Op3AM1 }, { Op3B }, + { Op3CM1X1 }, { Op3DM1X1 }, { Op3EM1X1 }, { Op3FM1 }, { Op40Slow }, + { Op41E1 }, { Op42 }, { Op43M1 }, { Op44X1 }, { Op45M1 }, + { Op46M1 }, { Op47M1 }, { Op48E1 }, { Op49M1 }, { Op4AM1 }, + { Op4BE1 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, + { Op50E1 }, { Op51E1 }, { Op52E1 }, { Op53M1 }, { Op54X1 }, + { Op55E1 }, { Op56E1 }, { Op57M1 }, { Op58 }, { Op59M1X1 }, + { Op5AE1 }, { Op5B }, { Op5C }, { Op5DM1X1 }, { Op5EM1X1 }, + { Op5FM1 }, { Op60E1 }, { Op61E1 }, { Op62E1 }, { Op63M1 }, + { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E1 }, + { Op69M1 }, { Op6AM1 }, { Op6BE1 }, { Op6C }, { Op6DM1 }, + { Op6EM1 }, { Op6FM1 }, { Op70E1 }, { Op71E1 }, { Op72E1 }, + { Op73M1 }, { Op74E1 }, { Op75E1 }, { Op76E1 }, { Op77M1 }, + { Op78 }, { Op79M1X1 }, { Op7AE1 }, { Op7B }, { Op7C }, + { Op7DM1X1 }, { Op7EM1X1 }, { Op7FM1 }, { Op80E1 }, { Op81E1 }, + { Op82 }, { Op83M1 }, { Op84X1 }, { Op85M1 }, { Op86X1 }, + { Op87M1 }, { Op88X1 }, { Op89M1 }, { Op8AM1 }, { Op8BE1 }, + { Op8CX1 }, { Op8DM1 }, { Op8EX1 }, { Op8FM1 }, { Op90E1 }, + { Op91E1 }, { Op92E1 }, { Op93M1 }, { Op94E1 }, { Op95E1 }, + { Op96E1 }, { Op97M1 }, { Op98M1 }, { Op99M1X1 }, { Op9A }, + { Op9BX1 }, { Op9CM1 }, { Op9DM1X1 }, { Op9EM1X1 }, { Op9FM1 }, + { OpA0X1 }, { OpA1E1 }, { OpA2X1 }, { OpA3M1 }, { OpA4X1 }, + { OpA5M1 }, { OpA6X1 }, { OpA7M1 }, { OpA8X1 }, { OpA9M1 }, + { OpAAX1 }, { OpABE1 }, { OpACX1 }, { OpADM1 }, { OpAEX1 }, + { OpAFM1 }, { OpB0E1 }, { OpB1E1 }, { OpB2E1 }, { OpB3M1 }, + { OpB4E1 }, { OpB5E1 }, { OpB6E1 }, { OpB7M1 }, { OpB8 }, + { OpB9M1X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM1X1 }, + { OpBEX1 }, { OpBFM1 }, { OpC0X1 }, { OpC1E1 }, { OpC2 }, + { OpC3M1 }, { OpC4X1 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, + { OpC8X1 }, { OpC9M1 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, + { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E1 }, { OpD1E1 }, + { OpD2E1 }, { OpD3M1 }, { OpD4E1 }, { OpD5E1 }, { OpD6E1 }, + { OpD7M1 }, { OpD8 }, { OpD9M1X1 }, { OpDAE1 }, { OpDB }, + { OpDC }, { OpDDM1X1 }, { OpDEM1X1 }, { OpDFM1 }, { OpE0X1 }, + { OpE1E1 }, { OpE2 }, { OpE3M1 }, { OpE4X1 }, { OpE5M1 }, + { OpE6M1 }, { OpE7M1 }, { OpE8X1 }, { OpE9M1 }, { OpEA }, + { OpEB }, { OpECX1 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, + { OpF0E1 }, { OpF1E1 }, { OpF2E1 }, { OpF3M1 }, { OpF4E1 }, + { OpF5E1 }, { OpF6E1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X1 }, + { OpFAE1 }, { OpFB }, { OpFCE1 }, { OpFDM1X1 }, { OpFEM1X1 }, + { OpFFM1 } +}; + +struct SOpcodes S9xOpcodesM1X0[256] = +{ + { Op00 }, { Op01E0M1 }, { Op02 }, { Op03M1 }, { Op04M1 }, + { Op05M1 }, { Op06M1 }, { Op07M1 }, { Op08E0 }, { Op09M1 }, + { Op0AM1 }, { Op0BE0 }, { Op0CM1 }, { Op0DM1 }, { Op0EM1 }, + { Op0FM1 }, { Op10E0 }, { Op11E0M1X0 }, { Op12E0M1 }, { Op13M1 }, + { Op14M1 }, { Op15E0M1 }, { Op16E0M1 }, { Op17M1 }, { Op18 }, + { Op19M1X0 }, { Op1AM1 }, { Op1B }, { Op1CM1 }, { Op1DM1X0 }, + { Op1EM1X0 }, { Op1FM1 }, { Op20E0 }, { Op21E0M1 }, { Op22E0 }, + { Op23M1 }, { Op24M1 }, { Op25M1 }, { Op26M1 }, { Op27M1 }, + { Op28E0 }, { Op29M1 }, { Op2AM1 }, { Op2BE0 }, { Op2CM1 }, + { Op2DM1 }, { Op2EM1 }, { Op2FM1 }, { Op30E0 }, { Op31E0M1X0 }, + { Op32E0M1 }, { Op33M1 }, { Op34E0M1 }, { Op35E0M1 }, { Op36E0M1 }, + { Op37M1 }, { Op38 }, { Op39M1X0 }, { Op3AM1 }, { Op3B }, + { Op3CM1X0 }, { Op3DM1X0 }, { Op3EM1X0 }, { Op3FM1 }, { Op40Slow }, + { Op41E0M1 }, { Op42 }, { Op43M1 }, { Op44X0 }, { Op45M1 }, + { Op46M1 }, { Op47M1 }, { Op48E0M1 }, { Op49M1 }, { Op4AM1 }, + { Op4BE0 }, { Op4C }, { Op4DM1 }, { Op4EM1 }, { Op4FM1 }, + { Op50E0 }, { Op51E0M1X0 }, { Op52E0M1 }, { Op53M1 }, { Op54X0 }, + { Op55E0M1 }, { Op56E0M1 }, { Op57M1 }, { Op58 }, { Op59M1X0 }, + { Op5AE0X0 }, { Op5B }, { Op5C }, { Op5DM1X0 }, { Op5EM1X0 }, + { Op5FM1 }, { Op60E0 }, { Op61E0M1 }, { Op62E0 }, { Op63M1 }, + { Op64M1 }, { Op65M1 }, { Op66M1 }, { Op67M1 }, { Op68E0M1 }, + { Op69M1 }, { Op6AM1 }, { Op6BE0 }, { Op6C }, { Op6DM1 }, + { Op6EM1 }, { Op6FM1 }, { Op70E0 }, { Op71E0M1X0 }, { Op72E0M1 }, + { Op73M1 }, { Op74E0M1 }, { Op75E0M1 }, { Op76E0M1 }, { Op77M1 }, + { Op78 }, { Op79M1X0 }, { Op7AE0X0 }, { Op7B }, { Op7C }, + { Op7DM1X0 }, { Op7EM1X0 }, { Op7FM1 }, { Op80E0 }, { Op81E0M1 }, + { Op82 }, { Op83M1 }, { Op84X0 }, { Op85M1 }, { Op86X0 }, + { Op87M1 }, { Op88X0 }, { Op89M1 }, { Op8AM1 }, { Op8BE0 }, + { Op8CX0 }, { Op8DM1 }, { Op8EX0 }, { Op8FM1 }, { Op90E0 }, + { Op91E0M1X0 }, { Op92E0M1 }, { Op93M1 }, { Op94E0X0 }, { Op95E0M1 }, + { Op96E0X0 }, { Op97M1 }, { Op98M1 }, { Op99M1X0 }, { Op9A }, + { Op9BX0 }, { Op9CM1 }, { Op9DM1X0 }, { Op9EM1X0 }, { Op9FM1 }, + { OpA0X0 }, { OpA1E0M1 }, { OpA2X0 }, { OpA3M1 }, { OpA4X0 }, + { OpA5M1 }, { OpA6X0 }, { OpA7M1 }, { OpA8X0 }, { OpA9M1 }, + { OpAAX0 }, { OpABE0 }, { OpACX0 }, { OpADM1 }, { OpAEX0 }, + { OpAFM1 }, { OpB0E0 }, { OpB1E0M1X0 }, { OpB2E0M1 }, { OpB3M1 }, + { OpB4E0X0 }, { OpB5E0M1 }, { OpB6E0X0 }, { OpB7M1 }, { OpB8 }, + { OpB9M1X0 }, { OpBAX0 }, { OpBBX0 }, { OpBCX0 }, { OpBDM1X0 }, + { OpBEX0 }, { OpBFM1 }, { OpC0X0 }, { OpC1E0M1 }, { OpC2 }, + { OpC3M1 }, { OpC4X0 }, { OpC5M1 }, { OpC6M1 }, { OpC7M1 }, + { OpC8X0 }, { OpC9M1 }, { OpCAX0 }, { OpCB }, { OpCCX0 }, + { OpCDM1 }, { OpCEM1 }, { OpCFM1 }, { OpD0E0 }, { OpD1E0M1X0 }, + { OpD2E0M1 }, { OpD3M1 }, { OpD4E0 }, { OpD5E0M1 }, { OpD6E0M1 }, + { OpD7M1 }, { OpD8 }, { OpD9M1X0 }, { OpDAE0X0 }, { OpDB }, + { OpDC }, { OpDDM1X0 }, { OpDEM1X0 }, { OpDFM1 }, { OpE0X0 }, + { OpE1E0M1 }, { OpE2 }, { OpE3M1 }, { OpE4X0 }, { OpE5M1 }, + { OpE6M1 }, { OpE7M1 }, { OpE8X0 }, { OpE9M1 }, { OpEA }, + { OpEB }, { OpECX0 }, { OpEDM1 }, { OpEEM1 }, { OpEFM1 }, + { OpF0E0 }, { OpF1E0M1X0 }, { OpF2E0M1 }, { OpF3M1 }, { OpF4E0 }, + { OpF5E0M1 }, { OpF6E0M1 }, { OpF7M1 }, { OpF8 }, { OpF9M1X0 }, + { OpFAE0X0 }, { OpFB }, { OpFCE0 }, { OpFDM1X0 }, { OpFEM1X0 }, + { OpFFM1 } +}; + +struct SOpcodes S9xOpcodesM0X0[256] = +{ + { Op00 }, { Op01E0M0 }, { Op02 }, { Op03M0 }, { Op04M0 }, + { Op05M0 }, { Op06M0 }, { Op07M0 }, { Op08E0 }, { Op09M0 }, + { Op0AM0 }, { Op0BE0 }, { Op0CM0 }, { Op0DM0 }, { Op0EM0 }, + { Op0FM0 }, { Op10E0 }, { Op11E0M0X0 }, { Op12E0M0 }, { Op13M0 }, + { Op14M0 }, { Op15E0M0 }, { Op16E0M0 }, { Op17M0 }, { Op18 }, + { Op19M0X0 }, { Op1AM0 }, { Op1B }, { Op1CM0 }, { Op1DM0X0 }, + { Op1EM0X0 }, { Op1FM0 }, { Op20E0 }, { Op21E0M0 }, { Op22E0 }, + { Op23M0 }, { Op24M0 }, { Op25M0 }, { Op26M0 }, { Op27M0 }, + { Op28E0 }, { Op29M0 }, { Op2AM0 }, { Op2BE0 }, { Op2CM0 }, + { Op2DM0 }, { Op2EM0 }, { Op2FM0 }, { Op30E0 }, { Op31E0M0X0 }, + { Op32E0M0 }, { Op33M0 }, { Op34E0M0 }, { Op35E0M0 }, { Op36E0M0 }, + { Op37M0 }, { Op38 }, { Op39M0X0 }, { Op3AM0 }, { Op3B }, + { Op3CM0X0 }, { Op3DM0X0 }, { Op3EM0X0 }, { Op3FM0 }, { Op40Slow }, + { Op41E0M0 }, { Op42 }, { Op43M0 }, { Op44X0 }, { Op45M0 }, + { Op46M0 }, { Op47M0 }, { Op48E0M0 }, { Op49M0 }, { Op4AM0 }, + { Op4BE0 }, { Op4C }, { Op4DM0 }, { Op4EM0 }, { Op4FM0 }, + { Op50E0 }, { Op51E0M0X0 }, { Op52E0M0 }, { Op53M0 }, { Op54X0 }, + { Op55E0M0 }, { Op56E0M0 }, { Op57M0 }, { Op58 }, { Op59M0X0 }, + { Op5AE0X0 }, { Op5B }, { Op5C }, { Op5DM0X0 }, { Op5EM0X0 }, + { Op5FM0 }, { Op60E0 }, { Op61E0M0 }, { Op62E0 }, { Op63M0 }, + { Op64M0 }, { Op65M0 }, { Op66M0 }, { Op67M0 }, { Op68E0M0 }, + { Op69M0 }, { Op6AM0 }, { Op6BE0 }, { Op6C }, { Op6DM0 }, + { Op6EM0 }, { Op6FM0 }, { Op70E0 }, { Op71E0M0X0 }, { Op72E0M0 }, + { Op73M0 }, { Op74E0M0 }, { Op75E0M0 }, { Op76E0M0 }, { Op77M0 }, + { Op78 }, { Op79M0X0 }, { Op7AE0X0 }, { Op7B }, { Op7C }, + { Op7DM0X0 }, { Op7EM0X0 }, { Op7FM0 }, { Op80E0 }, { Op81E0M0 }, + { Op82 }, { Op83M0 }, { Op84X0 }, { Op85M0 }, { Op86X0 }, + { Op87M0 }, { Op88X0 }, { Op89M0 }, { Op8AM0 }, { Op8BE0 }, + { Op8CX0 }, { Op8DM0 }, { Op8EX0 }, { Op8FM0 }, { Op90E0 }, + { Op91E0M0X0 }, { Op92E0M0 }, { Op93M0 }, { Op94E0X0 }, { Op95E0M0 }, + { Op96E0X0 }, { Op97M0 }, { Op98M0 }, { Op99M0X0 }, { Op9A }, + { Op9BX0 }, { Op9CM0 }, { Op9DM0X0 }, { Op9EM0X0 }, { Op9FM0 }, + { OpA0X0 }, { OpA1E0M0 }, { OpA2X0 }, { OpA3M0 }, { OpA4X0 }, + { OpA5M0 }, { OpA6X0 }, { OpA7M0 }, { OpA8X0 }, { OpA9M0 }, + { OpAAX0 }, { OpABE0 }, { OpACX0 }, { OpADM0 }, { OpAEX0 }, + { OpAFM0 }, { OpB0E0 }, { OpB1E0M0X0 }, { OpB2E0M0 }, { OpB3M0 }, + { OpB4E0X0 }, { OpB5E0M0 }, { OpB6E0X0 }, { OpB7M0 }, { OpB8 }, + { OpB9M0X0 }, { OpBAX0 }, { OpBBX0 }, { OpBCX0 }, { OpBDM0X0 }, + { OpBEX0 }, { OpBFM0 }, { OpC0X0 }, { OpC1E0M0 }, { OpC2 }, + { OpC3M0 }, { OpC4X0 }, { OpC5M0 }, { OpC6M0 }, { OpC7M0 }, + { OpC8X0 }, { OpC9M0 }, { OpCAX0 }, { OpCB }, { OpCCX0 }, + { OpCDM0 }, { OpCEM0 }, { OpCFM0 }, { OpD0E0 }, { OpD1E0M0X0 }, + { OpD2E0M0 }, { OpD3M0 }, { OpD4E0 }, { OpD5E0M0 }, { OpD6E0M0 }, + { OpD7M0 }, { OpD8 }, { OpD9M0X0 }, { OpDAE0X0 }, { OpDB }, + { OpDC }, { OpDDM0X0 }, { OpDEM0X0 }, { OpDFM0 }, { OpE0X0 }, + { OpE1E0M0 }, { OpE2 }, { OpE3M0 }, { OpE4X0 }, { OpE5M0 }, + { OpE6M0 }, { OpE7M0 }, { OpE8X0 }, { OpE9M0 }, { OpEA }, + { OpEB }, { OpECX0 }, { OpEDM0 }, { OpEEM0 }, { OpEFM0 }, + { OpF0E0 }, { OpF1E0M0X0 }, { OpF2E0M0 }, { OpF3M0 }, { OpF4E0 }, + { OpF5E0M0 }, { OpF6E0M0 }, { OpF7M0 }, { OpF8 }, { OpF9M0X0 }, + { OpFAE0X0 }, { OpFB }, { OpFCE0 }, { OpFDM0X0 }, { OpFEM0X0 }, + { OpFFM0 } +}; + +struct SOpcodes S9xOpcodesM0X1[256] = +{ + { Op00 }, { Op01E0M0 }, { Op02 }, { Op03M0 }, { Op04M0 }, + { Op05M0 }, { Op06M0 }, { Op07M0 }, { Op08E0 }, { Op09M0 }, + { Op0AM0 }, { Op0BE0 }, { Op0CM0 }, { Op0DM0 }, { Op0EM0 }, + { Op0FM0 }, { Op10E0 }, { Op11E0M0X1 }, { Op12E0M0 }, { Op13M0 }, + { Op14M0 }, { Op15E0M0 }, { Op16E0M0 }, { Op17M0 }, { Op18 }, + { Op19M0X1 }, { Op1AM0 }, { Op1B }, { Op1CM0 }, { Op1DM0X1 }, + { Op1EM0X1 }, { Op1FM0 }, { Op20E0 }, { Op21E0M0 }, { Op22E0 }, + { Op23M0 }, { Op24M0 }, { Op25M0 }, { Op26M0 }, { Op27M0 }, + { Op28E0 }, { Op29M0 }, { Op2AM0 }, { Op2BE0 }, { Op2CM0 }, + { Op2DM0 }, { Op2EM0 }, { Op2FM0 }, { Op30E0 }, { Op31E0M0X1 }, + { Op32E0M0 }, { Op33M0 }, { Op34E0M0 }, { Op35E0M0 }, { Op36E0M0 }, + { Op37M0 }, { Op38 }, { Op39M0X1 }, { Op3AM0 }, { Op3B }, + { Op3CM0X1 }, { Op3DM0X1 }, { Op3EM0X1 }, { Op3FM0 }, { Op40Slow }, + { Op41E0M0 }, { Op42 }, { Op43M0 }, { Op44X1 }, { Op45M0 }, + { Op46M0 }, { Op47M0 }, { Op48E0M0 }, { Op49M0 }, { Op4AM0 }, + { Op4BE0 }, { Op4C }, { Op4DM0 }, { Op4EM0 }, { Op4FM0 }, + { Op50E0 }, { Op51E0M0X1 }, { Op52E0M0 }, { Op53M0 }, { Op54X1 }, + { Op55E0M0 }, { Op56E0M0 }, { Op57M0 }, { Op58 }, { Op59M0X1 }, + { Op5AE0X1 }, { Op5B }, { Op5C }, { Op5DM0X1 }, { Op5EM0X1 }, + { Op5FM0 }, { Op60E0 }, { Op61E0M0 }, { Op62E0 }, { Op63M0 }, + { Op64M0 }, { Op65M0 }, { Op66M0 }, { Op67M0 }, { Op68E0M0 }, + { Op69M0 }, { Op6AM0 }, { Op6BE0 }, { Op6C }, { Op6DM0 }, + { Op6EM0 }, { Op6FM0 }, { Op70E0 }, { Op71E0M0X1 }, { Op72E0M0 }, + { Op73M0 }, { Op74E0M0 }, { Op75E0M0 }, { Op76E0M0 }, { Op77M0 }, + { Op78 }, { Op79M0X1 }, { Op7AE0X1 }, { Op7B }, { Op7C }, + { Op7DM0X1 }, { Op7EM0X1 }, { Op7FM0 }, { Op80E0 }, { Op81E0M0 }, + { Op82 }, { Op83M0 }, { Op84X1 }, { Op85M0 }, { Op86X1 }, + { Op87M0 }, { Op88X1 }, { Op89M0 }, { Op8AM0 }, { Op8BE0 }, + { Op8CX1 }, { Op8DM0 }, { Op8EX1 }, { Op8FM0 }, { Op90E0 }, + { Op91E0M0X1 }, { Op92E0M0 }, { Op93M0 }, { Op94E0X1 }, { Op95E0M0 }, + { Op96E0X1 }, { Op97M0 }, { Op98M0 }, { Op99M0X1 }, { Op9A }, + { Op9BX1 }, { Op9CM0 }, { Op9DM0X1 }, { Op9EM0X1 }, { Op9FM0 }, + { OpA0X1 }, { OpA1E0M0 }, { OpA2X1 }, { OpA3M0 }, { OpA4X1 }, + { OpA5M0 }, { OpA6X1 }, { OpA7M0 }, { OpA8X1 }, { OpA9M0 }, + { OpAAX1 }, { OpABE0 }, { OpACX1 }, { OpADM0 }, { OpAEX1 }, + { OpAFM0 }, { OpB0E0 }, { OpB1E0M0X1 }, { OpB2E0M0 }, { OpB3M0 }, + { OpB4E0X1 }, { OpB5E0M0 }, { OpB6E0X1 }, { OpB7M0 }, { OpB8 }, + { OpB9M0X1 }, { OpBAX1 }, { OpBBX1 }, { OpBCX1 }, { OpBDM0X1 }, + { OpBEX1 }, { OpBFM0 }, { OpC0X1 }, { OpC1E0M0 }, { OpC2 }, + { OpC3M0 }, { OpC4X1 }, { OpC5M0 }, { OpC6M0 }, { OpC7M0 }, + { OpC8X1 }, { OpC9M0 }, { OpCAX1 }, { OpCB }, { OpCCX1 }, + { OpCDM0 }, { OpCEM0 }, { OpCFM0 }, { OpD0E0 }, { OpD1E0M0X1 }, + { OpD2E0M0 }, { OpD3M0 }, { OpD4E0 }, { OpD5E0M0 }, { OpD6E0M0 }, + { OpD7M0 }, { OpD8 }, { OpD9M0X1 }, { OpDAE0X1 }, { OpDB }, + { OpDC }, { OpDDM0X1 }, { OpDEM0X1 }, { OpDFM0 }, { OpE0X1 }, + { OpE1E0M0 }, { OpE2 }, { OpE3M0 }, { OpE4X1 }, { OpE5M0 }, + { OpE6M0 }, { OpE7M0 }, { OpE8X1 }, { OpE9M0 }, { OpEA }, + { OpEB }, { OpECX1 }, { OpEDM0 }, { OpEEM0 }, { OpEFM0 }, + { OpF0E0 }, { OpF1E0M0X1 }, { OpF2E0M0 }, { OpF3M0 }, { OpF4E0 }, + { OpF5E0M0 }, { OpF6E0M0 }, { OpF7M0 }, { OpF8 }, { OpF9M0X1 }, + { OpFAE0X1 }, { OpFB }, { OpFCE0 }, { OpFDM0X1 }, { OpFEM0X1 }, + { OpFFM0 } +}; + +struct SOpcodes S9xOpcodesSlow[256] = +{ + { Op00 }, { Op01Slow }, { Op02 }, { Op03Slow }, { Op04Slow }, + { Op05Slow }, { Op06Slow }, { Op07Slow }, { Op08Slow }, { Op09Slow }, + { Op0ASlow }, { Op0BSlow }, { Op0CSlow }, { Op0DSlow }, { Op0ESlow }, + { Op0FSlow }, { Op10Slow }, { Op11Slow }, { Op12Slow }, { Op13Slow }, + { Op14Slow }, { Op15Slow }, { Op16Slow }, { Op17Slow }, { Op18 }, + { Op19Slow }, { Op1ASlow }, { Op1B }, { Op1CSlow }, { Op1DSlow }, + { Op1ESlow }, { Op1FSlow }, { Op20Slow }, { Op21Slow }, { Op22Slow }, + { Op23Slow }, { Op24Slow }, { Op25Slow }, { Op26Slow }, { Op27Slow }, + { Op28Slow }, { Op29Slow }, { Op2ASlow }, { Op2BSlow }, { Op2CSlow }, + { Op2DSlow }, { Op2ESlow }, { Op2FSlow }, { Op30Slow }, { Op31Slow }, + { Op32Slow }, { Op33Slow }, { Op34Slow }, { Op35Slow }, { Op36Slow }, + { Op37Slow }, { Op38 }, { Op39Slow }, { Op3ASlow }, { Op3B }, + { Op3CSlow }, { Op3DSlow }, { Op3ESlow }, { Op3FSlow }, { Op40Slow }, + { Op41Slow }, { Op42 }, { Op43Slow }, { Op44Slow }, { Op45Slow }, + { Op46Slow }, { Op47Slow }, { Op48Slow }, { Op49Slow }, { Op4ASlow }, + { Op4BSlow }, { Op4CSlow }, { Op4DSlow }, { Op4ESlow }, { Op4FSlow }, + { Op50Slow }, { Op51Slow }, { Op52Slow }, { Op53Slow }, { Op54Slow }, + { Op55Slow }, { Op56Slow }, { Op57Slow }, { Op58 }, { Op59Slow }, + { Op5ASlow }, { Op5B }, { Op5CSlow }, { Op5DSlow }, { Op5ESlow }, + { Op5FSlow }, { Op60Slow }, { Op61Slow }, { Op62Slow }, { Op63Slow }, + { Op64Slow }, { Op65Slow }, { Op66Slow }, { Op67Slow }, { Op68Slow }, + { Op69Slow }, { Op6ASlow }, { Op6BSlow }, { Op6CSlow }, { Op6DSlow }, + { Op6ESlow }, { Op6FSlow }, { Op70Slow }, { Op71Slow }, { Op72Slow }, + { Op73Slow }, { Op74Slow }, { Op75Slow }, { Op76Slow }, { Op77Slow }, + { Op78 }, { Op79Slow }, { Op7ASlow }, { Op7B }, { Op7CSlow }, + { Op7DSlow }, { Op7ESlow }, { Op7FSlow }, { Op80Slow }, { Op81Slow }, + { Op82Slow }, { Op83Slow }, { Op84Slow }, { Op85Slow }, { Op86Slow }, + { Op87Slow }, { Op88Slow }, { Op89Slow }, { Op8ASlow }, { Op8BSlow }, + { Op8CSlow }, { Op8DSlow }, { Op8ESlow }, { Op8FSlow }, { Op90Slow }, + { Op91Slow }, { Op92Slow }, { Op93Slow }, { Op94Slow }, { Op95Slow }, + { Op96Slow }, { Op97Slow }, { Op98Slow }, { Op99Slow }, { Op9A }, + { Op9BSlow }, { Op9CSlow }, { Op9DSlow }, { Op9ESlow }, { Op9FSlow }, + { OpA0Slow }, { OpA1Slow }, { OpA2Slow }, { OpA3Slow }, { OpA4Slow }, + { OpA5Slow }, { OpA6Slow }, { OpA7Slow }, { OpA8Slow }, { OpA9Slow }, + { OpAASlow }, { OpABSlow }, { OpACSlow }, { OpADSlow }, { OpAESlow }, + { OpAFSlow }, { OpB0Slow }, { OpB1Slow }, { OpB2Slow }, { OpB3Slow }, + { OpB4Slow }, { OpB5Slow }, { OpB6Slow }, { OpB7Slow }, { OpB8 }, + { OpB9Slow }, { OpBASlow }, { OpBBSlow }, { OpBCSlow }, { OpBDSlow }, + { OpBESlow }, { OpBFSlow }, { OpC0Slow }, { OpC1Slow }, { OpC2Slow }, + { OpC3Slow }, { OpC4Slow }, { OpC5Slow }, { OpC6Slow }, { OpC7Slow }, + { OpC8Slow }, { OpC9Slow }, { OpCASlow }, { OpCB }, { OpCCSlow }, + { OpCDSlow }, { OpCESlow }, { OpCFSlow }, { OpD0Slow }, { OpD1Slow }, + { OpD2Slow }, { OpD3Slow }, { OpD4Slow }, { OpD5Slow }, { OpD6Slow }, + { OpD7Slow }, { OpD8 }, { OpD9Slow }, { OpDASlow }, { OpDB }, + { OpDCSlow }, { OpDDSlow }, { OpDESlow }, { OpDFSlow }, { OpE0Slow }, + { OpE1Slow }, { OpE2Slow }, { OpE3Slow }, { OpE4Slow }, { OpE5Slow }, + { OpE6Slow }, { OpE7Slow }, { OpE8Slow }, { OpE9Slow }, { OpEA }, + { OpEB }, { OpECSlow }, { OpEDSlow }, { OpEESlow }, { OpEFSlow }, + { OpF0Slow }, { OpF1Slow }, { OpF2Slow }, { OpF3Slow }, { OpF4Slow }, + { OpF5Slow }, { OpF6Slow }, { OpF7Slow }, { OpF8 }, { OpF9Slow }, + { OpFASlow }, { OpFB }, { OpFCSlow }, { OpFDSlow }, { OpFESlow }, + { OpFFSlow } +}; diff --git a/cpuops.h b/cpuops.h new file mode 100644 index 00000000..acb34060 --- /dev/null +++ b/cpuops.h @@ -0,0 +1,188 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _CPUOPS_H_ +#define _CPUOPS_H_ + +void S9xOpcode_NMI (void); +void S9xOpcode_IRQ (void); + +#define CHECK_FOR_IRQ() \ +if (CPU.IRQActive && !CheckFlag(IRQ) && !Settings.DisableIRQ) \ + S9xOpcode_IRQ() + +#endif diff --git a/crosshairs.cpp b/crosshairs.cpp new file mode 100644 index 00000000..7c3f3851 --- /dev/null +++ b/crosshairs.cpp @@ -0,0 +1,682 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 HAVE_LIBPNG +#include +#endif +#include "port.h" +#include "crosshairs.h" + +static const char *crosshairs[32] = +{ + "` " // Crosshair 0 (no image) + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " " + " ", + + "` " // Crosshair 1 (the classic small dot) + " " + " " + " " + " " + " " + " " + " #. " + " " + " " + " " + " " + " " + " " + " ", + + "` " // Crosshair 2 (a standard cross) + " " + " " + " " + " .#. " + " .#. " + " ...#... " + " ####### " + " ...#... " + " .#. " + " .#. " + " " + " " + " " + " ", + + "` .#. " // Crosshair 3 (a standard cross) + " .#. " + " .#. " + " .#. " + " .#. " + " .#. " + ".......#......." + "###############" + ".......#......." + " .#. " + " .#. " + " .#. " + " .#. " + " .#. " + " .#. ", + + "` " // Crosshair 4 (an X) + " " + " " + " . . " + " .#. .#. " + " .#. .#. " + " .#.#. " + " .#. " + " .#.#. " + " .#. .#. " + " .#. .#. " + " . . " + " " + " " + " ", + + "`. . " // Crosshair 5 (an X) + ".#. .#." + " .#. .#. " + " .#. .#. " + " .#. .#. " + " .#. .#. " + " .#.#. " + " .#. " + " .#.#. " + " .#. .#. " + " .#. .#. " + " .#. .#. " + " .#. .#. " + ".#. .#." + " . . ", + + "` " // Crosshair 6 (a combo) + " " + " " + " " + " # . # " + " # . # " + " #.# " + " ...#... " + " #.# " + " # . # " + " # . # " + " " + " " + " " + " ", + + "` . " // Crosshair 7 (a combo) + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + " #.# " + ".......#......." + " #.# " + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + " . ", + + "` # " // Crosshair 8 (a diamond cross) + " #.# " + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + "#......#......#" + " # . # " + " # . # " + " # . # " + " # . # " + " # . # " + " #.# " + " # ", + + "` ### " // Crosshair 9 (a circle cross) + " ## . ## " + " # . # " + " # . # " + " # . # " + " # . # " + "# . #" + "#......#......#" + "# . #" + " # . # " + " # . # " + " # . # " + " # . # " + " ## . ## " + " ### ", + + "` .#. " // Crosshair 10 (a square cross) + " .#. " + " .#. " + " ....#.... " + " .#######. " + " .# #. " + "....# #...." + "##### #####" + "....# #...." + " .# #. " + " .#######. " + " ....#.... " + " .#. " + " .#. " + " .#. ", + + "` .#. " // Crosshair 11 (an interrupted cross) + " .#. " + " .#. " + " .#. " + " .#. " + " " + "..... ....." + "##### #####" + "..... ....." + " " + " .#. " + " .#. " + " .#. " + " .#. " + " .#. ", + + "`. . " // Crosshair 12 (an interrupted X) + ".#. .#." + " .#. .#. " + " .#. .#. " + " .#. .#. " + " " + " " + " " + " " + " " + " .#. .#. " + " .#. .#. " + " .#. .#. " + ".#. .#." + " . . ", + + "` . " // Crosshair 13 (an interrupted combo) + " # . # " + " # . # " + " # . # " + " # . # " + " " + " " + "..... ....." + " " + " " + " # . # " + " # . # " + " # . # " + " # . # " + " . ", + + "`#### #### " // Crosshair 14 + "#.... ....#" + "#. .#" + "#. .#" + "#. .#" + " # " + " # " + " ##### " + " # " + " # " + "#. .#" + "#. .#" + "#. .#" + "#.... ....#" + " #### #### ", + + "` .# #. " // Crosshair 15 + " .# #. " + " .# #. " + "....# #...." + "##### #####" + " " + " " + " " + " " + " " + "##### #####" + "....# #...." + " .# #. " + " .# #. " + " .# #. ", + + "` # " // Crosshair 16 + " # " + " # " + " ....#.... " + " . # . " + " . # . " + " . # . " + "###############" + " . # . " + " . # . " + " . # . " + " ....#.... " + " # " + " # " + " # ", + + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + + +bool S9xLoadCrosshairFile (int idx, const char *filename) +{ + if (idx < 1 || idx > 31) + return (false); + + char *s = (char *) calloc(15 * 15 + 1, sizeof(char)); + if (s == NULL) + { + fprintf(stderr, "S9xLoadCrosshairFile: malloc error while reading "); + perror(filename); + return (false); + } + + FILE *fp = fopen(filename, "rb"); + if (fp == NULL) + { + fprintf(stderr, "S9xLoadCrosshairFile: Couldn't open "); + perror(filename); + free(s); + return (false); + } + + size_t l = fread(s, 1, 8, fp); + if (l != 8) + { + fprintf(stderr, "S9xLoadCrosshairFile: File is too short!\n"); + free(s); + fclose(fp); + return (false); + } + +#ifdef HAVE_LIBPNG + png_structp png_ptr; + png_infop info_ptr; + + if (!png_sig_cmp((png_byte *) s, 0, 8)) + { + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + free(s); + fclose(fp); + return (false); + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + png_uint_32 width, height; + int bit_depth, color_type; + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + if (color_type != PNG_COLOR_TYPE_PALETTE) + { + fprintf(stderr, "S9xLoadCrosshairFile: Input PNG is not a palettized image!\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + + if (width != 15 || height != 15) + { + fprintf(stderr, "S9xLoadCrosshairFile: Expecting a 15x15 PNG\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + + png_color *pngpal; + png_byte *trans; + int num_palette = 0, num_trans = 0; + int transcol = -1, fgcol = -1, bgcol = -1; + + png_get_PLTE(png_ptr, info_ptr, &pngpal, &num_palette); + png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); + + if (num_palette != 3 || num_trans != 1) + { + fprintf(stderr, "S9xLoadCrosshairFile: Expecting a 3-color PNG with 1 trasnparent color\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + + for (int i = 0; i < 3; i++) + { + if (trans[0] == i) + transcol = i; + else + if (pngpal[i].red == 0 && pngpal[i].green == 0 && pngpal[i].blue == 0) + bgcol = i; + else + if (pngpal[i].red == 255 && pngpal[i].green == 255 && pngpal[i].blue == 255) + fgcol = i; + } + + if (transcol < 0 || fgcol < 0 || bgcol < 0) + { + fprintf(stderr, "S9xLoadCrosshairFile: PNG must have 3 colors: white (fg), black (bg), and transparent.\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + + png_set_packing(png_ptr); + png_read_update_info(png_ptr, info_ptr); + png_byte *row_pointer = new png_byte[png_get_rowbytes(png_ptr, info_ptr)]; + + for (int r = 0; r < 15 * 15; r += 15) + { + png_read_row(png_ptr, row_pointer, NULL); + + for (int i = 0; i < 15; i++) + { + if (row_pointer[i] == transcol) + s[r + i] = ' '; + else + if (row_pointer[i] == fgcol) + s[r + i] = '#'; + else + if (row_pointer[i] == bgcol) + s[r + i] = '.'; + else + { + fprintf(stderr, "S9xLoadCrosshairFile: WTF? This was supposed to be a 3-color PNG!\n"); + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + free(s); + fclose(fp); + return (false); + } + } + } + + s[15 * 15] = 0; + png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); + } + else +#endif + { + l = fread(s + 8, 1, 15 - 8, fp); + if (l != 15 - 8) + { + fprintf(stderr, "S9xLoadCrosshairFile: File is too short!\n"); + free(s); + fclose(fp); + return (false); + } + + if (getc(fp) != '\n') + { + fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format! (note: PNG support is not available)\n"); + free(s); + fclose(fp); + return (false); + } + + for (int r = 1; r < 15; r++) + { + l = fread(s + r * 15, 1, 15, fp); + if (l != 15) + { + fprintf(stderr, "S9xLoadCrosshairFile: File is too short! (note: PNG support is not available)\n"); + free(s); + fclose(fp); + return (false); + } + + if (getc(fp) != '\n') + { + fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format! (note: PNG support is not available)\n"); + free(s); + fclose(fp); + return (false); + } + } + + for (int i = 0; i < 15 * 15; i++) + { + if (s[i] != ' ' && s[i] != '#' && s[i] != '.') + { + fprintf(stderr, "S9xLoadCrosshairFile: Invalid file format! (note: PNG support is not available)\n"); + free(s); + fclose(fp); + return (false); + } + } + } + + fclose(fp); + + if (crosshairs[idx] != NULL && crosshairs[idx][0] != '`') + free((void *) crosshairs[idx]); + crosshairs[idx] = s; + + return (true); +} + +const char * S9xGetCrosshair (int idx) +{ + if (idx < 0 || idx > 31) + return (NULL); + + return (crosshairs[idx]); +} diff --git a/crosshairs.h b/crosshairs.h new file mode 100644 index 00000000..16c3811d --- /dev/null +++ b/crosshairs.h @@ -0,0 +1,233 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _CROSSHAIRS_H_ +#define _CROSSHAIRS_H_ + +// Read in the specified crosshair file, replacing whatever data might be in that slot. +// Available slots are 1-31. +// The input file must be a PNG or a text file. +// PNG: 15x15 pixels, palettized, with 3 colors (white, black, and transparent). +// text: 15 lines of 16 characters (counting the \n), consisting of ' ', '#', or '.'. + +bool S9xLoadCrosshairFile (int idx, const char *filename); + +// Return the specified crosshair. Woo-hoo. +// char * to a 225-byte string, with '#' marking foreground, '.' marking background, +// and anything else transparent. + +const char * S9xGetCrosshair (int idx); + +// In controls.cpp. Sets the crosshair for the specified device. Defaults are: +// cross fgcolor bgcolor +// Mouse 1: 1 White Black +// Mouse 2: 1 Purple White +// Superscope: 2 White Black +// Justifier 1: 4 Blue Black +// Justifier 2: 4 MagicPink Black +// +// Available colors are: Trans, Black, 25Grey, 50Grey, 75Grey, White, Red, Orange, +// Yellow, Green, Cyan, Sky, Blue, Violet, MagicPink, and Purple. +// You may also prefix a 't' (e.g. tBlue) for a 50%-transparent version. +// Use idx = -1 or fg/bg = NULL to keep the current setting. + +enum crosscontrols +{ + X_MOUSE1, + X_MOUSE2, + X_SUPERSCOPE, + X_JUSTIFIER1, + X_JUSTIFIER2 +}; + +void S9xSetControllerCrosshair (enum crosscontrols ctl, int8 idx, const char *fg, const char *bg); +void S9xGetControllerCrosshair (enum crosscontrols ctl, int8 *idx, const char **fg, const char **bg); + +// In gfx.cpp, much like S9xDisplayChar() except it takes the parameters +// listed and looks up GFX.Screen. +// The 'crosshair' arg is a 15x15 image, with '#' meaning fgcolor, +// '.' meaning bgcolor, and anything else meaning transparent. +// Color values should be (RGB): +// 0 = transparent 4 = 23 23 23 8 = 31 31 0 12 = 0 0 31 +// 1 = 0 0 0 5 = 31 31 31 9 = 0 31 0 13 = 23 0 31 +// 2 = 8 8 8 6 = 31 0 0 10 = 0 31 31 14 = 31 0 31 +// 3 = 16 16 16 7 = 31 16 0 11 = 0 23 31 15 = 31 0 16 +// 16-31 are 50% transparent versions of 0-15. + +void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 x, int16 y); + +#endif diff --git a/debug.cpp b/debug.cpp new file mode 100644 index 00000000..94918e68 --- /dev/null +++ b/debug.cpp @@ -0,0 +1,2533 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 DEBUGGER + +#include +#include "snes9x.h" +#include "memmap.h" +#include "cpuops.h" +#include "dma.h" +#include "apu/apu.h" +#include "display.h" +#include "debug.h" +#include "missing.h" + +extern SDMA DMA[8]; +extern FILE *apu_trace; +FILE *trace = NULL, *trace2 = NULL; + +struct SBreakPoint S9xBreakpoint[6]; + +struct SDebug +{ + struct + { + uint8 Bank; + uint16 Address; + } Dump; + + struct + { + uint8 Bank; + uint16 Address; + } Unassemble; +}; + +static struct SDebug Debug = { { 0, 0 }, { 0, 0 } }; + +static const char *HelpMessage[] = +{ + "Command Help:", + "?, help - Shows this command help", + "r - Shows the registers", + "i - Shows the interrupt vectors", + "t - Trace current instruction [step-into]", + "p - Proceed to next instruction [step-over]", + "s - Skip to next instruction [skip]", + "T - Toggle CPU instruction tracing to trace.log", + "TS - Toggle SA-1 instruction tracing to trace_sa1.log", + "E - Toggle HC-based event tracing to trace.log", + "V - Toggle non-DMA V-RAM read/write tracing to stdout", + "D - Toggle on-screen DMA tracing", + "H - Toggle on-screen HDMA tracing", + "U - Toggle on-screen unknown register read/write tracing", + "P - Toggle on-screen DSP tracing", + "S - Dump sprite (OBJ) status", + "g [Address] - Go or go to [Address]", + "u [Address] - Disassemble from PC or [Address]", + "d [Address] - Dump from PC or [Address]", + "bv [Number] - View breakpoints or view breakpoint [Number]", + "bs [Number] [Address] - Enable/disable breakpoint", + " [enable example: bs #2 $02:8002]", + " [disable example: bs #2]", + "c - Dump SNES colour palette", + "W - Show what SNES hardware features the ROM is using", + " which might not be implemented yet", + "w - Show some SNES hardware features used so far in this frame", + "R - Reset SNES", + "q - Quit emulation", +// "ai - Shou APU vectors", +// "a - Show APU status", +// "x - Show Sound DSP status", +// "A - Toggle APU instruction tracing to aputrace.log", +// "B - Toggle sound DSP register tracing to aputrace.log", +// "C - Dump sound sample addresses", +// "ad [Address] - Dump APU RAM from PC or [Address]", + "", + "[Address] - $Bank:Address or $Address", + " [for example: $01:8123]", + "[Number] - #Number", + " [for example: #1]", + "z - ", + "f - ", + "dump - ", + "", + NULL +}; + +static const char *S9xMnemonics[256] = +{ + "BRK", "ORA", "COP", "ORA", "TSB", "ORA", "ASL", "ORA", + "PHP", "ORA", "ASL", "PHD", "TSB", "ORA", "ASL", "ORA", + "BPL", "ORA", "ORA", "ORA", "TRB", "ORA", "ASL", "ORA", + "CLC", "ORA", "INC", "TCS", "TRB", "ORA", "ASL", "ORA", + "JSR", "AND", "JSL", "AND", "BIT", "AND", "ROL", "AND", + "PLP", "AND", "ROL", "PLD", "BIT", "AND", "ROL", "AND", + "BMI", "AND", "AND", "AND", "BIT", "AND", "ROL", "AND", + "SEC", "AND", "DEC", "TSC", "BIT", "AND", "ROL", "AND", + "RTI", "EOR", "WDM", "EOR", "MVP", "EOR", "LSR", "EOR", + "PHA", "EOR", "LSR", "PHK", "JMP", "EOR", "LSR", "EOR", + "BVC", "EOR", "EOR", "EOR", "MVN", "EOR", "LSR", "EOR", + "CLI", "EOR", "PHY", "TCD", "JMP", "EOR", "LSR", "EOR", + "RTS", "ADC", "PER", "ADC", "STZ", "ADC", "ROR", "ADC", + "PLA", "ADC", "ROR", "RTL", "JMP", "ADC", "ROR", "ADC", + "BVS", "ADC", "ADC", "ADC", "STZ", "ADC", "ROR", "ADC", + "SEI", "ADC", "PLY", "TDC", "JMP", "ADC", "ROR", "ADC", + "BRA", "STA", "BRL", "STA", "STY", "STA", "STX", "STA", + "DEY", "BIT", "TXA", "PHB", "STY", "STA", "STX", "STA", + "BCC", "STA", "STA", "STA", "STY", "STA", "STX", "STA", + "TYA", "STA", "TXS", "TXY", "STZ", "STA", "STZ", "STA", + "LDY", "LDA", "LDX", "LDA", "LDY", "LDA", "LDX", "LDA", + "TAY", "LDA", "TAX", "PLB", "LDY", "LDA", "LDX", "LDA", + "BCS", "LDA", "LDA", "LDA", "LDY", "LDA", "LDX", "LDA", + "CLV", "LDA", "TSX", "TYX", "LDY", "LDA", "LDX", "LDA", + "CPY", "CMP", "REP", "CMP", "CPY", "CMP", "DEC", "CMP", + "INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "CMP", + "BNE", "CMP", "CMP", "CMP", "PEI", "CMP", "DEC", "CMP", + "CLD", "CMP", "PHX", "STP", "JML", "CMP", "DEC", "CMP", + "CPX", "SBC", "SEP", "SBC", "CPX", "SBC", "INC", "SBC", + "INX", "SBC", "NOP", "XBA", "CPX", "SBC", "INC", "SBC", + "BEQ", "SBC", "SBC", "SBC", "PEA", "SBC", "INC", "SBC", + "SED", "SBC", "PLX", "XCE", "JSR", "SBC", "INC", "SBC" +}; + +static int AddrModes[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 3, 10, 3, 19, 6, 6, 6, 12, 0, 1, 24, 0, 14, 14, 14, 17, // 0 + 4, 11, 9, 20, 6, 7, 7, 13, 0, 16, 24, 0, 14, 15, 15, 18, // 1 + 14, 10, 17, 19, 6, 6, 6, 12, 0, 1, 24, 0, 14, 14, 14, 17, // 2 + 4, 11, 9, 20, 7, 7, 7, 13, 0, 16, 24, 0, 15, 15, 15, 18, // 3 + 0, 10, 3, 19, 25, 6, 6, 12, 0, 1, 24, 0, 14, 14, 14, 17, // 4 + 4, 11, 9, 20, 25, 7, 7, 13, 0, 16, 0, 0, 17, 15, 15, 18, // 5 + 0, 10, 5, 19, 6, 6, 6, 12, 0, 1, 24, 0, 21, 14, 14, 17, // 6 + 4, 11, 9, 20, 7, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18, // 7 + 4, 10, 5, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // 8 + 4, 11, 9, 20, 7, 7, 8, 13, 0, 16, 0, 0, 14, 15, 15, 18, // 9 + 2, 10, 2, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // A + 4, 11, 9, 20, 7, 7, 8, 13, 0, 16, 0, 0, 15, 15, 16, 18, // B + 2, 10, 3, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // C + 4, 11, 9, 9, 27, 7, 7, 13, 0, 16, 0, 0, 22, 15, 15, 18, // D + 2, 10, 3, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // E + 4, 11, 9, 20, 26, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18 // F +}; + +static uint8 debug_cpu_op_print (char *, uint8, uint16); +static uint8 debug_sa1_op_print (char *, uint8, uint16); +static void debug_line_print (const char *); +static int debug_get_number (char *, uint16 *); +static short debug_get_start_address (char *, uint8 *, uint32 *); +static void debug_process_command (char *); +static void debug_print_window (uint8 *); +static const char * debug_clip_fn (int); +static void debug_whats_used (void); +static void debug_whats_missing (void); + + +static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) +{ + uint8 S9xOpcode; + uint8 Operant[3]; + uint16 Word; + uint8 Byte; + int16 SWord; + int8 SByte; + uint8 Size = 0; + + int32 Cycles = CPU.Cycles; + uint32 WaitAddress = CPU.WaitAddress; + + S9xOpcode = S9xGetByte((Bank << 16) + Address); + sprintf(Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode); + + Operant[0] = S9xGetByte((Bank << 16) + Address + 1); + Operant[1] = S9xGetByte((Bank << 16) + Address + 2); + Operant[2] = S9xGetByte((Bank << 16) + Address + 3); + + switch (AddrModes[S9xOpcode]) + { + case 0: + // Implied + sprintf(Line, "%s %s", + Line, + S9xMnemonics[S9xOpcode]); + Size = 1; + break; + + case 1: + // Immediate[MemoryFlag] + if (!CheckFlag(MemoryFlag)) + { + // Accumulator 16 - Bit + sprintf(Line, "%s%02X %02X %s #$%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + } + else + { + // Accumulator 8 - Bit + sprintf(Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + } + + break; + + case 2: + // Immediate[IndexFlag] + if (!CheckFlag(IndexFlag)) + { + // X / Y 16 - Bit + sprintf(Line, "%s%02X %02X %s #$%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + } + else + { + // X / Y 8 - Bit + sprintf(Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + } + + break; + + case 3: + // Immediate[Always 8 - Bit] + sprintf(Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + break; + + case 4: + // Relative + sprintf(Line, "%s%02X %s $%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + SByte = Operant[0]; + Word = Address; + Word += SByte; + Word += 2; + sprintf(Line, "%-32s[$%04X]", Line, Word); + Size = 2; + break; + + case 5: + // Relative Long + sprintf(Line, "%s%02X %02X %s $%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + SWord = (Operant[1] << 8) | Operant[0]; + Word = Address; + Word += SWord; + Word += 3; + sprintf(Line, "%-32s[$%04X]", Line, Word); + Size = 3; + break; + + case 6: + // Direct + sprintf(Line, "%s%02X %s $%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + sprintf(Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + + case 7: + // Direct Indexed (with X) + sprintf(Line, "%s%02X %s $%02X,x", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word += Registers.X.W; + sprintf(Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + + case 8: + // Direct Indexed (with Y) + sprintf(Line, "%s%02X %s $%02X,y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word += Registers.Y.W; + sprintf(Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + + case 9: + // Direct Indirect + sprintf(Line, "%s%02X %s ($%02X)", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word = S9xGetWord(Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 2; + break; + + case 10: + // Direct Indexed Indirect + sprintf(Line, "%s%02X %s ($%02X,x)", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word += Registers.X.W; + Word = S9xGetWord(Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 2; + break; + + case 11: + // Direct Indirect Indexed + sprintf(Line, "%s%02X %s ($%02X),y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word = S9xGetWord(Word); + Word += Registers.Y.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 2; + break; + + case 12: + // Direct Indirect Long + sprintf(Line, "%s%02X %s [$%02X]", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Byte = S9xGetByte(Word + 2); + Word = S9xGetWord(Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 2; + break; + + case 13: + // Direct Indirect Indexed Long + sprintf(Line, "%s%02X %s [$%02X],y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Byte = S9xGetByte(Word + 2); + Word = S9xGetWord(Word); + Word += Registers.Y.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 2; + break; + + case 14: + // Absolute + sprintf(Line, "%s%02X %02X %s $%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 3; + break; + + case 15: + // Absolute Indexed (with X) + sprintf(Line, "%s%02X %02X %s $%02X%02X,x", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += Registers.X.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 3; + break; + + case 16: + // Absolute Indexed (with Y) + sprintf(Line, "%s%02X %02X %s $%02X%02X,y", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += Registers.Y.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 3; + break; + + case 17: + // Absolute Long + sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X", + Line, + Operant[0], + Operant[1], + Operant[2], + S9xMnemonics[S9xOpcode], + Operant[2], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word); + Size = 4; + break; + + case 18: + // Absolute Indexed Long + sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X,x", + Line, + Operant[0], + Operant[1], + Operant[2], + S9xMnemonics[S9xOpcode], + Operant[2], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += Registers.X.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word); + Size = 4; + break; + + case 19: + // Stack Relative + sprintf(Line, "%s%02X %s $%02X,s", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Registers.S.W; + Word += Operant[0]; + sprintf(Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + + case 20: + // Stack Relative Indirect Indexed + sprintf(Line, "%s%02X %s ($%02X,s),y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Registers.S.W; + Word += Operant[0]; + Word = S9xGetWord(Word); + Word += Registers.Y.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); + Size = 2; + break; + + case 21: + // Absolute Indirect + sprintf(Line, "%s%02X %02X %s ($%02X%02X)", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word = S9xGetWord(Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word); + Size = 3; + break; + + case 22: + // Absolute Indirect Long + sprintf(Line, "%s%02X %02X %s [$%02X%02X]", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Byte = S9xGetByte(Word + 2); + Word = S9xGetWord(Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 3; + break; + + case 23: + // Absolute Indexed Indirect + sprintf(Line, "%s%02X %02X %s ($%02X%02X,x)", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += Registers.X.W; + Word = S9xGetWord(ICPU.ShiftedPB + Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word); + Size = 3; + break; + + case 24: + // Implied Accumulator + sprintf(Line, "%s %s A", + Line, + S9xMnemonics[S9xOpcode]); + Size = 1; + break; + + case 25: + // MVN/MVP SRC DST + sprintf(Line, "%s%02X %02X %s %02X %02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + break; + + case 26: + // PEA + sprintf(Line, "%s%02X %02X %s $%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + break; + + case 27: + // PEI Direct Indirect + sprintf(Line, "%s%02X %s ($%02X)", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += Registers.D.W; + Word = S9xGetWord(Word); + sprintf(Line, "%-32s[$%04X]", Line, Word); + Size = 2; + break; + } + + sprintf(Line, "%-44s A:%04X X:%04X Y:%04X D:%04X DB:%02X S:%04X P:%c%c%c%c%c%c%c%c%c HC:%04ld VC:%03ld FC:%02d %02x", + Line, Registers.A.W, Registers.X.W, Registers.Y.W, + Registers.D.W, Registers.DB, Registers.S.W, + CheckEmulation() ? 'E' : 'e', + CheckNegative() ? 'N' : 'n', + CheckOverflow() ? 'V' : 'v', + CheckMemory() ? 'M' : 'm', + CheckIndex() ? 'X' : 'x', + CheckDecimal() ? 'D' : 'd', + CheckIRQ() ? 'I' : 'i', + CheckZero() ? 'Z' : 'z', + CheckCarry() ? 'C' : 'c', + (long) Cycles, + (long) CPU.V_Counter, + IPPU.FrameCount, + CPU.IRQActive); + + CPU.Cycles = Cycles; + CPU.WaitAddress = WaitAddress; + + return (Size); +} + +static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) +{ + uint8 S9xOpcode; + uint8 Operant[3]; + uint16 Word; + uint8 Byte; + int16 SWord; + int8 SByte; + uint8 Size = 0; + + S9xOpcode = S9xSA1GetByte((Bank << 16) + Address); + sprintf(Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode); + + Operant[0] = S9xSA1GetByte((Bank << 16) + Address + 1); + Operant[1] = S9xSA1GetByte((Bank << 16) + Address + 2); + Operant[2] = S9xSA1GetByte((Bank << 16) + Address + 3); + + switch (AddrModes[S9xOpcode]) + { + case 0: + // Implied + sprintf(Line, "%s %s", + Line, + S9xMnemonics[S9xOpcode]); + Size = 1; + break; + + case 1: + // Immediate[MemoryFlag] + if (!SA1CheckFlag(MemoryFlag)) + { + // Accumulator 16 - Bit + sprintf(Line, "%s%02X %02X %s #$%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + } + else + { + // Accumulator 8 - Bit + sprintf(Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + } + + break; + + case 2: + // Immediate[IndexFlag] + if (!SA1CheckFlag(IndexFlag)) + { + // X / Y 16 - Bit + sprintf(Line, "%s%02X %02X %s #$%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Size = 3; + } + else + { + // X / Y 8 - Bit + sprintf(Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + } + + break; + + case 3: + // Immediate[Always 8 - Bit] + sprintf(Line, "%s%02X %s #$%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Size = 2; + break; + + case 4: + // Relative + sprintf(Line, "%s%02X %s $%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + SByte = Operant[0]; + Word = Address; + Word += SByte; + Word += 2; + sprintf(Line, "%-32s[$%04X]", Line, Word); + Size = 2; + break; + + case 5: + // Relative Long + sprintf(Line, "%s%02X %02X %s $%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + SWord = (Operant[1] << 8) | Operant[0]; + Word = Address; + Word += SWord; + Word += 3; + sprintf(Line, "%-32s[$%04X]", Line, Word); + Size = 3; + break; + + case 6: + // Direct + sprintf(Line, "%s%02X %s $%02X", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + sprintf(Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + + case 7: + // Direct Indexed (with X) + sprintf(Line, "%s%02X %s $%02X,x", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Word += SA1Registers.X.W; + sprintf(Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + + case 8: + // Direct Indexed (with Y) + sprintf(Line, "%s%02X %s $%02X,y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Word += SA1Registers.Y.W; + sprintf(Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + + case 9: + // Direct Indirect + sprintf(Line, "%s%02X %s ($%02X)", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Word = S9xSA1GetWord(Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 2; + break; + + case 10: + // Direct Indexed Indirect + sprintf(Line, "%s%02X %s ($%02X,x)", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Word += SA1Registers.X.W; + Word = S9xSA1GetWord(Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 2; + break; + + case 11: + // Direct Indirect Indexed + sprintf(Line, "%s%02X %s ($%02X),y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Word = S9xSA1GetWord(Word); + Word += SA1Registers.Y.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 2; + break; + + case 12: + // Direct Indirect Long + sprintf(Line, "%s%02X %s [$%02X]", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Byte = S9xSA1GetByte(Word + 2); + Word = S9xSA1GetWord(Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 2; + break; + + case 13: + // Direct Indirect Indexed Long + sprintf(Line, "%s%02X %s [$%02X],y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = Operant[0]; + Word += SA1Registers.D.W; + Byte = S9xSA1GetByte(Word + 2); + Word = S9xSA1GetWord(Word); + Word += SA1Registers.Y.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 2; + break; + + case 14: + // Absolute + sprintf(Line, "%s%02X %02X %s $%02X%02X", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 3; + break; + + case 15: + // Absolute Indexed (with X) + sprintf(Line, "%s%02X %02X %s $%02X%02X,x", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += SA1Registers.X.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 3; + break; + + case 16: + // Absolute Indexed (with Y) + sprintf(Line, "%s%02X %02X %s $%02X%02X,y", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += SA1Registers.Y.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 3; + break; + + case 17: + // Absolute Long + sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X", + Line, + Operant[0], + Operant[1], + Operant[2], + S9xMnemonics[S9xOpcode], + Operant[2], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word); + Size = 4; + break; + + case 18: + // Absolute Indexed Long + sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X,x", + Line, + Operant[0], + Operant[1], + Operant[2], + S9xMnemonics[S9xOpcode], + Operant[2], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += SA1Registers.X.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word); + Size = 4; + break; + + case 19: + // Stack Relative + sprintf(Line, "%s%02X %s $%02X,s", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = SA1Registers.S.W; + Word += Operant[0]; + sprintf(Line, "%-32s[$00:%04X]", Line, Word); + Size = 2; + break; + + case 20: + // Stack Relative Indirect Indexed + sprintf(Line, "%s%02X %s ($%02X,s),y", + Line, + Operant[0], + S9xMnemonics[S9xOpcode], + Operant[0]); + Word = SA1Registers.S.W; + Word += Operant[0]; + Word = S9xSA1GetWord(Word); + Word += SA1Registers.Y.W; + sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 2; + break; + + case 21: + // Absolute Indirect + sprintf(Line, "%s%02X %02X %s ($%02X%02X)", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word = S9xSA1GetWord(Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word); + Size = 3; + break; + + case 22: + // Absolute Indirect Long + sprintf(Line, "%s%02X %02X %s [$%02X%02X]", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Byte = S9xSA1GetByte(Word + 2); + Word = S9xSA1GetWord(Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 3; + break; + + case 23: + // Absolute Indexed Indirect + sprintf(Line, "%s%02X %02X %s ($%02X%02X,x)", + Line, + Operant[0], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word += SA1Registers.X.W; + Word = S9xSA1GetWord(SA1.ShiftedPB + Word); + sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word); + Size = 3; + break; + + case 24: + // Implied Accumulator + sprintf(Line, "%s %s A", + Line, + S9xMnemonics[S9xOpcode]); + Size = 1; + break; + + case 25: + // MVN/MVP SRC DST + sprintf(Line, "%s %s %02X %02X", + Line, + S9xMnemonics[S9xOpcode], + Operant[0], + Operant[1]); + Size = 3; + break; + } + + sprintf(Line, "%-44s A:%04X X:%04X Y:%04X D:%04X DB:%02X S:%04X P:%c%c%c%c%c%c%c%c%c HC:%04ld VC:%03ld FC:%02d", + Line, SA1Registers.A.W, SA1Registers.X.W, SA1Registers.Y.W, + SA1Registers.D.W, SA1Registers.DB, SA1Registers.S.W, + SA1CheckEmulation() ? 'E' : 'e', + SA1CheckNegative() ? 'N' : 'n', + SA1CheckOverflow() ? 'V' : 'v', + SA1CheckMemory() ? 'M' : 'm', + SA1CheckIndex() ? 'X' : 'x', + SA1CheckDecimal() ? 'D' : 'd', + SA1CheckIRQ() ? 'I' : 'i', + SA1CheckZero() ? 'Z' : 'z', + SA1CheckCarry() ? 'C' : 'c', + (long) CPU.Cycles, + (long) CPU.V_Counter, + IPPU.FrameCount); + + return (Size); +} + +static void debug_line_print (const char *Line) +{ + printf("%s\n", Line); +} + +static int debug_get_number (char *Line, uint16 *Number) +{ + int i; + + if (sscanf(Line, " #%d", &i) == 1) + { + *Number = i; + return (1); + } + + return (-1); +} + +static short debug_get_start_address (char *Line, uint8 *Bank, uint32 *Address) +{ + uint32 a, b; + + if (sscanf(Line + 1, " $%x:%x", &b, &a) != 2) + return (-1); + + *Bank = b; + *Address = a; + + return (1); +} + +static void debug_process_command (char *Line) +{ + uint8 Bank = Registers.PB; + uint32 Address = Registers.PCw; + uint16 Hold = 0; + uint16 Number; + short ErrorCode; + char string[512]; + + if (strncasecmp(Line, "dump", 4) == 0) + { + int Count; + + if (sscanf(&Line[4], "%x %d", &Address, &Count) == 2) + { + FILE *fs; + + sprintf(string, "%06x%05d.sd2", Address, Count); + fs = fopen(string, "wb"); + if (fs) + { + for (int i = 0; i < Count; i++) + putc(S9xGetByte(Address + i), fs); + fclose(fs); + } + else + printf("Can't open %s for writing\n", string); + } + else + printf("Usage: dump start_address_in_hex count_in_decimal\n"); + + return; + } + + if (*Line == 'i') + { + printf("Vectors:\n"); + sprintf(string, " 8 Bit 16 Bit "); + debug_line_print(string); + sprintf(string, "ABT $00:%04X|$00:%04X", S9xGetWord(0xFFF8), S9xGetWord(0xFFE8)); + debug_line_print(string); + sprintf(string, "BRK $00:%04X|$00:%04X", S9xGetWord(0xFFFE), S9xGetWord(0xFFE6)); + debug_line_print(string); + sprintf(string, "COP $00:%04X|$00:%04X", S9xGetWord(0xFFF4), S9xGetWord(0xFFE4)); + debug_line_print(string); + sprintf(string, "IRQ $00:%04X|$00:%04X", S9xGetWord(0xFFFE), S9xGetWord(0xFFEE)); + debug_line_print(string); + sprintf(string, "NMI $00:%04X|$00:%04X", S9xGetWord(0xFFFA), S9xGetWord(0xFFEA)); + debug_line_print(string); + sprintf(string, "RES $00:%04X", S9xGetWord(0xFFFC)); + debug_line_print(string); + } + +/* + if (strncmp(Line, "ai", 2) == 0) + { + printf("APU vectors:"); + + for (int i = 0; i < 0x40; i += 2) + { + if (i % 16 == 0) + printf("\n%04x ", 0xffc0 + i); + + printf("%04x ", APU.ExtraRAM[i]); + } + + printf("\n"); + } +*/ + + if (*Line == 's') + { + Registers.PCw += debug_cpu_op_print(string, Bank, Address); + Bank = Registers.PB; + Address = Registers.PCw; + *Line = 'r'; + } + + if (*Line == 'z') + { + uint16 *p = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; + + for (int l = 0; l < 32; l++) + { + for (int c = 0; c < 32; c++, p++) + printf("%04x,", *p++); + + printf("\n"); + } + } + + if (*Line == 'c') + { + printf("Colours:\n"); + + for (int i = 0; i < 256; i++) + printf("%02x%02x%02x ", PPU.CGDATA[i] & 0x1f, (PPU.CGDATA[i] >> 5) & 0x1f, (PPU.CGDATA[i] >> 10) & 0x1f); + + printf("\n"); + } + + if (*Line == 'S') + { + int SmallWidth, LargeWidth, SmallHeight, LargeHeight; + + switch ((Memory.FillRAM[0x2101] >> 5) & 7) + { + + case 0: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 16; + break; + + case 1: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 32; + break; + + case 2: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 64; + break; + + case 3: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 32; + break; + + case 4: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 64; + break; + + default: + case 5: + SmallWidth = SmallHeight = 32; + LargeWidth = LargeHeight = 64; + break; + + case 6: + SmallWidth = 16; + SmallHeight = 32; + LargeWidth = 32; + LargeHeight = 64; + break; + + case 7: + SmallWidth = 16; + SmallHeight = 32; + LargeWidth = LargeHeight = 32; + break; + } + + printf("Sprites: Small: %dx%d, Large: %dx%d, OAMAddr: 0x%04x, OBJNameBase: 0x%04x, OBJNameSelect: 0x%04x, First: %d\n", + SmallWidth, SmallHeight, LargeWidth, LargeHeight, PPU.OAMAddr, PPU.OBJNameBase, PPU.OBJNameSelect, PPU.FirstSprite); + + for (int i = 0; i < 128; i++) + { + printf("X:%3d Y:%3d %c%c%d%c ", + PPU.OBJ[i].HPos, + PPU.OBJ[i].VPos, + PPU.OBJ[i].VFlip ? 'V' : 'v', + PPU.OBJ[i].HFlip ? 'H' : 'h', + PPU.OBJ[i].Priority, + PPU.OBJ[i].Size ? 'S' : 's'); + + if (i % 4 == 3) + printf("\n"); + } + } + + if (*Line == 'T') + { + if (Line[1] == 'S') + { + SA1.Flags ^= TRACE_FLAG; + + if (SA1.Flags & TRACE_FLAG) + { + printf("SA1 CPU instruction tracing enabled.\n"); + if (trace2 == NULL) + trace2 = fopen("trace_sa1.log", "wb"); + } + else + { + printf("SA1 CPU instruction tracing disabled.\n"); + fclose(trace2); + trace2 = NULL; + } + } + else + { + CPU.Flags ^= TRACE_FLAG; + + if (CPU.Flags & TRACE_FLAG) + { + printf("CPU instruction tracing enabled.\n"); + if (trace == NULL) + trace = fopen("trace.log", "wb"); + } + else + { + printf("CPU instruction tracing disabled.\n"); + fclose(trace); + trace = NULL; + } + } + } + + if (*Line == 'E') + { + Settings.TraceHCEvent = !Settings.TraceHCEvent; + printf("HC event tracing %s.\n", Settings.TraceHCEvent ? "enabled" : "disabled"); + } + +/* + if (*Line == 'A') + { + APU.Flags ^= TRACE_FLAG; + + if (APU.Flags & TRACE_FLAG) + { + printf("APU tracing enabled.\n"); + if (apu_trace == NULL) + apu_trace = fopen("aputrace.log", "wb"); + } + else + { + printf("APU tracing disabled.\n"); + fclose(apu_trace); + apu_trace = NULL; + } + } + + if (*Line == 'B') + { + Settings.TraceSoundDSP = !Settings.TraceSoundDSP; + printf("Sound DSP register tracing %s.\n", Settings.TraceSoundDSP ? "enabled" : "disabled"); + } + + if (*Line == 'x') + S9xPrintSoundDSPState(); + + if (*Line == 'C') + { + printf("SPC700 sample addresses at 0x%04x:\n", APU.DSP[APU_DIR] << 8); + + for (int i = 0; i < 256; i++) + { + uint8 *dir = IAPU.RAM + (((APU.DSP[APU_DIR] << 8) + i * 4) & 0xffff); + int addr = *dir + (*(dir + 1) << 8); + int addr2 = *(dir + 2) + (*(dir + 3) << 8); + printf("%04X %04X;", addr, addr2); + + if (i % 8 == 7) + printf("\n"); + } + } +*/ + + if (*Line == 'R') + { + S9xReset(); + printf("SNES reset.\n"); + CPU.Flags |= DEBUG_MODE_FLAG; + } + +/* + if (strncmp(Line, "ad", 2) == 0) + { + uint32 Count = 16; + Address = 0; + + if (sscanf(Line + 2, "%x,%x", &Address, &Count) != 2) + { + if (sscanf(Line + 2, "%x", &Address) == 1) + Count = 16; + } + + printf("APU RAM dump:\n"); + + for (uint32 l = 0; l < Count; l += 16) + { + printf("%04X ", Address); + + for (int i = 0; i < 16; i++) + printf("%02X ", IAPU.RAM[Address++]); + + printf("\n"); + } + + *Line = 0; + } + + if (*Line == 'a') + { + printf("APU in-ports : %02X %02X %02X %02X\n", IAPU.RAM[0xF4], IAPU.RAM[0xF5], IAPU.RAM[0xF6], IAPU.RAM[0xF7]); + printf("APU out-ports: %02X %02X %02X %02X\n", APU.OutPorts[0], APU.OutPorts[1], APU.OutPorts[2], APU.OutPorts[3]); + printf("ROM/RAM switch: %s\n", (IAPU.RAM[0xf1] & 0x80) ? "ROM" : "RAM"); + + for (int i = 0; i < 3; i++) + if (APU.TimerEnabled[i]) + printf("Timer%d enabled, Value: 0x%03X, 4-bit: 0x%02X, Target: 0x%03X\n", + i, APU.Timer[i], IAPU.RAM[0xfd + i], APU.TimerTarget[i]); + } + + if (*Line == 'P') + { + Settings.TraceDSP = !Settings.TraceDSP; + printf("DSP tracing %s.\n", Settings.TraceDSP ? "enabled" : "disabled"); + } +*/ + + if (*Line == 'p') + { + S9xBreakpoint[5].Enabled = FALSE; + Address += debug_cpu_op_print(string, Bank, Address); + + if (strncmp(&string[18], "JMP", 3) != 0 && + strncmp(&string[18], "JML", 3) != 0 && + strncmp(&string[18], "RT" , 2) != 0 && + strncmp(&string[18], "BRA", 3)) + { + S9xBreakpoint[5].Enabled = TRUE; + S9xBreakpoint[5].Bank = Bank; + S9xBreakpoint[5].Address = Address; + } + else + { + CPU.Flags |= SINGLE_STEP_FLAG; + CPU.Flags &= ~DEBUG_MODE_FLAG; + } + } + + if (*Line == 'b') + { + if (Line[1] == 's') + { + debug_get_number(Line + 2, &Hold); + + if (Hold > 4) + Hold = 0; + + if (Hold < 5) + { + if (debug_get_start_address(Line + 5, &Bank, &Address) == -1) + S9xBreakpoint[Hold].Enabled = FALSE; + else + { + S9xBreakpoint[Hold].Enabled = TRUE; + S9xBreakpoint[Hold].Bank = Bank; + S9xBreakpoint[Hold].Address = Address; + CPU.Flags |= BREAK_FLAG; + } + } + + Line[1] = 'v'; + } + + if (Line[1] == 'v') + { + Number = 0; + + if (debug_get_number(Line + 2, &Number) == -1 && Number < 5) + { + debug_line_print("Breakpoints:"); + + for (Number = 0; Number != 5; Number++) + { + if (S9xBreakpoint[Number].Enabled) + sprintf(string, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address); + else + sprintf(string, "%i @ Disabled", Number); + + debug_line_print(string); + } + } + else + { + debug_line_print("Breakpoint:"); + + if (S9xBreakpoint[Number].Enabled) + sprintf(string, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address); + else + sprintf(string, "%i @ Disabled", Number); + + debug_line_print(string); + } + } + } + + if (*Line == '?' || strcasecmp(Line, "help") == 0) + { + for (int i = 0; HelpMessage[i] != NULL; i++) + debug_line_print(HelpMessage[i]); + } + + if (*Line == 't') + { + CPU.Flags |= SINGLE_STEP_FLAG; + CPU.Flags &= ~DEBUG_MODE_FLAG; + } + + if (*Line == 'f') + { + CPU.Flags |= FRAME_ADVANCE_FLAG; + CPU.Flags &= ~DEBUG_MODE_FLAG; + + IPPU.RenderThisFrame = TRUE; + IPPU.FrameSkip = 0; + + if (sscanf(&Line[1], "%u", &ICPU.FrameAdvanceCount) != 1) + ICPU.Frame = 0; + } + + if (*Line == 'g') + { + S9xBreakpoint[5].Enabled = FALSE; + + bool8 found = FALSE; + + for (int i = 0; i < 5; i++) + { + if (S9xBreakpoint[i].Enabled) + { + found = TRUE; + + if (S9xBreakpoint[i].Bank == Registers.PB && S9xBreakpoint[i].Address == Registers.PCw) + { + S9xBreakpoint[i].Enabled = 2; + break; + } + } + } + + if (!found) + CPU.Flags &= ~BREAK_FLAG; + + ErrorCode = debug_get_start_address(Line, &Bank, &Address); + + if (ErrorCode == 1) + { + S9xBreakpoint[5].Enabled = TRUE; + S9xBreakpoint[5].Bank = Bank; + S9xBreakpoint[5].Address = Address; + CPU.Flags |= BREAK_FLAG; + } + + CPU.Flags &= ~DEBUG_MODE_FLAG; + } + + if (*Line == 'D') + { + Settings.TraceDMA = !Settings.TraceDMA; + printf("DMA tracing %s.\n", Settings.TraceDMA ? "enabled" : "disabled"); + } + + if (*Line == 'V') + { + Settings.TraceVRAM = !Settings.TraceVRAM; + printf("Non-DMA VRAM write tracing %s.\n", Settings.TraceVRAM ? "enabled" : "disabled"); + } + + if (*Line == 'H') + { + Settings.TraceHDMA = !Settings.TraceHDMA; + printf("HDMA tracing %s.\n", Settings.TraceHDMA ? "enabled" : "disabled"); + } + + if (*Line == 'U') + { + Settings.TraceUnknownRegisters = !Settings.TraceUnknownRegisters; + printf("Unknown registers read/write tracing %s.\n", Settings.TraceUnknownRegisters ? "enabled" : "disabled"); + } + + if (*Line == 'd') + { + int CLine; + int CByte; + uint8 MemoryByte; + int32 Cycles = CPU.Cycles; + + if (Debug.Dump.Bank != 0 || Debug.Dump.Address != 0) + { + Bank = Debug.Dump.Bank; + Address = Debug.Dump.Address; + } + + ErrorCode = debug_get_start_address(Line, &Bank, &Address); + + for (CLine = 0; CLine != 10; CLine++) + { + sprintf(string, "$%02X:%04X", Bank, Address); + + for (CByte = 0; CByte != 16; CByte++) + { + if (Address + CByte == 0x2140 || + Address + CByte == 0x2141 || + Address + CByte == 0x2142 || + Address + CByte == 0x2143 || + Address + CByte == 0x4210) + MemoryByte = 0; + else + MemoryByte = S9xGetByte((Bank << 16) + Address + CByte); + + sprintf(string, "%s %02X", string, MemoryByte); + } + + sprintf(string, "%s-", string); + + for (CByte = 0; CByte != 16; CByte++) + { + if (Address + CByte == 0x2140 || + Address + CByte == 0x2141 || + Address + CByte == 0x2142 || + Address + CByte == 0x2143 || + Address + CByte == 0x4210) + MemoryByte = 0; + else + MemoryByte = S9xGetByte((Bank << 16) + Address + CByte); + + if (MemoryByte < 32 || MemoryByte >= 127) + MemoryByte = '?'; + + sprintf(string, "%s%c", string, MemoryByte); + } + + Address += 16; + + debug_line_print(string); + } + + Debug.Dump.Bank = Bank; + Debug.Dump.Address = Address; + + CPU.Cycles = Cycles; + } + + if (*Line == 'q') + S9xExit(); + + if (*Line == 'W') + debug_whats_missing(); + + if (*Line == 'w') + debug_whats_used(); + + if (*Line == 'r') + { + debug_cpu_op_print(string, Bank, Address); + debug_line_print(string); + } + + if (*Line == 'u') + { + if (Debug.Unassemble.Bank != 0 || Debug.Unassemble.Address != 0) + { + Bank = Debug.Unassemble.Bank; + Address = Debug.Unassemble.Address; + } + + ErrorCode = debug_get_start_address(Line, &Bank, &Address); + + for (int i = 0; i != 10; i++) + { + Address += debug_cpu_op_print(string, Bank, Address); + debug_line_print(string); + } + + Debug.Unassemble.Bank = Bank; + Debug.Unassemble.Address = Address; + } + + debug_line_print(""); + + return; +} + +static void debug_print_window (uint8 *window) +{ + for (int i = 0; i < 6; i++) + { + if (window[i]) + { + switch (i) + { + case 0: + printf("Background 0, "); + break; + + case 1: + printf("Background 1, "); + break; + + case 2: + printf("Background 2, "); + break; + + case 3: + printf("Background 3, "); + break; + + case 4: + printf("Objects, "); + break; + + case 5: + printf("Color window, "); + break; + } + } + } +} + +static const char * debug_clip_fn (int logic) +{ + switch (logic) + { + case CLIP_OR: + return ("OR"); + + case CLIP_AND: + return ("AND"); + + case CLIP_XOR: + return ("XOR"); + + case CLIP_XNOR: + return ("XNOR"); + + default: + return ("???"); + } +} + +static void debug_whats_used (void) +{ + printf("V-line: %ld, H-Pos: %ld, \n", (long) CPU.V_Counter, (long) CPU.Cycles); + + printf("Screen mode: %d, ", PPU.BGMode); + + if (PPU.BGMode <= 1 && (Memory.FillRAM[0x2105] & 8)) + printf("(BG#2 Priority), "); + + printf("Brightness: %d, ", PPU.Brightness); + + if (Memory.FillRAM[0x2100] & 0x80) + printf("(screen blanked), "); + + printf("\n"); + + if (Memory.FillRAM[0x2133] & 1) + printf("Interlace, "); + + if (Memory.FillRAM[0x2133] & 4) + printf("240 line visible, "); + + if (Memory.FillRAM[0x2133] & 8) + printf("Pseudo 512 pixels horizontal resolution, "); + + if (Memory.FillRAM[0x2133] & 0x40) + printf("Mode 7 priority per pixel, "); + + printf("\n"); + + if (PPU.BGMode == 7 && (Memory.FillRAM[0x211a] & 3)) + printf("Mode 7 flipping, "); + + if (PPU.BGMode == 7) + printf("Mode 7 screen repeat: %d, ", (Memory.FillRAM[0x211a] & 0xc0) >> 6); + + if (Memory.FillRAM[0x2130] & 1) + printf("32K colour mode, "); + + printf("\n"); + + if (PPU.BGMode == 7) + { + // Sign extend 13 bit values to 16 bit values... + if (PPU.CentreX & (1 << 12)) + PPU.CentreX |= 0xe000; + + if (PPU.CentreY & (1 << 12)) + PPU.CentreY |= 0xe000; + + printf("Matrix A: %.3f, B: %.3f, C: %.3f, D: %.3f, Centre X: %d Y:%d, \n", + (double) PPU.MatrixA / 256, (double) PPU.MatrixB / 256, + (double) PPU.MatrixC / 256, (double) PPU.MatrixD / 256, + PPU.CentreX, PPU.CentreY); + } + + if ((Memory.FillRAM[0x2106] & 0xf0) && (Memory.FillRAM[0x2106] & 0x0f)) + { + printf("Mosaic effect(%d) on, ", PPU.Mosaic); + + for (int i = 0; i < 4; i++) + if (Memory.FillRAM[0x2106] & (1 << i)) + printf("BG%d, ", i); + } + + printf("\n"); + + if (PPU.HVBeamCounterLatched) + printf("V and H beam pos latched, \n"); + + if (Memory.FillRAM[0x4200] & 0x20) + printf("V-IRQ enabled at %d, \n", PPU.IRQVBeamPos); + + if (Memory.FillRAM[0x4200] & 0x10) + printf("H-IRQ enabled at %d, \n", PPU.IRQHBeamPos); + + if (Memory.FillRAM[0x4200] & 0x80) + printf("V-blank NMI enabled, \n"); + + for (int i = 0; i < 8; i++) + { + if (missing.hdma_this_frame & (1 << i)) + { + printf("H-DMA %d [%d] 0x%02X%04X->0x21%02X %s %s 0x%02X%04X %s addressing, \n", + i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress, + DMA[i].AAddressDecrement ? "dec" : "inc", + DMA[i].Repeat ? "repeat" : "continue", + DMA[i].IndirectBank, DMA[i].IndirectAddress, + DMA[i].HDMAIndirectAddressing ? "indirect" : "absolute"); + } + } + + for (int i = 0; i < 8; i++) + { + if (missing.dma_this_frame & (1 << i)) + { + printf("DMA %d [%d] 0x%02X%04X->0x21%02X Num: %d %s, \n", + i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress, DMA[i].TransferBytes, + DMA[i].AAddressFixed ? "fixed" : (DMA[i].AAddressDecrement ? "dec" : "inc")); + } + } + + printf("VRAM write address: 0x%04x(%s), Full Graphic: %d, Address inc: %d, \n", + PPU.VMA.Address, + PPU.VMA.High ? "Byte" : "Word", + PPU.VMA.FullGraphicCount, PPU.VMA.Increment); + + for (int i = 0; i < 4; i++) + { + printf("BG%d: VOffset:%d, HOffset:%d, W:%d, H:%d, TS:%d, BA:0x%04x, TA:0x%04X, \n", + i, PPU.BG[i].VOffset, PPU.BG[i].HOffset, + (PPU.BG[i].SCSize & 1) * 32 + 32, + (PPU.BG[i].SCSize & 2) * 16 + 32, + PPU.BG[i].BGSize * 8 + 8, + PPU.BG[i].SCBase, + PPU.BG[i].NameBase); + } + + const char *s = ""; + + switch ((Memory.FillRAM[0x2130] & 0xc0) >> 6) + { + case 0: + s = "always on"; + break; + + case 1: + s = "inside"; + break; + + case 2: + s = "outside"; + break; + + case 3: + s = "always off"; + break; + } + + printf("Main screen (%s): ", s); + + for (int i = 0; i < 5; i++) + { + if (Memory.FillRAM[0x212c] & (1 << i)) + { + switch (i) + { + case 0: + printf("BG0, "); + break; + + case 1: + printf("BG1, "); + break; + + case 2: + printf("BG2, "); + break; + + case 3: + printf("BG3, "); + break; + + case 4: + printf("OBJ, "); + break; + } + } + } + + printf("\n"); + + switch ((Memory.FillRAM[0x2130] & 0x30) >> 4) + { + case 0: + s = "always on"; + break; + + case 1: + s = "inside"; + break; + + case 2: + s = "outside"; + break; + + case 3: + s = "always off"; + break; + } + + printf("Subscreen (%s): ", s); + + for (int i = 0; i < 5; i++) + { + if (Memory.FillRAM[0x212d] & (1 << i)) + { + switch (i) + { + case 0: + printf("BG0, "); + break; + + case 1: + printf("BG1, "); + break; + + case 2: + printf("BG2, "); + break; + + case 3: + printf("BG3, "); + break; + + case 4: + printf("OBJ, "); + break; + } + } + } + + printf("\n"); + + if ((Memory.FillRAM[0x2131] & 0x3f)) + { + if (Memory.FillRAM[0x2131] & 0x80) + { + if (Memory.FillRAM[0x2130] & 0x02) + printf("Subscreen subtract"); + else + printf("Fixed colour subtract"); + } + else + { + if (Memory.FillRAM[0x2130] & 0x02) + printf("Subscreen addition"); + else + printf("Fixed colour addition"); + } + + if (Memory.FillRAM[0x2131] & 0x40) + printf("(half): "); + else + printf(": "); + + for (int i = 0; i < 6; i++) + { + if (Memory.FillRAM[0x2131] & (1 << i)) + { + switch (i) + { + case 0: + printf("BG0, "); + break; + + case 1: + printf("BG1, "); + break; + + case 2: + printf("BG2, "); + break; + + case 3: + printf("BG3, "); + break; + + case 4: + printf("OBJ, "); + break; + + case 5: + printf("BACK, "); + break; + } + } + } + + printf("\n"); + } + + printf("Window 1 (%d, %d, %02x, %02x): ", PPU.Window1Left, PPU.Window1Right, Memory.FillRAM[0x212e], Memory.FillRAM[0x212f]); + + for (int i = 0; i < 6; i++) + { + if (PPU.ClipWindow1Enable[i]) + { + switch (i) + { + case 0: + printf("BG0(%s-%s), ", PPU.ClipWindow1Inside[0] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[0])); + break; + + case 1: + printf("BG1(%s-%s), ", PPU.ClipWindow1Inside[1] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[1])); + break; + + case 2: + printf("BG2(%s-%s), ", PPU.ClipWindow1Inside[2] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[2])); + break; + + case 3: + printf("BG3(%s-%s), ", PPU.ClipWindow1Inside[3] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[3])); + break; + + case 4: + printf("OBJ(%s-%s), ", PPU.ClipWindow1Inside[4] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[4])); + break; + + case 5: + printf("COL(%s-%s), ", PPU.ClipWindow1Inside[5] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[5])); + break; + } + } + } + + printf("\n"); + + printf("Window 2 (%d, %d): ", PPU.Window2Left, PPU.Window2Right); + + for (int i = 0; i < 6; i++) + { + if (PPU.ClipWindow2Enable[i]) + { + switch (i) + { + case 0: + printf("BG0(%s), ", PPU.ClipWindow2Inside[0] ? "I" : "O"); + break; + + case 1: + printf("BG1(%s), ", PPU.ClipWindow2Inside[1] ? "I" : "O"); + break; + + case 2: + printf("BG2(%s), ", PPU.ClipWindow2Inside[2] ? "I" : "O"); + break; + + case 3: + printf("BG3(%s), ", PPU.ClipWindow2Inside[3] ? "I" : "O"); + break; + + case 4: + printf("OBJ(%s), ", PPU.ClipWindow2Inside[4] ? "I" : "O"); + break; + + case 5: + printf("COL(%s), " , PPU.ClipWindow2Inside[5] ? "I" : "O"); + break; + } + } + } + + printf("\n"); + + printf("Fixed colour: %02x%02x%02x, \n", PPU.FixedColourRed, PPU.FixedColourGreen, PPU.FixedColourBlue); +} + +static void debug_whats_missing (void) +{ + printf("Processor: "); + + if (missing.emulate6502) + printf("emulation mode, "); + + if (missing.decimal_mode) + printf("decimal mode, "); + + if (missing.mv_8bit_index) + printf("MVP/MVN with 8bit index registers and XH or YH > 0, "); + + if (missing.mv_8bit_acc) + printf("MVP/MVN with 8bit accumulator > 255, "); + + printf("\n"); + + printf("Screen modes used: "); + + for (int i = 0; i < 8; i++) + if (missing.modes[i]) + printf("%d, ", i); + + printf("\n"); + + if (missing.interlace) + printf("Interlace, "); + + if (missing.pseudo_512) + printf("Pseudo 512 pixels horizontal resolution, "); + + if (missing.lines_239) + printf("240 lines visible, "); + + if (missing.sprite_double_height) + printf("double-hight sprites, "); + + printf("\n"); + + if (missing.mode7_fx) + printf("Mode 7 rotation/scaling, "); + + if (missing.matrix_read) + printf("Mode 7 read matrix registers, "); + + if (missing.mode7_flip) + printf("Mode 7 flipping, "); + + if (missing.mode7_bgmode) + printf("Mode 7 priority per pixel, "); + + if (missing.direct) + printf("Direct 32000 colour mode, "); + + printf("\n"); + + if (missing.mosaic) + printf("Mosaic effect, "); + + if (missing.subscreen) + printf("Subscreen enabled, "); + + if (missing.subscreen_add) + printf("Subscreen colour add, "); + + if (missing.subscreen_sub) + printf("Subscreen colour subtract, "); + + if (missing.fixed_colour_add) + printf("Fixed colour add, "); + + if (missing.fixed_colour_sub) + printf("Fixed colour subtract, "); + + printf("\n"); + + printf("Window 1 enabled on: "); + debug_print_window(missing.window1); + + printf("\n"); + + printf("Window 2 enabled on: "); + debug_print_window(missing.window2); + + printf("\n"); + + if (missing.bg_offset_read) + printf("BG offset read, "); + + if (missing.oam_address_read) + printf("OAM address read, "); + + if (missing.sprite_priority_rotation) + printf("Sprite priority rotation, "); + + if (missing.fast_rom) + printf("Fast 3.58MHz ROM access enabled, "); + + if (missing.matrix_multiply) + printf("Matrix multiply 16bit by 8bit used, "); + + printf("\n"); + + if (missing.virq) + printf("V-IRQ used at line %d, ", missing.virq_pos); + + if (missing.hirq) + printf("H-IRQ used at position %d, ", missing.hirq_pos); + + printf("\n"); + + if (missing.h_v_latch) + printf("H and V-Pos latched, "); + + if (missing.h_counter_read) + printf("H-Pos read, "); + + if (missing.v_counter_read) + printf("V-Pos read, "); + + printf("\n"); + + if (missing.oam_read) + printf("OAM read, "); + + if (missing.vram_read) + printf("VRAM read, "); + + if (missing.cgram_read) + printf("CG-RAM read, "); + + if (missing.wram_read) + printf("WRAM read, "); + + if (missing.dma_read) + printf("DMA read, "); + + if (missing.vram_inc) + printf("VRAM inc: %d, ", missing.vram_inc); + + if (missing.vram_full_graphic_inc) + printf("VRAM full graphic inc: %d, ", missing.vram_full_graphic_inc); + + printf("\n"); + + for (int i = 0; i < 8; i++) + { + if (missing.hdma[i].used) + { + printf("HDMA %d 0x%02X%04X->0x21%02X %s, ", + i, missing.hdma[i].abus_bank, missing.hdma[i].abus_address, missing.hdma[i].bbus_address, + missing.hdma[i].indirect_address ? "indirect" : "absolute"); + + if (missing.hdma[i].force_table_address_write) + printf("Forced address write, "); + + if (missing.hdma[i].force_table_address_read) + printf("Current address read, "); + + if (missing.hdma[i].line_count_write) + printf("Line count write, "); + + if (missing.hdma[i].line_count_read) + printf("Line count read, "); + + printf("\n"); + } + } + + for (int i = 0; i < 8; i++) + { + if (missing.dma_channels & (1 << i)) + { + printf("DMA %d [%d] 0x%02X%04X->0x21%02X Num: %d %s, \n", + i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress, DMA[i].TransferBytes, + DMA[i].AAddressFixed ? "fixed" : (DMA[i].AAddressDecrement ? "dec" : "inc")); + } + } + + if (missing.unknownppu_read) + printf("Read from unknown PPU register: $%04X, \n", missing.unknownppu_read); + + if (missing.unknownppu_write) + printf("Write to unknown PPU register: $%04X, \n", missing.unknownppu_write); + + if (missing.unknowncpu_read) + printf("Read from unknown CPU register: $%04X, \n", missing.unknowncpu_read); + + if (missing.unknowncpu_write) + printf("Write to unknown CPU register: $%04X, \n", missing.unknowncpu_write); + + if (missing.unknowndsp_read) + printf("Read from unknown DSP register: $%04X, \n", missing.unknowndsp_read); + + if (missing.unknowndsp_write) + printf("Write to unknown DSP register: $%04X, \n", missing.unknowndsp_write); +} + +void S9xDoDebug (void) +{ + char Line[513]; + + Debug.Dump.Bank = 0; + Debug.Dump.Address = 0; + Debug.Unassemble.Bank = 0; + Debug.Unassemble.Address = 0; + + S9xTextMode(); + + strcpy(Line, "r"); + debug_process_command(Line); + + while (CPU.Flags & DEBUG_MODE_FLAG) + { + int32 Cycles; + char *p; + + printf("> "); + fflush(stdout); + + p = fgets(Line, sizeof(Line) - 1, stdin); + Line[strlen(Line) - 1] = 0; + + Cycles = CPU.Cycles; + debug_process_command(Line); + CPU.Cycles = Cycles; + } + + if (!(CPU.Flags & SINGLE_STEP_FLAG)) + S9xGraphicsMode(); +} + +void S9xTrace (void) +{ + char msg[512]; + + if (trace == NULL) + trace = fopen("trace.log", "a"); + + debug_cpu_op_print(msg, Registers.PB, Registers.PCw); + fprintf(trace, "%s\n", msg); +} + +void S9xSA1Trace (void) +{ + char msg[512]; + + if (trace2 == NULL) + trace2 = fopen("trace_sa1.log", "a"); + + debug_sa1_op_print(msg, SA1Registers.PB, SA1Registers.PCw); + fprintf(trace2, "%s\n", msg); +} + +void S9xTraceMessage (const char *s) +{ + if (s) + { + if (trace) + fprintf(trace, "%s\n", s); + else + if (trace2) + fprintf(trace2, "%s\n", s); + } +} + +void S9xTraceFormattedMessage (const char *s, ...) +{ + char msg[512]; + + if (s) + { + va_list argptr; + + va_start(argptr, s); + vsprintf(msg, s, argptr); + va_end(argptr); + + S9xTraceMessage(msg); + } +} + +#endif diff --git a/debug.h b/debug.h new file mode 100644 index 00000000..bffff81b --- /dev/null +++ b/debug.h @@ -0,0 +1,200 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 DEBUGGER + +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +struct SBreakPoint +{ + bool8 Enabled; + uint8 Bank; + uint16 Address; +}; + +extern struct SBreakPoint S9xBreakpoint[6]; + +void S9xDoDebug (void); +void S9xTrace (void); +void S9xSA1Trace (void); +void S9xTraceMessage (const char *); +void S9xTraceFormattedMessage (const char *, ...); + +#endif + +#endif diff --git a/display.h b/display.h new file mode 100644 index 00000000..fa784088 --- /dev/null +++ b/display.h @@ -0,0 +1,235 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _DISPLAY_H_ +#define _DISPLAY_H_ + +enum s9x_getdirtype +{ + DEFAULT_DIR = 0, + HOME_DIR, + ROMFILENAME_DIR, + ROM_DIR, + SRAM_DIR, + SNAPSHOT_DIR, + SCREENSHOT_DIR, + SPC_DIR, + CHEAT_DIR, + IPS_DIR, + BIOS_DIR, + LOG_DIR, + LAST_DIR +}; + +void S9xUsage (void); +char * S9xParseArgs (char **, int); +void S9xLoadConfigFiles (char **, int); +void S9xSetInfoString (const char *); + +// Routines the port has to implement even if it doesn't use them + +void S9xPutImage (int, int); +void S9xInitDisplay (int, char **); +void S9xDeinitDisplay (void); +void S9xTextMode (void); +void S9xGraphicsMode (void); +void S9xSetPalette (void); +void S9xToggleSoundChannel (int); +bool8 S9xOpenSnapshotFile (const char *, bool8, STREAM *); +void S9xCloseSnapshotFile (STREAM); +const char * S9xStringInput (const char *); +const char * S9xGetDirectory (enum s9x_getdirtype); +const char * S9xGetFilename (const char *, enum s9x_getdirtype); +const char * S9xGetFilenameInc (const char *, enum s9x_getdirtype); +const char * S9xChooseFilename (bool8); +const char * S9xBasename (const char *); + +// Routines the port has to implement if it uses command-line + +void S9xExtraUsage (void); +void S9xParseArg (char **, int &, int); + +// Routines the port may implement as needed + +void S9xExtraDisplayUsage (void); +void S9xParseDisplayArg (char **, int &, int); +void S9xSetTitle (const char *); +void S9xInitInputDevices (void); +void S9xProcessEvents (bool8); +const char * S9xSelectFilename (const char *, const char *, const char *, const char *); + +#endif diff --git a/dma.cpp b/dma.cpp new file mode 100644 index 00000000..ef8d7377 --- /dev/null +++ b/dma.cpp @@ -0,0 +1,1766 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "dma.h" +#include "apu/apu.h" +#include "sdd1emu.h" +#include "spc7110emu.h" +#ifdef DEBUGGER +#include "missing.h" +#endif + +extern uint8 *HDMAMemPointers[8]; +extern int HDMA_ModeByteCounts[8]; +extern SPC7110 s7emu; + +static uint8 sdd1_decode_buffer[0x10000]; + +static inline bool8 addCyclesInDMA (uint8); +static inline bool8 HDMAReadLineCount (int); + + +static inline bool8 addCyclesInDMA (uint8 dma_channel) +{ + // Add 8 cycles per byte, sync APU, and do HC related events. + // If HDMA was done in S9xDoHEventProcessing(), check if it used the same channel as DMA. + CPU.Cycles += SLOW_ONE_CYCLE; + while (CPU.Cycles >= CPU.NextEvent) + S9xDoHEventProcessing(); + + if (CPU.HDMARanInDMA & (1 << dma_channel)) + { + CPU.HDMARanInDMA = 0; + #ifdef DEBUGGER + printf("HDMA and DMA use the same channel %d!\n", dma_channel); + #endif + // If HDMA triggers in the middle of DMA transfer and it uses the same channel, + // it kills the DMA transfer immediately. $43x2 and $43x5 stop updating. + return (FALSE); + } + + CPU.HDMARanInDMA = 0; + return (TRUE); +} + +bool8 S9xDoDMA (uint8 Channel) +{ + CPU.InDMA = TRUE; + CPU.InDMAorHDMA = TRUE; + CPU.CurrentDMAorHDMAChannel = Channel; + + SDMA *d = &DMA[Channel]; + + // Check invalid DMA first + if ((d->ABank == 0x7E || d->ABank == 0x7F) && d->BAddress == 0x80 && !d->ReverseTransfer) + { + // Attempting a DMA from WRAM to $2180 will not work, WRAM will not be written. + // Attempting a DMA from $2180 to WRAM will similarly not work, + // the value written is (initially) the OpenBus value. + // In either case, the address in $2181-3 is not incremented. + + // Does an invalid DMA actually take time? + // I'd say yes, since 'invalid' is probably just the WRAM chip + // not being able to read and write itself at the same time + // And no, PPU.WRAM should not be updated. + + int32 c = d->TransferBytes; + // Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. + if (c == 0) + c = 0x10000; + + // 8 cycles per channel + CPU.Cycles += SLOW_ONE_CYCLE; + // 8 cycles per byte + while (c) + { + d->TransferBytes--; + d->AAddress++; + c--; + if (!addCyclesInDMA(Channel)) + { + CPU.InDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + CPU.CurrentDMAorHDMAChannel = -1; + return (FALSE); + } + } + + #ifdef DEBUGGER + if (Settings.TraceDMA) + { + sprintf(String, "DMA[%d]: WRAM Bank:%02X->$2180", Channel, d->ABank); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } + #endif + + CPU.InDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + CPU.CurrentDMAorHDMAChannel = -1; + return (TRUE); + } + + // Prepare for accessing $2118-2119 + switch (d->BAddress) + { + case 0x18: + case 0x19: + if (IPPU.RenderThisFrame) + FLUSH_REDRAW(); + break; + } + + int32 inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1); + int32 count = d->TransferBytes; + // Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0. + if (count == 0) + count = 0x10000; + + // Prepare for custom chip DMA + + // S-DD1 + + uint8 *in_sdd1_dma = NULL; + + if (Settings.SDD1) + { + if (d->AAddressFixed && Memory.FillRAM[0x4801] > 0) + { + // XXX: Should probably verify that we're DMAing from ROM? + // And somewhere we should make sure we're not running across a mapping boundary too. + // Hacky support for pre-decompressed S-DD1 data + inc = !d->AAddressDecrement ? 1 : -1; + + uint8 *in_ptr = S9xGetBasePointer(((d->ABank << 16) | d->AAddress)); + if (in_ptr) + { + in_ptr += d->AAddress; + SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes); + } + #ifdef DEBUGGER + else + { + sprintf(String, "S-DD1: DMA from non-block address $%02X:%04X", d->ABank, d->AAddress); + S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); + } + #endif + + in_sdd1_dma = sdd1_decode_buffer; + } + + Memory.FillRAM[0x4801] = 0; + } + + // SPC7110 + + uint8 *spc7110_dma = NULL; + + if (Settings.SPC7110) + { + if (d->AAddress == 0x4800 || d->ABank == 0x50) + { + spc7110_dma = new uint8[d->TransferBytes]; + for (int i = 0; i < d->TransferBytes; i++) + spc7110_dma[i] = s7emu.decomp.read(); + + int32 icount = s7emu.r4809 | (s7emu.r480a << 8); + icount -= d->TransferBytes; + s7emu.r4809 = icount & 0x00ff; + s7emu.r480a = (icount & 0xff00) >> 8; + + inc = 1; + d->AAddress -= count; + } + } + + // SA-1 + + bool8 in_sa1_dma = FALSE; + + if (Settings.SA1) + { + if (SA1.in_char_dma && d->BAddress == 0x18 && (d->ABank & 0xf0) == 0x40) + { + // Perform packed bitmap to PPU character format conversion on the data + // before transmitting it to V-RAM via-DMA. + int32 num_chars = 1 << ((Memory.FillRAM[0x2231] >> 2) & 7); + int32 depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; + int32 bytes_per_char = 8 * depth; + int32 bytes_per_line = depth * num_chars; + int32 char_line_bytes = bytes_per_char * num_chars; + uint32 addr = (d->AAddress / char_line_bytes) * char_line_bytes; + + uint8 *base = S9xGetBasePointer((d->ABank << 16) + addr); + if (!base) + { + sprintf(String, "SA-1: DMA from non-block address $%02X:%04X", d->ABank, addr); + S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String); + base = Memory.ROM; + } + + base += addr; + + uint8 *buffer = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000]; + uint8 *p = buffer; + uint32 inc_sa1 = char_line_bytes - (d->AAddress % char_line_bytes); + uint32 char_count = inc_sa1 / bytes_per_char; + + in_sa1_dma = TRUE; + + #if 0 + printf("SA-1 DMA: %08x,", base); + 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); + #endif + + switch (depth) + { + case 2: + for (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = 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 (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 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 (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = 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 (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 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 (int32 i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = 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 (int32 l = 0; l < 8; l++, q += bytes_per_line) + { + for (int32 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; + } + } + } + +#ifdef DEBUGGER + if (Settings.TraceDMA) + { + sprintf(String, "DMA[%d]: %s Mode:%d 0x%02X%04X->0x21%02X Bytes:%d (%s) V:%03d", + Channel, d->ReverseTransfer ? "PPU->CPU" : "CPU->PPU", d->TransferMode, d->ABank, d->AAddress, d->BAddress, + d->TransferBytes, d->AAddressFixed ? "fixed" : (d->AAddressDecrement ? "dec" : "inc"), CPU.V_Counter); + + if (d->BAddress == 0x18 || d->BAddress == 0x19 || d->BAddress == 0x39 || d->BAddress == 0x3a) + sprintf(String, "%s VRAM: %04X (%d,%d) %s", String, + PPU.VMA.Address, PPU.VMA.Increment, PPU.VMA.FullGraphicCount, PPU.VMA.High ? "word" : "byte"); + else + if (d->BAddress == 0x22 || d->BAddress == 0x3b) + sprintf(String, "%s CGRAM: %02X (%x)", String, PPU.CGADD, PPU.CGFLIP); + else + if (d->BAddress == 0x04 || d->BAddress == 0x38) + sprintf(String, "%s OBJADDR: %04X", String, PPU.OAMAddr); + + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } +#endif + + // Do Transfer + + uint8 Work; + + // 8 cycles per channel + CPU.Cycles += SLOW_ONE_CYCLE; + + if (!d->ReverseTransfer) + { + // CPU -> PPU + int32 b = 0; + uint16 p = d->AAddress; + uint8 *base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); + bool8 inWRAM_DMA; + + int32 rem = count; + // Transfer per block if d->AAdressFixed is FALSE + count = d->AAddressFixed ? rem : (d->AAddressDecrement ? ((p & MEMMAP_MASK) + 1) : (MEMMAP_BLOCK_SIZE - (p & MEMMAP_MASK))); + + // Settings for custom chip DMA + if (in_sa1_dma) + { + base = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000]; + p = 0; + count = rem; + } + else + if (in_sdd1_dma) + { + base = in_sdd1_dma; + p = 0; + count = rem; + } + else + if (spc7110_dma) + { + base = spc7110_dma; + p = 0; + count = rem; + } + + inWRAM_DMA = ((!in_sa1_dma && !in_sdd1_dma && !spc7110_dma) && + (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); + + // 8 cycles per byte + #define UPDATE_COUNTERS \ + d->TransferBytes--; \ + d->AAddress += inc; \ + p += inc; \ + if (!addCyclesInDMA(Channel)) \ + { \ + CPU.InDMA = FALSE; \ + CPU.InDMAorHDMA = FALSE; \ + CPU.InWRAMDMAorHDMA = FALSE; \ + CPU.CurrentDMAorHDMAChannel = -1; \ + return (FALSE); \ + } + + while (1) + { + if (count > rem) + count = rem; + rem -= count; + + CPU.InWRAMDMAorHDMA = inWRAM_DMA; + + if (!base) + { + // DMA SLOW PATH + if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) + { + do + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + } while (--count > 0); + } + else + if (d->TransferMode == 1 || d->TransferMode == 5) + { + // This is a variation on Duff's Device. It is legal C/C++. + switch (b) + { + default: + while (count > 1) + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + count--; + + case 1: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + count--; + } + } + + if (count == 1) + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + else + if (d->TransferMode == 3 || d->TransferMode == 7) + { + switch (b) + { + default: + do + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } + + case 1: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } + + case 2: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } + + case 3: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + else + if (d->TransferMode == 4) + { + switch (b) + { + default: + do + { + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } + + case 1: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } + + case 2: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2102 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } + + case 3: + Work = S9xGetByte((d->ABank << 16) + p); + S9xSetPPU(Work, 0x2103 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + #ifdef DEBUGGER + else + { + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } + #endif + } + else + { + // DMA FAST PATH + if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6) + { + switch (d->BAddress) + { + case 0x04: // OAMDATA + do + { + Work = *(base + p); + REGISTER_2104(Work); + UPDATE_COUNTERS; + } while (--count > 0); + + break; + + case 0x18: // VMDATAL + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { + do + { + Work = *(base + p); + REGISTER_2118_linear(Work); + UPDATE_COUNTERS; + } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2118_tile(Work); + UPDATE_COUNTERS; + } while (--count > 0); + } + + break; + + case 0x19: // VMDATAH + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { + do + { + Work = *(base + p); + REGISTER_2119_linear(Work); + UPDATE_COUNTERS; + } while (--count > 0); + } + else + { + do + { + Work = *(base + p); + REGISTER_2119_tile(Work); + UPDATE_COUNTERS; + } while (--count > 0); + } + + break; + + case 0x22: // CGDATA + do + { + Work = *(base + p); + REGISTER_2122(Work); + UPDATE_COUNTERS; + } while (--count > 0); + + break; + + case 0x80: // WMDATA + if (!CPU.InWRAMDMAorHDMA) + { + do + { + Work = *(base + p); + REGISTER_2180(Work); + UPDATE_COUNTERS; + } while (--count > 0); + } + else + { + do + { + UPDATE_COUNTERS; + } while (--count > 0); + } + + break; + + default: + do + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + } while (--count > 0); + + break; + } + } + else + if (d->TransferMode == 1 || d->TransferMode == 5) + { + if (d->BAddress == 0x18) + { + // VMDATAL + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + if (!PPU.VMA.FullGraphicCount) + { + switch (b) + { + default: + while (count > 1) + { + Work = *(base + p); + REGISTER_2118_linear(Work); + UPDATE_COUNTERS; + count--; + + case 1: + Work = *(base + p); + REGISTER_2119_linear(Work); + UPDATE_COUNTERS; + count--; + } + } + + if (count == 1) + { + Work = *(base + p); + REGISTER_2118_linear(Work); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + else + { + switch (b) + { + default: + while (count > 1) + { + Work = *(base + p); + REGISTER_2118_tile(Work); + UPDATE_COUNTERS; + count--; + + case 1: + Work = *(base + p); + REGISTER_2119_tile(Work); + UPDATE_COUNTERS; + count--; + } + } + + if (count == 1) + { + Work = *(base + p); + REGISTER_2118_tile(Work); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + } + else + { + // DMA mode 1 general case + switch (b) + { + default: + while (count > 1) + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + count--; + + case 1: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + count--; + } + } + + if (count == 1) + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + b = 1; + } + else + b = 0; + } + } + else + if (d->TransferMode == 3 || d->TransferMode == 7) + { + switch (b) + { + default: + do + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } + + case 1: + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } + + case 2: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } + + case 3: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + else + if (d->TransferMode == 4) + { + switch (b) + { + default: + do + { + Work = *(base + p); + S9xSetPPU(Work, 0x2100 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 1; + break; + } + + case 1: + Work = *(base + p); + S9xSetPPU(Work, 0x2101 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 2; + break; + } + + case 2: + Work = *(base + p); + S9xSetPPU(Work, 0x2102 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 3; + break; + } + + case 3: + Work = *(base + p); + S9xSetPPU(Work, 0x2103 + d->BAddress); + UPDATE_COUNTERS; + if (--count <= 0) + { + b = 0; + break; + } + } while (1); + } + } + #ifdef DEBUGGER + else + { + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + } + #endif + } + + if (rem <= 0) + break; + + base = S9xGetBasePointer((d->ABank << 16) + d->AAddress); + count = MEMMAP_BLOCK_SIZE; + inWRAM_DMA = ((!in_sa1_dma && !in_sdd1_dma && !spc7110_dma) && + (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000))); + } + + #undef UPDATE_COUNTERS + } + else + { + // PPU -> CPU + + // 8 cycles per byte + #define UPDATE_COUNTERS \ + d->TransferBytes--; \ + d->AAddress += inc; \ + if (!addCyclesInDMA(Channel)) \ + { \ + CPU.InDMA = FALSE; \ + CPU.InDMAorHDMA = FALSE; \ + CPU.InWRAMDMAorHDMA = FALSE; \ + CPU.CurrentDMAorHDMAChannel = -1; \ + return (FALSE); \ + } + + if (d->BAddress > 0x80 - 4 && d->BAddress <= 0x83 && !(d->ABank & 0x40)) + { + // REVERSE-DMA REALLY-SLOW PATH + do + { + switch (d->TransferMode) + { + case 0: + case 2: + case 6: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 1: + case 5: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 3: + case 7: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 4: + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2102 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000); + Work = S9xGetPPU(0x2103 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + default: + #ifdef DEBUGGER + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + #endif + while (count) + { + UPDATE_COUNTERS; + count--; + } + + break; + } + } while (count); + } + else + { + // REVERSE-DMA FASTER PATH + CPU.InWRAMDMAorHDMA = (d->ABank == 0x7e || d->ABank == 0x7f); + do + { + switch (d->TransferMode) + { + case 0: + case 2: + case 6: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 1: + case 5: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 3: + case 7: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + case 4: + Work = S9xGetPPU(0x2100 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2101 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2102 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + if (!--count) + break; + + Work = S9xGetPPU(0x2103 + d->BAddress); + S9xSetByte(Work, (d->ABank << 16) + d->AAddress); + UPDATE_COUNTERS; + count--; + + break; + + default: + #ifdef DEBUGGER + sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel); + S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String); + #endif + while (count) + { + UPDATE_COUNTERS; + count--; + } + + break; + } + } while (count); + } + } + + if ((CPU.Flags & NMI_FLAG) && (Timings.NMITriggerPos != 0xffff)) + { + Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay; + if (Timings.NMITriggerPos >= Timings.H_Max) + Timings.NMITriggerPos -= Timings.H_Max; + } + + // Release the memory used in SPC7110 DMA + if (Settings.SPC7110) + { + if (spc7110_dma) + delete [] spc7110_dma; + } + +#if 0 + // sanity check + if (d->TransferBytes != 0) + fprintf(stderr,"DMA[%d] TransferBytes not 0! $21%02x Reverse:%d %04x\n", Channel, d->BAddress, d->ReverseTransfer, d->TransferBytes); +#endif + + CPU.InDMA = FALSE; + CPU.InDMAorHDMA = FALSE; + CPU.InWRAMDMAorHDMA = FALSE; + CPU.CurrentDMAorHDMAChannel = -1; + + return (TRUE); +} + +static inline bool8 HDMAReadLineCount (int d) +{ + // CPU.InDMA is set, so S9xGetXXX() / S9xSetXXX() incur no charges. + + uint8 line; + + line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address); + CPU.Cycles += SLOW_ONE_CYCLE; + + if (!line) + { + DMA[d].Repeat = FALSE; + DMA[d].LineCount = 128; + + if (DMA[d].HDMAIndirectAddressing) + { + if (PPU.HDMA & (0xfe << d)) + { + DMA[d].Address++; + CPU.Cycles += SLOW_ONE_CYCLE * 2; + } + else + CPU.Cycles += SLOW_ONE_CYCLE; + + DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); + DMA[d].Address++; + } + + DMA[d].Address++; + HDMAMemPointers[d] = NULL; + + return (FALSE); + } + else + if (line == 0x80) + { + DMA[d].Repeat = TRUE; + DMA[d].LineCount = 128; + } + else + { + DMA[d].Repeat = !(line & 0x80); + DMA[d].LineCount = line & 0x7f; + } + + DMA[d].Address++; + DMA[d].DoTransfer = TRUE; + + if (DMA[d].HDMAIndirectAddressing) + { + CPU.Cycles += SLOW_ONE_CYCLE << 1; + DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); + DMA[d].Address += 2; + HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress); + } + else + HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].ABank << 16) + DMA[d].Address); + + return (TRUE); +} + +void S9xStartHDMA (void) +{ + if (Settings.DisableHDMA) + PPU.HDMA = 0; + else + PPU.HDMA = Memory.FillRAM[0x420c]; + +#ifdef DEBUGGER + missing.hdma_this_frame = PPU.HDMA; +#endif + + PPU.HDMAEnded = 0; + + int32 tmpch; + + CPU.InHDMA = TRUE; + CPU.InDMAorHDMA = TRUE; + tmpch = CPU.CurrentDMAorHDMAChannel; + + // XXX: Not quite right... + if (PPU.HDMA != 0) + CPU.Cycles += Timings.DMACPUSync; + + for (uint8 i = 0; i < 8; i++) + { + if (PPU.HDMA & (1 << i)) + { + CPU.CurrentDMAorHDMAChannel = i; + + DMA[i].Address = DMA[i].AAddress; + + if (!HDMAReadLineCount(i)) + { + PPU.HDMA &= ~(1 << i); + PPU.HDMAEnded |= (1 << i); + } + } + else + DMA[i].DoTransfer = FALSE; + } + + CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = CPU.InDMA; + CPU.HDMARanInDMA = CPU.InDMA ? PPU.HDMA : 0; + CPU.CurrentDMAorHDMAChannel = tmpch; +} + +uint8 S9xDoHDMA (uint8 byte) +{ + struct SDMA *p = &DMA[0]; + + uint32 ShiftedIBank; + uint16 IAddr; + bool8 temp; + int32 tmpch; + int d = 0; + + CPU.InHDMA = TRUE; + CPU.InDMAorHDMA = TRUE; + CPU.HDMARanInDMA = CPU.InDMA ? byte : 0; + temp = CPU.InWRAMDMAorHDMA; + tmpch = CPU.CurrentDMAorHDMAChannel; + + // XXX: Not quite right... + CPU.Cycles += Timings.DMACPUSync; + + for (uint8 mask = 1; mask; mask <<= 1, p++, d++) + { + if (byte & mask) + { + CPU.InWRAMDMAorHDMA = FALSE; + CPU.CurrentDMAorHDMAChannel = d; + + if (p->HDMAIndirectAddressing) + { + ShiftedIBank = (p->IndirectBank << 16); + IAddr = p->IndirectAddress; + } + else + { + ShiftedIBank = (p->ABank << 16); + IAddr = p->Address; + } + + if (!HDMAMemPointers[d]) + HDMAMemPointers[d] = S9xGetMemPointer(ShiftedIBank + IAddr); + + if (p->DoTransfer) + { + // XXX: Hack for Uniracers, because we don't understand + // OAM Address Invalidation + if (p->BAddress == 0x04) + { + if (SNESGameFixes.Uniracers) + { + PPU.OAMAddr = 0x10c; + PPU.OAMFlip = 0; + } + } + + #ifdef DEBUGGER + if (Settings.TraceHDMA && p->DoTransfer) + { + sprintf(String, "H-DMA[%d] %s (%d) 0x%06X->0x21%02X %s, Count: %3d, Rep: %s, V-LINE: %3ld %02X%04X", + p-DMA, p->ReverseTransfer? "read" : "write", + p->TransferMode, ShiftedIBank+IAddr, p->BAddress, + p->HDMAIndirectAddressing ? "ind" : "abs", + p->LineCount, + p->Repeat ? "yes" : "no ", (long) CPU.V_Counter, + p->ABank, p->Address); + S9xMessage(S9X_TRACE, S9X_HDMA_TRACE, String); + } + #endif + + if (!p->ReverseTransfer) + { + if ((IAddr & MEMMAP_MASK) + HDMA_ModeByteCounts[p->TransferMode] >= MEMMAP_BLOCK_SIZE) + { + // HDMA REALLY-SLOW PATH + HDMAMemPointers[d] = NULL; + + #define DOBYTE(Addr, RegOff) \ + CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ + (!(ShiftedIBank & 0x400000) && ((uint16) (Addr)) < 0x2000)); \ + S9xSetPPU(S9xGetByte(ShiftedIBank + ((uint16) (Addr))), 0x2100 + p->BAddress + (RegOff)); + + switch (p->TransferMode) + { + case 0: + CPU.Cycles += SLOW_ONE_CYCLE; + DOBYTE(IAddr, 0); + break; + + case 5: + CPU.Cycles += 4 * SLOW_ONE_CYCLE; + DOBYTE(IAddr + 0, 0); + DOBYTE(IAddr + 1, 1); + DOBYTE(IAddr + 2, 0); + DOBYTE(IAddr + 3, 1); + break; + + case 1: + CPU.Cycles += 2 * SLOW_ONE_CYCLE; + DOBYTE(IAddr + 0, 0); + DOBYTE(IAddr + 1, 1); + break; + + case 2: + case 6: + CPU.Cycles += 2 * SLOW_ONE_CYCLE; + DOBYTE(IAddr + 0, 0); + DOBYTE(IAddr + 1, 0); + break; + + case 3: + case 7: + CPU.Cycles += 4 * SLOW_ONE_CYCLE; + DOBYTE(IAddr + 0, 0); + DOBYTE(IAddr + 1, 0); + DOBYTE(IAddr + 2, 1); + DOBYTE(IAddr + 3, 1); + break; + + case 4: + CPU.Cycles += 4 * SLOW_ONE_CYCLE; + DOBYTE(IAddr + 0, 0); + DOBYTE(IAddr + 1, 1); + DOBYTE(IAddr + 2, 2); + DOBYTE(IAddr + 3, 3); + break; + } + + #undef DOBYTE + } + else + { + CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || + (!(ShiftedIBank & 0x400000) && IAddr < 0x2000)); + + if (!HDMAMemPointers[d]) + { + // HDMA SLOW PATH + uint32 Addr = ShiftedIBank + IAddr; + + switch (p->TransferMode) + { + case 0: + CPU.Cycles += SLOW_ONE_CYCLE; + S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); + break; + + case 5: + CPU.Cycles += 2 * SLOW_ONE_CYCLE; + S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); + Addr += 2; + /* fall through */ + case 1: + CPU.Cycles += 2 * SLOW_ONE_CYCLE; + S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); + break; + + case 2: + case 6: + CPU.Cycles += 2 * SLOW_ONE_CYCLE; + S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); + break; + + case 3: + case 7: + CPU.Cycles += 4 * SLOW_ONE_CYCLE; + S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); + S9xSetPPU(S9xGetByte(Addr + 2), 0x2101 + p->BAddress); + S9xSetPPU(S9xGetByte(Addr + 3), 0x2101 + p->BAddress); + break; + + case 4: + CPU.Cycles += 4 * SLOW_ONE_CYCLE; + S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); + S9xSetPPU(S9xGetByte(Addr + 2), 0x2102 + p->BAddress); + S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress); + break; + } + } + else + { + // HDMA FAST PATH + switch (p->TransferMode) + { + case 0: + CPU.Cycles += SLOW_ONE_CYCLE; + S9xSetPPU(*HDMAMemPointers[d]++, 0x2100 + p->BAddress); + break; + + case 5: + CPU.Cycles += 2 * SLOW_ONE_CYCLE; + S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); + HDMAMemPointers[d] += 2; + /* fall through */ + case 1: + CPU.Cycles += 2 * SLOW_ONE_CYCLE; + S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); + HDMAMemPointers[d] += 2; + break; + + case 2: + case 6: + CPU.Cycles += 2 * SLOW_ONE_CYCLE; + S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); + HDMAMemPointers[d] += 2; + break; + + case 3: + case 7: + CPU.Cycles += 4 * SLOW_ONE_CYCLE; + 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: + CPU.Cycles += 4 * SLOW_ONE_CYCLE; + 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; + } + } + } + } + else + { + // REVERSE HDMA REALLY-SLOW PATH + // anomie says: Since this is apparently never used + // (otherwise we would have noticed before now), let's not bother with faster paths. + HDMAMemPointers[d] = NULL; + + #define DOBYTE(Addr, RegOff) \ + CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \ + (!(ShiftedIBank & 0x400000) && ((uint16) (Addr)) < 0x2000)); \ + S9xSetByte(S9xGetPPU(0x2100 + p->BAddress + (RegOff)), ShiftedIBank + ((uint16) (Addr))); + + switch (p->TransferMode) + { + case 0: + CPU.Cycles += SLOW_ONE_CYCLE; + DOBYTE(IAddr, 0); + break; + + case 5: + CPU.Cycles += 4 * SLOW_ONE_CYCLE; + DOBYTE(IAddr + 0, 0); + DOBYTE(IAddr + 1, 1); + DOBYTE(IAddr + 2, 0); + DOBYTE(IAddr + 3, 1); + break; + + case 1: + CPU.Cycles += 2 * SLOW_ONE_CYCLE; + DOBYTE(IAddr + 0, 0); + DOBYTE(IAddr + 1, 1); + break; + + case 2: + case 6: + CPU.Cycles += 2 * SLOW_ONE_CYCLE; + DOBYTE(IAddr + 0, 0); + DOBYTE(IAddr + 1, 0); + break; + + case 3: + case 7: + CPU.Cycles += 4 * SLOW_ONE_CYCLE; + DOBYTE(IAddr + 0, 0); + DOBYTE(IAddr + 1, 0); + DOBYTE(IAddr + 2, 1); + DOBYTE(IAddr + 3, 1); + break; + + case 4: + CPU.Cycles += 4 * SLOW_ONE_CYCLE; + DOBYTE(IAddr + 0, 0); + DOBYTE(IAddr + 1, 1); + DOBYTE(IAddr + 2, 2); + DOBYTE(IAddr + 3, 3); + break; + } + + #undef DOBYTE + } + + if (p->HDMAIndirectAddressing) + p->IndirectAddress += HDMA_ModeByteCounts[p->TransferMode]; + else + p->Address += HDMA_ModeByteCounts[p->TransferMode]; + } + + p->DoTransfer = !p->Repeat; + + if (!--p->LineCount) + { + if (!HDMAReadLineCount(d)) + { + byte &= ~mask; + PPU.HDMAEnded |= mask; + p->DoTransfer = FALSE; + continue; + } + } + else + CPU.Cycles += SLOW_ONE_CYCLE; + } + } + + CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = CPU.InDMA; + CPU.InWRAMDMAorHDMA = temp; + CPU.CurrentDMAorHDMAChannel = tmpch; + + return (byte); +} + +void S9xResetDMA (void) +{ + for (int d = 0; d < 8; d++) + { + DMA[d].ReverseTransfer = TRUE; + DMA[d].HDMAIndirectAddressing = TRUE; + DMA[d].AAddressFixed = TRUE; + DMA[d].AAddressDecrement = TRUE; + DMA[d].TransferMode = 7; + DMA[d].BAddress = 0xff; + DMA[d].AAddress = 0xffff; + DMA[d].ABank = 0xff; + DMA[d].DMACount_Or_HDMAIndirectAddress = 0xffff; + DMA[d].IndirectBank = 0xff; + DMA[d].Address = 0xffff; + DMA[d].Repeat = FALSE; + DMA[d].LineCount = 0x7f; + DMA[d].UnknownByte = 0xff; + DMA[d].DoTransfer = FALSE; + DMA[d].UnusedBit43x0 = 1; + } +} diff --git a/dma.h b/dma.h new file mode 100644 index 00000000..c779a798 --- /dev/null +++ b/dma.h @@ -0,0 +1,211 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _DMA_H_ +#define _DMA_H_ + +struct SDMA +{ + bool8 ReverseTransfer; + bool8 HDMAIndirectAddressing; + bool8 UnusedBit43x0; + bool8 AAddressFixed; + bool8 AAddressDecrement; + uint8 TransferMode; + uint8 BAddress; + uint16 AAddress; + uint8 ABank; + uint16 DMACount_Or_HDMAIndirectAddress; + uint8 IndirectBank; + uint16 Address; + uint8 Repeat; + uint8 LineCount; + uint8 UnknownByte; + uint8 DoTransfer; +}; + +#define TransferBytes DMACount_Or_HDMAIndirectAddress +#define IndirectAddress DMACount_Or_HDMAIndirectAddress + +extern struct SDMA DMA[8]; + +bool8 S9xDoDMA (uint8); +void S9xStartHDMA (void); +uint8 S9xDoHDMA (uint8); +void S9xResetDMA (void); + +#endif diff --git a/docs/changes.txt b/docs/changes.txt new file mode 100644 index 00000000..3810e2b7 --- /dev/null +++ b/docs/changes.txt @@ -0,0 +1,2387 @@ +Snes9x 1.52 +- IMPORTANT NOTICE: The structure of savestates (also known + as snapshots / freeze files) is incompatible with older + versions! Snes9x 1.52 cannot read the savestates created + by 1.51 or older. (zones) +- Highly acculate SPC700 and S-DSP emulation. (Blargg) +- Replaced APU emulation cores (SPC700 and S-DSP) with + ones provided by Blargg's SNES_SPC library. This renders + savestates incompatible with older versions. (BearOso, zones) +- SPC7110 emulation. (byuu, neviksti) +- Merged bsnes' SPC7110 emulation code. Note that the .rtc + file of Far East of Eden Zero is incompatible with older + versions. (zones) +- Removed graphics pack support. It's no more necessary. (zones) +- Replaced S-RTC emulation code with bsnes' one to keep the + good compatibility of .rtc files between the two + emulators. As a result, Daikaijuu Monogatari 2 now + outputs the .rtc file, and its .srm file is incompatible + with older versions. (zones) +- Added savestate supports for DSP-2, DSP-4, ST-010 and + OBC1. (zones) +- Added UPS support. (byuu) +- Fixed DSP-4 AI problem. (Jonas Quinn) +- Fixed invalid memory accesses in C4 and OBC1 codes. (zones) +- Fixed invalid memory accesses in BSX codes. My mistake. (zones) +- Fixed the read value of $213e, $4210 and $4211. (zones) +- Fixed the writing of word values at the memory boundary. (zones) +- Fixed the bug that the unnecessary SA-1 emulation + continues once any SA-1 games are launched. (zones) +- Removed old color blending codes. (zones) +- Removed too-old Snes96 and ZSNES snapshot support. (zones) +- Updated command-line options. (zones) +- Code cleaning. (zones) +- GTK+ : Added a port of Snes9x to the GTK+ toolkit. (BearOso) +- Unix : Reconstructed and simplified all the contents. + Some features have been removed to be simple, and many + options have changed. GTK+ port is recommended for most + of Linux users. (zones) +- Win32: Now uses snes9x.conf to prevent problems with + modified meaning of settings. (OV2) +- Win32: Removed broken OpenGL mode. (OV2) +- Win32: Removed support for 8bit output. (OV2) +- Win32: Reworked settings dialogues to accomodate the + new APU core and display settings. (OV2) +- Win32: Updated defaults to use D3D and XA2 (better + Vista and Win7 support). (OV2) +- Win32: Direct3D and XAudio2 support. (OV2) +- Win32: Added Blargg's ntsc filter (three presets). (OV2) +- Mac : Fixed corrupted screenshot on Intel Mac. (zones) +- Mac : Fixed sudden abort in QuickTime movie export on + Intel Mac. (zones) +- Mac : Changed sound settings for the new APU core. (zones) +- Mac : Changed the default folder which Snes9x looks for + to 'Application Support' folder. (zones) +- Mac : Changed folder names: 'IPSs' -> 'Patches', + 'BIOSs' -> 'BIOSes'. (zones) +- Mac : Added Blargg's ntsc filter. (zones) +- Mac : Internal changes for Leopard and Snow Leopard. (zones) + +Snes9x 1.51 +- Added DSP1 and SuperFX savestate support. (nitsuja) +- Added screen state GFX to save states. (optional) (nitsuja) +- Fixed desync when loading inconsistent state in playback. (nitsuja) +- When playback reaches a movie's end, recording continues + instead of the movie suddenly closing. (after recording) (nitsuja) +- can now record resets and mouse/superscope/justifier(s) (nitsuja) +- Added same-line-comment support for config files. (nitsuja) +- input display for all controllers (including peripherals) (nitsuja) +- Win32: Now uses .cfg file instead of Windows registry. (nitsuja) +- Win32: open ROM dialog bugfixes and speedup and facelift (nitsuja) +- Win32: option to use standard file open dialog for ROMs (nitsuja) +- Win32: maintain aspect ratio and bilinear filter stretch (nitsuja) +- Win32: optional removal of the dreaded "black bar" (nitsuja) +- Win32: Added EPX,EPX2,EPX3,HQ2X,HQ3X,TV3X,DM3X filters. (nitsuja) +- Win32: Added hires support for Interlace and TV Mode. (nitsuja) +- Win32: text removed from .avi output (optional) (nitsuja) +- Win32: better directory management, customizeable (nitsuja) +- Win32: Screenshot support is back. (nitsuja) +- Win32: Netplay is back (but still not very good). (nitsuja) +- Win32: Made OpenGL Bi-linear an advanced .cfg option. (nitsuja) +- Win32: cheat search improvements (address, watch, SuperFX)(nitsuja) +- Win32: Added non-modal ("active") cheat search option. (nitsuja) +- Win32: new hotkey-config dialog and configurable hotkeys (nitsuja) +- Win32: Fixed joystick config in input dialog. (nitsuja) +- Win32: Fixed hires and extended height .avi output. (nitsuja) +- Win32: various small GUI improvements (nitsuja) +- Win32: Netplay fixes. (nitsuja) +- "Fake Mute" desync workaround option for movies, until + all ports have deterministic sound. (Bisqwit, nitsuja) +- Fix for save state blocks > 999999 bytes. (Bisqwit) +- C4 games now save C4 data in save states. (DeHackEd) +- Unix: Framework for high-speed seeking. Specify a frame + number in a movie, and the emulator will run at + maximum speed to that frame. Untested. (DeHackEd) +- X11: Support for window exposure. When a window is + damaged due to overlay, being iconified, etc. it will + be repainted correctly. (DeHackEd) +- Unix: parameter: -autodemo loads a movie for + playback on startup. Only the x11 code handles this + right now. (DeHackEd) +- Unix: parameter: -oldturbo, the turbo button renders all + frames when fast-forwarding. (DeHackEd) +- Unix: parameter: -upanddown, override U+D and + L+R protection. (DeHackEd) +- Unix: parameter: -mute, currently linux only, blocks out + audio output from your speakers while still emulating + sound. Not fully tested. (DeHackEd) +- Unix: parameter: -maxframes during movie + playback, snes9x will exit when the target is hit. (DeHackEd) +- Unix: parameter: -keypress shows to stderr and on-screen + the currently pressed buttons on joypad 1. (DeHackEd) +- Unix: Stream dumping (NOT COMPLETE). With -dumpstreams, + raw video and raw audio are dumped to videostream%d.dat + and audiostream%d.dat, where %d increments on each CPU + reset, starting at zero. (DeHackEd) +- Unix: Non-blocking sound on Linux. It makes seeking nicer.(DeHackEd) +- Unix: Configurable sound device. (pierredavidbelanger) +- configure.in now requires a sufficiently new version of + autoconf. (anomie) +- Fixed slow versions of branch opcodes. (anomie) +- Fixed the mosaic offset bug. (anomie) +- No sorting by priority in C4 command 00 00. MegaMan X2 + can go behind the legs of the intro stage boss. (anomie) +- New RTO discovery, fixes Super Conflict: The Mideast + title screen. (anomie, byuu) +- A 1->0 transition on $2100.7 causes OAM Address Reset. (anomie, byuu) +- The final HDMA Indirect Address load is only weird + on the last channel of the scanline. + Touge Densetsu Saisoku Battle problem solved. (anomie, byuu) +- Fixed BGnVOFS bug. Only HOFS needs ~&7 update. (byuu) +- Fixed superfluous VIRQ triggers. (zones) +- Fixed missing IRQ trigger just after the previous one. (zones) +- Fixed missing IRQ while writing to $4200. (zones) +- Fixed IRQ timing after WRAM refresh. (zones) +- Fixed NMA timing after DMA transfer. (zones) +- Fixed superfluous auto-joypad-reading. (zones) +- Fixed missing WRAM refresh during DMA transfer. (zones) +- Fixed DMA so that HDMA and any HC triggered events can + run during DMA transfer. (zones) +- Roughly fixed the case that HDMA and DMA use the same + channel at the same time. HDMA kills DMA. Thanks byuu. (zones) +- Changed initial DMA registers values. (zones) +- Slightly modified APU execute timings. (zones) +- Fixed APU I/O registers to get/set the proper value. (zones) +- Blocked invalid VRAM writings, though you can turn off + this option due to Snes9x's inaccurate timings. (zones) +- Omitted SPCTOOL, no one uses it. (zones) +- Added Sufami Turbo support. (zones) +- Added Same Game add-on cart support. (zones) +- Fixed HiROM SRAM and DSP1-4 memory maps a little. (zones) +- Improved mirroring. (Nach, grinvader, byuu) +- CRC32 on BS dumps now follows uCONSRT standard. (Nach) +- BS dumps now always run in NTSC mode. (Nach) +- Unknown regions (generally betas) default to NTSC. (Nach) +- Now support NSRT headers for setting up controllers. (Nach, nitsuja) +- Unix: Fixed command line help output. (Nach) +- Unix: Sound now defaults to 32KHz, Stereo, Interpolation + so Snes9x finally sounds like a real SNES by default. (Nach) +- Win32: Saner defaults for movie record. (Nach) +- Unix: Fixed crashing with mouse or super scope. (Nach) +- Removed some weird code which was crashing Korean + League and its varients. (Nach) +- Win32: Can now compile with MinGW. (Jonas Quinn, Nach) +- Win32: Can now cross compile Snes9xw. (Nach) +- Unix: SSnes9x compiles again. (Nach) +- Win32: ZSNES C4 and SuperFX compiles once again. (Jonas Quinn) +- Unix: Netplay Fixes. (Nach) +- Unix: Netplay Improvements. (Fabianx) + +Snes9x 1.5 +- Pseudo-hires rendering flush, Old 2xsai endian fix (anomie) +- Added 'oops' auto-snapshot support (anomie) +- Fixed usage messages (Unix) (anomie) +- Old split-ROM-in-zip bugfix (anomie) +- ./configure fix for detecting libpng (anomie) +- Fix "no PNG support" error message (anomie) +- Anomie's control remapping patch (anomie) +- Support for IPS patches in the zip file (anomie) +- OBC1 savestate fix (Overload) +- Fix turbo frameskip, X11 keyboard auto-repeat, VRAM reads (anomie) +- Add some missing ifdefs (UNZIP_SUPPORT and ZLIB), + from AaronOneal (anomie) +- Config file for Unix/X11 and Unix/SVGA (anomie) +- CPU instruction fixes (mostly emulation mode & timing) (anomie) +- Mode 7 fixes (anomie) +- Rewrote the renderer. Enjoy! (anomie) +- Correct-ish memmap boundary testing. (anomie) +- Add support for saner directory structures under Unix (anomie) +- Unix: Fixed detection of newer libpng (spotted by vapier) (PBortas) +- Added 4-point gaussian interpolation and proper envelopes + many thanks to Brad Martin and TRAC. (zones) +- Fixed several sound problems. (zones) +- Fixed the memory access problem in C++ Super FX core. (zones) +- Speed adjustment of C++ Super FX emulation. (zones) +- Various timing fixes: NMI, IRQ, WRAM refresh, + cycles per line, HBlank start, etc. + Many thanks to byuu for much information. (zones) +- Removed some game specific hacks. (zones) +- Added partial Satellaview (BS) emulation. (Dreamer Nom, zones) +- Added the Katakana font for onscreen messages. (107) +- Updated JMA to v1 (Nach) +- Unix: Fixed JMA options in config (Nach) +- Unix: Removed --with(out)-asmcpu option in config + because the i386 assembler CPU core is out of date. (zones) +- Unix: Changed the default settings in config. (zones) +- Updated porting.html (porting.txt) in sync with 1.5. (zones) +- Fixed buffer over/under flow due to incorrect logical + operator in S-RTC code (byuu) +- Fixed HDMA flags bug. (byuu, anomie) +- Fixed bugs causing crashing in Unix. (Nach) +- Ported Snes9x to AMD64. (John Weidman, Nach, zones) +- Completed DSP-1 code. (Andreas Naive, Overload, Nach) +- Updated DSP-3 code. (Nach, z80 gaiden) +- Updated DSP-4 code. (Dreamer Nom, Nach, z80 gaiden) +- Overhauled BS detection. (Nach) +- Improved Unix portability. (Nach, zones) +- Fixed infiniti loop and invalid read bug in + C++ C4 core. (Nach) + + +Snes9x 1.43 +- Win32: Disabled Netplay (funkyass) +- Win32: Various fixes, including ROM dialog (funkyass) +- Win32: New Input Config Dialog (funkyass) +- Win32: added .avi output feature (blip) +- Win32: fixed frame timings >100ms, added frame advance (blip) +- Rewrote Unfreeze, renamed it S9xUnfreezeFromStream, + failing to load a freeze file no longer resets emulation (blip) +- Fixed Unfreeze to restore IPPU.HDMA properly (blip) +- Rewrote OBC1 code to match the real chip (Overload) +- More updates the to DSP-1 code, fixes to projection (Overload, Andreas Naive) +- Unix/X11: Rewrote keyboard setup code (Bisqwit) +- Added movie recording+rerecording support (blip, Bisqwit) +- Added -hidemenu CLI switch (funkyass) +- fixed broken Win32 filters (lantus) +- Added internal support for emulating the new-style SNES (MKendora) +- Cleaned up many quirks of the cheat search engine (MKendora, Don Vincenzo) +- Fix mosaic in hires SNES modes (Tokimeki Memorial) (MKendora, zones) +- Rewrote Legend's hack, added another game to it (MKendora) +- Optimized the Open ROM dialog (MKendora) +- Rewrote the Seta DSP map (The Dumper, MKendora) +- Began string isolation for the UI, eases translation (funkyass) +- added -nopatch -nocheat, and -cheat CLI items (MKendora) +- fixed a UI typo (funkyass) +- fixed several C core stack ops in emulation mode (MKendora) +- split emulation mode ops from native mode ops (MKendora) +- Seta special chip emulation enhancements (Feather, The Dumper, Overload, MKendora) +- code tweaks to the ST010 (Nach, pagefault) +- fix some C/asm quirks and HDMA quirks (all my fault) (MKendora) +- several timing hacks to fix games (lantus) +- improved checksumming for odd mirrorings (MKendora) +- Snes9x uses a standard zlib instead of a packaged one (PBortas) +- Exhaust Heat 2 and regional ports are playable (Feather, The Dumper, Overload, MKendora) +- Game Doctor dumps that are 24 Mbit are now supported by + a force option (MKendora, Nach) +- SuperFx interleave format is now considered deprecated. + Support will be removed in future versions (Team decision) +- made SuperFx interleave detection a compile option (MKendora) +- added memory maps for slotted games (MKendora) +- fixed a typo in the usage messages (MKendora) +- fixed the bug that had nuked optimizations (The Dumper) +- restored full speed optimizations in release builds (funkyass) +- Added non-speed-hack version of color subtraction. (zones) +- OpenGL info message font fix (zones) +- APU timer fix (zones, Nach) +- Fixed mouse offset in resized X11 window. (PhaethonH) +- Fixed a (presumably) long-standing bug: Mode 6's BG is + depth 4, not depth 8! (anomie) +- Unix: unmap all joystick buttons before applying -joymapX (anomie) +- Win32: added a define to disable pausing when focus is + lost, NOPAUSE (funkyass) +- Win32: Changed the default for Auto-save SRAM to 15 sec (funkyass) +- Dreamcast: Added SH4 assembler (PBortas, Marcus Comstedt, Per Hedbor) +- C90 and aclocal 1.8 warning fixes (thanks Ville Skytt) (PBortas) +- Unix: AMD64 compilation fixes. (PBortas) +- Added support for NSRT Team's JMA format (Nach, NSRT Team, funkyass) +- Unix: Loading a zip file on binaries without zip support + will give an appropriate error message (Nach) +- Unix: Added install target with proper --prefix handling. (PBortas) + + +Snes9x 1.42 +- Added 8-bit rendering filters (funkyass) +- Added Sanity Checks for the Display Dialog (funkyass) +- New Layout for the Joypad Dialog, (funkyass) +- Fixed that anoying Joypad dialog bug. Now check to see + if the axis exists before asking for the info form it (funkyass) +- Added full POV support. (funkyass) +- Fixed sram sizes for SuperFx games (Nach, MKendora) +- Stopped saving sram for games with no battery (Nach, Mkendora) +- Killed the gray line and slightly optimized Win32 GL (MKendora) +- stack wrapping fix in C core (MKendora) +- removed some dead hacks (Oda Nobunaga and Dezaemon) (MKendora) +- fixed some DMA and HDMA modes (anomie, MKendora) +- improved HDMA timing (anomie) +- cleaned up load and deinterleave code (MKendora) +- removed old UI DLL (MKendora) +- new cheat dialogs (MKendora) +- started Unicode preparation in Win32 UI (MKendora) +- Implement odd sprite sizes, sprite priority rotation. (anomie) +- RTO code that hopefully works. MK's #define is + "MK_DEBUG_RTO" to try to debug the RTO code. (anomie) +- SDD1 decompression support for Linux. Also added a new + command line option -sdd1-pack. (anomie) +- Added correct VRAM read logic. #define CORRECT_VRAM_READS + if you want it. (anomie) +- removed the non-VAR_CYCLES path (MKendora) +- changed access timing map to be address-based. (MKendora, anomie) +- DSP-1 updates (Overload, Andreas Naive) +- S-DD1 decompression support (Andreas Naive) +- optimized S-DD1 code (anomie) +- S-DD1 can use packs or decompression (MKendora) +- More work on Exhaust Heat 2 (MKendora, Overload, The Dumper) +- separated ROM detection from file reading (lantus) +- fixed a mirroring bug in LoROMs (MKendora) +- cleaned up some mapping issues (MKendora) +- ST018 games now boot before locking up (Mkendora, Overload) +- SA-1 state was not completely reset, crashed Marvelous (zones) +- Removed sample caching. It caused problems, and was not + noticably faster. (MKendora) +- Fixed interlace without breaking the displays for MK (anomie) +- Fixed a PPU OpenBus hack (anomie) +- Moved SPC7110 and S-DD1 regs to speed up the general case + of reading the $4xxx registers (MKendora) +- altered Hi/Lo ROM detection to fix a few misdetects. (MKendora) +- Implemented RTO flags. With MK's implementation of $213F's + interlace bit, we now pass the SNES Test Cart's + Electronics Test (anomie) +- Fix sprite windowing bug (anomie) +- Way back in 1.40 MK changed the Windows port to default + to a plain old joypad instead of the MP5. And then we + removed the hacks for games that dislike the MP5. So + we need to change the defaults elsewhere too... (anomie) +- cleaned up the hacks section somewhat (MKendora) +- removed some interleave hacks (MKendora) +- fixed a bug in KartContents (MKendora) +- transparency fix for Jurassic Park (lantus) +- A hidden Win32 feature (MKendora) +- Kludged Mark Davis until I get stable APU timing (MKendora) +- Win32 renders overscan always, fixes some jumpy games (MKendora, lantus) +- Fixed an FMOD bug (MKendora) +- cosmetic tweaks (Everyone) +- Fixed 2 special chip bugs in the C core (zones) +- Added some sanity fixes to the C core, fixes MLBPA + Baseball for C core users (zones) +- updated zlib source (includes 1.1.4-1 patch) (MKendora) +- compiler warning fixes (PBortas) +- Updated the SuperFx asm core (pagefault) +- Kludged Unix compilation to produce working SuperFx (PBortas) + with the asm core. +- Kludged VC to deal with optimization weirdness (MKendora) +- Hacked Robocop vs. Terminator using Daffy Duck hack. Stops + flashing. (MKendora) +- Added some defines to the asm core (MKendora) +- Added possibility to take screenshots on Unix (PBortas) +- Initialize the C SuperFx core better (PBortas) +- Kludge a Japanese golf game until the APU timing is fixed (MKendora) + + +Snes9x 1.41-1 + +- Oops, in the asm CPU core i was stomping on %eax too + early, so register $4210 wasn't getting set properly. (anomie) + + +Snes9x 1.41 + +- Win32 controllers now stay the same between games (MKendora) +- Win 32 Open ROM dialog fixes (MKendora) +- Win32 Display dialog fixes (funkyass) +- Win32 OpenGL ratio tweaking. (Reduces the gray line) (kode54) +- Fixed Win32 superscope for those having issues (MKendora) +- Generic accuracy fix in main SUperscope emulation (MKendora) +- sprite bug fixed (gah! How'd we miss that) (anomie) +- SPC saving compatibility fix (Caz and zones) +- Window clipping update (anomie) +- Mode 7 clipping fix (TRAC) +- latching fix (anomie) +- BS BIOS checksum and mapping fix (MKendora) +- Working Uniracers hack (dma.cpp) (anomie) +- HDMA Indirect Address fix for Romancing Saga 2 (anomie) +- Better savestate hack, does it break anything? (anomie) +- C4 C core fixes. Mostly Trapezoid (thanks Nach), + some s/short/int16/, some indentation. (anomie) +- Damn, but the indentation in ppu.cpp was screwed up. + Killed some dead code too (twas commented forevermore). (anomie) +- fixed a potential crash in S-DD1 logging (MKendora) +- Improved accuracy of Hi/LoROM detection (~500 ROM test) (MKendora) +- Hack for Moryou Senki Madara 2, don't call + SelectTileRenderer from DrawOBJS if BGMode is 5 or 6. A + real fix requires at least rewriting SelectTileRenderer, + or inlining a special version in DrawOBJS. (anomie) +- DMA traces: add additional address info to reads too. (anomie) +- Killed the old Borland Joypad dialog (funkyass) +- Fixed issues with Dezaemon and CT, maybe others (anomie, MKendora) +- Changed the internal snapshot key from \ to VK_F12 (funkyass) + Fixes issues with non-US keyboard layouts. +- Fixed OAM reset to not occur during forced blank. (anomie) +- Killed some dead OAM reset code that doesn't need saving. (anomie) +- Unix/X11: Fixed screen jumping. CT enables overscan mid- + frame for only one frame, and we now update the rendered + screen height accordingly. Other ports are still broken. (anomie) +- Unix/X11: Fixed possible TV mode crash. (anomie) +- Fixed OAM reset timing (beginning of V-Blank rather than + end) for R-TYPE 3 (J). (anomie) +- Unix/X11: Fixed OpenGL target (PBortas) +- Unix/OSS: Fixed big endian sound (PBortas/ernstp) +- Tweaked the About Dialog so its read-only and no scroll (funkyass) + + +Snes9x 1.40 + +- cleaned up a sound skipping code issue. Same as the + RTC issue (lantus) +- re-fixed the invalid BRR header behavior twice (Lord Nightmare, FatlXception, Mkendora) +- More BS mapping fixes. (The Dumper, MKendora) +- Fixed Ranma Bun no 1 - Chonai Gekitou Hen (J) and + Street Combat (U). Interlace is not supported in the + non-Hi-res modes, as far as I can tell. (MKendora) +- Also fixes Maka Maka (J). Frank Yang's report, and + anomie's code both provided clues to this one. +- Removed special casing on setting 5c77 version to one. + This seems to be true for U and J units always. I need + it checked out on PAL... (neviksti) +- Using SNEeSe's values for 5c78 and 5A22. Note we know + that the 5c78 version can also be 1 or 2, instead of 3. (TRAC, neviksti) +- Added turbo buttons. Credit/blame for the design goes + to slack, Nave, Gogo, and myself. (MKendora) +- fixed a bug in turbo (slack, MKendora) +- Tried merging the behavior of Old $4200 with new $4200 (MKendora) +- Made $4200's return value match what VSMC Explorer + showed on Fancia's SNES (MKendora) +- Fixed a matrix multiplcation bug in ZSNES state loads (MKendora) +- Fixed Dezaemon and Ys3 mode 7 (lantus) +- Fixed H-DMA modes 5-7. Thanks to The Dumper for the + extra motivation needed. GunForce and Genocide 2 work. (The Dumper, MKendora) +- Fixed BG3 Priority. I'm stupid. anomie had fixed it, + but lantus fixed it again, because I didn't use it. (anomie, lantus) +- Added a Star Fox 2 hack, and an interleave skip (The Dumper, lantus, MKendora) +- Cleared BS setting on load (lantus) +- Fix for Mode 7 priorities. fixes F-1 Grand Prix (all 3) (anomie) +- JANJYU GAKUEN 2 needs Multi-tap 5 off. (Frank Yang, MKendora) +- HONKAKUHA IGO GOSEI: No multi-tap 5, allow mouse (lantus, MKendora) +- Added a few missed conditional compiles (Nach) +- disabled multitap 5 by default, added menu to enable (MKendora) +- special thanks to anomie and lantus. One of them is + responsible for a bug fix I forgot already. (anomie, lantus) +- Removed several Multitap5 disable hacks. (MKendora) +- Added an SPC dumping upgrade from kode54 (kode54) +- cleaned up some resource leaks (MKendora) +- I forgot this since 1.39mk, but SPC700 flag fixes (anomie) +- Mode 7 interpolation screen flip fix (anomie) +- Updated SPC7110 code a bit, for compatibility (Daniel, anomie) +- Changed RTC saving. (Byte exact to old format on Win32) + The submitted patch for "safety" doubled the file size, + so I had to write it in explicitly little-endian. (MKendora) +- Removed the old hidden cursor (MKendora) +- Applied a WAI correction from anomie. (anomie) +- Added a patch for Pseudo hi-res (anomie) +- Hacked around Word writes to $7F:FFFF. Thanks to lantus + and The Dumper for verification. (MKendora) +- PPC compile fix? and debugger reversion (anomie) +- Set defaults differently to improve sound quality. (MKendora) +- Clear Force load settings after Init (lantus) +- Made menu reset a soft reset. Fixed BL Sound Test & more (CaitSith2) +- Fixed word writes to block bounds in asm core. (MKendora) +- redone version of my bounds fix, only this one WORKS! (TRAC) +- Thanks to TRAC for the AT&T syntax refresher! (TRAC) +- Fixed screen saver disable (kode54) +- Fixed OAM and sprite priority in the asm core (anomie) +- Proper Interlace fix for mid-frame changes (anomie) +- Fixed OpenGL to accomodate previous patch (MKendora) +- Ported the "Settings" dialog to VC (MKendora) +- Fixed ROM Info bugs (_pentium_five, MKendora) +- Fixed non-stretched interlacing, but it's s.l.o.w. (anomie) +- Superscope and Mouse need to be enabled by the menu. (MKendora) +- Fixed HiROM sram reads in asm and C cores (anomie, MKendora) +- Added Company 48 to the list. Thanks to _pentium_five_ (StatMat) +- Set Super Drift Out's S-ram correctly. (Snes9xppSE Team) +- Fixed NTSC timing. Helps ToP Intro greatly (kode54) +- Added several entries to the company list, from uCON64 (Nach) +- Lots more companies (StatMat, Nach) +- Fixed Win32 Superscope support (NT kernel only?) (MKendora) +- Added ZSNES OBC1 code ported from asm to C (sanmaiwashi) +- Implemented Justifier emulation (neviksti, MKendora) +- Fixed Rudora no Hihou's clip window bug (anomie) +- Fixed Flintstones sprite issue (lantus) +- Fixed sram mappings for Big Sky Troopers and + Taikyoku - IGO Goliath. Both map in bank F0 (MKendora) +- Fixed a possible crash when switching audio settings (MKendora) +- Added per-pack gfx pack configuration (MKendora) +- Fixed glitches in DSP-1 games (Flintstones fix) (lantus) +- Added delay to Superscope latching. Fixes X-Zone. (neviksti, MKendora, zones) +- Added DSP-2 support (Overload, The Dumper, Lord Nightmare, + MKendora, neviksti) +- Fixed Super Bases Loaded 2 (and J/K ports) DSP-1 seems + to ignore the A15 line in LoROM maps (MKendora) +- Corrected $4200 again (The Dumper) +- Corrected $2100, $2102, and $2102 read behavior (anomie) +- Fixed Cancel on the Sound Options dialog. (MKendora) +- Fixed the sound options dialog (Thanks, Quattro) (MKendora) +- updated DSP-1 support to match chip better (Overload, neviksti, The Dumper) +- added a few Ops to the DSP-4 routine (Nothing plays yet) (neviksti, The Dumper, Overload, MKendora) +- added screenshot support (anomie, sanmaiwashi) +- stubbed the ST010 chip in Exhaust Heat 2 (Overload, MKendora) +- hacked around War 2410's lockup (pagefault, _Demo_, MKendora) +- updated tests for type 1 ROMs (based on reset vector) (MKendora) +- Emulation mode CPU fix (The Dumper) +- Open Bus fixes (anomie) +- Better Expansion port emulation (anomie) +- More Open Bus fixes (Overload, anomie) +- HDMA fixes (fix colors only in Full Throttle Racing) (anomie) +- Migrated DKJM2 onto the Tales map (MKendora) +- Tried to remove Dragon Knight 4 hack (LoROM sram fix) (MKendora) +- Fixed ROM Mirroring for LoROMs (<= 32 Mbit) (MKendora, TRAC) +- blocked wram to wram DMAs (neviksti) +- fixed HiROM mirroring, too. Thanks TRAC! (MKendora, TRAC) +- fixed C core RMW and Push ops to write in the correct + order, fixes Michael Jordan gfx. (anomie, Overload, MKendora) +- set RDIO to start as 0xFF, fixes SuperFx games. (anomie, Overload) +- New connect dialog (funkyass) +- better conditional compile of FMOD (funkyass) +- fixed screenshot code when libpng is not used (funkyass) +- added portability fixes (zones) +- fixed asm Pushes (anomie) +- fixed asm LoROM s-ram decode (MKendora) +- migrated DEZAEMON to standard LoROM map (MKendora) +- fixed the Madara 2 OpenGL bug (key found in Rudra) (MKendora) +- fixed asm RMW instructions (MKendora) +- fixed ADC opcode (The Dumper) +- added DSP-2 Op09 (The Dumper) +- updated C4 C code (anomie) +- updated C4 asm code (Nach) +- Keep OpenGL in ratio (kode54) +- Replaced many more Borland dialogs (funkyass, MKendora, Nach) +- Added CRC32 to displayed ROM Info (Nach, MKendora) +- Fix cheat support (The Dumper) +- improved DMA timing (MKendora, Overload, The Dumper) +- Fixed Mode 7 math, removed Dezaemon, Gaia, Ys 3 hacks (TRAC, MKendora) +- Mode 7 flip fix (TRAC) +- Multiple safety and initialization fixes (zones) +- Platform safety fixes (PBortas) +- Memmap cleanups (MKendora) +- More preliminary work on special chips (The Dumper, Overload, MKendora) +- Added color coding (MKendora) +- Another HDMA fix (anomie) +- added another known hack to the hacked games list (Nach) +- ToP memmap changes (MKendora) +- Checksum calculation changes (MKendora) +- Special cased a few games for OAM issues (MKendora) +- Reverted OAM reset to 1.39 timing (MKendora) +- Reworked vram wrapping (zones, Mkendora) +- Fixed $4210 and Super Professional Baseball 2 (Overload, MKendora) +- Fixed APU RAM init (Overload, MKendora) +- More support for Exhaust Heat 2 (not playable) (The Dumper, Overload, neviksti) +- removed some debris from save states (MKendora) +- fixed? Doom's save state bug (MKendora) +- simple overdump detection warning (MKendora) + + +1.39mk3b + +- Fixed the RTC detection. FINALLY done correctly (lantus, MKendora) + + +1.39mk3a + +- neatened up the company table. (MKendora) +- fixed a mistake in the ROM Info box (MKendora) +- Added a Calulcated Size field to ROM INfo. (MKendora) +- Added 3 more companies to the ROM Info table (MKendora) +- Fixed BS detection (The Dumper) +- Added a Legend-specific hack to get sound. I remembered + it being mentioned in the changelog. (Gary Henderson) +- Unbroke the Star Ocean special cases (Trigger of Time, MKendora) +- Company 255 is not Hudson-ZFE detects all Hudson games + without it, except a corrupt dump (StatMat, MKendora) +- fixed a bug in the redone detection for the SPC7110 (CaitSith2) +- 44Khz sound should be 44.1Kz. Changed, though you'll + need to re-set 44.1Khz to make it take effect. Not sure + if this affects non-Windows ports. (MKendora) +- Added 32Khz playback (MKendora) +- Inproved BS ROM mapping (_Demo_, The Dumper, MKendora) + + +1.39mk3 + +- Honkaku Syogi Fuunji Ryuou (J) fixed (force no multitap) (Frank Yang) + Also Fixed Super Castles (j). + Also fixed a bunch more. This dude e-mailed like 100 bugs + to my hosts, some already fixed in Snes9x1.39mk2, but + about 7 were clearly multi-tap5. +- also fixed Dekitate High School. Error was in Japanese (Frank Yang, Tomato) +- fixed 2 memory leaks (Aaron) +- Dai Kaiju Monogotari 2 works as a 40 Mbit ROM. (MKendora, The Dumper) +- Fixed the Flashback bug. Lots of info led to this. (neviksti, MKendora) + Thanks neviksti, The Dumper, TRAC, and FatlXception + for clarifying the behavior. +- Fixed Sailor Moon Fuwa Fuwa Panic 2 to work with (neviksti, MKendora) + previous fix. It's a total hack, but it should sound + just like the old Snes9x did. neviksti strikes again! +- Dirty hack to make 3 games deinterleave properly: (MKendora) + Wizardry 4, Mark Davis, and Honkakuha Igo Gosei(FX) + all work as well as the deinterleaved counterparts. + (The last is a hacked game, and you should get the + non-FX version) +- Fixed Seima Jyuden Beasts and Blades. Another Multitap, (Frank Yang) + but for some reason, the hack requires the C cpu core. + Thanks to Tomato for taking a stab at the error message, + as well. It was too vague to be of use, he said. I + just tried it because it worked on other games. +- Res Arcana fixed. Another Frank Yang report, another J (Frank Yang, MKendora) + error, but I can read kana well enough with a table! +- Removed a Terranigma specific hack. Not sure, but the (anomie) + new behavior might have fixed Tin-Tin in Tibet's colors. +- Dirty hack to work around a dirty hack. Both Yoshi's (MKendora) + Island (E) dumps should work now +- Added the JumboLoROM memory map, Extends LoROM support (The Dumper, neviksti, MKendora) + to 48+ Megabits. +- added an EXTBG fix, since iirc, TRAC is using it as well (anomie) + Does it actually fix anything? +- Fixed crash in DSP Op06 (The Dumper) +- Fixed a GUI error on my part (Trigger of Time) +- Cleaned up some of the SPC7110 detection/size code. (MKendora) +- Merged in XBox port changes to SPC7110 code (lantus) +- Added a call to Memory.Deinit when exiting. (lantus, MKendora) +- Many memory leaks fixed while chatting with lantus (lantus, MKendora) +- Fixed that stubborn open/close leak (lantus) + + +1.39mk2 + +- hacked in Shien's Revenge (anomie) +- fixed Orge Battle's green lines. (CPU source for DMA) (anomie) + - Looks interesting, and might apply to other DMA cases? +- maybe "fixed" DKC's barrels? by treating $2001 + as unmapped. The game worked before with a hack. (MKendora) +- optimized SPC7110 slightly by removing extra setup work (MKendora) +- Fixed DBZ 3 (Korean). S. Korea is, in fact, NTSC. (MKendora) +- Fixed a hard-coded value in the SPC7110 (MKendora) +- Added a Win port ROM Info dialog (MKendora) + - some companies aren't in the table I used. + If you encounter an Unimplemented company, + report it the the Snes9x development forum, with + the correct company and the number. + + +1.39mk +- SPC7110 support based on Dark Force's docs. (Dark Force, zsKnight, + The Dumper, MKendora) + Trust me when I say those guys deserve the credit more + than me. From what I'm told, Dark Force is the man + behind most of the reverse engineering, but they all + did a much harder bunch of work than I did following + their specs. It's plain and simple that these three + are the masterminds behind all SPC7110 support. + + Dark Force for reverse engineering the chip (Extremely tough work!) + zsKnight for the original core, and probably other things + The Dumper for dumping the packs and doing hardware tests. + + Also thanks to CaitSith2 for numerous bug reports + and a lot of bug fixes. + +- Theme Park hack removed, fixed via PPU latching (anomie, MKendora, TRAC) +- WWF Wrestlemania hack removed (anomie, TRAC) +- Strike Gunner hack fixed (anomie, MKendora, TRAC) +- FF:MQ text fixed. May help other sprite issues. (TRAC) +- Umi Hara Kawa Se timing corrected. (anomie) +- S-DD1 packs load by the same rules as ZSNES (MKendora) +- SPC7110 code builds in linux (Lord Nightmare, zinx) +- Added The Dumper's DSP-1 updates (The Dumper) +- SPC7110 is correctly displayed on load, RTC also noted. (MKendora) +- Fixed a potential graphics problem (TRAC) + no known games fixed, but who knows? +- Fixed Ballz3D (pagefault) +- Re-fixed Ballz3D, via DSP op 0F (The Dumper) +- included some of anomie's fixes. Many caused me grief, + so only Marko's Magic Football is intentionally fixed. (anomie) +- finished zsnes save support, though I don't know how + well it will work with SPC7110 games (MKendora) +- Added a new soundux.cpp again to fix some noise. + (Fixes the GW "fart track") (Lord Nightmare, info from Anti-Res) +- Added 3 cache modes for SPC7110 games (MKendora) +- Added new BRR decoder. Requires sample caching + and the Anti-Res decoder be disabled. (FatlXception, port by Lord Nightmare) +- Added CaitSith2's RTC debugger. define RTC_DEBUGGER in + project settings to enable it. (CaitSith2) +- SPC7110 per-game cumulative logging (MKendora) +- other fixes that I've forgotten (sanma iwashi, TRAC, anomie, ????) + +- "I'm not worthy" thanks to the original SPC7110 crew (DF, zsKnight, and the Dumper) +- Thanks again to the same people, because they deserve it! +- thanks to The Dumper, Dejap, TRAC, and all the ZSNES crew for technical assistance +- Thanks to most of the Snes9x mods for testing (no thanks to you, Raptor ;) +- and thanks to TRAC and #mkendora for letting me vent at you. + +1.39 +- Added SDD-1 unknown graphics data logging at the dumper's request. A bit late + but might help with Street Fighter 2 Alpha's data dumping. Creates a + romname.dat file in the freeze file folder. +- Implemented 16-bit texture support for OpenGL modes in Windows and Linux. + Had to support a new pixel format type to do it - RGB5551 (one bit of alpha) + which caused me some major problems - black was no longer always pixel value + zero! +- Removed the Bump map OpenGL mode from the Windows port (didn't look so good + anyway and was slow). +- Added a hidden novelty OpenGL mode (clue: a keyboard shortcut activates it) +- Reverted back to FMod version 3.20 after reports that version 3.33 broke + AD3 support. +- Implemented a better work-around for the broken select system call in the + Linux kernel - the original work-around was long-winded and stopped working + when I implemented OpenGL support under Linux. +- Added the same speed-up hack to the OpenGL code that the Glide code already + supported. Basically, if your OpenGL implementation supports 16-bit textures + then OpenGL mode should be as fast, or faster than the 3dfx Glide mode. +- Hopefully fixed Glide support. +- Reverted back to the original colour blending code. The newer code, although + more accurate in most cases, had too many glitches and was slower. +- Included multiple Japanese games fixes from Iswashi San. +- Fixed a timing problem caused by a speed up hack that was affecting Top Gear + 300. No the game still isn't playable yet, but I noticed the problem while + investigating the DSP-4 chip used by the game. +1.38 +- Added support for Star Ocean and Street Fighter 2 Alpha decompressed graphics + packs from dejap. Used a binary chop search rather than a linear search to + locate correct decompressed graphics more quickly - should help emulation + speed during later stages of the game. +- Included OpenGL support into the Linux port and speeded up the Windows OpenGL + implementation slightly. The real speed up would occur if I could figure out + how/if 16-bit textures are supported in OpenGL because at the moment the + 16-bit software rendered SNES image must be converted to 24-bit before being + uploaded as a texture... +- Included the latest ZSNES DSP-1 code. Now Pilotwings, SD Racer and Suzuka 8 + Hours are playable. Aim For The Ace, Super Air Diver 1 & 2 and Syutoko Battle 94 + are also playable, but with bugs. Thanks to zsKnight, _demo_, et al for all + their hard work. +- Another Daffy Duck: Marvin Missions screen flicker problem worked around - + writing to the IRQ enable register shouldn't clear any pending IRQs, but + Sieken 3 seems to require this or else the game hangs. Special-cased Daffy + Duck for now. +- An NMI emulation bug was triggering a Panic Bomberman World game bug, + crashing it. Basically, if a game enables NMIs after the normal trigger + point, the NMI should not trigger if the game has already read the NMI clear + register. +- Panic Bomberman World requires SPC700 memory to be initialised to zero on + reset otherwise the game hangs when a tune finishes and another one should + start. +- Added mouse pointer auto-hide to the Windows port. Much better than the turn + the mouse pointer into a black dot method I was using before. +- Included the latest ZSNES Super FX code. Not sure if it fixes actually fixes + any games. +- Added an offset hack for Strike Gunner to get the scrolling ground layer + to line up correctly - another offset-per-tile bug hacked around for now. +- Arrr! Left in some debugging code in the last release that prevented all + games that need the slower SPC700 timing from working. Removed it. +- Hmm. The broken cut-scenes in Deep Space 9 seem to indicate that I haven't + got the emulated clock speed of the 65c816 CPU correct yet. And not by a + little bit - a 9% too slow error. Hacked special timing for the game for now. +- Added triple-buffering to Windows port - enabling double-buffering actually + enables triple-buffering if you have enough free video RAM, defaulting to + double-buffering if you don't. +- Fixed another crash bug in the interpolated mode 7 code - if no scaling + was being used (either up or down) and screen repeat was enabled and the + screen was flipped horizontally, the routine would crash Snes9x. Was causing + Snes9x to crash during rock monster boss stage of Castlevania 4. +- Oops. Got the initialisation of the default SNES screen width and height + round the wrong way - could cause a X Windows System error message on the + UNIX port after loading a ZSNES freeze file. +- Included the unofficial Windows port emulation fixes for several games including + Kentouou World championship and TKO Super Championship. +- Included Iwashi San's improved Anti Res. sound sample decoding routine and + updated the C version to match. +- Included Anti Res. improved sample decompression code he sent me ages ago, + but for some reason I didn't include. Sorry. This version seems good enough + to leave enabled all the time. +1.37 +- Added fix for Captain America's corrupt graphics - a ROM bug causes it to + read from what I thought should be an unmapped memory area, but it expects + the value returned to be zero. +- Added code to support games that switch to the hi-res. SNES screen mode part + way down the screen while using the 3dfx bi-linear filter mode. The code + basically has to back out of the speed up hack it was using when the game + switches resolutions. +- Fixed support for games that have mixed lo-res. (256x224), medium res. + (512x224) and hi-res. (512x448) all on the same screen - corrects the display + of Majin Tensei 2. +- Added support for games that use sub-screen addition to the back-drop layer + while displaying hi-res. graphics - something I thought the SNES couldn't do + but the game Marvelous uses this. +- Reworked the UNIX/Linux output image handling code: the image doesn't always + have to be scaled when hi-res. support is enabled, the PutImage operation + only updates the area of the screen it has to, the SNES image is now always + centred in the window/full-screen area and if the SNES image changes size + between frames, the old screen areas are now correctly cleared. +- Fixed the corrupt graphics problem during the battle scene of Last Bible 3 - + it requires that previously unknown DMA mode 5 should just act the same as + DMA mode 1. +- Fixed a nasty bug when H-IRQs were being reused on the same scanline - a logic + bug could cause H-DMA processing for that line to be skipped. Was causing + the bridge and the start banners to be the wrong colours in Top Gear 2. +- Added Kreed's display processing modes to the Linux port, including his new + asm version of the Super2xSaI mode and the new software bi-linear filtering + mode. +- Think I might have figured out the odd Mode 7 glitch problems the games + Illusion and Gaia and Chase HQ were having. My original fix was to mod the + centre X & Y values with 1024, but looks like the true fix is to mod + X + horizontal offset and Y + vertical offset with 1024 when screen wrapping + is enabled. +- Disabled H-DMA'ing into V-RAM via registers 2118/2119. The game Hook + deliberately does this causing graphic corruption while dialog boxes are + displayed. Maybe the real SNES disallowed this and it was left in the game by + mistake? Not sure what effect the game was trying to produce because + disabling the emulation of this feature doesn't seem to affect the game at + all, other than stopping the corruption. + + Also fixes graphics junk problem on first screen of Bugs Bunny. +- Added a 'region-free' timing hack for Power Rangers Fight - without it the + NTSC version was displaying badly glitching graphics; I'd already fixed the + PAL version. +- Added true priority-per-pixel mode 7 support (the previous support was just + a hack to get the colours correct) - level 2 of Contra 3 used this feature. +- The Japanese, German, French and Spanish version of Illusion of Gaia needs the + slow SPC700 timing. +- Deleted the Breath of Fire 2 S-RAM hack for the hacker intro version - + according to reports it was causing problems for the non-hacked version. +- Legend, the PAL version, never sets the sound master volume control - Snes9x + was defaulting this to off, I guess the real SNES must default it to full + volume; changed Snes9x. The NTSC version of Legend does set the master + volume level, but sets it to off just after the title screen. Hmm. The -nmv + command-line switch allows you to hear sound in this version. +- Panic Bomber World was tripping an SA-1 emulation bug - the WAI instruction + emulation code was setting the 'waiting for interrupt' flag on the wrong CPU + causing the main SNES to skip an instruction when the next interrupt occurred. +- Panic Bomber World, Bomberman 4 and UFO Kamen Yakisoban all need the slower + SPC700 timing. +- Oops! The Super Formation Soccer 95 fix was causing Aero 2 to lock up. This + means I have no no idea what value the DMA in progress register should + represent. I've hacked it and made it toggle between 0 and $ff on each read + which gets both games working, for now... +- The ROM de-interleaving code always assumed the blocks were rearranged based + on a power of two, but Francois found a copy of Soldiers of Fortune where + this was not the case. Corrected the code. +1.36 +- Finally worked out why the menu items weren't being highlighted in several + ROMs, including Battletoads, U.N. Squadron and All Japan Pro Wrestling. + Two problems: its seems the SNES does halve the colour value result when + blending colours when only the fixed colour addition/subtraction is enabled, + but doesn't halve the result when sub-screen is being blended and its a clear + part of the sub-screen. The second problem was that I had an optimisation + that prevented the time consuming colour blending code from being called if + the colour being added/subtracted was black - adding zero to a number doesn't + affect the result, but not performing the side-effect of halving the result + does affect the final value... +- Super Formation Soccer 95 requires that the DMA enabled register doesn't + always return zero, otherwise the game locks up. +- Thanks to several people reporting a screen flickering problem in the + pseudo 3-d section of Jurassic Park 2 I've fixed a nasty problem in H-IRQ + handling code which could cause double-triggers or skip IRQs altogether. + With this fix I can now remove the special hacks for Ninja Warriors Again, + Chuck Rock and F-1 Grand Prix. +- More games needing the slow SPC700 timing: + Zennihon Puroresu 2, Soulblazer and Robotrek. +- The CPU idle time skipping code was skipping cycles during a software delay + loop in Itchy and Scratchy, causing screen flicker. +- Looks like reading the value of register $2137 shouldn't clear a pending + IRQ - was causing screen flicker on Yoshi's Island. +- Actraiser 1 & 2 both need the slow SPC700 timing. +- Terranigma reads a sound channel's current sample output value and waits for + it to be zero before preceeding. I forgot to always return zero when a + channel was silent. This mistake was causing the game to lock up. + + Itchy and Scratchy and was causing the music to stop and samples to be cut + short in the Mario Early Years series. +- Added a hack for Secret of the Evermore - at several points in the game, just + as the plane is about to land, it reads from unknown registers $4000 and + $4001 and, if it doesn't get the value its looking for, the game hangs or + displays corrupt graphics. +- Silva Saga 2 was accidentally triggering a colour blending hack I put in + place Kirby Dreamland 3 and Kirby Superstar. +- The ZSNES freeze-file loading code could leave a file open if the file wasn't + a valid ZSNES freeze file. +- Super Punch-out requires certain DMA registers to be updated after the DMA + completes. Snes9x used to do that, but I must have accidentally left the code + commented out whilst investigating a different problem in another game. +1.35 +- Added a recently played game list to the Windows port File menu so you can + quickly load up your favourite games. +- Included IPS patching support based on code from Neill Corlett - just rename + the patch file to match your ROM image name but with a .ips extension and + copy it into your ROM or freeze-file folder. +- Added John Weidman's and Darkforce's S-RTC, (Real Time Clock) emulation code. + The only game that seems to use it is Dai Kaijyu Monogatari II. +- Included code from Nose000 for games with 128Kbytes of S-RAM. Now + Sound Novel-Tcool, Thoroughbred Breeder 3, RPG-Tcool 2 and Dezaemon are + supported. +- The Windows port now has an option to make the 'turbo speed' button a toggle + button. +- The optimised fixed colour addition/subtraction code was ignoring the colour + window. Thanks to John Weidman for pointing this out. +- Added mode 7 and hi-res. hack for Dezaemon from Nose000 - the mode 7 hack + looks interesting (to me); I wonder if some other games would benefit? +- Both Tales of Phantasia and Star Ocean need custom sound CPU timing. Hmm. + That's 4 ROMs now, there will be more... That means I still haven't + discovered all the major SNES timing quirks. :-( +- Windows port now has an option to save the S-RAM data at any time. +- Windows port saving SPC dumps now auto-increments the filename. +- Added work-around for a Super Robot Wars Ex ROM bug - the game was checking + the wrong PPU register for end of h-blank. The game must have only worked by + chance rather than by design on a real SNES. +1.34 +- Corrected the colour addition/subtraction and halve the result code not to + halve the result when only the fixed colour is used, i.e. the sub-screen is + clear. Discovered and fixed this awhile ago, but I accidentally reintroduced + the bug when adding some optimisations a few versions back. +- Finally cleared the last of the offset per tile background mode bugs. There + was something odd about the tile at the left-hand edge of the screen that I + couldn't figure out - well now I have. Yoshi's Island level 6 boss screen, + Mario RPG mine cart screen and Jim Power title screen now all display + correctly. +- Made reading blank areas of the SNES memory map return the middle byte of + the address - fixes Home Alone which tries to execute code in an empty part + of its memory map but only works because the real SNES seems to return the + middle byte of the address - $60 in this case, which corresponds to the + ReTurn from Subroutine instruction. +- Added auto-cycle skipping disable for Earth Worm Jim 2 and several other + games that spool sample data using H-DMA as the sample is being played. + Improves some sound effects in these games. +- Fixed joy-pad routines to only report up or left if down or right are also + pressed respectively. Works around a game bug in Empire Strikes Back in the + asteroid stage where the game crashes if both left and right are pressed - + something impossible to do on the original SNES game-pad. +- Added custom SPC700 timing for Rendering Ranger R2 - the game now works with + full sound. No idea why it needs custom SPC700 timing. +- The ROM type detection was broken for Treasure Hunter G and Test Drive 2 - + fixed the code so type 2 ROMs can be LoROM. +- Adjusted the main CPU cycles per scan-line from 341 to 342 to give an exact + match for the timing required for Earth Worm Jim 2. All EWJ2 needs now + for perfect sound emulation is a method of synchronising the emulation + speed to the host hardware's sound card playback rate, oh, and a fast CPU! + The Linux port already has this but seems to be broken because games + play at double-speed when this option is enabled. +- Some SPC700 code in Earth Worm Jim 2 seemed to prove that I had guessed the + clock speed of the SPC700 sound CPU incorrectly - out by almost a factor of + two, in fact. Changed the relative emulated clock speed of SPC700. Now + Chrono Trigger doesn't lock up at certain points anymore, the special SPC700 + timing for games written by the Human Software company isn't required and + you can hear some more of the sound samples in Earth Worm Jim 2, etc. +- H-IRQ triggering code was broken - if a ROM turned on H-IRQ but later turned + it off, Snes9x could continued to generate H-IRQs, crashing some games. +- Added a generic test for Human Entertainment games - they need special + sound CPU timing to work. Gets Taekwon-Do working. +- Disabled offset-per-tile mode for Theme Park; the world map screen is corrupt + with it enabled. +- Yet more changes to the offset-per-tile backgrounds modes 2 and 4. Added + 64 tile wide screen support for Mario RPG's mine cart ride and fixed multiple + bugs with the handling of horizontal offset-per-tile used in Chrono Trigger's + fade in of the space ship. +- New feature: Snes9x can now load ZSNES freeze state files! Just copy them + into the freeze file folder and Snes9x will load them when you load a freeze + file, but only if the corresponding native format Snes9x freeze file doesn't + exist. +- Added memory map hack for Batman - Revenge of the Joker: its ROM header block + is in the wrong location and Snes9x incorrectly detected its ROM type. +- Fixed an off-by-one-pixel clip window 2 bug when the window was set to clip + outside the window area; clip window 1 was already correct. Removed the bright + line bug at the left edge when the combat screen is appearing in Starfox and + the clip problem when text boxes zoom-out in Yoshi's Island. +- Jim Power's title screen seems to prove that the per-tile offset data on + mode 2 isn't ignored for the left most tile as I originally thought. + Modified the code. +- The recent timing changes highlighted another problem with Daffy Duck - + changed IRQ enable register to only clear pending IRQs if one has been pending + for several microseconds. +- Speeded up the sprite data register handling slightly. +- Finally got Aero the AcroBat 2 working, after many hours of investigation, + spread over several years - literally! Two problems. The SNES doesn't seem + to consider scan-line line zero to be part of the v-blank period even though + the line is never drawn and V-IRQs at the start of the scan-line have to be + delayed until a few microseconds into the line - Traverse: Starlight & Prairie + required this as well, so I removed the original, Traverse specific hack. + There's a problem with the in-game music that I'll investigate at a later + date. + - The in-game music problem just required ENVX emulation to be switched on, + off by default on the Linux port, on by default on the Windows port. +- Fixed the mode 7 corruption problem on the title screen of Chase HQ using the + same trick as Illusion of Gaia - i.e. mod the mode 7 centre X & Y values with + 1024. +- Fixed another crash bug in the interpolated mode 7 code - a portion of + the code was ignoring the screen flip value and the fact that X render + direction reversed if the screen was flipped horizontally. Was causing a + crash on the whale boss screen of Kirby Superstar. +- Mortal Kombat 3 now auto-adjusts emulated cycles per scan-line work-around + a speech sample being cut short. +- Added sample data register reading support to the sound DSP - somehow I + seem to have missed implementing this. Not sure if any ROM actually reads + the value. +- Followed Sumire Kinoshita's suggestion and stopped clearing the ENDX flags + when the value is read, against my better judgement, and it does actually + improve speech samples in several games. Ooops! The Mortal Kombat series, + Magical Drop 2 and Metal Combat are the ones I've discovered so far. +- WWF Arcade now auto-adjusts the cycles per scan-line value to work-around + a sound sample repeat problem. +- Hmm. There's something about offset-per-tile mode I don't understand - WWF + Wrestlemania Arcade is getting corrupt graphics; not sure what effect the + ROM is trying to produce. Disabled offset-per-tile mode for the game for now. +- Fixed Street Racer player 1 wobble problem during the soccer game by auto- + adjusting the cycles per scan-line value slightly. +- Made Power Rangers Fight auto-adjust emulated cycles per scan-line to work + around a slight timing problem that causes an NMI to corrupt register + values that an IRQ handler is trying to update. Without it the scrolling + back-drop and fighter graphics are corrupt. +- Illusion of Gaia seems to need the mode 7 centre X & Y values to be mod 1024 + if the screen repeat flag is set. Fixes the island fly-over bug right at + the end of the intro but breaks a few other games. Hmm. Made it auto-switch + on for this game only. +- Added memory map support for Radical Dreamers. Thanks to satellite hut master + for the information. +- Made updates to the top bit of the sprite write address register be ignored + unless the low byte had been written to first. A ROM coding bug in + James Pond II requires this, otherwise it writes a junk byte value into the + main character's X position and Robocod wobbles around all over the place. +- Reverted back to pre 1.31 way of initialising unknown register values - + Rock and Roll Racing was reading a junk register value and using the value + to set up DMA, which in turn was causing corruption on the player select + screen. +- Added Star Ocean memory map - thanks zsKnight! The original ROM I was testing + was corrupt, no wonder I couldn't figure out the memory map myself! The game + still isn't playable, though, due to missing S-DD1 graphics decompression + (+ encryption?) emulation. +- Started to dump some compressed data values from Street Fighter 2 Alpha in + the hope that one day someone will be able to crack the S-DD1's compression + algorithm. +1.33a +- C4 emulation wasn't being automatically enabled for Rockman X2 / X3 - the + Japanese versions of Megaman X2 / X3. +- Fixed the Super FX plot table pointer that I accidentally broke while saving + 1Mb of workspace RAM - it was stopping all Super FX games from working. +1.33 +- Noticed another problem with the CPU_SHUTDOWN code - Chrono Trigger locked + up during the intro but only when using the asm code CPU core. Found the + algorithm difference between the code and made the CPU match what the C + version was doing. Still not sure why it caused a problem in the first place. +- Changed colour subtraction code to use Lindsey Dubb's newer version he sent + me some time ago but I 'forgot' to include. I say forgot, but I really put + off including it because, although it improves most games that use the + effect, it does result in one or two slight visual glitches. +- Hacked in zsKnight's C4 emulation asm code - now both Megaman X2 and X3 are + playable. Still got to complete the reverse engineering of the i386 asm code + to C so other, non-Intel ports can have C4 emulation. +- Shuffled the keyboard mapping a bit on the Linux port so now Tab key acts as + an emulation speed turbo button, `, # and ~ act as superscope turbo and + / acts as the superscope pause button. +- Fixed asm CPU_SHUTDOWN code that I accidentally broke while trying to + optimise it! Thanks to all the people who noticed Snes9x's frame skipping + had changed between releases. Frames rates should be improved again for more + than 50% of games. +- Re-enabled in-lining of the C SNES memory access routines, improves frame + rate by one or two on slower machines. +- Optimised the asm 65c816 addressing mode emulation code a little. +- Included some code changes making life easier for the Mac porter, John Stiles. +- Added memory map support for Sufami Turbo using information supplied by + Nose0000. No idea if it works because I don't have the ROM. +- Spent a few minutes trying to figure out the Star Ocean memory map so at + least the sound effects could be heard. But gave up after a couple of hours + due to laziness. If anyone knows the memory map details, let me know please! +1.32a +- The delay loading of the OpenGL DLLs on the Windows port was causing the + OpenGL initialisation code to fail. Reverted back to normal DDL loading but + with the side effect that Windows 95 users must visit the Microsoft web site + and download the OpenGL add-on before Snes9x will work for them. +- Corrected the OpenGL bump-map display option - my attempt to get the + bi-linear OpenGL display option to work with Voodoo card's limited texture + size had broken the bump-map mode. +1.32 +- Changed the Windows port to delay load the two OpenGL DLLs, so now they're + only loaded if you switch to OpenGL mode. The original version of Windows 95 + didn't include the OpenGL DDLs, so Snes9x wouldn't even start on that + platform; now it should. +- Added yet another sound buffer option to the Windows port - this time the + block size of sound data to mix. Some DirectSound sound card drivers only + report the play position moving in steps rather than continuous amounts and + Snes9x's default mix block size turned out to be smaller than this step + value on several cards. + Snes9x couldn't work out out where the true play position was accurately + enough resulting in broken, noisy sound output. +- Modified the Windows frame timer code to use semaphores rather than events - + they should make Snes9x more reliable at not missing frame sync pulses when + Windows is busy doing background tasks. +- Added SA-1 shutdown code - basically, Snes9x now stops emulating SA-1 CPU + instructions when the SA-1 enters an idle loop waiting for the main SNES + CPU to give it something to do. All SA-1 run much faster and smoother now. +- Added multi-axis joystick/game controller support to the Windows port and + tweaked the dead-zone threshold position a little. +- It looks like the SNES PPU was designed to support 128K of V-RAM but only + 64K was fitted; Snes9x wasn't wrapping all V-RAM address to stay within the + 64K limit causing a corrupt title screen on ReX Ronan - there will be others. +- Added amend functionality to the Windows Cheat Entry dialog and added extra + text boxes for direct address and cheat value input rather than only being + able to type in a Game Genie or Pro-Action Reply code. +- BS Suttehakkun2 was crashing just before start of play - the ROM was + performing a junk DMA that was corrupting RAM, crashing the game when it + went searching for a particular value. +- F-1 Grand Prix requires IRQ triggering when IRQ scan-line register set to + current scan line, but Chuck Rock objects. Hmm. Chuck Rock seems to indicate + the CPU emulation is running too fast, but I can't see where the mistake is. + Special-cased Chuck Rock for now. +- Optimised SNES DMA handling slightly - copying data to SNES V-RAM is now + significantly faster. +- Windows Cheat search dialog was ignoring data type parameter in various + places which was causing problems when larger numbers were being searched + for. +- Forced unknown PPU register reads to always return 0 - a coding bug in + Equinox shows that this is required. An earlier fix didn't work. +- Puya Puya 2 & remix were objecting to an NMI being triggered when enabling + NMIs after scan-line 226, but Ys 5 seems to require this. Hmm. Added a hack + to support both games. +1.31 +- Snes9x DirectSound code modified - the mixing block size is now always 10ms + for Windows 95/98/2000 and 20ms for NT 4.x, now there should be no need to + enable Sync Sound when a large sound buffer is required (helps emulation + speed). The maximum sound buffer length values have been updated to reflect + the smaller mixing block size. +- Changed the DirectSound code back to use an offset from the play position + as the place to write new sample data into the sound buffer - on NT 4.x the + write position seems to vary randomly rather than being a fixed distance + in front of the play position as documented. Now I know why I used the play + position originally! +- Changed the DirectSound code to fill the sound buffer at the write position + supplied by DirectSound, rather than just before the current play position - + should help reduce latency. +- Added an auto-detect method for interleaved mode 2 Super FX ROM images - + well, not really auto-detect: if the game crashes and its a Super FX game, + Snes9x assumes its in interleaved mode 2, de-mangles the ROM image and tries + to run the game again. +- Had to update the Snes9x Windows registry version number as the additional + diagonal settings make old registry settings incompatible. +- Added diagonal keyboard controls to the Windows port, as requested by + several users. +- Changed PPU code to return zero when reading non-existent registers - the + game Equinox relies on this due to an original game coding bug. +- Included FMOD sound driver support to Windows port - people experiencing + broken sound or delayed sound, etc, might want to give it a try. +- Tales of Phantasia - un-interleaved format ROM memory map changes to match + odd ZSNES format, now the hacked ROM works. +- Changed NMI again. Made reading or writing to PPU register 0x4210 + clear NMI pending flag again, without this Super Tennis does not work. +- Changed NMI timing back to be the same as several versions ago and just + special cased Cacoma Knight instead - although kept the code to prevent + the re-triggering of an NNI more than once in the same frame. +1.30 +- Forgot to force GUI surface to be displayed when some dialogs where popped + up - problem only happened on full-screen mode with triple or double + buffering enabled, or when using 3dfx mode. It appeared as if Snes9x had + locked up, but pressing Esc would pop down the hidden dialog. +- Added a couple of options to the Settings dialog. Now its possible to + disable S-RAM auto-save which was causing Snes9x to write to the hard disk + every 30 seconds on some games, causing the occasional skipped frame. +- Fixed Reset option which was accidentally broken when Netplay support was + added. +- Added support for Dirt Racer - it leaves the Super FX chip running all the + time, so the default CPU emulation method never allocated any time to other + CPUs and the emulation seemed to lock up. +- NMI timing changed again. Now an NMI can only be triggered once per + frame and enabling an NMI after the normal trigger scan line triggers + an NMI immediately. This fixes display glitches in Ys 5, Stargate and + Daffy Duck. +- Fixed the WAI instruction to only 'wake up' once an actual NMI has + triggered, rather than just waking up when it should have triggered. + This fixes Battletoads, broken since version 1.29(ish). +- Changed NMI again. Made reading or writing to PPU register 0x4210 not + clear NMI pending flag. Seems to allow all the NMI timing sensitive ROMs + I had on my list to now work without any special hacks. Illusion of + Gaia now works again. +- Another NMI fix - cleared the CPU pending NMI flag at start of frame; + Battletoads intro was crashing without this. A long DMA was stopping the + SNES CPU so it couldn't and shouldn't respond to the NMI signal from the PPU. +- Fixed Netplay problem when game didn't have any S-RAM and Sync Using Reset + was being used. An error dialog was displayed and the client would disconnect + from the server. +1.30b#1 +- The Windows auto-frame skip code was broken - badly. It didn't re-sync a + timer value with timer events being generated, causing Snes9x to deliberately + stop and wait for an event when it didn't need to, slowing down the overall + emulation speed and increasing the number of frames skipped. +- Improved the Windows cheat search dialog - its now possible to compare + against a value and more comparison functions are available. +- Finally worked out why Voodoo 3 support was so buggy in Snes9x - the Voodoo 3 + card generates a WM_DISPLAYCHANGE message when switching to Voodoo mode (the + Voodoo 1 and 2 cards don't); Snes9x thought that some other application had + changed the screen depth or resolution and tried to adjust its window to + match - triggering another WM_DISPLAYCHANGE message. No idea how the code + worked at all; it must have been only by chance and very dependant on the + driver version you were using! +- Implemented Netplay on the Windows port - but its buggy as hell. I seem to + be having major Windows multi-threading problems. Comments I've seen seem to + suggest that Windows 95/98 don't implement true multi-threading; hmm... +- Not happy with the current Netplay, so I scrapped it and tried again; + the protocol is much improved and not using select to control game timing + seems to have removed lots of the threading-type problems I was having. +- Attempted to switch to just using Borland's C++ Builder to build the Windows + port - and failed, again. Although C++ Builder can build Snes9x from sources, + it can't then link in the asm CPU cores. I had hoped Borland might have + fixed this with their latest release - they haven't. +- Several attempts to get Anti Resonance's super-fast sound CPU and sound DSP + code working in Snes9x, but all failed. Part of the problem was his code was + written using TASM and the object files it generated would only work under + Windows - but all my SNES debugging code was in the Linux port. Anti' fixed + that, and I then had some success getting his code working, but its just too + unstable at the moment for a main-stream release. +- Included an option to use Anti Resonance's alternate sample decoding routine; + it can approximate the wind and noise sound effects heard in several Square + Soft games. +- Thanks to Lindsey Dubb for the mode 7 bi-linear filtering code - it + generates a nice smooth image when a game scales the screen using the SNES' + mode 7, but you'll a fast machine if you don't want the frame rate to drop. +- Thanks again to Lindsey Dubb, he improved the colour addition/subtraction + subtraction routines - they are just a little slower but now mostly perform + full 15-bit precision addition and subtraction rather than the previous + 13-bits of precision. Many more colour shades can be seen - look at the + improved shading on the Mario Kart or F-Zero track for example. +- Added a reverse stereo option, for people with sound cards that swap the two + channels. +- Added a sound config dialog to the Windows port - now you can access extra + sound options that have always been there, but just no GUI interface to + access them. +- Fixed the 32-bit windowed support on the Windows port. +- Adjusted the NMI timing by a few microseconds to get Metal Warriors working + again. +- Added a few more sound playback rate choices. Most modern sound cards allow + any value to be used from a large range, rather than just a select few, may + be I ought to add text field so you could just type a value in? +- Used Factory Setup 4 to build a new installer package for the Windows port - + just shipping a zip file was confusing novice users and many (mostly AOL + users) seemed to have an odd program mapped to .zip files, further confusing + the issue. +1.29 +- Disabled the SPC700 noise feature simulation used by Chrono Trigger and + Final Fantasy 3 until I work out why its being triggered by sound effects + that don't use it. +- Rewrote/reorganised the DirectX and 3D/fx handling code, now both are never + enabled at the same time in Snes9X. It might fix the crashing problems some + Window port users are seeing. Changing between DirectX and Voodoo 3D/fx + modes now requires Snes9X to be restarted. +- Tracked down and fixed the Chrono Trigger black screen problem on the Windows + port: a rogue asm instruction was left in by mistake after some code edits - + it was only by chance that the code worked on the Linux port. +- Added some SNES debug options to the Windows port, but disabled by default, + on the shipped version. +- Clicking on the column headings in the OpenROM dialog in the Windows port + now sorts by that column; plus added some slight screen update optimisations. +- Added an optimisation to graphics rendering: don't add or subtract + sub-screen from background layers, or clear the sub-screen, if SNES fixed + colour is black and no background layers are enabled on sub-screen, even if + ROM tries to enable translucency effects for every background layer. + Discovered Sonic was doing this, there will be others. +- Forgot to enable auto S-RAM save on Windows port, oops! +1.28 +- Warning dialog added to the Windows port - if a ROM is loaded from a + read-only directory, e.g. a CD, and the freeze file folder is set to be the + same as the ROM image folder, then a warning is displayed when the game first + starts. +- The Windows port now supports 5 joy-pads - Snes9x always did support 5 but + the Windows port lacked the GUI option to enable and configure it. +- Added an about dialog to the Windows port. +- The Windows port now has a simple settings dialog, only one option so far - + changing the freeze file and S-RAM save directory; much better than having to + use regedit at least. +- Added a new cheat search dialog, you can use it to find where games are + storing life counters, health levels, etc. and then add cheats that stop the + values from changing. +- Added a cheat code entry dialog to the Windows port; now Game Genie, + Pro-Action Replay and Gold Finger codes can be graphically entered and + edited. +- Added a master cheat codes on/off toggle, available from the Cheats menu + on the Windows port. +- Extended the number of cheats per game from 10 to 75. +- Changed cheat code to reapply cheat every emulated frame so if RAM is being + patched the cheat value is continuously applied. +- Wrote some new cheat search code, the code won't be useful until I get around + to writing a cheat search dialog. +- Added automatic cheat code loading and saving using the same file format as + ZSNES. +- Rewrote large parts of the Snes9x cheat handling code ready for adding + cheat dialogs to the Windows port. +1.27 +- Added a flag to only enable SPC700 noise 'feature' when Chrono Trigger or + Final Fantasy 3 are loaded - the conditions that I thought were necessary to + trigger the feature where sometimes being met by other games. +- Added a simulation of the SPC700 noise 'feature' where some games, notably + Chrono Trigger and Final Fantasy 3, play samples that deliberately overrun + outside a 16-bit value, the SPC700 sound DSP then for some reason starts to + generate a type of noise sound which the games use to generate wind and + swish type sound effects. Thanks to ZSNES for some of the information. +- Fixed another sound interpolation problem, thanks to Mikael Bouillot - + the initial value of the sample byte being played was not being set correctly + when processing fractional offsets. +- Added auto S-RAM save option; S-RAM is automatically written to a .srm file + a few seconds (30 by default) after a ROM writes to it - useful for people + who were playing games long into to night, only to lose their progress + after a power cut or machine crash. +- NMI delay code changed again - the fix for Cacoma Knight was breaking + Tuff E Nuff; it would seem delaying NMI until the start of h-blank to too + long, added a cycle counter instead. +- Fixed yet another clip window bug - clip window was being incorrectly set + at no range if colour window was enabled but background layer clip window + was disabled (meaning layer should not be clipped). + Fixes the sunken ship level on FF5. +- Worked out (by example) how to add keyboard accelerators to the Windows port, + now toggling full screen using ALT+Return works. +- Added mouse-warp to the Windows port so the the cursor doesn't wonder off the + Window while SNES mouse emulation is enabled. +- Improved 3dfx support on Windows port - load dialog doesn't drop out of + bi-linear mode and underlying window zooms to full-screen so its easy to find + and click on the menu bar with the mouse. +- Added Mouse and Superscope SNES emulation support to the Windows port, use + '7' on the keyboard to select. +- Windows cursor now hidden unless super scope emulation is enabled. +- Windows port now has command line parsing - cheapo way of adding Game Genie, + Pro Action Replay cheat codes, disabling sound CPU emulation for the + corrupt copy of Star Fox 2, etc. Also allows ROM images to be dropped onto + the Snes9x icon. +- Cacoma Knight seems to provide proof that Snes9x triggers the SNES + non-maskable interrupt (NMI) too early. Changed interrupt to trigger at the + start of the next horizontal blank period. Will have to watch for it + causing problems for other ROMs. +- Added a translucency hack - when a ROM tries to create a stipple background + pattern by enabling pseudo hi-res. and not enabling a background layer on + one of the screens, Snes9x changes the effect to use transparency effects + instead (the real SNES can't do transparency effects with pseudo hi-res. + enabled). Now the water in Kirby 3 is translucent. +- SA-1 CPU reset bug fixed, now Jumpin' Derby boots and plays but with major + graphics problems. +- Fixed nasty asm SA-1 custom hardware read/write bug that was causing the + course map not to be displayed on Augusta Masters and Pebble Beach. +- Added SA-1 character conversion DMA support for all SNES depths, now + Augusta Masters and Pebble Beach work. +- Merged in minor code changes for Linux running on the Alpha processor. Thanks + to Sadruddin Rejeb for the changes. +- Added four more auto-multi-player-adaptor-emulation-off presets based on + code from Mystagogus. +- Added DirectX3D output image processing support to the Windows port... and + removed it again because it causes my desktop machine to lock up. Back to + the drawing board... +1.26 +- Fixed memory leak that crept in when SA-1 support was added when loading a + game freeze file. +- Added SPC dumping option based on code from Cyber Warrior X that he sent me + ages ago but I've just found again while looking for something else! +- Merged in most of the Amiga PPC port source code changes into the main + source code tree. +- Keying on a sound channel seems to clear its last-sound-sample-block-just- + played flag. Chaos Engine/Soldiers of Fortune needs this. +- Add multi-thread support to the UNIX ports for sound playing - required in + the Linux port to work around a Sound Blaster Live driver bug and useful if + you have multiple CPUs in your machine to help spread the emulation workload. +1.25 +- Added BS 24Mbit ROM memory map, for Derby Stallion 96 and Sound Novel-TCool. + No idea if it works. Thanks to Nose0000 for the info and code. +- Corrected unzip code not to loop forever if an encrypted zip file is loaded - + an error is generated instead. +- Changed relative SPC700 cycle length for Mortal Kombat 3 to fix sample + repeat problems - I wish I knew exactly how fast the SPC700 is clocked. + Maybe I should write a test ROM and run it on a real SNES? +1.24 +- 3dfx speed hack back again, only disabled when Seiken 3 is loaded. +- Some minor SA-1 speed ups added - the SA-1 instruction skipping code will + have to wait until I have more time. +1.23 +- Corrected a SA-1 reset bug that reset the SA-1 RAM bank pointer back to block + zero but didn't clear the RAM bank register. Was causing Kirby 3 to crash. +- Fixed a wave clipping problem with interpolated sound that was causing noise + on sound output when certain sound samples were played. +- Fixed a bug in the sync-sound code that could overrun the sound buffer by a + few bytes causing clicks on the sound output. +- The sound sample repeat bug that has plagued Snes9x ever since is was called + Snes96 finally bit the dust - Snes9x continued to play sample loops + even if the game dynamically updated the sample not to loop. Fixes the + stutter in the Mortal Kombat series and improves the sound from several games + that download sound samples in real-time as they are played. +- Rewrote the code the handled the SPC700's 64 byte shadow RAM area to fix a + possible sample corruption problem with ROMs that stored samples that + cross the 64 byte start area. +- Added code to allow ROMs to change the sample being played the next time the + channel loops or is keyed on - not sure if it fixes anything but seems more + correct. +- Added a zero-frequency fix to the stereo sound mixing code that I'd already + added to the mono code some time ago. +- Changed the code to set the end-of-sample flag just before the last block is + played, rather than just after. Seems to help improve the sound on some + games. +- Sound sample start code now doesn't reset the channel's envelope volume level + to zero before starting the sample - helps reduce the clicks being heard when + a channel envelope volume level hadn't reached zero before being keyed on + again. +- Changed initialisation of sample-end-register to 0 rather than 255 - seems + more logical now I've thought about it. Not sure if it helps anything. +1.22 +- Finally fixed the corrupt copy of Donkey Kong Country not working problem - + Snes9x thought the ROM used the same memory map as Street Fighter Alpha 2. +- Added explode, un-shrink and un-reduce decompression modes support to the + unzip code. +- Fixed offset per tile bug that crept in after me trying to fix the Starfox + on-tilt bug. +- Made some fixes to the C Super FX emulation code, enough to get most 'FX + games playable on the Mac port. +1.21 +- Finally worked out how character DMA worked on the SA-1 and implemented a + hacky, slow version, but its enough to get the level up screens displaying + correctly on Mario RPG. +- Incorporated ZSNES' new optimised Super FX asm code - had to track down and + fix a nasty memory overwrite bug in the code first to get it to work. +- Changed sample mixing code to not automatically wrap offsets to + keep inside the sound buffer, external port code is now expected to do that. + Helped me fix a problem in the Windows port that prevented very large sound + buffers from working, which are required for some badly written sound card + drivers. +- Corrected a bug in the SA-1 C code where incorrect processor emulation + functions where called if the code was compiled with in-lining turned off. +- Fixed crash bug in Super Mario RPG on the level up screen - forgot to mask + the enable bit from the RAM bank register. Thanks to Christian Wolf for + sending me a freeze file which made it easy to find the problem. +- Fixed a lockup bug in the window clipping code, if the ROM ever turned off + the sub-screen completely the clipping code would enter an infinite loop. + Fixes The Cartoon Addams. +- Made the Daffy Duck NMI fix only enable when Daffy Duck is loaded - fix was + causing problems for Breath Of Fire 1 and 2. +1.20 +- Windows port no longer sets DirectSound to exclusive mode, so its now + possible to hear sound output from Windows apps while Snes9x has focus. +- Fixed the freeze file loading and saving on the Windows port. +- More GUI settings are saved in the registry on the Windows port now. +- Added 3D/FX image scaling/filtering support to the Windows port. +- Added the TV mode from the Mac/Linux ports to the Windows port. +- Incorporated Kreed's new output image routines into the Windows port that + fixes RGB555 display colour problems. Many thanks to Kreed. +- New auto-frame rate timing code on the Windows port, stops the silly speed + up problems when the old code tried to 'catch up' after the emulator had + been paused. +- Increased the DirectSound secondary buffer length on the Windows port to + hopefully fix all the static/broken sound output problems some people were + experiencing. +- Altered the ZSNES Super FX asm code so the Windows port could use it - all + previous versions of the Windows port were shipped using the C Super FX + emulation code which is a lot slower. +- Implemented interpolated and sync-sound options on the Windows port. +- Added an image stretch option to the Windows port - stretches the SNES image + to fill the whole screen or the Window. Looks really good on my TNT card + since that chips seems to filter the image as it scales it. +- Implemented Windowed mode on the Windows port. +- Added special SPC700 cycle timing for Empire Strikes Back. +- Fixed the missing polygon problem for Super FX games - thanks to zsknight + for the information. +- Implemented SA-1 support required for Mario RPG, Kirby Superstar, + Paradius 3, etc. but since only a good image of Mario RPG exists, I could + only test that game. +- Fixed a graphics clip window bug: inverting the area of a clip area that + only consisted of empty bands should become the full width of the screen; + Mario Kart's rear-view mirror display needs it. +- Fixed mode 7 render code to use correct z-buffer when rendering onto the + sub-screen. Fixes Final Fantasy V title screen. +- Added horizontal offset per tile support in the offset per tile modes 2 + and 6, and switchable horizontal/vertical offset in mode 4. Fixes Chrono + Trigger in several places and Mario All Stars title screens. +- Changed SPC700 relative cycle length to 14, needed for Stunt Car Racer. +- Enabled immediate triggering of NMI if NMI enable flag set while scan-line + was on first line of v-blank. Needed to fix a background jitter bug in + Daffy Duck: The Marvin Missions. +- Altered ROM load code to ignore corrupt ROM map type byte in ROM header, + preventing the code erroneously detecting what it thinks are interleaved + ROMs. Fixes EEK! The cat, Formation Soccer, the corrupt copy of Donkey + Kong Country, ... +- Disabled IRQ re-triggering if V-IRQ registers set to the current line. Fixes + Chuck Rock. +- Fixed missing sprites in Andre Agassi Tennis - writing to low byte only of + the sprite write address register seems to also clear the hi-byte. +1.19 +- Games written by the Japanese software company Human seem to need special + SPC700 sound CPU timing, so the ROM load and reset routines now check the + software author company and adjust the CPU cycle length accordingly. + It gets Clock Tower, Super Fire Pro-wrestling Premium, etc working. +- Added ROM check sum calculation and testing code - Snes9x can now detect + pure, corrupt or hacked ROMs. +- Noticed a fast way to implement the SNES 4096 colour mode, so I implemented + it. Now the colours in ActRaiser 2 look correct. +- Corrected a noise frequency error thanks to information from Takehiro. +- Added a 'start in full screen mode' flag to the Linux port. +- While debugging the new graphics code I thought of a fast way to implement + the SNES direct colour mode, tried it out and now the colours in Actraiser 2 + are correct. +- Blast, forgot about the colour window and fixed colour effects. The separate + sub-screen is back again, but all the other graphics speed ups are there. +- Now I've got a z-buffer I keep finding other ways to optimise the SNES + graphics rendering - no need for a separate sub-screen, no need to clear + the sub-screen to the fixed colour, no need to waste CPU time on translucency + effects on hidden pixels, no need to completely clear the main-screen to the + back drop colour, etc., etc. +- Implemented a software z-buffer and changed the SNES graphics rendering to + use it (required change for future 3D card support). Finally fixes the + sprite-to-sprite priority bug that some games suffer from. Also a big speed + increasing for some games (10 fps+), others are slight losers. +- Added code to skip the rendering of completely transparent graphic tiles + rather than comparing each pixel to see if it is transparent; helps the + frame rate a bit on some games. +- Added a fixed for Tetris & Dr. Mario - the game didn't like a multi-player 5 + adaptor plugged in to the real SNES when being played, so turned off the + adaptor emulation for this game. +- Added hack for Final Fantasy II - if sync sound isn't on, make attack rate of + 1ms actually 0ms (old v1.16 behaviour). Causes a slight click but its better + than samples being cut short. +- Fixed a clip window area invert bug if the colour window was enabled on + on one window and the other window was being used to clip a background layer. + Fixes the finial (I hope) display problem with Gun Hazard. +- Added code to intersect the clip window areas if both a colour window and + a background layer clip window were enabled at the same time. Required by + Gun Hazard. +- Forgot to mark graphic clip windows as needing recomputing when the master + colour window inside/outside/on/off/main-screen/sub-screen PPU register was + updated. Was causing display problems for Gun Hazard. +- Internal H-DMA execution accelerator pointer variables where not always + being recomputed when started H-DMA part way into a frame. Was causing + display problems for Gun Hazard. +- Made H-DMA continue for one extra scan-line to fix a disappearing monster + problem in Dragon Quest 5. Thanks to Alex Jackson for the bug report. +- Zoop seems to require volume envelope height reading by the sound CPU to + always return 0 when the channel is in gain mode. +- The sound code was ignoring updates to the ADSR volume envelope rates while + one was in progress. Fixed that and now the bird song at the start of + Chrono Trigger sounds correct. +- Had to disable the CPU shutdown code for loops reading the horizontal beam + position, it was causing problems for Star Fox. Still no polygons though. +- Oops, sound DSP noise output was broken - accidentally deleted an important + line while removing debug code ready for the last release. +- Added initial 3Dfx support to the Linux port - basically using the Voodoo + card as a bi-linear filtering, scaling blitter. Actually slightly slower than + TV mode, for non-scrolling images due to poor texture upload speeds to the + card, but the full-screen feature is nice and the speed doesn't drop as more + of the screen changes. +1.18 +- Implemented a sync-sound mode where sound data gets generated in sync with + SPC700 instructions being executed. Finally the sound Williams Arcade + classics can be heard. Also helps slight sound timing problems in many other + games but doesn't fix Mortal Kombat 2 like I thought it would - its + sound routine programmers must have been on drugs or something! +- Added interpolated sound - gives low frequency sounds much more bass similar + to a real SNES especially with the playback rate ramped up to 44KHz. +- Added on-screen messages as various emulation options are toggled on and off + using the in-game keys. +- Fixed a PPU register read bug with the sprite register write position. Thanks + to Takehiro TOMINAGA for the bug report. +- Altered the auto-frame skip timing code to only wait and re-sync to the end + of frame when frames haven't been skipped. Again thanks to Takehiro. +- Speeded up the colour addition and subtraction code using ideas from + Takehiro. +1.17 +- Linux and UNIX sound code now driven directly from signal timer handler + rather than the timer handler just setting a flag which had to be polled in + the main emulation code. Slightly faster execution. +- Fixed the crash bug in the ZSNES Super FX asm code with Vortex - the game's + polygons still aren't visible though. +- Implemented bent-line increase and exponential decay and sustain volume + envelopes - they should match, or at least be very similar to the real SNES + sound DSP chip now. +- It would seem ROMs can key on sound channels even if the channel hasn't + been keyed-off, Pac-In-Time requires it. Changed code to allow it. +- Quick mod to ZSNES Super FX code to get Winter Gold working - it was already + working with the C Super FX code. +- Added emulation of the extra 1/2 scan-line per frame on PAL and NTSC - + should help improve music speed emulation. +- Worked around the click sound heard when ROMs use 0 volume envelope attack + rate. +- Removed the 'check for IRQ already happened' H-IRQ position register setting + code - it was causing problems for Ninja Warriors and was not required by + F1 Grand Prix. +- Fixed a bug in the new sound code - the sustain part of the + attack-decay-sustain-release volume envelope was being skipped if the + sustain level wasn't at 100%. The fix has helped some music notes from + being cut off early in a few games. +- Added fix to Pro Action Reply support (again). Thanks to Paul Shoener III for + the original fix and Gil Pedersen for reminding me to apply it! +- Finally fixed the Tales of Phantasia 'bum note' problem! The ROM set its + sample directory to the upper-most page and I forget to code for the hidden + 64 bytes of RAM, that appear when the boot ROM is switched off, when fetching + sample addresses. +- Adjusted the relative cycle length between the 65c816 and the SPC700 slightly + to get Terranigma working again. +- Oops, the emulated joypads 3 and 4 via the emulated Multi-player 5 interface + weren't working. Thanks to Steffen Schwenke for the bug report. +- Optimised the echo sound code - by-passed the the FIR filter code if only + a pass-through FIR filter was defined by the ROM. +- Modified V and H-IRQ register changing code to trigger an IRQ immediately if + V-IRQ is enabled and the scan-lines match and either H-IRQ is not enabled or + the electron beam position has already gone past the trigger point. Fixes + the screen flicker in F1 Grand Prix. +- Modified the priority-per-pixel mode 7 code to use BG#1's clipping data if + the top bit of the mode 7 pixel is set. Fixes initial track drive-through + display in F1 Grand Prix. +- Modified the sprite priority levels for the priority-per-pixel mode 7 + display. Now the car can be seen in F1 Grand Prix. +- Wrote a sound DSP register recording scheme which 'plays back' the register + changes in sync with the sound generation code. I'm bit disappointed, it + only improves the sound in a very few games... Scrapped the code, it actually + causes more problems than it fixes. Oh, well, another 3 weeks work wasted... +- Fixed a SPC700 wake up problem for Lufia I - made the SPC700 also wake up + when the 65c816 read from one of the four comm ports. +- Included lots of sound code speed ups and sound quality improvements + from Takehiro TOMINAGA - many thanks go to him. +1.16 +- Fixed a case where the -forcelorom option didn't work - the case was + required for Formation Soccer which claims in its ROM header to use the + same memory map as Super FX ROM, it doesn't. +- Pulled apart a real SNES using a crowbar (great fun), just to look at what + speed the SPC700 is actually clocked at for more accurate relative emulation + speed. +- Implemented SPC700 cycle counting in the hope the improved timing would fix + Tales'; no such luck but at least the -ratio option is obsolete now. +- Implemented executing SPC700 instructions during DMA, fixes BSZelda and + Goal lock up at start and music pausing briefly when ROMs do lots of DMA, + usually between game screens. +- Scrapped the i386 asm SPC700 code - it was the cause of the music not + restarting after a battle in Chrono Trigger and FF3 and I didn't realise + because the bug had already occurred in the test freeze-file I had. + Thanks to John Stiles for pointing out that the Mac port didn't have the + missing music problem. +- Fixed RGB subtraction bug on displays with only 5 bits for green, e.g. RGB555 + displays. The GREEN_HI_BIT variable was always set to a value for 6 bit + green displays. +- Added the SA-1 memory map, still a long way to go before any SA-1 game will + run. +1.15 +- Jumped versions to keep in sync with the DOS port release. +1.14 +- Improved 8-bit sound generation slightly, but it still sounds very poor + compared to 16-bit sound. +1.13 +- Implemented the Tales of Phantasia memory map using the information supplied + by zsKnight. Had to also implement a de-interleave routine to work around + a ROM feature and Snes9x CPU instruction fetching implementation detail. +- Added a frames-per-second on-screen display option. +- Fixed the final glitch bug with the Mario Kart track display - the byte code + for the termination of the DSP1 raster command wasn't been recognised. +- Disabled a NMI/DMA hack for Rise of the Robots, was causing problems for + Mario Kart and 'Robots wasn't working correctly anyway. +- Optimised the mode 7 rendering a little. +- Changed tile rendering code to use offsets into screen buffer rather than + direct pointers ready for z-buffer implementation. +1.12 +- Changed V-blank NMI to occur immediately after a WAI instruction, Toy Story + required this. +- Fixed reading of H-DMA line counter register, Top Gear 3000 needed this. +- Ripped off large parts of ZSNES's DSP1 code (with _Demo_'s and zsKnight's + approval). Now Mario Kart works almost 100%. +- Added a check to see if a vertical scan-line IRQ register change will cause + a H-IRQ later on the current scan-line. Pilot Wings needed this. +- Fixed possible crash bug in clip window code when both windows had two + spans. Could actually cause Chrono Trigger to crash the emulator. +- Fixed a lock-up problem with the C Super FX code, Star Fox and executing + a few 'FX instructions per scan-line (required for Winter Gold). +1.11 +- Partially fixed the DOS netplay server - the server timer is running too + slowly and it doesn't deal with disconnects correctly yet. +- Corrected the sound echo delay - it was varying with the sound playback + rate chosen by the user - it shouldn't have been. +- Implemented DOS netplay code - DOS server code still not working though. +- Removed all floating point calculations from the sound generation code. +- Fiddled with the pitch modulation code - my guess is the output of a + channel that is used to modulate the frequency of another channel is + automatically muted by the SPC700 chip. Just a guess, but the wind from + FF3 sounds 'better' but far from perfect. +- Optimised the tile palette index calculation. +- Optimised the planar to chunky tile conversion code. +- Fixed X11 port to always scale SNES image if hi-res. only (no interpolation) + support is enabled. +- Added zipped ROM image support using Gilles Vollant unzip code and + some code that Ivar (Lestat) sent me a long time ago. +- 65c816 asm RTI instruction was destroying the program bank in emulation mode, + the C code was already correct. Caused C64E to break. +1.10 +- Finished NetPlay v1 - allows up to five networked machines to play + multi-player SNES games, one player on each machine. +- Switchable full-screen mode added to Linux X11 port, some code and ideas + nicked from Maciej Babinski's original Snes9x XFree86 DGA Linux port, the + UAE Amiga emulator, plus lots of my own code. +1.08 +- Bug fixes to C Super FX emulation - now Winter Gold works correctly again. +1.07 +- More DSP1 work. Mario Kart is now playable! The character projection code + is still broken so the opponents and obstacles aren't always positioned + correctly on screen and you keep bumping into them, but I can still keep + coming first! +- Started work on NetPlay support. +- Decreased sound card DMA buffer size on DOS port to improve sound generation + and sound CPU synchronisation in some games. +- Included Linux joystick driver patches from Vojtech Pavlik so the port can + use the new v1.x joystick drivers, again written by Vojtech Pavlik. Allows + use of Micro$oft Sidewinder pads, NES and SNES pads, PlayStation pads, + Gamepad Pros, etc. +- Added halve-the-result colour subtraction. +1.06 +- Extended code to allow support for multiple 16-bit screen formats, + switchable at run-time, rather just supporting one, selectable at compile + time. +- Added XFree86 DGA Linux port - code from Maciej Babinski. +- More fixes to the X11 image format conversion and setup code. +- The asm SetByte routine wasn't wrapping writes to S-RAM correctly, allowing + some ROMs to think they were running on a copier and put up an error + screen. Thanks to Nu of #rom for the report. +- Added 'TV-Mode' support (interpolation and scan-lines) to the DOS and + UNIX ports from code based on John Stiles work. +- Added v-sync option to the DOS port. +- Added fix to Pro Action Reply support, thanks to Paul Shoener III. +- Added ggi support (untested) to Linux port using patches from + Alexander Larsson (alla@lysator.liu.se). +- Added 16 to 24/32 bit image conversion routines to the UNIX X11 code. +- The SPC700 OR1 instruction was broken. Thanks to Pyrgopolinices for the + report. +- DOS port was having trouble splitting and joining path names - caused + problems when specifying the full path name of a ROM when the ROM image + was on another drive. +- If a ROM reset the sound DSP and then turned on echo effects but kept + the same echo delay setting, then the echo effects could not be heard. + Thanks to madec@mclink.it for the bug report and freeze file that made it + easy to find the problem. +- DOS port was always using stereo sound setting, if sound card + supported it, regardless of the user preference. +- Linux port X11 port could crash if window was resized while transparency + effects were enabled. +- The colour subtraction accelerator look-up table was slightly wrong, causing + one bit of red, green blue values to 'spill' into the next field. +- Allowed colour window to cut a hole in the main-screen and show the sub- + screen underneath. The effect is used by Illusion of Gaia. +- Added support for colour subtraction, with the halve-the-result flag + set. +- Included DSP1 code from _Demo_. Now you can see the track in Mario Kart and + the ground in Pilot Wings - still can't play the games though due to other + missing commands. +- Added an NMI hack to work around a code bug in Battle Toads: BATTLEMANIACS, + its only by chance that the game works on a real SNES - And disabled it + again because it causes problems for Chrono Trigger. +- A frame skip of zero was actually still skipping one frame. Thanks to + Marius Fodor for the info. +- And yet more X-OR window bug fixes - now the effects during some of the more + 'posh' spells look correct in Chrono Trigger. +- Yet another window area inversion bug - off by one pixel on right-hand edge. +- Forgot to put dummy start and end points for XOR window combination modes - + now Uniracers looks correct and Sailor Moon looks like it does on a real + SNES. +- Window clip code was using wrong index into a 2-dimensional array when + the whole of the main or sub-screens were clipped. +1.05 +- The master volume disable code was looking that the wrong variable! +- Fixed crash bug in newer sound code if a ROM tried to start a sample + playing who's data went past the end of SPC700 memory. (Cannon Fodder) +1.04 +- Fixed DSP1 ROM header detection bug. +- More DSP1 work; still nothing works, although I know the multiply command + is correct because I've compared the results against a real DSP1. +1.03 +- Oops, the multi-player 5 disable code change broke the multi-player 5 being + the default controller. +- Implemented the colour window on the main screen - now Zelda's oval zoom + window displays correctly and Krusty's Super Fun House clips the left-most + 8 pixels as it does on the real SNES. +- TERRANIGMA didn't like me returning a random value when it attempted to + read a channel's the current sample byte. +- Hacked in initial support for mode 7 priority-per-pixel - the priority bit + doesn't actually change the priority of the pixel but the two games that I + know of that use the feature look OK. (Winter Extreme Skiing and the + intro of Tiny Toons Adventures). +- Colour addition/subtraction code now uses RGB565 rather than RGB555 + calculations - helps a little with the loss of the bottom bit of SNES + colour data. +- DSP1 emulation started - nothing works yet. +1.02 +- Switched to adding back drop colour rather than fixed colour when + sub-screen addition is enabled but there's nothing on the sub-screen. + Uniracers seems to need it. - DISABLED it again. Causes problems for + other ROMs and Uniracers itself on later screens. +- Fixed XOR window logic combination mode and area inversion code, now + Uniracers works correctly. +- Oops, if colour window and half colour addition/subtraction were both + switched on, area outside colour window was still being halved, it shouldn't. + Hacky fix at the moment until I implement the correct fix. +- Fixed several bugs with the mosaic effect and 16x16 tiles and a few + possible background scroll offset bugs and the mosaic effect. +- Optimised the sound sample generation code for cases when the SNES + sample playback frequency was higher than the sound card playback rate. +- Fixed possible click sound when a sample was first started to be played. +1.01 +- Corrected scan-line count for PAL games - should be 312 lines verses 262 for + NTSC. Was causing slow music on PAL games. +- Added error correction code to the SPC700 timer update code - the + SPC700 timers are updated using the emulated h-blank handler which is + called every emulated 63.6 microseconds (15.720KHz) but the SPC700 timers + need to be updated at multiples of 8KHz, hence the error. Was causing + music to be played slightly too fast. +- Switched back to using C SPC700 code - the old SPC700 asm code was lacking + several optimisations that the C version had. It also had multiple + speed hack cycle skipping bugs. Plus I hadn't even finished optimising + all the code from the last time I converted the C compiler output. +- Optimised SPC700 memory access routines a little. +- Disabled code that prevented ROMs updating SPC700 timer values while the + timer was running - it seems like it is allowed, even though docs on the + 'net I've seen say its not. +1.0 +- Fixed SuperScope support. +- Added hi-res. option to my DOS port. +- Fixed 4, 6, and 8 button standard PC joystick support. +- Changed some types the source code was using BYTE -> uint8, WORD -> uint16, + DWORD -> uint32 and BOOL -> bool8, types were clashing Windows typedefs + but sizes didn't always match. +0.99 +- 8-bit double height and/or width tile rendering was missing every other + group of 4 pixels - screen pointer advance count was wrong. +- Asm SPC700 emulation was ignoring the Shutdown flag - the result is its + not possible to turn off cycle skipping for the SPC700 emulation. +0.98 +- CPU to ROM address decoding code rewritten - used by Game Genie cheat codes, + orginal code might have been the cause of some Game Genie codes not working. +- Started to remove printf calls and replace them with calls to S9xMessage, + port code can then dicide what to do with message. +0.97 +- Re-enabled decompressed sample caching, still has a possible click problem + but the sound code is a lot faster with it enabled. Added command line option + to disable it if required. +- Added '7' key support to rotate through available controller options, in + the order multi-player5, mouse on #1, mouse on #2, superscope, + standard controller and then back to multi-player5. +- Hi-res. (512x448) support fixed. +- Mouse support completed - Lemmings 2 and Mario Paint working a treat. +- More colour window fixes. +- Fixed freeze game problem when ZSNES SuperFX code is being used - + ZSNES 'FX state was not being saved and restored. +- ZSNES SuperFX asm emulation code plugged in to Snes9x. +0.96 +- Looks like if the colour window is not enabled at all and the colour + window selector is defined to only allow colour effects inside the colour + window, then no effects should be visible. +- Offset-per-tile rendering code didn't support width 64 screen size, which + Chrono Trigger used on its title screen. +- Contra 3 seems to prove that defining the clip window area to be 'outside' + a window that covers the whole screen is not an area with no range. + - No it doesn't. It proves that I shouldn't have initialised the right + window edges to 255! Contra 3 enables clipping windows without first + defining their range. +- Debug frame advance feature was being prevented from forcing the next + frame to be rendered by SyncSpeed which was being called after the + debugger returned to the main loop. +- H-DMA code was allowing ROMs to manually start H-DMA during the v-blank + period, ROMs shouldn't be allowed to do this. +- Asm code would not push the correct CPU status onto the emulated stack if + returning from an NMI immediately triggered an IRQ - fixes Mortal Kombat 1 + and War of the Gems. +- 'd' dump memory debug command was not preserving the CYCLES count. +- C versions of SNES memory access code had same problem as asm code on the DOS + port except it didn't cause a crash just ROMs failed to work correctly. +- Asm i386 code was using signed compares to check for special case memory + areas - it was causing crash problems on the DOS port which was sometimes + returning valid address values with the top bit set - i.e. they seemed + like negative values! +- Changed event reschedule code to always allow h-blank start events, used to + disable them during v-blank period. +- Added code to HDMA when end of visible lines reached. +- Changed register 4212 code not to always return h-blank when in v-blank. +- Clipping fixed colour addition to background area was off by one pixel on + the right-hand edge. +- HDMA: Finally worked out how the real SNES operates when ROMs manual + start H-DMA during the frame - ROMs must set up the H-DMA line count + and address values before H-DMA is started. +- Fixed the asm code to remove all hard-wired structure offsets - one offset + into the IPPU structure was wrong in the code because the structure had + changed size. +- Added colour window support and allowed graphic window settings to be + different on the main screen and sub screen, just like a real SNES. +- SuperFX LJMP instruction had bank and address values swapped. +- Fixed possible memory overwrite problem because OBJList array was one + element too short. +- Added AND multi-graphic window combo support. +- ROM image memory allocation allocates an extra 32K of RAM, then moves the + pointer forward by that amount - stops the SuperFX emulation from accessing + unallocated memory, possibly causing a crash. +- SuperFX emulation now stores sign and zero flags in separate variables so + the MERGE instruction can set flags correctly. +- Added 65c816 instruction skipping to i386 asm code when 65c816 waiting in + a simple loop for some 'event' to happen e.g. end of frame NMI. +- Finally fixed the APU instruction skipping problem with the i386 asm + code when the WAI instruction is used - caused slow music on some ROMs. +- Offset-per-tile modes don't seem to support screen size - Mario All Stars + Super Mario 2 requires this on title screen. Doesn't seem to effect + Tetris Attack or Puzzle Bobble. +- Changed SNES select and start keys from shift and control to space and + enter - allows shift-fn key to save game positions without the SNES ROM + also getting a select joypad button press. +- Multiplayer5 support for controllers 3+ was broken for ROMs that used + automatic hardware joypad reading rather than reading joypads serially. +- ResetPPU was not clearing tile caches and marking OBJ as need recomputing. +- Cached OBJ positions and sizes were not being recomputed if ROM changed + global OBJ sizes during frame. +- Fixed brightness multiplication problem on 16-bit code for green. +- SPC700 emulation now uses one variable to store ZERO and NEGATIVE flags. +- SPC700 emulation now only increments PC once at end of instruction. +- New ROM type and interleaved detection code. +- Reading sound DSP register ENDX also clears the value. The docs on the + 'net said that only writing to the register cleared its value. Fixes + sound in Zoop. +- Fixed mode 4 colour palette problem on background #2 in tile-based graphics + code. +- Fixed graphics mode 4, offset-per-tile support. Only one set of offset data + that is switchable between horizontal and vertical, unlike modes 2 and 6 + which allow separate horizontal and vertical offsets per tile. +- Modified the APU timer code again, if the timer is enabled, a write to the + timer target register is only allowed if a value hasn't been written yet. + Fixed Donkey Kong Country 1 and Earth Worm Jim 1 & 2. +- Attack rate of 0ms changed from 1ms back to 0ms because of a group of ROMs + that change from attack mode to decay mode in real-time. Will change back + when I've added better SPC700 CPU and sound generation sync code. +- Added support for ROMs set a new sound timer value while the timer is + enabled (EWJ 1 & 2). +- Added support for ROMs that read the sound envelope height (MK1, MK2, etc). +- ROMs writing to the H-DMA enable register during visible scan-lines were + restarting H-DMA for that frame causing random screen effect corruption. +- Echo feedback seems to be after the FIR filter, not before as a diagram I've + seen suggests. +- Sound pitch modulation added. +- Memory access routines changed to pass a single 24-bit address rather than + the previous separate 8-bit bank and 16-bit address parameters. +0.3 +- Updates to A-Bus address during a frame must not update H-DMA address. + Fixes Actraiser 2 and Pacman 2. +- Removed sound volume mangling - with echo support enabled it doesn't seem to + be required. +- Attack rate of 0ms changed to 1ms to help prevent click sound with sudden + start of a sample playing. +- Sample caching of samples that looped using part of the original sample + created a click on the sound output. Caching disabled for the moment. Would + require 512K of cache RAM to fix sample caching. +- Colour addition/subtraction support added - but still a little buggy in + places and very slow. +- 16-bit colour support added. +- Sustain sound volume was not being set if a sample using ADSR was started + with both the attack rate and decay rate set to zero - resulted in missing + sound samples on with some games. +- Sound echo support added. +- Sound channel mixing code was not completely clearing a channel's sound + buffer when a channel finished playing a sample. +- Sound mixing code rewritten to use one buffer, rather than writing each + channel into a separate buffer then combining them into one buffer. +- Memory access routines rewritten to use an 8K block lookup table rather than + dedicated code for each ROM memory map - it was getting difficult to support + the new types of SNES ROM memory maps becoming apparent. +- Sound sample decoding wasn't decoding sound samples correctly if a + previously cached sample was only partially overwritten by the ROM as + opposed to being completely replaced. +- Sound sample decoding wasn't clipping generated sample values correctly. +- Changed H-DMA to start in the current frame only if enable register is + written to during v-blank, h-blank or while the screen is blanked. +- The SPC700 seems to start executing instructions before the 65c816 - + shorter reset pulse? (NO - forgot the SPC700 executes instructions while DMA + is taking place). +- ROMs that reset the H-IRQ position so another IRQ would be triggered on the + same scan-line where not supported - Super Off-Road: The Baj needs it. +- $4212 bit 7 needs to go high at the end of h-blank at line 224 not at the + start of h-blank - Bubsy needs it. +- Sample decoding routine could write to memory outside sample cache area if + address of block to decode was greater than $0x10000 - 9. +- Walking mario can be seen on map screen of MarioWorld - needed sprite + priority rotation working. ROM sets bit 7 of $2103 then sets rotation in + $2102. Reset rotation at start of v-blank not at end. +0.24 +- Fixed reading of DMA register values - now Ms Pacman works. +- Saved sprite memory address being restored on the wrong scan-line - caused + corrupt sprites on at least one game (GANBARE GOEMON 2). +- Screen colour palette not being updated if ROM only wrote to low byte of + palette register. +- Possible memory corruption fixed if a ROM tried to write to an invalid + sprite address via PPU registers. +- X11 port support quick load and save by pressing function keys to load or + shift + function keys to save. +0.23 +- Added option to disable graphic window effects - T2: The Arcade Game doesn't + seem to like them. +- Mode 7 "outside screen area" register interpretation fixed - now the + Actraiser map screen looks a lot better. +- Old DMA code hack for Battle Toads: Double Dragon removed as it was no + longer required and it was causing problems for Ys III. +- Lowered max volume level of 16-bit sound mixing code to help with sound + clipping problems is lots of SNES sound channels are playing. +0.22 +- Crash bug fixed in mode 7 graphics windows code +0.21 +- Fixed a noise channel volume bug - noise waveform was getting clipped. +- Fixed 24bit X Window System server support on the Solaris port. +- Sprites in priority level 1 on mode 7 were being drawn incorrectly behind + graphics screen. +- BG 3 priority 1 tiles sometimes not drawn dependent on the $2105 bit 3 + setting. +- Added graphic window support the tile redraw code. +- Added mosaic support to tile redraw code. +- Tile redraw code was drawing one line too many on screen-splits. +- Tile-based redraw code made more intelligent about when a background should + be displayed or not. +- Added wrap within bank support to large DMAs just to support Rock 'n' Roll + racing. +0.20 +- DMA routines added lots of special cases and removed most calls to GetByte, + using a pointer instead. +- Multiple using PPU registers is now only computed when first byte of result + is actually read. +- Sound enabled by default if compiled without DEBUGGER defined. +- Tile redraw method made the default. +- Fixed CPU_SHUTDOWN so SPC700 continues to execute even if main CPU is + "skipping" cycles waiting for an event to happen. +- More command line options added. +- Default cycles-per-scan-line to execute lowered to 90% from 100%. +- +/- keys now work even if auto-frame rate adjust was enabled. +- SPC700 emulation partially rewritten in assembler. +- Asm 65c816 code change to use same speed up techniques as the C++ code. +- Minor speed tweaks to the sound decoding and mixing code. +- C++ SPC700 emulation changed to use same method as 65c816 emulation for + computing and storing emulated CPU flags. +- Mode 7 code rewritten and several scrolling offset bugs fixed. +- Lo-ROM S-RAM memory map bug fixed - now Uniracers works. +- Multiple speed ups and changes to the tile and line-based redraw code. +- Tile and line redraw code changed to cache converted tiles between frames. +- Variable cycle length timing made compile-tile switchable. +- C++ 65c816 emulation changed to use several opcode jump tables to avoid + a register size comparison test on most emulated instructions. +- C++ 65c816 emulation changed how is computes and stores emulated CPU flags. +- Fixed high frequency sound playback bug - the sample rate calculation was + blowing the range of an unsigned long. +- Fixed V-RAM reading so DKC3, Addams Family, Aladdin and Pacman all work. +- Fixed sound code so ROMs can change from ADSR mode to decrease mode - fixes + lots of ROMs. +0.12 released +- Added dynamic speed regulation. +- TCALL vector calculation change from n to 15 - n. +- Fixed crash bug if ROM writes to sound DSP register numbers greater than + 127. +- Fixed DOS memory locked for interrupt code. +- Added long name versions of command line switches. +- Added command line switch for SPC700_SHUTDOWN code and WAI cycle skipping + code. +0.1 released +- All DOS memory is now locked from being swapped. +- Fixed DOS port keyboard polling code - could get confused if a keyboard + interrupt happened while keys were being checked. +- SPC700 ADC instruction never cleared Overflow or Carry flags! +- Changed selection of playback speeds for Solaris port. +- Sample caching code was broken - cached samples were never used. +- Added code speed ups for ROMs that use a lot of DMA to VRAM. +- More cpu code asm speed up. +- Fixed 16x16 size tiles on tile-based redraw code. +- Fixed sound gain-mode increase and decrease volume envelopes. +- Added code to support ROMs that reuse sprites in the same frame. +- Fixed processing of negative volume levels. +- Fixed SPC700 EOR1 instruction. +- Added SPC700 shutdown code to stop executing SPC700 instructions if in + a tight loop waiting for a timer or for the 65C816 to respond. +- DOS playback rate was being forced to 16KHz by Allegro - fixed. +- Fixed bug in SPC700 MOV1 C,bit, address. +- Fixed a off-by-one loop sample pointer bug in MixSamples. +- Added command line flags for cached-tile based drawing and sub-screen + background layers priority swapping. +- NOPE, got encoding of the OR1/EOR1,AND1 range of correct originally - + got duff information from an "SPC700" programmer. +- More SPC700 fixes: got the encoding of the OR1/EOR1,AND1 range of + instructions wrong - I guessed wrong originally. +- Sample looping bug fix on mono sound mixing code. +- Sound pitch value no-longer clipped to 14 bits - apparently FF3 needs this. +- Followed Paradox's suggestion and changed graphics code to place sub-screen + background layers below main-screen background layers. Helps lots of games + that use sub-screen addition/subtraction - now you don't have to toggle + background layers on and off so often just to see hidden text, characters, + or maps, etc. Made it switchable. + Acts as a good intermediate solution until sub-screen addition/subtraction + is actually implemented. +- Modified sound skipper code to return random values when ROM is stuck + waiting for the SPC700 CPU to respond - helps several ROMs that previously + don't work with the currently selection of APU skippers. +- Improved sound mixing code so volume is not attenuated so much, giving + better results on 8bit sound cards. +- Changed the frequency at which the joystick polling routine is called - now + called every-other frame rather than every 3rd frame. +- Recompiled Linux and DOS ports with the Pentium optimising version of gcc - + gives a few percent speed increase. +- Changed V-RAM increment count from 64 to 128 - apparently Final Fantasy 3 + needs this as well. +- Fixed sprite priority bug with Mode 7 - apparently Final Fantasy 3 needs + this. +- Fixed a screen clipping problem with the S-VGA mode. +- Fixed bug that had crept in with -m 2 S-VGA mode (Linux version). +- Fixed S-VGA Linux version with sound enabled. +- The SPC700 ADC (X),(Y) instruction was broken - with all these SPC700 fixes + now many more ROMs work with sound enabled. +- The SPC700 Pop PSW instruction was not resetting the direct page location. +- The SPC700 instruction MOV A,[DP+X] was incorrectly doing a MOV A,DP+X. +- Got the SPC700 SETx and CLRx instruction encoding swapped around. +- Fixed #define problem that was stopping DOS snapshot saving from working. +0.72 released +- Fixed the DOS filename handling - old Unix code was screwing up with ROM + filenames that contained backslashes (\) - the ROM would load but S-RAM + loading and saving would fail and the default filename for snapshots + wouldn't work. +- This time really fixed Allegro library keyboard handling (DOS port); it + was missing key some presses/releases (was stopping Chrono Trigger + Left + Right + A button combo from working). +- Added code to automatically remove headers off S-RAM save files with + 512 byte headers. +- 32Mbit ROMs in interleaved format are now automatically detected and + converted. +- Added -ss 3 sound skip method support to the asm version - now NBA Live '96 + works again. +- Added support for multi-part ROM images. +0.71 released +- Made libgz.so statically linked (again) on Linux port - sorry. +- Made writing to $4200 also clear any pending IRQs. This finally allows + Battle Toads: Double Dragon, Spawn and Sieken 3 all the work with the same + IRQ logic (but Sieken 3 still gets stuck in sound download code). +- Fixed a H-DMA wobble bug - some frames could randomly miss a line of + H-DMA causing the F-Zero screen to wobble, and slight text character + corruption on games like DKC3. +- Interleaved format ROM images are now swapped in-place, without the need + for a temp 4Mb buffer (saves lots of disk swapping on a 16Mb Windows 95 + machine). +0.7 released +- Fixed Allegro library keyboard handling (DOS port); it was missing key + some presses/releases. +- DOS port had a different MAX_PATH value which moved the location of the + SRAM size variable when using the asm CPU emulation core. This, in turn, + caused the SRAM emulation to fail on the DOS port. Donkey Kong County 2 & 3 + were reporting a ROM copier was connected to the SNES and refused to run. +- Fixed assembler version of XCE - it was always leaving the carry flag + clear - caused Killer Instinct and Super Punchout to think a ROM + copier was fitted to the SNES and they all refused to run. +- Fixed assembler versions of MVN/MVP - they weren't setting the data bank + register to the destination bank of the instruction. +- Fixed joystick detection on MS-DOS port - a single 2 or 4 button joystick in + port 1 was being ignored if a second joystick was not present in port 2. +- Fixed an uninitialised variable in graphics code - was causing random + missing scan lines on Mode 7 screens. +- Joysticks now scanned every 3rd frame (joystick scanning is slow in the PC). +- Double-whoops, Metriod 3 had stopped working in v0.6 - fixed it + (memory map bug). +- Made bit 6 of $4211 set if v-counter == v-timer-position. +- Made reading of $4200 read $4212 instead. +- Adjusted DMA timing to always access ROM memory at slow speed - this seems + to fix Battle Toads. +- Added code to automatically clear pending IRQs when the horizontal line + is no longer equal to the horizontal timer line - this fixes Seiken 3, it + now just gets stuck in the sound CPU wait code - oh well. +- Moved NMI back to its original pre-0.65 behaviour, now Puzzle Bobble works. +- More graphics speed ups - the code to render background tiles with their + priority bits set is only called if there are actual priority-bit tiles. +- Changed default frame skip rate from 1 to 2 - its seems most people don't + bother to read the docs, so I thought I'll help them out a bit! +- Speeded up Mode 7 graphics on games like F-Zero that rewrite the matrix + registers on each scan line using H-DMA. +- Reorganised the graphics code and did a slight speed up - graphics code + will be the next thing to rewrite in assembler. +- Rewrote CPU core in assembler for Intel platforms - gives a very noticeable + speed increase. +- Fixed several problems with the APU sound CPU emulation - its now getting + stable enough to try and implement sound. +- Fixed bug that caused 1 byte of S-RAM to be emulated when ROM didn't + expect any - it was enough to stop Street Fighter 2 and others from + working - thanks Lord ESNES. +- The TXS and TCS instructions shouldn't set the Z and N flags. +- Looks like MVP/MVN instructions should ignore accumulator size - change + code to always use all 16 bits and exit with accumulator set to 0xffff. +- Whoops, accidently left some test code in which was causing the V-BLANK + flag, bit 8 in register $4212, to be miss-calculated. +- Fixed palette in mode 0. +- Speeded up graphics drawing a little by skipping groups of 4 pixels that + were all transparent. +0.65 released +- S-VGA and MS-DOS ports now have a VGA mode command line flag. +- Improved the fading code - should be much more smooth now. +- Fixed second joy-pad support and re-mapped keys and joysticks to actually + make a match between what my docs said and a real SNES (SNES docs I'd + seen were wrong!). +- Fixed a bug in Relative Long CPU addressing mode. +- Ported Snes96 to MS-DOS. +- Snapshot loading and saving no longer uses external gzip binary. +- Added support for registers at $21c2 and $21c3. +- Made reading the software latch for the horizontal and vertical counters also + clear any pending IRQ. +- Added sprite priority rotation. +- Rewrote parts of the graphics routines to fix a sprite-to-sprite priority + bug. +- NMI flag changed again - now back to being reset by reading $4210 but + actual NMI is delayed. +- Made mode 7 background colour 0 transparent - this fixed several sprite + priority problems a few games where having. +- Finally worked out how sprite "Object Name Select" works and emulated it - + this fixes many (if not all) of the corrupted sprites some games + experienced. +- Delayed NMI activation for one instruction to give time for loops that + wait for bit 7 of $4210 to go high. +- Special-cased line count of 128 on H-DMA to mean repeat previous data with + a line count of 128 and not just terminate H-DMA on that channel. +- APU sound CPU emulation added - just need to debug the thing. +- Fixed Overflow flag setting in ADC and SBC instructions - it was never + being set. +- Rewrote how CPU instructions are fetched and how values are pushed and pulled + from the stack - it gave a very large increase in emulation speed. +- H-DMA was being started one scan-line too late. +- Added CG-RAM reading support. +- Added "Full Graphic" V-RAM reading. +- Speeded up C version of CPU emulation quite a bit - could speed it up a + little more before rewriting in assembler. +- Fixed bugs in 16x16 tile drawing on 2bit and 8bit deep screens. +0.6 released +- Speeded up 16x16 tile background rendering by removing a temp tile buffer + it was using. The speed up also fixed a vertical scroll bug. +- Fixed slight window clipping on 16x16 tile backgrounds. +- Added automatic PAL/NTSC mode switching. +- Fixed background and sprites so only visible if on main-screen or + on sub-screen under correct circumstance. +- Fixed lockup bug in DMA. +- Stopped NMI flag from being reset by reading $4210 - was causing a couple + of games to get stuck. +- Whoops, got horizontal and vertical Mode 7 flip bits around the wrong way! +- Fixed MIT shared memory pixmap support for X11 version (it was always turned + off). +- Fixed minor bug - first sprite in priority group was drawn twice. Didn't + cause any visual bugs, it just slowed down redrawing a little. +- Fixed DMA bug - transfer byte count should be 0 after DMA has finished. +- Fixed a scaling bug if width < height. +- Interleaved ROM image support added. +- 16bit and 24bit X11 server support added - with scaling. +- Added window scaling on X11 version. +- Partial clip windows added - the only window overlap option implemented at + the moment is OR, it seems it good enough for all the ROMs I've tested + it with. +- Partial Mosaic effect added (pixels only growing vertically). +- Missing Mode 7 "outside screen area" option added. +- Fixed mode 7 screen wrap "outside screen area" option. +- Used new event processing to finally fix H-IRQ so it triggers at the + correct position on the scan line. +- New event processing added. +- Linux version now statically links libgz.so (sorry). +0.5 released +- Linux S-VGA version changed from using a 320x240 ModeX screen (slow) to a + 256x256 chunky screen (faster) - thanks to Phillip Ezolt (pe28+@andrew.cmu.edu) + for information on how to do this. +- Mode 7 screen flipping added. +- Included Snes97's CPU emulation code into Snes96. Didn't fix any bugs but + slowed down the emulation some what and I couldn't compile it optimised + because it was so large - so I removed it again. +- Added a few extra features available via the keyboard. +- Fixed a H-DMA transfer mode - bad documentation. +- Fixed H-DMA indirect addressing (it was using the wrong CPU memory bank). +- The Linux slow down bug is my crappy laptop enabling battery saving features ! +- Changed graphics code to perform true line-by-line screen updates. +- Fixed sprite drawing bugs. +- Ported Snes97's graphics code to Snes96. +- Fixed memory map for HiROM save RAM area. +- Fixed HiROM memory map - now Killer Instinct and Donkey Kong County work ! +- OK the slow down bug is just actually my laptop trying to save battery + power by slowing the CPU clock! +- The Linux slow down bug shows itself on DOS emulators running under DOSEMU + so it must be a kernel problem (or feature). +- Fixed H-DMA (again) to be complete emulation - all I need now is line-by-line + screen update... +- Fixed DMA to not copy too many bytes if byte count was not a multiple of + the transfer mode quantity (caused corruption on Super Mario World map screen). +- Changed mapping of keyboard to joy-pad buttons and added additional + direction keys for joy-pad one so player one's right hand doesn't have to + obscure player two's keyboard joy-pad buttons. +- Changed joystick button layout to match SNES if using a 6 button joy-pad. +- Changed snapshot format so I can easily use libgz on Linux. +- Added few speed up tweaks that will be lost again when I add line-by-line + screen update. +- First visible scan-line changed from 8 to 1 to match with new docs. +- New SNES information source found; fixed partial H-DMA emulation to include + indirect addressing support. +- Snapshot files are now compressed. +- Compressed ROM images now supported on Linux. +- Snapshot loading and saving added. +- Joystick support for Linux added. One 2, 4 or 6 button joystick, or two 2 + button joysticks supported (PC hardware limitation). +- SVGA full screen support added for Linux. Still has the X11 slow down bug so + can't blame the X11 server any more! Must be a kernel bug or a very odd + emulator bug. +- Added emulation of two joy-pads on the PC/Sun keyboard. +- Removed -i command line flag as it is no longer used. -h value range has also + changed: now 1 - 100 (percentage). +- Actuate cycle counting rather than instruction counting now added including + fast and slow ROM timing - should give much better timing information when + line-by-line screen update added. +- Bug fixed old-style joy-pad access used by some ROMs - Mario All Stars still + gives problems if enabled and I don't know why; but at least Super Bomberman + now works ! +- Looks like if both horizontal and vertical IRQ are enabled then IRQ should + only be triggered once per frame and not once per scan line - looking at the + IRQ handler of a couple of ROMs seems to confirm this. +- Added initial cycle counting - not accurate enough for some ROMs though. +- Finally worked out how the odd VRAM address increments should work but only + found one ROM, so far, that actually uses it. +- Debugged the odd slow down problem with the Linux port - it seems to be a + bug in the X Window System server - starve the X server of keyboard presses + or mouse clicks or movement and the X server slows down, slowing down the + emulator with it ! +0.4 released +- Fixed sprite vertical clipping at top of screen. +- No need to invert the Mode 7 transformation matrix before use - the + ROM coder already had to! +- Fixed Mode 7 scrolling offset when using special effects. +- Added Mode 7 rotation, enlargement and reduction emulation. +- DMA shouldn't zero the byte count value after a DMA has completed. +- Added DMA reading (Addams Family was using it) +- Fixed V-RAM read function - returned data should lag behind the V-RAM + address by one byte/word. +- Added mode 7 graphics only. +0.3 released +- Speeded up the main CPU loop a bit. +- Add more command line options: + -f (default 1) + -i (default 32768) + -h (default 45, some games allow a lower + setting resulting in a increased + emulated frame rate) + -t enable CPU tracing + -ss (default 0, more methods to be added) + -H disable H-DMA emulation + -F Force Hi-ROM memory map +- Modified planar to chunky conversion to use look up tables. +- But now Mario All Stars won't start. Made emulation of $4016 optional with + -o command line switch. +- Thanks to Carlos (calb) of ESNES fame, I've added correct $4016 & $4017 + joy-pad register processing - now several more ROMs will start once a + button is pressed and can be controlled. +- DMA wasn't updating DMA registers with the final CPU address used after the + DMA had completed (caused sprite and background corruption with some ROMs). + Still suspect another DMA side effect isn't being emulated correctly though. +- Fixed setting of CPU overflow flag in ADC and SBC instructions in decimal + mode. +- Fixed MVP/MVN CPU instructions to leave X and Y values correct at end of + loop - several more ROMs now work. Still don't know if MVP/MVN instructions + should ignore the accumulator size flag or not. +- Rewrote background drawing code - gives a large increase in speed. +- Flag to only update X Windows colour palette when necessary was missing a + case - caused some ROMs to start with a black screen. +- Code to only update background tiles when changed wasn't working so I + disabled it. +- CPU WAI instruction needed to trigger on hardware IRQ even when interrupt + enable flag was false. +- DMA was not transferring 65536 bytes when byte count was 0. +- Fixed matrix 16bit x 8bit multiplication (old debug code was causing junk + value to be returned). +- Fixed Makefile so version.h header file change recompiles file that shows + version number in window title. +- Added more reporting of used but unimplemented missing hardware features to + debug command. +- New ROM loading code from Jerremy included, can now cope with ROM images + with no 512 byte header. +- Speeded up emulated memory access a little bit. +0.2 released +- Added matrix 16bit x 8bit multiplication for Super Off-Road Racer. +- Added initial H-DMA emulation - visual effects using it will not be seen + correctly until screen is updated line-by-line rather than the whole screen + at end-of-frame. +- Fixed horizontal sprite clipping (vertical clipping still has a problem). +- Integrated large sprite bug fixes and new background drawing code from + Jerremy. +- Fixed large size per-sprite flag; always stayed true after sprite size was + changed to large. +- Rewrote the planar to chunky pixel conversion routines (still need more + work). +- Made registers $4016 & $4017 always return $ff - lots of ROMs that previously + wouldn't go beyond the title screen thought old-style joy-pads were + connected and were waiting for the user to press a button on them. +- Frame skip rate now set to 1 instead of 5 on my P166 laptop! +- Fixed NMI v-blank flag being incorrect set, caused some ROMs to lock. +- X keyboard autorepeat now switched off when emulator has keyboard focus. +- Added number key options to toggle backgrounds 1 to 4 and objs (sprites) on + and off. +- Fixed sprite clipping problems at edge of left hand side of screen. +- Corrected Hi-ROM memory map (I think) (no I didn't) +- Fixed most of the sprite-to-sprite priority problems. +- Added sprite debug command, 'S'. +- Added a debug command to show what missing hardware features a ROM was using. +- Added horizontal and vertical beam position IRQ - horizontal always triggers + at start of line at the moment. +- Fixed SBC instruction to set carry flag the correct way around. +Initial release 0.1 +- Ported Windows 95 version of Snes96 to Linux on a PC and Solaris on a + SparcStation. +- Corrected work RAM memory map. diff --git a/docs/control-inputs.txt b/docs/control-inputs.txt new file mode 100644 index 00000000..4faddc33 --- /dev/null +++ b/docs/control-inputs.txt @@ -0,0 +1,68 @@ +Control input names are completely defined by the individual ports. This +document is intended to collect the rules for all ports. + +The various meta-characters in the rules are: + # - A number. The range is detemined by the context + ## - A two-digit number (i.e. with leading zeros) + [...] - Something optional + (...) - For grouping with | + | - "or", choose one of the options. + <...> - A named field + {...} - A list of possible values. Multiple values may be used, but they + must be in the order listed and joined with +-signs. + "" - 'ditto', used to indicate the same list as the above line. + +================================================================================ +Unix +================================================================================ + +Input names: + Jxx:Axis# Axis # on joystick xx. Axis0 may be + Up/Down, and Axis1 Left/Right. + Jxx:B# Button # on joystick xx. + + Jxx:{M1,M2,M3,M4,M5,M6,M7,M8}+B# Used with the 'JSx Meta#' port + Jxx:{M1,M2,M3,M4,M5,M6,M7,M8}+Axis# command. + + Jxx:X+B# Used to 'define' this key for all + Jxx:X+Axis# combinations of JS Meta. + +Port-specific Commands: + JSx Meta# Used to specify modifier keys (i.e. Shift, Control) to + affect the specified joystick. For example, you could + map J00:B20 to "JS0 Meta1", then map J00:B0 to "Joypad1 + A" and J00:M1+B0 to "Joypad1 Turbo A". '#' may range + from 1-8. + + Jsx ToggleMeta# Like the above, but toggles the meta-state each time + the button is pressed. + +================================================================================ +Unix/X11 +================================================================================ + +Keyboard Input: + + Note that only one keyboard (K00) is currently supported. If you know how + to support multiple keyboards (and can test it!), feel free to fix x11.cpp + and delete this note. + + Keyboard modifiers are S=Shift, C=Control, A=Alt, M=Meta. Combine them in + order, i.e. all 4 would be "SCAM". + + Kxx: Key names are as recognized by XStringToKeysym. + Kxx:+ Note however that keys are mapped by keycode, + so for example on a standard qwerty keyboard + "K00:colon" and "K00:semicolon" are identical. + +Pointer Input: + + Note that only one mouse (M00) is currently supported. If you know how to + support multiple pointing devices (and can test it!), feel free to fix + x11.cpp and delete this note. + + Mxx:Pointer Map the mouse pointer. If someone has a mouse + Mxx:Pointer# device with multiple pointers, fix x11.cpp to + report that and you can use the second syntax. + + Mxx:B# Mouse buttons. diff --git a/docs/controls.txt b/docs/controls.txt new file mode 100644 index 00000000..703cd33d --- /dev/null +++ b/docs/controls.txt @@ -0,0 +1,97 @@ +This lists the available commands, excluding the ones you get back from +S9xGetAllSnes9xCommands(). The various meta-characters are: + # - A number. The range is detemined by the context + ## - A two-digit number (i.e. with leading zeros) + [...] - Something optional + (...) - For grouping with | + | - "or", choose one of the options. + <...> - A named field + {...} - A list of possible values. Multiple values may be used, but they + must be in the order listed and joined with +-signs. + "" - 'ditto', used to indicate the same list as the above line. + +Speeds are: Var, Slow, Med, and Fast. 'Var' starts slow and speeds up as the +button is held. + +Axes are: Left/Right, Right/Left, Up/Down, Down/Up, Y/A, A/Y, X/B, B/X, L/R, +and R/L. Negative is listed first (i.e. "Y/A" means negative deflection is +towards Y, while "A/Y" means negative deflection is towards A). + +AxisToPointer, ButtonToPointer, and AxisToButtons allow for translating +between different input types. There are 8 'pointers' with IDs +PseudoPointerBase+0 to PseudoPointerBase+7, and 256 'buttons' with IDs +PseudoButtonBase+0 to PseudoButtonBase+255. So for example, +"AxisToButtons 0/255 T=50%" would take the axis data, and do +S9xReportButton(PseudoButtonBase+0,1) when said axis goes past 50% in the +negative direction and S9xReportButton(PseudoButtonBase+255,1) when it goes +over 50% deflection in the positive direction. Similarly, it will do +S9xReportButton(...,0) when the deflection drops under 50% in either +direction. "ButtonToPointer 1u Slow" would move the pointer with ID +PseudoPointerBase+0 up one pixel per frame as long as the button is pressed +(reporting this change at the end of each frame). + +--------------- +Button Commands +--------------- + +Joypad# {Up, Down, Left, Right, A, B, X, Y, L, R, Start, Select} +Joypad# Turbo "" +Joypad# Sticky "" +Joypad# StickyTurbo "" +Joypad# ToggleTurbo "" +Joypad# ToggleSticky "" +Joypad# ToggleStickyTurbo "" + +Mouse# (L|R|LR) + +Superscope AimOffscreen +Superscope {Fire, Cursor, ToggleTurbo, Pause} +Superscope AimOffscreen "" + +Justifier# AimOffscreen +Justifier# {Trigger, Start} +Justifier# AimOffscreen "" + +ButtonToPointer #[u|d][l|r] ; NOTE: "# " is invalid + +------------- +Axis Commands +------------- + +Joypad# Axis T=#% ; T = 0.1 to 100 by tenths +AxisToButtons #/# T=#% ; neg then pos, range 0-255, T as above +AxisToPointer #(h|v) [-] ; NOTE: '-' inverts the axis + +---------------- +Pointer Commands +---------------- + +Pointer {Mouse1, Mouse2, Superscope, Justifier1, Justifier2} + +------ +Multis +------ + +Multis are a type of button command. The basic format of a multi is "{...}", +where the '...' consists of 1 or more valid non-multi button command +strings. The braces are literal, not metacharacters. Subcommands separated +by commas are executed one after the next. Semicolons skip one frame before +continuing subcommand execution. Semicolons may be repeated. When the multi +button is pressed, each subcommand is 'pressed', and when the multi button +is released each subcommand is 'released'. + +There are also press-only multis, defined as "+{...}". These act just like +regular multis, with two differences: the multi is only run when you press +the button (release isignored), and each subcommand must be prefixed with +'+' or '-' to indicate whether the the subcommand should be pressed or +released. + +For example: {Joypad1 A,Joypad2 A;Joypad3 A;;;;;QuickSave000} + This presses (or releases) A on pads 1 and 2, then waits one frame, then + presses A on pad 3, then waits 5 frames, then saves to snapshot 0 (on press + only). + +You may access the multi number in the returned s9xcommand_t structure as +cmd.button.multi_idx. This may be used to assign the same multi to multiple +buttons: + MULTI# ; NOTE: that's a literal octothorpe diff --git a/docs/gpl-2.0.txt b/docs/gpl-2.0.txt new file mode 100644 index 00000000..d511905c --- /dev/null +++ b/docs/gpl-2.0.txt @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/docs/lgpl-2.1.txt b/docs/lgpl-2.1.txt new file mode 100644 index 00000000..602bfc94 --- /dev/null +++ b/docs/lgpl-2.1.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/docs/porting.html b/docs/porting.html new file mode 100644 index 00000000..63d80376 --- /dev/null +++ b/docs/porting.html @@ -0,0 +1,390 @@ + + + + + + + + Porting Snes9x + + +

How to Port Snes9x to a New Platform

+
+ Version: 1.52
+ (c) Copyright 1998 Gary Henderson +
+

Introduction

+

+ This is brief description of the steps to port Snes9x to the new platform. It describes what code you have to write and what functions exist that you can make use of. It also gives some insights as to how Snes9x actually works, although that will be subject of another document yet to be written. +

+

System Requirements

+

+ A C++ compiler. For the most part Snes9x really isn't written in C++, it just uses the C++ compiler as a “better C” compiler to get inline functions and so on. GCC is good for compiling Snes9x (http://gcc.gnu.org/). +

+

+ A fast CPU. SNES emulation is very compute intensive; two, or sometimes three CPUs to emulate, an 8-channel 16-bit stereo sound digital signal processor with real-time sample decompression, filter and echo effects, two custom graphics processor chips that can produce transparency, scaling, rotation and window effects in 32768 colors, and finally hardware DMA all take their toll on the host CPU. +

+

+ Enough RAM. Snes9x uses 8MB to load SNES ROM images and several MB for emulating sound, graphics, custom chips, and so on. +

+

+ A 16-bit color (two bytes per pixel) or deeper display, at least 512*478 pixels in resolution. Pixel format conversion may be required before you place the rendered SNES screen on to the display. +

+

+ Sound output requires spooling 8-bit or 16-bit, mono or stereo digital sound data to the host sound system. Some ports can use interrupts or callbacks from the sound system to know when more sound data is required, most other ports have to periodically poll the host sound system to see if more data is required; if it is then the sound mixing code is called to fill the sound buffer with SNES sound data, which then can be passed on to the host sound system. Sound data is generated as an array of bytes (uint8) for 8-bit sound or shorts (int16) for 16-bit data. Stereo sound data generates twice as many samples, with each channel's samples interleaved, first left's then right's. +

+

+ For the user to be able to control and play SNES games, some form of input device is required, a joypad or keyboard, for example. The real SNES can have 2 eight-button digital joypads connected to it or 5 joypads when an optional multi-player adaptor is connected, although most games only require a single joypad. Access to all eight buttons and the direction pad, of course, are usually required by most games. Snes9x does emulate the multi-player adaptor hardware, if you were wondering, but its still up to you to provide the emulation of the individual joypads. +

+

+ The real SNES also has a SNES mouse, Super Scope and Justifier (light-gun) available as optional extras. Snes9x can emulate all of these using some form of pointing device, usually the host system's mouse. +

+

+ Some SNES game cartridges contains a small amount of extra RAM and a battery, so ROMs could save a player's progress through a game for games that takes many hours to play from start to finish. Snes9x simulates this S-RAM by saving the contents of the area of memory occupied by the S-RAM into a file then automatically restoring it again the next time the user plays the same game. If the hardware you're porting to doesn't have a storage media available then you could be in trouble. +

+

+ Snes9x also implements freeze-game files which can record the state of the SNES hardware and RAM at a particular point in time and can restore it to that exact state at a later date - the result is that users can save a game at any point, not just at save-game or password points provided by the original game coders. Each freeze file is over 400k in size. To help save disk space, Snes9x can be compiled with zlib (http://www.zlib.net/), which is used to GZIP compress the freeze files, reducing the size to typically below 100k. zlib is also used to load GZIP or ZIP compressed ROM images. Additionally, Snes9x supports JMA archives compressed with NSRT (http://nsrt.edgeemu.com/). +

+

Compile-Time Options

+

DEBUGGER

+

+ Enables extra code to assist you in debugging SNES ROMs. The debugger has only ever been a quick-hack and user-interface to debugger facilities is virtually non-existent. Most of the debugger information is output via stdout and enabling the debugger slows the whole emulator down slightly. However, the debugger options available are very powerful; you could use it to help get your port working. You probably still want to ship the finished version with the debugger disabled, it will only confuse non-technical users. +

+

RIGHTSHIFT_IS_SAR

+

+ Define this if your compiler uses shift right arithmetic for signed values. For example, GCC and Visual C++ use shift right arithmetic. +

+

CPU_SHUTDOWN

+

+ This is a speed-up hack. When defined and if Settings.ShutdownMaster is true, Snes9x starts watching for when CPU is in a simply loop waiting for a known event to happen - like the end of the current scanline. If Snes9x spots CPU in such a loop, it simply skips the emulation of its instructions until the event happens. It can be a big win with lots of SNES games, but will break a small number of games. In this case, set Settings.ShutdownMaster to false before you load a ROM image. Note that this hack is forcibly disabled in some games. See Memory.ApplyROMFixes function for the list of such games. +

+

CORRECT_VRAM_READS

+

+ You must define this. It allows correct VRAM reads. +

+

ZLIB / UNZIP_SUPPORT / JMA_SUPPORT

+

+ Define these if you want to support GZIP/ZIP/JMA compressed ROM images and GZIP compressed freeze-game files. +

+

ZSNES_FX / ZSNES_C4

+

+ Define these if your CPU is x86 compatible and you're going to use the ZSNES Super FX and C4 assembler codes. +

+

USE_OPENGL

+

+ Define this and set Settings.OpenGLEnable to true, then you'll get the rendered SNES image as one OpenGL texture. +

+

Typical Options Common for Most Platforms

+

+ ZLIB
+ UNZIP_SUPPORT
+ JMA_SUPPORT
+ CPU_SHUTDOWN
+ RIGHTSHIFT_IS_SAR
+ CORRECT_VRAM_READS +

+

Editing port.h

+

+ You may need to edit port.h to fit Snes9x to your system. +

+

+ If the byte ordering of your system is least significant byte first, make sure LSB_FIRST is defined, otherwise make sure it's not defined. +

+

+ You'll need to make sure what pixel format your system uses for 16-bit colors (RGB565, RGB555, BGR565 or BGR555), and if it's not RGB565, define PIXEL_FORMAT to it so that Snes9x will use it to render the SNES screen. For example, Windows uses RGB565, Mac OS X uses RGB555. If your system supports more than one pixel format, you can define GFX_MULTI_FORMAT and change Snes9x's pixel format dynamically by calling S9xSetRenderPixelFormat function. If your system is 24 or 32-bit only, then don't define anything; instead write a conversion routine that will take a complete rendered 16-bit SNES screen in RGB565 format and convert to the format required to be displayed on your system. +

+

+ port.h also typedefs some types; uint8 for an unsigned 8-bit quantity, uint16 for an unsigned 16-bit quantity, uint32 for a 32-bit unsigned quantity and bool8 for a true/false type. Signed versions are also typedef'ed. +

+

Controllers Management

+

+ Read controls.h, crosshair.h, controls.txt and control-inputs.txt for details. This section is the minimal explanation to get the SNES controls workable. +

+

+ The real SNES allows several different types of devices to be plugged into the game controller ports. The devices Snes9x emulates are a joypad, multi-player adaptor known as the Multi Player 5 or Multi Tap (allowing a further 4 joypads to be plugged in), a 2-button mouse, a light gun known as the Super Scope, and a light gun known as the Justifier. +

+

+ In your initialization code, call S9xUnmapAllControl function. +

+

+ Map any IDs to each SNES controller's buttons and pointers. (ID 249-255 are reserved). +

+

+ Typically, use S9xMapPointer function for the pointer of the SNES mouse, Super Scope and Justifier, S9xMapButton function for other buttons. Set poll to false for the joypad buttons, true for the other buttons and pointers. +

+

+ S9xMapButton(k1P_A_Button, s9xcommand_t cmd = S9xGetCommandT("Joypad1 A"), false); +

+

+ In your main emulation loop, after S9xMainLoop function is called, check your system's keyboard/joypad, and call S9xReportButton function to report the states of the SNES joypad buttons to Snes9x. +

+

+ void MyMainLoop (void)
+ {
+     S9xMainLoop();
+     MyReportButttons();
+ }
+

+

+ void MyReportButtons (void)
+ {
+     S9xReportButton(k1P_A_Button, (key_is_pressed ? true : false));
+ }
+

+

+ Prepare your S9xPollButton and S9xPollPointer function to reply Snes9x's request for other buttons/cursors states. +

+

+ Call S9xSetController function. It connects each input device to each SNES input port.
+ Here's typical controller settings that is used by the real SNES games: +

+

Joypad
+ S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
+ S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);
+

+

Mouse (port 1)
+ S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0);
+ S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);
+

+

Mouse (port 2)
+ S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
+ S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0);
+

+

Super Scope
+ S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
+ S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0);
+

+

Multi Player 5
+ S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
+ S9xSetController(1, CTL_MP5, 1, 2, 3, 4);
+

+

Justifier
+ S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
+ S9xSetController(1, CTL_JUSTIFIER, 0, 0, 0, 0);
+

+

Justifier (2 players)
+ S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
+ S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0);
+

+

Existing Interface Functions

+

bool8 Memory.Init (void)

+

+ Allocates and initializes several major lumps of memory, for example the SNES ROM and RAM arrays, tile cache arrays, etc. Returns false if memory allocation fails. +

+

void Memory.Deinit (void)

+

+ Deallocates the memory allocations made by Memory.Init function. +

+

bool8 S9xGraphicsInit (void)

+

+ Allocates and initializes several lookup tables used to speed up SNES graphics rendering. Call after you have initialized the GFX.Screen and GFX.Pitch values. Returns false if memory allocation fails. +

+

void S9xGraphicsDeinit (void)

+

+ Deallocates the memory allocations made by S9xGraphicsInit function. +

+

bool8 S9xInitAPU (void)

+

+ Allocates and initializes several arrays used by the sound CPU and sound generation code. Returns false if memory allocation fails. +

+

void S9xDeinitAPU (void)

+

+ Deallocates the allocations made by S9xInitAPU function. +

+

bool8 S9xInitSound (int buffer_ms, int lag_ms)

+

+ Allocates memory for mixing and queueing SNES sound data, does more sound code initialization and opens the host system's sound device by calling S9xOpenSoundDevice, a function you must provide. Before calling this function you must set up Settings.SoundSync, Settings.SixteenBitSound, Settings.SoundPlaybackRate, Settings.SoundInputRate (see section below) and Settings.Stereo.
+ buffer_ms, given in milliseconds, is the memory buffer size for queueing sound data. lag_ms is allowable latency between when a sample is queued and when it is pulled in S9xMixSamples. Set lag_ms to zero if you have your own latency handling code in your port. +

+

void S9xReset (void)

+

+ Resets the SNES emulated hardware back to the state it was in at “switch-on” except the S-RAM area is preserved (“hardware reset”). The effect is it resets the current game back to the start. This function is automatically called by Memory.LoadROM function. +

+

void S9xSoftReset (void)

+

+ Similar to S9xReset function, but “software reset” as you press the SNES reset button. +

+

bool8 Memory.LoadROM (const char *filepath)

+

+ Attempts to load the specified ROM image filename into the emulated ROM area. There are many different SNES ROM image formats and the code attempts to auto-detect as many different types as it can and in a vast majority of the cases gets it right.
+ There are several ROM image options in the Settingsstructure; allow the user to set them before calling Memory.LoadROM function, or make sure they are all reset to default values before each call to Memory.LoadROM function. See Settings.ForceXXX in snes9x.h. +

+

bool8 Memory.LoadMultiCart (const char *cartApath, const char *cartBpath)

+

+ Attempts to load multiple ROM images into the emulated ROM area, for the multiple cartridge systems such as Sufami Turbo, Same Game, etc. +

+

bool8 Memory.LoadSRAM (const char *filepath)

+

+ Call this function to load the associated S-RAM save file (if any). The filename should be based on the ROM image name to allow easy linkage. The current ports change the directory and the filename extension of the ROM filename to derive the S-RAM filename. +

+

bool8 Memory.SaveSRAM (const char *filepath)

+

+ Call this function to save the emulated S-RAM area into a file so it can be restored again the next time the user wants to play the game. Remember to call this when just before the emulator exits or when the user has been playing a game and is about to load another one. +

+

void S9xMainLoop (void)

+

+ The emulator main loop. Call this from your own main loop that calls this function (if a ROM image is loaded and the game is not paused), processes any pending host system events, then goes back around the loop again until the emulator exits. S9xMainLoop function normally returns control to your main loop once every emulated frame, when it reaches the start of scan-line zero. However it may take a few frames when a huge memory transfer is being emulated. The function can return more often if the DEBUGGER compile-time flag is defined and the CPU has hit a break point, or the DEBUG_MODE_FLAG bit is set in CPU.Flags or instruction single-stepping is enabled. +

+

void S9xMixSamples (uint8 *buffer, int sample_count)

+

+ Call this function from your host sound system handling code to fill buffer with ready-mixed SNES sound data. If 16-bit sound mode is chosen, then the buffer will be filled with an array of sample_count int16, otherwise an array of sample_count uint8. If stereo sound generation is selected the buffer is filled with the same number of samples, but in pairs, first a left channel sample followed by the right channel sample.
+ If there are less queued samples than you request by sample_count, the function fills buffer with silent sound data and returns false. To avoid this shortage of queued samples, request larger buffer size when calling S9xInitSound, and handle sound latency safely. +

+

int S9xGetSampleCount (void)

+

+ Returns the number of sound samples available in the buffer for your configured playback settings. +

+

void S9xSetSamplesAvailableCallback (void (*) samples_available (void *), void *data)

+

+ Call this function to set up a callback that is run when sound samples are made available. samples_available is a function you provide that returns void and takes a pointer as an argument. data is a pointer that you may wish to pass to your callback or can be NULL. If you choose to provide a callback, you must call the provided S9xFinalizeSamples function inside it to actually buffer the samples. If you are using a callback-oriented sound API, it is recommended to set up a function that locks a common mutex during the calls to S9xFinalizeSamples and S9xMixSamples to prevent them from running at the same time and corrupting the sound buffer.
+ If you wish to disable a callback you have set up or need to temporarily shut down your sound system, you may pass NULL for both arguments to revert to the built-in version. +

+

bool8 S9xSyncSound (void)

+

+ Call this function to synchronize the sound buffers to the game state. If Snes9x is generating too much sound data, or a buffer-overrun is likely, this function will return false. In this case, you may wish to wait until your host sound system uses the available samples, and S9xSyncSound returns true before continuing to execute S9xMainLoop. +

+

bool8 S9xSetSoundMute (bool8 mute)

+

+ Call with a true parameter to prevent S9xMixSamples function from processing SNES sample data and instead just filling the return buffer with silent sound data. Useful if your sound system is interrupt or callback driven and the game has been paused either directly or indirectly because the user interacting with the emulator's user interface in some way. +

+

bool8 S9xFreezeGame (const char *filepath)

+

+ Call this function to record the current SNES hardware state into a file, the file can be loaded back using S9xUnfreezeGame function at a later date effectively restoring the current game to exact same spot. Call this function while you're processing any pending system events when S9xMainLoop function has returned control to you in your main loop. +

+

bool8 S9xUnfreezeGame (const char *filepath)

+

+ Restore the SNES hardware back to the exactly the state it was in when S9xFreezeGame function was used to generate the file specified. You have to arrange the correct ROM is already loaded using Memory.LoadROM function, an easy way to arrange this is to base freeze-game filenames on the ROM image name. The UNIX/Linux ports load freeze-game files when the user presses a function key, with the names romfilename.000 for F1, romfilename.001 for F2, etc. Games are frozen in the first place when the user presses Shift-function key. You could choose some other scheme. +

+

void S9xDumpSPCSnapshot (void)

+

+ Call this funtion to make a so-called SPC file, a snapshot of SNES sound state. Actual dump occurs at the first key-on event after this function is called. +

+

void S9xSetInfoString (const char *string)

+

+ Call this function if you want to show a message onto the SNES screen. +

+

Other Available Functions

+

+ See movie.h and movie.cpp to support the Snes9x movie feature.
+ See cheats.h, cheats.cpp and cheats2.cpp to support the cheat feature. +

+

Interface Functions You Need to Implement

+

bool8 S9xOpenSnapshotFile (const char *filepath, bool8 read_only, STREAM *file)

+

+ This function opens a freeze-game file. STREAM is defined as a gzFile if ZLIB is defined else it's defined as FILE *. The read_only parameter is set to true when reading a freeze-game file and false when writing a freeze-game file. Open the file filepath and return its pointer file. +

+

void S9xCloseSnapshotFile (STREAM file)

+

+ This function closes the freeze-game file opened by S9xOpenSnapshotFile function. +

+

void S9xExit (void)

+

+ Called when some fatal error situation arises or when the “q” debugger command is used. +

+

bool8 S9xInitUpdate (void)

+

+ Called just before Snes9x begins to render an SNES screen. Use this function if you should prepare before drawing, otherwise let it empty. +

+

bool8 S9xDeinitUpdate (int width, int height)

+

+ Called once a complete SNES screen has been rendered into the GFX.Screen memory buffer, now is your chance to copy the SNES rendered screen to the host computer's screen memory. The problem is that you have to cope with different sized SNES rendered screens: 256*224, 256*239, 512*224, 512*239, 512*448 and 512*478. +

+ +

bool8 S9xContinueUpdate (int width, int height)

+

+ Similar to S9xDeinitUpdate, but in interlace mode (512*448 or 512*478) only. Called once an even frame has been rendered into the GFX.Screen memory buffer. +

+

void S9xMessage (int type, int number, const char *message)

+

+ When Snes9x wants to display an error, information or warning message, it calls this function. Check in messages.h for the types and individual message numbers that Snes9x currently passes as parameters.
+ The idea is display the message string so the user can see it, but you choose not to display anything at all, or change the message based on the message number or message type.
+ Eventually all debug output will also go via this function, trace information already does. +

+

bool8 S9xOpenSoundDevice (void)

+

+ S9xInitSound function calls this function to actually open the host sound device. +

+

const char *S9xGetFilename (const char *extension, enum s9x_getdirtype dirtype)

+

+ When Snes9x needs to know the name of the cheat/IPS file and so on, this function is called. Check extension and dirtype, and return the appropriate filename. The current ports return the ROM file path with the given extension. +

+

const char *S9xGetFilenameInc (const char *extension, enum s9x_getdirtype dirtype)

+

+ Almost the same as S9xGetFilename function, but used for saving SPC files etc. So you have to take care not to delete the previously saved file, by increasing the number of the filename; romname.000.spc, romname.001.spc, ... +

+

const char *S9xGetDirectory (enum s9x_getdirtype dirtype)

+

+ Called when Snes9x wants to know the directory dirtype. +

+

const char *S9xChooseFilename (bool8 read_only)

+

+ If your port can match Snes9x's built-in LoadFreezeFile/SaveFreezeFile command (see controls.cpp), you may choose to use this function. Otherwise return NULL. +

+

const char *S9xChooseMovieFilename (bool8 read_only)

+

+ If your port can match Snes9x's built-in BeginRecordingMovie/LoadMovie command (see controls.cpp), you may choose to use this function. Otherwise return NULL. +

+

const char *S9xBasename (const char *path)

+

+ Called when Snes9x wants to know the name of the ROM image. Typically, extract the filename from path and return it. +

+

void S9xAutoSaveSRAM (void)

+

+ If Settings.AutoSaveDelay is not zero, Snes9x calls this function when the contents of the S-RAM has been changed. Typically, call Memory.SaveSRAM function from this function. +

+

void S9xToggleSoundChannel (int c)

+

+ If your port can match Snes9x's built-in SoundChannelXXX command (see controls.cpp), you may choose to use this function. Otherwise return NULL. Basically, turn on/off the sound channel c (0-7), and turn on all channels if c is 8. +

+

void S9xSetPalette (void)

+

+ Called when the SNES color palette has changed. Use this function if your system should change its color palette to match the SNES's. Otherwise let it empty. +

+

void S9xSyncSpeed (void)

+

+ Called at the end of S9xMainLoop function, when emulating one frame has been done. You should adjust the frame rate in this function. +

+

Global Variables

+

uint16 *GFX.Screen

+

+ A uint16 array pointer to (at least) 2*512*478 bytes buffer where Snes9x puts the rendered SNES screen. However, if your port will not support hires mode (Settings.SupportHiRes = false), then a 2*256*239 bytes buffer is allowed. You should allocate the space by yourself. As well you can change the GFX.Screen value after S9xDeinitUpdate function is called so that double-buffering will be easy. +

+

uint32 GFX.Pitch

+

+ Bytes per line (not pixels per line) of the GFX.Screen buffer. Typically set it to 1024. When the SNES screen is 256 pixels width and Settings.OpenGLEnable is false, last half 512 bytes per line are unused. When Settings.OpenGLEnable is true, GFX.Pitch is ignored. +

+

Settings structure

+

+ There are various switches in the Settings structure. See snes9x.h for details. At least the settings below are required for good emulation. +

+

+ memset(&Settings, 0, sizeof(Settings));
+ Settings.MouseMaster = true;
+ Settings.SuperScopeMaster = true;
+ Settings.JustifierMaster = true;
+ Settings.MultiPlayer5Master = true;
+ Settings.FrameTimePAL = 20000;
+ Settings.FrameTimeNTSC = 16667;
+ Settings.SixteenBitSound = true;
+ Settings.Stereo = true;
+ Settings.SoundPlaybackRate = 32000;
+ Settings.SoundInputRate = 32000;
+ Settings.SupportHiRes = true;
+ Settings.Transparency = true;
+ Settings.AutoDisplayMessages = true;
+ Settings.InitialInfoStringTimeout = 120;
+ Settings.HDMATimingHack = 100;
+ Settings.BlockInvalidVRAMAccessMaster = true; +

+

Settings.SoundInputRate

+

+ Adjusts the sound rate through resampling. For every Settings.SoundInputRate samples generated by the SNES, Settings.SoundPlaybackRate samples will be produced.
+ The sound generation rate on a SNES is directly proportional to the video output rate. Displays that synchronize with the vertical refresh but have a slightly lower refresh-rate than the emulated system can experience sound drop-outs. It may be beneficial to provide an option for users to configure Settings.SoundInputRate to suit their own systems. Setting Settings.SoundInputRate to a value that matches the actual output rate (i.e. 31977hz for 59.96hz) or lower will allow the users to eliminate crackling. A range of 31000hz to 33000hz should be inclusive enough for all displays. Use of this setting paired with the S9xSyncSound function can eliminate sound discontinuity. +

+
+ Updated most recently by: 2010/01/09 zones +
+ + diff --git a/docs/snapshots.txt b/docs/snapshots.txt new file mode 100644 index 00000000..ef0d1fdf --- /dev/null +++ b/docs/snapshots.txt @@ -0,0 +1,84 @@ +***** Important notice ******************************************************** + This document describes the snapshot file format for Snes9x 1.52 and later, + not compatible with 1.51. +******************************************************************************* + + Snes9x snapshot file format: (may be gzip-compressed) + + Begins with fixed length signature, consisting of a string, ':', a 4-digit + decimal version, and a '\n'. + +#!s9xsnp:0006 <-- '\n' after the 6 + + Then we have various blocks. The block format is: 3-character block name, + ':', 6-digit length, ':', then the data. Blocks are written in a defined + order. Structs are written packed with their members in a defined order, in + big-endian order where applicable. + +NAM:000019:Chrono Trigger.zip + + Currently defined blocks (in order) are: + + Essential parts: + NAM - ROM filename, from Memory.ROMFilename. 0-terminated string. + CPU - struct SCPUState, CPU internal state variables. + REG - struct SRegisters, emulated CPU registers. + PPU - struct SPPU, PPU internal variables. Note that IPPU is never saved. + DMA - struct SDMA, DMA/HDMA state variables. + VRA - Memory.VRAM, 0x10000 bytes. + RAM - Memory.RAM, 0x20000 bytes (WRAM). + SRA - Memory.SRAM, 0x20000 bytes. + FIL - Memory.FillRAM, 0x8000 bytes (register backing store). + SND - All of sound emulated registers and state valiables. + CTL - struct SControlSnapshot, controller emulation. + TIM - struct STimings, variables about timings between emulated events. + + Optional parts: + SFX - struct FxRegs_s, Super FX. + SA1 - struct SSA1, SA1 internal state variables. + SAR - struct SSA1Registers, SA1 emulated registers. + DP1 - struct SDSP1, DSP-1. + DP2 - struct SDSP2, DSP-2. + DP4 - struct SDSP4, DSP-4. + CX4 - Memory.C4RAM, 0x2000 bytes. + ST0 - struct SST010, ST-010. + OBC - struct SOBC1, OBC1 internal state variables. + OBM - Memory.OBC1RAM, 0x2000 byts. + S71 - struct SSPC7110Snapshot, SPC7110. + SRT - struct SSRTCSnapshot, S-RTC internal state variables. + CLK - struct SRTCData, S-RTC emulated registers. + BSX - struct SBSX, BS-X. + SHO - rendered SNES screen. + MOV - struct SnapshotMovieInfo. + MID - Some block of data the movie subsystem. + +================== + +Without changing the snapshot version number: +--------------------------------------------- + +Blocks may be safely added at the END of the file, as anything after the last +block is ignored. Blocks may not be moved or removed. + +Blocks may not decrease in size. Say you decrease from 10 bytes to 5. Then +later you increase back to 8. The only way you could safely do this is if +bytes 5-7 still mean the same thing they meant when the block was 10 bytes +long. + +Blocks may increase in size as you wish, as long as you can handle old +savestates with the old shorter size. + +Struct members may not change in interpretation. New struct members may be +added (at the END!) only if you can cope with them being binary-0 in older +savestates. Struct members may not be removed or changed in size/type. + +With changing the snapshot version number: +------------------------------------------ + +Blocks may be added, moved, or removed at will. + +Blocks may decrease in size. + +Struct members may be added, moved, or deleted, and their +interpretations/types may be changed. Use the 'debuted_in' and 'deleted_in' +fields to indicate when the new member debuted or the old member went away. diff --git a/docs/snes9x-license.txt b/docs/snes9x-license.txt new file mode 100644 index 00000000..698be102 --- /dev/null +++ b/docs/snes9x-license.txt @@ -0,0 +1,173 @@ + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. diff --git a/docs/snes9x.conf.default b/docs/snes9x.conf.default new file mode 100644 index 00000000..c7992087 --- /dev/null +++ b/docs/snes9x.conf.default @@ -0,0 +1,241 @@ +#----------------------------------------- +# snes9x.conf : Snes9x Configuration file +#----------------------------------------- + +[ROM] +# Filename = +LoROM = FALSE +HiROM = FALSE +PAL = FALSE +NTSC = FALSE +# Header = TRUE/FALSE to ForceHeader or ForceNoHeader +# Interleaved = TRUE/FALSE to ForceInterleaved or ForceNoInterleaved +Interleaved2 = FALSE +InterleaveGD24 = FALSE +Cheat = FALSE +Patch = TRUE + +[Sound] +Sync = FALSE +16BitSound = TRUE +Stereo = TRUE +ReverseStereo = FALSE +Rate = 32000 +InputRate = 32000 +Mute = FALSE + +[Display] +HiRes = TRUE +Transparency = TRUE +GraphicWindows = TRUE +DisplayFrameRate = FALSE +DisplayWatchedAddresses = FALSE +DisplayInput = FALSE +DisplayFrameCount = FALSE +MessagesInImage = TRUE +MessageDisplayTime = 120 + +[Settings] +BSXBootup = FALSE +# FrameTime = +FrameSkip = Auto +TurboMode = FALSE +TurboFrameSkip = 15 +MovieTruncateAtEnd = FALSE +MovieNotifyIgnored = FALSE +WrongMovieStateProtection = TRUE +StretchScreenshots = 1 +SnapshotScreenshots = TRUE +DontSaveOopsSnapshot = FALSE +AutoSaveDelay = 0 + +[Controls] +MouseMaster = TRUE +SuperscopeMaster = TRUE +JustifierMaster = TRUE +MP5Master = TRUE +AllowLeftRight = FALSE +Port1 = pad1 +Port2 = none +Mouse1Crosshair = 1 White/Black +Mouse2Crosshair = 1 White/Black +SuperscopeCrosshair = 2 White/Black +Justifier1Crosshair = 4 Blue/Black +Justifier2Crosshair = 4 MagicPink/Black + +[Hack] +EnableGameSpecificHacks = TRUE +AllowInvalidVRAMAccess = FALSE +SpeedHacks = FALSE +DisableIRQ = FALSE +DisableHDMA = FALSE +HDMATiming = 100 + +[Netplay] +Enable = FALSE +Port = 6096 +Server = "" + +[DEBUG] +Debugger = FALSE +Trace = FALSE + +[Unix] +# BaseDir = ~/.snes9x +# SnapshotFilename = +# PlayMovieFilename = +# RecordMovieFilename = +EnableGamePad = TRUE +PadDevice1 = (null) +PadDevice2 = (null) +PadDevice3 = (null) +PadDevice4 = (null) +PadDevice5 = (null) +PadDevice6 = (null) +PadDevice7 = (null) +PadDevice8 = (null) +ThreadSound = FALSE +SoundBufferSize = 100 +SoundFragmentSize = 2048 +# SoundDevice = +ClearAllControls = FALSE + +[Unix/X11] +SetKeyRepeat = TRUE +VideoMode = 1 + +[Unix/X11 Controls] +J00:Axis1 = Joypad1 Axis Up/Down T=50% +J00:Axis0 = Joypad1 Axis Left/Right T=50% +J00:B1 = Joypad1 A +J00:B2 = Joypad1 B +J00:B0 = Joypad1 X +J00:B3 = Joypad1 Y +J00:B6 = Joypad1 L +J00:B7 = Joypad1 R +J00:B8 = Joypad1 Select +J00:B11 = Joypad1 Start +K00:u = Joypad1 Up +K00:Up = Joypad1 Up +K00:j = Joypad1 Down +K00:n = Joypad1 Down +K00:Down = Joypad1 Down +K00:h = Joypad1 Left +K00:Left = Joypad1 Left +K00:k = Joypad1 Right +K00:Right = Joypad1 Right +K00:d = Joypad1 A +K00:S+d = Joypad1 ToggleTurbo A +K00:C+d = Joypad1 ToggleSticky A +K00:c = Joypad1 B +K00:S+c = Joypad1 ToggleTurbo B +K00:C+c = Joypad1 ToggleSticky B +K00:s = Joypad1 X +K00:S+s = Joypad1 ToggleTurbo X +K00:C+s = Joypad1 ToggleSticky X +K00:x = Joypad1 Y +K00:S+x = Joypad1 ToggleTurbo Y +K00:C+x = Joypad1 ToggleSticky Y +K00:a = Joypad1 L +K00:v = Joypad1 L +K00:S+a = Joypad1 ToggleTurbo L +K00:S+v = Joypad1 ToggleTurbo L +K00:C+a = Joypad1 ToggleSticky L +K00:C+v = Joypad1 ToggleSticky L +K00:z = Joypad1 R +K00:S+z = Joypad1 ToggleTurbo R +K00:C+z = Joypad1 ToggleSticky R +K00:space = Joypad1 Select +K00:Return = Joypad1 Start +K00:KP_Up = Joypad2 Up +K00:KP_Down = Joypad2 Down +K00:KP_Left = Joypad2 Left +K00:KP_Right = Joypad2 Right +K00:Prior = Joypad2 A +K00:Next = Joypad2 B +K00:Home = Joypad2 X +K00:End = Joypad2 Y +K00:Insert = Joypad2 L +K00:Delete = Joypad2 R +K00:KP_Add = Joypad2 Select +K00:KP_Enter = Joypad2 Start +K00:Escape = ExitEmu +K00:Pause = Pause +K00:Scroll_Lock = Pause +K00:CS+Escape = Reset +K00:S+Escape = SoftReset +K00:F12 = SaveFreezeFile +K00:A+F3 = SaveFreezeFile +K00:C+F3 = SaveFreezeFile +K00:F11 = LoadFreezeFile +K00:A+F2 = LoadFreezeFile +K00:C+F2 = LoadFreezeFile +K00:S+F1 = QuickSave000 +K00:S+F2 = QuickSave001 +K00:S+F3 = QuickSave002 +K00:S+F4 = QuickSave003 +K00:S+F5 = QuickSave004 +K00:S+F6 = QuickSave005 +K00:S+F7 = QuickSave006 +K00:S+F8 = QuickSave007 +K00:S+F9 = QuickSave008 +K00:F1 = QuickLoad000 +K00:F2 = QuickLoad001 +K00:F3 = QuickLoad002 +K00:F4 = QuickLoad003 +K00:F5 = QuickLoad004 +K00:F6 = QuickLoad005 +K00:F7 = QuickLoad006 +K00:F8 = QuickLoad007 +K00:F9 = QuickLoad008 +K00:F10 = LoadOopsFile +K00:A+F1 = SaveSPC +K00:C+F1 = SaveSPC +K00:Print = Screenshot +K00:S+1 = BeginRecordingMovie +K00:S+2 = EndRecordingMovie +K00:S+3 = LoadMovie +K00:Tab = EmuTurbo +K00:S+Tab = ToggleEmuTurbo +K00:equal = IncFrameRate +K00:minus = DecFrameRate +K00:S+equal = IncFrameTime +K00:S+minus = DecFrameTime +K00:A+equal = IncEmuTurbo +K00:A+minus = DecEmuTurbo +K00:C+equal = IncTurboSpeed +K00:C+minus = DecTurboSpeed +K00:6 = SwapJoypads +K00:A+F4 = SoundChannel0 +K00:C+F4 = SoundChannel0 +K00:A+F5 = SoundChannel1 +K00:C+F5 = SoundChannel1 +K00:A+F6 = SoundChannel2 +K00:C+F6 = SoundChannel2 +K00:A+F7 = SoundChannel3 +K00:C+F7 = SoundChannel3 +K00:A+F8 = SoundChannel4 +K00:C+F8 = SoundChannel4 +K00:A+F9 = SoundChannel5 +K00:C+F9 = SoundChannel5 +K00:A+F10 = SoundChannel6 +K00:C+F10 = SoundChannel6 +K00:A+F11 = SoundChannel7 +K00:C+F11 = SoundChannel7 +K00:A+F12 = SoundChannelsOn +K00:C+F12 = SoundChannelsOn +K00:1 = ToggleBG0 +K00:2 = ToggleBG1 +K00:3 = ToggleBG2 +K00:4 = ToggleBG3 +K00:5 = ToggleSprites +K00:9 = ToggleTransparency +K00:BackSpace = ClipWindows +K00:0 = ToggleHDMA +K00:A+Escape = Debugger +M00:Pointer = Pointer Mouse1+Superscope+Justifier1 +M00:B0 = {Mouse1 L,Superscope Fire,Justifier1 Trigger} +M00:B2 = {Mouse1 R,Superscope Cursor,Justifier1 Start} +M00:B1 = {Justifier1 AimOffscreen Trigger,Superscope AimOffscreen} +K00:grave = Superscope ToggleTurbo +K00:slash = Superscope Pause diff --git a/dsp.cpp b/dsp.cpp new file mode 100644 index 00000000..b6e23ff1 --- /dev/null +++ b/dsp.cpp @@ -0,0 +1,229 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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" +#ifdef DEBUGGER +#include "missing.h" +#endif + +uint8 (*GetDSP) (uint16) = NULL; +void (*SetDSP) (uint8, uint16) = NULL; + + +void S9xResetDSP (void) +{ + memset(&DSP1, 0, sizeof(DSP1)); + DSP1.waiting4command = TRUE; + DSP1.first_parameter = TRUE; + + memset(&DSP2, 0, sizeof(DSP2)); + DSP2.waiting4command = TRUE; + + memset(&DSP3, 0, sizeof(DSP3)); + DSP3_Reset(); + + memset(&DSP4, 0, sizeof(DSP4)); + DSP4.waiting4command = TRUE; +} + +uint8 S9xGetDSP (uint16 address) +{ +#ifdef DEBUGGER + if (Settings.TraceDSP) + { + sprintf(String, "DSP read: 0x%04X", address); + S9xMessage(S9X_TRACE, S9X_TRACE_DSP1, String); + } +#endif + + return ((*GetDSP)(address)); +} + +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); +} diff --git a/dsp.h b/dsp.h new file mode 100644 index 00000000..be4d073f --- /dev/null +++ b/dsp.h @@ -0,0 +1,618 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _DSP1_H_ +#define _DSP1_H_ + +enum +{ + M_DSP1_LOROM_S, + M_DSP1_LOROM_L, + M_DSP1_HIROM, + M_DSP2_LOROM, + M_DSP3_LOROM, + M_DSP4_LOROM +}; + +struct SDSP0 +{ + uint32 maptype; + uint32 boundary; +}; + +struct SDSP1 +{ + bool8 waiting4command; + bool8 first_parameter; + uint8 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; + + int16 CentreX; + int16 CentreY; + int16 VOffset; + + int16 VPlane_C; + int16 VPlane_E; + + // Azimuth and Zenith angles + int16 SinAas; + int16 CosAas; + int16 SinAzs; + int16 CosAzs; + + // Clipped Zenith angle + int16 SinAZS; + int16 CosAZS; + int16 SecAZS_C1; + int16 SecAZS_E1; + int16 SecAZS_C2; + int16 SecAZS_E2; + + int16 Nx; + int16 Ny; + int16 Nz; + int16 Gx; + int16 Gy; + int16 Gz; + int16 C_Les; + int16 E_Les; + int16 G_Les; + + int16 matrixA[3][3]; + int16 matrixB[3][3]; + int16 matrixC[3][3]; + + int16 Op00Multiplicand; + int16 Op00Multiplier; + int16 Op00Result; + + int16 Op20Multiplicand; + int16 Op20Multiplier; + int16 Op20Result; + + int16 Op10Coefficient; + int16 Op10Exponent; + int16 Op10CoefficientR; + int16 Op10ExponentR; + + int16 Op04Angle; + int16 Op04Radius; + int16 Op04Sin; + int16 Op04Cos; + + int16 Op0CA; + int16 Op0CX1; + int16 Op0CY1; + int16 Op0CX2; + int16 Op0CY2; + + int16 Op02FX; + int16 Op02FY; + int16 Op02FZ; + int16 Op02LFE; + int16 Op02LES; + int16 Op02AAS; + int16 Op02AZS; + int16 Op02VOF; + int16 Op02VVA; + int16 Op02CX; + int16 Op02CY; + + int16 Op0AVS; + int16 Op0AA; + int16 Op0AB; + int16 Op0AC; + int16 Op0AD; + + int16 Op06X; + int16 Op06Y; + int16 Op06Z; + int16 Op06H; + int16 Op06V; + int16 Op06M; + + int16 Op01m; + int16 Op01Zr; + int16 Op01Xr; + int16 Op01Yr; + + int16 Op11m; + int16 Op11Zr; + int16 Op11Xr; + int16 Op11Yr; + + int16 Op21m; + int16 Op21Zr; + int16 Op21Xr; + int16 Op21Yr; + + int16 Op0DX; + int16 Op0DY; + int16 Op0DZ; + int16 Op0DF; + int16 Op0DL; + int16 Op0DU; + + int16 Op1DX; + int16 Op1DY; + int16 Op1DZ; + int16 Op1DF; + int16 Op1DL; + int16 Op1DU; + + int16 Op2DX; + int16 Op2DY; + int16 Op2DZ; + int16 Op2DF; + int16 Op2DL; + int16 Op2DU; + + int16 Op03F; + int16 Op03L; + int16 Op03U; + int16 Op03X; + int16 Op03Y; + int16 Op03Z; + + int16 Op13F; + int16 Op13L; + int16 Op13U; + int16 Op13X; + int16 Op13Y; + int16 Op13Z; + + int16 Op23F; + int16 Op23L; + int16 Op23U; + int16 Op23X; + int16 Op23Y; + int16 Op23Z; + + int16 Op14Zr; + int16 Op14Xr; + int16 Op14Yr; + int16 Op14U; + int16 Op14F; + int16 Op14L; + int16 Op14Zrr; + int16 Op14Xrr; + int16 Op14Yrr; + + int16 Op0EH; + int16 Op0EV; + int16 Op0EX; + int16 Op0EY; + + int16 Op0BX; + int16 Op0BY; + int16 Op0BZ; + int16 Op0BS; + + int16 Op1BX; + int16 Op1BY; + int16 Op1BZ; + int16 Op1BS; + + int16 Op2BX; + int16 Op2BY; + int16 Op2BZ; + int16 Op2BS; + + int16 Op28X; + int16 Op28Y; + int16 Op28Z; + int16 Op28R; + + int16 Op1CX; + int16 Op1CY; + int16 Op1CZ; + int16 Op1CXBR; + int16 Op1CYBR; + int16 Op1CZBR; + int16 Op1CXAR; + int16 Op1CYAR; + int16 Op1CZAR; + int16 Op1CX1; + int16 Op1CY1; + int16 Op1CZ1; + int16 Op1CX2; + int16 Op1CY2; + int16 Op1CZ2; + + uint16 Op0FRamsize; + uint16 Op0FPass; + + int16 Op2FUnknown; + int16 Op2FSize; + + int16 Op08X; + int16 Op08Y; + int16 Op08Z; + int16 Op08Ll; + int16 Op08Lh; + + int16 Op18X; + int16 Op18Y; + int16 Op18Z; + int16 Op18R; + int16 Op18D; + + int16 Op38X; + int16 Op38Y; + int16 Op38Z; + int16 Op38R; + int16 Op38D; +}; + +struct SDSP2 +{ + bool8 waiting4command; + uint8 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; + + bool8 Op05HasLen; + int32 Op05Len; + uint8 Op05Transparent; + + bool8 Op06HasLen; + int32 Op06Len; + + uint16 Op09Word1; + uint16 Op09Word2; + + bool8 Op0DHasLen; + int32 Op0DOutLen; + int32 Op0DInLen; +}; + +struct SDSP3 +{ + uint16 DR; + uint16 SR; + uint16 MemoryIndex; + + int16 WinLo; + int16 WinHi; + int16 AddLo; + int16 AddHi; + + uint16 Codewords; + uint16 Outwords; + uint16 Symbol; + uint16 BitCount; + uint16 Index; + uint16 Codes[512]; + uint16 BitsLeft; + uint16 ReqBits; + uint16 ReqData; + uint16 BitCommand; + uint8 BaseLength; + uint16 BaseCodes; + uint16 BaseCode; + uint8 CodeLengths[8]; + uint16 CodeOffsets[8]; + uint16 LZCode; + uint8 LZLength; + + uint16 X; + uint16 Y; + + uint8 Bitmap[8]; + uint8 Bitplane[8]; + uint16 BMIndex; + uint16 BPIndex; + uint16 Count; + + int16 op3e_x; + int16 op3e_y; + + int16 op1e_terrain[0x2000]; + int16 op1e_cost[0x2000]; + int16 op1e_weight[0x2000]; + + int16 op1e_cell; + int16 op1e_turn; + int16 op1e_search; + + int16 op1e_x; + int16 op1e_y; + + int16 op1e_min_radius; + int16 op1e_max_radius; + + int16 op1e_max_search_radius; + int16 op1e_max_path_radius; + + int16 op1e_lcv_radius; + int16 op1e_lcv_steps; + int16 op1e_lcv_turns; +}; + +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]; + uint8 byte; + uint16 address; + + // op control + int8 Logic; // controls op flow + + // projection format + int16 lcv; // loop-control variable + int16 distance; // z-position into virtual world + int16 raster; // current raster line + int16 segments; // number of raster lines drawn + + // 1.15.16 or 1.15.0 [sign, integer, fraction] + int32 world_x; // line of x-projection in world + int32 world_y; // line of y-projection in world + int32 world_dx; // projection line x-delta + int32 world_dy; // projection line y-delta + int16 world_ddx; // x-delta increment + int16 world_ddy; // y-delta increment + int32 world_xenv; // world x-shaping factor + int16 world_yofs; // world y-vertical scroll + int16 view_x1; // current viewer-x + int16 view_y1; // current viewer-y + int16 view_x2; // future viewer-x + int16 view_y2; // future viewer-y + int16 view_dx; // view x-delta factor + int16 view_dy; // view y-delta factor + int16 view_xofs1; // current viewer x-vertical scroll + int16 view_yofs1; // current viewer y-vertical scroll + int16 view_xofs2; // future viewer x-vertical scroll + int16 view_yofs2; // future viewer y-vertical scroll + int16 view_yofsenv; // y-scroll shaping factor + int16 view_turnoff_x; // road turnoff data + int16 view_turnoff_dx; // road turnoff delta factor + + // drawing area + int16 viewport_cx; // x-center of viewport window + int16 viewport_cy; // y-center of render window + int16 viewport_left; // x-left of viewport + int16 viewport_right; // x-right of viewport + int16 viewport_top; // y-top of viewport + int16 viewport_bottom; // y-bottom of viewport + + // sprite structure + int16 sprite_x; // projected x-pos of sprite + int16 sprite_y; // projected y-pos of sprite + int16 sprite_attr; // obj attributes + bool8 sprite_size; // sprite size: 8x8 or 16x16 + int16 sprite_clipy; // visible line to clip pixels off + int16 sprite_count; + + // generic projection variables designed for two solid polygons + two polygon sides + int16 poly_clipLf[2][2]; // left clip boundary + int16 poly_clipRt[2][2]; // right clip boundary + int16 poly_ptr[2][2]; // HDMA structure pointers + int16 poly_raster[2][2]; // current raster line below horizon + int16 poly_top[2][2]; // top clip boundary + int16 poly_bottom[2][2]; // bottom clip boundary + int16 poly_cx[2][2]; // center for left/right points + int16 poly_start[2]; // current projection points + int16 poly_plane[2]; // previous z-plane distance + + // OAM + int16 OAM_attr[16]; // OAM (size, MSB) data + int16 OAM_index; // index into OAM table + int16 OAM_bits; // offset into OAM table + int16 OAM_RowMax; // maximum number of tiles per 8 aligned pixels (row) + int16 OAM_Row[32]; // current number of tiles per row +}; + +extern struct SDSP0 DSP0; +extern struct SDSP1 DSP1; +extern struct SDSP2 DSP2; +extern struct SDSP3 DSP3; +extern struct SDSP4 DSP4; + +uint8 S9xGetDSP (uint16); +void S9xSetDSP (uint8, uint16); +void S9xResetDSP (void); +uint8 DSP1GetByte (uint16); +void DSP1SetByte (uint8, uint16); +uint8 DSP2GetByte (uint16); +void DSP2SetByte (uint8, uint16); +uint8 DSP3GetByte (uint16); +void DSP3SetByte (uint8, uint16); +uint8 DSP4GetByte (uint16); +void DSP4SetByte (uint8, uint16); +void DSP3_Reset (void); + +extern uint8 (*GetDSP) (uint16); +extern void (*SetDSP) (uint8, uint16); + +#endif diff --git a/dsp1.cpp b/dsp1.cpp new file mode 100644 index 00000000..85f95123 --- /dev/null +++ b/dsp1.cpp @@ -0,0 +1,1894 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/* +Copyright (C) 1997-2006 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach ) + +http://www.zsnes.com +http://sourceforge.net/projects/zsnes + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "snes9x.h" +#include "memmap.h" + +#ifdef DEBUGGER +//#define DebugDSP1 +#endif + +#ifdef DebugDSP1 +#include +static FILE *LogFile = NULL; +#endif + +static const uint16 DSP1ROM[1024] = +{ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, + 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, + 0x4000, 0x7fff, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, + 0x0100, 0x0080, 0x0040, 0x0020, 0x0001, 0x0008, 0x0004, 0x0002, + 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x8000, 0xffe5, 0x0100, 0x7fff, 0x7f02, 0x7e08, + 0x7d12, 0x7c1f, 0x7b30, 0x7a45, 0x795d, 0x7878, 0x7797, 0x76ba, + 0x75df, 0x7507, 0x7433, 0x7361, 0x7293, 0x71c7, 0x70fe, 0x7038, + 0x6f75, 0x6eb4, 0x6df6, 0x6d3a, 0x6c81, 0x6bca, 0x6b16, 0x6a64, + 0x69b4, 0x6907, 0x685b, 0x67b2, 0x670b, 0x6666, 0x65c4, 0x6523, + 0x6484, 0x63e7, 0x634c, 0x62b3, 0x621c, 0x6186, 0x60f2, 0x6060, + 0x5fd0, 0x5f41, 0x5eb5, 0x5e29, 0x5d9f, 0x5d17, 0x5c91, 0x5c0c, + 0x5b88, 0x5b06, 0x5a85, 0x5a06, 0x5988, 0x590b, 0x5890, 0x5816, + 0x579d, 0x5726, 0x56b0, 0x563b, 0x55c8, 0x5555, 0x54e4, 0x5474, + 0x5405, 0x5398, 0x532b, 0x52bf, 0x5255, 0x51ec, 0x5183, 0x511c, + 0x50b6, 0x5050, 0x4fec, 0x4f89, 0x4f26, 0x4ec5, 0x4e64, 0x4e05, + 0x4da6, 0x4d48, 0x4cec, 0x4c90, 0x4c34, 0x4bda, 0x4b81, 0x4b28, + 0x4ad0, 0x4a79, 0x4a23, 0x49cd, 0x4979, 0x4925, 0x48d1, 0x487f, + 0x482d, 0x47dc, 0x478c, 0x473c, 0x46ed, 0x469f, 0x4651, 0x4604, + 0x45b8, 0x456c, 0x4521, 0x44d7, 0x448d, 0x4444, 0x43fc, 0x43b4, + 0x436d, 0x4326, 0x42e0, 0x429a, 0x4255, 0x4211, 0x41cd, 0x4189, + 0x4146, 0x4104, 0x40c2, 0x4081, 0x4040, 0x3fff, 0x41f7, 0x43e1, + 0x45bd, 0x478d, 0x4951, 0x4b0b, 0x4cbb, 0x4e61, 0x4fff, 0x5194, + 0x5322, 0x54a9, 0x5628, 0x57a2, 0x5914, 0x5a81, 0x5be9, 0x5d4a, + 0x5ea7, 0x5fff, 0x6152, 0x62a0, 0x63ea, 0x6530, 0x6672, 0x67b0, + 0x68ea, 0x6a20, 0x6b53, 0x6c83, 0x6daf, 0x6ed9, 0x6fff, 0x7122, + 0x7242, 0x735f, 0x747a, 0x7592, 0x76a7, 0x77ba, 0x78cb, 0x79d9, + 0x7ae5, 0x7bee, 0x7cf5, 0x7dfa, 0x7efe, 0x7fff, 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, 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, 0xfcdc, + 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e, 0xe708, 0xe3f5, + 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef, 0xcf05, 0xcc22, + 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86, 0xb8e4, 0xb64c, + 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be, 0xa57e, 0xa34c, + 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a, 0x9593, 0x93dc, + 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc, 0x89bf, 0x8894, + 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d, 0x8276, 0x81e3, + 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a, 0x6488, 0x0080, + 0x03ff, 0x0116, 0x0002, 0x0080, 0x4000, 0x3fd7, 0x3faf, 0x3f86, + 0x3f5d, 0x3f34, 0x3f0c, 0x3ee3, 0x3eba, 0x3e91, 0x3e68, 0x3e40, + 0x3e17, 0x3dee, 0x3dc5, 0x3d9c, 0x3d74, 0x3d4b, 0x3d22, 0x3cf9, + 0x3cd0, 0x3ca7, 0x3c7f, 0x3c56, 0x3c2d, 0x3c04, 0x3bdb, 0x3bb2, + 0x3b89, 0x3b60, 0x3b37, 0x3b0e, 0x3ae5, 0x3abc, 0x3a93, 0x3a69, + 0x3a40, 0x3a17, 0x39ee, 0x39c5, 0x399c, 0x3972, 0x3949, 0x3920, + 0x38f6, 0x38cd, 0x38a4, 0x387a, 0x3851, 0x3827, 0x37fe, 0x37d4, + 0x37aa, 0x3781, 0x3757, 0x372d, 0x3704, 0x36da, 0x36b0, 0x3686, + 0x365c, 0x3632, 0x3609, 0x35df, 0x35b4, 0x358a, 0x3560, 0x3536, + 0x350c, 0x34e1, 0x34b7, 0x348d, 0x3462, 0x3438, 0x340d, 0x33e3, + 0x33b8, 0x338d, 0x3363, 0x3338, 0x330d, 0x32e2, 0x32b7, 0x328c, + 0x3261, 0x3236, 0x320b, 0x31df, 0x31b4, 0x3188, 0x315d, 0x3131, + 0x3106, 0x30da, 0x30ae, 0x3083, 0x3057, 0x302b, 0x2fff, 0x2fd2, + 0x2fa6, 0x2f7a, 0x2f4d, 0x2f21, 0x2ef4, 0x2ec8, 0x2e9b, 0x2e6e, + 0x2e41, 0x2e14, 0x2de7, 0x2dba, 0x2d8d, 0x2d60, 0x2d32, 0x2d05, + 0x2cd7, 0x2ca9, 0x2c7b, 0x2c4d, 0x2c1f, 0x2bf1, 0x2bc3, 0x2b94, + 0x2b66, 0x2b37, 0x2b09, 0x2ada, 0x2aab, 0x2a7c, 0x2a4c, 0x2a1d, + 0x29ed, 0x29be, 0x298e, 0x295e, 0x292e, 0x28fe, 0x28ce, 0x289d, + 0x286d, 0x283c, 0x280b, 0x27da, 0x27a9, 0x2777, 0x2746, 0x2714, + 0x26e2, 0x26b0, 0x267e, 0x264c, 0x2619, 0x25e7, 0x25b4, 0x2581, + 0x254d, 0x251a, 0x24e6, 0x24b2, 0x247e, 0x244a, 0x2415, 0x23e1, + 0x23ac, 0x2376, 0x2341, 0x230b, 0x22d6, 0x229f, 0x2269, 0x2232, + 0x21fc, 0x21c4, 0x218d, 0x2155, 0x211d, 0x20e5, 0x20ad, 0x2074, + 0x203b, 0x2001, 0x1fc7, 0x1f8d, 0x1f53, 0x1f18, 0x1edd, 0x1ea1, + 0x1e66, 0x1e29, 0x1ded, 0x1db0, 0x1d72, 0x1d35, 0x1cf6, 0x1cb8, + 0x1c79, 0x1c39, 0x1bf9, 0x1bb8, 0x1b77, 0x1b36, 0x1af4, 0x1ab1, + 0x1a6e, 0x1a2a, 0x19e6, 0x19a1, 0x195c, 0x1915, 0x18ce, 0x1887, + 0x183f, 0x17f5, 0x17ac, 0x1761, 0x1715, 0x16c9, 0x167c, 0x162e, + 0x15df, 0x158e, 0x153d, 0x14eb, 0x1497, 0x1442, 0x13ec, 0x1395, + 0x133c, 0x12e2, 0x1286, 0x1228, 0x11c9, 0x1167, 0x1104, 0x109e, + 0x1036, 0x0fcc, 0x0f5f, 0x0eef, 0x0e7b, 0x0e04, 0x0d89, 0x0d0a, + 0x0c86, 0x0bfd, 0x0b6d, 0x0ad6, 0x0a36, 0x098d, 0x08d7, 0x0811, + 0x0736, 0x063e, 0x0519, 0x039a, 0x0000, 0x7fff, 0x0100, 0x0080, + 0x021d, 0x00c8, 0x00ce, 0x0048, 0x0a26, 0x277a, 0x00ce, 0x6488, + 0x14ac, 0x0001, 0x00f9, 0x00fc, 0x00ff, 0x00fc, 0x00f9, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff +}; + +static const int16 DSP1_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 +}; + +static const int16 DSP1_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 +}; + + +#ifdef DebugDSP1 + +static void Log_Message (const char *Message, ...) +{ + char Msg[400]; + va_list ap; + size_t ignore; + + va_start(ap, Message); + vsprintf(Msg, Message, ap); + va_end(ap); + + strcat(Msg, "\r\n\0"); + ignore = fwrite(Msg, strlen(Msg), 1, LogFile); + fflush(LogFile); +} + +static void Start_Log (void) +{ + LogFile = fopen("dsp1emu.log", "wb"); +} + +static void Stop_Log (void) +{ + if (LogFile) + { + fclose(LogFile); + LogFile = NULL; + } +} + +#endif + +static void DSP1_Op00 (void) +{ + DSP1.Op00Result = DSP1.Op00Multiplicand * DSP1.Op00Multiplier >> 15; + +#ifdef DebugDSP1 + Log_Message("OP00 MULT %d*%d/32768=%d", DSP1.Op00Multiplicand, DSP1.Op00Multiplier, DSP1.Op00Result); +#endif +} + +static void DSP1_Op20 (void) +{ + DSP1.Op20Result = DSP1.Op20Multiplicand * DSP1.Op20Multiplier >> 15; + DSP1.Op20Result++; + +#ifdef DebugDSP1 + Log_Message("OP20 MULT %d*%d/32768=%d", DSP1.Op20Multiplicand, DSP1.Op20Multiplier, DSP1.Op20Result); +#endif +} + +static void DSP1_Inverse (int16 Coefficient, int16 Exponent, int16 *iCoefficient, int16 *iExponent) +{ + // Step One: Division by Zero + if (Coefficient == 0x0000) + { + *iCoefficient = 0x7fff; + *iExponent = 0x002f; + } + else + { + int16 Sign = 1; + + // Step Two: Remove Sign + if (Coefficient < 0) + { + if (Coefficient < -32767) + Coefficient = -32767; + Coefficient = -Coefficient; + Sign = -1; + } + + // Step Three: Normalize + while (Coefficient < 0x4000) + { + Coefficient <<= 1; + Exponent--; + } + + // Step Four: Special Case + if (Coefficient == 0x4000) + { + if (Sign == 1) + *iCoefficient = 0x7fff; + else + { + *iCoefficient = -0x4000; + Exponent--; + } + } + else + { + // Step Five: Initial Guess + int16 i = DSP1ROM[((Coefficient - 0x4000) >> 7) + 0x0065]; + + // Step Six: Iterate "estimated" Newton's Method + i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; + i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; + + *iCoefficient = i * Sign; + } + + *iExponent = 1 - Exponent; + } +} + +static void DSP1_Op10 (void) +{ + DSP1_Inverse(DSP1.Op10Coefficient, DSP1.Op10Exponent, &DSP1.Op10CoefficientR, &DSP1.Op10ExponentR); + +#ifdef DebugDSP1 + Log_Message("OP10 INV %d*2^%d = %d*2^%d", DSP1.Op10Coefficient, DSP1.Op10Exponent, DSP1.Op10CoefficientR, DSP1.Op10ExponentR); +#endif +} + +static int16 DSP1_Sin (int16 Angle) +{ + int32 S; + + if (Angle < 0) + { + if (Angle == -32768) + return (0); + + return (-DSP1_Sin(-Angle)); + } + + S = DSP1_SinTable[Angle >> 8] + (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[0x40 + (Angle >> 8)] >> 15); + if (S > 32767) + S = 32767; + + return ((int16) S); +} + +static int16 DSP1_Cos (int16 Angle) +{ + int32 S; + + if (Angle < 0) + { + if (Angle == -32768) + return (-32768); + + Angle = -Angle; + } + + S = DSP1_SinTable[0x40 + (Angle >> 8)] - (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[Angle >> 8] >> 15); + if (S < -32768) + S = -32767; + + return ((int16) S); +} + +static void DSP1_Normalize (int16 m, int16 *Coefficient, int16 *Exponent) +{ + int16 i = 0x4000; + int16 e = 0; + + if (m < 0) + { + while ((m & i) && i) + { + i >>= 1; + e++; + } + } + else + { + while (!(m & i) && i) + { + i >>= 1; + e++; + } + } + + if (e > 0) + *Coefficient = m * DSP1ROM[0x21 + e] << 1; + else + *Coefficient = m; + + *Exponent -= e; +} + +static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Exponent) +{ + int16 n = Product & 0x7fff; + int16 m = Product >> 15; + int16 i = 0x4000; + int16 e = 0; + + if (m < 0) + { + while ((m & i) && i) + { + i >>= 1; + e++; + } + } + else + { + while (!(m & i) && i) + { + i >>= 1; + e++; + } + } + + if (e > 0) + { + *Coefficient = m * DSP1ROM[0x0021 + e] << 1; + + if (e < 15) + *Coefficient += n * DSP1ROM[0x0040 - e] >> 15; + else + { + i = 0x4000; + + if (m < 0) + { + while ((n & i) && i) + { + i >>= 1; + e++; + } + } + else + { + while (!(n & i) && i) + { + i >>= 1; + e++; + } + } + + if (e > 15) + *Coefficient = n * DSP1ROM[0x0012 + e] << 1; + else + *Coefficient += n; + } + } + else + *Coefficient = m; + + *Exponent = e; +} + +static int16 DSP1_Truncate (int16 C, int16 E) +{ + if (E > 0) + { + if (C > 0) + return (32767); + else + if (C < 0) + return (-32767); + } + else + { + if (E < 0) + return (C * DSP1ROM[0x0031 + E] >> 15); + } + + return (C); +} + +static void DSP1_Op04 (void) +{ + DSP1.Op04Sin = DSP1_Sin(DSP1.Op04Angle) * DSP1.Op04Radius >> 15; + DSP1.Op04Cos = DSP1_Cos(DSP1.Op04Angle) * DSP1.Op04Radius >> 15; +} + +static void DSP1_Op0C (void) +{ + DSP1.Op0CX2 = (DSP1.Op0CY1 * DSP1_Sin(DSP1.Op0CA) >> 15) + (DSP1.Op0CX1 * DSP1_Cos(DSP1.Op0CA) >> 15); + DSP1.Op0CY2 = (DSP1.Op0CY1 * DSP1_Cos(DSP1.Op0CA) >> 15) - (DSP1.Op0CX1 * DSP1_Sin(DSP1.Op0CA) >> 15); +} + +static void DSP1_Parameter (int16 Fx, int16 Fy, int16 Fz, int16 Lfe, int16 Les, int16 Aas, int16 Azs, int16 *Vof, int16 *Vva, int16 *Cx, int16 *Cy) +{ + const int16 MaxAZS_Exp[16] = + { + 0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca, + 0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4 + }; + + int16 CSec, C, E, MaxAZS, Aux; + int16 LfeNx, LfeNy, LfeNz; + int16 LesNx, LesNy, LesNz; + int16 CentreZ; + + // Copy Zenith angle for clipping + int16 AZS = Azs; + + // Store Sine and Cosine of Azimuth and Zenith angle + DSP1.SinAas = DSP1_Sin(Aas); + DSP1.CosAas = DSP1_Cos(Aas); + DSP1.SinAzs = DSP1_Sin(Azs); + DSP1.CosAzs = DSP1_Cos(Azs); + + DSP1.Nx = DSP1.SinAzs * -DSP1.SinAas >> 15; + DSP1.Ny = DSP1.SinAzs * DSP1.CosAas >> 15; + DSP1.Nz = DSP1.CosAzs * 0x7fff >> 15; + + LfeNx = Lfe * DSP1.Nx >> 15; + LfeNy = Lfe * DSP1.Ny >> 15; + LfeNz = Lfe * DSP1.Nz >> 15; + + // Center of Projection + DSP1.CentreX = Fx + LfeNx; + DSP1.CentreY = Fy + LfeNy; + CentreZ = Fz + LfeNz; + + LesNx = Les * DSP1.Nx >> 15; + LesNy = Les * DSP1.Ny >> 15; + LesNz = Les * DSP1.Nz >> 15; + + DSP1.Gx = DSP1.CentreX - LesNx; + DSP1.Gy = DSP1.CentreY - LesNy; + DSP1.Gz = CentreZ - LesNz; + + DSP1.E_Les = 0; + DSP1_Normalize(Les, &DSP1.C_Les, &DSP1.E_Les); + DSP1.G_Les = Les; + + E = 0; + DSP1_Normalize(CentreZ, &C, &E); + + DSP1.VPlane_C = C; + DSP1.VPlane_E = E; + + // Determine clip boundary and clip Zenith angle if necessary + MaxAZS = MaxAZS_Exp[-E]; + + if (AZS < 0) + { + MaxAZS = -MaxAZS; + if (AZS < MaxAZS + 1) + AZS = MaxAZS + 1; + } + else + { + if (AZS > MaxAZS) + AZS = MaxAZS; + } + + // Store Sine and Cosine of clipped Zenith angle + DSP1.SinAZS = DSP1_Sin(AZS); + DSP1.CosAZS = DSP1_Cos(AZS); + + DSP1_Inverse(DSP1.CosAZS, 0, &DSP1.SecAZS_C1, &DSP1.SecAZS_E1); + DSP1_Normalize(C * DSP1.SecAZS_C1 >> 15, &C, &E); + E += DSP1.SecAZS_E1; + + C = DSP1_Truncate(C, E) * DSP1.SinAZS >> 15; + + DSP1.CentreX += C * DSP1.SinAas >> 15; + DSP1.CentreY -= C * DSP1.CosAas >> 15; + + *Cx = DSP1.CentreX; + *Cy = DSP1.CentreY; + + // Raster number of imaginary center and horizontal line + *Vof = 0; + + if ((Azs != AZS) || (Azs == MaxAZS)) + { + if (Azs == -32768) + Azs = -32767; + + C = Azs - MaxAZS; + if (C >= 0) + C--; + Aux = ~(C << 2); + + C = Aux * DSP1ROM[0x0328] >> 15; + C = (C * Aux >> 15) + DSP1ROM[0x0327]; + *Vof -= (C * Aux >> 15) * Les >> 15; + + C = Aux * Aux >> 15; + Aux = (C * DSP1ROM[0x0324] >> 15) + DSP1ROM[0x0325]; + DSP1.CosAZS += (C * Aux >> 15) * DSP1.CosAZS >> 15; + } + + DSP1.VOffset = Les * DSP1.CosAZS >> 15; + + DSP1_Inverse(DSP1.SinAZS, 0, &CSec, &E); + DSP1_Normalize(DSP1.VOffset, &C, &E); + DSP1_Normalize(C * CSec >> 15, &C, &E); + + if (C == -32768) + { + C >>= 1; + E++; + } + + *Vva = DSP1_Truncate(-C, E); + + // Store Secant of clipped Zenith angle + DSP1_Inverse(DSP1.CosAZS, 0, &DSP1.SecAZS_C2, &DSP1.SecAZS_E2); +} + +static void DSP1_Raster (int16 Vs, int16 *An, int16 *Bn, int16 *Cn, int16 *Dn) +{ + int16 C, E, C1, E1; + + DSP1_Inverse((Vs * DSP1.SinAzs >> 15) + DSP1.VOffset, 7, &C, &E); + E += DSP1.VPlane_E; + + C1 = C * DSP1.VPlane_C >> 15; + E1 = E + DSP1.SecAZS_E2; + + DSP1_Normalize(C1, &C, &E); + + C = DSP1_Truncate(C, E); + + *An = C * DSP1.CosAas >> 15; + *Cn = C * DSP1.SinAas >> 15; + + DSP1_Normalize(C1 * DSP1.SecAZS_C2 >> 15, &C, &E1); + + C = DSP1_Truncate(C, E1); + + *Bn = C * -DSP1.SinAas >> 15; + *Dn = C * DSP1.CosAas >> 15; +} + +static void DSP1_Op02 (void) +{ + DSP1_Parameter(DSP1.Op02FX, DSP1.Op02FY, DSP1.Op02FZ, DSP1.Op02LFE, DSP1.Op02LES, DSP1.Op02AAS, DSP1.Op02AZS, &DSP1.Op02VOF, &DSP1.Op02VVA, &DSP1.Op02CX, &DSP1.Op02CY); +} + +static void DSP1_Op0A (void) +{ + DSP1_Raster(DSP1.Op0AVS, &DSP1.Op0AA, &DSP1.Op0AB, &DSP1.Op0AC, &DSP1.Op0AD); + DSP1.Op0AVS++; +} + +static int16 DSP1_ShiftR (int16 C, int16 E) +{ + return (C * DSP1ROM[0x0031 + E] >> 15); +} + +static void DSP1_Project (int16 X, int16 Y, int16 Z, int16 *H, int16 *V, int16 *M) +{ + int32 aux, aux4; + int16 E, E2, E3, E4, E5, refE, E6, E7; + int16 C2, C4, C6, C8, C9, C10, C11, C12, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26; + int16 Px, Py, Pz; + + E4 = E3 = E2 = E = E5 = 0; + + DSP1_NormalizeDouble((int32) X - DSP1.Gx, &Px, &E4); + DSP1_NormalizeDouble((int32) Y - DSP1.Gy, &Py, &E ); + DSP1_NormalizeDouble((int32) Z - DSP1.Gz, &Pz, &E3); + Px >>= 1; // to avoid overflows when calculating the scalar products + E4--; + Py >>= 1; + E--; + Pz >>= 1; + E3--; + + refE = (E < E3) ? E : E3; + refE = (refE < E4) ? refE : E4; + + Px = DSP1_ShiftR(Px, E4 - refE); // normalize them to the same exponent + Py = DSP1_ShiftR(Py, E - refE); + Pz = DSP1_ShiftR(Pz, E3 - refE); + + C11 =- (Px * DSP1.Nx >> 15); + C8 =- (Py * DSP1.Ny >> 15); + C9 =- (Pz * DSP1.Nz >> 15); + C12 = C11 + C8 + C9; // this cannot overflow! + + aux4 = C12; // de-normalization with 32-bits arithmetic + refE = 16 - refE; // refE can be up to 3 + if (refE >= 0) + aux4 <<= (refE); + else + aux4 >>= -(refE); + if (aux4 == -1) + aux4 = 0; // why? + aux4 >>= 1; + + aux = ((uint16) DSP1.G_Les) + aux4; // Les - the scalar product of P with the normal vector of the screen + DSP1_NormalizeDouble(aux, &C10, &E2); + E2 = 15 - E2; + + DSP1_Inverse(C10, 0, &C4, &E4); + C2 = C4 * DSP1.C_Les >> 15; // scale factor + + // H + E7 = 0; + C16 = Px * ( DSP1.CosAas * 0x7fff >> 15) >> 15; + C20 = Py * ( DSP1.SinAas * 0x7fff >> 15) >> 15; + C17 = C16 + C20; // scalar product of P with the normalized horizontal vector of the screen... + + C18 = C17 * C2 >> 15; // ... multiplied by the scale factor + DSP1_Normalize(C18, &C19, &E7); + *H = DSP1_Truncate(C19, DSP1.E_Les - E2 + refE + E7); + + // V + E6 = 0; + C21 = Px * ( DSP1.CosAzs * -DSP1.SinAas >> 15) >> 15; + C22 = Py * ( DSP1.CosAzs * DSP1.CosAas >> 15) >> 15; + C23 = Pz * (-DSP1.SinAzs * 0x7fff >> 15) >> 15; + C24 = C21 + C22 + C23; // scalar product of P with the normalized vertical vector of the screen... + + C26 = C24 * C2 >> 15; // ... multiplied by the scale factor + DSP1_Normalize(C26, &C25, &E6); + *V = DSP1_Truncate(C25, DSP1.E_Les - E2 + refE + E6); + + // M + DSP1_Normalize(C2, &C6, &E4); + *M = DSP1_Truncate(C6, E4 + DSP1.E_Les - E2 - 7); // M is the scale factor divided by 2^7 +} + +static void DSP1_Op06 (void) +{ + DSP1_Project(DSP1.Op06X, DSP1.Op06Y, DSP1.Op06Z, &DSP1.Op06H, &DSP1.Op06V, &DSP1.Op06M); +} + +static void DSP1_Op01 (void) +{ + int16 SinAz = DSP1_Sin(DSP1.Op01Zr); + int16 CosAz = DSP1_Cos(DSP1.Op01Zr); + int16 SinAy = DSP1_Sin(DSP1.Op01Yr); + int16 CosAy = DSP1_Cos(DSP1.Op01Yr); + int16 SinAx = DSP1_Sin(DSP1.Op01Xr); + int16 CosAx = DSP1_Cos(DSP1.Op01Xr); + + DSP1.Op01m >>= 1; + + DSP1.matrixA[0][0] = (DSP1.Op01m * CosAz >> 15) * CosAy >> 15; + DSP1.matrixA[0][1] = -((DSP1.Op01m * SinAz >> 15) * CosAy >> 15); + DSP1.matrixA[0][2] = DSP1.Op01m * SinAy >> 15; + + DSP1.matrixA[1][0] = ((DSP1.Op01m * SinAz >> 15) * CosAx >> 15) + (((DSP1.Op01m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixA[1][1] = ((DSP1.Op01m * CosAz >> 15) * CosAx >> 15) - (((DSP1.Op01m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixA[1][2] = -((DSP1.Op01m * SinAx >> 15) * CosAy >> 15); + + DSP1.matrixA[2][0] = ((DSP1.Op01m * SinAz >> 15) * SinAx >> 15) - (((DSP1.Op01m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixA[2][1] = ((DSP1.Op01m * CosAz >> 15) * SinAx >> 15) + (((DSP1.Op01m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixA[2][2] = (DSP1.Op01m * CosAx >> 15) * CosAy >> 15; +} + +static void DSP1_Op11 (void) +{ + int16 SinAz = DSP1_Sin(DSP1.Op11Zr); + int16 CosAz = DSP1_Cos(DSP1.Op11Zr); + int16 SinAy = DSP1_Sin(DSP1.Op11Yr); + int16 CosAy = DSP1_Cos(DSP1.Op11Yr); + int16 SinAx = DSP1_Sin(DSP1.Op11Xr); + int16 CosAx = DSP1_Cos(DSP1.Op11Xr); + + DSP1.Op11m >>= 1; + + DSP1.matrixB[0][0] = (DSP1.Op11m * CosAz >> 15) * CosAy >> 15; + DSP1.matrixB[0][1] = -((DSP1.Op11m * SinAz >> 15) * CosAy >> 15); + DSP1.matrixB[0][2] = DSP1.Op11m * SinAy >> 15; + + DSP1.matrixB[1][0] = ((DSP1.Op11m * SinAz >> 15) * CosAx >> 15) + (((DSP1.Op11m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixB[1][1] = ((DSP1.Op11m * CosAz >> 15) * CosAx >> 15) - (((DSP1.Op11m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixB[1][2] = -((DSP1.Op11m * SinAx >> 15) * CosAy >> 15); + + DSP1.matrixB[2][0] = ((DSP1.Op11m * SinAz >> 15) * SinAx >> 15) - (((DSP1.Op11m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixB[2][1] = ((DSP1.Op11m * CosAz >> 15) * SinAx >> 15) + (((DSP1.Op11m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixB[2][2] = (DSP1.Op11m * CosAx >> 15) * CosAy >> 15; +} + +static void DSP1_Op21 (void) +{ + int16 SinAz = DSP1_Sin(DSP1.Op21Zr); + int16 CosAz = DSP1_Cos(DSP1.Op21Zr); + int16 SinAy = DSP1_Sin(DSP1.Op21Yr); + int16 CosAy = DSP1_Cos(DSP1.Op21Yr); + int16 SinAx = DSP1_Sin(DSP1.Op21Xr); + int16 CosAx = DSP1_Cos(DSP1.Op21Xr); + + DSP1.Op21m >>= 1; + + DSP1.matrixC[0][0] = (DSP1.Op21m * CosAz >> 15) * CosAy >> 15; + DSP1.matrixC[0][1] = -((DSP1.Op21m * SinAz >> 15) * CosAy >> 15); + DSP1.matrixC[0][2] = DSP1.Op21m * SinAy >> 15; + + DSP1.matrixC[1][0] = ((DSP1.Op21m * SinAz >> 15) * CosAx >> 15) + (((DSP1.Op21m * CosAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixC[1][1] = ((DSP1.Op21m * CosAz >> 15) * CosAx >> 15) - (((DSP1.Op21m * SinAz >> 15) * SinAx >> 15) * SinAy >> 15); + DSP1.matrixC[1][2] = -((DSP1.Op21m * SinAx >> 15) * CosAy >> 15); + + DSP1.matrixC[2][0] = ((DSP1.Op21m * SinAz >> 15) * SinAx >> 15) - (((DSP1.Op21m * CosAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixC[2][1] = ((DSP1.Op21m * CosAz >> 15) * SinAx >> 15) + (((DSP1.Op21m * SinAz >> 15) * CosAx >> 15) * SinAy >> 15); + DSP1.matrixC[2][2] = (DSP1.Op21m * CosAx >> 15) * CosAy >> 15; +} + +static void DSP1_Op0D (void) +{ + DSP1.Op0DF = (DSP1.Op0DX * DSP1.matrixA[0][0] >> 15) + (DSP1.Op0DY * DSP1.matrixA[0][1] >> 15) + (DSP1.Op0DZ * DSP1.matrixA[0][2] >> 15); + DSP1.Op0DL = (DSP1.Op0DX * DSP1.matrixA[1][0] >> 15) + (DSP1.Op0DY * DSP1.matrixA[1][1] >> 15) + (DSP1.Op0DZ * DSP1.matrixA[1][2] >> 15); + DSP1.Op0DU = (DSP1.Op0DX * DSP1.matrixA[2][0] >> 15) + (DSP1.Op0DY * DSP1.matrixA[2][1] >> 15) + (DSP1.Op0DZ * DSP1.matrixA[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP0D X: %d Y: %d Z: %d / F: %d L: %d U: %d", DSP1.Op0DX, DSP1.Op0DY, DSP1.Op0DZ, DSP1.Op0DF, DSP1.Op0DL, DSP1.Op0DU); +#endif +} + +static void DSP1_Op1D (void) +{ + DSP1.Op1DF = (DSP1.Op1DX * DSP1.matrixB[0][0] >> 15) + (DSP1.Op1DY * DSP1.matrixB[0][1] >> 15) + (DSP1.Op1DZ * DSP1.matrixB[0][2] >> 15); + DSP1.Op1DL = (DSP1.Op1DX * DSP1.matrixB[1][0] >> 15) + (DSP1.Op1DY * DSP1.matrixB[1][1] >> 15) + (DSP1.Op1DZ * DSP1.matrixB[1][2] >> 15); + DSP1.Op1DU = (DSP1.Op1DX * DSP1.matrixB[2][0] >> 15) + (DSP1.Op1DY * DSP1.matrixB[2][1] >> 15) + (DSP1.Op1DZ * DSP1.matrixB[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP1D X: %d Y: %d Z: %d / F: %d L: %d U: %d", DSP1.Op1DX, DSP1.Op1DY, DSP1.Op1DZ, DSP1.Op1DF, DSP1.Op1DL, DSP1.Op1DU); +#endif +} + +static void DSP1_Op2D (void) +{ + DSP1.Op2DF = (DSP1.Op2DX * DSP1.matrixC[0][0] >> 15) + (DSP1.Op2DY * DSP1.matrixC[0][1] >> 15) + (DSP1.Op2DZ * DSP1.matrixC[0][2] >> 15); + DSP1.Op2DL = (DSP1.Op2DX * DSP1.matrixC[1][0] >> 15) + (DSP1.Op2DY * DSP1.matrixC[1][1] >> 15) + (DSP1.Op2DZ * DSP1.matrixC[1][2] >> 15); + DSP1.Op2DU = (DSP1.Op2DX * DSP1.matrixC[2][0] >> 15) + (DSP1.Op2DY * DSP1.matrixC[2][1] >> 15) + (DSP1.Op2DZ * DSP1.matrixC[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP2D X: %d Y: %d Z: %d / F: %d L: %d U: %d", DSP1.Op2DX, DSP1.Op2DY, DSP1.Op2DZ, DSP1.Op2DF, DSP1.Op2DL, DSP1.Op2DU); +#endif +} + +static void DSP1_Op03 (void) +{ + DSP1.Op03X = (DSP1.Op03F * DSP1.matrixA[0][0] >> 15) + (DSP1.Op03L * DSP1.matrixA[1][0] >> 15) + (DSP1.Op03U * DSP1.matrixA[2][0] >> 15); + DSP1.Op03Y = (DSP1.Op03F * DSP1.matrixA[0][1] >> 15) + (DSP1.Op03L * DSP1.matrixA[1][1] >> 15) + (DSP1.Op03U * DSP1.matrixA[2][1] >> 15); + DSP1.Op03Z = (DSP1.Op03F * DSP1.matrixA[0][2] >> 15) + (DSP1.Op03L * DSP1.matrixA[1][2] >> 15) + (DSP1.Op03U * DSP1.matrixA[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP03 F: %d L: %d U: %d / X: %d Y: %d Z: %d", DSP1.Op03F, DSP1.Op03L, DSP1.Op03U, DSP1.Op03X, DSP1.Op03Y, DSP1.Op03Z); +#endif +} + +static void DSP1_Op13 (void) +{ + DSP1.Op13X = (DSP1.Op13F * DSP1.matrixB[0][0] >> 15) + (DSP1.Op13L * DSP1.matrixB[1][0] >> 15) + (DSP1.Op13U * DSP1.matrixB[2][0] >> 15); + DSP1.Op13Y = (DSP1.Op13F * DSP1.matrixB[0][1] >> 15) + (DSP1.Op13L * DSP1.matrixB[1][1] >> 15) + (DSP1.Op13U * DSP1.matrixB[2][1] >> 15); + DSP1.Op13Z = (DSP1.Op13F * DSP1.matrixB[0][2] >> 15) + (DSP1.Op13L * DSP1.matrixB[1][2] >> 15) + (DSP1.Op13U * DSP1.matrixB[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP13 F: %d L: %d U: %d / X: %d Y: %d Z: %d", DSP1.Op13F, DSP1.Op13L, DSP1.Op13U, DSP1.Op13X, DSP1.Op13Y, DSP1.Op13Z); +#endif +} + +static void DSP1_Op23 (void) +{ + DSP1.Op23X = (DSP1.Op23F * DSP1.matrixC[0][0] >> 15) + (DSP1.Op23L * DSP1.matrixC[1][0] >> 15) + (DSP1.Op23U * DSP1.matrixC[2][0] >> 15); + DSP1.Op23Y = (DSP1.Op23F * DSP1.matrixC[0][1] >> 15) + (DSP1.Op23L * DSP1.matrixC[1][1] >> 15) + (DSP1.Op23U * DSP1.matrixC[2][1] >> 15); + DSP1.Op23Z = (DSP1.Op23F * DSP1.matrixC[0][2] >> 15) + (DSP1.Op23L * DSP1.matrixC[1][2] >> 15) + (DSP1.Op23U * DSP1.matrixC[2][2] >> 15); + +#ifdef DebugDSP1 + Log_Message("OP23 F: %d L: %d U: %d / X: %d Y: %d Z: %d", DSP1.Op23F, DSP1.Op23L, DSP1.Op23U, DSP1.Op23X, DSP1.Op23Y, DSP1.Op23Z); +#endif +} + +static void DSP1_Op14 (void) +{ + int16 CSec, ESec, CTan, CSin, C, E; + + DSP1_Inverse(DSP1_Cos(DSP1.Op14Xr), 0, &CSec, &ESec); + + // Rotation Around Z + DSP1_NormalizeDouble(DSP1.Op14U * DSP1_Cos(DSP1.Op14Yr) - DSP1.Op14F * DSP1_Sin(DSP1.Op14Yr), &C, &E); + + E = ESec - E; + + DSP1_Normalize(C * CSec >> 15, &C, &E); + + DSP1.Op14Zrr = DSP1.Op14Zr + DSP1_Truncate(C, E); + + // Rotation Around X + DSP1.Op14Xrr = DSP1.Op14Xr + (DSP1.Op14U * DSP1_Sin(DSP1.Op14Yr) >> 15) + (DSP1.Op14F * DSP1_Cos(DSP1.Op14Yr) >> 15); + + // Rotation Around Y + DSP1_NormalizeDouble(DSP1.Op14U * DSP1_Cos(DSP1.Op14Yr) + DSP1.Op14F * DSP1_Sin(DSP1.Op14Yr), &C, &E); + + E = ESec - E; + + DSP1_Normalize(DSP1_Sin(DSP1.Op14Xr), &CSin, &E); + + CTan = CSec * CSin >> 15; + + DSP1_Normalize(-(C * CTan >> 15), &C, &E); + + DSP1.Op14Yrr = DSP1.Op14Yr + DSP1_Truncate(C, E) + DSP1.Op14L; +} + +static void DSP1_Target (int16 H, int16 V, int16 *X, int16 *Y) +{ + int16 C, E, C1, E1; + + DSP1_Inverse((V * DSP1.SinAzs >> 15) + DSP1.VOffset, 8, &C, &E); + E += DSP1.VPlane_E; + + C1 = C * DSP1.VPlane_C >> 15; + E1 = E + DSP1.SecAZS_E1; + + H <<= 8; + + DSP1_Normalize(C1, &C, &E); + + C = DSP1_Truncate(C, E) * H >> 15; + + *X = DSP1.CentreX + (C * DSP1.CosAas >> 15); + *Y = DSP1.CentreY - (C * DSP1.SinAas >> 15); + + V <<= 8; + + DSP1_Normalize(C1 * DSP1.SecAZS_C1 >> 15, &C, &E1); + + C = DSP1_Truncate(C, E1) * V >> 15; + + *X += C * -DSP1.SinAas >> 15; + *Y += C * DSP1.CosAas >> 15; +} + +static void DSP1_Op0E (void) +{ + DSP1_Target(DSP1.Op0EH, DSP1.Op0EV, &DSP1.Op0EX, &DSP1.Op0EY); +} + +static void DSP1_Op0B (void) +{ + DSP1.Op0BS = (DSP1.Op0BX * DSP1.matrixA[0][0] + DSP1.Op0BY * DSP1.matrixA[0][1] + DSP1.Op0BZ * DSP1.matrixA[0][2]) >> 15; + +#ifdef DebugDSP1 + Log_Message("OP0B"); +#endif +} + +static void DSP1_Op1B (void) +{ + DSP1.Op1BS = (DSP1.Op1BX * DSP1.matrixB[0][0] + DSP1.Op1BY * DSP1.matrixB[0][1] + DSP1.Op1BZ * DSP1.matrixB[0][2]) >> 15; + +#ifdef DebugDSP1 + Log_Message("OP1B X: %d Y: %d Z: %d S: %d", DSP1.Op1BX, DSP1.Op1BY, DSP1.Op1BZ, DSP1.Op1BS); + Log_Message(" MX: %d MY: %d MZ: %d Scale: %d", (int16) (DSP1.matrixB[0][0] * 100), (int16) (DSP1.matrixB[0][1] * 100), (int16) (DSP1.matrixB[0][2] * 100), (int16) (DSP1.Op1BS * 100)); +#endif +} + +static void DSP1_Op2B (void) +{ + DSP1.Op2BS = (DSP1.Op2BX * DSP1.matrixC[0][0] + DSP1.Op2BY * DSP1.matrixC[0][1] + DSP1.Op2BZ * DSP1.matrixC[0][2]) >> 15; + +#ifdef DebugDSP1 + Log_Message("OP2B"); +#endif +} + +static void DSP1_Op08 (void) +{ + int32 op08Size = (DSP1.Op08X * DSP1.Op08X + DSP1.Op08Y * DSP1.Op08Y + DSP1.Op08Z * DSP1.Op08Z) << 1; + DSP1.Op08Ll = op08Size & 0xffff; + DSP1.Op08Lh = (op08Size >> 16) & 0xffff; + +#ifdef DebugDSP1 + Log_Message("OP08 %d,%d,%d", DSP1.Op08X, DSP1.Op08Y, DSP1.Op08Z); + Log_Message("OP08 ((OP08X^2)+(OP08Y^2)+(OP08Z^2))=%x", op08Size); +#endif +} + +static void DSP1_Op18 (void) +{ + DSP1.Op18D = (DSP1.Op18X * DSP1.Op18X + DSP1.Op18Y * DSP1.Op18Y + DSP1.Op18Z * DSP1.Op18Z - DSP1.Op18R * DSP1.Op18R) >> 15; + +#ifdef DebugDSP1 + Log_Message("OP18 X: %d Y: %d Z: %d R: %D DIFF %d", DSP1.Op18X, DSP1.Op18Y, DSP1.Op38Z, DSP1.Op18D); +#endif +} + +static void DSP1_Op38 (void) +{ + DSP1.Op38D = (DSP1.Op38X * DSP1.Op38X + DSP1.Op38Y * DSP1.Op38Y + DSP1.Op38Z * DSP1.Op38Z - DSP1.Op38R * DSP1.Op38R) >> 15; + DSP1.Op38D++; + +#ifdef DebugDSP1 + Log_Message("OP38 X: %d Y: %d Z: %d R: %D DIFF %d", DSP1.Op38X, DSP1.Op38Y, DSP1.Op38Z, DSP1.Op38D); +#endif +} + +static void DSP1_Op28 (void) +{ + int32 Radius = DSP1.Op28X * DSP1.Op28X + DSP1.Op28Y * DSP1.Op28Y + DSP1.Op28Z * DSP1.Op28Z; + + if (Radius == 0) + DSP1.Op28R = 0; + else + { + int16 C, E, Pos, Node1, Node2; + + DSP1_NormalizeDouble(Radius, &C, &E); + if (E & 1) + C = C * 0x4000 >> 15; + + Pos = C * 0x0040 >> 15; + + Node1 = DSP1ROM[0x00d5 + Pos]; + Node2 = DSP1ROM[0x00d6 + Pos]; + + DSP1.Op28R = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1; + DSP1.Op28R >>= (E >> 1); + } + +#ifdef DebugDSP1 + Log_Message("OP28 X:%d Y:%d Z:%d", DSP1.Op28X, DSP1.Op28Y, DSP1.Op28Z); + Log_Message("OP28 Vector Length %d", DSP1.Op28R); +#endif +} + +static void DSP1_Op1C (void) +{ + // Rotate Around Op1CZ1 + DSP1.Op1CX1 = (DSP1.Op1CYBR * DSP1_Sin(DSP1.Op1CZ) >> 15) + (DSP1.Op1CXBR * DSP1_Cos(DSP1.Op1CZ) >> 15); + DSP1.Op1CY1 = (DSP1.Op1CYBR * DSP1_Cos(DSP1.Op1CZ) >> 15) - (DSP1.Op1CXBR * DSP1_Sin(DSP1.Op1CZ) >> 15); + DSP1.Op1CXBR = DSP1.Op1CX1; + DSP1.Op1CYBR = DSP1.Op1CY1; + + // Rotate Around Op1CY1 + DSP1.Op1CZ1 = (DSP1.Op1CXBR * DSP1_Sin(DSP1.Op1CY) >> 15) + (DSP1.Op1CZBR * DSP1_Cos(DSP1.Op1CY) >> 15); + DSP1.Op1CX1 = (DSP1.Op1CXBR * DSP1_Cos(DSP1.Op1CY) >> 15) - (DSP1.Op1CZBR * DSP1_Sin(DSP1.Op1CY) >> 15); + DSP1.Op1CXAR = DSP1.Op1CX1; + DSP1.Op1CZBR = DSP1.Op1CZ1; + + // Rotate Around Op1CX1 + DSP1.Op1CY1 = (DSP1.Op1CZBR * DSP1_Sin(DSP1.Op1CX) >> 15) + (DSP1.Op1CYBR * DSP1_Cos(DSP1.Op1CX) >> 15); + DSP1.Op1CZ1 = (DSP1.Op1CZBR * DSP1_Cos(DSP1.Op1CX) >> 15) - (DSP1.Op1CYBR * DSP1_Sin(DSP1.Op1CX) >> 15); + DSP1.Op1CYAR = DSP1.Op1CY1; + DSP1.Op1CZAR = DSP1.Op1CZ1; + +#ifdef DebugDSP1 + Log_Message("OP1C Apply Matrix CX:%d CY:%d CZ", DSP1.Op1CXAR, DSP1.Op1CYAR, DSP1.Op1CZAR); +#endif +} + +static void DSP1_Op0F (void) +{ + DSP1.Op0FPass = 0x0000; + +#ifdef DebugDSP1 + Log_Message("OP0F RAM Test Pass:%d", DSP1.Op0FPass); +#endif +} + +static void DSP1_Op2F (void) +{ + DSP1.Op2FSize = 0x100; +} + +void DSP1SetByte (uint8 byte, uint16 address) +{ + if (address < DSP0.boundary) + { + 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; + #ifdef DEBUGGER + //printf("OP%02X\n",byte); + #endif + + 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; + default: + #ifdef DEBUGGER + //printf("OP%02X\n", byte); + #endif + 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.in_count) + { + 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 + DSP1.Op00Multiplicand = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op00Multiplier = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + + DSP1_Op00(); + + DSP1.out_count = 2; + DSP1.output[0] = DSP1.Op00Result & 0xFF; + DSP1.output[1] = (DSP1.Op00Result >> 8) & 0xFF; + break; + + case 0x20: // Multiple + DSP1.Op20Multiplicand = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op20Multiplier = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + + DSP1_Op20(); + + DSP1.out_count = 2; + DSP1.output[0] = DSP1.Op20Result & 0xFF; + DSP1.output[1] = (DSP1.Op20Result >> 8) & 0xFF; + break; + + case 0x30: + case 0x10: // Inverse + DSP1.Op10Coefficient = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op10Exponent = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + + DSP1_Op10(); + + DSP1.out_count = 4; + DSP1.output[0] = (uint8) ( ((int16) DSP1.Op10CoefficientR) & 0xFF); + DSP1.output[1] = (uint8) ((((int16) DSP1.Op10CoefficientR) >> 8) & 0xFF); + DSP1.output[2] = (uint8) ( ((int16) DSP1.Op10ExponentR ) & 0xFF); + DSP1.output[3] = (uint8) ((((int16) DSP1.Op10ExponentR ) >> 8) & 0xFF); + break; + + case 0x24: + case 0x04: // Sin and Cos of angle + DSP1.Op04Angle = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op04Radius = (uint16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + + DSP1_Op04(); + + DSP1.out_count = 4; + DSP1.output[0] = (uint8) (DSP1.Op04Sin & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op04Sin >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op04Cos & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op04Cos >> 8) & 0xFF); + break; + + case 0x08: // Radius + DSP1.Op08X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op08Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op08Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op08(); + + DSP1.out_count = 4; + DSP1.output[0] = (uint8) ( ((int16) DSP1.Op08Ll) & 0xFF); + DSP1.output[1] = (uint8) ((((int16) DSP1.Op08Ll) >> 8) & 0xFF); + DSP1.output[2] = (uint8) ( ((int16) DSP1.Op08Lh) & 0xFF); + DSP1.output[3] = (uint8) ((((int16) DSP1.Op08Lh) >> 8) & 0xFF); + break; + + case 0x18: // Range + + DSP1.Op18X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op18Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op18Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + DSP1.Op18R = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); + + DSP1_Op18(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op18D & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op18D >> 8) & 0xFF); + break; + + case 0x38: // Range + + DSP1.Op38X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op38Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op38Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + DSP1.Op38R = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); + + DSP1_Op38(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op38D & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op38D >> 8) & 0xFF); + break; + + case 0x28: // Distance (vector length) + DSP1.Op28X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op28Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op28Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op28(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op28R & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op28R >> 8) & 0xFF); + break; + + case 0x2c: + case 0x0c: // Rotate (2D rotate) + DSP1.Op0CA = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op0CX1 = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op0CY1 = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op0C(); + + DSP1.out_count = 4; + DSP1.output[0] = (uint8) (DSP1.Op0CX2 & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op0CX2 >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op0CY2 & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op0CY2 >> 8) & 0xFF); + break; + + case 0x3c: + case 0x1c: // Polar (3D rotate) + DSP1.Op1CZ = (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8)); + //MK: reversed X and Y on neviksti and John's advice. + DSP1.Op1CY = (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8)); + DSP1.Op1CX = (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8)); + DSP1.Op1CXBR = (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8)); + DSP1.Op1CYBR = (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8)); + DSP1.Op1CZBR = (DSP1.parameters[10] | (DSP1.parameters[11] << 8)); + + DSP1_Op1C(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op1CXAR & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op1CXAR >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op1CYAR & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op1CYAR >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op1CZAR & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op1CZAR >> 8) & 0xFF); + break; + + case 0x32: + case 0x22: + case 0x12: + case 0x02: // Parameter (Projection) + DSP1.Op02FX = (int16) (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8)); + DSP1.Op02FY = (int16) (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8)); + DSP1.Op02FZ = (int16) (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8)); + DSP1.Op02LFE = (int16) (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8)); + DSP1.Op02LES = (int16) (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8)); + DSP1.Op02AAS = (uint16) (DSP1.parameters[10] | (DSP1.parameters[11] << 8)); + DSP1.Op02AZS = (uint16) (DSP1.parameters[12] | (DSP1.parameters[13] << 8)); + + DSP1_Op02(); + + DSP1.out_count = 8; + DSP1.output[0] = (uint8) (DSP1.Op02VOF & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op02VOF >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op02VVA & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op02VVA >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op02CX & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op02CX >> 8) & 0xFF); + DSP1.output[6] = (uint8) (DSP1.Op02CY & 0xFF); + DSP1.output[7] = (uint8) ((DSP1.Op02CY >> 8) & 0xFF); + break; + + case 0x3a: + case 0x2a: + case 0x1a: // Raster mode 7 matrix data + case 0x0a: + DSP1.Op0AVS = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + + DSP1_Op0A(); + + DSP1.out_count = 8; + DSP1.output[0] = (uint8) (DSP1.Op0AA & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op0AA >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op0AB & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op0AB >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op0AC & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op0AC >> 8) & 0xFF); + DSP1.output[6] = (uint8) (DSP1.Op0AD & 0xFF); + DSP1.output[7] = (uint8) ((DSP1.Op0AD >> 8) & 0xFF); + DSP1.in_index = 0; + break; + + case 0x16: + case 0x26: + case 0x36: + case 0x06: // Project object + DSP1.Op06X = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op06Y = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op06Z = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op06(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op06H & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op06H >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op06V & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op06V >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op06M & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op06M >> 8) & 0xFF); + break; + + case 0x1e: + case 0x2e: + case 0x3e: + case 0x0e: // Target + DSP1.Op0EH = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op0EV = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + + DSP1_Op0E(); + + DSP1.out_count = 4; + DSP1.output[0] = (uint8) (DSP1.Op0EX & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op0EX >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op0EY & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op0EY >> 8) & 0xFF); + break; + + // Extra commands used by Pilot Wings + case 0x05: + case 0x35: + case 0x31: + case 0x01: // Set attitude matrix A + DSP1.Op01m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op01Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op01Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + DSP1.Op01Xr = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); + + DSP1_Op01(); + break; + + case 0x15: + case 0x11: // Set attitude matrix B + DSP1.Op11m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op11Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op11Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + DSP1.Op11Xr = (int16) (DSP1.parameters[7] | (DSP1.parameters[7] << 8)); + + DSP1_Op11(); + break; + + case 0x25: + case 0x21: // Set attitude matrix C + DSP1.Op21m = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op21Zr = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op21Yr = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + DSP1.Op21Xr = (int16) (DSP1.parameters[6] | (DSP1.parameters[7] << 8)); + + DSP1_Op21(); + break; + + case 0x09: + case 0x39: + case 0x3d: + case 0x0d: // Objective matrix A + DSP1.Op0DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op0DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op0DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op0D(); + + DSP1.out_count = 6; + DSP1.output [0] = (uint8) (DSP1.Op0DF & 0xFF); + DSP1.output [1] = (uint8) ((DSP1.Op0DF >> 8) & 0xFF); + DSP1.output [2] = (uint8) (DSP1.Op0DL & 0xFF); + DSP1.output [3] = (uint8) ((DSP1.Op0DL >> 8) & 0xFF); + DSP1.output [4] = (uint8) (DSP1.Op0DU & 0xFF); + DSP1.output [5] = (uint8) ((DSP1.Op0DU >> 8) & 0xFF); + break; + + case 0x19: + case 0x1d: // Objective matrix B + DSP1.Op1DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op1DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op1DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op1D(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op1DF & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op1DF >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op1DL & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op1DL >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op1DU & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op1DU >> 8) & 0xFF); + break; + + case 0x29: + case 0x2d: // Objective matrix C + DSP1.Op2DX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op2DY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op2DZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op2D(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op2DF & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op2DF >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op2DL & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op2DL >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op2DU & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op2DU >> 8) & 0xFF); + break; + + case 0x33: + case 0x03: // Subjective matrix A + DSP1.Op03F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op03L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op03U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op03(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op03X & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op03X >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op03Y & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op03Y >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op03Z & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op03Z >> 8) & 0xFF); + break; + + case 0x13: // Subjective matrix B + DSP1.Op13F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op13L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op13U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op13(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op13X & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op13X >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op13Y & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op13Y >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op13Z & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op13Z >> 8) & 0xFF); + break; + + case 0x23: // Subjective matrix C + DSP1.Op23F = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op23L = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op23U = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op23(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op23X & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op23X >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op23Y & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op23Y >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op23Z & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op23Z >> 8) & 0xFF); + break; + + case 0x3b: + case 0x0b: + DSP1.Op0BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op0BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op0BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op0B(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op0BS & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op0BS >> 8) & 0xFF); + break; + + case 0x1b: + DSP1.Op1BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op1BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op1BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op1B(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op1BS & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op1BS >> 8) & 0xFF); + break; + + case 0x2b: + DSP1.Op2BX = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + DSP1.Op2BY = (int16) (DSP1.parameters[2] | (DSP1.parameters[3] << 8)); + DSP1.Op2BZ = (int16) (DSP1.parameters[4] | (DSP1.parameters[5] << 8)); + + DSP1_Op2B(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op2BS & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op2BS >> 8) & 0xFF); + break; + + case 0x34: + case 0x14: + DSP1.Op14Zr = (int16) (DSP1.parameters[ 0] | (DSP1.parameters[ 1] << 8)); + DSP1.Op14Xr = (int16) (DSP1.parameters[ 2] | (DSP1.parameters[ 3] << 8)); + DSP1.Op14Yr = (int16) (DSP1.parameters[ 4] | (DSP1.parameters[ 5] << 8)); + DSP1.Op14U = (int16) (DSP1.parameters[ 6] | (DSP1.parameters[ 7] << 8)); + DSP1.Op14F = (int16) (DSP1.parameters[ 8] | (DSP1.parameters[ 9] << 8)); + DSP1.Op14L = (int16) (DSP1.parameters[10] | (DSP1.parameters[11] << 8)); + + DSP1_Op14(); + + DSP1.out_count = 6; + DSP1.output[0] = (uint8) (DSP1.Op14Zrr & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op14Zrr >> 8) & 0xFF); + DSP1.output[2] = (uint8) (DSP1.Op14Xrr & 0xFF); + DSP1.output[3] = (uint8) ((DSP1.Op14Xrr >> 8) & 0xFF); + DSP1.output[4] = (uint8) (DSP1.Op14Yrr & 0xFF); + DSP1.output[5] = (uint8) ((DSP1.Op14Yrr >> 8) & 0xFF); + break; + + case 0x27: + case 0x2F: + DSP1.Op2FUnknown = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + + DSP1_Op2F(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op2FSize & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op2FSize >> 8) & 0xFF); + break; + + + case 0x07: + case 0x0F: + DSP1.Op0FRamsize = (int16) (DSP1.parameters[0] | (DSP1.parameters[1] << 8)); + + DSP1_Op0F(); + + DSP1.out_count = 2; + DSP1.output[0] = (uint8) (DSP1.Op0FPass & 0xFF); + DSP1.output[1] = (uint8) ((DSP1.Op0FPass >> 8) & 0xFF); + break; + + default: + break; + } + } + } + } + } +} + +uint8 DSP1GetByte (uint16 address) +{ + uint8 t; + + if (address < DSP0.boundary) + { + if (DSP1.out_count) + { + t = (uint8) DSP1.output[DSP1.out_index]; + + DSP1.out_index++; + + if (--DSP1.out_count == 0) + { + if (DSP1.command == 0x1a || DSP1.command == 0x0a) + { + DSP1_Op0A(); + DSP1.out_count = 8; + DSP1.out_index = 0; + DSP1.output[0] = DSP1.Op0AA & 0xFF; + DSP1.output[1] = (DSP1.Op0AA >> 8) & 0xFF; + DSP1.output[2] = DSP1.Op0AB & 0xFF; + DSP1.output[3] = (DSP1.Op0AB >> 8) & 0xFF; + DSP1.output[4] = DSP1.Op0AC & 0xFF; + DSP1.output[5] = (DSP1.Op0AC >> 8) & 0xFF; + DSP1.output[6] = DSP1.Op0AD & 0xFF; + DSP1.output[7] = (DSP1.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 + t = 0xff; + } + else + t = 0x80; + + return (t); +} diff --git a/dsp2.cpp b/dsp2.cpp new file mode 100644 index 00000000..477209b4 --- /dev/null +++ b/dsp2.cpp @@ -0,0 +1,532 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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" + +static void DSP2_Op01 (void); +static void DSP2_Op03 (void); +static void DSP2_Op05 (void); +static void DSP2_Op06 (void); +static void DSP2_Op09 (void); +static void DSP2_Op0D (void); + + +// convert bitmap to bitplane tile +static void DSP2_Op01 (void) +{ + // Op01 size is always 32 bytes input and output + // The hardware does strange things if you vary the size + + uint8 c0, c1, c2, c3; + uint8 *p1 = DSP2.parameters; + uint8 *p2a = DSP2.output; + uint8 *p2b = DSP2.output + 16; // halfway + + // Process 8 blocks of 4 bytes each + + for (int j = 0; j < 8; j++) + { + c0 = *p1++; + c1 = *p1++; + c2 = *p1++; + c3 = *p1++; + + *p2a++ = (c0 & 0x10) << 3 | + (c0 & 0x01) << 6 | + (c1 & 0x10) << 1 | + (c1 & 0x01) << 4 | + (c2 & 0x10) >> 1 | + (c2 & 0x01) << 2 | + (c3 & 0x10) >> 3 | + (c3 & 0x01); + + *p2a++ = (c0 & 0x20) << 2 | + (c0 & 0x02) << 5 | + (c1 & 0x20) | + (c1 & 0x02) << 3 | + (c2 & 0x20) >> 2 | + (c2 & 0x02) << 1 | + (c3 & 0x20) >> 4 | + (c3 & 0x02) >> 1; + + *p2b++ = (c0 & 0x40) << 1 | + (c0 & 0x04) << 4 | + (c1 & 0x40) >> 1 | + (c1 & 0x04) << 2 | + (c2 & 0x40) >> 3 | + (c2 & 0x04) | + (c3 & 0x40) >> 5 | + (c3 & 0x04) >> 2; + + *p2b++ = (c0 & 0x80) | + (c0 & 0x08) << 3 | + (c1 & 0x80) >> 2 | + (c1 & 0x08) << 1 | + (c2 & 0x80) >> 4 | + (c2 & 0x08) >> 1 | + (c3 & 0x80) >> 6 | + (c3 & 0x08) >> 3; + } +} + +// set transparent color +static void DSP2_Op03 (void) +{ + DSP2.Op05Transparent = DSP2.parameters[0]; +} + +// replace bitmap using transparent color +static void DSP2_Op05 (void) +{ + // Overlay bitmap with transparency. + // Input: + // + // Bitmap 1: i[0] <=> i[size-1] + // Bitmap 2: i[size] <=> i[2*size-1] + // + // Output: + // + // Bitmap 3: o[0] <=> o[size-1] + // + // Processing: + // + // Process all 4-bit pixels (nibbles) in the bitmap + // + // if ( BM2_pixel == transparent_color ) + // pixelout = BM1_pixel + // else + // pixelout = BM2_pixel + + // The max size bitmap is limited to 255 because the size parameter is a byte + // I think size=0 is an error. The behavior of the chip on size=0 is to + // return the last value written to DR if you read DR on Op05 with + // size = 0. I don't think it's worth implementing this quirk unless it's + // proven necessary. + + uint8 color; + uint8 c1, c2; + uint8 *p1 = DSP2.parameters; + uint8 *p2 = DSP2.parameters + DSP2.Op05Len; + uint8 *p3 = DSP2.output; + + color = DSP2.Op05Transparent & 0x0f; + + for (int32 n = 0; n < DSP2.Op05Len; n++) + { + c1 = *p1++; + c2 = *p2++; + *p3++ = (((c2 >> 4) == color) ? c1 & 0xf0: c2 & 0xf0) | (((c2 & 0x0f) == color) ? c1 & 0x0f: c2 & 0x0f); + } +} + +// reverse bitmap +static void DSP2_Op06 (void) +{ + // Input: + // size + // bitmap + + for (int32 i = 0, j = DSP2.Op06Len - 1; i < DSP2.Op06Len; i++, j--) + DSP2.output[j] = (DSP2.parameters[i] << 4) | (DSP2.parameters[i] >> 4); +} + +// multiply +static void DSP2_Op09 (void) +{ + DSP2.Op09Word1 = DSP2.parameters[0] | (DSP2.parameters[1] << 8); + DSP2.Op09Word2 = DSP2.parameters[2] | (DSP2.parameters[3] << 8); + + uint32 temp = DSP2.Op09Word1 * DSP2.Op09Word2; + DSP2.output[0] = temp & 0xFF; + DSP2.output[1] = (temp >> 8) & 0xFF; + DSP2.output[2] = (temp >> 16) & 0xFF; + DSP2.output[3] = (temp >> 24) & 0xFF; +} + +// scale bitmap +static void DSP2_Op0D (void) +{ + // Bit accurate hardware algorithm - uses fixed point math + // This should match the DSP2 Op0D output exactly + // I wouldn't recommend using this unless you're doing hardware debug. + // In some situations it has small visual artifacts that + // are not readily apparent on a TV screen but show up clearly + // on a monitor. Use Overload's scaling instead. + // This is for hardware verification testing. + // + // One note: the HW can do odd byte scaling but since we divide + // by two to get the count of bytes this won't work well for + // odd byte scaling (in any of the current algorithm implementations). + // So far I haven't seen Dungeon Master use it. + // If it does we can adjust the parameters and code to work with it + + uint32 multiplier; // Any size int >= 32-bits + uint32 pixloc; // match size of multiplier + uint8 pixelarray[512]; + + if (DSP2.Op0DInLen <= DSP2.Op0DOutLen) + multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1 + else + multiplier = (DSP2.Op0DInLen << 17) / ((DSP2.Op0DOutLen << 1) + 1); + + pixloc = 0; + + for (int32 i = 0; i < DSP2.Op0DOutLen * 2; i++) + { + int32 j = pixloc >> 16; + + if (j & 1) + pixelarray[i] = DSP2.parameters[j >> 1] & 0x0f; + else + pixelarray[i] = (DSP2.parameters[j >> 1] & 0xf0) >> 4; + + pixloc += multiplier; + } + + for (int32 i = 0; i < DSP2.Op0DOutLen; i++) + DSP2.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; +} + +/* +static void DSP2_Op0D (void) +{ + // Overload's algorithm - use this unless doing hardware testing + + // One note: the HW can do odd byte scaling but since we divide + // by two to get the count of bytes this won't work well for + // odd byte scaling (in any of the current algorithm implementations). + // So far I haven't seen Dungeon Master use it. + // If it does we can adjust the parameters and code to work with it + + int32 pixel_offset; + uint8 pixelarray[512]; + + for (int32 i = 0; i < DSP2.Op0DOutLen * 2; i++) + { + pixel_offset = (i * DSP2.Op0DInLen) / DSP2.Op0DOutLen; + + if ((pixel_offset & 1) == 0) + pixelarray[i] = DSP2.parameters[pixel_offset >> 1] >> 4; + else + pixelarray[i] = DSP2.parameters[pixel_offset >> 1] & 0x0f; + } + + for (int32 i = 0; i < DSP2.Op0DOutLen; i++) + DSP2.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; +} +*/ + +void DSP2SetByte (uint8 byte, uint16 address) +{ + if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) + { + if (DSP2.waiting4command) + { + DSP2.command = byte; + DSP2.in_index = 0; + DSP2.waiting4command = FALSE; + + switch (byte) + { + case 0x01: DSP2.in_count = 32; break; + case 0x03: DSP2.in_count = 1; break; + case 0x05: DSP2.in_count = 1; break; + case 0x06: DSP2.in_count = 1; break; + case 0x09: DSP2.in_count = 4; break; + case 0x0D: DSP2.in_count = 2; break; + default: + #ifdef DEBUGGER + //printf("Op%02X\n", byte); + #endif + case 0x0f: DSP2.in_count = 0; break; + } + } + else + { + DSP2.parameters[DSP2.in_index] = byte; + DSP2.in_index++; + } + + if (DSP2.in_count == DSP2.in_index) + { + DSP2.waiting4command = TRUE; + DSP2.out_index = 0; + + switch (DSP2.command) + { + case 0x01: + DSP2.out_count = 32; + DSP2_Op01(); + break; + + case 0x03: + DSP2_Op03(); + break; + + case 0x05: + if (DSP2.Op05HasLen) + { + DSP2.Op05HasLen = FALSE; + DSP2.out_count = DSP2.Op05Len; + DSP2_Op05(); + } + else + { + DSP2.Op05Len = DSP2.parameters[0]; + DSP2.in_index = 0; + DSP2.in_count = 2 * DSP2.Op05Len; + DSP2.Op05HasLen = TRUE; + if (byte) + DSP2.waiting4command = FALSE; + } + + break; + + case 0x06: + if (DSP2.Op06HasLen) + { + DSP2.Op06HasLen = FALSE; + DSP2.out_count = DSP2.Op06Len; + DSP2_Op06(); + } + else + { + DSP2.Op06Len = DSP2.parameters[0]; + DSP2.in_index = 0; + DSP2.in_count = DSP2.Op06Len; + DSP2.Op06HasLen = TRUE; + if (byte) + DSP2.waiting4command = FALSE; + } + + break; + + case 0x09: + DSP2.out_count = 4; + DSP2_Op09(); + break; + + case 0x0D: + if (DSP2.Op0DHasLen) + { + DSP2.Op0DHasLen = FALSE; + DSP2.out_count = DSP2.Op0DOutLen; + DSP2_Op0D(); + } + else + { + DSP2.Op0DInLen = DSP2.parameters[0]; + DSP2.Op0DOutLen = DSP2.parameters[1]; + DSP2.in_index = 0; + DSP2.in_count = (DSP2.Op0DInLen + 1) >> 1; + DSP2.Op0DHasLen = TRUE; + if (byte) + DSP2.waiting4command = FALSE; + } + + break; + + case 0x0f: + default: + break; + } + } + } +} + +uint8 DSP2GetByte (uint16 address) +{ + uint8 t; + + if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) + { + if (DSP2.out_count) + { + t = (uint8) DSP2.output[DSP2.out_index]; + DSP2.out_index++; + if (DSP2.out_count == DSP2.out_index) + DSP2.out_count = 0; + } + else + t = 0xff; + } + else + t = 0x80; + + return (t); +} diff --git a/dsp3.cpp b/dsp3.cpp new file mode 100644 index 00000000..5c792403 --- /dev/null +++ b/dsp3.cpp @@ -0,0 +1,1268 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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" + +static void (*SetDSP3) (void); + +static const uint16 DSP3_DataROM[1024] = +{ + 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, + 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001, + 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, + 0x0000, 0x000f, 0x0400, 0x0200, 0x0140, 0x0400, 0x0200, 0x0040, + 0x007d, 0x007e, 0x007e, 0x007b, 0x007c, 0x007d, 0x007b, 0x007c, + 0x0002, 0x0020, 0x0030, 0x0000, 0x000d, 0x0019, 0x0026, 0x0032, + 0x003e, 0x004a, 0x0056, 0x0062, 0x006d, 0x0079, 0x0084, 0x008e, + 0x0098, 0x00a2, 0x00ac, 0x00b5, 0x00be, 0x00c6, 0x00ce, 0x00d5, + 0x00dc, 0x00e2, 0x00e7, 0x00ec, 0x00f1, 0x00f5, 0x00f8, 0x00fb, + 0x00fd, 0x00ff, 0x0100, 0x0100, 0x0100, 0x00ff, 0x00fd, 0x00fb, + 0x00f8, 0x00f5, 0x00f1, 0x00ed, 0x00e7, 0x00e2, 0x00dc, 0x00d5, + 0x00ce, 0x00c6, 0x00be, 0x00b5, 0x00ac, 0x00a2, 0x0099, 0x008e, + 0x0084, 0x0079, 0x006e, 0x0062, 0x0056, 0x004a, 0x003e, 0x0032, + 0x0026, 0x0019, 0x000d, 0x0000, 0xfff3, 0xffe7, 0xffdb, 0xffce, + 0xffc2, 0xffb6, 0xffaa, 0xff9e, 0xff93, 0xff87, 0xff7d, 0xff72, + 0xff68, 0xff5e, 0xff54, 0xff4b, 0xff42, 0xff3a, 0xff32, 0xff2b, + 0xff25, 0xff1e, 0xff19, 0xff14, 0xff0f, 0xff0b, 0xff08, 0xff05, + 0xff03, 0xff01, 0xff00, 0xff00, 0xff00, 0xff01, 0xff03, 0xff05, + 0xff08, 0xff0b, 0xff0f, 0xff13, 0xff18, 0xff1e, 0xff24, 0xff2b, + 0xff32, 0xff3a, 0xff42, 0xff4b, 0xff54, 0xff5d, 0xff67, 0xff72, + 0xff7c, 0xff87, 0xff92, 0xff9e, 0xffa9, 0xffb5, 0xffc2, 0xffce, + 0xffda, 0xffe7, 0xfff3, 0x002b, 0x007f, 0x0020, 0x00ff, 0xff00, + 0xffbe, 0x0000, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0x0045, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffc5, 0x0003, 0x0004, 0x0005, 0x0047, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008, + 0x0009, 0x004a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x004e, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011, + 0x0012, 0x0013, 0x0014, 0x0053, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, + 0x0059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e, + 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0060, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, + 0x002b, 0x002c, 0x0068, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0071, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, + 0x003e, 0x003f, 0x0040, 0x0041, 0x007b, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, + 0x000b, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, + 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0050, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b, + 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x005d, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, + 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, + 0x006b, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, + 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0044, 0x0000, 0x0000, + 0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, + 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, + 0x001f, 0x0020, 0x0054, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, + 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0065, + 0xffbe, 0x0000, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0xfead, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffc5, 0x0003, 0x0004, 0x0005, 0xfeaf, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008, + 0x0009, 0xfeb2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0xfeb6, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011, + 0x0012, 0x0013, 0x0014, 0xfebb, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, + 0xfec1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e, + 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0xfec8, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, + 0x002b, 0x002c, 0xfed0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0xfed9, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, + 0x003e, 0x003f, 0x0040, 0x0041, 0xfee3, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, + 0x000b, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, + 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0xfeb8, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b, + 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0xfec5, 0x0000, 0x0000, 0x0000, 0x0000, + 0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, + 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, + 0xfed3, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002, + 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, + 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0xfeac, 0x0000, 0x0000, + 0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, + 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, + 0x001f, 0x0020, 0xfebc, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, + 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0xfecd, + 0x0154, 0x0218, 0x0110, 0x00b0, 0x00cc, 0x00b0, 0x0088, 0x00b0, + 0x0044, 0x00b0, 0x0000, 0x00b0, 0x00fe, 0xff07, 0x0002, 0x00ff, + 0x00f8, 0x0007, 0x00fe, 0x00ee, 0x07ff, 0x0200, 0x00ef, 0xf800, + 0x0700, 0x00ee, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, + 0xffff, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, + 0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0x0001, 0x0000, 0x0001, + 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, + 0xffff, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, + 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0044, 0x0088, 0x00cc, + 0x0110, 0x0154, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff +}; + +static bool8 DSP3_GetBits (uint8); +//static void DSP3_MemorySize (void); +static void DSP3_TestMemory (void); +static void DSP3_DumpDataROM (void); +static void DSP3_MemoryDump (void); +static void DSP3_Coordinate (void); +static void DSP3_Command (void); +static void DSP3_Decode_Data (void); +static void DSP3_Decode_Tree (void); +static void DSP3_Decode_Symbols (void); +static void DSP3_Decode (void); +static void DSP3_Decode_A (void); +static void DSP3_Convert (void); +static void DSP3_Convert_A (void); +static void DSP3_OP03 (void); +static void DSP3_OP06 (void); +static void DSP3_OP07 (void); +static void DSP3_OP07_A (void); +static void DSP3_OP07_B (void); +static void DSP3_OP0C (void); +//static void DSP3_OP0C_A (void); +static void DSP3_OP10 (void); +static void DSP3_OP1C (void); +static void DSP3_OP1C_A (void); +static void DSP3_OP1C_B (void); +static void DSP3_OP1C_C (void); +static void DSP3_OP1E (void); +static void DSP3_OP1E_A (void); +static void DSP3_OP1E_A1 (void); +static void DSP3_OP1E_A2 (void); +static void DSP3_OP1E_A3 (void); +static void DSP3_OP1E_B (void); +static void DSP3_OP1E_B1 (void); +static void DSP3_OP1E_B2 (void); +static void DSP3_OP1E_C (void); +static void DSP3_OP1E_C1 (void); +static void DSP3_OP1E_C2 (void); +static void DSP3_OP1E_D (int16, int16 *, int16 *); +static void DSP3_OP1E_D1 (int16, int16 *, int16 *); +static void DSP3_OP3E (void); + + +void DSP3_Reset (void) +{ + DSP3.DR = 0x0080; + DSP3.SR = 0x0084; + SetDSP3 = &DSP3_Command; +} + +/* +static void DSP3_MemorySize (void) +{ + DSP3.DR = 0x0300; + SetDSP3 = &DSP3_Reset; +} +*/ + +static void DSP3_TestMemory (void) +{ + DSP3.DR = 0x0000; + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_DumpDataROM (void) +{ + DSP3.DR = DSP3_DataROM[DSP3.MemoryIndex++]; + if (DSP3.MemoryIndex == 1024) + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_MemoryDump (void) +{ + DSP3.MemoryIndex = 0; + SetDSP3 = &DSP3_DumpDataROM; + DSP3_DumpDataROM(); +} + +static void DSP3_OP06 (void) +{ + DSP3.WinLo = (uint8) (DSP3.DR); + DSP3.WinHi = (uint8) (DSP3.DR >> 8); + DSP3_Reset(); +} + +static void DSP3_OP03 (void) +{ + int16 Lo = (uint8) (DSP3.DR); + int16 Hi = (uint8) (DSP3.DR >> 8); + int16 Ofs = (DSP3.WinLo * Hi << 1) + (Lo << 1); + + DSP3.DR = Ofs >> 1; + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_OP07_B (void) +{ + int16 Ofs = (DSP3.WinLo * DSP3.AddHi << 1) + (DSP3.AddLo << 1); + + DSP3.DR = Ofs >> 1; + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_OP07_A (void) +{ + int16 Lo = (uint8) (DSP3.DR); + int16 Hi = (uint8) (DSP3.DR >> 8); + + if (Lo & 1) + Hi += (DSP3.AddLo & 1); + + DSP3.AddLo += Lo; + DSP3.AddHi += Hi; + + if (DSP3.AddLo < 0) + DSP3.AddLo += DSP3.WinLo; + else + if (DSP3.AddLo >= DSP3.WinLo) + DSP3.AddLo -= DSP3.WinLo; + + if (DSP3.AddHi < 0) + DSP3.AddHi += DSP3.WinHi; + else + if (DSP3.AddHi >= DSP3.WinHi) + DSP3.AddHi -= DSP3.WinHi; + + DSP3.DR = DSP3.AddLo | (DSP3.AddHi << 8) | ((DSP3.AddHi >> 8) & 0xff); + SetDSP3 = &DSP3_OP07_B; +} + +static void DSP3_OP07 (void) +{ + uint32 dataOfs = ((DSP3.DR << 1) + 0x03b2) & 0x03ff; + + DSP3.AddHi = DSP3_DataROM[dataOfs]; + DSP3.AddLo = DSP3_DataROM[dataOfs + 1]; + + SetDSP3 = &DSP3_OP07_A; + DSP3.SR = 0x0080; +} + +static void DSP3_Coordinate (void) +{ + DSP3.Index++; + + switch (DSP3.Index) + { + case 3: + if (DSP3.DR == 0xffff) + DSP3_Reset(); + break; + + case 4: + DSP3.X = DSP3.DR; + break; + + case 5: + DSP3.Y = DSP3.DR; + DSP3.DR = 1; + break; + + case 6: + DSP3.DR = DSP3.X; + break; + + case 7: + DSP3.DR = DSP3.Y; + DSP3.Index = 0; + break; + } +} + +static void DSP3_Convert_A (void) +{ + if (DSP3.BMIndex < 8) + { + DSP3.Bitmap[DSP3.BMIndex++] = (uint8) (DSP3.DR); + DSP3.Bitmap[DSP3.BMIndex++] = (uint8) (DSP3.DR >> 8); + + if (DSP3.BMIndex == 8) + { + for (int i = 0; i < 8; i++) + { + for (int j = 0; j < 8; j++) + { + DSP3.Bitplane[j] <<= 1; + DSP3.Bitplane[j] |= (DSP3.Bitmap[i] >> j) & 1; + } + } + + DSP3.BPIndex = 0; + DSP3.Count--; + } + } + + if (DSP3.BMIndex == 8) + { + if (DSP3.BPIndex == 8) + { + if (!DSP3.Count) + DSP3_Reset(); + + DSP3.BMIndex = 0; + } + else + { + DSP3.DR = DSP3.Bitplane[DSP3.BPIndex++]; + DSP3.DR |= DSP3.Bitplane[DSP3.BPIndex++] << 8; + } + } +} + +static void DSP3_Convert (void) +{ + DSP3.Count = DSP3.DR; + DSP3.BMIndex = 0; + SetDSP3 = &DSP3_Convert_A; +} + +static bool8 DSP3_GetBits (uint8 Count) +{ + if (!DSP3.BitsLeft) + { + DSP3.BitsLeft = Count; + DSP3.ReqBits = 0; + } + + do + { + if (!DSP3.BitCount) + { + DSP3.SR = 0xC0; + return (FALSE); + } + + DSP3.ReqBits <<= 1; + if (DSP3.ReqData & 0x8000) + DSP3.ReqBits++; + DSP3.ReqData <<= 1; + + DSP3.BitCount--; + DSP3.BitsLeft--; + + } + while (DSP3.BitsLeft); + + return (TRUE); +} + +static void DSP3_Decode_Data (void) +{ + if (!DSP3.BitCount) + { + if (DSP3.SR & 0x40) + { + DSP3.ReqData = DSP3.DR; + DSP3.BitCount += 16; + } + else + { + DSP3.SR = 0xC0; + return; + } + } + + if (DSP3.LZCode == 1) + { + if (!DSP3_GetBits(1)) + return; + + if (DSP3.ReqBits) + DSP3.LZLength = 12; + else + DSP3.LZLength = 8; + + DSP3.LZCode++; + } + + if (DSP3.LZCode == 2) + { + if (!DSP3_GetBits(DSP3.LZLength)) + return; + + DSP3.LZCode = 0; + DSP3.Outwords--; + if (!DSP3.Outwords) + SetDSP3 = &DSP3_Reset; + + DSP3.SR = 0x80; + DSP3.DR = DSP3.ReqBits; + return; + } + + if (DSP3.BaseCode == 0xffff) + { + if (!DSP3_GetBits(DSP3.BaseLength)) + return; + + DSP3.BaseCode = DSP3.ReqBits; + } + + if (!DSP3_GetBits(DSP3.CodeLengths[DSP3.BaseCode])) + return; + + DSP3.Symbol = DSP3.Codes[DSP3.CodeOffsets[DSP3.BaseCode] + DSP3.ReqBits]; + DSP3.BaseCode = 0xffff; + + if (DSP3.Symbol & 0xff00) + { + DSP3.Symbol += 0x7f02; + DSP3.LZCode++; + } + else + { + DSP3.Outwords--; + if (!DSP3.Outwords) + SetDSP3 = &DSP3_Reset; + } + + DSP3.SR = 0x80; + DSP3.DR = DSP3.Symbol; +} + +static void DSP3_Decode_Tree (void) +{ + if (!DSP3.BitCount) + { + DSP3.ReqData = DSP3.DR; + DSP3.BitCount += 16; + } + + if (!DSP3.BaseCodes) + { + DSP3_GetBits(1); + + if (DSP3.ReqBits) + { + DSP3.BaseLength = 3; + DSP3.BaseCodes = 8; + } + else + { + DSP3.BaseLength = 2; + DSP3.BaseCodes = 4; + } + } + + while (DSP3.BaseCodes) + { + if (!DSP3_GetBits(3)) + return; + + DSP3.ReqBits++; + + DSP3.CodeLengths[DSP3.Index] = (uint8) DSP3.ReqBits; + DSP3.CodeOffsets[DSP3.Index] = DSP3.Symbol; + DSP3.Index++; + + DSP3.Symbol += 1 << DSP3.ReqBits; + DSP3.BaseCodes--; + } + + DSP3.BaseCode = 0xffff; + DSP3.LZCode = 0; + + SetDSP3 = &DSP3_Decode_Data; + if (DSP3.BitCount) + DSP3_Decode_Data(); +} + +static void DSP3_Decode_Symbols (void) +{ + DSP3.ReqData = DSP3.DR; + DSP3.BitCount += 16; + + do + { + if (DSP3.BitCommand == 0xffff) + { + if (!DSP3_GetBits(2)) + return; + + DSP3.BitCommand = DSP3.ReqBits; + } + + switch (DSP3.BitCommand) + { + case 0: + if (!DSP3_GetBits(9)) + return; + DSP3.Symbol = DSP3.ReqBits; + break; + + case 1: + DSP3.Symbol++; + break; + + case 2: + if (!DSP3_GetBits(1)) + return; + DSP3.Symbol += 2 + DSP3.ReqBits; + break; + + case 3: + if (!DSP3_GetBits(4)) + return; + DSP3.Symbol += 4 + DSP3.ReqBits; + break; + } + + DSP3.BitCommand = 0xffff; + + DSP3.Codes[DSP3.Index++] = DSP3.Symbol; + DSP3.Codewords--; + + } + while (DSP3.Codewords); + + DSP3.Index = 0; + DSP3.Symbol = 0; + DSP3.BaseCodes = 0; + + SetDSP3 = &DSP3_Decode_Tree; + if (DSP3.BitCount) + DSP3_Decode_Tree(); +} + +static void DSP3_Decode_A (void) +{ + DSP3.Outwords = DSP3.DR; + SetDSP3 = &DSP3_Decode_Symbols; + DSP3.BitCount = 0; + DSP3.BitsLeft = 0; + DSP3.Symbol = 0; + DSP3.Index = 0; + DSP3.BitCommand = 0xffff; + DSP3.SR = 0xC0; +} + +static void DSP3_Decode (void) +{ + DSP3.Codewords = DSP3.DR; + SetDSP3 = &DSP3_Decode_A; +} + +// Opcodes 1E/3E bit-perfect to 'dsp3-intro' log +// src: adapted from SD Gundam X/G-Next + +static void DSP3_OP3E (void) +{ + DSP3. op3e_x = (uint8) (DSP3.DR & 0x00ff); + DSP3. op3e_y = (uint8) ((DSP3.DR & 0xff00) >> 8); + + DSP3_OP03(); + + DSP3.op1e_terrain[DSP3.DR] = 0x00; + DSP3.op1e_cost[DSP3.DR] = 0xff; + DSP3.op1e_weight[DSP3.DR] = 0; + + DSP3.op1e_max_search_radius = 0; + DSP3.op1e_max_path_radius = 0; +} + +static void DSP3_OP1E (void) +{ + DSP3.op1e_min_radius = (uint8) (DSP3.DR & 0x00ff); + DSP3.op1e_max_radius = (uint8) ((DSP3.DR & 0xff00) >> 8); + + if (DSP3.op1e_min_radius == 0) + DSP3.op1e_min_radius++; + + if (DSP3.op1e_max_search_radius >= DSP3.op1e_min_radius) + DSP3.op1e_min_radius = DSP3.op1e_max_search_radius + 1; + + if (DSP3.op1e_max_radius > DSP3.op1e_max_search_radius) + DSP3.op1e_max_search_radius = DSP3.op1e_max_radius; + + DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; + DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + + DSP3.op1e_lcv_turns = 6; + DSP3.op1e_turn = 0; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + + DSP3_OP1E_A(); +} + +static void DSP3_OP1E_A (void) +{ + if (DSP3.op1e_lcv_steps == 0) + { + DSP3.op1e_lcv_radius++; + + DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_lcv_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + } + + if (DSP3.op1e_lcv_radius > DSP3.op1e_max_radius) + { + DSP3.op1e_turn++; + DSP3.op1e_lcv_turns--; + + DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; + DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + } + + if (DSP3.op1e_lcv_turns == 0) + { + DSP3.DR = 0xffff; + DSP3.SR = 0x0080; + SetDSP3 = &DSP3_OP1E_B; + return; + } + + DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); + DSP3_OP03(); + + DSP3.op1e_cell = DSP3.DR; + + DSP3.SR = 0x0080; + SetDSP3 = &DSP3_OP1E_A1; +} + +static void DSP3_OP1E_A1 (void) +{ + DSP3.SR = 0x0084; + SetDSP3 = &DSP3_OP1E_A2; +} + +static void DSP3_OP1E_A2 (void) +{ + DSP3.op1e_terrain[DSP3.op1e_cell] = (uint8) (DSP3.DR & 0x00ff); + + DSP3.SR = 0x0084; + SetDSP3 = &DSP3_OP1E_A3; +} + +static void DSP3_OP1E_A3 (void) +{ + DSP3.op1e_cost[DSP3.op1e_cell] = (uint8) (DSP3.DR & 0x00ff); + + if (DSP3.op1e_lcv_radius == 1) + { + if (DSP3.op1e_terrain[DSP3.op1e_cell] & 1) + DSP3.op1e_weight[DSP3.op1e_cell] = 0xff; + else + DSP3.op1e_weight[DSP3.op1e_cell] = DSP3.op1e_cost[DSP3.op1e_cell]; + } + else + DSP3.op1e_weight[DSP3.op1e_cell] = 0xff; + + DSP3_OP1E_D((int16) (DSP3.op1e_turn + 2), &DSP3.op1e_x, &DSP3.op1e_y); + DSP3.op1e_lcv_steps--; + + DSP3.SR = 0x0080; + DSP3_OP1E_A(); +} + +static void DSP3_OP1E_B (void) +{ + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + DSP3.op1e_lcv_radius = 1; + + DSP3.op1e_search = 0; + + DSP3_OP1E_B1(); + + SetDSP3 = &DSP3_OP1E_C; +} + +static void DSP3_OP1E_B1 (void) +{ + while (DSP3.op1e_lcv_radius < DSP3.op1e_max_radius) + { + DSP3.op1e_y--; + + DSP3.op1e_lcv_turns = 6; + DSP3.op1e_turn = 5; + + while (DSP3.op1e_lcv_turns) + { + DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; + + while (DSP3.op1e_lcv_steps) + { + DSP3_OP1E_D1(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + + if (0 <= DSP3.op1e_y && DSP3.op1e_y < DSP3.WinHi && 0 <= DSP3.op1e_x && DSP3.op1e_x < DSP3.WinLo) + { + DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); + DSP3_OP03(); + + DSP3.op1e_cell = DSP3.DR; + if (DSP3.op1e_cost[DSP3.op1e_cell] < 0x80 && DSP3.op1e_terrain[DSP3.op1e_cell] < 0x40) + DSP3_OP1E_B2(); // end cell perimeter + } + + DSP3.op1e_lcv_steps--; + } // end search line + + DSP3.op1e_turn--; + if (DSP3.op1e_turn == 0) + DSP3.op1e_turn = 6; + + DSP3.op1e_lcv_turns--; + } // end circle search + + DSP3.op1e_lcv_radius++; + } // end radius search +} + +static void DSP3_OP1E_B2 (void) +{ + int16 cell; + int16 path; + int16 x, y; + int16 lcv_turns; + + path = 0xff; + lcv_turns = 6; + + while (lcv_turns) + { + x = DSP3.op1e_x; + y = DSP3.op1e_y; + + DSP3_OP1E_D1(lcv_turns, &x, &y); + + DSP3.DR = (uint8) (x) | ((uint8) (y) << 8); + DSP3_OP03(); + + cell = DSP3.DR; + + if (0 <= y && y < DSP3.WinHi && 0 <= x && x < DSP3.WinLo) + { + if (DSP3.op1e_terrain[cell] < 0x80 || DSP3.op1e_weight[cell] == 0) + { + if (DSP3.op1e_weight[cell] < path) + path = DSP3.op1e_weight[cell]; + } + } // end step travel + + lcv_turns--; + } // end while turns + + if (path != 0xff) + DSP3.op1e_weight[DSP3.op1e_cell] = path + DSP3.op1e_cost[DSP3.op1e_cell]; +} + +static void DSP3_OP1E_C (void) +{ + DSP3.op1e_min_radius = (uint8) (DSP3.DR & 0x00ff); + DSP3.op1e_max_radius = (uint8) ((DSP3.DR & 0xff00) >> 8); + + if (DSP3.op1e_min_radius == 0) + DSP3.op1e_min_radius++; + + if (DSP3.op1e_max_path_radius >= DSP3.op1e_min_radius) + DSP3.op1e_min_radius = DSP3.op1e_max_path_radius + 1; + + if (DSP3.op1e_max_radius > DSP3.op1e_max_path_radius) + DSP3.op1e_max_path_radius = DSP3.op1e_max_radius; + + DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; + DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + + DSP3.op1e_lcv_turns = 6; + DSP3.op1e_turn = 0; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + + DSP3_OP1E_C1(); +} + +static void DSP3_OP1E_C1 (void) +{ + if (DSP3.op1e_lcv_steps == 0) + { + DSP3.op1e_lcv_radius++; + + DSP3.op1e_lcv_steps = DSP3.op1e_lcv_radius; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_lcv_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + } + + if (DSP3.op1e_lcv_radius > DSP3.op1e_max_radius) + { + DSP3.op1e_turn++; + DSP3.op1e_lcv_turns--; + + DSP3.op1e_lcv_radius = DSP3.op1e_min_radius; + DSP3.op1e_lcv_steps = DSP3.op1e_min_radius; + + DSP3.op1e_x = DSP3. op3e_x; + DSP3.op1e_y = DSP3. op3e_y; + + for (int lcv = 0; lcv < DSP3.op1e_min_radius; lcv++) + DSP3_OP1E_D(DSP3.op1e_turn, &DSP3.op1e_x, &DSP3.op1e_y); + } + + if (DSP3.op1e_lcv_turns == 0) + { + DSP3.DR = 0xffff; + DSP3.SR = 0x0080; + SetDSP3 = &DSP3_Reset; + return; + } + + DSP3.DR = (uint8) (DSP3.op1e_x) | ((uint8) (DSP3.op1e_y) << 8); + DSP3_OP03(); + + DSP3.op1e_cell = DSP3.DR; + + DSP3.SR = 0x0080; + SetDSP3 = &DSP3_OP1E_C2; +} + +static void DSP3_OP1E_C2 (void) +{ + DSP3.DR = DSP3.op1e_weight[DSP3.op1e_cell]; + + DSP3_OP1E_D((int16) (DSP3.op1e_turn + 2), &DSP3.op1e_x, &DSP3.op1e_y); + DSP3.op1e_lcv_steps--; + + DSP3.SR = 0x0084; + SetDSP3 = &DSP3_OP1E_C1; +} + +static void DSP3_OP1E_D (int16 move, int16 *lo, int16 *hi) +{ + uint32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; + int16 Lo; + int16 Hi; + + DSP3.AddHi = DSP3_DataROM[dataOfs]; + DSP3.AddLo = DSP3_DataROM[dataOfs + 1]; + + Lo = (uint8) (*lo); + Hi = (uint8) (*hi); + + if (Lo & 1) + Hi += (DSP3.AddLo & 1); + + DSP3.AddLo += Lo; + DSP3.AddHi += Hi; + + if (DSP3.AddLo < 0) + DSP3.AddLo += DSP3.WinLo; + else + if (DSP3.AddLo >= DSP3.WinLo) + DSP3.AddLo -= DSP3.WinLo; + + if (DSP3.AddHi < 0) + DSP3.AddHi += DSP3.WinHi; + else + if (DSP3.AddHi >= DSP3.WinHi) + DSP3.AddHi -= DSP3.WinHi; + + *lo = DSP3.AddLo; + *hi = DSP3.AddHi; +} + +static void DSP3_OP1E_D1 (int16 move, int16 *lo, int16 *hi) +{ + const uint16 HiAdd[] = + { + 0x00, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00 + }; + + const uint16 LoAdd[] = + { + 0x00, 0x00, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00 + }; + + int16 Lo; + int16 Hi; + + if ((*lo) & 1) + DSP3.AddHi = HiAdd[move + 8]; + else + DSP3.AddHi = HiAdd[move + 0]; + + DSP3.AddLo = LoAdd[move]; + + Lo = (uint8) (*lo); + Hi = (uint8) (*hi); + + if (Lo & 1) + Hi += (DSP3.AddLo & 1); + + DSP3.AddLo += Lo; + DSP3.AddHi += Hi; + + *lo = DSP3.AddLo; + *hi = DSP3.AddHi; +} + +static void DSP3_OP10 (void) +{ + if (DSP3.DR == 0xffff) + DSP3_Reset(); + else + // absorb 2 bytes + DSP3.DR = DSP3.DR; +} + +/* +static void DSP3_OP0C_A (void) +{ + // absorb 2 bytes + DSP3.DR = 0; + SetDSP3 = &DSP3_Reset; +} +*/ + +static void DSP3_OP0C (void) +{ + // absorb 2 bytes + DSP3.DR = 0; + //SetDSP3 = &DSP3_OP0C_A; + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_OP1C_C (void) +{ + // return 2 bytes + DSP3.DR = 0; + SetDSP3 = &DSP3_Reset; +} + +static void DSP3_OP1C_B (void) +{ + // return 2 bytes + DSP3.DR = 0; + SetDSP3 = &DSP3_OP1C_C; +} + +static void DSP3_OP1C_A (void) +{ + // absorb 2 bytes + SetDSP3 = &DSP3_OP1C_B; +} + +static void DSP3_OP1C (void) +{ + // absorb 2 bytes + SetDSP3 = &DSP3_OP1C_A; +} + +static void DSP3_Command (void) +{ + if (DSP3.DR < 0x40) + { + switch (DSP3.DR) + { + case 0x02: SetDSP3 = &DSP3_Coordinate; break; + case 0x03: SetDSP3 = &DSP3_OP03; break; + case 0x06: SetDSP3 = &DSP3_OP06; break; + case 0x07: SetDSP3 = &DSP3_OP07; return; + case 0x0c: SetDSP3 = &DSP3_OP0C; break; + case 0x0f: SetDSP3 = &DSP3_TestMemory; break; + case 0x10: SetDSP3 = &DSP3_OP10; break; + case 0x18: SetDSP3 = &DSP3_Convert; break; + case 0x1c: SetDSP3 = &DSP3_OP1C; break; + case 0x1e: SetDSP3 = &DSP3_OP1E; break; + case 0x1f: SetDSP3 = &DSP3_MemoryDump; break; + case 0x38: SetDSP3 = &DSP3_Decode; break; + case 0x3e: SetDSP3 = &DSP3_OP3E; break; + default: + return; + } + + DSP3.SR = 0x0080; + DSP3.Index = 0; + } +} + +void DSP3SetByte (uint8 byte, uint16 address) +{ + if (address < DSP0.boundary) + { + if (DSP3.SR & 0x04) + { + DSP3.DR = (DSP3.DR & 0xff00) + byte; + (*SetDSP3)(); + } + else + { + DSP3.SR ^= 0x10; + + if (DSP3.SR & 0x10) + DSP3.DR = (DSP3.DR & 0xff00) + byte; + else + { + DSP3.DR = (DSP3.DR & 0x00ff) + (byte << 8); + (*SetDSP3)(); + } + } + } +} + +uint8 DSP3GetByte (uint16 address) +{ + if (address < DSP0.boundary) + { + uint8 byte; + + if (DSP3.SR & 0x04) + { + byte = (uint8) DSP3.DR; + (*SetDSP3)(); + } + else + { + DSP3.SR ^= 0x10; + + if (DSP3.SR & 0x10) + byte = (uint8) (DSP3.DR); + else + { + byte = (uint8) (DSP3.DR >> 8); + (*SetDSP3)(); + } + } + + return (byte); + } + + return (uint8) DSP3.SR; +} diff --git a/dsp4.cpp b/dsp4.cpp new file mode 100644 index 00000000..9d6f3fd7 --- /dev/null +++ b/dsp4.cpp @@ -0,0 +1,2220 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/* + Due recognition and credit are given on Overload's DSP website. + Thank those contributors for their hard work on this chip. + + Fixed-point math reminder: + [sign, integer, fraction] + 1.15.00 * 1.15.00 = 2.30.00 -> 1.30.00 (DSP) -> 1.31.00 (LSB is '0') + 1.15.00 * 1.00.15 = 2.15.15 -> 1.15.15 (DSP) -> 1.15.16 (LSB is '0') +*/ + + +#include "snes9x.h" +#include "memmap.h" + +#define DSP4_CLEAR_OUT() \ + { DSP4.out_count = 0; DSP4.out_index = 0; } + +#define DSP4_WRITE_BYTE(d) \ + { WRITE_WORD(DSP4.output + DSP4.out_count, (d)); DSP4.out_count++; } + +#define DSP4_WRITE_WORD(d) \ + { WRITE_WORD(DSP4.output + DSP4.out_count, (d)); DSP4.out_count += 2; } + +#ifndef MSB_FIRST +#define DSP4_WRITE_16_WORD(d) \ + { memcpy(DSP4.output + DSP4.out_count, (d), 32); DSP4.out_count += 32; } +#else +#define DSP4_WRITE_16_WORD(d) \ + { for (int p = 0; p < 16; p++) DSP4_WRITE_WORD((d)[p]); } +#endif + +// used to wait for dsp i/o +#define DSP4_WAIT(x) \ + DSP4.in_index = 0; DSP4.Logic = (x); return + +// 1.7.8 -> 1.15.16 +#define SEX78(a) (((int32) ((int16) (a))) << 8) + +// 1.15.0 -> 1.15.16 +#define SEX16(a) (((int32) ((int16) (a))) << 16) + +static int16 DSP4_READ_WORD (void); +static int32 DSP4_READ_DWORD (void); +static int16 DSP4_Inverse (int16); +static void DSP4_Multiply (int16, int16, int32 *); +static void DSP4_OP01 (void); +static void DSP4_OP03 (void); +static void DSP4_OP05 (void); +static void DSP4_OP06 (void); +static void DSP4_OP07 (void); +static void DSP4_OP08 (void); +static void DSP4_OP09 (void); +static void DSP4_OP0A (int16, int16 *, int16 *, int16 *, int16 *); +static void DSP4_OP0B (bool8 *, int16, int16, int16, bool8, bool8); +static void DSP4_OP0D (void); +static void DSP4_OP0E (void); +static void DSP4_OP0F (void); +static void DSP4_OP10 (void); +static void DSP4_OP11 (int16, int16, int16, int16, int16 *); +static void DSP4_SetByte (void); +static void DSP4_GetByte (void); + + +static int16 DSP4_READ_WORD (void) +{ + int16 out; + + out = READ_WORD(DSP4.parameters + DSP4.in_index); + DSP4.in_index += 2; + + return (out); +} + +static int32 DSP4_READ_DWORD (void) +{ + int32 out; + + out = READ_DWORD(DSP4.parameters + DSP4.in_index); + DSP4.in_index += 4; + + return (out); +} + +static int16 DSP4_Inverse (int16 value) +{ + // Attention: This lookup table is not verified + const uint16 div_lut[64] = + { + 0x0000, 0x8000, 0x4000, 0x2aaa, 0x2000, 0x1999, 0x1555, 0x1249, + 0x1000, 0x0e38, 0x0ccc, 0x0ba2, 0x0aaa, 0x09d8, 0x0924, 0x0888, + 0x0800, 0x0787, 0x071c, 0x06bc, 0x0666, 0x0618, 0x05d1, 0x0590, + 0x0555, 0x051e, 0x04ec, 0x04bd, 0x0492, 0x0469, 0x0444, 0x0421, + 0x0400, 0x03e0, 0x03c3, 0x03a8, 0x038e, 0x0375, 0x035e, 0x0348, + 0x0333, 0x031f, 0x030c, 0x02fa, 0x02e8, 0x02d8, 0x02c8, 0x02b9, + 0x02aa, 0x029c, 0x028f, 0x0282, 0x0276, 0x026a, 0x025e, 0x0253, + 0x0249, 0x023e, 0x0234, 0x022b, 0x0222, 0x0219, 0x0210, 0x0208 + }; + + // saturate bounds + if (value < 0) + value = 0; + if (value > 63) + value = 63; + + return (div_lut[value]); +} + +static void DSP4_Multiply (int16 Multiplicand, int16 Multiplier, int32 *Product) +{ + *Product = (Multiplicand * Multiplier << 1) >> 1; +} + +static void DSP4_OP01 (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + case 3: goto resume3; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + DSP4.world_y = DSP4_READ_DWORD(); + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + DSP4.world_x = DSP4_READ_DWORD(); + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.world_yofs = DSP4_READ_WORD(); + DSP4.world_dy = DSP4_READ_DWORD(); + DSP4.world_dx = DSP4_READ_DWORD(); + DSP4.distance = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + DSP4.world_xenv = DSP4_READ_DWORD(); + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // initial (x, y, offset) at starting raster line + DSP4.view_x1 = (DSP4.world_x + DSP4.world_xenv) >> 16; + DSP4.view_y1 = DSP4.world_y >> 16; + DSP4.view_xofs1 = DSP4.world_x >> 16; + DSP4.view_yofs1 = DSP4.world_yofs; + DSP4.view_turnoff_x = 0; + DSP4.view_turnoff_dx = 0; + + // first raster line + DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // perspective projection of world (x, y, scroll) points + // based on the current projection lines + DSP4.view_x2 = (((DSP4.world_x + DSP4.world_xenv) >> 16) * DSP4.distance >> 15) + (DSP4.view_turnoff_x * DSP4.distance >> 15); + DSP4.view_y2 = (DSP4.world_y >> 16) * DSP4.distance >> 15; + DSP4.view_xofs2 = DSP4.view_x2; + DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; + + // 1. World x-location before transformation + // 2. Viewer x-position at the next + // 3. World y-location before perspective projection + // 4. Viewer y-position below the horizon + // 5. Number of raster lines drawn in this iteration + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD((DSP4.world_x + DSP4.world_xenv) >> 16); + DSP4_WRITE_WORD(DSP4.view_x2); + DSP4_WRITE_WORD(DSP4.world_y >> 16); + DSP4_WRITE_WORD(DSP4.view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + DSP4.segments = DSP4.poly_raster[0][0] - DSP4.view_y2; + + // prevent overdraw + if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) + DSP4.segments = 0; + else + DSP4.poly_raster[0][0] = DSP4.view_y2; + + // don't draw outside the window + if (DSP4.view_y2 < DSP4.poly_top[0][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (DSP4.view_y1 >= DSP4.poly_top[0][0]) + DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(DSP4.segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; + py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; + + // starting step values + x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); + y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); + + // SR = 0x80 + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + // 1. HDMA memory pointer (bg1) + // 2. vertical scroll offset ($210E) + // 3. horizontal scroll offset ($210D) + DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + DSP4.poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + //////////////////////////////////////////////////// + // Post-update + + // update new viewer (x, y, scroll) to last raster line drawn + DSP4.view_x1 = DSP4.view_x2; + DSP4.view_y1 = DSP4.view_y2; + DSP4.view_xofs1 = DSP4.view_xofs2; + DSP4.view_yofs1 = DSP4.view_yofs2; + + // add deltas for projection lines + DSP4.world_dx += SEX78(DSP4.world_ddx); + DSP4.world_dy += SEX78(DSP4.world_ddy); + + // update projection lines + DSP4.world_x += (DSP4.world_dx + DSP4.world_xenv); + DSP4.world_y += DSP4.world_dy; + + // update road turnoff position + DSP4.view_turnoff_x += DSP4.view_turnoff_dx; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1); + + resume1: + + // check for termination + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + break; + + // road turnoff + if ((uint16) DSP4.distance == 0x8001) + { + DSP4.in_count = 6; + DSP4_WAIT(2); + + resume2: + + DSP4.distance = DSP4_READ_WORD(); + DSP4.view_turnoff_x = DSP4_READ_WORD(); + DSP4.view_turnoff_dx = DSP4_READ_WORD(); + + // factor in new changes + DSP4.view_x1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); + DSP4.view_xofs1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); + + // update stepping values + DSP4.view_turnoff_x += DSP4.view_turnoff_dx; + + DSP4.in_count = 2; + DSP4_WAIT(1); + } + + // already have 2 bytes read + DSP4.in_count = 6; + DSP4_WAIT(3); + + resume3: + + // inspect inputs + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // no envelope here + DSP4.world_xenv = 0; + } + while (1); + + // terminate op + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP03 (void) +{ + DSP4.OAM_RowMax = 33; + memset(DSP4.OAM_Row, 0, 64); +} + +static void DSP4_OP05 (void) +{ + DSP4.OAM_index = 0; + DSP4.OAM_bits = 0; + memset(DSP4.OAM_attr, 0, 32); + DSP4.sprite_count = 0; +} + +static void DSP4_OP06 (void) +{ + DSP4_CLEAR_OUT(); + DSP4_WRITE_16_WORD(DSP4.OAM_attr); +} + +static void DSP4_OP07 (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + } + + //////////////////////////////////////////////////// + // sort inputs + + DSP4.world_y = DSP4_READ_DWORD(); + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + DSP4.world_x = DSP4_READ_DWORD(); + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.world_yofs = DSP4_READ_WORD(); + DSP4.distance = DSP4_READ_WORD(); + DSP4.view_y2 = DSP4_READ_WORD(); + DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_x2 = DSP4_READ_WORD(); + DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // initial (x, y, offset) at starting raster line + DSP4.view_x1 = DSP4.world_x >> 16; + DSP4.view_y1 = DSP4.world_y >> 16; + DSP4.view_xofs1 = DSP4.view_x1; + DSP4.view_yofs1 = DSP4.world_yofs; + + // first raster line + DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // add shaping + DSP4.view_x2 += DSP4.view_dx; + DSP4.view_y2 += DSP4.view_dy; + + // vertical scroll calculation + DSP4.view_xofs2 = DSP4.view_x2; + DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; + + // 1. Viewer x-position at the next + // 2. Viewer y-position below the horizon + // 3. Number of raster lines drawn in this iteration + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(DSP4.view_x2); + DSP4_WRITE_WORD(DSP4.view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + DSP4.segments = DSP4.view_y1 - DSP4.view_y2; + + // prevent overdraw + if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) + DSP4.segments = 0; + else + DSP4.poly_raster[0][0] = DSP4.view_y2; + + // don't draw outside the window + if (DSP4.view_y2 < DSP4.poly_top[0][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (DSP4.view_y1 >= DSP4.poly_top[0][0]) + DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(DSP4.segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; + py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; + + // starting step values + x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); + y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); + + // SR = 0x80 + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + // 1. HDMA memory pointer (bg2) + // 2. vertical scroll offset ($2110) + // 3. horizontal scroll offset ($210F) + DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + DSP4.poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + ///////////////////////////////////////////////////// + // Post-update + + // update new viewer (x, y, scroll) to last raster line drawn + DSP4.view_x1 = DSP4.view_x2; + DSP4.view_y1 = DSP4.view_y2; + DSP4.view_xofs1 = DSP4.view_xofs2; + DSP4.view_yofs1 = DSP4.view_yofs2; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1); + + resume1: + + // check for opcode termination + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 10; + DSP4_WAIT(2); + + resume2: + + // inspect inputs + DSP4.view_y2 = DSP4_READ_WORD(); + DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_x2 = DSP4_READ_WORD(); + DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_yofsenv = DSP4_READ_WORD(); + } + while (1); + + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP08 (void) +{ + int16 win_left, win_right; + int16 view_x[2], view_y[2]; + int16 envelope[2][2]; + + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + } + + //////////////////////////////////////////////////// + // process initial inputs for two polygons + + // clip values + DSP4.poly_clipRt[0][0] = DSP4_READ_WORD(); + DSP4.poly_clipRt[0][1] = DSP4_READ_WORD(); + DSP4.poly_clipRt[1][0] = DSP4_READ_WORD(); + DSP4.poly_clipRt[1][1] = DSP4_READ_WORD(); + + DSP4.poly_clipLf[0][0] = DSP4_READ_WORD(); + DSP4.poly_clipLf[0][1] = DSP4_READ_WORD(); + DSP4.poly_clipLf[1][0] = DSP4_READ_WORD(); + DSP4.poly_clipLf[1][1] = DSP4_READ_WORD(); + + // unknown (constant) (ex. 1P/2P = $00A6, $00A6, $00A6, $00A6) + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + + // unknown (constant) (ex. 1P/2P = $00A5, $00A5, $00A7, $00A7) + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + + // polygon centering (left, right) + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[0][1] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][1] = DSP4_READ_WORD(); + + // HDMA pointer locations + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][1] = DSP4_READ_WORD(); + DSP4.poly_ptr[1][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[1][1] = DSP4_READ_WORD(); + + // starting raster line below the horizon + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_bottom[0][1] = DSP4_READ_WORD(); + DSP4.poly_bottom[1][0] = DSP4_READ_WORD(); + DSP4.poly_bottom[1][1] = DSP4_READ_WORD(); + + // top boundary line to clip + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][1] = DSP4_READ_WORD(); + DSP4.poly_top[1][0] = DSP4_READ_WORD(); + DSP4.poly_top[1][1] = DSP4_READ_WORD(); + + // unknown + // (ex. 1P = $2FC8, $0034, $FF5C, $0035) + // + // (ex. 2P = $3178, $0034, $FFCC, $0035) + // (ex. 2P = $2FC8, $0034, $FFCC, $0035) + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + DSP4_READ_WORD(); + + // look at guidelines for both polygon shapes + DSP4.distance = DSP4_READ_WORD(); + view_x[0] = DSP4_READ_WORD(); + view_y[0] = DSP4_READ_WORD(); + view_x[1] = DSP4_READ_WORD(); + view_y[1] = DSP4_READ_WORD(); + + // envelope shaping guidelines (one frame only) + envelope[0][0] = DSP4_READ_WORD(); + envelope[0][1] = DSP4_READ_WORD(); + envelope[1][0] = DSP4_READ_WORD(); + envelope[1][1] = DSP4_READ_WORD(); + + // starting base values to project from + DSP4.poly_start[0] = view_x[0]; + DSP4.poly_start[1] = view_x[1]; + + // starting raster lines to begin drawing + DSP4.poly_raster[0][0] = view_y[0]; + DSP4.poly_raster[0][1] = view_y[0]; + DSP4.poly_raster[1][0] = view_y[1]; + DSP4.poly_raster[1][1] = view_y[1]; + + // starting distances + DSP4.poly_plane[0] = DSP4.distance; + DSP4.poly_plane[1] = DSP4.distance; + + // SR = 0x00 + + // re-center coordinates + win_left = DSP4.poly_cx[0][0] - view_x[0] + envelope[0][0]; + win_right = DSP4.poly_cx[0][1] - view_x[0] + envelope[0][1]; + + // saturate offscreen data for polygon #1 + if (win_left < DSP4.poly_clipLf[0][0]) + win_left = DSP4.poly_clipLf[0][0]; + if (win_left > DSP4.poly_clipRt[0][0]) + win_left = DSP4.poly_clipRt[0][0]; + if (win_right < DSP4.poly_clipLf[0][1]) + win_right = DSP4.poly_clipLf[0][1]; + if (win_right > DSP4.poly_clipRt[0][1]) + win_right = DSP4.poly_clipRt[0][1]; + + // SR = 0x80 + + // initial output for polygon #1 + DSP4_CLEAR_OUT(); + DSP4_WRITE_BYTE(win_left & 0xff); + DSP4_WRITE_BYTE(win_right & 0xff); + + do + { + int16 polygon; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1); + + resume1: + + // terminate op + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 16; + DSP4_WAIT(2); + + resume2: + + // look at guidelines for both polygon shapes + view_x[0] = DSP4_READ_WORD(); + view_y[0] = DSP4_READ_WORD(); + view_x[1] = DSP4_READ_WORD(); + view_y[1] = DSP4_READ_WORD(); + + // envelope shaping guidelines (one frame only) + envelope[0][0] = DSP4_READ_WORD(); + envelope[0][1] = DSP4_READ_WORD(); + envelope[1][0] = DSP4_READ_WORD(); + envelope[1][1] = DSP4_READ_WORD(); + + //////////////////////////////////////////////////// + // projection begins + + // init + DSP4_CLEAR_OUT(); + + ////////////////////////////////////////////// + // solid polygon renderer - 2 shapes + + for (polygon = 0; polygon < 2; polygon++) + { + int32 left_inc, right_inc; + int16 x1_final, x2_final; + int16 env[2][2]; + int16 poly; + + // SR = 0x00 + + // # raster lines to draw + DSP4.segments = DSP4.poly_raster[polygon][0] - view_y[polygon]; + + // prevent overdraw + if (DSP4.segments > 0) + { + // bump drawing cursor + DSP4.poly_raster[polygon][0] = view_y[polygon]; + DSP4.poly_raster[polygon][1] = view_y[polygon]; + } + else + DSP4.segments = 0; + + // don't draw outside the window + if (view_y[polygon] < DSP4.poly_top[polygon][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (view_y[polygon] >= DSP4.poly_top[polygon][0]) + DSP4.segments = view_y[polygon] - DSP4.poly_top[polygon][0]; + } + + // SR = 0x80 + + // tell user how many raster structures to read in + DSP4_WRITE_WORD(DSP4.segments); + + // normal parameters + poly = polygon; + + ///////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 w_left, w_right; + + // road turnoff selection + if ((uint16) envelope[polygon][0] == (uint16) 0xc001) + poly = 1; + else + if (envelope[polygon][1] == 0x3fff) + poly = 1; + + /////////////////////////////////////////////// + // left side of polygon + + // perspective correction on additional shaping parameters + env[0][0] = envelope[polygon][0] * DSP4.poly_plane[poly] >> 15; + env[0][1] = envelope[polygon][0] * DSP4.distance >> 15; + + // project new shapes (left side) + x1_final = view_x[poly] + env[0][0]; + x2_final = DSP4.poly_start[poly] + env[0][1]; + + // interpolate between projected points with shaping + left_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4.segments) << 1; + if (DSP4.segments == 1) + left_inc = -left_inc; + + /////////////////////////////////////////////// + // right side of polygon + + // perspective correction on additional shaping parameters + env[1][0] = envelope[polygon][1] * DSP4.poly_plane[poly] >> 15; + env[1][1] = envelope[polygon][1] * DSP4.distance >> 15; + + // project new shapes (right side) + x1_final = view_x[poly] + env[1][0]; + x2_final = DSP4.poly_start[poly] + env[1][1]; + + // interpolate between projected points with shaping + right_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4.segments) << 1; + if (DSP4.segments == 1) + right_inc = -right_inc; + + /////////////////////////////////////////////// + // update each point on the line + + w_left = SEX16(DSP4.poly_cx[polygon][0] - DSP4.poly_start[poly] + env[0][0]); + w_right = SEX16(DSP4.poly_cx[polygon][1] - DSP4.poly_start[poly] + env[1][0]); + + // update distance drawn into world + DSP4.poly_plane[polygon] = DSP4.distance; + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + int16 x_left, x_right; + + // project new coordinates + w_left += left_inc; + w_right += right_inc; + + // grab integer portion, drop fraction (no rounding) + x_left = w_left >> 16; + x_right = w_right >> 16; + + // saturate offscreen data + if (x_left < DSP4.poly_clipLf[polygon][0]) + x_left = DSP4.poly_clipLf[polygon][0]; + if (x_left > DSP4.poly_clipRt[polygon][0]) + x_left = DSP4.poly_clipRt[polygon][0]; + if (x_right < DSP4.poly_clipLf[polygon][1]) + x_right = DSP4.poly_clipLf[polygon][1]; + if (x_right > DSP4.poly_clipRt[polygon][1]) + x_right = DSP4.poly_clipRt[polygon][1]; + + // 1. HDMA memory pointer + // 2. Left window position ($2126/$2128) + // 3. Right window position ($2127/$2129) + DSP4_WRITE_WORD(DSP4.poly_ptr[polygon][0]); + DSP4_WRITE_BYTE(x_left & 0xff); + DSP4_WRITE_BYTE(x_right & 0xff); + + // update memory pointers + DSP4.poly_ptr[polygon][0] -= 4; + DSP4.poly_ptr[polygon][1] -= 4; + } // end rasterize line + } + + //////////////////////////////////////////////// + // Post-update + + // new projection spot to continue rasterizing from + DSP4.poly_start[polygon] = view_x[poly]; + } // end polygon rasterizer + } + while (1); + + // unknown output + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(0); + + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP09 (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + case 3: goto resume3; break; + case 4: goto resume4; break; + case 5: goto resume5; break; + case 6: goto resume6; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // grab screen information + DSP4.viewport_cx = DSP4_READ_WORD(); + DSP4.viewport_cy = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + DSP4.viewport_left = DSP4_READ_WORD(); + DSP4.viewport_right = DSP4_READ_WORD(); + DSP4.viewport_top = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + + // starting raster line below the horizon + DSP4.poly_bottom[0][0] = DSP4.viewport_bottom - DSP4.viewport_cy; + DSP4.poly_raster[0][0] = 0x100; + + do + { + //////////////////////////////////////////////////// + // check for new sprites + + DSP4.in_count = 4; + DSP4_WAIT(1); + + resume1: + + //////////////////////////////////////////////// + // raster overdraw check + + DSP4.raster = DSP4_READ_WORD(); + + // continue updating the raster line where overdraw begins + if (DSP4.raster < DSP4.poly_raster[0][0]) + { + DSP4.sprite_clipy = DSP4.viewport_bottom - (DSP4.poly_bottom[0][0] - DSP4.raster); + DSP4.poly_raster[0][0] = DSP4.raster; + } + + ///////////////////////////////////////////////// + // identify sprite + + // op termination + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + goto terminate; + + // no sprite + if (DSP4.distance == 0x0000) + continue; + + //////////////////////////////////////////////////// + // process projection information + + // vehicle sprite + if ((uint16) DSP4.distance == 0x9000) + { + int16 car_left, car_right, car_back; + int16 impact_left, impact_back; + int16 world_spx, world_spy; + int16 view_spx, view_spy; + uint16 energy; + + // we already have 4 bytes we want + DSP4.in_count = 14; + DSP4_WAIT(2); + + resume2: + + // filter inputs + energy = DSP4_READ_WORD(); + impact_back = DSP4_READ_WORD(); + car_back = DSP4_READ_WORD(); + impact_left = DSP4_READ_WORD(); + car_left = DSP4_READ_WORD(); + DSP4.distance = DSP4_READ_WORD(); + car_right = DSP4_READ_WORD(); + + // calculate car's world (x, y) values + world_spx = car_right - car_left; + world_spy = car_back; + + // add in collision vector [needs bit-twiddling] + world_spx -= energy * (impact_left - car_left) >> 16; + world_spy -= energy * (car_back - impact_back) >> 16; + + // perspective correction for world (x, y) + view_spx = world_spx * DSP4.distance >> 15; + view_spy = world_spy * DSP4.distance >> 15; + + // convert to screen values + DSP4.sprite_x = DSP4.viewport_cx + view_spx; + DSP4.sprite_y = DSP4.viewport_bottom - (DSP4.poly_bottom[0][0] - view_spy); + + // make the car's (x)-coordinate available + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(world_spx); + + // grab a few remaining vehicle values + DSP4.in_count = 4; + DSP4_WAIT(3); + + resume3: + + // add vertical lift factor + DSP4.sprite_y += DSP4_READ_WORD(); + } + // terrain sprite + else + { + int16 world_spx, world_spy; + int16 view_spx, view_spy; + + // we already have 4 bytes we want + DSP4.in_count = 10; + DSP4_WAIT(4); + + resume4: + + // sort loop inputs + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_raster[0][1] = DSP4_READ_WORD(); + world_spx = DSP4_READ_WORD(); + world_spy = DSP4_READ_WORD(); + + // compute base raster line from the bottom + DSP4.segments = DSP4.poly_bottom[0][0] - DSP4.raster; + + // perspective correction for world (x, y) + view_spx = world_spx * DSP4.distance >> 15; + view_spy = world_spy * DSP4.distance >> 15; + + // convert to screen values + DSP4.sprite_x = DSP4.viewport_cx + view_spx - DSP4.poly_cx[0][0]; + DSP4.sprite_y = DSP4.viewport_bottom - DSP4.segments + view_spy; + } + + // default sprite size: 16x16 + DSP4.sprite_size = 1; + DSP4.sprite_attr = DSP4_READ_WORD(); + + //////////////////////////////////////////////////// + // convert tile data to SNES OAM format + + do + { + int16 sp_x, sp_y, sp_attr, sp_dattr; + int16 sp_dx, sp_dy; + int16 pixels; + uint16 header; + bool8 draw; + + DSP4.in_count = 2; + DSP4_WAIT(5); + + resume5: + + draw = TRUE; + + // opcode termination + DSP4.raster = DSP4_READ_WORD(); + if (DSP4.raster == -0x8000) + goto terminate; + + // stop code + if (DSP4.raster == 0x0000 && !DSP4.sprite_size) + break; + + // toggle sprite size + if (DSP4.raster == 0x0000) + { + DSP4.sprite_size = !DSP4.sprite_size; + continue; + } + + // check for valid sprite header + header = DSP4.raster; + header >>= 8; + if (header != 0x20 && + header != 0x2e && // This is for attractor sprite + header != 0x40 && + header != 0x60 && + header != 0xa0 && + header != 0xc0 && + header != 0xe0) + break; + + // read in rest of sprite data + DSP4.in_count = 4; + DSP4_WAIT(6); + + resume6: + + draw = TRUE; + + ///////////////////////////////////// + // process tile data + + // sprite deltas + sp_dattr = DSP4.raster; + sp_dy = DSP4_READ_WORD(); + sp_dx = DSP4_READ_WORD(); + + // update coordinates to screen space + sp_x = DSP4.sprite_x + sp_dx; + sp_y = DSP4.sprite_y + sp_dy; + + // update sprite nametable/attribute information + sp_attr = DSP4.sprite_attr + sp_dattr; + + // allow partially visibile tiles + pixels = DSP4.sprite_size ? 15 : 7; + + DSP4_CLEAR_OUT(); + + // transparent tile to clip off parts of a sprite (overdraw) + if (DSP4.sprite_clipy - pixels <= sp_y && sp_y <= DSP4.sprite_clipy && sp_x >= DSP4.viewport_left - pixels && sp_x <= DSP4.viewport_right && DSP4.sprite_clipy >= DSP4.viewport_top - pixels && DSP4.sprite_clipy <= DSP4.viewport_bottom) + DSP4_OP0B(&draw, sp_x, DSP4.sprite_clipy, 0x00EE, DSP4.sprite_size, 0); + + // normal sprite tile + if (sp_x >= DSP4.viewport_left - pixels && sp_x <= DSP4.viewport_right && sp_y >= DSP4.viewport_top - pixels && sp_y <= DSP4.viewport_bottom && sp_y <= DSP4.sprite_clipy) + DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, DSP4.sprite_size, 0); + + // no following OAM data + DSP4_OP0B(&draw, 0, 0x0100, 0, 0, 1); + } + while (1); + } + while (1); + + terminate: + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP0A (int16 n2, int16 *o1, int16 *o2, int16 *o3, int16 *o4) +{ + const uint16 OP0A_Values[16] = + { + 0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150, + 0xfe80, 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0 + }; + + *o4 = OP0A_Values[(n2 & 0x000f)]; + *o3 = OP0A_Values[(n2 & 0x00f0) >> 4]; + *o2 = OP0A_Values[(n2 & 0x0f00) >> 8]; + *o1 = OP0A_Values[(n2 & 0xf000) >> 12]; +} + +static void DSP4_OP0B (bool8 *draw, int16 sp_x, int16 sp_y, int16 sp_attr, bool8 size, bool8 stop) +{ + int16 Row1, Row2; + + // SR = 0x00 + + // align to nearest 8-pixel row + Row1 = (sp_y >> 3) & 0x1f; + Row2 = (Row1 + 1) & 0x1f; + + // check boundaries + if (!((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb))) + *draw = 0; + + if (size) + { + if (DSP4.OAM_Row[Row1] + 1 >= DSP4.OAM_RowMax) + *draw = 0; + if (DSP4.OAM_Row[Row2] + 1 >= DSP4.OAM_RowMax) + *draw = 0; + } + else + { + if (DSP4.OAM_Row[Row1] >= DSP4.OAM_RowMax) + *draw = 0; + } + + // emulator fail-safe (unknown if this really exists) + if (DSP4.sprite_count >= 128) + *draw = 0; + + // SR = 0x80 + + if (*draw) + { + // Row tiles + if (size) + { + DSP4.OAM_Row[Row1] += 2; + DSP4.OAM_Row[Row2] += 2; + } + else + DSP4.OAM_Row[Row1]++; + + // yield OAM output + DSP4_WRITE_WORD(1); + + // pack OAM data: x, y, name, attr + DSP4_WRITE_BYTE(sp_x & 0xff); + DSP4_WRITE_BYTE(sp_y & 0xff); + DSP4_WRITE_WORD(sp_attr); + + DSP4.sprite_count++; + + // OAM: size, msb data + // save post-oam table data for future retrieval + DSP4.OAM_attr[DSP4.OAM_index] |= ((sp_x < 0 || sp_x > 255) << DSP4.OAM_bits); + DSP4.OAM_bits++; + + DSP4.OAM_attr[DSP4.OAM_index] |= (size << DSP4.OAM_bits); + DSP4.OAM_bits++; + + // move to next byte in buffer + if (DSP4.OAM_bits == 16) + { + DSP4.OAM_bits = 0; + DSP4.OAM_index++; + } + } + else + if (stop) + // yield no OAM output + DSP4_WRITE_WORD(0); +} + +static void DSP4_OP0D (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + DSP4.world_y = DSP4_READ_DWORD(); + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + DSP4.world_x = DSP4_READ_DWORD(); + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.world_yofs = DSP4_READ_WORD(); + DSP4.world_dy = DSP4_READ_DWORD(); + DSP4.world_dx = DSP4_READ_DWORD(); + DSP4.distance = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + DSP4.world_xenv = SEX78(DSP4_READ_WORD()); + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // initial (x, y, offset) at starting raster line + DSP4.view_x1 = (DSP4.world_x + DSP4.world_xenv) >> 16; + DSP4.view_y1 = DSP4.world_y >> 16; + DSP4.view_xofs1 = DSP4.world_x >> 16; + DSP4.view_yofs1 = DSP4.world_yofs; + + // first raster line + DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // perspective projection of world (x, y, scroll) points + // based on the current projection lines + DSP4.view_x2 = (((DSP4.world_x + DSP4.world_xenv) >> 16) * DSP4.distance >> 15) + (DSP4.view_turnoff_x * DSP4.distance >> 15); + DSP4.view_y2 = (DSP4.world_y >> 16) * DSP4.distance >> 15; + DSP4.view_xofs2 = DSP4.view_x2; + DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; + + // 1. World x-location before transformation + // 2. Viewer x-position at the current + // 3. World y-location before perspective projection + // 4. Viewer y-position below the horizon + // 5. Number of raster lines drawn in this iteration + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD((DSP4.world_x + DSP4.world_xenv) >> 16); + DSP4_WRITE_WORD(DSP4.view_x2); + DSP4_WRITE_WORD(DSP4.world_y >> 16); + DSP4_WRITE_WORD(DSP4.view_y2); + + ////////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + DSP4.segments = DSP4.view_y1 - DSP4.view_y2; + + // prevent overdraw + if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) + DSP4.segments = 0; + else + DSP4.poly_raster[0][0] = DSP4.view_y2; + + // don't draw outside the window + if (DSP4.view_y2 < DSP4.poly_top[0][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (DSP4.view_y1 >= DSP4.poly_top[0][0]) + DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(DSP4.segments); + + ////////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; + py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; + + // starting step values + x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); + y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); + + // SR = 0x80 + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + // 1. HDMA memory pointer (bg1) + // 2. vertical scroll offset ($210E) + // 3. horizontal scroll offset ($210D) + DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + DSP4.poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + ///////////////////////////////////////////////////// + // Post-update + + // update new viewer (x, y, scroll) to last raster line drawn + DSP4.view_x1 = DSP4.view_x2; + DSP4.view_y1 = DSP4.view_y2; + DSP4.view_xofs1 = DSP4.view_xofs2; + DSP4.view_yofs1 = DSP4.view_yofs2; + + // add deltas for projection lines + DSP4.world_dx += SEX78(DSP4.world_ddx); + DSP4.world_dy += SEX78(DSP4.world_ddy); + + // update projection lines + DSP4.world_x += (DSP4.world_dx + DSP4.world_xenv); + DSP4.world_y += DSP4.world_dy; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(1); + + resume1: + + // inspect input + DSP4.distance = DSP4_READ_WORD(); + + // terminate op + if (DSP4.distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 6; + DSP4_WAIT(2); + + resume2: + + // inspect inputs + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // no envelope here + DSP4.world_xenv = 0; + } + while (1); + + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP0E (void) +{ + DSP4.OAM_RowMax = 16; + memset(DSP4.OAM_Row, 0, 64); +} + +static void DSP4_OP0F (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + case 3: goto resume3; break; + case 4: goto resume4; break; + } + + //////////////////////////////////////////////////// + // process initial inputs + + // sort inputs + DSP4_READ_WORD(); // 0x0000 + DSP4.world_y = DSP4_READ_DWORD(); + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + DSP4.world_x = DSP4_READ_DWORD(); + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.world_yofs = DSP4_READ_WORD(); + DSP4.world_dy = DSP4_READ_DWORD(); + DSP4.world_dx = DSP4_READ_DWORD(); + DSP4.distance = DSP4_READ_WORD(); + DSP4_READ_WORD(); // 0x0000 + DSP4.world_xenv = DSP4_READ_DWORD(); + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // initial (x, y, offset) at starting raster line + DSP4.view_x1 = (DSP4.world_x + DSP4.world_xenv) >> 16; + DSP4.view_y1 = DSP4.world_y >> 16; + DSP4.view_xofs1 = DSP4.world_x >> 16; + DSP4.view_yofs1 = DSP4.world_yofs; + DSP4.view_turnoff_x = 0; + DSP4.view_turnoff_dx = 0; + + // first raster line + DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // perspective projection of world (x, y, scroll) points + // based on the current projection lines + DSP4.view_x2 = ((DSP4.world_x + DSP4.world_xenv) >> 16) * DSP4.distance >> 15; + DSP4.view_y2 = (DSP4.world_y >> 16) * DSP4.distance >> 15; + DSP4.view_xofs2 = DSP4.view_x2; + DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; + + // 1. World x-location before transformation + // 2. Viewer x-position at the next + // 3. World y-location before perspective projection + // 4. Viewer y-position below the horizon + // 5. Number of raster lines drawn in this iteration + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD((DSP4.world_x + DSP4.world_xenv) >> 16); + DSP4_WRITE_WORD(DSP4.view_x2); + DSP4_WRITE_WORD(DSP4.world_y >> 16); + DSP4_WRITE_WORD(DSP4.view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + DSP4.segments = DSP4.poly_raster[0][0] - DSP4.view_y2; + + // prevent overdraw + if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) + DSP4.segments = 0; + else + DSP4.poly_raster[0][0] = DSP4.view_y2; + + // don't draw outside the window + if (DSP4.view_y2 < DSP4.poly_top[0][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (DSP4.view_y1 >= DSP4.poly_top[0][0]) + DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(DSP4.segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + for (DSP4.lcv = 0; DSP4.lcv < 4; DSP4.lcv++) + { + // grab inputs + DSP4.in_count = 4; + DSP4_WAIT(1); + + resume1: + + for (;;) + { + int16 dist; + int16 color, red, green, blue; + + dist = DSP4_READ_WORD(); + color = DSP4_READ_WORD(); + + // U1+B5+G5+R5 + red = color & 0x1f; + green = (color >> 5) & 0x1f; + blue = (color >> 10) & 0x1f; + + // dynamic lighting + red = (red * dist >> 15) & 0x1f; + green = (green * dist >> 15) & 0x1f; + blue = (blue * dist >> 15) & 0x1f; + color = red | (green << 5) | (blue << 10); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(color); + + break; + } + } + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; + py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; + + // starting step values + x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); + y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); + + // SR = 0x80 + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + // 1. HDMA memory pointer + // 2. vertical scroll offset ($210E) + // 3. horizontal scroll offset ($210D) + DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + DSP4.poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + //////////////////////////////////////////////////// + // Post-update + + // update new viewer (x, y, scroll) to last raster line drawn + DSP4.view_x1 = DSP4.view_x2; + DSP4.view_y1 = DSP4.view_y2; + DSP4.view_xofs1 = DSP4.view_xofs2; + DSP4.view_yofs1 = DSP4.view_yofs2; + + // add deltas for projection lines + DSP4.world_dx += SEX78(DSP4.world_ddx); + DSP4.world_dy += SEX78(DSP4.world_ddy); + + // update projection lines + DSP4.world_x += (DSP4.world_dx + DSP4.world_xenv); + DSP4.world_y += DSP4.world_dy; + + // update road turnoff position + DSP4.view_turnoff_x += DSP4.view_turnoff_dx; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(2); + + resume2: + + // check for termination + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + break; + + // road splice + if ((uint16) DSP4.distance == 0x8001) + { + DSP4.in_count = 6; + DSP4_WAIT(3); + + resume3: + + DSP4.distance = DSP4_READ_WORD(); + DSP4.view_turnoff_x = DSP4_READ_WORD(); + DSP4.view_turnoff_dx = DSP4_READ_WORD(); + + // factor in new changes + DSP4.view_x1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); + DSP4.view_xofs1 += (DSP4.view_turnoff_x * DSP4.distance >> 15); + + // update stepping values + DSP4.view_turnoff_x += DSP4.view_turnoff_dx; + + DSP4.in_count = 2; + DSP4_WAIT(2); + } + + // already have 2 bytes in queue + DSP4.in_count = 6; + DSP4_WAIT(4); + + resume4: + + // inspect inputs + DSP4.world_ddy = DSP4_READ_WORD(); + DSP4.world_ddx = DSP4_READ_WORD(); + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // no envelope here + DSP4.world_xenv = 0; + } + while (1); + + // terminate op + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP10 (void) +{ + DSP4.waiting4command = FALSE; + + // op flow control + switch (DSP4.Logic) + { + case 1: goto resume1; break; + case 2: goto resume2; break; + case 3: goto resume3; break; + } + + //////////////////////////////////////////////////// + // sort inputs + + DSP4_READ_WORD(); // 0x0000 + DSP4.world_y = DSP4_READ_DWORD(); + DSP4.poly_bottom[0][0] = DSP4_READ_WORD(); + DSP4.poly_top[0][0] = DSP4_READ_WORD(); + DSP4.poly_cx[1][0] = DSP4_READ_WORD(); + DSP4.viewport_bottom = DSP4_READ_WORD(); + DSP4.world_x = DSP4_READ_DWORD(); + DSP4.poly_cx[0][0] = DSP4_READ_WORD(); + DSP4.poly_ptr[0][0] = DSP4_READ_WORD(); + DSP4.world_yofs = DSP4_READ_WORD(); + DSP4.distance = DSP4_READ_WORD(); + DSP4.view_y2 = DSP4_READ_WORD(); + DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_x2 = DSP4_READ_WORD(); + DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_yofsenv = DSP4_READ_WORD(); + + // initial (x, y, offset) at starting raster line + DSP4.view_x1 = DSP4.world_x >> 16; + DSP4.view_y1 = DSP4.world_y >> 16; + DSP4.view_xofs1 = DSP4.view_x1; + DSP4.view_yofs1 = DSP4.world_yofs; + + // first raster line + DSP4.poly_raster[0][0] = DSP4.poly_bottom[0][0]; + + do + { + //////////////////////////////////////////////////// + // process one iteration of projection + + // add shaping + DSP4.view_x2 += DSP4.view_dx; + DSP4.view_y2 += DSP4.view_dy; + + // vertical scroll calculation + DSP4.view_xofs2 = DSP4.view_x2; + DSP4.view_yofs2 = (DSP4.world_yofs * DSP4.distance >> 15) + DSP4.poly_bottom[0][0] - DSP4.view_y2; + + // 1. Viewer x-position at the next + // 2. Viewer y-position below the horizon + // 3. Number of raster lines drawn in this iteration + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(DSP4.view_x2); + DSP4_WRITE_WORD(DSP4.view_y2); + + ////////////////////////////////////////////////////// + + // SR = 0x00 + + // determine # of raster lines used + DSP4.segments = DSP4.view_y1 - DSP4.view_y2; + + // prevent overdraw + if (DSP4.view_y2 >= DSP4.poly_raster[0][0]) + DSP4.segments = 0; + else + DSP4.poly_raster[0][0] = DSP4.view_y2; + + // don't draw outside the window + if (DSP4.view_y2 < DSP4.poly_top[0][0]) + { + DSP4.segments = 0; + + // flush remaining raster lines + if (DSP4.view_y1 >= DSP4.poly_top[0][0]) + DSP4.segments = DSP4.view_y1 - DSP4.poly_top[0][0]; + } + + // SR = 0x80 + + DSP4_WRITE_WORD(DSP4.segments); + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + for (DSP4.lcv = 0; DSP4.lcv < 4; DSP4.lcv++) + { + // grab inputs + DSP4.in_count = 4; + DSP4_WAIT(1); + + resume1: + + for (;;) + { + int16 dist; + int16 color, red, green, blue; + + dist = DSP4_READ_WORD(); + color = DSP4_READ_WORD(); + + // U1+B5+G5+R5 + red = color & 0x1f; + green = (color >> 5) & 0x1f; + blue = (color >> 10) & 0x1f; + + // dynamic lighting + red = (red * dist >> 15) & 0x1f; + green = (green * dist >> 15) & 0x1f; + blue = (blue * dist >> 15) & 0x1f; + color = red | (green << 5) | (blue << 10); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(color); + + break; + } + } + } + + ////////////////////////////////////////////////////// + + // scan next command if no SR check needed + if (DSP4.segments) + { + int32 px_dx, py_dy; + int32 x_scroll, y_scroll; + + // SR = 0x00 + + // linear interpolation (lerp) between projected points + px_dx = (DSP4.view_xofs2 - DSP4.view_xofs1) * DSP4_Inverse(DSP4.segments) << 1; + py_dy = (DSP4.view_yofs2 - DSP4.view_yofs1) * DSP4_Inverse(DSP4.segments) << 1; + + // starting step values + x_scroll = SEX16(DSP4.poly_cx[0][0] + DSP4.view_xofs1); + y_scroll = SEX16(-DSP4.viewport_bottom + DSP4.view_yofs1 + DSP4.view_yofsenv + DSP4.poly_cx[1][0] - DSP4.world_yofs); + + // SR = 0x80 + + // rasterize line + for (DSP4.lcv = 0; DSP4.lcv < DSP4.segments; DSP4.lcv++) + { + // 1. HDMA memory pointer (bg2) + // 2. vertical scroll offset ($2110) + // 3. horizontal scroll offset ($210F) + DSP4_WRITE_WORD(DSP4.poly_ptr[0][0]); + DSP4_WRITE_WORD((y_scroll + 0x8000) >> 16); + DSP4_WRITE_WORD((x_scroll + 0x8000) >> 16); + + // update memory address + DSP4.poly_ptr[0][0] -= 4; + + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } + + ///////////////////////////////////////////////////// + // Post-update + + // update new viewer (x, y, scroll) to last raster line drawn + DSP4.view_x1 = DSP4.view_x2; + DSP4.view_y1 = DSP4.view_y2; + DSP4.view_xofs1 = DSP4.view_xofs2; + DSP4.view_yofs1 = DSP4.view_yofs2; + + //////////////////////////////////////////////////// + // command check + + // scan next command + DSP4.in_count = 2; + DSP4_WAIT(2); + + resume2: + + // check for opcode termination + DSP4.distance = DSP4_READ_WORD(); + if (DSP4.distance == -0x8000) + break; + + // already have 2 bytes in queue + DSP4.in_count = 10; + DSP4_WAIT(3); + + resume3: + + // inspect inputs + DSP4.view_y2 = DSP4_READ_WORD(); + DSP4.view_dy = DSP4_READ_WORD() * DSP4.distance >> 15; + DSP4.view_x2 = DSP4_READ_WORD(); + DSP4.view_dx = DSP4_READ_WORD() * DSP4.distance >> 15; + } + while (1); + + DSP4.waiting4command = TRUE; +} + +static void DSP4_OP11 (int16 A, int16 B, int16 C, int16 D, int16 *M) +{ + // 0x155 = 341 = Horizontal Width of the Screen + *M = ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) | ((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f); +} + +static void DSP4_SetByte (void) +{ + // clear pending read + if (DSP4.out_index < DSP4.out_count) + { + DSP4.out_index++; + return; + } + + if (DSP4.waiting4command) + { + if (DSP4.half_command) + { + DSP4.command |= (DSP4.byte << 8); + DSP4.in_index = 0; + DSP4.waiting4command = FALSE; + DSP4.half_command = FALSE; + DSP4.out_count = 0; + DSP4.out_index = 0; + + DSP4.Logic = 0; + + switch (DSP4.command) + { + case 0x0000: DSP4.in_count = 4; break; + case 0x0001: DSP4.in_count = 44; break; + case 0x0003: DSP4.in_count = 0; break; + case 0x0005: DSP4.in_count = 0; break; + case 0x0006: DSP4.in_count = 0; break; + case 0x0007: DSP4.in_count = 34; break; + case 0x0008: DSP4.in_count = 90; break; + case 0x0009: DSP4.in_count = 14; break; + case 0x000a: DSP4.in_count = 6; break; + case 0x000b: DSP4.in_count = 6; break; + case 0x000d: DSP4.in_count = 42; break; + case 0x000e: DSP4.in_count = 0; break; + case 0x000f: DSP4.in_count = 46; break; + case 0x0010: DSP4.in_count = 36; break; + case 0x0011: DSP4.in_count = 8; break; + default: + DSP4.waiting4command = TRUE; + break; + } + } + else + { + DSP4.command = DSP4.byte; + DSP4.half_command = TRUE; + } + } + else + { + DSP4.parameters[DSP4.in_index] = DSP4.byte; + DSP4.in_index++; + } + + if (!DSP4.waiting4command && DSP4.in_count == DSP4.in_index) + { + // Actually execute the command + DSP4.waiting4command = TRUE; + DSP4.out_index = 0; + DSP4.in_index = 0; + + switch (DSP4.command) + { + // 16-bit multiplication + case 0x0000: + { + int16 multiplier, multiplicand; + int32 product; + + multiplier = DSP4_READ_WORD(); + multiplicand = DSP4_READ_WORD(); + + DSP4_Multiply(multiplicand, multiplier, &product); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(product); + DSP4_WRITE_WORD(product >> 16); + + break; + } + + // single-player track projection + case 0x0001: + DSP4_OP01(); + break; + + // single-player selection + case 0x0003: + DSP4_OP03(); + break; + + // clear OAM + case 0x0005: + DSP4_OP05(); + break; + + // transfer OAM + case 0x0006: + DSP4_OP06(); + break; + + // single-player track turnoff projection + case 0x0007: + DSP4_OP07(); + break; + + // solid polygon projection + case 0x0008: + DSP4_OP08(); + break; + + // sprite projection + case 0x0009: + DSP4_OP09(); + break; + + // unknown + case 0x000A: + { + DSP4_READ_WORD(); + int16 in2a = DSP4_READ_WORD(); + DSP4_READ_WORD(); + int16 out1a, out2a, out3a, out4a; + + DSP4_OP0A(in2a, &out2a, &out1a, &out4a, &out3a); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(out1a); + DSP4_WRITE_WORD(out2a); + DSP4_WRITE_WORD(out3a); + DSP4_WRITE_WORD(out4a); + + break; + } + + // set OAM + case 0x000B: + { + int16 sp_x = DSP4_READ_WORD(); + int16 sp_y = DSP4_READ_WORD(); + int16 sp_attr = DSP4_READ_WORD(); + bool8 draw = TRUE; + + DSP4_CLEAR_OUT(); + DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, 0, 1); + + break; + } + + // multi-player track projection + case 0x000D: + DSP4_OP0D(); + break; + + // multi-player selection + case 0x000E: + DSP4_OP0E(); + break; + + // single-player track projection with lighting + case 0x000F: + DSP4_OP0F(); + break; + + // single-player track turnoff projection with lighting + case 0x0010: + DSP4_OP10(); + break; + + // unknown: horizontal mapping command + case 0x0011: + { + int16 a, b, c, d, m; + + d = DSP4_READ_WORD(); + c = DSP4_READ_WORD(); + b = DSP4_READ_WORD(); + a = DSP4_READ_WORD(); + + DSP4_OP11(a, b, c, d, &m); + + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(m); + + break; + } + + default: + break; + } + } +} + +static void DSP4_GetByte (void) +{ + if (DSP4.out_count) + { + DSP4.byte = (uint8) DSP4.output[DSP4.out_index & 0x1FF]; + + DSP4.out_index++; + if (DSP4.out_count == DSP4.out_index) + DSP4.out_count = 0; + } + else + DSP4.byte = 0xff; +} + +void DSP4SetByte (uint8 byte, uint16 address) +{ + if (address < DSP0.boundary) + { + DSP4.byte = byte; + DSP4.address = address; + DSP4_SetByte(); + } +} + +uint8 DSP4GetByte (uint16 address) +{ + if (address < DSP0.boundary) + { + DSP4.address = address; + DSP4_GetByte(); + return (DSP4.byte); + } + + return (0x80); +} diff --git a/filter/2xsai.cpp b/filter/2xsai.cpp new file mode 100644 index 00000000..b8225d72 --- /dev/null +++ b/filter/2xsai.cpp @@ -0,0 +1,654 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "2xsai.h" + +#define ALL_COLOR_MASK (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) + +#ifdef GFX_MULTI_FORMAT +static uint32 colorMask = 0, qcolorMask = 0, lowPixelMask = 0, qlowpixelMask = 0; +#else +#define colorMask (((~RGB_LOW_BITS_MASK & ALL_COLOR_MASK) << 16) | (~RGB_LOW_BITS_MASK & ALL_COLOR_MASK)) +#define qcolorMask (((~TWO_LOW_BITS_MASK & ALL_COLOR_MASK) << 16) | (~TWO_LOW_BITS_MASK & ALL_COLOR_MASK)) +#define lowPixelMask ((RGB_LOW_BITS_MASK << 16) | RGB_LOW_BITS_MASK) +#define qlowpixelMask ((TWO_LOW_BITS_MASK << 16) | TWO_LOW_BITS_MASK) +#endif + +static inline int GetResult (uint32, uint32, uint32, uint32); +static inline int GetResult1 (uint32, uint32, uint32, uint32, uint32); +static inline int GetResult2 (uint32, uint32, uint32, uint32, uint32); +static inline uint32 INTERPOLATE (uint32, uint32); +static inline uint32 Q_INTERPOLATE (uint32, uint32, uint32, uint32); + + +static inline int GetResult (uint32 A, uint32 B, uint32 C, uint32 D) +{ + int x = 0, y = 0, r = 0; + + if (A == C) x += 1; else if (B == C) y += 1; + if (A == D) x += 1; else if (B == D) y += 1; + if (x <= 1) r += 1; + if (y <= 1) r -= 1; + + return (r); +} + +static inline int GetResult1 (uint32 A, uint32 B, uint32 C, uint32 D, uint32 E) +{ + int x = 0, y = 0, r = 0; + + if (A == C) x += 1; else if (B == C) y += 1; + if (A == D) x += 1; else if (B == D) y += 1; + if (x <= 1) r += 1; + if (y <= 1) r -= 1; + + return (r); +} + +static inline int GetResult2 (uint32 A, uint32 B, uint32 C, uint32 D, uint32 E) +{ + int x = 0, y = 0, r = 0; + + if (A == C) x += 1; else if (B == C) y += 1; + if (A == D) x += 1; else if (B == D) y += 1; + if (x <= 1) r -= 1; + if (y <= 1) r += 1; + + return (r); +} + +static inline uint32 INTERPOLATE (uint32 A, uint32 B) +{ + return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + (A & B & lowPixelMask)); +} + +static inline uint32 Q_INTERPOLATE (uint32 A, uint32 B, uint32 C, uint32 D) +{ + uint32 x = ((A & qcolorMask) >> 2) + ((B & qcolorMask) >> 2) + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2); + uint32 y = (A & qlowpixelMask) + (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask); + + y = (y >> 2) & qlowpixelMask; + + return (x + y); +} + +bool8 S9xBlit2xSaIFilterInit (void) +{ +#ifdef GFX_MULTI_FORMAT + colorMask = ((~RGB_LOW_BITS_MASK & ALL_COLOR_MASK) << 16) | (~RGB_LOW_BITS_MASK & ALL_COLOR_MASK); + qcolorMask = ((~TWO_LOW_BITS_MASK & ALL_COLOR_MASK) << 16) | (~TWO_LOW_BITS_MASK & ALL_COLOR_MASK); + lowPixelMask = (RGB_LOW_BITS_MASK << 16) | RGB_LOW_BITS_MASK; + qlowpixelMask = (TWO_LOW_BITS_MASK << 16) | TWO_LOW_BITS_MASK; +#endif + + return (TRUE); +} + +void S9xBlit2xSaIFilterDeinit (void) +{ + return; +} + +void SuperEagle (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + uint16 *bP; + uint32 *dP; + uint32 nextline = srcRowBytes >> 1; + + for (; height; height--) + { + bP = (uint16 *) srcPtr; + dP = (uint32 *) dstPtr; + + for (int i = 0; i < width; i++) + { + uint32 color1, color2, color3, color4, color5, color6; + uint32 colorA0, colorA1, colorA2, colorA3, colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; + uint32 product1a, product1b, product2a, product2b; + + colorB0 = *(bP - nextline - 1); + colorB1 = *(bP - nextline ); + colorB2 = *(bP - nextline + 1); + colorB3 = *(bP - nextline + 2); + + color4 = *(bP - 1); + color5 = *(bP ); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + nextline - 1); + color2 = *(bP + nextline ); + color3 = *(bP + nextline + 1); + colorS1 = *(bP + nextline + 2); + + colorA0 = *(bP + nextline + nextline - 1); + colorA1 = *(bP + nextline + nextline ); + colorA2 = *(bP + nextline + nextline + 1); + colorA3 = *(bP + nextline + nextline + 2); + + if (color2 == color6 && color5 != color3) + { + product1b = product2a = color2; + if ((color1 == color2 && color6 == colorS2) || (color2 == colorA1 && color6 == colorB2)) + { + product1a = INTERPOLATE(color2, color5); + product1a = INTERPOLATE(color2, product1a); + product2b = INTERPOLATE(color2, color3); + product2b = INTERPOLATE(color2, product2b); + } + else + { + product1a = INTERPOLATE(color5, color6); + product2b = INTERPOLATE(color2, color3); + } + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1a = color5; + if ((colorB1 == color5 && color3 == colorA2) || (color4 == color5 && color3 == colorS1)) + { + product1b = INTERPOLATE(color5, color6); + product1b = INTERPOLATE(color5, product1b); + product2a = INTERPOLATE(color5, color2); + product2a = INTERPOLATE(color5, product2a); + } + else + { + product1b = INTERPOLATE(color5, color6); + product2a = INTERPOLATE(color2, color3); + } + } + else + if (color5 == color3 && color2 == color6 && color5 != color6) + { + int r = 0; + + r += GetResult(color6, color5, color1, colorA1); + r += GetResult(color6, color5, color4, colorB1); + r += GetResult(color6, color5, colorA2, colorS1); + r += GetResult(color6, color5, colorB2, colorS2); + + if (r > 0) + { + product1b = product2a = color2; + product1a = product2b = INTERPOLATE(color5, color6); + } + else + if (r < 0) + { + product2b = product1a = color5; + product1b = product2a = INTERPOLATE(color5, color6); + } + else + { + product2b = product1a = color5; + product1b = product2a = color2; + } + } + else + { + if ((color2 == color5) || (color3 == color6)) + { + product1a = color5; + product2a = color2; + product1b = color6; + product2b = color3; + } + else + { + product1b = product1a = INTERPOLATE(color5, color6); + product1a = INTERPOLATE(color5, product1a); + product1b = INTERPOLATE(color6, product1b); + + product2a = product2b = INTERPOLATE(color2, color3); + product2a = INTERPOLATE(color2, product2a); + product2b = INTERPOLATE(color3, product2b); + } + } + + #ifdef MSB_FIRST + product1a = (product1a << 16) | product1b; + product2a = (product2a << 16) | product2b; + #else + product1a = product1a | (product1b << 16); + product2a = product2a | (product2b << 16); + #endif + + *(dP) = product1a; + *(dP + (dstRowBytes >> 2)) = product2a; + + bP++; + dP++; + } + + dstPtr += dstRowBytes << 1; + srcPtr += srcRowBytes; + } +} + +void _2xSaI (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + uint16 *bP; + uint32 *dP; + uint32 nextline = srcRowBytes >> 1; + + for (; height; height--) + { + bP = (uint16 *) srcPtr; + dP = (uint32 *) dstPtr; + + for (int i = 0; i < width; i++) + { + uint32 colorA, colorB, colorC, colorD, colorE, colorF, colorG, colorH, colorI, colorJ, colorK, colorL, colorM, colorN, colorO, colorP; + uint32 product, product1, product2; + + colorI = *(bP - nextline - 1); + colorE = *(bP - nextline ); + colorF = *(bP - nextline + 1); + colorJ = *(bP - nextline + 2); + + colorG = *(bP - 1); + colorA = *(bP ); + colorB = *(bP + 1); + colorK = *(bP + 2); + + colorH = *(bP + nextline - 1); + colorC = *(bP + nextline ); + colorD = *(bP + nextline + 1); + colorL = *(bP + nextline + 2); + + colorM = *(bP + nextline + nextline - 1); + colorN = *(bP + nextline + nextline ); + colorO = *(bP + nextline + nextline + 1); + colorP = *(bP + nextline + nextline + 2); + + if ((colorA == colorD) && (colorB != colorC)) + { + if (((colorA == colorE) && (colorB == colorL)) || ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ))) + product = colorA; + else + product = INTERPOLATE(colorA, colorB); + + if (((colorA == colorG) && (colorC == colorO)) || ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM))) + product1 = colorA; + else + product1 = INTERPOLATE(colorA, colorC); + + product2 = colorA; + } + else + if ((colorB == colorC) && (colorA != colorD)) + { + if (((colorB == colorF) && (colorA == colorH)) || ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI))) + product = colorB; + else + product = INTERPOLATE(colorA, colorB); + + if (((colorC == colorH) && (colorA == colorF)) || ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI))) + product1 = colorC; + else + product1 = INTERPOLATE(colorA, colorC); + + product2 = colorB; + } + else + if ((colorA == colorD) && (colorB == colorC)) + { + if (colorA == colorB) + { + product = colorA; + product1 = colorA; + product2 = colorA; + } + else + { + int r = 0; + + product1 = INTERPOLATE(colorA, colorC); + product = INTERPOLATE(colorA, colorB); + + r += GetResult1(colorA, colorB, colorG, colorE, colorI); + r += GetResult2(colorB, colorA, colorK, colorF, colorJ); + r += GetResult2(colorB, colorA, colorH, colorN, colorM); + r += GetResult1(colorA, colorB, colorL, colorO, colorP); + + if (r > 0) + product2 = colorA; + else + if (r < 0) + product2 = colorB; + else + product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD); + } + } + else + { + product2 = Q_INTERPOLATE(colorA, colorB, colorC, colorD); + + if ((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ)) + product = colorA; + else + if ((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI)) + product = colorB; + else + product = INTERPOLATE(colorA, colorB); + + if ((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM)) + product1 = colorA; + else + if ((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI)) + product1 = colorC; + else + product1 = INTERPOLATE(colorA, colorC); + } + + #ifdef MSB_FIRST + product = (colorA << 16) | product; + product1 = (product1 << 16) | product2; + #else + product = colorA | (product << 16); + product1 = product1 | (product2 << 16); + #endif + + *(dP) = product; + *(dP + (dstRowBytes >> 2)) = product1; + + bP++; + dP++; + } + + dstPtr += dstRowBytes << 1; + srcPtr += srcRowBytes; + } +} + +void Super2xSaI (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + uint16 *bP; + uint32 *dP; + uint32 nextline = srcRowBytes >> 1; + + for (; height; height--) + { + bP = (uint16 *) srcPtr; + dP = (uint32 *) dstPtr; + + for (int i = 0; i < width; i++) + { + uint32 color1, color2, color3, color4, color5, color6; + uint32 colorA0, colorA1, colorA2, colorA3, colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; + uint32 product1a, product1b, product2a, product2b; + + colorB0 = *(bP - nextline - 1); + colorB1 = *(bP - nextline ); + colorB2 = *(bP - nextline + 1); + colorB3 = *(bP - nextline + 2); + + color4 = *(bP - 1); + color5 = *(bP ); + color6 = *(bP + 1); + colorS2 = *(bP + 2); + + color1 = *(bP + nextline - 1); + color2 = *(bP + nextline ); + color3 = *(bP + nextline + 1); + colorS1 = *(bP + nextline + 2); + + colorA0 = *(bP + nextline + nextline - 1); + colorA1 = *(bP + nextline + nextline ); + colorA2 = *(bP + nextline + nextline + 1); + colorA3 = *(bP + nextline + nextline + 2); + + if (color2 == color6 && color5 != color3) + product2b = product1b = color2; + else + if (color5 == color3 && color2 != color6) + product2b = product1b = color5; + else + if (color5 == color3 && color2 == color6 && color5 != color6) + { + int r = 0; + + r += GetResult(color6, color5, color1, colorA1); + r += GetResult(color6, color5, color4, colorB1); + r += GetResult(color6, color5, colorA2, colorS1); + r += GetResult(color6, color5, colorB2, colorS2); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + product2b = product1b = INTERPOLATE(color5, color6); + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE(color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE(color2, color2, color2, color3); + else + product2b = INTERPOLATE(color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE(color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE(color6, color5, color5, color5); + else + product1b = INTERPOLATE (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE(color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE(color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE(color2, color5); + else + product1a = color5; + + #ifdef MSB_FIRST + product1a = (product1a << 16) | product1b; + product2a = (product2a << 16) | product2b; + #else + product1a = product1a | (product1b << 16); + product2a = product2a | (product2b << 16); + #endif + + *(dP) = product1a; + *(dP +(dstRowBytes >> 2)) = product2a; + + bP++; + dP++; + } + + dstPtr += dstRowBytes << 1; + srcPtr += srcRowBytes; + } +} diff --git a/filter/2xsai.h b/filter/2xsai.h new file mode 100644 index 00000000..86da4b3d --- /dev/null +++ b/filter/2xsai.h @@ -0,0 +1,187 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _2xsai_h_ +#define _2xsai_h_ + +bool8 S9xBlit2xSaIFilterInit (void); +void S9xBlit2xSaIFilterDeinit (void); +void SuperEagle (uint8 *, int, uint8 *, int, int, int); +void _2xSaI (uint8 *, int, uint8 *, int, int, int); +void Super2xSaI (uint8 *, int, uint8 *, int, int, int); + +#endif diff --git a/filter/blit.cpp b/filter/blit.cpp new file mode 100644 index 00000000..c3dca16e --- /dev/null +++ b/filter/blit.cpp @@ -0,0 +1,638 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "blit.h" + +#define ALL_COLOR_MASK (FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) + +#ifdef GFX_MULTI_FORMAT +static uint16 lowPixelMask = 0, qlowPixelMask = 0; +static uint32 colorMask = 0; +#else +#define lowPixelMask (RGB_LOW_BITS_MASK) +#define qlowPixelMask ((RGB_HI_BITS_MASK >> 3) | TWO_LOW_BITS_MASK) +#define colorMask (((~RGB_HI_BITS_MASK & ALL_COLOR_MASK) << 16) | (~RGB_HI_BITS_MASK & ALL_COLOR_MASK)) +#endif + +static snes_ntsc_t *ntsc = NULL; +static uint8 *XDelta = NULL; + + +bool8 S9xBlitFilterInit (void) +{ + XDelta = new uint8[SNES_WIDTH * SNES_HEIGHT_EXTENDED * 4]; + if (!XDelta) + return (FALSE); + + S9xBlitClearDelta(); + +#ifdef GFX_MULTI_FORMAT + lowPixelMask = RGB_LOW_BITS_MASK; + qlowPixelMask = (RGB_HI_BITS_MASK >> 3) | TWO_LOW_BITS_MASK; + colorMask = ((~RGB_HI_BITS_MASK & ALL_COLOR_MASK) << 16) | (~RGB_HI_BITS_MASK & ALL_COLOR_MASK); +#endif + + return (TRUE); +} + +void S9xBlitFilterDeinit (void) +{ + if (XDelta) + { + delete[] XDelta; + XDelta = NULL; + } +} + +void S9xBlitClearDelta (void) +{ + uint32 *d = (uint32 *) XDelta; + + for (int y = 0; y < SNES_HEIGHT_EXTENDED; y++) + for (int x = 0; x < SNES_WIDTH; x++) + *d++ = 0x80008000; +} + +bool8 S9xBlitNTSCFilterInit (void) +{ + ntsc = (snes_ntsc_t *) malloc(sizeof(snes_ntsc_t)); + if (!ntsc) + return (FALSE); + + snes_ntsc_init(ntsc, &snes_ntsc_composite); + return (TRUE); +} + +void S9xBlitNTSCFilterDeinit (void) +{ + if (ntsc) + { + free(ntsc); + ntsc = NULL; + } +} + +void S9xBlitNTSCFilterSet (const snes_ntsc_setup_t *setup) +{ + snes_ntsc_init(ntsc, setup); +} + +void S9xBlitPixSmall16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + width <<= 1; + + for (; height; height--) + { + memcpy(dstPtr, srcPtr, width); + srcPtr += srcRowBytes; + dstPtr += dstRowBytes; + } +} + +void S9xBlitPixScaled16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + uint8 *dstPtr2 = dstPtr + dstRowBytes, *deltaPtr = XDelta; + dstRowBytes <<= 1; + + for (; height; height--) + { + uint32 *dP1 = (uint32 *) dstPtr, *dP2 = (uint32 *) dstPtr2, *bP = (uint32 *) srcPtr, *xP = (uint32 *) deltaPtr; + uint32 currentPixel, lastPixel, currentPixA, currentPixB, colorA, colorB; + + for (int i = 0; i < (width >> 1); i++) + { + currentPixel = *bP; + lastPixel = *xP; + + if (currentPixel != lastPixel) + { + #ifdef MSB_FIRST + colorA = (currentPixel >> 16) & 0xFFFF; + colorB = (currentPixel ) & 0xFFFF; + #else + colorA = (currentPixel ) & 0xFFFF; + colorB = (currentPixel >> 16) & 0xFFFF; + #endif + + currentPixA = (colorA << 16) | colorA; + currentPixB = (colorB << 16) | colorB; + + dP1[0] = currentPixA; + dP1[1] = currentPixB; + dP2[0] = currentPixA; + dP2[1] = currentPixB; + + *xP = *bP; + } + + bP++; + xP++; + dP1 += 2; + dP2 += 2; + } + + srcPtr += srcRowBytes; + deltaPtr += srcRowBytes; + dstPtr += dstRowBytes; + dstPtr2 += dstRowBytes; + } +} + +void S9xBlitPixHiRes16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + width <<= 1; + + for (; height; height--) + { + memcpy(dstPtr, srcPtr, width); + dstPtr += dstRowBytes; + memcpy(dstPtr, srcPtr, width); + srcPtr += srcRowBytes; + dstPtr += dstRowBytes; + } +} + +void S9xBlitPixScaledTV16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + uint8 *dstPtr2 = dstPtr + dstRowBytes, *deltaPtr = XDelta; + dstRowBytes <<= 1; + + for (; height; height--) + { + uint32 *dP1 = (uint32 *) dstPtr, *dP2 = (uint32 *) dstPtr2, *bP = (uint32 *) srcPtr, *xP = (uint32 *) deltaPtr; + uint32 currentPixel, nextPixel, currentDelta, nextDelta, colorA, colorB, product, darkened; + + for (int i = 0; i < (width >> 1) - 1; i++) + { + currentPixel = *bP; + currentDelta = *xP; + nextPixel = *(bP + 1); + nextDelta = *(xP + 1); + + if ((currentPixel != currentDelta) || (nextPixel != nextDelta)) + { + *xP = *bP; + + #ifdef MSB_FIRST + colorA = (currentPixel >> 16) & 0xFFFF; + colorB = (currentPixel ) & 0xFFFF; + #else + colorA = (currentPixel ) & 0xFFFF; + colorB = (currentPixel >> 16) & 0xFFFF; + #endif + + #ifdef MSB_FIRST + *dP1 = product = (colorA << 16) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) ); + #else + *dP1 = product = (colorA ) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) << 16); + #endif + + darkened = (product = ((product >> 1) & colorMask)); + darkened += (product = ((product >> 1) & colorMask)); + darkened += (product >> 1) & colorMask; + + *dP2 = darkened; + + #ifdef MSB_FIRST + colorA = (nextPixel >> 16) & 0xFFFF; + #else + colorA = (nextPixel ) & 0xFFFF; + #endif + + #ifdef MSB_FIRST + *(dP1 + 1) = product = (colorB << 16) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) ); + #else + *(dP1 + 1) = product = (colorB ) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) << 16); + #endif + + darkened = (product = ((product >> 1) & colorMask)); + darkened += (product = ((product >> 1) & colorMask)); + darkened += (product >> 1) & colorMask; + + *(dP2 + 1) = darkened; + } + + bP++; + xP++; + dP1 += 2; + dP2 += 2; + } + + // Last 2 Pixels + + currentPixel = *bP; + currentDelta = *xP; + + if (currentPixel != currentDelta) + { + *xP = *bP; + + #ifdef MSB_FIRST + colorA = (currentPixel >> 16) & 0xFFFF; + colorB = (currentPixel ) & 0xFFFF; + #else + colorA = (currentPixel ) & 0xFFFF; + colorB = (currentPixel >> 16) & 0xFFFF; + #endif + + #ifdef MSB_FIRST + *dP1 = product = (colorA << 16) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) ); + #else + *dP1 = product = (colorA ) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) << 16); + #endif + + darkened = (product = ((product >> 1) & colorMask)); + darkened += (product = ((product >> 1) & colorMask)); + darkened += (product >> 1) & colorMask; + + *dP2 = darkened; + + *(dP1 + 1) = product = (colorB << 16) | colorB; + + darkened = (product = ((product >> 1) & colorMask)); + darkened += (product = ((product >> 1) & colorMask)); + darkened += (product >> 1) & colorMask; + + *(dP2 + 1) = darkened; + } + + srcPtr += srcRowBytes; + deltaPtr += srcRowBytes; + dstPtr += dstRowBytes; + dstPtr2 += dstRowBytes; + } +} + +void S9xBlitPixHiResTV16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + uint8 *dstPtr2 = dstPtr + dstRowBytes; + dstRowBytes <<= 1; + + for (; height; height--) + { + uint32 *dP1 = (uint32 *) dstPtr, *dP2 = (uint32 *) dstPtr2, *bP = (uint32 *) srcPtr; + uint32 product, darkened; + + for (int i = 0; i < (width >> 1); i++) + { + product = *dP1++ = *bP++; + darkened = (product = (product >> 1) & colorMask); + darkened += (product = (product >> 1) & colorMask); + *dP2++ = darkened; + } + + srcPtr += srcRowBytes; + dstPtr += dstRowBytes; + dstPtr2 += dstRowBytes; + } +} + +void S9xBlitPixHiResMixedTV16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + uint8 *dstPtr2 = dstPtr + dstRowBytes, *srcPtr2 = srcPtr + srcRowBytes; + dstRowBytes <<= 1; + + for (; height > 1; height--) + { + uint16 *dP1 = (uint16 *) dstPtr, *dP2 = (uint16 *) dstPtr2, *bP1 = (uint16 *) srcPtr, *bP2 = (uint16 *) srcPtr2; + uint16 prev, next, mixed; + + for (int i = 0; i < width; i++) + { + prev = *bP1++; + next = *bP2++; + mixed = prev + next + ((prev ^ next) & lowPixelMask); + + *dP1++ = prev; + *dP2++ = (mixed >> 1) - (mixed >> 4 & qlowPixelMask); + } + + srcPtr += srcRowBytes; + srcPtr2 += srcRowBytes; + dstPtr += dstRowBytes; + dstPtr2 += dstRowBytes; + } + + // Last 1 line + + uint16 *dP1 = (uint16 *) dstPtr, *dP2 = (uint16 *) dstPtr2, *bP1 = (uint16 *) srcPtr; + uint16 prev, mixed; + + for (int i = 0; i < width; i++) + { + prev = *bP1++; + mixed = prev + ((prev ^ 0) & lowPixelMask); + + *dP1++ = prev; + *dP2++ = (mixed >> 1) - (mixed >> 4 & qlowPixelMask); + } +} + +void S9xBlitPixSmooth16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + uint8 *dstPtr2 = dstPtr + dstRowBytes, *deltaPtr = XDelta; + uint32 lastLinePix[SNES_WIDTH << 1]; + uint8 lastLineChg[SNES_WIDTH >> 1]; + int lineBytes = width << 1; + + dstRowBytes <<= 1; + + memset(lastLinePix, 0, sizeof(lastLinePix)); + memset(lastLineChg, 0, sizeof(lastLineChg)); + + for (; height; height--) + { + uint32 *dP1 = (uint32 *) dstPtr, *dP2 = (uint32 *) dstPtr2, *bP = (uint32 *) srcPtr, *xP = (uint32 *) deltaPtr; + uint32 *lL = lastLinePix; + uint8 *lC = lastLineChg; + uint32 currentPixel, nextPixel, currentDelta, nextDelta, lastPix, lastChg, thisChg, currentPixA, currentPixB, colorA, colorB, colorC; + uint16 savePixel; + + savePixel = *(uint16 *) (srcPtr + lineBytes); + *(uint16 *) (srcPtr + lineBytes) = *(uint16 *) (srcPtr + lineBytes - 2); + *(uint32 *) (deltaPtr + lineBytes) = *(uint32 *) (srcPtr + lineBytes); + + nextPixel = *bP++; + nextDelta = *xP++; + + for (int i = 0; i < (width >> 1); i++) + { + currentPixel = nextPixel; + currentDelta = nextDelta; + nextPixel = *bP++; + nextDelta = *xP++; + lastChg = *lC; + thisChg = (nextPixel - nextDelta) | (currentPixel - currentDelta); + + #ifdef MSB_FIRST + colorA = (currentPixel >> 16) & 0xFFFF; + colorB = (currentPixel ) & 0xFFFF; + colorC = (nextPixel >> 16) & 0xFFFF; + + currentPixA = (colorA << 16) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) ); + currentPixB = (colorB << 16) | ((((colorC >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorC & colorB & lowPixelMask)) ); + #else + colorA = (currentPixel ) & 0xFFFF; + colorB = (currentPixel >> 16) & 0xFFFF; + colorC = (nextPixel ) & 0xFFFF; + + currentPixA = (colorA ) | ((((colorA >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorA & colorB & lowPixelMask)) << 16); + currentPixB = (colorB ) | ((((colorC >> 1) & colorMask) + ((colorB >> 1) & colorMask) + (colorC & colorB & lowPixelMask)) << 16); + #endif + + if (thisChg | lastChg) + { + xP[-2] = currentPixel; + + lastPix = lL[0]; + dP1[0] = ((currentPixA >> 1) & colorMask) + ((lastPix >> 1) & colorMask) + (currentPixA & lastPix & lowPixelMask); + dP2[0] = currentPixA; + lL[0] = currentPixA; + + lastPix = lL[1]; + dP1[1] = ((currentPixB >> 1) & colorMask) + ((lastPix >> 1) & colorMask) + (currentPixB & lastPix & lowPixelMask); + dP2[1] = currentPixB; + lL[1] = currentPixB; + + *lC++ = (thisChg != 0); + } + else + { + lL[0] = currentPixA; + lL[1] = currentPixB; + *lC++ = 0; + } + + lL += 2; + dP2 += 2; + dP1 += 2; + } + + *(uint16 *) (srcPtr + lineBytes) = savePixel; + + srcPtr += srcRowBytes; + deltaPtr += srcRowBytes; + dstPtr += dstRowBytes; + dstPtr2 += dstRowBytes; + } +} + +void S9xBlitPixSuper2xSaI16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + Super2xSaI(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height); +} + +void S9xBlitPix2xSaI16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + _2xSaI(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height); +} + +void S9xBlitPixSuperEagle16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + SuperEagle(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height); +} + +void S9xBlitPixEPX16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + EPX_16(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height); +} + +void S9xBlitPixHQ2x16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + HQ2X_16(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height); +} + +void S9xBlitPixHQ3x16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + HQ3X_16(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height); +} + +void S9xBlitPixHQ4x16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + HQ4X_16(srcPtr, srcRowBytes, dstPtr, dstRowBytes, width, height); +} + +void S9xBlitPixNTSC16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + snes_ntsc_blit(ntsc, (SNES_NTSC_IN_T const *) srcPtr, srcRowBytes >> 1, 0, width, height, dstPtr, dstRowBytes); +} + +void S9xBlitPixHiResNTSC16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + snes_ntsc_blit_hires(ntsc, (SNES_NTSC_IN_T const *) srcPtr, srcRowBytes >> 1, 0, width, height, dstPtr, dstRowBytes); +} diff --git a/filter/blit.h b/filter/blit.h new file mode 100644 index 00000000..493c4f6d --- /dev/null +++ b/filter/blit.h @@ -0,0 +1,209 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _blit_h_ +#define _blit_h_ + +#include "2xsai.h" +#include "epx.h" +#include "hq2x.h" +#include "snes_ntsc.h" + +bool8 S9xBlitFilterInit (void); +void S9xBlitFilterDeinit (void); +void S9xBlitClearDelta (void); +bool8 S9xBlitNTSCFilterInit (void); +void S9xBlitNTSCFilterDeinit (void); +void S9xBlitNTSCFilterSet (const snes_ntsc_setup_t *); +void S9xBlitPixSmall16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixScaled16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixHiRes16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixScaledTV16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixHiResTV16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixHiResMixedTV16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixSmooth16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixSuperEagle16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPix2xSaI16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixSuper2xSaI16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixEPX16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixHQ2x16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixHQ3x16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixHQ4x16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixNTSC16 (uint8 *, int, uint8 *, int, int, int); +void S9xBlitPixHiResNTSC16 (uint8 *, int, uint8 *, int, int, int); + +#endif diff --git a/filter/epx.cpp b/filter/epx.cpp new file mode 100644 index 00000000..38241110 --- /dev/null +++ b/filter/epx.cpp @@ -0,0 +1,429 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "epx.h" + + +void EPX_16 (uint8 *srcPtr, int srcRowBytes, uint8 *dstPtr, int dstRowBytes, int width, int height) +{ + uint16 colorX, colorA, colorB, colorC, colorD; + uint16 *sP, *uP, *lP; + uint32 *dP1, *dP2; + int w; + + height -= 2; + + // D + // A X C + // B + + // top edge + + sP = (uint16 *) srcPtr; + lP = (uint16 *) (srcPtr + srcRowBytes); + dP1 = (uint32 *) dstPtr; + dP2 = (uint32 *) (dstPtr + dstRowBytes); + + // left edge + + colorX = *sP; + colorC = *++sP; + colorB = *lP++; + + if ((colorX != colorC) && (colorB != colorX)) + { + #ifdef MSB_FIRST + *dP1 = (colorX << 16) + colorX; + *dP2 = (colorX << 16) + ((colorB == colorC) ? colorB : colorX); + #else + *dP1 = colorX + (colorX << 16); + *dP2 = colorX + (((colorB == colorC) ? colorB : colorX) << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + dP1++; + dP2++; + + // + + for (w = width - 2; w; w--) + { + colorA = colorX; + colorX = colorC; + colorC = *++sP; + colorB = *lP++; + + if ((colorA != colorC) && (colorB != colorX)) + { + #ifdef MSB_FIRST + *dP1 = (colorX << 16) + colorX; + *dP2 = (((colorA == colorB) ? colorA : colorX) << 16) + ((colorB == colorC) ? colorB : colorX); + #else + *dP1 = colorX + (colorX << 16); + *dP2 = ((colorA == colorB) ? colorA : colorX) + (((colorB == colorC) ? colorB : colorX) << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + dP1++; + dP2++; + } + + // right edge + + colorA = colorX; + colorX = colorC; + colorB = *lP; + + if ((colorA != colorX) && (colorB != colorX)) + { + #ifdef MSB_FIRST + *dP1 = (colorX << 16) + colorX; + *dP2 = (((colorA == colorB) ? colorA : colorX) << 16) + colorX; + #else + *dP1 = colorX + (colorX << 16); + *dP2 = ((colorA == colorB) ? colorA : colorX) + (colorX << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + srcPtr += srcRowBytes; + dstPtr += dstRowBytes << 1; + + // + + for (; height; height--) + { + sP = (uint16 *) srcPtr; + uP = (uint16 *) (srcPtr - srcRowBytes); + lP = (uint16 *) (srcPtr + srcRowBytes); + dP1 = (uint32 *) dstPtr; + dP2 = (uint32 *) (dstPtr + dstRowBytes); + + // left edge + + colorX = *sP; + colorC = *++sP; + colorB = *lP++; + colorD = *uP++; + + if ((colorX != colorC) && (colorB != colorD)) + { + #ifdef MSB_FIRST + *dP1 = (colorX << 16) + ((colorC == colorD) ? colorC : colorX); + *dP2 = (colorX << 16) + ((colorB == colorC) ? colorB : colorX); + #else + *dP1 = colorX + (((colorC == colorD) ? colorC : colorX) << 16); + *dP2 = colorX + (((colorB == colorC) ? colorB : colorX) << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + dP1++; + dP2++; + + // + + for (w = width - 2; w; w--) + { + colorA = colorX; + colorX = colorC; + colorC = *++sP; + colorB = *lP++; + colorD = *uP++; + + if ((colorA != colorC) && (colorB != colorD)) + { + #ifdef MSB_FIRST + *dP1 = (((colorD == colorA) ? colorD : colorX) << 16) + ((colorC == colorD) ? colorC : colorX); + *dP2 = (((colorA == colorB) ? colorA : colorX) << 16) + ((colorB == colorC) ? colorB : colorX); + #else + *dP1 = ((colorD == colorA) ? colorD : colorX) + (((colorC == colorD) ? colorC : colorX) << 16); + *dP2 = ((colorA == colorB) ? colorA : colorX) + (((colorB == colorC) ? colorB : colorX) << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + dP1++; + dP2++; + } + + // right edge + + colorA = colorX; + colorX = colorC; + colorB = *lP; + colorD = *uP; + + if ((colorA != colorX) && (colorB != colorD)) + { + #ifdef MSB_FIRST + *dP1 = (((colorD == colorA) ? colorD : colorX) << 16) + colorX; + *dP2 = (((colorA == colorB) ? colorA : colorX) << 16) + colorX; + #else + *dP1 = ((colorD == colorA) ? colorD : colorX) + (colorX << 16); + *dP2 = ((colorA == colorB) ? colorA : colorX) + (colorX << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + srcPtr += srcRowBytes; + dstPtr += dstRowBytes << 1; + } + + // bottom edge + + sP = (uint16 *) srcPtr; + uP = (uint16 *) (srcPtr - srcRowBytes); + dP1 = (uint32 *) dstPtr; + dP2 = (uint32 *) (dstPtr + dstRowBytes); + + // left edge + + colorX = *sP; + colorC = *++sP; + colorD = *uP++; + + if ((colorX != colorC) && (colorX != colorD)) + { + #ifdef MSB_FIRST + *dP1 = (colorX << 16) + ((colorC == colorD) ? colorC : colorX); + *dP2 = (colorX << 16) + colorX; + #else + *dP1 = colorX + (((colorC == colorD) ? colorC : colorX) << 16); + *dP2 = colorX + (colorX << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + dP1++; + dP2++; + + // + + for (w = width - 2; w; w--) + { + colorA = colorX; + colorX = colorC; + colorC = *++sP; + colorD = *uP++; + + if ((colorA != colorC) && (colorX != colorD)) + { + #ifdef MSB_FIRST + *dP1 = (((colorD == colorA) ? colorD : colorX) << 16) + ((colorC == colorD) ? colorC : colorX); + *dP2 = (colorX << 16) + colorX; + #else + *dP1 = ((colorD == colorA) ? colorD : colorX) + (((colorC == colorD) ? colorC : colorX) << 16); + *dP2 = colorX + (colorX << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + dP1++; + dP2++; + } + + // right edge + + colorA = colorX; + colorX = colorC; + colorD = *uP; + + if ((colorA != colorX) && (colorX != colorD)) + { + #ifdef MSB_FIRST + *dP1 = (((colorD == colorA) ? colorD : colorX) << 16) + colorX; + *dP2 = (colorX << 16) + colorX; + #else + *dP1 = ((colorD == colorA) ? colorD : colorX) + (colorX << 16); + *dP2 = colorX + (colorX << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; +} diff --git a/filter/epx.h b/filter/epx.h new file mode 100644 index 00000000..25782728 --- /dev/null +++ b/filter/epx.h @@ -0,0 +1,183 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _epx_h_ +#define _epx_h_ + +void EPX_16 (uint8 *, int, uint8 *, int, int, int); + +#endif diff --git a/filter/hq2x.cpp b/filter/hq2x.cpp new file mode 100644 index 00000000..9b41ad36 --- /dev/null +++ b/filter/hq2x.cpp @@ -0,0 +1,11975 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "gfx.h" +#include "hq2x.h" + +#define Ymask 0xFF0000 +#define Umask 0x00FF00 +#define Vmask 0x0000FF +#define trY 0x300000 +#define trU 0x000700 +#define trV 0x000006 + +#ifdef GFX_MULTI_FORMAT +static uint16 Mask_2 = 0, Mask13 = 0; +#else +#define Mask_2 SECOND_COLOR_MASK +#define Mask13 FIRST_THIRD_COLOR_MASK +#endif + +#define Interp01(c1, c2) \ +(c1 == c2) ? c1 : \ +(((((c1 & Mask_2) * 3 + (c2 & Mask_2) ) >> 2) & Mask_2) + \ + ((((c1 & Mask13) * 3 + (c2 & Mask13) ) >> 2) & Mask13)) + +#define Interp02(c1, c2, c3) \ +(((((c1 & Mask_2) * 2 + (c2 & Mask_2) + (c3 & Mask_2) ) >> 2) & Mask_2) + \ + ((((c1 & Mask13) * 2 + (c2 & Mask13) + (c3 & Mask13) ) >> 2) & Mask13)) + +#define Interp03(c1, c2) \ +(c1 == c2) ? c1 : \ +(((((c1 & Mask_2) * 7 + (c2 & Mask_2) ) >> 3) & Mask_2) + \ + ((((c1 & Mask13) * 7 + (c2 & Mask13) ) >> 3) & Mask13)) + +#define Interp04(c1, c2, c3) \ +(((((c1 & Mask_2) * 2 + (c2 & Mask_2) * 7 + (c3 & Mask_2) * 7) >> 4) & Mask_2) + \ + ((((c1 & Mask13) * 2 + (c2 & Mask13) * 7 + (c3 & Mask13) * 7) >> 4) & Mask13)) + +#define Interp05(c1, c2) \ +(c1 == c2) ? c1 : \ +(((((c1 & Mask_2) + (c2 & Mask_2)) >> 1) & Mask_2) + \ + ((((c1 & Mask13) + (c2 & Mask13)) >> 1) & Mask13)) + +#define Interp06(c1, c2, c3) \ +(((((c1 & Mask_2) * 5 + (c2 & Mask_2) * 2 + (c3 & Mask_2) ) >> 3) & Mask_2) + \ + ((((c1 & Mask13) * 5 + (c2 & Mask13) * 2 + (c3 & Mask13) ) >> 3) & Mask13)) + +#define Interp07(c1, c2, c3) \ +(((((c1 & Mask_2) * 6 + (c2 & Mask_2) + (c3 & Mask_2) ) >> 3) & Mask_2) + \ + ((((c1 & Mask13) * 6 + (c2 & Mask13) + (c3 & Mask13) ) >> 3) & Mask13)) + +#define Interp08(c1, c2) \ +(c1 == c2) ? c1 : \ +(((((c1 & Mask_2) * 5 + (c2 & Mask_2) * 3) >> 3) & Mask_2) + \ + ((((c1 & Mask13) * 5 + (c2 & Mask13) * 3) >> 3) & Mask13)) + +#define Interp09(c1, c2, c3) \ +(((((c1 & Mask_2) * 2 + (c2 & Mask_2) * 3 + (c3 & Mask_2) * 3) >> 3) & Mask_2) + \ + ((((c1 & Mask13) * 2 + (c2 & Mask13) * 3 + (c3 & Mask13) * 3) >> 3) & Mask13)) + +#define Interp10(c1, c2, c3) \ +(((((c1 & Mask_2) * 14 + (c2 & Mask_2) + (c3 & Mask_2) ) >> 4) & Mask_2) + \ + ((((c1 & Mask13) * 14 + (c2 & Mask13) + (c3 & Mask13) ) >> 4) & Mask13)) + +#define X2PIXEL00_0 *(dp) = w5; +#define X2PIXEL00_10 *(dp) = Interp01(w5, w1); +#define X2PIXEL00_11 *(dp) = Interp01(w5, w4); +#define X2PIXEL00_12 *(dp) = Interp01(w5, w2); +#define X2PIXEL00_20 *(dp) = Interp02(w5, w4, w2); +#define X2PIXEL00_21 *(dp) = Interp02(w5, w1, w2); +#define X2PIXEL00_22 *(dp) = Interp02(w5, w1, w4); +#define X2PIXEL00_60 *(dp) = Interp06(w5, w2, w4); +#define X2PIXEL00_61 *(dp) = Interp06(w5, w4, w2); +#define X2PIXEL00_70 *(dp) = Interp07(w5, w4, w2); +#define X2PIXEL00_90 *(dp) = Interp09(w5, w4, w2); +#define X2PIXEL00_100 *(dp) = Interp10(w5, w4, w2); + +#define X2PIXEL01_0 *(dp + 1) = w5; +#define X2PIXEL01_10 *(dp + 1) = Interp01(w5, w3); +#define X2PIXEL01_11 *(dp + 1) = Interp01(w5, w2); +#define X2PIXEL01_12 *(dp + 1) = Interp01(w5, w6); +#define X2PIXEL01_20 *(dp + 1) = Interp02(w5, w2, w6); +#define X2PIXEL01_21 *(dp + 1) = Interp02(w5, w3, w6); +#define X2PIXEL01_22 *(dp + 1) = Interp02(w5, w3, w2); +#define X2PIXEL01_60 *(dp + 1) = Interp06(w5, w6, w2); +#define X2PIXEL01_61 *(dp + 1) = Interp06(w5, w2, w6); +#define X2PIXEL01_70 *(dp + 1) = Interp07(w5, w2, w6); +#define X2PIXEL01_90 *(dp + 1) = Interp09(w5, w2, w6); +#define X2PIXEL01_100 *(dp + 1) = Interp10(w5, w2, w6); + +#define X2PIXEL10_0 *(dp + dst1line) = w5; +#define X2PIXEL10_10 *(dp + dst1line) = Interp01(w5, w7); +#define X2PIXEL10_11 *(dp + dst1line) = Interp01(w5, w8); +#define X2PIXEL10_12 *(dp + dst1line) = Interp01(w5, w4); +#define X2PIXEL10_20 *(dp + dst1line) = Interp02(w5, w8, w4); +#define X2PIXEL10_21 *(dp + dst1line) = Interp02(w5, w7, w4); +#define X2PIXEL10_22 *(dp + dst1line) = Interp02(w5, w7, w8); +#define X2PIXEL10_60 *(dp + dst1line) = Interp06(w5, w4, w8); +#define X2PIXEL10_61 *(dp + dst1line) = Interp06(w5, w8, w4); +#define X2PIXEL10_70 *(dp + dst1line) = Interp07(w5, w8, w4); +#define X2PIXEL10_90 *(dp + dst1line) = Interp09(w5, w8, w4); +#define X2PIXEL10_100 *(dp + dst1line) = Interp10(w5, w8, w4); + +#define X2PIXEL11_0 *(dp + dst1line + 1) = w5; +#define X2PIXEL11_10 *(dp + dst1line + 1) = Interp01(w5, w9); +#define X2PIXEL11_11 *(dp + dst1line + 1) = Interp01(w5, w6); +#define X2PIXEL11_12 *(dp + dst1line + 1) = Interp01(w5, w8); +#define X2PIXEL11_20 *(dp + dst1line + 1) = Interp02(w5, w6, w8); +#define X2PIXEL11_21 *(dp + dst1line + 1) = Interp02(w5, w9, w8); +#define X2PIXEL11_22 *(dp + dst1line + 1) = Interp02(w5, w9, w6); +#define X2PIXEL11_60 *(dp + dst1line + 1) = Interp06(w5, w8, w6); +#define X2PIXEL11_61 *(dp + dst1line + 1) = Interp06(w5, w6, w8); +#define X2PIXEL11_70 *(dp + dst1line + 1) = Interp07(w5, w6, w8); +#define X2PIXEL11_90 *(dp + dst1line + 1) = Interp09(w5, w6, w8); +#define X2PIXEL11_100 *(dp + dst1line + 1) = Interp10(w5, w6, w8); + +#define X3PIXEL00_1M *(dp) = Interp01(w5, w1); +#define X3PIXEL00_1U *(dp) = Interp01(w5, w2); +#define X3PIXEL00_1L *(dp) = Interp01(w5, w4); +#define X3PIXEL00_2 *(dp) = Interp02(w5, w4, w2); +#define X3PIXEL00_4 *(dp) = Interp04(w5, w4, w2); +#define X3PIXEL00_5 *(dp) = Interp05(w4, w2); +#define X3PIXEL00_C *(dp) = w5; + +#define X3PIXEL01_1 *(dp + 1) = Interp01(w5, w2); +#define X3PIXEL01_3 *(dp + 1) = Interp03(w5, w2); +#define X3PIXEL01_6 *(dp + 1) = Interp01(w2, w5); +#define X3PIXEL01_C *(dp + 1) = w5; + +#define X3PIXEL02_1M *(dp + 2) = Interp01(w5, w3); +#define X3PIXEL02_1U *(dp + 2) = Interp01(w5, w2); +#define X3PIXEL02_1R *(dp + 2) = Interp01(w5, w6); +#define X3PIXEL02_2 *(dp + 2) = Interp02(w5, w2, w6); +#define X3PIXEL02_4 *(dp + 2) = Interp04(w5, w2, w6); +#define X3PIXEL02_5 *(dp + 2) = Interp05(w2, w6); +#define X3PIXEL02_C *(dp + 2) = w5; + +#define X3PIXEL10_1 *(dp + dst1line) = Interp01(w5, w4); +#define X3PIXEL10_3 *(dp + dst1line) = Interp03(w5, w4); +#define X3PIXEL10_6 *(dp + dst1line) = Interp01(w4, w5); +#define X3PIXEL10_C *(dp + dst1line) = w5; + +#define X3PIXEL11 *(dp + dst1line + 1) = w5; + +#define X3PIXEL12_1 *(dp + dst1line + 2) = Interp01(w5, w6); +#define X3PIXEL12_3 *(dp + dst1line + 2) = Interp03(w5, w6); +#define X3PIXEL12_6 *(dp + dst1line + 2) = Interp01(w6, w5); +#define X3PIXEL12_C *(dp + dst1line + 2) = w5; + +#define X3PIXEL20_1M *(dp + dst1line + dst1line) = Interp01(w5, w7); +#define X3PIXEL20_1D *(dp + dst1line + dst1line) = Interp01(w5, w8); +#define X3PIXEL20_1L *(dp + dst1line + dst1line) = Interp01(w5, w4); +#define X3PIXEL20_2 *(dp + dst1line + dst1line) = Interp02(w5, w8, w4); +#define X3PIXEL20_4 *(dp + dst1line + dst1line) = Interp04(w5, w8, w4); +#define X3PIXEL20_5 *(dp + dst1line + dst1line) = Interp05(w8, w4); +#define X3PIXEL20_C *(dp + dst1line + dst1line) = w5; + +#define X3PIXEL21_1 *(dp + dst1line + dst1line + 1) = Interp01(w5, w8); +#define X3PIXEL21_3 *(dp + dst1line + dst1line + 1) = Interp03(w5, w8); +#define X3PIXEL21_6 *(dp + dst1line + dst1line + 1) = Interp01(w8, w5); +#define X3PIXEL21_C *(dp + dst1line + dst1line + 1) = w5; + +#define X3PIXEL22_1M *(dp + dst1line + dst1line + 2) = Interp01(w5, w9); +#define X3PIXEL22_1D *(dp + dst1line + dst1line + 2) = Interp01(w5, w8); +#define X3PIXEL22_1R *(dp + dst1line + dst1line + 2) = Interp01(w5, w6); +#define X3PIXEL22_2 *(dp + dst1line + dst1line + 2) = Interp02(w5, w6, w8); +#define X3PIXEL22_4 *(dp + dst1line + dst1line + 2) = Interp04(w5, w6, w8); +#define X3PIXEL22_5 *(dp + dst1line + dst1line + 2) = Interp05(w6, w8); +#define X3PIXEL22_C *(dp + dst1line + dst1line + 2) = w5; + +#define X4PIXEL00_0 *(dp) = w5; +#define X4PIXEL00_11 *(dp) = Interp01(w5, w4); +#define X4PIXEL00_12 *(dp) = Interp01(w5, w2); +#define X4PIXEL00_20 *(dp) = Interp02(w5, w2, w4); +#define X4PIXEL00_50 *(dp) = Interp05(w2, w4); +#define X4PIXEL00_80 *(dp) = Interp08(w5, w1); +#define X4PIXEL00_81 *(dp) = Interp08(w5, w4); +#define X4PIXEL00_82 *(dp) = Interp08(w5, w2); + +#define X4PIXEL01_0 *(dp + 1) = w5; +#define X4PIXEL01_10 *(dp + 1) = Interp01(w5, w1); +#define X4PIXEL01_12 *(dp + 1) = Interp01(w5, w2); +#define X4PIXEL01_14 *(dp + 1) = Interp01(w2, w5); +#define X4PIXEL01_21 *(dp + 1) = Interp02(w2, w5, w4); +#define X4PIXEL01_31 *(dp + 1) = Interp03(w5, w4); +#define X4PIXEL01_50 *(dp + 1) = Interp05(w2, w5); +#define X4PIXEL01_60 *(dp + 1) = Interp06(w5, w2, w4); +#define X4PIXEL01_61 *(dp + 1) = Interp06(w5, w2, w1); +#define X4PIXEL01_82 *(dp + 1) = Interp08(w5, w2); +#define X4PIXEL01_83 *(dp + 1) = Interp08(w2, w4); + +#define X4PIXEL02_0 *(dp + 2) = w5; +#define X4PIXEL02_10 *(dp + 2) = Interp01(w5, w3); +#define X4PIXEL02_11 *(dp + 2) = Interp01(w5, w2); +#define X4PIXEL02_13 *(dp + 2) = Interp01(w2, w5); +#define X4PIXEL02_21 *(dp + 2) = Interp02(w2, w5, w6); +#define X4PIXEL02_32 *(dp + 2) = Interp03(w5, w6); +#define X4PIXEL02_50 *(dp + 2) = Interp05(w2, w5); +#define X4PIXEL02_60 *(dp + 2) = Interp06(w5, w2, w6); +#define X4PIXEL02_61 *(dp + 2) = Interp06(w5, w2, w3); +#define X4PIXEL02_81 *(dp + 2) = Interp08(w5, w2); +#define X4PIXEL02_83 *(dp + 2) = Interp08(w2, w6); + +#define X4PIXEL03_0 *(dp + 3) = w5; +#define X4PIXEL03_11 *(dp + 3) = Interp01(w5, w2); +#define X4PIXEL03_12 *(dp + 3) = Interp01(w5, w6); +#define X4PIXEL03_20 *(dp + 3) = Interp02(w5, w2, w6); +#define X4PIXEL03_50 *(dp + 3) = Interp05(w2, w6); +#define X4PIXEL03_80 *(dp + 3) = Interp08(w5, w3); +#define X4PIXEL03_81 *(dp + 3) = Interp08(w5, w2); +#define X4PIXEL03_82 *(dp + 3) = Interp08(w5, w6); + +#define X4PIXEL10_0 *(dp + dst1line) = w5; +#define X4PIXEL10_10 *(dp + dst1line) = Interp01(w5, w1); +#define X4PIXEL10_11 *(dp + dst1line) = Interp01(w5, w4); +#define X4PIXEL10_13 *(dp + dst1line) = Interp01(w4, w5); +#define X4PIXEL10_21 *(dp + dst1line) = Interp02(w4, w5, w2); +#define X4PIXEL10_32 *(dp + dst1line) = Interp03(w5, w2); +#define X4PIXEL10_50 *(dp + dst1line) = Interp05(w4, w5); +#define X4PIXEL10_60 *(dp + dst1line) = Interp06(w5, w4, w2); +#define X4PIXEL10_61 *(dp + dst1line) = Interp06(w5, w4, w1); +#define X4PIXEL10_81 *(dp + dst1line) = Interp08(w5, w4); +#define X4PIXEL10_83 *(dp + dst1line) = Interp08(w4, w2); + +#define X4PIXEL11_0 *(dp + dst1line + 1) = w5; +#define X4PIXEL11_30 *(dp + dst1line + 1) = Interp03(w5, w1); +#define X4PIXEL11_31 *(dp + dst1line + 1) = Interp03(w5, w4); +#define X4PIXEL11_32 *(dp + dst1line + 1) = Interp03(w5, w2); +#define X4PIXEL11_70 *(dp + dst1line + 1) = Interp07(w5, w4, w2); + +#define X4PIXEL12_0 *(dp + dst1line + 2) = w5; +#define X4PIXEL12_30 *(dp + dst1line + 2) = Interp03(w5, w3); +#define X4PIXEL12_31 *(dp + dst1line + 2) = Interp03(w5, w2); +#define X4PIXEL12_32 *(dp + dst1line + 2) = Interp03(w5, w6); +#define X4PIXEL12_70 *(dp + dst1line + 2) = Interp07(w5, w6, w2); + +#define X4PIXEL13_0 *(dp + dst1line + 3) = w5; +#define X4PIXEL13_10 *(dp + dst1line + 3) = Interp01(w5, w3); +#define X4PIXEL13_12 *(dp + dst1line + 3) = Interp01(w5, w6); +#define X4PIXEL13_14 *(dp + dst1line + 3) = Interp01(w6, w5); +#define X4PIXEL13_21 *(dp + dst1line + 3) = Interp02(w6, w5, w2); +#define X4PIXEL13_31 *(dp + dst1line + 3) = Interp03(w5, w2); +#define X4PIXEL13_50 *(dp + dst1line + 3) = Interp05(w6, w5); +#define X4PIXEL13_60 *(dp + dst1line + 3) = Interp06(w5, w6, w2); +#define X4PIXEL13_61 *(dp + dst1line + 3) = Interp06(w5, w6, w3); +#define X4PIXEL13_82 *(dp + dst1line + 3) = Interp08(w5, w6); +#define X4PIXEL13_83 *(dp + dst1line + 3) = Interp08(w6, w2); + +#define X4PIXEL20_0 *(dp + dst1line + dst1line) = w5; +#define X4PIXEL20_10 *(dp + dst1line + dst1line) = Interp01(w5, w7); +#define X4PIXEL20_12 *(dp + dst1line + dst1line) = Interp01(w5, w4); +#define X4PIXEL20_14 *(dp + dst1line + dst1line) = Interp01(w4, w5); +#define X4PIXEL20_21 *(dp + dst1line + dst1line) = Interp02(w4, w5, w8); +#define X4PIXEL20_31 *(dp + dst1line + dst1line) = Interp03(w5, w8); +#define X4PIXEL20_50 *(dp + dst1line + dst1line) = Interp05(w4, w5); +#define X4PIXEL20_60 *(dp + dst1line + dst1line) = Interp06(w5, w4, w8); +#define X4PIXEL20_61 *(dp + dst1line + dst1line) = Interp06(w5, w4, w7); +#define X4PIXEL20_82 *(dp + dst1line + dst1line) = Interp08(w5, w4); +#define X4PIXEL20_83 *(dp + dst1line + dst1line) = Interp08(w4, w8); + +#define X4PIXEL21_0 *(dp + dst1line + dst1line + 1) = w5; +#define X4PIXEL21_30 *(dp + dst1line + dst1line + 1) = Interp03(w5, w7); +#define X4PIXEL21_31 *(dp + dst1line + dst1line + 1) = Interp03(w5, w8); +#define X4PIXEL21_32 *(dp + dst1line + dst1line + 1) = Interp03(w5, w4); +#define X4PIXEL21_70 *(dp + dst1line + dst1line + 1) = Interp07(w5, w4, w8); + +#define X4PIXEL22_0 *(dp + dst1line + dst1line + 2) = w5; +#define X4PIXEL22_30 *(dp + dst1line + dst1line + 2) = Interp03(w5, w9); +#define X4PIXEL22_31 *(dp + dst1line + dst1line + 2) = Interp03(w5, w6); +#define X4PIXEL22_32 *(dp + dst1line + dst1line + 2) = Interp03(w5, w8); +#define X4PIXEL22_70 *(dp + dst1line + dst1line + 2) = Interp07(w5, w6, w8); + +#define X4PIXEL23_0 *(dp + dst1line + dst1line + 3) = w5; +#define X4PIXEL23_10 *(dp + dst1line + dst1line + 3) = Interp01(w5, w9); +#define X4PIXEL23_11 *(dp + dst1line + dst1line + 3) = Interp01(w5, w6); +#define X4PIXEL23_13 *(dp + dst1line + dst1line + 3) = Interp01(w6, w5); +#define X4PIXEL23_21 *(dp + dst1line + dst1line + 3) = Interp02(w6, w5, w8); +#define X4PIXEL23_32 *(dp + dst1line + dst1line + 3) = Interp03(w5, w8); +#define X4PIXEL23_50 *(dp + dst1line + dst1line + 3) = Interp05(w6, w5); +#define X4PIXEL23_60 *(dp + dst1line + dst1line + 3) = Interp06(w5, w6, w8); +#define X4PIXEL23_61 *(dp + dst1line + dst1line + 3) = Interp06(w5, w6, w9); +#define X4PIXEL23_81 *(dp + dst1line + dst1line + 3) = Interp08(w5, w6); +#define X4PIXEL23_83 *(dp + dst1line + dst1line + 3) = Interp08(w6, w8); + +#define X4PIXEL30_0 *(dp + dst1line + dst1line + dst1line) = w5; +#define X4PIXEL30_11 *(dp + dst1line + dst1line + dst1line) = Interp01(w5, w8); +#define X4PIXEL30_12 *(dp + dst1line + dst1line + dst1line) = Interp01(w5, w4); +#define X4PIXEL30_20 *(dp + dst1line + dst1line + dst1line) = Interp02(w5, w8, w4); +#define X4PIXEL30_50 *(dp + dst1line + dst1line + dst1line) = Interp05(w8, w4); +#define X4PIXEL30_80 *(dp + dst1line + dst1line + dst1line) = Interp08(w5, w7); +#define X4PIXEL30_81 *(dp + dst1line + dst1line + dst1line) = Interp08(w5, w8); +#define X4PIXEL30_82 *(dp + dst1line + dst1line + dst1line) = Interp08(w5, w4); + +#define X4PIXEL31_0 *(dp + dst1line + dst1line + dst1line + 1) = w5; +#define X4PIXEL31_10 *(dp + dst1line + dst1line + dst1line + 1) = Interp01(w5, w7); +#define X4PIXEL31_11 *(dp + dst1line + dst1line + dst1line + 1) = Interp01(w5, w8); +#define X4PIXEL31_13 *(dp + dst1line + dst1line + dst1line + 1) = Interp01(w8, w5); +#define X4PIXEL31_21 *(dp + dst1line + dst1line + dst1line + 1) = Interp02(w8, w5, w4); +#define X4PIXEL31_32 *(dp + dst1line + dst1line + dst1line + 1) = Interp03(w5, w4); +#define X4PIXEL31_50 *(dp + dst1line + dst1line + dst1line + 1) = Interp05(w8, w5); +#define X4PIXEL31_60 *(dp + dst1line + dst1line + dst1line + 1) = Interp06(w5, w8, w4); +#define X4PIXEL31_61 *(dp + dst1line + dst1line + dst1line + 1) = Interp06(w5, w8, w7); +#define X4PIXEL31_81 *(dp + dst1line + dst1line + dst1line + 1) = Interp08(w5, w8); +#define X4PIXEL31_83 *(dp + dst1line + dst1line + dst1line + 1) = Interp08(w8, w4); + +#define X4PIXEL32_0 *(dp + dst1line + dst1line + dst1line + 2) = w5; +#define X4PIXEL32_10 *(dp + dst1line + dst1line + dst1line + 2) = Interp01(w5, w9); +#define X4PIXEL32_12 *(dp + dst1line + dst1line + dst1line + 2) = Interp01(w5, w8); +#define X4PIXEL32_14 *(dp + dst1line + dst1line + dst1line + 2) = Interp01(w8, w5); +#define X4PIXEL32_21 *(dp + dst1line + dst1line + dst1line + 2) = Interp02(w8, w5, w6); +#define X4PIXEL32_31 *(dp + dst1line + dst1line + dst1line + 2) = Interp03(w5, w6); +#define X4PIXEL32_50 *(dp + dst1line + dst1line + dst1line + 2) = Interp05(w8, w5); +#define X4PIXEL32_60 *(dp + dst1line + dst1line + dst1line + 2) = Interp06(w5, w8, w6); +#define X4PIXEL32_61 *(dp + dst1line + dst1line + dst1line + 2) = Interp06(w5, w8, w9); +#define X4PIXEL32_82 *(dp + dst1line + dst1line + dst1line + 2) = Interp08(w5, w8); +#define X4PIXEL32_83 *(dp + dst1line + dst1line + dst1line + 2) = Interp08(w8, w6); + +#define X4PIXEL33_0 *(dp + dst1line + dst1line + dst1line + 3) = w5; +#define X4PIXEL33_11 *(dp + dst1line + dst1line + dst1line + 3) = Interp01(w5, w6); +#define X4PIXEL33_12 *(dp + dst1line + dst1line + dst1line + 3) = Interp01(w5, w8); +#define X4PIXEL33_20 *(dp + dst1line + dst1line + dst1line + 3) = Interp02(w5, w8, w6); +#define X4PIXEL33_50 *(dp + dst1line + dst1line + dst1line + 3) = Interp05(w8, w6); +#define X4PIXEL33_80 *(dp + dst1line + dst1line + dst1line + 3) = Interp08(w5, w9); +#define X4PIXEL33_81 *(dp + dst1line + dst1line + dst1line + 3) = Interp08(w5, w6); +#define X4PIXEL33_82 *(dp + dst1line + dst1line + dst1line + 3) = Interp08(w5, w8); + +#define Absolute(c) \ +(!(c & (1 << 31)) ? c : (~c + 1)) + +static int *RGBtoYUV = NULL; + +static void InitLUTs (void); +static inline bool Diff (int, int); + + +bool8 S9xBlitHQ2xFilterInit (void) +{ + uint32 n = 1 << ((FIRST_COLOR_MASK & 0x8000) ? 16 : 15); + RGBtoYUV = new int[n]; + if (!RGBtoYUV) + return (FALSE); + +#ifdef GFX_MULTI_FORMAT + Mask_2 = SECOND_COLOR_MASK; + Mask13 = FIRST_THIRD_COLOR_MASK; +#endif + + InitLUTs(); + + return (TRUE); +} + +void S9xBlitHQ2xFilterDeinit (void) +{ + if (RGBtoYUV) + { + delete[] RGBtoYUV; + RGBtoYUV = NULL; + } +} + +static void InitLUTs (void) +{ + uint32 r, g, b; + int y, u, v; + + uint32 n = 1 << ((FIRST_COLOR_MASK & 0x8000) ? 16 : 15); + for (uint32 c = 0 ; c < n ; c++) + { + DECOMPOSE_PIXEL(c, r, g, b); + r <<= 3; + g <<= 3; + b <<= 3; + + y = (int) ( 0.256788f * r + 0.504129f * g + 0.097906f * b + 0.5f) + 16; + u = (int) (-0.148223f * r - 0.290993f * g + 0.439216f * b + 0.5f) + 128; + v = (int) ( 0.439216f * r - 0.367788f * g - 0.071427f * b + 0.5f) + 128; + + RGBtoYUV[c] = (y << 16) + (u << 8) + v; + } +} + +static inline bool Diff (int c1, int c2) +{ + int c1y = (c1 & Ymask) - (c2 & Ymask); + if (Absolute(c1y) > trY) + return (true); + + int c1u = (c1 & Umask) - (c2 & Umask); + if (Absolute(c1u) > trU) + return (true); + + int c1v = (c1 & Vmask) - (c2 & Vmask); + if (Absolute(c1v) > trV) + return (true); + + return (false); +} + +void HQ2X_16 (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + register int w1, w2, w3, w4, w5, w6, w7, w8, w9; + register uint32 src1line = srcPitch >> 1; + register uint32 dst1line = dstPitch >> 1; + register uint16 *sp = (uint16 *) srcPtr; + register uint16 *dp = (uint16 *) dstPtr; + + uint32 pattern; + int l, y; + + while (height--) + { + sp--; + + w1 = *(sp - src1line); + w4 = *(sp); + w7 = *(sp + src1line); + + sp++; + + w2 = *(sp - src1line); + w5 = *(sp); + w8 = *(sp + src1line); + + for (l = width; l; l--) + { + sp++; + + w3 = *(sp - src1line); + w6 = *(sp); + w9 = *(sp + src1line); + + y = RGBtoYUV[w5]; + pattern = 0; + + if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7); + + switch (pattern) + { + case 0: + case 1: + case 4: + case 32: + case 128: + case 5: + case 132: + case 160: + case 33: + case 129: + case 36: + case 133: + case 164: + case 161: + case 37: + case 165: + { + X2PIXEL00_20 + X2PIXEL01_20 + X2PIXEL10_20 + X2PIXEL11_20 + break; + } + case 2: + case 34: + case 130: + case 162: + { + X2PIXEL00_22 + X2PIXEL01_21 + X2PIXEL10_20 + X2PIXEL11_20 + break; + } + case 16: + case 17: + case 48: + case 49: + { + X2PIXEL00_20 + X2PIXEL01_22 + X2PIXEL10_20 + X2PIXEL11_21 + break; + } + case 64: + case 65: + case 68: + case 69: + { + X2PIXEL00_20 + X2PIXEL01_20 + X2PIXEL10_21 + X2PIXEL11_22 + break; + } + case 8: + case 12: + case 136: + case 140: + { + X2PIXEL00_21 + X2PIXEL01_20 + X2PIXEL10_22 + X2PIXEL11_20 + break; + } + case 3: + case 35: + case 131: + case 163: + { + X2PIXEL00_11 + X2PIXEL01_21 + X2PIXEL10_20 + X2PIXEL11_20 + break; + } + case 6: + case 38: + case 134: + case 166: + { + X2PIXEL00_22 + X2PIXEL01_12 + X2PIXEL10_20 + X2PIXEL11_20 + break; + } + case 20: + case 21: + case 52: + case 53: + { + X2PIXEL00_20 + X2PIXEL01_11 + X2PIXEL10_20 + X2PIXEL11_21 + break; + } + case 144: + case 145: + case 176: + case 177: + { + X2PIXEL00_20 + X2PIXEL01_22 + X2PIXEL10_20 + X2PIXEL11_12 + break; + } + case 192: + case 193: + case 196: + case 197: + { + X2PIXEL00_20 + X2PIXEL01_20 + X2PIXEL10_21 + X2PIXEL11_11 + break; + } + case 96: + case 97: + case 100: + case 101: + { + X2PIXEL00_20 + X2PIXEL01_20 + X2PIXEL10_12 + X2PIXEL11_22 + break; + } + case 40: + case 44: + case 168: + case 172: + { + X2PIXEL00_21 + X2PIXEL01_20 + X2PIXEL10_11 + X2PIXEL11_20 + break; + } + case 9: + case 13: + case 137: + case 141: + { + X2PIXEL00_12 + X2PIXEL01_20 + X2PIXEL10_22 + X2PIXEL11_20 + break; + } + case 18: + case 50: + { + X2PIXEL00_22 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_20 + X2PIXEL11_21 + break; + } + case 80: + case 81: + { + X2PIXEL00_20 + X2PIXEL01_22 + X2PIXEL10_21 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_20 + } + break; + } + case 72: + case 76: + { + X2PIXEL00_21 + X2PIXEL01_20 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_22 + break; + } + case 10: + case 138: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_21 + X2PIXEL10_22 + X2PIXEL11_20 + break; + } + case 66: + { + X2PIXEL00_22 + X2PIXEL01_21 + X2PIXEL10_21 + X2PIXEL11_22 + break; + } + case 24: + { + X2PIXEL00_21 + X2PIXEL01_22 + X2PIXEL10_22 + X2PIXEL11_21 + break; + } + case 7: + case 39: + case 135: + { + X2PIXEL00_11 + X2PIXEL01_12 + X2PIXEL10_20 + X2PIXEL11_20 + break; + } + case 148: + case 149: + case 180: + { + X2PIXEL00_20 + X2PIXEL01_11 + X2PIXEL10_20 + X2PIXEL11_12 + break; + } + case 224: + case 228: + case 225: + { + X2PIXEL00_20 + X2PIXEL01_20 + X2PIXEL10_12 + X2PIXEL11_11 + break; + } + case 41: + case 169: + case 45: + { + X2PIXEL00_12 + X2PIXEL01_20 + X2PIXEL10_11 + X2PIXEL11_20 + break; + } + case 22: + case 54: + { + X2PIXEL00_22 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_20 + X2PIXEL11_21 + break; + } + case 208: + case 209: + { + X2PIXEL00_20 + X2PIXEL01_22 + X2PIXEL10_21 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 104: + case 108: + { + X2PIXEL00_21 + X2PIXEL01_20 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_22 + break; + } + case 11: + case 139: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_21 + X2PIXEL10_22 + X2PIXEL11_20 + break; + } + case 19: + case 51: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL00_11 + X2PIXEL01_10 + } + else + { + X2PIXEL00_60 + X2PIXEL01_90 + } + X2PIXEL10_20 + X2PIXEL11_21 + break; + } + case 146: + case 178: + { + X2PIXEL00_22 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + X2PIXEL11_12 + } + else + { + X2PIXEL01_90 + X2PIXEL11_61 + } + X2PIXEL10_20 + break; + } + case 84: + case 85: + { + X2PIXEL00_20 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL01_11 + X2PIXEL11_10 + } + else + { + X2PIXEL01_60 + X2PIXEL11_90 + } + X2PIXEL10_21 + break; + } + case 112: + case 113: + { + X2PIXEL00_20 + X2PIXEL01_22 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL10_12 + X2PIXEL11_10 + } + else + { + X2PIXEL10_61 + X2PIXEL11_90 + } + break; + } + case 200: + case 204: + { + X2PIXEL00_21 + X2PIXEL01_20 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + X2PIXEL11_11 + } + else + { + X2PIXEL10_90 + X2PIXEL11_60 + } + break; + } + case 73: + case 77: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL00_12 + X2PIXEL10_10 + } + else + { + X2PIXEL00_61 + X2PIXEL10_90 + } + X2PIXEL01_20 + X2PIXEL11_22 + break; + } + case 42: + case 170: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + X2PIXEL10_11 + } + else + { + X2PIXEL00_90 + X2PIXEL10_60 + } + X2PIXEL01_21 + X2PIXEL11_20 + break; + } + case 14: + case 142: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + X2PIXEL01_12 + } + else + { + X2PIXEL00_90 + X2PIXEL01_61 + } + X2PIXEL10_22 + X2PIXEL11_20 + break; + } + case 67: + { + X2PIXEL00_11 + X2PIXEL01_21 + X2PIXEL10_21 + X2PIXEL11_22 + break; + } + case 70: + { + X2PIXEL00_22 + X2PIXEL01_12 + X2PIXEL10_21 + X2PIXEL11_22 + break; + } + case 28: + { + X2PIXEL00_21 + X2PIXEL01_11 + X2PIXEL10_22 + X2PIXEL11_21 + break; + } + case 152: + { + X2PIXEL00_21 + X2PIXEL01_22 + X2PIXEL10_22 + X2PIXEL11_12 + break; + } + case 194: + { + X2PIXEL00_22 + X2PIXEL01_21 + X2PIXEL10_21 + X2PIXEL11_11 + break; + } + case 98: + { + X2PIXEL00_22 + X2PIXEL01_21 + X2PIXEL10_12 + X2PIXEL11_22 + break; + } + case 56: + { + X2PIXEL00_21 + X2PIXEL01_22 + X2PIXEL10_11 + X2PIXEL11_21 + break; + } + case 25: + { + X2PIXEL00_12 + X2PIXEL01_22 + X2PIXEL10_22 + X2PIXEL11_21 + break; + } + case 26: + case 31: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_22 + X2PIXEL11_21 + break; + } + case 82: + case 214: + { + X2PIXEL00_22 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_21 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 88: + case 248: + { + X2PIXEL00_21 + X2PIXEL01_22 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 74: + case 107: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_21 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_22 + break; + } + case 27: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_10 + X2PIXEL10_22 + X2PIXEL11_21 + break; + } + case 86: + { + X2PIXEL00_22 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_21 + X2PIXEL11_10 + break; + } + case 216: + { + X2PIXEL00_21 + X2PIXEL01_22 + X2PIXEL10_10 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 106: + { + X2PIXEL00_10 + X2PIXEL01_21 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_22 + break; + } + case 30: + { + X2PIXEL00_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_22 + X2PIXEL11_21 + break; + } + case 210: + { + X2PIXEL00_22 + X2PIXEL01_10 + X2PIXEL10_21 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 120: + { + X2PIXEL00_21 + X2PIXEL01_22 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_10 + break; + } + case 75: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_21 + X2PIXEL10_10 + X2PIXEL11_22 + break; + } + case 29: + { + X2PIXEL00_12 + X2PIXEL01_11 + X2PIXEL10_22 + X2PIXEL11_21 + break; + } + case 198: + { + X2PIXEL00_22 + X2PIXEL01_12 + X2PIXEL10_21 + X2PIXEL11_11 + break; + } + case 184: + { + X2PIXEL00_21 + X2PIXEL01_22 + X2PIXEL10_11 + X2PIXEL11_12 + break; + } + case 99: + { + X2PIXEL00_11 + X2PIXEL01_21 + X2PIXEL10_12 + X2PIXEL11_22 + break; + } + case 57: + { + X2PIXEL00_12 + X2PIXEL01_22 + X2PIXEL10_11 + X2PIXEL11_21 + break; + } + case 71: + { + X2PIXEL00_11 + X2PIXEL01_12 + X2PIXEL10_21 + X2PIXEL11_22 + break; + } + case 156: + { + X2PIXEL00_21 + X2PIXEL01_11 + X2PIXEL10_22 + X2PIXEL11_12 + break; + } + case 226: + { + X2PIXEL00_22 + X2PIXEL01_21 + X2PIXEL10_12 + X2PIXEL11_11 + break; + } + case 60: + { + X2PIXEL00_21 + X2PIXEL01_11 + X2PIXEL10_11 + X2PIXEL11_21 + break; + } + case 195: + { + X2PIXEL00_11 + X2PIXEL01_21 + X2PIXEL10_21 + X2PIXEL11_11 + break; + } + case 102: + { + X2PIXEL00_22 + X2PIXEL01_12 + X2PIXEL10_12 + X2PIXEL11_22 + break; + } + case 153: + { + X2PIXEL00_12 + X2PIXEL01_22 + X2PIXEL10_22 + X2PIXEL11_12 + break; + } + case 58: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + X2PIXEL10_11 + X2PIXEL11_21 + break; + } + case 83: + { + X2PIXEL00_11 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + X2PIXEL10_21 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 92: + { + X2PIXEL00_21 + X2PIXEL01_11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 202: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + X2PIXEL01_21 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + X2PIXEL11_11 + break; + } + case 78: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + X2PIXEL01_12 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + X2PIXEL11_22 + break; + } + case 154: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + X2PIXEL10_22 + X2PIXEL11_12 + break; + } + case 114: + { + X2PIXEL00_22 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + X2PIXEL10_12 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 89: + { + X2PIXEL00_12 + X2PIXEL01_22 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 90: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 55: + case 23: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL00_11 + X2PIXEL01_0 + } + else + { + X2PIXEL00_60 + X2PIXEL01_90 + } + X2PIXEL10_20 + X2PIXEL11_21 + break; + } + case 182: + case 150: + { + X2PIXEL00_22 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + X2PIXEL11_12 + } + else + { + X2PIXEL01_90 + X2PIXEL11_61 + } + X2PIXEL10_20 + break; + } + case 213: + case 212: + { + X2PIXEL00_20 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL01_11 + X2PIXEL11_0 + } + else + { + X2PIXEL01_60 + X2PIXEL11_90 + } + X2PIXEL10_21 + break; + } + case 241: + case 240: + { + X2PIXEL00_20 + X2PIXEL01_22 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL10_12 + X2PIXEL11_0 + } + else + { + X2PIXEL10_61 + X2PIXEL11_90 + } + break; + } + case 236: + case 232: + { + X2PIXEL00_21 + X2PIXEL01_20 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + X2PIXEL11_11 + } + else + { + X2PIXEL10_90 + X2PIXEL11_60 + } + break; + } + case 109: + case 105: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL00_12 + X2PIXEL10_0 + } + else + { + X2PIXEL00_61 + X2PIXEL10_90 + } + X2PIXEL01_20 + X2PIXEL11_22 + break; + } + case 171: + case 43: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + X2PIXEL10_11 + } + else + { + X2PIXEL00_90 + X2PIXEL10_60 + } + X2PIXEL01_21 + X2PIXEL11_20 + break; + } + case 143: + case 15: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + X2PIXEL01_12 + } + else + { + X2PIXEL00_90 + X2PIXEL01_61 + } + X2PIXEL10_22 + X2PIXEL11_20 + break; + } + case 124: + { + X2PIXEL00_21 + X2PIXEL01_11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_10 + break; + } + case 203: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_21 + X2PIXEL10_10 + X2PIXEL11_11 + break; + } + case 62: + { + X2PIXEL00_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_11 + X2PIXEL11_21 + break; + } + case 211: + { + X2PIXEL00_11 + X2PIXEL01_10 + X2PIXEL10_21 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 118: + { + X2PIXEL00_22 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_12 + X2PIXEL11_10 + break; + } + case 217: + { + X2PIXEL00_12 + X2PIXEL01_22 + X2PIXEL10_10 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 110: + { + X2PIXEL00_10 + X2PIXEL01_12 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_22 + break; + } + case 155: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_10 + X2PIXEL10_22 + X2PIXEL11_12 + break; + } + case 188: + { + X2PIXEL00_21 + X2PIXEL01_11 + X2PIXEL10_11 + X2PIXEL11_12 + break; + } + case 185: + { + X2PIXEL00_12 + X2PIXEL01_22 + X2PIXEL10_11 + X2PIXEL11_12 + break; + } + case 61: + { + X2PIXEL00_12 + X2PIXEL01_11 + X2PIXEL10_11 + X2PIXEL11_21 + break; + } + case 157: + { + X2PIXEL00_12 + X2PIXEL01_11 + X2PIXEL10_22 + X2PIXEL11_12 + break; + } + case 103: + { + X2PIXEL00_11 + X2PIXEL01_12 + X2PIXEL10_12 + X2PIXEL11_22 + break; + } + case 227: + { + X2PIXEL00_11 + X2PIXEL01_21 + X2PIXEL10_12 + X2PIXEL11_11 + break; + } + case 230: + { + X2PIXEL00_22 + X2PIXEL01_12 + X2PIXEL10_12 + X2PIXEL11_11 + break; + } + case 199: + { + X2PIXEL00_11 + X2PIXEL01_12 + X2PIXEL10_21 + X2PIXEL11_11 + break; + } + case 220: + { + X2PIXEL00_21 + X2PIXEL01_11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 158: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_22 + X2PIXEL11_12 + break; + } + case 234: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + X2PIXEL01_21 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_11 + break; + } + case 242: + { + X2PIXEL00_22 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + X2PIXEL10_12 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 59: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + X2PIXEL10_11 + X2PIXEL11_21 + break; + } + case 121: + { + X2PIXEL00_12 + X2PIXEL01_22 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 87: + { + X2PIXEL00_11 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_21 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 79: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_12 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + X2PIXEL11_22 + break; + } + case 122: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 94: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 218: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 91: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 229: + { + X2PIXEL00_20 + X2PIXEL01_20 + X2PIXEL10_12 + X2PIXEL11_11 + break; + } + case 167: + { + X2PIXEL00_11 + X2PIXEL01_12 + X2PIXEL10_20 + X2PIXEL11_20 + break; + } + case 173: + { + X2PIXEL00_12 + X2PIXEL01_20 + X2PIXEL10_11 + X2PIXEL11_20 + break; + } + case 181: + { + X2PIXEL00_20 + X2PIXEL01_11 + X2PIXEL10_20 + X2PIXEL11_12 + break; + } + case 186: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + X2PIXEL10_11 + X2PIXEL11_12 + break; + } + case 115: + { + X2PIXEL00_11 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + X2PIXEL10_12 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 93: + { + X2PIXEL00_12 + X2PIXEL01_11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 206: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + X2PIXEL01_12 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + X2PIXEL11_11 + break; + } + case 205: + case 201: + { + X2PIXEL00_12 + X2PIXEL01_20 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_10 + } + else + { + X2PIXEL10_70 + } + X2PIXEL11_11 + break; + } + case 174: + case 46: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_10 + } + else + { + X2PIXEL00_70 + } + X2PIXEL01_12 + X2PIXEL10_11 + X2PIXEL11_20 + break; + } + case 179: + case 147: + { + X2PIXEL00_11 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_10 + } + else + { + X2PIXEL01_70 + } + X2PIXEL10_20 + X2PIXEL11_12 + break; + } + case 117: + case 116: + { + X2PIXEL00_20 + X2PIXEL01_11 + X2PIXEL10_12 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_10 + } + else + { + X2PIXEL11_70 + } + break; + } + case 189: + { + X2PIXEL00_12 + X2PIXEL01_11 + X2PIXEL10_11 + X2PIXEL11_12 + break; + } + case 231: + { + X2PIXEL00_11 + X2PIXEL01_12 + X2PIXEL10_12 + X2PIXEL11_11 + break; + } + case 126: + { + X2PIXEL00_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_10 + break; + } + case 219: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_10 + X2PIXEL10_10 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 125: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL00_12 + X2PIXEL10_0 + } + else + { + X2PIXEL00_61 + X2PIXEL10_90 + } + X2PIXEL01_11 + X2PIXEL11_10 + break; + } + case 221: + { + X2PIXEL00_12 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL01_11 + X2PIXEL11_0 + } + else + { + X2PIXEL01_60 + X2PIXEL11_90 + } + X2PIXEL10_10 + break; + } + case 207: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + X2PIXEL01_12 + } + else + { + X2PIXEL00_90 + X2PIXEL01_61 + } + X2PIXEL10_10 + X2PIXEL11_11 + break; + } + case 238: + { + X2PIXEL00_10 + X2PIXEL01_12 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + X2PIXEL11_11 + } + else + { + X2PIXEL10_90 + X2PIXEL11_60 + } + break; + } + case 190: + { + X2PIXEL00_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + X2PIXEL11_12 + } + else + { + X2PIXEL01_90 + X2PIXEL11_61 + } + X2PIXEL10_11 + break; + } + case 187: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + X2PIXEL10_11 + } + else + { + X2PIXEL00_90 + X2PIXEL10_60 + } + X2PIXEL01_10 + X2PIXEL11_12 + break; + } + case 243: + { + X2PIXEL00_11 + X2PIXEL01_10 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL10_12 + X2PIXEL11_0 + } + else + { + X2PIXEL10_61 + X2PIXEL11_90 + } + break; + } + case 119: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL00_11 + X2PIXEL01_0 + } + else + { + X2PIXEL00_60 + X2PIXEL01_90 + } + X2PIXEL10_12 + X2PIXEL11_10 + break; + } + case 237: + case 233: + { + X2PIXEL00_12 + X2PIXEL01_20 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_100 + } + X2PIXEL11_11 + break; + } + case 175: + case 47: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_100 + } + X2PIXEL01_12 + X2PIXEL10_11 + X2PIXEL11_20 + break; + } + case 183: + case 151: + { + X2PIXEL00_11 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_100 + } + X2PIXEL10_20 + X2PIXEL11_12 + break; + } + case 245: + case 244: + { + X2PIXEL00_20 + X2PIXEL01_11 + X2PIXEL10_12 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_100 + } + break; + } + case 250: + { + X2PIXEL00_10 + X2PIXEL01_10 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 123: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_10 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_10 + break; + } + case 95: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_10 + X2PIXEL11_10 + break; + } + case 222: + { + X2PIXEL00_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_10 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 252: + { + X2PIXEL00_21 + X2PIXEL01_11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_100 + } + break; + } + case 249: + { + X2PIXEL00_12 + X2PIXEL01_22 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_100 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 235: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_21 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_100 + } + X2PIXEL11_11 + break; + } + case 111: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_100 + } + X2PIXEL01_12 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_22 + break; + } + case 63: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_100 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_11 + X2PIXEL11_21 + break; + } + case 159: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_100 + } + X2PIXEL10_22 + X2PIXEL11_12 + break; + } + case 215: + { + X2PIXEL00_11 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_100 + } + X2PIXEL10_21 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 246: + { + X2PIXEL00_22 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + X2PIXEL10_12 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_100 + } + break; + } + case 254: + { + X2PIXEL00_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_100 + } + break; + } + case 253: + { + X2PIXEL00_12 + X2PIXEL01_11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_100 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_100 + } + break; + } + case 251: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + X2PIXEL01_10 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_100 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 239: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_100 + } + X2PIXEL01_12 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_100 + } + X2PIXEL11_11 + break; + } + case 127: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_100 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_20 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_20 + } + X2PIXEL11_10 + break; + } + case 191: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_100 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_100 + } + X2PIXEL10_11 + X2PIXEL11_12 + break; + } + case 223: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_20 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_100 + } + X2PIXEL10_10 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_20 + } + break; + } + case 247: + { + X2PIXEL00_11 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_100 + } + X2PIXEL10_12 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_100 + } + break; + } + case 255: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X2PIXEL00_0 + } + else + { + X2PIXEL00_100 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X2PIXEL01_0 + } + else + { + X2PIXEL01_100 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X2PIXEL10_0 + } + else + { + X2PIXEL10_100 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X2PIXEL11_0 + } + else + { + X2PIXEL11_100 + } + break; + } + } + + w1 = w2; w4 = w5; w7 = w8; + w2 = w3; w5 = w6; w8 = w9; + + dp += 2; + } + + dp += (dst1line - width) * 2; + sp += (src1line - width); + } +} + +void HQ3X_16 (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + register int w1, w2, w3, w4, w5, w6, w7, w8, w9; + register uint32 src1line = srcPitch >> 1; + register uint32 dst1line = dstPitch >> 1; + register uint16 *sp = (uint16 *) srcPtr; + register uint16 *dp = (uint16 *) dstPtr; + + uint32 pattern; + int l, y; + + while (height--) + { + sp--; + + w1 = *(sp - src1line); + w4 = *(sp); + w7 = *(sp + src1line); + + sp++; + + w2 = *(sp - src1line); + w5 = *(sp); + w8 = *(sp + src1line); + + for (l = width; l; l--) + { + sp++; + + w3 = *(sp - src1line); + w6 = *(sp); + w9 = *(sp + src1line); + + y = RGBtoYUV[w5]; + pattern = 0; + + if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7); + + switch (pattern) + { + case 0: + case 1: + case 4: + case 32: + case 128: + case 5: + case 132: + case 160: + case 33: + case 129: + case 36: + case 133: + case 164: + case 161: + case 37: + case 165: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 2: + case 34: + case 130: + case 162: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 16: + case 17: + case 48: + case 49: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 64: + case 65: + case 68: + case 69: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 8: + case 12: + case 136: + case 140: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 3: + case 35: + case 131: + case 163: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 6: + case 38: + case 134: + case 166: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 20: + case 21: + case 52: + case 53: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 144: + case 145: + case 176: + case 177: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 192: + case 193: + case 196: + case 197: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 96: + case 97: + case 100: + case 101: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 40: + case 44: + case 168: + case 172: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 9: + case 13: + case 137: + case 141: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 18: + case 50: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 80: + case 81: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_1M + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 72: + case 76: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_1M + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 10: + case 138: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + X3PIXEL10_3 + } + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 66: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 24: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 7: + case 39: + case 135: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 148: + case 149: + case 180: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 224: + case 228: + case 225: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 41: + case 169: + case 45: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 22: + case 54: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 208: + case 209: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 104: + case 108: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 11: + case 139: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + X3PIXEL10_3 + } + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 19: + case 51: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL12_C + } + else + { + X3PIXEL00_2 + X3PIXEL01_6 + X3PIXEL02_5 + X3PIXEL12_1 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 146: + case 178: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL12_C + X3PIXEL22_1D + } + else + { + X3PIXEL01_1 + X3PIXEL02_5 + X3PIXEL12_6 + X3PIXEL22_2 + } + X3PIXEL00_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_2 + X3PIXEL21_1 + break; + } + case 84: + case 85: + { + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL02_1U + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_1M + } + else + { + X3PIXEL02_2 + X3PIXEL12_6 + X3PIXEL21_1 + X3PIXEL22_5 + } + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1M + break; + } + case 112: + case 113: + { + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1M + } + else + { + X3PIXEL12_1 + X3PIXEL20_2 + X3PIXEL21_6 + X3PIXEL22_5 + } + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + break; + } + case 200: + case 204: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1R + } + else + { + X3PIXEL10_1 + X3PIXEL20_5 + X3PIXEL21_6 + X3PIXEL22_2 + } + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL11 + X3PIXEL12_1 + break; + } + case 73: + case 77: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL00_1U + X3PIXEL10_C + X3PIXEL20_1M + X3PIXEL21_C + } + else + { + X3PIXEL00_2 + X3PIXEL10_6 + X3PIXEL20_5 + X3PIXEL21_1 + } + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL22_1M + break; + } + case 42: + case 170: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL10_C + X3PIXEL20_1D + } + else + { + X3PIXEL00_5 + X3PIXEL01_1 + X3PIXEL10_6 + X3PIXEL20_2 + } + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 14: + case 142: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_C + } + else + { + X3PIXEL00_5 + X3PIXEL01_6 + X3PIXEL02_2 + X3PIXEL10_1 + } + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 67: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 70: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 28: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 152: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 194: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 98: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 56: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 25: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 26: + case 31: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL10_3 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL11 + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 82: + case 214: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 88: + case 248: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL22_4 + } + break; + } + case 74: + case 107: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + } + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 27: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + X3PIXEL10_3 + } + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 86: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 216: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 106: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 30: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 210: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 120: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 75: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + X3PIXEL10_3 + } + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 29: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 198: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 184: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 99: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 57: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 71: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 156: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 226: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 60: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 195: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 102: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 153: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 58: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 83: + { + X3PIXEL00_1L + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 92: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 202: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 78: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 154: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 114: + { + X3PIXEL00_1M + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1L + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 89: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 90: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 55: + case 23: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL00_2 + X3PIXEL01_6 + X3PIXEL02_5 + X3PIXEL12_1 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 182: + case 150: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + X3PIXEL22_1D + } + else + { + X3PIXEL01_1 + X3PIXEL02_5 + X3PIXEL12_6 + X3PIXEL22_2 + } + X3PIXEL00_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_2 + X3PIXEL21_1 + break; + } + case 213: + case 212: + { + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL02_1U + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL02_2 + X3PIXEL12_6 + X3PIXEL21_1 + X3PIXEL22_5 + } + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1M + break; + } + case 241: + case 240: + { + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_1 + X3PIXEL20_2 + X3PIXEL21_6 + X3PIXEL22_5 + } + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + break; + } + case 236: + case 232: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + X3PIXEL22_1R + } + else + { + X3PIXEL10_1 + X3PIXEL20_5 + X3PIXEL21_6 + X3PIXEL22_2 + } + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL11 + X3PIXEL12_1 + break; + } + case 109: + case 105: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL00_1U + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL00_2 + X3PIXEL10_6 + X3PIXEL20_5 + X3PIXEL21_1 + } + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL22_1M + break; + } + case 171: + case 43: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + X3PIXEL20_1D + } + else + { + X3PIXEL00_5 + X3PIXEL01_1 + X3PIXEL10_6 + X3PIXEL20_2 + } + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 143: + case 15: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_C + } + else + { + X3PIXEL00_5 + X3PIXEL01_6 + X3PIXEL02_2 + X3PIXEL10_1 + } + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 124: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 203: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + X3PIXEL10_3 + } + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 62: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 211: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 118: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 217: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 110: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 155: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + X3PIXEL10_3 + } + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 188: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 185: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 61: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 157: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 103: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 227: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 230: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 199: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 220: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 158: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 234: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1R + break; + } + case 242: + { + X3PIXEL00_1M + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1L + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 59: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + X3PIXEL10_3 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 121: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + X3PIXEL21_3 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 87: + { + X3PIXEL00_1L + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1M + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 79: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + X3PIXEL10_3 + } + X3PIXEL02_1R + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 122: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + X3PIXEL21_3 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 94: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL10_C + X3PIXEL11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 218: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_C + X3PIXEL11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 91: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + X3PIXEL10_3 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 229: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 167: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 173: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 181: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 186: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 115: + { + X3PIXEL00_1L + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1L + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 93: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 206: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 205: + case 201: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_1M + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 174: + case 46: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_1M + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 179: + case 147: + { + X3PIXEL00_1L + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_1M + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 117: + case 116: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1L + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_1M + } + else + { + X3PIXEL22_2 + } + break; + } + case 189: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 231: + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 126: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 219: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + X3PIXEL10_3 + } + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 125: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL00_1U + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL00_2 + X3PIXEL10_6 + X3PIXEL20_5 + X3PIXEL21_1 + } + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL11 + X3PIXEL12_C + X3PIXEL22_1M + break; + } + case 221: + { + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL02_1U + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL02_2 + X3PIXEL12_6 + X3PIXEL21_1 + X3PIXEL22_5 + } + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL10_C + X3PIXEL11 + X3PIXEL20_1M + break; + } + case 207: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_C + } + else + { + X3PIXEL00_5 + X3PIXEL01_6 + X3PIXEL02_2 + X3PIXEL10_1 + } + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 238: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + X3PIXEL22_1R + } + else + { + X3PIXEL10_1 + X3PIXEL20_5 + X3PIXEL21_6 + X3PIXEL22_2 + } + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL11 + X3PIXEL12_1 + break; + } + case 190: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + X3PIXEL22_1D + } + else + { + X3PIXEL01_1 + X3PIXEL02_5 + X3PIXEL12_6 + X3PIXEL22_2 + } + X3PIXEL00_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL20_1D + X3PIXEL21_1 + break; + } + case 187: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + X3PIXEL20_1D + } + else + { + X3PIXEL00_5 + X3PIXEL01_1 + X3PIXEL10_6 + X3PIXEL20_2 + } + X3PIXEL02_1M + X3PIXEL11 + X3PIXEL12_C + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 243: + { + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_1 + X3PIXEL20_2 + X3PIXEL21_6 + X3PIXEL22_5 + } + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL10_1 + X3PIXEL11 + break; + } + case 119: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL00_1L + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL00_2 + X3PIXEL01_6 + X3PIXEL02_5 + X3PIXEL12_1 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL20_1L + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 237: + case 233: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_2 + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_C + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 175: + case 47: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_2 + break; + } + case 183: + case 151: + { + X3PIXEL00_1L + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_C + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_2 + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 245: + case 244: + { + X3PIXEL00_2 + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1L + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_C + } + else + { + X3PIXEL22_2 + } + break; + } + case 250: + { + X3PIXEL00_1M + X3PIXEL01_C + X3PIXEL02_1M + X3PIXEL11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL22_4 + } + break; + } + case 123: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + } + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 95: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL10_3 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL11 + X3PIXEL20_1M + X3PIXEL21_C + X3PIXEL22_1M + break; + } + case 222: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 252: + { + X3PIXEL00_1M + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_C + } + else + { + X3PIXEL22_2 + } + break; + } + case 249: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_C + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL22_4 + } + break; + } + case 235: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + } + X3PIXEL02_1M + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_C + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 111: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 63: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1M + break; + } + case 159: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL10_3 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_C + } + else + { + X3PIXEL02_2 + } + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 215: + { + X3PIXEL00_1L + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_C + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 246: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1L + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_C + } + else + { + X3PIXEL22_2 + } + break; + } + case 254: + { + X3PIXEL00_1M + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_4 + } + X3PIXEL11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_4 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL21_3 + X3PIXEL22_2 + } + break; + } + case 253: + { + X3PIXEL00_1U + X3PIXEL01_1 + X3PIXEL02_1U + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_C + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_C + } + else + { + X3PIXEL22_2 + } + break; + } + case 251: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + } + else + { + X3PIXEL00_4 + X3PIXEL01_3 + } + X3PIXEL02_1M + X3PIXEL11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL10_C + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL10_3 + X3PIXEL20_2 + X3PIXEL21_3 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL12_C + X3PIXEL22_C + } + else + { + X3PIXEL12_3 + X3PIXEL22_4 + } + break; + } + case 239: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + X3PIXEL02_1R + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_1 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_C + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + X3PIXEL22_1R + break; + } + case 127: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL01_C + X3PIXEL10_C + } + else + { + X3PIXEL00_2 + X3PIXEL01_3 + X3PIXEL10_3 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL02_4 + X3PIXEL12_3 + } + X3PIXEL11 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_C + X3PIXEL21_C + } + else + { + X3PIXEL20_4 + X3PIXEL21_3 + } + X3PIXEL22_1M + break; + } + case 191: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_C + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1D + X3PIXEL21_1 + X3PIXEL22_1D + break; + } + case 223: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + X3PIXEL10_C + } + else + { + X3PIXEL00_4 + X3PIXEL10_3 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL01_C + X3PIXEL02_C + X3PIXEL12_C + } + else + { + X3PIXEL01_3 + X3PIXEL02_2 + X3PIXEL12_3 + } + X3PIXEL11 + X3PIXEL20_1M + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL21_C + X3PIXEL22_C + } + else + { + X3PIXEL21_3 + X3PIXEL22_4 + } + break; + } + case 247: + { + X3PIXEL00_1L + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_C + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_1 + X3PIXEL11 + X3PIXEL12_C + X3PIXEL20_1L + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_C + } + else + { + X3PIXEL22_2 + } + break; + } + case 255: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X3PIXEL00_C + } + else + { + X3PIXEL00_2 + } + X3PIXEL01_C + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X3PIXEL02_C + } + else + { + X3PIXEL02_2 + } + X3PIXEL10_C + X3PIXEL11 + X3PIXEL12_C + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X3PIXEL20_C + } + else + { + X3PIXEL20_2 + } + X3PIXEL21_C + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X3PIXEL22_C + } + else + { + X3PIXEL22_2 + } + break; + } + } + + w1 = w2; w4 = w5; w7 = w8; + w2 = w3; w5 = w6; w8 = w9; + + dp += 3; + } + + dp += (dst1line - width) * 3; + sp += (src1line - width); + } +} + +void HQ4X_16 (uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) +{ + register int w1, w2, w3, w4, w5, w6, w7, w8, w9; + register uint32 src1line = srcPitch >> 1; + register uint32 dst1line = dstPitch >> 1; + register uint16 *sp = (uint16 *) srcPtr; + register uint16 *dp = (uint16 *) dstPtr; + + uint32 pattern; + int l, y; + + while (height--) + { + sp--; + + w1 = *(sp - src1line); + w4 = *(sp); + w7 = *(sp + src1line); + + sp++; + + w2 = *(sp - src1line); + w5 = *(sp); + w8 = *(sp + src1line); + + for (l = width; l; l--) + { + sp++; + + w3 = *(sp - src1line); + w6 = *(sp); + w9 = *(sp + src1line); + + y = RGBtoYUV[w5]; + pattern = 0; + + if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7); + + switch (pattern) + { + case 0: + case 1: + case 4: + case 32: + case 128: + case 5: + case 132: + case 160: + case 33: + case 129: + case 36: + case 133: + case 164: + case 161: + case 37: + case 165: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 2: + case 34: + case 130: + case 162: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 16: + case 17: + case 48: + case 49: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 64: + case 65: + case 68: + case 69: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 8: + case 12: + case 136: + case 140: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 3: + case 35: + case 131: + case 163: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 6: + case 38: + case 134: + case 166: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 20: + case 21: + case 52: + case 53: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 144: + case 145: + case 176: + case 177: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 192: + case 193: + case 196: + case 197: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 96: + case 97: + case 100: + case 101: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 40: + case 44: + case 168: + case 172: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 9: + case 13: + case 137: + case 141: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 18: + case 50: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL12_0 + X4PIXEL13_50 + } + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 80: + case 81: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_61 + X4PIXEL21_30 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 72: + case 76: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_70 + X4PIXEL13_60 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_50 + X4PIXEL21_0 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 10: + case 138: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + X4PIXEL11_0 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 66: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 24: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 7: + case 39: + case 135: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 148: + case 149: + case 180: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 224: + case 228: + case 225: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 41: + case 169: + case 45: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 22: + case 54: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_0 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 208: + case 209: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 104: + case 108: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_70 + X4PIXEL13_60 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 11: + case 139: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL11_0 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 19: + case 51: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL00_12 + X4PIXEL01_14 + X4PIXEL02_83 + X4PIXEL03_50 + X4PIXEL12_70 + X4PIXEL13_21 + } + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 146: + case 178: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL23_32 + X4PIXEL33_82 + } + else + { + X4PIXEL02_21 + X4PIXEL03_50 + X4PIXEL12_70 + X4PIXEL13_83 + X4PIXEL23_13 + X4PIXEL33_11 + } + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_32 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_82 + break; + } + case 84: + case 85: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_81 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL03_81 + X4PIXEL13_31 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL03_12 + X4PIXEL13_14 + X4PIXEL22_70 + X4PIXEL23_83 + X4PIXEL32_21 + X4PIXEL33_50 + } + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_31 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 112: + case 113: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_82 + X4PIXEL21_32 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_70 + X4PIXEL23_21 + X4PIXEL30_11 + X4PIXEL31_13 + X4PIXEL32_83 + X4PIXEL33_50 + } + break; + } + case 200: + case 204: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_70 + X4PIXEL13_60 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_31 + X4PIXEL33_81 + } + else + { + X4PIXEL20_21 + X4PIXEL21_70 + X4PIXEL30_50 + X4PIXEL31_83 + X4PIXEL32_14 + X4PIXEL33_12 + } + X4PIXEL22_31 + X4PIXEL23_81 + break; + } + case 73: + case 77: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL00_82 + X4PIXEL10_32 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL00_11 + X4PIXEL10_13 + X4PIXEL20_83 + X4PIXEL21_70 + X4PIXEL30_50 + X4PIXEL31_21 + } + X4PIXEL01_82 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL11_32 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 42: + case 170: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL20_31 + X4PIXEL30_81 + } + else + { + X4PIXEL00_50 + X4PIXEL01_21 + X4PIXEL10_83 + X4PIXEL11_70 + X4PIXEL20_14 + X4PIXEL30_12 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL21_31 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL31_81 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 14: + case 142: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_50 + X4PIXEL01_83 + X4PIXEL02_13 + X4PIXEL03_11 + X4PIXEL10_21 + X4PIXEL11_70 + } + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 67: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 70: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 28: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 152: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 194: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 98: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 56: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 25: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 26: + case 31: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL11_0 + X4PIXEL12_0 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 82: + case 214: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_0 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 88: + case 248: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_10 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + break; + } + case 74: + case 107: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL11_0 + X4PIXEL12_30 + X4PIXEL13_61 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 27: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL11_0 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 86: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_0 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 216: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 106: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_61 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 30: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_0 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 210: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 120: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_10 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 75: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL11_0 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 29: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 198: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 184: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 99: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 57: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 71: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 156: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 226: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 60: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 195: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 102: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 153: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 58: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 83: + { + X4PIXEL00_81 + X4PIXEL01_31 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL20_61 + X4PIXEL21_30 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 92: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_31 + X4PIXEL13_31 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + break; + } + case 202: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_61 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 78: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL12_32 + X4PIXEL13_82 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 154: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 114: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL20_82 + X4PIXEL21_32 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + X4PIXEL30_82 + X4PIXEL31_32 + break; + } + case 89: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_30 + X4PIXEL13_10 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + break; + } + case 90: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + break; + } + case 55: + case 23: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL12_0 + X4PIXEL13_0 + } + else + { + X4PIXEL00_12 + X4PIXEL01_14 + X4PIXEL02_83 + X4PIXEL03_50 + X4PIXEL12_70 + X4PIXEL13_21 + } + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 182: + case 150: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL12_0 + X4PIXEL13_0 + X4PIXEL23_32 + X4PIXEL33_82 + } + else + { + X4PIXEL02_21 + X4PIXEL03_50 + X4PIXEL12_70 + X4PIXEL13_83 + X4PIXEL23_13 + X4PIXEL33_11 + } + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_32 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_82 + break; + } + case 213: + case 212: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_81 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL03_81 + X4PIXEL13_31 + X4PIXEL22_0 + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL03_12 + X4PIXEL13_14 + X4PIXEL22_70 + X4PIXEL23_83 + X4PIXEL32_21 + X4PIXEL33_50 + } + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_31 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 241: + case 240: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_82 + X4PIXEL21_32 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_0 + X4PIXEL23_0 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL22_70 + X4PIXEL23_21 + X4PIXEL30_11 + X4PIXEL31_13 + X4PIXEL32_83 + X4PIXEL33_50 + } + break; + } + case 236: + case 232: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_70 + X4PIXEL13_60 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL30_0 + X4PIXEL31_0 + X4PIXEL32_31 + X4PIXEL33_81 + } + else + { + X4PIXEL20_21 + X4PIXEL21_70 + X4PIXEL30_50 + X4PIXEL31_83 + X4PIXEL32_14 + X4PIXEL33_12 + } + X4PIXEL22_31 + X4PIXEL23_81 + break; + } + case 109: + case 105: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL00_82 + X4PIXEL10_32 + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL00_11 + X4PIXEL10_13 + X4PIXEL20_83 + X4PIXEL21_70 + X4PIXEL30_50 + X4PIXEL31_21 + } + X4PIXEL01_82 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL11_32 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 171: + case 43: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + X4PIXEL11_0 + X4PIXEL20_31 + X4PIXEL30_81 + } + else + { + X4PIXEL00_50 + X4PIXEL01_21 + X4PIXEL10_83 + X4PIXEL11_70 + X4PIXEL20_14 + X4PIXEL30_12 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL21_31 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL31_81 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 143: + case 15: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_0 + X4PIXEL11_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_83 + X4PIXEL02_13 + X4PIXEL03_11 + X4PIXEL10_21 + X4PIXEL11_70 + } + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 124: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_31 + X4PIXEL13_31 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 203: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL11_0 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 62: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_0 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 211: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 118: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_0 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 217: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 110: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_32 + X4PIXEL13_82 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 155: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL11_0 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 188: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 185: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 61: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 157: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 103: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 227: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 230: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 199: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 220: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_31 + X4PIXEL13_31 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + break; + } + case 158: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL12_0 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 234: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_61 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 242: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_82 + X4PIXEL31_32 + break; + } + case 59: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + X4PIXEL11_0 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 121: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_30 + X4PIXEL13_10 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + break; + } + case 87: + { + X4PIXEL00_81 + X4PIXEL01_31 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_0 + X4PIXEL20_61 + X4PIXEL21_30 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 79: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL11_0 + X4PIXEL12_32 + X4PIXEL13_82 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 122: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + break; + } + case 94: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL12_0 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + break; + } + case 218: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + break; + } + case 91: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + X4PIXEL11_0 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + break; + } + case 229: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 167: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 173: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 181: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 186: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 115: + { + X4PIXEL00_81 + X4PIXEL01_31 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL20_82 + X4PIXEL21_32 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + X4PIXEL30_82 + X4PIXEL31_32 + break; + } + case 93: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_31 + X4PIXEL13_31 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + break; + } + case 206: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL12_32 + X4PIXEL13_82 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 205: + case 201: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_70 + X4PIXEL13_60 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + } + else + { + X4PIXEL20_12 + X4PIXEL21_0 + X4PIXEL30_20 + X4PIXEL31_11 + } + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 174: + case 46: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL10_10 + X4PIXEL11_30 + } + else + { + X4PIXEL00_20 + X4PIXEL01_12 + X4PIXEL10_11 + X4PIXEL11_0 + } + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 179: + case 147: + { + X4PIXEL00_81 + X4PIXEL01_31 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + } + else + { + X4PIXEL02_11 + X4PIXEL03_20 + X4PIXEL12_0 + X4PIXEL13_12 + } + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 117: + case 116: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_82 + X4PIXEL21_32 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + } + else + { + X4PIXEL22_0 + X4PIXEL23_11 + X4PIXEL32_12 + X4PIXEL33_20 + } + X4PIXEL30_82 + X4PIXEL31_32 + break; + } + case 189: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 231: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 126: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_0 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 219: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL11_0 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 125: + { + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL00_82 + X4PIXEL10_32 + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL00_11 + X4PIXEL10_13 + X4PIXEL20_83 + X4PIXEL21_70 + X4PIXEL30_50 + X4PIXEL31_21 + } + X4PIXEL01_82 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL11_32 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 221: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_81 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL03_81 + X4PIXEL13_31 + X4PIXEL22_0 + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL03_12 + X4PIXEL13_14 + X4PIXEL22_70 + X4PIXEL23_83 + X4PIXEL32_21 + X4PIXEL33_50 + } + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_31 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 207: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_0 + X4PIXEL11_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_83 + X4PIXEL02_13 + X4PIXEL03_11 + X4PIXEL10_21 + X4PIXEL11_70 + } + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_31 + X4PIXEL23_81 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 238: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_32 + X4PIXEL13_82 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL30_0 + X4PIXEL31_0 + X4PIXEL32_31 + X4PIXEL33_81 + } + else + { + X4PIXEL20_21 + X4PIXEL21_70 + X4PIXEL30_50 + X4PIXEL31_83 + X4PIXEL32_14 + X4PIXEL33_12 + } + X4PIXEL22_31 + X4PIXEL23_81 + break; + } + case 190: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL12_0 + X4PIXEL13_0 + X4PIXEL23_32 + X4PIXEL33_82 + } + else + { + X4PIXEL02_21 + X4PIXEL03_50 + X4PIXEL12_70 + X4PIXEL13_83 + X4PIXEL23_13 + X4PIXEL33_11 + } + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_32 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_82 + break; + } + case 187: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + X4PIXEL11_0 + X4PIXEL20_31 + X4PIXEL30_81 + } + else + { + X4PIXEL00_50 + X4PIXEL01_21 + X4PIXEL10_83 + X4PIXEL11_70 + X4PIXEL20_14 + X4PIXEL30_12 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL21_31 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL31_81 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 243: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_82 + X4PIXEL21_32 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL22_0 + X4PIXEL23_0 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL22_70 + X4PIXEL23_21 + X4PIXEL30_11 + X4PIXEL31_13 + X4PIXEL32_83 + X4PIXEL33_50 + } + break; + } + case 119: + { + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL12_0 + X4PIXEL13_0 + } + else + { + X4PIXEL00_12 + X4PIXEL01_14 + X4PIXEL02_83 + X4PIXEL03_50 + X4PIXEL12_70 + X4PIXEL13_21 + } + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 237: + case 233: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_60 + X4PIXEL03_20 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_70 + X4PIXEL13_60 + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL22_31 + X4PIXEL23_81 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL30_0 + } + else + { + X4PIXEL30_20 + } + X4PIXEL31_0 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 175: + case 47: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + } + else + { + X4PIXEL00_20 + } + X4PIXEL01_0 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_0 + X4PIXEL11_0 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_70 + X4PIXEL23_60 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_60 + X4PIXEL33_20 + break; + } + case 183: + case 151: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_0 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL03_0 + } + else + { + X4PIXEL03_20 + } + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_0 + X4PIXEL13_0 + X4PIXEL20_60 + X4PIXEL21_70 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_20 + X4PIXEL31_60 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 245: + case 244: + { + X4PIXEL00_20 + X4PIXEL01_60 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_60 + X4PIXEL11_70 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_0 + X4PIXEL23_0 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL33_0 + } + else + { + X4PIXEL33_20 + } + break; + } + case 250: + { + X4PIXEL00_80 + X4PIXEL01_10 + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_30 + X4PIXEL13_10 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + break; + } + case 123: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL11_0 + X4PIXEL12_30 + X4PIXEL13_10 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 95: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL11_0 + X4PIXEL12_0 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_80 + X4PIXEL31_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 222: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_0 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 252: + { + X4PIXEL00_80 + X4PIXEL01_61 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_31 + X4PIXEL13_31 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_0 + X4PIXEL23_0 + X4PIXEL32_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL33_0 + } + else + { + X4PIXEL33_20 + } + break; + } + case 249: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_61 + X4PIXEL03_80 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL30_0 + } + else + { + X4PIXEL30_20 + } + X4PIXEL31_0 + break; + } + case 235: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL11_0 + X4PIXEL12_30 + X4PIXEL13_61 + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL22_31 + X4PIXEL23_81 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL30_0 + } + else + { + X4PIXEL30_20 + } + X4PIXEL31_0 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 111: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + } + else + { + X4PIXEL00_20 + } + X4PIXEL01_0 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_0 + X4PIXEL11_0 + X4PIXEL12_32 + X4PIXEL13_82 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_30 + X4PIXEL23_61 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 63: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + } + else + { + X4PIXEL00_20 + } + X4PIXEL01_0 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_0 + X4PIXEL11_0 + X4PIXEL12_0 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_61 + X4PIXEL33_80 + break; + } + case 159: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_0 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL03_0 + } + else + { + X4PIXEL03_20 + } + X4PIXEL11_0 + X4PIXEL12_0 + X4PIXEL13_0 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_80 + X4PIXEL31_61 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 215: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_0 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL03_0 + } + else + { + X4PIXEL03_20 + } + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_0 + X4PIXEL13_0 + X4PIXEL20_61 + X4PIXEL21_30 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 246: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_61 + X4PIXEL11_30 + X4PIXEL12_0 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_0 + X4PIXEL23_0 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL33_0 + } + else + { + X4PIXEL33_20 + } + break; + } + case 254: + { + X4PIXEL00_80 + X4PIXEL01_10 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_10 + X4PIXEL11_30 + X4PIXEL12_0 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_0 + X4PIXEL23_0 + X4PIXEL32_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL33_0 + } + else + { + X4PIXEL33_20 + } + break; + } + case 253: + { + X4PIXEL00_82 + X4PIXEL01_82 + X4PIXEL02_81 + X4PIXEL03_81 + X4PIXEL10_32 + X4PIXEL11_32 + X4PIXEL12_31 + X4PIXEL13_31 + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL22_0 + X4PIXEL23_0 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL30_0 + } + else + { + X4PIXEL30_20 + } + X4PIXEL31_0 + X4PIXEL32_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL33_0 + } + else + { + X4PIXEL33_20 + } + break; + } + case 251: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_10 + X4PIXEL03_80 + X4PIXEL11_0 + X4PIXEL12_30 + X4PIXEL13_10 + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL30_0 + } + else + { + X4PIXEL30_20 + } + X4PIXEL31_0 + break; + } + case 239: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + } + else + { + X4PIXEL00_20 + } + X4PIXEL01_0 + X4PIXEL02_32 + X4PIXEL03_82 + X4PIXEL10_0 + X4PIXEL11_0 + X4PIXEL12_32 + X4PIXEL13_82 + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL22_31 + X4PIXEL23_81 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL30_0 + } + else + { + X4PIXEL30_20 + } + X4PIXEL31_0 + X4PIXEL32_31 + X4PIXEL33_81 + break; + } + case 127: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + } + else + { + X4PIXEL00_20 + } + X4PIXEL01_0 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL02_0 + X4PIXEL03_0 + X4PIXEL13_0 + } + else + { + X4PIXEL02_50 + X4PIXEL03_50 + X4PIXEL13_50 + } + X4PIXEL10_0 + X4PIXEL11_0 + X4PIXEL12_0 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL20_0 + X4PIXEL30_0 + X4PIXEL31_0 + } + else + { + X4PIXEL20_50 + X4PIXEL30_50 + X4PIXEL31_50 + } + X4PIXEL21_0 + X4PIXEL22_30 + X4PIXEL23_10 + X4PIXEL32_10 + X4PIXEL33_80 + break; + } + case 191: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + } + else + { + X4PIXEL00_20 + } + X4PIXEL01_0 + X4PIXEL02_0 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL03_0 + } + else + { + X4PIXEL03_20 + } + X4PIXEL10_0 + X4PIXEL11_0 + X4PIXEL12_0 + X4PIXEL13_0 + X4PIXEL20_31 + X4PIXEL21_31 + X4PIXEL22_32 + X4PIXEL23_32 + X4PIXEL30_81 + X4PIXEL31_81 + X4PIXEL32_82 + X4PIXEL33_82 + break; + } + case 223: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + X4PIXEL01_0 + X4PIXEL10_0 + } + else + { + X4PIXEL00_50 + X4PIXEL01_50 + X4PIXEL10_50 + } + X4PIXEL02_0 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL03_0 + } + else + { + X4PIXEL03_20 + } + X4PIXEL11_0 + X4PIXEL12_0 + X4PIXEL13_0 + X4PIXEL20_10 + X4PIXEL21_30 + X4PIXEL22_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL23_0 + X4PIXEL32_0 + X4PIXEL33_0 + } + else + { + X4PIXEL23_50 + X4PIXEL32_50 + X4PIXEL33_50 + } + X4PIXEL30_80 + X4PIXEL31_10 + break; + } + case 247: + { + X4PIXEL00_81 + X4PIXEL01_31 + X4PIXEL02_0 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL03_0 + } + else + { + X4PIXEL03_20 + } + X4PIXEL10_81 + X4PIXEL11_31 + X4PIXEL12_0 + X4PIXEL13_0 + X4PIXEL20_82 + X4PIXEL21_32 + X4PIXEL22_0 + X4PIXEL23_0 + X4PIXEL30_82 + X4PIXEL31_32 + X4PIXEL32_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL33_0 + } + else + { + X4PIXEL33_20 + } + break; + } + case 255: + { + if (Diff(RGBtoYUV[w4], RGBtoYUV[w2])) + { + X4PIXEL00_0 + } + else + { + X4PIXEL00_20 + } + X4PIXEL01_0 + X4PIXEL02_0 + if (Diff(RGBtoYUV[w2], RGBtoYUV[w6])) + { + X4PIXEL03_0 + } + else + { + X4PIXEL03_20 + } + X4PIXEL10_0 + X4PIXEL11_0 + X4PIXEL12_0 + X4PIXEL13_0 + X4PIXEL20_0 + X4PIXEL21_0 + X4PIXEL22_0 + X4PIXEL23_0 + if (Diff(RGBtoYUV[w8], RGBtoYUV[w4])) + { + X4PIXEL30_0 + } + else + { + X4PIXEL30_20 + } + X4PIXEL31_0 + X4PIXEL32_0 + if (Diff(RGBtoYUV[w6], RGBtoYUV[w8])) + { + X4PIXEL33_0 + } + else + { + X4PIXEL33_20 + } + break; + } + } + + w1 = w2; w4 = w5; w7 = w8; + w2 = w3; w5 = w6; w8 = w9; + + dp += 4; + } + + dp += (dst1line - width) * 4; + sp += (src1line - width); + } +} diff --git a/filter/hq2x.h b/filter/hq2x.h new file mode 100644 index 00000000..bb98097f --- /dev/null +++ b/filter/hq2x.h @@ -0,0 +1,187 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _hq2x_h_ +#define _hq2x_h_ + +bool8 S9xBlitHQ2xFilterInit (void); +void S9xBlitHQ2xFilterDeinit (void); +void HQ2X_16 (uint8 *, uint32, uint8 *, uint32, int, int); +void HQ3X_16 (uint8 *, uint32, uint8 *, uint32, int, int); +void HQ4X_16 (uint8 *, uint32, uint8 *, uint32, int, int); + +#endif diff --git a/filter/snes_ntsc-license.txt b/filter/snes_ntsc-license.txt new file mode 100644 index 00000000..5ab7695a --- /dev/null +++ b/filter/snes_ntsc-license.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/filter/snes_ntsc.c b/filter/snes_ntsc.c new file mode 100644 index 00000000..f622baf8 --- /dev/null +++ b/filter/snes_ntsc.c @@ -0,0 +1,251 @@ +/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */ + +#include "snes_ntsc.h" + +/* Copyright (C) 2006-2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +snes_ntsc_setup_t const snes_ntsc_monochrome = { 0,-1, 0, 0,.2, 0,.2,-.2,-.2,-1, 1, 0, 0 }; +snes_ntsc_setup_t const snes_ntsc_composite = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; +snes_ntsc_setup_t const snes_ntsc_svideo = { 0, 0, 0, 0,.2, 0,.2, -1, -1, 0, 1, 0, 0 }; +snes_ntsc_setup_t const snes_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1, 1, 0, 0 }; + +#define alignment_count 3 +#define burst_count 3 +#define rescale_in 8 +#define rescale_out 7 + +#define artifacts_mid 1.0f +#define fringing_mid 1.0f +#define std_decoder_hue 0 + +#define rgb_bits 7 /* half normal range to allow for doubled hires pixels */ +#define gamma_size 32 + +#include "snes_ntsc_impl.h" + +/* 3 input pixels -> 8 composite samples */ +pixel_info_t const snes_ntsc_pixels [alignment_count] = { + { PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } }, + { PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } }, + { PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } }, +}; + +static void merge_kernel_fields( snes_ntsc_rgb_t* io ) +{ + int n; + for ( n = burst_size; n; --n ) + { + snes_ntsc_rgb_t p0 = io [burst_size * 0] + rgb_bias; + snes_ntsc_rgb_t p1 = io [burst_size * 1] + rgb_bias; + snes_ntsc_rgb_t p2 = io [burst_size * 2] + rgb_bias; + /* merge colors without losing precision */ + io [burst_size * 0] = + ((p0 + p1 - ((p0 ^ p1) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + io [burst_size * 1] = + ((p1 + p2 - ((p1 ^ p2) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + io [burst_size * 2] = + ((p2 + p0 - ((p2 ^ p0) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + ++io; + } +} + +static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ) +{ + int n; + for ( n = burst_count; n; --n ) + { + unsigned i; + for ( i = 0; i < rgb_kernel_size / 2; i++ ) + { + snes_ntsc_rgb_t error = color - + out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] - + out [i + 7] - out [i + 5 +14] - out [i + 3 +28]; + DISTRIBUTE_ERROR( i+3+28, i+5+14, i+7 ); + } + out += alignment_count * rgb_kernel_size; + } +} + +void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ) +{ + int merge_fields; + int entry; + init_t impl; + if ( !setup ) + setup = &snes_ntsc_composite; + init( &impl, setup ); + + merge_fields = setup->merge_fields; + if ( setup->artifacts <= -1 && setup->fringing <= -1 ) + merge_fields = 1; + + for ( entry = 0; entry < snes_ntsc_palette_size; entry++ ) + { + /* Reduce number of significant bits of source color. Clearing the + low bits of R and B were least notictable. Modifying green was too + noticeable. */ + int ir = entry >> 8 & 0x1E; + int ig = entry >> 4 & 0x1F; + int ib = entry << 1 & 0x1E; + + #if SNES_NTSC_BSNES_COLORTBL + if ( setup->bsnes_colortbl ) + { + int bgr15 = (ib << 10) | (ig << 5) | ir; + unsigned long rgb16 = setup->bsnes_colortbl [bgr15]; + ir = rgb16 >> 11 & 0x1E; + ig = rgb16 >> 6 & 0x1F; + ib = rgb16 & 0x1E; + } + #endif + + { + float rr = impl.to_float [ir]; + float gg = impl.to_float [ig]; + float bb = impl.to_float [ib]; + + float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i ); + + int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g ); + snes_ntsc_rgb_t rgb = PACK_RGB( r, g, b ); + + snes_ntsc_rgb_t* out = ntsc->table [entry]; + gen_kernel( &impl, y, i, q, out ); + if ( merge_fields ) + merge_kernel_fields( out ); + correct_errors( rgb, out ); + } + } +} + +#ifndef SNES_NTSC_NO_BLITTERS + +void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, + int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) +{ + int chunk_count = (in_width - 1) / snes_ntsc_in_chunk; + for ( ; in_height; --in_height ) + { + SNES_NTSC_IN_T const* line_in = input; + SNES_NTSC_BEGIN_ROW( ntsc, burst_phase, + snes_ntsc_black, snes_ntsc_black, SNES_NTSC_ADJ_IN( *line_in ) ); + snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out; + int n; + ++line_in; + + for ( n = chunk_count; n; --n ) + { + /* order of input and output pixels must not be altered */ + SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) ); + SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) ); + SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) ); + SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); + + line_in += 3; + line_out += 7; + } + + /* finish final pixels */ + SNES_NTSC_COLOR_IN( 0, snes_ntsc_black ); + SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 1, snes_ntsc_black ); + SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 2, snes_ntsc_black ); + SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); + + burst_phase = (burst_phase + 1) % snes_ntsc_burst_count; + input += in_row_width; + rgb_out = (char*) rgb_out + out_pitch; + } +} + +void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, + int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) +{ + int chunk_count = (in_width - 2) / (snes_ntsc_in_chunk * 2); + for ( ; in_height; --in_height ) + { + SNES_NTSC_IN_T const* line_in = input; + SNES_NTSC_HIRES_ROW( ntsc, burst_phase, + snes_ntsc_black, snes_ntsc_black, snes_ntsc_black, + SNES_NTSC_ADJ_IN( line_in [0] ), + SNES_NTSC_ADJ_IN( line_in [1] ) ); + snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out; + int n; + line_in += 2; + + for ( n = chunk_count; n; --n ) + { + /* twice as many input pixels per chunk */ + SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) ); + SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) ); + SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) ); + SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 3, SNES_NTSC_ADJ_IN( line_in [3] ) ); + SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 4, SNES_NTSC_ADJ_IN( line_in [4] ) ); + SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 5, SNES_NTSC_ADJ_IN( line_in [5] ) ); + SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); + + line_in += 6; + line_out += 7; + } + + SNES_NTSC_COLOR_IN( 0, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 1, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 2, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 3, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 4, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 5, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); + + burst_phase = (burst_phase + 1) % snes_ntsc_burst_count; + input += in_row_width; + rgb_out = (char*) rgb_out + out_pitch; + } +} + +#endif diff --git a/filter/snes_ntsc.h b/filter/snes_ntsc.h new file mode 100644 index 00000000..0c991386 --- /dev/null +++ b/filter/snes_ntsc.h @@ -0,0 +1,210 @@ +/* SNES NTSC video filter */ + +/* snes_ntsc 0.2.2 */ +#ifndef SNES_NTSC_H +#define SNES_NTSC_H + +#include "snes_ntsc_config.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown +in parenthesis and should remain fairly stable in future versions. */ +typedef struct snes_ntsc_setup_t +{ + /* Basic parameters */ + double hue; /* -1 = -180 degrees +1 = +180 degrees */ + double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */ + double contrast; /* -1 = dark (0.5) +1 = light (1.5) */ + double brightness; /* -1 = dark (0.5) +1 = light (1.5) */ + double sharpness; /* edge contrast enhancement/blurring */ + + /* Advanced parameters */ + double gamma; /* -1 = dark (1.5) +1 = light (0.5) */ + double resolution; /* image resolution */ + double artifacts; /* artifacts caused by color changes */ + double fringing; /* color artifacts caused by brightness changes */ + double bleed; /* color bleed (color resolution reduction) */ + int merge_fields; /* if 1, merges even and odd fields together to reduce flicker */ + float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */ + + unsigned long const* bsnes_colortbl; /* undocumented; set to 0 */ +} snes_ntsc_setup_t; + +/* Video format presets */ +extern snes_ntsc_setup_t const snes_ntsc_composite; /* color bleeding + artifacts */ +extern snes_ntsc_setup_t const snes_ntsc_svideo; /* color bleeding only */ +extern snes_ntsc_setup_t const snes_ntsc_rgb; /* crisp image */ +extern snes_ntsc_setup_t const snes_ntsc_monochrome;/* desaturated + artifacts */ + +/* Initializes and adjusts parameters. Can be called multiple times on the same +snes_ntsc_t object. Can pass NULL for either parameter. */ +typedef struct snes_ntsc_t snes_ntsc_t; +void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ); + +/* Filters one or more rows of pixels. Input pixel format is set by SNES_NTSC_IN_FORMAT +and output RGB depth is set by SNES_NTSC_OUT_DEPTH. Both default to 16-bit RGB. +In_row_width is the number of pixels to get to the next input row. Out_pitch +is the number of *bytes* to get to the next output row. */ +void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, + long in_row_width, int burst_phase, int in_width, int in_height, + void* rgb_out, long out_pitch ); + +void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, + long in_row_width, int burst_phase, int in_width, int in_height, + void* rgb_out, long out_pitch ); + +/* Number of output pixels written by low-res blitter for given input width. Width +might be rounded down slightly; use SNES_NTSC_IN_WIDTH() on result to find rounded +value. Guaranteed not to round 256 down at all. */ +#define SNES_NTSC_OUT_WIDTH( in_width ) \ + ((((in_width) - 1) / snes_ntsc_in_chunk + 1) * snes_ntsc_out_chunk) + +/* Number of low-res input pixels that will fit within given output width. Might be +rounded down slightly; use SNES_NTSC_OUT_WIDTH() on result to find rounded +value. */ +#define SNES_NTSC_IN_WIDTH( out_width ) \ + (((out_width) / snes_ntsc_out_chunk - 1) * snes_ntsc_in_chunk + 1) + + +/* Interface for user-defined custom blitters */ + +enum { snes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */ +enum { snes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */ +enum { snes_ntsc_black = 0 }; /* palette index for black */ +enum { snes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */ + +/* Begins outputting row and starts three pixels. First pixel will be cut off a bit. +Use snes_ntsc_black for unused pixels. Declares variables, so must be before first +statement in a block (unless you're using C++). */ +#define SNES_NTSC_BEGIN_ROW( ntsc, burst, pixel0, pixel1, pixel2 ) \ + char const* ktable = \ + (char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\ + SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, SNES_NTSC_IN_FORMAT, ktable ) + +/* Begins input pixel */ +#define SNES_NTSC_COLOR_IN( index, color ) \ + SNES_NTSC_COLOR_IN_( index, color, SNES_NTSC_IN_FORMAT, ktable ) + +/* Generates output pixel. Bits can be 24, 16, 15, 14, 32 (treated as 24), or 0: +24: RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8 RGB) +16: RRRRRGGG GGGBBBBB (5-6-5 RGB) +15: RRRRRGG GGGBBBBB (5-5-5 RGB) +14: BBBBBGG GGGRRRRR (5-5-5 BGR, native SNES format) + 0: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format; x = junk bits) */ +#define SNES_NTSC_RGB_OUT( index, rgb_out, bits ) \ + SNES_NTSC_RGB_OUT_14_( index, rgb_out, bits, 1 ) + +/* Hires equivalents */ +#define SNES_NTSC_HIRES_ROW( ntsc, burst, pixel1, pixel2, pixel3, pixel4, pixel5 ) \ + char const* ktable = \ + (char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\ + unsigned const snes_ntsc_pixel1_ = (pixel1);\ + snes_ntsc_rgb_t const* kernel1 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel1_ );\ + unsigned const snes_ntsc_pixel2_ = (pixel2);\ + snes_ntsc_rgb_t const* kernel2 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel2_ );\ + unsigned const snes_ntsc_pixel3_ = (pixel3);\ + snes_ntsc_rgb_t const* kernel3 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel3_ );\ + unsigned const snes_ntsc_pixel4_ = (pixel4);\ + snes_ntsc_rgb_t const* kernel4 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel4_ );\ + unsigned const snes_ntsc_pixel5_ = (pixel5);\ + snes_ntsc_rgb_t const* kernel5 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel5_ );\ + snes_ntsc_rgb_t const* kernel0 = kernel1;\ + snes_ntsc_rgb_t const* kernelx0;\ + snes_ntsc_rgb_t const* kernelx1 = kernel1;\ + snes_ntsc_rgb_t const* kernelx2 = kernel1;\ + snes_ntsc_rgb_t const* kernelx3 = kernel1;\ + snes_ntsc_rgb_t const* kernelx4 = kernel1;\ + snes_ntsc_rgb_t const* kernelx5 = kernel1 + +#define SNES_NTSC_HIRES_OUT( x, rgb_out, bits ) {\ + snes_ntsc_rgb_t raw_ =\ + kernel0 [ x ] + kernel2 [(x+5)%7+14] + kernel4 [(x+3)%7+28] +\ + kernelx0 [(x+7)%7+7] + kernelx2 [(x+5)%7+21] + kernelx4 [(x+3)%7+35] +\ + kernel1 [(x+6)%7 ] + kernel3 [(x+4)%7+14] + kernel5 [(x+2)%7+28] +\ + kernelx1 [(x+6)%7+7] + kernelx3 [(x+4)%7+21] + kernelx5 [(x+2)%7+35];\ + SNES_NTSC_CLAMP_( raw_, 0 );\ + SNES_NTSC_RGB_OUT_( rgb_out, (bits), 0 );\ +} + + +/* private */ +enum { snes_ntsc_entry_size = 128 }; +enum { snes_ntsc_palette_size = 0x2000 }; +typedef unsigned long snes_ntsc_rgb_t; +struct snes_ntsc_t { + snes_ntsc_rgb_t table [snes_ntsc_palette_size] [snes_ntsc_entry_size]; +}; +enum { snes_ntsc_burst_size = snes_ntsc_entry_size / snes_ntsc_burst_count }; + +#define SNES_NTSC_RGB16( ktable, n ) \ + (snes_ntsc_rgb_t const*) (ktable + ((n & 0x001E) | (n >> 1 & 0x03E0) | (n >> 2 & 0x3C00)) * \ + (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t))) + +#define SNES_NTSC_RGB15( ktable, n ) \ + (snes_ntsc_rgb_t const*) (ktable + ((n & 0x001E) | (n >> 0 & 0x03E0) | (n >> 1 & 0x3C00)) * \ + (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t))) + +#define SNES_NTSC_BGR15( ktable, n ) \ + (snes_ntsc_rgb_t const*) (ktable + ((n << 9 & 0x3C00) | (n & 0x03E0) | (n >> 10 & 0x001E)) * \ + (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t))) + +/* common 3->7 ntsc macros */ +#define SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, ENTRY, table ) \ + unsigned const snes_ntsc_pixel0_ = (pixel0);\ + snes_ntsc_rgb_t const* kernel0 = ENTRY( table, snes_ntsc_pixel0_ );\ + unsigned const snes_ntsc_pixel1_ = (pixel1);\ + snes_ntsc_rgb_t const* kernel1 = ENTRY( table, snes_ntsc_pixel1_ );\ + unsigned const snes_ntsc_pixel2_ = (pixel2);\ + snes_ntsc_rgb_t const* kernel2 = ENTRY( table, snes_ntsc_pixel2_ );\ + snes_ntsc_rgb_t const* kernelx0;\ + snes_ntsc_rgb_t const* kernelx1 = kernel0;\ + snes_ntsc_rgb_t const* kernelx2 = kernel0 + +#define SNES_NTSC_RGB_OUT_14_( x, rgb_out, bits, shift ) {\ + snes_ntsc_rgb_t raw_ =\ + kernel0 [x ] + kernel1 [(x+12)%7+14] + kernel2 [(x+10)%7+28] +\ + kernelx0 [(x+7)%14] + kernelx1 [(x+ 5)%7+21] + kernelx2 [(x+ 3)%7+35];\ + SNES_NTSC_CLAMP_( raw_, shift );\ + SNES_NTSC_RGB_OUT_( rgb_out, bits, shift );\ +} + +/* common ntsc macros */ +#define snes_ntsc_rgb_builder ((1L << 21) | (1 << 11) | (1 << 1)) +#define snes_ntsc_clamp_mask (snes_ntsc_rgb_builder * 3 / 2) +#define snes_ntsc_clamp_add (snes_ntsc_rgb_builder * 0x101) +#define SNES_NTSC_CLAMP_( io, shift ) {\ + snes_ntsc_rgb_t sub = (io) >> (9-(shift)) & snes_ntsc_clamp_mask;\ + snes_ntsc_rgb_t clamp = snes_ntsc_clamp_add - sub;\ + io |= clamp;\ + clamp -= sub;\ + io &= clamp;\ +} + +#define SNES_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\ + unsigned color_;\ + kernelx##index = kernel##index;\ + kernel##index = (color_ = (color), ENTRY( table, color_ ));\ +} + +/* x is always zero except in snes_ntsc library */ +#define SNES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\ + if ( bits == 16 )\ + rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\ + if ( bits == 24 || bits == 32 )\ + rgb_out = (raw_>>(5-x)&0xFF0000)|(raw_>>(3-x)&0xFF00)|(raw_>>(1-x)&0xFF);\ + if ( bits == 15 )\ + rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\ + if ( bits == 14 )\ + rgb_out = (raw_>>(24-x)& 0x001F)|(raw_>>(9-x)&0x03E0)|(raw_<<(6+x)&0x7C00);\ + if ( bits == 0 )\ + rgb_out = raw_ << x;\ +} + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/filter/snes_ntsc_config.h b/filter/snes_ntsc_config.h new file mode 100644 index 00000000..653b8bc5 --- /dev/null +++ b/filter/snes_ntsc_config.h @@ -0,0 +1,27 @@ +/* Configure library by modifying this file */ + +#ifndef SNES_NTSC_CONFIG_H +#define SNES_NTSC_CONFIG_H + +/* Format of source pixels */ +#define SNES_NTSC_IN_FORMAT SNES_NTSC_RGB15 +/* #define SNES_NTSC_IN_FORMAT SNES_NTSC_RGB16 */ +/* #define SNES_NTSC_IN_FORMAT SNES_NTSC_BGR15 */ + +/* The following affect the built-in blitter only; a custom blitter can +handle things however it wants. */ + +/* Bits per pixel of output. Can be 15, 16, 32, or 24 (same as 32). */ +#define SNES_NTSC_OUT_DEPTH 15 + +/* Type of input pixel values */ +#define SNES_NTSC_IN_T unsigned short + +/* Each raw pixel input value is passed through this. You might want to mask +the pixel index if you use the high bits as flags, etc. */ +#define SNES_NTSC_ADJ_IN( in ) in + +/* For each pixel, this is the basic operation: +output_color = SNES_NTSC_ADJ_IN( SNES_NTSC_IN_T ) */ + +#endif diff --git a/filter/snes_ntsc_impl.h b/filter/snes_ntsc_impl.h new file mode 100644 index 00000000..c10dcbec --- /dev/null +++ b/filter/snes_ntsc_impl.h @@ -0,0 +1,439 @@ +/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */ + +/* Common implementation of NTSC filters */ + +#include +#include + +/* Copyright (C) 2006 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#define DISABLE_CORRECTION 0 + +#undef PI +#define PI 3.14159265358979323846f + +#ifndef LUMA_CUTOFF + #define LUMA_CUTOFF 0.20 +#endif +#ifndef gamma_size + #define gamma_size 1 +#endif +#ifndef rgb_bits + #define rgb_bits 8 +#endif +#ifndef artifacts_max + #define artifacts_max (artifacts_mid * 1.5f) +#endif +#ifndef fringing_max + #define fringing_max (fringing_mid * 2) +#endif +#ifndef STD_HUE_CONDITION + #define STD_HUE_CONDITION( setup ) 1 +#endif + +#define ext_decoder_hue (std_decoder_hue + 15) +#define rgb_unit (1 << rgb_bits) +#define rgb_offset (rgb_unit * 2 + 0.5f) + +enum { burst_size = snes_ntsc_entry_size / burst_count }; +enum { kernel_half = 16 }; +enum { kernel_size = kernel_half * 2 + 1 }; + +typedef struct init_t +{ + float to_rgb [burst_count * 6]; + float to_float [gamma_size]; + float contrast; + float brightness; + float artifacts; + float fringing; + float kernel [rescale_out * kernel_size * 2]; +} init_t; + +#define ROTATE_IQ( i, q, sin_b, cos_b ) {\ + float t;\ + t = i * cos_b - q * sin_b;\ + q = i * sin_b + q * cos_b;\ + i = t;\ +} + +static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup ) +{ +#if rescale_out > 1 + float kernels [kernel_size * 2]; +#else + float* const kernels = impl->kernel; +#endif + + /* generate luma (y) filter using sinc kernel */ + { + /* sinc with rolloff (dsf) */ + float const rolloff = 1 + (float) setup->sharpness * (float) 0.032; + float const maxh = 32; + float const pow_a_n = (float) pow( rolloff, maxh ); + float sum; + int i; + /* quadratic mapping to reduce negative (blurring) range */ + float to_angle = (float) setup->resolution + 1; + to_angle = PI / maxh * (float) LUMA_CUTOFF * (to_angle * to_angle + 1); + + kernels [kernel_size * 3 / 2] = maxh; /* default center value */ + for ( i = 0; i < kernel_half * 2 + 1; i++ ) + { + int x = i - kernel_half; + float angle = x * to_angle; + /* instability occurs at center point with rolloff very close to 1.0 */ + if ( x || pow_a_n > (float) 1.056 || pow_a_n < (float) 0.981 ) + { + float rolloff_cos_a = rolloff * (float) cos( angle ); + float num = 1 - rolloff_cos_a - + pow_a_n * (float) cos( maxh * angle ) + + pow_a_n * rolloff * (float) cos( (maxh - 1) * angle ); + float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff; + float dsf = num / den; + kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - (float) 0.5; + } + } + + /* apply blackman window and find sum */ + sum = 0; + for ( i = 0; i < kernel_half * 2 + 1; i++ ) + { + float x = PI * 2 / (kernel_half * 2) * i; + float blackman = 0.42f - 0.5f * (float) cos( x ) + 0.08f * (float) cos( x * 2 ); + sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman); + } + + /* normalize kernel */ + sum = 1.0f / sum; + for ( i = 0; i < kernel_half * 2 + 1; i++ ) + { + int x = kernel_size * 3 / 2 - kernel_half + i; + kernels [x] *= sum; + /* assert( kernels [x] == kernels [x] ); catch numerical instability */ + } + } + + /* generate chroma (iq) filter using gaussian kernel */ + { + float const cutoff_factor = -0.03125f; + float cutoff = (float) setup->bleed; + int i; + + if ( cutoff < 0 ) + { + /* keep extreme value accessible only near upper end of scale (1.0) */ + cutoff *= cutoff; + cutoff *= cutoff; + cutoff *= cutoff; + cutoff *= -30.0f / 0.65f; + } + cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff; + + for ( i = -kernel_half; i <= kernel_half; i++ ) + kernels [kernel_size / 2 + i] = (float) exp( i * i * cutoff ); + + /* normalize even and odd phases separately */ + for ( i = 0; i < 2; i++ ) + { + float sum = 0; + int x; + for ( x = i; x < kernel_size; x += 2 ) + sum += kernels [x]; + + sum = 1.0f / sum; + for ( x = i; x < kernel_size; x += 2 ) + { + kernels [x] *= sum; + /* assert( kernels [x] == kernels [x] ); catch numerical instability */ + } + } + } + + /* + printf( "luma:\n" ); + for ( i = kernel_size; i < kernel_size * 2; i++ ) + printf( "%f\n", kernels [i] ); + printf( "chroma:\n" ); + for ( i = 0; i < kernel_size; i++ ) + printf( "%f\n", kernels [i] ); + */ + + /* generate linear rescale kernels */ + #if rescale_out > 1 + { + float weight = 1.0f; + float* out = impl->kernel; + int n = rescale_out; + do + { + float remain = 0; + int i; + weight -= 1.0f / rescale_in; + for ( i = 0; i < kernel_size * 2; i++ ) + { + float cur = kernels [i]; + float m = cur * weight; + *out++ = m + remain; + remain = cur - m; + } + } + while ( --n ); + } + #endif +} + +static float const default_decoder [6] = + { 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f }; + +static void init( init_t* impl, snes_ntsc_setup_t const* setup ) +{ + impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset; + impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit; + #ifdef default_palette_contrast + if ( !setup->palette ) + impl->contrast *= default_palette_contrast; + #endif + + impl->artifacts = (float) setup->artifacts; + if ( impl->artifacts > 0 ) + impl->artifacts *= artifacts_max - artifacts_mid; + impl->artifacts = impl->artifacts * artifacts_mid + artifacts_mid; + + impl->fringing = (float) setup->fringing; + if ( impl->fringing > 0 ) + impl->fringing *= fringing_max - fringing_mid; + impl->fringing = impl->fringing * fringing_mid + fringing_mid; + + init_filters( impl, setup ); + + /* generate gamma table */ + if ( gamma_size > 1 ) + { + float const to_float = 1.0f / (gamma_size - (gamma_size > 1)); + float const gamma = 1.1333f - (float) setup->gamma * 0.5f; + /* match common PC's 2.2 gamma to TV's 2.65 gamma */ + int i; + for ( i = 0; i < gamma_size; i++ ) + impl->to_float [i] = + (float) pow( i * to_float, gamma ) * impl->contrast + impl->brightness; + } + + /* setup decoder matricies */ + { + float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue; + float sat = (float) setup->saturation + 1; + float const* decoder = setup->decoder_matrix; + if ( !decoder ) + { + decoder = default_decoder; + if ( STD_HUE_CONDITION( setup ) ) + hue += PI / 180 * (std_decoder_hue - ext_decoder_hue); + } + + { + float s = (float) sin( hue ) * sat; + float c = (float) cos( hue ) * sat; + float* out = impl->to_rgb; + int n; + + n = burst_count; + do + { + float const* in = decoder; + int n = 3; + do + { + float i = *in++; + float q = *in++; + *out++ = i * c - q * s; + *out++ = i * s + q * c; + } + while ( --n ); + if ( burst_count <= 1 ) + break; + ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */ + } + while ( --n ); + } + } +} + +/* kernel generation */ + +#define RGB_TO_YIQ( r, g, b, y, i ) (\ + (y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\ + (i = (r) * 0.596f - (g) * 0.275f - (b) * 0.321f),\ + ((r) * 0.212f - (g) * 0.523f + (b) * 0.311f)\ +) + +#define YIQ_TO_RGB( y, i, q, to_rgb, type, r, g ) (\ + r = (type) (y + to_rgb [0] * i + to_rgb [1] * q),\ + g = (type) (y + to_rgb [2] * i + to_rgb [3] * q),\ + (type) (y + to_rgb [4] * i + to_rgb [5] * q)\ +) + +#define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1) + +enum { rgb_kernel_size = burst_size / alignment_count }; +enum { rgb_bias = rgb_unit * 2 * snes_ntsc_rgb_builder }; + +typedef struct pixel_info_t +{ + int offset; + float negate; + float kernel [4]; +} pixel_info_t; + +#if rescale_in > 1 + #define PIXEL_OFFSET_( ntsc, scaled ) \ + (kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \ + (kernel_size * 2 * scaled)) + + #define PIXEL_OFFSET( ntsc, scaled ) \ + PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\ + (((scaled) + rescale_out * 10) % rescale_out) ),\ + (1.0f - (((ntsc) + 100) & 2)) +#else + #define PIXEL_OFFSET( ntsc, scaled ) \ + (kernel_size / 2 + (ntsc) - (scaled)),\ + (1.0f - (((ntsc) + 100) & 2)) +#endif + +extern pixel_info_t const snes_ntsc_pixels [alignment_count]; + +/* Generate pixel at all burst phases and column alignments */ +static void gen_kernel( init_t* impl, float y, float i, float q, snes_ntsc_rgb_t* out ) +{ + /* generate for each scanline burst phase */ + float const* to_rgb = impl->to_rgb; + int burst_remain = burst_count; + y -= rgb_offset; + do + { + /* Encode yiq into *two* composite signals (to allow control over artifacting). + Convolve these with kernels which: filter respective components, apply + sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack + into integer. Based on algorithm by NewRisingSun. */ + pixel_info_t const* pixel = snes_ntsc_pixels; + int alignment_remain = alignment_count; + do + { + /* negate is -1 when composite starts at odd multiple of 2 */ + float const yy = y * impl->fringing * pixel->negate; + float const ic0 = (i + yy) * pixel->kernel [0]; + float const qc1 = (q + yy) * pixel->kernel [1]; + float const ic2 = (i - yy) * pixel->kernel [2]; + float const qc3 = (q - yy) * pixel->kernel [3]; + + float const factor = impl->artifacts * pixel->negate; + float const ii = i * factor; + float const yc0 = (y + ii) * pixel->kernel [0]; + float const yc2 = (y - ii) * pixel->kernel [2]; + + float const qq = q * factor; + float const yc1 = (y + qq) * pixel->kernel [1]; + float const yc3 = (y - qq) * pixel->kernel [3]; + + float const* k = &impl->kernel [pixel->offset]; + int n; + ++pixel; + for ( n = rgb_kernel_size; n; --n ) + { + float i = k[0]*ic0 + k[2]*ic2; + float q = k[1]*qc1 + k[3]*qc3; + float y = k[kernel_size+0]*yc0 + k[kernel_size+1]*yc1 + + k[kernel_size+2]*yc2 + k[kernel_size+3]*yc3 + rgb_offset; + if ( rescale_out <= 1 ) + k--; + else if ( k < &impl->kernel [kernel_size * 2 * (rescale_out - 1)] ) + k += kernel_size * 2 - 1; + else + k -= kernel_size * 2 * (rescale_out - 1) + 2; + { + int r, g, b = YIQ_TO_RGB( y, i, q, to_rgb, int, r, g ); + *out++ = PACK_RGB( r, g, b ) - rgb_bias; + } + } + } + while ( alignment_count > 1 && --alignment_remain ); + + if ( burst_count <= 1 ) + break; + + to_rgb += 6; + + ROTATE_IQ( i, q, -0.866025f, -0.5f ); /* -120 degrees */ + } + while ( --burst_remain ); +} + +static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ); + +#if DISABLE_CORRECTION + #define CORRECT_ERROR( a ) { out [i] += rgb_bias; } + #define DISTRIBUTE_ERROR( a, b, c ) { out [i] += rgb_bias; } +#else + #define CORRECT_ERROR( a ) { out [a] += error; } + #define DISTRIBUTE_ERROR( a, b, c ) {\ + snes_ntsc_rgb_t fourth = (error + 2 * snes_ntsc_rgb_builder) >> 2;\ + fourth &= (rgb_bias >> 1) - snes_ntsc_rgb_builder;\ + fourth -= rgb_bias >> 2;\ + out [a] += fourth;\ + out [b] += fourth;\ + out [c] += fourth;\ + out [i] += error - (fourth * 3);\ + } +#endif + +#define RGB_PALETTE_OUT( rgb, out_ )\ +{\ + unsigned char* out = (out_);\ + snes_ntsc_rgb_t clamped = (rgb);\ + SNES_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\ + out [0] = (unsigned char) (clamped >> 21);\ + out [1] = (unsigned char) (clamped >> 11);\ + out [2] = (unsigned char) (clamped >> 1);\ +} + +/* blitter related */ + +#ifndef restrict + #if defined (__GNUC__) + #define restrict __restrict__ + #elif defined (_MSC_VER) && _MSC_VER > 1300 + #define restrict __restrict + #else + /* no support for restricted pointers */ + #define restrict + #endif +#endif + +#include + +#if SNES_NTSC_OUT_DEPTH <= 16 + #if USHRT_MAX == 0xFFFF + typedef unsigned short snes_ntsc_out_t; + #else + #error "Need 16-bit int type" + #endif + +#else + #if UINT_MAX == 0xFFFFFFFF + typedef unsigned int snes_ntsc_out_t; + #elif ULONG_MAX == 0xFFFFFFFF + typedef unsigned long snes_ntsc_out_t; + #else + #error "Need 32-bit int type" + #endif + +#endif diff --git a/font.h b/font.h new file mode 100644 index 00000000..27011f6b --- /dev/null +++ b/font.h @@ -0,0 +1,325 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _FONT_H_ +#define _FONT_H_ + +static const char *font[] = +{ + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " . . . . .. . . ", + " .#. .#.#. . . ... .#. . . .##. .#. .#. . . . . ", + " .#. .#.#. .#.#. .###. .#..#. .#. .#. .#. .#. .#.#. .#. .#. ", + " .#. .#.#. .#####. .#.#. ..#. .#.#. .#. .#. .#. .#. ..#.. .... .#. ", + " .#. . . .#.#. .###. .#.. .#. . .#. .#. .###. .#####. .. .####. .. .#. ", + " . .#####. .#.#. .#..#. .#.#. .#. .#. .#. ..#.. .##. .... .##. .#. ", + " .#. .#.#. .###. . .#. .#.#. .#. .#. .#.#. .#. .#. .##. . ", + " . . . ... . . . . . . . . .#. .. ", + " . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " . . .. .... . .... .. .... .. .. . ", + " .#. .#. .##. .####. .#. .####. .##. .####. .##. .##. .. .. . . .#. ", + ".#.#. .##. .#..#. ...#. .##. .#... .#.. ...#. .#..#. .#..#. .##. .##. .#. .... .#. .#.#. ", + ".#.#. .#. . .#. .##. .#.#. .###. .###. .#. .##. .#..#. .##. .##. .#. .####. .#. ..#. ", + ".#.#. .#. .#. ...#. .####. ...#. .#..#. .#. .#..#. .###. .. .. .#. .... .#. .#. ", + ".#.#. .#. .#.. .#..#. ..#. .#..#. .#..#. .#. .#..#. ..#. .##. .##. .#. .####. .#. . ", + " .#. .###. .####. .##. .#. .##. .##. .#. .##. .##. .##. .#. .#. .... .#. .#. ", + " . ... .... .. . .. .. . .. .. .. .#. . . . ", + " . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .. .. ... .. ... .... .... .. . . ... . . . . . . . . .. ", + " .##. .##. .###. .##. .###. .####. .####. .##. .#..#. .###. .#. .#..#. .#. .#. .#. .#. .#. .##. ", + ".#..#. .#..#. .#..#. .#..#. .#..#. .#... .#... .#..#. .#..#. .#. .#. .#.#. .#. .##.##. .##..#. .#..#. ", + ".#.##. .#..#. .###. .#. . .#..#. .###. .###. .#... .####. .#. .#. .##. .#. .#.#.#. .#.#.#. .#..#. ", + ".#.##. .####. .#..#. .#. . .#..#. .#.. .#.. .#.##. .#..#. .#. . .#. .##. .#. .#...#. .#.#.#. .#..#. ", + ".#... .#..#. .#..#. .#..#. .#..#. .#... .#. .#..#. .#..#. .#. .#..#. .#.#. .#... .#. .#. .#..##. .#..#. ", + " .##. .#..#. .###. .##. .###. .####. .#. .###. .#..#. .###. .##. .#..#. .####. .#. .#. .#. .#. .##. ", + " .. . . ... .. ... .... . ... . . ... .. . . .... . . . . .. ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " ... .. ... .. ... . . . . . . . . . . .... ... ... . ", + ".###. .##. .###. .##. .###. .#. .#. .#. .#. .#. .#. .#..#. .#.#. .####. .###. . .###. .#. ", + ".#..#. .#..#. .#..#. .#..#. .#. .#. .#. .#. .#. .#...#. .#..#. .#.#. ...#. .#.. .#. ..#. .#.#. ", + ".#..#. .#..#. .#..#. .#.. .#. .#. .#. .#. .#. .#.#.#. .##. .#.#. .#. .#. .#. .#. . . ", + ".###. .#..#. .###. ..#. .#. .#. .#. .#. .#. .#.#.#. .#..#. .#. .#. .#. .#. .#. ", + ".#.. .##.#. .#.#. .#..#. .#. .#...#. .#.#. .##.##. .#..#. .#. .#... .#.. .#. ..#. .... ", + ".#. .##. .#..#. .##. .#. .###. .#. .#. .#. .#..#. .#. .####. .###. . .###. .####. ", + " . ..#. . . .. . ... . . . . . . .... ... ... .... ", + " . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .. . . . . . . . .. ", + ".##. .#. .#. .#. .#. .#. .#. .#. .##. ", + " .#. ... .#.. .. ..#. .. .#.#. ... .#.. .. . .#.. .#. .. .. ... .. ", + " .#. .###. .###. .##. .###. .##. .#.. .###. .###. .##. .#. .#.#. .#. .##.##. .###. .##. ", + " . .#..#. .#..#. .#.. .#..#. .#.##. .###. .#..#. .#..#. .#. .#. .##. .#. .#.#.#. .#..#. .#..#. ", + " .#.##. .#..#. .#.. .#..#. .##.. .#. .##. .#..#. .#. ..#. .#.#. .#. .#...#. .#..#. .#..#. ", + " .#.#. .###. .##. .###. .##. .#. .#... .#..#. .###. .#.#. .#..#. .###. .#. .#. .#..#. .##. ", + " . . ... .. ... .. . .###. . . ... .#. . . ... . . . . .. ", + " ... . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " . . . . . . ", + " .#. .#. .#. .#. .#.#. ", + " ... ... ... ... .#. . . . . . . . . . . .... .#. .#. .#. .#.#. ", + ".###. .###. .###. .###. .###. .#..#. .#.#. .#...#. .#..#. .#..#. .####. .##. .#. .##. . . ", + ".#..#. .#..#. .#..#. .##.. .#. .#..#. .#.#. .#.#.#. .##. .#..#. ..#. .#. .#. .#. ", + ".#..#. .#..#. .#. . ..##. .#.. .#..#. .#.#. .#.#.#. .##. .#.#. .#.. .#. .#. .#. ", + ".###. .###. .#. .###. .##. .###. .#. .#.#. .#..#. .#. .####. .#. .#. .#. ", + ".#.. ..#. . ... .. ... . . . . . .#. .... . . . ", + " . . . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .. ..... ", + " .##. .#####. ... . . . . .. ", + " .#. . .. ....#. .###. .#. .#. .#. .#.. .##. . . . ", + " .#. .#. .##. .#####. .#. .#. .###. ... .###. .###. .. .#. .#.#.#. ", + " . .#. .#. . .##. ....#. .#. .##. .#.#. .###. .#. .##.#. .##. .##. .#.#.#. ", + " .#. . .#. .#. .. ...#. .#. .#. ..#. .#. .##. .#.. ..#. .#. ...#. ", + " .#.#. .##. .#. .###. .#. .#. .#. .###. .#. .#. .####. .##. .##. ", + " .#. .. .#. ... . . . ... . . .... .. .. ", + " . . ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .... . . ... . . . .... . . . .. . ..... . . . ", + " .####. .#. ..#.. .###. ...#. ..#.. ..#.. .####. .#... .... .#.#. .##..#. .#####. .#... .#. .#. ", + " .... ...#. .#. .#####. .#. .#####. .#####. .#####. .#..#. .####. .####. .#####. .. .#. ....#. .#####. .#. .#. ", + ".####. .##. .## .#...#. .#. ...#. ..#.#. ..#.. .# .#. .#..#. ...#. .#.#. .##..#. .#. .#..#. .#..#. ", + " .... .#. .#.# . .#. .#. .##. .#..#. .#####. .#. .#. . .#. .#. ..#. .. .#. .#. .#.#. . .#. ", + " .#. .#. ..#. ..#.. .#.#. .#..#. ..#.. . .#. .#. ...#. .#. ...#. .#.#. .#... ...#. ", + " .#. .#. .##. .#####. .#..#. .#..#. .#. .#. .#. .####. .#. .###. .#. .#. .###. .###. ", + " . . .. ..... . . . . . . . .... . ... . . ... ... ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .... .. . . . ... . . ... .... . . . ..... . . ", + " .####. ..##. .#.#.#. .###. .#. ..#.. .###. .####. ..#.. .#. . . .#. .. .#####. .#. ..#.. ..... ", + " .#..#. .###. .#.#.#. ..... .#. .#####. ... ...#. .#####. .#. .#.#. .#..##. ....#. .#.#. .#####. .#####. ", + " .####. ..#. .#.#.#. .#####. .##. ..#.. .#.#. ....#. .#. .#.#. .###.. .#. .#..#. ..#.. .#. ", + ".#...#. .####. . ..#. ..#.. .#.#. .#. .#. .###. .#. .#. .#. .#.. .#. . .#. .#.#.#. .#.#. ", + " . .#. ..#. ...#. .#. .#.. ..#. ..... .#.#. .#.#.#. .#. .#. .#. .#.... ..#. .#. .#.#.#. .#. ", + " .#. .##. .###. .#. .#. .##. .#####. .#. .#. ..#.. .#. .#. .#. .####. .##. .#. ..#.. .#. ", + " . .. ... . . .. ..... . . . . . . .... .. . . . ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " .. . . ... . .... .... . . . . . ..... . . . . ", + " .##. .#. .#. .###. .#... ... .####. .####. .#..#. .#.#. .#. ..... .#####. ....#. .#.#. .#. ", + " ..#. .#. . .#. .#. .#.##. .###. ...#. ..... .#..#. .#.#. .#. .#####. .#...#. .###.#. .#.#. .#.#. ", + " .##. .#. . .#.#. .#####. .##.#. .#. .###. .#####. .#..#. .#.#. .#. . .#...#. . .#. ....#. . . .#. ", + " ..#. .#..#. .##. ..#.. .#.#. ..#. ..#. ....#. . .#. .#.#. .#..#. .#...#. .#. .#. . ", + " .##. .####. ..#.#. .#.. .#. ...#. ...#. ..#. ..#. .#.#. .#.#. .#####. ..#. ...#. ", + " ..#. ...#. .##. . .###. .#. .#####. .####. .##. .##. .#..##. .##. .#...#. .##. .###. ", + " . . .. ... . ..... .... .. ... . .. .. . . .. ... ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + //2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678/2345678 + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " +}; + +#endif diff --git a/fxdbg.cpp b/fxdbg.cpp new file mode 100644 index 00000000..ed971234 --- /dev/null +++ b/fxdbg.cpp @@ -0,0 +1,1425 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 DEBUGGER + +#include "snes9x.h" +#include "fxinst.h" +#include "fxemu.h" + +/* + When printing a line from the pipe, it could look like this: + + 01:8006 f4 fb 86 iwt r4, #$86fb + + The values are: + program bank : 01 + adress : 8006 + values at memory address 8006 : f4 fb 86 + instruction in the pipe : iwt r4, #$86fb + + Note! If the instruction has more than one byte (like in 'iwt') and the instruction is in a delay slot, + the second and third byte displayed will not be the same as those used. + Since the instrction is in a delay slot, + the first byte of the instruction will be taken from the pipe at the address after the branch instruction, + and the next one or two bytes will be taken from the address that the branch points to. + This is a bit complicated, but I've taken this into account, in this debug function. + (See the diffrence of how the values vPipe1 and vPipe2 are read, compared to the values vByte1 and vByte2) +*/ + +/* +static const char *fx_apvMnemonicTable[] = +{ + // ALT0 Table + + // 00 - 0f + "stop", + "nop", + "cache", + "lsr", + "rol", + "bra $%04x", + "blt $%04x", + "bge $%04x", + "bne $%04x", + "beq $%04x", + "bpl $%04x", + "bmi $%04x", + "bcc $%04x", + "bcs $%04x", + "bvc $%04x", + "bvs $%04x", + + // 10 - 1f + "to r0", + "to r1", + "to r2", + "to r3", + "to r4", + "to r5", + "to r6", + "to r7", + "to r8", + "to r9", + "to r10", + "to r11", + "to r12", + "to r13", + "to r14", + "to r15", + + // 20 - 2f + "with r0", + "with r1", + "with r2", + "with r3", + "with r4", + "with r5", + "with r6", + "with r7", + "with r8", + "with r9", + "with r10", + "with r11", + "with r12", + "with r13", + "with r14", + "with r15", + + // 30 - 3f + "stw (r0)", + "stw (r1)", + "stw (r2)", + "stw (r3)", + "stw (r4)", + "stw (r5)", + "stw (r6)", + "stw (r7)", + "stw (r8)", + "stw (r9)", + "stw (r10)", + "stw (r11)", + "loop", + "alt1", + "alt2", + "alt3", + + // 40 - 4f + "ldw (r0)", + "ldw (r1)", + "ldw (r2)", + "ldw (r3)", + "ldw (r4)", + "ldw (r5)", + "ldw (r6)", + "ldw (r7)", + "ldw (r8)", + "ldw (r9)", + "ldw (r10)", + "ldw (r11)", + "plot", + "swap", + "color", + "not", + + // 50 - 5f + "add r0", + "add r1", + "add r2", + "add r3", + "add r4", + "add r5", + "add r6", + "add r7", + "add r8", + "add r9", + "add r10", + "add r11", + "add r12", + "add r13", + "add r14", + "add r15", + + // 60 - 6f + "sub r0", + "sub r1", + "sub r2", + "sub r3", + "sub r4", + "sub r5", + "sub r6", + "sub r7", + "sub r8", + "sub r9", + "sub r10", + "sub r11", + "sub r12", + "sub r13", + "sub r14", + "sub r15", + + // 70 - 7f + "merge", + "and r1", + "and r2", + "and r3", + "and r4", + "and r5", + "and r6", + "and r7", + "and r8", + "and r9", + "and r10", + "and r11", + "and r12", + "and r13", + "and r14", + "and r15", + + // 80 - 8f + "mult r0", + "mult r1", + "mult r2", + "mult r3", + "mult r4", + "mult r5", + "mult r6", + "mult r7", + "mult r8", + "mult r9", + "mult r10", + "mult r11", + "mult r12", + "mult r13", + "mult r14", + "mult r15", + + // 90 - 9f + "sbk", + "link #1", + "link #2", + "link #3", + "link #4", + "sex", + "asr", + "ror", + "jmp (r8)", + "jmp (r9)", + "jmp (r10)", + "jmp (r11)", + "jmp (r12)", + "jmp (r13)", + "lob", + "fmult", + + // a0 - af + "ibt r0, #$%02x", + "ibt r1, #$%02x", + "ibt r2, #$%02x", + "ibt r3, #$%02x", + "ibt r4, #$%02x", + "ibt r5, #$%02x", + "ibt r6, #$%02x", + "ibt r7, #$%02x", + "ibt r8, #$%02x", + "ibt r9, #$%02x", + "ibt r10, #$%02x", + "ibt r11, #$%02x", + "ibt r12, #$%02x", + "ibt r13, #$%02x", + "ibt r14, #$%02x", + "ibt r15, #$%02x", + + // b0 - bf + "from r0", + "from r1", + "from r2", + "from r3", + "from r4", + "from r5", + "from r6", + "from r7", + "from r8", + "from r9", + "from r10", + "from r11", + "from r12", + "from r13", + "from r14", + "from r15", + + // c0 - cf + "hib", + "or r1", + "or r2", + "or r3", + "or r4", + "or r5", + "or r6", + "or r7", + "or r8", + "or r9", + "or r10", + "or r11", + "or r12", + "or r13", + "or r14", + "or r15", + + // d0 - df + "inc r0", + "inc r1", + "inc r2", + "inc r3", + "inc r4", + "inc r5", + "inc r6", + "inc r7", + "inc r8", + "inc r9", + "inc r10", + "inc r11", + "inc r12", + "inc r13", + "inc r14", + "getc", + + // e0 - ef + "dec r0", + "dec r1", + "dec r2", + "dec r3", + "dec r4", + "dec r5", + "dec r6", + "dec r7", + "dec r8", + "dec r9", + "dec r10", + "dec r11", + "dec r12", + "dec r13", + "dec r14", + "getb", + + // f0 - ff + "iwt r0, #$%04x", + "iwt r1, #$%04x", + "iwt r2, #$%04x", + "iwt r3, #$%04x", + "iwt r4, #$%04x", + "iwt r5, #$%04x", + "iwt r6, #$%04x", + "iwt r7, #$%04x", + "iwt r8, #$%04x", + "iwt r9, #$%04x", + "iwt r10, #$%04x", + "iwt r11, #$%04x", + "iwt r12, #$%04x", + "iwt r13, #$%04x", + "iwt r14, #$%04x", + "iwt r15, #$%04x", + + // ALT1 Table + + // 00 - 0f + "stop", + "nop", + "cache", + "lsr", + "rol", + "bra $%04x", + "blt $%04x", + "bge $%04x", + "bne $%04x", + "beq $%04x", + "bpl $%04x", + "bmi $%04x", + "bcc $%04x", + "bcs $%04x", + "bvc $%04x", + "bvs $%04x", + + // 10 - 1f + "to r0", + "to r1", + "to r2", + "to r3", + "to r4", + "to r5", + "to r6", + "to r7", + "to r8", + "to r9", + "to r10", + "to r11", + "to r12", + "to r13", + "to r14", + "to r15", + + // 20 - 2f + "with r0", + "with r1", + "with r2", + "with r3", + "with r4", + "with r5", + "with r6", + "with r7", + "with r8", + "with r9", + "with r10", + "with r11", + "with r12", + "with r13", + "with r14", + "with r15", + + // 30 - 3f + "stb (r0)", + "stb (r1)", + "stb (r2)", + "stb (r3)", + "stb (r4)", + "stb (r5)", + "stb (r6)", + "stb (r7)", + "stb (r8)", + "stb (r9)", + "stb (r10)", + "stb (r11)", + "loop", + "alt1", + "alt2", + "alt3", + + // 40 - 4f + "ldb (r0)", + "ldb (r1)", + "ldb (r2)", + "ldb (r3)", + "ldb (r4)", + "ldb (r5)", + "ldb (r6)", + "ldb (r7)", + "ldb (r8)", + "ldb (r9)", + "ldb (r10)", + "ldb (r11)", + "rpix", + "swap", + "cmode", + "not", + + // 50 - 5f + "adc r0", + "adc r1", + "adc r2", + "adc r3", + "adc r4", + "adc r5", + "adc r6", + "adc r7", + "adc r8", + "adc r9", + "adc r10", + "adc r11", + "adc r12", + "adc r13", + "adc r14", + "adc r15", + + // 60 - 6f + "sbc r0", + "sbc r1", + "sbc r2", + "sbc r3", + "sbc r4", + "sbc r5", + "sbc r6", + "sbc r7", + "sbc r8", + "sbc r9", + "sbc r10", + "sbc r11", + "sbc r12", + "sbc r13", + "sbc r14", + "sbc r15", + + // 70 - 7f + "merge", + "bic r1", + "bic r2", + "bic r3", + "bic r4", + "bic r5", + "bic r6", + "bic r7", + "bic r8", + "bic r9", + "bic r10", + "bic r11", + "bic r12", + "bic r13", + "bic r14", + "bic r15", + + // 80 - 8f + "umult r0", + "umult r1", + "umult r2", + "umult r3", + "umult r4", + "umult r5", + "umult r6", + "umult r7", + "umult r8", + "umult r9", + "umult r10", + "umult r11", + "umult r12", + "umult r13", + "umult r14", + "umult r15", + + // 90 - 9f + "sbk", + "link #1", + "link #2", + "link #3", + "link #4", + "sex", + "div2", + "ror", + "ljmp (r8)", + "ljmp (r9)", + "ljmp (r10)", + "ljmp (r11)", + "ljmp (r12)", + "ljmp (r13)", + "lob", + "lmult", + + // a0 - af + "lms r0, ($%04x)", + "lms r1, ($%04x)", + "lms r2, ($%04x)", + "lms r3, ($%04x)", + "lms r4, ($%04x)", + "lms r5, ($%04x)", + "lms r6, ($%04x)", + "lms r7, ($%04x)", + "lms r8, ($%04x)", + "lms r9, ($%04x)", + "lms r10, ($%04x)", + "lms r11, ($%04x)", + "lms r12, ($%04x)", + "lms r13, ($%04x)", + "lms r14, ($%04x)", + "lms r15, ($%04x)", + + // b0 - bf + "from r0", + "from r1", + "from r2", + "from r3", + "from r4", + "from r5", + "from r6", + "from r7", + "from r8", + "from r9", + "from r10", + "from r11", + "from r12", + "from r13", + "from r14", + "from r15", + + // c0 - cf + "hib", + "xor r1", + "xor r2", + "xor r3", + "xor r4", + "xor r5", + "xor r6", + "xor r7", + "xor r8", + "xor r9", + "xor r10", + "xor r11", + "xor r12", + "xor r13", + "xor r14", + "xor r15", + + // d0 - df + "inc r0", + "inc r1", + "inc r2", + "inc r3", + "inc r4", + "inc r5", + "inc r6", + "inc r7", + "inc r8", + "inc r9", + "inc r10", + "inc r11", + "inc r12", + "inc r13", + "inc r14", + "getc", + + // e0 - ef + "dec r0", + "dec r1", + "dec r2", + "dec r3", + "dec r4", + "dec r5", + "dec r6", + "dec r7", + "dec r8", + "dec r9", + "dec r10", + "dec r11", + "dec r12", + "dec r13", + "dec r14", + "getbh", + + // f0 - ff + "lm r0, ($%04x)", + "lm r1, ($%04x)", + "lm r2, ($%04x)", + "lm r3, ($%04x)", + "lm r4, ($%04x)", + "lm r5, ($%04x)", + "lm r6, ($%04x)", + "lm r7, ($%04x)", + "lm r8, ($%04x)", + "lm r9, ($%04x)", + "lm r10, ($%04x)", + "lm r11, ($%04x)", + "lm r12, ($%04x)", + "lm r13, ($%04x)", + "lm r14, ($%04x)", + "lm r15, ($%04x)", + + // ALT2 Table + + // 00 - 0f + "stop", + "nop", + "cache", + "lsr", + "rol", + "bra $%04x", + "blt $%04x", + "bge $%04x", + "bne $%04x", + "beq $%04x", + "bpl $%04x", + "bmi $%04x", + "bcc $%04x", + "bcs $%04x", + "bvc $%04x", + "bvs $%04x", + + // 10 - 1f + "to r0", + "to r1", + "to r2", + "to r3", + "to r4", + "to r5", + "to r6", + "to r7", + "to r8", + "to r9", + "to r10", + "to r11", + "to r12", + "to r13", + "to r14", + "to r15", + + // 20 - 2f + "with r0", + "with r1", + "with r2", + "with r3", + "with r4", + "with r5", + "with r6", + "with r7", + "with r8", + "with r9", + "with r10", + "with r11", + "with r12", + "with r13", + "with r14", + "with r15", + + // 30 - 3f + "stw (r0)", + "stw (r1)", + "stw (r2)", + "stw (r3)", + "stw (r4)", + "stw (r5)", + "stw (r6)", + "stw (r7)", + "stw (r8)", + "stw (r9)", + "stw (r10)", + "stw (r11)", + "loop", + "alt1", + "alt2", + "alt3", + + // 40 - 4f + "ldw (r0)", + "ldw (r1)", + "ldw (r2)", + "ldw (r3)", + "ldw (r4)", + "ldw (r5)", + "ldw (r6)", + "ldw (r7)", + "ldw (r8)", + "ldw (r9)", + "ldw (r10)", + "ldw (r11)", + "plot", + "swap", + "color", + "not", + + // 50 - 5f + "add #0", + "add #1", + "add #2", + "add #3", + "add #4", + "add #5", + "add #6", + "add #7", + "add #8", + "add #9", + "add #10", + "add #11", + "add #12", + "add #13", + "add #14", + "add #15", + + // 60 - 6f + "sub #0", + "sub #1", + "sub #2", + "sub #3", + "sub #4", + "sub #5", + "sub #6", + "sub #7", + "sub #8", + "sub #9", + "sub #10", + "sub #11", + "sub #12", + "sub #13", + "sub #14", + "sub #15", + + // 70 - 7f + "merge", + "and #1", + "and #2", + "and #3", + "and #4", + "and #5", + "and #6", + "and #7", + "and #8", + "and #9", + "and #10", + "and #11", + "and #12", + "and #13", + "and #14", + "and #15", + + // 80 - 8f + "mult #0", + "mult #1", + "mult #2", + "mult #3", + "mult #4", + "mult #5", + "mult #6", + "mult #7", + "mult #8", + "mult #9", + "mult #10", + "mult #11", + "mult #12", + "mult #13", + "mult #14", + "mult #15", + + // 90 - 9f + "sbk", + "link #1", + "link #2", + "link #3", + "link #4", + "sex", + "asr", + "ror", + "jmp (r8)", + "jmp (r9)", + "jmp (r10)", + "jmp (r11)", + "jmp (r12)", + "jmp (r13)", + "lob", + "fmult", + + // a0 - af + "sms ($%04x), r0", + "sms ($%04x), r1", + "sms ($%04x), r2", + "sms ($%04x), r3", + "sms ($%04x), r4", + "sms ($%04x), r5", + "sms ($%04x), r6", + "sms ($%04x), r7", + "sms ($%04x), r8", + "sms ($%04x), r9", + "sms ($%04x), r10", + "sms ($%04x), r11", + "sms ($%04x), r12", + "sms ($%04x), r13", + "sms ($%04x), r14", + "sms ($%04x), r15", + + // b0 - bf + "from r0", + "from r1", + "from r2", + "from r3", + "from r4", + "from r5", + "from r6", + "from r7", + "from r8", + "from r9", + "from r10", + "from r11", + "from r12", + "from r13", + "from r14", + "from r15", + + // c0 - cf + "hib", + "or #1", + "or #2", + "or #3", + "or #4", + "or #5", + "or #6", + "or #7", + "or #8", + "or #9", + "or #10", + "or #11", + "or #12", + "or #13", + "or #14", + "or #15", + + // d0 - df + "inc r0", + "inc r1", + "inc r2", + "inc r3", + "inc r4", + "inc r5", + "inc r6", + "inc r7", + "inc r8", + "inc r9", + "inc r10", + "inc r11", + "inc r12", + "inc r13", + "inc r14", + "ramb", + + // e0 - ef + "dec r0", + "dec r1", + "dec r2", + "dec r3", + "dec r4", + "dec r5", + "dec r6", + "dec r7", + "dec r8", + "dec r9", + "dec r10", + "dec r11", + "dec r12", + "dec r13", + "dec r14", + "getbl", + + // f0 - ff + "sm ($%04x), r0", + "sm ($%04x), r1", + "sm ($%04x), r2", + "sm ($%04x), r3", + "sm ($%04x), r4", + "sm ($%04x), r5", + "sm ($%04x), r6", + "sm ($%04x), r7", + "sm ($%04x), r8", + "sm ($%04x), r9", + "sm ($%04x), r10", + "sm ($%04x), r11", + "sm ($%04x), r12", + "sm ($%04x), r13", + "sm ($%04x), r14", + "sm ($%04x), r15", + + // ALT3 Table + + // 00 - 0f + "stop", + "nop", + "cache", + "lsr", + "rol", + "bra $%04x", + "blt $%04x", + "bge $%04x", + "bne $%04x", + "beq $%04x", + "bpl $%04x", + "bmi $%04x", + "bcc $%04x", + "bcs $%04x", + "bvc $%04x", + "bvs $%04x", + + // 10 - 1f + "to r0", + "to r1", + "to r2", + "to r3", + "to r4", + "to r5", + "to r6", + "to r7", + "to r8", + "to r9", + "to r10", + "to r11", + "to r12", + "to r13", + "to r14", + "to r15", + + // 20 - 2f + "with r0", + "with r1", + "with r2", + "with r3", + "with r4", + "with r5", + "with r6", + "with r7", + "with r8", + "with r9", + "with r10", + "with r11", + "with r12", + "with r13", + "with r14", + "with r15", + + // 30 - 3f + "stb (r0)", + "stb (r1)", + "stb (r2)", + "stb (r3)", + "stb (r4)", + "stb (r5)", + "stb (r6)", + "stb (r7)", + "stb (r8)", + "stb (r9)", + "stb (r10)", + "stb (r11)", + "loop", + "alt1", + "alt2", + "alt3", + + // 40 - 4f + "ldb (r0)", + "ldb (r1)", + "ldb (r2)", + "ldb (r3)", + "ldb (r4)", + "ldb (r5)", + "ldb (r6)", + "ldb (r7)", + "ldb (r8)", + "ldb (r9)", + "ldb (r10)", + "ldb (r11)", + "rpix", + "swap", + "cmode", + "not", + + // 50 - 5f + "adc #0", + "adc #1", + "adc #2", + "adc #3", + "adc #4", + "adc #5", + "adc #6", + "adc #7", + "adc #8", + "adc #9", + "adc #10", + "adc #11", + "adc #12", + "adc #13", + "adc #14", + "adc #15", + + // 60 - 6f + "cmp r0", + "cmp r1", + "cmp r2", + "cmp r3", + "cmp r4", + "cmp r5", + "cmp r6", + "cmp r7", + "cmp r8", + "cmp r9", + "cmp r10", + "cmp r11", + "cmp r12", + "cmp r13", + "cmp r14", + "cmp r15", + + // 70 - 7f + "merge", + "bic #1", + "bic #2", + "bic #3", + "bic #4", + "bic #5", + "bic #6", + "bic #7", + "bic #8", + "bic #9", + "bic #10", + "bic #11", + "bic #12", + "bic #13", + "bic #14", + "bic #15", + + // 80 - 8f + "umult #0", + "umult #1", + "umult #2", + "umult #3", + "umult #4", + "umult #5", + "umult #6", + "umult #7", + "umult #8", + "umult #9", + "umult #10", + "umult #11", + "umult #12", + "umult #13", + "umult #14", + "umult #15", + + // 90 - 9f + "sbk", + "link #1", + "link #2", + "link #3", + "link #4", + "sex", + "div2", + "ror", + "ljmp (r8)", + "ljmp (r9)", + "ljmp (r10)", + "ljmp (r11)", + "ljmp (r12)", + "ljmp (r13)", + "lob", + "lmult", + + // a0 - af + "lms r0, ($%04x)", + "lms r1, ($%04x)", + "lms r2, ($%04x)", + "lms r3, ($%04x)", + "lms r4, ($%04x)", + "lms r5, ($%04x)", + "lms r6, ($%04x)", + "lms r7, ($%04x)", + "lms r8, ($%04x)", + "lms r9, ($%04x)", + "lms r10, ($%04x)", + "lms r11, ($%04x)", + "lms r12, ($%04x)", + "lms r13, ($%04x)", + "lms r14, ($%04x)", + "lms r15, ($%04x)", + + // b0 - bf + "from r0", + "from r1", + "from r2", + "from r3", + "from r4", + "from r5", + "from r6", + "from r7", + "from r8", + "from r9", + "from r10", + "from r11", + "from r12", + "from r13", + "from r14", + "from r15", + + // c0 - cf + "hib", + "xor #1", + "xor #2", + "xor #3", + "xor #4", + "xor #5", + "xor #6", + "xor #7", + "xor #8", + "xor #9", + "xor #10", + "xor #11", + "xor #12", + "xor #13", + "xor #14", + "xor #15", + + // d0 - df + "inc r0", + "inc r1", + "inc r2", + "inc r3", + "inc r4", + "inc r5", + "inc r6", + "inc r7", + "inc r8", + "inc r9", + "inc r10", + "inc r11", + "inc r12", + "inc r13", + "inc r14", + "romb", + + // e0 - ef + "dec r0", + "dec r1", + "dec r2", + "dec r3", + "dec r4", + "dec r5", + "dec r6", + "dec r7", + "dec r8", + "dec r9", + "dec r10", + "dec r11", + "dec r12", + "dec r13", + "dec r14", + "getbs", + + // f0 - ff + "lm r0, ($%04x)", + "lm r1, ($%04x)", + "lm r2, ($%04x)", + "lm r3, ($%04x)", + "lm r4, ($%04x)", + "lm r5, ($%04x)", + "lm r6, ($%04x)", + "lm r7, ($%04x)", + "lm r8, ($%04x)", + "lm r9, ($%04x)", + "lm r10, ($%04x)", + "lm r11, ($%04x)", + "lm r12, ($%04x)", + "lm r13, ($%04x)", + "lm r14, ($%04x)", + "lm r15, ($%04x)" +}; +*/ + +/* +static void FxPipeString (char *pvString) +{ + uint32 vOpcode = (GSU.vStatusReg & 0x300) | ((uint32) PIPE); + const char *m = fx_apvMnemonicTable[vOpcode]; + uint8 vPipe1, vPipe2, vByte1, vByte2; + uint8 vPipeBank = GSU.vPipeAdr >> 16; + char *p; + + // The next two bytes after the pipe's address + vPipe1 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr + 1)]; + vPipe2 = GSU.apvRomBank[vPipeBank][USEX16(GSU.vPipeAdr + 2)]; + + // The actual next two bytes to be read + vByte1 = PRGBANK(USEX16(R15)); + vByte2 = PRGBANK(USEX16(R15 + 1)); + + // Print ROM address of the pipe + sprintf(pvString, "%02x:%04x %02x ", USEX8(vPipeBank), USEX16(GSU.vPipeAdr), USEX8(PIPE)); + p = &pvString[strlen(pvString)]; + + if (PIPE >= 0x05 && PIPE <= 0x0f) // Check if it's a branch instruction + { + sprintf(&pvString[11], "%02x ", USEX8(vPipe1)); + #ifdef BRANCH_DELAY_RELATIVE + sprintf(p, m, USEX16(R15 + SEX8(vByte1) + 1)); + #else + sprintf(p, m, USEX16(R15 + SEX8(vByte1) - 1)); + #endif + } + else + if (PIPE >= 0x10 && PIPE <= 0x1f && TF(B)) // Check for 'move' instruction + sprintf(p, "move r%d, r%d", USEX8(PIPE & 0x0f), (uint32) (GSU.pvSreg - GSU.avReg)); + else + if (PIPE >= 0xa0 && PIPE <= 0xaf) // Check for 'ibt', 'lms' or 'sms' + { + sprintf(&pvString[11], "%02x ", USEX8(vPipe1)); + if ((GSU.vStatusReg & 0x300) == 0x100 || (GSU.vStatusReg & 0x300) == 0x200) + sprintf(p, m, USEX16(vByte1) << 1); + else + sprintf(p, m, USEX16(vByte1)); + } + else + if (PIPE >= 0xb0 && PIPE <= 0xbf && TF(B)) // Check for 'moves' + sprintf(p, "moves r%d, r%d", (uint32) (GSU.pvDreg - GSU.avReg), USEX8(PIPE & 0x0f)); + else + if (PIPE >= 0xf0) // Check for 'iwt', 'lm' or 'sm' + { + sprintf(&pvString[11], "%02x %02x ", USEX8(vPipe1), USEX8(vPipe2)); + sprintf(p, m, USEX8(vByte1) | (USEX16(vByte2) << 8)); + } + else // Normal instruction + strcpy(p, m); +} +*/ + +#endif diff --git a/fxemu.cpp b/fxemu.cpp new file mode 100644 index 00000000..b3237ae6 --- /dev/null +++ b/fxemu.cpp @@ -0,0 +1,987 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "fxinst.h" +#include "fxemu.h" + +static void FxReset (struct FxInfo_s *); +static void fx_readRegisterSpace (void); +static void fx_writeRegisterSpace (void); +static void fx_updateRamBank (uint8); +static void fx_dirtySCBR (void); +static bool8 fx_checkStartAddress (void); +static uint32 FxEmulate (uint32); +static void FxCacheWriteAccess (uint16); +static void FxFlushCache (void); + + +void S9xInitSuperFX (void) +{ + memset((uint8 *) &GSU, 0, sizeof(struct FxRegs_s)); +} + +void S9xResetSuperFX (void) +{ + // FIXME: Snes9x can't execute CPU and SuperFX at a time. Don't ask me what is 0.417 :P + SuperFX.speedPerLine = (uint32) (0.417 * 10.5e6 * ((1.0 / (float) Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max)))); + SuperFX.oneLineDone = FALSE; + SuperFX.vFlags = 0; + FxReset(&SuperFX); +} + +void S9xSetSuperFX (uint8 byte, uint16 address) +{ + switch (address) + { + case 0x3030: + if ((Memory.FillRAM[0x3030] ^ byte) & FLG_G) + { + Memory.FillRAM[0x3030] = byte; + if (byte & FLG_G) + { + if (!SuperFX.oneLineDone) + { + S9xSuperFXExec(); + SuperFX.oneLineDone = TRUE; + } + } + else + FxFlushCache(); + } + else + Memory.FillRAM[0x3030] = byte; + + break; + + case 0x3031: + Memory.FillRAM[0x3031] = byte; + break; + + case 0x3033: + Memory.FillRAM[0x3033] = byte; + break; + + case 0x3034: + Memory.FillRAM[0x3034] = byte & 0x7f; + break; + + case 0x3036: + Memory.FillRAM[0x3036] = byte & 0x7f; + break; + + case 0x3037: + Memory.FillRAM[0x3037] = byte; + break; + + case 0x3038: + Memory.FillRAM[0x3038] = byte; + fx_dirtySCBR(); + break; + + case 0x3039: + Memory.FillRAM[0x3039] = byte; + break; + + case 0x303a: + Memory.FillRAM[0x303a] = byte; + break; + + case 0x303b: + break; + + case 0x303c: + Memory.FillRAM[0x303c] = byte; + fx_updateRamBank(byte); + break; + + case 0x303f: + Memory.FillRAM[0x303f] = byte; + break; + + case 0x301f: + Memory.FillRAM[0x301f] = byte; + Memory.FillRAM[0x3000 + GSU_SFR] |= FLG_G; + if (!SuperFX.oneLineDone) + { + S9xSuperFXExec(); + SuperFX.oneLineDone = TRUE; + } + + break; + + default: + Memory.FillRAM[address] = byte; + if (address >= 0x3100) + FxCacheWriteAccess(address); + + break; + } +} + +uint8 S9xGetSuperFX (uint16 address) +{ + uint8 byte; + + byte = Memory.FillRAM[address]; +#ifdef CPU_SHUTDOWN + if (address == 0x3030) + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; +#endif + if (address == 0x3031) + { + S9xClearIRQ(GSU_IRQ_SOURCE); + Memory.FillRAM[0x3031] = byte & 0x7f; + } + + return (byte); +} + +void S9xSuperFXExec (void) +{ + if ((Memory.FillRAM[0x3000 + GSU_SFR] & FLG_G) && (Memory.FillRAM[0x3000 + GSU_SCMR] & 0x18) == 0x18) + { + FxEmulate((Memory.FillRAM[0x3000 + GSU_CLSR] & 1) ? SuperFX.speedPerLine * 2 : SuperFX.speedPerLine); + + uint16 GSUStatus = Memory.FillRAM[0x3000 + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8); + if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ) + S9xSetIRQ(GSU_IRQ_SOURCE); + } +} + +static void FxReset (struct FxInfo_s *psFxInfo) +{ + // 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 (int 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 (int 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 void fx_readRegisterSpace (void) +{ + static uint32 avHeight[] = { 128, 160, 192, 256 }; + static uint32 avMult[] = { 16, 32, 32, 64 }; + + uint8 *p; + int n; + + GSU.vErrorCode = 0; + + // Update R0-R15 + p = GSU.pvRegisters; + for (int 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]; + n = (int) (!!(p[GSU_SCMR] & 0x04)); + n |= ((int) (!!(p[GSU_SCMR] & 0x20))) << 1; + GSU.vScreenHeight = GSU.vScreenRealHeight = avHeight[n]; + GSU.vMode = p[GSU_SCMR] & 0x03; + + if (n == 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 (GSU.pvScreenBase + GSU.vScreenSize > GSU.pvRam + (GSU.nRamBanks * 65536)) + GSU.pvScreenBase = GSU.pvRam + (GSU.nRamBanks * 65536) - GSU.vScreenSize; + + GSU.pfPlot = fx_PlotTable[GSU.vMode]; + GSU.pfRpix = fx_PlotTable[GSU.vMode + 5]; + + fx_OpcodeTable[0x04c] = GSU.pfPlot; + fx_OpcodeTable[0x14c] = GSU.pfRpix; + fx_OpcodeTable[0x24c] = GSU.pfPlot; + fx_OpcodeTable[0x34c] = GSU.pfRpix; + + fx_computeScreenPointers(); + + //fx_backupCache(); +} + +static void fx_writeRegisterSpace (void) +{ + uint8 *p; + + p = GSU.pvRegisters; + for (int 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(); +} + +// Update RamBankReg and RAM Bank pointer +static void fx_updateRamBank (uint8 byte) +{ + // Update BankReg and Bank pointer + GSU.vRamBankReg = (uint32) byte & (FX_RAM_BANKS - 1); + GSU.pvRamBank = GSU.apvRamBank[byte & 0x3]; +} + +// SCBR write seen. We need to update our cached screen pointers +static void fx_dirtySCBR (void) +{ + GSU.vSCBRDirty = TRUE; +} + +static bool8 fx_checkStartAddress (void) +{ + // 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 +static uint32 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(); + /* + GSU.vIllegalAddress = (GSU.vPrgBankReg << 24) | R15; + return (FX_ERROR_ILLEGAL_ADDRESS); + */ + + return (0); + } + + // Execute GSU session + CF(IRQ); + + /* + if (GSU.bBreakPoint) + vCount = fx_run_to_breakpoint(nInstructions); + else + */ + vCount = fx_run(nInstructions); + + // Store GSU registers + fx_writeRegisterSpace(); + + // Check for error code + if (GSU.vErrorCode) + return (GSU.vErrorCode); + else + return (vCount); +} + +void fx_computeScreenPointers (void) +{ + if (GSU.vMode != GSU.vPrevMode || GSU.vPrevScreenHeight != GSU.vScreenHeight || GSU.vSCBRDirty) + { + 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 (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = i << 8; + } + + break; + + case 1: + for (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 5); + GSU.x[i] = i << 9; + } + + break; + + case 2: + case 3: + for (int 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 (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = (i << 8) + (i << 6); + } + + break; + + case 1: + for (int 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 (int 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 (int i = 0; i < 32; i++) + { + GSU.apvScreen[i] = GSU.pvScreenBase + (i << 4); + GSU.x[i] = (i << 8) + (i << 7); + } + + break; + + case 1: + for (int 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 (int 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 (int 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 (int 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 (int 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; + } +} + +// Write access to the cache +static void FxCacheWriteAccess (uint16 vAddress) +{ + /* + if (!GSU.bCacheActive) + { + uint8 v = GSU.pvCache[GSU.pvCache[vAddress & 0x1ff]; + fx_setCache(); + GSU.pvCache[GSU.pvCache[vAddress & 0x1ff] = v; + } + */ + + if ((vAddress & 0x00f) == 0x00f) + GSU.vCacheFlags |= 1 << ((vAddress & 0x1f0) >> 4); +} + +static void FxFlushCache (void) +{ + GSU.vCacheFlags = 0; + GSU.vCacheBaseReg = 0; + GSU.bCacheActive = FALSE; + //GSU.vPipe = 0x1; +} + +void fx_flushCache (void) +{ + //fx_restoreCache(); + GSU.vCacheFlags = 0; + GSU.bCacheActive = FALSE; +} + +/* +static void fx_setCache (void) +{ + 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)) + { + const uint8 *t = &ROM(c); + memcpy(GSU.pvCache, t, 512); + } + else + { + const uint8 *t1, *t2; + uint32 i = 0x10000 - c; + + t1 = &ROM(c); + t2 = &ROM(0); + memcpy(GSU.pvCache, t1, i); + memcpy(&GSU.pvCache[i], t2, 512 - i); + } +} +*/ + +/* +static void fx_backupCache (void) +{ + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); + + if (v) + { + for (int 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, *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; + } + } +} +*/ + +/* +static void fx_restoreCache() +{ + uint32 v = GSU.vCacheFlags; + uint32 c = USEX16(GSU.vCacheBaseReg); + + if (v) + { + for (int 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, *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; + } + } +} +*/ + +// Breakpoints +/* +static void FxBreakPointSet (uint32 vAddress) +{ + GSU.bBreakPoint = TRUE; + GSU.vBreakPoint = USEX16(vAddress); +} +*/ + +/* +static void FxBreakPointClear (void) +{ + GSU.bBreakPoint = FALSE; +} +*/ + +// Step by step execution +/* +static uint32 FxStepOver (uint32 nInstructions) +{ + uint32 vCount; + + fx_readRegisterSpace(); + + 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_step_over(nInstructions); + + fx_writeRegisterSpace(); + + if (GSU.vErrorCode) + return (GSU.vErrorCode); + else + return (vCount); +} +*/ + +// Errors +/* +static int FxGetErrorCode (void) +{ + return (GSU.vErrorCode); +} +*/ + +/* +static int FxGetIllegalAddress (void) +{ + return (GSU.vIllegalAddress); +} +*/ + +// Access to internal registers +/* +static uint32 FxGetColorRegister (void) +{ + return (GSU.vColorReg & 0xff); +} +*/ + +/* +static uint32 FxGetPlotOptionRegister (void) +{ + return (GSU.vPlotOptionReg & 0x1f); +} +*/ + +/* +static uint32 FxGetSourceRegisterIndex (void) +{ + return (GSU.pvSreg - GSU.avReg); +} +*/ + +/* +static uint32 FxGetDestinationRegisterIndex (void) +{ + return (GSU.pvDreg - GSU.avReg); +} +*/ + +// Get the byte currently in the pipe +/* +static uint8 FxPipe (void) +{ + return (GSU.vPipe); +} +*/ diff --git a/fxemu.h b/fxemu.h new file mode 100644 index 00000000..45df36e8 --- /dev/null +++ b/fxemu.h @@ -0,0 +1,236 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _FXEMU_H_ +#define _FXEMU_H_ + +#ifndef ZSNES_FX + +// The FxInfo_s structure, the link between the FxEmulator and the Snes Emulator +struct FxInfo_s +{ + uint32 vFlags; + uint8 *pvRegisters; // 768 bytes located in the memory at address 0x3000 + uint32 nRamBanks; // Number of 64kb-banks in GSU-RAM/BackupRAM (banks 0x70-0x73) + uint8 *pvRam; // Pointer to GSU-RAM + uint32 nRomBanks; // Number of 32kb-banks in Cart-ROM + uint8 *pvRom; // Pointer to Cart-ROM + uint32 speedPerLine; + bool8 oneLineDone; +}; + +extern struct FxInfo_s SuperFX; + +void S9xInitSuperFX (void); +void S9xSetSuperFX (uint8, uint16); +uint8 S9xGetSuperFX (uint16); +void fx_flushCache (void); +void fx_computeScreenPointers (void); +uint32 fx_run (uint32); + +#define FX_BREAKPOINT (-1) +#define FX_ERROR_ILLEGAL_ADDRESS (-2) + +#else + +#define S9xSetSuperFX S9xSuperFXWriteReg +#define S9xGetSuperFX S9xSuperFXReadReg + +START_EXTERN_C +extern uint8 *SFXPlotTable; + +void S9xSuperFXWriteReg (uint8, uint32); +uint8 S9xSuperFXReadReg (uint32); +void S9xSuperFXPreSaveState (void); +void S9xSuperFXPostSaveState (void); +void S9xSuperFXPostLoadState (void); +END_EXTERN_C + +#endif + +#ifdef ZSNES_FX +START_EXTERN_C +#endif + +void S9xResetSuperFX (void); +void S9xSuperFXExec (void); + +#ifdef ZSNES_FX +END_EXTERN_C +#endif + +#endif diff --git a/fxinst.cpp b/fxinst.cpp new file mode 100644 index 00000000..5f7df2bf --- /dev/null +++ b/fxinst.cpp @@ -0,0 +1,4424 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "fxinst.h" +#include "fxemu.h" + +// 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 void fx_stop (void) +{ + 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 void fx_nop (void) +{ + CLRFLAGS; + R15++; +} + +// 02 - cache - reintialize GSU cache +static void fx_cache (void) +{ + uint32 c = R15 & 0xfff0; + + if (GSU.vCacheBaseReg != c || !GSU.bCacheActive) + { + fx_flushCache(); + GSU.vCacheBaseReg = c; + GSU.bCacheActive = TRUE; + + #if 0 + if (c < (0x10000 - 512)) + { + const uint8 *t = &ROM(c); + memcpy(GSU.pvCache, t, 512); + } + else + { + const uint8 *t1, t2; + uint32 i = 0x10000 - c; + t1 = &ROM(c); + t2 = &ROM(0); + memcpy(GSU.pvCache, t1, i); + memcpy(&GSU.pvCache[i], t2, 512 - i); + } + #endif + } + + CLRFLAGS; + R15++; +} + +// 03 - lsr - logic shift right +static void fx_lsr (void) +{ + 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 void fx_rol (void) +{ + 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 void fx_bra (void) +{ + 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 void fx_blt (void) +{ + BRA_COND((TEST_S != 0) != (TEST_OV != 0)); +} + +// 07 - bge - branch on greater or equals +static void fx_bge (void) +{ + BRA_COND((TEST_S != 0) == (TEST_OV != 0)); +} + +// 08 - bne - branch on not equal +static void fx_bne (void) +{ + BRA_COND(!TEST_Z); +} + +// 09 - beq - branch on equal +static void fx_beq (void) +{ + BRA_COND(TEST_Z); +} + +// 0a - bpl - branch on plus +static void fx_bpl (void) +{ + BRA_COND(!TEST_S); +} + +// 0b - bmi - branch on minus +static void fx_bmi (void) +{ + BRA_COND(TEST_S); +} + +// 0c - bcc - branch on carry clear +static void fx_bcc (void) +{ + BRA_COND(!TEST_CY); +} + +// 0d - bcs - branch on carry set +static void fx_bcs (void) +{ + BRA_COND(TEST_CY); +} + +// 0e - bvc - branch on overflow clear +static void fx_bvc (void) +{ + BRA_COND(!TEST_OV); +} + +// 0f - bvs - branch on overflow set +static void fx_bvs (void) +{ + 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 void fx_to_r0 (void) +{ + FX_TO(0); +} + +static void fx_to_r1 (void) +{ + FX_TO(1); +} + +static void fx_to_r2 (void) +{ + FX_TO(2); +} + +static void fx_to_r3 (void) +{ + FX_TO(3); +} + +static void fx_to_r4 (void) +{ + FX_TO(4); +} + +static void fx_to_r5 (void) +{ + FX_TO(5); +} + +static void fx_to_r6 (void) +{ + FX_TO(6); +} + +static void fx_to_r7 (void) +{ + FX_TO(7); +} + +static void fx_to_r8 (void) +{ + FX_TO(8); +} + +static void fx_to_r9 (void) +{ + FX_TO(9); +} + +static void fx_to_r10 (void) +{ + FX_TO(10); +} + +static void fx_to_r11 (void) +{ + FX_TO(11); +} + +static void fx_to_r12 (void) +{ + FX_TO(12); +} + +static void fx_to_r13 (void) +{ + FX_TO(13); +} + +static void fx_to_r14 (void) +{ + FX_TO_R14(14); +} + +static void fx_to_r15 (void) +{ + 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 void fx_with_r0 (void) +{ + FX_WITH(0); +} + +static void fx_with_r1 (void) +{ + FX_WITH(1); +} + +static void fx_with_r2 (void) +{ + FX_WITH(2); +} + +static void fx_with_r3 (void) +{ + FX_WITH(3); +} + +static void fx_with_r4 (void) +{ + FX_WITH(4); +} + +static void fx_with_r5 (void) +{ + FX_WITH(5); +} + +static void fx_with_r6 (void) +{ + FX_WITH(6); +} + +static void fx_with_r7 (void) +{ + FX_WITH(7); +} + +static void fx_with_r8 (void) +{ + FX_WITH(8); +} + +static void fx_with_r9 (void) +{ + FX_WITH(9); +} + +static void fx_with_r10 (void) +{ + FX_WITH(10); +} + +static void fx_with_r11 (void) +{ + FX_WITH(11); +} + +static void fx_with_r12 (void) +{ + FX_WITH(12); +} + +static void fx_with_r13 (void) +{ + FX_WITH(13); +} + +static void fx_with_r14 (void) +{ + FX_WITH(14); +} + +static void fx_with_r15 (void) +{ + 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 void fx_stw_r0 (void) +{ + FX_STW(0); +} + +static void fx_stw_r1 (void) +{ + FX_STW(1); +} + +static void fx_stw_r2 (void) +{ + FX_STW(2); +} + +static void fx_stw_r3 (void) +{ + FX_STW(3); +} + +static void fx_stw_r4 (void) +{ + FX_STW(4); +} + +static void fx_stw_r5 (void) +{ + FX_STW(5); +} + +static void fx_stw_r6 (void) +{ + FX_STW(6); +} + +static void fx_stw_r7 (void) +{ + FX_STW(7); +} + +static void fx_stw_r8 (void) +{ + FX_STW(8); +} + +static void fx_stw_r9 (void) +{ + FX_STW(9); +} + +static void fx_stw_r10 (void) +{ + FX_STW(10); +} + +static void fx_stw_r11 (void) +{ + 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 void fx_stb_r0 (void) +{ + FX_STB(0); +} + +static void fx_stb_r1 (void) +{ + FX_STB(1); +} + +static void fx_stb_r2 (void) +{ + FX_STB(2); +} + +static void fx_stb_r3 (void) +{ + FX_STB(3); +} + +static void fx_stb_r4 (void) +{ + FX_STB(4); +} + +static void fx_stb_r5 (void) +{ + FX_STB(5); +} + +static void fx_stb_r6 (void) +{ + FX_STB(6); +} + +static void fx_stb_r7 (void) +{ + FX_STB(7); +} + +static void fx_stb_r8 (void) +{ + FX_STB(8); +} + +static void fx_stb_r9 (void) +{ + FX_STB(9); +} + +static void fx_stb_r10 (void) +{ + FX_STB(10); +} + +static void fx_stb_r11 (void) +{ + FX_STB(11); +} + +// 3c - loop - decrement loop counter, and branch on not zero +static void fx_loop (void) +{ + GSU.vSign = GSU.vZero = --R12; + if ((uint16) R12 != 0) + R15 = R13; + else + R15++; + CLRFLAGS; +} + +// 3d - alt1 - set alt1 mode +static void fx_alt1 (void) +{ + SF(ALT1); + CF(B); + R15++; +} + +// 3e - alt2 - set alt2 mode +static void fx_alt2 (void) +{ + SF(ALT2); + CF(B); + R15++; +} + +// 3f - alt3 - set alt3 mode +static void fx_alt3 (void) +{ + 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 void fx_ldw_r0 (void) +{ + FX_LDW(0); +} + +static void fx_ldw_r1 (void) +{ + FX_LDW(1); +} + +static void fx_ldw_r2 (void) +{ + FX_LDW(2); +} + +static void fx_ldw_r3 (void) +{ + FX_LDW(3); +} + +static void fx_ldw_r4 (void) +{ + FX_LDW(4); +} + +static void fx_ldw_r5 (void) +{ + FX_LDW(5); +} + +static void fx_ldw_r6 (void) +{ + FX_LDW(6); +} + +static void fx_ldw_r7 (void) +{ + FX_LDW(7); +} + +static void fx_ldw_r8 (void) +{ + FX_LDW(8); +} + +static void fx_ldw_r9 (void) +{ + FX_LDW(9); +} + +static void fx_ldw_r10 (void) +{ + FX_LDW(10); +} + +static void fx_ldw_r11 (void) +{ + 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 void fx_ldb_r0 (void) +{ + FX_LDB(0); +} + +static void fx_ldb_r1 (void) +{ + FX_LDB(1); +} + +static void fx_ldb_r2 (void) +{ + FX_LDB(2); +} + +static void fx_ldb_r3 (void) +{ + FX_LDB(3); +} + +static void fx_ldb_r4 (void) +{ + FX_LDB(4); +} + +static void fx_ldb_r5 (void) +{ + FX_LDB(5); +} + +static void fx_ldb_r6 (void) +{ + FX_LDB(6); +} + +static void fx_ldb_r7 (void) +{ + FX_LDB(7); +} + +static void fx_ldb_r8 (void) +{ + FX_LDB(8); +} + +static void fx_ldb_r9 (void) +{ + FX_LDB(9); +} + +static void fx_ldb_r10 (void) +{ + FX_LDB(10); +} + +static void fx_ldb_r11 (void) +{ + FX_LDB(11); +} + +// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color +static void fx_plot_2bit (void) +{ + 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; +} + +// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y +static void fx_rpix_2bit (void) +{ + 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 void fx_plot_4bit (void) +{ + 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 void fx_rpix_4bit (void) +{ + 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; +} + +// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color +static void fx_plot_8bit (void) +{ + 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 void fx_rpix_8bit (void) +{ + 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; +} + +// 4c - plot - plot pixel with R1, R2 as x, y and the color register as the color +static void fx_plot_obj (void) +{ +#ifdef DEBUGGER + fprintf(stderr, "ERROR fx_plot_obj called\n"); +#endif +} + +// 4c (ALT1) - rpix - read color of the pixel with R1, R2 as x, y +static void fx_rpix_obj (void) +{ +#ifdef DEBUGGER + fprintf(stderr, "ERROR fx_rpix_obj called\n"); +#endif +} + +// 4d - swap - swap upper and lower byte of a register +static void fx_swap (void) +{ + 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 void fx_color (void) +{ + 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 void fx_cmode (void) +{ + GSU.vPlotOptionReg = SREG; + + if (GSU.vPlotOptionReg & 0x10) + GSU.vScreenHeight = 256; // OBJ Mode (for drawing into sprites) + else + GSU.vScreenHeight = GSU.vScreenRealHeight; + + fx_computeScreenPointers(); + CLRFLAGS; + R15++; +} + +// 4f - not - perform exclusive exor with 1 on all bits +static void fx_not (void) +{ + 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 void fx_add_r0 (void) +{ + FX_ADD(0); +} + +static void fx_add_r1 (void) +{ + FX_ADD(1); +} + +static void fx_add_r2 (void) +{ + FX_ADD(2); +} + +static void fx_add_r3 (void) +{ + FX_ADD(3); +} + +static void fx_add_r4 (void) +{ + FX_ADD(4); +} + +static void fx_add_r5 (void) +{ + FX_ADD(5); +} + +static void fx_add_r6 (void) +{ + FX_ADD(6); +} + +static void fx_add_r7 (void) +{ + FX_ADD(7); +} + +static void fx_add_r8 (void) +{ + FX_ADD(8); +} + +static void fx_add_r9 (void) +{ + FX_ADD(9); +} + +static void fx_add_r10 (void) +{ + FX_ADD(10); +} + +static void fx_add_r11 (void) +{ + FX_ADD(11); +} + +static void fx_add_r12 (void) +{ + FX_ADD(12); +} + +static void fx_add_r13 (void) +{ + FX_ADD(13); +} + +static void fx_add_r14 (void) +{ + FX_ADD(14); +} + +static void fx_add_r15 (void) +{ + 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 void fx_adc_r0 (void) +{ + FX_ADC(0); +} + +static void fx_adc_r1 (void) +{ + FX_ADC(1); +} + +static void fx_adc_r2 (void) +{ + FX_ADC(2); +} + +static void fx_adc_r3 (void) +{ + FX_ADC(3); +} + +static void fx_adc_r4 (void) +{ + FX_ADC(4); +} + +static void fx_adc_r5 (void) +{ + FX_ADC(5); +} + +static void fx_adc_r6 (void) +{ + FX_ADC(6); +} + +static void fx_adc_r7 (void) +{ + FX_ADC(7); +} + +static void fx_adc_r8 (void) +{ + FX_ADC(8); +} + +static void fx_adc_r9 (void) +{ + FX_ADC(9); +} + +static void fx_adc_r10 (void) +{ + FX_ADC(10); +} + +static void fx_adc_r11 (void) +{ + FX_ADC(11); +} + +static void fx_adc_r12 (void) +{ + FX_ADC(12); +} + +static void fx_adc_r13 (void) +{ + FX_ADC(13); +} + +static void fx_adc_r14 (void) +{ + FX_ADC(14); +} + +static void fx_adc_r15 (void) +{ + 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 void fx_add_i0 (void) +{ + FX_ADD_I(0); +} + +static void fx_add_i1 (void) +{ + FX_ADD_I(1); +} + +static void fx_add_i2 (void) +{ + FX_ADD_I(2); +} + +static void fx_add_i3 (void) +{ + FX_ADD_I(3); +} + +static void fx_add_i4 (void) +{ + FX_ADD_I(4); +} + +static void fx_add_i5 (void) +{ + FX_ADD_I(5); +} + +static void fx_add_i6 (void) +{ + FX_ADD_I(6); +} + +static void fx_add_i7 (void) +{ + FX_ADD_I(7); +} + +static void fx_add_i8 (void) +{ + FX_ADD_I(8); +} + +static void fx_add_i9 (void) +{ + FX_ADD_I(9); +} + +static void fx_add_i10 (void) +{ + FX_ADD_I(10); +} + +static void fx_add_i11 (void) +{ + FX_ADD_I(11); +} + +static void fx_add_i12 (void) +{ + FX_ADD_I(12); +} + +static void fx_add_i13 (void) +{ + FX_ADD_I(13); +} + +static void fx_add_i14 (void) +{ + FX_ADD_I(14); +} + +static void fx_add_i15 (void) +{ + 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 void fx_adc_i0 (void) +{ + FX_ADC_I(0); +} + +static void fx_adc_i1 (void) +{ + FX_ADC_I(1); +} + +static void fx_adc_i2 (void) +{ + FX_ADC_I(2); +} + +static void fx_adc_i3 (void) +{ + FX_ADC_I(3); +} + +static void fx_adc_i4 (void) +{ + FX_ADC_I(4); +} + +static void fx_adc_i5 (void) +{ + FX_ADC_I(5); +} + +static void fx_adc_i6 (void) +{ + FX_ADC_I(6); +} + +static void fx_adc_i7 (void) +{ + FX_ADC_I(7); +} + +static void fx_adc_i8 (void) +{ + FX_ADC_I(8); +} + +static void fx_adc_i9 (void) +{ + FX_ADC_I(9); +} + +static void fx_adc_i10 (void) +{ + FX_ADC_I(10); +} + +static void fx_adc_i11 (void) +{ + FX_ADC_I(11); +} + +static void fx_adc_i12 (void) +{ + FX_ADC_I(12); +} + +static void fx_adc_i13 (void) +{ + FX_ADC_I(13); +} + +static void fx_adc_i14 (void) +{ + FX_ADC_I(14); +} + +static void fx_adc_i15 (void) +{ + 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 void fx_sub_r0 (void) +{ + FX_SUB(0); +} + +static void fx_sub_r1 (void) +{ + FX_SUB(1); +} + +static void fx_sub_r2 (void) +{ + FX_SUB(2); +} + +static void fx_sub_r3 (void) +{ + FX_SUB(3); +} + +static void fx_sub_r4 (void) +{ + FX_SUB(4); +} + +static void fx_sub_r5 (void) +{ + FX_SUB(5); +} + +static void fx_sub_r6 (void) +{ + FX_SUB(6); +} + +static void fx_sub_r7 (void) +{ + FX_SUB(7); +} + +static void fx_sub_r8 (void) +{ + FX_SUB(8); +} + +static void fx_sub_r9 (void) +{ + FX_SUB(9); +} + +static void fx_sub_r10 (void) +{ + FX_SUB(10); +} + +static void fx_sub_r11 (void) +{ + FX_SUB(11); +} + +static void fx_sub_r12 (void) +{ + FX_SUB(12); +} + +static void fx_sub_r13 (void) +{ + FX_SUB(13); +} + +static void fx_sub_r14 (void) +{ + FX_SUB(14); +} + +static void fx_sub_r15 (void) +{ + 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 void fx_sbc_r0 (void) +{ + FX_SBC(0); +} + +static void fx_sbc_r1 (void) +{ + FX_SBC(1); +} + +static void fx_sbc_r2 (void) +{ + FX_SBC(2); +} + +static void fx_sbc_r3 (void) +{ + FX_SBC(3); +} + +static void fx_sbc_r4 (void) +{ + FX_SBC(4); +} + +static void fx_sbc_r5 (void) +{ + FX_SBC(5); +} + +static void fx_sbc_r6 (void) +{ + FX_SBC(6); +} + +static void fx_sbc_r7 (void) +{ + FX_SBC(7); +} + +static void fx_sbc_r8 (void) +{ + FX_SBC(8); +} + +static void fx_sbc_r9 (void) +{ + FX_SBC(9); +} + +static void fx_sbc_r10 (void) +{ + FX_SBC(10); +} + +static void fx_sbc_r11 (void) +{ + FX_SBC(11); +} + +static void fx_sbc_r12 (void) +{ + FX_SBC(12); +} + +static void fx_sbc_r13 (void) +{ + FX_SBC(13); +} + +static void fx_sbc_r14 (void) +{ + FX_SBC(14); +} + +static void fx_sbc_r15 (void) +{ + 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 void fx_sub_i0 (void) +{ + FX_SUB_I(0); +} + +static void fx_sub_i1 (void) +{ + FX_SUB_I(1); +} + +static void fx_sub_i2 (void) +{ + FX_SUB_I(2); +} + +static void fx_sub_i3 (void) +{ + FX_SUB_I(3); +} + +static void fx_sub_i4 (void) +{ + FX_SUB_I(4); +} + +static void fx_sub_i5 (void) +{ + FX_SUB_I(5); +} + +static void fx_sub_i6 (void) +{ + FX_SUB_I(6); +} + +static void fx_sub_i7 (void) +{ + FX_SUB_I(7); +} + +static void fx_sub_i8 (void) +{ + FX_SUB_I(8); +} + +static void fx_sub_i9 (void) +{ + FX_SUB_I(9); +} + +static void fx_sub_i10 (void) +{ + FX_SUB_I(10); +} + +static void fx_sub_i11 (void) +{ + FX_SUB_I(11); +} + +static void fx_sub_i12 (void) +{ + FX_SUB_I(12); +} + +static void fx_sub_i13 (void) +{ + FX_SUB_I(13); +} + +static void fx_sub_i14 (void) +{ + FX_SUB_I(14); +} + +static void fx_sub_i15 (void) +{ + 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 void fx_cmp_r0 (void) +{ + FX_CMP(0); +} + +static void fx_cmp_r1 (void) +{ + FX_CMP(1); +} + +static void fx_cmp_r2 (void) +{ + FX_CMP(2); +} + +static void fx_cmp_r3 (void) +{ + FX_CMP(3); +} + +static void fx_cmp_r4 (void) +{ + FX_CMP(4); +} + +static void fx_cmp_r5 (void) +{ + FX_CMP(5); +} + +static void fx_cmp_r6 (void) +{ + FX_CMP(6); +} + +static void fx_cmp_r7 (void) +{ + FX_CMP(7); +} + +static void fx_cmp_r8 (void) +{ + FX_CMP(8); +} + +static void fx_cmp_r9 (void) +{ + FX_CMP(9); +} + +static void fx_cmp_r10 (void) +{ + FX_CMP(10); +} + +static void fx_cmp_r11 (void) +{ + FX_CMP(11); +} + +static void fx_cmp_r12 (void) +{ + FX_CMP(12); +} + +static void fx_cmp_r13 (void) +{ + FX_CMP(13); +} + +static void fx_cmp_r14 (void) +{ + FX_CMP(14); +} + +static void fx_cmp_r15 (void) +{ + FX_CMP(15); +} + +// 70 - merge - R7 as upper byte, R8 as lower byte (used for texture-mapping) +static void fx_merge (void) +{ + 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 void fx_and_r1 (void) +{ + FX_AND(1); +} + +static void fx_and_r2 (void) +{ + FX_AND(2); +} + +static void fx_and_r3 (void) +{ + FX_AND(3); +} + +static void fx_and_r4 (void) +{ + FX_AND(4); +} + +static void fx_and_r5 (void) +{ + FX_AND(5); +} + +static void fx_and_r6 (void) +{ + FX_AND(6); +} + +static void fx_and_r7 (void) +{ + FX_AND(7); +} + +static void fx_and_r8 (void) +{ + FX_AND(8); +} + +static void fx_and_r9 (void) +{ + FX_AND(9); +} + +static void fx_and_r10 (void) +{ + FX_AND(10); +} + +static void fx_and_r11 (void) +{ + FX_AND(11); +} + +static void fx_and_r12 (void) +{ + FX_AND(12); +} + +static void fx_and_r13 (void) +{ + FX_AND(13); +} + +static void fx_and_r14 (void) +{ + FX_AND(14); +} + +static void fx_and_r15 (void) +{ + 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 void fx_bic_r1 (void) +{ + FX_BIC(1); +} + +static void fx_bic_r2 (void) +{ + FX_BIC(2); +} + +static void fx_bic_r3 (void) +{ + FX_BIC(3); +} + +static void fx_bic_r4 (void) +{ + FX_BIC(4); +} + +static void fx_bic_r5 (void) +{ + FX_BIC(5); +} + +static void fx_bic_r6 (void) +{ + FX_BIC(6); +} + +static void fx_bic_r7 (void) +{ + FX_BIC(7); +} + +static void fx_bic_r8 (void) +{ + FX_BIC(8); +} + +static void fx_bic_r9 (void) +{ + FX_BIC(9); +} + +static void fx_bic_r10 (void) +{ + FX_BIC(10); +} + +static void fx_bic_r11 (void) +{ + FX_BIC(11); +} + +static void fx_bic_r12 (void) +{ + FX_BIC(12); +} + +static void fx_bic_r13 (void) +{ + FX_BIC(13); +} + +static void fx_bic_r14 (void) +{ + FX_BIC(14); +} + +static void fx_bic_r15 (void) +{ + 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 void fx_and_i1 (void) +{ + FX_AND_I(1); +} + +static void fx_and_i2 (void) +{ + FX_AND_I(2); +} + +static void fx_and_i3 (void) +{ + FX_AND_I(3); +} + +static void fx_and_i4 (void) +{ + FX_AND_I(4); +} + +static void fx_and_i5 (void) +{ + FX_AND_I(5); +} + +static void fx_and_i6 (void) +{ + FX_AND_I(6); +} + +static void fx_and_i7 (void) +{ + FX_AND_I(7); +} + +static void fx_and_i8 (void) +{ + FX_AND_I(8); +} + +static void fx_and_i9 (void) +{ + FX_AND_I(9); +} + +static void fx_and_i10 (void) +{ + FX_AND_I(10); +} + +static void fx_and_i11 (void) +{ + FX_AND_I(11); +} + +static void fx_and_i12 (void) +{ + FX_AND_I(12); +} + +static void fx_and_i13 (void) +{ + FX_AND_I(13); +} + +static void fx_and_i14 (void) +{ + FX_AND_I(14); +} + +static void fx_and_i15 (void) +{ + 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 void fx_bic_i1 (void) +{ + FX_BIC_I(1); +} + +static void fx_bic_i2 (void) +{ + FX_BIC_I(2); +} + +static void fx_bic_i3 (void) +{ + FX_BIC_I(3); +} + +static void fx_bic_i4 (void) +{ + FX_BIC_I(4); +} + +static void fx_bic_i5 (void) +{ + FX_BIC_I(5); +} + +static void fx_bic_i6 (void) +{ + FX_BIC_I(6); +} + +static void fx_bic_i7 (void) +{ + FX_BIC_I(7); +} + +static void fx_bic_i8 (void) +{ + FX_BIC_I(8); +} + +static void fx_bic_i9 (void) +{ + FX_BIC_I(9); +} + +static void fx_bic_i10 (void) +{ + FX_BIC_I(10); +} + +static void fx_bic_i11 (void) +{ + FX_BIC_I(11); +} + +static void fx_bic_i12 (void) +{ + FX_BIC_I(12); +} + +static void fx_bic_i13 (void) +{ + FX_BIC_I(13); +} + +static void fx_bic_i14 (void) +{ + FX_BIC_I(14); +} + +static void fx_bic_i15 (void) +{ + 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 void fx_mult_r0 (void) +{ + FX_MULT(0); +} + +static void fx_mult_r1 (void) +{ + FX_MULT(1); +} + +static void fx_mult_r2 (void) +{ + FX_MULT(2); +} + +static void fx_mult_r3 (void) +{ + FX_MULT(3); +} + +static void fx_mult_r4 (void) +{ + FX_MULT(4); +} + +static void fx_mult_r5 (void) +{ + FX_MULT(5); +} + +static void fx_mult_r6 (void) +{ + FX_MULT(6); +} + +static void fx_mult_r7 (void) +{ + FX_MULT(7); +} + +static void fx_mult_r8 (void) +{ + FX_MULT(8); +} + +static void fx_mult_r9 (void) +{ + FX_MULT(9); +} + +static void fx_mult_r10 (void) +{ + FX_MULT(10); +} + +static void fx_mult_r11 (void) +{ + FX_MULT(11); +} + +static void fx_mult_r12 (void) +{ + FX_MULT(12); +} + +static void fx_mult_r13 (void) +{ + FX_MULT(13); +} + +static void fx_mult_r14 (void) +{ + FX_MULT(14); +} + +static void fx_mult_r15 (void) +{ + 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 void fx_umult_r0 (void) +{ + FX_UMULT(0); +} + +static void fx_umult_r1 (void) +{ + FX_UMULT(1); +} + +static void fx_umult_r2 (void) +{ + FX_UMULT(2); +} + +static void fx_umult_r3 (void) +{ + FX_UMULT(3); +} + +static void fx_umult_r4 (void) +{ + FX_UMULT(4); +} + +static void fx_umult_r5 (void) +{ + FX_UMULT(5); +} + +static void fx_umult_r6 (void) +{ + FX_UMULT(6); +} + +static void fx_umult_r7 (void) +{ + FX_UMULT(7); +} + +static void fx_umult_r8 (void) +{ + FX_UMULT(8); +} + +static void fx_umult_r9 (void) +{ + FX_UMULT(9); +} + +static void fx_umult_r10 (void) +{ + FX_UMULT(10); +} + +static void fx_umult_r11 (void) +{ + FX_UMULT(11); +} + +static void fx_umult_r12 (void) +{ + FX_UMULT(12); +} + +static void fx_umult_r13 (void) +{ + FX_UMULT(13); +} + +static void fx_umult_r14 (void) +{ + FX_UMULT(14); +} + +static void fx_umult_r15 (void) +{ + 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 void fx_mult_i0 (void) +{ + FX_MULT_I(0); +} + +static void fx_mult_i1 (void) +{ + FX_MULT_I(1); +} + +static void fx_mult_i2 (void) +{ + FX_MULT_I(2); +} + +static void fx_mult_i3 (void) +{ + FX_MULT_I(3); +} + +static void fx_mult_i4 (void) +{ + FX_MULT_I(4); +} + +static void fx_mult_i5 (void) +{ + FX_MULT_I(5); +} + +static void fx_mult_i6 (void) +{ + FX_MULT_I(6); +} + +static void fx_mult_i7 (void) +{ + FX_MULT_I(7); +} + +static void fx_mult_i8 (void) +{ + FX_MULT_I(8); +} + +static void fx_mult_i9 (void) +{ + FX_MULT_I(9); +} + +static void fx_mult_i10 (void) +{ + FX_MULT_I(10); +} + +static void fx_mult_i11 (void) +{ + FX_MULT_I(11); +} + +static void fx_mult_i12 (void) +{ + FX_MULT_I(12); +} + +static void fx_mult_i13 (void) +{ + FX_MULT_I(13); +} + +static void fx_mult_i14 (void) +{ + FX_MULT_I(14); +} + +static void fx_mult_i15 (void) +{ + 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 void fx_umult_i0 (void) +{ + FX_UMULT_I(0); +} + +static void fx_umult_i1 (void) +{ + FX_UMULT_I(1); +} + +static void fx_umult_i2 (void) +{ + FX_UMULT_I(2); +} + +static void fx_umult_i3 (void) +{ + FX_UMULT_I(3); +} + +static void fx_umult_i4 (void) +{ + FX_UMULT_I(4); +} + +static void fx_umult_i5 (void) +{ + FX_UMULT_I(5); +} + +static void fx_umult_i6 (void) +{ + FX_UMULT_I(6); +} + +static void fx_umult_i7 (void) +{ + FX_UMULT_I(7); +} + +static void fx_umult_i8 (void) +{ + FX_UMULT_I(8); +} + +static void fx_umult_i9 (void) +{ + FX_UMULT_I(9); +} + +static void fx_umult_i10 (void) +{ + FX_UMULT_I(10); +} + +static void fx_umult_i11 (void) +{ + FX_UMULT_I(11); +} + +static void fx_umult_i12 (void) +{ + FX_UMULT_I(12); +} + +static void fx_umult_i13 (void) +{ + FX_UMULT_I(13); +} + +static void fx_umult_i14 (void) +{ + FX_UMULT_I(14); +} + +static void fx_umult_i15 (void) +{ + FX_UMULT_I(15); +} + +// 90 - sbk - store word to last accessed RAM address +static void fx_sbk (void) +{ + 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 void fx_link_i1 (void) +{ + FX_LINK_I(1); +} + +static void fx_link_i2 (void) +{ + FX_LINK_I(2); +} + +static void fx_link_i3 (void) +{ + FX_LINK_I(3); +} + +static void fx_link_i4 (void) +{ + FX_LINK_I(4); +} + +// 95 - sex - sign extend 8 bit to 16 bit +static void fx_sex (void) +{ + uint32 v = (uint32) SEX8(SREG); + R15++; + DREG = v; + GSU.vSign = v; + GSU.vZero = v; + TESTR14; + CLRFLAGS; +} + +// 96 - asr - aritmetric shift right by one +static void fx_asr (void) +{ + 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 void fx_div2 (void) +{ + 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 void fx_ror (void) +{ + 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 void fx_jmp_r8 (void) +{ + FX_JMP(8); +} + +static void fx_jmp_r9 (void) +{ + FX_JMP(9); +} + +static void fx_jmp_r10 (void) +{ + FX_JMP(10); +} + +static void fx_jmp_r11 (void) +{ + FX_JMP(11); +} + +static void fx_jmp_r12 (void) +{ + FX_JMP(12); +} + +static void fx_jmp_r13 (void) +{ + 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 void fx_ljmp_r8 (void) +{ + FX_LJMP(8); +} + +static void fx_ljmp_r9 (void) +{ + FX_LJMP(9); +} + +static void fx_ljmp_r10 (void) +{ + FX_LJMP(10); +} + +static void fx_ljmp_r11 (void) +{ + FX_LJMP(11); +} + +static void fx_ljmp_r12 (void) +{ + FX_LJMP(12); +} + +static void fx_ljmp_r13 (void) +{ + FX_LJMP(13); +} + +// 9e - lob - set upper byte to zero (keep low byte) +static void fx_lob (void) +{ + 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 void fx_fmult (void) +{ + 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 void fx_lmult (void) +{ + 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 void fx_ibt_r0 (void) +{ + FX_IBT(0); +} + +static void fx_ibt_r1 (void) +{ + FX_IBT(1); +} + +static void fx_ibt_r2 (void) +{ + FX_IBT(2); +} + +static void fx_ibt_r3 (void) +{ + FX_IBT(3); +} + +static void fx_ibt_r4 (void) +{ + FX_IBT(4); +} + +static void fx_ibt_r5 (void) +{ + FX_IBT(5); +} + +static void fx_ibt_r6 (void) +{ + FX_IBT(6); +} + +static void fx_ibt_r7 (void) +{ + FX_IBT(7); +} + +static void fx_ibt_r8 (void) +{ + FX_IBT(8); +} + +static void fx_ibt_r9 (void) +{ + FX_IBT(9); +} + +static void fx_ibt_r10 (void) +{ + FX_IBT(10); +} + +static void fx_ibt_r11 (void) +{ + FX_IBT(11); +} + +static void fx_ibt_r12 (void) +{ + FX_IBT(12); +} + +static void fx_ibt_r13 (void) +{ + FX_IBT(13); +} + +static void fx_ibt_r14 (void) +{ + FX_IBT(14); + READR14; +} + +static void fx_ibt_r15 (void) +{ + 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 void fx_lms_r0 (void) +{ + FX_LMS(0); +} + +static void fx_lms_r1 (void) +{ + FX_LMS(1); +} + +static void fx_lms_r2 (void) +{ + FX_LMS(2); +} + +static void fx_lms_r3 (void) +{ + FX_LMS(3); +} + +static void fx_lms_r4 (void) +{ + FX_LMS(4); +} + +static void fx_lms_r5 (void) +{ + FX_LMS(5); +} + +static void fx_lms_r6 (void) +{ + FX_LMS(6); +} + +static void fx_lms_r7 (void) +{ + FX_LMS(7); +} + +static void fx_lms_r8 (void) +{ + FX_LMS(8); +} + +static void fx_lms_r9 (void) +{ + FX_LMS(9); +} + +static void fx_lms_r10 (void) +{ + FX_LMS(10); +} + +static void fx_lms_r11 (void) +{ + FX_LMS(11); +} + +static void fx_lms_r12 (void) +{ + FX_LMS(12); +} + +static void fx_lms_r13 (void) +{ + FX_LMS(13); +} + +static void fx_lms_r14 (void) +{ + FX_LMS(14); + READR14; +} + +static void fx_lms_r15 (void) +{ + FX_LMS(15); +} + +// a0-af (ALT2) - sms (yy), rn - store word in RAM (short address) +// XXX: 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 void fx_sms_r0 (void) +{ + FX_SMS(0); +} + +static void fx_sms_r1 (void) +{ + FX_SMS(1); +} + +static void fx_sms_r2 (void) +{ + FX_SMS(2); +} + +static void fx_sms_r3 (void) +{ + FX_SMS(3); +} + +static void fx_sms_r4 (void) +{ + FX_SMS(4); +} + +static void fx_sms_r5 (void) +{ + FX_SMS(5); +} + +static void fx_sms_r6 (void) +{ + FX_SMS(6); +} + +static void fx_sms_r7 (void) +{ + FX_SMS(7); +} + +static void fx_sms_r8 (void) +{ + FX_SMS(8); +} + +static void fx_sms_r9 (void) +{ + FX_SMS(9); +} + +static void fx_sms_r10 (void) +{ + FX_SMS(10); +} + +static void fx_sms_r11 (void) +{ + FX_SMS(11); +} + +static void fx_sms_r12 (void) +{ + FX_SMS(12); +} + +static void fx_sms_r13 (void) +{ + FX_SMS(13); +} + +static void fx_sms_r14 (void) +{ + FX_SMS(14); +} + +static void fx_sms_r15 (void) +{ + 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 void fx_from_r0 (void) +{ + FX_FROM(0); +} + +static void fx_from_r1 (void) +{ + FX_FROM(1); +} + +static void fx_from_r2 (void) +{ + FX_FROM(2); +} + +static void fx_from_r3 (void) +{ + FX_FROM(3); +} + +static void fx_from_r4 (void) +{ + FX_FROM(4); +} + +static void fx_from_r5 (void) +{ + FX_FROM(5); +} + +static void fx_from_r6 (void) +{ + FX_FROM(6); +} + +static void fx_from_r7 (void) +{ + FX_FROM(7); +} + +static void fx_from_r8 (void) +{ + FX_FROM(8); +} + +static void fx_from_r9 (void) +{ + FX_FROM(9); +} + +static void fx_from_r10 (void) +{ + FX_FROM(10); +} + +static void fx_from_r11 (void) +{ + FX_FROM(11); +} + +static void fx_from_r12 (void) +{ + FX_FROM(12); +} + +static void fx_from_r13 (void) +{ + FX_FROM(13); +} + +static void fx_from_r14 (void) +{ + FX_FROM(14); +} + +static void fx_from_r15 (void) +{ + FX_FROM(15); +} + +// c0 - hib - move high-byte to low-byte +static void fx_hib (void) +{ + 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 void fx_or_r1 (void) +{ + FX_OR(1); +} + +static void fx_or_r2 (void) +{ + FX_OR(2); +} + +static void fx_or_r3 (void) +{ + FX_OR(3); +} + +static void fx_or_r4 (void) +{ + FX_OR(4); +} + +static void fx_or_r5 (void) +{ + FX_OR(5); +} + +static void fx_or_r6 (void) +{ + FX_OR(6); +} + +static void fx_or_r7 (void) +{ + FX_OR(7); +} + +static void fx_or_r8 (void) +{ + FX_OR(8); +} + +static void fx_or_r9 (void) +{ + FX_OR(9); +} + +static void fx_or_r10 (void) +{ + FX_OR(10); +} + +static void fx_or_r11 (void) +{ + FX_OR(11); +} + +static void fx_or_r12 (void) +{ + FX_OR(12); +} + +static void fx_or_r13 (void) +{ + FX_OR(13); +} + +static void fx_or_r14 (void) +{ + FX_OR(14); +} + +static void fx_or_r15 (void) +{ + 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 void fx_xor_r1 (void) +{ + FX_XOR(1); +} + +static void fx_xor_r2 (void) +{ + FX_XOR(2); +} + +static void fx_xor_r3 (void) +{ + FX_XOR(3); +} + +static void fx_xor_r4 (void) +{ + FX_XOR(4); +} + +static void fx_xor_r5 (void) +{ + FX_XOR(5); +} + +static void fx_xor_r6 (void) +{ + FX_XOR(6); +} + +static void fx_xor_r7 (void) +{ + FX_XOR(7); +} + +static void fx_xor_r8 (void) +{ + FX_XOR(8); +} + +static void fx_xor_r9 (void) +{ + FX_XOR(9); +} + +static void fx_xor_r10 (void) +{ + FX_XOR(10); +} + +static void fx_xor_r11 (void) +{ + FX_XOR(11); +} + +static void fx_xor_r12 (void) +{ + FX_XOR(12); +} + +static void fx_xor_r13 (void) +{ + FX_XOR(13); +} + +static void fx_xor_r14 (void) +{ + FX_XOR(14); +} + +static void fx_xor_r15 (void) +{ + 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 void fx_or_i1 (void) +{ + FX_OR_I(1); +} + +static void fx_or_i2 (void) +{ + FX_OR_I(2); +} + +static void fx_or_i3 (void) +{ + FX_OR_I(3); +} + +static void fx_or_i4 (void) +{ + FX_OR_I(4); +} + +static void fx_or_i5 (void) +{ + FX_OR_I(5); +} + +static void fx_or_i6 (void) +{ + FX_OR_I(6); +} + +static void fx_or_i7 (void) +{ + FX_OR_I(7); +} + +static void fx_or_i8 (void) +{ + FX_OR_I(8); +} + +static void fx_or_i9 (void) +{ + FX_OR_I(9); +} + +static void fx_or_i10 (void) +{ + FX_OR_I(10); +} + +static void fx_or_i11 (void) +{ + FX_OR_I(11); +} + +static void fx_or_i12 (void) +{ + FX_OR_I(12); +} + +static void fx_or_i13 (void) +{ + FX_OR_I(13); +} + +static void fx_or_i14 (void) +{ + FX_OR_I(14); +} + +static void fx_or_i15 (void) +{ + 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 void fx_xor_i1 (void) +{ + FX_XOR_I(1); +} + +static void fx_xor_i2 (void) +{ + FX_XOR_I(2); +} + +static void fx_xor_i3 (void) +{ + FX_XOR_I(3); +} + +static void fx_xor_i4 (void) +{ + FX_XOR_I(4); +} + +static void fx_xor_i5 (void) +{ + FX_XOR_I(5); +} + +static void fx_xor_i6 (void) +{ + FX_XOR_I(6); +} + +static void fx_xor_i7 (void) +{ + FX_XOR_I(7); +} + +static void fx_xor_i8 (void) +{ + FX_XOR_I(8); +} + +static void fx_xor_i9 (void) +{ + FX_XOR_I(9); +} + +static void fx_xor_i10 (void) +{ + FX_XOR_I(10); +} + +static void fx_xor_i11 (void) +{ + FX_XOR_I(11); +} + +static void fx_xor_i12 (void) +{ + FX_XOR_I(12); +} + +static void fx_xor_i13 (void) +{ + FX_XOR_I(13); +} + +static void fx_xor_i14 (void) +{ + FX_XOR_I(14); +} + +static void fx_xor_i15 (void) +{ + 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 void fx_inc_r0 (void) +{ + FX_INC(0); +} + +static void fx_inc_r1 (void) +{ + FX_INC(1); +} + +static void fx_inc_r2 (void) +{ + FX_INC(2); +} + +static void fx_inc_r3 (void) +{ + FX_INC(3); +} + +static void fx_inc_r4 (void) +{ + FX_INC(4); +} + +static void fx_inc_r5 (void) +{ + FX_INC(5); +} + +static void fx_inc_r6 (void) +{ + FX_INC(6); +} + +static void fx_inc_r7 (void) +{ + FX_INC(7); +} + +static void fx_inc_r8 (void) +{ + FX_INC(8); +} + +static void fx_inc_r9 (void) +{ + FX_INC(9); +} + +static void fx_inc_r10 (void) +{ + FX_INC(10); +} + +static void fx_inc_r11 (void) +{ + FX_INC(11); +} + +static void fx_inc_r12 (void) +{ + FX_INC(12); +} + +static void fx_inc_r13 (void) +{ + FX_INC(13); +} + +static void fx_inc_r14 (void) +{ + FX_INC(14); + READR14; +} + +// df - getc - transfer ROM buffer to color register +static void fx_getc (void) +{ +#ifndef FX_DO_ROMBUFFER + uint8 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 void fx_ramb (void) +{ + GSU.vRamBankReg = SREG & (FX_RAM_BANKS - 1); + GSU.pvRamBank = GSU.apvRamBank[GSU.vRamBankReg & 0x3]; + CLRFLAGS; + R15++; +} + +// df (ALT3) - romb - set current ROM bank +static void fx_romb (void) +{ + 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 void fx_dec_r0 (void) +{ + FX_DEC(0); +} + +static void fx_dec_r1 (void) +{ + FX_DEC(1); +} + +static void fx_dec_r2 (void) +{ + FX_DEC(2); +} + +static void fx_dec_r3 (void) +{ + FX_DEC(3); +} + +static void fx_dec_r4 (void) +{ + FX_DEC(4); +} + +static void fx_dec_r5 (void) +{ + FX_DEC(5); +} + +static void fx_dec_r6 (void) +{ + FX_DEC(6); +} + +static void fx_dec_r7 (void) +{ + FX_DEC(7); +} + +static void fx_dec_r8 (void) +{ + FX_DEC(8); +} + +static void fx_dec_r9 (void) +{ + FX_DEC(9); +} + +static void fx_dec_r10 (void) +{ + FX_DEC(10); +} + +static void fx_dec_r11 (void) +{ + FX_DEC(11); +} + +static void fx_dec_r12 (void) +{ + FX_DEC(12); +} + +static void fx_dec_r13 (void) +{ + FX_DEC(13); +} + +static void fx_dec_r14 (void) +{ + FX_DEC(14); + READR14; +} + +// ef - getb - get byte from ROM at address R14 +static void fx_getb (void) +{ + 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 void fx_getbh (void) +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + uint32 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 void fx_getbl (void) +{ + uint32 v; +#ifndef FX_DO_ROMBUFFER + uint32 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 void fx_getbs (void) +{ + 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 void fx_iwt_r0 (void) +{ + FX_IWT(0); +} + +static void fx_iwt_r1 (void) +{ + FX_IWT(1); +} + +static void fx_iwt_r2 (void) +{ + FX_IWT(2); +} + +static void fx_iwt_r3 (void) +{ + FX_IWT(3); +} + +static void fx_iwt_r4 (void) +{ + FX_IWT(4); +} + +static void fx_iwt_r5 (void) +{ + FX_IWT(5); +} + +static void fx_iwt_r6 (void) +{ + FX_IWT(6); +} + +static void fx_iwt_r7 (void) +{ + FX_IWT(7); +} + +static void fx_iwt_r8 (void) +{ + FX_IWT(8); +} + +static void fx_iwt_r9 (void) +{ + FX_IWT(9); +} + +static void fx_iwt_r10 (void) +{ + FX_IWT(10); +} + +static void fx_iwt_r11 (void) +{ + FX_IWT(11); +} + +static void fx_iwt_r12 (void) +{ + FX_IWT(12); +} + +static void fx_iwt_r13 (void) +{ + FX_IWT(13); +} + +static void fx_iwt_r14 (void) +{ + FX_IWT(14); + READR14; +} + +static void fx_iwt_r15 (void) +{ + 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 void fx_lm_r0 (void) +{ + FX_LM(0); +} + +static void fx_lm_r1 (void) +{ + FX_LM(1); +} + +static void fx_lm_r2 (void) +{ + FX_LM(2); +} + +static void fx_lm_r3 (void) +{ + FX_LM(3); +} + +static void fx_lm_r4 (void) +{ + FX_LM(4); +} + +static void fx_lm_r5 (void) +{ + FX_LM(5); +} + +static void fx_lm_r6 (void) +{ + FX_LM(6); +} + +static void fx_lm_r7 (void) +{ + FX_LM(7); +} + +static void fx_lm_r8 (void) +{ + FX_LM(8); +} + +static void fx_lm_r9 (void) +{ + FX_LM(9); +} + +static void fx_lm_r10 (void) +{ + FX_LM(10); +} + +static void fx_lm_r11 (void) +{ + FX_LM(11); +} + +static void fx_lm_r12 (void) +{ + FX_LM(12); +} + +static void fx_lm_r13 (void) +{ + FX_LM(13); +} + +static void fx_lm_r14 (void) +{ + FX_LM(14); + READR14; +} + +static void fx_lm_r15 (void) +{ + FX_LM(15); +} + +// f0-ff (ALT2) - sm (xx), rn - store word in RAM +// XXX: 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 void fx_sm_r0 (void) +{ + FX_SM(0); +} + +static void fx_sm_r1 (void) +{ + FX_SM(1); +} + +static void fx_sm_r2 (void) +{ + FX_SM(2); +} + +static void fx_sm_r3 (void) +{ + FX_SM(3); +} + +static void fx_sm_r4 (void) +{ + FX_SM(4); +} + +static void fx_sm_r5 (void) +{ + FX_SM(5); +} + +static void fx_sm_r6 (void) +{ + FX_SM(6); +} + +static void fx_sm_r7 (void) +{ + FX_SM(7); +} + +static void fx_sm_r8 (void) +{ + FX_SM(8); +} + +static void fx_sm_r9 (void) +{ + FX_SM(9); +} + +static void fx_sm_r10 (void) +{ + FX_SM(10); +} + +static void fx_sm_r11 (void) +{ + FX_SM(11); +} + +static void fx_sm_r12 (void) +{ + FX_SM(12); +} + +static void fx_sm_r13 (void) +{ + FX_SM(13); +} + +static void fx_sm_r14 (void) +{ + FX_SM(14); +} + +static void fx_sm_r15 (void) +{ + FX_SM(15); +} + +// GSU executions functions + +uint32 fx_run (uint32 nInstructions) +{ + GSU.vCounter = nInstructions; + READR14; + while (TF(G) && (GSU.vCounter-- > 0)) + FX_STEP; +#if 0 +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15 - 1) | (USEX8(GSU.vPrgBankReg) << 16); +#endif +#endif + + return (nInstructions - GSU.vInstCount); +} + +/* +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; + } + } + +#if 0 +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15 - 1) | (USEX8(GSU.vPrgBankReg) << 16); +#endif +#endif + + return (vCounter); +} +*/ + +/* +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; + } + +#if 0 +#ifndef FX_ADDRESS_CHECK + GSU.vPipeAdr = USEX16(R15 - 1) | (USEX8(GSU.vPrgBankReg) << 16); +#endif +#endif + + return (vCounter); +} +*/ + +// Special table for the different plot configurations + +void (*fx_PlotTable[]) (void) = +{ + &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 + +void (*fx_OpcodeTable[]) (void) = +{ + // 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/fxinst.h b/fxinst.h new file mode 100644 index 00000000..e1c649a3 --- /dev/null +++ b/fxinst.h @@ -0,0 +1,546 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _FXINST_H_ +#define _FXINST_H_ + +#ifndef ZSNES_FX + +/* + * FxChip(GSU) register space specification + * (Register address space 3000-32ff) + * + * The 16 generic 16 bit registers: + * (Some have a special function in special circumstances) + * 3000 - R0 default source/destination register + * 3002 - R1 pixel plot X position register + * 3004 - R2 pixel plot Y position register + * 3006 - R3 + * 3008 - R4 lower 16 bit result of lmult + * 300a - R5 + * 300c - R6 multiplier for fmult and lmult + * 300e - R7 fixed point texel X position for merge + * 3010 - R8 fixed point texel Y position for merge + * 3012 - R9 + * 3014 - R10 + * 3016 - R11 return address set by link + * 3018 - R12 loop counter + * 301a - R13 loop point address + * 301c - R14 rom address for getb, getbh, getbl, getbs + * 301e - R15 program counter + * + * 3020-302f - unused + * + * Other internal registers + * 3030 - SFR status flag register (16bit) + * 3032 - unused + * 3033 - BRAMR Backup RAM register (8bit) + * 3034 - PBR program bank register (8bit) + * 3035 - unused + * 3036 - ROMBR rom bank register (8bit) + * 3037 - CFGR control flags register (8bit) + * 3038 - SCBR screen base register (8bit) + * 3039 - CLSR clock speed register (8bit) + * 303a - SCMR screen mode register (8bit) + * 303b - VCR version code register (8bit) (read only) + * 303c - RAMBR ram bank register (8bit) + * 303d - unused + * 303e - CBR cache base register (16bit) + * + * 3040-30ff - unused + * + * 3100-32ff - CACHERAM 512 bytes of GSU cache memory + * + * SFR status flag register bits: + * 0 - + * 1 Z Zero flag + * 2 CY Carry flag + * 3 S Sign flag + * 4 OV Overflow flag + * 5 G Go flag (set to 1 when the GSU is running) + * 6 R Set to 1 when reading ROM using R14 address + * 7 - + * 8 ALT1 Mode set-up flag for the next instruction + * 9 ALT2 Mode set-up flag for the next instruction + * 10 IL Immediate lower 8-bit flag + * 11 IH Immediate higher 8-bit flag + * 12 B Set to 1 when the WITH instruction is executed + * 13 - + * 14 - + * 15 IRQ Set to 1 when GSU caused an interrupt + * Set to 0 when read by 658c16 + * + * BRAMR = 0, BackupRAM is disabled + * BRAMR = 1, BackupRAM is enabled + * + * CFGR control flags register bits: + * 0 - + * 1 - + * 2 - + * 3 - + * 4 - + * 5 MS0 Multiplier speed, 0=standard, 1=high speed + * 6 - + * 7 IRQ Set to 1 when GSU interrupt request is masked + * + * CLSR clock speed register bits: + * 0 CLSR clock speed, 0 = 10.7Mhz, 1 = 21.4Mhz + * + * SCMR screen mode register bits: + * 0 MD0 color depth mode bit 0 + * 1 MD1 color depth mode bit 1 + * 2 HT0 screen height bit 1 + * 3 RAN RAM access control + * 4 RON ROM access control + * 5 HT1 screen height bit 2 + * 6 - + * 7 - + * + * RON = 0 SNES CPU has ROM access + * RON = 1 GSU has ROM access + * + * RAN = 0 SNES has game pak RAM access + * RAN = 1 GSU has game pak RAM access + * + * HT1 HT0 Screen height mode + * 0 0 128 pixels high + * 0 1 160 pixels high + * 1 0 192 pixels high + * 1 1 OBJ mode + * + * MD1 MD0 Color depth mode + * 0 0 4 color mode + * 0 1 16 color mode + * 1 0 not used + * 1 1 256 color mode + * + * CBR cache base register bits: + * 15-4 Specify base address for data to cache from ROM or RAM + * 3-0 Are 0 when address is read + * + * Write access to the program counter (301e) from + * the SNES-CPU will start the GSU, and it will not + * stop until it reaches a stop instruction. + * + */ + +// Number of banks in GSU RAM +#define FX_RAM_BANKS 4 + +// Emulate proper R14 ROM access (slower, but safer) +#define FX_DO_ROMBUFFER + +// Address checking (definately slow) +//#define FX_ADDRESS_CHECK + +struct FxRegs_s +{ + // FxChip registers + uint32 avReg[16]; // 16 Generic registers + uint32 vColorReg; // Internal color register + uint32 vPlotOptionReg; // Plot option register + uint32 vStatusReg; // Status register + uint32 vPrgBankReg; // Program bank index register + uint32 vRomBankReg; // Rom bank index register + uint32 vRamBankReg; // Ram bank index register + uint32 vCacheBaseReg; // Cache base address register + uint32 vCacheFlags; // Saying what parts of the cache was written to + uint32 vLastRamAdr; // Last RAM address accessed + uint32 *pvDreg; // Pointer to current destination register + uint32 *pvSreg; // Pointer to current source register + uint8 vRomBuffer; // Current byte read by R14 + uint8 vPipe; // Instructionset pipe + uint32 vPipeAdr; // The address of where the pipe was read from + + // Status register optimization stuff + uint32 vSign; // v & 0x8000 + uint32 vZero; // v == 0 + uint32 vCarry; // a value of 1 or 0 + int32 vOverflow; // (v >= 0x8000 || v < -0x8000) + + // Other emulator variables + int32 vErrorCode; + uint32 vIllegalAddress; + + uint8 bBreakPoint; + uint32 vBreakPoint; + uint32 vStepPoint; + + uint8 *pvRegisters; // 768 bytes located in the memory at address 0x3000 + uint32 nRamBanks; // Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!) + uint8 *pvRam; // Pointer to FxRam + uint32 nRomBanks; // Number of 32kb-banks in Cart-ROM + uint8 *pvRom; // Pointer to Cart-ROM + + uint32 vMode; // Color depth/mode + uint32 vPrevMode; // Previous depth + uint8 *pvScreenBase; + uint8 *apvScreen[32]; // Pointer to each of the 32 screen colums + int32 x[32]; + uint32 vScreenHeight; // 128, 160, 192 or 256 (could be overriden by cmode) + uint32 vScreenRealHeight; // 128, 160, 192 or 256 + uint32 vPrevScreenHeight; + uint32 vScreenSize; + void (*pfPlot) (void); + void (*pfRpix) (void); + + uint8 *pvRamBank; // Pointer to current RAM-bank + uint8 *pvRomBank; // Pointer to current ROM-bank + uint8 *pvPrgBank; // Pointer to current program ROM-bank + + uint8 *apvRamBank[FX_RAM_BANKS]; // Ram bank table (max 256kb) + uint8 *apvRomBank[256]; // Rom bank table + + uint8 bCacheActive; + uint8 *pvCache; // Pointer to the GSU cache + uint8 avCacheBackup[512]; // Backup of ROM when the cache has replaced it + uint32 vCounter; + uint32 vInstCount; + uint32 vSCBRDirty; // If SCBR is written, our cached screen pointers need updating + + uint8 *avRegAddr; // To reference avReg in snapshot.cpp +}; + +extern struct FxRegs_s GSU; + +// GSU registers +#define GSU_R0 0x000 +#define GSU_R1 0x002 +#define GSU_R2 0x004 +#define GSU_R3 0x006 +#define GSU_R4 0x008 +#define GSU_R5 0x00a +#define GSU_R6 0x00c +#define GSU_R7 0x00e +#define GSU_R8 0x010 +#define GSU_R9 0x012 +#define GSU_R10 0x014 +#define GSU_R11 0x016 +#define GSU_R12 0x018 +#define GSU_R13 0x01a +#define GSU_R14 0x01c +#define GSU_R15 0x01e +#define GSU_SFR 0x030 +#define GSU_BRAMR 0x033 +#define GSU_PBR 0x034 +#define GSU_ROMBR 0x036 +#define GSU_CFGR 0x037 +#define GSU_SCBR 0x038 +#define GSU_CLSR 0x039 +#define GSU_SCMR 0x03a +#define GSU_VCR 0x03b +#define GSU_RAMBR 0x03c +#define GSU_CBR 0x03e +#define GSU_CACHERAM 0x100 + +// SFR flags +#define FLG_Z (1 << 1) +#define FLG_CY (1 << 2) +#define FLG_S (1 << 3) +#define FLG_OV (1 << 4) +#define FLG_G (1 << 5) +#define FLG_R (1 << 6) +#define FLG_ALT1 (1 << 8) +#define FLG_ALT2 (1 << 9) +#define FLG_IL (1 << 10) +#define FLG_IH (1 << 11) +#define FLG_B (1 << 12) +#define FLG_IRQ (1 << 15) + +// Test flag +#define TF(a) (GSU.vStatusReg & FLG_##a) +#define CF(a) (GSU.vStatusReg &= ~FLG_##a) +#define SF(a) (GSU.vStatusReg |= FLG_##a) + +// Test and set flag if condition, clear if not +#define TS(a, b) GSU.vStatusReg = ((GSU.vStatusReg & (~FLG_##a)) | ((!!(##b)) * FLG_##a)) + +// Testing ALT1 & ALT2 bits +#define ALT0 (!TF(ALT1) && !TF(ALT2)) +#define ALT1 ( TF(ALT1) && !TF(ALT2)) +#define ALT2 (!TF(ALT1) && TF(ALT2)) +#define ALT3 ( TF(ALT1) && TF(ALT2)) + +// Sign extend from 8/16 bit to 32 bit +#define SEX8(a) ((int32) ((int8) (a))) +#define SEX16(a) ((int32) ((int16) (a))) + +// Unsign extend from 8/16 bit to 32 bit +#define USEX8(a) ((uint32) ((uint8) (a))) +#define USEX16(a) ((uint32) ((uint16) (a))) +#define SUSEX16(a) ((int32) ((uint16) (a))) + +// Set/Clr Sign and Zero flag +#define TSZ(num) TS(S, ((num) & 0x8000)); TS(Z, (!USEX16(num))) + +// Clear flags +#define CLRFLAGS GSU.vStatusReg &= ~(FLG_ALT1 | FLG_ALT2 | FLG_B); GSU.pvDreg = GSU.pvSreg = &R0 + +// Read current RAM-Bank +#define RAM(adr) GSU.pvRamBank[USEX16(adr)] + +// Read current ROM-Bank +#define ROM(idx) GSU.pvRomBank[USEX16(idx)] + +// Access the current value in the pipe +#define PIPE GSU.vPipe + +// Access data in the current program bank +#define PRGBANK(idx) GSU.pvPrgBank[USEX16(idx)] + +// Update pipe from ROM +#if 0 +#define FETCHPIPE { PIPE = PRGBANK(R15); GSU.vPipeAdr = (GSU.vPrgBankReg << 16) + R15; } +#else +#define FETCHPIPE { PIPE = PRGBANK(R15); } +#endif + +// ABS +#define ABS(x) ((x) < 0 ? -(x) : (x)) + +// Access source register +#define SREG (*GSU.pvSreg) + +// Access destination register +#define DREG (*GSU.pvDreg) + +#ifndef FX_DO_ROMBUFFER + +// Don't read R14 +#define READR14 + +// Don't test and/or read R14 +#define TESTR14 + +#else + +// Read R14 +#define READR14 GSU.vRomBuffer = ROM(R14) + +// Test and/or read R14 +#define TESTR14 if (GSU.pvDreg == &R14) READR14 + +#endif + +// Access to registers +#define R0 GSU.avReg[0] +#define R1 GSU.avReg[1] +#define R2 GSU.avReg[2] +#define R3 GSU.avReg[3] +#define R4 GSU.avReg[4] +#define R5 GSU.avReg[5] +#define R6 GSU.avReg[6] +#define R7 GSU.avReg[7] +#define R8 GSU.avReg[8] +#define R9 GSU.avReg[9] +#define R10 GSU.avReg[10] +#define R11 GSU.avReg[11] +#define R12 GSU.avReg[12] +#define R13 GSU.avReg[13] +#define R14 GSU.avReg[14] +#define R15 GSU.avReg[15] +#define SFR GSU.vStatusReg +#define PBR GSU.vPrgBankReg +#define ROMBR GSU.vRomBankReg +#define RAMBR GSU.vRamBankReg +#define CBR GSU.vCacheBaseReg +#define SCBR USEX8(GSU.pvRegisters[GSU_SCBR]) +#define SCMR USEX8(GSU.pvRegisters[GSU_SCMR]) +#define COLR GSU.vColorReg +#define POR GSU.vPlotOptionReg +#define BRAMR USEX8(GSU.pvRegisters[GSU_BRAMR]) +#define VCR USEX8(GSU.pvRegisters[GSU_VCR]) +#define CFGR USEX8(GSU.pvRegisters[GSU_CFGR]) +#define CLSR USEX8(GSU.pvRegisters[GSU_CLSR]) + +// Execute instruction from the pipe, and fetch next byte to the pipe +#define FX_STEP \ +{ \ + uint32 vOpcode = (uint32) PIPE; \ + FETCHPIPE; \ + (*fx_OpcodeTable[(GSU.vStatusReg & 0x300) | vOpcode])(); \ +} + +extern void (*fx_PlotTable[]) (void); +extern void (*fx_OpcodeTable[]) (void); + +// Set this define if branches are relative to the instruction in the delay slot (I think they are) +#define BRANCH_DELAY_RELATIVE + +#endif + +#endif diff --git a/getset.h b/getset.h new file mode 100644 index 00000000..6d2b6459 --- /dev/null +++ b/getset.h @@ -0,0 +1,904 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _GETSET_H_ +#define _GETSET_H_ + +#include "cpuexec.h" +#include "dsp.h" +#include "sa1.h" +#include "spc7110.h" +#include "c4.h" +#include "obc1.h" +#include "seta.h" +#include "bsx.h" + +extern uint8 OpenBus; + +inline uint8 S9xGetByte (uint32 Address) +{ + int block; + uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; + + if (!CPU.InDMAorHDMA) + CPU.Cycles += Memory.MemorySpeed[block]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + #ifdef CPU_SHUTDOWN + if (Memory.BlockIsRAM[block]) + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; + #endif + return (*(GetAddress + (Address & 0xffff))); + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_CPU: + return (S9xGetCPU(Address & 0xffff)); + + case CMemory::MAP_PPU: + if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) + return (OpenBus); + return (S9xGetPPU(Address & 0xffff)); + + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + // Address & 0x7fff : offset into bank + // Address & 0xff0000 : bank + // bank >> 1 | offset : SRAM address, unbound + // unbound & SRAMMask : SRAM offset + return (*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))); + + case CMemory::MAP_LOROM_SRAM_B: + return (*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))); + + case CMemory::MAP_HIROM_SRAM: + case CMemory::MAP_RONLY_SRAM: + return (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))); + + case CMemory::MAP_BWRAM: + return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); + + case CMemory::MAP_DSP: + return (S9xGetDSP(Address & 0xffff)); + + case CMemory::MAP_SPC7110_ROM: + return (S9xGetSPC7110Byte(Address)); + + case CMemory::MAP_SPC7110_DRAM: + return (S9xGetSPC7110(0x4800)); + + case CMemory::MAP_C4: + return (S9xGetC4(Address & 0xffff)); + + case CMemory::MAP_OBC_RAM: + return (S9xGetOBC1(Address & 0xffff)); + + case CMemory::MAP_SETA_DSP: + return (S9xGetSetaDSP(Address)); + + case CMemory::MAP_SETA_RISC: + return (S9xGetST018(Address)); + + case CMemory::MAP_BSX: + return (S9xGetBSX(Address)); + + case CMemory::MAP_NONE: + default: + return (OpenBus); + } +} + +inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE) +{ + uint32 mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff)); + if ((Address & mask) == mask) + { + PC_t a; + + OpenBus = S9xGetByte(Address); + + switch (w) + { + case WRAP_PAGE: + a.xPBPC = Address; + a.B.xPCl++; + return (OpenBus | (S9xGetByte(a.xPBPC) << 8)); + + case WRAP_BANK: + a.xPBPC = Address; + a.W.xPC++; + return (OpenBus | (S9xGetByte(a.xPBPC) << 8)); + + case WRAP_NONE: + default: + return (OpenBus | (S9xGetByte(Address + 1) << 8)); + } + } + + int block; + uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; + + if (!CPU.InDMAorHDMA) + CPU.Cycles += (Memory.MemorySpeed[block] << 1); + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + #ifdef CPU_SHUTDOWN + if (Memory.BlockIsRAM[block]) + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; + #endif + return (READ_WORD(GetAddress + (Address & 0xffff))); + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_CPU: + return (S9xGetCPU(Address & 0xffff) | (S9xGetCPU((Address + 1) & 0xffff) << 8)); + + case CMemory::MAP_PPU: + if (CPU.InDMAorHDMA) + { + OpenBus = S9xGetByte(Address); + return (OpenBus | (S9xGetByte(Address + 1) << 8)); + } + + return (S9xGetPPU(Address & 0xffff) | (S9xGetPPU((Address + 1) & 0xffff) << 8)); + + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + if (Memory.SRAMMask >= MEMMAP_MASK) + return (READ_WORD(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))); + else + return ((*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))) | + ((*(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask))) << 8)); + + case CMemory::MAP_LOROM_SRAM_B: + if (Multi.sramMaskB >= MEMMAP_MASK) + return (READ_WORD(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))); + else + return ((*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))) | + ((*(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB))) << 8)); + + case CMemory::MAP_HIROM_SRAM: + case CMemory::MAP_RONLY_SRAM: + if (Memory.SRAMMask >= MEMMAP_MASK) + return (READ_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))); + else + return ((*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) | + (*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8))); + + case CMemory::MAP_BWRAM: + return (READ_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); + + case CMemory::MAP_DSP: + return (S9xGetDSP(Address & 0xffff) | (S9xGetDSP((Address + 1) & 0xffff) << 8)); + + case CMemory::MAP_SPC7110_ROM: + return (S9xGetSPC7110Byte(Address) | (S9xGetSPC7110Byte(Address + 1) << 8)); + + case CMemory::MAP_SPC7110_DRAM: + return (S9xGetSPC7110(0x4800) | (S9xGetSPC7110(0x4800) << 8)); + + case CMemory::MAP_C4: + return (S9xGetC4(Address & 0xffff) | (S9xGetC4((Address + 1) & 0xffff) << 8)); + + case CMemory::MAP_OBC_RAM: + return (S9xGetOBC1(Address & 0xffff) | (S9xGetOBC1((Address + 1) & 0xffff) << 8)); + + case CMemory::MAP_SETA_DSP: + return (S9xGetSetaDSP(Address) | (S9xGetSetaDSP(Address + 1) << 8)); + + case CMemory::MAP_SETA_RISC: + return (S9xGetST018(Address) | (S9xGetST018(Address + 1) << 8)); + + case CMemory::MAP_BSX: + return (S9xGetBSX(Address) | (S9xGetBSX(Address + 1) << 8)); + + case CMemory::MAP_NONE: + default: + return (OpenBus | (OpenBus << 8)); + } +} + +inline void S9xSetByte (uint8 Byte, uint32 Address) +{ +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + int block; + uint8 *SetAddress = Memory.WriteMap[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; + + if (!CPU.InDMAorHDMA) + CPU.Cycles += Memory.MemorySpeed[block]; + + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { + #ifdef CPU_SHUTDOWN + SetAddress += (Address & 0xffff); + *SetAddress = Byte; + + if (Settings.SA1) + { + if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2) + { + SA1.Executing = SA1.S9xOpcodes != NULL; + SA1.WaitCounter = 0; + } + } + #else + *(SetAddress + (Address & 0xffff)) = Byte; + #endif + return; + } + + switch ((pint) SetAddress) + { + case CMemory::MAP_CPU: + S9xSetCPU(Byte, Address & 0xffff); + return; + + case CMemory::MAP_PPU: + if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) + return; + S9xSetPPU(Byte, Address & 0xffff); + return; + + case CMemory::MAP_LOROM_SRAM: + if (Memory.SRAMMask) + { + *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)) = Byte; + CPU.SRAMModified = TRUE; + } + + return; + + case CMemory::MAP_LOROM_SRAM_B: + if (Multi.sramMaskB) + { + *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)) = Byte; + CPU.SRAMModified = TRUE; + } + + return; + + case CMemory::MAP_HIROM_SRAM: + if (Memory.SRAMMask) + { + *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = Byte; + CPU.SRAMModified = TRUE; + } + + return; + + case CMemory::MAP_BWRAM: + *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte; + CPU.SRAMModified = TRUE; + return; + + case CMemory::MAP_SA1RAM: + *(Memory.SRAM + (Address & 0xffff)) = Byte; + SA1.Executing = !SA1.Waiting; + return; + + case CMemory::MAP_DSP: + S9xSetDSP(Byte, Address & 0xffff); + return; + + case CMemory::MAP_C4: + S9xSetC4(Byte, Address & 0xffff); + return; + + case CMemory::MAP_OBC_RAM: + S9xSetOBC1(Byte, Address & 0xffff); + return; + + case CMemory::MAP_SETA_DSP: + S9xSetSetaDSP(Byte, Address); + return; + + case CMemory::MAP_SETA_RISC: + S9xSetST018(Byte, Address); + return; + + case CMemory::MAP_BSX: + S9xSetBSX(Byte, Address); + return; + + case CMemory::MAP_NONE: + default: + return; + } +} + +inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NONE, enum s9xwriteorder_t o = WRITE_01) +{ + uint32 mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff)); + if ((Address & mask) == mask) + { + PC_t a; + + if (!o) + S9xSetByte((uint8) Word, Address); + + switch (w) + { + case WRAP_PAGE: + a.xPBPC = Address; + a.B.xPCl++; + S9xSetByte(Word >> 8, a.xPBPC); + break; + + case WRAP_BANK: + a.xPBPC = Address; + a.W.xPC++; + S9xSetByte(Word >> 8, a.xPBPC); + break; + + case WRAP_NONE: + default: + S9xSetByte(Word >> 8, Address + 1); + break; + } + + if (o) + S9xSetByte((uint8) Word, Address); + + return; + } + +#ifdef CPU_SHUTDOWN + CPU.WaitAddress = 0xffffffff; +#endif + + int block; + uint8 *SetAddress = Memory.WriteMap[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; + + if (!CPU.InDMAorHDMA) + CPU.Cycles += (Memory.MemorySpeed[block] << 1); + + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { + #ifdef CPU_SHUTDOWN + SetAddress += (Address & 0xffff); + WRITE_WORD(SetAddress, Word); + + if (Settings.SA1) + { + if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2) + { + SA1.Executing = SA1.S9xOpcodes != NULL; + SA1.WaitCounter = 0; + } + } + #else + WRITE_WORD(SetAddress + (Address & 0xffff), Word); + #endif + return; + } + + switch ((pint) SetAddress) + { + case CMemory::MAP_CPU: + if (o) + { + S9xSetCPU(Word >> 8, (Address + 1) & 0xffff); + S9xSetCPU((uint8) Word, Address & 0xffff); + } + else + { + S9xSetCPU((uint8) Word, Address & 0xffff); + S9xSetCPU(Word >> 8, (Address + 1) & 0xffff); + } + + return; + + case CMemory::MAP_PPU: + if (CPU.InDMAorHDMA) + { + if ((Address & 0xff00) != 0x2100) + S9xSetPPU((uint8) Word, Address & 0xffff); + if (((Address + 1) & 0xff00) != 0x2100) + S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); + return; + } + + if (o) + { + S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); + S9xSetPPU((uint8) Word, Address & 0xffff); + } + else + { + S9xSetPPU((uint8) Word, Address & 0xffff); + S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); + } + + return; + + case CMemory::MAP_LOROM_SRAM: + if (Memory.SRAMMask) + { + if (Memory.SRAMMask >= MEMMAP_MASK) + WRITE_WORD(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask), Word); + else + { + *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)) = (uint8) Word; + *(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask)) = Word >> 8; + } + + CPU.SRAMModified = TRUE; + } + + return; + + case CMemory::MAP_LOROM_SRAM_B: + if (Multi.sramMaskB) + { + if (Multi.sramMaskB >= MEMMAP_MASK) + WRITE_WORD(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB), Word); + else + { + *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)) = (uint8) Word; + *(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB)) = Word >> 8; + } + + CPU.SRAMModified = TRUE; + } + + return; + + case CMemory::MAP_HIROM_SRAM: + if (Memory.SRAMMask) + { + if (Memory.SRAMMask >= MEMMAP_MASK) + WRITE_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask), Word); + else + { + *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = (uint8) Word; + *(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) = Word >> 8; + } + + CPU.SRAMModified = TRUE; + } + + return; + + case CMemory::MAP_BWRAM: + WRITE_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000), Word); + CPU.SRAMModified = TRUE; + return; + + case CMemory::MAP_SA1RAM: + WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word); + SA1.Executing = !SA1.Waiting; + return; + + case CMemory::MAP_DSP: + if (o) + { + S9xSetDSP(Word >> 8, (Address + 1) & 0xffff); + S9xSetDSP((uint8) Word, Address & 0xffff); + } + else + { + S9xSetDSP((uint8) Word, Address & 0xffff); + S9xSetDSP(Word >> 8, (Address + 1) & 0xffff); + } + + return; + + case CMemory::MAP_C4: + if (o) + { + S9xSetC4(Word >> 8, (Address + 1) & 0xffff); + S9xSetC4((uint8) Word, Address & 0xffff); + } + else + { + S9xSetC4((uint8) Word, Address & 0xffff); + S9xSetC4(Word >> 8, (Address + 1) & 0xffff); + } + + return; + + case CMemory::MAP_OBC_RAM: + if (o) + { + S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff); + S9xSetOBC1((uint8) Word, Address & 0xffff); + } + else + { + S9xSetOBC1((uint8) Word, Address & 0xffff); + S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff); + } + + return; + + case CMemory::MAP_SETA_DSP: + if (o) + { + S9xSetSetaDSP(Word >> 8, Address + 1); + S9xSetSetaDSP((uint8) Word, Address); + } + else + { + S9xSetSetaDSP((uint8) Word, Address); + S9xSetSetaDSP(Word >> 8, Address + 1); + } + + return; + + case CMemory::MAP_SETA_RISC: + if (o) + { + S9xSetST018(Word >> 8, Address + 1); + S9xSetST018((uint8) Word, Address); + } + else + { + S9xSetST018((uint8) Word, Address); + S9xSetST018(Word >> 8, Address + 1); + } + + return; + + case CMemory::MAP_BSX: + if (o) + { + S9xSetBSX(Word >> 8, Address + 1); + S9xSetBSX((uint8) Word, Address); + } + else + { + S9xSetBSX((uint8) Word, Address); + S9xSetBSX(Word >> 8, Address + 1); + } + + return; + + case CMemory::MAP_NONE: + default: + return; + } +} + +inline void S9xSetPCBase (uint32 Address) +{ + Registers.PBPC = Address & 0xffffff; + ICPU.ShiftedPB = Address & 0xff0000; + + int block; + uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; + + CPU.MemSpeed = Memory.MemorySpeed[block]; + CPU.MemSpeedx2 = CPU.MemSpeed << 1; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + CPU.PCBase = GetAddress; + return; + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + CPU.PCBase = NULL; + else + CPU.PCBase = Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask) - (Address & 0xffff); + return; + + case CMemory::MAP_LOROM_SRAM_B: + if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK) + CPU.PCBase = NULL; + else + CPU.PCBase = Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB) - (Address & 0xffff); + return; + + case CMemory::MAP_HIROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + CPU.PCBase = NULL; + else + CPU.PCBase = Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff); + return; + + case CMemory::MAP_BWRAM: + CPU.PCBase = Memory.BWRAM - 0x6000 - (Address & 0x8000); + return; + + case CMemory::MAP_SA1RAM: + CPU.PCBase = Memory.SRAM; + return; + + case CMemory::MAP_SPC7110_ROM: + CPU.PCBase = S9xGetBasePointerSPC7110(Address); + return; + + case CMemory::MAP_C4: + CPU.PCBase = S9xGetBasePointerC4(Address & 0xffff); + return; + + case CMemory::MAP_OBC_RAM: + CPU.PCBase = S9xGetBasePointerOBC1(Address & 0xffff); + return; + + case CMemory::MAP_BSX: + CPU.PCBase = S9xGetBasePointerBSX(Address); + return; + + case CMemory::MAP_NONE: + default: + CPU.PCBase = NULL; + return; + } +} + +inline uint8 * S9xGetBasePointer (uint32 Address) +{ + uint8 *GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (GetAddress); + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask) - (Address & 0xffff)); + + case CMemory::MAP_LOROM_SRAM_B: + if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB) - (Address & 0xffff)); + + case CMemory::MAP_HIROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff)); + + case CMemory::MAP_BWRAM: + return (Memory.BWRAM - 0x6000 - (Address & 0x8000)); + + case CMemory::MAP_SA1RAM: + return (Memory.SRAM); + + case CMemory::MAP_SPC7110_ROM: + return (S9xGetBasePointerSPC7110(Address)); + + case CMemory::MAP_C4: + return (S9xGetBasePointerC4(Address & 0xffff)); + + case CMemory::MAP_OBC_RAM: + return (S9xGetBasePointerOBC1(Address & 0xffff)); + + case CMemory::MAP_NONE: + default: + return (NULL); + } +} + +inline uint8 * S9xGetMemPointer (uint32 Address) +{ + uint8 *GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (GetAddress + (Address & 0xffff)); + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)); + + case CMemory::MAP_LOROM_SRAM_B: + if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)); + + case CMemory::MAP_HIROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + return (NULL); + return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)); + + case CMemory::MAP_BWRAM: + return (Memory.BWRAM - 0x6000 + (Address & 0x7fff)); + + case CMemory::MAP_SA1RAM: + return (Memory.SRAM + (Address & 0xffff)); + + case CMemory::MAP_SPC7110_ROM: + return (S9xGetBasePointerSPC7110(Address) + (Address & 0xffff)); + + case CMemory::MAP_C4: + return (S9xGetMemPointerC4(Address & 0xffff)); + + case CMemory::MAP_OBC_RAM: + return (S9xGetMemPointerOBC1(Address & 0xffff)); + + case CMemory::MAP_NONE: + default: + return (NULL); + } +} + +#endif diff --git a/gfx.cpp b/gfx.cpp new file mode 100644 index 00000000..dff2ef20 --- /dev/null +++ b/gfx.cpp @@ -0,0 +1,2391 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "ppu.h" +#include "tile.h" +#include "controls.h" +#include "crosshairs.h" +#include "cheats.h" +#include "movie.h" +#include "screenshot.h" +#include "font.h" +#include "display.h" + +extern struct SCheatData Cheat; +extern struct SLineData LineData[240]; +extern struct SLineMatrixData LineMatrixData[240]; + +void S9xComputeClipWindows (void); + +static int font_width = 8, font_height = 9; + +static void SetupOBJ (void); +static void DrawOBJS (int); +static void DisplayFrameRate (void); +static void DisplayPressedKeys (void); +static void DisplayWatchedAddresses (void); +static void DisplayStringFromBottom (const char *, int, int, bool); +static void DrawBackground (int, uint8, uint8); +static void DrawBackgroundMosaic (int, uint8, uint8); +static void DrawBackgroundOffset (int, uint8, uint8, int); +static void DrawBackgroundOffsetMosaic (int, uint8, uint8, int); +static inline void DrawBackgroundMode7 (int, void (*DrawMath) (uint32, uint32, int), void (*DrawNomath) (uint32, uint32, int), int); +static inline void DrawBackdrop (void); +static inline void RenderScreen (bool8); +static uint16 get_crosshair_color (uint8); + +#define TILE_PLUS(t, x) (((t) & 0xfc00) | ((t + x) & 0x3ff)) + + +bool8 S9xGraphicsInit (void) +{ + S9xInitTileRenderer(); + ZeroMemory(BlackColourMap, 256 * sizeof(uint16)); + +#ifdef GFX_MULTI_FORMAT + if (GFX.BuildPixel == NULL) + S9xSetRenderPixelFormat(RGB565); +#endif + + GFX.DoInterlace = 0; + GFX.InterlaceFrame = 0; + GFX.RealPPL = GFX.Pitch >> 1; + IPPU.OBJChanged = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + Settings.BG_Forced = 0; + S9xFixColourBrightness(); + + GFX.X2 = (uint16 *) malloc(sizeof(uint16) * 0x10000); + GFX.ZERO = (uint16 *) malloc(sizeof(uint16) * 0x10000); + + GFX.ScreenSize = GFX.Pitch / 2 * SNES_HEIGHT_EXTENDED * (Settings.SupportHiRes ? 2 : 1); + GFX.SubScreen = (uint16 *) malloc(GFX.ScreenSize * sizeof(uint16)); + GFX.ZBuffer = (uint8 *) malloc(GFX.ScreenSize); + GFX.SubZBuffer = (uint8 *) malloc(GFX.ScreenSize); + + if (!GFX.X2 || !GFX.ZERO || !GFX.SubScreen || !GFX.ZBuffer || !GFX.SubZBuffer) + { + S9xGraphicsDeinit(); + return (FALSE); + } + + // Lookup table for color addition + ZeroMemory(GFX.X2, 0x10000 * sizeof(uint16)); + for (uint32 r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r << 1; + if (r2 > MAX_RED) + r2 = MAX_RED; + + for (uint32 g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g << 1; + if (g2 > MAX_GREEN) + g2 = MAX_GREEN; + + for (uint32 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); + } + } + } + + // Lookup table for 1/2 color subtraction + ZeroMemory(GFX.ZERO, 0x10000 * sizeof(uint16)); + for (uint32 r = 0; r <= MAX_RED; r++) + { + uint32 r2 = r; + if (r2 & 0x10) + r2 &= ~0x10; + else + r2 = 0; + + for (uint32 g = 0; g <= MAX_GREEN; g++) + { + uint32 g2 = g; + if (g2 & GREEN_HI_BIT) + g2 &= ~GREEN_HI_BIT; + else + g2 = 0; + + for (uint32 b = 0; b <= MAX_BLUE; b++) + { + uint32 b2 = b; + if (b2 & 0x10) + b2 &= ~0x10; + else + b2 = 0; + + 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) +{ + if (GFX.X2) { free(GFX.X2); GFX.X2 = NULL; } + if (GFX.ZERO) { free(GFX.ZERO); GFX.ZERO = NULL; } + if (GFX.SubScreen) { free(GFX.SubScreen); GFX.SubScreen = NULL; } + if (GFX.ZBuffer) { free(GFX.ZBuffer); GFX.ZBuffer = NULL; } + if (GFX.SubZBuffer) { free(GFX.SubZBuffer); GFX.SubZBuffer = NULL; } +} + +void S9xBuildDirectColourMaps (void) +{ + IPPU.XB = mul_brightness[PPU.Brightness]; + + for (uint32 p = 0; p < 8; p++) + for (uint32 c = 0; c < 256; c++) + 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)]); + + IPPU.DirectColourMapsNeedRebuild = FALSE; +} + +void S9xStartScreenRefresh (void) +{ + if (IPPU.RenderThisFrame) + { + if (GFX.DoInterlace && GFX.InterlaceFrame == 0) + GFX.InterlaceFrame = 1; + else + { + if (!S9xInitUpdate()) + { + IPPU.RenderThisFrame = FALSE; + return; + } + + GFX.InterlaceFrame = 0; + if (GFX.DoInterlace) + GFX.DoInterlace--; + + IPPU.MaxBrightness = PPU.Brightness; + + IPPU.PseudoHires = Memory.FillRAM[0x2133] & 8; + if (PPU.BGMode == 5 || PPU.BGMode == 6) + { + IPPU.Interlace = Memory.FillRAM[0x2133] & 1; + IPPU.InterlaceOBJ = Memory.FillRAM[0x2133] & 2; + } + + if (Settings.SupportHiRes && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || IPPU.Interlace || IPPU.InterlaceOBJ)) + { + GFX.RealPPL = GFX.Pitch >> 1; + IPPU.DoubleWidthPixels = TRUE; + IPPU.RenderedScreenWidth = SNES_WIDTH << 1; + if (IPPU.Interlace || IPPU.InterlaceOBJ) + { + GFX.PPL = GFX.RealPPL << 1; + IPPU.DoubleHeightPixels = TRUE; + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + GFX.DoInterlace++; + } + else + { + GFX.PPL = GFX.RealPPL; + IPPU.DoubleHeightPixels = FALSE; + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + } + } + else + { + IPPU.DoubleWidthPixels = FALSE; + IPPU.DoubleHeightPixels = FALSE; + IPPU.RenderedScreenWidth = SNES_WIDTH; + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + #ifdef USE_OPENGL + if (Settings.OpenGLEnable) + GFX.RealPPL = GFX.PPL = SNES_WIDTH; + else + #endif + GFX.RealPPL = GFX.PPL = GFX.Pitch >> 1; + } + + IPPU.RenderedFramesCount++; + } + + PPU.MosaicStart = 0; + PPU.RecomputeClipWindows = TRUE; + IPPU.PreviousLine = IPPU.CurrentLine = 0; + + ZeroMemory(GFX.ZBuffer, GFX.ScreenSize); + ZeroMemory(GFX.SubZBuffer, GFX.ScreenSize); + } + + if (++IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) + { + IPPU.DisplayedRenderedFrameCount = IPPU.RenderedFramesCount; + IPPU.RenderedFramesCount = 0; + IPPU.FrameCount = 0; + } + + if (GFX.InfoStringTimeout > 0 && --GFX.InfoStringTimeout == 0) + GFX.InfoString = NULL; + + IPPU.TotalEmulatedFrames++; +} + +void S9xEndScreenRefresh (void) +{ + if (IPPU.RenderThisFrame) + { + FLUSH_REDRAW(); + + if (GFX.DoInterlace && GFX.InterlaceFrame == 0) + { + S9xControlEOF(); + S9xContinueUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); + } + else + { + if (IPPU.ColorsChanged) + { + uint32 saved = PPU.CGDATA[0]; + IPPU.ColorsChanged = FALSE; + S9xSetPalette(); + PPU.CGDATA[0] = saved; + } + + S9xControlEOF(); + + if (Settings.TakeScreenshot) + S9xDoScreenshot(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); + + if (Settings.AutoDisplayMessages) + S9xDisplayMessages(GFX.Screen, GFX.RealPPL, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, 1); + + S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); + } + } + else + S9xControlEOF(); + + S9xApplyCheats(); + +#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 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; + p->M7HOFS = PPU.M7HOFS; + p->M7VOFS = PPU.M7VOFS; + } + 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; + } + else + { + // if we're not rendering this frame, we still need to update this + // XXX: Check ForceBlank? Or anything else? + if (IPPU.OBJChanged) + SetupOBJ(); + PPU.RangeTimeOver |= GFX.OBJLines[C].RTOFlags; + } +} + +static inline void RenderScreen (bool8 sub) +{ + uint8 BGActive; + int D; + + if (!sub) + { + GFX.S = GFX.Screen; + if (GFX.DoInterlace && GFX.InterlaceFrame) + GFX.S += GFX.RealPPL; + GFX.DB = GFX.ZBuffer; + GFX.Clip = IPPU.Clip[0]; + BGActive = Memory.FillRAM[0x212c] & ~Settings.BG_Forced; + D = 32; + } + else + { + GFX.S = GFX.SubScreen; + GFX.DB = GFX.SubZBuffer; + GFX.Clip = IPPU.Clip[1]; + BGActive = Memory.FillRAM[0x212d] & ~Settings.BG_Forced; + D = (Memory.FillRAM[0x2130] & 2) << 4; // 'do math' depth flag + } + + if (BGActive & 0x10) + { + BG.TileAddress = PPU.OBJNameBase; + BG.NameSelect = PPU.OBJNameSelect; + BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & 0x10); + BG.StartPalette = 128; + S9xSelectTileConverter(4, FALSE, sub, FALSE); + S9xSelectTileRenderers(PPU.BGMode, sub, TRUE); + DrawOBJS(D + 4); + } + + BG.NameSelect = 0; + S9xSelectTileRenderers(PPU.BGMode, sub, FALSE); + + #define DO_BG(n, pal, depth, hires, offset, Zh, Zl, voffoff) \ + if (BGActive & (1 << n)) \ + { \ + BG.StartPalette = pal; \ + BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & (1 << n)); \ + BG.TileSizeH = (!hires && PPU.BG[n].BGSize) ? 16 : 8; \ + BG.TileSizeV = (PPU.BG[n].BGSize) ? 16 : 8; \ + S9xSelectTileConverter(depth, hires, sub, PPU.BGMosaic[n]); \ + \ + if (offset) \ + { \ + BG.OffsetSizeH = (!hires && PPU.BG[2].BGSize) ? 16 : 8; \ + BG.OffsetSizeV = (PPU.BG[2].BGSize) ? 16 : 8; \ + \ + if (PPU.BGMosaic[n] && (hires || PPU.Mosaic > 1)) \ + DrawBackgroundOffsetMosaic(n, D + Zh, D + Zl, voffoff); \ + else \ + DrawBackgroundOffset(n, D + Zh, D + Zl, voffoff); \ + } \ + else \ + { \ + if (PPU.BGMosaic[n] && (hires || PPU.Mosaic > 1)) \ + DrawBackgroundMosaic(n, D + Zh, D + Zl); \ + else \ + DrawBackground(n, D + Zh, D + Zl); \ + } \ + } + + switch (PPU.BGMode) + { + case 0: + DO_BG(0, 0, 2, FALSE, FALSE, 15, 11, 0); + DO_BG(1, 32, 2, FALSE, FALSE, 14, 10, 0); + DO_BG(2, 64, 2, FALSE, FALSE, 7, 3, 0); + DO_BG(3, 96, 2, FALSE, FALSE, 6, 2, 0); + break; + + case 1: + DO_BG(0, 0, 4, FALSE, FALSE, 15, 11, 0); + DO_BG(1, 0, 4, FALSE, FALSE, 14, 10, 0); + DO_BG(2, 0, 2, FALSE, FALSE, (PPU.BG3Priority ? 17 : 7), 3, 0); + break; + + case 2: + DO_BG(0, 0, 4, FALSE, TRUE, 15, 7, 8); + DO_BG(1, 0, 4, FALSE, TRUE, 11, 3, 8); + break; + + case 3: + DO_BG(0, 0, 8, FALSE, FALSE, 15, 7, 0); + DO_BG(1, 0, 4, FALSE, FALSE, 11, 3, 0); + break; + + case 4: + DO_BG(0, 0, 8, FALSE, TRUE, 15, 7, 0); + DO_BG(1, 0, 2, FALSE, TRUE, 11, 3, 0); + break; + + case 5: + DO_BG(0, 0, 4, TRUE, FALSE, 15, 7, 0); + DO_BG(1, 0, 2, TRUE, FALSE, 11, 3, 0); + break; + + case 6: + DO_BG(0, 0, 4, TRUE, TRUE, 15, 7, 8); + break; + + case 7: + if (BGActive & 0x01) + { + BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & 1); + DrawBackgroundMode7(0, GFX.DrawMode7BG1Math, GFX.DrawMode7BG1Nomath, D); + } + + if ((Memory.FillRAM[0x2133] & 0x40) && (BGActive & 0x02)) + { + BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & 2); + DrawBackgroundMode7(1, GFX.DrawMode7BG2Math, GFX.DrawMode7BG2Nomath, D); + } + + break; + } + + #undef DO_BG + + BG.EnableMath = !sub && (Memory.FillRAM[0x2131] & 0x20); + + DrawBackdrop(); +} + +void S9xUpdateScreen (void) +{ + if (IPPU.OBJChanged) + SetupOBJ(); + + // XXX: Check ForceBlank? Or anything else? + PPU.RangeTimeOver |= GFX.OBJLines[GFX.EndY].RTOFlags; + + GFX.StartY = IPPU.PreviousLine; + if ((GFX.EndY = IPPU.CurrentLine - 1) >= PPU.ScreenHeight) + GFX.EndY = PPU.ScreenHeight - 1; + + if (!PPU.ForcedBlanking) + { + // If force blank, may as well completely skip all this. We only did + // the OBJ because (AFAWK) the RTO flags are updated even during force-blank. + + if (PPU.RecomputeClipWindows) + { + S9xComputeClipWindows(); + PPU.RecomputeClipWindows = FALSE; + } + + if (Settings.SupportHiRes) + { + if (!IPPU.DoubleWidthPixels && (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || IPPU.Interlace || IPPU.InterlaceOBJ)) + { + #ifdef USE_OPENGL + if (Settings.OpenGLEnable && GFX.RealPPL == 256) + { + // Have to back out of the speed up hack where the low res. + // SNES image was rendered into a 256x239 sized buffer, + // ignoring the true, larger size of the buffer. + GFX.RealPPL = GFX.Pitch >> 1; + + for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--) + { + register uint16 *p = GFX.Screen + y * GFX.PPL + 255; + register uint16 *q = GFX.Screen + y * GFX.RealPPL + 510; + + for (register int x = 255; x >= 0; x--, p--, q -= 2) + *q = *(q + 1) = *p; + } + + GFX.PPL = GFX.RealPPL; // = GFX.Pitch >> 1 above + } + else + #endif + { + // Have to back out of the regular speed hack + for (register uint32 y = 0; y < GFX.StartY; y++) + { + register uint16 *p = GFX.Screen + y * GFX.PPL + 255; + register uint16 *q = GFX.Screen + y * GFX.PPL + 510; + + for (register int x = 255; x >= 0; x--, p--, q -= 2) + *q = *(q + 1) = *p; + } + } + + IPPU.DoubleWidthPixels = TRUE; + IPPU.RenderedScreenWidth = 512; + } + + if (!IPPU.DoubleHeightPixels && (IPPU.Interlace || IPPU.InterlaceOBJ)) + { + IPPU.DoubleHeightPixels = TRUE; + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + GFX.PPL = GFX.RealPPL << 1; + GFX.DoInterlace = 2; + + for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--) + memmove(GFX.Screen + y * GFX.PPL, GFX.Screen + y * GFX.RealPPL, IPPU.RenderedScreenWidth * sizeof(uint16)); + } + } + + if ((Memory.FillRAM[0x2130] & 0x30) != 0x30 && (Memory.FillRAM[0x2131] & 0x3f)) + GFX.FixedColour = BUILD_PIXEL(IPPU.XB[PPU.FixedColourRed], IPPU.XB[PPU.FixedColourGreen], IPPU.XB[PPU.FixedColourBlue]); + + if (PPU.BGMode == 5 || PPU.BGMode == 6 || IPPU.PseudoHires || + ((Memory.FillRAM[0x2130] & 0x30) != 0x30 && (Memory.FillRAM[0x2130] & 2) && (Memory.FillRAM[0x2131] & 0x3f) && (Memory.FillRAM[0x212d] & 0x1f))) + // If hires (Mode 5/6 or pseudo-hires) or math is to be done + // involving the subscreen, then we need to render the subscreen... + RenderScreen(TRUE); + + RenderScreen(FALSE); + } + else + { + const uint16 black = BUILD_PIXEL(0, 0, 0); + + GFX.S = GFX.Screen + GFX.StartY * GFX.PPL; + if (GFX.DoInterlace && GFX.InterlaceFrame) + GFX.S += GFX.RealPPL; + + for (uint32 l = GFX.StartY; l <= GFX.EndY; l++, GFX.S += GFX.PPL) + for (int x = 0; x < IPPU.RenderedScreenWidth; x++) + GFX.S[x] = black; + } + + IPPU.PreviousLine = IPPU.CurrentLine; +} + +static void SetupOBJ (void) +{ + int SmallWidth, SmallHeight, LargeWidth, LargeHeight; + + switch (PPU.OBJSizeSelect) + { + case 0: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 16; + break; + + case 1: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 32; + break; + + case 2: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 64; + break; + + case 3: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 32; + break; + + case 4: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 64; + break; + + case 5: + default: + SmallWidth = SmallHeight = 32; + LargeWidth = LargeHeight = 64; + break; + + case 6: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = 32; LargeHeight = 64; + break; + + case 7: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = LargeHeight = 32; + break; + } + + int inc = IPPU.InterlaceOBJ ? 2 : 1; + + // OK, we have three cases here. Either there's no priority, priority is + // normal FirstSprite, or priority is FirstSprite+Y. The first two are + // easy, the last is somewhat more ... interesting. So we split them up. + + int Height; + uint8 S; + + if (!PPU.OAMPriorityRotation || !(PPU.OAMFlip & PPU.OAMAddr & 1)) // normal case + { + uint8 LineOBJ[SNES_HEIGHT_EXTENDED]; + ZeroMemory(LineOBJ, sizeof(LineOBJ)); + + for (int i = 0; i < SNES_HEIGHT_EXTENDED; i++) + { + GFX.OBJLines[i].RTOFlags = 0; + GFX.OBJLines[i].Tiles = 34; + for (int j = 0; j < 32; j++) + GFX.OBJLines[i].OBJ[j].Sprite = -1; + } + + uint8 FirstSprite = PPU.FirstSprite; + S = FirstSprite; + + do + { + if (PPU.OBJ[S].Size) + { + GFX.OBJWidths[S] = LargeWidth; + Height = LargeHeight; + } + else + { + GFX.OBJWidths[S] = SmallWidth; + Height = SmallHeight; + } + + int HPos = PPU.OBJ[S].HPos; + if (HPos == -256) + HPos = 0; + + if (HPos > -GFX.OBJWidths[S] && HPos <= 256) + { + if (HPos < 0) + GFX.OBJVisibleTiles[S] = (GFX.OBJWidths[S] + HPos + 7) >> 3; + else + if (HPos + GFX.OBJWidths[S] > 255) + GFX.OBJVisibleTiles[S] = (256 - HPos + 7) >> 3; + else + GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3; + + for (uint8 line = 0, Y = (uint8) (PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line += inc) + { + if (Y >= SNES_HEIGHT_EXTENDED) + continue; + + if (LineOBJ[Y] >= 32) + { + GFX.OBJLines[Y].RTOFlags |= 0x40; + continue; + } + + GFX.OBJLines[Y].Tiles -= GFX.OBJVisibleTiles[S]; + if (GFX.OBJLines[Y].Tiles < 0) + GFX.OBJLines[Y].RTOFlags |= 0x80; + + GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Sprite = S; + if (PPU.OBJ[S].VFlip) + // Yes, Width not Height. It so happens that the + // sprites with H=2*W flip as two WxW sprites. + GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line = line ^ (GFX.OBJWidths[S] - 1); + else + GFX.OBJLines[Y].OBJ[LineOBJ[Y]].Line = line; + + LineOBJ[Y]++; + } + } + + S = (S + 1) & 0x7f; + } while (S != FirstSprite); + + for (int Y = 1; Y < SNES_HEIGHT_EXTENDED; Y++) + GFX.OBJLines[Y].RTOFlags |= GFX.OBJLines[Y - 1].RTOFlags; + } + else // evil FirstSprite+Y case + { + // First, find out which sprites are on which lines + uint8 OBJOnLine[SNES_HEIGHT_EXTENDED][128]; + ZeroMemory(OBJOnLine, sizeof(OBJOnLine)); + + for (S = 0; S < 128; S++) + { + if (PPU.OBJ[S].Size) + { + GFX.OBJWidths[S] = LargeWidth; + Height = LargeHeight; + } + else + { + GFX.OBJWidths[S] = SmallWidth; + Height = SmallHeight; + } + + int HPos = PPU.OBJ[S].HPos; + if (HPos == -256) + HPos = 256; + + if (HPos > -GFX.OBJWidths[S] && HPos <= 256) + { + if (HPos < 0) + GFX.OBJVisibleTiles[S] = (GFX.OBJWidths[S] + HPos + 7) >> 3; + else + if (HPos + GFX.OBJWidths[S] >= 257) + GFX.OBJVisibleTiles[S] = (257 - HPos + 7) >> 3; + else + GFX.OBJVisibleTiles[S] = GFX.OBJWidths[S] >> 3; + + for (uint8 line = 0, Y = (uint8) (PPU.OBJ[S].VPos & 0xff); line < Height; Y++, line += inc) + { + if (Y >= SNES_HEIGHT_EXTENDED) + continue; + + if (PPU.OBJ[S].VFlip) + // Yes, Width not Height. It so happens that the + // sprites with H=2*W flip as two WxW sprites. + OBJOnLine[Y][S] = (line ^ (GFX.OBJWidths[S] - 1)) | 0x80; + else + OBJOnLine[Y][S] = line | 0x80; + } + } + } + + // Now go through and pull out those OBJ that are actually visible. + int j; + for (int Y = 0; Y < SNES_HEIGHT_EXTENDED; Y++) + { + GFX.OBJLines[Y].RTOFlags = Y ? GFX.OBJLines[Y - 1].RTOFlags : 0; + GFX.OBJLines[Y].Tiles = 34; + + uint8 FirstSprite = (PPU.FirstSprite + Y) & 0x7f; + S = FirstSprite; + j = 0; + + do + { + if (OBJOnLine[Y][S]) + { + if (j >= 32) + { + GFX.OBJLines[Y].RTOFlags |= 0x40; + break; + } + + GFX.OBJLines[Y].Tiles -= GFX.OBJVisibleTiles[S]; + if (GFX.OBJLines[Y].Tiles < 0) + GFX.OBJLines[Y].RTOFlags |= 0x80; + GFX.OBJLines[Y].OBJ[j].Sprite = S; + GFX.OBJLines[Y].OBJ[j++].Line = OBJOnLine[Y][S] & ~0x80; + } + + S = (S + 1) & 0x7f; + } while (S != FirstSprite); + + if (j < 32) + GFX.OBJLines[Y].OBJ[j].Sprite = -1; + } + } + + IPPU.OBJChanged = FALSE; +} + +static void DrawOBJS (int D) +{ + void (*DrawTile) (uint32, uint32, uint32, uint32) = NULL; + void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32) = NULL; + + int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + BG.InterlaceLine = GFX.InterlaceFrame ? 8 : 0; + GFX.Z1 = 2; + + for (uint32 Y = GFX.StartY, Offset = Y * GFX.PPL; Y <= GFX.EndY; Y++, Offset += GFX.PPL) + { + int I = 0; + int tiles = GFX.OBJLines[Y].Tiles; + + for (int S = GFX.OBJLines[Y].OBJ[I].Sprite; S >= 0 && I < 32; S = GFX.OBJLines[Y].OBJ[++I].Sprite) + { + tiles += GFX.OBJVisibleTiles[S]; + if (tiles <= 0) + continue; + + int BaseTile = (((GFX.OBJLines[Y].OBJ[I].Line << 1) + (PPU.OBJ[S].Name & 0xf0)) & 0xf0) | (PPU.OBJ[S].Name & 0x100) | (PPU.OBJ[S].Palette << 10); + int TileX = PPU.OBJ[S].Name & 0x0f; + int TileLine = (GFX.OBJLines[Y].OBJ[I].Line & 7) * 8; + if (IPPU.InterlaceOBJ) + TileLine >>= 1; + int TileInc = 1; + + if (PPU.OBJ[S].HFlip) + { + TileX = (TileX + (GFX.OBJWidths[S] >> 3) - 1) & 0x0f; + BaseTile |= H_FLIP; + TileInc = -1; + } + + GFX.Z2 = D + PPU.OBJ[S].Priority * 4; + + int DrawMode = 3; + int clip = 0, next_clip = -1000; + int X = PPU.OBJ[S].HPos; + if (X == -256) + X = 256; + + for (int t = tiles, O = Offset + X * PixWidth; X <= 256 && X < PPU.OBJ[S].HPos + GFX.OBJWidths[S]; TileX = (TileX + TileInc) & 0x0f, X += 8, O += 8 * PixWidth) + { + if (X < -7 || --t < 0 || X == 256) + continue; + + for (int x = X; x < X + 8;) + { + if (x >= next_clip) + { + for (; clip < GFX.Clip[4].Count && GFX.Clip[4].Left[clip] <= x; clip++) ; + if (clip == 0 || x >= GFX.Clip[4].Right[clip - 1]) + { + DrawMode = 0; + next_clip = ((clip < GFX.Clip[4].Count) ? GFX.Clip[4].Left[clip] : 1000); + } + else + { + DrawMode = GFX.Clip[4].DrawMode[clip - 1]; + next_clip = GFX.Clip[4].Right[clip - 1]; + GFX.ClipColors = !(DrawMode & 1); + + if (BG.EnableMath && (PPU.OBJ[S].Palette & 4) && (DrawMode & 2)) + { + DrawTile = GFX.DrawTileMath; + DrawClippedTile = GFX.DrawClippedTileMath; + } + else + { + DrawTile = GFX.DrawTileNomath; + DrawClippedTile = GFX.DrawClippedTileNomath; + } + } + } + + if (x == X && x + 8 < next_clip) + { + if (DrawMode) + DrawTile(BaseTile | TileX, O, TileLine, 1); + x += 8; + } + else + { + int w = (next_clip <= X + 8) ? next_clip - x : X + 8 - x; + if (DrawMode) + DrawClippedTile(BaseTile | TileX, O, x - X, w, TileLine, 1); + x += w; + } + } + } + } + } +} + +static void DrawBackground (int bg, uint8 Zh, uint8 Zl) +{ + BG.TileAddress = PPU.BG[bg].NameBase << 1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; + if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC1 -= 0x8000; + SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; + if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC2 -= 0x8000; + SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; + if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC3 -= 0x8000; + + uint32 Lines; + int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; + int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; + int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + + void (*DrawTile) (uint32, uint32, uint32, uint32); + void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32); + + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + { + DrawTile = GFX.DrawTileMath; + DrawClippedTile = GFX.DrawClippedTileMath; + } + else + { + DrawTile = GFX.DrawTileNomath; + DrawClippedTile = GFX.DrawClippedTileNomath; + } + + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y += Lines) + { + uint32 Y2 = IPPU.Interlace ? Y * 2 + GFX.InterlaceFrame : Y; + uint32 VOffset = LineData[Y].BG[bg].VOffset + (IPPU.Interlace ? 1 : 0); + uint32 HOffset = LineData[Y].BG[bg].HOffset; + int VirtAlign = ((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0); + + for (Lines = 1; Lines < GFX.LinesPerTile - 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 - Y + 1; + + VirtAlign <<= 3; + + uint32 t1, t2; + uint32 TilemapRow = (VOffset + Y2) >> OffsetShift; + BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; + + if ((VOffset + Y2) & 8) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + + uint16 *b1, *b2; + + if (TilemapRow & 0x20) + { + b1 = SC2; + b2 = SC3; + } + else + { + b1 = SC0; + b2 = SC1; + } + + b1 += (TilemapRow & 0x1f) << 5; + b2 += (TilemapRow & 0x1f) << 5; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left * PixWidth + Y * GFX.PPL; + uint32 HPos = (HOffset + Left) & OffsetMask; + uint32 HTile = HPos >> 3; + uint16 *t; + + if (BG.TileSizeH == 8) + { + if (HTile > 31) + t = b2 + (HTile & 0x1f); + else + t = b1 + HTile; + } + else + { + if (HTile > 63) + t = b2 + ((HTile >> 1) & 0x1f); + else + t = b1 + (HTile >> 1); + } + + uint32 Width = Right - Left; + + if (HPos & 7) + { + uint32 l = HPos & 7; + uint32 w = 8 - l; + if (w > Width) + w = Width; + + Offset -= l * PixWidth; + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + { + DrawClippedTile(Tile, Offset, l, w, VirtAlign, Lines); + t++; + if (HTile == 31) + t = b2; + else + if (HTile == 63) + t = b1; + } + else + { + if (!(Tile & H_FLIP)) + DrawClippedTile(TILE_PLUS(Tile, (HTile & 1)), Offset, l, w, VirtAlign, Lines); + else + DrawClippedTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, l, w, VirtAlign, Lines); + t += HTile & 1; + if (HTile == 63) + t = b2; + else + if (HTile == 127) + t = b1; + } + + HTile++; + Offset += 8 * PixWidth; + Width -= w; + } + + while (Width >= 8) + { + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + { + DrawTile(Tile, Offset, VirtAlign, Lines); + t++; + if (HTile == 31) + t = b2; + else + if (HTile == 63) + t = b1; + } + else + { + if (!(Tile & H_FLIP)) + DrawTile(TILE_PLUS(Tile, (HTile & 1)), Offset, VirtAlign, Lines); + else + DrawTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, VirtAlign, Lines); + t += HTile & 1; + if (HTile == 63) + t = b2; + else + if (HTile == 127) + t = b1; + } + + HTile++; + Offset += 8 * PixWidth; + Width -= 8; + } + + if (Width) + { + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + DrawClippedTile(Tile, Offset, 0, Width, VirtAlign, Lines); + else + { + if (!(Tile & H_FLIP)) + DrawClippedTile(TILE_PLUS(Tile, (HTile & 1)), Offset, 0, Width, VirtAlign, Lines); + else + DrawClippedTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, 0, Width, VirtAlign, Lines); + } + } + } + } +} + +static void DrawBackgroundMosaic (int bg, uint8 Zh, uint8 Zl) +{ + BG.TileAddress = PPU.BG[bg].NameBase << 1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; + if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC1 -= 0x8000; + SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; + if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC2 -= 0x8000; + SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; + if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC3 -= 0x8000; + + int Lines; + int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; + int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; + int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + + void (*DrawPix) (uint32, uint32, uint32, uint32, uint32, uint32); + + int MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % PPU.Mosaic; + + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + DrawPix = GFX.DrawMosaicPixelMath; + else + DrawPix = GFX.DrawMosaicPixelNomath; + + for (uint32 Y = GFX.StartY - MosaicStart; Y <= GFX.EndY; Y += PPU.Mosaic) + { + uint32 Y2 = IPPU.Interlace ? Y * 2 : Y; + uint32 VOffset = LineData[Y].BG[bg].VOffset + (IPPU.Interlace ? 1 : 0); + uint32 HOffset = LineData[Y].BG[bg].HOffset; + + Lines = PPU.Mosaic - MosaicStart; + if (Y + MosaicStart + Lines > GFX.EndY) + Lines = GFX.EndY - Y - MosaicStart + 1; + + int VirtAlign = (((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0)) << 3; + + uint32 t1, t2; + uint32 TilemapRow = (VOffset + Y2) >> OffsetShift; + BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; + + if ((VOffset + Y2) & 8) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + + uint16 *b1, *b2; + + if (TilemapRow & 0x20) + { + b1 = SC2; + b2 = SC3; + } + else + { + b1 = SC0; + b2 = SC1; + } + + b1 += (TilemapRow & 0x1f) << 5; + b2 += (TilemapRow & 0x1f) << 5; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left * PixWidth + (Y + MosaicStart) * GFX.PPL; + uint32 HPos = (HOffset + Left - (Left % PPU.Mosaic)) & OffsetMask; + uint32 HTile = HPos >> 3; + uint16 *t; + + if (BG.TileSizeH == 8) + { + if (HTile > 31) + t = b2 + (HTile & 0x1f); + else + t = b1 + HTile; + } + else + { + if (HTile > 63) + t = b2 + ((HTile >> 1) & 0x1f); + else + t = b1 + (HTile >> 1); + } + + uint32 Width = Right - Left; + + HPos &= 7; + + while (Left < Right) + { + uint32 w = PPU.Mosaic - (Left % PPU.Mosaic); + if (w > Width) + w = Width; + + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + DrawPix(Tile, Offset, VirtAlign, HPos & 7, w, Lines); + else + { + if (!(Tile & H_FLIP)) + DrawPix(TILE_PLUS(Tile, (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); + else + DrawPix(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); + } + + HPos += PPU.Mosaic; + + while (HPos >= 8) + { + HPos -= 8; + + if (BG.TileSizeH == 8) + { + t++; + if (HTile == 31) + t = b2; + else + if (HTile == 63) + t = b1; + } + else + { + t += HTile & 1; + if (HTile == 63) + t = b2; + else + if (HTile == 127) + t = b1; + } + + HTile++; + } + + Offset += w * PixWidth; + Width -= w; + Left += w; + } + + MosaicStart = 0; + } + } +} + +static void DrawBackgroundOffset (int bg, uint8 Zh, uint8 Zl, int VOffOff) +{ + BG.TileAddress = PPU.BG[bg].NameBase << 1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + uint16 *BPS0, *BPS1, *BPS2, *BPS3; + + BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; + BPS1 = (PPU.BG[2].SCSize & 1) ? BPS0 + 1024 : BPS0; + if (BPS1 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS1 -= 0x8000; + BPS2 = (PPU.BG[2].SCSize & 2) ? BPS1 + 1024 : BPS0; + if (BPS2 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS2 -= 0x8000; + BPS3 = (PPU.BG[2].SCSize & 1) ? BPS2 + 1024 : BPS2; + if (BPS3 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS3 -= 0x8000; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; + if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC1 -= 0x8000; + SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; + if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC2 -= 0x8000; + SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; + if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC3 -= 0x8000; + + int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; + int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; + int Offset2Mask = (BG.OffsetSizeH == 16) ? 0x3ff : 0x1ff; + int Offset2Shift = (BG.OffsetSizeV == 16) ? 4 : 3; + int OffsetEnableMask = 0x2000 << bg; + int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + + void (*DrawTile) (uint32, uint32, uint32, uint32); + void (*DrawClippedTile) (uint32, uint32, uint32, uint32, uint32, uint32); + + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + { + DrawTile = GFX.DrawTileMath; + DrawClippedTile = GFX.DrawClippedTileMath; + } + else + { + DrawTile = GFX.DrawTileNomath; + DrawClippedTile = GFX.DrawClippedTileNomath; + } + + for (uint32 Y = GFX.StartY; Y <= GFX.EndY; Y++) + { + uint32 Y2 = IPPU.Interlace ? Y * 2 + GFX.InterlaceFrame : Y; + uint32 VOff = LineData[Y].BG[2].VOffset - 1; + uint32 HOff = LineData[Y].BG[2].HOffset; + uint32 HOffsetRow = VOff >> Offset2Shift; + uint32 VOffsetRow = (VOff + VOffOff) >> Offset2Shift; + uint16 *s, *s1, *s2; + + if (HOffsetRow & 0x20) + { + s1 = BPS2; + s2 = BPS3; + } + else + { + s1 = BPS0; + s2 = BPS1; + } + + s1 += (HOffsetRow & 0x1f) << 5; + s2 += (HOffsetRow & 0x1f) << 5; + s = ((VOffsetRow & 0x20) ? BPS2 : BPS0) + ((VOffsetRow & 0x1f) << 5); + int32 VOffsetOffset = s - s1; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left * PixWidth + Y * GFX.PPL; + uint32 LineHOffset = LineData[Y].BG[bg].HOffset; + bool8 left_edge = (Left < (8 - (LineHOffset & 7))); + uint32 Width = Right - Left; + + while (Left < Right) + { + uint32 VOffset, HOffset; + + if (left_edge) + { + // SNES cannot do OPT for leftmost tile column + VOffset = LineData[Y].BG[bg].VOffset; + HOffset = LineHOffset; + left_edge = FALSE; + } + else + { + int HOffTile = ((HOff + Left - 1) & Offset2Mask) >> 3; + + if (BG.OffsetSizeH == 8) + { + if (HOffTile > 31) + s = s2 + (HOffTile & 0x1f); + else + s = s1 + HOffTile; + } + else + { + if (HOffTile > 63) + s = s2 + ((HOffTile >> 1) & 0x1f); + else + s = s1 + (HOffTile >> 1); + } + + uint16 HCellOffset = READ_WORD(s); + uint16 VCellOffset; + + if (VOffOff) + VCellOffset = READ_WORD(s + VOffsetOffset); + else + { + if (HCellOffset & 0x8000) + { + VCellOffset = HCellOffset; + HCellOffset = 0; + } + else + VCellOffset = 0; + } + + if (VCellOffset & OffsetEnableMask) + VOffset = VCellOffset + 1; + else + VOffset = LineData[Y].BG[bg].VOffset; + + if (HCellOffset & OffsetEnableMask) + HOffset = (HCellOffset & ~7) | (LineHOffset & 7); + else + HOffset = LineHOffset; + } + + if (IPPU.Interlace) + VOffset++; + + uint32 t1, t2; + int VirtAlign = (((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0)) << 3; + int TilemapRow = (VOffset + Y2) >> OffsetShift; + BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; + + if ((VOffset + Y2) & 8) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + + uint16 *b1, *b2; + + if (TilemapRow & 0x20) + { + b1 = SC2; + b2 = SC3; + } + else + { + b1 = SC0; + b2 = SC1; + } + + b1 += (TilemapRow & 0x1f) << 5; + b2 += (TilemapRow & 0x1f) << 5; + + uint32 HPos = (HOffset + Left) & OffsetMask; + uint32 HTile = HPos >> 3; + uint16 *t; + + if (BG.TileSizeH == 8) + { + if (HTile > 31) + t = b2 + (HTile & 0x1f); + else + t = b1 + HTile; + } + else + { + if (HTile > 63) + t = b2 + ((HTile >> 1) & 0x1f); + else + t = b1 + (HTile >> 1); + } + + uint32 l = HPos & 7; + uint32 w = 8 - l; + if (w > Width) + w = Width; + + Offset -= l * PixWidth; + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + { + DrawClippedTile(Tile, Offset, l, w, VirtAlign, 1); + } + else + { + if (!(Tile & H_FLIP)) + DrawClippedTile(TILE_PLUS(Tile, (HTile & 1)), Offset, l, w, VirtAlign, 1); + else + DrawClippedTile(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, l, w, VirtAlign, 1); + } + + Left += w; + Offset += 8 * PixWidth; + Width -= w; + } + } + } +} + +static void DrawBackgroundOffsetMosaic (int bg, uint8 Zh, uint8 Zl, int VOffOff) +{ + BG.TileAddress = PPU.BG[bg].NameBase << 1; + + uint32 Tile; + uint16 *SC0, *SC1, *SC2, *SC3; + uint16 *BPS0, *BPS1, *BPS2, *BPS3; + + BPS0 = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1]; + BPS1 = (PPU.BG[2].SCSize & 1) ? BPS0 + 1024 : BPS0; + if (BPS1 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS1 -= 0x8000; + BPS2 = (PPU.BG[2].SCSize & 2) ? BPS1 + 1024 : BPS0; + if (BPS2 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS2 -= 0x8000; + BPS3 = (PPU.BG[2].SCSize & 1) ? BPS2 + 1024 : BPS2; + if (BPS3 >= (uint16 *) (Memory.VRAM + 0x10000)) + BPS3 -= 0x8000; + + SC0 = (uint16 *) &Memory.VRAM[PPU.BG[bg].SCBase << 1]; + SC1 = (PPU.BG[bg].SCSize & 1) ? SC0 + 1024 : SC0; + if (SC1 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC1 -= 0x8000; + SC2 = (PPU.BG[bg].SCSize & 2) ? SC1 + 1024 : SC0; + if (SC2 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC2 -= 0x8000; + SC3 = (PPU.BG[bg].SCSize & 1) ? SC2 + 1024 : SC2; + if (SC3 >= (uint16 *) (Memory.VRAM + 0x10000)) + SC3 -= 0x8000; + + int Lines; + int OffsetMask = (BG.TileSizeH == 16) ? 0x3ff : 0x1ff; + int OffsetShift = (BG.TileSizeV == 16) ? 4 : 3; + int Offset2Mask = (BG.OffsetSizeH == 16) ? 0x3ff : 0x1ff; + int Offset2Shift = (BG.OffsetSizeV == 16) ? 4 : 3; + int OffsetEnableMask = 0x2000 << bg; + int PixWidth = IPPU.DoubleWidthPixels ? 2 : 1; + + void (*DrawPix) (uint32, uint32, uint32, uint32, uint32, uint32); + + int MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % PPU.Mosaic; + + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + DrawPix = GFX.DrawMosaicPixelMath; + else + DrawPix = GFX.DrawMosaicPixelNomath; + + for (uint32 Y = GFX.StartY - MosaicStart; Y <= GFX.EndY; Y += PPU.Mosaic) + { + uint32 Y2 = IPPU.Interlace ? Y * 2 : Y; + uint32 VOff = LineData[Y].BG[2].VOffset - 1; + uint32 HOff = LineData[Y].BG[2].HOffset; + + Lines = PPU.Mosaic - MosaicStart; + if (Y + MosaicStart + Lines > GFX.EndY) + Lines = GFX.EndY - Y - MosaicStart + 1; + + uint32 HOffsetRow = VOff >> Offset2Shift; + uint32 VOffsetRow = (VOff + VOffOff) >> Offset2Shift; + uint16 *s, *s1, *s2; + + if (HOffsetRow & 0x20) + { + s1 = BPS2; + s2 = BPS3; + } + else + { + s1 = BPS0; + s2 = BPS1; + } + + s1 += (HOffsetRow & 0x1f) << 5; + s2 += (HOffsetRow & 0x1f) << 5; + s = ((VOffsetRow & 0x20) ? BPS2 : BPS0) + ((VOffsetRow & 0x1f) << 5); + int32 VOffsetOffset = s - s1; + + uint32 Left = GFX.Clip[bg].Left[clip]; + uint32 Right = GFX.Clip[bg].Right[clip]; + uint32 Offset = Left * PixWidth + (Y + MosaicStart) * GFX.PPL; + uint32 LineHOffset = LineData[Y].BG[bg].HOffset; + bool8 left_edge = (Left < (8 - (LineHOffset & 7))); + uint32 Width = Right - Left; + + while (Left < Right) + { + uint32 VOffset, HOffset; + + if (left_edge) + { + // SNES cannot do OPT for leftmost tile column + VOffset = LineData[Y].BG[bg].VOffset; + HOffset = LineHOffset; + left_edge = FALSE; + } + else + { + int HOffTile = ((HOff + Left - 1) & Offset2Mask) >> 3; + + if (BG.OffsetSizeH == 8) + { + if (HOffTile > 31) + s = s2 + (HOffTile & 0x1f); + else + s = s1 + HOffTile; + } + else + { + if (HOffTile > 63) + s = s2 + ((HOffTile >> 1) & 0x1f); + else + s = s1 + (HOffTile >> 1); + } + + uint16 HCellOffset = READ_WORD(s); + uint16 VCellOffset; + + if (VOffOff) + VCellOffset = READ_WORD(s + VOffsetOffset); + else + { + if (HCellOffset & 0x8000) + { + VCellOffset = HCellOffset; + HCellOffset = 0; + } + else + VCellOffset = 0; + } + + if (VCellOffset & OffsetEnableMask) + VOffset = VCellOffset + 1; + else + VOffset = LineData[Y].BG[bg].VOffset; + + if (HCellOffset & OffsetEnableMask) + HOffset = (HCellOffset & ~7) | (LineHOffset & 7); + else + HOffset = LineHOffset; + } + + if (IPPU.Interlace) + VOffset++; + + uint32 t1, t2; + int VirtAlign = (((Y2 + VOffset) & 7) >> (IPPU.Interlace ? 1 : 0)) << 3; + int TilemapRow = (VOffset + Y2) >> OffsetShift; + BG.InterlaceLine = ((VOffset + Y2) & 1) << 3; + + if ((VOffset + Y2) & 8) + { + t1 = 16; + t2 = 0; + } + else + { + t1 = 0; + t2 = 16; + } + + uint16 *b1, *b2; + + if (TilemapRow & 0x20) + { + b1 = SC2; + b2 = SC3; + } + else + { + b1 = SC0; + b2 = SC1; + } + + b1 += (TilemapRow & 0x1f) << 5; + b2 += (TilemapRow & 0x1f) << 5; + + uint32 HPos = (HOffset + Left - (Left % PPU.Mosaic)) & OffsetMask; + uint32 HTile = HPos >> 3; + uint16 *t; + + if (BG.TileSizeH == 8) + { + if (HTile > 31) + t = b2 + (HTile & 0x1f); + else + t = b1 + HTile; + } + else + { + if (HTile > 63) + t = b2 + ((HTile >> 1) & 0x1f); + else + t = b1 + (HTile >> 1); + } + + uint32 w = PPU.Mosaic - (Left % PPU.Mosaic); + if (w > Width) + w = Width; + + Tile = READ_WORD(t); + GFX.Z1 = GFX.Z2 = (Tile & 0x2000) ? Zh : Zl; + + if (BG.TileSizeV == 16) + Tile = TILE_PLUS(Tile, ((Tile & V_FLIP) ? t2 : t1)); + + if (BG.TileSizeH == 8) + DrawPix(Tile, Offset, VirtAlign, HPos & 7, w, Lines); + else + { + if (!(Tile & H_FLIP)) + DrawPix(TILE_PLUS(Tile, (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); + else + if (!(Tile & V_FLIP)) + DrawPix(TILE_PLUS(Tile, 1 - (HTile & 1)), Offset, VirtAlign, HPos & 7, w, Lines); + } + + Left += w; + Offset += w * PixWidth; + Width -= w; + } + + MosaicStart = 0; + } + } +} + +static inline void DrawBackgroundMode7 (int bg, void (*DrawMath) (uint32, uint32, int), void (*DrawNomath) (uint32, uint32, int), int D) +{ + for (int clip = 0; clip < GFX.Clip[bg].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[bg].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[bg].DrawMode[clip] & 2)) + DrawMath(GFX.Clip[bg].Left[clip], GFX.Clip[bg].Right[clip], D); + else + DrawNomath(GFX.Clip[bg].Left[clip], GFX.Clip[bg].Right[clip], D); + } +} + +static inline void DrawBackdrop (void) +{ + uint32 Offset = GFX.StartY * GFX.PPL; + + for (int clip = 0; clip < GFX.Clip[5].Count; clip++) + { + GFX.ClipColors = !(GFX.Clip[5].DrawMode[clip] & 1); + + if (BG.EnableMath && (GFX.Clip[5].DrawMode[clip] & 2)) + GFX.DrawBackdropMath(Offset, GFX.Clip[5].Left[clip], GFX.Clip[5].Right[clip]); + else + GFX.DrawBackdropNomath(Offset, GFX.Clip[5].Left[clip], GFX.Clip[5].Right[clip]); + } +} + +void S9xReRefresh (void) +{ + // Be careful when calling this function from the thread other than the emulation one... + // Here it's assumed no drawing occurs from the emulation thread when Settings.Paused is TRUE. + if (Settings.Paused) + S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); +} + +void S9xSetInfoString (const char *string) +{ + if (Settings.InitialInfoStringTimeout > 0) + { + GFX.InfoString = string; + GFX.InfoStringTimeout = Settings.InitialInfoStringTimeout; + S9xReRefresh(); + } +} + +void S9xDisplayChar (uint16 *s, uint8 c) +{ + const uint16 black = BUILD_PIXEL(0, 0, 0); + + int line = ((c - 32) >> 4) * font_height; + int offset = ((c - 32) & 15) * font_width; + + for (int h = 0; h < font_height; h++, line++, s += GFX.RealPPL - font_width) + { + for (int w = 0; w < font_width; w++, s++) + { + char p = font[line][offset + w]; + + if (p == '#') + *s = Settings.DisplayColor; + else + if (p == '.') + *s = black; + } + } +} + +static void DisplayStringFromBottom (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap) +{ + if (linesFromBottom <= 0) + linesFromBottom = 1; + + uint16 *dst = GFX.Screen + (IPPU.RenderedScreenHeight - font_height * linesFromBottom) * GFX.RealPPL + pixelsFromLeft; + + int len = strlen(string); + int max_chars = IPPU.RenderedScreenWidth / (font_width - 1); + int char_count = 0; + + for (int i = 0 ; i < len ; i++, char_count++) + { + if (char_count >= max_chars || (uint8) string[i] < 32) + { + if (!allowWrap) + break; + + dst += font_height * GFX.RealPPL - (font_width - 1) * max_chars; + if (dst >= GFX.Screen + IPPU.RenderedScreenHeight * GFX.RealPPL) + break; + + char_count -= max_chars; + } + + if ((uint8) string[i] < 32) + continue; + + S9xDisplayChar(dst, string[i]); + dst += font_width - 1; + } +} + +static void DisplayFrameRate (void) +{ + char string[10]; +#ifdef DEBUGGER + const int len = 8; + sprintf(string, "%02d/%02d %02d", (int) IPPU.DisplayedRenderedFrameCount, (int) Memory.ROMFramesPerSecond, (int) IPPU.FrameCount); +#else + const int len = 5; + sprintf(string, "%02d/%02d", (int) IPPU.DisplayedRenderedFrameCount, (int) Memory.ROMFramesPerSecond); +#endif + + S9xDisplayString(string, 1, IPPU.RenderedScreenWidth - (font_width - 1) * len - 1, false); +} + +static void DisplayPressedKeys (void) +{ + static char KeyMap[] = { '0', '1', '2', 'R', 'L', 'X', 'A', '>', '<', 'v', '^', 'S', 's', 'Y', 'B' }; + static int KeyOrder[] = { 8, 10, 7, 9, 0, 6, 14, 13, 5, 1, 4, 3, 2, 11, 12 }; // < ^ > v A B Y X L R S s + + enum controllers controller; + int line = 1; + int8 ids[4]; + char string[255]; + + for (int port = 0; port < 2; port++) + { + S9xGetController(port, &controller, &ids[0], &ids[1], &ids[2], &ids[3]); + + switch (controller) + { + case CTL_MOUSE: + { + uint8 buf[5], *p = buf; + MovieGetMouse(port, buf); + int16 x = READ_WORD(p); + int16 y = READ_WORD(p + 2); + uint8 buttons = buf[4]; + sprintf(string, "#%d %d: (%03d,%03d) %c%c", port, ids[0], x, y, + (buttons & 0x40) ? 'L' : ' ', (buttons & 0x80) ? 'R' : ' '); + S9xDisplayString(string, line++, 1, false); + break; + } + + case CTL_SUPERSCOPE: + { + uint8 buf[6], *p = buf; + MovieGetScope(port, buf); + int16 x = READ_WORD(p); + int16 y = READ_WORD(p + 2); + uint8 buttons = buf[4]; + sprintf(string, "#%d %d: (%03d,%03d) %c%c%c%c", port, ids[0], x, y, + (buttons & 0x80) ? 'F' : ' ', (buttons & 0x40) ? 'C' : ' ', + (buttons & 0x20) ? 'T' : ' ', (buttons & 0x10) ? 'P' : ' '); + S9xDisplayString(string, line++, 1, false); + break; + } + + case CTL_JUSTIFIER: + { + uint8 buf[11], *p = buf; + MovieGetJustifier(port, buf); + int16 x1 = READ_WORD(p); + int16 x2 = READ_WORD(p + 2); + int16 y1 = READ_WORD(p + 4); + int16 y2 = READ_WORD(p + 6); + uint8 buttons = buf[8]; + bool8 offscreen1 = buf[9]; + bool8 offscreen2 = buf[10]; + sprintf(string, "#%d %d: (%03d,%03d) %c%c%c / (%03d,%03d) %c%c%c", port, ids[0], + x1, y1, (buttons & 0x80) ? 'T' : ' ', (buttons & 0x20) ? 'S' : ' ', offscreen1 ? 'O' : ' ', + x2, y2, (buttons & 0x40) ? 'T' : ' ', (buttons & 0x10) ? 'S' : ' ', offscreen2 ? 'O' : ' '); + S9xDisplayString(string, line++, 1, false); + break; + } + + case CTL_JOYPAD: + { + sprintf(string, "#%d %d: ", port, ids[0]); + uint16 pad = MovieGetJoypad(ids[0]); + for (int i = 0; i < 15; i++) + { + int j = KeyOrder[i]; + int mask = (1 << (j + 1)); + string[6 + i]= (pad & mask) ? KeyMap[j] : ' '; + } + + S9xDisplayString(string, line++, 1, false); + break; + } + + case CTL_MP5: + { + for (int n = 0; n < 4; n++) + { + if (ids[n] != -1) + { + sprintf(string, "#%d %d: ", port, ids[n]); + uint16 pad = MovieGetJoypad(ids[n]); + for (int i = 0; i < 15; i++) + { + int j = KeyOrder[i]; + int mask = (1 << (j + 1)); + string[6 + i]= (pad & mask) ? KeyMap[j] : ' '; + } + + S9xDisplayString(string, line++, 1, false); + } + } + + break; + } + + case CTL_NONE: + { + sprintf(string, "#%d -", port); + S9xDisplayString(string, line++, 1, false); + break; + } + } + } +} + +static void DisplayWatchedAddresses (void) +{ + for (unsigned int i = 0; i < sizeof(watches) / sizeof(watches[0]); i++) + { + if (!watches[i].on) + break; + + int32 displayNumber = 0; + char buf[32]; + + for (int r = 0; r < watches[i].size; r++) + displayNumber += (Cheat.CWatchRAM[(watches[i].address - 0x7E0000) + r]) << (8 * r); + + if (watches[i].format == 1) + sprintf(buf, "%s,%du = %u", watches[i].desc, watches[i].size, (unsigned int) displayNumber); + else + if (watches[i].format == 3) + sprintf(buf, "%s,%dx = %X", watches[i].desc, watches[i].size, (unsigned int) displayNumber); + else // signed + { + if (watches[i].size == 1) + displayNumber = (int32) ((int8) displayNumber); + else + if (watches[i].size == 2) + displayNumber = (int32) ((int16) displayNumber); + else + if (watches[i].size == 3) + if (displayNumber >= 8388608) + displayNumber -= 16777216; + + sprintf(buf, "%s,%ds = %d", watches[i].desc, watches[i].size, (int) displayNumber); + } + + S9xDisplayString(buf, 6 + i, 1, false); + } +} + +void S9xDisplayMessages (uint16 *screen, int ppl, int width, int height, int scale) +{ + if (Settings.DisplayFrameRate) + DisplayFrameRate(); + + if (Settings.DisplayWatchedAddresses) + DisplayWatchedAddresses(); + + if (Settings.DisplayPressedKeys) + DisplayPressedKeys(); + + if (Settings.DisplayMovieFrame && S9xMovieActive()) + S9xDisplayString(GFX.FrameDisplayString, 1, 1, false); + + if (GFX.InfoString && *GFX.InfoString) + S9xDisplayString(GFX.InfoString, 5, 1, true); +} + +static uint16 get_crosshair_color (uint8 color) +{ + switch (color & 15) + { + case 0: return (BUILD_PIXEL( 0, 0, 0)); // transparent, shouldn't be used + case 1: return (BUILD_PIXEL( 0, 0, 0)); // Black + case 2: return (BUILD_PIXEL( 8, 8, 8)); // 25Grey + case 3: return (BUILD_PIXEL(16, 16, 16)); // 50Grey + case 4: return (BUILD_PIXEL(23, 23, 23)); // 75Grey + case 5: return (BUILD_PIXEL(31, 31, 31)); // White + case 6: return (BUILD_PIXEL(31, 0, 0)); // Red + case 7: return (BUILD_PIXEL(31, 16, 0)); // Orange + case 8: return (BUILD_PIXEL(31, 31, 0)); // Yellow + case 9: return (BUILD_PIXEL( 0, 31, 0)); // Green + case 10: return (BUILD_PIXEL( 0, 31, 31)); // Cyan + case 11: return (BUILD_PIXEL( 0, 23, 31)); // Sky + case 12: return (BUILD_PIXEL( 0, 0, 31)); // Blue + case 13: return (BUILD_PIXEL(23, 0, 31)); // Violet + case 14: return (BUILD_PIXEL(31, 0, 31)); // Magenta + case 15: return (BUILD_PIXEL(31, 0, 16)); // Purple + } + + return (0); +} + +void S9xDrawCrosshair (const char *crosshair, uint8 fgcolor, uint8 bgcolor, int16 x, int16 y) +{ + if (!crosshair) + return; + + int16 r, rx = 1, c, cx = 1, W = SNES_WIDTH, H = PPU.ScreenHeight; + uint16 fg, bg; + + x -= 7; + y -= 7; + + if (IPPU.DoubleWidthPixels) { cx = 2; x *= 2; W *= 2; } + if (IPPU.DoubleHeightPixels) { rx = 2; y *= 2; H *= 2; } + + fg = get_crosshair_color(fgcolor); + bg = get_crosshair_color(bgcolor); + + // XXX: FIXME: why does it crash without this on Linux port? There are no out-of-bound writes without it... +#if (defined(__unix) || defined(__linux) || defined(__sun) || defined(__DJGPP)) + if (x >= 0 && y >= 0) +#endif + { + uint16 *s = GFX.Screen + y * GFX.RealPPL + x; + + for (r = 0; r < 15 * rx; r++, s += GFX.RealPPL - 15 * cx) + { + if (y + r < 0) + { + s += 15 * cx; + continue; + } + + if (y + r >= H) + break; + + for (c = 0; c < 15 * cx; c++, s++) + { + if (x + c < 0 || s < GFX.Screen) + continue; + + if (x + c >= W) + { + s += 15 * cx - c; + break; + } + + uint8 p = crosshair[(r / rx) * 15 + (c / cx)]; + + if (p == '#' && fgcolor) + *s = (fgcolor & 0x10) ? COLOR_ADD1_2(fg, *s) : fg; + else + if (p == '.' && bgcolor) + *s = (bgcolor & 0x10) ? COLOR_ADD1_2(*s, bg) : bg; + } + } + } +} + +#ifdef GFX_MULTI_FORMAT + +static uint32 BuildPixelRGB565 (uint32, uint32, uint32); +static uint32 BuildPixelRGB555 (uint32, uint32, uint32); +static uint32 BuildPixelBGR565 (uint32, uint32, uint32); +static uint32 BuildPixelBGR555 (uint32, uint32, uint32); +static uint32 BuildPixelGBR565 (uint32, uint32, uint32); +static uint32 BuildPixelGBR555 (uint32, uint32, uint32); +static uint32 BuildPixelRGB5551 (uint32, uint32, uint32); + +static uint32 BuildPixel2RGB565 (uint32, uint32, uint32); +static uint32 BuildPixel2RGB555 (uint32, uint32, uint32); +static uint32 BuildPixel2BGR565 (uint32, uint32, uint32); +static uint32 BuildPixel2BGR555 (uint32, uint32, uint32); +static uint32 BuildPixel2GBR565 (uint32, uint32, uint32); +static uint32 BuildPixel2GBR555 (uint32, uint32, uint32); +static uint32 BuildPixel2RGB5551 (uint32, uint32, uint32); + +static void DecomposePixelRGB565 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelRGB555 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelBGR565 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelBGR555 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelGBR565 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelGBR555 (uint32, uint32 &, uint32 &, uint32 &); +static void DecomposePixelRGB5551 (uint32, uint32 &, uint32 &, uint32 &); + +#define _BUILD_PIXEL(F) \ +static uint32 BuildPixel##F (uint32 R, uint32 G, uint32 B) \ +{ \ + return (BUILD_PIXEL_##F(R, G, B)); \ +} \ +\ +static uint32 BuildPixel2##F (uint32 R, uint32 G, uint32 B) \ +{ \ + return (BUILD_PIXEL2_##F(R, G, B)); \ +} \ +\ +static 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) + +#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; \ +SPARE_RGB_BIT_MASK = SPARE_RGB_BIT_MASK_##F; \ +GREEN_HI_BIT = ((MAX_GREEN_##F + 1) >> 1); \ +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; + +bool8 S9xSetRenderPixelFormat (int format) +{ + GFX.PixelFormat = 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/gfx.h b/gfx.h new file mode 100644 index 00000000..75981cc2 --- /dev/null +++ b/gfx.h @@ -0,0 +1,366 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _GFX_H_ +#define _GFX_H_ + +struct SGFX +{ + uint16 *Screen; + uint16 *SubScreen; + uint8 *ZBuffer; + uint8 *SubZBuffer; + uint32 Pitch; + uint32 ScreenSize; + uint16 *S; + uint8 *DB; + uint16 *X2; + uint16 *ZERO; + uint32 RealPPL; // true PPL of Screen buffer + uint32 PPL; // number of pixels on each of Screen buffer + uint32 LinesPerTile; // number of lines in 1 tile (4 or 8 due to interlace) + uint16 *ScreenColors; // screen colors for rendering main + uint16 *RealScreenColors; // screen colors, ignoring color window clipping + uint8 Z1; // depth for comparison + uint8 Z2; // depth to save + uint32 FixedColour; + uint8 DoInterlace; + uint8 InterlaceFrame; + uint32 StartY; + uint32 EndY; + bool8 ClipColors; + uint8 OBJWidths[128]; + uint8 OBJVisibleTiles[128]; + + struct ClipData *Clip; + + struct + { + uint8 RTOFlags; + int16 Tiles; + + struct + { + int8 Sprite; + uint8 Line; + } OBJ[32]; + } OBJLines[SNES_HEIGHT_EXTENDED]; + +#ifdef GFX_MULTI_FORMAT + uint32 PixelFormat; + uint32 (*BuildPixel) (uint32, uint32, uint32); + uint32 (*BuildPixel2) (uint32, uint32, uint32); + void (*DecomposePixel) (uint32, uint32 &, uint32 &, uint32 &); +#endif + + void (*DrawBackdropMath) (uint32, uint32, uint32); + void (*DrawBackdropNomath) (uint32, uint32, uint32); + void (*DrawTileMath) (uint32, uint32, uint32, uint32); + void (*DrawTileNomath) (uint32, uint32, uint32, uint32); + void (*DrawClippedTileMath) (uint32, uint32, uint32, uint32, uint32, uint32); + void (*DrawClippedTileNomath) (uint32, uint32, uint32, uint32, uint32, uint32); + void (*DrawMosaicPixelMath) (uint32, uint32, uint32, uint32, uint32, uint32); + void (*DrawMosaicPixelNomath) (uint32, uint32, uint32, uint32, uint32, uint32); + void (*DrawMode7BG1Math) (uint32, uint32, int); + void (*DrawMode7BG1Nomath) (uint32, uint32, int); + void (*DrawMode7BG2Math) (uint32, uint32, int); + void (*DrawMode7BG2Nomath) (uint32, uint32, int); + + const char *InfoString; + uint32 InfoStringTimeout; + char FrameDisplayString[256]; +}; + +struct SBG +{ + uint8 (*ConvertTile) (uint8 *, uint32, uint32); + uint8 (*ConvertTileFlip) (uint8 *, uint32, uint32); + + uint32 TileSizeH; + uint32 TileSizeV; + uint32 OffsetSizeH; + uint32 OffsetSizeV; + uint32 TileShift; + uint32 TileAddress; + uint32 NameSelect; + uint32 SCBase; + + uint32 StartPalette; + uint32 PaletteShift; + uint32 PaletteMask; + uint8 EnableMath; + uint8 InterlaceLine; + + uint8 *Buffer; + uint8 *BufferFlip; + uint8 *Buffered; + uint8 *BufferedFlip; + bool8 DirectColourMode; +}; + +struct SLineData +{ + struct + { + uint16 VOffset; + uint16 HOffset; + } BG[4]; +}; + +struct SLineMatrixData +{ + short MatrixA; + short MatrixB; + short MatrixC; + short MatrixD; + short CentreX; + short CentreY; + short M7HOFS; + short M7VOFS; +}; + +extern uint16 BlackColourMap[256]; +extern uint16 DirectColourMaps[8][256]; +extern uint8 mul_brightness[16][32]; +extern struct SBG BG; +extern struct SGFX GFX; + +#define H_FLIP 0x4000 +#define V_FLIP 0x8000 +#define BLANK_TILE 2 + +#define COLOR_ADD1_2(C1, C2) \ + ((((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ + ((C1) & (C2) & RGB_LOW_BITS_MASK)) | ALPHA_BITS_MASK) + +#define COLOR_ADD(C1, C2) \ + (GFX.X2[((((C1) & RGB_REMOVE_LOW_BITS_MASK) + \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1) + \ + ((C1) & (C2) & RGB_LOW_BITS_MASK)] | \ + (((C1) ^ (C2)) & RGB_LOW_BITS_MASK)) + +#define COLOR_SUB1_2(C1, C2) \ + GFX.ZERO[(((C1) | RGB_HI_BITS_MASKx2) - \ + ((C2) & RGB_REMOVE_LOW_BITS_MASK)) >> 1] + +inline uint16 COLOR_SUB (uint16 C1, uint16 C2) +{ + uint16 mC1, mC2, v = ALPHA_BITS_MASK; + + mC1 = C1 & FIRST_COLOR_MASK; + mC2 = C2 & FIRST_COLOR_MASK; + if (mC1 > mC2) v += (mC1 - mC2); + + mC1 = C1 & SECOND_COLOR_MASK; + mC2 = C2 & SECOND_COLOR_MASK; + if (mC1 > mC2) v += (mC1 - mC2); + + mC1 = C1 & THIRD_COLOR_MASK; + mC2 = C2 & THIRD_COLOR_MASK; + if (mC1 > mC2) v += (mC1 - mC2); + + return (v); +} + +void S9xStartScreenRefresh (void); +void S9xEndScreenRefresh (void); +void S9xUpdateScreen (void); +void S9xBuildDirectColourMaps (void); +void RenderLine (uint8); +void S9xComputeClipWindows (void); +void S9xDisplayChar (uint16 *, uint8); +// called automatically unless Settings.AutoDisplayMessages is false +void S9xDisplayMessages (uint16 *, int, int, int, int); +#ifdef GFX_MULTI_FORMAT +bool8 S9xSetRenderPixelFormat (int); +#endif + +// external port interface which must be implemented or initialised for each port +bool8 S9xGraphicsInit (void); +void S9xGraphicsDeinit (void); +bool8 S9xInitUpdate (void); +bool8 S9xDeinitUpdate (int, int); +bool8 S9xContinueUpdate (int, int); +void S9xReRefresh (void); +void S9xSetPalette (void); +void S9xSyncSpeed (void); + +// called instead of S9xDisplayString if set to non-NULL +extern void (*S9xCustomDisplayString) (const char *, int, int, bool); + +#endif diff --git a/globals.cpp b/globals.cpp new file mode 100644 index 00000000..2fc439a3 --- /dev/null +++ b/globals.cpp @@ -0,0 +1,410 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "dma.h" +#include "apu/apu.h" +#include "fxinst.h" +#include "fxemu.h" +#include "srtc.h" +#include "cheats.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif +#ifdef DEBUGGER +#include "debug.h" +#include "missing.h" +#endif + +struct SCPUState CPU; +struct SICPU ICPU; +struct SRegisters Registers; +struct SPPU PPU; +struct InternalPPU IPPU; +struct SDMA DMA[8]; +struct STimings Timings; +struct SGFX GFX; +struct SBG BG; +struct SLineData LineData[240]; +struct SLineMatrixData LineMatrixData[240]; +struct SDSP0 DSP0; +struct SDSP1 DSP1; +struct SDSP2 DSP2; +struct SDSP3 DSP3; +struct SDSP4 DSP4; +struct SSA1 SA1; +struct SSA1Registers SA1Registers; +struct SST010 ST010; +struct SST011 ST011; +struct SST018 ST018; +struct SOBC1 OBC1; +struct SSPC7110Snapshot s7snap; +struct SSRTCSnapshot srtcsnap; +struct SRTCData RTCData; +struct SBSX BSX; +struct SMulti Multi; +struct SSettings Settings; +struct SSNESGameFixes SNESGameFixes; +#ifdef NETPLAY_SUPPORT +struct SNetPlay NetPlay; +#endif +#ifdef DEBUGGER +struct Missing missing; +#endif +struct SCheatData Cheat; +struct Watch watches[16]; +#ifndef ZSNES_FX +struct FxRegs_s GSU; +struct FxInfo_s SuperFX; +#endif +CMemory Memory; + +char String[513]; +uint8 OpenBus = 0; +uint8 *HDMAMemPointers[8]; +uint16 BlackColourMap[256]; +uint16 DirectColourMaps[8][256]; + +SnesModel M1SNES = { 1, 3, 2 }; +SnesModel M2SNES = { 2, 4, 3 }; +SnesModel *Model = &M1SNES; + +#if defined(ZSNES_FX) || defined(ZSNES_C4) +uint8 *ROM = NULL; +uint8 *SRAM = NULL; +uint8 *RegRAM = NULL; +#endif +#ifdef ZSNES_FX +uint8 *SFXPlotTable = NULL; +#endif + +#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; +#endif + +uint16 SignExtend[2] = +{ + 0x0000, + 0xff00 +}; + +int HDMA_ModeByteCounts[8] = +{ + 1, 2, 2, 4, 4, 4, 2, 4 +}; + +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 } +}; + +uint8 S9xOpLengthsM0X0[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 3, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 3, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 3, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; + +uint8 S9xOpLengthsM0X1[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; + +uint8 S9xOpLengthsM1X0[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 3, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 3, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 3, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; + +uint8 S9xOpLengthsM1X1[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 1 + 3, 2, 4, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 2 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 3 + 1, 2, 2, 2, 3, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 4 + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 4, 3, 3, 4, // 5 + 1, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 6 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 7 + 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 8 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 9 + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // A + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // B + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // C + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // D + 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // E + 2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4 // F +}; diff --git a/gtk/AUTHORS b/gtk/AUTHORS new file mode 100644 index 00000000..ec75270c --- /dev/null +++ b/gtk/AUTHORS @@ -0,0 +1,7 @@ +Brandon Wright (bearoso@gmail.com) + +Translators: +Tukuyomi (fr_FR) +Inukaze (es_VE) +Tibério Vítor (pt_BR) +Milan Kostić (sr@latin) diff --git a/gtk/Makefile.am b/gtk/Makefile.am new file mode 100644 index 00000000..64395f09 --- /dev/null +++ b/gtk/Makefile.am @@ -0,0 +1,241 @@ +SUBDIRS = data po + +bin_PROGRAMS = snes9x-gtk +snes9x_gtk_LDADD = +if DEBUG +else +snes9x_gtk_CXXFLAGS = -fno-exceptions -fno-rtti +endif +noinst_LIBRARIES = + +INCLUDES = -I$(top_srcdir) -I.. -DSNES9XLOCALEDIR=\""$(snes9xlocaledir)"\" + +CLEANFILES = \ + src/gtk_glade.cpp \ + src/sourcify + +snes9x_gtk_SOURCES = \ + src/gtk_sound_driver.h \ + ../filter/2xsai.cpp \ + ../filter/2xsai.h \ + ../filter/epx.cpp \ + ../filter/epx.h \ + ../filter/hq2x.cpp \ + ../filter/hq2x.h \ + src/filter_epx_unsafe.h \ + src/filter_epx_unsafe.cpp \ + src/gtk_binding.cpp \ + src/gtk_binding.h \ + src/gtk_cheat.cpp \ + src/gtk_cheat.h \ + src/gtk_config.cpp \ + src/gtk_config.h \ + src/gtk_control.cpp \ + src/gtk_control.h \ + src/gtk_display.cpp \ + src/gtk_display_driver_gtk.cpp \ + src/gtk_display_driver_gtk.h \ + src/gtk_display_driver.h \ + src/gtk_display.h \ + src/gtk_file.cpp \ + src/gtk_file.h \ + src/gtk_glade.cpp \ + src/gtk_glade_window.cpp \ + src/gtk_glade_window.h \ + src/gtk_preferences.cpp \ + src/gtk_preferences.h \ + src/gtk_s9xcore.h \ + src/gtk_s9x.cpp \ + src/gtk_s9x.h \ + src/gtk_s9xwindow.cpp \ + src/gtk_s9xwindow.h \ + src/gtk_sound.cpp \ + src/gtk_sound.h \ + src/gtk_splash.h \ + src/snes_ntsc_config.h \ + src/snes_ntsc.h \ + src/snes_ntsc_impl.h \ + src/snes_ntsc.c + +if PORTAUDIO +snes9x_gtk_SOURCES += \ + src/gtk_sound_driver_portaudio.cpp \ + src/gtk_sound_driver_portaudio.h +endif + +if PULSEAUDIO +snes9x_gtk_SOURCES += \ + src/gtk_sound_driver_pulse.cpp \ + src/gtk_sound_driver_pulse.h +endif + +if OSS +snes9x_gtk_SOURCES += \ + src/gtk_sound_driver_oss.h \ + src/gtk_sound_driver_oss.cpp +endif + +if SDL +snes9x_gtk_SOURCES += \ + src/gtk_sound_driver_sdl.h \ + src/gtk_sound_driver_sdl.cpp +endif + +if ALSA +snes9x_gtk_SOURCES += \ + src/gtk_sound_driver_alsa.h \ + src/gtk_sound_driver_alsa.cpp +endif + +if ZSNESFX +snes9x_gtk_SOURCES += \ + ../i386/fxemu2b.asm \ + ../i386/fxemu2.asm \ + ../i386/fxemu2c.asm \ + ../i386/fxtable.asm \ + ../i386/sfxproc.asm \ + ../i386/zsnes.asm +else +snes9x_gtk_SOURCES += \ + ../fxinst.cpp \ + ../fxemu.cpp \ + ../fxdbg.cpp +endif + +if ZSNESC4 +snes9x_gtk_SOURCES += \ + ../i386/c4.asm \ + ../i386/zsnesc4.asm \ + ../c4.cpp +else +snes9x_gtk_SOURCES += \ + ../c4.cpp \ + ../c4emu.cpp +endif + +# APU +snes9x_gtk_SOURCES += \ + ../apu/apu.cpp \ + ../apu/SNES_SPC.cpp \ + ../apu/SNES_SPC_misc.cpp \ + ../apu/SNES_SPC_state.cpp \ + ../apu/SPC_DSP.cpp \ + ../apu/SPC_Filter.cpp + +# DSP +snes9x_gtk_SOURCES += \ + ../dsp.cpp \ + ../dsp1.cpp \ + ../dsp2.cpp \ + ../dsp3.cpp \ + ../dsp4.cpp + +# Base +snes9x_gtk_SOURCES += \ + ../spc7110.cpp \ + ../obc1.cpp \ + ../seta.cpp \ + ../seta010.cpp \ + ../seta011.cpp \ + ../seta018.cpp \ + ../controls.cpp \ + ../crosshairs.cpp \ + ../cpu.cpp \ + ../sa1.cpp \ + ../debug.cpp \ + ../sdd1.cpp \ + ../tile.cpp \ + ../srtc.cpp \ + ../gfx.cpp \ + ../memmap.cpp \ + ../clip.cpp \ + ../ppu.cpp \ + ../dma.cpp \ + ../snes9x.cpp \ + ../globals.cpp \ + ../reader.cpp \ + ../conffile.cpp \ + ../bsx.cpp \ + ../logger.cpp \ + ../snapshot.cpp \ + ../screenshot.cpp \ + ../movie.cpp + +# ASMCPU Doesn't exist anymore. +snes9x_gtk_SOURCES += \ + ../cpuops.cpp \ + ../cpuexec.cpp \ + ../sa1cpu.cpp + +snes9x_gtk_SOURCES += \ + ../cheats.cpp \ + ../cheats2.cpp + +if SDD1_DECOMP +snes9x_gtk_SOURCES += ../sdd1emu.cpp +endif + +if NETPLAY +snes9x_gtk_SOURCES += \ + ../netplay.cpp \ + ../server.cpp +endif + +# Zip support is nonconfigurable. +snes9x_gtk_SOURCES += \ + ../loadzip.cpp \ + ../unzip/unzip.c \ + ../unzip/ioapi.c \ + ../unzip/zip.c +UNZIPDEFINES=-DUNZIP_SUPPORT + +if JMA +snes9x_gtk_LDADD += libjma.a +noinst_LIBRARIES += libjma.a +libjma_a_SOURCES = \ + ../jma/s9x-jma.cpp \ + ../jma/7zlzma.cpp \ + ../jma/crc32.cpp \ + ../jma/iiostrm.cpp \ + ../jma/inbyte.cpp \ + ../jma/jma.cpp \ + ../jma/lzma.cpp \ + ../jma/lzmadec.cpp \ + ../jma/winout.cpp +libjma_a_CPPFLAGS = -fexceptions +endif + +if OPENGL +snes9x_gtk_SOURCES += \ + src/gtk_display_driver_opengl.cpp \ + src/gtk_display_driver_opengl.h +endif + +if XV +snes9x_gtk_SOURCES += \ + src/gtk_display_driver_xv.cpp \ + src/gtk_display_driver_xv.h +endif + +if NETPLAY +snes9x_gtk_SOURCES += \ + src/gtk_netplay_dialog.cpp \ + src/gtk_netplay_dialog.h \ + src/gtk_netplay.cpp \ + src/gtk_netplay.h +endif + +SUFFIXES = .asm .ASM + +src/sourcify: src/sourcify.c + $(CC) src/sourcify.c -o src/sourcify + +src/gtk_glade.cpp: src/sourcify src/snes9x.glade + src/sourcify src/snes9x.glade src/gtk_glade.cpp snes9x_glade + +.asm.o: + $(NASM) -f elf -DELF $(NASM_FLAGS) -i ./ -i ../ -i ../i386/ -i i386/ -o $@ $*.asm + +.ASM.o: + $(NASM) -f elf -DELF $(NASM_FLAGS) -i ./ -i ../ -i ../i386/ -i i386/ $*.ASM -o $@ + diff --git a/gtk/Makefile.in b/gtk/Makefile.in new file mode 100644 index 00000000..79ccfe88 --- /dev/null +++ b/gtk/Makefile.in @@ -0,0 +1,3002 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +bin_PROGRAMS = snes9x-gtk$(EXEEXT) +@PORTAUDIO_TRUE@am__append_1 = \ +@PORTAUDIO_TRUE@ src/gtk_sound_driver_portaudio.cpp \ +@PORTAUDIO_TRUE@ src/gtk_sound_driver_portaudio.h + +@PULSEAUDIO_TRUE@am__append_2 = \ +@PULSEAUDIO_TRUE@ src/gtk_sound_driver_pulse.cpp \ +@PULSEAUDIO_TRUE@ src/gtk_sound_driver_pulse.h + +@OSS_TRUE@am__append_3 = \ +@OSS_TRUE@ src/gtk_sound_driver_oss.h \ +@OSS_TRUE@ src/gtk_sound_driver_oss.cpp + +@SDL_TRUE@am__append_4 = \ +@SDL_TRUE@ src/gtk_sound_driver_sdl.h \ +@SDL_TRUE@ src/gtk_sound_driver_sdl.cpp + +@ALSA_TRUE@am__append_5 = \ +@ALSA_TRUE@ src/gtk_sound_driver_alsa.h \ +@ALSA_TRUE@ src/gtk_sound_driver_alsa.cpp + +@ZSNESFX_TRUE@am__append_6 = \ +@ZSNESFX_TRUE@ ../i386/fxemu2b.asm \ +@ZSNESFX_TRUE@ ../i386/fxemu2.asm \ +@ZSNESFX_TRUE@ ../i386/fxemu2c.asm \ +@ZSNESFX_TRUE@ ../i386/fxtable.asm \ +@ZSNESFX_TRUE@ ../i386/sfxproc.asm \ +@ZSNESFX_TRUE@ ../i386/zsnes.asm + +@ZSNESFX_FALSE@am__append_7 = \ +@ZSNESFX_FALSE@ ../fxinst.cpp \ +@ZSNESFX_FALSE@ ../fxemu.cpp \ +@ZSNESFX_FALSE@ ../fxdbg.cpp + +@ZSNESC4_TRUE@am__append_8 = \ +@ZSNESC4_TRUE@ ../i386/c4.asm \ +@ZSNESC4_TRUE@ ../i386/zsnesc4.asm \ +@ZSNESC4_TRUE@ ../c4.cpp + +@ZSNESC4_FALSE@am__append_9 = \ +@ZSNESC4_FALSE@ ../c4.cpp \ +@ZSNESC4_FALSE@ ../c4emu.cpp + +@SDD1_DECOMP_TRUE@am__append_10 = ../sdd1emu.cpp +@NETPLAY_TRUE@am__append_11 = \ +@NETPLAY_TRUE@ ../netplay.cpp \ +@NETPLAY_TRUE@ ../server.cpp + +@JMA_TRUE@am__append_12 = libjma.a +@JMA_TRUE@am__append_13 = libjma.a +@OPENGL_TRUE@am__append_14 = \ +@OPENGL_TRUE@ src/gtk_display_driver_opengl.cpp \ +@OPENGL_TRUE@ src/gtk_display_driver_opengl.h + +@XV_TRUE@am__append_15 = \ +@XV_TRUE@ src/gtk_display_driver_xv.cpp \ +@XV_TRUE@ src/gtk_display_driver_xv.h + +@NETPLAY_TRUE@am__append_16 = \ +@NETPLAY_TRUE@ src/gtk_netplay_dialog.cpp \ +@NETPLAY_TRUE@ src/gtk_netplay_dialog.h \ +@NETPLAY_TRUE@ src/gtk_netplay.cpp \ +@NETPLAY_TRUE@ src/gtk_netplay.h + +subdir = . +DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/configure AUTHORS compile \ + depcomp install-sh missing mkinstalldirs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +AM_V_AR = $(am__v_AR_$(V)) +am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY)) +am__v_AR_0 = @echo " AR " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +libjma_a_AR = $(AR) $(ARFLAGS) +libjma_a_LIBADD = +am__libjma_a_SOURCES_DIST = ../jma/s9x-jma.cpp ../jma/7zlzma.cpp \ + ../jma/crc32.cpp ../jma/iiostrm.cpp ../jma/inbyte.cpp \ + ../jma/jma.cpp ../jma/lzma.cpp ../jma/lzmadec.cpp \ + ../jma/winout.cpp +am__dirstamp = $(am__leading_dot)dirstamp +@JMA_TRUE@am_libjma_a_OBJECTS = ../jma/libjma_a-s9x-jma.$(OBJEXT) \ +@JMA_TRUE@ ../jma/libjma_a-7zlzma.$(OBJEXT) \ +@JMA_TRUE@ ../jma/libjma_a-crc32.$(OBJEXT) \ +@JMA_TRUE@ ../jma/libjma_a-iiostrm.$(OBJEXT) \ +@JMA_TRUE@ ../jma/libjma_a-inbyte.$(OBJEXT) \ +@JMA_TRUE@ ../jma/libjma_a-jma.$(OBJEXT) \ +@JMA_TRUE@ ../jma/libjma_a-lzma.$(OBJEXT) \ +@JMA_TRUE@ ../jma/libjma_a-lzmadec.$(OBJEXT) \ +@JMA_TRUE@ ../jma/libjma_a-winout.$(OBJEXT) +libjma_a_OBJECTS = $(am_libjma_a_OBJECTS) +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__snes9x_gtk_SOURCES_DIST = src/gtk_sound_driver.h \ + ../filter/2xsai.cpp ../filter/2xsai.h ../filter/epx.cpp \ + ../filter/epx.h ../filter/hq2x.cpp ../filter/hq2x.h \ + src/filter_epx_unsafe.h src/filter_epx_unsafe.cpp \ + src/gtk_binding.cpp src/gtk_binding.h src/gtk_cheat.cpp \ + src/gtk_cheat.h src/gtk_config.cpp src/gtk_config.h \ + src/gtk_control.cpp src/gtk_control.h src/gtk_display.cpp \ + src/gtk_display_driver_gtk.cpp src/gtk_display_driver_gtk.h \ + src/gtk_display_driver.h src/gtk_display.h src/gtk_file.cpp \ + src/gtk_file.h src/gtk_glade.cpp src/gtk_glade_window.cpp \ + src/gtk_glade_window.h src/gtk_preferences.cpp \ + src/gtk_preferences.h src/gtk_s9xcore.h src/gtk_s9x.cpp \ + src/gtk_s9x.h src/gtk_s9xwindow.cpp src/gtk_s9xwindow.h \ + src/gtk_sound.cpp src/gtk_sound.h src/gtk_splash.h \ + src/snes_ntsc_config.h src/snes_ntsc.h src/snes_ntsc_impl.h \ + src/snes_ntsc.c src/gtk_sound_driver_portaudio.cpp \ + src/gtk_sound_driver_portaudio.h \ + src/gtk_sound_driver_pulse.cpp src/gtk_sound_driver_pulse.h \ + src/gtk_sound_driver_oss.h src/gtk_sound_driver_oss.cpp \ + src/gtk_sound_driver_sdl.h src/gtk_sound_driver_sdl.cpp \ + src/gtk_sound_driver_alsa.h src/gtk_sound_driver_alsa.cpp \ + ../i386/fxemu2b.asm ../i386/fxemu2.asm ../i386/fxemu2c.asm \ + ../i386/fxtable.asm ../i386/sfxproc.asm ../i386/zsnes.asm \ + ../fxinst.cpp ../fxemu.cpp ../fxdbg.cpp ../i386/c4.asm \ + ../i386/zsnesc4.asm ../c4.cpp ../c4emu.cpp ../apu/apu.cpp \ + ../apu/SNES_SPC.cpp ../apu/SNES_SPC_misc.cpp \ + ../apu/SNES_SPC_state.cpp ../apu/SPC_DSP.cpp \ + ../apu/SPC_Filter.cpp ../dsp.cpp ../dsp1.cpp ../dsp2.cpp \ + ../dsp3.cpp ../dsp4.cpp ../spc7110.cpp ../obc1.cpp ../seta.cpp \ + ../seta010.cpp ../seta011.cpp ../seta018.cpp ../controls.cpp \ + ../crosshairs.cpp ../cpu.cpp ../sa1.cpp ../debug.cpp \ + ../sdd1.cpp ../tile.cpp ../srtc.cpp ../gfx.cpp ../memmap.cpp \ + ../clip.cpp ../ppu.cpp ../dma.cpp ../snes9x.cpp ../globals.cpp \ + ../reader.cpp ../conffile.cpp ../bsx.cpp ../logger.cpp \ + ../snapshot.cpp ../screenshot.cpp ../movie.cpp ../cpuops.cpp \ + ../cpuexec.cpp ../sa1cpu.cpp ../cheats.cpp ../cheats2.cpp \ + ../sdd1emu.cpp ../netplay.cpp ../server.cpp ../loadzip.cpp \ + ../unzip/unzip.c ../unzip/ioapi.c ../unzip/zip.c \ + src/gtk_display_driver_opengl.cpp \ + src/gtk_display_driver_opengl.h src/gtk_display_driver_xv.cpp \ + src/gtk_display_driver_xv.h src/gtk_netplay_dialog.cpp \ + src/gtk_netplay_dialog.h src/gtk_netplay.cpp src/gtk_netplay.h +@PORTAUDIO_TRUE@am__objects_1 = src/snes9x_gtk-gtk_sound_driver_portaudio.$(OBJEXT) +@PULSEAUDIO_TRUE@am__objects_2 = src/snes9x_gtk-gtk_sound_driver_pulse.$(OBJEXT) +@OSS_TRUE@am__objects_3 = \ +@OSS_TRUE@ src/snes9x_gtk-gtk_sound_driver_oss.$(OBJEXT) +@SDL_TRUE@am__objects_4 = \ +@SDL_TRUE@ src/snes9x_gtk-gtk_sound_driver_sdl.$(OBJEXT) +@ALSA_TRUE@am__objects_5 = \ +@ALSA_TRUE@ src/snes9x_gtk-gtk_sound_driver_alsa.$(OBJEXT) +@ZSNESFX_TRUE@am__objects_6 = ../i386/fxemu2b.$(OBJEXT) \ +@ZSNESFX_TRUE@ ../i386/fxemu2.$(OBJEXT) \ +@ZSNESFX_TRUE@ ../i386/fxemu2c.$(OBJEXT) \ +@ZSNESFX_TRUE@ ../i386/fxtable.$(OBJEXT) \ +@ZSNESFX_TRUE@ ../i386/sfxproc.$(OBJEXT) \ +@ZSNESFX_TRUE@ ../i386/zsnes.$(OBJEXT) +@ZSNESFX_FALSE@am__objects_7 = ../snes9x_gtk-fxinst.$(OBJEXT) \ +@ZSNESFX_FALSE@ ../snes9x_gtk-fxemu.$(OBJEXT) \ +@ZSNESFX_FALSE@ ../snes9x_gtk-fxdbg.$(OBJEXT) +@ZSNESC4_TRUE@am__objects_8 = ../i386/c4.$(OBJEXT) \ +@ZSNESC4_TRUE@ ../i386/zsnesc4.$(OBJEXT) \ +@ZSNESC4_TRUE@ ../snes9x_gtk-c4.$(OBJEXT) +@ZSNESC4_FALSE@am__objects_9 = ../snes9x_gtk-c4.$(OBJEXT) \ +@ZSNESC4_FALSE@ ../snes9x_gtk-c4emu.$(OBJEXT) +@SDD1_DECOMP_TRUE@am__objects_10 = ../snes9x_gtk-sdd1emu.$(OBJEXT) +@NETPLAY_TRUE@am__objects_11 = ../snes9x_gtk-netplay.$(OBJEXT) \ +@NETPLAY_TRUE@ ../snes9x_gtk-server.$(OBJEXT) +@OPENGL_TRUE@am__objects_12 = src/snes9x_gtk-gtk_display_driver_opengl.$(OBJEXT) +@XV_TRUE@am__objects_13 = \ +@XV_TRUE@ src/snes9x_gtk-gtk_display_driver_xv.$(OBJEXT) +@NETPLAY_TRUE@am__objects_14 = \ +@NETPLAY_TRUE@ src/snes9x_gtk-gtk_netplay_dialog.$(OBJEXT) \ +@NETPLAY_TRUE@ src/snes9x_gtk-gtk_netplay.$(OBJEXT) +am_snes9x_gtk_OBJECTS = ../filter/snes9x_gtk-2xsai.$(OBJEXT) \ + ../filter/snes9x_gtk-epx.$(OBJEXT) \ + ../filter/snes9x_gtk-hq2x.$(OBJEXT) \ + src/snes9x_gtk-filter_epx_unsafe.$(OBJEXT) \ + src/snes9x_gtk-gtk_binding.$(OBJEXT) \ + src/snes9x_gtk-gtk_cheat.$(OBJEXT) \ + src/snes9x_gtk-gtk_config.$(OBJEXT) \ + src/snes9x_gtk-gtk_control.$(OBJEXT) \ + src/snes9x_gtk-gtk_display.$(OBJEXT) \ + src/snes9x_gtk-gtk_display_driver_gtk.$(OBJEXT) \ + src/snes9x_gtk-gtk_file.$(OBJEXT) \ + src/snes9x_gtk-gtk_glade.$(OBJEXT) \ + src/snes9x_gtk-gtk_glade_window.$(OBJEXT) \ + src/snes9x_gtk-gtk_preferences.$(OBJEXT) \ + src/snes9x_gtk-gtk_s9x.$(OBJEXT) \ + src/snes9x_gtk-gtk_s9xwindow.$(OBJEXT) \ + src/snes9x_gtk-gtk_sound.$(OBJEXT) src/snes_ntsc.$(OBJEXT) \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) $(am__objects_5) $(am__objects_6) \ + $(am__objects_7) $(am__objects_8) $(am__objects_9) \ + ../apu/snes9x_gtk-apu.$(OBJEXT) \ + ../apu/snes9x_gtk-SNES_SPC.$(OBJEXT) \ + ../apu/snes9x_gtk-SNES_SPC_misc.$(OBJEXT) \ + ../apu/snes9x_gtk-SNES_SPC_state.$(OBJEXT) \ + ../apu/snes9x_gtk-SPC_DSP.$(OBJEXT) \ + ../apu/snes9x_gtk-SPC_Filter.$(OBJEXT) \ + ../snes9x_gtk-dsp.$(OBJEXT) ../snes9x_gtk-dsp1.$(OBJEXT) \ + ../snes9x_gtk-dsp2.$(OBJEXT) ../snes9x_gtk-dsp3.$(OBJEXT) \ + ../snes9x_gtk-dsp4.$(OBJEXT) ../snes9x_gtk-spc7110.$(OBJEXT) \ + ../snes9x_gtk-obc1.$(OBJEXT) ../snes9x_gtk-seta.$(OBJEXT) \ + ../snes9x_gtk-seta010.$(OBJEXT) \ + ../snes9x_gtk-seta011.$(OBJEXT) \ + ../snes9x_gtk-seta018.$(OBJEXT) \ + ../snes9x_gtk-controls.$(OBJEXT) \ + ../snes9x_gtk-crosshairs.$(OBJEXT) ../snes9x_gtk-cpu.$(OBJEXT) \ + ../snes9x_gtk-sa1.$(OBJEXT) ../snes9x_gtk-debug.$(OBJEXT) \ + ../snes9x_gtk-sdd1.$(OBJEXT) ../snes9x_gtk-tile.$(OBJEXT) \ + ../snes9x_gtk-srtc.$(OBJEXT) ../snes9x_gtk-gfx.$(OBJEXT) \ + ../snes9x_gtk-memmap.$(OBJEXT) ../snes9x_gtk-clip.$(OBJEXT) \ + ../snes9x_gtk-ppu.$(OBJEXT) ../snes9x_gtk-dma.$(OBJEXT) \ + ../snes9x_gtk-snes9x.$(OBJEXT) ../snes9x_gtk-globals.$(OBJEXT) \ + ../snes9x_gtk-reader.$(OBJEXT) \ + ../snes9x_gtk-conffile.$(OBJEXT) ../snes9x_gtk-bsx.$(OBJEXT) \ + ../snes9x_gtk-logger.$(OBJEXT) \ + ../snes9x_gtk-snapshot.$(OBJEXT) \ + ../snes9x_gtk-screenshot.$(OBJEXT) \ + ../snes9x_gtk-movie.$(OBJEXT) ../snes9x_gtk-cpuops.$(OBJEXT) \ + ../snes9x_gtk-cpuexec.$(OBJEXT) ../snes9x_gtk-sa1cpu.$(OBJEXT) \ + ../snes9x_gtk-cheats.$(OBJEXT) ../snes9x_gtk-cheats2.$(OBJEXT) \ + $(am__objects_10) $(am__objects_11) \ + ../snes9x_gtk-loadzip.$(OBJEXT) ../unzip/unzip.$(OBJEXT) \ + ../unzip/ioapi.$(OBJEXT) ../unzip/zip.$(OBJEXT) \ + $(am__objects_12) $(am__objects_13) $(am__objects_14) +snes9x_gtk_OBJECTS = $(am_snes9x_gtk_OBJECTS) +snes9x_gtk_DEPENDENCIES = $(am__append_12) +snes9x_gtk_LINK = $(CXXLD) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_$(V)) +am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY)) +am__v_CXX_0 = @echo " CXX " $@; +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_$(V)) +am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CXXLD_0 = @echo " CXXLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libjma_a_SOURCES) $(snes9x_gtk_SOURCES) +DIST_SOURCES = $(am__libjma_a_SOURCES_DIST) \ + $(am__snes9x_gtk_SOURCES_DIST) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADE_CFLAGS = @GLADE_CFLAGS@ +GLADE_LIBS = @GLADE_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GREP = @GREP@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ +LIBS = @LIBS@ +LIBXML_CFLAGS = @LIBXML_CFLAGS@ +LIBXML_LIBS = @LIBXML_LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NASM = @NASM@ +NASM_FLAGS = @NASM_FLAGS@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POFILES = @POFILES@ +PORTAUDIO_CFLAGS = @PORTAUDIO_CFLAGS@ +PORTAUDIO_LIBS = @PORTAUDIO_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ +PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ +RANLIB = @RANLIB@ +SDLCONFIGFOUND = @SDLCONFIGFOUND@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XRANDR_CFLAGS = @XRANDR_CFLAGS@ +XRANDR_LIBS = @XRANDR_LIBS@ +XV_CFLAGS = @XV_CFLAGS@ +XV_LIBS = @XV_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +prog_nasm = @prog_nasm@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +snes9xlocaledir = @snes9xlocaledir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = data po +snes9x_gtk_LDADD = $(am__append_12) +@DEBUG_FALSE@snes9x_gtk_CXXFLAGS = -fno-exceptions -fno-rtti +noinst_LIBRARIES = $(am__append_13) +INCLUDES = -I$(top_srcdir) -I.. -DSNES9XLOCALEDIR=\""$(snes9xlocaledir)"\" +CLEANFILES = \ + src/gtk_glade.cpp \ + src/sourcify + + +# APU + +# DSP + +# Base + +# ASMCPU Doesn't exist anymore. + +# Zip support is nonconfigurable. +snes9x_gtk_SOURCES = src/gtk_sound_driver.h ../filter/2xsai.cpp \ + ../filter/2xsai.h ../filter/epx.cpp ../filter/epx.h \ + ../filter/hq2x.cpp ../filter/hq2x.h src/filter_epx_unsafe.h \ + src/filter_epx_unsafe.cpp src/gtk_binding.cpp \ + src/gtk_binding.h src/gtk_cheat.cpp src/gtk_cheat.h \ + src/gtk_config.cpp src/gtk_config.h src/gtk_control.cpp \ + src/gtk_control.h src/gtk_display.cpp \ + src/gtk_display_driver_gtk.cpp src/gtk_display_driver_gtk.h \ + src/gtk_display_driver.h src/gtk_display.h src/gtk_file.cpp \ + src/gtk_file.h src/gtk_glade.cpp src/gtk_glade_window.cpp \ + src/gtk_glade_window.h src/gtk_preferences.cpp \ + src/gtk_preferences.h src/gtk_s9xcore.h src/gtk_s9x.cpp \ + src/gtk_s9x.h src/gtk_s9xwindow.cpp src/gtk_s9xwindow.h \ + src/gtk_sound.cpp src/gtk_sound.h src/gtk_splash.h \ + src/snes_ntsc_config.h src/snes_ntsc.h src/snes_ntsc_impl.h \ + src/snes_ntsc.c $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_4) $(am__append_5) \ + $(am__append_6) $(am__append_7) $(am__append_8) \ + $(am__append_9) ../apu/apu.cpp ../apu/SNES_SPC.cpp \ + ../apu/SNES_SPC_misc.cpp ../apu/SNES_SPC_state.cpp \ + ../apu/SPC_DSP.cpp ../apu/SPC_Filter.cpp ../dsp.cpp \ + ../dsp1.cpp ../dsp2.cpp ../dsp3.cpp ../dsp4.cpp ../spc7110.cpp \ + ../obc1.cpp ../seta.cpp ../seta010.cpp ../seta011.cpp \ + ../seta018.cpp ../controls.cpp ../crosshairs.cpp ../cpu.cpp \ + ../sa1.cpp ../debug.cpp ../sdd1.cpp ../tile.cpp ../srtc.cpp \ + ../gfx.cpp ../memmap.cpp ../clip.cpp ../ppu.cpp ../dma.cpp \ + ../snes9x.cpp ../globals.cpp ../reader.cpp ../conffile.cpp \ + ../bsx.cpp ../logger.cpp ../snapshot.cpp ../screenshot.cpp \ + ../movie.cpp ../cpuops.cpp ../cpuexec.cpp ../sa1cpu.cpp \ + ../cheats.cpp ../cheats2.cpp $(am__append_10) $(am__append_11) \ + ../loadzip.cpp ../unzip/unzip.c ../unzip/ioapi.c \ + ../unzip/zip.c $(am__append_14) $(am__append_15) \ + $(am__append_16) +UNZIPDEFINES = -DUNZIP_SUPPORT +@JMA_TRUE@libjma_a_SOURCES = \ +@JMA_TRUE@ ../jma/s9x-jma.cpp \ +@JMA_TRUE@ ../jma/7zlzma.cpp \ +@JMA_TRUE@ ../jma/crc32.cpp \ +@JMA_TRUE@ ../jma/iiostrm.cpp \ +@JMA_TRUE@ ../jma/inbyte.cpp \ +@JMA_TRUE@ ../jma/jma.cpp \ +@JMA_TRUE@ ../jma/lzma.cpp \ +@JMA_TRUE@ ../jma/lzmadec.cpp \ +@JMA_TRUE@ ../jma/winout.cpp + +@JMA_TRUE@libjma_a_CPPFLAGS = -fexceptions +SUFFIXES = .asm .ASM +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .asm .ASM .c .cpp .o .obj +am--refresh: + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +../jma/$(am__dirstamp): + @$(MKDIR_P) ../jma + @: > ../jma/$(am__dirstamp) +../jma/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ../jma/$(DEPDIR) + @: > ../jma/$(DEPDIR)/$(am__dirstamp) +../jma/libjma_a-s9x-jma.$(OBJEXT): ../jma/$(am__dirstamp) \ + ../jma/$(DEPDIR)/$(am__dirstamp) +../jma/libjma_a-7zlzma.$(OBJEXT): ../jma/$(am__dirstamp) \ + ../jma/$(DEPDIR)/$(am__dirstamp) +../jma/libjma_a-crc32.$(OBJEXT): ../jma/$(am__dirstamp) \ + ../jma/$(DEPDIR)/$(am__dirstamp) +../jma/libjma_a-iiostrm.$(OBJEXT): ../jma/$(am__dirstamp) \ + ../jma/$(DEPDIR)/$(am__dirstamp) +../jma/libjma_a-inbyte.$(OBJEXT): ../jma/$(am__dirstamp) \ + ../jma/$(DEPDIR)/$(am__dirstamp) +../jma/libjma_a-jma.$(OBJEXT): ../jma/$(am__dirstamp) \ + ../jma/$(DEPDIR)/$(am__dirstamp) +../jma/libjma_a-lzma.$(OBJEXT): ../jma/$(am__dirstamp) \ + ../jma/$(DEPDIR)/$(am__dirstamp) +../jma/libjma_a-lzmadec.$(OBJEXT): ../jma/$(am__dirstamp) \ + ../jma/$(DEPDIR)/$(am__dirstamp) +../jma/libjma_a-winout.$(OBJEXT): ../jma/$(am__dirstamp) \ + ../jma/$(DEPDIR)/$(am__dirstamp) +libjma.a: $(libjma_a_OBJECTS) $(libjma_a_DEPENDENCIES) + $(AM_V_at)-rm -f libjma.a + $(AM_V_AR)$(libjma_a_AR) libjma.a $(libjma_a_OBJECTS) $(libjma_a_LIBADD) + $(AM_V_at)$(RANLIB) libjma.a +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +../filter/$(am__dirstamp): + @$(MKDIR_P) ../filter + @: > ../filter/$(am__dirstamp) +../filter/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ../filter/$(DEPDIR) + @: > ../filter/$(DEPDIR)/$(am__dirstamp) +../filter/snes9x_gtk-2xsai.$(OBJEXT): ../filter/$(am__dirstamp) \ + ../filter/$(DEPDIR)/$(am__dirstamp) +../filter/snes9x_gtk-epx.$(OBJEXT): ../filter/$(am__dirstamp) \ + ../filter/$(DEPDIR)/$(am__dirstamp) +../filter/snes9x_gtk-hq2x.$(OBJEXT): ../filter/$(am__dirstamp) \ + ../filter/$(DEPDIR)/$(am__dirstamp) +src/$(am__dirstamp): + @$(MKDIR_P) src + @: > src/$(am__dirstamp) +src/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) src/$(DEPDIR) + @: > src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-filter_epx_unsafe.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_binding.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_cheat.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_config.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_control.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_display.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_display_driver_gtk.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_file.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_glade.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_glade_window.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_preferences.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_s9x.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_s9xwindow.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_sound.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes_ntsc.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_sound_driver_portaudio.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_sound_driver_pulse.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_sound_driver_oss.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_sound_driver_sdl.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_sound_driver_alsa.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +../i386/$(am__dirstamp): + @$(MKDIR_P) ../i386 + @: > ../i386/$(am__dirstamp) +../i386/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ../i386/$(DEPDIR) + @: > ../i386/$(DEPDIR)/$(am__dirstamp) +../i386/fxemu2b.$(OBJEXT): ../i386/$(am__dirstamp) \ + ../i386/$(DEPDIR)/$(am__dirstamp) +../i386/fxemu2.$(OBJEXT): ../i386/$(am__dirstamp) \ + ../i386/$(DEPDIR)/$(am__dirstamp) +../i386/fxemu2c.$(OBJEXT): ../i386/$(am__dirstamp) \ + ../i386/$(DEPDIR)/$(am__dirstamp) +../i386/fxtable.$(OBJEXT): ../i386/$(am__dirstamp) \ + ../i386/$(DEPDIR)/$(am__dirstamp) +../i386/sfxproc.$(OBJEXT): ../i386/$(am__dirstamp) \ + ../i386/$(DEPDIR)/$(am__dirstamp) +../i386/zsnes.$(OBJEXT): ../i386/$(am__dirstamp) \ + ../i386/$(DEPDIR)/$(am__dirstamp) +../$(am__dirstamp): + @$(MKDIR_P) .. + @: > ../$(am__dirstamp) +../$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ../$(DEPDIR) + @: > ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-fxinst.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-fxemu.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-fxdbg.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../i386/c4.$(OBJEXT): ../i386/$(am__dirstamp) \ + ../i386/$(DEPDIR)/$(am__dirstamp) +../i386/zsnesc4.$(OBJEXT): ../i386/$(am__dirstamp) \ + ../i386/$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-c4.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-c4emu.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../apu/$(am__dirstamp): + @$(MKDIR_P) ../apu + @: > ../apu/$(am__dirstamp) +../apu/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ../apu/$(DEPDIR) + @: > ../apu/$(DEPDIR)/$(am__dirstamp) +../apu/snes9x_gtk-apu.$(OBJEXT): ../apu/$(am__dirstamp) \ + ../apu/$(DEPDIR)/$(am__dirstamp) +../apu/snes9x_gtk-SNES_SPC.$(OBJEXT): ../apu/$(am__dirstamp) \ + ../apu/$(DEPDIR)/$(am__dirstamp) +../apu/snes9x_gtk-SNES_SPC_misc.$(OBJEXT): ../apu/$(am__dirstamp) \ + ../apu/$(DEPDIR)/$(am__dirstamp) +../apu/snes9x_gtk-SNES_SPC_state.$(OBJEXT): ../apu/$(am__dirstamp) \ + ../apu/$(DEPDIR)/$(am__dirstamp) +../apu/snes9x_gtk-SPC_DSP.$(OBJEXT): ../apu/$(am__dirstamp) \ + ../apu/$(DEPDIR)/$(am__dirstamp) +../apu/snes9x_gtk-SPC_Filter.$(OBJEXT): ../apu/$(am__dirstamp) \ + ../apu/$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-dsp.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-dsp1.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-dsp2.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-dsp3.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-dsp4.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-spc7110.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-obc1.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-seta.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-seta010.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-seta011.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-seta018.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-controls.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-crosshairs.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-cpu.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-sa1.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-debug.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-sdd1.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-tile.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-srtc.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-gfx.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-memmap.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-clip.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-ppu.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-dma.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-snes9x.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-globals.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-reader.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-conffile.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-bsx.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-logger.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-snapshot.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-screenshot.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-movie.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-cpuops.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-cpuexec.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-sa1cpu.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-cheats.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-cheats2.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-sdd1emu.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-netplay.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-server.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../snes9x_gtk-loadzip.$(OBJEXT): ../$(am__dirstamp) \ + ../$(DEPDIR)/$(am__dirstamp) +../unzip/$(am__dirstamp): + @$(MKDIR_P) ../unzip + @: > ../unzip/$(am__dirstamp) +../unzip/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ../unzip/$(DEPDIR) + @: > ../unzip/$(DEPDIR)/$(am__dirstamp) +../unzip/unzip.$(OBJEXT): ../unzip/$(am__dirstamp) \ + ../unzip/$(DEPDIR)/$(am__dirstamp) +../unzip/ioapi.$(OBJEXT): ../unzip/$(am__dirstamp) \ + ../unzip/$(DEPDIR)/$(am__dirstamp) +../unzip/zip.$(OBJEXT): ../unzip/$(am__dirstamp) \ + ../unzip/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_display_driver_opengl.$(OBJEXT): \ + src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_display_driver_xv.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_netplay_dialog.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +src/snes9x_gtk-gtk_netplay.$(OBJEXT): src/$(am__dirstamp) \ + src/$(DEPDIR)/$(am__dirstamp) +snes9x-gtk$(EXEEXT): $(snes9x_gtk_OBJECTS) $(snes9x_gtk_DEPENDENCIES) + @rm -f snes9x-gtk$(EXEEXT) + $(AM_V_CXXLD)$(snes9x_gtk_LINK) $(snes9x_gtk_OBJECTS) $(snes9x_gtk_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f ../apu/snes9x_gtk-SNES_SPC.$(OBJEXT) + -rm -f ../apu/snes9x_gtk-SNES_SPC_misc.$(OBJEXT) + -rm -f ../apu/snes9x_gtk-SNES_SPC_state.$(OBJEXT) + -rm -f ../apu/snes9x_gtk-SPC_DSP.$(OBJEXT) + -rm -f ../apu/snes9x_gtk-SPC_Filter.$(OBJEXT) + -rm -f ../apu/snes9x_gtk-apu.$(OBJEXT) + -rm -f ../filter/snes9x_gtk-2xsai.$(OBJEXT) + -rm -f ../filter/snes9x_gtk-epx.$(OBJEXT) + -rm -f ../filter/snes9x_gtk-hq2x.$(OBJEXT) + -rm -f ../i386/c4.$(OBJEXT) + -rm -f ../i386/fxemu2.$(OBJEXT) + -rm -f ../i386/fxemu2b.$(OBJEXT) + -rm -f ../i386/fxemu2c.$(OBJEXT) + -rm -f ../i386/fxtable.$(OBJEXT) + -rm -f ../i386/sfxproc.$(OBJEXT) + -rm -f ../i386/zsnes.$(OBJEXT) + -rm -f ../i386/zsnesc4.$(OBJEXT) + -rm -f ../jma/libjma_a-7zlzma.$(OBJEXT) + -rm -f ../jma/libjma_a-crc32.$(OBJEXT) + -rm -f ../jma/libjma_a-iiostrm.$(OBJEXT) + -rm -f ../jma/libjma_a-inbyte.$(OBJEXT) + -rm -f ../jma/libjma_a-jma.$(OBJEXT) + -rm -f ../jma/libjma_a-lzma.$(OBJEXT) + -rm -f ../jma/libjma_a-lzmadec.$(OBJEXT) + -rm -f ../jma/libjma_a-s9x-jma.$(OBJEXT) + -rm -f ../jma/libjma_a-winout.$(OBJEXT) + -rm -f ../snes9x_gtk-bsx.$(OBJEXT) + -rm -f ../snes9x_gtk-c4.$(OBJEXT) + -rm -f ../snes9x_gtk-c4emu.$(OBJEXT) + -rm -f ../snes9x_gtk-cheats.$(OBJEXT) + -rm -f ../snes9x_gtk-cheats2.$(OBJEXT) + -rm -f ../snes9x_gtk-clip.$(OBJEXT) + -rm -f ../snes9x_gtk-conffile.$(OBJEXT) + -rm -f ../snes9x_gtk-controls.$(OBJEXT) + -rm -f ../snes9x_gtk-cpu.$(OBJEXT) + -rm -f ../snes9x_gtk-cpuexec.$(OBJEXT) + -rm -f ../snes9x_gtk-cpuops.$(OBJEXT) + -rm -f ../snes9x_gtk-crosshairs.$(OBJEXT) + -rm -f ../snes9x_gtk-debug.$(OBJEXT) + -rm -f ../snes9x_gtk-dma.$(OBJEXT) + -rm -f ../snes9x_gtk-dsp.$(OBJEXT) + -rm -f ../snes9x_gtk-dsp1.$(OBJEXT) + -rm -f ../snes9x_gtk-dsp2.$(OBJEXT) + -rm -f ../snes9x_gtk-dsp3.$(OBJEXT) + -rm -f ../snes9x_gtk-dsp4.$(OBJEXT) + -rm -f ../snes9x_gtk-fxdbg.$(OBJEXT) + -rm -f ../snes9x_gtk-fxemu.$(OBJEXT) + -rm -f ../snes9x_gtk-fxinst.$(OBJEXT) + -rm -f ../snes9x_gtk-gfx.$(OBJEXT) + -rm -f ../snes9x_gtk-globals.$(OBJEXT) + -rm -f ../snes9x_gtk-loadzip.$(OBJEXT) + -rm -f ../snes9x_gtk-logger.$(OBJEXT) + -rm -f ../snes9x_gtk-memmap.$(OBJEXT) + -rm -f ../snes9x_gtk-movie.$(OBJEXT) + -rm -f ../snes9x_gtk-netplay.$(OBJEXT) + -rm -f ../snes9x_gtk-obc1.$(OBJEXT) + -rm -f ../snes9x_gtk-ppu.$(OBJEXT) + -rm -f ../snes9x_gtk-reader.$(OBJEXT) + -rm -f ../snes9x_gtk-sa1.$(OBJEXT) + -rm -f ../snes9x_gtk-sa1cpu.$(OBJEXT) + -rm -f ../snes9x_gtk-screenshot.$(OBJEXT) + -rm -f ../snes9x_gtk-sdd1.$(OBJEXT) + -rm -f ../snes9x_gtk-sdd1emu.$(OBJEXT) + -rm -f ../snes9x_gtk-server.$(OBJEXT) + -rm -f ../snes9x_gtk-seta.$(OBJEXT) + -rm -f ../snes9x_gtk-seta010.$(OBJEXT) + -rm -f ../snes9x_gtk-seta011.$(OBJEXT) + -rm -f ../snes9x_gtk-seta018.$(OBJEXT) + -rm -f ../snes9x_gtk-snapshot.$(OBJEXT) + -rm -f ../snes9x_gtk-snes9x.$(OBJEXT) + -rm -f ../snes9x_gtk-spc7110.$(OBJEXT) + -rm -f ../snes9x_gtk-srtc.$(OBJEXT) + -rm -f ../snes9x_gtk-tile.$(OBJEXT) + -rm -f ../unzip/ioapi.$(OBJEXT) + -rm -f ../unzip/unzip.$(OBJEXT) + -rm -f ../unzip/zip.$(OBJEXT) + -rm -f src/snes9x_gtk-filter_epx_unsafe.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_binding.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_cheat.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_config.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_control.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_display.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_display_driver_gtk.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_display_driver_opengl.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_display_driver_xv.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_file.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_glade.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_glade_window.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_netplay.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_netplay_dialog.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_preferences.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_s9x.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_s9xwindow.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_sound.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_sound_driver_alsa.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_sound_driver_oss.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_sound_driver_portaudio.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_sound_driver_pulse.$(OBJEXT) + -rm -f src/snes9x_gtk-gtk_sound_driver_sdl.$(OBJEXT) + -rm -f src/snes_ntsc.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-bsx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-c4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-c4emu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-cheats.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-cheats2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-clip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-conffile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-controls.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-cpu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-cpuexec.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-cpuops.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-crosshairs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-debug.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-dma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-dsp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-dsp1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-dsp2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-dsp3.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-dsp4.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-fxdbg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-fxemu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-fxinst.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-gfx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-globals.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-loadzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-logger.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-memmap.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-movie.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-netplay.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-obc1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-ppu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-reader.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-sa1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-sa1cpu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-screenshot.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-sdd1.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-sdd1emu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-server.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-seta.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-seta010.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-seta011.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-seta018.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-snapshot.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-snes9x.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-spc7110.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-srtc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../$(DEPDIR)/snes9x_gtk-tile.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_misc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_state.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../apu/$(DEPDIR)/snes9x_gtk-SPC_DSP.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../apu/$(DEPDIR)/snes9x_gtk-SPC_Filter.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../apu/$(DEPDIR)/snes9x_gtk-apu.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../filter/$(DEPDIR)/snes9x_gtk-2xsai.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../filter/$(DEPDIR)/snes9x_gtk-epx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../filter/$(DEPDIR)/snes9x_gtk-hq2x.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../jma/$(DEPDIR)/libjma_a-7zlzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../jma/$(DEPDIR)/libjma_a-crc32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../jma/$(DEPDIR)/libjma_a-iiostrm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../jma/$(DEPDIR)/libjma_a-inbyte.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../jma/$(DEPDIR)/libjma_a-jma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../jma/$(DEPDIR)/libjma_a-lzma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../jma/$(DEPDIR)/libjma_a-lzmadec.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../jma/$(DEPDIR)/libjma_a-s9x-jma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../jma/$(DEPDIR)/libjma_a-winout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../unzip/$(DEPDIR)/ioapi.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../unzip/$(DEPDIR)/unzip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@../unzip/$(DEPDIR)/zip.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-filter_epx_unsafe.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_binding.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_cheat.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_control.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_display.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_gtk.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_opengl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_xv.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_file.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_glade.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_glade_window.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_netplay.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_netplay_dialog.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_preferences.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_s9x.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_s9xwindow.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_sound.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_alsa.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_oss.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_portaudio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_pulse.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_sdl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/snes_ntsc.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +../jma/libjma_a-s9x-jma.o: ../jma/s9x-jma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-s9x-jma.o -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-s9x-jma.Tpo -c -o ../jma/libjma_a-s9x-jma.o `test -f '../jma/s9x-jma.cpp' || echo '$(srcdir)/'`../jma/s9x-jma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-s9x-jma.Tpo ../jma/$(DEPDIR)/libjma_a-s9x-jma.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/s9x-jma.cpp' object='../jma/libjma_a-s9x-jma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-s9x-jma.o `test -f '../jma/s9x-jma.cpp' || echo '$(srcdir)/'`../jma/s9x-jma.cpp + +../jma/libjma_a-s9x-jma.obj: ../jma/s9x-jma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-s9x-jma.obj -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-s9x-jma.Tpo -c -o ../jma/libjma_a-s9x-jma.obj `if test -f '../jma/s9x-jma.cpp'; then $(CYGPATH_W) '../jma/s9x-jma.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/s9x-jma.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-s9x-jma.Tpo ../jma/$(DEPDIR)/libjma_a-s9x-jma.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/s9x-jma.cpp' object='../jma/libjma_a-s9x-jma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-s9x-jma.obj `if test -f '../jma/s9x-jma.cpp'; then $(CYGPATH_W) '../jma/s9x-jma.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/s9x-jma.cpp'; fi` + +../jma/libjma_a-7zlzma.o: ../jma/7zlzma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-7zlzma.o -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-7zlzma.Tpo -c -o ../jma/libjma_a-7zlzma.o `test -f '../jma/7zlzma.cpp' || echo '$(srcdir)/'`../jma/7zlzma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-7zlzma.Tpo ../jma/$(DEPDIR)/libjma_a-7zlzma.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/7zlzma.cpp' object='../jma/libjma_a-7zlzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-7zlzma.o `test -f '../jma/7zlzma.cpp' || echo '$(srcdir)/'`../jma/7zlzma.cpp + +../jma/libjma_a-7zlzma.obj: ../jma/7zlzma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-7zlzma.obj -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-7zlzma.Tpo -c -o ../jma/libjma_a-7zlzma.obj `if test -f '../jma/7zlzma.cpp'; then $(CYGPATH_W) '../jma/7zlzma.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/7zlzma.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-7zlzma.Tpo ../jma/$(DEPDIR)/libjma_a-7zlzma.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/7zlzma.cpp' object='../jma/libjma_a-7zlzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-7zlzma.obj `if test -f '../jma/7zlzma.cpp'; then $(CYGPATH_W) '../jma/7zlzma.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/7zlzma.cpp'; fi` + +../jma/libjma_a-crc32.o: ../jma/crc32.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-crc32.o -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-crc32.Tpo -c -o ../jma/libjma_a-crc32.o `test -f '../jma/crc32.cpp' || echo '$(srcdir)/'`../jma/crc32.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-crc32.Tpo ../jma/$(DEPDIR)/libjma_a-crc32.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/crc32.cpp' object='../jma/libjma_a-crc32.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-crc32.o `test -f '../jma/crc32.cpp' || echo '$(srcdir)/'`../jma/crc32.cpp + +../jma/libjma_a-crc32.obj: ../jma/crc32.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-crc32.obj -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-crc32.Tpo -c -o ../jma/libjma_a-crc32.obj `if test -f '../jma/crc32.cpp'; then $(CYGPATH_W) '../jma/crc32.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/crc32.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-crc32.Tpo ../jma/$(DEPDIR)/libjma_a-crc32.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/crc32.cpp' object='../jma/libjma_a-crc32.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-crc32.obj `if test -f '../jma/crc32.cpp'; then $(CYGPATH_W) '../jma/crc32.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/crc32.cpp'; fi` + +../jma/libjma_a-iiostrm.o: ../jma/iiostrm.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-iiostrm.o -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-iiostrm.Tpo -c -o ../jma/libjma_a-iiostrm.o `test -f '../jma/iiostrm.cpp' || echo '$(srcdir)/'`../jma/iiostrm.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-iiostrm.Tpo ../jma/$(DEPDIR)/libjma_a-iiostrm.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/iiostrm.cpp' object='../jma/libjma_a-iiostrm.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-iiostrm.o `test -f '../jma/iiostrm.cpp' || echo '$(srcdir)/'`../jma/iiostrm.cpp + +../jma/libjma_a-iiostrm.obj: ../jma/iiostrm.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-iiostrm.obj -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-iiostrm.Tpo -c -o ../jma/libjma_a-iiostrm.obj `if test -f '../jma/iiostrm.cpp'; then $(CYGPATH_W) '../jma/iiostrm.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/iiostrm.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-iiostrm.Tpo ../jma/$(DEPDIR)/libjma_a-iiostrm.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/iiostrm.cpp' object='../jma/libjma_a-iiostrm.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-iiostrm.obj `if test -f '../jma/iiostrm.cpp'; then $(CYGPATH_W) '../jma/iiostrm.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/iiostrm.cpp'; fi` + +../jma/libjma_a-inbyte.o: ../jma/inbyte.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-inbyte.o -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-inbyte.Tpo -c -o ../jma/libjma_a-inbyte.o `test -f '../jma/inbyte.cpp' || echo '$(srcdir)/'`../jma/inbyte.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-inbyte.Tpo ../jma/$(DEPDIR)/libjma_a-inbyte.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/inbyte.cpp' object='../jma/libjma_a-inbyte.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-inbyte.o `test -f '../jma/inbyte.cpp' || echo '$(srcdir)/'`../jma/inbyte.cpp + +../jma/libjma_a-inbyte.obj: ../jma/inbyte.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-inbyte.obj -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-inbyte.Tpo -c -o ../jma/libjma_a-inbyte.obj `if test -f '../jma/inbyte.cpp'; then $(CYGPATH_W) '../jma/inbyte.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/inbyte.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-inbyte.Tpo ../jma/$(DEPDIR)/libjma_a-inbyte.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/inbyte.cpp' object='../jma/libjma_a-inbyte.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-inbyte.obj `if test -f '../jma/inbyte.cpp'; then $(CYGPATH_W) '../jma/inbyte.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/inbyte.cpp'; fi` + +../jma/libjma_a-jma.o: ../jma/jma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-jma.o -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-jma.Tpo -c -o ../jma/libjma_a-jma.o `test -f '../jma/jma.cpp' || echo '$(srcdir)/'`../jma/jma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-jma.Tpo ../jma/$(DEPDIR)/libjma_a-jma.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/jma.cpp' object='../jma/libjma_a-jma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-jma.o `test -f '../jma/jma.cpp' || echo '$(srcdir)/'`../jma/jma.cpp + +../jma/libjma_a-jma.obj: ../jma/jma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-jma.obj -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-jma.Tpo -c -o ../jma/libjma_a-jma.obj `if test -f '../jma/jma.cpp'; then $(CYGPATH_W) '../jma/jma.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/jma.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-jma.Tpo ../jma/$(DEPDIR)/libjma_a-jma.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/jma.cpp' object='../jma/libjma_a-jma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-jma.obj `if test -f '../jma/jma.cpp'; then $(CYGPATH_W) '../jma/jma.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/jma.cpp'; fi` + +../jma/libjma_a-lzma.o: ../jma/lzma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-lzma.o -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-lzma.Tpo -c -o ../jma/libjma_a-lzma.o `test -f '../jma/lzma.cpp' || echo '$(srcdir)/'`../jma/lzma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-lzma.Tpo ../jma/$(DEPDIR)/libjma_a-lzma.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/lzma.cpp' object='../jma/libjma_a-lzma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-lzma.o `test -f '../jma/lzma.cpp' || echo '$(srcdir)/'`../jma/lzma.cpp + +../jma/libjma_a-lzma.obj: ../jma/lzma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-lzma.obj -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-lzma.Tpo -c -o ../jma/libjma_a-lzma.obj `if test -f '../jma/lzma.cpp'; then $(CYGPATH_W) '../jma/lzma.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/lzma.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-lzma.Tpo ../jma/$(DEPDIR)/libjma_a-lzma.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/lzma.cpp' object='../jma/libjma_a-lzma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-lzma.obj `if test -f '../jma/lzma.cpp'; then $(CYGPATH_W) '../jma/lzma.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/lzma.cpp'; fi` + +../jma/libjma_a-lzmadec.o: ../jma/lzmadec.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-lzmadec.o -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-lzmadec.Tpo -c -o ../jma/libjma_a-lzmadec.o `test -f '../jma/lzmadec.cpp' || echo '$(srcdir)/'`../jma/lzmadec.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-lzmadec.Tpo ../jma/$(DEPDIR)/libjma_a-lzmadec.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/lzmadec.cpp' object='../jma/libjma_a-lzmadec.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-lzmadec.o `test -f '../jma/lzmadec.cpp' || echo '$(srcdir)/'`../jma/lzmadec.cpp + +../jma/libjma_a-lzmadec.obj: ../jma/lzmadec.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-lzmadec.obj -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-lzmadec.Tpo -c -o ../jma/libjma_a-lzmadec.obj `if test -f '../jma/lzmadec.cpp'; then $(CYGPATH_W) '../jma/lzmadec.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/lzmadec.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-lzmadec.Tpo ../jma/$(DEPDIR)/libjma_a-lzmadec.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/lzmadec.cpp' object='../jma/libjma_a-lzmadec.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-lzmadec.obj `if test -f '../jma/lzmadec.cpp'; then $(CYGPATH_W) '../jma/lzmadec.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/lzmadec.cpp'; fi` + +../jma/libjma_a-winout.o: ../jma/winout.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-winout.o -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-winout.Tpo -c -o ../jma/libjma_a-winout.o `test -f '../jma/winout.cpp' || echo '$(srcdir)/'`../jma/winout.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-winout.Tpo ../jma/$(DEPDIR)/libjma_a-winout.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/winout.cpp' object='../jma/libjma_a-winout.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-winout.o `test -f '../jma/winout.cpp' || echo '$(srcdir)/'`../jma/winout.cpp + +../jma/libjma_a-winout.obj: ../jma/winout.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ../jma/libjma_a-winout.obj -MD -MP -MF ../jma/$(DEPDIR)/libjma_a-winout.Tpo -c -o ../jma/libjma_a-winout.obj `if test -f '../jma/winout.cpp'; then $(CYGPATH_W) '../jma/winout.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/winout.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../jma/$(DEPDIR)/libjma_a-winout.Tpo ../jma/$(DEPDIR)/libjma_a-winout.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../jma/winout.cpp' object='../jma/libjma_a-winout.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libjma_a_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ../jma/libjma_a-winout.obj `if test -f '../jma/winout.cpp'; then $(CYGPATH_W) '../jma/winout.cpp'; else $(CYGPATH_W) '$(srcdir)/../jma/winout.cpp'; fi` + +../filter/snes9x_gtk-2xsai.o: ../filter/2xsai.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../filter/snes9x_gtk-2xsai.o -MD -MP -MF ../filter/$(DEPDIR)/snes9x_gtk-2xsai.Tpo -c -o ../filter/snes9x_gtk-2xsai.o `test -f '../filter/2xsai.cpp' || echo '$(srcdir)/'`../filter/2xsai.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../filter/$(DEPDIR)/snes9x_gtk-2xsai.Tpo ../filter/$(DEPDIR)/snes9x_gtk-2xsai.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../filter/2xsai.cpp' object='../filter/snes9x_gtk-2xsai.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../filter/snes9x_gtk-2xsai.o `test -f '../filter/2xsai.cpp' || echo '$(srcdir)/'`../filter/2xsai.cpp + +../filter/snes9x_gtk-2xsai.obj: ../filter/2xsai.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../filter/snes9x_gtk-2xsai.obj -MD -MP -MF ../filter/$(DEPDIR)/snes9x_gtk-2xsai.Tpo -c -o ../filter/snes9x_gtk-2xsai.obj `if test -f '../filter/2xsai.cpp'; then $(CYGPATH_W) '../filter/2xsai.cpp'; else $(CYGPATH_W) '$(srcdir)/../filter/2xsai.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../filter/$(DEPDIR)/snes9x_gtk-2xsai.Tpo ../filter/$(DEPDIR)/snes9x_gtk-2xsai.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../filter/2xsai.cpp' object='../filter/snes9x_gtk-2xsai.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../filter/snes9x_gtk-2xsai.obj `if test -f '../filter/2xsai.cpp'; then $(CYGPATH_W) '../filter/2xsai.cpp'; else $(CYGPATH_W) '$(srcdir)/../filter/2xsai.cpp'; fi` + +../filter/snes9x_gtk-epx.o: ../filter/epx.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../filter/snes9x_gtk-epx.o -MD -MP -MF ../filter/$(DEPDIR)/snes9x_gtk-epx.Tpo -c -o ../filter/snes9x_gtk-epx.o `test -f '../filter/epx.cpp' || echo '$(srcdir)/'`../filter/epx.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../filter/$(DEPDIR)/snes9x_gtk-epx.Tpo ../filter/$(DEPDIR)/snes9x_gtk-epx.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../filter/epx.cpp' object='../filter/snes9x_gtk-epx.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../filter/snes9x_gtk-epx.o `test -f '../filter/epx.cpp' || echo '$(srcdir)/'`../filter/epx.cpp + +../filter/snes9x_gtk-epx.obj: ../filter/epx.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../filter/snes9x_gtk-epx.obj -MD -MP -MF ../filter/$(DEPDIR)/snes9x_gtk-epx.Tpo -c -o ../filter/snes9x_gtk-epx.obj `if test -f '../filter/epx.cpp'; then $(CYGPATH_W) '../filter/epx.cpp'; else $(CYGPATH_W) '$(srcdir)/../filter/epx.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../filter/$(DEPDIR)/snes9x_gtk-epx.Tpo ../filter/$(DEPDIR)/snes9x_gtk-epx.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../filter/epx.cpp' object='../filter/snes9x_gtk-epx.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../filter/snes9x_gtk-epx.obj `if test -f '../filter/epx.cpp'; then $(CYGPATH_W) '../filter/epx.cpp'; else $(CYGPATH_W) '$(srcdir)/../filter/epx.cpp'; fi` + +../filter/snes9x_gtk-hq2x.o: ../filter/hq2x.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../filter/snes9x_gtk-hq2x.o -MD -MP -MF ../filter/$(DEPDIR)/snes9x_gtk-hq2x.Tpo -c -o ../filter/snes9x_gtk-hq2x.o `test -f '../filter/hq2x.cpp' || echo '$(srcdir)/'`../filter/hq2x.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../filter/$(DEPDIR)/snes9x_gtk-hq2x.Tpo ../filter/$(DEPDIR)/snes9x_gtk-hq2x.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../filter/hq2x.cpp' object='../filter/snes9x_gtk-hq2x.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../filter/snes9x_gtk-hq2x.o `test -f '../filter/hq2x.cpp' || echo '$(srcdir)/'`../filter/hq2x.cpp + +../filter/snes9x_gtk-hq2x.obj: ../filter/hq2x.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../filter/snes9x_gtk-hq2x.obj -MD -MP -MF ../filter/$(DEPDIR)/snes9x_gtk-hq2x.Tpo -c -o ../filter/snes9x_gtk-hq2x.obj `if test -f '../filter/hq2x.cpp'; then $(CYGPATH_W) '../filter/hq2x.cpp'; else $(CYGPATH_W) '$(srcdir)/../filter/hq2x.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../filter/$(DEPDIR)/snes9x_gtk-hq2x.Tpo ../filter/$(DEPDIR)/snes9x_gtk-hq2x.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../filter/hq2x.cpp' object='../filter/snes9x_gtk-hq2x.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../filter/snes9x_gtk-hq2x.obj `if test -f '../filter/hq2x.cpp'; then $(CYGPATH_W) '../filter/hq2x.cpp'; else $(CYGPATH_W) '$(srcdir)/../filter/hq2x.cpp'; fi` + +src/snes9x_gtk-filter_epx_unsafe.o: src/filter_epx_unsafe.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-filter_epx_unsafe.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-filter_epx_unsafe.Tpo -c -o src/snes9x_gtk-filter_epx_unsafe.o `test -f 'src/filter_epx_unsafe.cpp' || echo '$(srcdir)/'`src/filter_epx_unsafe.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-filter_epx_unsafe.Tpo src/$(DEPDIR)/snes9x_gtk-filter_epx_unsafe.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/filter_epx_unsafe.cpp' object='src/snes9x_gtk-filter_epx_unsafe.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-filter_epx_unsafe.o `test -f 'src/filter_epx_unsafe.cpp' || echo '$(srcdir)/'`src/filter_epx_unsafe.cpp + +src/snes9x_gtk-filter_epx_unsafe.obj: src/filter_epx_unsafe.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-filter_epx_unsafe.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-filter_epx_unsafe.Tpo -c -o src/snes9x_gtk-filter_epx_unsafe.obj `if test -f 'src/filter_epx_unsafe.cpp'; then $(CYGPATH_W) 'src/filter_epx_unsafe.cpp'; else $(CYGPATH_W) '$(srcdir)/src/filter_epx_unsafe.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-filter_epx_unsafe.Tpo src/$(DEPDIR)/snes9x_gtk-filter_epx_unsafe.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/filter_epx_unsafe.cpp' object='src/snes9x_gtk-filter_epx_unsafe.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-filter_epx_unsafe.obj `if test -f 'src/filter_epx_unsafe.cpp'; then $(CYGPATH_W) 'src/filter_epx_unsafe.cpp'; else $(CYGPATH_W) '$(srcdir)/src/filter_epx_unsafe.cpp'; fi` + +src/snes9x_gtk-gtk_binding.o: src/gtk_binding.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_binding.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_binding.Tpo -c -o src/snes9x_gtk-gtk_binding.o `test -f 'src/gtk_binding.cpp' || echo '$(srcdir)/'`src/gtk_binding.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_binding.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_binding.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_binding.cpp' object='src/snes9x_gtk-gtk_binding.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_binding.o `test -f 'src/gtk_binding.cpp' || echo '$(srcdir)/'`src/gtk_binding.cpp + +src/snes9x_gtk-gtk_binding.obj: src/gtk_binding.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_binding.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_binding.Tpo -c -o src/snes9x_gtk-gtk_binding.obj `if test -f 'src/gtk_binding.cpp'; then $(CYGPATH_W) 'src/gtk_binding.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_binding.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_binding.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_binding.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_binding.cpp' object='src/snes9x_gtk-gtk_binding.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_binding.obj `if test -f 'src/gtk_binding.cpp'; then $(CYGPATH_W) 'src/gtk_binding.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_binding.cpp'; fi` + +src/snes9x_gtk-gtk_cheat.o: src/gtk_cheat.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_cheat.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_cheat.Tpo -c -o src/snes9x_gtk-gtk_cheat.o `test -f 'src/gtk_cheat.cpp' || echo '$(srcdir)/'`src/gtk_cheat.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_cheat.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_cheat.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_cheat.cpp' object='src/snes9x_gtk-gtk_cheat.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_cheat.o `test -f 'src/gtk_cheat.cpp' || echo '$(srcdir)/'`src/gtk_cheat.cpp + +src/snes9x_gtk-gtk_cheat.obj: src/gtk_cheat.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_cheat.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_cheat.Tpo -c -o src/snes9x_gtk-gtk_cheat.obj `if test -f 'src/gtk_cheat.cpp'; then $(CYGPATH_W) 'src/gtk_cheat.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_cheat.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_cheat.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_cheat.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_cheat.cpp' object='src/snes9x_gtk-gtk_cheat.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_cheat.obj `if test -f 'src/gtk_cheat.cpp'; then $(CYGPATH_W) 'src/gtk_cheat.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_cheat.cpp'; fi` + +src/snes9x_gtk-gtk_config.o: src/gtk_config.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_config.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_config.Tpo -c -o src/snes9x_gtk-gtk_config.o `test -f 'src/gtk_config.cpp' || echo '$(srcdir)/'`src/gtk_config.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_config.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_config.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_config.cpp' object='src/snes9x_gtk-gtk_config.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_config.o `test -f 'src/gtk_config.cpp' || echo '$(srcdir)/'`src/gtk_config.cpp + +src/snes9x_gtk-gtk_config.obj: src/gtk_config.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_config.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_config.Tpo -c -o src/snes9x_gtk-gtk_config.obj `if test -f 'src/gtk_config.cpp'; then $(CYGPATH_W) 'src/gtk_config.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_config.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_config.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_config.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_config.cpp' object='src/snes9x_gtk-gtk_config.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_config.obj `if test -f 'src/gtk_config.cpp'; then $(CYGPATH_W) 'src/gtk_config.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_config.cpp'; fi` + +src/snes9x_gtk-gtk_control.o: src/gtk_control.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_control.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_control.Tpo -c -o src/snes9x_gtk-gtk_control.o `test -f 'src/gtk_control.cpp' || echo '$(srcdir)/'`src/gtk_control.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_control.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_control.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_control.cpp' object='src/snes9x_gtk-gtk_control.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_control.o `test -f 'src/gtk_control.cpp' || echo '$(srcdir)/'`src/gtk_control.cpp + +src/snes9x_gtk-gtk_control.obj: src/gtk_control.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_control.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_control.Tpo -c -o src/snes9x_gtk-gtk_control.obj `if test -f 'src/gtk_control.cpp'; then $(CYGPATH_W) 'src/gtk_control.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_control.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_control.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_control.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_control.cpp' object='src/snes9x_gtk-gtk_control.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_control.obj `if test -f 'src/gtk_control.cpp'; then $(CYGPATH_W) 'src/gtk_control.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_control.cpp'; fi` + +src/snes9x_gtk-gtk_display.o: src/gtk_display.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_display.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_display.Tpo -c -o src/snes9x_gtk-gtk_display.o `test -f 'src/gtk_display.cpp' || echo '$(srcdir)/'`src/gtk_display.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_display.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_display.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_display.cpp' object='src/snes9x_gtk-gtk_display.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_display.o `test -f 'src/gtk_display.cpp' || echo '$(srcdir)/'`src/gtk_display.cpp + +src/snes9x_gtk-gtk_display.obj: src/gtk_display.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_display.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_display.Tpo -c -o src/snes9x_gtk-gtk_display.obj `if test -f 'src/gtk_display.cpp'; then $(CYGPATH_W) 'src/gtk_display.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_display.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_display.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_display.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_display.cpp' object='src/snes9x_gtk-gtk_display.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_display.obj `if test -f 'src/gtk_display.cpp'; then $(CYGPATH_W) 'src/gtk_display.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_display.cpp'; fi` + +src/snes9x_gtk-gtk_display_driver_gtk.o: src/gtk_display_driver_gtk.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_display_driver_gtk.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_gtk.Tpo -c -o src/snes9x_gtk-gtk_display_driver_gtk.o `test -f 'src/gtk_display_driver_gtk.cpp' || echo '$(srcdir)/'`src/gtk_display_driver_gtk.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_gtk.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_gtk.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_display_driver_gtk.cpp' object='src/snes9x_gtk-gtk_display_driver_gtk.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_display_driver_gtk.o `test -f 'src/gtk_display_driver_gtk.cpp' || echo '$(srcdir)/'`src/gtk_display_driver_gtk.cpp + +src/snes9x_gtk-gtk_display_driver_gtk.obj: src/gtk_display_driver_gtk.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_display_driver_gtk.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_gtk.Tpo -c -o src/snes9x_gtk-gtk_display_driver_gtk.obj `if test -f 'src/gtk_display_driver_gtk.cpp'; then $(CYGPATH_W) 'src/gtk_display_driver_gtk.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_display_driver_gtk.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_gtk.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_gtk.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_display_driver_gtk.cpp' object='src/snes9x_gtk-gtk_display_driver_gtk.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_display_driver_gtk.obj `if test -f 'src/gtk_display_driver_gtk.cpp'; then $(CYGPATH_W) 'src/gtk_display_driver_gtk.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_display_driver_gtk.cpp'; fi` + +src/snes9x_gtk-gtk_file.o: src/gtk_file.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_file.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_file.Tpo -c -o src/snes9x_gtk-gtk_file.o `test -f 'src/gtk_file.cpp' || echo '$(srcdir)/'`src/gtk_file.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_file.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_file.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_file.cpp' object='src/snes9x_gtk-gtk_file.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_file.o `test -f 'src/gtk_file.cpp' || echo '$(srcdir)/'`src/gtk_file.cpp + +src/snes9x_gtk-gtk_file.obj: src/gtk_file.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_file.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_file.Tpo -c -o src/snes9x_gtk-gtk_file.obj `if test -f 'src/gtk_file.cpp'; then $(CYGPATH_W) 'src/gtk_file.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_file.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_file.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_file.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_file.cpp' object='src/snes9x_gtk-gtk_file.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_file.obj `if test -f 'src/gtk_file.cpp'; then $(CYGPATH_W) 'src/gtk_file.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_file.cpp'; fi` + +src/snes9x_gtk-gtk_glade.o: src/gtk_glade.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_glade.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_glade.Tpo -c -o src/snes9x_gtk-gtk_glade.o `test -f 'src/gtk_glade.cpp' || echo '$(srcdir)/'`src/gtk_glade.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_glade.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_glade.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_glade.cpp' object='src/snes9x_gtk-gtk_glade.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_glade.o `test -f 'src/gtk_glade.cpp' || echo '$(srcdir)/'`src/gtk_glade.cpp + +src/snes9x_gtk-gtk_glade.obj: src/gtk_glade.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_glade.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_glade.Tpo -c -o src/snes9x_gtk-gtk_glade.obj `if test -f 'src/gtk_glade.cpp'; then $(CYGPATH_W) 'src/gtk_glade.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_glade.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_glade.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_glade.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_glade.cpp' object='src/snes9x_gtk-gtk_glade.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_glade.obj `if test -f 'src/gtk_glade.cpp'; then $(CYGPATH_W) 'src/gtk_glade.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_glade.cpp'; fi` + +src/snes9x_gtk-gtk_glade_window.o: src/gtk_glade_window.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_glade_window.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_glade_window.Tpo -c -o src/snes9x_gtk-gtk_glade_window.o `test -f 'src/gtk_glade_window.cpp' || echo '$(srcdir)/'`src/gtk_glade_window.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_glade_window.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_glade_window.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_glade_window.cpp' object='src/snes9x_gtk-gtk_glade_window.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_glade_window.o `test -f 'src/gtk_glade_window.cpp' || echo '$(srcdir)/'`src/gtk_glade_window.cpp + +src/snes9x_gtk-gtk_glade_window.obj: src/gtk_glade_window.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_glade_window.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_glade_window.Tpo -c -o src/snes9x_gtk-gtk_glade_window.obj `if test -f 'src/gtk_glade_window.cpp'; then $(CYGPATH_W) 'src/gtk_glade_window.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_glade_window.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_glade_window.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_glade_window.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_glade_window.cpp' object='src/snes9x_gtk-gtk_glade_window.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_glade_window.obj `if test -f 'src/gtk_glade_window.cpp'; then $(CYGPATH_W) 'src/gtk_glade_window.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_glade_window.cpp'; fi` + +src/snes9x_gtk-gtk_preferences.o: src/gtk_preferences.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_preferences.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_preferences.Tpo -c -o src/snes9x_gtk-gtk_preferences.o `test -f 'src/gtk_preferences.cpp' || echo '$(srcdir)/'`src/gtk_preferences.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_preferences.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_preferences.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_preferences.cpp' object='src/snes9x_gtk-gtk_preferences.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_preferences.o `test -f 'src/gtk_preferences.cpp' || echo '$(srcdir)/'`src/gtk_preferences.cpp + +src/snes9x_gtk-gtk_preferences.obj: src/gtk_preferences.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_preferences.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_preferences.Tpo -c -o src/snes9x_gtk-gtk_preferences.obj `if test -f 'src/gtk_preferences.cpp'; then $(CYGPATH_W) 'src/gtk_preferences.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_preferences.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_preferences.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_preferences.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_preferences.cpp' object='src/snes9x_gtk-gtk_preferences.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_preferences.obj `if test -f 'src/gtk_preferences.cpp'; then $(CYGPATH_W) 'src/gtk_preferences.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_preferences.cpp'; fi` + +src/snes9x_gtk-gtk_s9x.o: src/gtk_s9x.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_s9x.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_s9x.Tpo -c -o src/snes9x_gtk-gtk_s9x.o `test -f 'src/gtk_s9x.cpp' || echo '$(srcdir)/'`src/gtk_s9x.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_s9x.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_s9x.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_s9x.cpp' object='src/snes9x_gtk-gtk_s9x.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_s9x.o `test -f 'src/gtk_s9x.cpp' || echo '$(srcdir)/'`src/gtk_s9x.cpp + +src/snes9x_gtk-gtk_s9x.obj: src/gtk_s9x.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_s9x.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_s9x.Tpo -c -o src/snes9x_gtk-gtk_s9x.obj `if test -f 'src/gtk_s9x.cpp'; then $(CYGPATH_W) 'src/gtk_s9x.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_s9x.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_s9x.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_s9x.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_s9x.cpp' object='src/snes9x_gtk-gtk_s9x.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_s9x.obj `if test -f 'src/gtk_s9x.cpp'; then $(CYGPATH_W) 'src/gtk_s9x.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_s9x.cpp'; fi` + +src/snes9x_gtk-gtk_s9xwindow.o: src/gtk_s9xwindow.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_s9xwindow.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_s9xwindow.Tpo -c -o src/snes9x_gtk-gtk_s9xwindow.o `test -f 'src/gtk_s9xwindow.cpp' || echo '$(srcdir)/'`src/gtk_s9xwindow.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_s9xwindow.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_s9xwindow.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_s9xwindow.cpp' object='src/snes9x_gtk-gtk_s9xwindow.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_s9xwindow.o `test -f 'src/gtk_s9xwindow.cpp' || echo '$(srcdir)/'`src/gtk_s9xwindow.cpp + +src/snes9x_gtk-gtk_s9xwindow.obj: src/gtk_s9xwindow.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_s9xwindow.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_s9xwindow.Tpo -c -o src/snes9x_gtk-gtk_s9xwindow.obj `if test -f 'src/gtk_s9xwindow.cpp'; then $(CYGPATH_W) 'src/gtk_s9xwindow.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_s9xwindow.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_s9xwindow.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_s9xwindow.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_s9xwindow.cpp' object='src/snes9x_gtk-gtk_s9xwindow.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_s9xwindow.obj `if test -f 'src/gtk_s9xwindow.cpp'; then $(CYGPATH_W) 'src/gtk_s9xwindow.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_s9xwindow.cpp'; fi` + +src/snes9x_gtk-gtk_sound.o: src/gtk_sound.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound.Tpo -c -o src/snes9x_gtk-gtk_sound.o `test -f 'src/gtk_sound.cpp' || echo '$(srcdir)/'`src/gtk_sound.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound.cpp' object='src/snes9x_gtk-gtk_sound.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound.o `test -f 'src/gtk_sound.cpp' || echo '$(srcdir)/'`src/gtk_sound.cpp + +src/snes9x_gtk-gtk_sound.obj: src/gtk_sound.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound.Tpo -c -o src/snes9x_gtk-gtk_sound.obj `if test -f 'src/gtk_sound.cpp'; then $(CYGPATH_W) 'src/gtk_sound.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound.cpp' object='src/snes9x_gtk-gtk_sound.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound.obj `if test -f 'src/gtk_sound.cpp'; then $(CYGPATH_W) 'src/gtk_sound.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound.cpp'; fi` + +src/snes9x_gtk-gtk_sound_driver_portaudio.o: src/gtk_sound_driver_portaudio.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound_driver_portaudio.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_portaudio.Tpo -c -o src/snes9x_gtk-gtk_sound_driver_portaudio.o `test -f 'src/gtk_sound_driver_portaudio.cpp' || echo '$(srcdir)/'`src/gtk_sound_driver_portaudio.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_portaudio.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_portaudio.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound_driver_portaudio.cpp' object='src/snes9x_gtk-gtk_sound_driver_portaudio.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound_driver_portaudio.o `test -f 'src/gtk_sound_driver_portaudio.cpp' || echo '$(srcdir)/'`src/gtk_sound_driver_portaudio.cpp + +src/snes9x_gtk-gtk_sound_driver_portaudio.obj: src/gtk_sound_driver_portaudio.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound_driver_portaudio.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_portaudio.Tpo -c -o src/snes9x_gtk-gtk_sound_driver_portaudio.obj `if test -f 'src/gtk_sound_driver_portaudio.cpp'; then $(CYGPATH_W) 'src/gtk_sound_driver_portaudio.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound_driver_portaudio.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_portaudio.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_portaudio.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound_driver_portaudio.cpp' object='src/snes9x_gtk-gtk_sound_driver_portaudio.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound_driver_portaudio.obj `if test -f 'src/gtk_sound_driver_portaudio.cpp'; then $(CYGPATH_W) 'src/gtk_sound_driver_portaudio.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound_driver_portaudio.cpp'; fi` + +src/snes9x_gtk-gtk_sound_driver_pulse.o: src/gtk_sound_driver_pulse.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound_driver_pulse.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_pulse.Tpo -c -o src/snes9x_gtk-gtk_sound_driver_pulse.o `test -f 'src/gtk_sound_driver_pulse.cpp' || echo '$(srcdir)/'`src/gtk_sound_driver_pulse.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_pulse.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_pulse.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound_driver_pulse.cpp' object='src/snes9x_gtk-gtk_sound_driver_pulse.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound_driver_pulse.o `test -f 'src/gtk_sound_driver_pulse.cpp' || echo '$(srcdir)/'`src/gtk_sound_driver_pulse.cpp + +src/snes9x_gtk-gtk_sound_driver_pulse.obj: src/gtk_sound_driver_pulse.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound_driver_pulse.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_pulse.Tpo -c -o src/snes9x_gtk-gtk_sound_driver_pulse.obj `if test -f 'src/gtk_sound_driver_pulse.cpp'; then $(CYGPATH_W) 'src/gtk_sound_driver_pulse.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound_driver_pulse.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_pulse.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_pulse.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound_driver_pulse.cpp' object='src/snes9x_gtk-gtk_sound_driver_pulse.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound_driver_pulse.obj `if test -f 'src/gtk_sound_driver_pulse.cpp'; then $(CYGPATH_W) 'src/gtk_sound_driver_pulse.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound_driver_pulse.cpp'; fi` + +src/snes9x_gtk-gtk_sound_driver_oss.o: src/gtk_sound_driver_oss.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound_driver_oss.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_oss.Tpo -c -o src/snes9x_gtk-gtk_sound_driver_oss.o `test -f 'src/gtk_sound_driver_oss.cpp' || echo '$(srcdir)/'`src/gtk_sound_driver_oss.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_oss.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_oss.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound_driver_oss.cpp' object='src/snes9x_gtk-gtk_sound_driver_oss.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound_driver_oss.o `test -f 'src/gtk_sound_driver_oss.cpp' || echo '$(srcdir)/'`src/gtk_sound_driver_oss.cpp + +src/snes9x_gtk-gtk_sound_driver_oss.obj: src/gtk_sound_driver_oss.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound_driver_oss.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_oss.Tpo -c -o src/snes9x_gtk-gtk_sound_driver_oss.obj `if test -f 'src/gtk_sound_driver_oss.cpp'; then $(CYGPATH_W) 'src/gtk_sound_driver_oss.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound_driver_oss.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_oss.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_oss.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound_driver_oss.cpp' object='src/snes9x_gtk-gtk_sound_driver_oss.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound_driver_oss.obj `if test -f 'src/gtk_sound_driver_oss.cpp'; then $(CYGPATH_W) 'src/gtk_sound_driver_oss.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound_driver_oss.cpp'; fi` + +src/snes9x_gtk-gtk_sound_driver_sdl.o: src/gtk_sound_driver_sdl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound_driver_sdl.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_sdl.Tpo -c -o src/snes9x_gtk-gtk_sound_driver_sdl.o `test -f 'src/gtk_sound_driver_sdl.cpp' || echo '$(srcdir)/'`src/gtk_sound_driver_sdl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_sdl.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_sdl.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound_driver_sdl.cpp' object='src/snes9x_gtk-gtk_sound_driver_sdl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound_driver_sdl.o `test -f 'src/gtk_sound_driver_sdl.cpp' || echo '$(srcdir)/'`src/gtk_sound_driver_sdl.cpp + +src/snes9x_gtk-gtk_sound_driver_sdl.obj: src/gtk_sound_driver_sdl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound_driver_sdl.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_sdl.Tpo -c -o src/snes9x_gtk-gtk_sound_driver_sdl.obj `if test -f 'src/gtk_sound_driver_sdl.cpp'; then $(CYGPATH_W) 'src/gtk_sound_driver_sdl.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound_driver_sdl.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_sdl.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_sdl.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound_driver_sdl.cpp' object='src/snes9x_gtk-gtk_sound_driver_sdl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound_driver_sdl.obj `if test -f 'src/gtk_sound_driver_sdl.cpp'; then $(CYGPATH_W) 'src/gtk_sound_driver_sdl.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound_driver_sdl.cpp'; fi` + +src/snes9x_gtk-gtk_sound_driver_alsa.o: src/gtk_sound_driver_alsa.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound_driver_alsa.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_alsa.Tpo -c -o src/snes9x_gtk-gtk_sound_driver_alsa.o `test -f 'src/gtk_sound_driver_alsa.cpp' || echo '$(srcdir)/'`src/gtk_sound_driver_alsa.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_alsa.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_alsa.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound_driver_alsa.cpp' object='src/snes9x_gtk-gtk_sound_driver_alsa.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound_driver_alsa.o `test -f 'src/gtk_sound_driver_alsa.cpp' || echo '$(srcdir)/'`src/gtk_sound_driver_alsa.cpp + +src/snes9x_gtk-gtk_sound_driver_alsa.obj: src/gtk_sound_driver_alsa.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_sound_driver_alsa.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_alsa.Tpo -c -o src/snes9x_gtk-gtk_sound_driver_alsa.obj `if test -f 'src/gtk_sound_driver_alsa.cpp'; then $(CYGPATH_W) 'src/gtk_sound_driver_alsa.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound_driver_alsa.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_alsa.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_sound_driver_alsa.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_sound_driver_alsa.cpp' object='src/snes9x_gtk-gtk_sound_driver_alsa.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_sound_driver_alsa.obj `if test -f 'src/gtk_sound_driver_alsa.cpp'; then $(CYGPATH_W) 'src/gtk_sound_driver_alsa.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_sound_driver_alsa.cpp'; fi` + +../snes9x_gtk-fxinst.o: ../fxinst.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-fxinst.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-fxinst.Tpo -c -o ../snes9x_gtk-fxinst.o `test -f '../fxinst.cpp' || echo '$(srcdir)/'`../fxinst.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-fxinst.Tpo ../$(DEPDIR)/snes9x_gtk-fxinst.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../fxinst.cpp' object='../snes9x_gtk-fxinst.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-fxinst.o `test -f '../fxinst.cpp' || echo '$(srcdir)/'`../fxinst.cpp + +../snes9x_gtk-fxinst.obj: ../fxinst.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-fxinst.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-fxinst.Tpo -c -o ../snes9x_gtk-fxinst.obj `if test -f '../fxinst.cpp'; then $(CYGPATH_W) '../fxinst.cpp'; else $(CYGPATH_W) '$(srcdir)/../fxinst.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-fxinst.Tpo ../$(DEPDIR)/snes9x_gtk-fxinst.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../fxinst.cpp' object='../snes9x_gtk-fxinst.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-fxinst.obj `if test -f '../fxinst.cpp'; then $(CYGPATH_W) '../fxinst.cpp'; else $(CYGPATH_W) '$(srcdir)/../fxinst.cpp'; fi` + +../snes9x_gtk-fxemu.o: ../fxemu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-fxemu.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-fxemu.Tpo -c -o ../snes9x_gtk-fxemu.o `test -f '../fxemu.cpp' || echo '$(srcdir)/'`../fxemu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-fxemu.Tpo ../$(DEPDIR)/snes9x_gtk-fxemu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../fxemu.cpp' object='../snes9x_gtk-fxemu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-fxemu.o `test -f '../fxemu.cpp' || echo '$(srcdir)/'`../fxemu.cpp + +../snes9x_gtk-fxemu.obj: ../fxemu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-fxemu.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-fxemu.Tpo -c -o ../snes9x_gtk-fxemu.obj `if test -f '../fxemu.cpp'; then $(CYGPATH_W) '../fxemu.cpp'; else $(CYGPATH_W) '$(srcdir)/../fxemu.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-fxemu.Tpo ../$(DEPDIR)/snes9x_gtk-fxemu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../fxemu.cpp' object='../snes9x_gtk-fxemu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-fxemu.obj `if test -f '../fxemu.cpp'; then $(CYGPATH_W) '../fxemu.cpp'; else $(CYGPATH_W) '$(srcdir)/../fxemu.cpp'; fi` + +../snes9x_gtk-fxdbg.o: ../fxdbg.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-fxdbg.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-fxdbg.Tpo -c -o ../snes9x_gtk-fxdbg.o `test -f '../fxdbg.cpp' || echo '$(srcdir)/'`../fxdbg.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-fxdbg.Tpo ../$(DEPDIR)/snes9x_gtk-fxdbg.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../fxdbg.cpp' object='../snes9x_gtk-fxdbg.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-fxdbg.o `test -f '../fxdbg.cpp' || echo '$(srcdir)/'`../fxdbg.cpp + +../snes9x_gtk-fxdbg.obj: ../fxdbg.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-fxdbg.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-fxdbg.Tpo -c -o ../snes9x_gtk-fxdbg.obj `if test -f '../fxdbg.cpp'; then $(CYGPATH_W) '../fxdbg.cpp'; else $(CYGPATH_W) '$(srcdir)/../fxdbg.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-fxdbg.Tpo ../$(DEPDIR)/snes9x_gtk-fxdbg.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../fxdbg.cpp' object='../snes9x_gtk-fxdbg.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-fxdbg.obj `if test -f '../fxdbg.cpp'; then $(CYGPATH_W) '../fxdbg.cpp'; else $(CYGPATH_W) '$(srcdir)/../fxdbg.cpp'; fi` + +../snes9x_gtk-c4.o: ../c4.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-c4.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-c4.Tpo -c -o ../snes9x_gtk-c4.o `test -f '../c4.cpp' || echo '$(srcdir)/'`../c4.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-c4.Tpo ../$(DEPDIR)/snes9x_gtk-c4.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../c4.cpp' object='../snes9x_gtk-c4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-c4.o `test -f '../c4.cpp' || echo '$(srcdir)/'`../c4.cpp + +../snes9x_gtk-c4.obj: ../c4.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-c4.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-c4.Tpo -c -o ../snes9x_gtk-c4.obj `if test -f '../c4.cpp'; then $(CYGPATH_W) '../c4.cpp'; else $(CYGPATH_W) '$(srcdir)/../c4.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-c4.Tpo ../$(DEPDIR)/snes9x_gtk-c4.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../c4.cpp' object='../snes9x_gtk-c4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-c4.obj `if test -f '../c4.cpp'; then $(CYGPATH_W) '../c4.cpp'; else $(CYGPATH_W) '$(srcdir)/../c4.cpp'; fi` + +../snes9x_gtk-c4emu.o: ../c4emu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-c4emu.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-c4emu.Tpo -c -o ../snes9x_gtk-c4emu.o `test -f '../c4emu.cpp' || echo '$(srcdir)/'`../c4emu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-c4emu.Tpo ../$(DEPDIR)/snes9x_gtk-c4emu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../c4emu.cpp' object='../snes9x_gtk-c4emu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-c4emu.o `test -f '../c4emu.cpp' || echo '$(srcdir)/'`../c4emu.cpp + +../snes9x_gtk-c4emu.obj: ../c4emu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-c4emu.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-c4emu.Tpo -c -o ../snes9x_gtk-c4emu.obj `if test -f '../c4emu.cpp'; then $(CYGPATH_W) '../c4emu.cpp'; else $(CYGPATH_W) '$(srcdir)/../c4emu.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-c4emu.Tpo ../$(DEPDIR)/snes9x_gtk-c4emu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../c4emu.cpp' object='../snes9x_gtk-c4emu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-c4emu.obj `if test -f '../c4emu.cpp'; then $(CYGPATH_W) '../c4emu.cpp'; else $(CYGPATH_W) '$(srcdir)/../c4emu.cpp'; fi` + +../apu/snes9x_gtk-apu.o: ../apu/apu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-apu.o -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-apu.Tpo -c -o ../apu/snes9x_gtk-apu.o `test -f '../apu/apu.cpp' || echo '$(srcdir)/'`../apu/apu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-apu.Tpo ../apu/$(DEPDIR)/snes9x_gtk-apu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/apu.cpp' object='../apu/snes9x_gtk-apu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-apu.o `test -f '../apu/apu.cpp' || echo '$(srcdir)/'`../apu/apu.cpp + +../apu/snes9x_gtk-apu.obj: ../apu/apu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-apu.obj -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-apu.Tpo -c -o ../apu/snes9x_gtk-apu.obj `if test -f '../apu/apu.cpp'; then $(CYGPATH_W) '../apu/apu.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/apu.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-apu.Tpo ../apu/$(DEPDIR)/snes9x_gtk-apu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/apu.cpp' object='../apu/snes9x_gtk-apu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-apu.obj `if test -f '../apu/apu.cpp'; then $(CYGPATH_W) '../apu/apu.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/apu.cpp'; fi` + +../apu/snes9x_gtk-SNES_SPC.o: ../apu/SNES_SPC.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-SNES_SPC.o -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC.Tpo -c -o ../apu/snes9x_gtk-SNES_SPC.o `test -f '../apu/SNES_SPC.cpp' || echo '$(srcdir)/'`../apu/SNES_SPC.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC.Tpo ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/SNES_SPC.cpp' object='../apu/snes9x_gtk-SNES_SPC.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-SNES_SPC.o `test -f '../apu/SNES_SPC.cpp' || echo '$(srcdir)/'`../apu/SNES_SPC.cpp + +../apu/snes9x_gtk-SNES_SPC.obj: ../apu/SNES_SPC.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-SNES_SPC.obj -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC.Tpo -c -o ../apu/snes9x_gtk-SNES_SPC.obj `if test -f '../apu/SNES_SPC.cpp'; then $(CYGPATH_W) '../apu/SNES_SPC.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/SNES_SPC.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC.Tpo ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/SNES_SPC.cpp' object='../apu/snes9x_gtk-SNES_SPC.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-SNES_SPC.obj `if test -f '../apu/SNES_SPC.cpp'; then $(CYGPATH_W) '../apu/SNES_SPC.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/SNES_SPC.cpp'; fi` + +../apu/snes9x_gtk-SNES_SPC_misc.o: ../apu/SNES_SPC_misc.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-SNES_SPC_misc.o -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_misc.Tpo -c -o ../apu/snes9x_gtk-SNES_SPC_misc.o `test -f '../apu/SNES_SPC_misc.cpp' || echo '$(srcdir)/'`../apu/SNES_SPC_misc.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_misc.Tpo ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_misc.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/SNES_SPC_misc.cpp' object='../apu/snes9x_gtk-SNES_SPC_misc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-SNES_SPC_misc.o `test -f '../apu/SNES_SPC_misc.cpp' || echo '$(srcdir)/'`../apu/SNES_SPC_misc.cpp + +../apu/snes9x_gtk-SNES_SPC_misc.obj: ../apu/SNES_SPC_misc.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-SNES_SPC_misc.obj -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_misc.Tpo -c -o ../apu/snes9x_gtk-SNES_SPC_misc.obj `if test -f '../apu/SNES_SPC_misc.cpp'; then $(CYGPATH_W) '../apu/SNES_SPC_misc.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/SNES_SPC_misc.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_misc.Tpo ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_misc.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/SNES_SPC_misc.cpp' object='../apu/snes9x_gtk-SNES_SPC_misc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-SNES_SPC_misc.obj `if test -f '../apu/SNES_SPC_misc.cpp'; then $(CYGPATH_W) '../apu/SNES_SPC_misc.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/SNES_SPC_misc.cpp'; fi` + +../apu/snes9x_gtk-SNES_SPC_state.o: ../apu/SNES_SPC_state.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-SNES_SPC_state.o -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_state.Tpo -c -o ../apu/snes9x_gtk-SNES_SPC_state.o `test -f '../apu/SNES_SPC_state.cpp' || echo '$(srcdir)/'`../apu/SNES_SPC_state.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_state.Tpo ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_state.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/SNES_SPC_state.cpp' object='../apu/snes9x_gtk-SNES_SPC_state.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-SNES_SPC_state.o `test -f '../apu/SNES_SPC_state.cpp' || echo '$(srcdir)/'`../apu/SNES_SPC_state.cpp + +../apu/snes9x_gtk-SNES_SPC_state.obj: ../apu/SNES_SPC_state.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-SNES_SPC_state.obj -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_state.Tpo -c -o ../apu/snes9x_gtk-SNES_SPC_state.obj `if test -f '../apu/SNES_SPC_state.cpp'; then $(CYGPATH_W) '../apu/SNES_SPC_state.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/SNES_SPC_state.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_state.Tpo ../apu/$(DEPDIR)/snes9x_gtk-SNES_SPC_state.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/SNES_SPC_state.cpp' object='../apu/snes9x_gtk-SNES_SPC_state.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-SNES_SPC_state.obj `if test -f '../apu/SNES_SPC_state.cpp'; then $(CYGPATH_W) '../apu/SNES_SPC_state.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/SNES_SPC_state.cpp'; fi` + +../apu/snes9x_gtk-SPC_DSP.o: ../apu/SPC_DSP.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-SPC_DSP.o -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-SPC_DSP.Tpo -c -o ../apu/snes9x_gtk-SPC_DSP.o `test -f '../apu/SPC_DSP.cpp' || echo '$(srcdir)/'`../apu/SPC_DSP.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-SPC_DSP.Tpo ../apu/$(DEPDIR)/snes9x_gtk-SPC_DSP.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/SPC_DSP.cpp' object='../apu/snes9x_gtk-SPC_DSP.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-SPC_DSP.o `test -f '../apu/SPC_DSP.cpp' || echo '$(srcdir)/'`../apu/SPC_DSP.cpp + +../apu/snes9x_gtk-SPC_DSP.obj: ../apu/SPC_DSP.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-SPC_DSP.obj -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-SPC_DSP.Tpo -c -o ../apu/snes9x_gtk-SPC_DSP.obj `if test -f '../apu/SPC_DSP.cpp'; then $(CYGPATH_W) '../apu/SPC_DSP.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/SPC_DSP.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-SPC_DSP.Tpo ../apu/$(DEPDIR)/snes9x_gtk-SPC_DSP.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/SPC_DSP.cpp' object='../apu/snes9x_gtk-SPC_DSP.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-SPC_DSP.obj `if test -f '../apu/SPC_DSP.cpp'; then $(CYGPATH_W) '../apu/SPC_DSP.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/SPC_DSP.cpp'; fi` + +../apu/snes9x_gtk-SPC_Filter.o: ../apu/SPC_Filter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-SPC_Filter.o -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-SPC_Filter.Tpo -c -o ../apu/snes9x_gtk-SPC_Filter.o `test -f '../apu/SPC_Filter.cpp' || echo '$(srcdir)/'`../apu/SPC_Filter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-SPC_Filter.Tpo ../apu/$(DEPDIR)/snes9x_gtk-SPC_Filter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/SPC_Filter.cpp' object='../apu/snes9x_gtk-SPC_Filter.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-SPC_Filter.o `test -f '../apu/SPC_Filter.cpp' || echo '$(srcdir)/'`../apu/SPC_Filter.cpp + +../apu/snes9x_gtk-SPC_Filter.obj: ../apu/SPC_Filter.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../apu/snes9x_gtk-SPC_Filter.obj -MD -MP -MF ../apu/$(DEPDIR)/snes9x_gtk-SPC_Filter.Tpo -c -o ../apu/snes9x_gtk-SPC_Filter.obj `if test -f '../apu/SPC_Filter.cpp'; then $(CYGPATH_W) '../apu/SPC_Filter.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/SPC_Filter.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../apu/$(DEPDIR)/snes9x_gtk-SPC_Filter.Tpo ../apu/$(DEPDIR)/snes9x_gtk-SPC_Filter.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../apu/SPC_Filter.cpp' object='../apu/snes9x_gtk-SPC_Filter.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../apu/snes9x_gtk-SPC_Filter.obj `if test -f '../apu/SPC_Filter.cpp'; then $(CYGPATH_W) '../apu/SPC_Filter.cpp'; else $(CYGPATH_W) '$(srcdir)/../apu/SPC_Filter.cpp'; fi` + +../snes9x_gtk-dsp.o: ../dsp.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dsp.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dsp.Tpo -c -o ../snes9x_gtk-dsp.o `test -f '../dsp.cpp' || echo '$(srcdir)/'`../dsp.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dsp.Tpo ../$(DEPDIR)/snes9x_gtk-dsp.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dsp.cpp' object='../snes9x_gtk-dsp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dsp.o `test -f '../dsp.cpp' || echo '$(srcdir)/'`../dsp.cpp + +../snes9x_gtk-dsp.obj: ../dsp.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dsp.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dsp.Tpo -c -o ../snes9x_gtk-dsp.obj `if test -f '../dsp.cpp'; then $(CYGPATH_W) '../dsp.cpp'; else $(CYGPATH_W) '$(srcdir)/../dsp.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dsp.Tpo ../$(DEPDIR)/snes9x_gtk-dsp.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dsp.cpp' object='../snes9x_gtk-dsp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dsp.obj `if test -f '../dsp.cpp'; then $(CYGPATH_W) '../dsp.cpp'; else $(CYGPATH_W) '$(srcdir)/../dsp.cpp'; fi` + +../snes9x_gtk-dsp1.o: ../dsp1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dsp1.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dsp1.Tpo -c -o ../snes9x_gtk-dsp1.o `test -f '../dsp1.cpp' || echo '$(srcdir)/'`../dsp1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dsp1.Tpo ../$(DEPDIR)/snes9x_gtk-dsp1.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dsp1.cpp' object='../snes9x_gtk-dsp1.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dsp1.o `test -f '../dsp1.cpp' || echo '$(srcdir)/'`../dsp1.cpp + +../snes9x_gtk-dsp1.obj: ../dsp1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dsp1.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dsp1.Tpo -c -o ../snes9x_gtk-dsp1.obj `if test -f '../dsp1.cpp'; then $(CYGPATH_W) '../dsp1.cpp'; else $(CYGPATH_W) '$(srcdir)/../dsp1.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dsp1.Tpo ../$(DEPDIR)/snes9x_gtk-dsp1.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dsp1.cpp' object='../snes9x_gtk-dsp1.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dsp1.obj `if test -f '../dsp1.cpp'; then $(CYGPATH_W) '../dsp1.cpp'; else $(CYGPATH_W) '$(srcdir)/../dsp1.cpp'; fi` + +../snes9x_gtk-dsp2.o: ../dsp2.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dsp2.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dsp2.Tpo -c -o ../snes9x_gtk-dsp2.o `test -f '../dsp2.cpp' || echo '$(srcdir)/'`../dsp2.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dsp2.Tpo ../$(DEPDIR)/snes9x_gtk-dsp2.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dsp2.cpp' object='../snes9x_gtk-dsp2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dsp2.o `test -f '../dsp2.cpp' || echo '$(srcdir)/'`../dsp2.cpp + +../snes9x_gtk-dsp2.obj: ../dsp2.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dsp2.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dsp2.Tpo -c -o ../snes9x_gtk-dsp2.obj `if test -f '../dsp2.cpp'; then $(CYGPATH_W) '../dsp2.cpp'; else $(CYGPATH_W) '$(srcdir)/../dsp2.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dsp2.Tpo ../$(DEPDIR)/snes9x_gtk-dsp2.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dsp2.cpp' object='../snes9x_gtk-dsp2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dsp2.obj `if test -f '../dsp2.cpp'; then $(CYGPATH_W) '../dsp2.cpp'; else $(CYGPATH_W) '$(srcdir)/../dsp2.cpp'; fi` + +../snes9x_gtk-dsp3.o: ../dsp3.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dsp3.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dsp3.Tpo -c -o ../snes9x_gtk-dsp3.o `test -f '../dsp3.cpp' || echo '$(srcdir)/'`../dsp3.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dsp3.Tpo ../$(DEPDIR)/snes9x_gtk-dsp3.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dsp3.cpp' object='../snes9x_gtk-dsp3.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dsp3.o `test -f '../dsp3.cpp' || echo '$(srcdir)/'`../dsp3.cpp + +../snes9x_gtk-dsp3.obj: ../dsp3.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dsp3.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dsp3.Tpo -c -o ../snes9x_gtk-dsp3.obj `if test -f '../dsp3.cpp'; then $(CYGPATH_W) '../dsp3.cpp'; else $(CYGPATH_W) '$(srcdir)/../dsp3.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dsp3.Tpo ../$(DEPDIR)/snes9x_gtk-dsp3.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dsp3.cpp' object='../snes9x_gtk-dsp3.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dsp3.obj `if test -f '../dsp3.cpp'; then $(CYGPATH_W) '../dsp3.cpp'; else $(CYGPATH_W) '$(srcdir)/../dsp3.cpp'; fi` + +../snes9x_gtk-dsp4.o: ../dsp4.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dsp4.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dsp4.Tpo -c -o ../snes9x_gtk-dsp4.o `test -f '../dsp4.cpp' || echo '$(srcdir)/'`../dsp4.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dsp4.Tpo ../$(DEPDIR)/snes9x_gtk-dsp4.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dsp4.cpp' object='../snes9x_gtk-dsp4.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dsp4.o `test -f '../dsp4.cpp' || echo '$(srcdir)/'`../dsp4.cpp + +../snes9x_gtk-dsp4.obj: ../dsp4.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dsp4.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dsp4.Tpo -c -o ../snes9x_gtk-dsp4.obj `if test -f '../dsp4.cpp'; then $(CYGPATH_W) '../dsp4.cpp'; else $(CYGPATH_W) '$(srcdir)/../dsp4.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dsp4.Tpo ../$(DEPDIR)/snes9x_gtk-dsp4.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dsp4.cpp' object='../snes9x_gtk-dsp4.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dsp4.obj `if test -f '../dsp4.cpp'; then $(CYGPATH_W) '../dsp4.cpp'; else $(CYGPATH_W) '$(srcdir)/../dsp4.cpp'; fi` + +../snes9x_gtk-spc7110.o: ../spc7110.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-spc7110.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-spc7110.Tpo -c -o ../snes9x_gtk-spc7110.o `test -f '../spc7110.cpp' || echo '$(srcdir)/'`../spc7110.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-spc7110.Tpo ../$(DEPDIR)/snes9x_gtk-spc7110.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../spc7110.cpp' object='../snes9x_gtk-spc7110.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-spc7110.o `test -f '../spc7110.cpp' || echo '$(srcdir)/'`../spc7110.cpp + +../snes9x_gtk-spc7110.obj: ../spc7110.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-spc7110.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-spc7110.Tpo -c -o ../snes9x_gtk-spc7110.obj `if test -f '../spc7110.cpp'; then $(CYGPATH_W) '../spc7110.cpp'; else $(CYGPATH_W) '$(srcdir)/../spc7110.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-spc7110.Tpo ../$(DEPDIR)/snes9x_gtk-spc7110.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../spc7110.cpp' object='../snes9x_gtk-spc7110.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-spc7110.obj `if test -f '../spc7110.cpp'; then $(CYGPATH_W) '../spc7110.cpp'; else $(CYGPATH_W) '$(srcdir)/../spc7110.cpp'; fi` + +../snes9x_gtk-obc1.o: ../obc1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-obc1.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-obc1.Tpo -c -o ../snes9x_gtk-obc1.o `test -f '../obc1.cpp' || echo '$(srcdir)/'`../obc1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-obc1.Tpo ../$(DEPDIR)/snes9x_gtk-obc1.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../obc1.cpp' object='../snes9x_gtk-obc1.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-obc1.o `test -f '../obc1.cpp' || echo '$(srcdir)/'`../obc1.cpp + +../snes9x_gtk-obc1.obj: ../obc1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-obc1.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-obc1.Tpo -c -o ../snes9x_gtk-obc1.obj `if test -f '../obc1.cpp'; then $(CYGPATH_W) '../obc1.cpp'; else $(CYGPATH_W) '$(srcdir)/../obc1.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-obc1.Tpo ../$(DEPDIR)/snes9x_gtk-obc1.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../obc1.cpp' object='../snes9x_gtk-obc1.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-obc1.obj `if test -f '../obc1.cpp'; then $(CYGPATH_W) '../obc1.cpp'; else $(CYGPATH_W) '$(srcdir)/../obc1.cpp'; fi` + +../snes9x_gtk-seta.o: ../seta.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-seta.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-seta.Tpo -c -o ../snes9x_gtk-seta.o `test -f '../seta.cpp' || echo '$(srcdir)/'`../seta.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-seta.Tpo ../$(DEPDIR)/snes9x_gtk-seta.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../seta.cpp' object='../snes9x_gtk-seta.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-seta.o `test -f '../seta.cpp' || echo '$(srcdir)/'`../seta.cpp + +../snes9x_gtk-seta.obj: ../seta.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-seta.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-seta.Tpo -c -o ../snes9x_gtk-seta.obj `if test -f '../seta.cpp'; then $(CYGPATH_W) '../seta.cpp'; else $(CYGPATH_W) '$(srcdir)/../seta.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-seta.Tpo ../$(DEPDIR)/snes9x_gtk-seta.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../seta.cpp' object='../snes9x_gtk-seta.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-seta.obj `if test -f '../seta.cpp'; then $(CYGPATH_W) '../seta.cpp'; else $(CYGPATH_W) '$(srcdir)/../seta.cpp'; fi` + +../snes9x_gtk-seta010.o: ../seta010.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-seta010.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-seta010.Tpo -c -o ../snes9x_gtk-seta010.o `test -f '../seta010.cpp' || echo '$(srcdir)/'`../seta010.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-seta010.Tpo ../$(DEPDIR)/snes9x_gtk-seta010.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../seta010.cpp' object='../snes9x_gtk-seta010.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-seta010.o `test -f '../seta010.cpp' || echo '$(srcdir)/'`../seta010.cpp + +../snes9x_gtk-seta010.obj: ../seta010.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-seta010.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-seta010.Tpo -c -o ../snes9x_gtk-seta010.obj `if test -f '../seta010.cpp'; then $(CYGPATH_W) '../seta010.cpp'; else $(CYGPATH_W) '$(srcdir)/../seta010.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-seta010.Tpo ../$(DEPDIR)/snes9x_gtk-seta010.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../seta010.cpp' object='../snes9x_gtk-seta010.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-seta010.obj `if test -f '../seta010.cpp'; then $(CYGPATH_W) '../seta010.cpp'; else $(CYGPATH_W) '$(srcdir)/../seta010.cpp'; fi` + +../snes9x_gtk-seta011.o: ../seta011.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-seta011.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-seta011.Tpo -c -o ../snes9x_gtk-seta011.o `test -f '../seta011.cpp' || echo '$(srcdir)/'`../seta011.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-seta011.Tpo ../$(DEPDIR)/snes9x_gtk-seta011.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../seta011.cpp' object='../snes9x_gtk-seta011.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-seta011.o `test -f '../seta011.cpp' || echo '$(srcdir)/'`../seta011.cpp + +../snes9x_gtk-seta011.obj: ../seta011.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-seta011.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-seta011.Tpo -c -o ../snes9x_gtk-seta011.obj `if test -f '../seta011.cpp'; then $(CYGPATH_W) '../seta011.cpp'; else $(CYGPATH_W) '$(srcdir)/../seta011.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-seta011.Tpo ../$(DEPDIR)/snes9x_gtk-seta011.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../seta011.cpp' object='../snes9x_gtk-seta011.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-seta011.obj `if test -f '../seta011.cpp'; then $(CYGPATH_W) '../seta011.cpp'; else $(CYGPATH_W) '$(srcdir)/../seta011.cpp'; fi` + +../snes9x_gtk-seta018.o: ../seta018.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-seta018.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-seta018.Tpo -c -o ../snes9x_gtk-seta018.o `test -f '../seta018.cpp' || echo '$(srcdir)/'`../seta018.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-seta018.Tpo ../$(DEPDIR)/snes9x_gtk-seta018.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../seta018.cpp' object='../snes9x_gtk-seta018.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-seta018.o `test -f '../seta018.cpp' || echo '$(srcdir)/'`../seta018.cpp + +../snes9x_gtk-seta018.obj: ../seta018.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-seta018.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-seta018.Tpo -c -o ../snes9x_gtk-seta018.obj `if test -f '../seta018.cpp'; then $(CYGPATH_W) '../seta018.cpp'; else $(CYGPATH_W) '$(srcdir)/../seta018.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-seta018.Tpo ../$(DEPDIR)/snes9x_gtk-seta018.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../seta018.cpp' object='../snes9x_gtk-seta018.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-seta018.obj `if test -f '../seta018.cpp'; then $(CYGPATH_W) '../seta018.cpp'; else $(CYGPATH_W) '$(srcdir)/../seta018.cpp'; fi` + +../snes9x_gtk-controls.o: ../controls.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-controls.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-controls.Tpo -c -o ../snes9x_gtk-controls.o `test -f '../controls.cpp' || echo '$(srcdir)/'`../controls.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-controls.Tpo ../$(DEPDIR)/snes9x_gtk-controls.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../controls.cpp' object='../snes9x_gtk-controls.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-controls.o `test -f '../controls.cpp' || echo '$(srcdir)/'`../controls.cpp + +../snes9x_gtk-controls.obj: ../controls.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-controls.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-controls.Tpo -c -o ../snes9x_gtk-controls.obj `if test -f '../controls.cpp'; then $(CYGPATH_W) '../controls.cpp'; else $(CYGPATH_W) '$(srcdir)/../controls.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-controls.Tpo ../$(DEPDIR)/snes9x_gtk-controls.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../controls.cpp' object='../snes9x_gtk-controls.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-controls.obj `if test -f '../controls.cpp'; then $(CYGPATH_W) '../controls.cpp'; else $(CYGPATH_W) '$(srcdir)/../controls.cpp'; fi` + +../snes9x_gtk-crosshairs.o: ../crosshairs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-crosshairs.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-crosshairs.Tpo -c -o ../snes9x_gtk-crosshairs.o `test -f '../crosshairs.cpp' || echo '$(srcdir)/'`../crosshairs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-crosshairs.Tpo ../$(DEPDIR)/snes9x_gtk-crosshairs.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../crosshairs.cpp' object='../snes9x_gtk-crosshairs.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-crosshairs.o `test -f '../crosshairs.cpp' || echo '$(srcdir)/'`../crosshairs.cpp + +../snes9x_gtk-crosshairs.obj: ../crosshairs.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-crosshairs.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-crosshairs.Tpo -c -o ../snes9x_gtk-crosshairs.obj `if test -f '../crosshairs.cpp'; then $(CYGPATH_W) '../crosshairs.cpp'; else $(CYGPATH_W) '$(srcdir)/../crosshairs.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-crosshairs.Tpo ../$(DEPDIR)/snes9x_gtk-crosshairs.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../crosshairs.cpp' object='../snes9x_gtk-crosshairs.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-crosshairs.obj `if test -f '../crosshairs.cpp'; then $(CYGPATH_W) '../crosshairs.cpp'; else $(CYGPATH_W) '$(srcdir)/../crosshairs.cpp'; fi` + +../snes9x_gtk-cpu.o: ../cpu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-cpu.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-cpu.Tpo -c -o ../snes9x_gtk-cpu.o `test -f '../cpu.cpp' || echo '$(srcdir)/'`../cpu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-cpu.Tpo ../$(DEPDIR)/snes9x_gtk-cpu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../cpu.cpp' object='../snes9x_gtk-cpu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-cpu.o `test -f '../cpu.cpp' || echo '$(srcdir)/'`../cpu.cpp + +../snes9x_gtk-cpu.obj: ../cpu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-cpu.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-cpu.Tpo -c -o ../snes9x_gtk-cpu.obj `if test -f '../cpu.cpp'; then $(CYGPATH_W) '../cpu.cpp'; else $(CYGPATH_W) '$(srcdir)/../cpu.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-cpu.Tpo ../$(DEPDIR)/snes9x_gtk-cpu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../cpu.cpp' object='../snes9x_gtk-cpu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-cpu.obj `if test -f '../cpu.cpp'; then $(CYGPATH_W) '../cpu.cpp'; else $(CYGPATH_W) '$(srcdir)/../cpu.cpp'; fi` + +../snes9x_gtk-sa1.o: ../sa1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-sa1.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-sa1.Tpo -c -o ../snes9x_gtk-sa1.o `test -f '../sa1.cpp' || echo '$(srcdir)/'`../sa1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-sa1.Tpo ../$(DEPDIR)/snes9x_gtk-sa1.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../sa1.cpp' object='../snes9x_gtk-sa1.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-sa1.o `test -f '../sa1.cpp' || echo '$(srcdir)/'`../sa1.cpp + +../snes9x_gtk-sa1.obj: ../sa1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-sa1.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-sa1.Tpo -c -o ../snes9x_gtk-sa1.obj `if test -f '../sa1.cpp'; then $(CYGPATH_W) '../sa1.cpp'; else $(CYGPATH_W) '$(srcdir)/../sa1.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-sa1.Tpo ../$(DEPDIR)/snes9x_gtk-sa1.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../sa1.cpp' object='../snes9x_gtk-sa1.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-sa1.obj `if test -f '../sa1.cpp'; then $(CYGPATH_W) '../sa1.cpp'; else $(CYGPATH_W) '$(srcdir)/../sa1.cpp'; fi` + +../snes9x_gtk-debug.o: ../debug.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-debug.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-debug.Tpo -c -o ../snes9x_gtk-debug.o `test -f '../debug.cpp' || echo '$(srcdir)/'`../debug.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-debug.Tpo ../$(DEPDIR)/snes9x_gtk-debug.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../debug.cpp' object='../snes9x_gtk-debug.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-debug.o `test -f '../debug.cpp' || echo '$(srcdir)/'`../debug.cpp + +../snes9x_gtk-debug.obj: ../debug.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-debug.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-debug.Tpo -c -o ../snes9x_gtk-debug.obj `if test -f '../debug.cpp'; then $(CYGPATH_W) '../debug.cpp'; else $(CYGPATH_W) '$(srcdir)/../debug.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-debug.Tpo ../$(DEPDIR)/snes9x_gtk-debug.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../debug.cpp' object='../snes9x_gtk-debug.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-debug.obj `if test -f '../debug.cpp'; then $(CYGPATH_W) '../debug.cpp'; else $(CYGPATH_W) '$(srcdir)/../debug.cpp'; fi` + +../snes9x_gtk-sdd1.o: ../sdd1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-sdd1.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-sdd1.Tpo -c -o ../snes9x_gtk-sdd1.o `test -f '../sdd1.cpp' || echo '$(srcdir)/'`../sdd1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-sdd1.Tpo ../$(DEPDIR)/snes9x_gtk-sdd1.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../sdd1.cpp' object='../snes9x_gtk-sdd1.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-sdd1.o `test -f '../sdd1.cpp' || echo '$(srcdir)/'`../sdd1.cpp + +../snes9x_gtk-sdd1.obj: ../sdd1.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-sdd1.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-sdd1.Tpo -c -o ../snes9x_gtk-sdd1.obj `if test -f '../sdd1.cpp'; then $(CYGPATH_W) '../sdd1.cpp'; else $(CYGPATH_W) '$(srcdir)/../sdd1.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-sdd1.Tpo ../$(DEPDIR)/snes9x_gtk-sdd1.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../sdd1.cpp' object='../snes9x_gtk-sdd1.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-sdd1.obj `if test -f '../sdd1.cpp'; then $(CYGPATH_W) '../sdd1.cpp'; else $(CYGPATH_W) '$(srcdir)/../sdd1.cpp'; fi` + +../snes9x_gtk-tile.o: ../tile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-tile.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-tile.Tpo -c -o ../snes9x_gtk-tile.o `test -f '../tile.cpp' || echo '$(srcdir)/'`../tile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-tile.Tpo ../$(DEPDIR)/snes9x_gtk-tile.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../tile.cpp' object='../snes9x_gtk-tile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-tile.o `test -f '../tile.cpp' || echo '$(srcdir)/'`../tile.cpp + +../snes9x_gtk-tile.obj: ../tile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-tile.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-tile.Tpo -c -o ../snes9x_gtk-tile.obj `if test -f '../tile.cpp'; then $(CYGPATH_W) '../tile.cpp'; else $(CYGPATH_W) '$(srcdir)/../tile.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-tile.Tpo ../$(DEPDIR)/snes9x_gtk-tile.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../tile.cpp' object='../snes9x_gtk-tile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-tile.obj `if test -f '../tile.cpp'; then $(CYGPATH_W) '../tile.cpp'; else $(CYGPATH_W) '$(srcdir)/../tile.cpp'; fi` + +../snes9x_gtk-srtc.o: ../srtc.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-srtc.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-srtc.Tpo -c -o ../snes9x_gtk-srtc.o `test -f '../srtc.cpp' || echo '$(srcdir)/'`../srtc.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-srtc.Tpo ../$(DEPDIR)/snes9x_gtk-srtc.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../srtc.cpp' object='../snes9x_gtk-srtc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-srtc.o `test -f '../srtc.cpp' || echo '$(srcdir)/'`../srtc.cpp + +../snes9x_gtk-srtc.obj: ../srtc.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-srtc.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-srtc.Tpo -c -o ../snes9x_gtk-srtc.obj `if test -f '../srtc.cpp'; then $(CYGPATH_W) '../srtc.cpp'; else $(CYGPATH_W) '$(srcdir)/../srtc.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-srtc.Tpo ../$(DEPDIR)/snes9x_gtk-srtc.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../srtc.cpp' object='../snes9x_gtk-srtc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-srtc.obj `if test -f '../srtc.cpp'; then $(CYGPATH_W) '../srtc.cpp'; else $(CYGPATH_W) '$(srcdir)/../srtc.cpp'; fi` + +../snes9x_gtk-gfx.o: ../gfx.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-gfx.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-gfx.Tpo -c -o ../snes9x_gtk-gfx.o `test -f '../gfx.cpp' || echo '$(srcdir)/'`../gfx.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-gfx.Tpo ../$(DEPDIR)/snes9x_gtk-gfx.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../gfx.cpp' object='../snes9x_gtk-gfx.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-gfx.o `test -f '../gfx.cpp' || echo '$(srcdir)/'`../gfx.cpp + +../snes9x_gtk-gfx.obj: ../gfx.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-gfx.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-gfx.Tpo -c -o ../snes9x_gtk-gfx.obj `if test -f '../gfx.cpp'; then $(CYGPATH_W) '../gfx.cpp'; else $(CYGPATH_W) '$(srcdir)/../gfx.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-gfx.Tpo ../$(DEPDIR)/snes9x_gtk-gfx.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../gfx.cpp' object='../snes9x_gtk-gfx.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-gfx.obj `if test -f '../gfx.cpp'; then $(CYGPATH_W) '../gfx.cpp'; else $(CYGPATH_W) '$(srcdir)/../gfx.cpp'; fi` + +../snes9x_gtk-memmap.o: ../memmap.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-memmap.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-memmap.Tpo -c -o ../snes9x_gtk-memmap.o `test -f '../memmap.cpp' || echo '$(srcdir)/'`../memmap.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-memmap.Tpo ../$(DEPDIR)/snes9x_gtk-memmap.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../memmap.cpp' object='../snes9x_gtk-memmap.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-memmap.o `test -f '../memmap.cpp' || echo '$(srcdir)/'`../memmap.cpp + +../snes9x_gtk-memmap.obj: ../memmap.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-memmap.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-memmap.Tpo -c -o ../snes9x_gtk-memmap.obj `if test -f '../memmap.cpp'; then $(CYGPATH_W) '../memmap.cpp'; else $(CYGPATH_W) '$(srcdir)/../memmap.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-memmap.Tpo ../$(DEPDIR)/snes9x_gtk-memmap.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../memmap.cpp' object='../snes9x_gtk-memmap.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-memmap.obj `if test -f '../memmap.cpp'; then $(CYGPATH_W) '../memmap.cpp'; else $(CYGPATH_W) '$(srcdir)/../memmap.cpp'; fi` + +../snes9x_gtk-clip.o: ../clip.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-clip.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-clip.Tpo -c -o ../snes9x_gtk-clip.o `test -f '../clip.cpp' || echo '$(srcdir)/'`../clip.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-clip.Tpo ../$(DEPDIR)/snes9x_gtk-clip.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../clip.cpp' object='../snes9x_gtk-clip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-clip.o `test -f '../clip.cpp' || echo '$(srcdir)/'`../clip.cpp + +../snes9x_gtk-clip.obj: ../clip.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-clip.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-clip.Tpo -c -o ../snes9x_gtk-clip.obj `if test -f '../clip.cpp'; then $(CYGPATH_W) '../clip.cpp'; else $(CYGPATH_W) '$(srcdir)/../clip.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-clip.Tpo ../$(DEPDIR)/snes9x_gtk-clip.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../clip.cpp' object='../snes9x_gtk-clip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-clip.obj `if test -f '../clip.cpp'; then $(CYGPATH_W) '../clip.cpp'; else $(CYGPATH_W) '$(srcdir)/../clip.cpp'; fi` + +../snes9x_gtk-ppu.o: ../ppu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-ppu.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-ppu.Tpo -c -o ../snes9x_gtk-ppu.o `test -f '../ppu.cpp' || echo '$(srcdir)/'`../ppu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-ppu.Tpo ../$(DEPDIR)/snes9x_gtk-ppu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../ppu.cpp' object='../snes9x_gtk-ppu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-ppu.o `test -f '../ppu.cpp' || echo '$(srcdir)/'`../ppu.cpp + +../snes9x_gtk-ppu.obj: ../ppu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-ppu.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-ppu.Tpo -c -o ../snes9x_gtk-ppu.obj `if test -f '../ppu.cpp'; then $(CYGPATH_W) '../ppu.cpp'; else $(CYGPATH_W) '$(srcdir)/../ppu.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-ppu.Tpo ../$(DEPDIR)/snes9x_gtk-ppu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../ppu.cpp' object='../snes9x_gtk-ppu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-ppu.obj `if test -f '../ppu.cpp'; then $(CYGPATH_W) '../ppu.cpp'; else $(CYGPATH_W) '$(srcdir)/../ppu.cpp'; fi` + +../snes9x_gtk-dma.o: ../dma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dma.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dma.Tpo -c -o ../snes9x_gtk-dma.o `test -f '../dma.cpp' || echo '$(srcdir)/'`../dma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dma.Tpo ../$(DEPDIR)/snes9x_gtk-dma.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dma.cpp' object='../snes9x_gtk-dma.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dma.o `test -f '../dma.cpp' || echo '$(srcdir)/'`../dma.cpp + +../snes9x_gtk-dma.obj: ../dma.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-dma.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-dma.Tpo -c -o ../snes9x_gtk-dma.obj `if test -f '../dma.cpp'; then $(CYGPATH_W) '../dma.cpp'; else $(CYGPATH_W) '$(srcdir)/../dma.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-dma.Tpo ../$(DEPDIR)/snes9x_gtk-dma.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../dma.cpp' object='../snes9x_gtk-dma.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-dma.obj `if test -f '../dma.cpp'; then $(CYGPATH_W) '../dma.cpp'; else $(CYGPATH_W) '$(srcdir)/../dma.cpp'; fi` + +../snes9x_gtk-snes9x.o: ../snes9x.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-snes9x.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-snes9x.Tpo -c -o ../snes9x_gtk-snes9x.o `test -f '../snes9x.cpp' || echo '$(srcdir)/'`../snes9x.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-snes9x.Tpo ../$(DEPDIR)/snes9x_gtk-snes9x.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../snes9x.cpp' object='../snes9x_gtk-snes9x.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-snes9x.o `test -f '../snes9x.cpp' || echo '$(srcdir)/'`../snes9x.cpp + +../snes9x_gtk-snes9x.obj: ../snes9x.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-snes9x.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-snes9x.Tpo -c -o ../snes9x_gtk-snes9x.obj `if test -f '../snes9x.cpp'; then $(CYGPATH_W) '../snes9x.cpp'; else $(CYGPATH_W) '$(srcdir)/../snes9x.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-snes9x.Tpo ../$(DEPDIR)/snes9x_gtk-snes9x.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../snes9x.cpp' object='../snes9x_gtk-snes9x.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-snes9x.obj `if test -f '../snes9x.cpp'; then $(CYGPATH_W) '../snes9x.cpp'; else $(CYGPATH_W) '$(srcdir)/../snes9x.cpp'; fi` + +../snes9x_gtk-globals.o: ../globals.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-globals.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-globals.Tpo -c -o ../snes9x_gtk-globals.o `test -f '../globals.cpp' || echo '$(srcdir)/'`../globals.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-globals.Tpo ../$(DEPDIR)/snes9x_gtk-globals.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../globals.cpp' object='../snes9x_gtk-globals.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-globals.o `test -f '../globals.cpp' || echo '$(srcdir)/'`../globals.cpp + +../snes9x_gtk-globals.obj: ../globals.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-globals.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-globals.Tpo -c -o ../snes9x_gtk-globals.obj `if test -f '../globals.cpp'; then $(CYGPATH_W) '../globals.cpp'; else $(CYGPATH_W) '$(srcdir)/../globals.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-globals.Tpo ../$(DEPDIR)/snes9x_gtk-globals.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../globals.cpp' object='../snes9x_gtk-globals.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-globals.obj `if test -f '../globals.cpp'; then $(CYGPATH_W) '../globals.cpp'; else $(CYGPATH_W) '$(srcdir)/../globals.cpp'; fi` + +../snes9x_gtk-reader.o: ../reader.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-reader.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-reader.Tpo -c -o ../snes9x_gtk-reader.o `test -f '../reader.cpp' || echo '$(srcdir)/'`../reader.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-reader.Tpo ../$(DEPDIR)/snes9x_gtk-reader.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../reader.cpp' object='../snes9x_gtk-reader.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-reader.o `test -f '../reader.cpp' || echo '$(srcdir)/'`../reader.cpp + +../snes9x_gtk-reader.obj: ../reader.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-reader.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-reader.Tpo -c -o ../snes9x_gtk-reader.obj `if test -f '../reader.cpp'; then $(CYGPATH_W) '../reader.cpp'; else $(CYGPATH_W) '$(srcdir)/../reader.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-reader.Tpo ../$(DEPDIR)/snes9x_gtk-reader.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../reader.cpp' object='../snes9x_gtk-reader.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-reader.obj `if test -f '../reader.cpp'; then $(CYGPATH_W) '../reader.cpp'; else $(CYGPATH_W) '$(srcdir)/../reader.cpp'; fi` + +../snes9x_gtk-conffile.o: ../conffile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-conffile.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-conffile.Tpo -c -o ../snes9x_gtk-conffile.o `test -f '../conffile.cpp' || echo '$(srcdir)/'`../conffile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-conffile.Tpo ../$(DEPDIR)/snes9x_gtk-conffile.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../conffile.cpp' object='../snes9x_gtk-conffile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-conffile.o `test -f '../conffile.cpp' || echo '$(srcdir)/'`../conffile.cpp + +../snes9x_gtk-conffile.obj: ../conffile.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-conffile.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-conffile.Tpo -c -o ../snes9x_gtk-conffile.obj `if test -f '../conffile.cpp'; then $(CYGPATH_W) '../conffile.cpp'; else $(CYGPATH_W) '$(srcdir)/../conffile.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-conffile.Tpo ../$(DEPDIR)/snes9x_gtk-conffile.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../conffile.cpp' object='../snes9x_gtk-conffile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-conffile.obj `if test -f '../conffile.cpp'; then $(CYGPATH_W) '../conffile.cpp'; else $(CYGPATH_W) '$(srcdir)/../conffile.cpp'; fi` + +../snes9x_gtk-bsx.o: ../bsx.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-bsx.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-bsx.Tpo -c -o ../snes9x_gtk-bsx.o `test -f '../bsx.cpp' || echo '$(srcdir)/'`../bsx.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-bsx.Tpo ../$(DEPDIR)/snes9x_gtk-bsx.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../bsx.cpp' object='../snes9x_gtk-bsx.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-bsx.o `test -f '../bsx.cpp' || echo '$(srcdir)/'`../bsx.cpp + +../snes9x_gtk-bsx.obj: ../bsx.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-bsx.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-bsx.Tpo -c -o ../snes9x_gtk-bsx.obj `if test -f '../bsx.cpp'; then $(CYGPATH_W) '../bsx.cpp'; else $(CYGPATH_W) '$(srcdir)/../bsx.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-bsx.Tpo ../$(DEPDIR)/snes9x_gtk-bsx.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../bsx.cpp' object='../snes9x_gtk-bsx.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-bsx.obj `if test -f '../bsx.cpp'; then $(CYGPATH_W) '../bsx.cpp'; else $(CYGPATH_W) '$(srcdir)/../bsx.cpp'; fi` + +../snes9x_gtk-logger.o: ../logger.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-logger.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-logger.Tpo -c -o ../snes9x_gtk-logger.o `test -f '../logger.cpp' || echo '$(srcdir)/'`../logger.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-logger.Tpo ../$(DEPDIR)/snes9x_gtk-logger.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../logger.cpp' object='../snes9x_gtk-logger.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-logger.o `test -f '../logger.cpp' || echo '$(srcdir)/'`../logger.cpp + +../snes9x_gtk-logger.obj: ../logger.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-logger.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-logger.Tpo -c -o ../snes9x_gtk-logger.obj `if test -f '../logger.cpp'; then $(CYGPATH_W) '../logger.cpp'; else $(CYGPATH_W) '$(srcdir)/../logger.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-logger.Tpo ../$(DEPDIR)/snes9x_gtk-logger.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../logger.cpp' object='../snes9x_gtk-logger.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-logger.obj `if test -f '../logger.cpp'; then $(CYGPATH_W) '../logger.cpp'; else $(CYGPATH_W) '$(srcdir)/../logger.cpp'; fi` + +../snes9x_gtk-snapshot.o: ../snapshot.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-snapshot.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-snapshot.Tpo -c -o ../snes9x_gtk-snapshot.o `test -f '../snapshot.cpp' || echo '$(srcdir)/'`../snapshot.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-snapshot.Tpo ../$(DEPDIR)/snes9x_gtk-snapshot.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../snapshot.cpp' object='../snes9x_gtk-snapshot.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-snapshot.o `test -f '../snapshot.cpp' || echo '$(srcdir)/'`../snapshot.cpp + +../snes9x_gtk-snapshot.obj: ../snapshot.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-snapshot.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-snapshot.Tpo -c -o ../snes9x_gtk-snapshot.obj `if test -f '../snapshot.cpp'; then $(CYGPATH_W) '../snapshot.cpp'; else $(CYGPATH_W) '$(srcdir)/../snapshot.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-snapshot.Tpo ../$(DEPDIR)/snes9x_gtk-snapshot.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../snapshot.cpp' object='../snes9x_gtk-snapshot.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-snapshot.obj `if test -f '../snapshot.cpp'; then $(CYGPATH_W) '../snapshot.cpp'; else $(CYGPATH_W) '$(srcdir)/../snapshot.cpp'; fi` + +../snes9x_gtk-screenshot.o: ../screenshot.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-screenshot.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-screenshot.Tpo -c -o ../snes9x_gtk-screenshot.o `test -f '../screenshot.cpp' || echo '$(srcdir)/'`../screenshot.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-screenshot.Tpo ../$(DEPDIR)/snes9x_gtk-screenshot.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../screenshot.cpp' object='../snes9x_gtk-screenshot.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-screenshot.o `test -f '../screenshot.cpp' || echo '$(srcdir)/'`../screenshot.cpp + +../snes9x_gtk-screenshot.obj: ../screenshot.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-screenshot.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-screenshot.Tpo -c -o ../snes9x_gtk-screenshot.obj `if test -f '../screenshot.cpp'; then $(CYGPATH_W) '../screenshot.cpp'; else $(CYGPATH_W) '$(srcdir)/../screenshot.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-screenshot.Tpo ../$(DEPDIR)/snes9x_gtk-screenshot.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../screenshot.cpp' object='../snes9x_gtk-screenshot.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-screenshot.obj `if test -f '../screenshot.cpp'; then $(CYGPATH_W) '../screenshot.cpp'; else $(CYGPATH_W) '$(srcdir)/../screenshot.cpp'; fi` + +../snes9x_gtk-movie.o: ../movie.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-movie.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-movie.Tpo -c -o ../snes9x_gtk-movie.o `test -f '../movie.cpp' || echo '$(srcdir)/'`../movie.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-movie.Tpo ../$(DEPDIR)/snes9x_gtk-movie.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../movie.cpp' object='../snes9x_gtk-movie.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-movie.o `test -f '../movie.cpp' || echo '$(srcdir)/'`../movie.cpp + +../snes9x_gtk-movie.obj: ../movie.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-movie.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-movie.Tpo -c -o ../snes9x_gtk-movie.obj `if test -f '../movie.cpp'; then $(CYGPATH_W) '../movie.cpp'; else $(CYGPATH_W) '$(srcdir)/../movie.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-movie.Tpo ../$(DEPDIR)/snes9x_gtk-movie.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../movie.cpp' object='../snes9x_gtk-movie.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-movie.obj `if test -f '../movie.cpp'; then $(CYGPATH_W) '../movie.cpp'; else $(CYGPATH_W) '$(srcdir)/../movie.cpp'; fi` + +../snes9x_gtk-cpuops.o: ../cpuops.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-cpuops.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-cpuops.Tpo -c -o ../snes9x_gtk-cpuops.o `test -f '../cpuops.cpp' || echo '$(srcdir)/'`../cpuops.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-cpuops.Tpo ../$(DEPDIR)/snes9x_gtk-cpuops.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../cpuops.cpp' object='../snes9x_gtk-cpuops.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-cpuops.o `test -f '../cpuops.cpp' || echo '$(srcdir)/'`../cpuops.cpp + +../snes9x_gtk-cpuops.obj: ../cpuops.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-cpuops.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-cpuops.Tpo -c -o ../snes9x_gtk-cpuops.obj `if test -f '../cpuops.cpp'; then $(CYGPATH_W) '../cpuops.cpp'; else $(CYGPATH_W) '$(srcdir)/../cpuops.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-cpuops.Tpo ../$(DEPDIR)/snes9x_gtk-cpuops.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../cpuops.cpp' object='../snes9x_gtk-cpuops.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-cpuops.obj `if test -f '../cpuops.cpp'; then $(CYGPATH_W) '../cpuops.cpp'; else $(CYGPATH_W) '$(srcdir)/../cpuops.cpp'; fi` + +../snes9x_gtk-cpuexec.o: ../cpuexec.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-cpuexec.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-cpuexec.Tpo -c -o ../snes9x_gtk-cpuexec.o `test -f '../cpuexec.cpp' || echo '$(srcdir)/'`../cpuexec.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-cpuexec.Tpo ../$(DEPDIR)/snes9x_gtk-cpuexec.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../cpuexec.cpp' object='../snes9x_gtk-cpuexec.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-cpuexec.o `test -f '../cpuexec.cpp' || echo '$(srcdir)/'`../cpuexec.cpp + +../snes9x_gtk-cpuexec.obj: ../cpuexec.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-cpuexec.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-cpuexec.Tpo -c -o ../snes9x_gtk-cpuexec.obj `if test -f '../cpuexec.cpp'; then $(CYGPATH_W) '../cpuexec.cpp'; else $(CYGPATH_W) '$(srcdir)/../cpuexec.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-cpuexec.Tpo ../$(DEPDIR)/snes9x_gtk-cpuexec.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../cpuexec.cpp' object='../snes9x_gtk-cpuexec.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-cpuexec.obj `if test -f '../cpuexec.cpp'; then $(CYGPATH_W) '../cpuexec.cpp'; else $(CYGPATH_W) '$(srcdir)/../cpuexec.cpp'; fi` + +../snes9x_gtk-sa1cpu.o: ../sa1cpu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-sa1cpu.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-sa1cpu.Tpo -c -o ../snes9x_gtk-sa1cpu.o `test -f '../sa1cpu.cpp' || echo '$(srcdir)/'`../sa1cpu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-sa1cpu.Tpo ../$(DEPDIR)/snes9x_gtk-sa1cpu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../sa1cpu.cpp' object='../snes9x_gtk-sa1cpu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-sa1cpu.o `test -f '../sa1cpu.cpp' || echo '$(srcdir)/'`../sa1cpu.cpp + +../snes9x_gtk-sa1cpu.obj: ../sa1cpu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-sa1cpu.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-sa1cpu.Tpo -c -o ../snes9x_gtk-sa1cpu.obj `if test -f '../sa1cpu.cpp'; then $(CYGPATH_W) '../sa1cpu.cpp'; else $(CYGPATH_W) '$(srcdir)/../sa1cpu.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-sa1cpu.Tpo ../$(DEPDIR)/snes9x_gtk-sa1cpu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../sa1cpu.cpp' object='../snes9x_gtk-sa1cpu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-sa1cpu.obj `if test -f '../sa1cpu.cpp'; then $(CYGPATH_W) '../sa1cpu.cpp'; else $(CYGPATH_W) '$(srcdir)/../sa1cpu.cpp'; fi` + +../snes9x_gtk-cheats.o: ../cheats.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-cheats.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-cheats.Tpo -c -o ../snes9x_gtk-cheats.o `test -f '../cheats.cpp' || echo '$(srcdir)/'`../cheats.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-cheats.Tpo ../$(DEPDIR)/snes9x_gtk-cheats.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../cheats.cpp' object='../snes9x_gtk-cheats.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-cheats.o `test -f '../cheats.cpp' || echo '$(srcdir)/'`../cheats.cpp + +../snes9x_gtk-cheats.obj: ../cheats.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-cheats.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-cheats.Tpo -c -o ../snes9x_gtk-cheats.obj `if test -f '../cheats.cpp'; then $(CYGPATH_W) '../cheats.cpp'; else $(CYGPATH_W) '$(srcdir)/../cheats.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-cheats.Tpo ../$(DEPDIR)/snes9x_gtk-cheats.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../cheats.cpp' object='../snes9x_gtk-cheats.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-cheats.obj `if test -f '../cheats.cpp'; then $(CYGPATH_W) '../cheats.cpp'; else $(CYGPATH_W) '$(srcdir)/../cheats.cpp'; fi` + +../snes9x_gtk-cheats2.o: ../cheats2.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-cheats2.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-cheats2.Tpo -c -o ../snes9x_gtk-cheats2.o `test -f '../cheats2.cpp' || echo '$(srcdir)/'`../cheats2.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-cheats2.Tpo ../$(DEPDIR)/snes9x_gtk-cheats2.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../cheats2.cpp' object='../snes9x_gtk-cheats2.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-cheats2.o `test -f '../cheats2.cpp' || echo '$(srcdir)/'`../cheats2.cpp + +../snes9x_gtk-cheats2.obj: ../cheats2.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-cheats2.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-cheats2.Tpo -c -o ../snes9x_gtk-cheats2.obj `if test -f '../cheats2.cpp'; then $(CYGPATH_W) '../cheats2.cpp'; else $(CYGPATH_W) '$(srcdir)/../cheats2.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-cheats2.Tpo ../$(DEPDIR)/snes9x_gtk-cheats2.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../cheats2.cpp' object='../snes9x_gtk-cheats2.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-cheats2.obj `if test -f '../cheats2.cpp'; then $(CYGPATH_W) '../cheats2.cpp'; else $(CYGPATH_W) '$(srcdir)/../cheats2.cpp'; fi` + +../snes9x_gtk-sdd1emu.o: ../sdd1emu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-sdd1emu.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-sdd1emu.Tpo -c -o ../snes9x_gtk-sdd1emu.o `test -f '../sdd1emu.cpp' || echo '$(srcdir)/'`../sdd1emu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-sdd1emu.Tpo ../$(DEPDIR)/snes9x_gtk-sdd1emu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../sdd1emu.cpp' object='../snes9x_gtk-sdd1emu.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-sdd1emu.o `test -f '../sdd1emu.cpp' || echo '$(srcdir)/'`../sdd1emu.cpp + +../snes9x_gtk-sdd1emu.obj: ../sdd1emu.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-sdd1emu.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-sdd1emu.Tpo -c -o ../snes9x_gtk-sdd1emu.obj `if test -f '../sdd1emu.cpp'; then $(CYGPATH_W) '../sdd1emu.cpp'; else $(CYGPATH_W) '$(srcdir)/../sdd1emu.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-sdd1emu.Tpo ../$(DEPDIR)/snes9x_gtk-sdd1emu.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../sdd1emu.cpp' object='../snes9x_gtk-sdd1emu.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-sdd1emu.obj `if test -f '../sdd1emu.cpp'; then $(CYGPATH_W) '../sdd1emu.cpp'; else $(CYGPATH_W) '$(srcdir)/../sdd1emu.cpp'; fi` + +../snes9x_gtk-netplay.o: ../netplay.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-netplay.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-netplay.Tpo -c -o ../snes9x_gtk-netplay.o `test -f '../netplay.cpp' || echo '$(srcdir)/'`../netplay.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-netplay.Tpo ../$(DEPDIR)/snes9x_gtk-netplay.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../netplay.cpp' object='../snes9x_gtk-netplay.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-netplay.o `test -f '../netplay.cpp' || echo '$(srcdir)/'`../netplay.cpp + +../snes9x_gtk-netplay.obj: ../netplay.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-netplay.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-netplay.Tpo -c -o ../snes9x_gtk-netplay.obj `if test -f '../netplay.cpp'; then $(CYGPATH_W) '../netplay.cpp'; else $(CYGPATH_W) '$(srcdir)/../netplay.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-netplay.Tpo ../$(DEPDIR)/snes9x_gtk-netplay.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../netplay.cpp' object='../snes9x_gtk-netplay.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-netplay.obj `if test -f '../netplay.cpp'; then $(CYGPATH_W) '../netplay.cpp'; else $(CYGPATH_W) '$(srcdir)/../netplay.cpp'; fi` + +../snes9x_gtk-server.o: ../server.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-server.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-server.Tpo -c -o ../snes9x_gtk-server.o `test -f '../server.cpp' || echo '$(srcdir)/'`../server.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-server.Tpo ../$(DEPDIR)/snes9x_gtk-server.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../server.cpp' object='../snes9x_gtk-server.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-server.o `test -f '../server.cpp' || echo '$(srcdir)/'`../server.cpp + +../snes9x_gtk-server.obj: ../server.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-server.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-server.Tpo -c -o ../snes9x_gtk-server.obj `if test -f '../server.cpp'; then $(CYGPATH_W) '../server.cpp'; else $(CYGPATH_W) '$(srcdir)/../server.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-server.Tpo ../$(DEPDIR)/snes9x_gtk-server.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../server.cpp' object='../snes9x_gtk-server.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-server.obj `if test -f '../server.cpp'; then $(CYGPATH_W) '../server.cpp'; else $(CYGPATH_W) '$(srcdir)/../server.cpp'; fi` + +../snes9x_gtk-loadzip.o: ../loadzip.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-loadzip.o -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-loadzip.Tpo -c -o ../snes9x_gtk-loadzip.o `test -f '../loadzip.cpp' || echo '$(srcdir)/'`../loadzip.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-loadzip.Tpo ../$(DEPDIR)/snes9x_gtk-loadzip.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../loadzip.cpp' object='../snes9x_gtk-loadzip.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-loadzip.o `test -f '../loadzip.cpp' || echo '$(srcdir)/'`../loadzip.cpp + +../snes9x_gtk-loadzip.obj: ../loadzip.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT ../snes9x_gtk-loadzip.obj -MD -MP -MF ../$(DEPDIR)/snes9x_gtk-loadzip.Tpo -c -o ../snes9x_gtk-loadzip.obj `if test -f '../loadzip.cpp'; then $(CYGPATH_W) '../loadzip.cpp'; else $(CYGPATH_W) '$(srcdir)/../loadzip.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) ../$(DEPDIR)/snes9x_gtk-loadzip.Tpo ../$(DEPDIR)/snes9x_gtk-loadzip.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../loadzip.cpp' object='../snes9x_gtk-loadzip.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o ../snes9x_gtk-loadzip.obj `if test -f '../loadzip.cpp'; then $(CYGPATH_W) '../loadzip.cpp'; else $(CYGPATH_W) '$(srcdir)/../loadzip.cpp'; fi` + +src/snes9x_gtk-gtk_display_driver_opengl.o: src/gtk_display_driver_opengl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_display_driver_opengl.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_opengl.Tpo -c -o src/snes9x_gtk-gtk_display_driver_opengl.o `test -f 'src/gtk_display_driver_opengl.cpp' || echo '$(srcdir)/'`src/gtk_display_driver_opengl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_opengl.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_opengl.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_display_driver_opengl.cpp' object='src/snes9x_gtk-gtk_display_driver_opengl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_display_driver_opengl.o `test -f 'src/gtk_display_driver_opengl.cpp' || echo '$(srcdir)/'`src/gtk_display_driver_opengl.cpp + +src/snes9x_gtk-gtk_display_driver_opengl.obj: src/gtk_display_driver_opengl.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_display_driver_opengl.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_opengl.Tpo -c -o src/snes9x_gtk-gtk_display_driver_opengl.obj `if test -f 'src/gtk_display_driver_opengl.cpp'; then $(CYGPATH_W) 'src/gtk_display_driver_opengl.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_display_driver_opengl.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_opengl.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_opengl.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_display_driver_opengl.cpp' object='src/snes9x_gtk-gtk_display_driver_opengl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_display_driver_opengl.obj `if test -f 'src/gtk_display_driver_opengl.cpp'; then $(CYGPATH_W) 'src/gtk_display_driver_opengl.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_display_driver_opengl.cpp'; fi` + +src/snes9x_gtk-gtk_display_driver_xv.o: src/gtk_display_driver_xv.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_display_driver_xv.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_xv.Tpo -c -o src/snes9x_gtk-gtk_display_driver_xv.o `test -f 'src/gtk_display_driver_xv.cpp' || echo '$(srcdir)/'`src/gtk_display_driver_xv.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_xv.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_xv.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_display_driver_xv.cpp' object='src/snes9x_gtk-gtk_display_driver_xv.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_display_driver_xv.o `test -f 'src/gtk_display_driver_xv.cpp' || echo '$(srcdir)/'`src/gtk_display_driver_xv.cpp + +src/snes9x_gtk-gtk_display_driver_xv.obj: src/gtk_display_driver_xv.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_display_driver_xv.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_xv.Tpo -c -o src/snes9x_gtk-gtk_display_driver_xv.obj `if test -f 'src/gtk_display_driver_xv.cpp'; then $(CYGPATH_W) 'src/gtk_display_driver_xv.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_display_driver_xv.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_xv.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_display_driver_xv.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_display_driver_xv.cpp' object='src/snes9x_gtk-gtk_display_driver_xv.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_display_driver_xv.obj `if test -f 'src/gtk_display_driver_xv.cpp'; then $(CYGPATH_W) 'src/gtk_display_driver_xv.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_display_driver_xv.cpp'; fi` + +src/snes9x_gtk-gtk_netplay_dialog.o: src/gtk_netplay_dialog.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_netplay_dialog.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_netplay_dialog.Tpo -c -o src/snes9x_gtk-gtk_netplay_dialog.o `test -f 'src/gtk_netplay_dialog.cpp' || echo '$(srcdir)/'`src/gtk_netplay_dialog.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_netplay_dialog.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_netplay_dialog.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_netplay_dialog.cpp' object='src/snes9x_gtk-gtk_netplay_dialog.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_netplay_dialog.o `test -f 'src/gtk_netplay_dialog.cpp' || echo '$(srcdir)/'`src/gtk_netplay_dialog.cpp + +src/snes9x_gtk-gtk_netplay_dialog.obj: src/gtk_netplay_dialog.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_netplay_dialog.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_netplay_dialog.Tpo -c -o src/snes9x_gtk-gtk_netplay_dialog.obj `if test -f 'src/gtk_netplay_dialog.cpp'; then $(CYGPATH_W) 'src/gtk_netplay_dialog.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_netplay_dialog.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_netplay_dialog.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_netplay_dialog.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_netplay_dialog.cpp' object='src/snes9x_gtk-gtk_netplay_dialog.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_netplay_dialog.obj `if test -f 'src/gtk_netplay_dialog.cpp'; then $(CYGPATH_W) 'src/gtk_netplay_dialog.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_netplay_dialog.cpp'; fi` + +src/snes9x_gtk-gtk_netplay.o: src/gtk_netplay.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_netplay.o -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_netplay.Tpo -c -o src/snes9x_gtk-gtk_netplay.o `test -f 'src/gtk_netplay.cpp' || echo '$(srcdir)/'`src/gtk_netplay.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_netplay.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_netplay.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_netplay.cpp' object='src/snes9x_gtk-gtk_netplay.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_netplay.o `test -f 'src/gtk_netplay.cpp' || echo '$(srcdir)/'`src/gtk_netplay.cpp + +src/snes9x_gtk-gtk_netplay.obj: src/gtk_netplay.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -MT src/snes9x_gtk-gtk_netplay.obj -MD -MP -MF src/$(DEPDIR)/snes9x_gtk-gtk_netplay.Tpo -c -o src/snes9x_gtk-gtk_netplay.obj `if test -f 'src/gtk_netplay.cpp'; then $(CYGPATH_W) 'src/gtk_netplay.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_netplay.cpp'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/snes9x_gtk-gtk_netplay.Tpo src/$(DEPDIR)/snes9x_gtk-gtk_netplay.Po +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/gtk_netplay.cpp' object='src/snes9x_gtk-gtk_netplay.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(snes9x_gtk_CXXFLAGS) $(CXXFLAGS) -c -o src/snes9x_gtk-gtk_netplay.obj `if test -f 'src/gtk_netplay.cpp'; then $(CYGPATH_W) 'src/gtk_netplay.cpp'; else $(CYGPATH_W) '$(srcdir)/src/gtk_netplay.cpp'; fi` + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(LIBRARIES) $(PROGRAMS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f ../$(DEPDIR)/$(am__dirstamp) + -rm -f ../$(am__dirstamp) + -rm -f ../apu/$(DEPDIR)/$(am__dirstamp) + -rm -f ../apu/$(am__dirstamp) + -rm -f ../filter/$(DEPDIR)/$(am__dirstamp) + -rm -f ../filter/$(am__dirstamp) + -rm -f ../i386/$(DEPDIR)/$(am__dirstamp) + -rm -f ../i386/$(am__dirstamp) + -rm -f ../jma/$(DEPDIR)/$(am__dirstamp) + -rm -f ../jma/$(am__dirstamp) + -rm -f ../unzip/$(DEPDIR)/$(am__dirstamp) + -rm -f ../unzip/$(am__dirstamp) + -rm -f src/$(DEPDIR)/$(am__dirstamp) + -rm -f src/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf ../$(DEPDIR) ../apu/$(DEPDIR) ../filter/$(DEPDIR) ../jma/$(DEPDIR) ../unzip/$(DEPDIR) src/$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -rf ../$(DEPDIR) ../apu/$(DEPDIR) ../filter/$(DEPDIR) ../jma/$(DEPDIR) ../unzip/$(DEPDIR) src/$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-binPROGRAMS \ + clean-generic clean-noinstLIBRARIES ctags ctags-recursive dist \ + dist-all dist-bzip2 dist-gzip dist-lzma dist-shar dist-tarZ \ + dist-xz dist-zip distcheck distclean distclean-compile \ + distclean-generic distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-binPROGRAMS + + +src/sourcify: src/sourcify.c + $(CC) src/sourcify.c -o src/sourcify + +src/gtk_glade.cpp: src/sourcify src/snes9x.glade + src/sourcify src/snes9x.glade src/gtk_glade.cpp snes9x_glade + +.asm.o: + $(NASM) -f elf -DELF $(NASM_FLAGS) -i ./ -i ../ -i ../i386/ -i i386/ -o $@ $*.asm + +.ASM.o: + $(NASM) -f elf -DELF $(NASM_FLAGS) -i ./ -i ../ -i ../i386/ -i i386/ $*.ASM -o $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gtk/aclocal.m4 b/gtk/aclocal.m4 new file mode 100644 index 00000000..4bd1a0d8 --- /dev/null +++ b/gtk/aclocal.m4 @@ -0,0 +1,1828 @@ +# generated automatically by aclocal 1.11.1 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],, +[m4_warning([this file was generated for autoconf 2.65. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# Copyright (C) 1995-2002 Free Software Foundation, Inc. +# Copyright (C) 2001-2003,2004 Red Hat, Inc. +# +# This file is free software, distributed under the terms of the GNU +# General Public License. As a special exception to the GNU General +# Public License, this file may be distributed as part of a program +# that contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995, 1996 +# +# Modified to never use included libintl. +# Owen Taylor , 12/15/1998 +# +# Major rework to remove unused code +# Owen Taylor , 12/11/2002 +# +# Added better handling of ALL_LINGUAS from GNU gettext version +# written by Bruno Haible, Owen Taylor 5/30/3002 +# +# Modified to require ngettext +# Matthias Clasen 08/06/2004 +# +# We need this here as well, since someone might use autoconf-2.5x +# to configure GLib then an older version to configure a package +# using AM_GLIB_GNU_GETTEXT +AC_PREREQ(2.53) + +dnl +dnl We go to great lengths to make sure that aclocal won't +dnl try to pull in the installed version of these macros +dnl when running aclocal in the glib directory. +dnl +m4_copy([AC_DEFUN],[glib_DEFUN]) +m4_copy([AC_REQUIRE],[glib_REQUIRE]) +dnl +dnl At the end, if we're not within glib, we'll define the public +dnl definitions in terms of our private definitions. +dnl + +# GLIB_LC_MESSAGES +#-------------------- +glib_DEFUN([GLIB_LC_MESSAGES], + [AC_CHECK_HEADERS([locale.h]) + if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your file defines LC_MESSAGES.]) + fi + fi]) + +# GLIB_PATH_PROG_WITH_TEST +#---------------------------- +dnl GLIB_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +glib_DEFUN([GLIB_PATH_PROG_WITH_TEST], +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# GLIB_WITH_NLS +#----------------- +glib_DEFUN([GLIB_WITH_NLS], + dnl NLS is obligatory + [USE_NLS=yes + AC_SUBST(USE_NLS) + + gt_cv_have_gettext=no + + CATOBJEXT=NONE + XGETTEXT=: + INTLLIBS= + + AC_CHECK_HEADER(libintl.h, + [gt_cv_func_dgettext_libintl="no" + libintl_extra_libs="" + + # + # First check in libc + # + AC_CACHE_CHECK([for ngettext in libc], gt_cv_func_ngettext_libc, + [AC_TRY_LINK([ +#include +], + [return !ngettext ("","", 1)], + gt_cv_func_ngettext_libc=yes, + gt_cv_func_ngettext_libc=no) + ]) + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc, + [AC_TRY_LINK([ +#include +], + [return !dgettext ("","")], + gt_cv_func_dgettext_libc=yes, + gt_cv_func_dgettext_libc=no) + ]) + fi + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + AC_CHECK_FUNCS(bind_textdomain_codeset) + fi + + # + # If we don't have everything we want, check in libintl + # + if test "$gt_cv_func_dgettext_libc" != "yes" \ + || test "$gt_cv_func_ngettext_libc" != "yes" \ + || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then + + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CHECK_LIB(intl, ngettext, + [AC_CHECK_LIB(intl, dgettext, + gt_cv_func_dgettext_libintl=yes)])]) + + if test "$gt_cv_func_dgettext_libintl" != "yes" ; then + AC_MSG_CHECKING([if -liconv is needed to use gettext]) + AC_MSG_RESULT([]) + AC_CHECK_LIB(intl, ngettext, + [AC_CHECK_LIB(intl, dcgettext, + [gt_cv_func_dgettext_libintl=yes + libintl_extra_libs=-liconv], + :,-liconv)], + :,-liconv) + fi + + # + # If we found libintl, then check in it for bind_textdomain_codeset(); + # we'll prefer libc if neither have bind_textdomain_codeset(), + # and both have dgettext and ngettext + # + if test "$gt_cv_func_dgettext_libintl" = "yes" ; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS -lintl $libintl_extra_libs" + unset ac_cv_func_bind_textdomain_codeset + AC_CHECK_FUNCS(bind_textdomain_codeset) + LIBS="$glib_save_LIBS" + + if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then + gt_cv_func_dgettext_libc=no + else + if test "$gt_cv_func_dgettext_libc" = "yes" \ + && test "$gt_cv_func_ngettext_libc" = "yes"; then + gt_cv_func_dgettext_libintl=no + fi + fi + fi + fi + + if test "$gt_cv_func_dgettext_libc" = "yes" \ + || test "$gt_cv_func_dgettext_libintl" = "yes"; then + gt_cv_have_gettext=yes + fi + + if test "$gt_cv_func_dgettext_libintl" = "yes"; then + INTLLIBS="-lintl $libintl_extra_libs" + fi + + if test "$gt_cv_have_gettext" = "yes"; then + AC_DEFINE(HAVE_GETTEXT,1, + [Define if the GNU gettext() function is already present or preinstalled.]) + GLIB_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS $INTLLIBS" + AC_CHECK_FUNCS(dcgettext) + MSGFMT_OPTS= + AC_MSG_CHECKING([if msgfmt accepts -c]) + GLIB_RUN_PROG([$MSGFMT -c -o /dev/null],[ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: test 1.0\n" +"PO-Revision-Date: 2007-02-15 12:01+0100\n" +"Last-Translator: test \n" +"Language-Team: C \n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" +], [MSGFMT_OPTS=-c; AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) + AC_SUBST(MSGFMT_OPTS) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + GLIB_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [case $host in + *-*-solaris*) + dnl On Solaris, if bind_textdomain_codeset is in libc, + dnl GNU format message catalog is always supported, + dnl since both are added to the libc all together. + dnl Hence, we'd like to go with DATADIRNAME=share and + dnl and CATOBJEXT=.gmo in this case. + AC_CHECK_FUNC(bind_textdomain_codeset, + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + ;; + *) + CATOBJEXT=.mo + DATADIRNAME=lib + ;; + esac]) + LIBS="$glib_save_LIBS" + INSTOBJEXT=.mo + else + gt_cv_have_gettext=no + fi + fi + ]) + + if test "$gt_cv_have_gettext" = "yes" ; then + AC_DEFINE(ENABLE_NLS, 1, + [always defined to indicate that i18n is enabled]) + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is not GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + + AC_OUTPUT_COMMANDS( + [case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac]) + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.in. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLLIBS) + AC_SUBST(PO_IN_DATADIR_TRUE) + AC_SUBST(PO_IN_DATADIR_FALSE) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +# AM_GLIB_GNU_GETTEXT +# ------------------- +# Do checks necessary for use of gettext. If a suitable implementation +# of gettext is found in either in libintl or in the C library, +# it will set INTLLIBS to the libraries needed for use of gettext +# and AC_DEFINE() HAVE_GETTEXT and ENABLE_NLS. (The shell variable +# gt_cv_have_gettext will be set to "yes".) It will also call AC_SUBST() +# on various variables needed by the Makefile.in.in installed by +# glib-gettextize. +dnl +glib_DEFUN([GLIB_GNU_GETTEXT], + [AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + + GLIB_LC_MESSAGES + GLIB_WITH_NLS + + if test "$gt_cv_have_gettext" = "yes"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + NEW_LINGUAS="$NEW_LINGUAS $presentlang" + fi + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but ($top_srcdir). + dnl Try to locate is. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + ]) + +# AM_GLIB_DEFINE_LOCALEDIR(VARIABLE) +# ------------------------------- +# Define VARIABLE to the location where catalog files will +# be installed by po/Makefile. +glib_DEFUN([GLIB_DEFINE_LOCALEDIR], +[glib_REQUIRE([GLIB_GNU_GETTEXT])dnl +glib_save_prefix="$prefix" +glib_save_exec_prefix="$exec_prefix" +glib_save_datarootdir="$datarootdir" +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix=$prefix +datarootdir=`eval echo "${datarootdir}"` +if test "x$CATOBJEXT" = "x.mo" ; then + localedir=`eval echo "${libdir}/locale"` +else + localedir=`eval echo "${datadir}/locale"` +fi +prefix="$glib_save_prefix" +exec_prefix="$glib_save_exec_prefix" +datarootdir="$glib_save_datarootdir" +AC_DEFINE_UNQUOTED($1, "$localedir", + [Define the location where the catalogs will be installed]) +]) + +dnl +dnl Now the definitions that aclocal will find +dnl +ifdef(glib_configure_in,[],[ +AC_DEFUN([AM_GLIB_GNU_GETTEXT],[GLIB_GNU_GETTEXT($@)]) +AC_DEFUN([AM_GLIB_DEFINE_LOCALEDIR],[GLIB_DEFINE_LOCALEDIR($@)]) +])dnl + +# GLIB_RUN_PROG(PROGRAM, TEST-FILE, [ACTION-IF-PASS], [ACTION-IF-FAIL]) +# +# Create a temporary file with TEST-FILE as its contents and pass the +# file name to PROGRAM. Perform ACTION-IF-PASS if PROGRAM exits with +# 0 and perform ACTION-IF-FAIL for any other exit status. +AC_DEFUN([GLIB_RUN_PROG], +[cat >conftest.foo <<_ACEOF +$2 +_ACEOF +if AC_RUN_LOG([$1 conftest.foo]); then + m4_ifval([$3], [$3], [:]) +m4_ifvaln([$4], [else $4])dnl +echo "$as_me: failed input was:" >&AS_MESSAGE_LOG_FD +sed 's/^/| /' conftest.foo >&AS_MESSAGE_LOG_FD +fi]) + + + +dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml]) +# serial 40 IT_PROG_INTLTOOL +AC_DEFUN([IT_PROG_INTLTOOL], [ +AC_PREREQ([2.50])dnl +AC_REQUIRE([AM_NLS])dnl + +case "$am__api_version" in + 1.[01234]) + AC_MSG_ERROR([Automake 1.5 or newer is required to use intltool]) + ;; + *) + ;; +esac + +if test -n "$1"; then + AC_MSG_CHECKING([for intltool >= $1]) + + INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` + INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3` + [INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` + ] + AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found]) + test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" || + AC_MSG_ERROR([Your intltool is too old. You need intltool $1 or later.]) +fi + +AC_PATH_PROG(INTLTOOL_UPDATE, [intltool-update]) +AC_PATH_PROG(INTLTOOL_MERGE, [intltool-merge]) +AC_PATH_PROG(INTLTOOL_EXTRACT, [intltool-extract]) +if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then + AC_MSG_ERROR([The intltool scripts were not found. Please install intltool.]) +fi + + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -p $(top_srcdir)/po $< [$]@' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< [$]@' + INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + INTLTOOL_POLICY_RULE='%.policy: %.policy.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' + +_IT_SUBST(INTLTOOL_DESKTOP_RULE) +_IT_SUBST(INTLTOOL_DIRECTORY_RULE) +_IT_SUBST(INTLTOOL_KEYS_RULE) +_IT_SUBST(INTLTOOL_PROP_RULE) +_IT_SUBST(INTLTOOL_OAF_RULE) +_IT_SUBST(INTLTOOL_PONG_RULE) +_IT_SUBST(INTLTOOL_SERVER_RULE) +_IT_SUBST(INTLTOOL_SHEET_RULE) +_IT_SUBST(INTLTOOL_SOUNDLIST_RULE) +_IT_SUBST(INTLTOOL_UI_RULE) +_IT_SUBST(INTLTOOL_XAM_RULE) +_IT_SUBST(INTLTOOL_KBD_RULE) +_IT_SUBST(INTLTOOL_XML_RULE) +_IT_SUBST(INTLTOOL_XML_NOMERGE_RULE) +_IT_SUBST(INTLTOOL_CAVES_RULE) +_IT_SUBST(INTLTOOL_SCHEMAS_RULE) +_IT_SUBST(INTLTOOL_THEME_RULE) +_IT_SUBST(INTLTOOL_SERVICE_RULE) +_IT_SUBST(INTLTOOL_POLICY_RULE) + +# Check the gettext tools to make sure they are GNU +AC_PATH_PROG(XGETTEXT, xgettext) +AC_PATH_PROG(MSGMERGE, msgmerge) +AC_PATH_PROG(MSGFMT, msgfmt) +AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) +if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then + AC_MSG_ERROR([GNU gettext tools not found; required for intltool]) +fi +xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`" +mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`" +mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`" +if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then + AC_MSG_ERROR([GNU gettext tools not found; required for intltool]) +fi + +AC_PATH_PROG(INTLTOOL_PERL, perl) +if test -z "$INTLTOOL_PERL"; then + AC_MSG_ERROR([perl not found]) +fi +AC_MSG_CHECKING([for perl >= 5.8.1]) +$INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1 +if test $? -ne 0; then + AC_MSG_ERROR([perl 5.8.1 is required for intltool]) +else + IT_PERL_VERSION="`$INTLTOOL_PERL -e \"printf '%vd', $^V\"`" + AC_MSG_RESULT([$IT_PERL_VERSION]) +fi +if test "x$2" != "xno-xml"; then + AC_MSG_CHECKING([for XML::Parser]) + if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then + AC_MSG_RESULT([ok]) + else + AC_MSG_ERROR([XML::Parser perl module is required for intltool]) + fi +fi + +# Substitute ALL_LINGUAS so we can use it in po/Makefile +AC_SUBST(ALL_LINGUAS) + +# Set DATADIRNAME correctly if it is not set yet +# (copied from glib-gettext.m4) +if test -z "$DATADIRNAME"; then + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[]], + [[extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr]])], + [DATADIRNAME=share], + [case $host in + *-*-solaris*) + dnl On Solaris, if bind_textdomain_codeset is in libc, + dnl GNU format message catalog is always supported, + dnl since both are added to the libc all together. + dnl Hence, we'd like to go with DATADIRNAME=share + dnl in this case. + AC_CHECK_FUNC(bind_textdomain_codeset, + [DATADIRNAME=share], [DATADIRNAME=lib]) + ;; + *) + [DATADIRNAME=lib] + ;; + esac]) +fi +AC_SUBST(DATADIRNAME) + +IT_PO_SUBDIR([po]) + +]) + + +# IT_PO_SUBDIR(DIRNAME) +# --------------------- +# All po subdirs have to be declared with this macro; the subdir "po" is +# declared by IT_PROG_INTLTOOL. +# +AC_DEFUN([IT_PO_SUBDIR], +[AC_PREREQ([2.53])dnl We use ac_top_srcdir inside AC_CONFIG_COMMANDS. +dnl +dnl The following CONFIG_COMMANDS should be exetuted at the very end +dnl of config.status. +AC_CONFIG_COMMANDS_PRE([ + AC_CONFIG_COMMANDS([$1/stamp-it], [ + if [ ! grep "^# INTLTOOL_MAKEFILE$" "$1/Makefile.in" > /dev/null ]; then + AC_MSG_ERROR([$1/Makefile.in.in was not created by intltoolize.]) + fi + rm -f "$1/stamp-it" "$1/stamp-it.tmp" "$1/POTFILES" "$1/Makefile.tmp" + >"$1/stamp-it.tmp" + [sed '/^#/d + s/^[[].*] *// + /^[ ]*$/d + '"s|^| $ac_top_srcdir/|" \ + "$srcdir/$1/POTFILES.in" | sed '$!s/$/ \\/' >"$1/POTFILES" + ] + [sed '/^POTFILES =/,/[^\\]$/ { + /^POTFILES =/!d + r $1/POTFILES + } + ' "$1/Makefile.in" >"$1/Makefile"] + rm -f "$1/Makefile.tmp" + mv "$1/stamp-it.tmp" "$1/stamp-it" + ]) +])dnl +]) + +# _IT_SUBST(VARIABLE) +# ------------------- +# Abstract macro to do either _AM_SUBST_NOTMAKE or AC_SUBST +# +AC_DEFUN([_IT_SUBST], +[ +AC_SUBST([$1]) +m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([$1])]) +] +) + +# deprecated macros +AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL]) +# A hint is needed for aclocal from Automake <= 1.9.4: +# AC_DEFUN([AC_PROG_INTLTOOL], ...) + + +# nls.m4 serial 3 (gettext-0.15) +dnl Copyright (C) 1995-2003, 2005-2006 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper , 1995-2000. +dnl Bruno Haible , 2000-2003. + +AC_PREREQ(2.50) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) +]) + +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# +# Copyright © 2004 Scott James Remnant . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi + +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# +# Similar to PKG_CHECK_MODULES, make sure that the first instance of +# this or PKG_CHECK_MODULES is called, or make sure to call +# PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_ifval([$2], [$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + ifelse([$4], , [AC_MSG_ERROR(dnl +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT +])], + [AC_MSG_RESULT([no]) + $4]) +elif test $pkg_failed = untried; then + ifelse([$4], , [AC_MSG_FAILURE(dnl +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])], + [$4]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + ifelse([$3], , :, [$3]) +fi[]dnl +])# PKG_CHECK_MODULES + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 10 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 16 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_PROG_CC_C_O +# -------------- +# Like AC_PROG_CC_C_O, but changed for automake. +AC_DEFUN([AM_PROG_CC_C_O], +[AC_REQUIRE([AC_PROG_CC_C_O])dnl +AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +dnl Make sure AC_PROG_CC is never called again, or it will override our +dnl setting of CC. +m4_define([AC_PROG_CC], + [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# (`yes' being less verbose, `no' or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], +[ --enable-silent-rules less verbose build output (undo: `make V=1') + --disable-silent-rules verbose build output (undo: `make V=0')]) +case $enable_silent_rules in +yes) AM_DEFAULT_VERBOSITY=0;; +no) AM_DEFAULT_VERBOSITY=1;; +*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + diff --git a/gtk/autogen.sh b/gtk/autogen.sh new file mode 100644 index 00000000..37968b95 --- /dev/null +++ b/gtk/autogen.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +glib-gettextize -f -c +intltoolize --copy --force --automake +aclocal +automake --add-missing --copy +autoconf + +rm -f intltool-extract.in intltool-merge.in intltool-update.in + diff --git a/gtk/compile b/gtk/compile new file mode 100644 index 00000000..c0096a7b --- /dev/null +++ b/gtk/compile @@ -0,0 +1,143 @@ +#! /bin/sh +# Wrapper for compilers which do not understand `-c -o'. + +scriptversion=2009-10-06.20; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software +# Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand `-c -o'. +Remove `-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file `INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; +esac + +ofile= +cfile= +eat= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as `compile cc -o foo foo.c'. + # So we strip `-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no `-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # `.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use `[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/gtk/configure b/gtk/configure new file mode 100644 index 00000000..f1ec4b5f --- /dev/null +++ b/gtk/configure @@ -0,0 +1,9597 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.65 for snes9x-gtk 1.52. +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='snes9x-gtk' +PACKAGE_TARNAME='snes9x-gtk' +PACKAGE_VERSION='1.52' +PACKAGE_STRING='snes9x-gtk 1.52' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +NASM_FLAGS +NASM +PULSEAUDIO_FALSE +PULSEAUDIO_TRUE +ALSA_FALSE +ALSA_TRUE +SDL_FALSE +SDL_TRUE +DEBUG_FALSE +DEBUG_TRUE +OSS_FALSE +OSS_TRUE +PORTAUDIO_FALSE +PORTAUDIO_TRUE +XV_FALSE +XV_TRUE +OPENGL_FALSE +OPENGL_TRUE +JMA_FALSE +JMA_TRUE +NETPLAY_FALSE +NETPLAY_TRUE +SDD1_DECOMP_FALSE +SDD1_DECOMP_TRUE +ASMCPU_FALSE +ASMCPU_TRUE +ZSNESC4_FALSE +ZSNESC4_TRUE +ZSNESFX_FALSE +ZSNESFX_TRUE +prog_nasm +LIBPNG_LIBS +LIBPNG_CFLAGS +XRANDR_LIBS +XRANDR_CFLAGS +PULSEAUDIO_LIBS +PULSEAUDIO_CFLAGS +ALSA_LIBS +ALSA_CFLAGS +PORTAUDIO_LIBS +PORTAUDIO_CFLAGS +XV_LIBS +XV_CFLAGS +SDLCONFIGFOUND +SDL_LIBS +SDL_CFLAGS +LIBXML_LIBS +LIBXML_CFLAGS +GLADE_LIBS +GLADE_CFLAGS +GLIB_LIBS +GLIB_CFLAGS +GTK_LIBS +GTK_CFLAGS +PKG_CONFIG +snes9xlocaledir +MKINSTALLDIRS +POSUB +POFILES +PO_IN_DATADIR_FALSE +PO_IN_DATADIR_TRUE +INTLLIBS +INSTOBJEXT +GMOFILES +CATOBJEXT +CATALOGS +MSGFMT_OPTS +EGREP +GREP +CXXCPP +GETTEXT_PACKAGE +DATADIRNAME +ALL_LINGUAS +INTLTOOL_PERL +GMSGFMT +MSGFMT +MSGMERGE +XGETTEXT +INTLTOOL_POLICY_RULE +INTLTOOL_SERVICE_RULE +INTLTOOL_THEME_RULE +INTLTOOL_SCHEMAS_RULE +INTLTOOL_CAVES_RULE +INTLTOOL_XML_NOMERGE_RULE +INTLTOOL_XML_RULE +INTLTOOL_KBD_RULE +INTLTOOL_XAM_RULE +INTLTOOL_UI_RULE +INTLTOOL_SOUNDLIST_RULE +INTLTOOL_SHEET_RULE +INTLTOOL_SERVER_RULE +INTLTOOL_PONG_RULE +INTLTOOL_OAF_RULE +INTLTOOL_PROP_RULE +INTLTOOL_KEYS_RULE +INTLTOOL_DIRECTORY_RULE +INTLTOOL_DESKTOP_RULE +INTLTOOL_EXTRACT +INTLTOOL_MERGE +INTLTOOL_UPDATE +USE_NLS +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +RANLIB +ac_ct_CXX +CXXFLAGS +CXX +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_dependency_tracking +enable_silent_rules +enable_nls +with_debug +with_opengl +with_joystick +with_xv +with_xrandr +with_portaudio +with_oss +with_alsa +with_pulseaudio +with_assembler +with_zsnesc4 +with_zsnesfx +with_debugger +with_sdd1_decomp +with_netplay +with_jma_decomp +with_newblend +with_zlib +with_png +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CXX +CXXFLAGS +CCC +CXXCPP +PKG_CONFIG +GTK_CFLAGS +GTK_LIBS +GLIB_CFLAGS +GLIB_LIBS +GLADE_CFLAGS +GLADE_LIBS +LIBXML_CFLAGS +LIBXML_LIBS +SDL_CFLAGS +SDL_LIBS +XV_CFLAGS +XV_LIBS +PORTAUDIO_CFLAGS +PORTAUDIO_LIBS +ALSA_CFLAGS +ALSA_LIBS +PULSEAUDIO_CFLAGS +PULSEAUDIO_LIBS +XRANDR_CFLAGS +XRANDR_LIBS +LIBPNG_CFLAGS +LIBPNG_LIBS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information." + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures snes9x-gtk 1.52 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/snes9x-gtk] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of snes9x-gtk 1.52:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-silent-rules less verbose build output (undo: `make V=1') + --disable-silent-rules verbose build output (undo: `make V=0') + --disable-nls do not use Native Language Support + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with(out)-debug Leave debug information in the final binary + (default: without) + --with(out)-opengl Use OpenGL for output (default: with) + --with(out)-joystick Enable joystick support if available (default: with) + --with(out)-xv Enable XVideo output on GTK (default: with) + --with(out)-xrandr Enable XRandR support on GTK (default: with) + --with(out)-portaudio Enable PortAudio sound driver support (default: + with) + --with(out)-oss Enable OSS sound driver support (default: with) + --with(out)-alsa Enable ALSA sound driver support (default: with) + --with(out)-pulseaudio Enable PulseAudio sound driver support (default: + with) + --with(out)-assembler Use assembler cores if available (default: with) + --with(out)-zsnesc4 Use ZSNES C4 core if available (default: same as + --with-assembler) + --with(out)-zsnesfx Use ZSNES SuperFX core if available (default: same + as --with-assembler) + --with(out)-debugger Enable debugger (default: without) + --with(out)-sdd1-decomp Use SDD1 decompression (default: with) + --with(out)-netplay Enable netplay support (default: without) + --with(out)-jma-decomp Enable JMA archive decompression (default: with) + --with(out)-newblend New colour blender (default: with) + --with(out)-zlib Support gzip decompression + --with(out)-screenshot Screenshot support through libpng if available + (default: with) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + PKG_CONFIG path to pkg-config utility + GTK_CFLAGS C compiler flags for GTK, overriding pkg-config + GTK_LIBS linker flags for GTK, overriding pkg-config + GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config + GLIB_LIBS linker flags for GLIB, overriding pkg-config + GLADE_CFLAGS + C compiler flags for GLADE, overriding pkg-config + GLADE_LIBS linker flags for GLADE, overriding pkg-config + LIBXML_CFLAGS + C compiler flags for LIBXML, overriding pkg-config + LIBXML_LIBS linker flags for LIBXML, overriding pkg-config + SDL_CFLAGS C compiler flags for SDL, overriding pkg-config + SDL_LIBS linker flags for SDL, overriding pkg-config + XV_CFLAGS C compiler flags for XV, overriding pkg-config + XV_LIBS linker flags for XV, overriding pkg-config + PORTAUDIO_CFLAGS + C compiler flags for PORTAUDIO, overriding pkg-config + PORTAUDIO_LIBS + linker flags for PORTAUDIO, overriding pkg-config + ALSA_CFLAGS C compiler flags for ALSA, overriding pkg-config + ALSA_LIBS linker flags for ALSA, overriding pkg-config + PULSEAUDIO_CFLAGS + C compiler flags for PULSEAUDIO, overriding pkg-config + PULSEAUDIO_LIBS + linker flags for PULSEAUDIO, overriding pkg-config + XRANDR_CFLAGS + C compiler flags for XRANDR, overriding pkg-config + XRANDR_LIBS linker flags for XRANDR, overriding pkg-config + LIBPNG_CFLAGS + C compiler flags for LIBPNG, overriding pkg-config + LIBPNG_LIBS linker flags for LIBPNG, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +snes9x-gtk configure 1.52 +generated by GNU Autoconf 2.65 + +Copyright (C) 2009 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_cxx_check_func LINENO FUNC VAR +# ------------------------------------ +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_cxx_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_cxx_check_func + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_try_run LINENO +# ------------------------ +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_cxx_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_run + +# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_cxx_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_cxx_check_header_mongrel + +# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_cxx_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_cxx_check_header_compile +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by snes9x-gtk $as_me 1.52, which was +generated by GNU Autoconf 2.65. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + ac_site_file1=$CONFIG_SITE +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +CFLAGS="-O2 -Wall -W -pedantic -Wno-unused-parameter -pipe $CFLAGS" +CXXFLAGS="$CFLAGS" + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "no acceptable C compiler found in \$PATH +See \`config.log' for more details." "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "C compiler cannot create executables +See \`config.log' for more details." "$LINENO" 5; }; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if test "${ac_cv_objext+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot compute suffix of object files: cannot compile +See \`config.log' for more details." "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + for ac_t in install-sh install.sh shtool; do + if test -f "$ac_dir/$ac_t"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/$ac_t -c" + break 2 + fi + done +done +if test -z "$ac_aux_dir"; then + as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +am__api_version='1.11' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error "ls -t appears to fail. Make sure there is not a broken +alias in your environment" "$LINENO" 5 + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if test "${ac_cv_path_mkdir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AWK+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='snes9x-gtk' + VERSION='1.52' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + + + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in +yes) AM_DEFAULT_VERBOSITY=0;; +no) AM_DEFAULT_VERBOSITY=1;; +*) AM_DEFAULT_VERBOSITY=0;; +esac +AM_BACKSLASH='\' + + +if test "x$CC" != xcc; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 +$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 +$as_echo_n "checking whether cc understands -c and -o together... " >&6; } +fi +set dummy $CC; ac_cc=`$as_echo "$2" | + sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +# Make sure it works both with $CC and with simple cc. +# We do the test twice because some compilers refuse to overwrite an +# existing .o file with -o, though they will create one. +ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' +rm -f conftest2.* +if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; +then + eval ac_cv_prog_cc_${ac_cc}_c_o=yes + if test "x$CC" != xcc; then + # Test first that cc exists at all. + if { ac_try='cc -c conftest.$ac_ext >&5' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' + rm -f conftest2.* + if { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && + test -f conftest2.$ac_objext && { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; + then + # cc works too. + : + else + # cc exists but doesn't like -o. + eval ac_cv_prog_cc_${ac_cc}_c_o=no + fi + fi + fi +else + eval ac_cv_prog_cc_${ac_cc}_c_o=no +fi +rm -f core conftest* + +fi +if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h + +fi + +# FIXME: we rely on the cache variable name because +# there is no other way. +set dummy $CC +am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` +eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o +if test "$am_t" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; USE_NLS=$enableval +else + USE_NLS=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + + + + + +case "$am__api_version" in + 1.01234) + as_fn_error "Automake 1.5 or newer is required to use intltool" "$LINENO" 5 + ;; + *) + ;; +esac + +if test -n "0.40.1"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intltool >= 0.40.1" >&5 +$as_echo_n "checking for intltool >= 0.40.1... " >&6; } + + INTLTOOL_REQUIRED_VERSION_AS_INT=`echo 0.40.1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` + INTLTOOL_APPLIED_VERSION=`intltool-update --version | head -1 | cut -d" " -f3` + INTLTOOL_APPLIED_VERSION_AS_INT=`echo $INTLTOOL_APPLIED_VERSION | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'` + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_APPLIED_VERSION found" >&5 +$as_echo "$INTLTOOL_APPLIED_VERSION found" >&6; } + test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" || + as_fn_error "Your intltool is too old. You need intltool 0.40.1 or later." "$LINENO" 5 +fi + +# Extract the first word of "intltool-update", so it can be a program name with args. +set dummy intltool-update; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_INTLTOOL_UPDATE+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_UPDATE in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_UPDATE="$INTLTOOL_UPDATE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_INTLTOOL_UPDATE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_UPDATE=$ac_cv_path_INTLTOOL_UPDATE +if test -n "$INTLTOOL_UPDATE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_UPDATE" >&5 +$as_echo "$INTLTOOL_UPDATE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "intltool-merge", so it can be a program name with args. +set dummy intltool-merge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_INTLTOOL_MERGE+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_MERGE in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_MERGE="$INTLTOOL_MERGE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_INTLTOOL_MERGE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_MERGE=$ac_cv_path_INTLTOOL_MERGE +if test -n "$INTLTOOL_MERGE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_MERGE" >&5 +$as_echo "$INTLTOOL_MERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "intltool-extract", so it can be a program name with args. +set dummy intltool-extract; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_INTLTOOL_EXTRACT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_EXTRACT in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_EXTRACT="$INTLTOOL_EXTRACT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_INTLTOOL_EXTRACT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_EXTRACT=$ac_cv_path_INTLTOOL_EXTRACT +if test -n "$INTLTOOL_EXTRACT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_EXTRACT" >&5 +$as_echo "$INTLTOOL_EXTRACT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$INTLTOOL_UPDATE" -o -z "$INTLTOOL_MERGE" -o -z "$INTLTOOL_EXTRACT"; then + as_fn_error "The intltool scripts were not found. Please install intltool." "$LINENO" 5 +fi + + INTLTOOL_DESKTOP_RULE='%.desktop: %.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_KEYS_RULE='%.keys: %.keys.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_PROP_RULE='%.prop: %.prop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_OAF_RULE='%.oaf: %.oaf.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -p $(top_srcdir)/po $< $@' + INTLTOOL_PONG_RULE='%.pong: %.pong.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SERVER_RULE='%.server: %.server.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SHEET_RULE='%.sheet: %.sheet.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' +INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_UI_RULE='%.ui: %.ui.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_XML_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_XML_NOMERGE_RULE='%.xml: %.xml.in $(INTLTOOL_MERGE) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< $@' + INTLTOOL_XAM_RULE='%.xam: %.xml.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_KBD_RULE='%.kbd: %.kbd.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_CAVES_RULE='%.caves: %.caves.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SCHEMAS_RULE='%.schemas: %.schemas.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_THEME_RULE='%.theme: %.theme.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + INTLTOOL_POLICY_RULE='%.policy: %.policy.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# Check the gettext tools to make sure they are GNU +# Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_XGETTEXT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $XGETTEXT in + [\\/]* | ?:[\\/]*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_XGETTEXT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +XGETTEXT=$ac_cv_path_XGETTEXT +if test -n "$XGETTEXT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "msgmerge", so it can be a program name with args. +set dummy msgmerge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_MSGMERGE+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $MSGMERGE in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MSGMERGE="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +MSGMERGE=$ac_cv_path_MSGMERGE +if test -n "$MSGMERGE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +$as_echo "$MSGMERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_MSGFMT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $MSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +MSGFMT=$ac_cv_path_MSGFMT +if test -n "$MSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_GMSGFMT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then + as_fn_error "GNU gettext tools not found; required for intltool" "$LINENO" 5 +fi +xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`" +mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`" +mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`" +if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then + as_fn_error "GNU gettext tools not found; required for intltool" "$LINENO" 5 +fi + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_INTLTOOL_PERL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $INTLTOOL_PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_INTLTOOL_PERL="$INTLTOOL_PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_INTLTOOL_PERL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +INTLTOOL_PERL=$ac_cv_path_INTLTOOL_PERL +if test -n "$INTLTOOL_PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLTOOL_PERL" >&5 +$as_echo "$INTLTOOL_PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$INTLTOOL_PERL"; then + as_fn_error "perl not found" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl >= 5.8.1" >&5 +$as_echo_n "checking for perl >= 5.8.1... " >&6; } +$INTLTOOL_PERL -e "use 5.8.1;" > /dev/null 2>&1 +if test $? -ne 0; then + as_fn_error "perl 5.8.1 is required for intltool" "$LINENO" 5 +else + IT_PERL_VERSION="`$INTLTOOL_PERL -e \"printf '%vd', $^V\"`" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $IT_PERL_VERSION" >&5 +$as_echo "$IT_PERL_VERSION" >&6; } +fi +if test "x" != "xno-xml"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XML::Parser" >&5 +$as_echo_n "checking for XML::Parser... " >&6; } + if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } + else + as_fn_error "XML::Parser perl module is required for intltool" "$LINENO" 5 + fi +fi + +# Substitute ALL_LINGUAS so we can use it in po/Makefile + + +# Set DATADIRNAME correctly if it is not set yet +# (copied from glib-gettext.m4) +if test -z "$DATADIRNAME"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + DATADIRNAME=share +else + case $host in + *-*-solaris*) + ac_fn_cxx_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = x""yes; then : + DATADIRNAME=share +else + DATADIRNAME=lib +fi + + ;; + *) + DATADIRNAME=lib + ;; + esac +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + + + + + +GETTEXT_PACKAGE=snes9x-gtk + +cat >>confdefs.h <<_ACEOF +#define GETTEXT_PACKAGE "$GETTEXT_PACKAGE" +_ACEOF + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." "$LINENO" 5; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if test "${ac_cv_path_GREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + for ac_header in locale.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" +if test "x$ac_cv_header_locale_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALE_H 1 +_ACEOF + +fi + +done + + if test $ac_cv_header_locale_h = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LC_MESSAGES" >&5 +$as_echo_n "checking for LC_MESSAGES... " >&6; } +if test "${am_cv_val_LC_MESSAGES+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +return LC_MESSAGES + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + am_cv_val_LC_MESSAGES=yes +else + am_cv_val_LC_MESSAGES=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_val_LC_MESSAGES" >&5 +$as_echo "$am_cv_val_LC_MESSAGES" >&6; } + if test $am_cv_val_LC_MESSAGES = yes; then + +$as_echo "#define HAVE_LC_MESSAGES 1" >>confdefs.h + + fi + fi + USE_NLS=yes + + + gt_cv_have_gettext=no + + CATOBJEXT=NONE + XGETTEXT=: + INTLLIBS= + + ac_fn_cxx_check_header_mongrel "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default" +if test "x$ac_cv_header_libintl_h" = x""yes; then : + gt_cv_func_dgettext_libintl="no" + libintl_extra_libs="" + + # + # First check in libc + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in libc" >&5 +$as_echo_n "checking for ngettext in libc... " >&6; } +if test "${gt_cv_func_ngettext_libc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ +return !ngettext ("","", 1) + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gt_cv_func_ngettext_libc=yes +else + gt_cv_func_ngettext_libc=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_ngettext_libc" >&5 +$as_echo "$gt_cv_func_ngettext_libc" >&6; } + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dgettext in libc" >&5 +$as_echo_n "checking for dgettext in libc... " >&6; } +if test "${gt_cv_func_dgettext_libc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + +int +main () +{ +return !dgettext ("","") + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + gt_cv_func_dgettext_libc=yes +else + gt_cv_func_dgettext_libc=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_dgettext_libc" >&5 +$as_echo "$gt_cv_func_dgettext_libc" >&6; } + fi + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + for ac_func in bind_textdomain_codeset +do : + ac_fn_cxx_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BIND_TEXTDOMAIN_CODESET 1 +_ACEOF + +fi +done + + fi + + # + # If we don't have everything we want, check in libintl + # + if test "$gt_cv_func_dgettext_libc" != "yes" \ + || test "$gt_cv_func_ngettext_libc" != "yes" \ + || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bindtextdomain in -lintl" >&5 +$as_echo_n "checking for bindtextdomain in -lintl... " >&6; } +if test "${ac_cv_lib_intl_bindtextdomain+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char bindtextdomain (); +int +main () +{ +return bindtextdomain (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_intl_bindtextdomain=yes +else + ac_cv_lib_intl_bindtextdomain=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_bindtextdomain" >&5 +$as_echo "$ac_cv_lib_intl_bindtextdomain" >&6; } +if test "x$ac_cv_lib_intl_bindtextdomain" = x""yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in -lintl" >&5 +$as_echo_n "checking for ngettext in -lintl... " >&6; } +if test "${ac_cv_lib_intl_ngettext+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ngettext (); +int +main () +{ +return ngettext (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_intl_ngettext=yes +else + ac_cv_lib_intl_ngettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_ngettext" >&5 +$as_echo "$ac_cv_lib_intl_ngettext" >&6; } +if test "x$ac_cv_lib_intl_ngettext" = x""yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dgettext in -lintl" >&5 +$as_echo_n "checking for dgettext in -lintl... " >&6; } +if test "${ac_cv_lib_intl_dgettext+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dgettext (); +int +main () +{ +return dgettext (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_intl_dgettext=yes +else + ac_cv_lib_intl_dgettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dgettext" >&5 +$as_echo "$ac_cv_lib_intl_dgettext" >&6; } +if test "x$ac_cv_lib_intl_dgettext" = x""yes; then : + gt_cv_func_dgettext_libintl=yes +fi + +fi + +fi + + + if test "$gt_cv_func_dgettext_libintl" != "yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -liconv is needed to use gettext" >&5 +$as_echo_n "checking if -liconv is needed to use gettext... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 +$as_echo "" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in -lintl" >&5 +$as_echo_n "checking for ngettext in -lintl... " >&6; } +if test "${ac_cv_lib_intl_ngettext+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl -liconv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ngettext (); +int +main () +{ +return ngettext (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_intl_ngettext=yes +else + ac_cv_lib_intl_ngettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_ngettext" >&5 +$as_echo "$ac_cv_lib_intl_ngettext" >&6; } +if test "x$ac_cv_lib_intl_ngettext" = x""yes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dcgettext in -lintl" >&5 +$as_echo_n "checking for dcgettext in -lintl... " >&6; } +if test "${ac_cv_lib_intl_dcgettext+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl -liconv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dcgettext (); +int +main () +{ +return dcgettext (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_intl_dcgettext=yes +else + ac_cv_lib_intl_dcgettext=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dcgettext" >&5 +$as_echo "$ac_cv_lib_intl_dcgettext" >&6; } +if test "x$ac_cv_lib_intl_dcgettext" = x""yes; then : + gt_cv_func_dgettext_libintl=yes + libintl_extra_libs=-liconv +else + : +fi + +else + : +fi + + fi + + # + # If we found libintl, then check in it for bind_textdomain_codeset(); + # we'll prefer libc if neither have bind_textdomain_codeset(), + # and both have dgettext and ngettext + # + if test "$gt_cv_func_dgettext_libintl" = "yes" ; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS -lintl $libintl_extra_libs" + unset ac_cv_func_bind_textdomain_codeset + for ac_func in bind_textdomain_codeset +do : + ac_fn_cxx_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BIND_TEXTDOMAIN_CODESET 1 +_ACEOF + +fi +done + + LIBS="$glib_save_LIBS" + + if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then + gt_cv_func_dgettext_libc=no + else + if test "$gt_cv_func_dgettext_libc" = "yes" \ + && test "$gt_cv_func_ngettext_libc" = "yes"; then + gt_cv_func_dgettext_libintl=no + fi + fi + fi + fi + + if test "$gt_cv_func_dgettext_libc" = "yes" \ + || test "$gt_cv_func_dgettext_libintl" = "yes"; then + gt_cv_have_gettext=yes + fi + + if test "$gt_cv_func_dgettext_libintl" = "yes"; then + INTLLIBS="-lintl $libintl_extra_libs" + fi + + if test "$gt_cv_have_gettext" = "yes"; then + +$as_echo "#define HAVE_GETTEXT 1" >>confdefs.h + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_MSGFMT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test "$MSGFMT" != "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + if test "$MSGFMT" != "no"; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS $INTLLIBS" + for ac_func in dcgettext +do : + ac_fn_cxx_check_func "$LINENO" "dcgettext" "ac_cv_func_dcgettext" +if test "x$ac_cv_func_dcgettext" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DCGETTEXT 1 +_ACEOF + +fi +done + + MSGFMT_OPTS= + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if msgfmt accepts -c" >&5 +$as_echo_n "checking if msgfmt accepts -c... " >&6; } + cat >conftest.foo <<_ACEOF + +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: test 1.0\n" +"PO-Revision-Date: 2007-02-15 12:01+0100\n" +"Last-Translator: test \n" +"Language-Team: C \n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" + +_ACEOF +if { { $as_echo "$as_me:${as_lineno-$LINENO}: \$MSGFMT -c -o /dev/null conftest.foo"; } >&5 + ($MSGFMT -c -o /dev/null conftest.foo) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + MSGFMT_OPTS=-c; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +echo "$as_me: failed input was:" >&5 +sed 's/^/| /' conftest.foo >&5 +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_GMSGFMT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_XGETTEXT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test "$XGETTEXT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + CATOBJEXT=.gmo + DATADIRNAME=share +else + case $host in + *-*-solaris*) + ac_fn_cxx_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" +if test "x$ac_cv_func_bind_textdomain_codeset" = x""yes; then : + CATOBJEXT=.gmo + DATADIRNAME=share +else + CATOBJEXT=.mo + DATADIRNAME=lib +fi + + ;; + *) + CATOBJEXT=.mo + DATADIRNAME=lib + ;; + esac +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$glib_save_LIBS" + INSTOBJEXT=.mo + else + gt_cv_have_gettext=no + fi + fi + +fi + + + + if test "$gt_cv_have_gettext" = "yes" ; then + +$as_echo "#define ENABLE_NLS 1" >>confdefs.h + + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found xgettext program is not GNU xgettext; ignore it" >&5 +$as_echo "found xgettext program is not GNU xgettext; ignore it" >&6; } + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + + ac_config_commands="$ac_config_commands default-1" + + + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + + + + + + + + + + + + + if test "$gt_cv_have_gettext" = "yes"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for catalogs to be installed" >&5 +$as_echo_n "checking for catalogs to be installed... " >&6; } + NEW_LINGUAS= + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + NEW_LINGUAS="$NEW_LINGUAS $presentlang" + fi + done + LINGUAS=$NEW_LINGUAS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINGUAS" >&5 +$as_echo "$LINGUAS" >&6; } + fi + + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + + + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + + +snes9xlocaledir='${prefix}/${DATADIRNAME}/locale' + + + +# Check whether --with-debug was given. +if test "${with_debug+set}" = set; then : + withval=$with_debug; +else + with_debug=no +fi + + + +# Check whether --with-opengl was given. +if test "${with_opengl+set}" = set; then : + withval=$with_opengl; +else + with_opengl=yes +fi + + + +# Check whether --with-joystick was given. +if test "${with_joystick+set}" = set; then : + withval=$with_joystick; +else + with_joystick=yes +fi + + + +# Check whether --with-xv was given. +if test "${with_xv+set}" = set; then : + withval=$with_xv; +else + with_xv=yes +fi + + + +# Check whether --with-xrandr was given. +if test "${with_xrandr+set}" = set; then : + withval=$with_xrandr; +else + with_xrandr=yes +fi + + + +# Check whether --with-portaudio was given. +if test "${with_portaudio+set}" = set; then : + withval=$with_portaudio; +else + with_portaudio=yes +fi + + + +# Check whether --with-oss was given. +if test "${with_oss+set}" = set; then : + withval=$with_oss; +else + with_oss=yes +fi + + + +# Check whether --with-alsa was given. +if test "${with_alsa+set}" = set; then : + withval=$with_alsa; +else + with_alsa=yes +fi + + + +# Check whether --with-pulseaudio was given. +if test "${with_pulseaudio+set}" = set; then : + withval=$with_pulseaudio; +else + with_pulseaudio=yes +fi + + + +# Check whether --with-assembler was given. +if test "${with_assembler+set}" = set; then : + withval=$with_assembler; +else + with_assembler=yes +fi + + + +# Check whether --with-zsnesc4 was given. +if test "${with_zsnesc4+set}" = set; then : + withval=$with_zsnesc4; +else + with_zsnesc4=$with_assembler +fi + + + +# Check whether --with-zsnesfx was given. +if test "${with_zsnesfx+set}" = set; then : + withval=$with_zsnesfx; +else + with_zsnesfx=$with_assembler +fi + + + +# Check whether --with-debugger was given. +if test "${with_debugger+set}" = set; then : + withval=$with_debugger; +else + with_debugger=no +fi + + + +# Check whether --with-sdd1-decomp was given. +if test "${with_sdd1_decomp+set}" = set; then : + withval=$with_sdd1_decomp; +else + with_sdd1_decomp=yes +fi + + + +# Check whether --with-netplay was given. +if test "${with_netplay+set}" = set; then : + withval=$with_netplay; +else + with_netplay=yes +fi + + + +# Check whether --with-jma-decomp was given. +if test "${with_jma_decomp+set}" = set; then : + withval=$with_jma_decomp; +else + with_jma_decomp=yes +fi + + + +# Check whether --with-newblend was given. +if test "${with_newblend+set}" = set; then : + withval=$with_newblend; +else + with_newblend=yes +fi + + + +# Check whether --with-zlib was given. +if test "${with_zlib+set}" = set; then : + withval=$with_zlib; +else + with_zlib=yes +fi + + + +# Check whether --with-png was given. +if test "${with_png+set}" = set; then : + withval=$with_png; +else + with_screenshot=yes +fi + + +if test yes = "$with_debug" ; then + CFLAGS="$CFLAGS -g" +else + CFLAGS="$CFLAGS -fomit-frame-pointer" +fi + +ZSNESFX='#ZSNESFX=yes' +ZSNESC4='#ZSNESC4=yes' +ASMCPU='' +SDD1_DECOMP='#SDD1_DECOMP=yes' +JMA='#JMA=yes' +SPC700ASM='' +I386SPC='' +CPUINC='' +NETPLAY='#NETPLAY=yes' + +SYSLIBS='' +NASM='not_found' + +OPENGL=0 + +if test yes = "$with_opengl" ; then + OPENGL=yes +fi + +GTK=yes +snes9x_info_display="GTK" + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_PKG_CONFIG+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi + +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTK" >&5 +$as_echo_n "checking for GTK... " >&6; } + +if test -n "$GTK_CFLAGS"; then + pkg_cv_GTK_CFLAGS="$GTK_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0 >= 2.10\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-2.0 >= 2.10") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTK_CFLAGS=`$PKG_CONFIG --cflags "gtk+-2.0 >= 2.10" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GTK_LIBS"; then + pkg_cv_GTK_LIBS="$GTK_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtk+-2.0 >= 2.10\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtk+-2.0 >= 2.10") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTK_LIBS=`$PKG_CONFIG --libs "gtk+-2.0 >= 2.10" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "gtk+-2.0 >= 2.10" 2>&1` + else + GTK_PKG_ERRORS=`$PKG_CONFIG --print-errors "gtk+-2.0 >= 2.10" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTK_PKG_ERRORS" >&5 + + as_fn_error "Package requirements (gtk+-2.0 >= 2.10) were not met: + +$GTK_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GTK_CFLAGS +and GTK_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" "$LINENO" 5 +elif test $pkg_failed = untried; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GTK_CFLAGS +and GTK_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details." "$LINENO" 5; } +else + GTK_CFLAGS=$pkg_cv_GTK_CFLAGS + GTK_LIBS=$pkg_cv_GTK_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5 +$as_echo_n "checking for GLIB... " >&6; } + +if test -n "$GLIB_CFLAGS"; then + pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gthread-2.0 >= 2.6 gobject-2.0 >= 2.6\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gthread-2.0 >= 2.6 gobject-2.0 >= 2.6") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "gthread-2.0 >= 2.6 gobject-2.0 >= 2.6" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GLIB_LIBS"; then + pkg_cv_GLIB_LIBS="$GLIB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gthread-2.0 >= 2.6 gobject-2.0 >= 2.6\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gthread-2.0 >= 2.6 gobject-2.0 >= 2.6") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "gthread-2.0 >= 2.6 gobject-2.0 >= 2.6" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "gthread-2.0 >= 2.6 gobject-2.0 >= 2.6" 2>&1` + else + GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors "gthread-2.0 >= 2.6 gobject-2.0 >= 2.6" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GLIB_PKG_ERRORS" >&5 + + as_fn_error "Package requirements (gthread-2.0 >= 2.6 gobject-2.0 >= 2.6) were not met: + +$GLIB_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GLIB_CFLAGS +and GLIB_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" "$LINENO" 5 +elif test $pkg_failed = untried; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GLIB_CFLAGS +and GLIB_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details." "$LINENO" 5; } +else + GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS + GLIB_LIBS=$pkg_cv_GLIB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLADE" >&5 +$as_echo_n "checking for GLADE... " >&6; } + +if test -n "$GLADE_CFLAGS"; then + pkg_cv_GLADE_CFLAGS="$GLADE_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libglade-2.0 >= 2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libglade-2.0 >= 2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLADE_CFLAGS=`$PKG_CONFIG --cflags "libglade-2.0 >= 2.0" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$GLADE_LIBS"; then + pkg_cv_GLADE_LIBS="$GLADE_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libglade-2.0 >= 2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libglade-2.0 >= 2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GLADE_LIBS=`$PKG_CONFIG --libs "libglade-2.0 >= 2.0" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GLADE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libglade-2.0 >= 2.0" 2>&1` + else + GLADE_PKG_ERRORS=`$PKG_CONFIG --print-errors "libglade-2.0 >= 2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$GLADE_PKG_ERRORS" >&5 + + as_fn_error "Package requirements (libglade-2.0 >= 2.0) were not met: + +$GLADE_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables GLADE_CFLAGS +and GLADE_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" "$LINENO" 5 +elif test $pkg_failed = untried; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables GLADE_CFLAGS +and GLADE_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details." "$LINENO" 5; } +else + GLADE_CFLAGS=$pkg_cv_GLADE_CFLAGS + GLADE_LIBS=$pkg_cv_GLADE_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBXML" >&5 +$as_echo_n "checking for LIBXML... " >&6; } + +if test -n "$LIBXML_CFLAGS"; then + pkg_cv_LIBXML_CFLAGS="$LIBXML_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0 >= 2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libxml-2.0 >= 2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBXML_CFLAGS=`$PKG_CONFIG --cflags "libxml-2.0 >= 2.0" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBXML_LIBS"; then + pkg_cv_LIBXML_LIBS="$LIBXML_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libxml-2.0 >= 2.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libxml-2.0 >= 2.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBXML_LIBS=`$PKG_CONFIG --libs "libxml-2.0 >= 2.0" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBXML_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libxml-2.0 >= 2.0" 2>&1` + else + LIBXML_PKG_ERRORS=`$PKG_CONFIG --print-errors "libxml-2.0 >= 2.0" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBXML_PKG_ERRORS" >&5 + + as_fn_error "Package requirements (libxml-2.0 >= 2.0) were not met: + +$LIBXML_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables LIBXML_CFLAGS +and LIBXML_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" "$LINENO" 5 +elif test $pkg_failed = untried; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables LIBXML_CFLAGS +and LIBXML_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details." "$LINENO" 5; } +else + LIBXML_CFLAGS=$pkg_cv_LIBXML_CFLAGS + LIBXML_LIBS=$pkg_cv_LIBXML_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + +if test yes = "$with_opengl" ; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glGetString in -lGL" >&5 +$as_echo_n "checking for glGetString in -lGL... " >&6; } +if test "${ac_cv_lib_GL_glGetString+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lGL $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char glGetString (); +int +main () +{ +return glGetString (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_GL_glGetString=yes +else + ac_cv_lib_GL_glGetString=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_GL_glGetString" >&5 +$as_echo "$ac_cv_lib_GL_glGetString" >&6; } +if test "x$ac_cv_lib_GL_glGetString" = x""yes; then : + + OPENGL=yes + CFLAGS="$CFLAGS -DUSE_OPENGL" + LIBS="-lGL" + +else + + OPENGL=0 + +fi + +fi + +GTKJOY=0 +SDL_CFLAGS="" +SDL_LIBS="" +if test yes = "$with_joystick"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL" >&5 +$as_echo_n "checking for SDL... " >&6; } + +if test -n "$SDL_CFLAGS"; then + pkg_cv_SDL_CFLAGS="$SDL_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "sdl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SDL_CFLAGS=`$PKG_CONFIG --cflags "sdl" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$SDL_LIBS"; then + pkg_cv_SDL_LIBS="$SDL_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sdl\""; } >&5 + ($PKG_CONFIG --exists --print-errors "sdl") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_SDL_LIBS=`$PKG_CONFIG --libs "sdl" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + SDL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "sdl" 2>&1` + else + SDL_PKG_ERRORS=`$PKG_CONFIG --print-errors "sdl" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$SDL_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + # Extract the first word of "sdl-config", so it can be a program name with args. +set dummy sdl-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_SDLCONFIGFOUND+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$SDLCONFIGFOUND"; then + ac_cv_prog_SDLCONFIGFOUND="$SDLCONFIGFOUND" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_SDLCONFIGFOUND="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_SDLCONFIGFOUND" && ac_cv_prog_SDLCONFIGFOUND="no" +fi +fi +SDLCONFIGFOUND=$ac_cv_prog_SDLCONFIGFOUND +if test -n "$SDLCONFIGFOUND"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SDLCONFIGFOUND" >&5 +$as_echo "$SDLCONFIGFOUND" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + if test yes = "$SDLCONFIGFOUND" ; then + SDL_CFLAGS="-DUSE_JOYSTICK `sdl-config --cflags`" + SDL_LIBS="`sdl-config --libs`" + GTKJOY=yes + else + echo "Cannot find SDL. Disabling joystick support." + fi + +elif test $pkg_failed = untried; then + + # Extract the first word of "sdl-config", so it can be a program name with args. +set dummy sdl-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_SDLCONFIGFOUND+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$SDLCONFIGFOUND"; then + ac_cv_prog_SDLCONFIGFOUND="$SDLCONFIGFOUND" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_SDLCONFIGFOUND="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_SDLCONFIGFOUND" && ac_cv_prog_SDLCONFIGFOUND="no" +fi +fi +SDLCONFIGFOUND=$ac_cv_prog_SDLCONFIGFOUND +if test -n "$SDLCONFIGFOUND"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SDLCONFIGFOUND" >&5 +$as_echo "$SDLCONFIGFOUND" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + if test yes = "$SDLCONFIGFOUND" ; then + SDL_CFLAGS="-DUSE_JOYSTICK `sdl-config --cflags`" + SDL_LIBS="`sdl-config --libs`" + GTKJOY=yes + else + echo "Cannot find SDL. Disabling joystick support." + fi + +else + SDL_CFLAGS=$pkg_cv_SDL_CFLAGS + SDL_LIBS=$pkg_cv_SDL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + GTKJOY=yes + CFLAGS="$CFLAGS -DUSE_JOYSTICK" + +fi +fi + +XV=0 +XV_CFLAGS="" +XV_LIBS="" +if test yes = "$with_xv" ; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XV" >&5 +$as_echo_n "checking for XV... " >&6; } + +if test -n "$XV_CFLAGS"; then + pkg_cv_XV_CFLAGS="$XV_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xv\""; } >&5 + ($PKG_CONFIG --exists --print-errors "xv") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_XV_CFLAGS=`$PKG_CONFIG --cflags "xv" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$XV_LIBS"; then + pkg_cv_XV_LIBS="$XV_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xv\""; } >&5 + ($PKG_CONFIG --exists --print-errors "xv") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_XV_LIBS=`$PKG_CONFIG --libs "xv" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + XV_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "xv" 2>&1` + else + XV_PKG_ERRORS=`$PKG_CONFIG --print-errors "xv" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$XV_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + echo "Cannot find libXv. Make sure the X11 development headers are installed." + echo "--> Disabling Xv support" + +elif test $pkg_failed = untried; then + + echo "Cannot find libXv. Make sure the X11 development headers are installed." + echo "--> Disabling Xv support" + +else + XV_CFLAGS=$pkg_cv_XV_CFLAGS + XV_LIBS=$pkg_cv_XV_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + XV=yes + CFLAGS="$CFLAGS -DUSE_XV" + +fi +fi + +PORTAUDIO=0 +PORTAUDIO_CFLAGS="" +PORTAUDIO_LIBS="" +if test yes = "$with_portaudio" ; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PORTAUDIO" >&5 +$as_echo_n "checking for PORTAUDIO... " >&6; } + +if test -n "$PORTAUDIO_CFLAGS"; then + pkg_cv_PORTAUDIO_CFLAGS="$PORTAUDIO_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"portaudio-2.0 >= 10\""; } >&5 + ($PKG_CONFIG --exists --print-errors "portaudio-2.0 >= 10") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PORTAUDIO_CFLAGS=`$PKG_CONFIG --cflags "portaudio-2.0 >= 10" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$PORTAUDIO_LIBS"; then + pkg_cv_PORTAUDIO_LIBS="$PORTAUDIO_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"portaudio-2.0 >= 10\""; } >&5 + ($PKG_CONFIG --exists --print-errors "portaudio-2.0 >= 10") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PORTAUDIO_LIBS=`$PKG_CONFIG --libs "portaudio-2.0 >= 10" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + PORTAUDIO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "portaudio-2.0 >= 10" 2>&1` + else + PORTAUDIO_PKG_ERRORS=`$PKG_CONFIG --print-errors "portaudio-2.0 >= 10" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$PORTAUDIO_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + echo "Cannot find PortAudio." + echo "--> Disabling PortAudio support" + +elif test $pkg_failed = untried; then + + echo "Cannot find PortAudio." + echo "--> Disabling PortAudio support" + +else + PORTAUDIO_CFLAGS=$pkg_cv_PORTAUDIO_CFLAGS + PORTAUDIO_LIBS=$pkg_cv_PORTAUDIO_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + PORTAUDIO=yes + CFLAGS="$CFLAGS -DUSE_PORTAUDIO" + +fi +fi + +OSS=0 +if test yes = "$with_oss" ; then + + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/soundcard.h" "ac_cv_header_sys_soundcard_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_soundcard_h" = x""yes; then : + + CFLAGS="$CFLAGS -DUSE_OSS" + OSS=yes + +else + + echo "Cannot find OSS headers." + echo "--> Disabling OSS support" + +fi + + +fi + +ALSA=0 +ALSA_CFLAGS="" +ALSA_LIBS="" +if test yes = "$with_alsa" ; then + + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ALSA" >&5 +$as_echo_n "checking for ALSA... " >&6; } + +if test -n "$ALSA_CFLAGS"; then + pkg_cv_ALSA_CFLAGS="$ALSA_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa\""; } >&5 + ($PKG_CONFIG --exists --print-errors "alsa") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ALSA_CFLAGS=`$PKG_CONFIG --cflags "alsa" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$ALSA_LIBS"; then + pkg_cv_ALSA_LIBS="$ALSA_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"alsa\""; } >&5 + ($PKG_CONFIG --exists --print-errors "alsa") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ALSA_LIBS=`$PKG_CONFIG --libs "alsa" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + ALSA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "alsa" 2>&1` + else + ALSA_PKG_ERRORS=`$PKG_CONFIG --print-errors "alsa" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$ALSA_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + echo "Cannot find ALSA development support." + echo "--> Disabling ALSA" + +elif test $pkg_failed = untried; then + + echo "Cannot find ALSA development support." + echo "--> Disabling ALSA" + +else + ALSA_CFLAGS=$pkg_cv_ALSA_CFLAGS + ALSA_LIBS=$pkg_cv_ALSA_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + ALSA=yes + CFLAGS="$CFLAGS -DUSE_ALSA" + +fi +fi + +PULSEAUDIO=0 +PULSEAUDIO_CFLAGS="" +PULSEAUDIO_LIBS="" +if test yes = "$with_pulseaudio" ; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PULSEAUDIO" >&5 +$as_echo_n "checking for PULSEAUDIO... " >&6; } + +if test -n "$PULSEAUDIO_CFLAGS"; then + pkg_cv_PULSEAUDIO_CFLAGS="$PULSEAUDIO_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpulse-simple\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libpulse-simple") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PULSEAUDIO_CFLAGS=`$PKG_CONFIG --cflags "libpulse-simple" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$PULSEAUDIO_LIBS"; then + pkg_cv_PULSEAUDIO_LIBS="$PULSEAUDIO_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpulse-simple\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libpulse-simple") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_PULSEAUDIO_LIBS=`$PKG_CONFIG --libs "libpulse-simple" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + PULSEAUDIO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libpulse-simple" 2>&1` + else + PULSEAUDIO_PKG_ERRORS=`$PKG_CONFIG --print-errors "libpulse-simple" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$PULSEAUDIO_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + echo "Cannot find PulseAudio library." + echo "--> Disabling PulseAudio" + +elif test $pkg_failed = untried; then + + echo "Cannot find PulseAudio library." + echo "--> Disabling PulseAudio" + +else + PULSEAUDIO_CFLAGS=$pkg_cv_PULSEAUDIO_CFLAGS + PULSEAUDIO_LIBS=$pkg_cv_PULSEAUDIO_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + PULSEAUDIO=yes + CFLAGS="$CFLAGS -DUSE_PULSEAUDIO" + +fi +fi + +XRANDR=0 +XRANDR_CFLAGS="" +XRANDR_LIBS="" +if test yes = "$with_xrandr" ; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XRANDR" >&5 +$as_echo_n "checking for XRANDR... " >&6; } + +if test -n "$XRANDR_CFLAGS"; then + pkg_cv_XRANDR_CFLAGS="$XRANDR_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xrandr\""; } >&5 + ($PKG_CONFIG --exists --print-errors "xrandr") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_XRANDR_CFLAGS=`$PKG_CONFIG --cflags "xrandr" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$XRANDR_LIBS"; then + pkg_cv_XRANDR_LIBS="$XRANDR_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"xrandr\""; } >&5 + ($PKG_CONFIG --exists --print-errors "xrandr") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_XRANDR_LIBS=`$PKG_CONFIG --libs "xrandr" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + XRANDR_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "xrandr" 2>&1` + else + XRANDR_PKG_ERRORS=`$PKG_CONFIG --print-errors "xrandr" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$XRANDR_PKG_ERRORS" >&5 + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + echo "Cannot find libXrandr. Make sure the X11 development headers are installed." + echo "--> Disabling Xrandr support." + +elif test $pkg_failed = untried; then + + echo "Cannot find libXrandr. Make sure the X11 development headers are installed." + echo "--> Disabling Xrandr support." + +else + XRANDR_CFLAGS=$pkg_cv_XRANDR_CFLAGS + XRANDR_LIBS=$pkg_cv_XRANDR_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + XRANDR=yes + CFLAGS="$CFLAGS -DUSE_XRANDR" + +fi +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBPNG" >&5 +$as_echo_n "checking for LIBPNG... " >&6; } + +if test -n "$LIBPNG_CFLAGS"; then + pkg_cv_LIBPNG_CFLAGS="$LIBPNG_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libpng") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBPNG_CFLAGS=`$PKG_CONFIG --cflags "libpng" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBPNG_LIBS"; then + pkg_cv_LIBPNG_LIBS="$LIBPNG_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libpng") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBPNG_LIBS=`$PKG_CONFIG --libs "libpng" 2>/dev/null` +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBPNG_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libpng" 2>&1` + else + LIBPNG_PKG_ERRORS=`$PKG_CONFIG --print-errors "libpng" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBPNG_PKG_ERRORS" >&5 + + as_fn_error "Package requirements (libpng) were not met: + +$LIBPNG_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +Alternatively, you may set the environment variables LIBPNG_CFLAGS +and LIBPNG_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. +" "$LINENO" 5 +elif test $pkg_failed = untried; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +Alternatively, you may set the environment variables LIBPNG_CFLAGS +and LIBPNG_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details. + +To get pkg-config, see . +See \`config.log' for more details." "$LINENO" 5; } +else + LIBPNG_CFLAGS=$pkg_cv_LIBPNG_CFLAGS + LIBPNG_LIBS=$pkg_cv_LIBPNG_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + : +fi + +CFLAGS="$CFLAGS $GTK_CFLAGS $GLIB_CFLAGS $GLADE_CFLAGS $LIBXML_CFLAGS $PORTAUDIO_CFLAGS $LIBPNG_CFLAGS $SDL_CFLAGS $XV_CFLAGS $XRANDR_CFLAGS $ALSA_CFLAGS $PULSEAUDIO_CFLAGS" +LIBS="$LIBS $GTK_LIBS $GLIB_LIBS $GLADE_LIBS $LIBXML_LIBS $PORTAUDIO_LIBS $LIBPNG_LIBS $SDL_LIBS $XV_LIBS $XRANDR_LIBS $ALSA_LIBS $PULSEAUDIO_LIBS" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the CPU is IA32" >&5 +$as_echo_n "checking if the CPU is IA32... " >&6; } +if test "${snes9x_cv_i386_cpu+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if (defined (__i386__) || defined (__i486__) ||\ + defined (__i586__) || defined (__i686__) || defined (__WIN32__) || defined (__DJGPP)) +/* */ +#else +#error Not i386. +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + snes9x_cv_i386_cpu=yes +else + snes9x_cv_i386_cpu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + + +NASM="not_found" +if test yes = "$with_assembler"; then + # Extract the first word of "nasm", so it can be a program name with args. +set dummy nasm; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_prog_nasm+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $prog_nasm in + [\\/]* | ?:[\\/]*) + ac_cv_path_prog_nasm="$prog_nasm" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_prog_nasm="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_prog_nasm" && ac_cv_path_prog_nasm="no" + ;; +esac +fi +prog_nasm=$ac_cv_path_prog_nasm +if test -n "$prog_nasm"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $prog_nasm" >&5 +$as_echo "$prog_nasm" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + if test "x$ac_cv_path_prog_nasm" = "xno"; then + if test yes = "$snes9x_cv_i386_cpu"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: No nasm found. Will build without assembler optimizations." >&5 +$as_echo "$as_me: WARNING: No nasm found. Will build without assembler optimizations." >&2;} + fi + else + if test yes = "$snes9x_cv_i386_cpu"; then + NASM="$ac_cv_path_prog_nasm" + fi + fi +fi + +if test $NASM != "not_found"; then + if test yes = "$with_zsnesc4"; then + ZSNESC4=yes + CFLAGS="$CFLAGS -DZSNES_C4" + NASM_FLAGS="$NASM_FLAGS -DZSNES_C4" + fi + if test yes = "$with_zsnesfx"; then + ZSNESFX=yes + CFLAGS="$CFLAGS -DZSNES_FX -DEXECUTE_SUPERFX_PER_LINE" + NASM_FLAGS="$NASM_FLAGS -DZSNES_FX -DEXECUTE_SUPERFX_PER_LINE" + fi + CPUINC='-Ii386' +fi + +CFLAGS="$CFLAGS -DCORRECT_VRAM_READS" +CORRECT_VRAM_READS=1 + +if test yes = "$with_debugger"; then + CFLAGS="$CFLAGS -DDEBUGGER" +fi + + +if test yes = "$with_sdd1_decomp"; then + CFLAGS="$CFLAGS -DSDD1_DECOMP" + SDD1_DECOMP=yes +fi + +if test yes = "$with_netplay"; then + CFLAGS="$CFLAGS -DNETPLAY_SUPPORT" + NETPLAY=yes +fi + +if test yes = "$with_jma_decomp"; then + CFLAGS="$CFLAGS -DJMA_SUPPORT" + JMA=yes +fi + +if test yes = "$with_newblend"; then + CFLAGS="$CFLAGS -DNEW_COLOUR_BLENDING" +else + #OLD_COLOUR_BLENDING hasn't been default for a while + # SYSDEFINES="$SYSDEFINES"' -DOLD_COLOUR_BLENDING' + : +fi + +if test yes = "$with_zlib"; then + for ac_header in zlib.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzread in -lz" >&5 +$as_echo_n "checking for gzread in -lz... " >&6; } +if test "${ac_cv_lib_z_gzread+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gzread (); +int +main () +{ +return gzread (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_z_gzread=yes +else + ac_cv_lib_z_gzread=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzread" >&5 +$as_echo "$ac_cv_lib_z_gzread" >&6; } +if test "x$ac_cv_lib_z_gzread" = x""yes; then : + + CFLAGS="$CFLAGS -DZLIB" + LIBS="$LIBS -lz" + +fi + +fi + +if test yes = "$with_screenshot"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for png_init_io in -lpng" >&5 +$as_echo_n "checking for png_init_io in -lpng... " >&6; } +if test "${ac_cv_lib_png_png_init_io+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpng -lz -lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char png_init_io (); +int +main () +{ +return png_init_io (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_png_png_init_io=yes +else + ac_cv_lib_png_png_init_io=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_png_png_init_io" >&5 +$as_echo "$ac_cv_lib_png_png_init_io" >&6; } +if test "x$ac_cv_lib_png_png_init_io" = x""yes; then : + + CFLAGS="$CFLAGS -DHAVE_LIBPNG" + LIBS="$LIBS -lpng" + +fi + +fi + +ac_fn_cxx_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp" +if test "x$ac_cv_func_mkstemp" = x""yes; then : + + CFLAGS="$CFLAGS -DHAVE_MKSTEMP" + +fi + + + +ac_fn_cxx_check_header_mongrel "$LINENO" "strings.h" "ac_cv_header_strings_h" "$ac_includes_default" +if test "x$ac_cv_header_strings_h" = x""yes; then : + + CFLAGS="$CFLAGS -DHAVE_STRINGS_H" + +fi + + + +ac_fn_cxx_check_header_mongrel "$LINENO" "sys/ioctl.h" "ac_cv_header_sys_ioctl_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_ioctl_h" = x""yes; then : + + CFLAGS="$CFLAGS -DHAVE_SYS_IOCTL_H" + +fi + + + +ac_fn_cxx_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" +if test "x$ac_cv_header_stdint_h" = x""yes; then : + + CFLAGS="$CFLAGS -DHAVE_STDINT_H" + +fi + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sizeof(void *) == sizeof(int)" >&5 +$as_echo_n "checking if sizeof(void *) == sizeof(int)... " >&6; } +if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot run test program while cross compiling +See \`config.log' for more details." "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + int main() + { + return(!(sizeof(void *) == sizeof(int))); + } + +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + snes9x_ptr_is_int=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +if test x$snes9x_ptr_is_int = xyes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + CFLAGS="$CFLAGS -DPTR_NOT_INT" +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if rightshift int8 is arithmetic" >&5 +$as_echo_n "checking if rightshift int8 is arithmetic... " >&6; } +if test "${ac_cv_my_sar_int8+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + +if test "$cross_compiling" = yes; then : + ac_cv_my_sar_%1=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include "../port.h" + +int main(void){ + int8 i; + + i=-1; + i>>=1; + return(i<0?0:1); +} + +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_my_sar_int8=yes +else + ac_cv_my_sar_int8=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi + + +if test $ac_cv_my_sar_int8 = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + CFLAGS="$CFLAGS -DRIGHTSHIFT_int8_IS_SAR" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if rightshift int16 is arithmetic" >&5 +$as_echo_n "checking if rightshift int16 is arithmetic... " >&6; } +if test "${ac_cv_my_sar_int16+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + +if test "$cross_compiling" = yes; then : + ac_cv_my_sar_%1=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include "../port.h" + +int main(void){ + int16 i; + + i=-1; + i>>=1; + return(i<0?0:1); +} + +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_my_sar_int16=yes +else + ac_cv_my_sar_int16=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi + + +if test $ac_cv_my_sar_int16 = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + CFLAGS="$CFLAGS -DRIGHTSHIFT_int16_IS_SAR" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if rightshift int32 is arithmetic" >&5 +$as_echo_n "checking if rightshift int32 is arithmetic... " >&6; } +if test "${ac_cv_my_sar_int32+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + +if test "$cross_compiling" = yes; then : + ac_cv_my_sar_%1=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include "../port.h" + +int main(void){ + int32 i; + + i=-1; + i>>=1; + return(i<0?0:1); +} + +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_my_sar_int32=yes +else + ac_cv_my_sar_int32=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi + + +if test $ac_cv_my_sar_int32 = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + CFLAGS="$CFLAGS -DRIGHTSHIFT_int32_IS_SAR" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if rightshift int64 is arithmetic" >&5 +$as_echo_n "checking if rightshift int64 is arithmetic... " >&6; } +if test "${ac_cv_my_sar_int64+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + +if test "$cross_compiling" = yes; then : + ac_cv_my_sar_%1=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include "../port.h" + +int main(void){ + int64 i; + + i=-1; + i>>=1; + return(i<0?0:1); +} + +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_my_sar_int64=yes +else + ac_cv_my_sar_int64=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi + + +if test $ac_cv_my_sar_int64 = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + CFLAGS="$CFLAGS -DRIGHTSHIFT_int64_IS_SAR" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi + +if test $ac_cv_my_sar_int8 = yes && \ + test $ac_cv_my_sar_int16 = yes && \ + test $ac_cv_my_sar_int32 = yes && \ + test $ac_cv_my_sar_int64 = yes ; then + CFLAGS="$CFLAGS -DRIGHTSHIFT_IS_SAR" +fi + +CFLAGS="$CFLAGS -DCPU_SHUTDOWN -DSPC700_SHUTDOWN -DNO_INLINE_SET_GET -DUNZIP_SUPPORT -DSPC700_C -I. -I.. -I../unzip" + +CXXFLAGS="$CFLAGS" + +CCASFLAGS="$CFLAGS -I.. -I../i386" + + if test yes = "$ZSNESFX"; then + ZSNESFX_TRUE= + ZSNESFX_FALSE='#' +else + ZSNESFX_TRUE='#' + ZSNESFX_FALSE= +fi + + if test yes = "$ZSNESC4"; then + ZSNESC4_TRUE= + ZSNESC4_FALSE='#' +else + ZSNESC4_TRUE='#' + ZSNESC4_FALSE= +fi + + if test yes = "$ASMCPU"; then + ASMCPU_TRUE= + ASMCPU_FALSE='#' +else + ASMCPU_TRUE='#' + ASMCPU_FALSE= +fi + + if test yes = "$SDD1_DECOMP"; then + SDD1_DECOMP_TRUE= + SDD1_DECOMP_FALSE='#' +else + SDD1_DECOMP_TRUE='#' + SDD1_DECOMP_FALSE= +fi + + if test yes = "$NETPLAY"; then + NETPLAY_TRUE= + NETPLAY_FALSE='#' +else + NETPLAY_TRUE='#' + NETPLAY_FALSE= +fi + + if test yes = "$JMA"; then + JMA_TRUE= + JMA_FALSE='#' +else + JMA_TRUE='#' + JMA_FALSE= +fi + + if test yes = "$OPENGL"; then + OPENGL_TRUE= + OPENGL_FALSE='#' +else + OPENGL_TRUE='#' + OPENGL_FALSE= +fi + + if test yes = "$XV"; then + XV_TRUE= + XV_FALSE='#' +else + XV_TRUE='#' + XV_FALSE= +fi + + if test yes = "$PORTAUDIO"; then + PORTAUDIO_TRUE= + PORTAUDIO_FALSE='#' +else + PORTAUDIO_TRUE='#' + PORTAUDIO_FALSE= +fi + + if test yes = "$OSS"; then + OSS_TRUE= + OSS_FALSE='#' +else + OSS_TRUE='#' + OSS_FALSE= +fi + + if test yes = "$with_debug" ; then + DEBUG_TRUE= + DEBUG_FALSE='#' +else + DEBUG_TRUE='#' + DEBUG_FALSE= +fi + + if test yes = "$GTKJOY"; then + SDL_TRUE= + SDL_FALSE='#' +else + SDL_TRUE='#' + SDL_FALSE= +fi + + if test yes = "$ALSA"; then + ALSA_TRUE= + ALSA_FALSE='#' +else + ALSA_TRUE='#' + ALSA_FALSE= +fi + + if test yes = "$PULSEAUDIO"; then + PULSEAUDIO_TRUE= + PULSEAUDIO_FALSE='#' +else + PULSEAUDIO_TRUE='#' + PULSEAUDIO_FALSE= +fi + + + + + +ac_config_files="$ac_config_files Makefile data/Makefile po/Makefile.in" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + + + ac_config_commands="$ac_config_commands po/stamp-it" + + +if test -z "${ZSNESFX_TRUE}" && test -z "${ZSNESFX_FALSE}"; then + as_fn_error "conditional \"ZSNESFX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ZSNESC4_TRUE}" && test -z "${ZSNESC4_FALSE}"; then + as_fn_error "conditional \"ZSNESC4\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ASMCPU_TRUE}" && test -z "${ASMCPU_FALSE}"; then + as_fn_error "conditional \"ASMCPU\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SDD1_DECOMP_TRUE}" && test -z "${SDD1_DECOMP_FALSE}"; then + as_fn_error "conditional \"SDD1_DECOMP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${NETPLAY_TRUE}" && test -z "${NETPLAY_FALSE}"; then + as_fn_error "conditional \"NETPLAY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${JMA_TRUE}" && test -z "${JMA_FALSE}"; then + as_fn_error "conditional \"JMA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${OPENGL_TRUE}" && test -z "${OPENGL_FALSE}"; then + as_fn_error "conditional \"OPENGL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${XV_TRUE}" && test -z "${XV_FALSE}"; then + as_fn_error "conditional \"XV\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PORTAUDIO_TRUE}" && test -z "${PORTAUDIO_FALSE}"; then + as_fn_error "conditional \"PORTAUDIO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${OSS_TRUE}" && test -z "${OSS_FALSE}"; then + as_fn_error "conditional \"OSS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DEBUG_TRUE}" && test -z "${DEBUG_FALSE}"; then + as_fn_error "conditional \"DEBUG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${SDL_TRUE}" && test -z "${SDL_FALSE}"; then + as_fn_error "conditional \"SDL\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ALSA_TRUE}" && test -z "${ALSA_FALSE}"; then + as_fn_error "conditional \"ALSA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PULSEAUDIO_TRUE}" && test -z "${PULSEAUDIO_FALSE}"; then + as_fn_error "conditional \"PULSEAUDIO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: ${CONFIG_STATUS=./config.status} +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by snes9x-gtk $as_me 1.52, which was +generated by GNU Autoconf 2.65. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Configuration commands: +$config_commands + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +snes9x-gtk config.status 1.52 +configured by $0, generated by GNU Autoconf 2.65, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2009 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; + "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; + "po/stamp-it") CONFIG_COMMANDS="$CONFIG_COMMANDS po/stamp-it" ;; + + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || as_fn_error "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + ;; + + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "default-1":C) case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac ;; + "po/stamp-it":C) + if ! grep "^# INTLTOOL_MAKEFILE$" "po/Makefile.in" > /dev/null ; then + as_fn_error "po/Makefile.in.in was not created by intltoolize." "$LINENO" 5 + fi + rm -f "po/stamp-it" "po/stamp-it.tmp" "po/POTFILES" "po/Makefile.tmp" + >"po/stamp-it.tmp" + sed '/^#/d + s/^[[].*] *// + /^[ ]*$/d + '"s|^| $ac_top_srcdir/|" \ + "$srcdir/po/POTFILES.in" | sed '$!s/$/ \\/' >"po/POTFILES" + + sed '/^POTFILES =/,/[^\\]$/ { + /^POTFILES =/!d + r po/POTFILES + } + ' "po/Makefile.in" >"po/Makefile" + rm -f "po/Makefile.tmp" + mv "po/stamp-it.tmp" "po/stamp-it" + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit $? +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +echo "" +echo "Snes9x will build with support for the following:" +echo "" + +if test yes = "$ALSA" ; then + echo " ALSA" +fi + +if test yes = "$PULSEAUDIO" ; then + echo " PulseAudio" +fi + +if test yes = "$OPENGL" ; then + echo " OpenGL" +else + if test yes = "$with_opengl" ; then + echo "!!! NOT able to use OpenGL support" + echo "--- Needs gtkglext and OpenGL libraries and headers" + fi +fi + +if test yes = "$XV" ; then + echo " XVideo" +else + if test yes = "$with_xv" ; then + echo "!!! NOT able to use XVideo support" + echo "--- Needs recent X11 libraries and headers" + fi +fi + +if test yes = "$XRANDR" ; then + echo " XRandR" +else + if test yes = "$with_xrandr" ; then + echo "!!! NOT able to use XRandR support" + echo "--- Needs recent X11 libraries and headers" + fi +fi + +if test yes = "$GTKJOY" ; then + echo " Joysticks" +else + if test yes = "$with_joystick" ; then + echo "!!! NOT able to use joystick support" + echo "--- Needs SDL libraries and headers" + fi +fi + +if test yes = "$NETPLAY" ; then + echo " NetPlay" +else + if test yes = "$with_netplay" ; then + echo "!!! NOT able to build NetPlay support" + + fi +fi + +echo "" + +if ! test yes = "$PORTAUDIO" ; then + if ! test yes = "$OSS" ; then + if ! test yes = "$SDL"; then + if ! test yes = "$ALSA"; then + echo "ERROR: No audio driver is selected or available. Snes9x will probably not build." + fi + fi + fi +fi diff --git a/gtk/configure.ac b/gtk/configure.ac new file mode 100644 index 00000000..03ae6d37 --- /dev/null +++ b/gtk/configure.ac @@ -0,0 +1,547 @@ +AC_INIT([snes9x-gtk], 1.52) +dnl Set CFLAGS, CXXFLAGS to something +dnl before doing AC_PROG_CC, AC_PROG_CXX to avoid default -g +CFLAGS="-O2 -Wall -W -pedantic -Wno-unused-parameter -pipe $CFLAGS" +CXXFLAGS="$CFLAGS" + +AC_PROG_CC +AC_PROG_CXX +AC_PROG_RANLIB +AC_LANG_CPLUSPLUS + +AC_PROG_INSTALL +AM_INIT_AUTOMAKE([foreign subdir-objects]) + +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + +AM_PROG_CC_C_O +IT_PROG_INTLTOOL([0.40.1]) +GETTEXT_PACKAGE=[snes9x-gtk] +AC_SUBST(GETTEXT_PACKAGE) +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE") + +AM_GLIB_GNU_GETTEXT + +snes9xlocaledir='${prefix}/${DATADIRNAME}/locale' +AC_SUBST(snes9xlocaledir) + +AC_ARG_WITH(debug, + [AS_HELP_STRING([--with(out)-debug], + [Leave debug information in the final binary (default: without)])], + [], + [with_debug=no]) + +AC_ARG_WITH(opengl, + [AS_HELP_STRING([--with(out)-opengl], + [Use OpenGL for output (default: with)])], + [], + [with_opengl=yes]) + +AC_ARG_WITH(joystick, + [AS_HELP_STRING([--with(out)-joystick], + [Enable joystick support if available (default: with)])], + [], + [with_joystick=yes]) + +AC_ARG_WITH(xv, + [AS_HELP_STRING([--with(out)-xv], + [Enable XVideo output on GTK (default: with)])], + [], + [with_xv=yes]) + +AC_ARG_WITH(xrandr, + [AS_HELP_STRING([--with(out)-xrandr], + [Enable XRandR support on GTK (default: with)])], + [], + [with_xrandr=yes]) + +AC_ARG_WITH(portaudio, + [AS_HELP_STRING([--with(out)-portaudio], + [Enable PortAudio sound driver support (default: with)])], + [], + [with_portaudio=yes]) + +AC_ARG_WITH(oss, + [AS_HELP_STRING([--with(out)-oss], + [Enable OSS sound driver support (default: with)])], + [], + [with_oss=yes]) + +AC_ARG_WITH(alsa, + [AS_HELP_STRING([--with(out)-alsa], + [Enable ALSA sound driver support (default: with)])], + [], + [with_alsa=yes]) + +AC_ARG_WITH(pulseaudio, + [AS_HELP_STRING([--with(out)-pulseaudio], + [Enable PulseAudio sound driver support (default: with)])], + [], + [with_pulseaudio=yes]) + +AC_ARG_WITH(assembler, + [AS_HELP_STRING([--with(out)-assembler], + [Use assembler cores if available (default: with)])], + [], + [with_assembler=yes]) + +AC_ARG_WITH(zsnesc4, + [AS_HELP_STRING([--with(out)-zsnesc4], + [Use ZSNES C4 core if available (default: same as --with-assembler)])], + [], + [with_zsnesc4=$with_assembler]) + +AC_ARG_WITH(zsnesfx, + [AS_HELP_STRING([--with(out)-zsnesfx], + [Use ZSNES SuperFX core if available (default: same as --with-assembler)])], + [], + [with_zsnesfx=$with_assembler]) + +AC_ARG_WITH(debugger, + [AS_HELP_STRING([--with(out)-debugger], + [Enable debugger (default: without)])], + [], + [with_debugger=no]) + +AC_ARG_WITH(sdd1-decomp, + [AS_HELP_STRING([--with(out)-sdd1-decomp], + [Use SDD1 decompression (default: with)])], + [], + [with_sdd1_decomp=yes]) + +AC_ARG_WITH(netplay, + [AS_HELP_STRING([--with(out)-netplay], + [Enable netplay support (default: without)])], + [], + [with_netplay=yes]) + +AC_ARG_WITH(jma-decomp, + [AS_HELP_STRING([--with(out)-jma-decomp], + [Enable JMA archive decompression (default: with)])], + [], + [with_jma_decomp=yes]) + +AC_ARG_WITH(newblend, + [AS_HELP_STRING([--with(out)-newblend], + [New colour blender (default: with)])], + [], + [with_newblend=yes]) + +AC_ARG_WITH(zlib, + [AS_HELP_STRING([--with(out)-zlib], + [Support gzip decompression])], + [], + [with_zlib=yes]) + +AC_ARG_WITH(png, + [AS_HELP_STRING([--with(out)-screenshot], + [Screenshot support through libpng if available (default: with)])], + [], + [with_screenshot=yes]) + +if test yes = "$with_debug" ; then + CFLAGS="$CFLAGS -g" +else + CFLAGS="$CFLAGS -fomit-frame-pointer" +fi + +ZSNESFX='#ZSNESFX=yes' +ZSNESC4='#ZSNESC4=yes' +ASMCPU='' +SDD1_DECOMP='#SDD1_DECOMP=yes' +JMA='#JMA=yes' +SPC700ASM='' +I386SPC='' +CPUINC='' +NETPLAY='#NETPLAY=yes' + +SYSLIBS='' +NASM='not_found' + +OPENGL=0 + +if test yes = "$with_opengl" ; then + OPENGL=yes +fi + +GTK=yes +snes9x_info_display="GTK" + +PKG_CHECK_MODULES([GTK], [gtk+-2.0 >= 2.10]) +PKG_CHECK_MODULES([GLIB], [gthread-2.0 >= 2.6 gobject-2.0 >= 2.6]) +PKG_CHECK_MODULES([GLADE], [libglade-2.0 >= 2.0]) +PKG_CHECK_MODULES([LIBXML], [libxml-2.0 >= 2.0]) + +if test yes = "$with_opengl" ; then + + AC_CHECK_LIB(GL,glGetString,[ + OPENGL=yes + CFLAGS="$CFLAGS -DUSE_OPENGL" + LIBS="-lGL" + ],[ + OPENGL=0 + ]) +fi + +GTKJOY=0 +SDL_CFLAGS="" +SDL_LIBS="" +if test yes = "$with_joystick"; then + PKG_CHECK_MODULES([SDL],[sdl],[ + GTKJOY=yes + CFLAGS="$CFLAGS -DUSE_JOYSTICK" + ],[ + AC_CHECK_PROG(SDLCONFIGFOUND,[sdl-config],yes,no) + + if test yes = "$SDLCONFIGFOUND" ; then + SDL_CFLAGS="-DUSE_JOYSTICK `sdl-config --cflags`" + SDL_LIBS="`sdl-config --libs`" + GTKJOY=yes + else + echo "Cannot find SDL. Disabling joystick support." + fi + ]) +fi + +XV=0 +XV_CFLAGS="" +XV_LIBS="" +if test yes = "$with_xv" ; then + PKG_CHECK_MODULES([XV],[xv],[ + XV=yes + CFLAGS="$CFLAGS -DUSE_XV" + ],[ + echo "Cannot find libXv. Make sure the X11 development headers are installed." + echo "--> Disabling Xv support" + ]) +fi + +PORTAUDIO=0 +PORTAUDIO_CFLAGS="" +PORTAUDIO_LIBS="" +if test yes = "$with_portaudio" ; then + PKG_CHECK_MODULES([PORTAUDIO], [portaudio-2.0 >= 10],[ + PORTAUDIO=yes + CFLAGS="$CFLAGS -DUSE_PORTAUDIO" + ],[ + echo "Cannot find PortAudio." + echo "--> Disabling PortAudio support" + ]) +fi + +OSS=0 +if test yes = "$with_oss" ; then + + AC_CHECK_HEADER(sys/soundcard.h, [ + CFLAGS="$CFLAGS -DUSE_OSS" + OSS=yes + ],[ + echo "Cannot find OSS headers." + echo "--> Disabling OSS support" + ]) +fi + +ALSA=0 +ALSA_CFLAGS="" +ALSA_LIBS="" +if test yes = "$with_alsa" ; then + + PKG_CHECK_MODULES([ALSA], [alsa],[ + ALSA=yes + CFLAGS="$CFLAGS -DUSE_ALSA" + ],[ + echo "Cannot find ALSA development support." + echo "--> Disabling ALSA" + ]) +fi + +PULSEAUDIO=0 +PULSEAUDIO_CFLAGS="" +PULSEAUDIO_LIBS="" +if test yes = "$with_pulseaudio" ; then + PKG_CHECK_MODULES([PULSEAUDIO], [libpulse-simple],[ + PULSEAUDIO=yes + CFLAGS="$CFLAGS -DUSE_PULSEAUDIO" + ],[ + echo "Cannot find PulseAudio library." + echo "--> Disabling PulseAudio" + ]) +fi + +XRANDR=0 +XRANDR_CFLAGS="" +XRANDR_LIBS="" +if test yes = "$with_xrandr" ; then + PKG_CHECK_MODULES([XRANDR],[xrandr],[ + XRANDR=yes + CFLAGS="$CFLAGS -DUSE_XRANDR" + ],[ + echo "Cannot find libXrandr. Make sure the X11 development headers are installed." + echo "--> Disabling Xrandr support." + ]) +fi +PKG_CHECK_MODULES([LIBPNG],libpng) + +CFLAGS="$CFLAGS $GTK_CFLAGS $GLIB_CFLAGS $GLADE_CFLAGS $LIBXML_CFLAGS $PORTAUDIO_CFLAGS $LIBPNG_CFLAGS $SDL_CFLAGS $XV_CFLAGS $XRANDR_CFLAGS $ALSA_CFLAGS $PULSEAUDIO_CFLAGS" +LIBS="$LIBS $GTK_LIBS $GLIB_LIBS $GLADE_LIBS $LIBXML_LIBS $PORTAUDIO_LIBS $LIBPNG_LIBS $SDL_LIBS $XV_LIBS $XRANDR_LIBS $ALSA_LIBS $PULSEAUDIO_LIBS" + + +AC_MSG_CHECKING(if the CPU is IA32) +AC_CACHE_VAL(snes9x_cv_i386_cpu, [ + AC_TRY_COMPILE([ +#if (defined (__i386__) || defined (__i486__) ||\ + defined (__i586__) || defined (__i686__) || defined (__WIN32__) || defined (__DJGPP)) +/* */ +#else +#error Not i386. +#endif + ], [], snes9x_cv_i386_cpu=yes, snes9x_cv_i386_cpu=no)]) + +dnl Enable assembler optimizations if CPU is x86 + +NASM="not_found" +if test yes = "$with_assembler"; then + AC_PATH_PROG(prog_nasm, nasm, no) + + if test "x$ac_cv_path_prog_nasm" = "xno"; then + if test yes = "$snes9x_cv_i386_cpu"; then + AC_MSG_WARN([No nasm found. Will build without assembler optimizations.]) + fi + else + if test yes = "$snes9x_cv_i386_cpu"; then + NASM="$ac_cv_path_prog_nasm" + fi + fi +fi + +if test $NASM != "not_found"; then + if test yes = "$with_zsnesc4"; then + ZSNESC4=yes + CFLAGS="$CFLAGS -DZSNES_C4" + NASM_FLAGS="$NASM_FLAGS -DZSNES_C4" + fi + if test yes = "$with_zsnesfx"; then + ZSNESFX=yes + CFLAGS="$CFLAGS -DZSNES_FX -DEXECUTE_SUPERFX_PER_LINE" + NASM_FLAGS="$NASM_FLAGS -DZSNES_FX -DEXECUTE_SUPERFX_PER_LINE" + fi + CPUINC='-Ii386' +fi + +CFLAGS="$CFLAGS -DCORRECT_VRAM_READS" +CORRECT_VRAM_READS=1 + +if test yes = "$with_debugger"; then + CFLAGS="$CFLAGS -DDEBUGGER" +fi + + +dnl Enable SDD1 decompression if requested +if test yes = "$with_sdd1_decomp"; then + CFLAGS="$CFLAGS -DSDD1_DECOMP" + SDD1_DECOMP=yes +fi + +dnl Enable Netplay support if requested +if test yes = "$with_netplay"; then + CFLAGS="$CFLAGS -DNETPLAY_SUPPORT" + NETPLAY=yes +fi + +dnl Enable jma decompression (nachs own format) +if test yes = "$with_jma_decomp"; then + CFLAGS="$CFLAGS -DJMA_SUPPORT" + JMA=yes +fi + +dnl FIXME: There is a third case (OLD) that is missed with this. +if test yes = "$with_newblend"; then + CFLAGS="$CFLAGS -DNEW_COLOUR_BLENDING" +else + #OLD_COLOUR_BLENDING hasn't been default for a while + # SYSDEFINES="$SYSDEFINES"' -DOLD_COLOUR_BLENDING' + : +fi + +if test yes = "$with_zlib"; then + AC_CHECK_HEADERS(zlib.h) + AC_CHECK_LIB(z, gzread, [ + CFLAGS="$CFLAGS -DZLIB" + LIBS="$LIBS -lz" + ], ,) +fi + +if test yes = "$with_screenshot"; then + AC_CHECK_LIB(png, png_init_io, [ + CFLAGS="$CFLAGS -DHAVE_LIBPNG" + LIBS="$LIBS -lpng" + ], , -lz -lm) +fi + +dnl Check for functions +AC_CHECK_FUNC(mkstemp, [ + CFLAGS="$CFLAGS -DHAVE_MKSTEMP" +]) + +dnl Check for headers + +AC_CHECK_HEADER(strings.h, [ + CFLAGS="$CFLAGS -DHAVE_STRINGS_H" +]) + +AC_CHECK_HEADER(sys/ioctl.h, [ + CFLAGS="$CFLAGS -DHAVE_SYS_IOCTL_H" +]) + +AC_CHECK_HEADER(stdint.h, [ + CFLAGS="$CFLAGS -DHAVE_STDINT_H" +]) + + +dnl Check SAR + +AC_DEFUN([AC_MY_CHECK_SAR], +[ +AC_MSG_CHECKING([if rightshift $1 is arithmetic]) +AC_CACHE_VAL(ac_cv_my_sar_$1, +[ +AC_TRY_RUN([ +#include "../port.h" + +int main(void){ + $1 i; + + i=-1; + i>>=1; + return(i<0?0:1); +} +],ac_cv_my_sar_$1=yes,ac_cv_my_sar_$1=no,ac_cv_my_sar_%1=no) +]) + +if test $ac_cv_my_sar_$1 = no; then + AC_MSG_RESULT(no) +else + CFLAGS="$CFLAGS -DRIGHTSHIFT_$1_IS_SAR" + AC_MSG_RESULT(yes) +fi +]) + +AC_MSG_CHECKING(if sizeof(void *) == sizeof(int)) +AC_TRY_RUN([ + int main() + { + return(!(sizeof(void *) == sizeof(int))); + } +], snes9x_ptr_is_int=yes) +if test x$snes9x_ptr_is_int = xyes; then + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) + CFLAGS="$CFLAGS -DPTR_NOT_INT" +fi + +AC_MY_CHECK_SAR(int8) +AC_MY_CHECK_SAR(int16) +AC_MY_CHECK_SAR(int32) +AC_MY_CHECK_SAR(int64) +if test $ac_cv_my_sar_int8 = yes && \ + test $ac_cv_my_sar_int16 = yes && \ + test $ac_cv_my_sar_int32 = yes && \ + test $ac_cv_my_sar_int64 = yes ; then + CFLAGS="$CFLAGS -DRIGHTSHIFT_IS_SAR" +fi + +CFLAGS="$CFLAGS -DCPU_SHUTDOWN -DSPC700_SHUTDOWN -DNO_INLINE_SET_GET -DUNZIP_SUPPORT -DSPC700_C -I. -I.. -I../unzip" + +CXXFLAGS="$CFLAGS" + +CCASFLAGS="$CFLAGS -I.. -I../i386" + +AM_CONDITIONAL(ZSNESFX, [test yes = "$ZSNESFX"]) +AM_CONDITIONAL(ZSNESC4, [test yes = "$ZSNESC4"]) +AM_CONDITIONAL(ASMCPU, [test yes = "$ASMCPU"]) +AM_CONDITIONAL(SDD1_DECOMP, [test yes = "$SDD1_DECOMP"]) +AM_CONDITIONAL(NETPLAY, [test yes = "$NETPLAY"]) +AM_CONDITIONAL(JMA, [test yes = "$JMA"]) +AM_CONDITIONAL(OPENGL, [test yes = "$OPENGL"]) +AM_CONDITIONAL(XV, [test yes = "$XV"]) +AM_CONDITIONAL(PORTAUDIO, [test yes = "$PORTAUDIO"]) +AM_CONDITIONAL(OSS, [test yes = "$OSS"]) +AM_CONDITIONAL(DEBUG, [test yes = "$with_debug" ]) +AM_CONDITIONAL(SDL, [test yes = "$GTKJOY"]) +AM_CONDITIONAL(ALSA, [test yes = "$ALSA"]) +AM_CONDITIONAL(PULSEAUDIO, [test yes = "$PULSEAUDIO"]) + +AC_SUBST(NASM) +AC_SUBST(NASM_FLAGS) + +AC_OUTPUT(Makefile data/Makefile po/Makefile.in) + +echo "" +echo "Snes9x will build with support for the following:" +echo "" + +if test yes = "$ALSA" ; then + echo " ALSA" +fi + +if test yes = "$PULSEAUDIO" ; then + echo " PulseAudio" +fi + +if test yes = "$OPENGL" ; then + echo " OpenGL" +else + if test yes = "$with_opengl" ; then + echo "!!! NOT able to use OpenGL support" + echo "--- Needs gtkglext and OpenGL libraries and headers" + fi +fi + +if test yes = "$XV" ; then + echo " XVideo" +else + if test yes = "$with_xv" ; then + echo "!!! NOT able to use XVideo support" + echo "--- Needs recent X11 libraries and headers" + fi +fi + +if test yes = "$XRANDR" ; then + echo " XRandR" +else + if test yes = "$with_xrandr" ; then + echo "!!! NOT able to use XRandR support" + echo "--- Needs recent X11 libraries and headers" + fi +fi + +if test yes = "$GTKJOY" ; then + echo " Joysticks" +else + if test yes = "$with_joystick" ; then + echo "!!! NOT able to use joystick support" + echo "--- Needs SDL libraries and headers" + fi +fi + +if test yes = "$NETPLAY" ; then + echo " NetPlay" +else + if test yes = "$with_netplay" ; then + echo "!!! NOT able to build NetPlay support" + + fi +fi + +echo "" + +if ! test yes = "$PORTAUDIO" ; then + if ! test yes = "$OSS" ; then + if ! test yes = "$SDL"; then + if ! test yes = "$ALSA"; then + echo "ERROR: No audio driver is selected or available. Snes9x will probably not build." + fi + fi + fi +fi diff --git a/gtk/data/Makefile.am b/gtk/data/Makefile.am new file mode 100644 index 00000000..72e39cc9 --- /dev/null +++ b/gtk/data/Makefile.am @@ -0,0 +1,24 @@ +desktopdir = $(datadir)/applications +desktop_DATA = snes9x.desktop + +icon16x16dir = $(datadir)/icons/hicolor/16x16/apps +icon16x16_DATA = snes9x_16x16.png + +icon24x24dir = $(datadir)/icons/hicolor/24x24/apps +icon24x24_DATA = snes9x_24x24.png + +icon32x32dir = $(datadir)/icons/hicolor/32x32/apps +icon32x32_DATA = snes9x_32x32.png + +iconscalabledir = $(datadir)/icons/hicolor/scalable/apps +iconscalable_DATA = snes9x.svg + +install-data-hook: + mv -f $(DESTDIR)$(datadir)/icons/hicolor/16x16/apps/snes9x_16x16.png \ + $(DESTDIR)$(datadir)/icons/hicolor/16x16/apps/snes9x.png + mv -f $(DESTDIR)$(datadir)/icons/hicolor/24x24/apps/snes9x_24x24.png \ + $(DESTDIR)$(datadir)/icons/hicolor/24x24/apps/snes9x.png + mv -f $(DESTDIR)$(datadir)/icons/hicolor/32x32/apps/snes9x_32x32.png \ + $(DESTDIR)$(datadir)/icons/hicolor/32x32/apps/snes9x.png + touch -c $(DESTDIR)$(datadir)/icons/hicolor + diff --git a/gtk/data/Makefile.in b/gtk/data/Makefile.in new file mode 100644 index 00000000..db85b4e0 --- /dev/null +++ b/gtk/data/Makefile.in @@ -0,0 +1,534 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = data +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(desktopdir)" \ + "$(DESTDIR)$(icon16x16dir)" "$(DESTDIR)$(icon24x24dir)" \ + "$(DESTDIR)$(icon32x32dir)" "$(DESTDIR)$(iconscalabledir)" +DATA = $(desktop_DATA) $(icon16x16_DATA) $(icon24x24_DATA) \ + $(icon32x32_DATA) $(iconscalable_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLADE_CFLAGS = @GLADE_CFLAGS@ +GLADE_LIBS = @GLADE_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_LIBS = @GLIB_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GREP = @GREP@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBPNG_CFLAGS = @LIBPNG_CFLAGS@ +LIBPNG_LIBS = @LIBPNG_LIBS@ +LIBS = @LIBS@ +LIBXML_CFLAGS = @LIBXML_CFLAGS@ +LIBXML_LIBS = @LIBXML_LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +NASM = @NASM@ +NASM_FLAGS = @NASM_FLAGS@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +POFILES = @POFILES@ +PORTAUDIO_CFLAGS = @PORTAUDIO_CFLAGS@ +PORTAUDIO_LIBS = @PORTAUDIO_LIBS@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PULSEAUDIO_CFLAGS = @PULSEAUDIO_CFLAGS@ +PULSEAUDIO_LIBS = @PULSEAUDIO_LIBS@ +RANLIB = @RANLIB@ +SDLCONFIGFOUND = @SDLCONFIGFOUND@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XRANDR_CFLAGS = @XRANDR_CFLAGS@ +XRANDR_LIBS = @XRANDR_LIBS@ +XV_CFLAGS = @XV_CFLAGS@ +XV_LIBS = @XV_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +prog_nasm = @prog_nasm@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +snes9xlocaledir = @snes9xlocaledir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +desktopdir = $(datadir)/applications +desktop_DATA = snes9x.desktop +icon16x16dir = $(datadir)/icons/hicolor/16x16/apps +icon16x16_DATA = snes9x_16x16.png +icon24x24dir = $(datadir)/icons/hicolor/24x24/apps +icon24x24_DATA = snes9x_24x24.png +icon32x32dir = $(datadir)/icons/hicolor/32x32/apps +icon32x32_DATA = snes9x_32x32.png +iconscalabledir = $(datadir)/icons/hicolor/scalable/apps +iconscalable_DATA = snes9x.svg +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign data/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign data/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-desktopDATA: $(desktop_DATA) + @$(NORMAL_INSTALL) + test -z "$(desktopdir)" || $(MKDIR_P) "$(DESTDIR)$(desktopdir)" + @list='$(desktop_DATA)'; test -n "$(desktopdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(desktopdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(desktopdir)" || exit $$?; \ + done + +uninstall-desktopDATA: + @$(NORMAL_UNINSTALL) + @list='$(desktop_DATA)'; test -n "$(desktopdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(desktopdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(desktopdir)" && rm -f $$files +install-icon16x16DATA: $(icon16x16_DATA) + @$(NORMAL_INSTALL) + test -z "$(icon16x16dir)" || $(MKDIR_P) "$(DESTDIR)$(icon16x16dir)" + @list='$(icon16x16_DATA)'; test -n "$(icon16x16dir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(icon16x16dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(icon16x16dir)" || exit $$?; \ + done + +uninstall-icon16x16DATA: + @$(NORMAL_UNINSTALL) + @list='$(icon16x16_DATA)'; test -n "$(icon16x16dir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(icon16x16dir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(icon16x16dir)" && rm -f $$files +install-icon24x24DATA: $(icon24x24_DATA) + @$(NORMAL_INSTALL) + test -z "$(icon24x24dir)" || $(MKDIR_P) "$(DESTDIR)$(icon24x24dir)" + @list='$(icon24x24_DATA)'; test -n "$(icon24x24dir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(icon24x24dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(icon24x24dir)" || exit $$?; \ + done + +uninstall-icon24x24DATA: + @$(NORMAL_UNINSTALL) + @list='$(icon24x24_DATA)'; test -n "$(icon24x24dir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(icon24x24dir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(icon24x24dir)" && rm -f $$files +install-icon32x32DATA: $(icon32x32_DATA) + @$(NORMAL_INSTALL) + test -z "$(icon32x32dir)" || $(MKDIR_P) "$(DESTDIR)$(icon32x32dir)" + @list='$(icon32x32_DATA)'; test -n "$(icon32x32dir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(icon32x32dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(icon32x32dir)" || exit $$?; \ + done + +uninstall-icon32x32DATA: + @$(NORMAL_UNINSTALL) + @list='$(icon32x32_DATA)'; test -n "$(icon32x32dir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(icon32x32dir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(icon32x32dir)" && rm -f $$files +install-iconscalableDATA: $(iconscalable_DATA) + @$(NORMAL_INSTALL) + test -z "$(iconscalabledir)" || $(MKDIR_P) "$(DESTDIR)$(iconscalabledir)" + @list='$(iconscalable_DATA)'; test -n "$(iconscalabledir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(iconscalabledir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(iconscalabledir)" || exit $$?; \ + done + +uninstall-iconscalableDATA: + @$(NORMAL_UNINSTALL) + @list='$(iconscalable_DATA)'; test -n "$(iconscalabledir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(iconscalabledir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(iconscalabledir)" && rm -f $$files +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(desktopdir)" "$(DESTDIR)$(icon16x16dir)" "$(DESTDIR)$(icon24x24dir)" "$(DESTDIR)$(icon32x32dir)" "$(DESTDIR)$(iconscalabledir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-desktopDATA install-icon16x16DATA \ + install-icon24x24DATA install-icon32x32DATA \ + install-iconscalableDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-desktopDATA uninstall-icon16x16DATA \ + uninstall-icon24x24DATA uninstall-icon32x32DATA \ + uninstall-iconscalableDATA + +.MAKE: install-am install-data-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-data-hook install-desktopDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-icon16x16DATA install-icon24x24DATA \ + install-icon32x32DATA install-iconscalableDATA install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-desktopDATA \ + uninstall-icon16x16DATA uninstall-icon24x24DATA \ + uninstall-icon32x32DATA uninstall-iconscalableDATA + + +install-data-hook: + mv -f $(DESTDIR)$(datadir)/icons/hicolor/16x16/apps/snes9x_16x16.png \ + $(DESTDIR)$(datadir)/icons/hicolor/16x16/apps/snes9x.png + mv -f $(DESTDIR)$(datadir)/icons/hicolor/24x24/apps/snes9x_24x24.png \ + $(DESTDIR)$(datadir)/icons/hicolor/24x24/apps/snes9x.png + mv -f $(DESTDIR)$(datadir)/icons/hicolor/32x32/apps/snes9x_32x32.png \ + $(DESTDIR)$(datadir)/icons/hicolor/32x32/apps/snes9x.png + touch -c $(DESTDIR)$(datadir)/icons/hicolor + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gtk/data/snes9x.desktop b/gtk/data/snes9x.desktop new file mode 100644 index 00000000..32927bb9 --- /dev/null +++ b/gtk/data/snes9x.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=Snes9x +Comment=Super NES Emulator +Type=Application +Categories=Game;Emulator; +MimeType=application/x-snes-rom; +Exec=snes9x-gtk %F +TryExec=snes9x-gtk +Icon=snes9x diff --git a/gtk/data/snes9x.svg b/gtk/data/snes9x.svg new file mode 100644 index 00000000..26ff5522 --- /dev/null +++ b/gtk/data/snes9x.svg @@ -0,0 +1,587 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gtk/data/snes9x_16x16.png b/gtk/data/snes9x_16x16.png new file mode 100644 index 00000000..a8e85ac0 Binary files /dev/null and b/gtk/data/snes9x_16x16.png differ diff --git a/gtk/data/snes9x_24x24.png b/gtk/data/snes9x_24x24.png new file mode 100644 index 00000000..3d938f0e Binary files /dev/null and b/gtk/data/snes9x_24x24.png differ diff --git a/gtk/data/snes9x_32x32.png b/gtk/data/snes9x_32x32.png new file mode 100644 index 00000000..e5c75b01 Binary files /dev/null and b/gtk/data/snes9x_32x32.png differ diff --git a/gtk/depcomp b/gtk/depcomp new file mode 100644 index 00000000..df8eea7e --- /dev/null +++ b/gtk/depcomp @@ -0,0 +1,630 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free +# Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u="sed s,\\\\\\\\,/,g" + depmode=msvisualcpp +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add `dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/gtk/doc/LICENSE b/gtk/doc/LICENSE new file mode 100644 index 00000000..b94d3de2 --- /dev/null +++ b/gtk/doc/LICENSE @@ -0,0 +1,7 @@ +The Snes9x GTK port (C) Brandon Wright is provided under +the GNU Lesser General Public License (LGPL) as noted in lgpl.txt, and also +under the Snes9x license as noted in snes9x-license.txt. The snes_ntsc filter +is licensed under the LGPL 2.1 (lgpl.txt). Particular files may also be the +work of other authors, and will note any license information within them. + +Brandon Wright (bearoso) diff --git a/gtk/doc/README b/gtk/doc/README new file mode 100644 index 00000000..ae845450 --- /dev/null +++ b/gtk/doc/README @@ -0,0 +1,49 @@ +Snes9x for GTK/X11 README +------------------------- + + The following contains installation instructions, known issues, and info on + features currently missing from the GTK port of Snes9x. + + +Requirements / Build Notes: +--------------------------- + + The GTK port of Snes9x is a separate codebase from the unix port, and uses a + variety of multiplatform libraries for compatibility. The following + are the required libraries for this port: + + Library Required Version + ------------------------------------ + GTK+ >= 2.10 and dependencies + libxml2 >= 2.0 + One or more of portaudio, PulseAudio, SDL, ALSA, or OSS + + And for joystick support: + + Library Required Version + ------------------------------------ + SDL >= 1.2.12 + + Building requires you run the configure script with the parameter + --with-gtk + and for OpenGL support + --with-gtk --with-opengl + + An appropriate configure command as an example would be: + $ ./configure --prefix=/usr --with-gtk --with-opengl + + Next, issue the "make" command: + $ make + + An standalone executable named "snes9x-gtk" will be created. This may be + run in place. To install the program and errata, use + # make install + as a privileged user. + + +Joystick Support: +----------------- + + Snes9x will autodetect your joystick when run. If you've used any + calibration programs beforehand, you may need to reboot your operating + system to undo the damage they've done. diff --git a/gtk/doc/lgpl.txt b/gtk/doc/lgpl.txt new file mode 100644 index 00000000..5ab7695a --- /dev/null +++ b/gtk/doc/lgpl.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/gtk/install-sh b/gtk/install-sh new file mode 100644 index 00000000..6781b987 --- /dev/null +++ b/gtk/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/gtk/missing b/gtk/missing new file mode 100644 index 00000000..28055d2a --- /dev/null +++ b/gtk/missing @@ -0,0 +1,376 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + tar*) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar*) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case $firstarg in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case $firstarg in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/gtk/mkinstalldirs b/gtk/mkinstalldirs new file mode 100644 index 00000000..d2d5f21b --- /dev/null +++ b/gtk/mkinstalldirs @@ -0,0 +1,111 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." + +# process command line arguments +while test $# -gt 0 ; do + case $1 in + -h | --help | --h*) # -h for help + echo "$usage" 1>&2 + exit 0 + ;; + -m) # -m PERM arg + shift + test $# -eq 0 && { echo "$usage" 1>&2; exit 1; } + dirmode=$1 + shift + ;; + --) # stop option processing + shift + break + ;; + -*) # unknown option + echo "$usage" 1>&2 + exit 1 + ;; + *) # first non-opt arg + break + ;; + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in + 0) exit 0 ;; +esac + +case $dirmode in + '') + if mkdir -p -- . 2>/dev/null; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + fi + ;; + *) + if mkdir -m "$dirmode" -p -- . 2>/dev/null; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + fi + ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case $pathcomp in + -*) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# End: +# mkinstalldirs ends here diff --git a/gtk/po/LINGUAS b/gtk/po/LINGUAS new file mode 100644 index 00000000..08a368c2 --- /dev/null +++ b/gtk/po/LINGUAS @@ -0,0 +1,6 @@ +# please keep this list sorted alphabetically +# +es_VE +fr_FR +pt_BR +sr@latin diff --git a/gtk/po/Makefile.in.in b/gtk/po/Makefile.in.in new file mode 100644 index 00000000..402a25f7 --- /dev/null +++ b/gtk/po/Makefile.in.in @@ -0,0 +1,217 @@ +# Makefile for program source directory in GNU NLS utilities package. +# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper +# Copyright (C) 2004-2008 Rodney Dawes +# +# This file may be copied and used freely without restrictions. It may +# be used in projects which are not available under a GNU Public License, +# but which still want to provide support for the GNU gettext functionality. +# +# - Modified by Owen Taylor to use GETTEXT_PACKAGE +# instead of PACKAGE and to look for po2tbl in ./ not in intl/ +# +# - Modified by jacob berkman to install +# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize +# +# - Modified by Rodney Dawes for use with intltool +# +# We have the following line for use by intltoolize: +# INTLTOOL_MAKEFILE + +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datadir = @datadir@ +datarootdir = @datarootdir@ +libdir = @libdir@ +DATADIRNAME = @DATADIRNAME@ +itlocaledir = $(prefix)/$(DATADIRNAME)/locale +subdir = po +install_sh = @install_sh@ +# Automake >= 1.8 provides @mkdir_p@. +# Until it can be supposed, use the safe fallback: +mkdir_p = $(install_sh) -d + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +GMSGFMT = @GMSGFMT@ +MSGFMT = @MSGFMT@ +XGETTEXT = @XGETTEXT@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist +GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot + +ALL_LINGUAS = @ALL_LINGUAS@ + +PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi) + +USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep \^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep \^$$lang$$`"; then printf "$$lang "; fi; done; fi) + +USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done) + +POFILES=$(shell LINGUAS="$(PO_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done) + +DISTFILES = Makefile.in.in POTFILES.in $(POFILES) +EXTRA_DISTFILES = ChangeLog POTFILES.skip Makevars LINGUAS + +POTFILES = \ +# This comment gets stripped out + +CATALOGS=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.gmo "; done) + +.SUFFIXES: +.SUFFIXES: .po .pox .gmo .mo .msg .cat + +.po.pox: + $(MAKE) $(GETTEXT_PACKAGE).pot + $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox + +.po.mo: + $(MSGFMT) -o $@ $< + +.po.gmo: + file=`echo $* | sed 's,.*/,,'`.gmo \ + && rm -f $$file && $(GMSGFMT) -o $$file $< + +.po.cat: + sed -f ../intl/po2msg.sed < $< > $*.msg \ + && rm -f $@ && gencat $@ $*.msg + + +all: all-@USE_NLS@ + +all-yes: $(CATALOGS) +all-no: + +$(GETTEXT_PACKAGE).pot: $(POTFILES) + $(GENPOT) + +install: install-data +install-data: install-data-@USE_NLS@ +install-data-no: all +install-data-yes: all + linguas="$(USE_LINGUAS)"; \ + for lang in $$linguas; do \ + dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \ + $(mkdir_p) $$dir; \ + if test -r $$lang.gmo; then \ + $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ + echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ + echo "installing $(srcdir)/$$lang.gmo as" \ + "$$dir/$(GETTEXT_PACKAGE).mo"; \ + fi; \ + if test -r $$lang.gmo.m; then \ + $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \ + echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \ + else \ + if test -r $(srcdir)/$$lang.gmo.m ; then \ + $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \ + $$dir/$(GETTEXT_PACKAGE).mo.m; \ + echo "installing $(srcdir)/$$lang.gmo.m as" \ + "$$dir/$(GETTEXT_PACKAGE).mo.m"; \ + else \ + true; \ + fi; \ + fi; \ + done + +# Empty stubs to satisfy archaic automake needs +dvi info tags TAGS ID: + +# Define this as empty until I found a useful application. +install-exec installcheck: + +uninstall: + linguas="$(USE_LINGUAS)"; \ + for lang in $$linguas; do \ + rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ + rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ + done + +check: all $(GETTEXT_PACKAGE).pot + rm -f missing notexist + srcdir=$(srcdir) $(INTLTOOL_UPDATE) -m + if [ -r missing -o -r notexist ]; then \ + exit 1; \ + fi + +mostlyclean: + rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp + rm -f .intltool-merge-cache + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES stamp-it + rm -f *.mo *.msg *.cat *.cat.m *.gmo + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f Makefile.in.in + +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: $(DISTFILES) + dists="$(DISTFILES)"; \ + extra_dists="$(EXTRA_DISTFILES)"; \ + for file in $$extra_dists; do \ + test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \ + done; \ + for file in $$dists; do \ + test -f $$file || file="$(srcdir)/$$file"; \ + ln $$file $(distdir) 2> /dev/null \ + || cp -p $$file $(distdir); \ + done + +update-po: Makefile + $(MAKE) $(GETTEXT_PACKAGE).pot + tmpdir=`pwd`; \ + linguas="$(USE_LINGUAS)"; \ + for lang in $$linguas; do \ + echo "$$lang:"; \ + result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \ + if $$result; then \ + if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ + rm -f $$tmpdir/$$lang.new.po; \ + else \ + if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ + :; \ + else \ + echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ + rm -f $$tmpdir/$$lang.new.po; \ + exit 1; \ + fi; \ + fi; \ + else \ + echo "msgmerge for $$lang.gmo failed!"; \ + rm -f $$tmpdir/$$lang.new.po; \ + fi; \ + done + +Makefile POTFILES: stamp-it + @if test ! -f $@; then \ + rm -f stamp-it; \ + $(MAKE) stamp-it; \ + fi + +stamp-it: Makefile.in.in $(top_builddir)/config.status POTFILES.in + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \ + $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/gtk/po/POTFILES.in b/gtk/po/POTFILES.in new file mode 100644 index 00000000..32e6d8d8 --- /dev/null +++ b/gtk/po/POTFILES.in @@ -0,0 +1,8 @@ +src/gtk_binding.cpp +src/gtk_cheat.cpp +src/gtk_config.cpp +src/gtk_display_driver_opengl.cpp +src/gtk_preferences.cpp +src/gtk_s9x.cpp +src/gtk_s9xwindow.cpp +src/snes9x.glade diff --git a/gtk/po/es_VE.po b/gtk/po/es_VE.po new file mode 100644 index 00000000..6c9f9f6d --- /dev/null +++ b/gtk/po/es_VE.po @@ -0,0 +1,1530 @@ +# Snes9x-gtk Traduccion al español. +# Copyleft (C) 2009 +# Este archivo puede ser modificado siempre y cuando se mantenga al autor original bajo la licensia GPL +# Primer Autor Inukaze , 30/08/2009 (30 de Agosto del 2009). +# +msgid "" +msgstr "" +"Snes9x-gtk: 1.5.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-08-30 13:59-0430\n" +"PO-Revision-Date: 2009-08-30 19:43-0400\n" +"Last-Translator: Inukaze \n" +"Language-Team: Spanish / Español \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Project-Id-Version: \n" + +#: ../src/gtk_binding.cpp:176 +#, c-format +msgid "Unknown" +msgstr "Desconocido" + +#: ../src/gtk_binding.cpp:191 +#, c-format +msgid "Keyboard %s%s%s%s" +msgstr "Teclado %s%s%s%s" + +#: ../src/gtk_binding.cpp:202 +#, c-format +msgid "Axis #%d %s %d%%" +msgstr "Eje #%d %s %d%%" + +#: ../src/gtk_binding.cpp:207 +#, c-format +msgid "Button %d" +msgstr "Boton %d" + +#: ../src/gtk_binding.cpp:209 +#, c-format +msgid "Joystick %d %s" +msgstr "Control %d %s" + +#: ../src/gtk_binding.cpp:214 +#, c-format +msgid "Unset" +msgstr "Sin Asignar" + +#: ../src/gtk_cheat.cpp:84 +msgid "Description" +msgstr "Descripcion" + +#: ../src/gtk_cheat.cpp:92 +msgid "Cheat" +msgstr "Codigo" + +#: ../src/gtk_cheat.cpp:203 +#: ../src/gtk_cheat.cpp:274 +msgid "No description" +msgstr "Sin descripcion" + +#: ../src/gtk_config.cpp:741 +#, c-format +msgid "bad option name: %s\n" +msgstr "Nombre de opcion mala: %s\n" + +#: ../src/gtk_config.cpp:988 +#, c-format +msgid "failure to read snes9x node" +msgstr "Falla al leer nodo de snes9x" + +#: ../src/gtk_config.cpp:1025 +#, c-format +msgid "Couldn't create config directory: %s\n" +msgstr "Imposible crear directorio de configuracion: %s\n" + +#: ../src/gtk_config.cpp:1044 +#, c-format +msgid "Couldn't open config file: %s\n" +msgstr "Imposible abrir archivo de configuracion: %s\n" + +#: ../src/gtk_display_driver_opengl.cpp:503 +#, c-format +msgid "pixel_buffer_object extension not supported.\n" +msgstr "pixel_bufer_object extension no soportada.\n" + +#: ../src/gtk_preferences.cpp:299 +msgid "Rotate all axes to their maximum values, then press OK" +msgstr "Rueda todos los ejes hasta su maximo valor, entonces presiona OK" + +#: ../src/gtk_preferences.cpp:335 +msgid "GTK port version: " +msgstr "Puerto de la version gtk : " + +#: ../src/gtk_preferences.cpp:337 +msgid "English localization by Brandon Wright" +msgstr "Traduccion al español por INUKAZE" + +#: ../src/gtk_preferences.cpp:341 +msgid "" +"\n" +"Features enabled:" +msgstr "" +"\n" +"Opciones Activas:" + +#: ../src/gtk_preferences.cpp:343 +msgid " Only barebones features enabled" +msgstr " Solo caracteristicas barebones activas" + +#: ../src/gtk_preferences.cpp:346 +msgid " OpenGL" +msgstr " OpenGL" + +#: ../src/gtk_preferences.cpp:349 +msgid " XVideo" +msgstr " XVideo" + +#: ../src/gtk_preferences.cpp:352 +msgid " XRandR" +msgstr " XRandR" + +#: ../src/gtk_preferences.cpp:355 +msgid " Joystick" +msgstr " Control" + +#: ../src/gtk_preferences.cpp:358 +msgid " NetPlay" +msgstr " NetPlay" + +#: ../src/gtk_preferences.cpp:360 +msgid "" +"\n" +"\n" +"Snes9x version: " +msgstr "" +"\n" +"\n" +" Version snes9x : " + +#: ../src/gtk_preferences.cpp:730 +msgid "Select Folder" +msgstr "Selecciona carpeta" + +#: ../src/gtk_preferences.cpp:804 +msgid "None - Use software scaler" +msgstr "Nada - Usa ajuste por software" + +#: ../src/gtk_preferences.cpp:808 +msgid "OpenGL - Use 3D graphics hardware" +msgstr "OpenGL - Usa hardware de aceleracion 3D" + +#: ../src/gtk_preferences.cpp:812 +msgid "XVideo - Use hardware video blitter" +msgstr "XVideo - Usa cegador por hardware de video" + +#: ../src/gtk_preferences.cpp:818 +msgid "PortAudio" +msgstr "PortAudio" + +#: ../src/gtk_preferences.cpp:822 +msgid "Open Sound System" +msgstr "Open Sound System" + +#: ../src/gtk_preferences.cpp:826 +msgid "SDL" +msgstr "SDL" + +#: ../src/gtk_s9x.cpp:175 +#, c-format +msgid "Error opening: %s\n" +msgstr "Error abriendo : %s\n" + +#: ../src/gtk_s9xwindow.cpp:721 +msgid "Open SNES Movie" +msgstr "Abrir video snes" + +#: ../src/gtk_s9xwindow.cpp:740 +msgid "New SNES Movie" +msgstr "Nuevo video snes" + +#: ../src/gtk_s9xwindow.cpp:753 +msgid "SNES Movies" +msgstr "Videos snes" + +#: ../src/gtk_s9xwindow.cpp:761 +#: ../src/gtk_s9xwindow.cpp:905 +#: ../src/gtk_s9xwindow.cpp:1050 +#: ../src/gtk_s9xwindow.cpp:1117 +msgid "All Files" +msgstr "Todos los archivos" + +#: ../src/gtk_s9xwindow.cpp:822 +#, c-format +msgid "Couldn't load file '%s'" +msgstr "No puedo cargar el archivo '%s'" + +#: ../src/gtk_s9xwindow.cpp:878 +msgid "Load Saved State" +msgstr "Cargar estado guardado" + +#: ../src/gtk_s9xwindow.cpp:889 +#: ../src/gtk_s9xwindow.cpp:1034 +#: ../src/snes9x.glade.h:202 +msgid "Save States" +msgstr "Estados guardado" + +#: ../src/gtk_s9xwindow.cpp:955 +#, c-format +msgid "The current frame in the movie is %d." +msgstr "El cuadro actual en el video is %d" + +#: ../src/gtk_s9xwindow.cpp:1021 +msgid "Save State" +msgstr "Guardar estado" + +#: ../src/gtk_s9xwindow.cpp:1098 +msgid "Save SPC file..." +msgstr "Guardar archivo SPC" + +#: ../src/gtk_s9xwindow.cpp:1111 +msgid "SPC Files" +msgstr "Archivos SPC" + +#: ../src/gtk_s9xwindow.cpp:1142 +#, c-format +msgid "Couldn't save SPC file '%s'" +msgstr "Imposible salvar archivo SPC '%s'" + +#: ../src/gtk_s9xwindow.cpp:1193 +#, c-format +msgid "%sHosting NetPlay - %s" +msgstr "%sAnfitrion de netplay - %s" + +#: ../src/gtk_s9xwindow.cpp:1194 +#: ../src/gtk_s9xwindow.cpp:1202 +#: ../src/gtk_s9xwindow.cpp:1216 +msgid "Paused - " +msgstr "Pausa -" + +#: ../src/gtk_s9xwindow.cpp:1201 +#, c-format +msgid "%s%s on NetPlay %s:%d - Player %d" +msgstr "%s%s en netplay %s:%d - Jugador %d" + +#: ../src/gtk_s9xwindow.cpp:1238 +#, c-format +msgid "" +"Information for %s\n" +"\n" +"Name: %s\n" +"Speed: %02X/%s\n" +"Map: %s\n" +"Type: %02x\n" +"Contents: %s\n" +"ROM Size: %s\n" +"Calculated Size: %d\n" +"SRAM Size: %s\n" +"Header Checksum: %04X\n" +"Checksum Compliment: %04X\n" +"Actual Checksum: %04X\n" +"Video: %s\n" +"CRC32: %08X\n" +"Revision: %s%s" +msgstr "" +"Information for %s\n" +"\n" +"Nombre : %s\n" +"Velocidad : %02X/%s\n" +"Mapa : %s\n" +"Tipo : %02x\n" +"Contenido : %s\n" +"Tamaño del ROM : %s\n" +"Tamaño Calculado : %d\n" +"Tamaño de SRAM : %s\n" +"ChequeoSuma Cabezera : %04X\n" +"ChequeoSuma Cumplida : %04X\n" +"ChequeoSuma Actual : %04X\n" +"Video : %s\n" +"CRC32 : %08X\n" +"Revision : %s%s" + +#: ../src/gtk_s9xwindow.cpp:1276 +msgid "" +"\n" +"\n" +"This ROM has been modified or damaged" +msgstr "" +"\n" +"\n" +" Este rom ha sido modificado o dañado" + +#: ../src/snes9x.glade.h:2 +#, no-c-format +msgid "" +"0%\n" +"12.5%\n" +"25%\n" +"50%\n" +"100%" +msgstr "" +"0%\n" +"12.5%\n" +"25%\n" +"50%\n" +"100%" + +#: ../src/snes9x.glade.h:7 +msgid "" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8" +msgstr "" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8" + +#: ../src/snes9x.glade.h:16 +#, no-c-format +msgid "" +"12.5%\n" +"25%\n" +"50%\n" +"100%" +msgstr "" +"12.5%\n" +"25%\n" +"50%\n" +"100%" + +#: ../src/snes9x.glade.h:20 +msgid "16 Bit audio output" +msgstr "16 Bits" + +#: ../src/snes9x.glade.h:21 +msgid "" +"16-bit (GL_BGRA)\n" +"24-bit (GL_RGB)\n" +"32-bit (GL_BGRA)" +msgstr "" +"16bit (GL_BGRA)\n" +"24-bit (GL_RGB)\n" +"32-bit (GL_BGRA)" + +#: ../src/snes9x.glade.h:24 +msgid "1x" +msgstr "1x" + +#: ../src/snes9x.glade.h:25 +msgid "2x" +msgstr "2x" + +#: ../src/snes9x.glade.h:26 +msgid "3x" +msgstr "3x" + +#: ../src/snes9x.glade.h:27 +msgid "" +"48000 hz\n" +"44100 hz\n" +"32000 hz (SNES Default)\n" +"22050 hz\n" +"16000 hz\n" +"11025 hz\n" +"8000 hz\n" +"0 hz" +msgstr "" +"48000 hz\n" +"44100 hz\n" +"32000 hz (Real del SNES)\n" +"22050 hz\n" +"16000 hz\n" +"11025 hz\n" +"8000 hz\n" +"0 hz" + +#: ../src/snes9x.glade.h:35 +msgid "4x" +msgstr "4x" + +#: ../src/snes9x.glade.h:36 +msgid "5x" +msgstr "5x" + +#: ../src/snes9x.glade.h:37 +msgid "" +"8:7 Square pixels\n" +"4:3 SNES correct aspect" +msgstr "" +"8:7 PĂ­xeles cuadrados\n" +"4:3 Correccion de aspecto" + +#: ../src/snes9x.glade.h:39 +msgid "Accuracy" +msgstr "Presicion" + +#: ../src/snes9x.glade.h:40 +msgid "Basic Settings" +msgstr "Configuracion basica" + +#: ../src/snes9x.glade.h:41 +msgid "Calibration" +msgstr "Calibracion" + +#: ../src/snes9x.glade.h:42 +msgid "Game Data" +msgstr "Datos del juego" + +#: ../src/snes9x.glade.h:43 +msgid "Hardware Acceleration" +msgstr "Aceleracion hardware" + +#: ../src/snes9x.glade.h:44 +msgid "Image Adjustments" +msgstr "Ajustes de imagen" + +#: ../src/snes9x.glade.h:45 +msgid "Joypad:" +msgstr "Control : " + +#: ../src/snes9x.glade.h:46 +msgid "Joystick Axis Threshold" +msgstr " Eje umbral del control " + +#: ../src/snes9x.glade.h:47 +msgid "NTSC Filter" +msgstr " Filtro NTSC " + +#: ../src/snes9x.glade.h:48 +msgid "Quick load state" +msgstr " Cargar estado " + +#: ../src/snes9x.glade.h:49 +msgid "Quick save state" +msgstr " Guardar estado " + +#: ../src/snes9x.glade.h:50 +msgid "ROM Image" +msgstr " ROM " + +#: ../src/snes9x.glade.h:51 +msgid "Scanline Filter" +msgstr " Filtro Scanline " + +#: ../src/snes9x.glade.h:52 +msgid "Screensaver" +msgstr " Protector de Pantalla " + +#: ../src/snes9x.glade.h:53 +msgid "Server" +msgstr " Servidor " + +#: ../src/snes9x.glade.h:54 +msgid "Settings" +msgstr " Configuracion " + +#: ../src/snes9x.glade.h:55 +msgid "Snes9x Emulator Shortcut Keys" +msgstr " Atajos de teclado del emulador snes9x " + +#: ../src/snes9x.glade.h:56 +msgid "Sound Settings" +msgstr " Configuracion del sonido " + +#: ../src/snes9x.glade.h:57 +msgid "Sticky" +msgstr "Pegajoso " + +#: ../src/snes9x.glade.h:58 +msgid "Turbo" +msgstr "Turbo" + +#: ../src/snes9x.glade.h:59 +msgid "Window behavior" +msgstr "Comportamiento de la ventana" + +#: ../src/snes9x.glade.h:60 +msgid "" +"Click an entry and then press the desired keys or joystick button\n" +"Escape: Move to next Shift-Escape: Clear selected" +msgstr "" +"Has clic y entonces designa una tecla o boton del control\n" +"Escape: Pasa al siguiente | Shift-Escape: Limpia al seleccionado " + +#: ../src/snes9x.glade.h:62 +msgid "A" +msgstr "A" + +#: ../src/snes9x.glade.h:63 +msgid "Act as a server" +msgstr "Ser un servidor" + +#: ../src/snes9x.glade.h:64 +msgid "Advance to Frame" +msgstr "Avanza al cuadro" + +#: ../src/snes9x.glade.h:65 +msgid "Allow emulation of SNES echo effects" +msgstr "Permitir la emulacion del eco del snes" + +#: ../src/snes9x.glade.h:66 +msgid "Allow non-power-of-two textures" +msgstr "Permitir texturas non-power-of-two" + +#: ../src/snes9x.glade.h:67 +msgid "Allow opposing dpad directions" +msgstr "Permitir direcciones opuestas en el control" + +#: ../src/snes9x.glade.h:68 +msgid "Allows games to use transparency effects. Recommended for correct graphics" +msgstr "Permitir efectos de transparencia en los juegos. Recomendado para corregir graficos" + +#: ../src/snes9x.glade.h:69 +msgid "Allows scaling and filtering to use multiple processors" +msgstr "Permitir el uso de multiples procesadores para ajuste y filtrado" + +#: ../src/snes9x.glade.h:70 +msgid "Apply scaling filter:" +msgstr "Usar filtro : " + +#: ../src/snes9x.glade.h:71 +msgid "Artifacts" +msgstr "Artefactos" + +#: ../src/snes9x.glade.h:72 +msgid "Ask server to pause when" +msgstr "Preguntar cuando pausar" + +#: ../src/snes9x.glade.h:73 +msgid "" +"Automatic\n" +"0\n" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8\n" +"9" +msgstr "" +"Automatico\n" +"0\n" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8\n" +"9" + +#: ../src/snes9x.glade.h:84 +msgid "Automatically save the game's SRAM at this interval. Setting this to 0 will only save when quitting or changing ROMs" +msgstr "Guardar automaticamente la SRAM en este intervalo. Colocar en 0 guardara solo cuando se cambie el ROM o finalize" + +#: ../src/snes9x.glade.h:85 +msgid "B" +msgstr "B" + +#: ../src/snes9x.glade.h:86 +msgid "BG layering hack" +msgstr "Hack de capas BG" + +#: ../src/snes9x.glade.h:87 +msgid "Begin movie recording" +msgstr "Iniciar grabracion" + +#: ../src/snes9x.glade.h:88 +msgid "Bilinear-filter output" +msgstr "Filtro Bilinear" + +#: ../src/snes9x.glade.h:89 +msgid "Block invalid VRAM access" +msgstr "Bloquear acceso invalido de VRAM" + +#: ../src/snes9x.glade.h:90 +msgid "Brightness:" +msgstr "Brillo : " + +#: ../src/snes9x.glade.h:91 +msgid "Browse..." +msgstr "Explorar..." + +#: ../src/snes9x.glade.h:92 +msgid "Buffer size:" +msgstr "Tamaño del Bufer : " + +#: ../src/snes9x.glade.h:93 +msgid "Buttons" +msgstr "Botones" + +#: ../src/snes9x.glade.h:94 +msgid "Cali_brate" +msgstr "Cali_brar" + +#: ../src/snes9x.glade.h:95 +msgid "Can be faster or slower depending on drivers" +msgstr "Rapido o Lento Depende de los controladores" + +#: ../src/snes9x.glade.h:96 +msgid "Center all axes on all joysticks and press Calibrate." +msgstr "Centra todos los ejes en todos los controles y presiona. calibrar" + +#: ../src/snes9x.glade.h:97 +msgid "Change fullscreen resolution:" +msgstr "Resolucion de pantalla completa : " + +#: ../src/snes9x.glade.h:98 +msgid "Changes the amount a joystick should be tilted to register a button press" +msgstr "Cambia el monto de un control cuando este es presionado para registrar una pulsacion de boton" + +#: ../src/snes9x.glade.h:99 +msgid "Changes the screen resolution when running Snes9x in fullscreen mode" +msgstr "Cambia la resolucion cuando snes9x esta en pantalla completa" + +#: ../src/snes9x.glade.h:100 +msgid "Clear entry" +msgstr "Limpiar Entrada" + +#: ../src/snes9x.glade.h:101 +msgid "Code:" +msgstr "Codigo : " + +#: ../src/snes9x.glade.h:102 +msgid "" +"Composite\n" +"S-Video\n" +"RGB" +msgstr "" +"Compuesto\n" +"S-Video\n" +"RGB" + +#: ../src/snes9x.glade.h:105 +msgid "Connect to another computer" +msgstr "Conectar a otra computadora" + +#: ../src/snes9x.glade.h:106 +msgid "Connect to another computer that is running Snes9x NetPlay as a server" +msgstr "Conectar a otra computadora que este ejecutando snes9x como servidor" + +#: ../src/snes9x.glade.h:107 +msgid "Connect to specified TCP port on remote computer" +msgstr "Conectar al puerto TCP especifico de un PC remoto" + +#: ../src/snes9x.glade.h:108 +msgid "Contrast:" +msgstr "Contraste : " + +#: ../src/snes9x.glade.h:109 +msgid "Controller Ports" +msgstr "Puerto de controles" + +#: ../src/snes9x.glade.h:110 +msgid "Correct Aspect" +msgstr "Correccion de aspecto" + +#: ../src/snes9x.glade.h:111 +msgid "Custom folder:" +msgstr "Carpeta Especificada : " + +#: ../src/snes9x.glade.h:112 +msgid "Decrease frame rate" +msgstr "Disminuir proporcion de cuadro" + +#: ../src/snes9x.glade.h:113 +msgid "Decrease frame time" +msgstr "Disminuir tiempo de cuadro" + +#: ../src/snes9x.glade.h:114 +msgid "Default port:" +msgstr "Puerto estandar : " + +#: ../src/snes9x.glade.h:115 +msgid "Description:" +msgstr "Descripcion : " + +#: ../src/snes9x.glade.h:116 +msgid "Detects frames that are not output by Snes9x in hires, and scales them" +msgstr "Detectar cuadros que no son mostrados en snes9x con hires , forzar para mostrarlos" + +#: ../src/snes9x.glade.h:117 +msgid "Different formats can yield highly different performance" +msgstr "Diferente formatos puedes producir resultados muy diferentes" + +#: ../src/snes9x.glade.h:118 +msgid "Disables output of sound" +msgstr "Desactivar sonido" + +#: ../src/snes9x.glade.h:119 +msgid "Display" +msgstr "Pantalla" + +#: ../src/snes9x.glade.h:120 +msgid "Domain name or internet protocol address of a remote computer" +msgstr "Nombre de dominio o IP del PC Remoto" + +#: ../src/snes9x.glade.h:121 +msgid "Down" +msgstr "Abajo" + +#: ../src/snes9x.glade.h:122 +msgid "Echo effects" +msgstr "Efecto de eco" + +#: ../src/snes9x.glade.h:123 +msgid "Emulation" +msgstr "Emulacion" + +#: ../src/snes9x.glade.h:124 +msgid "Enable HDMA" +msgstr "Activar HDMA" + +#: ../src/snes9x.glade.h:125 +msgid "Enable HDMA. Required feature for compatibility with some games" +msgstr "Activar HDMA. Requerido para compatibilidad con algunos juegos" + +#: ../src/snes9x.glade.h:126 +msgid "Enable hacks that may improve performance, but can cause errors" +msgstr "Activar hacks puede aumentar el rendimiento, pero puede causar errores" + +#: ../src/snes9x.glade.h:127 +msgid "Enable speed hacks" +msgstr "Activar hacks de velocidad" + +#: ../src/snes9x.glade.h:128 +msgid "Enable transparency" +msgstr "Activar transparencia" + +#: ../src/snes9x.glade.h:129 +msgid "Enable turbo" +msgstr "Activar Turbo" + +#: ../src/snes9x.glade.h:130 +msgid "Exact Pixels" +msgstr "Pixeles exactos" + +#: ../src/snes9x.glade.h:131 +msgid "Fast-forward to frame" +msgstr "Avanze-rapido de cuadro" + +#: ../src/snes9x.glade.h:132 +msgid "Files" +msgstr "Archivos" + +#: ../src/snes9x.glade.h:133 +msgid "Force SNES-hires output" +msgstr "Forzar salida de hires" + +#: ../src/snes9x.glade.h:134 +msgid "Force an inverted byte-ordering" +msgstr "Forzar un byte-ordering invertido" + +#: ../src/snes9x.glade.h:135 +msgid "Forces a swapped byte-ordering for cases where the system's endian is used instead of the video card" +msgstr "Forzar intercambio byte-ordering para casos donde el sistema usa endian en lugar de la tarjeta de video" + +#: ../src/snes9x.glade.h:136 +msgid "Frameskip:" +msgstr "Salto de cuadro : " + +#: ../src/snes9x.glade.h:137 +msgid "From _File..." +msgstr "Desde de un _archivo..." + +#: ../src/snes9x.glade.h:138 +msgid "" +"Game Genie\n" +"Pro Action Replay\n" +"Goldfinger" +msgstr "" +"Game genie\n" +"Pro Action replay\n" +"Goldfinger" + +#: ../src/snes9x.glade.h:141 +msgid "Gaussian interpolation" +msgstr "Interpolacion gaussian" + +#: ../src/snes9x.glade.h:142 +msgid "Go to fullscreen mode immediately after opening a ROM" +msgstr "Pantalla completa al Iniciar rom" + +#: ../src/snes9x.glade.h:143 +msgid "Graphics" +msgstr "Graficos" + +#: ../src/snes9x.glade.h:144 +msgid "Hardware reset" +msgstr "Reinicio duro" + +#: ../src/snes9x.glade.h:145 +msgid "Host a game on this computer as Player 1, requiring extra throughput to support multitple users" +msgstr "Anfitrion como jugador 1, requiere suporte para multiples clientes" + +#: ../src/snes9x.glade.h:146 +msgid "Hue:" +msgstr "Matiz:" + +#: ../src/snes9x.glade.h:147 +msgid "Increase frame rate" +msgstr "Aumentar proporcion de cuadro" + +#: ../src/snes9x.glade.h:148 +msgid "Increase frame time" +msgstr "Aumentar tiempo de cuadro" + +#: ../src/snes9x.glade.h:149 +msgid "Interpolates between samples. Smoothes the sound output to match the real SNES" +msgstr "Interpolar entre muestras. Suaviza el sonido para igualar al snes Real" + +#: ../src/snes9x.glade.h:150 +msgid "Joypad" +msgstr "Control" + +#: ../src/snes9x.glade.h:151 +msgid "Joypads" +msgstr "Controles" + +#: ../src/snes9x.glade.h:152 +msgid "Joystick Options" +msgstr "Opciones del control" + +#: ../src/snes9x.glade.h:153 +msgid "L" +msgstr "L" + +#: ../src/snes9x.glade.h:154 +msgid "Left" +msgstr "Izquierda" + +#: ../src/snes9x.glade.h:155 +msgid "Let left and right or up and down be pressed at the same time" +msgstr "Permitir que Izquierda y Derecha o Arriba y Abajo puedan ser pulsados al mismo tiempo" + +#: ../src/snes9x.glade.h:156 +msgid "Load Movie" +msgstr "Cargar video" + +#: ../src/snes9x.glade.h:157 +msgid "Load _Movie..." +msgstr "Cargar _video..." + +#: ../src/snes9x.glade.h:158 +msgid "Maintain aspect-ratio:" +msgstr "Mantener relacion de aspecto :" + +#: ../src/snes9x.glade.h:159 +msgid "Misc" +msgstr "Varios" + +#: ../src/snes9x.glade.h:160 +msgid "Mouse" +msgstr "Raton" + +#: ../src/snes9x.glade.h:161 +msgid "Multitap" +msgstr "Tap multiple" + +#: ../src/snes9x.glade.h:162 +msgid "Mute sound output" +msgstr "Silenciar sonido" + +#: ../src/snes9x.glade.h:163 +msgid "Name or IP address:" +msgstr "Nombre o direccion IP : " + +#: ../src/snes9x.glade.h:164 +msgid "" +"None\n" +"SuperEagle\n" +"2xSaI\n" +"Super2xSaI\n" +"hq2x\n" +"hq3x\n" +"hq4x\n" +"EPX\n" +"Blargg's NTSC\n" +"Scanlines" +msgstr "" +"None\n" +"SuperEagle\n" +"2xSaI\n" +"Super2xSaI\n" +"hq2x\n" +"hq3x\n" +"hq4x\n" +"EPX\n" +"Blargg's NTSC\n" +"Scanlines" + +#: ../src/snes9x.glade.h:174 +msgid "Open ROM" +msgstr "Abrir ROM" + +#: ../src/snes9x.glade.h:175 +msgid "Open Recent" +msgstr "Abrir Reciente" + +#: ../src/snes9x.glade.h:176 +msgid "Open a ROM to use with NetPlay" +msgstr "Abrir ROM con netplay" + +#: ../src/snes9x.glade.h:177 +msgid "Open with _NetPlay..." +msgstr "Abrir con _netplay..." + +#: ../src/snes9x.glade.h:178 +msgid "Output two channels, left and right" +msgstr "Salida de 2 canales, zurdo y diestro" + +#: ../src/snes9x.glade.h:179 +msgid "Outputs at 16 bits per sample instead of 8 bits. More accurate sound" +msgstr "Salida a 16 bits por muestra en lugar de 8 bits. Precisa mejor el sonido" + +#: ../src/snes9x.glade.h:180 +msgid "Pause" +msgstr "Pausa" + +#: ../src/snes9x.glade.h:181 +msgid "Pause emulation when switching away from Snes9x" +msgstr "Pausar emulacion cuando no estas en snes9x" + +#: ../src/snes9x.glade.h:182 +msgid "Pixel-buffer format:" +msgstr "Formato de pixer-bufer : " + +#: ../src/snes9x.glade.h:183 +msgid "Playback rate:" +msgstr "Calidad de reproduccion" + +#: ../src/snes9x.glade.h:184 +msgid "Port:" +msgstr "Puerto" + +#: ../src/snes9x.glade.h:185 +msgid "Prevent the screensaver from activating" +msgstr "Desactivar" + +#: ../src/snes9x.glade.h:186 +msgid "Prevents edge artifacts, but can slow performance" +msgstr "Previene artefactos de los bordes, pero puede disminuir el rendimiento" + +#: ../src/snes9x.glade.h:187 +msgid "Quit Snes9x" +msgstr "Salir de snes9x" + +#: ../src/snes9x.glade.h:188 +msgid "R" +msgstr "R" + +#: ../src/snes9x.glade.h:189 +msgid "ROM folder" +msgstr "Carpeta de roms" + +#: ../src/snes9x.glade.h:190 +msgid "R_ecord Movie..." +msgstr "G_rabar video..." + +#: ../src/snes9x.glade.h:191 +msgid "Reset" +msgstr "Reiniciar" + +#: ../src/snes9x.glade.h:192 +msgid "Reset the game when players join instead of transferring potentially unreliable freeze states" +msgstr "Reiniciar el juego cuando los jugadores se unan en vez de enviarlo potencialmente" + +#: ../src/snes9x.glade.h:193 +msgid "Reverse stereo" +msgstr "Invertir estereo" + +#: ../src/snes9x.glade.h:194 +msgid "Right" +msgstr "Derecha" + +#: ../src/snes9x.glade.h:195 +msgid "Run / _Continue" +msgstr "_Continuar" + +#: ../src/snes9x.glade.h:196 +msgid "SNES Port 1" +msgstr "SNES 1" + +#: ../src/snes9x.glade.h:197 +msgid "SNES Port 2" +msgstr "SNES 2" + +#: ../src/snes9x.glade.h:198 +msgid "Saturation:" +msgstr "Saturacion : " + +#: ../src/snes9x.glade.h:199 +msgid "Save SPC" +msgstr "Guardar SPC" + +#: ../src/snes9x.glade.h:200 +msgid "Save SPC..." +msgstr "Guardar SPC..." + +#: ../src/snes9x.glade.h:201 +msgid "Save SRAM:" +msgstr "Guardar SRAM : " + +#: ../src/snes9x.glade.h:203 +msgid "Save data in:" +msgstr "Guardar datos en : " + +#: ../src/snes9x.glade.h:204 +msgid "Scale image to fit window" +msgstr "Aumentar imagen hasta ajustar a la ventana" + +#: ../src/snes9x.glade.h:205 +msgid "Scales the image as large as possible without distortion" +msgstr "Ajusta la imagen lo mas grande posible sin distorciones" + +#: ../src/snes9x.glade.h:206 +msgid "Scales the image so no black bars are present" +msgstr "Ajusta la imagen hasta que los bordes negros no esten" + +#: ../src/snes9x.glade.h:207 +msgid "Scanline intensity:" +msgstr "Intensidad de scanline : " + +#: ../src/snes9x.glade.h:208 +msgid "Screenshot" +msgstr "Captura de pantalla" + +#: ../src/snes9x.glade.h:209 +msgid "Seek to frame" +msgstr "Ir al cuadro" + +#: ../src/snes9x.glade.h:210 +msgid "Select" +msgstr "Select" + +#: ../src/snes9x.glade.h:211 +msgid "Send ROM image to clients" +msgstr "Enviar rom al cliente" + +#: ../src/snes9x.glade.h:212 +msgid "Send the running game image to players instead of requiring them to have their own copies" +msgstr "Enviar el juego actual en lugar de exigir que el cliente lo tenga" + +#: ../src/snes9x.glade.h:213 +msgid "Set new axis bindings at:" +msgstr "Establecer nuevos enlaces de ejes en : " + +#: ../src/snes9x.glade.h:214 +msgid "Sharpness:" +msgstr "Nitidez :" + +#: ../src/snes9x.glade.h:215 +msgid "Shortcuts" +msgstr "Atajos" + +#: ../src/snes9x.glade.h:216 +msgid "Show ROM _Info..." +msgstr "Mostrar _info del rom..." + +#: ../src/snes9x.glade.h:217 +msgid "Show frame rate" +msgstr "Mostrar cuadros por segundo" + +#: ../src/snes9x.glade.h:218 +msgid "Slot 0" +msgstr "0" + +#: ../src/snes9x.glade.h:219 +msgid "Slot 1" +msgstr "1" + +#: ../src/snes9x.glade.h:220 +msgid "Slot 2" +msgstr "2 " + +#: ../src/snes9x.glade.h:221 +msgid "Slot 3" +msgstr "3" + +#: ../src/snes9x.glade.h:222 +msgid "Slot 4" +msgstr "4" + +#: ../src/snes9x.glade.h:223 +msgid "Slot 5" +msgstr "5" + +#: ../src/snes9x.glade.h:224 +msgid "Slot 6" +msgstr "6" + +#: ../src/snes9x.glade.h:225 +msgid "Slot 7" +msgstr "7" + +#: ../src/snes9x.glade.h:226 +msgid "Slot 8" +msgstr "8" + +#: ../src/snes9x.glade.h:227 +msgid "Slot _0" +msgstr "_0" + +#: ../src/snes9x.glade.h:228 +msgid "Slot _1" +msgstr "_1" + +#: ../src/snes9x.glade.h:229 +msgid "Slot _2" +msgstr "_2" + +#: ../src/snes9x.glade.h:230 +msgid "Slot _3" +msgstr "_3" + +#: ../src/snes9x.glade.h:231 +msgid "Slot _4" +msgstr "_4" + +#: ../src/snes9x.glade.h:232 +msgid "Slot _5" +msgstr "_5" + +#: ../src/snes9x.glade.h:233 +msgid "Slot _6" +msgstr "_6" + +#: ../src/snes9x.glade.h:234 +msgid "Slot _7" +msgstr "_7" + +#: ../src/snes9x.glade.h:235 +msgid "Slot _8" +msgstr "_8" + +#: ../src/snes9x.glade.h:236 +msgid "Smoothens (blurs) the image" +msgstr "Suaviza la (borrosa) imagen " + +#: ../src/snes9x.glade.h:237 +msgid "Snes9x" +msgstr "Snes9x" + +#: ../src/snes9x.glade.h:238 +msgid "Snes9x Cheats" +msgstr "Trucos snes9x" + +#: ../src/snes9x.glade.h:239 +msgid "Snes9x NetPlay" +msgstr "Juego en red o internet" + +#: ../src/snes9x.glade.h:240 +msgid "Snes9x Preferences" +msgstr "Configuracion del snes9x" + +#: ../src/snes9x.glade.h:241 +msgid "Snes9x configuration folder" +msgstr "Carpeta de configuracion del snes9x" + +#: ../src/snes9x.glade.h:242 +msgid "Soft _Reset" +msgstr "_Reinicio suave" + +#: ../src/snes9x.glade.h:243 +msgid "Soft reset" +msgstr "Reinicio suave" + +#: ../src/snes9x.glade.h:244 +msgid "Sound" +msgstr "Sonido" + +#: ../src/snes9x.glade.h:245 +msgid "Sound driver:" +msgstr "Controlador de sonido :" + +#: ../src/snes9x.glade.h:246 +msgid "Start" +msgstr "Start" + +#: ../src/snes9x.glade.h:247 +msgid "Stereo" +msgstr "Estereo" + +#: ../src/snes9x.glade.h:248 +msgid "Stop movie recording" +msgstr "Detener grabacion" + +#: ../src/snes9x.glade.h:249 +msgid "Store data in $HOME/.snes9x/sram" +msgstr "Guardar datos en $HOME/.snes9x/sram" + +#: ../src/snes9x.glade.h:250 +msgid "Store data in the same folder as the ROM file used" +msgstr "Guardar datos en la misma carpeta del rom" + +#: ../src/snes9x.glade.h:251 +msgid "Superscope" +msgstr "Superscope" + +#: ../src/snes9x.glade.h:252 +msgid "Swap controllers 1 & 2" +msgstr "Intercambiar controles 1 & 2" + +#: ../src/snes9x.glade.h:253 +msgid "Swap the left and right sound channels" +msgstr "Intercambiar canales de sonido diestro y zurdo" + +#: ../src/snes9x.glade.h:254 +msgid "Swap with:" +msgstr "Intercambiar con : " + +#: ../src/snes9x.glade.h:255 +msgid "Sy_nc Clients" +msgstr "Si_ncronizar clientes" + +#: ../src/snes9x.glade.h:256 +msgid "Sync the image to the vertical retrace to stop tearing" +msgstr "Sincronizar la imagen vertical para detener desgarres" + +#: ../src/snes9x.glade.h:257 +msgid "Sync to vertical blank" +msgstr "Sincronizar al blanco vertical" + +#: ../src/snes9x.glade.h:258 +msgid "Sync using reset" +msgstr "Reiniciar para sincronizar" + +#: ../src/snes9x.glade.h:259 +msgid "TCP port used as a connection point for remote clients" +msgstr "El puerto TCP usado como punto de conexion para clientes remoto" + +#: ../src/snes9x.glade.h:260 +msgid "The ESC key should:" +msgstr "La tecla ESC permitira : " + +#: ../src/snes9x.glade.h:261 +msgid "The current frame in the movie is" +msgstr "El cuadro actual en el video es" + +#: ../src/snes9x.glade.h:262 +msgid "The game chosen will be loaded before connecting. This field can be blank if the server will send the ROM image" +msgstr "El juego seleccionado sera cargado antes de conectarse. Este campo debe dejarse en blanco si el servidor envia el rom" + +#: ../src/snes9x.glade.h:263 +msgid "To _File..." +msgstr "En un _archivo" + +#: ../src/snes9x.glade.h:264 +msgid "Toggle BG layer 0" +msgstr "Alternar capa BG 0" + +#: ../src/snes9x.glade.h:265 +msgid "Toggle BG layer 1" +msgstr "Alternar capa BG 1" + +#: ../src/snes9x.glade.h:266 +msgid "Toggle BG layer 2" +msgstr "Alternar capa BG 2" + +#: ../src/snes9x.glade.h:267 +msgid "Toggle BG layer 3" +msgstr "Alternar capa BG 2" + +#: ../src/snes9x.glade.h:268 +msgid "Toggle all sound channels" +msgstr "Alternar todos los canales de sonido" + +#: ../src/snes9x.glade.h:269 +msgid "Toggle fullscreen" +msgstr "Alternar pantalla completa" + +#: ../src/snes9x.glade.h:270 +msgid "Toggle sound channel 0" +msgstr "Alternar canal de Sonido 0" + +#: ../src/snes9x.glade.h:271 +msgid "Toggle sound channel 1" +msgstr "Alternar canal de Sonido 1" + +#: ../src/snes9x.glade.h:272 +msgid "Toggle sound channel 2" +msgstr "Alternar canal de Sonido 2" + +#: ../src/snes9x.glade.h:273 +msgid "Toggle sound channel 3" +msgstr "Alternar canal de Sonido 3" + +#: ../src/snes9x.glade.h:274 +msgid "Toggle sound channel 4" +msgstr "Alternar canal de Sonido 4" + +#: ../src/snes9x.glade.h:275 +msgid "Toggle sound channel 5" +msgstr "Alternar canal de Sonido 5" + +#: ../src/snes9x.glade.h:276 +msgid "Toggle sound channel 6" +msgstr "Alternar canal de Sonido 6" + +#: ../src/snes9x.glade.h:277 +msgid "Toggle sound channel 7" +msgstr "Alternar canal de Sonido 7" + +#: ../src/snes9x.glade.h:278 +msgid "Toggle sound interpolation" +msgstr "Alternar interpolacion de sonido" + +#: ../src/snes9x.glade.h:279 +msgid "Toggle sprites" +msgstr "Alternar sprites" + +#: ../src/snes9x.glade.h:280 +msgid "" +"Toggle the menu bar\n" +"Exit fullscreen mode\n" +"Quit Snes9x" +msgstr "" +"Alternar barra de menu\n" +"Salir de pantalla completa\n" +"Salir de snes9x" + +#: ../src/snes9x.glade.h:283 +msgid "Toggle turbo" +msgstr "Alternar turbo" + +#: ../src/snes9x.glade.h:284 +msgid "Turbo / Sticky Buttons" +msgstr "Turbo / Botones pegajosos" + +#: ../src/snes9x.glade.h:285 +msgid "Type:" +msgstr "Tipo : " + +#: ../src/snes9x.glade.h:286 +msgid "Up" +msgstr "Arriba" + +#: ../src/snes9x.glade.h:287 +msgid "Use " +msgstr "Usar" + +#: ../src/snes9x.glade.h:288 +msgid "Use SNES extended height. Will probably cause letterboxing" +msgstr "Usar extension de altura SNES. Posiblemente cause bordes negros" + +#: ../src/snes9x.glade.h:289 +msgid "Use fullscreen on ROM open" +msgstr "Usar pantalla completa al abrir un rom" + +#: ../src/snes9x.glade.h:290 +msgid "Use overscanned height" +msgstr "Usar altura overscanned" + +#: ../src/snes9x.glade.h:291 +msgid "Use pixel-buffer objects" +msgstr "Usar objetos del pixel-buffer" + +#: ../src/snes9x.glade.h:292 +msgid "Version Info" +msgstr "Info de version" + +#: ../src/snes9x.glade.h:293 +msgid "Video format:" +msgstr "Formato de video : " + +#: ../src/snes9x.glade.h:294 +msgid "Volume envelope height reading" +msgstr "Envoltura de volumen en lectura de altura" + +#: ../src/snes9x.glade.h:295 +msgid "X" +msgstr "X" + +#: ../src/snes9x.glade.h:296 +msgid "Y" +msgstr "Y" + +#: ../src/snes9x.glade.h:297 +msgid "_1x" +msgstr "_1x" + +#: ../src/snes9x.glade.h:298 +msgid "_2x" +msgstr "_2x" + +#: ../src/snes9x.glade.h:299 +msgid "_3x" +msgstr "_3x" + +#: ../src/snes9x.glade.h:300 +msgid "_4x" +msgstr "_4x" + +#: ../src/snes9x.glade.h:301 +msgid "_5x" +msgstr "_5x" + +#: ../src/snes9x.glade.h:302 +msgid "_Change Size" +msgstr "_Cambiar tamaño" + +#: ../src/snes9x.glade.h:303 +msgid "_Cheats..." +msgstr "_Trucos..." + +#: ../src/snes9x.glade.h:304 +msgid "_Emulation" +msgstr "_Emulacion" + +#: ../src/snes9x.glade.h:305 +msgid "_File" +msgstr "_Archivo" + +#: ../src/snes9x.glade.h:306 +msgid "_Fullscreen" +msgstr "_Pantall Completa" + +#: ../src/snes9x.glade.h:307 +msgid "_Hide Menu" +msgstr "_Ocultar Menu" + +#: ../src/snes9x.glade.h:308 +msgid "_Jump to Frame..." +msgstr "_Ir al Cuadro..." + +#: ../src/snes9x.glade.h:309 +msgid "_Load State" +msgstr "_Cargar Estado" + +#: ../src/snes9x.glade.h:310 +msgid "_Open ROM..." +msgstr "_Abrir ROM..." + +#: ../src/snes9x.glade.h:311 +msgid "_Options" +msgstr "_Opciones" + +#: ../src/snes9x.glade.h:312 +msgid "_Pause" +msgstr "_Pausa" + +#: ../src/snes9x.glade.h:313 +msgid "_Preferences..." +msgstr "_Configuraciones..." + +#: ../src/snes9x.glade.h:314 +msgid "_Quit" +msgstr "_Salir" + +#: ../src/snes9x.glade.h:315 +msgid "_Reset" +msgstr "_Reiniciar" + +#: ../src/snes9x.glade.h:316 +msgid "_Save State" +msgstr "_Guardar Estado" + +#: ../src/snes9x.glade.h:317 +msgid "_Status Bar" +msgstr "_Barra de estado" + +#: ../src/snes9x.glade.h:318 +msgid "_Stop Recording" +msgstr "_Detener Grabacion" + +#: ../src/snes9x.glade.h:319 +msgid "_Swap" +msgstr "_Intercambiar" + +#: ../src/snes9x.glade.h:320 +msgid "_View" +msgstr "_Ver" + +#: ../src/snes9x.glade.h:321 +msgid "frames behind" +msgstr "cuadros de retraso" + +#: ../src/snes9x.glade.h:322 +msgid "gtk-add" +msgstr "Añadir" + +#: ../src/snes9x.glade.h:323 +msgid "gtk-cancel" +msgstr "Cancelar" + +#: ../src/snes9x.glade.h:324 +msgid "gtk-close" +msgstr "Cerrar" + +#: ../src/snes9x.glade.h:325 +msgid "gtk-connect" +msgstr "Conectar" + +#: ../src/snes9x.glade.h:326 +msgid "gtk-ok" +msgstr "Ok" + +#: ../src/snes9x.glade.h:327 +msgid "gtk-remove" +msgstr "Eliminar" + +#: ../src/snes9x.glade.h:328 +msgid "milliseconds" +msgstr "Milisegundos" + +#: ../src/snes9x.glade.h:329 +msgid "percent" +msgstr "%" + +#: ../src/snes9x.glade.h:330 +msgid "seconds after change" +msgstr "Segundos despues de cambiar" + +#: ../src/snes9x.glade.h:331 +msgid "threads for filtering and scaling" +msgstr "hilos para filtrar y ajustar" + diff --git a/gtk/po/fr_FR.po b/gtk/po/fr_FR.po new file mode 100644 index 00000000..510751c2 --- /dev/null +++ b/gtk/po/fr_FR.po @@ -0,0 +1,1553 @@ +# Snes9x-gtk translation file. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-08-31 19:10+0200\n" +"PO-Revision-Date: 2009-03-14 HO:MI+ZONE\n" +"Last-Translator: tukuyomi \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../src/gtk_binding.cpp:176 +#, c-format +msgid "Unknown" +msgstr "Inconnu" + +#: ../src/gtk_binding.cpp:191 +#, c-format +msgid "Keyboard %s%s%s%s" +msgstr "Clavier %s%s%s%s" + +#: ../src/gtk_binding.cpp:202 +#, c-format +msgid "Axis #%d %s %d%%" +msgstr "Axe #%d %s %d%%" + +#: ../src/gtk_binding.cpp:207 +#, c-format +msgid "Button %d" +msgstr "Bouton %d" + +#: ../src/gtk_binding.cpp:209 +#, c-format +msgid "Joystick %d %s" +msgstr "" + +#: ../src/gtk_binding.cpp:214 +#, c-format +msgid "Unset" +msgstr "Non assignĂ©" + +#: ../src/gtk_cheat.cpp:84 +msgid "Description" +msgstr "" + +#: ../src/gtk_cheat.cpp:92 +msgid "Cheat" +msgstr "" + +#: ../src/gtk_cheat.cpp:203 ../src/gtk_cheat.cpp:274 +msgid "No description" +msgstr "Pas de description" + +#: ../src/gtk_config.cpp:741 +#, c-format +msgid "bad option name: %s\n" +msgstr "option non reconnue: %s\n" + +#: ../src/gtk_config.cpp:988 +#, c-format +msgid "failure to read snes9x node" +msgstr "" + +#: ../src/gtk_config.cpp:1025 +#, c-format +msgid "Couldn't create config directory: %s\n" +msgstr "Impossible de crĂ©er le rĂ©pertoire de configuration: %s\n" + +#: ../src/gtk_config.cpp:1044 +#, c-format +msgid "Couldn't open config file: %s\n" +msgstr "Impossible d'ouvrir le fichier de configuration: %s\n" + +#: ../src/gtk_display_driver_opengl.cpp:503 +#, c-format +msgid "pixel_buffer_object extension not supported.\n" +msgstr "Extension pixel_buffer_object non supportĂ©e.\n" + +#: ../src/gtk_preferences.cpp:299 +msgid "Rotate all axes to their maximum values, then press OK" +msgstr "Pivoter tous les axes Ă  leur maximum, puis presser OK" + +#: ../src/gtk_preferences.cpp:335 +msgid "GTK port version: " +msgstr "Version du port GTK: " + +#: ../src/gtk_preferences.cpp:337 +msgid "English localization by Brandon Wright" +msgstr "RĂ©gionalisation française par tukuyomi" + +#: ../src/gtk_preferences.cpp:341 +msgid "" +"\n" +"Features enabled:" +msgstr "" +"\n" +"Options activĂ©es:" + +#: ../src/gtk_preferences.cpp:343 +msgid " Only barebones features enabled" +msgstr "" + +#: ../src/gtk_preferences.cpp:346 +msgid " OpenGL" +msgstr "" + +#: ../src/gtk_preferences.cpp:349 +msgid " XVideo" +msgstr "" + +#: ../src/gtk_preferences.cpp:352 +msgid " XRandR" +msgstr "" + +#: ../src/gtk_preferences.cpp:355 +msgid " Joystick" +msgstr "" + +#: ../src/gtk_preferences.cpp:358 +msgid " NetPlay" +msgstr " Jeu en rĂ©seau" + +#: ../src/gtk_preferences.cpp:360 +msgid "" +"\n" +"\n" +"Snes9x version: " +msgstr "" +"\n" +"\n" +"Version de Snes9x: " + +#: ../src/gtk_preferences.cpp:730 +msgid "Select Folder" +msgstr "SĂ©lectionner un rĂ©pertoire" + +#: ../src/gtk_preferences.cpp:804 +msgid "None - Use software scaler" +msgstr "Aucun - Utilisation du rendu logiciel" + +#: ../src/gtk_preferences.cpp:808 +msgid "OpenGL - Use 3D graphics hardware" +msgstr "OpenGL - Utilisation de l'accĂ©lĂ©raion matĂ©rielle" + +#: ../src/gtk_preferences.cpp:812 +msgid "XVideo - Use hardware video blitter" +msgstr "XVideo - Utilise la sortie vidĂ©o matĂ©rielle" + +#: ../src/gtk_preferences.cpp:818 +msgid "PortAudio" +msgstr "" + +#: ../src/gtk_preferences.cpp:822 +msgid "Open Sound System" +msgstr "" + +#: ../src/gtk_preferences.cpp:826 +msgid "SDL" +msgstr "" + +#: ../src/gtk_s9x.cpp:175 +#, c-format +msgid "Error opening: %s\n" +msgstr "Erreur Ă  l'ouverture de %s\n" + +#: ../src/gtk_s9xwindow.cpp:721 +msgid "Open SNES Movie" +msgstr "Ouvrir une vidĂ©o SNES" + +#: ../src/gtk_s9xwindow.cpp:740 +msgid "New SNES Movie" +msgstr "Nouvelle vidĂ©o SNES" + +#: ../src/gtk_s9xwindow.cpp:753 +msgid "SNES Movies" +msgstr "VidĂ©os SNES" + +#: ../src/gtk_s9xwindow.cpp:761 ../src/gtk_s9xwindow.cpp:905 +#: ../src/gtk_s9xwindow.cpp:1050 ../src/gtk_s9xwindow.cpp:1117 +msgid "All Files" +msgstr "Tous les fichiers" + +#: ../src/gtk_s9xwindow.cpp:822 +#, c-format +msgid "Couldn't load file '%s'" +msgstr "Impossible de charger le fichier '%s'" + +#: ../src/gtk_s9xwindow.cpp:878 +msgid "Load Saved State" +msgstr "Charger une sauvegarde instantanĂ©e" + +#: ../src/gtk_s9xwindow.cpp:889 ../src/gtk_s9xwindow.cpp:1034 +#: ../src/snes9x.glade.h:202 +msgid "Save States" +msgstr "Sauvegardes instantanĂ©es" + +#: ../src/gtk_s9xwindow.cpp:955 +#, c-format +msgid "The current frame in the movie is %d." +msgstr "L'image actuelle de la vidĂ©o est %d." + +#: ../src/gtk_s9xwindow.cpp:1021 +msgid "Save State" +msgstr "Sauvegarde instantanĂ©e" + +#: ../src/gtk_s9xwindow.cpp:1098 +msgid "Save SPC file..." +msgstr "Sauver le fichier SPC..." + +#: ../src/gtk_s9xwindow.cpp:1111 +msgid "SPC Files" +msgstr "Fichiers SPC" + +#: ../src/gtk_s9xwindow.cpp:1142 +#, c-format +msgid "Couldn't save SPC file '%s'" +msgstr "Impossible de sauver le fichier SPC '%s'" + +#: ../src/gtk_s9xwindow.cpp:1193 +#, c-format +msgid "%sHosting NetPlay - %s" +msgstr "%sHĂ´te du jeu en rĂ©seau -%s" + +#: ../src/gtk_s9xwindow.cpp:1194 ../src/gtk_s9xwindow.cpp:1202 +#: ../src/gtk_s9xwindow.cpp:1216 +msgid "Paused - " +msgstr "Pause - " + +#: ../src/gtk_s9xwindow.cpp:1201 +#, c-format +msgid "%s%s on NetPlay %s:%d - Player %d" +msgstr "%s%s en rĂ©seau %s:%d - Joueur %d" + +#: ../src/gtk_s9xwindow.cpp:1238 +#, c-format +msgid "" +"Information for %s\n" +"\n" +"Name: %s\n" +"Speed: %02X/%s\n" +"Map: %s\n" +"Type: %02x\n" +"Contents: %s\n" +"ROM Size: %s\n" +"Calculated Size: %d\n" +"SRAM Size: %s\n" +"Header Checksum: %04X\n" +"Checksum Compliment: %04X\n" +"Actual Checksum: %04X\n" +"Video: %s\n" +"CRC32: %08X\n" +"Revision: %s%s" +msgstr "" +"Information pour %s\n" +"\n" +"Name: %s\n" +"Speed: %02X/%s\n" +"Map: %s\n" +"Type: %02x\n" +"Contents: %s\n" +"ROM Size: %s\n" +"Calculated Size: %d\n" +"SRAM Size: %s\n" +"Header Checksum: %04X\n" +"Checksum Compliment: %04X\n" +"Actual Checksum: %04X\n" +"Video: %s\n" +"CRC32: %08X\n" +"Revision: %s%s" + +#: ../src/gtk_s9xwindow.cpp:1276 +msgid "" +"\n" +"\n" +"This ROM has been modified or damaged" +msgstr "" +"\n" +"\n" +"Cette image ROM a Ă©tĂ© altĂ©rĂ©e ou endommagĂ©e" + +#: ../src/snes9x.glade.h:2 +#, no-c-format +msgid "" +"0%\n" +"12.5%\n" +"25%\n" +"50%\n" +"100%" +msgstr "" + +#: ../src/snes9x.glade.h:7 +msgid "" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8" +msgstr "" + +#: ../src/snes9x.glade.h:16 +#, no-c-format +msgid "" +"12.5%\n" +"25%\n" +"50%\n" +"100%" +msgstr "" + +#: ../src/snes9x.glade.h:20 +msgid "16 Bit audio output" +msgstr "Sortie audio 16 bits" + +#: ../src/snes9x.glade.h:21 +msgid "" +"16-bit (GL_BGRA)\n" +"24-bit (GL_RGB)\n" +"32-bit (GL_BGRA)" +msgstr "" +"16-bit (GL_BVRA)\n" +"24-bit (GL_RVB)\n" +"32-bit (GL_BVRA)" + +#: ../src/snes9x.glade.h:24 +msgid "1x" +msgstr "" + +#: ../src/snes9x.glade.h:25 +msgid "2x" +msgstr "" + +#: ../src/snes9x.glade.h:26 +msgid "3x" +msgstr "" + +#: ../src/snes9x.glade.h:27 +msgid "" +"48000 hz\n" +"44100 hz\n" +"32000 hz (SNES Default)\n" +"22050 hz\n" +"16000 hz\n" +"11025 hz\n" +"8000 hz\n" +"0 hz" +msgstr "" +"48000 hz\n" +"44100 hz\n" +"32000 hz (UtilisĂ©e par la SNES)\n" +"22050 hz\n" +"16000 hz\n" +"11025 hz\n" +"8000 hz\n" +"0 hz" + +#: ../src/snes9x.glade.h:35 +msgid "4x" +msgstr "" + +#: ../src/snes9x.glade.h:36 +msgid "5x" +msgstr "" + +#: ../src/snes9x.glade.h:37 +msgid "" +"8:7 Square pixels\n" +"4:3 SNES correct aspect" +msgstr "" +"8:7 Pixels carrĂ©s\n" +"4:3 Aspect correct de la SNES" + +#: ../src/snes9x.glade.h:39 +msgid "Accuracy" +msgstr "PrĂ©cision" + +#: ../src/snes9x.glade.h:40 +msgid "Basic Settings" +msgstr "RĂ©glages de base" + +#: ../src/snes9x.glade.h:41 +msgid "Calibration" +msgstr "Étalonnage" + +#: ../src/snes9x.glade.h:42 +msgid "Game Data" +msgstr "DonnĂ©es de Jeu" + +#: ../src/snes9x.glade.h:43 +msgid "Hardware Acceleration" +msgstr "AccĂ©lĂ©ration matĂ©rielle" + +#: ../src/snes9x.glade.h:44 +msgid "Image Adjustments" +msgstr "RĂ©glages de l'image" + +#: ../src/snes9x.glade.h:45 +msgid "Joypad:" +msgstr "Manette:" + +#: ../src/snes9x.glade.h:46 +msgid "Joystick Axis Threshold" +msgstr "Seuil des axes du joystick" + +#: ../src/snes9x.glade.h:47 +msgid "NTSC Filter" +msgstr "Filtre NTSC" + +#: ../src/snes9x.glade.h:48 +msgid "Quick load state" +msgstr "Chargement rapide" + +#: ../src/snes9x.glade.h:49 +msgid "Quick save state" +msgstr "Sauvegarde rapide" + +#: ../src/snes9x.glade.h:50 +msgid "ROM Image" +msgstr "Image ROM" + +#: ../src/snes9x.glade.h:51 +msgid "Scanline Filter" +msgstr "Filtre Scanline" + +#: ../src/snes9x.glade.h:52 +msgid "Screensaver" +msgstr "Écran de veille" + +#: ../src/snes9x.glade.h:53 +msgid "Server" +msgstr "Serveur" + +#: ../src/snes9x.glade.h:54 +msgid "Settings" +msgstr "RĂ©glages" + +#: ../src/snes9x.glade.h:55 +msgid "Snes9x Emulator Shortcut Keys" +msgstr "Raccourcis clavier" + +#: ../src/snes9x.glade.h:56 +msgid "Sound Settings" +msgstr "RĂ©glages audio" + +#: ../src/snes9x.glade.h:57 +msgid "Sticky" +msgstr "" + +#: ../src/snes9x.glade.h:58 +msgid "Turbo" +msgstr "" + +#: ../src/snes9x.glade.h:59 +#, fuzzy +msgid "Window behavior" +msgstr "Comportement de la fenĂªtre" + +#: ../src/snes9x.glade.h:60 +msgid "" +"Click an entry and then press the desired keys or joystick button\n" +"Escape: Move to next Shift-Escape: Clear selected" +msgstr "" +"Cliquer sur une entrĂ©e puis presser une touche ou un bouton\n" +"Échap: Passer au suivant Shift-Échap: Effacer l'entrĂ©e en " +"cours" + +#: ../src/snes9x.glade.h:62 +msgid "A" +msgstr "" + +#: ../src/snes9x.glade.h:63 +msgid "Act as a server" +msgstr "Faire office de serveur" + +#: ../src/snes9x.glade.h:64 +msgid "Advance to Frame" +msgstr "Avancer Ă  l'image" + +#: ../src/snes9x.glade.h:65 +msgid "Allow emulation of SNES echo effects" +msgstr "Émulation des effets d'Ă©cho" + +#: ../src/snes9x.glade.h:66 +msgid "Allow non-power-of-two textures" +msgstr "Autoriser les textures non puissance de 2" + +#: ../src/snes9x.glade.h:67 +msgid "Allow opposing dpad directions" +msgstr "Autoriser Haut/Bas et Gauche/Droite" + +#: ../src/snes9x.glade.h:68 +msgid "" +"Allows games to use transparency effects. Recommended for correct graphics" +msgstr "" +"Effets de transparence dans les jeux. RecommandĂ© pour un affichage correct" + +#: ../src/snes9x.glade.h:69 +msgid "Allows scaling and filtering to use multiple processors" +msgstr "Autoriser les filtres Ă  utiliser plusieurs processeurs" + +#: ../src/snes9x.glade.h:70 +msgid "Apply scaling filter:" +msgstr "Appliquer un filtre" + +#: ../src/snes9x.glade.h:71 +msgid "Artifacts" +msgstr "Artefacts" + +#: ../src/snes9x.glade.h:72 +msgid "Ask server to pause when" +msgstr "Demander au serveur de mettre en pause" + +#: ../src/snes9x.glade.h:73 +msgid "" +"Automatic\n" +"0\n" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8\n" +"9" +msgstr "" +"Automatique\n" +"0\n" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8\n" +"9" + +#: ../src/snes9x.glade.h:84 +msgid "" +"Automatically save the game's SRAM at this interval. Setting this to 0 will " +"only save when quitting or changing ROMs" +msgstr "" +"Sauver automatiquement la SRAM Ă  cet interval. RĂ©gler Ă  0 pour ne sauver " +"qu'en quittant ou en changeant de ROM" + +#: ../src/snes9x.glade.h:85 +msgid "B" +msgstr "" + +#: ../src/snes9x.glade.h:86 +msgid "BG layering hack" +msgstr "" + +#: ../src/snes9x.glade.h:87 +msgid "Begin movie recording" +msgstr "Commencer l'enregistremant d'une vidĂ©o" + +#: ../src/snes9x.glade.h:88 +msgid "Bilinear-filter output" +msgstr "Sortie bi-linĂ©raire" + +#: ../src/snes9x.glade.h:89 +msgid "Block invalid VRAM access" +msgstr "Bloquer les accès VRAM invalides" + +#: ../src/snes9x.glade.h:90 +msgid "Brightness:" +msgstr "Brillance:" + +#: ../src/snes9x.glade.h:91 +msgid "Browse..." +msgstr "Parcourir..." + +#: ../src/snes9x.glade.h:92 +msgid "Buffer size:" +msgstr "Taille du tampon:" + +#: ../src/snes9x.glade.h:93 +msgid "Buttons" +msgstr "Boutons" + +#: ../src/snes9x.glade.h:94 +msgid "Cali_brate" +msgstr "Cali_brer" + +#: ../src/snes9x.glade.h:95 +msgid "Can be faster or slower depending on drivers" +msgstr "Peut Ăªtre plus rapide ou plus lent selon le pilote" + +#: ../src/snes9x.glade.h:96 +msgid "Center all axes on all joysticks and press Calibrate." +msgstr "Centrer tous les axes des joysticks puis presser Calibrer" + +#: ../src/snes9x.glade.h:97 +msgid "Change fullscreen resolution:" +msgstr "Changer la rĂ©solution du plein-Ă©cran:" + +#: ../src/snes9x.glade.h:98 +msgid "" +"Changes the amount a joystick should be tilted to register a button press" +msgstr "Seuil de dĂ©tection des boutons pour les joysticks analogiques" + +#: ../src/snes9x.glade.h:99 +msgid "Changes the screen resolution when running Snes9x in fullscreen mode" +msgstr "Change la rĂ©solution lorsque Snes9x utilise le plein-Ă©cran" + +#: ../src/snes9x.glade.h:100 +msgid "Clear entry" +msgstr "Effacer l'entrĂ©e" + +#: ../src/snes9x.glade.h:101 +msgid "Code:" +msgstr "Code:" + +#: ../src/snes9x.glade.h:102 +msgid "" +"Composite\n" +"S-Video\n" +"RGB" +msgstr "" +"Composite\n" +"S-Video\n" +"RVB" + +#: ../src/snes9x.glade.h:105 +msgid "Connect to another computer" +msgstr "Se connecter Ă  un autre ordinateur" + +#: ../src/snes9x.glade.h:106 +msgid "Connect to another computer that is running Snes9x NetPlay as a server" +msgstr "" +"Se connecter Ă  un autre ordinateur qui hĂ©berge une partie avec Snes9x Netplay" + +#: ../src/snes9x.glade.h:107 +msgid "Connect to specified TCP port on remote computer" +msgstr "Se connecter Ă  un port TCP spĂ©cifique sur l'ordinateur distant" + +#: ../src/snes9x.glade.h:108 +msgid "Contrast:" +msgstr "Contraste:" + +#: ../src/snes9x.glade.h:109 +msgid "Controller Ports" +msgstr "Ports manette" + +#: ../src/snes9x.glade.h:110 +msgid "Correct Aspect" +msgstr "Corriger l'aspect" + +#: ../src/snes9x.glade.h:111 +msgid "Custom folder:" +msgstr "RĂ©pertoire personnalisĂ©:" + +#: ../src/snes9x.glade.h:112 +msgid "Decrease frame rate" +msgstr "Diminuer le saut d'image" + +#: ../src/snes9x.glade.h:113 +msgid "Decrease frame time" +msgstr "Diminuer le temps entre chaque image" + +#: ../src/snes9x.glade.h:114 +msgid "Default port:" +msgstr "Port par dĂ©faut:" + +#: ../src/snes9x.glade.h:115 +msgid "Description:" +msgstr "Description:" + +#: ../src/snes9x.glade.h:116 +msgid "Detects frames that are not output by Snes9x in hires, and scales them" +msgstr "" +"Detecter les images qui ne sont pas affichĂ©es par Snes9x en Hires, et les " +"ajuster" + +#: ../src/snes9x.glade.h:117 +msgid "Different formats can yield highly different performance" +msgstr "Des formats diffĂ©rents peuvent mener Ă  des performances diffĂ©rentes" + +#: ../src/snes9x.glade.h:118 +msgid "Disables output of sound" +msgstr "DĂ©sactiver la sortie audio" + +#: ../src/snes9x.glade.h:119 +msgid "Display" +msgstr "Affichage" + +#: ../src/snes9x.glade.h:120 +msgid "Domain name or internet protocol address of a remote computer" +msgstr "Nom de domaine ou adresse IP de l'ordinateur distant" + +#: ../src/snes9x.glade.h:121 +msgid "Down" +msgstr "Bas" + +#: ../src/snes9x.glade.h:122 +msgid "Echo effects" +msgstr "Effets d'Ă©cho" + +#: ../src/snes9x.glade.h:123 +msgid "Emulation" +msgstr "Emulation" + +#: ../src/snes9x.glade.h:124 +msgid "Enable HDMA" +msgstr "Activer HDMA" + +#: ../src/snes9x.glade.h:125 +msgid "Enable HDMA. Required feature for compatibility with some games" +msgstr "Activer HDMA. Requis pour la compatibilitĂ© avec certains jeux" + +#: ../src/snes9x.glade.h:126 +msgid "Enable hacks that may improve performance, but can cause errors" +msgstr "" +"Activer des hacks amĂ©liorant les performances, mais pouvant causer des " +"erreurs" + +#: ../src/snes9x.glade.h:127 +msgid "Enable speed hacks" +msgstr "Activer des hacks pour plus de rapiditĂ©" + +#: ../src/snes9x.glade.h:128 +msgid "Enable transparency" +msgstr "Activer la transparence" + +#: ../src/snes9x.glade.h:129 +msgid "Enable turbo" +msgstr "Activer le turbo" + +#: ../src/snes9x.glade.h:130 +msgid "Exact Pixels" +msgstr "Pixels carrĂ©s" + +#: ../src/snes9x.glade.h:131 +msgid "Fast-forward to frame" +msgstr "Avance-rapide jusqu'Ă  l'image" + +#: ../src/snes9x.glade.h:132 +msgid "Files" +msgstr "Fichiers" + +#: ../src/snes9x.glade.h:133 +msgid "Force SNES-hires output" +msgstr "Forcer la sortie Hires" + +#: ../src/snes9x.glade.h:134 +msgid "Force an inverted byte-ordering" +msgstr "" + +#: ../src/snes9x.glade.h:135 +msgid "" +"Forces a swapped byte-ordering for cases where the system's endian is used " +"instead of the video card" +msgstr "" + +#: ../src/snes9x.glade.h:136 +msgid "Frameskip:" +msgstr "Saut d'image:" + +#: ../src/snes9x.glade.h:137 +msgid "From _File..." +msgstr "Depuis un _Fichier..." + +#: ../src/snes9x.glade.h:138 +msgid "" +"Game Genie\n" +"Pro Action Replay\n" +"Goldfinger" +msgstr "" + +#: ../src/snes9x.glade.h:141 +msgid "Gaussian interpolation" +msgstr "Interpolation gaussienne" + +#: ../src/snes9x.glade.h:142 +msgid "Go to fullscreen mode immediately after opening a ROM" +msgstr "Passer en plein-Ă©cran après avoir chargĂ© un jeu" + +#: ../src/snes9x.glade.h:143 +msgid "Graphics" +msgstr "Graphiques" + +#: ../src/snes9x.glade.h:144 +msgid "Hardware reset" +msgstr "Reset matĂ©riel" + +#: ../src/snes9x.glade.h:145 +msgid "" +"Host a game on this computer as Player 1, requiring extra throughput to " +"support multitple users" +msgstr "" +"HĂ©berger une partie sur cet ordinateur en temps que 'Joueur 1', requiert un " +"dĂ©bit plus important pour supporter plusieurs utilisateurs" + +#: ../src/snes9x.glade.h:146 +msgid "Hue:" +msgstr "Teinte" + +#: ../src/snes9x.glade.h:147 +msgid "Increase frame rate" +msgstr "Augmenter le saut d'image" + +#: ../src/snes9x.glade.h:148 +msgid "Increase frame time" +msgstr "Augmenter le temps entre chaque image" + +#: ../src/snes9x.glade.h:149 +msgid "" +"Interpolates between samples. Smoothes the sound output to match the real " +"SNES" +msgstr "" +"Interpole entre les samples. Fluidifie la sortie sonore pour correspondre au " +"mieux Ă  la SNES" + +#: ../src/snes9x.glade.h:150 +msgid "Joypad" +msgstr "Manette" + +#: ../src/snes9x.glade.h:151 +msgid "Joypads" +msgstr "Manette" + +#: ../src/snes9x.glade.h:152 +msgid "Joystick Options" +msgstr "Option du joystick" + +#: ../src/snes9x.glade.h:153 +msgid "L" +msgstr "" + +#: ../src/snes9x.glade.h:154 +msgid "Left" +msgstr "Gauche" + +#: ../src/snes9x.glade.h:155 +msgid "Let left and right or up and down be pressed at the same time" +msgstr "Gauche et droite ou haut et bas peuvent Ăªtre pressĂ©s en mĂªme temps" + +#: ../src/snes9x.glade.h:156 +msgid "Load Movie" +msgstr "Charger une vidĂ©o" + +#: ../src/snes9x.glade.h:157 +msgid "Load _Movie..." +msgstr "Charger une vidĂ©o (_M)..." + +#: ../src/snes9x.glade.h:158 +msgid "Maintain aspect-ratio:" +msgstr "Maintenir les proportions de l'image:" + +#: ../src/snes9x.glade.h:159 +msgid "Misc" +msgstr "Divers" + +#: ../src/snes9x.glade.h:160 +msgid "Mouse" +msgstr "Souris" + +#: ../src/snes9x.glade.h:161 +msgid "Multitap" +msgstr "" + +#: ../src/snes9x.glade.h:162 +msgid "Mute sound output" +msgstr "Sourdine" + +#: ../src/snes9x.glade.h:163 +msgid "Name or IP address:" +msgstr "Nom ou adresse IP" + +#: ../src/snes9x.glade.h:164 +msgid "" +"None\n" +"SuperEagle\n" +"2xSaI\n" +"Super2xSaI\n" +"hq2x\n" +"hq3x\n" +"hq4x\n" +"EPX\n" +"Blargg's NTSC\n" +"Scanlines" +msgstr "" +"Aucun\n" +"SuperEagle\n" +"2xSaI\n" +"Super2xSaI\n" +"hq2x\n" +"hq3x\n" +"hq4x\n" +"EPX\n" +"Blargg's NTSC\n" +"Scanlines" + +#: ../src/snes9x.glade.h:174 +msgid "Open ROM" +msgstr "Charger une image ROM" + +#: ../src/snes9x.glade.h:175 +msgid "Open Recent" +msgstr "Jeux rĂ©cents" + +#: ../src/snes9x.glade.h:176 +msgid "Open a ROM to use with NetPlay" +msgstr "Charger une image ROM pour jouer en rĂ©seau" + +#: ../src/snes9x.glade.h:177 +msgid "Open with _NetPlay..." +msgstr "Ouvrir avec le rĂ©seau (_N)..." + +#: ../src/snes9x.glade.h:178 +msgid "Output two channels, left and right" +msgstr "Sortie 2 canaux, gauche et droit" + +#: ../src/snes9x.glade.h:179 +msgid "Outputs at 16 bits per sample instead of 8 bits. More accurate sound" +msgstr "Sortie en 16 bits par sample au lieu de 8. Son plus prĂ©cis" + +#: ../src/snes9x.glade.h:180 +msgid "Pause" +msgstr "" + +#: ../src/snes9x.glade.h:181 +msgid "Pause emulation when switching away from Snes9x" +msgstr "Mettre en pause quand Snes9x n'a plus le focus" + +#: ../src/snes9x.glade.h:182 +msgid "Pixel-buffer format:" +msgstr "Format du pixel-buffer:" + +#: ../src/snes9x.glade.h:183 +msgid "Playback rate:" +msgstr "FrĂ©quence de lecture:" + +#: ../src/snes9x.glade.h:184 +msgid "Port:" +msgstr "Port:" + +#: ../src/snes9x.glade.h:185 +msgid "Prevent the screensaver from activating" +msgstr "DĂ©sactiver l'Ă©cran de veille" + +#: ../src/snes9x.glade.h:186 +msgid "Prevents edge artifacts, but can slow performance" +msgstr "EmpĂªche les artefacts des bords, mais peut ralentir le jeu" + +#: ../src/snes9x.glade.h:187 +msgid "Quit Snes9x" +msgstr "Quitter Snes9x" + +#: ../src/snes9x.glade.h:188 +msgid "R" +msgstr "" + +#: ../src/snes9x.glade.h:189 +msgid "ROM folder" +msgstr "Dossier des images ROM" + +#: ../src/snes9x.glade.h:190 +msgid "R_ecord Movie..." +msgstr "Enr_egistrer une vidĂ©o..." + +#: ../src/snes9x.glade.h:191 +msgid "Reset" +msgstr "" + +#: ../src/snes9x.glade.h:192 +msgid "" +"Reset the game when players join instead of transferring potentially " +"unreliable freeze states" +msgstr "" +"RĂ©initialiser le jeu quand des joueurs se connectent" + +#: ../src/snes9x.glade.h:193 +msgid "Reverse stereo" +msgstr "StĂ©rĂ©o inversĂ©e" + +#: ../src/snes9x.glade.h:194 +msgid "Right" +msgstr "Droite" + +#: ../src/snes9x.glade.h:195 +msgid "Run / _Continue" +msgstr "ExĂ©cuter / _Continuer" + +#: ../src/snes9x.glade.h:196 +msgid "SNES Port 1" +msgstr "Port SNES 1" + +#: ../src/snes9x.glade.h:197 +msgid "SNES Port 2" +msgstr "Port SNES 2" + +#: ../src/snes9x.glade.h:198 +msgid "Saturation:" +msgstr "" + +#: ../src/snes9x.glade.h:199 +msgid "Save SPC" +msgstr "Sauver les donnĂ©es SPC" + +#: ../src/snes9x.glade.h:200 +msgid "Save SPC..." +msgstr "Sauver les donnĂ©es SPC..." + +#: ../src/snes9x.glade.h:201 +msgid "Save SRAM:" +msgstr "Sauver la SRAM:" + +#: ../src/snes9x.glade.h:203 +msgid "Save data in:" +msgstr "Sauver les donnĂ©es dans:" + +#: ../src/snes9x.glade.h:204 +msgid "Scale image to fit window" +msgstr "Ajuster l'image pour s'adapter Ă  la fenĂªtre" + +#: ../src/snes9x.glade.h:205 +msgid "Scales the image as large as possible without distortion" +msgstr "Ajuste l'image au maximum sans distorsion" + +#: ../src/snes9x.glade.h:206 +msgid "Scales the image so no black bars are present" +msgstr "Ajuste l'image afin de supprimer les bandes noires" + +#: ../src/snes9x.glade.h:207 +msgid "Scanline intensity:" +msgstr "IntensitĂ© des scanlines:" + +#: ../src/snes9x.glade.h:208 +msgid "Screenshot" +msgstr "Capture d'Ă©cran" + +#: ../src/snes9x.glade.h:209 +msgid "Seek to frame" +msgstr "Aller Ă  l'image" + +#: ../src/snes9x.glade.h:210 +msgid "Select" +msgstr "" + +#: ../src/snes9x.glade.h:211 +msgid "Send ROM image to clients" +msgstr "Envoyer l'image ROM aux clients" + +#: ../src/snes9x.glade.h:212 +msgid "" +"Send the running game image to players instead of requiring them to have " +"their own copies" +msgstr "" +"Envoyer l'image du jeu en cours aux joueurs plutot que de les obliger Ă  " +"possĂ©der leur propre copie" + +#: ../src/snes9x.glade.h:213 +msgid "Set new axis bindings at:" +msgstr "RĂ©gler les axes Ă :" + +#: ../src/snes9x.glade.h:214 +msgid "Sharpness:" +msgstr "NettetĂ©:" + +#: ../src/snes9x.glade.h:215 +msgid "Shortcuts" +msgstr "Raccourcis" + +#: ../src/snes9x.glade.h:216 +msgid "Show ROM _Info..." +msgstr "Afficher les _Information de l'image ROM..." + +#: ../src/snes9x.glade.h:217 +msgid "Show frame rate" +msgstr "Afficher le taux d'images par seconde" + +#: ../src/snes9x.glade.h:218 +msgid "Slot 0" +msgstr "" + +#: ../src/snes9x.glade.h:219 +msgid "Slot 1" +msgstr "" + +#: ../src/snes9x.glade.h:220 +msgid "Slot 2" +msgstr "" + +#: ../src/snes9x.glade.h:221 +msgid "Slot 3" +msgstr "" + +#: ../src/snes9x.glade.h:222 +msgid "Slot 4" +msgstr "" + +#: ../src/snes9x.glade.h:223 +msgid "Slot 5" +msgstr "" + +#: ../src/snes9x.glade.h:224 +msgid "Slot 6" +msgstr "" + +#: ../src/snes9x.glade.h:225 +msgid "Slot 7" +msgstr "" + +#: ../src/snes9x.glade.h:226 +msgid "Slot 8" +msgstr "" + +#: ../src/snes9x.glade.h:227 +msgid "Slot _0" +msgstr "" + +#: ../src/snes9x.glade.h:228 +msgid "Slot _1" +msgstr "" + +#: ../src/snes9x.glade.h:229 +msgid "Slot _2" +msgstr "" + +#: ../src/snes9x.glade.h:230 +msgid "Slot _3" +msgstr "" + +#: ../src/snes9x.glade.h:231 +msgid "Slot _4" +msgstr "" + +#: ../src/snes9x.glade.h:232 +msgid "Slot _5" +msgstr "" + +#: ../src/snes9x.glade.h:233 +msgid "Slot _6" +msgstr "" + +#: ../src/snes9x.glade.h:234 +msgid "Slot _7" +msgstr "" + +#: ../src/snes9x.glade.h:235 +msgid "Slot _8" +msgstr "" + +#: ../src/snes9x.glade.h:236 +msgid "Smoothens (blurs) the image" +msgstr "Adoucie (floue) l'image" + +#: ../src/snes9x.glade.h:237 +msgid "Snes9x" +msgstr "" + +#: ../src/snes9x.glade.h:238 +msgid "Snes9x Cheats" +msgstr "" + +#: ../src/snes9x.glade.h:239 +msgid "Snes9x NetPlay" +msgstr "Snes9x Jeu en rĂ©seau" + +#: ../src/snes9x.glade.h:240 +msgid "Snes9x Preferences" +msgstr "Snes9x PrĂ©fĂ©rences" + +#: ../src/snes9x.glade.h:241 +msgid "Snes9x configuration folder" +msgstr "RĂ©pertoire de configuration de Snes9x" + +#: ../src/snes9x.glade.h:242 +msgid "Soft _Reset" +msgstr "_Reset logiciel" + +#: ../src/snes9x.glade.h:243 +msgid "Soft reset" +msgstr "Reset logiciel" + +#: ../src/snes9x.glade.h:244 +msgid "Sound" +msgstr "Son" + +#: ../src/snes9x.glade.h:245 +msgid "Sound driver:" +msgstr "Pilote audio" + +#: ../src/snes9x.glade.h:246 +msgid "Start" +msgstr "" + +#: ../src/snes9x.glade.h:247 +msgid "Stereo" +msgstr "StĂ©rĂ©o" + +#: ../src/snes9x.glade.h:248 +msgid "Stop movie recording" +msgstr "Stopper l'enregistrement de la vidĂ©o" + +#: ../src/snes9x.glade.h:249 +msgid "Store data in $HOME/.snes9x/sram" +msgstr "Sauver les donnĂ©es dans $HOME/.snes9x/sram" + +#: ../src/snes9x.glade.h:250 +msgid "Store data in the same folder as the ROM file used" +msgstr "Sauver les donnĂ©es dans le mĂªme rĂ©pertoire que l'image ROM en cours" + +#: ../src/snes9x.glade.h:251 +msgid "Superscope" +msgstr "" + +#: ../src/snes9x.glade.h:252 +msgid "Swap controllers 1 & 2" +msgstr "Inverser les manettes 1 et 2" + +#: ../src/snes9x.glade.h:253 +msgid "Swap the left and right sound channels" +msgstr "Inverser les canaux gauche et droit" + +#: ../src/snes9x.glade.h:254 +msgid "Swap with:" +msgstr "Intervertir avec:" + +#: ../src/snes9x.glade.h:255 +msgid "Sy_nc Clients" +msgstr "Sy_nchroniser les clients" + +#: ../src/snes9x.glade.h:256 +msgid "Sync the image to the vertical retrace to stop tearing" +msgstr "Synchroniser l'image avec le retracement vertical" + +#: ../src/snes9x.glade.h:257 +msgid "Sync to vertical blank" +msgstr "Synchroniser avec le vertical blank" + +#: ../src/snes9x.glade.h:258 +msgid "Sync using reset" +msgstr "Synchroniser en utilisant le Reset" + +#: ../src/snes9x.glade.h:259 +msgid "TCP port used as a connection point for remote clients" +msgstr "Écouter les clients sur ce port TCP" + +#: ../src/snes9x.glade.h:260 +msgid "The ESC key should:" +msgstr "La touche ESC doit:" + +#: ../src/snes9x.glade.h:261 +msgid "The current frame in the movie is" +msgstr "L'image actuelle de la vidĂ©o est" + +#: ../src/snes9x.glade.h:262 +msgid "" +"The game chosen will be loaded before connecting. This field can be blank if " +"the server will send the ROM image" +msgstr "" +"Le jeu choisi sera chargĂ© avant la connection. Ce champ peut rester vide si " +"le serveur envoie l'image ROM" + +#: ../src/snes9x.glade.h:263 +msgid "To _File..." +msgstr "Vers un _Fichier..." + +#: ../src/snes9x.glade.h:264 +msgid "Toggle BG layer 0" +msgstr "Afficher/Masquer le calque BG 0" + +#: ../src/snes9x.glade.h:265 +msgid "Toggle BG layer 1" +msgstr "Afficher/Masquer le calque BG 1" + +#: ../src/snes9x.glade.h:266 +msgid "Toggle BG layer 2" +msgstr "Afficher/Masquer le calque BG 2" + +#: ../src/snes9x.glade.h:267 +msgid "Toggle BG layer 3" +msgstr "Afficher/Masquer le calque BG 3" + +#: ../src/snes9x.glade.h:268 +msgid "Toggle all sound channels" +msgstr "Basculer tous les canaux audio" + +#: ../src/snes9x.glade.h:269 +msgid "Toggle fullscreen" +msgstr "Basculer le plein-Ă©cran" + +#: ../src/snes9x.glade.h:270 +msgid "Toggle sound channel 0" +msgstr "Basculer le canal son 0" + +#: ../src/snes9x.glade.h:271 +msgid "Toggle sound channel 1" +msgstr "Basculer le canal son 1" + +#: ../src/snes9x.glade.h:272 +msgid "Toggle sound channel 2" +msgstr "Basculer le canal son 2" + +#: ../src/snes9x.glade.h:273 +msgid "Toggle sound channel 3" +msgstr "Basculer le canal son 3" + +#: ../src/snes9x.glade.h:274 +msgid "Toggle sound channel 4" +msgstr "Basculer le canal son 4" + +#: ../src/snes9x.glade.h:275 +msgid "Toggle sound channel 5" +msgstr "Basculer le canal son 5" + +#: ../src/snes9x.glade.h:276 +msgid "Toggle sound channel 6" +msgstr "Basculer le canal son 6" + +#: ../src/snes9x.glade.h:277 +msgid "Toggle sound channel 7" +msgstr "Basculer le canal son 7" + +#: ../src/snes9x.glade.h:278 +msgid "Toggle sound interpolation" +msgstr "Basculer l'interpolation du son" + +#: ../src/snes9x.glade.h:279 +msgid "Toggle sprites" +msgstr "Afficher/Masquer les sprites" + +#: ../src/snes9x.glade.h:280 +msgid "" +"Toggle the menu bar\n" +"Exit fullscreen mode\n" +"Quit Snes9x" +msgstr "" +"Afficher/masquer la barre de menu\n" +"Quitter le plein-Ă©cran\n" +"Quitter Snes9x" + +#: ../src/snes9x.glade.h:283 +msgid "Toggle turbo" +msgstr "Basculer le turbo" + +#: ../src/snes9x.glade.h:284 +msgid "Turbo / Sticky Buttons" +msgstr "Boutons Turbo / Sticky" + +#: ../src/snes9x.glade.h:285 +msgid "Type:" +msgstr "" + +#: ../src/snes9x.glade.h:286 +msgid "Up" +msgstr "Haut:" + +#: ../src/snes9x.glade.h:287 +msgid "Use " +msgstr "Utiliser " + +#: ../src/snes9x.glade.h:288 +msgid "Use SNES extended height. Will probably cause letterboxing" +msgstr "" + +#: ../src/snes9x.glade.h:289 +msgid "Use fullscreen on ROM open" +msgstr "Plein-Ă©cran au chargement d'une image ROM" + +#: ../src/snes9x.glade.h:290 +msgid "Use overscanned height" +msgstr "" + +#: ../src/snes9x.glade.h:291 +msgid "Use pixel-buffer objects" +msgstr "" + +#: ../src/snes9x.glade.h:292 +msgid "Version Info" +msgstr "Informations de version" + +#: ../src/snes9x.glade.h:293 +msgid "Video format:" +msgstr "Format vidĂ©o:" + +#: ../src/snes9x.glade.h:294 +msgid "Volume envelope height reading" +msgstr "" + +#: ../src/snes9x.glade.h:295 +msgid "X" +msgstr "" + +#: ../src/snes9x.glade.h:296 +msgid "Y" +msgstr "" + +#: ../src/snes9x.glade.h:297 +msgid "_1x" +msgstr "" + +#: ../src/snes9x.glade.h:298 +msgid "_2x" +msgstr "" + +#: ../src/snes9x.glade.h:299 +msgid "_3x" +msgstr "" + +#: ../src/snes9x.glade.h:300 +msgid "_4x" +msgstr "" + +#: ../src/snes9x.glade.h:301 +msgid "_5x" +msgstr "" + +#: ../src/snes9x.glade.h:302 +msgid "_Change Size" +msgstr "_Changer la taille" + +#: ../src/snes9x.glade.h:303 +msgid "_Cheats..." +msgstr "_Cheats..." + +#: ../src/snes9x.glade.h:304 +msgid "_Emulation" +msgstr "_Emulation" + +#: ../src/snes9x.glade.h:305 +msgid "_File" +msgstr "_Fichier" + +#: ../src/snes9x.glade.h:306 +msgid "_Fullscreen" +msgstr "Plein-Ă©cran (_F)" + +#: ../src/snes9x.glade.h:307 +msgid "_Hide Menu" +msgstr "Cac_Her le menu" + +#: ../src/snes9x.glade.h:308 +msgid "_Jump to Frame..." +msgstr "Aller Ă  l'image (_J)..." + +#: ../src/snes9x.glade.h:309 +msgid "_Load State" +msgstr "Charger une sauvegarde (_L)" + +#: ../src/snes9x.glade.h:310 +msgid "_Open ROM..." +msgstr "_Ouvrir une image ROM..." + +#: ../src/snes9x.glade.h:311 +msgid "_Options" +msgstr "" + +#: ../src/snes9x.glade.h:312 +msgid "_Pause" +msgstr "" + +#: ../src/snes9x.glade.h:313 +msgid "_Preferences..." +msgstr "_PrĂ©fĂ©rences..." + +#: ../src/snes9x.glade.h:314 +msgid "_Quit" +msgstr "_Quitter" + +#: ../src/snes9x.glade.h:315 +msgid "_Reset" +msgstr "_Reset" + +#: ../src/snes9x.glade.h:316 +msgid "_Save State" +msgstr "_Sauvegarde instantanĂ©e" + +#: ../src/snes9x.glade.h:317 +msgid "_Status Bar" +msgstr "Barre de _Statut" + +#: ../src/snes9x.glade.h:318 +msgid "_Stop Recording" +msgstr "_Stopper l'enregistrement" + +#: ../src/snes9x.glade.h:319 +msgid "_Swap" +msgstr "Intervertir (_S)" + +#: ../src/snes9x.glade.h:320 +msgid "_View" +msgstr "Affichage (_V)" + +#: ../src/snes9x.glade.h:321 +msgid "frames behind" +msgstr "images en arrière" + +#: ../src/snes9x.glade.h:322 +msgid "gtk-add" +msgstr "" + +#: ../src/snes9x.glade.h:323 +msgid "gtk-cancel" +msgstr "" + +#: ../src/snes9x.glade.h:324 +msgid "gtk-close" +msgstr "" + +#: ../src/snes9x.glade.h:325 +msgid "gtk-connect" +msgstr "" + +#: ../src/snes9x.glade.h:326 +msgid "gtk-ok" +msgstr "" + +#: ../src/snes9x.glade.h:327 +msgid "gtk-remove" +msgstr "" + +#: ../src/snes9x.glade.h:328 +msgid "milliseconds" +msgstr "millisecondes" + +#: ../src/snes9x.glade.h:329 +msgid "percent" +msgstr "pourcent" + +#: ../src/snes9x.glade.h:330 +msgid "seconds after change" +msgstr "secondes après un changement" + +#: ../src/snes9x.glade.h:331 +msgid "threads for filtering and scaling" +msgstr "threads pour le filtrage et le zoom" + +#~ msgid "Escape Key Behavior" +#~ msgstr "Comportement de la touche Échap" + +#~ msgid "Escape exits fullscreen instead of hiding menus" +#~ msgstr "Échap quitte le plein-Ă©cran au lieu de cacher le menu" + +#~ msgid "Master volume control" +#~ msgstr "ContrĂ´le du volume" + +#~ msgid "Sample decoder:" +#~ msgstr "DĂ©codeur de samples:" + +#~ msgid "SNES Joypads" +#~ msgstr "Manettes SNES" diff --git a/gtk/po/pt_BR.po b/gtk/po/pt_BR.po new file mode 100644 index 00000000..98a1d2bb --- /dev/null +++ b/gtk/po/pt_BR.po @@ -0,0 +1,1548 @@ +# Snes9x-gtk translation file. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# TibĂ©rio VĂ­tor , 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-09-12 18:50-0300\n" +"PO-Revision-Date: 2009-09-12 23:32-0300\n" +"Last-Translator: TibĂ©rio VĂ­tor \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../src/gtk_binding.cpp:176 +#, c-format +msgid "Unknown" +msgstr "Desconhecido" + +#: ../src/gtk_binding.cpp:191 +#, c-format +msgid "Keyboard %s%s%s%s" +msgstr "Tecla %s%s%s%s" + +#: ../src/gtk_binding.cpp:202 +#, c-format +msgid "Axis #%d %s %d%%" +msgstr "Eixo #%d %s %d%%" + +#: ../src/gtk_binding.cpp:207 +#, c-format +msgid "Button %d" +msgstr "BotĂ£o %d" + +#: ../src/gtk_binding.cpp:209 +#, c-format +msgid "Joystick %d %s" +msgstr "Controle %d %s" + +#: ../src/gtk_binding.cpp:214 +#, c-format +msgid "Unset" +msgstr "NĂ£o configurado" + +#: ../src/gtk_cheat.cpp:84 +msgid "Description" +msgstr "DescriĂ§Ă£o" + +#: ../src/gtk_cheat.cpp:92 +msgid "Cheat" +msgstr "Trapaça" + +#: ../src/gtk_cheat.cpp:203 ../src/gtk_cheat.cpp:274 +msgid "No description" +msgstr "Sem descriĂ§Ă£o" + +#: ../src/gtk_config.cpp:741 +#, c-format +msgid "bad option name: %s\n" +msgstr "nome de opĂ§Ă£o desconhecida %s\n" + +#: ../src/gtk_config.cpp:988 +#, c-format +msgid "failure to read snes9x node" +msgstr "A leitura do snes9x falhou!" + +#: ../src/gtk_config.cpp:1025 +#, c-format +msgid "Couldn't create config directory: %s\n" +msgstr "NĂ£o foi possĂ­vel criar o diretĂ³rio de configuraĂ§Ă£o %s\n" + +#: ../src/gtk_config.cpp:1044 +#, c-format +msgid "Couldn't open config file: %s\n" +msgstr "NĂ£o foi possĂ­vel abrir o arquivo de configuraĂ§Ă£o %s\n" + +#: ../src/gtk_display_driver_opengl.cpp:503 +#, c-format +msgid "pixel_buffer_object extension not supported.\n" +msgstr "A extensĂ£o pixel_buffer_object nĂ£o Ă© suportada!\n" + +#: ../src/gtk_preferences.cpp:299 +msgid "Rotate all axes to their maximum values, then press OK" +msgstr "Gire o eixo bem pelas extremidades, depois aperte OK." + +#: ../src/gtk_preferences.cpp:335 +msgid "GTK port version: " +msgstr "VersĂ£o GTK: " + +#: ../src/gtk_preferences.cpp:337 +msgid "English localization by Brandon Wright" +msgstr "LocalizaĂ§Ă£o em portuguĂªs brasileiro por TibĂ©rio VĂ­tor (tvtoon)" + +#: ../src/gtk_preferences.cpp:341 +msgid "" +"\n" +"Features enabled:" +msgstr "" +"\n" +"Opcionais ativados:" + +#: ../src/gtk_preferences.cpp:343 +msgid " Only barebones features enabled" +msgstr "Ativar somente as opções padrões" + +#: ../src/gtk_preferences.cpp:346 +msgid " OpenGL" +msgstr " OpenGL" + +#: ../src/gtk_preferences.cpp:349 +msgid " XVideo" +msgstr " XVideo" + +#: ../src/gtk_preferences.cpp:352 +msgid " XRandR" +msgstr " XRandR" + +#: ../src/gtk_preferences.cpp:355 +msgid " Joystick" +msgstr " Controle" + +#: ../src/gtk_preferences.cpp:358 +msgid " NetPlay" +msgstr " Jogo em Rede" + +#: ../src/gtk_preferences.cpp:360 +msgid "" +"\n" +"\n" +"Snes9x version: " +msgstr "" +"\n" +"\n" +"VersĂ£o do Snes9x: " + +#: ../src/gtk_preferences.cpp:730 +msgid "Select Folder" +msgstr "Escolha um diretĂ³rio" + +#: ../src/gtk_preferences.cpp:804 +msgid "None - Use software scaler" +msgstr "Nenhum - rodar por software" + +#: ../src/gtk_preferences.cpp:808 +msgid "OpenGL - Use 3D graphics hardware" +msgstr "OpenGL - usar aceleraĂ§Ă£o 3D do hardware" + +#: ../src/gtk_preferences.cpp:812 +msgid "XVideo - Use hardware video blitter" +msgstr "XVideo - usar recursos do hardware" + +#: ../src/gtk_preferences.cpp:818 +msgid "PortAudio" +msgstr "PortAudio" + +#: ../src/gtk_preferences.cpp:822 +msgid "Open Sound System" +msgstr "Open Sound System" + +#: ../src/gtk_preferences.cpp:826 +msgid "SDL" +msgstr "SDL" + +#: ../src/gtk_s9x.cpp:175 +#, c-format +msgid "Error opening: %s\n" +msgstr "Erro ao abrir o arquivo %s\n" + +#: ../src/gtk_s9xwindow.cpp:721 +msgid "Open SNES Movie" +msgstr "Abrir um filme de SNES" + +#: ../src/gtk_s9xwindow.cpp:740 +msgid "New SNES Movie" +msgstr "Novo filme de SNES" + +#: ../src/gtk_s9xwindow.cpp:753 +msgid "SNES Movies" +msgstr "Filmes de SNES" + +#: ../src/gtk_s9xwindow.cpp:761 ../src/gtk_s9xwindow.cpp:905 +#: ../src/gtk_s9xwindow.cpp:1050 ../src/gtk_s9xwindow.cpp:1117 +msgid "All Files" +msgstr "Todos os arquivos" + +#: ../src/gtk_s9xwindow.cpp:822 +#, c-format +msgid "Couldn't load file '%s'" +msgstr "NĂ£o foi possĂ­vel carregar o arquivo '%s'" + +#: ../src/gtk_s9xwindow.cpp:878 +msgid "Load Saved State" +msgstr "Carregar estado de memĂ³ria" + +#: ../src/gtk_s9xwindow.cpp:889 ../src/gtk_s9xwindow.cpp:1034 +#: ../src/snes9x.glade.h:202 +msgid "Save States" +msgstr "Estados salvos" + +#: ../src/gtk_s9xwindow.cpp:955 +#, c-format +msgid "The current frame in the movie is %d." +msgstr "O quadro atual do filme Ă© %d." + +#: ../src/gtk_s9xwindow.cpp:1021 +msgid "Save State" +msgstr "Salvar estado" + +#: ../src/gtk_s9xwindow.cpp:1098 +msgid "Save SPC file..." +msgstr "Salvar arquivo SPC..." + +#: ../src/gtk_s9xwindow.cpp:1111 +msgid "SPC Files" +msgstr "Arquivos SPC" + +#: ../src/gtk_s9xwindow.cpp:1142 +#, c-format +msgid "Couldn't save SPC file '%s'" +msgstr "NĂ£o foi possĂ­vel salvar o arquivo SPC '%s'" + +#: ../src/gtk_s9xwindow.cpp:1193 +#, c-format +msgid "%sHosting NetPlay - %s" +msgstr "%sHospedando o jogo em rede -%s" + +#: ../src/gtk_s9xwindow.cpp:1194 ../src/gtk_s9xwindow.cpp:1202 +#: ../src/gtk_s9xwindow.cpp:1216 +msgid "Paused - " +msgstr "Pausado - " + +#: ../src/gtk_s9xwindow.cpp:1201 +#, c-format +msgid "%s%s on NetPlay %s:%d - Player %d" +msgstr "%s%s no jogo em rede %s:%d - Jogador %d" + +#: ../src/gtk_s9xwindow.cpp:1238 +#, c-format +msgid "" +"Information for %s\n" +"\n" +"Name: %s\n" +"Speed: %02X/%s\n" +"Map: %s\n" +"Type: %02x\n" +"Contents: %s\n" +"ROM Size: %s\n" +"Calculated Size: %d\n" +"SRAM Size: %s\n" +"Header Checksum: %04X\n" +"Checksum Compliment: %04X\n" +"Actual Checksum: %04X\n" +"Video: %s\n" +"CRC32: %08X\n" +"Revision: %s%s" +msgstr "" +"Informações sobre %s\n" +"\n" +"Nome interno: %s\n" +"Velocidade: %02X/%s\n" +"Mapeador: %s\n" +"Tipo: %02x\n" +"ConteĂºdo: %s\n" +"Tamanho da ROM: %s\n" +"Tamanho real calculado: %d\n" +"Tamanho da SRAM: %s\n" +"Soma de verificaĂ§Ă£o no cabeçalho: %04X\n" +"Soma de verificaĂ§Ă£o complementar (inversa): %04X\n" +"Soma de verificaĂ§Ă£o real: %04X\n" +"Tipo de vĂ­deo: %s\n" +"CRC32: %08X\n" +"RevisĂ£o: %s%s" + +#: ../src/gtk_s9xwindow.cpp:1276 +msgid "" +"\n" +"\n" +"This ROM has been modified or damaged" +msgstr "" +"\n" +"\n" +"Essa ROM foi alterada ou danificada." + +#: ../src/snes9x.glade.h:2 +#, no-c-format +msgid "" +"0%\n" +"12.5%\n" +"25%\n" +"50%\n" +"100%" +msgstr "" + +#: ../src/snes9x.glade.h:7 +msgid "" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8" +msgstr "" + +#: ../src/snes9x.glade.h:16 +#, no-c-format +msgid "" +"12.5%\n" +"25%\n" +"50%\n" +"100%" +msgstr "" + +#: ../src/snes9x.glade.h:20 +msgid "16 Bit audio output" +msgstr "SaĂ­da de Ă¡udio em 16 bits" + +#: ../src/snes9x.glade.h:21 +msgid "" +"16-bit (GL_BGRA)\n" +"24-bit (GL_RGB)\n" +"32-bit (GL_BGRA)" +msgstr "" +"16-bit (GL_BGRA)\n" +"24-bit (GL_RGB)\n" +"32-bit (GL_BGRA)" + +#: ../src/snes9x.glade.h:24 +msgid "1x" +msgstr "1x" + +#: ../src/snes9x.glade.h:25 +msgid "2x" +msgstr "2x" + +#: ../src/snes9x.glade.h:26 +msgid "3x" +msgstr "3x" + +#: ../src/snes9x.glade.h:27 +msgid "" +"48000 hz\n" +"44100 hz\n" +"32000 hz (SNES Default)\n" +"22050 hz\n" +"16000 hz\n" +"11025 hz\n" +"8000 hz\n" +"0 hz" +msgstr "" +"48000 Hz\n" +"44100 Hz\n" +"32000 Hz (PadrĂ£o do SNES)\n" +"22050 Hz\n" +"16000 Hz\n" +"11025 Hz\n" +"8000 Hz\n" +"0 Hz" + +#: ../src/snes9x.glade.h:35 +msgid "4x" +msgstr "4x" + +#: ../src/snes9x.glade.h:36 +msgid "5x" +msgstr "5x" + +#: ../src/snes9x.glade.h:37 +msgid "" +"8:7 Square pixels\n" +"4:3 SNES correct aspect" +msgstr "" +"8:7 Pontos definidos\n" +"4:3 Aspecto correto do SNES" + +#: ../src/snes9x.glade.h:39 +msgid "Accuracy" +msgstr "PrecisĂ£o" + +#: ../src/snes9x.glade.h:40 +msgid "Basic Settings" +msgstr "Configurações bĂ¡sicas" + +#: ../src/snes9x.glade.h:41 +msgid "Calibration" +msgstr "CalibraĂ§Ă£o" + +#: ../src/snes9x.glade.h:42 +msgid "Game Data" +msgstr "Dados do jogo" + +#: ../src/snes9x.glade.h:43 +msgid "Hardware Acceleration" +msgstr "AceleraĂ§Ă£o de hardware" + +#: ../src/snes9x.glade.h:44 +msgid "Image Adjustments" +msgstr "Ajustes na imagem" + +#: ../src/snes9x.glade.h:45 +msgid "Joypad:" +msgstr "Controle:" + +#: ../src/snes9x.glade.h:46 +msgid "Joystick Axis Threshold" +msgstr "Limites dos eixos do controle" + +#: ../src/snes9x.glade.h:47 +msgid "NTSC Filter" +msgstr "Filtro NTSC" + +#: ../src/snes9x.glade.h:48 +msgid "Quick load state" +msgstr "Carregar estado rapidamente" + +#: ../src/snes9x.glade.h:49 +msgid "Quick save state" +msgstr "Salvar estado rapidamente" + +#: ../src/snes9x.glade.h:50 +msgid "ROM Image" +msgstr "Imagem de ROM" + +#: ../src/snes9x.glade.h:51 +msgid "Scanline Filter" +msgstr "Filtro scanline" + +#: ../src/snes9x.glade.h:52 +msgid "Screensaver" +msgstr "Protetor de tela" + +#: ../src/snes9x.glade.h:53 +msgid "Server" +msgstr "Servidor" + +#: ../src/snes9x.glade.h:54 +msgid "Settings" +msgstr "Opções" + +#: ../src/snes9x.glade.h:55 +msgid "Snes9x Emulator Shortcut Keys" +msgstr "Teclas de atalho" + +#: ../src/snes9x.glade.h:56 +msgid "Sound Settings" +msgstr "Configurações de som" + +#: ../src/snes9x.glade.h:57 +msgid "Sticky" +msgstr "Fixo" + +#: ../src/snes9x.glade.h:58 +msgid "Turbo" +msgstr "Ao pressionar" + +#: ../src/snes9x.glade.h:59 +msgid "Window behavior" +msgstr "Comportamento da janela" + +#: ../src/snes9x.glade.h:60 +msgid "" +"Click an entry and then press the desired keys or joystick button\n" +"Escape: Move to next Shift-Escape: Clear selected" +msgstr "" +"Clique em uma entrada e aperte a tecla ou botĂ£o desejado\n" +"Esc: Vai para a prĂ³xima. Shift+Esc: Limpa a entrada." + +#: ../src/snes9x.glade.h:62 +msgid "A" +msgstr "A" + +#: ../src/snes9x.glade.h:63 +msgid "Act as a server" +msgstr "Ser o servidor" + +#: ../src/snes9x.glade.h:64 +msgid "Advance to Frame" +msgstr "Avançar para o quadro" + +#: ../src/snes9x.glade.h:65 +msgid "Allow emulation of SNES echo effects" +msgstr "Emular os efeitos de eco do SNES." + +#: ../src/snes9x.glade.h:66 +msgid "Allow non-power-of-two textures" +msgstr "Permitir texturas nĂ£o quadradas" + +#: ../src/snes9x.glade.h:67 +msgid "Allow opposing dpad directions" +msgstr "Permitir entradas opostas no direcional" + +#: ../src/snes9x.glade.h:68 +msgid "" +"Allows games to use transparency effects. Recommended for correct graphics" +msgstr "" +"Ligar a transparĂªncia. RecomendĂ¡vel deixar ligado, pois muitos jogos utilizam!" + +#: ../src/snes9x.glade.h:69 +msgid "Allows scaling and filtering to use multiple processors" +msgstr "Permitir que o escalonamento e a filtragem usem mĂºltiplos processadores." + +#: ../src/snes9x.glade.h:70 +msgid "Apply scaling filter:" +msgstr "Aplicar um filtro:" + +#: ../src/snes9x.glade.h:71 +msgid "Artifacts" +msgstr "Artefatos" + +#: ../src/snes9x.glade.h:72 +msgid "Ask server to pause when" +msgstr "Perguntar ao servidor quando deve pausar" + +#: ../src/snes9x.glade.h:73 +msgid "" +"Automatic\n" +"0\n" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8\n" +"9" +msgstr "" +"AutomĂ¡tico\n" +"0\n" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8\n" +"9" + +#: ../src/snes9x.glade.h:84 +msgid "" +"Automatically save the game's SRAM at this interval. Setting this to 0 will " +"only save when quitting or changing ROMs" +msgstr "" +"Salva automaticamente a SRAM nesse intervalo. Colocando 0, o jogo sĂ³ serĂ¡ " +"salvo ao sair do emulador ou trocar de ROM." + +#: ../src/snes9x.glade.h:85 +msgid "B" +msgstr "B" + +#: ../src/snes9x.glade.h:86 +msgid "BG layering hack" +msgstr "Hack nas camadas do fundo" + +#: ../src/snes9x.glade.h:87 +msgid "Begin movie recording" +msgstr "Começar a gravar um filme" + +#: ../src/snes9x.glade.h:88 +msgid "Bilinear-filter output" +msgstr "SaĂ­da em filtro bilinear" + +#: ../src/snes9x.glade.h:89 +msgid "Block invalid VRAM access" +msgstr "Bloquear acesso invĂ¡lido a VRAM" + +#: ../src/snes9x.glade.h:90 +msgid "Brightness:" +msgstr "Brilho:" + +#: ../src/snes9x.glade.h:91 +msgid "Browse..." +msgstr "Navegar..." + +#: ../src/snes9x.glade.h:92 +msgid "Buffer size:" +msgstr "Tamanho do buffer:" + +#: ../src/snes9x.glade.h:93 +msgid "Buttons" +msgstr "Botões" + +#: ../src/snes9x.glade.h:94 +msgid "Cali_brate" +msgstr "Cali_brar" + +#: ../src/snes9x.glade.h:95 +msgid "Can be faster or slower depending on drivers" +msgstr "Pode ser mais rĂ¡pido ou lento dependendo dos drivers" + +#: ../src/snes9x.glade.h:96 +msgid "Center all axes on all joysticks and press Calibrate." +msgstr "Centralize todos os eixos em todos os controles e clique em Calibrar." + +#: ../src/snes9x.glade.h:97 +msgid "Change fullscreen resolution:" +msgstr "Mudar a resoluĂ§Ă£o em tela cheia:" + +#: ../src/snes9x.glade.h:98 +msgid "" +"Changes the amount a joystick should be tilted to register a button press" +msgstr "Muda o valor da pressĂ£o para o controle registrar uma entrada no botĂ£o" + +#: ../src/snes9x.glade.h:99 +msgid "Changes the screen resolution when running Snes9x in fullscreen mode" +msgstr "Muda a resoluĂ§Ă£o da tela quando for rodar em tela cheia." + +#: ../src/snes9x.glade.h:100 +msgid "Clear entry" +msgstr "Limpar entrada" + +#: ../src/snes9x.glade.h:101 +msgid "Code:" +msgstr "CĂ³digo:" + +#: ../src/snes9x.glade.h:102 +msgid "" +"Composite\n" +"S-Video\n" +"RGB" +msgstr "" +"Composto\n" +"S-Video\n" +"RGB" + +#: ../src/snes9x.glade.h:105 +msgid "Connect to another computer" +msgstr "Conectar-se a outro computador" + +#: ../src/snes9x.glade.h:106 +msgid "Connect to another computer that is running Snes9x NetPlay as a server" +msgstr "Conectar-se a um computador que estĂ¡ rodando o Snes9x como servidor" + +#: ../src/snes9x.glade.h:107 +msgid "Connect to specified TCP port on remote computer" +msgstr "Conectar-se a uma porta TCP especĂ­fica de um computador remoto" + +#: ../src/snes9x.glade.h:108 +msgid "Contrast:" +msgstr "Contraste:" + +#: ../src/snes9x.glade.h:109 +msgid "Controller Ports" +msgstr "Entradas de controles" + +#: ../src/snes9x.glade.h:110 +msgid "Correct Aspect" +msgstr "Corrigir o aspecto" + +#: ../src/snes9x.glade.h:111 +msgid "Custom folder:" +msgstr "Modificar diretĂ³rio:" + +#: ../src/snes9x.glade.h:112 +msgid "Decrease frame rate" +msgstr "Diminuir taxa de quadros" + +#: ../src/snes9x.glade.h:113 +msgid "Decrease frame time" +msgstr "Diminuir intervalo entre quadros" + +#: ../src/snes9x.glade.h:114 +msgid "Default port:" +msgstr "Porta padrĂ£o:" + +#: ../src/snes9x.glade.h:115 +msgid "Description:" +msgstr "DescriĂ§Ă£o:" + +#: ../src/snes9x.glade.h:116 +msgid "Detects frames that are not output by Snes9x in hires, and scales them" +msgstr "Detectar e escalonar os quadros que nĂ£o sĂ£o exibidos em alta resoluĂ§Ă£o." + +#: ../src/snes9x.glade.h:117 +msgid "Different formats can yield highly different performance" +msgstr "Formatos diferentes geram perfomances bem diferentes" + +#: ../src/snes9x.glade.h:118 +msgid "Disables output of sound" +msgstr "Desativar saĂ­da de Ă¡udio." + +#: ../src/snes9x.glade.h:119 +msgid "Display" +msgstr "Tela" + +#: ../src/snes9x.glade.h:120 +msgid "Domain name or internet protocol address of a remote computer" +msgstr "Nome do domĂ­nio ou endereço protocolado de um computador remoto" + +#: ../src/snes9x.glade.h:121 +msgid "Down" +msgstr "Baixo" + +#: ../src/snes9x.glade.h:122 +msgid "Echo effects" +msgstr "Efeitos de eco" + +#: ../src/snes9x.glade.h:123 +msgid "Emulation" +msgstr "EmulaĂ§Ă£o" + +#: ../src/snes9x.glade.h:124 +msgid "Enable HDMA" +msgstr "Ativar HDMA" + +#: ../src/snes9x.glade.h:125 +msgid "Enable HDMA. Required feature for compatibility with some games" +msgstr "Ativar HDMA, requerido para compatibilidade com alguns jogos." + +#: ../src/snes9x.glade.h:126 +msgid "Enable hacks that may improve performance, but can cause errors" +msgstr "Ativar hacks que aumentam o desempenho, mas diminuem compatibilidade." + +#: ../src/snes9x.glade.h:127 +msgid "Enable speed hacks" +msgstr "Ativar hacks de velocidade" + +#: ../src/snes9x.glade.h:128 +msgid "Enable transparency" +msgstr "Ativar transparĂªncia" + +#: ../src/snes9x.glade.h:129 +msgid "Enable turbo" +msgstr "Turbo pressionado" + +#: ../src/snes9x.glade.h:130 +msgid "Exact Pixels" +msgstr "Pontos definidos" + +#: ../src/snes9x.glade.h:131 +msgid "Fast-forward to frame" +msgstr "Avançar rapidamente para um quadro" + +#: ../src/snes9x.glade.h:132 +msgid "Files" +msgstr "Arquivos" + +#: ../src/snes9x.glade.h:133 +msgid "Force SNES-hires output" +msgstr "Forçar saĂ­da em alta resoluĂ§Ă£o do SNES" + +#: ../src/snes9x.glade.h:134 +msgid "Force an inverted byte-ordering" +msgstr "Forçar finalizaĂ§Ă£o invertida de bytes" + +#: ../src/snes9x.glade.h:135 +msgid "" +"Forces a swapped byte-ordering for cases where the system's endian is used " +"instead of the video card" +msgstr "Força uma finalizaĂ§Ă£o invertida de bytes nos casos onde a finalizaĂ§Ă£o do" +"sistema Ă© usada ao invĂ©s da placa de vĂ­deo." + +#: ../src/snes9x.glade.h:136 +msgid "Frameskip:" +msgstr "Pulo de quadros:" + +#: ../src/snes9x.glade.h:137 +msgid "From _File..." +msgstr "De _arquivo..." + +#: ../src/snes9x.glade.h:138 +msgid "" +"Game Genie\n" +"Pro Action Replay\n" +"Goldfinger" +msgstr "" + +#: ../src/snes9x.glade.h:141 +msgid "Gaussian interpolation" +msgstr "InterpolaĂ§Ă£o gaussiana" + +#: ../src/snes9x.glade.h:142 +msgid "Go to fullscreen mode immediately after opening a ROM" +msgstr "Ir para tela cheia assim que abrir a ROM." + +#: ../src/snes9x.glade.h:143 +msgid "Graphics" +msgstr "GrĂ¡ficos" + +#: ../src/snes9x.glade.h:144 +msgid "Hardware reset" +msgstr "Reiniciar mĂ¡quina" + +#: ../src/snes9x.glade.h:145 +msgid "" +"Host a game on this computer as Player 1, requiring extra throughput to " +"support multitple users" +msgstr "" +"Hospedar um jogo nesse computador como Jogador 1, requer uma banda larga" +"para suportar mĂºltiplos jogadores." + +#: ../src/snes9x.glade.h:146 +msgid "Hue:" +msgstr "Matiz:" + +#: ../src/snes9x.glade.h:147 +msgid "Increase frame rate" +msgstr "Aumentar a taxa de quadros" + +#: ../src/snes9x.glade.h:148 +msgid "Increase frame time" +msgstr "Aumentar intervalo entre quadros" + +#: ../src/snes9x.glade.h:149 +msgid "" +"Interpolates between samples. Smoothes the sound output to match the real " +"SNES" +msgstr "" +"InterpolaĂ§Ă£o entre amostras. Suaviza a saĂ­da de Ă¡udio para ficar igual ao" +"SNES real." + +#: ../src/snes9x.glade.h:150 +msgid "Joypad" +msgstr "Controle" + +#: ../src/snes9x.glade.h:151 +msgid "Joypads" +msgstr "Controles" + +#: ../src/snes9x.glade.h:152 +msgid "Joystick Options" +msgstr "Opções do controle" + +#: ../src/snes9x.glade.h:153 +msgid "L" +msgstr "L" + +#: ../src/snes9x.glade.h:154 +msgid "Left" +msgstr "Esquerda" + +#: ../src/snes9x.glade.h:155 +msgid "Let left and right or up and down be pressed at the same time" +msgstr "Deixa direita e esquerda ou cima e baixo serem pressionados ao mesmo tempo." + +#: ../src/snes9x.glade.h:156 +msgid "Load Movie" +msgstr "Carregar filme" + +#: ../src/snes9x.glade.h:157 +msgid "Load _Movie..." +msgstr "Carregar _Filme..." + +#: ../src/snes9x.glade.h:158 +msgid "Maintain aspect-ratio:" +msgstr "Manter proporĂ§Ă£o de aspecto:" + +#: ../src/snes9x.glade.h:159 +msgid "Misc" +msgstr "MiscelĂ¢nea" + +#: ../src/snes9x.glade.h:160 +msgid "Mouse" +msgstr "Mouse" + +#: ../src/snes9x.glade.h:161 +msgid "Multitap" +msgstr "Multitap" + +#: ../src/snes9x.glade.h:162 +msgid "Mute sound output" +msgstr "SaĂ­da de Ă¡udio muda" + +#: ../src/snes9x.glade.h:163 +msgid "Name or IP address:" +msgstr "Nome ou endereço de IP:" + +#: ../src/snes9x.glade.h:164 +msgid "" +"None\n" +"SuperEagle\n" +"2xSaI\n" +"Super2xSaI\n" +"hq2x\n" +"hq3x\n" +"hq4x\n" +"EPX\n" +"Blargg's NTSC\n" +"Scanlines" +msgstr "" +"Nenhum\n" +"SuperEagle\n" +"2xSaI\n" +"Super2xSaI\n" +"hq2x\n" +"hq3x\n" +"hq4x\n" +"EPX\n" +"Blargg's NTSC\n" +"Scanlines" + +#: ../src/snes9x.glade.h:174 +msgid "Open ROM" +msgstr "Abrir uma ROM" + +#: ../src/snes9x.glade.h:175 +msgid "Open Recent" +msgstr "ROMs recentes" + +#: ../src/snes9x.glade.h:176 +msgid "Open a ROM to use with NetPlay" +msgstr "Abrir uma ROM para usar com jogo em rede" + +#: ../src/snes9x.glade.h:177 +msgid "Open with _NetPlay..." +msgstr "Abrir com jogo em _rede..." + +#: ../src/snes9x.glade.h:178 +msgid "Output two channels, left and right" +msgstr "SaĂ­da com dois canais, esquerdo e direito." + +#: ../src/snes9x.glade.h:179 +msgid "Outputs at 16 bits per sample instead of 8 bits. More accurate sound" +msgstr "SaĂ­da com 16 bits por amostra ao invĂ©s de 8. PrecisĂ£o maior." + +#: ../src/snes9x.glade.h:180 +msgid "Pause" +msgstr "Pause" + +#: ../src/snes9x.glade.h:181 +msgid "Pause emulation when switching away from Snes9x" +msgstr "Pausar emulaĂ§Ă£o ao desfocalizar a janela do Snes9x" + +#: ../src/snes9x.glade.h:182 +msgid "Pixel-buffer format:" +msgstr "Formato do buffer de pixels:" + +#: ../src/snes9x.glade.h:183 +msgid "Playback rate:" +msgstr "FrequĂªncia de saĂ­da:" + +#: ../src/snes9x.glade.h:184 +msgid "Port:" +msgstr "Porta:" + +#: ../src/snes9x.glade.h:185 +msgid "Prevent the screensaver from activating" +msgstr "Desativar a proteĂ§Ă£o de tela" + +#: ../src/snes9x.glade.h:186 +msgid "Prevents edge artifacts, but can slow performance" +msgstr "Previne sujeira nas bordas, mas pode comprometer o desempenho" + +#: ../src/snes9x.glade.h:187 +msgid "Quit Snes9x" +msgstr "Sair do Snes9x" + +#: ../src/snes9x.glade.h:188 +msgid "R" +msgstr "R" + +#: ../src/snes9x.glade.h:189 +msgid "ROM folder" +msgstr "DiretĂ³rio das ROMs" + +#: ../src/snes9x.glade.h:190 +msgid "R_ecord Movie..." +msgstr "_Gravar filme..." + +#: ../src/snes9x.glade.h:191 +msgid "Reset" +msgstr "Reiniciar" + +#: ../src/snes9x.glade.h:192 +msgid "" +"Reset the game when players join instead of transferring potentially " +"unreliable freeze states" +msgstr "" +"Reinicia o jogo somente quando novos jogadores entrarem, prevenindo" +"estados de memĂ³ria quebrados" + +#: ../src/snes9x.glade.h:193 +msgid "Reverse stereo" +msgstr "EstĂ©reo inverso" + +#: ../src/snes9x.glade.h:194 +msgid "Right" +msgstr "Direita" + +#: ../src/snes9x.glade.h:195 +msgid "Run / _Continue" +msgstr "Executar / _Continuar" + +#: ../src/snes9x.glade.h:196 +msgid "SNES Port 1" +msgstr "Controle 1" + +#: ../src/snes9x.glade.h:197 +msgid "SNES Port 2" +msgstr "Controle 2" + +#: ../src/snes9x.glade.h:198 +msgid "Saturation:" +msgstr "SaturaĂ§Ă£o:" + +#: ../src/snes9x.glade.h:199 +msgid "Save SPC" +msgstr "Salvar SPC" + +#: ../src/snes9x.glade.h:200 +msgid "Save SPC..." +msgstr "Salvar SPC..." + +#: ../src/snes9x.glade.h:201 +msgid "Save SRAM:" +msgstr "Salvar SRAM:" + +#: ../src/snes9x.glade.h:203 +msgid "Save data in:" +msgstr "Salvar dados em:" + +#: ../src/snes9x.glade.h:204 +msgid "Scale image to fit window" +msgstr "Escalonar imagem para o tamanho da janela" + +#: ../src/snes9x.glade.h:205 +msgid "Scales the image as large as possible without distortion" +msgstr "Escalonar a imagem o mais largo possĂ­vel, sem distorções." + +#: ../src/snes9x.glade.h:206 +msgid "Scales the image so no black bars are present" +msgstr "Escalonar a imagem para tirar as bordas negras." + +#: ../src/snes9x.glade.h:207 +msgid "Scanline intensity:" +msgstr "Intensidade das scanlines:" + +#: ../src/snes9x.glade.h:208 +msgid "Screenshot" +msgstr "Captura de tela" + +#: ../src/snes9x.glade.h:209 +msgid "Seek to frame" +msgstr "Ir para um quadro" + +#: ../src/snes9x.glade.h:210 +msgid "Select" +msgstr "Select" + +#: ../src/snes9x.glade.h:211 +msgid "Send ROM image to clients" +msgstr "Enviar imagem de ROM para os clientes" + +#: ../src/snes9x.glade.h:212 +msgid "" +"Send the running game image to players instead of requiring them to have " +"their own copies" +msgstr "" +"Envia a ROM do jogo atual para os jogadores ao invĂ©s de requerer uma cĂ³pia" +"de cada um." + +#: ../src/snes9x.glade.h:213 +msgid "Set new axis bindings at:" +msgstr "Colocar novas posições do eixo em:" + +#: ../src/snes9x.glade.h:214 +msgid "Sharpness:" +msgstr "PrecisĂ£o:" + +#: ../src/snes9x.glade.h:215 +msgid "Shortcuts" +msgstr "Atalhos" + +#: ../src/snes9x.glade.h:216 +msgid "Show ROM _Info..." +msgstr "Mostrar _informações da ROM..." + +#: ../src/snes9x.glade.h:217 +msgid "Show frame rate" +msgstr "Mostrar taxa de quadros" + +#: ../src/snes9x.glade.h:218 +msgid "Slot 0" +msgstr "Unidade 0" + +#: ../src/snes9x.glade.h:219 +msgid "Slot 1" +msgstr "Unidade 1" + +#: ../src/snes9x.glade.h:220 +msgid "Slot 2" +msgstr "Unidade 2" + +#: ../src/snes9x.glade.h:221 +msgid "Slot 3" +msgstr "Unidade 3" + +#: ../src/snes9x.glade.h:222 +msgid "Slot 4" +msgstr "Unidade 4" + +#: ../src/snes9x.glade.h:223 +msgid "Slot 5" +msgstr "Unidade 5" + +#: ../src/snes9x.glade.h:224 +msgid "Slot 6" +msgstr "Unidade 6" + +#: ../src/snes9x.glade.h:225 +msgid "Slot 7" +msgstr "Unidade 7" + +#: ../src/snes9x.glade.h:226 +msgid "Slot 8" +msgstr "Unidade 8" + +#: ../src/snes9x.glade.h:227 +msgid "Slot _0" +msgstr "Unidade _0" + +#: ../src/snes9x.glade.h:228 +msgid "Slot _1" +msgstr "Unidade _1" + +#: ../src/snes9x.glade.h:229 +msgid "Slot _2" +msgstr "Unidade _2" + +#: ../src/snes9x.glade.h:230 +msgid "Slot _3" +msgstr "Unidade _3" + +#: ../src/snes9x.glade.h:231 +msgid "Slot _4" +msgstr "Unidade _4" + +#: ../src/snes9x.glade.h:232 +msgid "Slot _5" +msgstr "Unidade _5" + +#: ../src/snes9x.glade.h:233 +msgid "Slot _6" +msgstr "Unidade _6" + +#: ../src/snes9x.glade.h:234 +msgid "Slot _7" +msgstr "Unidade _7" + +#: ../src/snes9x.glade.h:235 +msgid "Slot _8" +msgstr "Unidade _8" + +#: ../src/snes9x.glade.h:236 +msgid "Smoothens (blurs) the image" +msgstr "Suavizar a imagem" + +#: ../src/snes9x.glade.h:237 +msgid "Snes9x" +msgstr "Snes9x" + +#: ../src/snes9x.glade.h:238 +msgid "Snes9x Cheats" +msgstr "Trapaças do Snes9x" + +#: ../src/snes9x.glade.h:239 +msgid "Snes9x NetPlay" +msgstr "Jogo em rede do Snes9x" + +#: ../src/snes9x.glade.h:240 +msgid "Snes9x Preferences" +msgstr "PreferĂªncias do Snes9x" + +#: ../src/snes9x.glade.h:241 +msgid "Snes9x configuration folder" +msgstr "DiretĂ³rio de configuraĂ§Ă£o do Snes9x" + +#: ../src/snes9x.glade.h:242 +msgid "Soft _Reset" +msgstr "_Reiniciar jogo" + +#: ../src/snes9x.glade.h:243 +msgid "Soft reset" +msgstr "Reiniciar jogo" + +#: ../src/snes9x.glade.h:244 +msgid "Sound" +msgstr "Som" + +#: ../src/snes9x.glade.h:245 +msgid "Sound driver:" +msgstr "Driver de som:" + +#: ../src/snes9x.glade.h:246 +msgid "Start" +msgstr "Start" + +#: ../src/snes9x.glade.h:247 +msgid "Stereo" +msgstr "EstĂ©reo" + +#: ../src/snes9x.glade.h:248 +msgid "Stop movie recording" +msgstr "Parar gravaĂ§Ă£o de filme" + +#: ../src/snes9x.glade.h:249 +msgid "Store data in $HOME/.snes9x/sram" +msgstr "Guardar dados em $HOME/.snes9x/sram" + +#: ../src/snes9x.glade.h:250 +msgid "Store data in the same folder as the ROM file used" +msgstr "Guardar dados no mesmo diretĂ³rio da ROM" + +#: ../src/snes9x.glade.h:251 +msgid "Superscope" +msgstr "Superscope" + +#: ../src/snes9x.glade.h:252 +msgid "Swap controllers 1 & 2" +msgstr "Trocar controles 1 e 2" + +#: ../src/snes9x.glade.h:253 +msgid "Swap the left and right sound channels" +msgstr "Trocar os canais de som direito e esquerdo." + +#: ../src/snes9x.glade.h:254 +msgid "Swap with:" +msgstr "Trocar por:" + +#: ../src/snes9x.glade.h:255 +msgid "Sy_nc Clients" +msgstr "Si_ncronizar clientes" + +#: ../src/snes9x.glade.h:256 +msgid "Sync the image to the vertical retrace to stop tearing" +msgstr "Sincronizar a imagem de acordo com o alinhamento vertical para evitar imagens cortadas" + +#: ../src/snes9x.glade.h:257 +msgid "Sync to vertical blank" +msgstr "SincronizaĂ§Ă£o vertical" + +#: ../src/snes9x.glade.h:258 +msgid "Sync using reset" +msgstr "Sincronizar os reinĂ­cios" + +#: ../src/snes9x.glade.h:259 +msgid "TCP port used as a connection point for remote clients" +msgstr "Porta TCP usada como ponto de conexĂ£o entre clientes" + +#: ../src/snes9x.glade.h:260 +msgid "The ESC key should:" +msgstr "A tecla ESC deve:" + +#: ../src/snes9x.glade.h:261 +msgid "The current frame in the movie is" +msgstr "O quadro atual do filme Ă©" + +#: ../src/snes9x.glade.h:262 +msgid "" +"The game chosen will be loaded before connecting. This field can be blank if " +"the server will send the ROM image" +msgstr "" +"O jogo escolhido serĂ¡ carregado antes de conectar. Esse campo pode ficar em" +"branco se o servidor mandar a imagem da ROM." + +#: ../src/snes9x.glade.h:263 +msgid "To _File..." +msgstr "Para o _arquivo..." + +#: ../src/snes9x.glade.h:264 +msgid "Toggle BG layer 0" +msgstr "Ligar ou desligar a camada BG 0" + +#: ../src/snes9x.glade.h:265 +msgid "Toggle BG layer 1" +msgstr "Ligar ou desligar a camada BG 1" + +#: ../src/snes9x.glade.h:266 +msgid "Toggle BG layer 2" +msgstr "Ligar ou desligar a camada BG 2" + +#: ../src/snes9x.glade.h:267 +msgid "Toggle BG layer 3" +msgstr "Ligar ou desligar a camada BG 3" + +#: ../src/snes9x.glade.h:268 +msgid "Toggle all sound channels" +msgstr "Ligar ou desligar todos os canais de som" + +#: ../src/snes9x.glade.h:269 +msgid "Toggle fullscreen" +msgstr "Ligar ou desligar a tela cheia" + +#: ../src/snes9x.glade.h:270 +msgid "Toggle sound channel 0" +msgstr "Ligar ou desligar o canal de som 0" + +#: ../src/snes9x.glade.h:271 +msgid "Toggle sound channel 1" +msgstr "Ligar ou desligar o canal de som 1" + +#: ../src/snes9x.glade.h:272 +msgid "Toggle sound channel 2" +msgstr "Ligar ou desligar o canal de som 2" + +#: ../src/snes9x.glade.h:273 +msgid "Toggle sound channel 3" +msgstr "Ligar ou desligar o canal de som 3" + +#: ../src/snes9x.glade.h:274 +msgid "Toggle sound channel 4" +msgstr "Ligar ou desligar o canal de som 4" + +#: ../src/snes9x.glade.h:275 +msgid "Toggle sound channel 5" +msgstr "Ligar ou desligar o canal de som 5" + +#: ../src/snes9x.glade.h:276 +msgid "Toggle sound channel 6" +msgstr "Ligar ou desligar o canal de som 6" + +#: ../src/snes9x.glade.h:277 +msgid "Toggle sound channel 7" +msgstr "Ligar ou desligar o canal de som 7" + +#: ../src/snes9x.glade.h:278 +msgid "Toggle sound interpolation" +msgstr "Ligar ou desligar a interpolaĂ§Ă£o sonora" + +#: ../src/snes9x.glade.h:279 +msgid "Toggle sprites" +msgstr "Ligar ou desligar sprites" + +#: ../src/snes9x.glade.h:280 +msgid "" +"Toggle the menu bar\n" +"Exit fullscreen mode\n" +"Quit Snes9x" +msgstr "" +"Ligar ou desligar a barra do menu\n" +"Sair do modo de tela cheia\n" +"Sair do Snes9x" + +#: ../src/snes9x.glade.h:283 +msgid "Toggle turbo" +msgstr "Ligar ou desligar o turbo" + +#: ../src/snes9x.glade.h:284 +msgid "Turbo / Sticky Buttons" +msgstr "Configurar turbo" + +#: ../src/snes9x.glade.h:285 +msgid "Type:" +msgstr "Tipo:" + +#: ../src/snes9x.glade.h:286 +msgid "Up" +msgstr "Cima" + +#: ../src/snes9x.glade.h:287 +msgid "Use " +msgstr "Usar " + +#: ../src/snes9x.glade.h:288 +msgid "Use SNES extended height. Will probably cause letterboxing" +msgstr "Usar a altura extendida do SNES. Pode causar problema nas fontes." + +#: ../src/snes9x.glade.h:289 +msgid "Use fullscreen on ROM open" +msgstr "Usar tela cheia ao abrir a ROM" + +#: ../src/snes9x.glade.h:290 +msgid "Use overscanned height" +msgstr "Usar altura extendida" + +#: ../src/snes9x.glade.h:291 +msgid "Use pixel-buffer objects" +msgstr "Usar objetos do buffer de pixels" + +#: ../src/snes9x.glade.h:292 +msgid "Version Info" +msgstr "Informações da versĂ£o" + +#: ../src/snes9x.glade.h:293 +msgid "Video format:" +msgstr "Formato do vĂ­deo:" + +#: ../src/snes9x.glade.h:294 +msgid "Volume envelope height reading" +msgstr "Ajuste antecipado do volume de som" + +#: ../src/snes9x.glade.h:295 +msgid "X" +msgstr "X" + +#: ../src/snes9x.glade.h:296 +msgid "Y" +msgstr "Y" + +#: ../src/snes9x.glade.h:297 +msgid "_1x" +msgstr "_1x" + +#: ../src/snes9x.glade.h:298 +msgid "_2x" +msgstr "_2x" + +#: ../src/snes9x.glade.h:299 +msgid "_3x" +msgstr "_3x" + +#: ../src/snes9x.glade.h:300 +msgid "_4x" +msgstr "_4x" + +#: ../src/snes9x.glade.h:301 +msgid "_5x" +msgstr "_5x" + +#: ../src/snes9x.glade.h:302 +msgid "_Change Size" +msgstr "_Mudar tamanho" + +#: ../src/snes9x.glade.h:303 +msgid "_Cheats..." +msgstr "_Trapaças..." + +#: ../src/snes9x.glade.h:304 +msgid "_Emulation" +msgstr "_EmulaĂ§Ă£o" + +#: ../src/snes9x.glade.h:305 +msgid "_File" +msgstr "_Arquivo" + +#: ../src/snes9x.glade.h:306 +msgid "_Fullscreen" +msgstr "_Tela cheia" + +#: ../src/snes9x.glade.h:307 +msgid "_Hide Menu" +msgstr "_Esconder menu" + +#: ../src/snes9x.glade.h:308 +msgid "_Jump to Frame..." +msgstr "_Pular para quadro..." + +#: ../src/snes9x.glade.h:309 +msgid "_Load State" +msgstr "_Carregar estado" + +#: ../src/snes9x.glade.h:310 +msgid "_Open ROM..." +msgstr "_Abrir uma ROM..." + +#: ../src/snes9x.glade.h:311 +msgid "_Options" +msgstr "_Opções" + +#: ../src/snes9x.glade.h:312 +msgid "_Pause" +msgstr "_Pause" + +#: ../src/snes9x.glade.h:313 +msgid "_Preferences..." +msgstr "_PreferĂªncias..." + +#: ../src/snes9x.glade.h:314 +msgid "_Quit" +msgstr "_Sair" + +#: ../src/snes9x.glade.h:315 +msgid "_Reset" +msgstr "_PadrĂ£o" + +#: ../src/snes9x.glade.h:316 +msgid "_Save State" +msgstr "_Salvar estado" + +#: ../src/snes9x.glade.h:317 +msgid "_Status Bar" +msgstr "Barra de _estado" + +#: ../src/snes9x.glade.h:318 +msgid "_Stop Recording" +msgstr "_Parar gravaĂ§Ă£o" + +#: ../src/snes9x.glade.h:319 +msgid "_Swap" +msgstr "_Inverter" + +#: ../src/snes9x.glade.h:320 +msgid "_View" +msgstr "_Visualizar" + +#: ../src/snes9x.glade.h:321 +msgid "frames behind" +msgstr "quadros atrasados" + +#: ../src/snes9x.glade.h:322 +msgid "gtk-add" +msgstr "" + +#: ../src/snes9x.glade.h:323 +msgid "gtk-cancel" +msgstr "" + +#: ../src/snes9x.glade.h:324 +msgid "gtk-close" +msgstr "" + +#: ../src/snes9x.glade.h:325 +msgid "gtk-connect" +msgstr "" + +#: ../src/snes9x.glade.h:326 +msgid "gtk-ok" +msgstr "" + +#: ../src/snes9x.glade.h:327 +msgid "gtk-remove" +msgstr "" + +#: ../src/snes9x.glade.h:328 +msgid "milliseconds" +msgstr "milissegundos" + +#: ../src/snes9x.glade.h:329 +msgid "percent" +msgstr "porcento" + +#: ../src/snes9x.glade.h:330 +msgid "seconds after change" +msgstr "segundos apĂ³s mudança" + +#: ../src/snes9x.glade.h:331 +msgid "threads for filtering and scaling" +msgstr "processos para filtragem e escalonamento" + +#~ msgid "Escape Key Behavior" +#~ msgstr "Comportement de la touche Échap" + +#~ msgid "Escape exits fullscreen instead of hiding menus" +#~ msgstr "Échap quitte le plein-Ă©cran au lieu de cacher le menu" + +#~ msgid "Master volume control" +#~ msgstr "ContrĂ´le du volume" + +#~ msgid "Sample decoder:" +#~ msgstr "DĂ©codeur de samples:" + +#~ msgid "SNES Joypads" +#~ msgstr "Manettes SNES" diff --git a/gtk/po/sr@latin.po b/gtk/po/sr@latin.po new file mode 100644 index 00000000..2f36f747 --- /dev/null +++ b/gtk/po/sr@latin.po @@ -0,0 +1,1496 @@ +# Serbian translation of snes9x-gtk +# Copyright (C) 2010 +# This file is distributed under the same license as the snes9x-gtk package. +# Milan Kostić , 2010. +# +msgid "" +msgstr "" +"Snes9x-gtk: 1.5.2\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-01-02 12:20+0100\n" +"PO-Revision-Date: 2010-01-02 12:20+0100\n" +"Last-Translator: Milan Kostić \n" +"Language-Team: Serbian / Srpski \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../src/gtk_binding.cpp:187 +#, c-format +msgid "Unknown" +msgstr "Nepoznato" + +#: ../src/gtk_binding.cpp:202 +#, c-format +msgid "Keyboard %s%s%s%s" +msgstr "Tastatura %s%s%s%s" + +#: ../src/gtk_binding.cpp:213 +#, c-format +msgid "Axis #%d %s %d%%" +msgstr "Smerovi #%d %s %d%%" + +#: ../src/gtk_binding.cpp:218 +#, c-format +msgid "Button %d" +msgstr "Dugme %d" + +#: ../src/gtk_binding.cpp:220 +#, c-format +msgid "Joystick %d %s" +msgstr "Dzojstik %d %s" + +#: ../src/gtk_binding.cpp:225 +#, c-format +msgid "Unset" +msgstr "NepodeÅ¡eno" + +#: ../src/gtk_cheat.cpp:84 +msgid "Description" +msgstr "Opis" + +#: ../src/gtk_cheat.cpp:92 +msgid "Cheat" +msgstr "Varanja" + +#: ../src/gtk_cheat.cpp:203 ../src/gtk_cheat.cpp:274 +msgid "No description" +msgstr "Bez opisa" + +#: ../src/gtk_config.cpp:766 +#, c-format +msgid "bad option name: %s\n" +msgstr "pogreÅ¡an naziv za opciju: %s\n" + +#: ../src/gtk_config.cpp:1013 +#, c-format +msgid "failure to read snes9x node" +msgstr "ne mogu da uÄitam snes9x-ov Ävor" + +#: ../src/gtk_config.cpp:1050 +#, c-format +msgid "Couldn't create config directory: %s\n" +msgstr "Ne mogu napraviti konfiguracijski direktorijum: %s\n" + +#: ../src/gtk_config.cpp:1069 +#, c-format +msgid "Couldn't open config file: %s\n" +msgstr "Ne mogu otvoriti konfiguracijski fajl: %s\n" + +#: ../src/gtk_display_driver_opengl.cpp:509 +#, c-format +msgid "pixel_buffer_object extension not supported.\n" +msgstr "GL_ARB_pixel_buffer_object ekstenzija nije podržana.\n" + +#: ../src/gtk_preferences.cpp:343 +msgid "Rotate all axes to their maximum values, then press OK" +msgstr "Okreći maksimalno u svim smerovima, onda pritisni OK" + +#: ../src/gtk_preferences.cpp:383 +msgid "GTK port version: " +msgstr "Verzija GTK porta: " + +#: ../src/gtk_preferences.cpp:385 +msgid "English localization by Brandon Wright" +msgstr "Prevod saÄinio Milan Kostić" + +#: ../src/gtk_preferences.cpp:389 +msgid "" +"\n" +"Features enabled:" +msgstr "" +"\n" +"Dostupne osobine:" + +#: ../src/gtk_preferences.cpp:391 +msgid " Only barebones features enabled" +msgstr "" + +#: ../src/gtk_preferences.cpp:394 +msgid " OpenGL" +msgstr " OpenGL" + +#: ../src/gtk_preferences.cpp:397 +msgid " XVideo" +msgstr " XVideo" + +#: ../src/gtk_preferences.cpp:400 +msgid " XRandR" +msgstr " XRandR" + +#: ../src/gtk_preferences.cpp:403 +msgid " Joystick" +msgstr " Joystick" + +#: ../src/gtk_preferences.cpp:406 +msgid " NetPlay" +msgstr " NetPlay" + +#: ../src/gtk_preferences.cpp:408 +msgid "" +"\n" +"\n" +"Snes9x version: " +msgstr "" +"\n" +"\n" +"Snes9x verzija: " + +#: ../src/gtk_preferences.cpp:796 +msgid "Select Folder" +msgstr "Odaberi direktorijum" + +#: ../src/gtk_preferences.cpp:870 +msgid "None - Use software scaler" +msgstr "Nijedno - softversko prilagoÄ‘avanje" + +#: ../src/gtk_preferences.cpp:874 +msgid "OpenGL - Use 3D graphics hardware" +msgstr "OpenGL - hardverski 2D/3D" + +#: ../src/gtk_preferences.cpp:878 +msgid "XVideo - Use hardware video blitter" +msgstr "XVideo - hardverski video" + +#: ../src/gtk_preferences.cpp:884 +msgid "PortAudio" +msgstr "PortAudio" + +#: ../src/gtk_preferences.cpp:888 +msgid "Open Sound System" +msgstr "OSS" + +#: ../src/gtk_preferences.cpp:892 +msgid "SDL" +msgstr "SDL" + +#: ../src/gtk_preferences.cpp:896 +msgid "ALSA" +msgstr "ALSA" + +#: ../src/gtk_preferences.cpp:900 +msgid "PulseAudio" +msgstr "PulseAudio" + +#: ../src/gtk_s9x.cpp:177 +#, c-format +msgid "Error opening: %s\n" +msgstr "GreÅ¡ka pri otvaranju: %s\n" + +#: ../src/gtk_s9xwindow.cpp:729 +msgid "Open SNES Movie" +msgstr "Otvori SNES Film" + +#: ../src/gtk_s9xwindow.cpp:748 +msgid "New SNES Movie" +msgstr "Novi SNES Film" + +#: ../src/gtk_s9xwindow.cpp:761 +msgid "SNES Movies" +msgstr "SNES Filmovi" + +#: ../src/gtk_s9xwindow.cpp:769 ../src/gtk_s9xwindow.cpp:915 +#: ../src/gtk_s9xwindow.cpp:1060 ../src/gtk_s9xwindow.cpp:1127 +msgid "All Files" +msgstr "Svi Fajlovi" + +#: ../src/gtk_s9xwindow.cpp:830 +#, c-format +msgid "Couldn't load file '%s'" +msgstr "Ne mogu uÄitati fajl '%s'" + +#: ../src/gtk_s9xwindow.cpp:888 +msgid "Load Saved State" +msgstr "UÄitaj Snimljenu Poziciju" + +#: ../src/gtk_s9xwindow.cpp:899 ../src/gtk_s9xwindow.cpp:1044 +#: ../src/snes9x.glade.h:201 +msgid "Save States" +msgstr "Pozicije" + +#: ../src/gtk_s9xwindow.cpp:965 +#, c-format +msgid "The current frame in the movie is %d." +msgstr "Trenutni frejm u filmu je %d." + +#: ../src/gtk_s9xwindow.cpp:1031 +msgid "Save State" +msgstr "Snimi poziciju" + +#: ../src/gtk_s9xwindow.cpp:1108 +msgid "Save SPC file..." +msgstr "Snimi SPC fajl..." + +#: ../src/gtk_s9xwindow.cpp:1121 +msgid "SPC Files" +msgstr "SPC fajlovi" + +#: ../src/gtk_s9xwindow.cpp:1152 +#, c-format +msgid "Couldn't save SPC file '%s'" +msgstr "Ne mogu saÄuvati SPC fajl '%s'" + +#: ../src/gtk_s9xwindow.cpp:1226 +#, c-format +msgid "%sHosting NetPlay - %s" +msgstr "%sHostuj NetPlay - %s" + +#: ../src/gtk_s9xwindow.cpp:1227 ../src/gtk_s9xwindow.cpp:1235 +#: ../src/gtk_s9xwindow.cpp:1249 +msgid "Paused - " +msgstr "Pauza - " + +#: ../src/gtk_s9xwindow.cpp:1234 +#, c-format +msgid "%s%s on NetPlay %s:%d - Player %d" +msgstr "%s%s na NetPlay %s:%d - IgraÄ %d" + +#: ../src/gtk_s9xwindow.cpp:1271 +#, c-format +msgid "" +"Information for %s\n" +"\n" +"Name: %s\n" +"Speed: %02X/%s\n" +"Map: %s\n" +"Type: %02x\n" +"Contents: %s\n" +"ROM Size: %s\n" +"Calculated Size: %d\n" +"SRAM Size: %s\n" +"Header Checksum: %04X\n" +"Checksum Compliment: %04X\n" +"Actual Checksum: %04X\n" +"Video: %s\n" +"CRC32: %08X\n" +"Revision: %s%s" +msgstr "" + +#: ../src/gtk_s9xwindow.cpp:1309 +msgid "" +"\n" +"\n" +"This ROM has been modified or damaged" +msgstr "" + +#: ../src/snes9x.glade.h:2 +#, no-c-format +msgid "" +"0%\n" +"12.5%\n" +"25%\n" +"50%\n" +"100%" +msgstr "" + +#: ../src/snes9x.glade.h:8 +#, no-c-format +msgid "" +"12.5%\n" +"25%\n" +"50%\n" +"100%" +msgstr "" + +#: ../src/snes9x.glade.h:12 +msgid "16 Bit audio output" +msgstr "16-bitni izlaz za zvuk" + +#: ../src/snes9x.glade.h:13 +msgid "" +"16-bit (GL_BGRA)\n" +"24-bit (GL_RGB)\n" +"32-bit (GL_BGRA)" +msgstr "" + +#: ../src/snes9x.glade.h:16 +msgid "1x" +msgstr "Original" + +#: ../src/snes9x.glade.h:17 +msgid "2x" +msgstr "2 puta" + +#: ../src/snes9x.glade.h:18 +msgid "3x" +msgstr "3 puta" + +#: ../src/snes9x.glade.h:19 +msgid "" +"48000 hz\n" +"44100 hz\n" +"32000 hz (SNES Default)\n" +"22050 hz\n" +"16000 hz\n" +"11025 hz\n" +"8000 hz\n" +"0 hz" +msgstr "" + +#: ../src/snes9x.glade.h:27 +msgid "4x" +msgstr "4 puta" + +#: ../src/snes9x.glade.h:28 +msgid "5x" +msgstr "5 puta" + +#: ../src/snes9x.glade.h:29 +msgid "" +"8:7 Square pixels\n" +"4:3 SNES correct aspect" +msgstr "" + +#: ../src/snes9x.glade.h:31 +msgid "Accuracy" +msgstr "TaÄnost" + +#: ../src/snes9x.glade.h:32 +msgid "Basic Settings" +msgstr "Osnovna podeÅ¡avanja" + +#: ../src/snes9x.glade.h:33 +msgid "Calibration" +msgstr "Kalibracija" + +#: ../src/snes9x.glade.h:34 +msgid "Game Data" +msgstr "Podaci igre" + +#: ../src/snes9x.glade.h:35 +msgid "Hardware Acceleration" +msgstr "Hardversko ubrzanje" + +#: ../src/snes9x.glade.h:36 +msgid "Image Adjustments" +msgstr "PodeÅ¡avanje slike" + +#: ../src/snes9x.glade.h:37 +msgid "Joypad:" +msgstr "Dzojped" + +#: ../src/snes9x.glade.h:38 +msgid "Joystick Axis Threshold" +msgstr "Smerovi dzojstika" + +#: ../src/snes9x.glade.h:39 +msgid "NTSC Filter" +msgstr "NTSC Filter" + +#: ../src/snes9x.glade.h:40 +msgid "Quick load state" +msgstr "Brzo uÄitaj" + +#: ../src/snes9x.glade.h:41 +msgid "Quick save state" +msgstr "Brzo snimi" + +#: ../src/snes9x.glade.h:42 +msgid "ROM Image" +msgstr "ROM slika" + +#: ../src/snes9x.glade.h:43 +msgid "Scanline Filter" +msgstr "Scanline Filter" + +#: ../src/snes9x.glade.h:44 +msgid "Screensaver" +msgstr "ÄŒuvar ekrana" + +#: ../src/snes9x.glade.h:45 +msgid "Server" +msgstr "Server" + +#: ../src/snes9x.glade.h:46 +msgid "Settings" +msgstr "PodeÅ¡avanja" + +#: ../src/snes9x.glade.h:47 +msgid "Snes9x Emulator Shortcut Keys" +msgstr "Tastaturne preÄice za Snes9x Emulator" + +#: ../src/snes9x.glade.h:48 +msgid "Sound Settings" +msgstr "PodeÅ¡avanje zvuka" + +#: ../src/snes9x.glade.h:49 +msgid "Sticky" +msgstr "Lepljiva" + +#: ../src/snes9x.glade.h:50 +msgid "Turbo" +msgstr "Turbo" + +#: ../src/snes9x.glade.h:51 +msgid "Window Switching" +msgstr "Prebacivanje izmedju prozora" + +#: ../src/snes9x.glade.h:52 +msgid "" +"Click an entry and then press the desired keys or joystick button\n" +"Escape: Move to next Shift-Escape: Clear selected" +msgstr "" + +#: ../src/snes9x.glade.h:54 +msgid "A" +msgstr "A" + +#: ../src/snes9x.glade.h:55 +msgid "Act as a server" +msgstr "Radi kao server" + +#: ../src/snes9x.glade.h:56 +msgid "" +"Adjust to produce more or less data. Decrease the rate if experiencing " +"crackling. Increase the rate if experiencing frame-rate stuttering. Best " +"used with the \"Synchronize with sound\" option" +msgstr "" +"Ova regulacija stvara viÅ¡e ili manje podataka za obradu. Umanjavajte vrednost " +"ako Äujete 'pucketanje' ili povećajte vrednost ako primetite zastajkivanje " +"'frejm-rejta'. Najbolje se koristi uz opciju \"Sinhronizacija sa zvukom\"" + +#: ../src/snes9x.glade.h:57 +msgid "Advance to Frame" +msgstr "Doteraj do okvira Prozora" + +#: ../src/snes9x.glade.h:58 +msgid "Allow non-power-of-two textures" +msgstr "Dozvoli NPOT teksture" + +#: ../src/snes9x.glade.h:59 +msgid "Allow opposing dpad directions" +msgstr "Dozvoli suprotne dpad pravce" + +#: ../src/snes9x.glade.h:60 +msgid "Allow using modifier keys as independent keys instead of modifiers" +msgstr "Dozvoli korišćenje modifikacijskih tastera kao nezavisnih tastera" + +#: ../src/snes9x.glade.h:61 +msgid "" +"Allows games to use transparency effects. Recommended for correct graphics" +msgstr "" +"Dozvoli igrama da koriste efekte providnosti. " +"PreporuÄeno radi ispravne grafike" + +#: ../src/snes9x.glade.h:62 +msgid "Allows scaling and filtering to use multiple processors" +msgstr "Omogući većem broju CPU jezgara da ubrzaju skaliranje/filtere" + +#: ../src/snes9x.glade.h:63 +msgid "Apply scaling filter:" +msgstr "Potvrdi filter za skaliranje" + +#: ../src/snes9x.glade.h:64 +msgid "Artifacts:" +msgstr "Artifakti:" + +#: ../src/snes9x.glade.h:65 +msgid "Ask server to pause when" +msgstr "Server će pauzirati nakon" + +#: ../src/snes9x.glade.h:66 +msgid "" +"Automatic\n" +"0\n" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8\n" +"9" +msgstr "" +"Automatsko\n" +"0\n" +"1\n" +"2\n" +"3\n" +"4\n" +"5\n" +"6\n" +"7\n" +"8\n" +"9" + +#: ../src/snes9x.glade.h:77 +msgid "" +"Automatically save the game's SRAM at this interval. Setting this to 0 will " +"only save when quitting or changing ROMs" +msgstr "" +"Automatski snimaj SRAM igre u ovom intervalu. Vrednost 0 (nula) će snimati " +"jedino pri izlasku iz emulatora ili pak pri promeni ROMova" + +#: ../src/snes9x.glade.h:78 +msgid "B" +msgstr "B" + +#: ../src/snes9x.glade.h:79 +msgid "BG layering hack" +msgstr "BG hak za sloj" + +#: ../src/snes9x.glade.h:80 +msgid "Base emulation speed on the rate sound is output" +msgstr "Baziraj brzinu emulacije srazmerno zvuÄnoj slici" + +#: ../src/snes9x.glade.h:81 +msgid "Begin movie recording" +msgstr "ZapoÄni snimanje filma" + +#: ../src/snes9x.glade.h:82 +msgid "Bilinear-filter output" +msgstr "Bilinearno filtriranje" + +#: ../src/snes9x.glade.h:83 +msgid "Bleed:" +msgstr "Bledilo:" + +#: ../src/snes9x.glade.h:84 +msgid "Block invalid VRAM access" +msgstr "Blokiraj pogreÅ¡an pristup video memoriji" + +#: ../src/snes9x.glade.h:85 +msgid "Brightness:" +msgstr "Osvetljenje:" + +#: ../src/snes9x.glade.h:86 +msgid "Browse..." +msgstr "Pretraži..." + +#: ../src/snes9x.glade.h:87 +msgid "Buffer size:" +msgstr "Vrednost bafera: " + +#: ../src/snes9x.glade.h:88 +msgid "Buttons" +msgstr "Dugmad" + +#: ../src/snes9x.glade.h:89 +msgid "Cali_brate" +msgstr "Kali_bracija" + +#: ../src/snes9x.glade.h:90 +msgid "Can be faster or slower depending on drivers" +msgstr "Može biti i sporije i brže... zavisno od drajvera" + +#: ../src/snes9x.glade.h:91 +msgid "Center all axes on all joysticks and press Calibrate." +msgstr "Centriraj prvo sve ose na svim dzojsticima, tek onda Kalibracija!" + +#: ../src/snes9x.glade.h:92 +msgid "Change fullscreen resolution:" +msgstr "Promena rezolucije za ceo ekran:" + +#: ../src/snes9x.glade.h:93 +msgid "" +"Changes the amount a joystick should be tilted to register a button press" +msgstr "" +"Menja vredost koliko treba palicu dzojstika nakriviti da bi registrovao taster" + +#: ../src/snes9x.glade.h:94 +msgid "Changes the screen resolution when running Snes9x in fullscreen mode" +msgstr "Ekranska rezolucija kada slika bude prekrila ceo ekran" + +#: ../src/snes9x.glade.h:95 +msgid "Clear entry" +msgstr "OÄisti upis" + +#: ../src/snes9x.glade.h:96 +msgid "Code:" +msgstr "Kod: " + +#: ../src/snes9x.glade.h:97 +msgid "Composite" +msgstr "Composite" + +#: ../src/snes9x.glade.h:98 +msgid "Connect to another computer" +msgstr "Poveži se sa drugim raÄunarom" + +#: ../src/snes9x.glade.h:99 +msgid "Connect to another computer that is running Snes9x NetPlay as a server" +msgstr "Poveži se sa raÄunarom kod koga je Snes9x NetPlay server" + +#: ../src/snes9x.glade.h:100 +msgid "Connect to specified TCP port on remote computer" +msgstr "Poveži se specifiÄnim TCP portom ka udaljenom raÄunaru" + +#: ../src/snes9x.glade.h:101 +msgid "Contrast:" +msgstr "Kontrast:" + +#: ../src/snes9x.glade.h:102 +msgid "Controller Ports" +msgstr "Portovi kontrolera" + +#: ../src/snes9x.glade.h:103 +msgid "Correct Aspect" +msgstr "Ispravan prizor" + +#: ../src/snes9x.glade.h:104 +msgid "Custom folder:" +msgstr "Direktorijum po izboru:" + +#: ../src/snes9x.glade.h:105 +msgid "Decrease frame rate" +msgstr "Uspori frajmove" + +#: ../src/snes9x.glade.h:106 +msgid "Decrease frame time" +msgstr "Uspori frejmove" + +#: ../src/snes9x.glade.h:107 +msgid "Default port:" +msgstr "Podrazumevani port:" + +#: ../src/snes9x.glade.h:108 +msgid "Description:" +msgstr "Opis:" + +#: ../src/snes9x.glade.h:109 +msgid "Detects frames that are not output by Snes9x in hires, and scales them" +msgstr "PronaÄ‘i frejmove koji nisu emulirani u većim rezolucijama i prilagodi ih" + +#: ../src/snes9x.glade.h:110 +msgid "Different formats can yield highly different performance" +msgstr "RazliÄiti formati mogu doprineti drugaÄijim performansama" + +#: ../src/snes9x.glade.h:111 +msgid "Disables output of sound" +msgstr "IskljuÄuje izvor zvuka" + +#: ../src/snes9x.glade.h:112 +msgid "Display" +msgstr "Prikaz" + +#: ../src/snes9x.glade.h:113 +msgid "Domain name or internet protocol address of a remote computer" +msgstr "Naziv domena ili adresa interent protokola udaljenog raÄunara" + +#: ../src/snes9x.glade.h:114 +msgid "Down" +msgstr "Dole" + +#: ../src/snes9x.glade.h:115 +msgid "Emulation" +msgstr "Emulacija" + +#: ../src/snes9x.glade.h:116 +msgid "Enable HDMA" +msgstr "Omogući HDMA" + +#: ../src/snes9x.glade.h:117 +msgid "Enable HDMA. Required feature for compatibility with some games" +msgstr "Potrebna osobina radi kompatibilnosti sa nekim igrama" + +#: ../src/snes9x.glade.h:118 +msgid "Enable hacks that may improve performance, but can cause errors" +msgstr "Ovi hakovi mogu poboljÅ¡ati performanse, ali ponekad mogu biti i uzrok pojava greÅ¡ki" + +#: ../src/snes9x.glade.h:119 +msgid "Enable speed hacks" +msgstr "Omogući hakove za brzinu" + +#: ../src/snes9x.glade.h:120 +msgid "Enable transparency" +msgstr "Omogući transparenciju" + +#: ../src/snes9x.glade.h:121 +msgid "Enable turbo" +msgstr "Omogući turbo" + +#: ../src/snes9x.glade.h:122 +msgid "Exact Pixels" +msgstr "Ispravni pikseli" + +#: ../src/snes9x.glade.h:123 +msgid "Fast-forward to frame" +msgstr "Ubrzaj do frejma..." + +#: ../src/snes9x.glade.h:124 +msgid "Files" +msgstr "Fajlovi" + +#: ../src/snes9x.glade.h:125 +msgid "Force SNES-hires output" +msgstr "Prisili emulaciju većih rezolucija" + +#: ../src/snes9x.glade.h:126 +msgid "Force an inverted byte-ordering" +msgstr "Prisili na preinaÄeni poredak bajtova" + +#: ../src/snes9x.glade.h:127 +msgid "" +"Forces a swapped byte-ordering for cases where the system's endian is used " +"instead of the video card" +msgstr "" +"Prisiljava na izmenu poretka bajtova u sluÄajevima kada se koristi sistemski " +"endian umesto video kartice" +#: ../src/snes9x.glade.h:128 +msgid "Frameskip:" +msgstr "Preskakanje frejmova:" + +#: ../src/snes9x.glade.h:129 +msgid "Fringing:" +msgstr "" + +#: ../src/snes9x.glade.h:130 +msgid "From _File..." +msgstr "Iz _Fajla..." + +#: ../src/snes9x.glade.h:131 +msgid "" +"Game Genie\n" +"Pro Action Replay\n" +"Goldfinger" +msgstr "" + +#: ../src/snes9x.glade.h:134 +msgid "Gamma:" +msgstr "Gama:" + +#: ../src/snes9x.glade.h:135 +msgid "Go to fullscreen mode immediately after opening a ROM" +msgstr "PreÄ‘i na ceo ekran odmah nakon otvaranja ROMa" + +#: ../src/snes9x.glade.h:136 +msgid "Graphics" +msgstr "Grafika" + +#: ../src/snes9x.glade.h:137 +msgid "Hardware reset" +msgstr "Hardverski reset" + +#: ../src/snes9x.glade.h:138 +msgid "" +"Host a game on this computer as Player 1, requiring extra throughput to " +"support multitple users" +msgstr "" +"Hostuj igru na ovom raÄunaru kao IgraÄ 1. Ovo će zahtevati viÅ¡e propusne moći za " +"podrÅ¡ku većeg broja korisnika" + +#: ../src/snes9x.glade.h:139 +msgid "Hue:" +msgstr "Nijansa boje:" + +#: ../src/snes9x.glade.h:140 +msgid "Increase frame rate" +msgstr "Ubrzaj frejmove" + +#: ../src/snes9x.glade.h:141 +msgid "Increase frame time" +msgstr "Ubrzaj frejmove" + +#: ../src/snes9x.glade.h:142 +msgid "Input rate:" +msgstr "Ulazna vrednost:" + +#: ../src/snes9x.glade.h:143 +msgid "Joypad" +msgstr "Dzojped" + +#: ../src/snes9x.glade.h:144 +msgid "Joypads" +msgstr "Dzojpedi" + +#: ../src/snes9x.glade.h:145 +msgid "Joystick Options" +msgstr "Opcije za dzojstik" + +#: ../src/snes9x.glade.h:146 +msgid "L" +msgstr "L" + +#: ../src/snes9x.glade.h:147 +msgid "Left" +msgstr "Levo" + +#: ../src/snes9x.glade.h:148 +msgid "Let left and right or up and down be pressed at the same time" +msgstr "Levo-desno ili gore-dole će biti moguće istovremeno koristiti" + +#: ../src/snes9x.glade.h:149 +msgid "Load Movie" +msgstr "UÄitaj film" + +#: ../src/snes9x.glade.h:150 +msgid "Load _Movie..." +msgstr "UÄitaj _film..." + +#: ../src/snes9x.glade.h:151 +msgid "Maintain aspect-ratio:" +msgstr "OÄuvaj proporciju prizora:" + +#: ../src/snes9x.glade.h:152 +msgid "Merge odd and even fields" +msgstr "" + +#: ../src/snes9x.glade.h:153 +msgid "Misc" +msgstr "Razno" + +#: ../src/snes9x.glade.h:154 +msgid "Monochrome" +msgstr "MonoChrome" + +#: ../src/snes9x.glade.h:155 +msgid "Mouse" +msgstr "MiÅ¡" + +#: ../src/snes9x.glade.h:156 +msgid "Multitap" +msgstr "" + +#: ../src/snes9x.glade.h:157 +msgid "Mute sound output" +msgstr "PriguÅ¡i izvor zvuka" + +#: ../src/snes9x.glade.h:158 +msgid "Name or IP address:" +msgstr "Naziv ili IP adresa:" + +#: ../src/snes9x.glade.h:159 +msgid "" +"None\n" +"SuperEagle\n" +"2xSaI\n" +"Super2xSaI\n" +"hq2x\n" +"hq3x\n" +"hq4x\n" +"EPX\n" +"EPX Smooth\n" +"Blargg's NTSC\n" +"Scanlines" +msgstr "" + +#: ../src/snes9x.glade.h:170 +msgid "Open ROM" +msgstr "Otvori ROM" + +#: ../src/snes9x.glade.h:171 +msgid "Open Recent" +msgstr "Otvori poslednje" + +#: ../src/snes9x.glade.h:172 +msgid "Open a ROM to use with NetPlay" +msgstr "Otvori ROM koji ćeÅ¡ koristiti za NetPlay" + +#: ../src/snes9x.glade.h:173 +msgid "Open with _NetPlay..." +msgstr "Otvori uz _NetPlay..." + +#: ../src/snes9x.glade.h:174 +msgid "Output two channels, left and right" +msgstr "Dvokanalni zvuk - odvojeno levi i desni" + +#: ../src/snes9x.glade.h:175 +msgid "Outputs at 16 bits per sample instead of 8 bits. More accurate sound" +msgstr "Izlaz od 16 bita po semplu umesto 8 bita - joÅ¡ ispravniji zvuk" + +#: ../src/snes9x.glade.h:176 +msgid "Pause" +msgstr "Pauza" + +#: ../src/snes9x.glade.h:177 +msgid "Pause emulation when switching away from Snes9x" +msgstr "Pauziraj emulaciju kada istovremeno koristiÅ¡ i druge GUI programe" + +#: ../src/snes9x.glade.h:178 +msgid "Pixel-buffer format:" +msgstr "" + +#: ../src/snes9x.glade.h:179 +msgid "Playback rate:" +msgstr "Plejbek vrednost:" + +#: ../src/snes9x.glade.h:180 +msgid "Port:" +msgstr "Port:" + +#: ../src/snes9x.glade.h:181 +msgid "Prevent the screensaver from activating" +msgstr "SpreÄi aktiviranje Äuvara ekrana" + +#: ../src/snes9x.glade.h:182 +msgid "Prevents edge artifacts, but can slow performance" +msgstr "SpreÄava moguću pojavu artifakata na rubovima prikaza. " +"Može usporiti, ali i ubrzati performanse - zavisno od drajvera." + +#: ../src/snes9x.glade.h:183 +msgid "Quit Snes9x" +msgstr "IskljuÄi Snes9x" + +#: ../src/snes9x.glade.h:184 +msgid "R" +msgstr "R" + +#: ../src/snes9x.glade.h:185 +msgid "RGB" +msgstr "RedGreenBlue" + +#: ../src/snes9x.glade.h:186 +msgid "ROM folder" +msgstr "ROM direktorijum" + +#: ../src/snes9x.glade.h:187 +msgid "R_ecord Movie..." +msgstr "S_nimi film..." + +#: ../src/snes9x.glade.h:188 +msgid "Reset" +msgstr "Hardverski reset" + +#: ../src/snes9x.glade.h:189 +msgid "" +"Reset the game when players join instead of transferring potentially " +"unreliable freeze states" +msgstr "" +"Resetuj igru kada se igraÄi prikljuÄe, zbog mogućeg zamrzavanja " +"i zbog pouzdanog prenosa" + +#: ../src/snes9x.glade.h:190 +msgid "Resolution:" +msgstr "Rezolucija:" + +#: ../src/snes9x.glade.h:191 +msgid "Reverse stereo" +msgstr "Reverzni stereo" + +#: ../src/snes9x.glade.h:192 +msgid "Right" +msgstr "Levo" + +#: ../src/snes9x.glade.h:193 +msgid "Run / _Continue" +msgstr "Pokreni / _Nastavi" + +#: ../src/snes9x.glade.h:194 +msgid "S-Video" +msgstr "" + +#: ../src/snes9x.glade.h:195 +msgid "SNES Port 1" +msgstr "" + +#: ../src/snes9x.glade.h:196 +msgid "SNES Port 2" +msgstr "" + +#: ../src/snes9x.glade.h:197 +msgid "Saturation:" +msgstr "Zasićenje:" + +#: ../src/snes9x.glade.h:198 +msgid "Save SPC" +msgstr "SaÄuvaj SPC" + +#: ../src/snes9x.glade.h:199 +msgid "Save SPC..." +msgstr "Snimi SPC..." + +#: ../src/snes9x.glade.h:200 +msgid "Save SRAM:" +msgstr "SaÄuvaj SRAM:" + +#: ../src/snes9x.glade.h:202 +msgid "Save data in:" +msgstr "SaÄuvaj podatke u:" + +#: ../src/snes9x.glade.h:203 +msgid "Scale image to fit window" +msgstr "Prilagodi sliku prozoru" + +#: ../src/snes9x.glade.h:204 +msgid "Scales the image as large as possible without distortion" +msgstr "Prilagodi sliku Å¡to je god moguće veću, ali bez izobliÄenja" + +#: ../src/snes9x.glade.h:205 +msgid "Scales the image so no black bars are present" +msgstr "Prilagodi sliku tako da se ne vide crni delovi" + +#: ../src/snes9x.glade.h:206 +msgid "Scanline intensity:" +msgstr "Scanline intenzitet:" + +#: ../src/snes9x.glade.h:207 +msgid "Screenshot" +msgstr "Snimak ekrana" + +#: ../src/snes9x.glade.h:208 +msgid "Seek to frame" +msgstr "PreÄ‘i na frejm" + +#: ../src/snes9x.glade.h:209 +msgid "Select" +msgstr "Odaberi" + +#: ../src/snes9x.glade.h:210 +msgid "Send ROM image to clients" +msgstr "PoÅ¡alji ROM sliku drugim klijentima" + +#: ../src/snes9x.glade.h:211 +msgid "" +"Send the running game image to players instead of requiring them to have " +"their own copies" +msgstr "" +"PoÅ¡alji trenutnu igru drugim igraÄima, umesto da im tražite da imaju " +"iste takve kopije" + +#: ../src/snes9x.glade.h:212 +msgid "Set new axis bindings at:" +msgstr "Prilagodi nove tastere na:" + +#: ../src/snes9x.glade.h:213 +msgid "Sharpness:" +msgstr "OÅ¡trina:" + +#: ../src/snes9x.glade.h:214 +msgid "Shortcuts" +msgstr "PreÄice" + +#: ../src/snes9x.glade.h:215 +msgid "Show ROM _Info..." +msgstr "Prikaži informacije o ROMu..." + +#: ../src/snes9x.glade.h:216 +msgid "Show frame rate" +msgstr "Prikaži vrednost frejmova" + +#: ../src/snes9x.glade.h:217 +msgid "Slot 0" +msgstr "" + +#: ../src/snes9x.glade.h:218 +msgid "Slot 1" +msgstr "" + +#: ../src/snes9x.glade.h:219 +msgid "Slot 2" +msgstr "" + +#: ../src/snes9x.glade.h:220 +msgid "Slot 3" +msgstr "" + +#: ../src/snes9x.glade.h:221 +msgid "Slot 4" +msgstr "" + +#: ../src/snes9x.glade.h:222 +msgid "Slot 5" +msgstr "" + +#: ../src/snes9x.glade.h:223 +msgid "Slot 6" +msgstr "" + +#: ../src/snes9x.glade.h:224 +msgid "Slot 7" +msgstr "" + +#: ../src/snes9x.glade.h:225 +msgid "Slot 8" +msgstr "" + +#: ../src/snes9x.glade.h:226 +msgid "Slot _0" +msgstr "" + +#: ../src/snes9x.glade.h:227 +msgid "Slot _1" +msgstr "" + +#: ../src/snes9x.glade.h:228 +msgid "Slot _2" +msgstr "" + +#: ../src/snes9x.glade.h:229 +msgid "Slot _3" +msgstr "" + +#: ../src/snes9x.glade.h:230 +msgid "Slot _4" +msgstr "" + +#: ../src/snes9x.glade.h:231 +msgid "Slot _5" +msgstr "" + +#: ../src/snes9x.glade.h:232 +msgid "Slot _6" +msgstr "" + +#: ../src/snes9x.glade.h:233 +msgid "Slot _7" +msgstr "" + +#: ../src/snes9x.glade.h:234 +msgid "Slot _8" +msgstr "" + +#: ../src/snes9x.glade.h:235 +msgid "Smoothens (blurs) the image" +msgstr "Ugladi (zamagli) sliku" + +#: ../src/snes9x.glade.h:236 +msgid "Snes9x" +msgstr "Snes9x" + +#: ../src/snes9x.glade.h:237 +msgid "Snes9x Cheats" +msgstr "Snes9x Varanja" + +#: ../src/snes9x.glade.h:238 +msgid "Snes9x NetPlay" +msgstr "Snes9x NetPlay" + +#: ../src/snes9x.glade.h:239 +msgid "Snes9x Preferences" +msgstr "Snes9x PodeÅ¡avanja" + +#: ../src/snes9x.glade.h:240 +msgid "Snes9x configuration folder" +msgstr "Snes9x konfiguracijski direktorijum" + +#: ../src/snes9x.glade.h:241 +msgid "Soft _Reset" +msgstr "Softverski _reset" + +#: ../src/snes9x.glade.h:242 +msgid "Soft reset" +msgstr "Softverski reset" + +#: ../src/snes9x.glade.h:243 +msgid "Sound" +msgstr "Zvuk" + +#: ../src/snes9x.glade.h:244 +msgid "Sound driver:" +msgstr "PokretaÄ zvuka:" + +#: ../src/snes9x.glade.h:245 +msgid "Start" +msgstr "PoÄetak" + +#: ../src/snes9x.glade.h:246 +msgid "Stereo" +msgstr "Stereo" + +#: ../src/snes9x.glade.h:247 +msgid "Stop movie recording" +msgstr "Zaustavi snimanje filma" + +#: ../src/snes9x.glade.h:248 +msgid "Store data in $HOME/.snes9x/sram" +msgstr "ÄŒuvaj podatke u $HOME/.snes9x/sram" + +#: ../src/snes9x.glade.h:249 +msgid "Store data in the same folder as the ROM file used" +msgstr "ÄŒuvaj podatke u istom direktorijumu gde je i sam ROM fajl" + +#: ../src/snes9x.glade.h:250 +msgid "Superscope" +msgstr "Superscope" + +#: ../src/snes9x.glade.h:251 +msgid "Swap controllers 1 & 2" +msgstr "Zameni mesta kontrolerima 1 i 2" + +#: ../src/snes9x.glade.h:252 +msgid "Swap the left and right sound channels" +msgstr "Zamena zvuÄnih kanala - levi kao desni, a desni kao levi" + +#: ../src/snes9x.glade.h:253 +msgid "Swap with:" +msgstr "Zameni sa:" + +#: ../src/snes9x.glade.h:254 +msgid "Sy_nc Clients" +msgstr "Si_nhronizuj klijente" + +#: ../src/snes9x.glade.h:255 +msgid "Sync the image to the vertical retrace to stop tearing" +msgstr "Sinhronizuje sliku sa vertikalnim osvežavanjem da bi se izbeglo 'suzenje'" + +#: ../src/snes9x.glade.h:256 +msgid "Sync to vertical blank" +msgstr "Sinhronizacija sa vertikalnim osvežavanjem ekrana" + +#: ../src/snes9x.glade.h:257 +msgid "Sync using reset" +msgstr "Resetuj igru radi sinhronizacije" + +#: ../src/snes9x.glade.h:258 +msgid "Synchronize with sound" +msgstr "Sinhronizacija sa zvukom" + +#: ../src/snes9x.glade.h:259 +msgid "TCP port used as a connection point for remote clients" +msgstr "" +"Podrazumevani TCP port koji će se koristi za povezivanje sa " +"udaljenim raÄunarom" + +#: ../src/snes9x.glade.h:260 +msgid "The ESC key should:" +msgstr "ESC taster će:" + +#: ../src/snes9x.glade.h:261 +msgid "The current frame in the movie is" +msgstr "Trenutni frejm u filmu je" + +#: ../src/snes9x.glade.h:262 +msgid "" +"The game chosen will be loaded before connecting. This field can be blank if " +"the server will send the ROM image" +msgstr "" +"Izabrana igra biće uÄitana pre konekcije. Ovo polje može biti prazno ako " +"će server da poÅ¡alje ROM" + +#: ../src/snes9x.glade.h:263 +msgid "To _File..." +msgstr "Ka _Fajlu..." + +#: ../src/snes9x.glade.h:264 +msgid "Toggle BG layer 0" +msgstr "UkljuÄi BG sloj 0" + +#: ../src/snes9x.glade.h:265 +msgid "Toggle BG layer 1" +msgstr "UkljuÄi BG sloj 1" + +#: ../src/snes9x.glade.h:266 +msgid "Toggle BG layer 2" +msgstr "UkljuÄi BG sloj 2" + +#: ../src/snes9x.glade.h:267 +msgid "Toggle BG layer 3" +msgstr "UkljuÄi BG sloj 3" + +#: ../src/snes9x.glade.h:268 +msgid "Toggle all sound channels" +msgstr "UkljuÄi sve zvuÄne kanale" + +#: ../src/snes9x.glade.h:269 +msgid "Toggle fullscreen" +msgstr "PreÄ‘i na ceo ekran" + +#: ../src/snes9x.glade.h:270 +msgid "Toggle sound channel 0" +msgstr "UkljuÄi zvuÄni kanal 0" + +#: ../src/snes9x.glade.h:271 +msgid "Toggle sound channel 1" +msgstr "UkljuÄi zvuÄni kanal 1" + +#: ../src/snes9x.glade.h:272 +msgid "Toggle sound channel 2" +msgstr "UkljuÄi zvuÄni kanal 2" + +#: ../src/snes9x.glade.h:273 +msgid "Toggle sound channel 3" +msgstr "UkljuÄi zvuÄni kanal 3" + +#: ../src/snes9x.glade.h:274 +msgid "Toggle sound channel 4" +msgstr "UkljuÄi zvuÄni kanal 4" + +#: ../src/snes9x.glade.h:275 +msgid "Toggle sound channel 5" +msgstr "UkljuÄi zvuÄni kanal 5" + +#: ../src/snes9x.glade.h:276 +msgid "Toggle sound channel 6" +msgstr "UkljuÄi zvuÄni kanal 6" + +#: ../src/snes9x.glade.h:277 +msgid "Toggle sound channel 7" +msgstr "UkljuÄi zvuÄni kanal 7" + +#: ../src/snes9x.glade.h:278 +msgid "Toggle sprites" +msgstr "UkljuÄi sprajtove" + +#: ../src/snes9x.glade.h:279 +msgid "" +"Toggle the menu bar\n" +"Exit fullscreen mode\n" +"Quit Snes9x" +msgstr "" +"UkljuÄi/IskljuÄi meni\n" +"IzaÄ‘i iz moda celog ekrana\n" +"IskljuÄi Snes9x" + +#: ../src/snes9x.glade.h:282 +msgid "Toggle turbo" +msgstr "UkljuÄi/IskljuÄi turbo" + +#: ../src/snes9x.glade.h:283 +msgid "Turbo / Sticky Buttons" +msgstr "Turbo / Lepljiva Dugmad" + +#: ../src/snes9x.glade.h:284 +msgid "Type:" +msgstr "Odaberi:" + +#: ../src/snes9x.glade.h:285 +msgid "Up" +msgstr "Gore" + +#: ../src/snes9x.glade.h:286 +msgid "Use " +msgstr "Koristi " + +#: ../src/snes9x.glade.h:287 +msgid "Use SNES extended height. Will probably cause letterboxing" +msgstr "" +"Korišćenje prekomerne visine će verovatno izazvati letterboxing" + +#: ../src/snes9x.glade.h:288 +msgid "Use fullscreen on ROM open" +msgstr "Koristi ceo ekran pri otvaranju ROMa" + +#: ../src/snes9x.glade.h:289 +msgid "Use modifier keys (CTRL, SHIFT, ALT) directly" +msgstr "Koristi mod. tastere (CTRL, SHIFT, ALT) direktno" + +#: ../src/snes9x.glade.h:290 +msgid "Use overscanned height" +msgstr "Koristi prekomernu visinu" + +#: ../src/snes9x.glade.h:291 +msgid "Use pixel-buffer objects" +msgstr "Koristi pixel-buffer objects" + +#: ../src/snes9x.glade.h:292 +msgid "Version Info" +msgstr "O programu" + +#: ../src/snes9x.glade.h:293 +msgid "Video preset:" +msgstr "Video postavke:" + +#: ../src/snes9x.glade.h:294 +msgid "X" +msgstr "X" + +#: ../src/snes9x.glade.h:295 +msgid "Y" +msgstr "Y" + +#: ../src/snes9x.glade.h:296 +msgid "_1x" +msgstr "_Original" + +#: ../src/snes9x.glade.h:297 +msgid "_2x" +msgstr "_2 puta" + +#: ../src/snes9x.glade.h:298 +msgid "_3x" +msgstr "_3 puta" + +#: ../src/snes9x.glade.h:299 +msgid "_4x" +msgstr "_4 puta" + +#: ../src/snes9x.glade.h:300 +msgid "_5x" +msgstr "_5 puta" + +#: ../src/snes9x.glade.h:301 +msgid "_Change Size" +msgstr "_Promeni veliÄinu" + +#: ../src/snes9x.glade.h:302 +msgid "_Cheats..." +msgstr "_Varanja" + +#: ../src/snes9x.glade.h:303 +msgid "_Emulation" +msgstr "_Emulacija" + +#: ../src/snes9x.glade.h:304 +msgid "_File" +msgstr "_Fajl" + +#: ../src/snes9x.glade.h:305 +msgid "_Fullscreen" +msgstr "_Ceo ekran" + +#: ../src/snes9x.glade.h:306 +msgid "_Hide Menu" +msgstr "_Sakrij meni" + +#: ../src/snes9x.glade.h:307 +msgid "_Jump to Frame..." +msgstr "_PreÄ‘i na frejm..." + +#: ../src/snes9x.glade.h:308 +msgid "_Load State" +msgstr "_UÄitaj poziciju" + +#: ../src/snes9x.glade.h:309 +msgid "_Open ROM..." +msgstr "_Otvori ROM..." + +#: ../src/snes9x.glade.h:310 +msgid "_Options" +msgstr "_Opcije" + +#: ../src/snes9x.glade.h:311 +msgid "_Pause" +msgstr "_Pauza" + +#: ../src/snes9x.glade.h:312 +msgid "_Preferences..." +msgstr "_PodeÅ¡avanja..." + +#: ../src/snes9x.glade.h:313 +msgid "_Quit" +msgstr "_Izlaz" + +#: ../src/snes9x.glade.h:314 +msgid "_Reset" +msgstr "_Resetuj" + +#: ../src/snes9x.glade.h:315 +msgid "_Save State" +msgstr "_Snimi poziciju" + +#: ../src/snes9x.glade.h:316 +msgid "_Status Bar" +msgstr "_Statusna linija" + +#: ../src/snes9x.glade.h:317 +msgid "_Stop Recording" +msgstr "_Zaustavi snimanje" + +#: ../src/snes9x.glade.h:318 +msgid "_Swap" +msgstr "_Zamena" + +#: ../src/snes9x.glade.h:319 +msgid "_View" +msgstr "_Pregled" + +#: ../src/snes9x.glade.h:320 +msgid "frames behind" +msgstr "frejmova" + +#: ../src/snes9x.glade.h:321 +msgid "milliseconds" +msgstr "milisekunde" + +#: ../src/snes9x.glade.h:322 +msgid "percent" +msgstr "procenat" + +#: ../src/snes9x.glade.h:323 +msgid "seconds after change" +msgstr "sekundi nakon promene" + +#: ../src/snes9x.glade.h:324 +msgid "threads for filtering and scaling" +msgstr "niti za za filtriranje i prilagoÄ‘avanje slike" diff --git a/gtk/src/filter_epx_unsafe.cpp b/gtk/src/filter_epx_unsafe.cpp new file mode 100644 index 00000000..62874e29 --- /dev/null +++ b/gtk/src/filter_epx_unsafe.cpp @@ -0,0 +1,389 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "dma.h" +#include "apu/apu.h" +#include "fxemu.h" +#include "snapshot.h" +#ifdef DEBUGGER +#include "debug.h" +#include "missing.h" +#endif + +#include "port.h" +#include "filter_epx_unsafe.h" + +/* Allows vertical overlap. We need this to avoid seams when threading */ +void EPX_16_unsafe (uint8 *srcPtr, + uint32 srcPitch, + uint8 *dstPtr, + uint32 dstPitch, + int width, + int height) +{ + uint16 colorX, colorA, colorB, colorC, colorD; + uint16 *sP, *uP, *lP; + uint32 *dP1, *dP2; + int w; + + for (; height; height--) + { + sP = (uint16 *) srcPtr; + uP = (uint16 *) (srcPtr - srcPitch); + lP = (uint16 *) (srcPtr + srcPitch); + dP1 = (uint32 *) dstPtr; + dP2 = (uint32 *) (dstPtr + dstPitch); + + // left edge + + colorX = *sP; + colorC = *++sP; + colorB = *lP++; + colorD = *uP++; + + if ((colorX != colorC) && (colorB != colorD)) + { + #ifdef __BIG_ENDIAN__ + *dP1 = (colorX << 16) + ((colorC == colorD) ? colorC : colorX); + *dP2 = (colorX << 16) + ((colorB == colorC) ? colorB : colorX); + #else + *dP1 = colorX + (((colorC == colorD) ? colorC : colorX) << 16); + *dP2 = colorX + (((colorB == colorC) ? colorB : colorX) << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + dP1++; + dP2++; + + // + + for (w = width - 2; w; w--) + { + colorA = colorX; + colorX = colorC; + colorC = *++sP; + colorB = *lP++; + colorD = *uP++; + + if ((colorA != colorC) && (colorB != colorD)) + { + #ifdef __BIG_ENDIAN__ + *dP1 = (((colorD == colorA) ? colorD : colorX) << 16) + ((colorC == colorD) ? colorC : colorX); + *dP2 = (((colorA == colorB) ? colorA : colorX) << 16) + ((colorB == colorC) ? colorB : colorX); + #else + *dP1 = ((colorD == colorA) ? colorD : colorX) + (((colorC == colorD) ? colorC : colorX) << 16); + *dP2 = ((colorA == colorB) ? colorA : colorX) + (((colorB == colorC) ? colorB : colorX) << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + dP1++; + dP2++; + } + + // right edge + + colorA = colorX; + colorX = colorC; + colorB = *lP; + colorD = *uP; + + if ((colorA != colorX) && (colorB != colorD)) + { + #ifdef __BIG_ENDIAN__ + *dP1 = (((colorD == colorA) ? colorD : colorX) << 16) + colorX; + *dP2 = (((colorA == colorB) ? colorA : colorX) << 16) + colorX; + #else + *dP1 = ((colorD == colorA) ? colorD : colorX) + (colorX << 16); + *dP2 = ((colorA == colorB) ? colorA : colorX) + (colorX << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + srcPtr += srcPitch; + dstPtr += dstPitch << 1; + } + + return; +} + +#undef AVERAGE_1555 +#define AVERAGE_1555(el0, el1) (((el0) & (el1)) + ((((el0) ^ (el1)) & 0x7BDE) >> 1)) + +/* Blends with edge pixel instead of just using it directly. */ +void EPX_16_smooth_unsafe (uint8 *srcPtr, + uint32 srcPitch, + uint8 *dstPtr, + uint32 dstPitch, + int width, + int height) +{ + uint16 colorX, colorA, colorB, colorC, colorD; + uint16 *sP, *uP, *lP; + uint32 *dP1, *dP2; + int w; + + for (; height; height--) + { + sP = (uint16 *) srcPtr; + uP = (uint16 *) (srcPtr - srcPitch); + lP = (uint16 *) (srcPtr + srcPitch); + dP1 = (uint32 *) dstPtr; + dP2 = (uint32 *) (dstPtr + dstPitch); + + // left edge + + colorX = *sP; + colorC = *++sP; + colorB = *lP++; + colorD = *uP++; + + if ((colorX != colorC) && (colorB != colorD)) + { + #ifdef __BIG_ENDIAN__ + *dP1 = (colorX << 16) + ((colorC == colorD) ? AVERAGE_1555 (colorC, colorX) : colorX); + *dP2 = (colorX << 16) + ((colorB == colorC) ? AVERAGE_1555 (colorB, colorX) : colorX); + #else + *dP1 = colorX + (((colorC == colorD) ? AVERAGE_1555 (colorC, colorX) : colorX) << 16); + *dP2 = colorX + (((colorB == colorC) ? AVERAGE_1555 (colorB, colorX) : colorX) << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + dP1++; + dP2++; + + // + + for (w = width - 2; w; w--) + { + colorA = colorX; + colorX = colorC; + colorC = *++sP; + colorB = *lP++; + colorD = *uP++; + + if ((colorA != colorC) && (colorB != colorD)) + { + #ifdef __BIG_ENDIAN__ + *dP1 = (((colorD == colorA) ? AVERAGE_1555 (colorD, colorX) : colorX) << 16) + ((colorC == colorD) ? AVERAGE_1555 (colorC, colorX) : colorX); + *dP2 = (((colorA == colorB) ? AVERAGE_1555 (colorA, colorX) : colorX) << 16) + ((colorB == colorC) ? AVERAGE_1555 (colorB, colorX) : colorX); + #else + *dP1 = ((colorD == colorA) ? AVERAGE_1555 (colorD, colorX) : colorX) + (((colorC == colorD) ? AVERAGE_1555 (colorC, colorX) : colorX) << 16); + *dP2 = ((colorA == colorB) ? AVERAGE_1555 (colorA, colorX) : colorX) + (((colorB == colorC) ? AVERAGE_1555 (colorB, colorX) : colorX) << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + dP1++; + dP2++; + } + + // right edge + + colorA = colorX; + colorX = colorC; + colorB = *lP; + colorD = *uP; + + if ((colorA != colorX) && (colorB != colorD)) + { + #ifdef __BIG_ENDIAN__ + *dP1 = (((colorD == colorA) ? AVERAGE_1555 (colorD, colorX) : colorX) << 16) + colorX; + *dP2 = (((colorA == colorB) ? AVERAGE_1555 (colorA, colorX) : colorX) << 16) + colorX; + #else + *dP1 = ((colorD == colorA) ? AVERAGE_1555 (colorD, colorX) : colorX) + (colorX << 16); + *dP2 = ((colorA == colorB) ? AVERAGE_1555 (colorA, colorX) : colorX) + (colorX << 16); + #endif + } + else + *dP1 = *dP2 = (colorX << 16) + colorX; + + srcPtr += srcPitch; + dstPtr += dstPitch << 1; + } + + return; +} diff --git a/gtk/src/filter_epx_unsafe.h b/gtk/src/filter_epx_unsafe.h new file mode 100644 index 00000000..29792035 --- /dev/null +++ b/gtk/src/filter_epx_unsafe.h @@ -0,0 +1,7 @@ +#ifndef __FILTER_EPX_UNSAFE_H +#define __FILTER_EPX_UNSAFE_H + +void EPX_16_unsafe (uint8 *, uint32, uint8 *, uint32, int, int); +void EPX_16_smooth_unsafe (uint8 *, uint32, uint8 *, uint32, int, int); + +#endif /* __FILTER_EPX_UNSAFE_H */ diff --git a/gtk/src/gtk_binding.cpp b/gtk/src/gtk_binding.cpp new file mode 100644 index 00000000..fc5ca9f7 --- /dev/null +++ b/gtk/src/gtk_binding.cpp @@ -0,0 +1,229 @@ +#include +#include +#include +#include +#include + +#include "gtk_s9x.h" +#include "gtk_binding.h" + +Binding::Binding (void) +{ + value = 0; + + return; +} + +Binding::Binding (GdkEventKey *event) +{ + /* Make keypress lower-case */ + if (event->keyval >= GDK_A && event->keyval <= GDK_Z) + value = BINDING_KEY | ((event->keyval - GDK_A + GDK_a) & BINDING_KEY_MASK); + else + value = BINDING_KEY | (event->keyval & BINDING_KEY_MASK); + + /* Strip modifiers from modifiers */ + if (event->keyval == GDK_Control_L || + event->keyval == GDK_Control_R || + event->keyval == GDK_Shift_L || + event->keyval == GDK_Shift_R || + event->keyval == GDK_Alt_L || + event->keyval == GDK_Alt_R) + { + return; + } + + if (event->state & GDK_SHIFT_MASK) + value |= BINDING_SHIFT; + + if (event->state & GDK_CONTROL_MASK) + value |= BINDING_CTRL; + + if (event->state & GDK_MOD1_MASK) + value |= BINDING_ALT; + + return; +} + +Binding::Binding (unsigned int key, bool ctrl, bool shift, bool alt) +{ + value = BINDING_KEY; + + value |= key & BINDING_KEY_MASK; + if (ctrl) + value |= BINDING_CTRL; + if (shift) + value |= BINDING_SHIFT; + if (alt) + value |= BINDING_ALT; +} + +Binding::Binding (unsigned int device, + unsigned int button, + unsigned int threshold) +{ + value = BINDING_JOY; + value |= JOY_DEVICE_MASK (device + 1); + value |= BINDING_KEY_MASK & button; + if (button >= 512) + value |= THRESHOLD_MASK (threshold); +} + +Binding::Binding (unsigned int val) +{ + value = val; + + return; +} + +Binding::Binding (const Binding& binding) +{ + this->value = binding.value; +} + +bool +Binding::matches (Binding &binding) +{ + if ((value & ~BINDING_THRESHOLD_MASK) == + (binding.value & ~BINDING_THRESHOLD_MASK) && + is_joy ()) + return true; + + return false; +} + +void +Binding::clear (void) +{ + value = 0; + + return; +} + +unsigned int +Binding::hex (void) +{ + return value; +} + +unsigned int +Binding::base_hex (void) +{ + return (value & ~BINDING_THRESHOLD_MASK); +} + +bool +Binding::is_joy (void) +{ + return (value & BINDING_JOY); +} + +bool +Binding::is_key (void) +{ + return (value & BINDING_KEY); +} + +unsigned int +Binding::get_key (void) +{ + return (value & BINDING_KEY_MASK); +} + +unsigned int +Binding::get_device (void) +{ + return JOY_DEVICE_UNMASK (value); +} + +unsigned int +Binding::get_threshold (void) +{ + return THRESHOLD_UNMASK (value); +} + +unsigned int +Binding::get_axis (void) +{ + return JOY_AXIS_UNMASK (value); +} + +GdkModifierType +Binding::get_gdk_modifiers (void) +{ + return (GdkModifierType) ((BINDING_CTRL & value ? GDK_CONTROL_MASK : 0) | + (BINDING_ALT & value ? GDK_MOD1_MASK : 0) | + (BINDING_SHIFT & value ? GDK_SHIFT_MASK : 0)); +} + +bool +Binding::is_positive (void) +{ + return JOY_DIRECTION_UNMASK (value) == AXIS_POS; +} + +bool +Binding::is_negative (void) +{ + return JOY_DIRECTION_UNMASK (value) == AXIS_NEG; +} + +void +Binding::to_string (char *str) +{ + char buf[256]; + char *c; + + str[0] = '\0'; + + if (is_key ()) + { + char *keyval_name = NULL; + unsigned int keyval = gdk_keyval_to_lower (get_key ()); + keyval_name = gdk_keyval_name (keyval); + + if (keyval_name == NULL) + { + sprintf (buf, _("Unknown")); + } + + else + { + strncpy (buf, + keyval_name, + 256); + } + + while ((c = strstr (buf, "_"))) + { + *c = ' '; + } + + sprintf (str, _("Keyboard %s%s%s%s"), + value & BINDING_SHIFT ? "Shift+" : "", + value & BINDING_CTRL ? "Ctrl+" : "", + value & BINDING_ALT ? "Alt+" : "", + buf); + } + + else if (is_joy ()) + { + if ((get_key ()) >= 512) + sprintf (buf, + _("Axis #%d %s %d%%"), + get_axis (), + is_positive () ? "+" : "-", + get_threshold ()); + else + sprintf (buf, _("Button %d"), get_key ()); + + sprintf (str, _("Joystick %d %s"), get_device (), buf); + } + + else + { + sprintf (str, _("Unset")); + } + + return; +} diff --git a/gtk/src/gtk_binding.h b/gtk/src/gtk_binding.h new file mode 100644 index 00000000..de8a2270 --- /dev/null +++ b/gtk/src/gtk_binding.h @@ -0,0 +1,57 @@ +#ifndef __GTK_BINDING_H +#define __GTK_BINDING_H + +#include + +#define AXIS_POS 1 +#define AXIS_NEG 0 +#define JOY_AXIS(axis, button) (512 + ((axis) * 2 + (button))) +#define JOY_AXIS_UNMASK(bin) ((((bin) & 0x0000ffff) - 512) / 2) +#define JOY_DIRECTION_UNMASK(bin) ((((bin) & 0x0000ffff) - 512) % 2) +#define BINDING_KEY 0x10000000 +#define BINDING_JOY 0x20000000 +#define BINDING_CTRL 0x01000000 +#define BINDING_SHIFT 0x02000000 +#define BINDING_ALT 0x04000000 +#define BINDING_JOYDEV_MASK 0x0f000000 +#define BINDING_THRESHOLD_MASK 0x00ff0000 +#define BINDING_KEY_MASK 0x0000ffff +#define THRESHOLD_MASK(threshold) ((threshold) << 16) +#define THRESHOLD_UNMASK(bin) (((bin) & 0x00ff0000) >> 16) +#define JOY_DEVICE_MASK(devnum) ((devnum) << 24) +#define JOY_DEVICE_UNMASK(bin) (((bin) & 0x0f000000) >> 24) +#define BINDING_MOUSE_POINTER 0x41000000 +#define BINDING_MOUSE_BUTTON0 0x42000000 +#define BINDING_MOUSE_BUTTON1 0x42000001 +#define BINDING_MOUSE_BUTTON2 0x42000002 + +class Binding +{ + public: + Binding (unsigned int key, bool ctrl, bool shift, bool alt); + Binding (unsigned int device, unsigned int button, unsigned int threshold); + Binding (const Binding &binding); + Binding (GdkEventKey *event); + Binding (unsigned int); + Binding (void); + void to_string (char *str); + unsigned int hex (void); + unsigned int base_hex (void); + bool matches (Binding &binding); + void clear (void); + bool is_joy (void); + bool is_key (void); + bool is_mouse (void); + bool is_positive (void); + bool is_negative (void); + unsigned int get_key (void); + unsigned int get_device (void); + unsigned int get_threshold (void); + unsigned int get_axis (void); + GdkModifierType get_gdk_modifiers (void); + + private: + unsigned int value; +}; + +#endif /* __GTK_BINDING_H_ */ diff --git a/gtk/src/gtk_cheat.cpp b/gtk/src/gtk_cheat.cpp new file mode 100644 index 00000000..442d1803 --- /dev/null +++ b/gtk/src/gtk_cheat.cpp @@ -0,0 +1,318 @@ +#include "gtk_s9xcore.h" + +#include "gtk_s9x.h" +#include "gtk_cheat.h" + +enum +{ + COLUMN_ENABLED = 0, + COLUMN_DESCRIPTION = 1, + COLUMN_CHEAT = 2, + NUM_COLS +}; + +extern SCheatData Cheat; + +static void +display_errorbox (const char *error) +{ + GtkWidget *dialog = gtk_message_dialog_new (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "%s", + error); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + return; +} + +static void +event_add_code (GtkButton *button, gpointer data) +{ + ((Snes9xCheats *) data)->add_code (); +} + +static void +event_remove_code (GtkButton *button, gpointer data) +{ + ((Snes9xCheats *) data)->remove_code (); +} + +static void +event_code_toggled (GtkCellRendererToggle *cell_renderer, + gchar *path, + gpointer data) +{ + ((Snes9xCheats *) data)->toggle_code (path); + + return; +} + +Snes9xCheats::Snes9xCheats (void) + : GladeWindow (snes9x_glade, snes9x_glade_size, "cheat_window") +{ + GtkTreeView *view; + GtkCellRenderer *renderer; + GladeWindowCallbacks callbacks[] = + { + { "add_code", G_CALLBACK (event_add_code) }, + { "remove_code", G_CALLBACK (event_remove_code) }, + { NULL, NULL} + }; + + view = GTK_TREE_VIEW (get_widget ("cheat_treeview")); + + + renderer = gtk_cell_renderer_toggle_new (); + gtk_tree_view_insert_column_with_attributes (view, + -1, + "", + renderer, + "active", COLUMN_ENABLED, + NULL); + + g_signal_connect (renderer, + "toggled", + G_CALLBACK (event_code_toggled), + (gpointer) this); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, + -1, + _("Description"), + renderer, + "text", COLUMN_DESCRIPTION, + NULL); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, + -1, + _("Cheat"), + renderer, + "text", COLUMN_CHEAT, + NULL); + + store = gtk_list_store_new (NUM_COLS, + G_TYPE_BOOLEAN, + G_TYPE_STRING, + G_TYPE_STRING); + + gtk_tree_view_set_model (view, GTK_TREE_MODEL (store)); + + gtk_widget_realize (window); + + gtk_combo_box_set_active (GTK_COMBO_BOX (get_widget ("code_type_combo")), + 0); + + signal_connect (callbacks); + + return; +} + +Snes9xCheats::~Snes9xCheats (void) +{ + gtk_widget_destroy (window); + + g_object_unref (store); + + return; +} + +void +Snes9xCheats::show (void) +{ + top_level->pause_from_focus_change (); + + gtk_window_set_transient_for (GTK_WINDOW (window), + top_level->get_window ()); + + refresh_tree_view (); + gtk_dialog_run (GTK_DIALOG (window)); + + top_level->unpause_from_focus_change (); + + return; +} + +int +Snes9xCheats::get_selected_index (void) +{ + GtkTreeSelection *selection; + GList *rows; + gint *indices; + int index; + GtkTreeModel *model = GTK_TREE_MODEL (store); + + selection = + gtk_tree_view_get_selection ( + GTK_TREE_VIEW (get_widget ("cheat_treeview"))); + + rows = gtk_tree_selection_get_selected_rows (selection, + &model); + + if (rows) + { + indices = gtk_tree_path_get_indices ((GtkTreePath *) (rows->data)); + + index = indices[0]; + + for (GList *i = rows; i; i = i->next) + gtk_tree_path_free ((GtkTreePath *)(i->data)); + + g_list_free (rows); + } + else + index = -1; + + return index; +} + +int +Snes9xCheats::get_index_from_path (const gchar *path) +{ + GtkTreePath *tree_path = gtk_tree_path_new_from_string (path); + gint *indices = gtk_tree_path_get_indices (tree_path); + int index = indices[0]; + gtk_tree_path_free (tree_path); + + return index; +} + +void +Snes9xCheats::refresh_tree_view (void) +{ + GtkTreeIter iter; + char str [1024]; + + gtk_list_store_clear (store); + + for (unsigned int i = 0; i < Cheat.num_cheats; i++) + { + snprintf (str, + 1024, + "%06x:%02x/%02x", + Cheat.c [i].address, + Cheat.c [i].byte, + Cheat.c [i].saved_byte); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + COLUMN_DESCRIPTION, + !strcmp (Cheat.c [i].name, "") ? _("No description") + : Cheat.c [i].name, + COLUMN_CHEAT, str, + COLUMN_ENABLED, Cheat.c [i].enabled, + -1); + } + + + return; +} + +void +Snes9xCheats::add_code (void) +{ + uint32 address; + uint8 byte; + uint8 bytes [3]; + bool8 sram; + uint8 num_bytes; + const char *error; + int errorno = 0; + + int type = get_combo ("code_type_combo"); + + const gchar *code = get_entry_text ("code_entry"); + + switch (type) + { + case TYPE_GAME_GENIE: + if ((error = S9xGameGenieToRaw (code, address, byte)) == NULL) + S9xAddCheat (TRUE, FALSE, address, byte); + else + { + display_errorbox (error); + errorno = 1; + } + break; + + case TYPE_ACTION_REPLAY: + if ((error = S9xProActionReplayToRaw (code, address, byte)) == NULL) + S9xAddCheat (TRUE, FALSE, address, byte); + else + { + display_errorbox (error); + errorno = 1; + } + + break; + + case TYPE_GOLDFINGER: + + if ((error = S9xGoldFingerToRaw (code, address, sram, + num_bytes, bytes)) == NULL) + { + for (int c = 0; c < num_bytes; c++) + S9xAddCheat (TRUE, FALSE, address + c, bytes [c]); + } + else + { + display_errorbox (error); + errorno = 1; + } + + break; + } + + if (!errorno) + { + const char *entry_text = get_entry_text ("description_entry"); + + if (strlen (entry_text) <= 0) + strncpy (Cheat.c[Cheat.num_cheats - 1].name, _("No description"), 22); + else + strncpy (Cheat.c[Cheat.num_cheats - 1].name, entry_text, 22); + } + + gtk_widget_grab_focus (get_widget ("code_entry")); + + refresh_tree_view (); + + return; +} + +void +Snes9xCheats::remove_code (void) +{ + int index = get_selected_index (); + + if (index < 0) + return; + + S9xDeleteCheat (index); + + refresh_tree_view (); + + return; +} + +void +Snes9xCheats::toggle_code (const gchar *path) +{ + int index = get_index_from_path (path); + + if (index < 0) + return; + + if (Cheat.c[index].enabled) + S9xDisableCheat (index); + else + S9xEnableCheat (index); + + refresh_tree_view (); + + return; +} + diff --git a/gtk/src/gtk_cheat.h b/gtk/src/gtk_cheat.h new file mode 100644 index 00000000..c1df7f7c --- /dev/null +++ b/gtk/src/gtk_cheat.h @@ -0,0 +1,28 @@ +#ifndef __GTK_CHEAT_H +#define __GTK_CHEAT_H + +#include "gtk_glade_window.h" + +#define TYPE_GAME_GENIE 0 +#define TYPE_ACTION_REPLAY 1 +#define TYPE_GOLDFINGER 2 + +class Snes9xCheats : public GladeWindow +{ + public: + Snes9xCheats (void); + ~Snes9xCheats (void); + void show (void); + void add_code (void); + void remove_code (void); + void toggle_code (const gchar *path); + + private: + void refresh_tree_view (void); + int get_selected_index (void); + int get_index_from_path (const gchar *path); + + GtkListStore *store; +}; + +#endif /* __GTK_CHEAT_H */ diff --git a/gtk/src/gtk_config.cpp b/gtk/src/gtk_config.cpp new file mode 100644 index 00000000..0cbeb545 --- /dev/null +++ b/gtk/src/gtk_config.cpp @@ -0,0 +1,1141 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gtk_config.h" +#include "gtk_s9x.h" +#include "gtk_sound.h" +#include "gtk_display.h" + +char * +get_config_dir (void) +{ + char *homedir, *configdir; + + /* Find config directory */ + homedir = getenv ("HOME"); + + if (!homedir) + { + configdir = strdup (".snes9x"); + } + else + { + configdir = (char *) malloc (strlen (homedir) + 9); + sprintf (configdir, "%s/.snes9x", homedir); + } + + return configdir; +} + +char * +get_config_file_name (void) +{ + char *filename; + + filename = get_config_dir (); + + filename = (char *) realloc (filename, strlen (filename) + 12); + strcat (filename, "/snes9x.xml"); + + return filename; +} + +static void +xml_out_string (xmlTextWriterPtr xml, const char *name, const char *value) +{ + xmlTextWriterStartElement (xml, BAD_CAST ("option")); + xmlTextWriterWriteAttribute (xml, BAD_CAST ("name"), BAD_CAST (name)); + xmlTextWriterWriteAttribute (xml, BAD_CAST ("value"), BAD_CAST (value)); + xmlTextWriterEndElement (xml); +} + +static void +xml_out_int (xmlTextWriterPtr xml, const char *name, int value) +{ + char string[1024]; + snprintf (string, 1024, "%d", value); + + xmlTextWriterStartElement (xml, BAD_CAST "option"); + xmlTextWriterWriteAttribute (xml, BAD_CAST "name", BAD_CAST name); + xmlTextWriterWriteAttribute (xml, BAD_CAST "value", BAD_CAST string); + xmlTextWriterEndElement (xml); +} + +static void +xml_out_float (xmlTextWriterPtr xml, const char *name, float value) +{ + char string[1024]; + snprintf (string, 1024, "%f", value); + + xmlTextWriterStartElement (xml, BAD_CAST "option"); + xmlTextWriterWriteAttribute (xml, BAD_CAST "name", BAD_CAST name); + xmlTextWriterWriteAttribute (xml, BAD_CAST "value", BAD_CAST string); + xmlTextWriterEndElement (xml); +} + +static void +xml_out_binding (xmlTextWriterPtr xml, const char *name, unsigned int value) +{ + char string[1024]; + snprintf (string, 1024, "%u", value); + + xmlTextWriterStartElement (xml, BAD_CAST ("binding")); + xmlTextWriterWriteAttribute (xml, BAD_CAST ("name"), BAD_CAST (name)); + xmlTextWriterWriteAttribute (xml, BAD_CAST ("binding"), BAD_CAST (string)); + xmlTextWriterEndElement (xml); +} + +void +S9xParsePortConfig (ConfigFile &conf, int pass) +{ + return; +} + +Snes9xConfig::Snes9xConfig (void) +{ +#ifdef USE_JOYSTICK + joystick = NULL; + joystick_threshold = 50; +#endif + +#ifdef USE_OPENGL + opengl_activated = FALSE; +#endif + + return; +} + +int +Snes9xConfig::load_defaults (void) +{ + full_screen_on_open = 0; + change_display_resolution = 0; + xrr_index = 0; + xrr_width = 0; + xrr_height = 0; + scale_to_fit = 1; + maintain_aspect_ratio = 0; + aspect_ratio = 0; + scale_method = 0; + overscan = 0; + data_location = DIR_ROM; + save_sram_after_secs = 0; + rom_loaded = 0; + multithreading = 0; + hw_accel = 0; + allow_opengl = 0; + allow_xv = 0; + allow_xrandr = 0; + force_inverted_byte_order = FALSE; + force_hires = 0; + pause_emulation_on_switch = 0; + num_threads = 2; + mute_sound = FALSE; + fullscreen = FALSE; + ui_visible = TRUE; + statusbar_visible = TRUE; + default_esc_behavior = 1; + prevent_screensaver = FALSE; + sound_driver = 0; + sound_buffer_size = 64; + sound_playback_rate = 5; + sound_input_rate = 31950; + last_directory[0] = '\0'; + window_width = -1; + window_height = -1; + preferences_width = -1; + preferences_height = -1; + custom_sram_directory[0] = '\0'; + screensaver_needs_reset = FALSE; + ntsc_setup = snes_ntsc_composite; + ntsc_scanline_intensity = 1; + scanline_filter_intensity = 0; + netplay_activated = FALSE; + netplay_server_up = FALSE; + netplay_is_server = FALSE; + netplay_sync_reset = TRUE; + netplay_send_rom = FALSE; + netplay_default_port = 6096; + netplay_max_frame_loss = 10; + netplay_last_rom [0] = '\0'; + netplay_last_host [0] = '\0'; + netplay_last_port = 6096; + +#ifdef USE_OPENGL + bilinear_filter = 0; + sync_to_vblank = 1; + use_pbos = 1; + pbo_format = 0; + npot_textures = FALSE; +#endif + + /* Snes9X Variables */ + Settings.MouseMaster = TRUE; + Settings.SuperScopeMaster = TRUE; + Settings.JustifierMaster = TRUE; + Settings.MultiPlayer5Master = TRUE; + Settings.UpAndDown = FALSE; + Settings.AutoSaveDelay = 0; + Settings.SkipFrames = AUTO_FRAMERATE; + Settings.Transparency = TRUE; + Settings.DisplayFrameRate = FALSE; + Settings.SixteenBitSound = TRUE; + Settings.Stereo = TRUE; + Settings.ReverseStereo = FALSE; + Settings.SoundPlaybackRate = 32000; + Settings.DisableHDMA = 0; + Settings.ShutdownMaster = 0; + Settings.StopEmulation = TRUE; + Settings.DisableIRQ = FALSE; + Settings.FrameTimeNTSC = 16667; + Settings.FrameTimePAL = 20000; + Settings.SupportHiRes = true; + Settings.FrameTime = Settings.FrameTimeNTSC; + Settings.BlockInvalidVRAMAccessMaster = TRUE; + Settings.SoundSync = 1; + Settings.HDMATimingHack = 100; + +#ifdef NETPLAY_SUPPORT + Settings.NetPlay = FALSE; + NetPlay.Paused = FALSE; + NetPlay.MaxFrameSkip = 10; +#endif + + memset (pad, 0, sizeof (JoypadBinding) * NUM_JOYPADS); + memset (shortcut, 0, sizeof (Binding) * NUM_EMU_LINKS); + + return 0; +} + +#ifdef USE_JOYSTICK + +void +Snes9xConfig::joystick_register_centers (void) +{ + for (int i = 0; joystick[i] != NULL; i++) + joystick[i]->register_centers (); + + return; +} + +void +Snes9xConfig::flush_joysticks (void) +{ + int i; + + for (i = 0; joystick[i] != NULL; i++) + joystick[i]->flush (); + + return; +} + +void +Snes9xConfig::set_joystick_mode (int mode) +{ + int i; + for (i = 0; joystick[i] != NULL; i++) + joystick[i]->mode = mode; + + return; +} + +#endif + +int +Snes9xConfig::save_config_file (void) +{ + xmlTextWriterPtr xml; + char *filename; + char buffer[256]; + + filename = get_config_file_name (); + xml = xmlNewTextWriterFilename (filename, 0); + free (filename); + + xmlTextWriterSetIndent (xml, 1); + + xmlTextWriterStartDocument (xml, NULL, NULL, NULL); + xmlTextWriterStartElement (xml, BAD_CAST "snes9x"); + xmlTextWriterStartElement (xml, BAD_CAST "preferences"); + + xml_out_int (xml, "full_screen_on_open", full_screen_on_open); + xml_out_int (xml, "change_display_resolution", change_display_resolution); + xml_out_int (xml, "video_mode", xrr_index); + xml_out_int (xml, "video_mode_width", xrr_width); + xml_out_int (xml, "video_mode_height", xrr_height); + xml_out_int (xml, "scale_to_fit", scale_to_fit); + xml_out_int (xml, "maintain_aspect_ratio", maintain_aspect_ratio); + xml_out_int (xml, "aspect_ratio", aspect_ratio); + xml_out_int (xml, "scale_method", scale_method); + xml_out_int (xml, "overscan", overscan); + xml_out_int (xml, "force_hires", force_hires); + xml_out_int (xml, "force_inverted_byte_order", force_inverted_byte_order); + xml_out_int (xml, "data_location", data_location); + xml_out_int (xml, "multithreading", multithreading); + xml_out_string (xml, "last_directory", last_directory); + xml_out_string (xml, "custom_sram_directory", custom_sram_directory); + xml_out_int (xml, "window_width", window_width); + xml_out_int (xml, "window_height", window_height); + xml_out_int (xml, "preferences_width", preferences_width); + xml_out_int (xml, "preferences_height", preferences_height); + xml_out_int (xml, "pause_emulation_on_switch", pause_emulation_on_switch); + xml_out_int (xml, "num_threads", num_threads); + xml_out_int (xml, "default_esc_behavior", default_esc_behavior); + xml_out_int (xml, "prevent_screensaver", prevent_screensaver); + if (default_esc_behavior != ESC_TOGGLE_MENUBAR) + xml_out_int (xml, "fullscreen", 0); + else + xml_out_int (xml, "fullscreen", fullscreen); + xml_out_int (xml, "ui_visible", ui_visible); + xml_out_int (xml, "statusbar_visible", statusbar_visible); + + xml_out_float (xml, "ntsc_hue", ntsc_setup.hue); + xml_out_float (xml, "ntsc_saturation", ntsc_setup.saturation); + xml_out_float (xml, "ntsc_contrast", ntsc_setup.contrast); + xml_out_float (xml, "ntsc_brightness", ntsc_setup.brightness); + xml_out_float (xml, "ntsc_sharpness", ntsc_setup.sharpness); + xml_out_float (xml, "ntsc_artifacts", ntsc_setup.artifacts); + xml_out_float (xml, "ntsc_gamma", ntsc_setup.gamma); + xml_out_float (xml, "ntsc_bleed", ntsc_setup.bleed); + xml_out_float (xml, "ntsc_fringing", ntsc_setup.fringing); + xml_out_float (xml, "ntsc_resolution", ntsc_setup.resolution); + xml_out_int (xml, "ntsc_merge_fields", ntsc_setup.merge_fields); + xml_out_int (xml, "ntsc_scanline_intensity", ntsc_scanline_intensity); + xml_out_int (xml, "scanline_filter_intensity", scanline_filter_intensity); + xml_out_int (xml, "hw_accel", hw_accel); + +#ifdef USE_OPENGL + xml_out_int (xml, "bilinear_filter", bilinear_filter); + xml_out_int (xml, "sync_to_vblank", sync_to_vblank); + xml_out_int (xml, "use_pbos", use_pbos); + xml_out_int (xml, "pbo_format", pbo_format); + xml_out_int (xml, "npot_textures", npot_textures); +#endif + +#ifdef USE_JOYSTICK + xml_out_int (xml, "joystick_threshold", joystick_threshold); +#endif + + xml_out_int (xml, "netplay_is_server", netplay_is_server); + xml_out_int (xml, "netplay_sync_reset", netplay_sync_reset); + xml_out_int (xml, "netplay_send_rom", netplay_send_rom); + xml_out_int (xml, "netplay_default_port", netplay_default_port); + xml_out_int (xml, "netplay_max_frame_loss", netplay_max_frame_loss); + xml_out_int (xml, "netplay_last_port", netplay_last_port); + xml_out_string (xml, "netplay_last_rom", netplay_last_rom); + xml_out_string (xml, "netplay_last_host", netplay_last_host); + + xml_out_int (xml, "mute_sound", mute_sound); + xml_out_int (xml, "sound_buffer_size", sound_buffer_size); + xml_out_int (xml, "sound_driver", sound_driver); + xml_out_int (xml, "sound_input_rate", sound_input_rate); + xml_out_int (xml, "sound_sync", Settings.SoundSync); + + /* Snes9X core-stored variables */ + xml_out_int (xml, "transparency", Settings.Transparency); + xml_out_int (xml, "show_frame_rate", Settings.DisplayFrameRate); + xml_out_int (xml, "frameskip", Settings.SkipFrames); + xml_out_int (xml, "save_sram_after_secs", Settings.AutoSaveDelay); + xml_out_int (xml, "16bit_sound", Settings.SixteenBitSound); + xml_out_int (xml, "stereo", Settings.Stereo); + xml_out_int (xml, "reverse_stereo", Settings.ReverseStereo); + xml_out_int (xml, "playback_rate", gui_config->sound_playback_rate); + xml_out_int (xml, "speedhacks", Settings.ShutdownMaster); + xml_out_int (xml, "hdma", !(Settings.DisableHDMA)); + xml_out_int (xml, "block_invalid_vram_access", Settings.BlockInvalidVRAMAccessMaster); + xml_out_int (xml, "upanddown", Settings.UpAndDown); + + xmlTextWriterEndElement (xml); /* preferences */ + + xmlTextWriterStartElement (xml, BAD_CAST "controls"); + +#ifdef USE_JOYSTICK + for (int i = 0; joystick[i]; i++) + { + xmlTextWriterStartElement (xml, BAD_CAST "calibration"); + snprintf (buffer, 256, "%d", i); + xmlTextWriterWriteAttribute (xml, BAD_CAST "joystick", BAD_CAST buffer); + + for (int j = 0; j < joystick[i]->num_axes; j++) + { + xmlTextWriterStartElement (xml, BAD_CAST "axis"); + + snprintf (buffer, 256, "%d", j); + xmlTextWriterWriteAttribute (xml, BAD_CAST "number", BAD_CAST buffer); + + snprintf (buffer, 256, "%d", joystick[i]->calibration[j].min); + xmlTextWriterWriteAttribute (xml, BAD_CAST "min", BAD_CAST buffer); + + snprintf (buffer, 256, "%d", joystick[i]->calibration[j].max); + xmlTextWriterWriteAttribute (xml, BAD_CAST "max", BAD_CAST buffer); + + snprintf (buffer, 256, "%d", joystick[i]->calibration[j].center); + xmlTextWriterWriteAttribute (xml, BAD_CAST "center", BAD_CAST buffer); + + xmlTextWriterEndElement (xml); /* axis */ + } + + xmlTextWriterEndElement (xml); /* Calibration */ + } +#endif + + for (int i = 0; i < NUM_JOYPADS; i++) + { + Binding *joypad = (Binding *) &pad[i]; + + xmlTextWriterStartElement (xml, BAD_CAST "joypad"); + snprintf (buffer, 256, "%d", i); + xmlTextWriterWriteAttribute (xml, BAD_CAST "number", BAD_CAST buffer); + + for (int j = 0; j < NUM_JOYPAD_LINKS; j++) + { + xml_out_binding (xml, b_links[j].snes9x_name, joypad[j].hex ()); + } + + xmlTextWriterEndElement (xml); /* joypad */ + } + + for (int i = NUM_JOYPAD_LINKS; b_links[i].snes9x_name; i++) + { + xml_out_binding (xml, + b_links[i].snes9x_name, + shortcut[i - NUM_JOYPAD_LINKS].hex ()); + } + + xmlTextWriterEndElement (xml); /* controls */ + xmlTextWriterEndElement (xml); /* snes9x */ + xmlTextWriterEndDocument (xml); + + xmlFreeTextWriter (xml); + + return 0; +} + +int +Snes9xConfig::set_option (const char *name, const char *value) +{ + if (!strcasecmp (name, "full_screen_on_open")) + { + full_screen_on_open = atoi (value); + } + else if (!strcasecmp (name, "change_display_resolution")) + { + change_display_resolution = atoi (value); + } + else if (!strcasecmp (name, "video_mode")) + { + } + else if (!strcasecmp (name, "video_mode_width")) + { + xrr_width = atoi (value); + } + else if (!strcasecmp (name, "video_mode_height")) + { + xrr_height = atoi (value); + } + else if (!strcasecmp (name, "scale_to_fit")) + { + scale_to_fit = atoi (value); + } + else if (!strcasecmp (name, "maintain_aspect_ratio")) + { + maintain_aspect_ratio = atoi (value); + } + else if (!strcasecmp (name, "aspect_ratio")) + { + aspect_ratio = atoi (value); + } + else if (!strcasecmp (name, "force_hires")) + { + force_hires = atoi (value); + } + else if (!strcasecmp (name, "scale_method")) + { + scale_method = atoi (value); + + if (scale_method >= NUM_FILTERS) + scale_method = 0; + } + else if (!strcasecmp (name, "multithreading")) + { + multithreading = atoi (value); + } + else if (!strcasecmp (name, "hw_accel")) + { + hw_accel = atoi (value); + } + else if (!strcasecmp (name, "use_opengl")) + { +#ifdef USE_OPENGL + if (atoi (value) == 1) + hw_accel = HWA_OPENGL; +#endif + } + else if (!strcasecmp (name, "bilinear_filter")) + { +#ifdef USE_OPENGL + bilinear_filter = atoi (value); +#endif + } + else if (!strcasecmp (name, "sync_to_vblank")) + { +#ifdef USE_OPENGL + sync_to_vblank = atoi (value); +#endif + } + else if (!strcasecmp (name, "use_pbos")) + { +#ifdef USE_OPENGL + use_pbos = atoi (value); +#endif + } + else if (!strcasecmp (name, "pbo_format")) + { +#ifdef USE_OPENGL + pbo_format = atoi (value); + pbo_format = CLAMP (pbo_format, 0, 2); +#endif + } + else if (!strcasecmp (name, "npot_textures")) + { +#ifdef USE_OPENGL + npot_textures = atoi (value); +#endif + } + else if (!strcasecmp (name, "joystick_threshold")) + { +#ifdef USE_JOYSTICK + joystick_threshold = atoi (value); +#endif + } + else if (!strcasecmp (name, "data_location")) + { + data_location = atoi (value); + } + else if (!strcasecmp (name, "save_sram_after_secs")) + { + Settings.AutoSaveDelay = atoi (value); + } + else if (!strcasecmp (name, "pause_emulation_on_switch")) + { + pause_emulation_on_switch = atoi (value); + } + else if (!strcasecmp (name, "transparency")) + { + Settings.Transparency = atoi (value); + } + else if (!strcasecmp (name, "show_frame_rate")) + { + Settings.DisplayFrameRate = atoi (value); + } + else if (!strcasecmp (name, "frameskip")) + { + Settings.SkipFrames = atoi (value); + } + else if (!strcasecmp (name, "sound_emulation")) + { + mute_sound = !(atoi (value)); + } + else if (!strcasecmp (name, "mute_sound")) + { + mute_sound = atoi (value); + } + else if (!strcasecmp (name, "16bit_sound")) + { + Settings.SixteenBitSound = atoi (value); + } + else if (!strcasecmp (name, "stereo")) + { + Settings.Stereo = atoi (value); + } + else if (!strcasecmp (name, "reverse_stereo")) + { + Settings.ReverseStereo = atoi (value); + } + else if (!strcasecmp (name, "gaussian_interpolation")) + { + } + else if (!strcasecmp (name, "envelope_reading")) + { + } + else if (!strcasecmp (name, "sound_echo")) + { + } + else if (!strcasecmp (name, "master_volume")) + { + } + else if (!strcasecmp (name, "playback_rate")) + { + sound_playback_rate = atoi (value); + } + else if (!strcasecmp (name, "sound_decoder")) + { + } + else if (!strcasecmp (name, "hdma")) + { + Settings.DisableHDMA = !(atoi (value)); + } + else if (!strcasecmp (name, "speedhacks")) + { + Settings.ShutdownMaster = atoi (value); + } + else if (!strcasecmp (name, "overscan")) + { + overscan = atoi (value); + } + else if (!strcasecmp (name, "last_directory")) + { + strncpy (last_directory, value, PATH_MAX); + } + else if (!strcasecmp (name, "custom_sram_directory")) + { + strncpy (custom_sram_directory, value, PATH_MAX); + } + else if (!strcasecmp (name, "window_width")) + { + window_width = atoi (value); + } + else if (!strcasecmp (name, "window_height")) + { + window_height = atoi (value); + } + else if (!strcasecmp (name, "preferences_width")) + { + preferences_width = atoi (value); + } + else if (!strcasecmp (name, "preferences_height")) + { + preferences_height = atoi (value); + } + else if (!strcasecmp (name, "ntsc_format")) + { + /* Deprecated */ + } + else if (!strcasecmp (name, "ntsc_hue")) + { + ntsc_setup.hue = (float) atof (value); + } + else if (!strcasecmp (name, "ntsc_saturation")) + { + ntsc_setup.saturation = (float) atof (value); + } + else if (!strcasecmp (name, "ntsc_contrast")) + { + ntsc_setup.contrast = (float) atof (value); + } + else if (!strcasecmp (name, "ntsc_brightness")) + { + ntsc_setup.brightness = (float) atof (value); + } + else if (!strcasecmp (name, "ntsc_sharpness")) + { + ntsc_setup.sharpness = (float) atof (value); + } + else if (!strcasecmp (name, "ntsc_warping")) + { + /* Deprecated */ + } + else if (!strcasecmp (name, "ntsc_artifacts")) + { + ntsc_setup.artifacts = (float) atof (value); + } + else if (!strcasecmp (name, "ntsc_gamma")) + { + ntsc_setup.gamma = (float) atof (value); + } + else if (!strcasecmp (name, "ntsc_fringing")) + { + ntsc_setup.fringing = (float) atof (value); + } + else if (!strcasecmp (name, "ntsc_bleed")) + { + ntsc_setup.bleed = (float) atof (value); + } + else if (!strcasecmp (name, "ntsc_resolution")) + { + ntsc_setup.resolution = (float) atof (value); + } + else if (!strcasecmp (name, "ntsc_merge_fields")) + { + ntsc_setup.merge_fields = atoi (value); + } + else if (!strcasecmp (name, "ntsc_scanline_intensity")) + { + ntsc_scanline_intensity = CLAMP (atoi (value), 0, 4); + } + else if (!strcasecmp (name, "scanline_filter_intensity")) + { + scanline_filter_intensity = CLAMP (atoi (value), 0, 3); + } + else if (!strcasecmp (name, "num_threads")) + { + num_threads = atoi (value); + } + else if (!strcasecmp (name, "netplay_is_server")) + { + netplay_is_server = atoi (value); + } + else if (!strcasecmp (name, "netplay_sync_reset")) + { + netplay_sync_reset = atoi (value); + } + else if (!strcasecmp (name, "netplay_send_rom")) + { + netplay_send_rom = atoi (value); + } + else if (!strcasecmp (name, "netplay_default_port")) + { + netplay_default_port = atoi (value); + } + else if (!strcasecmp (name, "netplay_max_frame_loss")) + { + netplay_max_frame_loss = atoi (value); + } + else if (!strcasecmp (name, "netplay_last_port")) + { + netplay_last_port = atoi (value); + } + else if (!strcasecmp (name, "netplay_last_rom")) + { + strncpy (netplay_last_rom, value, PATH_MAX); + } + else if (!strcasecmp (name, "netplay_last_host")) + { + strncpy (netplay_last_host, value, PATH_MAX); + } + else if (!strcasecmp (name, "fullscreen")) + { + fullscreen = atoi (value); + } + else if (!strcasecmp (name, "ui_visible")) + { + ui_visible = atoi (value); + } + else if (!strcasecmp (name, "statusbar_visible")) + { + statusbar_visible = atoi (value); + } + else if (!strcasecmp (name, "default_esc_behavior")) + { + default_esc_behavior = atoi (value); + } + else if (!strcasecmp (name, "sound_buffer_size")) + { + sound_buffer_size = atoi (value); + } + else if (!strcasecmp (name, "sound_input_rate")) + { + sound_input_rate = atoi (value); + } + else if (!strcasecmp (name, "sound_driver")) + { + sound_driver = atoi (value); + } + else if (!strcasecmp (name, "prevent_screensaver")) + { + prevent_screensaver = atoi (value); + } + else if (!strcasecmp (name, "force_inverted_byte_order")) + { + force_inverted_byte_order = atoi (value); + } + else if (!strcasecmp (name, "block_invalid_vram_access")) + { + Settings.BlockInvalidVRAMAccessMaster = CLAMP (atoi (value), 0, 1); + } + else if (!strcasecmp (name, "upanddown")) + { + Settings.UpAndDown = CLAMP (atoi (value), 0, 1); + } + else if (!strcasecmp (name, "sound_sync")) + { + Settings.SoundSync = atoi (value) ? 1 : 0; + } + else + { + fprintf (stderr, _("bad option name: %s\n"), name); + return 1; + } + + return 0; +} + +int +Snes9xConfig::parse_option (xmlNodePtr node) +{ + xmlAttrPtr attr = NULL; + char *name, *value; + + /* Find name string */ + for (attr = node->properties; attr; attr = attr->next) + { + if (!xmlStrcasecmp (attr->name, BAD_CAST "name")) + { + name = (char *) attr->children->content; + break; + } + } + + if (!attr) + return 1; + + /* Find value string */ + for (attr = node->properties; attr; attr = attr->next) + { + if (!xmlStrcasecmp (attr->name, BAD_CAST "value")) + { + value = (char *) attr->children->content; + break; + } + } + + if (!attr) + return 1; + + return set_option (name, value); +} + +int +Snes9xConfig::parse_binding (xmlNodePtr node, int joypad_number) +{ + char *name = NULL; + char *type = NULL; + Binding b; + + for (xmlAttrPtr attr = node->properties; attr; attr = attr->next) + { + if (!xmlStrcasecmp (attr->name, BAD_CAST "name")) + name = (char *) attr->children->content; + + else if (!xmlStrcasecmp (attr->name, BAD_CAST "binding")) + type = (char *) attr->children->content; + } + + b = Binding ((unsigned int) strtoul (type, NULL, 10)); + + if (joypad_number > -1 && joypad_number < NUM_JOYPAD_LINKS) + { + for (int i = 0; i < NUM_JOYPAD_LINKS; i++) + { + if (!strcasecmp (b_links[i].snes9x_name, name)) + { + Binding *buttons = (Binding *) &pad[joypad_number]; + + if (b.is_key () || b.is_joy ()) + buttons[i] = b; + else + buttons[i].clear (); + } + } + } + else + { + for (int i = NUM_JOYPAD_LINKS; b_links[i].snes9x_name; i++) + { + if (!strcasecmp (b_links[i].snes9x_name, name)) + { + if (b.is_key () || b.is_joy ()) + shortcut[i - NUM_JOYPAD_LINKS] = b; + else + shortcut[i - NUM_JOYPAD_LINKS].clear (); + + } + } + } + + return 0; +} + +int +Snes9xConfig::parse_joypad (xmlNodePtr node) +{ + xmlAttrPtr attr; + int joypad_number = -1; + int retval = 0; + + /* Try to read joypad number */ + for (attr = node->properties; attr; attr = attr->next) + { + if (!xmlStrcasecmp (attr->name, BAD_CAST "number")) + { + joypad_number = atoi ((char *) attr->children->content); + + if (joypad_number < 0 || joypad_number > (NUM_JOYPADS - 1)) + return 1; + } + } + + for (xmlNodePtr i = node->children; i; i = i->next) + { + if (!xmlStrcasecmp (i->name, BAD_CAST "binding")) + { + retval = parse_binding (i, joypad_number) || retval; + } + } + + return retval; +} + +#ifdef USE_JOYSTICK + +int +Snes9xConfig::parse_axis (xmlNodePtr node, int joynum) +{ + xmlAttrPtr attr; + int retval = 0; + + int number = -1, min = -32767, max = 32767, center = 0; + + for (attr = node->properties; attr; attr = attr->next) + { + if (!xmlStrcasecmp (attr->name, BAD_CAST "number")) + { + number = atoi ((char *) attr->children->content); + } + + else if (!xmlStrcasecmp (attr->name, BAD_CAST "min")) + { + min = atoi ((char *) attr->children->content); + } + + else if (!xmlStrcasecmp (attr->name, BAD_CAST "max")) + { + max = atoi ((char *) attr->children->content); + } + + else if (!xmlStrcasecmp (attr->name, BAD_CAST "center")) + { + center = atoi ((char *) attr->children->content); + } + } + + if (number >= 0 && number < joystick[joynum]->num_axes) + { + joystick[joynum]->calibration[number].min = min; + joystick[joynum]->calibration[number].max = max; + joystick[joynum]->calibration[number].center = center; + } + + return retval; +} + +int +Snes9xConfig::parse_calibration (xmlNodePtr node) +{ + xmlAttrPtr attr; + int joynum = -1; + int num_joysticks = 0; + int retval = 0; + + for (num_joysticks = 0; joystick[num_joysticks]; num_joysticks++) + { + } + + for (attr = node->properties; attr; attr = attr->next) + { + if (!xmlStrcasecmp (attr->name, BAD_CAST "joystick")) + { + joynum = atoi ((char *) attr->children->content); + + if (joynum < 0 || joynum >= num_joysticks) + return 0; + } + } + + for (xmlNodePtr i = node->children; i; i = i->next) + { + if (!xmlStrcasecmp (i->name, BAD_CAST "axis")) + { + retval = parse_axis (i, joynum) | retval; + } + } + + return retval; +} + +#endif + +int +Snes9xConfig::parse_preferences (xmlNodePtr node) +{ + xmlNodePtr i = NULL; + int retval = 0; + + for (i = node->children; i; i = i->next) + { + if (!xmlStrcasecmp (i->name, BAD_CAST "option")) + retval = parse_option (i) || retval; + } + + return retval; +} + +int +Snes9xConfig::parse_controls (xmlNodePtr node) +{ + int retval = 0; + + for (xmlNodePtr i = node->children; i; i = i->next) + { + if (!xmlStrcasecmp (i->name, BAD_CAST "joypad")) + retval = parse_joypad (i) || retval; + + if (!xmlStrcasecmp (i->name, BAD_CAST "binding")) + retval = parse_binding (i, -1) || retval; + +#ifdef USE_JOYSTICK + if (!xmlStrcasecmp (i->name, BAD_CAST "calibration")) + retval = parse_calibration (i) || retval; +#endif + } + + return retval; +} + +int +Snes9xConfig::parse_snes9x (xmlNodePtr node) +{ + xmlNodePtr i = NULL; + int retval = 0; + + if (xmlStrcasecmp (node->name, BAD_CAST "snes9x")) + { + fprintf (stderr, _("failure to read snes9x node")); + return 1; + } + + for (i = node->children; i; i = i->next) + { + if (!xmlStrcasecmp (i->name, BAD_CAST "preferences")) + { + retval = parse_preferences (i) || retval; + } + + else if (!xmlStrcasecmp (i->name, BAD_CAST "controls")) + { + retval = parse_controls (i) || retval; + } + } + + return 0; +} + +int +Snes9xConfig::load_config_file (void) +{ + struct stat file_info; + char *pathname; + xmlDoc *xml_doc = NULL; + xmlNodePtr xml_root = NULL; + + load_defaults (); + + pathname = get_config_dir (); + + if (stat (pathname, &file_info)) + { + if (mkdir (pathname, 0)) + { + fprintf (stderr, + _("Couldn't create config directory: %s\n"), + pathname); + return -1; + } + } + + free (pathname); + + pathname = get_config_file_name (); + + if (stat (pathname, &file_info)) + { + save_config_file (); + } + + xml_doc = xmlReadFile (pathname, NULL, 0); + + if (!xml_doc) + { + fprintf (stderr, _("Couldn't open config file: %s\n"), pathname); + return -2; + } + + free (pathname); + + xml_root = xmlDocGetRootElement (xml_doc); + + parse_snes9x (xml_root); + + return 0; +} + +void +Snes9xConfig::rebind_keys (void) +{ + s9xcommand_t cmd; + char buf[256]; + + S9xUnmapAllControls (); + + for (int joypad_i = 0; joypad_i < NUM_JOYPADS; joypad_i++ ) + { + Binding *bin = (Binding *) &pad[joypad_i]; + + for (int button_i = 0; button_i < NUM_JOYPAD_LINKS; button_i++) + { + snprintf (buf, + 256, + "Joypad%d %s", + (joypad_i % 5) + 1, + b_links[button_i].snes9x_name); + + cmd = S9xGetPortCommandT (buf); + + S9xMapButton (bin[button_i].base_hex (), cmd, FALSE); + } + } + + for (int i = NUM_JOYPAD_LINKS; b_links[i].snes9x_name; i++) + { + snprintf (buf, 256, "%s", b_links[i].snes9x_name); + cmd = S9xGetPortCommandT (buf); + S9xMapButton (shortcut[i - NUM_JOYPAD_LINKS].base_hex (), + cmd, + FALSE); + } + + cmd = S9xGetPortCommandT ("Pointer Mouse1+Superscope+Justifier1"); + S9xMapPointer (BINDING_MOUSE_POINTER, cmd, TRUE); + + cmd = S9xGetPortCommandT ("{Mouse1 L,Superscope Fire,Justifier1 Trigger}"); + S9xMapButton (BINDING_MOUSE_BUTTON0, cmd, FALSE); + + cmd = S9xGetPortCommandT ("{Justifier1 AimOffscreen Trigger,Superscope AimOffscreen}"); + S9xMapButton (BINDING_MOUSE_BUTTON1, cmd, FALSE); + + cmd = S9xGetPortCommandT ("{Mouse1 R,Superscope Cursor,Justifier1 Start}"); + S9xMapButton (BINDING_MOUSE_BUTTON2, cmd, FALSE); + + return; +} + +void +Snes9xConfig::reconfigure (void) +{ + rebind_keys (); + + return; +} + + + diff --git a/gtk/src/gtk_config.h b/gtk/src/gtk_config.h new file mode 100644 index 00000000..94b4c346 --- /dev/null +++ b/gtk/src/gtk_config.h @@ -0,0 +1,155 @@ +#ifndef __GTK_CONFIG_H +#define __GTK_CONFIG_H + +#include +#include +#ifdef USE_XRANDR +#include +#endif + +#include "gtk_control.h" +#include "snes_ntsc.h" + +#define DIR_ROM 0 +#define DIR_CONFIG 1 +#define DIR_CUSTOM 2 + +#define HWA_NONE 0 +#define HWA_OPENGL 1 +#define HWA_XV 2 + +#define ESC_TOGGLE_MENUBAR 0 +#define ESC_EXIT_FULLSCREEN 1 +#define ESC_EXIT_SNES9X 2 + +class Snes9xConfig +{ + public: + Snes9xConfig (void); + int load_config_file (void); + int save_config_file (void); + int load_defaults (void); + void reconfigure (void); + void rebind_keys (void); + + /* XML parsers */ + int parse_snes9x (xmlNodePtr node); + int parse_preferences (xmlNodePtr node); + int parse_option (xmlNodePtr node); + int parse_joypad (xmlNodePtr node); + int parse_binding (xmlNodePtr node, int joypad_number); + int parse_controls (xmlNodePtr node); + int set_option (const char *name, const char *value); + +#ifdef USE_JOYSTICK + void flush_joysticks (void); + void set_joystick_mode (int mode); + void joystick_register_centers (void); + int parse_calibration (xmlNodePtr node); + int parse_axis (xmlNodePtr node, int joystick_number); +#endif + + /* Screen options */ + unsigned char full_screen_on_open; + unsigned char change_display_resolution; + unsigned char fullscreen; + unsigned char ui_visible; + unsigned char statusbar_visible; + unsigned char default_esc_behavior; + unsigned char prevent_screensaver; + unsigned int xrr_index; + int xrr_width; + int xrr_height; + unsigned char scale_to_fit; + unsigned char maintain_aspect_ratio; + int aspect_ratio; + unsigned int scale_method; + unsigned char overscan; + unsigned char multithreading; + unsigned char force_hires; + unsigned char force_inverted_byte_order; + + snes_ntsc_setup_t ntsc_setup; + unsigned char ntsc_format; + float ntsc_hue; + float ntsc_saturation; + float ntsc_contrast; + float ntsc_brightness; + float ntsc_sharpness; + float ntsc_artifacts; + float ntsc_gamma; + float ntsc_resolution; + float ntsc_fringing; + float ntsc_bleed; + float ntsc_merge_fields; + unsigned int ntsc_scanline_intensity; + unsigned int scanline_filter_intensity; + unsigned char hw_accel; + unsigned char allow_opengl; + unsigned char allow_xv; + unsigned char allow_xrandr; + + /* Data options */ + unsigned char data_location; + unsigned char save_sram_after_secs; + char custom_sram_directory [PATH_MAX]; + char last_directory [PATH_MAX]; + + /* Controls */ + JoypadBinding pad[NUM_JOYPADS]; + Binding shortcut[NUM_EMU_LINKS]; + + /* Netplay */ + int netplay_is_server; + int netplay_sync_reset; + int netplay_send_rom; + int netplay_default_port; + int netplay_max_frame_loss; + char netplay_last_rom [PATH_MAX]; + char netplay_last_host [PATH_MAX]; + int netplay_last_port; + int netplay_activated; + int netplay_server_up; + + /* Operational */ + int sound_driver; + int mute_sound; + int sound_buffer_size; + int sound_playback_rate; + int sound_input_rate; + int rom_loaded; + int window_width, window_height; + int preferences_width, preferences_height; + int pause_emulation_on_switch; + int num_threads; + unsigned char screensaver_needs_reset; + +#ifdef USE_XRANDR + XRRScreenConfiguration *xrr_config; + XRRScreenSize *xrr_sizes; + int xrr_num_sizes; + Rotation xrr_rotation; + SizeID xrr_original_size; +#endif + + +#ifdef USE_OPENGL + unsigned char bilinear_filter; + unsigned char sync_to_vblank; + unsigned char opengl_activated; + unsigned char use_pbos; + int pbo_format; + unsigned char npot_textures; +#endif + +#ifdef USE_JOYSTICK + JoyDevice **joystick; + int joystick_threshold; +#endif + +}; + +char *get_config_dir (void); +char *get_config_file_name (void); + +#endif /* __GTK_CONFIG_H */ diff --git a/gtk/src/gtk_control.cpp b/gtk/src/gtk_control.cpp new file mode 100644 index 00000000..5498bfab --- /dev/null +++ b/gtk/src/gtk_control.cpp @@ -0,0 +1,686 @@ +#include +#ifdef USE_JOYSTICK +# include "SDL.h" +#endif + +#include "gtk_s9xcore.h" +#include "gtk_s9x.h" +#include "gtk_config.h" +#include "gtk_control.h" + +const BindingLink b_links[] = +{ + /* Joypad-specific bindings. "Joypad# " will be prepended */ + { "b_up", "Up" }, + { "b_down", "Down" }, + { "b_left", "Left" }, + { "b_right", "Right" }, + { "b_start", "Start" }, + { "b_select", "Select" }, + { "b_a", "A" }, + { "b_b", "B" }, + { "b_x", "X" }, + { "b_y", "Y" }, + { "b_l", "L" }, + { "b_r", "R" }, + { "b_a_turbo", "Turbo A" }, + { "b_b_turbo", "Turbo B" }, + { "b_x_turbo", "Turbo X" }, + { "b_y_turbo", "Turbo Y" }, + { "b_l_turbo", "Turbo L" }, + { "b_r_turbo", "Turbo R" }, + { "b_a_sticky", "Sticky A" }, + { "b_b_sticky", "Sticky B" }, + { "b_x_sticky", "Sticky X" }, + { "b_y_sticky", "Sticky Y" }, + { "b_l_sticky", "Sticky L" }, + { "b_r_sticky", "Sticky R" }, + + /* Emulator based bindings */ + { "b_open_rom", "GTK_open_rom" }, + { "b_enable_turbo", "EmuTurbo" }, + { "b_toggle_turbo", "ToggleEmuTurbo" }, + { "b_pause", "GTK_pause" }, + { "b_decrease_frame_rate", "DecFrameRate" }, + { "b_increase_frame_rate", "IncFrameRate" }, + { "b_decrease_frame_time", "DecFrameTime" }, + { "b_increase_frame_time", "IncFrameTime" }, + { "b_hardware_reset", "Reset" }, + { "b_soft_reset", "SoftReset" }, + { "b_quit", "GTK_quit" }, + { "b_bg_layer_0", "ToggleBG0" }, + { "b_bg_layer_1", "ToggleBG1" }, + { "b_bg_layer_2", "ToggleBG2" }, + { "b_bg_layer_3", "ToggleBG3" }, + { "b_sprites", "ToggleSprites" }, + { "b_bg_layering_hack", "BGLayeringHack" }, + { "b_screenshot", "Screenshot" }, + { "b_fullscreen", "GTK_fullscreen" }, + { "b_save_0", "QuickSave000" }, + { "b_save_1", "QuickSave001" }, + { "b_save_2", "QuickSave002" }, + { "b_save_3", "QuickSave003" }, + { "b_save_4", "QuickSave004" }, + { "b_save_5", "QuickSave005" }, + { "b_save_6", "QuickSave006" }, + { "b_save_7", "QuickSave007" }, + { "b_save_8", "QuickSave008" }, + { "b_load_0", "QuickLoad000" }, + { "b_load_1", "QuickLoad001" }, + { "b_load_2", "QuickLoad002" }, + { "b_load_3", "QuickLoad003" }, + { "b_load_4", "QuickLoad004" }, + { "b_load_5", "QuickLoad005" }, + { "b_load_6", "QuickLoad006" }, + { "b_load_7", "QuickLoad007" }, + { "b_load_8", "QuickLoad008" }, + { "b_sound_channel_0", "SoundChannel0" }, + { "b_sound_channel_1", "SoundChannel1" }, + { "b_sound_channel_2", "SoundChannel2" }, + { "b_sound_channel_3", "SoundChannel3" }, + { "b_sound_channel_4", "SoundChannel4" }, + { "b_sound_channel_5", "SoundChannel5" }, + { "b_sound_channel_6", "SoundChannel6" }, + { "b_sound_channel_7", "SoundChannel7" }, + { "b_all_sound_channels", "SoundChannelsOn" }, + { "b_save_spc", "GTK_save_spc" }, + { "b_begin_recording_movie", "BeginRecordingMovie" }, + { "b_stop_recording_movie", "EndRecordingMovie" }, + { "b_load_movie", "LoadMovie" }, + { "b_seek_to_frame", "GTK_seek_to_frame" }, + { "b_swap_controllers", "GTK_swap_controllers" }, + + { NULL, NULL } +}; + +/* Where the page breaks occur in the preferences pane */ +const int b_breaks[] = +{ + 12, /* End of main buttons */ + 24, /* End of turbo/sticky buttons */ + 35, /* End of base emulator buttons */ + 43, /* End of Graphic options */ + 61, /* End of save/load states */ + 70, /* End of sound buttons */ + 76, /* End of miscellaneous buttons */ + -1 +}; + +static int joystick_lock = 0; + +bool +S9xPollButton (uint32 id, bool *pressed) +{ + return true; +} + +bool +S9xPollAxis (uint32 id, int16 *value) +{ + return true; +} + +bool +S9xPollPointer (uint32 id, int16 *x, int16 *y) +{ + *x = top_level->mouse_loc_x; + *y = top_level->mouse_loc_y; + + return true; +} + +bool +S9xGrabJoysticks (void) +{ + if (joystick_lock) + return FALSE; + + joystick_lock++; + + return TRUE; +} + +void +S9xReleaseJoysticks (void) +{ + joystick_lock--; + + return; +} + +static void +swap_controllers_1_2 (void) +{ + JoypadBinding interrim; + + memcpy (&interrim, + &gui_config->pad[0], + sizeof (JoypadBinding)); + memcpy (&gui_config->pad[0], + &gui_config->pad[1], + sizeof (JoypadBinding)); + memcpy (&gui_config->pad[1], + &interrim, + sizeof (JoypadBinding)); + + gui_config->rebind_keys (); + + return; +} + +void +S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2) +{ + static bool quit_binding_down = FALSE; + + if (data1 == TRUE) + { + if (cmd.port[0] == PORT_QUIT) + quit_binding_down = TRUE; + } + + if (data1 == FALSE) /* Release */ + { + if (cmd.port[0] != PORT_QUIT) + { + quit_binding_down = FALSE; + } + + if (cmd.port[0] == PORT_COMMAND_FULLSCREEN) + { + top_level->toggle_fullscreen_mode (); + } + + else if (cmd.port[0] == PORT_COMMAND_SAVE_SPC) + { + top_level->save_spc_dialog (); + } + + else if (cmd.port[0] == PORT_OPEN_ROM) + { + top_level->open_rom_dialog (); + } + + else if (cmd.port[0] == PORT_PAUSE) + { + if (!(top_level->user_pause)) + top_level->pause_from_user (); + else + top_level->unpause_from_user (); + } + + else if (cmd.port[0] == PORT_SEEK_TO_FRAME) + { + top_level->movie_seek_dialog (); + } + + else if (cmd.port[0] == PORT_SWAP_CONTROLLERS) + { + swap_controllers_1_2 (); + } + + else if (cmd.port[0] == PORT_QUIT) + { + if (quit_binding_down) + S9xExit (); + } + } + + return; +} + +Binding +S9xGetBindingByName (const char *name) +{ + for (int i = 0; i < NUM_EMU_LINKS; i++) + { + if (!strcasecmp (b_links[i + NUM_JOYPAD_LINKS].snes9x_name, name)) + { + return gui_config->shortcut[i]; + } + } + + return Binding (); +} + +s9xcommand_t +S9xGetPortCommandT (const char *name) +{ + s9xcommand_t cmd; + + cmd.type = S9xButtonPort; + cmd.multi_press = 0; + cmd.button_norpt = 0; + cmd.port[0] = 0; + cmd.port[1] = 0; + cmd.port[2] = 0; + cmd.port[3] = 0; + + if (!strcasecmp (name, "GTK_fullscreen")) + { + cmd.port[0] = PORT_COMMAND_FULLSCREEN; + } + + else if (!strcasecmp (name, "GTK_save_spc")) + { + cmd.port[0] = PORT_COMMAND_SAVE_SPC; + } + + else if (!strcasecmp (name, "GTK_open_rom")) + { + cmd.port[0] = PORT_OPEN_ROM; + } + + else if (!strcasecmp (name, "GTK_pause")) + { + cmd.port[0] = PORT_PAUSE; + } + + else if (!strcasecmp (name, "GTK_seek_to_frame")) + { + cmd.port[0] = PORT_SEEK_TO_FRAME; + } + + else if (!strcasecmp (name, "GTK_quit")) + { + cmd.port[0] = PORT_QUIT; + } + + else if (!strcasecmp (name, "GTK_swap_controllers")) + { + cmd.port[0] = PORT_SWAP_CONTROLLERS; + } + + else + { + cmd = S9xGetCommandT (name); + } + + return cmd; +} + +void +S9xProcessEvents (bool8 block) +{ +#ifdef USE_JOYSTICK + JoyEvent event; + Binding binding; + + if (S9xGrabJoysticks ()) + { + for (int i = 0; gui_config->joystick[i]; i++) + { + while (gui_config->joystick[i]->get_event (&event)) + { + binding = Binding (i, event.parameter, 0); + S9xReportButton (binding.hex (), event.state == JOY_PRESSED ? 1 : 0); + gui_config->screensaver_needs_reset = TRUE; + } + } + + S9xReleaseJoysticks (); + } +#endif + + return; +} + +#ifdef USE_JOYSTICK +static void +poll_joystick_events (void) +{ + SDL_Event event; + + while (SDL_PollEvent (&event)) + { + if (event.type == SDL_JOYAXISMOTION) + { + gui_config->joystick[event.jaxis.which]->handle_event (&event); + } + + else if (event.type == SDL_JOYHATMOTION) + { + gui_config->joystick[event.jhat.which]->handle_event (&event); + } + + else if (event.type == SDL_JOYBUTTONUP || + event.type == SDL_JOYBUTTONDOWN) + { + gui_config->joystick[event.jbutton.which]->handle_event (&event); + } + } + + return; +} +#endif + +void +S9xInitInputDevices (void) +{ +#ifdef USE_JOYSTICK + SDL_Init (SDL_INIT_VIDEO | SDL_INIT_JOYSTICK); + + for (int i = 0; ; i++) + { + gui_config->joystick = (JoyDevice **) + realloc (gui_config->joystick, + sizeof (JoyDevice *) * (i + 1)); + + gui_config->joystick[i] = new JoyDevice (i); + + if (!gui_config->joystick[i]->enabled) + { + delete gui_config->joystick[i]; + gui_config->joystick[i] = NULL; + break; + } + else + { + gui_config->joystick[i]->joynum = i; + } + } +#endif + + return; +} + +void +S9xDeinitInputDevices (void) +{ +#ifdef USE_JOYSTICK + for (int i = 0; gui_config->joystick[i] != NULL; i++) + { + delete gui_config->joystick[i]; + } + + free (gui_config->joystick); + + SDL_Quit (); +#endif + + return; +} + +#ifdef USE_JOYSTICK +JoyDevice::JoyDevice (unsigned int device_num) +{ + enabled = false; + axis = NULL; + filedes = NULL; + mode = JOY_MODE_INDIVIDUAL; + + if ((int) device_num >= SDL_NumJoysticks ()) + return; + + filedes = SDL_JoystickOpen (device_num); + + if (!filedes) + return; + + enabled = true; + + num_axes = SDL_JoystickNumAxes (filedes); + num_hats = SDL_JoystickNumHats (filedes); + axis = (int *) malloc (sizeof (int) * num_axes); + hat = (int *) malloc (sizeof (int) * num_hats); + calibration = (Calibration *) malloc (sizeof (Calibration) * num_axes); + + for (int i = 0; i < num_axes; i++) + { + calibration[i].min = -32767; + calibration[i].max = 32767; + calibration[i].center = 0; + } + + memset (axis, 0, sizeof (int) * num_axes); + + return; +} + +JoyDevice::~JoyDevice (void) +{ + if (enabled) + { + SDL_JoystickClose (filedes); + free (axis); + free (hat); + free (calibration); + } + + enabled = false; + + return; +} + +void +JoyDevice::add_event (int parameter, int state) +{ + JoyEvent event = { parameter, state }; + + queue.push (event); + + return; +} + +void +JoyDevice::register_centers (void) +{ + for (int i = 0; i < num_axes; i++) + { + calibration[i].center = SDL_JoystickGetAxis (filedes, i); + + /* Snap centers to specific target points */ + if (calibration[i].center < -24576) + calibration[i].center = -32768; + else if (calibration[i].center < -8192) + calibration[i].center = -16384; + else if (calibration[i].center < 8192) + calibration[i].center = 0; + else if (calibration[i].center < 24576) + calibration[i].center = 16383; + else + calibration[i].center = 32767; + } + + return; +} + +void +JoyDevice::handle_event (SDL_Event *event) +{ + if (event->type == SDL_JOYAXISMOTION) + { + int cal_min = calibration[event->jaxis.axis].min; + int cal_max = calibration[event->jaxis.axis].max; + int cal_cen = calibration[event->jaxis.axis].center; + int t = gui_config->joystick_threshold; + int ax_min = (cal_min - cal_cen) * t / 100 + cal_cen; + int ax_max = (cal_max - cal_cen) * t / 100 + cal_cen; + + if (mode == JOY_MODE_INDIVIDUAL) + { + for (int i = 0; i < NUM_JOYPADS; i++) + { + Binding *pad = (Binding *) &(gui_config->pad[i]); + + for (int j = 0; j < NUM_JOYPAD_LINKS; j++) + { + if (pad[j].get_axis () == event->jaxis.axis && + pad[j].get_device () == (unsigned int) (joynum + 1)) + { + t = pad[j].get_threshold (); + + if (pad[j].is_positive ()) + { + ax_max = (cal_max - cal_cen) * t / 100 + cal_cen; + } + else if (pad[j].is_negative ()) + { + ax_min = (cal_min - cal_cen) * t / 100 + cal_cen; + } + } + } + } + + for (int i = 0; i < NUM_EMU_LINKS; i++) + { + if (gui_config->shortcut[i].get_axis () == event->jaxis.axis && + gui_config->shortcut[i].get_device () == + (unsigned int) (joynum + 1)) + { + t = gui_config->shortcut[i].get_threshold (); + if (gui_config->shortcut[i].is_positive ()) + { + ax_max = (cal_max - cal_cen) * t / 100 + cal_cen; + } + else if (gui_config->shortcut[i].is_negative ()) + { + ax_min = (cal_min - cal_cen) * t / 100 + cal_cen; + } + } + } + } + else if (mode == JOY_MODE_CALIBRATE) + { + if (event->jaxis.value < calibration[event->jaxis.axis].min) + calibration[event->jaxis.axis].min = event->jaxis.value; + if (event->jaxis.value > calibration[event->jaxis.axis].max) + calibration[event->jaxis.axis].min = event->jaxis.value; + } + + /* Sanity Check */ + if (ax_min >= cal_cen) + ax_min = cal_cen - 1; + if (ax_max <= cal_cen) + ax_max = cal_cen + 1; + + if (event->jaxis.value <= ax_min && + axis[event->jaxis.axis] > ax_min) + { + add_event (JOY_AXIS (event->jaxis.axis, AXIS_NEG), 1); + } + + if (event->jaxis.value > ax_min && + axis[event->jaxis.axis] <= ax_min) + { + add_event (JOY_AXIS (event->jaxis.axis, AXIS_NEG), 0); + } + + if (event->jaxis.value >= ax_max && + axis[event->jaxis.axis] < ax_max) + { + add_event (JOY_AXIS (event->jaxis.axis, AXIS_POS), 1); + } + + if (event->jaxis.value < ax_max && + axis[event->jaxis.axis] >= ax_max) + { + add_event (JOY_AXIS (event->jaxis.axis, AXIS_POS), 0); + } + + axis[event->jaxis.axis] = event->jaxis.value; + + } + + else if (event->type == SDL_JOYBUTTONUP || + event->type == SDL_JOYBUTTONDOWN) + { + add_event (event->jbutton.button, + event->jbutton.state == SDL_PRESSED ? 1 : 0); + } + + else if (event->type == SDL_JOYHATMOTION) + { + if ((event->jhat.value & SDL_HAT_UP) && + !(hat[event->jhat.hat] & SDL_HAT_UP)) + { + add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_POS), 1); + } + + if (!(event->jhat.value & SDL_HAT_UP) && + (hat[event->jhat.hat] & SDL_HAT_UP)) + { + add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_POS), 0); + } + + if ((event->jhat.value & SDL_HAT_DOWN) && + !(hat[event->jhat.hat] & SDL_HAT_DOWN)) + { + add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_NEG), 1); + } + + if (!(event->jhat.value & SDL_HAT_DOWN) && + (hat[event->jhat.hat] & SDL_HAT_DOWN)) + { + add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2), AXIS_NEG), 0); + } + + if ((event->jhat.value & SDL_HAT_LEFT) && + !(hat[event->jhat.hat] & SDL_HAT_LEFT)) + { + add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_NEG), 1); + } + + if (!(event->jhat.value & SDL_HAT_LEFT) && + (hat[event->jhat.hat] & SDL_HAT_LEFT)) + { + add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_NEG), 0); + } + + if ((event->jhat.value & SDL_HAT_RIGHT) && + !(hat[event->jhat.hat] & SDL_HAT_RIGHT)) + { + add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_POS), 1); + } + + if (!(event->jhat.value & SDL_HAT_RIGHT) && + (hat[event->jhat.hat] & SDL_HAT_RIGHT)) + { + add_event (JOY_AXIS (num_axes + (event->jhat.hat * 2) + 1, AXIS_POS), 0); + } + + hat[event->jhat.hat] = event->jhat.value; + } + + return; +} + +int +JoyDevice::get_event (JoyEvent *event) +{ + poll_events (); + + if (queue.empty ()) + return 0; + + event->parameter = queue.front ().parameter; + event->state = queue.front ().state; + + queue.pop (); + + return 1; +} + +void +JoyDevice::poll_events (void) +{ + poll_joystick_events (); + + return; +} + +void +JoyDevice::flush (void) +{ + SDL_Event event; + + while (SDL_PollEvent (&event)) + { + } + + while (!queue.empty ()) + queue.pop (); + + return; +} +#endif diff --git a/gtk/src/gtk_control.h b/gtk/src/gtk_control.h new file mode 100644 index 00000000..a1454029 --- /dev/null +++ b/gtk/src/gtk_control.h @@ -0,0 +1,98 @@ +#ifndef __GTK_CONTROL_H +#define __GTK_CONTROL_H + +#include + +#include "gtk_binding.h" +#ifdef USE_JOYSTICK +#include "SDL.h" +#endif + +#ifndef NUM_JOYPADS +#define NUM_JOYPADS 10 +#endif + +#define JOY_MODE_GLOBAL 0 +#define JOY_MODE_INDIVIDUAL 1 +#define JOY_MODE_CALIBRATE 2 + +#define JOY_RELEASED 0 +#define JOY_PRESSED 1 + +#define PORT_COMMAND_FULLSCREEN 1 +#define PORT_COMMAND_SAVE_SPC 2 +#define PORT_OPEN_ROM 3 +#define PORT_PAUSE 4 +#define PORT_SEEK_TO_FRAME 5 +#define PORT_QUIT 6 +#define PORT_SWAP_CONTROLLERS 7 + +typedef struct BindingLink +{ + const char *button_name; + const char *snes9x_name; + +} BindingLink; + +extern const BindingLink b_links[]; +extern const int b_breaks[]; +#define NUM_JOYPAD_LINKS 24 +#define NUM_EMU_LINKS 52 + +typedef struct JoypadBinding +{ + Binding data[NUM_JOYPAD_LINKS]; /* Avoid packing issues */ +} JoypadBinding; + +#ifdef USE_JOYSTICK + +bool S9xGrabJoysticks (void); +void S9xReleaseJoysticks (void); + +typedef struct JoyEvent +{ + unsigned int parameter; + unsigned int state; + +} JoyEvent; + +typedef struct Calibration +{ + int min; + int max; + int center; +} Calibration; + +class JoyDevice +{ + public: + JoyDevice (unsigned int device_num); + ~JoyDevice (void); + int get_event (JoyEvent *event); + void flush (void); + void handle_event (SDL_Event *event); + void register_centers (void); + + SDL_Joystick *filedes; + Calibration *calibration; + std::queue queue; + int mode; + int joynum; + int num_axes; + int num_hats; + int *axis; + int *hat; + bool enabled; + + + private: + void poll_events (void); + void add_event (int parameter, int state); + +}; +#endif + +void S9xDeinitInputDevices (void); +Binding S9xGetBindingByName (const char *name); + +#endif /* __GTK_CONTROL_H*/ diff --git a/gtk/src/gtk_display.cpp b/gtk/src/gtk_display.cpp new file mode 100644 index 00000000..435a9bc8 --- /dev/null +++ b/gtk/src/gtk_display.cpp @@ -0,0 +1,1984 @@ +#include +#include +#include + +#include "gtk_s9x.h" +#include "gtk_display.h" +#include "gtk_display_driver.h" +#include "gtk_display_driver_gtk.h" +#include "snes_ntsc.h" +#ifdef USE_XV +#include "gtk_display_driver_xv.h" +#endif +#ifdef USE_OPENGL +#include "gtk_display_driver_opengl.h" +#endif + +static S9xDisplayDriver *driver; +static snes_ntsc_t snes_ntsc; +static thread_job_t job[8]; +static GThreadPool *pool; +static uint8 *y_table, *u_table, *v_table; +static int endianess = ENDIAN_LSB; + +/* Scanline constants for the NTSC filter */ +static unsigned int scanline_offsets[] = +{ + 0, /* 0% */ + 3, /* 12.5% */ + 2, /* 25% */ + 1, /* 50% */ + 0, /* 100% */ +}; + +static unsigned short scanline_masks[] = +{ + 0x0000, /* 0% */ + 0x0C63, /* 12.5% */ + 0x1CE7, /* 25% */ + 0x3DEF, /* 50% */ + 0xffff, /* 100% */ +}; + +extern unsigned int scanline_offset; +extern unsigned short scanline_mask; + +/* Scanline constants for standard scanline filter */ +static uint8 scanline_shifts[] = +{ + 3, + 2, + 1, + 0 +}; + +void +S9xSetEndianess (int type) +{ + endianess = type; + + return; +} + +double +S9xGetAspect (void) +{ + if (gui_config->aspect_ratio) + return (4.0 / 3.0); + else + return (8.0 / 7.0); +} + +void +S9xRegisterYUVTables (uint8 *y, uint8 *u, uint8 *v) +{ + y_table = y; + u_table = u; + v_table = v; + + return; +} + +/* YUY2 in LSB first format */ +static void +internal_convert_16_yuv (void *src_buffer, + void *dst_buffer, + int src_pitch, + int dst_pitch, + int width, + int height) +{ + register int x, y; + register uint16 *src; + register uint8 *dst; + register uint16 p0, p1; + + if (endianess == ENDIAN_MSB) + { + for (y = 0; y < height; y++) + { + src = (uint16 *) (((uint8 *) src_buffer) + src_pitch * y); + dst = (uint8 *) (((uint8 *) dst_buffer) + dst_pitch * y); + + for (x = 0; x < width >> 1; x++) + { + p0 = *src++; + p1 = *src++; + + *dst++ = (v_table[p0] + v_table[p1]) >> 1; + *dst++ = y_table[p1]; + *dst++ = (u_table[p0] + u_table[p1]) >> 1; + *dst++ = y_table[p0]; + } + } + } + + else + { + for (y = 0; y < height; y++) + { + src = (uint16 *) (((uint8 *) src_buffer) + src_pitch * y); + dst = (uint8 *) (((uint8 *) dst_buffer) + dst_pitch * y); + + for (x = 0; x < width >> 1; x++) + { + p0 = *src++; + p1 = *src++; + + *dst++ = y_table[p0]; + *dst++ = (u_table[p0] + u_table[p1]) >> 1; + *dst++ = y_table[p1]; + *dst++ = (v_table[p0] + v_table[p1]) >> 1; + } + } + } + + return; +} + +static void +internal_convert_mask (void *src_buffer, + void *dst_buffer, + int src_pitch, + int dst_pitch, + int width, + int height, + unsigned int inv_rshift, + unsigned int inv_gshift, + unsigned int inv_bshift, + unsigned int bpp) +{ +#ifdef __BIG_ENDIAN__ + if (endianess == ENDIAN_MSB) +#else + if (endianess == ENDIAN_LSB) +#endif + { + switch (bpp) + { + case 15: + case 16: + + for (register int y = 0; y < height; y++) + { + register uint16 *data = + (uint16 *) ((uint8 *) dst_buffer + y * dst_pitch); + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + + *data++ = ((pixel & 0x7c00) << 1) >> inv_rshift + | ((pixel & 0x03e0) << 6) >> inv_gshift + | ((pixel & 0x001f) << 11) >> inv_bshift; + } + } + + break; + + case 24: + +#ifdef __BIG_ENDIAN__ + if (inv_rshift > 8) +#else + if (!(inv_rshift > 8)) +#endif + { + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + *data++ = ((pixel & 0x001f) << 3); + *data++ = ((pixel & 0x03e0) >> 2); + *data++ = ((pixel & 0x7c00) >> 7); + } + } + } + + else + { + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + *data++ = ((pixel & 0x7c00) >> 7); + *data++ = ((pixel & 0x03e0) >> 2); + *data++ = ((pixel & 0x001f) << 3); + } + } + } + + break; + + case 32: + + for (register int y = 0; y < height; y++) + { + register uint32 *data = + (uint32 *) ((uint8 *) dst_buffer + y * dst_pitch); + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + + *data++ = ((uint32) (pixel & 0x7c00) << 17) >> inv_rshift + | ((uint32) (pixel & 0x03e0) << 22) >> inv_gshift + | ((uint32) (pixel & 0x001f) << 27) >> inv_bshift; + } + } + + break; + } + } + + else /* Byte-order is inverted from native */ + { + switch (bpp) + { + case 15: + case 16: + + for (register int y = 0; y < height; y++) + { + register uint16 *data = + (uint16 *) ((uint8 *) dst_buffer + y * dst_pitch); + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + register uint16 value; + + value = ((pixel & 0x7c00) << 1) >> inv_rshift + | ((pixel & 0x03e0) << 6) >> inv_gshift + | ((pixel & 0x001f) << 11) >> inv_bshift; + + *data++ = ((value & 0xff) << 8) + | ((value & 0xff00) >> 8); + } + } + + break; + + case 24: + +#ifdef __BIG_ENDIAN__ + if (inv_rshift > 8) +#else + if (!(inv_rshift > 8)) +#endif + { + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + *data++ = ((pixel & 0x7c00) >> 7); + *data++ = ((pixel & 0x03e0) >> 2); + *data++ = ((pixel & 0x001f) << 3); + } + } + } + + else + { + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + *data++ = ((pixel & 0x001f) << 3); + *data++ = ((pixel & 0x03e0) >> 2); + *data++ = ((pixel & 0x7c00) >> 7); + } + } + } + + break; + + case 32: + + for (register int y = 0; y < height; y++) + { + register uint32 *data = + (uint32 *) ((uint8 *) dst_buffer + y * dst_pitch); + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + register uint32 value; + + value = ((uint32) (pixel & 0x7c00) << 17) >> inv_rshift + | ((uint32) (pixel & 0x03e0) << 22) >> inv_gshift + | ((uint32) (pixel & 0x001f) << 27) >> inv_bshift; + + *data++ = ((value & 0x000000ff) << 24) + | ((value & 0x0000ff00) << 8) + | ((value & 0x00ff0000) >> 8) + | ((value & 0xff000000) >> 24); + } + } + + break; + } + } + + return; +} + +static void +internal_convert (void *src_buffer, + void *dst_buffer, + int src_pitch, + int dst_pitch, + int width, + int height, + int bpp) +{ + if (endianess == ENDIAN_MSB) + { + if (bpp == 15) + { + /* Format in fourcc is xrrrrrgg gggbbbbb */ + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + *data++ = (pixel & 0x7c00) >> 8 + | (pixel & 0x0300) >> 8; /* Top 2 green, 5 red */ + *data++ = (pixel & 0x00c0) + | (pixel & 0x001f); /* Top 3 of last 4 green 5 blue */ + } + } + } + + else if (bpp == 16) + { + /* Format in fourcc is rrrrrggg gggbbbbb */ + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + + *data++ = (pixel & 0x7c00) >> 7 + | (pixel & 0x0300) >> 7; /* 5 red, first 3 green */ + *data++ = (pixel & 0x00c0) + | (pixel & 0x001f); /* last 3 green, 5 blue */ + } + } + } + + else if (bpp == 24) + { + /* Format in fourcc is rrrrrrrr gggggggg bbbbbbbb */ + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + + *data++ = (pixel & 0x7c00) >> 7; /* Red */ + *data++ = (pixel & 0x03e0) >> 2; /* Green */ + *data++ = (pixel & 0x001f) << 3; /* Blue */ + } + } + } + + else if (bpp == 32) + { + /* Format in fourcc is xxxxxxxx rrrrrrrr gggggggg bbbbbbbb */ + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + + *data++ = 0xff; /* Null */ + *data++ = (pixel & 0x7c00) >> 7; /* Red */ + *data++ = (pixel & 0x03e0) >> 2; /* Green */ + *data++ = (pixel & 0x001f) << 3; /* Blue */ + } + } + } + } + + else /* Least significant byte first :-P */ + { + if (bpp == 15) + { + /* Format in fourcc is xrrrrrgg gggbbbbb */ + + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + *data++ = (pixel & 0x00c0) + | (pixel & 0x001f); /* Top 3 of last 4 green 5 blue */ + *data++ = (pixel & 0x7c00) >> 8 + | (pixel & 0x0300) >> 8; /* Top 2 green, 5 red */ + } + } + } + + else if (bpp == 16) + { + /* Format in fourcc is rrrrrggg gggbbbbb */ + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + + *data++ = (pixel & 0x00c0) + | (pixel & 0x001f); /* last 3 green, 5 blue */ + *data++ = (pixel & 0x7c00) >> 7 + | (pixel & 0x0300) >> 7; /* 5 red, first 3 green */ + } + } + } + + else if (bpp == 24) + { + /* Format in fourcc is rrrrrrrr gggggggg bbbbbbbb */ + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + + *data++ = (pixel & 0x001f) << 3; /* Blue */ + *data++ = (pixel & 0x03e0) >> 2; /* Green */ + *data++ = (pixel & 0x7c00) >> 7; /* Red */ + } + } + } + + else if (bpp == 32) + { + /* Format in fourcc is xxxxxxxx rrrrrrrr gggggggg bbbbbbbb */ + for (register int y = 0; y < height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + y * src_pitch); + + for (register int x = 0; x < width; x++) + { + uint32 pixel = *snes++; + + *data++ = (pixel & 0x001f) << 3; /* Blue */ + *data++ = (pixel & 0x03e0) >> 2; /* Green */ + *data++ = (pixel & 0x7c00) >> 7; /* Red */ + *data++ = 0xff; /* Null */ + } + } + } + } + + return; +} + +static void +internal_convert_scale (void *src_buffer, + void *dst_buffer, + int src_pitch, + int dst_pitch, + int width, + int height, + int dest_width, + int dest_height, + int bpp) +{ + register uint32 x_error = 0, x_fraction; + uint32 y_error = 0, y_fraction; + int yy = 0; + + x_fraction = (width * 0x10000) / dest_width; + y_fraction = (height * 0x10000) / dest_height; + + if (endianess == ENDIAN_MSB) + { + if (bpp == 15) + { + /* Format in fourcc is xrrrrrgg gggbbbbb */ + for (register int y = 0; y < dest_height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + yy * src_pitch); + + y_error += y_fraction; + + while (y_error >= 0x10000) + { + yy++; + y_error -= 0x10000; + } + x_error = 0; + + for (register int x = 0; x < dest_width; x++) + { + uint32 pixel = *snes; + *data++ = (pixel & 0x7c00) >> 8 | + (pixel & 0x0300) >> 8; /* Top 2 green, 5 red */ + *data++ = (pixel & 0x00c0) | + (pixel & 0x001f); /* Top 3 of last 4 green 5 blue */ + + x_error += x_fraction; + + while (x_error >= 0x10000) + { + snes++; + x_error -= 0x10000; + } + } + } + } + + else if (bpp == 16) + { + /* Format in fourcc is rrrrrggg gggbbbbb */ + for (register int y = 0; y < dest_height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + yy * src_pitch); + + y_error += y_fraction; + + while (y_error >= 0x10000) + { + yy++; + y_error -= 0x10000; + } + x_error = 0; + + for (register int x = 0; x < dest_width; x++) + { + uint32 pixel = *snes; + + *data++ = (pixel & 0x7c00) >> 7 | + (pixel & 0x0300) >> 7; /* 5 red, first 3 green */ + *data++ = (pixel & 0x00c0) | + (pixel & 0x001f); /* last 3 green, 5 blue */ + + x_error += x_fraction; + + while (x_error >= 0x10000) + { + snes++; + x_error -= 0x10000; + } + } + } + } + + else if (bpp == 24) + { + /* Format in fourcc is rrrrrrrr gggggggg bbbbbbbb */ + for (register int y = 0; y < dest_height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + yy * src_pitch); + + y_error += y_fraction; + + while (y_error >= 0x10000) + { + yy++; + y_error -= 0x10000; + } + x_error = 0; + + for (register int x = 0; x < dest_width; x++) + { + uint32 pixel = *snes; + + *data++ = (pixel & 0x7c00) >> 7; /* Red */ + *data++ = (pixel & 0x03e0) >> 2; /* Green */ + *data++ = (pixel & 0x001f) << 3; /* Blue */ + + x_error += x_fraction; + + while (x_error >= 0x10000) + { + snes++; + x_error -= 0x10000; + } + } + } + } + + else if (bpp == 32) + { + /* Format in fourcc is xxxxxxxx rrrrrrrr gggggggg bbbbbbbb */ + for (register int y = 0; y < dest_height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + yy * src_pitch); + + y_error += y_fraction; + + while (y_error >= 0x10000) + { + yy++; + y_error -= 0x10000; + } + x_error = 0; + + for (register int x = 0; x < dest_width; x++) + { + uint32 pixel = *snes; + + *data++ = 0xff; /* Null */ + *data++ = (pixel & 0x7c00) >> 7; /* Red */ + *data++ = (pixel & 0x03e0) >> 2; /* Green */ + *data++ = (pixel & 0x001f) << 3; /* Blue */ + + x_error += x_fraction; + + while (x_error >= 0x10000) + { + snes++; + x_error -= 0x10000; + } + } + } + } + } + + else /* Least significant byte first :-P */ + { + if (bpp == 15) + { + /* Format in fourcc is xrrrrrgg gggbbbbb */ + + for (register int y = 0; y < dest_height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + yy * src_pitch); + + y_error += y_fraction; + + while (y_error >= 0x10000) + { + yy++; + y_error -= 0x10000; + } + x_error = 0; + + for (register int x = 0; x < dest_width; x++) + { + uint32 pixel = *snes; + *data++ = (pixel & 0x00c0) | + (pixel & 0x001f); /* Top 3 of last 4 green 5 blue */ + *data++ = (pixel & 0x7c00) >> 8 | + (pixel & 0x0300) >> 8; /* Top 2 green, 5 red */ + + x_error += x_fraction; + + while (x_error >= 0x10000) + { + snes++; + x_error -= 0x10000; + } + } + } + } + + else if (bpp == 16) + { + /* Format in fourcc is rrrrrggg gggbbbbb */ + for (register int y = 0; y < dest_height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + yy * src_pitch); + + y_error += y_fraction; + + while (y_error >= 0x10000) + { + yy++; + y_error -= 0x10000; + } + x_error = 0; + + for (register int x = 0; x < dest_width; x++) + { + uint32 pixel = *snes; + + *data++ = (pixel & 0x00c0) | + (pixel & 0x001f); /* last 3 green, 5 blue */ + *data++ = (pixel & 0x7c00) >> 7 | + (pixel & 0x0300) >> 7; /* 5 red, first 3 green */ + + x_error += x_fraction; + + while (x_error >= 0x10000) + { + snes++; + x_error -= 0x10000; + } + } + } + } + + else if (bpp == 24) + { + /* Format in fourcc is rrrrrrrr gggggggg bbbbbbbb */ + for (register int y = 0; y < dest_height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + yy * src_pitch); + + y_error += y_fraction; + + while (y_error >= 0x10000) + { + yy++; + y_error -= 0x10000; + } + x_error = 0; + + for (register int x = 0; x < dest_width; x++) + { + uint32 pixel = *snes; + + *data++ = (pixel & 0x001f) << 3; /* Blue */ + *data++ = (pixel & 0x03e0) >> 2; /* Green */ + *data++ = (pixel & 0x7c00) >> 7; /* Red */ + + x_error += x_fraction; + + while (x_error >= 0x10000) + { + snes++; + x_error -= 0x10000; + } + } + } + } + + else if (bpp == 32) + { + /* Format in fourcc is xxxxxxxx rrrrrrrr gggggggg bbbbbbbb */ + for (register int y = 0; y < dest_height; y++) + { + register uint8 *data = + (uint8 *) dst_buffer + y * dst_pitch; + + register uint16 *snes = + (uint16 *) (((uint8 *) src_buffer) + yy * src_pitch); + + y_error += y_fraction; + + while (y_error >= 0x10000) + { + yy++; + y_error -= 0x10000; + } + + for (register int x = 0; x < dest_width; x++) + { + uint32 pixel = *snes; + + *data++ = (pixel & 0x001f) << 3; /* Blue */ + *data++ = (pixel & 0x03e0) >> 2; /* Green */ + *data++ = (pixel & 0x7c00) >> 7; /* Red */ + *data++ = 0xff; /* Null */ + + x_error += x_fraction; + + while (x_error >= 0x10000) + { + snes++; + x_error -= 0x10000; + } + } + } + } + } + + return; +} + +static void +S9xForceHires (void *buffer, + int pitch, + int &width, + int &height) +{ + int double_width = 0, + double_height = 0; + + if (width <= 256) + double_width++; + + /*if (height <= 224) + double_height++; */ + + if (double_width && double_height) + { + for (register int y = (height * 2) - 1; y >= 0; y--) + { + register uint16 *src_line = (uint16 *) ((uint8 *) buffer + (y >> 1) * pitch); + register uint16 *dst_line = (uint16 *) ((uint8 *) buffer + y * pitch); + + for (register int x = (width * 2) - 1; x >= 0; x--) + { + *(dst_line + x) = *(src_line + (x >> 1)); + } + } + + width *= 2; height *= 2; + } + else if (double_width && !double_height) + { + for (register int y = (height) - 1; y >= 0; y--) + { + register uint16 *line = (uint16 *) ((uint8 *) buffer + y * pitch); + + for (register int x = (width * 2) - 1; x >= 0; x--) + { + *(line + x) = *(line + (x >> 1)); + } + } + + width *= 2; + } + else if (!double_width && double_height) + { + for (register int y = (height * 2) - 1; y >= 0; y--) + { + register uint16 *src_line = (uint16 *) ((uint8 *) buffer + (y >> 1) * pitch); + register uint16 *dst_line = (uint16 *) ((uint8 *) buffer + y * pitch); + + memcpy (dst_line, src_line, width * 2); + } + + height *= 2; + } + + return; +} + +void +filter_scanlines (void *src_buffer, + int src_pitch, + void *dst_buffer, + int dst_pitch, + int width, + int height) +{ + register int x, y; + + uint8 shift = scanline_shifts[gui_config->scanline_filter_intensity]; + + for (y = 0; y < height; y++) + { + register uint16 *src = (uint16 *) ((uint8 *) src_buffer + y * src_pitch); + register uint16 *dst_a = (uint16 *) ((uint8 *) dst_buffer + (y * 2) * dst_pitch); + register uint16 *dst_b = (uint16 *) ((uint8 *) dst_buffer + ((y * 2) + 1) * dst_pitch); + + for (x = 0; x < width; x++) + { + register uint8 rs, gs, bs, /* Source components */ + rh, gh, bh; /* High (bright) components */ + + rs = ((*(src + x) >> 10) & 0x1f); + gs = ((*(src + x) >> 5) & 0x1f); + bs = ((*(src + x)) & 0x1f); + + rh = rs + (rs >> shift); + gh = gs + (gs >> shift); + bh = bs + (bs >> shift); + + rh = (rh > 31) ? 31 : rh; + gh = (gh > 31) ? 31 : gh; + bh = (bh > 31) ? 31 : bh; + + *(dst_a + x) = (rh << 10) | (gh << 5) | (bh); + *(dst_b + x) = ((rs + rs - rh) << 10) | + ((gs + gs - gh) << 5) | + (bs + bs - bh); + } + } + + return; +} + + +void +get_filter_scale (int &width, int &height) +{ + switch (gui_config->scale_method) + { + case FILTER_SUPEREAGLE: + width *= 2; + height *= 2; + break; + + case FILTER_2XSAI: + width *= 2; + height *= 2; + break; + + case FILTER_SUPER2XSAI: + width *= 2; + height *= 2; + break; + + case FILTER_HQ4X: + if (((width * 4) <= S9xDisplayDriver::scaled_max_width) && + ((height * 4) <= S9xDisplayDriver::scaled_max_height)) + { + width *= 4; + height *= 4; + break; + } + + case FILTER_HQ3X: + if (width * 3 <= S9xDisplayDriver::scaled_max_width && + height * 3 <= S9xDisplayDriver::scaled_max_height) + { + width *= 3; + height *= 3; + break; + } + + case FILTER_HQ2X: + width *= 2; + height *= 2; + break; + + case FILTER_EPX: + width *= 2; + height *= 2; + break; + + case FILTER_NTSC: + if (width > 256) + width = SNES_NTSC_OUT_WIDTH (width / 2); + else + width = SNES_NTSC_OUT_WIDTH (width); + height *= 2; + break; + + case FILTER_SCANLINES: + height *= 2; + break; + + case FILTER_EPX_SMOOTH: + width *= 2; + height *= 2; + break; + } + + return; +} + +static void +internal_filter (uint8 *src_buffer, + int src_pitch, + uint8 *dst_buffer, + int dst_pitch, + int &width, + int &height) +{ + switch (gui_config->scale_method) + { + case FILTER_SUPEREAGLE: + SuperEagle (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; + + case FILTER_2XSAI: + _2xSaI (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; + + case FILTER_SUPER2XSAI: + Super2xSaI (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; + + + case FILTER_HQ4X: + + if (((width * 4) <= S9xDisplayDriver::scaled_max_width) && + ((height * 4) <= S9xDisplayDriver::scaled_max_height)) + { + HQ4X_16 (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; + } + /* Fall back to 3x */ + + case FILTER_HQ3X: + + if (width * 3 <= S9xDisplayDriver::scaled_max_width && + height * 3 <= S9xDisplayDriver::scaled_max_height) + { + HQ3X_16 (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; + } + /* Fall back to 2x */ + + case FILTER_HQ2X: + + HQ2X_16 (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; + + case FILTER_EPX: + + EPX_16_unsafe (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; + + case FILTER_EPX_SMOOTH: + + EPX_16_smooth_unsafe (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + break; + + case FILTER_NTSC: + if (width > 256) + snes_ntsc_blit_hires (&snes_ntsc, + (SNES_NTSC_IN_T *) src_buffer, + src_pitch >> 1, + 0, /* Burst_phase */ + width, + height, + (void *) dst_buffer, + dst_pitch); + else + snes_ntsc_blit (&snes_ntsc, + (SNES_NTSC_IN_T *) src_buffer, + src_pitch >> 1, + 0, /* Burst_phase */ + width, + height, + (void *) dst_buffer, + dst_pitch); + break; + + case FILTER_SCANLINES: + filter_scanlines (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + break; + + } + + get_filter_scale (width, height); + + return; +} + +static void +thread_worker (gpointer data, + gpointer user_data) +{ + thread_job_t *job = ((thread_job_t *) data); + + switch (job->operation_type) + { + case JOB_FILTER: + internal_filter (job->src_buffer, + job->src_pitch, + job->dst_buffer, + job->dst_pitch, + job->width, + job->height); + break; + + case JOB_CONVERT: + internal_convert (job->src_buffer, + job->dst_buffer, + job->src_pitch, + job->dst_pitch, + job->width, + job->height, + job->bpp); + break; + + case JOB_CONVERT_YUV: + internal_convert_16_yuv (job->src_buffer, + job->dst_buffer, + job->src_pitch, + job->dst_pitch, + job->width, + job->height); + break; + + case JOB_CONVERT_MASK: + internal_convert_mask (job->src_buffer, + job->dst_buffer, + job->src_pitch, + job->dst_pitch, + job->width, + job->height, + job->inv_rmask, + job->inv_bmask, + job->inv_gmask, + job->bpp); + + case JOB_SCALE_AND_CONVERT: + internal_convert_scale (job->src_buffer, + job->dst_buffer, + job->src_pitch, + job->dst_pitch, + job->width, + job->height, + job->dst_width, + job->dst_height, + job->bpp); + break; + } + + job->complete = 1; + + return; +} + +static void +create_thread_pool (void) +{ + if (pool == NULL) + { + pool = g_thread_pool_new (thread_worker, + NULL, + gui_config->num_threads - 1, + TRUE, + NULL); + } + + return; +} + +static void +internal_threaded_convert_scale (void *src_buffer, + void *dst_buffer, + int src_pitch, + int dst_pitch, + int width, + int height, + int dst_width, + int dst_height, + int bpp) +{ + int i, flag; + + /* If the threadpool doesn't exist, create it */ + create_thread_pool (); + + for (i = 0; i < gui_config->num_threads - 1; i++) + { + job[i].operation_type = JOB_SCALE_AND_CONVERT; + job[i].src_buffer = + ((uint8 *) src_buffer) + (src_pitch * i * (height / gui_config->num_threads)); + job[i].src_pitch = src_pitch; + job[i].dst_buffer = + ((uint8 *) dst_buffer) + (dst_pitch * i * (dst_height / gui_config->num_threads)); + job[i].dst_pitch = dst_pitch; + job[i].width = width; + job[i].height = height / gui_config->num_threads; + job[i].dst_width = dst_width; + job[i].dst_height = dst_height / gui_config->num_threads; + job[i].bpp = bpp; + job[i].complete = 0; + + g_thread_pool_push (pool, (gpointer) &(job[i]), NULL); + } + + i = gui_config->num_threads - 1; + + job[i].operation_type = JOB_SCALE_AND_CONVERT; + job[i].src_buffer = + ((uint8 *) src_buffer) + (src_pitch * i * (height / gui_config->num_threads)); + job[i].src_pitch = src_pitch; + job[i].dst_buffer = + ((uint8 *) dst_buffer) + (dst_pitch * i * (dst_height / gui_config->num_threads)); + job[i].dst_pitch = dst_pitch; + job[i].width = width; + job[i].height = + height - ((gui_config->num_threads - 1) * (height / gui_config->num_threads)); + job[i].dst_width = dst_width; + job[i].dst_height = + dst_height - ((gui_config->num_threads - 1) * (dst_height / gui_config->num_threads)); + job[i].bpp = bpp; + + thread_worker ((gpointer) &(job[i]), NULL); + + while (1) + { + flag = 1; + for (i = 0; i < gui_config->num_threads - 1; i++) + flag = flag && job[i].complete; + + if (flag) + break; + + sched_yield (); + } + + return; +} + +static void +internal_threaded_convert (void *src_buffer, + void *dst_buffer, + int src_pitch, + int dst_pitch, + int width, + int height, + int bpp) +{ + int i, flag; + + create_thread_pool (); + + for (i = 0; i < gui_config->num_threads - 1; i++) + { + job[i].operation_type = (bpp == -1 ? JOB_CONVERT_YUV : JOB_CONVERT); + job[i].src_buffer = + ((uint8 *) src_buffer) + (src_pitch * i * (height / gui_config->num_threads)); + job[i].src_pitch = src_pitch; + job[i].dst_buffer = + ((uint8 *) dst_buffer) + (dst_pitch * i * (height / gui_config->num_threads)); + job[i].dst_pitch = dst_pitch; + job[i].width = width; + job[i].height = height / gui_config->num_threads; + job[i].bpp = bpp; + job[i].complete = 0; + + g_thread_pool_push (pool, (gpointer) &(job[i]), NULL); + } + + i = gui_config->num_threads - 1; + + job[i].operation_type = (bpp == -1 ? JOB_CONVERT_YUV : JOB_CONVERT); + job[i].src_buffer = + ((uint8 *) src_buffer) + (src_pitch * i * (height / gui_config->num_threads)); + job[i].src_pitch = src_pitch; + job[i].dst_buffer = + ((uint8 *) dst_buffer) + (dst_pitch * i * (height / gui_config->num_threads)); + job[i].dst_pitch = dst_pitch; + job[i].width = width; + job[i].height = height - ((gui_config->num_threads - 1) * (height / gui_config->num_threads)); + job[i].bpp = bpp; + + thread_worker ((gpointer) &(job[i]), NULL); + + while (1) + { + flag = 1; + for (i = 0; i < gui_config->num_threads - 1; i++) + flag = flag && job[i].complete; + + if (flag) + break; + + sched_yield (); + } + + return; +} + +static void +internal_threaded_convert_mask (void *src_buffer, + void *dst_buffer, + int src_pitch, + int dst_pitch, + int width, + int height, + int inv_rmask, + int inv_gmask, + int inv_bmask, + int bpp) +{ + int i, flag; + + create_thread_pool (); + + for (i = 0; i < gui_config->num_threads - 1; i++) + { + job[i].operation_type = (bpp == -1 ? JOB_CONVERT_YUV : JOB_CONVERT); + job[i].src_buffer = + ((uint8 *) src_buffer) + (src_pitch * i * (height / gui_config->num_threads)); + job[i].src_pitch = src_pitch; + job[i].dst_buffer = + ((uint8 *) dst_buffer) + (dst_pitch * i * (height / gui_config->num_threads)); + job[i].dst_pitch = dst_pitch; + job[i].width = width; + job[i].height = height / gui_config->num_threads; + job[i].bpp = bpp; + job[i].inv_rmask = inv_rmask; + job[i].inv_gmask = inv_gmask; + job[i].inv_bmask = inv_bmask; + job[i].complete = 0; + + g_thread_pool_push (pool, (gpointer) &(job[i]), NULL); + } + + i = gui_config->num_threads - 1; + + job[i].operation_type = (bpp == -1 ? JOB_CONVERT_YUV : JOB_CONVERT); + job[i].src_buffer = + ((uint8 *) src_buffer) + (src_pitch * i * (height / gui_config->num_threads)); + job[i].src_pitch = src_pitch; + job[i].dst_buffer = + ((uint8 *) dst_buffer) + (dst_pitch * i * (height / gui_config->num_threads)); + job[i].dst_pitch = dst_pitch; + job[i].width = width; + job[i].height = height - ((gui_config->num_threads - 1) * (height / gui_config->num_threads)); + job[i].bpp = bpp; + job[i].inv_rmask = inv_rmask; + job[i].inv_gmask = inv_gmask; + job[i].inv_bmask = inv_bmask; + + thread_worker ((gpointer) &(job[i]), NULL); + + while (1) + { + flag = 1; + for (i = 0; i < gui_config->num_threads - 1; i++) + flag = flag && job[i].complete; + + if (flag) + break; + + sched_yield (); + } + + return; +} + +static void +internal_threaded_filter (uint8 *src_buffer, + int src_pitch, + uint8 *dst_buffer, + int dst_pitch, + int &width, + int &height) +{ + int i, flag; + int dwidth = width, dheight = height; + + get_filter_scale (dwidth, dheight); + + /* If the threadpool doesn't exist, create it */ + create_thread_pool (); + + for (i = 0; i < gui_config->num_threads - 1; i++) + { + job[i].operation_type = JOB_FILTER; + job[i].src_buffer = + src_buffer + (src_pitch * i * (height / gui_config->num_threads)); + job[i].src_pitch = src_pitch; + job[i].dst_buffer = + dst_buffer + (dst_pitch * i * (dheight / gui_config->num_threads)); + job[i].dst_pitch = dst_pitch; + job[i].width = width; + job[i].height = height / gui_config->num_threads; + job[i].complete = 0; + job[i].dst_width = width; + job[i].dst_height = height; + + g_thread_pool_push (pool, (gpointer) &(job[i]), NULL); + } + + i = gui_config->num_threads - 1; + + job[i].operation_type = JOB_FILTER; + job[i].src_buffer = + src_buffer + (src_pitch * i * (height / gui_config->num_threads)); + job[i].src_pitch = src_pitch; + job[i].dst_buffer = + dst_buffer + (dst_pitch * i * (dheight / gui_config->num_threads)); + job[i].dst_pitch = dst_pitch; + job[i].width = width; + job[i].height = height - ((gui_config->num_threads - 1) * (height / gui_config->num_threads)); + job[i].dst_width = width; + job[i].dst_height = height; + + thread_worker ((gpointer) &(job[i]), NULL); + + while (1) + { + flag = 1; + for (i = 0; i < gui_config->num_threads - 1; i++) + flag = flag && job[i].complete; + + if (flag) + break; + + sched_yield (); + } + + get_filter_scale (width, height); + + return; +} + +void +S9xFilter (uint8 *src_buffer, + int src_pitch, + uint8 *dst_buffer, + int dst_pitch, + int &width, + int &height) +{ + + if (gui_config->multithreading) + internal_threaded_filter (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + else + internal_filter (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + return; +} + +void +S9xConvertYUV (void *src_buffer, + void *dst_buffer, + int src_pitch, + int dst_pitch, + int width, + int height) +{ + if (gui_config->multithreading) + internal_threaded_convert (src_buffer, + dst_buffer, + src_pitch, + dst_pitch, + width, + height, + -1); + else + internal_convert_16_yuv (src_buffer, + dst_buffer, + src_pitch, + dst_pitch, + width, + height); + return; +} + +void +S9xConvert (void *src, + void *dst, + int src_pitch, + int dst_pitch, + int width, + int height, + int bpp) +{ + if (gui_config->multithreading) + internal_threaded_convert (src, + dst, + src_pitch, + dst_pitch, + width, + height, + bpp); + else + internal_convert (src, + dst, + src_pitch, + dst_pitch, + width, + height, + bpp); + return; +} + +void +S9xConvertMask (void *src, + void *dst, + int src_pitch, + int dst_pitch, + int width, + int height, + int rshift, + int gshift, + int bshift, + int bpp) +{ + if (gui_config->multithreading) + internal_threaded_convert_mask (src, + dst, + src_pitch, + dst_pitch, + width, + height, + rshift, + gshift, + bshift, + bpp); + else + internal_convert_mask (src, + dst, + src_pitch, + dst_pitch, + width, + height, + rshift, + gshift, + bshift, + bpp); + return; +} + +void +S9xConvertScale (void *src, + void *dst, + int src_pitch, + int dst_pitch, + int width, + int height, + int dest_width, + int dest_height, + int bpp) +{ + if (gui_config->multithreading) + internal_threaded_convert_scale (src, + dst, + src_pitch, + dst_pitch, + width, + height, + dest_width, + dest_height, + bpp); + else + internal_convert_scale (src, + dst, + src_pitch, + dst_pitch, + width, + height, + dest_width, + dest_height, + bpp); + return; +} + +void +S9xDisplayRefresh (int width, int height) +{ + driver->refresh (width, height); + + return; +} + +static void +ntsc_filter_init (void) +{ + scanline_offset = scanline_offsets [gui_config->ntsc_scanline_intensity]; + scanline_mask = scanline_masks [gui_config->ntsc_scanline_intensity]; + + snes_ntsc_init (&snes_ntsc, &gui_config->ntsc_setup); + + return; +} + +void +S9xDisplayReconfigure (void) +{ + ntsc_filter_init (); + + if (pool) + { + g_thread_pool_set_max_threads (pool, gui_config->num_threads - 1, NULL); + } + + return; +} + +void +S9xQueryDrivers (void) +{ +#ifdef USE_XV + gui_config->allow_xv = S9xXVDisplayDriver::query_availability (); +#else + gui_config->allow_xv = 0; +#endif + +#ifdef USE_OPENGL + gui_config->allow_opengl = S9xOpenGLDisplayDriver::query_availability (); +#else + gui_config->allow_opengl = 0; +#endif + +#ifdef USE_XRANDR + int error_base_p, event_base_p; + + gui_config->allow_xrandr = 1; + + if (!XRRQueryExtension (GDK_DISPLAY (), &event_base_p, &error_base_p)) + { + gui_config->allow_xrandr = 0; + gui_config->change_display_resolution = FALSE; + } + + if (gui_config->allow_xrandr) + { + gui_config->xrr_config = XRRGetScreenInfo (GDK_DISPLAY (), + DefaultRootWindow (GDK_DISPLAY ())); + gui_config->xrr_original_size = + XRRConfigCurrentConfiguration (gui_config->xrr_config, + &(gui_config->xrr_rotation)); + gui_config->xrr_sizes = XRRConfigSizes (gui_config->xrr_config, + &(gui_config->xrr_num_sizes)); + } +#else + gui_config->allow_xrandr = 0; +#endif + + return; +} + +bool8 +S9xDeinitUpdate (int width, int height) +{ + if (!Settings.Paused +#ifdef NETPLAY_SUPPORT + && !NetPlay.Paused +#endif + ) + + { + if (gui_config->overscan) + height = (height > SNES_HEIGHT_EXTENDED) ? + SNES_HEIGHT_EXTENDED * 2 : + SNES_HEIGHT_EXTENDED; + else + if (height > SNES_HEIGHT_EXTENDED) + height = 448; + else + height = 224; + + if (gui_config->force_hires) + { + S9xForceHires (GFX.Screen, + S9xDisplayDriver::image_width * + S9xDisplayDriver::image_bpp, + width, + height); + } + + GFX.Screen = driver->get_next_buffer (); + } + + top_level->last_width = width; + top_level->last_height = height; + + driver->update (width, height); + + return TRUE; +} + +static void +S9xInitDriver (void) +{ + switch (gui_config->hw_accel) + { +#ifdef USE_OPENGL + case HWA_OPENGL: + + driver = new S9xOpenGLDisplayDriver (top_level, + gui_config); + + break; +#endif +#ifdef USE_XV + case HWA_XV: + + driver = new S9xXVDisplayDriver (top_level, gui_config); + + break; +#endif + default: + + driver = new S9xGTKDisplayDriver (top_level, gui_config); + } + + if (driver->init ()) + { + if (gui_config->hw_accel > 0) + { + driver->deinit (); + delete driver; + + gui_config->hw_accel = HWA_NONE; + + S9xInitDriver (); + } + else + { + fprintf (stderr, "Error: Couldn't initialize any display output.\n"); + exit (1); + } + } + + pool = NULL; + + return; +} + +void +S9xInitDisplay (int argc, char **argv) +{ + Settings.SupportHiRes = TRUE; + S9xSetRenderPixelFormat (RGB555); + S9xBlit2xSaIFilterInit (); + S9xBlitHQ2xFilterInit (); + + S9xQueryDrivers (); + S9xInitDriver (); + S9xGraphicsInit (); + S9xDisplayReconfigure (); + + return; +} + +void +S9xDisplayClearBuffers (void) +{ + driver->clear_buffers (); + + return; +} + +void +S9xDeinitDisplay (void) +{ + driver->deinit (); + delete driver; + + driver = NULL; + GFX.Screen = NULL; + + if (pool) + g_thread_pool_free (pool, FALSE, TRUE); + + return; +} + +void +S9xReinitDisplay (void) +{ + uint16 *buffer = NULL; + int width, height; + + buffer = (uint16 *) malloc (S9xDisplayDriver::image_size); + memmove (buffer, + driver->get_current_buffer (), + S9xDisplayDriver::image_size); + + width = top_level->last_width; + height = top_level->last_height; + + S9xDeinitDisplay (); + S9xInitDriver (); + S9xDisplayReconfigure (); + + top_level->last_width = width; + top_level->last_height = height; + + driver->push_buffer (buffer); + + free (buffer); + + return; +} + +bool8 +S9xContinueUpdate (int width, int height) +{ + return TRUE; +} + +bool8 +S9xInitUpdate (void) +{ + return TRUE; +} + +void +S9xSetPalette (void) +{ + return; +} + +void +S9xTextMode (void) +{ + return; +} + +void +S9xGraphicsMode (void) +{ + return; +} + + diff --git a/gtk/src/gtk_display.h b/gtk/src/gtk_display.h new file mode 100644 index 00000000..039b90c9 --- /dev/null +++ b/gtk/src/gtk_display.h @@ -0,0 +1,110 @@ +#ifndef __GTK_DISPLAY_H +#define __GTK_DISPLAY_H + +#include "gtk_s9x.h" +#include "filter/2xsai.h" +#include "filter/hq2x.h" +#include "filter/epx.h" +#include "filter_epx_unsafe.h" + +#define FILTER_NONE 0 +#define FILTER_SUPEREAGLE 1 +#define FILTER_2XSAI 2 +#define FILTER_SUPER2XSAI 3 +#define FILTER_HQ2X 4 +#define FILTER_HQ3X 5 +#define FILTER_HQ4X 6 +#define FILTER_EPX 7 +#define FILTER_EPX_SMOOTH 8 +#define FILTER_NTSC 9 +#define FILTER_SCANLINES 10 +#define NUM_FILTERS 11 + +#define NTSC_COMPOSITE 0 +#define NTSC_SVIDEO 1 +#define NTSC_RGB 2 + +#define ENDIAN_LSB 0 +#define ENDIAN_MSB 1 + +#define JOB_FILTER 0 +#define JOB_CONVERT 1 +#define JOB_SCALE_AND_CONVERT 2 +#define JOB_CONVERT_YUV 3 +#define JOB_CONVERT_MASK 4 + +typedef struct thread_job_t +{ + int operation_type; + uint8 *src_buffer; + int src_pitch; + uint8 *dst_buffer; + int dst_pitch; + int width; + int height; + int dst_width; + int dst_height; + int bpp; + int inv_rmask; + int inv_gmask; + int inv_bmask; + + volatile int complete; +} +thread_job_t; + +void S9xRegisterYUVTables (uint8 *y, uint8 *u, uint8 *v); +void S9xSetEndianess (int type); +double S9xGetAspect (void); + +void S9xConvertYUV (void *src_buffer, + void *dst_buffer, + int src_pitch, + int dst_pitch, + int width, + int height); + +void S9xConvert (void *src, + void *dst, + int src_pitch, + int dst_pitch, + int width, + int height, + int bpp); + +void S9xConvertScale (void *src, + void *dst, + int src_pitch, + int dst_pitch, + int width, + int height, + int dest_width, + int dest_height, + int bpp); + +void S9xConvertMask (void *src, + void *dst, + int src_pitch, + int dst_pitch, + int width, + int height, + int rshift, + int gshift, + int bshift, + int bpp); + +void S9xFilter (uint8 *src_buffer, + int src_pitch, + uint8 *dst_buffer, + int dst_pitch, + int& width, + int& height); +void get_filter_scale (int& width, int& height); + +void S9xDisplayRefresh (int width, int height); +void S9xDisplayClearBuffers (void); +void S9xReinitDisplay (void); +void S9xDisplayReconfigure (void); +void S9xQueryDrivers (void); + +#endif /* __GTK_DISPLAY_H */ diff --git a/gtk/src/gtk_display_driver.h b/gtk/src/gtk_display_driver.h new file mode 100644 index 00000000..a3d9f11c --- /dev/null +++ b/gtk/src/gtk_display_driver.h @@ -0,0 +1,45 @@ +#ifndef __GTK_DISPLAY_DRIVER_H +#define __GTK_DISPLAY_DRIVER_H + +#include "gtk_s9x.h" + +class S9xDisplayDriver +{ + public: + virtual void refresh (int width, int height) = 0; + virtual int init (void) = 0; + virtual void deinit (void) = 0; + virtual void clear_buffers (void) = 0; + virtual void update (int width, int height) = 0; + virtual uint16 *get_next_buffer (void) = 0; + virtual uint16 *get_current_buffer (void) = 0; + virtual void push_buffer (uint16 *src) = 0; + virtual void reconfigure (int width, int height) = 0; + + /* Namespaced sizing constants */ + static const int image_width = 512; + static const int image_height = 478; + static const int image_bpp = 2; + static const int scaled_max_width = 1024; + static const int scaled_max_height = 956; + + static const int image_size = image_width * image_height * image_bpp; + static const int image_padded_size = (image_width + 8) * + (image_height + 8) * + image_bpp; + static const int scaled_size = scaled_max_width * + scaled_max_height * + image_bpp; + static const int scaled_padded_size = (scaled_max_width + 8) * + (scaled_max_height + 8) * + image_bpp; + + protected: + Snes9xWindow *window; + Snes9xConfig *config; + GtkWidget *drawing_area; + void *padded_buffer[4]; + void *buffer[4]; +}; + +#endif /* __GTK_DISPLAY_DRIVER_H*/ diff --git a/gtk/src/gtk_display_driver_gtk.cpp b/gtk/src/gtk_display_driver_gtk.cpp new file mode 100644 index 00000000..394a1ea0 --- /dev/null +++ b/gtk/src/gtk_display_driver_gtk.cpp @@ -0,0 +1,387 @@ +#include +#include "gtk_display.h" +#include "gtk_display_driver_gtk.h" + + +S9xGTKDisplayDriver::S9xGTKDisplayDriver (Snes9xWindow *window, + Snes9xConfig *config) +{ + this->window = window; + this->config = config; + this->drawing_area = GTK_WIDGET (window->drawing_area); + + return; +} + +void +S9xGTKDisplayDriver::update (int width, int height) +{ + int c_width, c_height, final_pitch; + uint8 *final_buffer; + + c_width = drawing_area->allocation.width; + c_height = drawing_area->allocation.height; + + if (width == SIZE_FLAG_DIRTY) + { + this->clear (); + return; + } + + if (width <= 0) + return; + + if (config->scale_method > 0) + { + uint8 *src_buffer = (uint8 *) padded_buffer[0]; + uint8 *dst_buffer = (uint8 *) padded_buffer[1]; + int src_pitch = image_width * image_bpp; + int dst_pitch = scaled_max_width * image_bpp; + + S9xFilter (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + final_buffer = (uint8 *) padded_buffer[1]; + final_pitch = dst_pitch; + } + else + { + final_buffer = (uint8 *) padded_buffer[0]; + final_pitch = image_width * image_bpp; + } + + if (!config->scale_to_fit && + (width > gdk_buffer_width || height > gdk_buffer_height)) + { + this->clear (); + + return; + } + + if (config->scale_to_fit) + { + double screen_aspect = (double) c_width / (double) c_height; + double snes_aspect = S9xGetAspect (); + double granularity = 1.0 / (double) MAX (c_width, c_height); + + if (config->maintain_aspect_ratio && + !(screen_aspect <= snes_aspect * (1.0 + granularity) && + screen_aspect >= snes_aspect * (1.0 - granularity))) + { + if (screen_aspect > snes_aspect) + { + output (final_buffer, + final_pitch, + (c_width - (int) (c_height * snes_aspect)) / 2, + 0, + width, + height, + (int) (c_height * snes_aspect), + c_height); + } + else + { + output (final_buffer, + final_pitch, + 0, + (c_height - c_width / snes_aspect) / 2, + width, + height, + c_width, + (c_width / snes_aspect)); + } + } + else + { + output (final_buffer, + final_pitch, + 0, + 0, + width, + height, + c_width, + c_height); + } + } + else + { + output (final_buffer, + final_pitch, + (c_width - width) / 2, + (c_height - height) / 2, + width, + height, + width, + height); + } + + return; +} + +void +S9xGTKDisplayDriver::output (void *src, + int src_pitch, + int x, + int y, + int width, + int height, + int dst_width, + int dst_height) +{ + GdkGC *gc = drawing_area->style->bg_gc[GTK_WIDGET_STATE (drawing_area)]; + + if (width != dst_width || height != dst_height) + { + S9xConvertScale (src, + padded_buffer[2], + src_pitch, + gdk_buffer_width * 3, + width, + height, + dst_width, dst_height, + 24); + } + else + { + S9xConvert (src, + padded_buffer[2], + src_pitch, + gdk_buffer_width * 3, + width, + height, + 24); + } + + gdk_draw_rgb_image (drawing_area->window, + gc, + x, y, + dst_width, dst_height, + GDK_RGB_DITHER_NORMAL, + (guchar *) padded_buffer[2], + gdk_buffer_width * 3); + + window->set_mouseable_area (x, y, width, height); + + return; +} + +int +S9xGTKDisplayDriver::init (void) +{ + int padding; + + buffer[0] = malloc (image_padded_size); + buffer[1] = malloc (scaled_padded_size); + + padding = (image_padded_size - image_size) / 2; + padded_buffer[0] = (void *) (((uint8 *) buffer[0]) + padding); + + padding = (scaled_padded_size - scaled_size) / 2; + padded_buffer[1] = (void *) (((uint8 *) buffer[1]) + padding); + + gdk_buffer_width = drawing_area->allocation.width; + gdk_buffer_height = drawing_area->allocation.height; + + padded_buffer[2] = malloc (gdk_buffer_width * gdk_buffer_height * 3); + S9xSetEndianess (ENDIAN_MSB); + + memset (buffer[0], 0, image_padded_size); + memset (buffer[1], 0, scaled_padded_size); + + GFX.Screen = (uint16 *) padded_buffer[0]; + GFX.Pitch = image_width * image_bpp; + + return 0; +} + +void +S9xGTKDisplayDriver::deinit (void) +{ + padded_buffer[0] = NULL; + padded_buffer[1] = NULL; + + free (buffer[0]); + free (buffer[1]); + free (padded_buffer[2]); + + return; +} + +void +S9xGTKDisplayDriver::clear (void) +{ + int w, h; + int c_width = drawing_area->allocation.width; + int c_height = drawing_area->allocation.height; + GdkColor black = { 0, 0, 0, 0 }; + GdkGC *gc = NULL; + + gc = drawing_area->style->fg_gc[GTK_WIDGET_STATE (drawing_area)]; + gdk_gc_set_rgb_fg_color (gc, &black); + + if (window->last_width <= 0 || window->last_height <= 0) + { + gdk_draw_rectangle (drawing_area->window, + gc, + TRUE, + 0, 0, + c_width, c_height); + return; + } + + /* Get width of modified display */ + w = window->last_width; + h = window->last_height; + get_filter_scale (w, h); + + if (config->scale_to_fit) + { + double screen_aspect = (double) c_width / (double) c_height; + double snes_aspect = S9xGetAspect (); + double granularity = 1.0 / (double) MAX (c_width, c_height); + + if (config->maintain_aspect_ratio && + !(screen_aspect <= snes_aspect * (1.0 + granularity) && + screen_aspect >= snes_aspect * (1.0 - granularity))) + { + int bar_size; + if (screen_aspect > snes_aspect) + { + /* Black bars on left and right */ + w = (int) (c_height * snes_aspect); + bar_size = (c_width - w) / 2; + + gdk_draw_rectangle (drawing_area->window, + gc, + TRUE, + 0, 0, + bar_size, c_height); + gdk_draw_rectangle (drawing_area->window, + gc, + TRUE, + bar_size + w, 0, + c_width - bar_size - w, + c_height); + } + else + { + /* Black bars on top and bottom */ + h = (int) (c_width / snes_aspect); + bar_size = (c_height - h) / 2; + gdk_draw_rectangle (drawing_area->window, + gc, + TRUE, + 0, 0, + c_width, bar_size); + gdk_draw_rectangle (drawing_area->window, + gc, + TRUE, + 0, bar_size + h, + c_width, + c_height - bar_size - h); + } + } + else + return; + } + else + { + /* Black bars on top, bottom, left, and right :-) */ + int bar_width, bar_height; + + bar_height = (c_height - h) / 2; + bar_width = (c_width - w) / 2; + + gdk_draw_rectangle (drawing_area->window, + gc, + TRUE, + 0, 0, + c_width, bar_height); + gdk_draw_rectangle (drawing_area->window, + gc, + TRUE, + 0, + bar_height + h, + c_width, + c_height - (bar_height + h)); + gdk_draw_rectangle (drawing_area->window, + gc, + TRUE, + 0, bar_height, + bar_width, h); + gdk_draw_rectangle (drawing_area->window, + gc, + TRUE, + bar_width + w, bar_height, + c_width - (bar_width + w), + h); + } + + return; +} + +void +S9xGTKDisplayDriver::refresh (int width, int height) +{ + int c_width, c_height; + + c_width = drawing_area->allocation.width; + c_height = drawing_area->allocation.height; + + if (c_width != gdk_buffer_width || c_height != gdk_buffer_height) + { + free (padded_buffer[2]); + + gdk_buffer_width = c_width; + gdk_buffer_height = c_height; + + padded_buffer[2] = malloc (gdk_buffer_width * gdk_buffer_height * 3); + } + + if (!config->rom_loaded) + return; + + clear (); + + return; +} + +uint16 * +S9xGTKDisplayDriver::get_next_buffer (void) +{ + return (uint16 *) padded_buffer[0]; +} + +uint16 * +S9xGTKDisplayDriver::get_current_buffer (void) +{ + return (uint16 *) padded_buffer[0]; +} + +void +S9xGTKDisplayDriver::push_buffer (uint16 *src) +{ + memmove (GFX.Screen, src, image_size); + update (window->last_width, window->last_height); + + return; +} + +void +S9xGTKDisplayDriver::clear_buffers (void) +{ + memset (buffer[0], 0, image_padded_size); + memset (buffer[1], 0, scaled_padded_size); + + return; +} + +void +S9xGTKDisplayDriver::reconfigure (int width, int height) +{ + return; +} diff --git a/gtk/src/gtk_display_driver_gtk.h b/gtk/src/gtk_display_driver_gtk.h new file mode 100644 index 00000000..fd4e7619 --- /dev/null +++ b/gtk/src/gtk_display_driver_gtk.h @@ -0,0 +1,36 @@ +#ifndef __GTK_DISPLAY_DRIVER_GTK_H +#define __GTK_DISPLAY_DRIVER_GTK_H + +#include "gtk_s9x.h" +#include "gtk_display_driver.h" + +class S9xGTKDisplayDriver : public S9xDisplayDriver +{ + public: + S9xGTKDisplayDriver (Snes9xWindow *window, Snes9xConfig *config); + void refresh (int width, int height); + int init (void); + void deinit (void); + void clear_buffers (void); + void update (int width, int height); + uint16 *get_next_buffer (void); + uint16 *get_current_buffer (void); + void push_buffer (uint16 *src); + void reconfigure (int width, int height); + + private: + void clear (void); + void output (void *src, + int src_pitch, + int x, + int y, + int width, + int height, + int dst_width, + int dst_height); + + int gdk_buffer_width; + int gdk_buffer_height; +}; + +#endif /* __GTK_DISPLAY_DRIVER_GTK_H */ diff --git a/gtk/src/gtk_display_driver_opengl.cpp b/gtk/src/gtk_display_driver_opengl.cpp new file mode 100644 index 00000000..268b6a9d --- /dev/null +++ b/gtk/src/gtk_display_driver_opengl.cpp @@ -0,0 +1,787 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gtk_display.h" +#include "gtk_display_driver_opengl.h" + +static const char *glGenBuffersNames[] = { "glGenBuffers", + "glGenBuffersARB", + "glGenBuffersEXT", + NULL }; +static const char *glDeleteBuffersNames[] = { "glDeleteBuffers", + "glDeleteBuffersARB", + "glDeleteBuffersEXT", + NULL }; +static const char *glBindBufferNames[] = { "glBindBuffer", + "glBindBufferARB", + "glBindBufferEXT", + NULL }; +static const char *glBufferDataNames[] = { "glBufferData", + "glBufferDataARB", + "glBufferDataEXT", + NULL }; +static const char *glBufferSubDataNames[] = { "glBufferSubData", + "glBufferSubDataARB", + "glBufferSubDataEXT", + NULL }; +static const char *glMapBufferNames[] = { "glMapBuffer", + "glMapBufferARB", + "glMapBufferEXT", + NULL }; +static const char *glUnmapBufferNames[] = { "glUnmapBuffer", + "glUnmapBufferARB", + "glUnmapBufferEXT", + NULL }; + +gl_proc +get_null_address_proc (const GLubyte *name) +{ + return NULL; +} + +gl_proc +S9xOpenGLDisplayDriver::get_aliased_extension (const char **name) +{ + gl_proc ext_proc = NULL; + + for (int i = 0; name[i]; i++) + { + ext_proc = glGetProcAddress ((GLubyte *) name[i]); + + if (ext_proc) + break; + } + + return ext_proc; +} + +S9xOpenGLDisplayDriver::S9xOpenGLDisplayDriver (Snes9xWindow *window, + Snes9xConfig *config) +{ + void *dl_handle = NULL; + + this->window = window; + this->config = config; + this->drawing_area = GTK_WIDGET (window->drawing_area); + + dl_handle = dlopen (NULL, RTLD_LAZY); + + if (dl_handle) + { + dlerror (); + +#ifdef __GNUC__ +__extension__ +#endif + getProcAddressProc functor = reinterpret_cast (dlsym (dl_handle, "glXGetProcAddress")); + glGetProcAddress = functor; + + if (dlerror () != NULL) + { +#ifdef __GNUC__ +__extension__ +#endif + getProcAddressProc functor = reinterpret_cast (dlsym (dl_handle, "glXGetProcAddressARB")); + glGetProcAddress = functor; + + if (dlerror () != NULL) + glGetProcAddress = get_null_address_proc; + } + + /* ok to close the handle, since didn't really open anything */ + dlclose (dl_handle); + } + else + { + glGetProcAddress = get_null_address_proc; + } + + return; +} + +void +S9xOpenGLDisplayDriver::update (int width, int height) +{ + GLint filter; + uint8 *final_buffer = NULL; + int final_pitch; + int c_width, c_height; + void *pboMemory = NULL; + + c_width = drawing_area->allocation.width; + c_height = drawing_area->allocation.height; + + if (width <= 0) + return; + + gl_lock (); + + /* This avoids messing with the texture parameters every time */ + if (config->bilinear_filter != filtering) + { + filter = config->bilinear_filter ? GL_LINEAR : GL_NEAREST; + glTexParameteri (tex_target, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri (tex_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (tex_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + filtering = config->bilinear_filter; + } + + glClear (GL_COLOR_BUFFER_BIT); + glEnable (tex_target); + + if (config->scale_method > 0) + { + uint8 *src_buffer = (uint8 *) padded_buffer[0]; + int src_pitch = image_width * image_bpp; + uint8 *dst_buffer; + int dst_pitch; + + dst_buffer = (uint8 *) padded_buffer[1]; + dst_pitch = scaled_max_width * image_bpp; + final_buffer = (uint8 *) padded_buffer[1]; + final_pitch = scaled_max_width * image_bpp; + + S9xFilter (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + } + else + { + final_buffer = (uint8 *) padded_buffer[0]; + final_pitch = image_width * image_bpp; + } + + double screen_aspect = (double) c_width / (double) c_height; + double snes_aspect = S9xGetAspect (); + double granularity = 1.0 / (double) MAX (c_width, c_height); + + if (!config->scale_to_fit) + { + glViewport ((c_width - width) / 2, (c_height - height) / 2, + width, height); + + window->set_mouseable_area ((c_width - width) / 2, + (c_height - height) / 2, + width, + height); + } + + else if (config->maintain_aspect_ratio && + !(screen_aspect <= snes_aspect * (1.0 + granularity) && + screen_aspect >= snes_aspect * (1.0 - granularity))) + { + if (screen_aspect > snes_aspect) + { + glViewport ((c_width - (int)(c_height * snes_aspect)) / 2, 0, + (int)(c_height * snes_aspect), c_height); + + window->set_mouseable_area ((c_width - + (int) (c_height * snes_aspect)) / 2, + 0, + (int) (c_height * snes_aspect), + c_height); + } + + else + { + glViewport (0, (c_height - (int) (c_width / snes_aspect)) / 2, + c_width, (int) (c_width / snes_aspect)); + window->set_mouseable_area (0, + (c_height - + (int) (c_width / snes_aspect)) / 2, + c_width, + (int) (c_width / snes_aspect)); + } + } + + else + { + glViewport (0, 0, c_width, c_height); + window->set_mouseable_area (0, 0, c_width, c_height); + } + + if (width > 0 && height > 0) + { + update_texture_size (width, height); + + if (using_pbos) + { + if (config->pbo_format == PBO_FMT_16) + { + + glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); + glBufferData (GL_PIXEL_UNPACK_BUFFER, + width * height * 2, + NULL, + GL_STREAM_DRAW); + pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + + for (int y = 0; y < height; y++) + { + memcpy ((uint8 *) pboMemory + (width * y * 2), + final_buffer + (y * final_pitch), + width * image_bpp); + } + + glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); + + glPixelStorei (GL_UNPACK_ROW_LENGTH, width); + glTexSubImage2D (tex_target, + 0, + 0, + 0, + width, + height, + GL_BGRA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + BUFFER_OFFSET (0)); + + glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); + } + else if (config->pbo_format == PBO_FMT_24) + { + /* Complement width to next multiple of 4 to force line size to + * be a multiple of 4 bytes. Otherwise, packing fails. */ + int width_mul_4 = width + ((4 - (width % 4)) % 4); + + glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); + glBufferData (GL_PIXEL_UNPACK_BUFFER, + width_mul_4 * height * 3, + NULL, + GL_STREAM_DRAW); + pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + + /* Pixel swizzling in software */ + S9xSetEndianess (ENDIAN_MSB); + S9xConvert (final_buffer, + pboMemory, + final_pitch, + width_mul_4 * 3, + width, + height, + 24); + + glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); + + glPixelStorei (GL_UNPACK_ROW_LENGTH, width_mul_4); + glTexSubImage2D (tex_target, + 0, + 0, + 0, + width, + height, + GL_RGB, + GL_UNSIGNED_BYTE, + BUFFER_OFFSET (0)); + + glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); + } + else /* PBO_FMT_32 */ + { + glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); + glBufferData (GL_PIXEL_UNPACK_BUFFER, + width * height * 4, + NULL, + GL_STREAM_DRAW); + pboMemory = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + + /* Pixel swizzling in software */ +#ifdef __BIG_ENDIAN__ + S9xSetEndianess (ENDIAN_MSB); +#else + S9xSetEndianess (ENDIAN_LSB); +#endif + S9xConvert (final_buffer, + pboMemory, + final_pitch, + width * 4, + width, + height, + 32); + + glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER); + + glPixelStorei (GL_UNPACK_ROW_LENGTH, width); + glTexSubImage2D (tex_target, + 0, + 0, + 0, + width, + height, + GL_BGRA, + PBO_BGRA_NATIVE_ORDER, + BUFFER_OFFSET (0)); + + glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); + } + } + else + { + glPixelStorei (GL_UNPACK_ROW_LENGTH, final_pitch / image_bpp); + glTexSubImage2D (tex_target, + 0, + 0, + 0, + width, + height, + GL_BGRA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + final_buffer); + } + + if (tex_target == GL_TEXTURE_2D) + { + texcoords[1] = (float) (height) / texture_height; + texcoords[2] = (float) (width) / texture_width; + texcoords[3] = texcoords[1]; + texcoords[4] = texcoords[2]; + } + else if (tex_target == GL_TEXTURE_RECTANGLE) + { + texcoords[1] = (float) (height); + texcoords[2] = (float) (width); + texcoords[3] = texcoords[1]; + texcoords[4] = texcoords[2]; + } + + glDrawArrays (GL_QUADS, 0, 4); + } + + gl_unlock (); + gl_swap (); + + return; +} + +void +S9xOpenGLDisplayDriver::clear_buffers (void) +{ + memset (buffer[0], 0, image_padded_size); + memset (buffer[1], 0, scaled_padded_size); + + gl_lock (); + + glPixelStorei (GL_UNPACK_ROW_LENGTH, scaled_max_width); + glTexSubImage2D (tex_target, + 0, + 0, + 0, + scaled_max_width, + scaled_max_height, + GL_BGRA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + buffer[1]); + gl_unlock (); + + return; +} + +void +S9xOpenGLDisplayDriver::update_texture_size (int width, int height) +{ + if (width != texture_width || height != texture_height) + { + if (dyn_resizing) + { + glBindTexture (tex_target, texmap); + + if (using_pbos) + { + glTexImage2D (tex_target, + 0, + config->pbo_format == PBO_FMT_16 ? GL_RGB5_A1 : 4, + width, + height, + 0, + GL_RGB, + GL_UNSIGNED_BYTE, + NULL); + } + else + { + glTexImage2D (tex_target, + 0, + GL_RGB5_A1, + width, + height, + 0, + GL_BGRA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + NULL); + } + + texture_width = width; + texture_height = height; + } + } + + return; +} + +int +S9xOpenGLDisplayDriver::load_pixel_buffer_functions (void) +{ + const char *extensions = (const char *) glGetString (GL_EXTENSIONS); + + if (strstr (extensions, "pixel_buffer_object")) + { + glGenBuffers = + (glGenBuffersProc) + get_aliased_extension (glGenBuffersNames); + + glDeleteBuffers = + (glDeleteBuffersProc) + get_aliased_extension (glDeleteBuffersNames); + + glBindBuffer = + (glBindBufferProc) + get_aliased_extension (glBindBufferNames); + + glBufferData = + (glBufferDataProc) + get_aliased_extension (glBufferDataNames); + + glBufferSubData = + (glBufferSubDataProc) + get_aliased_extension (glBufferSubDataNames); + + glMapBuffer = + (glMapBufferProc) + get_aliased_extension (glMapBufferNames); + + glUnmapBuffer = + (glUnmapBufferProc) + get_aliased_extension (glUnmapBufferNames); + + if (!glGenBuffers || + !glBindBuffer || + !glBufferData || + !glBufferSubData || + !glMapBuffer || + !glUnmapBuffer || + !glDeleteBuffers) + { + return 0; + } + } + + else + { + return 0; + } + + return 1; +} + +void +S9xOpenGLDisplayDriver::opengl_defaults (void) +{ + XVisualInfo *vi; + int glx_attribs[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None }; + Display *display = GDK_DISPLAY (); + + vi = glXChooseVisual (display, DefaultScreen (display), glx_attribs); + + glx_context = glXCreateContext (display, + vi, + 0, + 1); + glXMakeCurrent (display, GDK_WINDOW_XWINDOW (drawing_area->window), glx_context); + + gl_lock (); + + const char *extensions = (const char *) glGetString (GL_EXTENSIONS); + + using_pbos = 0; + if (config->use_pbos) + { + if (!load_pixel_buffer_functions ()) + { + fprintf (stderr, _("pixel_buffer_object extension not supported.\n")); + + config->use_pbos = 0; + } + else + { + using_pbos = 1; + } + } + + tex_target = GL_TEXTURE_2D; + texture_width = 1024; + texture_height = 1024; + dyn_resizing = FALSE; + + if (config->npot_textures) + { + if (strstr (extensions, "_texture_rectangle")) + { + tex_target = GL_TEXTURE_RECTANGLE; + texture_width = scaled_max_width; + texture_height = scaled_max_height; + dyn_resizing = TRUE; + } + else if (strstr (extensions, "GL_ARB_texture_non_power_of_two")) + { + dyn_resizing = TRUE; + } + } + + glEnable (GL_VERTEX_ARRAY); + glEnable (GL_TEXTURE_COORD_ARRAY); + + vertices[0] = 0.0f; + vertices[1] = 0.0f; + vertices[2] = 1.0f; + vertices[3] = 0.0f; + vertices[4] = 1.0f; + vertices[5] = 1.0f; + vertices[6] = 0.0f; + vertices[7] = 1.0f; + + glVertexPointer (2, GL_FLOAT, 0, vertices); + + texcoords[0] = 0.0f; + texcoords[5] = 0.0f; + texcoords[6] = 0.0f; + texcoords[7] = 0.0f; + + glTexCoordPointer (2, GL_FLOAT, 0, texcoords); + + if (config->use_pbos) + { + glGenBuffers (1, &pbo); + glGenTextures (1, &texmap); + + glBindTexture (tex_target, texmap); + glTexImage2D (tex_target, + 0, + config->pbo_format == PBO_FMT_16 ? GL_RGB5_A1 : 4, + texture_width, + texture_height, + 0, + GL_RGB, + GL_UNSIGNED_BYTE, + NULL); + + glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo); + glBufferData (GL_PIXEL_UNPACK_BUFFER, + texture_width * texture_height * 3, + NULL, + GL_STREAM_DRAW); + + glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); + } + else + { + glGenTextures (1, &texmap); + + glBindTexture (tex_target, texmap); + glTexImage2D (tex_target, + 0, + GL_RGB5_A1, + texture_width, + texture_height, + 0, + GL_BGRA, + GL_UNSIGNED_SHORT_1_5_5_5_REV, + NULL); + } + + glEnable (GL_DITHER); + + glDisable (GL_POLYGON_SMOOTH); + glShadeModel (GL_FLAT); + glPolygonMode (GL_FRONT, GL_FILL); + + glEnable (GL_CULL_FACE); + glCullFace (GL_BACK); + + glClearColor (0.0, 0.0, 0.0, 0.0); + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glDisable (GL_BLEND); + glDisable (GL_DEPTH_TEST); + glDisable (GL_TEXTURE_2D); + glDisable (GL_TEXTURE_RECTANGLE); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + glOrtho (0.0, 1.0, 0.0, 1.0, -1, 1); + + gl_unlock (); + + return; +} + +void +S9xOpenGLDisplayDriver::refresh (int width, int height) +{ + return; +} + +int +S9xOpenGLDisplayDriver::init (void) +{ + int padding; + + opengl_defaults (); + + /* Create two system buffers to avoid DMA contention */ + + buffer[0] = malloc (image_padded_size); + buffer[1] = malloc (scaled_padded_size); + + clear_buffers (); + + padding = (image_padded_size - image_size) / 2; + padded_buffer[0] = (void *) (((uint8 *) buffer[0]) + padding); + + padding = (scaled_padded_size - scaled_size) / 2; + padded_buffer[1] = (void *) (((uint8 *) buffer[1]) + padding); + + GFX.Screen = (uint16 *) padded_buffer[0]; + GFX.Pitch = image_width * image_bpp; + + filtering = -1; + + this->swap_control (config->sync_to_vblank); + + return 0; +} + +void +S9xOpenGLDisplayDriver::swap_control (int enable) +{ + glSwapIntervalProc glSwapInterval = NULL; + const char *ext_str; + + ext_str = glXQueryExtensionsString (GDK_DISPLAY (), + GDK_SCREEN_XNUMBER ( + gdk_screen_get_default ())); + + /* We try to set this with both extensions since some cards pretend + * to support both, but ignore one. */ + + if (strstr (ext_str, "GLX_MESA_swap_control")) + { + glSwapInterval = (glSwapIntervalProc) + glGetProcAddress ((GLubyte *) "glXSwapIntervalMESA"); + if (glSwapInterval) + glSwapInterval (enable ? 1 : 0); + } + + else if (strstr (ext_str, "GLX_SGI_swap_control")) + { + glSwapInterval = (glSwapIntervalProc) + glGetProcAddress ((GLubyte *) "glXSwapIntervalSGI"); + if (glSwapInterval) + { + glSwapInterval (enable ? 1 : 0); + } + } + + return; +} + +uint16 * +S9xOpenGLDisplayDriver::get_next_buffer (void) +{ + return (uint16 *) padded_buffer[0]; +} + +void +S9xOpenGLDisplayDriver::push_buffer (uint16 *src) +{ + memmove (padded_buffer[0], src, image_size); + update (window->last_width, window->last_height); + + return; +} + +uint16 * +S9xOpenGLDisplayDriver::get_current_buffer (void) +{ + return (uint16 *) padded_buffer[0]; +} + +void +S9xOpenGLDisplayDriver::gl_lock (void) +{ + + return; +} + +void +S9xOpenGLDisplayDriver::gl_unlock (void) +{ + + return; +} + +void +S9xOpenGLDisplayDriver::gl_swap (void) +{ + glXSwapBuffers (GDK_DISPLAY (), GDK_WINDOW_XWINDOW (drawing_area->window)); + + return; +} + +void +S9xOpenGLDisplayDriver::deinit (void) +{ + glXDestroyContext (GDK_DISPLAY (), glx_context); + + GFX.Screen = NULL; + + padded_buffer[0] = NULL; + padded_buffer[1] = NULL; + + free (buffer[0]); + free (buffer[1]); + + gl_lock (); + + if (using_pbos) + { + glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0); + glDeleteBuffers (1, &pbo); + } + + glDeleteTextures (1, &texmap); + + gl_unlock (); + + return; +} + +void +S9xOpenGLDisplayDriver::reconfigure (int width, int height) +{ + return; +} + +int +S9xOpenGLDisplayDriver::query_availability (void) +{ + int errorBase, eventBase; + + if (glXQueryExtension (GDK_DISPLAY (), &errorBase, &eventBase) == False) + { + if (gui_config->hw_accel == HWA_OPENGL) + gui_config->hw_accel = HWA_NONE; + return 0; + } + + return 1; + +} diff --git a/gtk/src/gtk_display_driver_opengl.h b/gtk/src/gtk_display_driver_opengl.h new file mode 100644 index 00000000..6639133c --- /dev/null +++ b/gtk/src/gtk_display_driver_opengl.h @@ -0,0 +1,97 @@ +#ifndef __GTK_DISPLAY_DRIVER_OPENGL_H +#define __GTK_DISPLAY_DRIVER_OPENGL_H + +#include "gtk_s9x.h" +#include "gtk_display_driver.h" + +#include +#include + +#define PBO_FMT_16 0 +#define PBO_FMT_24 1 +#define PBO_FMT_32 2 + +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_WRITE_ONLY 0x88B9 +#define GL_STREAM_DRAW 0x88E0 +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define BUFFER_OFFSET(i) ((char *) NULL + (i)) + +#ifdef __BIG_ENDIAN__ +/* We have to reverse the bytes on MSB systems. This can be slow */ +/* GL_UNSIGNED_INT_8_8_8_8_REV = 0x8367 */ +#define PBO_BGRA_NATIVE_ORDER 0x8367 +#else +#define PBO_BGRA_NATIVE_ORDER GL_UNSIGNED_BYTE +#endif + +/* The following are procedure pointer types. + * These aren't necessarily guaranteed to be in GL 1.1 */ +typedef int (*glSwapIntervalProc) (int interval); + +typedef void (*gl_proc) (void); +typedef gl_proc (*getProcAddressProc) (const GLubyte *name); + +typedef void (*glGenBuffersProc) (GLsizei n, GLuint *buffers); +typedef void (*glDeleteBuffersProc) (GLsizei n, const GLuint *buffers); +typedef void (*glBindBufferProc) (GLenum target, GLuint buffer); +typedef void (*glBufferDataProc) (GLenum target, + GLsizeiptr size, + const GLvoid *data, + GLenum usage); +typedef void (*glBufferSubDataProc) (GLenum target, + GLintptr offset, + GLsizeiptr size, + const GLvoid *data); +typedef GLvoid *(*glMapBufferProc) (GLenum target, GLenum access); +typedef GLboolean (*glUnmapBufferProc) (GLenum target); + +class S9xOpenGLDisplayDriver : public S9xDisplayDriver +{ + public: + S9xOpenGLDisplayDriver (Snes9xWindow *window, Snes9xConfig *config); + void refresh (int width, int height); + int init (void); + void deinit (void); + void clear_buffers (void); + void update (int width, int height); + uint16 *get_next_buffer (void); + uint16 *get_current_buffer (void); + void push_buffer (uint16 *src); + void reconfigure (int width, int height); + static int query_availability (void); + + private: + void opengl_defaults (void); + void swap_control (int enable); + void gl_lock (void); + void gl_unlock (void); + void gl_swap (void); + int load_pixel_buffer_functions (void); + gl_proc get_aliased_extension (const char **name); + void update_texture_size (int width, int height); + + getProcAddressProc glGetProcAddress; + glGenBuffersProc glGenBuffers; + glBindBufferProc glBindBuffer; + glBufferDataProc glBufferData; + glBufferSubDataProc glBufferSubData; + glMapBufferProc glMapBuffer; + glUnmapBufferProc glUnmapBuffer; + glDeleteBuffersProc glDeleteBuffers; + + GLint texture_width; + GLint texture_height; + GLfloat vertices[8]; + GLfloat texcoords[8]; + GLuint texmap; + GLuint pbo; + GLenum tex_target; + + int dyn_resizing; + int filtering; + int using_pbos; + GLXContext glx_context; +}; + +#endif /* __GTK_DISPLAY_DRIVER_OPENGL_H */ diff --git a/gtk/src/gtk_display_driver_xv.cpp b/gtk/src/gtk_display_driver_xv.cpp new file mode 100644 index 00000000..9fdcff78 --- /dev/null +++ b/gtk/src/gtk_display_driver_xv.cpp @@ -0,0 +1,716 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "gtk_display.h" +#include "gtk_display_driver_xv.h" + +static int +get_inv_shift (uint32 mask, int bpp) +{ + int i; + + /* Find mask */ + for (i = 0; (i < bpp) && !(mask & (1 << i)); i++) {}; + + /* Find start of mask */ + for (; (i < bpp) && (mask & (1 << i)); i++) {}; + + return (bpp - i); +} + +S9xXVDisplayDriver::S9xXVDisplayDriver (Snes9xWindow *window, + Snes9xConfig *config) +{ + this->window = window; + this->config = config; + this->drawing_area = GTK_WIDGET (window->drawing_area); + display = + gdk_x11_drawable_get_xdisplay (GDK_DRAWABLE (drawing_area->window)); + last_known_width = last_known_height = -1; + + return; +} + +void +S9xXVDisplayDriver::update (int width, int height) +{ + int current_width, current_height, final_pitch; + uint8 *final_buffer; + int dst_x, dst_y, dst_width, dst_height; + + current_width = drawing_area->allocation.width; + current_height = drawing_area->allocation.height; + + if (width <= 0) + { + gdk_window_hide (gdk_window); + return; + } + + if (output_window_width != current_width || + output_window_height!= current_height) + { + gdk_window_move_resize (gdk_window, 0, 0, current_width, current_height); + gdk_window_show (gdk_window); + output_window_width = current_width; + output_window_height = current_height; + } + + if (config->scale_method > 0) + { + uint8 *src_buffer = (uint8 *) padded_buffer[0]; + uint8 *dst_buffer = (uint8 *) padded_buffer[1]; + int src_pitch = image_width * image_bpp; + int dst_pitch = scaled_max_width * image_bpp; + + S9xFilter (src_buffer, + src_pitch, + dst_buffer, + dst_pitch, + width, + height); + + final_buffer = (uint8 *) padded_buffer[1]; + final_pitch = dst_pitch; + } + else + { + final_buffer = (uint8 *) padded_buffer[0]; + final_pitch = image_width * image_bpp; + } + + if (!config->scale_to_fit && (width > current_width || height > current_height)) + { + clear (); + return; + } + + update_image_size (width, height); + + if (format == FOURCC_YUY2) + { + S9xConvertYUV (final_buffer, + (uint8 *) xv_image->data, + final_pitch, + 2 * xv_image->width, + width + (width < xv_image->width ? (width % 2) + 4 : 0), + height + (height < xv_image->height ? 4 : 0)); + } + else + { + S9xConvertMask (final_buffer, + (uint8 *) xv_image->data, + final_pitch, + bytes_per_pixel * xv_image->width, + width + (width < xv_image->width ? (width % 2) + 4 : 0), + height + (height < xv_image->height ? 4 : 0), + rshift, + gshift, + bshift, + bpp); + } + + if (config->scale_to_fit) + { + double screen_aspect = (double) current_width / (double) current_height; + double snes_aspect = S9xGetAspect (); + double granularity = 1.0 / (double) MAX (current_width, current_height); + + if (config->maintain_aspect_ratio && + !(screen_aspect <= snes_aspect * (1.0 + granularity) && + screen_aspect >= snes_aspect * (1.0 - granularity))) + { + if (screen_aspect > snes_aspect) + { + dst_x = (current_width - (int) (current_height * snes_aspect)) / 2; + dst_y = 0; + dst_width = (int) (current_height * snes_aspect); + dst_height = current_height; + } + else + { + dst_x = 0; + dst_y = (current_height - current_width / snes_aspect) / 2; + dst_width = current_width; + dst_height = (current_width / snes_aspect); + } + } + else + { + dst_x = 0; + dst_y = 0; + dst_width = current_width; + dst_height = current_height; + } + } + else + { + dst_x = (current_width - width) / 2; + dst_y = (current_height - height) / 2; + dst_width = width; + dst_height = height; + } + + + if (last_known_width != dst_width || last_known_height != dst_height) + { + last_known_width = dst_width; + last_known_height = dst_height; + clear (); + } + + XvShmPutImage (display, + xv_portid, + xwindow, + xgc, + xv_image, + 0, + 0, + width, + height, + dst_x, + dst_y, + dst_width, + dst_height, + False); + + top_level->set_mouseable_area (dst_x, dst_y, dst_width, dst_height); + + XSync (display, False); + + return; +} + +void +S9xXVDisplayDriver::update_image_size (int width, int height) +{ + if (desired_width != width || desired_height != height) + { + XShmDetach (display, &shm); + XSync (display, 0); + + shmctl (shm.shmid, IPC_RMID, 0); + shmdt (shm.shmaddr); + + xv_image = XvShmCreateImage (display, + xv_portid, + format, + 0, + width, + height, + &shm); + + shm.shmid = shmget (IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777); + for (int tries = 0; tries <= 10; tries++) + { + shm.shmaddr = (char *) shmat (shm.shmid, 0, 0); + + if (shm.shmaddr == (void *) -1 && tries >= 10) + { + /* Can't recover, send exit. */ + fprintf (stderr, "Couldn't reallocate shared memory.\n"); + S9xExit (); + } + else if (shm.shmaddr != (void *) -1) + { + break; + } + } + + shm.readOnly = FALSE; + + xv_image->data = shm.shmaddr; + + XShmAttach (display, &shm); + + desired_width = width; + desired_height = height; + } + + return; +} + +int +S9xXVDisplayDriver::init (void) +{ + int padding; + int depth = 0, num_formats, num_attrs, highest_formats = 0; + XvImageFormatValues *formats = NULL; + XvAdaptorInfo *adaptors; + XvAttribute *port_attr; + VisualID visualid = None; + unsigned int num_adaptors; + GdkScreen *screen; + GdkWindow *root; + + buffer[0] = malloc (image_padded_size); + buffer[1] = malloc (scaled_padded_size); + + padding = (image_padded_size - image_size) / 2; + padded_buffer[0] = (void *) (((uint8 *) buffer[0]) + padding); + + padding = (scaled_padded_size - scaled_size) / 2; + padded_buffer[1] = (void *) (((uint8 *) buffer[1]) + padding); + + memset (buffer[0], 0, image_padded_size); + memset (buffer[1], 0, scaled_padded_size); + + /* Setup XV */ + gtk_widget_realize (drawing_area); + + display = gdk_x11_drawable_get_xdisplay (GDK_DRAWABLE (drawing_area->window)); + screen = gtk_widget_get_screen (drawing_area); + root = gdk_screen_get_root_window (screen); + + xv_portid = -1; + XvQueryAdaptors (display, + GDK_WINDOW_XWINDOW (root), + &num_adaptors, + &adaptors); + + + for (int i = 0; i < (int) num_adaptors; i++) + { + if (adaptors[i].type & XvInputMask && + adaptors[i].type & XvImageMask) + { + formats = XvListImageFormats (display, + adaptors[i].base_id, + &num_formats); + + if (num_formats > highest_formats) + { + xv_portid = adaptors[i].base_id; + highest_formats = num_formats; + visualid = adaptors[i].formats->visual_id; + } + + free (formats); + } + } + + XvFreeAdaptorInfo (adaptors); + + if (xv_portid < 0) + { + fprintf (stderr, "Could not open Xv output port.\n"); + return -1; + } + + /* Set XV_AUTOPAINT_COLORKEY _only_ if available */ + port_attr = XvQueryPortAttributes (display, xv_portid, &num_attrs); + + for (int i = 0; i < num_attrs; i++) + { + if (!strcmp (port_attr[i].name, "XV_AUTOPAINT_COLORKEY")) + { + Atom colorkey = None; + + colorkey = XInternAtom (display, "XV_AUTOPAINT_COLORKEY", True); + if (colorkey != None) + XvSetPortAttribute (display, xv_portid, colorkey, 1); + } + } + + /* Try to find an RGB format */ + format = FOURCC_YUY2; + bpp = 100; + + formats = XvListImageFormats (display, + xv_portid, + &num_formats); + + for (int i = 0; i < num_formats; i++) + { + if (formats[i].id == 0x3 || formats[i].type == XvRGB) + { + if (formats[i].bits_per_pixel < bpp) + { + format = formats[i].id; + bpp = formats[i].bits_per_pixel; + bytes_per_pixel = (bpp == 15) ? 2 : bpp >> 3; + depth = formats[i].depth; + + this->rshift = get_inv_shift (formats[i].red_mask, bpp); + this->gshift = get_inv_shift (formats[i].green_mask, bpp); + this->bshift = get_inv_shift (formats[i].blue_mask, bpp); + + /* Check for red-blue inversion on SiliconMotion drivers */ + if (formats[i].red_mask == 0x001f && + formats[i].blue_mask == 0x7c00) + { + int copy = this->rshift; + this->rshift = this->bshift; + this->bshift = copy; + } + + /* on big-endian Xv still seems to like LSB order */ + if (config->force_inverted_byte_order) + S9xSetEndianess (ENDIAN_MSB); + else + S9xSetEndianess (ENDIAN_LSB); + } + } + } + + if (format == FOURCC_YUY2) + { + for (int i = 0; i < num_formats; i++) + { + if (formats[i].id == FOURCC_YUY2) + { + depth = formats[i].depth; + + if (formats[i].byte_order == LSBFirst) + { + if (config->force_inverted_byte_order) + S9xSetEndianess (ENDIAN_MSB); + else + S9xSetEndianess (ENDIAN_LSB); + } + else + { + if (config->force_inverted_byte_order) + S9xSetEndianess (ENDIAN_LSB); + else + S9xSetEndianess (ENDIAN_MSB); + } + + break; + } + } + } + + free (formats); + + /* Build a table for yuv conversion */ + if (format == FOURCC_YUY2) + { + for (unsigned int color = 0; color < 65536; color++) + { + int r, g, b; + int y, u, v; + + r = (color & 0x7c00) >> 7; + g = (color & 0x03e0) >> 2; + b = (color & 0x001F) << 3; + + y = (int) ((0.257 * ((double) r)) + (0.504 * ((double) g)) + (0.098 * ((double) b)) + 16.0); + u = (int) ((-0.148 * ((double) r)) + (-0.291 * ((double) g)) + (0.439 * ((double) b)) + 128.0); + v = (int) ((0.439 * ((double) r)) + (-0.368 * ((double) g)) + (-0.071 * ((double) b)) + 128.0); + + y_table[color] = CLAMP (y, 0, 255); + u_table[color] = CLAMP (u, 0, 255); + v_table[color] = CLAMP (v, 0, 255); + } + + S9xRegisterYUVTables (y_table, u_table, v_table); + } + + /* Create a sub-window */ + XVisualInfo vi_template, *vi; + int vi_num_items; + + vi_template.visualid = visualid; + vi_template.depth = depth; + vi_template.visual = NULL; + vi = XGetVisualInfo (display, VisualIDMask | VisualDepthMask, &vi_template, &vi_num_items); + + if (!vi) + { + vi_template.depth = 0; + vi = XGetVisualInfo (display, VisualIDMask, &vi_template, &vi_num_items); + + if (!vi) + { + fprintf (stderr, "Couldn't map visual.\n"); + return -1; + } + } + + XSetWindowAttributes window_attr; + xcolormap = XCreateColormap (display, + GDK_WINDOW_XWINDOW (drawing_area->window), + vi->visual, + AllocNone); + + window_attr.colormap = xcolormap; + window_attr.border_pixel = 0; + window_attr.event_mask = StructureNotifyMask | ExposureMask; + window_attr.background_pixmap = None; + + xwindow = XCreateWindow (display, + GDK_WINDOW_XWINDOW (drawing_area->window), + 0, + 0, + 256, + 224, + 0, + vi->depth, + InputOutput, + vi->visual, + CWColormap | CWBorderPixel | CWBackPixmap | CWEventMask, + &window_attr); + XSync (display, False); + + output_window_width = 256; + output_window_height = 224; + + XMapWindow (display, xwindow); + XSync (display, False); + + xgc = XCreateGC (display, xwindow, 0, NULL); + XFree (vi); + + gdk_display_sync (gtk_widget_get_display (drawing_area)); + gdk_window = gdk_window_foreign_new (xwindow); + XSync (display, False); + gdk_display_sync (gtk_widget_get_display (drawing_area)); + + if (gdk_window == NULL) + { + fprintf (stderr, "Failed to wrap native window.\n"); + return -1; + } + + gdk_window_set_user_data (gdk_window, drawing_area); + gdk_window_hide (gdk_window); + + /* Allocate a shared memory image. */ + xv_image = XvShmCreateImage (display, + xv_portid, + format, + 0, + scaled_max_width, + scaled_max_width, + &shm); + + shm.shmid = shmget (IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777); + shm.shmaddr = (char *) shmat (shm.shmid, 0, 0); + if (shm.shmaddr == (void *) -1) + { + fprintf (stderr, "Could not attach shared memory segment.\n"); + return -1; + } + + shm.readOnly = FALSE; + + xv_image->data = shm.shmaddr; + + XShmAttach (display, &shm); + + desired_width = scaled_max_width; + desired_height = scaled_max_width; + + clear_buffers (); + + /* Give Snes9x core a pointer to draw on */ + GFX.Screen = (uint16 *) padded_buffer[0]; + GFX.Pitch = image_width * image_bpp; + + return 0; +} + +void +S9xXVDisplayDriver::deinit (void) +{ + XShmDetach (display, &shm); + XSync (display, 0); + + XFreeColormap (display, xcolormap); + gdk_window_unref (gdk_window); + XDestroyWindow (display, xwindow); + XFreeGC (display, xgc); + + free (buffer[0]); + free (buffer[1]); + + shmctl (shm.shmid, IPC_RMID, 0); + shmdt (shm.shmaddr); + + padded_buffer[0] = NULL; + padded_buffer[1] = NULL; + + return; +} + +void +S9xXVDisplayDriver::clear (void) +{ + int x, y, w, h; + int width = drawing_area->allocation.width; + int height = drawing_area->allocation.height; + + if (window->last_width <= 0 || window->last_height <= 0) + { + XDrawRectangle (display, xwindow, xgc, 0, 0, width, height); + return; + } + + /* Get width of modified display */ + w = window->last_width; + h = window->last_height; + get_filter_scale (w, h); + + if (config->scale_to_fit) + { + double screen_aspect = (double) width / (double) height; + double snes_aspect = S9xGetAspect (); + double granularity = 1.0 / (double) MAX (width, height); + + if (config->maintain_aspect_ratio && + !(screen_aspect <= snes_aspect * (1.0 + granularity) && + screen_aspect >= snes_aspect * (1.0 - granularity))) + { + if (screen_aspect > snes_aspect) + { + x = (width - (int) (height * snes_aspect)) / 2; + y = 0; + w = (int) (height * snes_aspect); + h = height; + } + else + { + x = 0; + y = (height - width / snes_aspect) / 2; + w = width; + h = (width / snes_aspect); + } + } + else + { + return; + } + } + else + { + x = (width - w) / 2; + y = (height - h) / 2; + } + + if (x > 0) + { + XFillRectangle (display, xwindow, xgc, 0, y, x, h); + } + if (x + w < width) + { + XFillRectangle (display, xwindow, xgc, x + w, y, width - (x + w), h); + } + if (y > 0) + { + XFillRectangle (display, xwindow, xgc, 0, 0, width, y); + } + if (y + h < height) + { + XFillRectangle (display, xwindow, xgc, 0, y + h, width, height - (y + h)); + } + + XSync (display, False); + + return; +} + +void +S9xXVDisplayDriver::refresh (int width, int height) +{ + if (!config->rom_loaded) + { + gdk_window_hide (gdk_window); + return; + } + + clear (); + + return; +} + +uint16 * +S9xXVDisplayDriver::get_next_buffer (void) +{ + return (uint16 *) padded_buffer[0]; +} + +uint16 * +S9xXVDisplayDriver::get_current_buffer (void) +{ + return get_next_buffer (); +} + +void +S9xXVDisplayDriver::push_buffer (uint16 *src) +{ + memmove (GFX.Screen, src, image_size); + update (window->last_width, window->last_height); + + return; +} + +void +S9xXVDisplayDriver::clear_buffers (void) +{ + uint32 black; + uint8 *color; + + memset (buffer[0], 0, image_padded_size); + memset (buffer[1], 0, scaled_padded_size); + + /* Construct value byte-order independently */ + if (format == FOURCC_YUY2) + { + color = (uint8 *) &black; + *color++ = y_table[0]; + *color++ = u_table[0]; + *color++ = y_table[0]; + *color++ = v_table[0]; + + for (int i = 0; i < xv_image->data_size >> 2; i++) + { + *(((uint32 *) xv_image->data) + i) = black; + } + } + else + { + memset (xv_image->data, 0, xv_image->data_size); + } + + return; +} + +int +S9xXVDisplayDriver::query_availability (void) +{ + unsigned int p_version, + p_release, + p_request_base, + p_event_base, + p_error_base; + + /* Test if XV and SHM are feasible */ + if (!XShmQueryExtension (GDK_DISPLAY ())) + { + return 0; + } + + if (XvQueryExtension (GDK_DISPLAY (), + &p_version, + &p_release, + &p_request_base, + &p_event_base, + &p_error_base) != Success) + { + return 0; + } + + return 1; +} + +void +S9xXVDisplayDriver::reconfigure (int width, int height) +{ + return; +} diff --git a/gtk/src/gtk_display_driver_xv.h b/gtk/src/gtk_display_driver_xv.h new file mode 100644 index 00000000..68b13882 --- /dev/null +++ b/gtk/src/gtk_display_driver_xv.h @@ -0,0 +1,57 @@ +#ifndef __GTK_DISPLAY_DRIVER_XV_H +#define __GTK_DISPLAY_DRIVER_XV_H + +#include +#include + +#include "gtk_s9x.h" +#include "gtk_display_driver.h" + +#define FOURCC_YUY2 0x32595559 + +class S9xXVDisplayDriver : public S9xDisplayDriver +{ + public: + S9xXVDisplayDriver (Snes9xWindow *window, Snes9xConfig *config); + void refresh (int width, int height); + int init (void); + void deinit (void); + void clear_buffers (void); + void update (int width, int height); + uint16 *get_next_buffer (void); + uint16 *get_current_buffer (void); + void push_buffer (uint16 *src); + void reconfigure (int width, int height); + static int query_availability (void); + + private: + void clear (void); + void update_image_size (int width, int height); + + Display *display; + Window xwindow; + GC xgc; + Colormap xcolormap; + GdkWindow *gdk_window; + + XvImage *xv_image; + int xv_portid; + XShmSegmentInfo shm; + + int output_window_width; + int output_window_height; + int last_known_width; + int last_known_height; + int desired_width; + int desired_height; + int format; + int bpp; + int bytes_per_pixel; + int rshift, gshift, bshift; + + uint8 y_table[65536]; + uint8 u_table[65536]; + uint8 v_table[65536]; +}; + +#endif /* __GTK_DISPLAY_DRIVER_XV_H */ diff --git a/gtk/src/gtk_file.cpp b/gtk/src/gtk_file.cpp new file mode 100644 index 00000000..912bd978 --- /dev/null +++ b/gtk/src/gtk_file.cpp @@ -0,0 +1,540 @@ +#include +#include + +#include "gtk_s9x.h" + +static char buf[256]; + +const char * +S9xChooseMovieFilename (bool8 read_only) +{ + if (!gui_config->rom_loaded) + return strdup (""); + + return top_level->open_movie_dialog (read_only); +} + +const char * +S9xChooseFilename (bool8 read_only) +{ + + return strdup (""); +} + +/* _splitpath/_makepath: Modified from unix.cpp. See file for credits. */ +#ifndef SLASH_CHAR +#define SLASH_CHAR '/' +#endif + +void +_splitpath (const char *path, char *drive, char *dir, char *fname, char *ext) +{ + char *slash = strrchr ((char *) path, SLASH_CHAR); + char *dot = strrchr ((char *) path, '.'); + + *drive = '\0'; + + if (dot && slash && dot < slash) + { + dot = 0; + } + + if (!slash) + { + *dir = '\0'; + strcpy (fname, path); + + if (dot) + { + fname[dot - path] = '\0'; + strcpy (ext, dot + 1); + } + else + { + *ext = '\0'; + } + } + else + { + strcpy (dir, path); + dir[slash - path] = '\0'; + strcpy (fname, slash + 1); + + if (dot) + { + fname[(dot - slash) - 1] = '\0'; + strcpy (ext, dot + 1); + } + else + { + *ext = '\0'; + } + } + + return; +} + +void +_makepath (char *path, + const char *drive, + const char *dir, + const char *fname, + const char *ext) +{ + if (dir && *dir) + { + strcpy (path, dir); + strcat (path, "/"); + } + else + *path = '\0'; + + strcat (path, fname); + + if (ext && *ext) + { + strcat (path, "."); + strcat (path, ext); + } + + return; +} + +const char * +S9xGetFilenameInc (const char *e, enum s9x_getdirtype dirtype) +{ + static char filename[PATH_MAX + 1]; + char dir[_MAX_DIR + 1]; + char drive[_MAX_DRIVE + 1]; + char fname[_MAX_FNAME + 1]; + char ext[_MAX_EXT + 1]; + unsigned int i = 0; + struct stat buf; + const char *d; + + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + d = S9xGetDirectory (dirtype); + + do + { + snprintf (filename, sizeof (filename), + "%s" SLASH_STR "%s%03d%s", d, fname, i, e); + i++; + } + while (stat (filename, &buf) == 0 && i != 0); /* Overflow? ...riiight :-) */ + + return (filename); +} + +const char * +S9xGetDirectory (enum s9x_getdirtype dirtype) +{ + static char path[PATH_MAX + 1]; + char *config_dir = get_config_dir (); + + switch (dirtype) + { + default: + case DEFAULT_DIR: + strcpy (path, config_dir); + break; + + case HOME_DIR: + strcpy (path, getenv ("HOME")); + break; + + case ROM_DIR: + sprintf (path, "%s/roms", config_dir); + break; + + case SNAPSHOT_DIR: + sprintf (path, "%s/snapshots", config_dir); + break; + + case IPS_DIR: + case CHEAT_DIR: + case SRAM_DIR: + case ROMFILENAME_DIR: + case BIOS_DIR: + char *loc; + + strcpy (path, Memory.ROMFilename); + + loc = strrchr (path, SLASH_CHAR); + + if (loc == NULL) + { + if (getcwd (path, PATH_MAX + 1) == NULL) + { + strcpy (path, getenv ("HOME")); + } + } + else + { + path[loc - path] = '\0'; + } + + if (gui_config->data_location == DIR_ROM || + dirtype == ROMFILENAME_DIR) + { + /* printf ("Got %s\n", path); */ + + break; + } + + if (gui_config->data_location == DIR_CONFIG) + sprintf (path, "%s/sram", config_dir); + else if (gui_config->data_location == DIR_CUSTOM) + sprintf (path, "%s", gui_config->custom_sram_directory); + + break; + } + + /* Try and mkdir, whether it exists or not */ + mkdir (path, 0777); + + free (config_dir); + + /* printf ("path: %s\n", path); */ + + return path; +} + +const char * +S9xGetFilename (const char *ex, enum s9x_getdirtype dirtype) +{ + static char filename[PATH_MAX + 1]; + char dir[_MAX_DIR + 1]; + char drive[_MAX_DRIVE + 1]; + char fname[_MAX_FNAME + 1]; + char ext[_MAX_EXT + 1]; + + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + + snprintf (filename, sizeof (filename), "%s" SLASH_STR "%s%s", + S9xGetDirectory (dirtype), fname, ex); + + return (filename); +} + +const char * +S9xBasename (const char *f) +{ + const char *p; + + if ((p = strrchr (f, '/')) != NULL || (p = strrchr (f, '\\')) != NULL) + return (p + 1); + + return f; +} + +const char * +S9xBasenameNoExt (const char *f) +{ + static char filename[PATH_MAX + 1]; + const char *base, *ext; + + if (!(base = strrchr (f, SLASH_CHAR))) + base = f; + else + base += 1; + + ext = strrchr (f, '.'); + + if (!ext) + strncpy (filename, base, PATH_MAX); + else + { + int len = ext - base; + strncpy (filename, base, len); + filename[len] = '\0'; + } + + return filename; +} + +static int +file_exists (const char *name) +{ + FILE *f = NULL; + + f = fopen (name, "r"); + + if (!f) + return 0; + else + { + fclose (f); + return 1; + } +} + +bool8 +S9xOpenSnapshotFile (const char *fname, bool8 read_only, STREAM *file) +{ + char filename [PATH_MAX + 1]; + char drive [_MAX_DRIVE + 1]; + char dir [_MAX_DIR + 1]; + char ext [_MAX_EXT + 1]; + + _splitpath (fname, drive, dir, filename, ext); + + if (*drive || *dir == '/' || (*dir == '.' && (*(dir + 1) == '/'))) + { + strncpy (filename, fname, PATH_MAX); + + if (!file_exists (filename)) + { + if (!*ext) + strcat (filename, ".s9x"); + } + } + else + { + strcpy (filename, S9xGetDirectory (SNAPSHOT_DIR)); + strcat (filename, SLASH_STR); + strcat (filename, fname); + + if (!file_exists (filename)) + { + if (!*ext) + strcat (filename, ".s9x"); + } + } + +#ifdef ZLIB + if (read_only) + { + if ((*file = OPEN_STREAM (filename, "rb"))) + return (TRUE); + } + else + { + if ((*file = OPEN_STREAM (filename, "wb"))) + { + if (chown (filename, getuid (), getgid ()) < 0) + return (FALSE); + else + return (TRUE); + } + } +#else + char command [PATH_MAX]; + + if (read_only) + { + sprintf (command, "gzip -d <\"%s\"", filename); + if (*file = popen (command, "r")) + return (TRUE); + } + else + { + sprintf (command, "gzip --best >\"%s\"", filename); + if (*file = popen (command, "wb")) + return (TRUE); + } +#endif + return (FALSE); +} + +void S9xCloseSnapshotFile (STREAM file) +{ +#ifdef ZLIB + CLOSE_STREAM (file); +#else + pclose (file); +#endif +} + +extern "C" +{ + uint8 snes9x_clear_change_log = 0; +} + +extern "C" char *osd_GetPackDir (void) +{ + return NULL; +} + +void +S9xLoadSDD1Data (void) +{ + return; +} + +void +S9xAutoSaveSRAM (void) +{ + Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR)); + S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + return; +} + +void +S9xLoadState (const char *filename) +{ + if (S9xUnfreezeGame (filename)) + { + sprintf (buf, "%s loaded", filename); + S9xSetInfoString (buf); + } + else + { + fprintf (stderr, "Failed to load state file %s\n", filename); + } + + return; +} + +void +S9xSaveState (const char *filename) +{ + S9xFreezeGame (filename); + + sprintf (buf, "%s saved", filename); + S9xSetInfoString (buf); + + return; +} + +char * +S9xOpenROMDialog (void) +{ + GtkWidget *dialog; + GtkFileFilter *filter; + char *filename = NULL; + gint result; + const char *extensions[] = + { + "*.smc", "*.SMC", "*.fig", "*.FIG", "*.sfc", "*.SFC", + "*.jma", "*.JMA", "*.zip", "*.ZIP", "*.gd3", "*.GD3", + "*.swc", "*.SWC", + NULL + }; + + top_level->pause_from_focus_change (); + + dialog = gtk_file_chooser_dialog_new ("Open SNES ROM Image", + top_level->get_window (), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, "SNES ROM Images"); + for (int i = 0; extensions[i]; i++) + { + gtk_file_filter_add_pattern (filter, extensions[i]); + } + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, "All Files"); + gtk_file_filter_add_pattern (filter, "*.*"); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + if (strcmp (gui_config->last_directory, "")) + { + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), + gui_config->last_directory); + } + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_hide_all (dialog); + + if (result == GTK_RESPONSE_ACCEPT) + { + char *directory; + + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + directory = + gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); + strncpy (gui_config->last_directory, directory, PATH_MAX); + g_free (directory); + } + + else + { + filename = NULL; + } + + gtk_widget_destroy (dialog); + + top_level->unpause_from_focus_change (); + + return filename; +} + +/* QuickSave/Load from S9x base controls.cpp */ +void +S9xQuickSaveSlot (int slot) +{ + char def[PATH_MAX]; + char filename[PATH_MAX]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char ext[_MAX_EXT]; + + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + + sprintf (filename, "%s%s%s.%03d", + S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, + slot); + + sprintf (buf, "%s.%03d saved", def, slot); + + S9xSetInfoString (buf); + + S9xFreezeGame (filename); + + return; +} + +void +S9xQuickLoadSlot (int slot) +{ + char def[PATH_MAX]; + char filename[PATH_MAX]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char ext[_MAX_EXT]; + + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + + sprintf (filename, "%s%s%s.%03d", + S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def, + slot); + + if (S9xUnfreezeGame (filename)) + { + sprintf (buf, "%s.%03d loaded", def, slot); + S9xSetInfoString (buf); + } + else + { + static const char *digits = "t123456789"; + + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + + sprintf (filename, "%s%s%s.zs%c", + S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, + def, digits[slot]); + + if (S9xUnfreezeGame (filename)) + { + sprintf (buf, + "Loaded ZSNES freeze file %s.zs%c", + def, digits [slot]); + S9xSetInfoString (buf); + } + else + S9xMessage (S9X_ERROR, + S9X_FREEZE_FILE_NOT_FOUND, + "Freeze file not found"); + } + + return; +} + diff --git a/gtk/src/gtk_file.h b/gtk/src/gtk_file.h new file mode 100644 index 00000000..d8084c1e --- /dev/null +++ b/gtk/src/gtk_file.h @@ -0,0 +1,13 @@ +#ifndef __GTK_FILE_H +#define __GTK_FILE_H + +char *S9xOpenROMDialog (void); +const char *S9xBasenameNoExt (const char *); + +void S9xLoadState (const char *filename); +void S9xSaveState (const char *filename); + +void S9xQuickSaveSlot (int slot); +void S9xQuickLoadSlot (int slot); + +#endif /* __GTK_FILE_H */ diff --git a/gtk/src/gtk_glade_window.cpp b/gtk/src/gtk_glade_window.cpp new file mode 100644 index 00000000..41e45b37 --- /dev/null +++ b/gtk/src/gtk_glade_window.cpp @@ -0,0 +1,194 @@ +#include +#include "gtk_glade_window.h" + +GladeWindow::GladeWindow (const char *buffer, int size, const char *root) +{ + glade = glade_xml_new_from_buffer (buffer, size, root, NULL); + + window = get_widget (root); + + return; +} + +GtkWidget * +GladeWindow::get_widget (const char *name) +{ + return glade_xml_get_widget (glade, name); +} + +void +GladeWindow::signal_connect (const char *name, GCallback func) +{ + glade_xml_signal_connect_data (glade, name, func, (gpointer) this); + + return; +} + +void +GladeWindow::signal_connect (const char *name, GCallback func, gpointer data) +{ + glade_xml_signal_connect_data (glade, name, func, (gpointer) data); + + return; +} + +void +GladeWindow::signal_connect (GladeWindowCallbacks *callbacks) +{ + if (!callbacks) + return; + + for (int i = 0; callbacks[i].signal; i++) + { + signal_connect (callbacks[i].signal, callbacks[i].function); + } + + return; +} + +void +GladeWindow::enable_widget (const char *name, unsigned char state) +{ + gtk_widget_set_sensitive (get_widget (name), state); + + return; +} + +void +GladeWindow::resize (int width, int height) +{ + gtk_window_resize (GTK_WINDOW (window), width, height); + + return; +} + +void +GladeWindow::refresh (void) +{ + gtk_widget_queue_draw (GTK_WIDGET (window)); + + return; +} + +int +GladeWindow::get_width (void) +{ + return window->allocation.width; +} + +int +GladeWindow::get_height (void) +{ + return window->allocation.height; +} + +void +GladeWindow::set_button_label (const char *name, const char *label) +{ + gtk_button_set_label (GTK_BUTTON (get_widget (name)), label); + + return; +} + +unsigned char +GladeWindow::get_check (const char *name) +{ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (get_widget (name)))) + return 1; + return 0; +} + +unsigned int +GladeWindow::get_entry_value (const char *name) +{ + return atoi (gtk_entry_get_text (GTK_ENTRY (get_widget (name))));; +} + +const char * +GladeWindow::get_entry_text (const char *name) +{ + return gtk_entry_get_text (GTK_ENTRY (get_widget (name))); +} + +float +GladeWindow::get_slider (const char *name) +{ + return (float) gtk_range_get_value (GTK_RANGE (get_widget (name))); +} + +unsigned char +GladeWindow::get_combo (const char *name) +{ + return gtk_combo_box_get_active (GTK_COMBO_BOX (get_widget (name))); +} + +void +GladeWindow::set_slider (const char *name, float value) +{ + gtk_range_set_value (GTK_RANGE (get_widget (name)), (double) value); + + return; +} + +void +GladeWindow::set_check (const char *name, unsigned char value) +{ + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (get_widget (name)), + value); + return; +} + +void +GladeWindow::set_entry_value (const char *name, unsigned int value) +{ + char text[80]; + + snprintf (text, 80, "%u", value); + gtk_entry_set_text (GTK_ENTRY (get_widget (name)), text); + + return; +} + +void +GladeWindow::set_entry_text (const char *name, const char *text) +{ + gtk_entry_set_text (GTK_ENTRY (get_widget (name)), text); + + return; +} + +void +GladeWindow::set_combo (const char *name, unsigned char value) +{ + gtk_combo_box_set_active (GTK_COMBO_BOX (get_widget (name)), value); + + return; +} + +void +GladeWindow::set_spin (const char *name, unsigned int value) +{ + gtk_spin_button_set_value (GTK_SPIN_BUTTON (get_widget (name)), + (double) value); + + return; +} + +GtkWindow * +GladeWindow::get_window (void) +{ + return GTK_WINDOW (window); +} + +unsigned int +GladeWindow::get_spin (const char *name) +{ + return (unsigned int) + gtk_spin_button_get_value (GTK_SPIN_BUTTON (get_widget (name))); +} + +int +GladeWindow::has_focus (const char *widget) +{ + return gtk_widget_is_focus (get_widget (widget)); +} diff --git a/gtk/src/gtk_glade_window.h b/gtk/src/gtk_glade_window.h new file mode 100644 index 00000000..f8d84bce --- /dev/null +++ b/gtk/src/gtk_glade_window.h @@ -0,0 +1,48 @@ +#ifndef __GTK_GLADE_WINDOW_H +#define __GTK_GLADE_WINDOW_H + +#include +#include + +typedef struct +{ + const char *signal; + GCallback function; +} GladeWindowCallbacks; + +class GladeWindow +{ + public: + GladeWindow (const char *buffer, int size, const char *root); + GtkWidget *get_widget (const char *name); + void resize (int width, int height); + GtkWindow *get_window (void); + void refresh (void); + int get_width (void); + int get_height (void); + + protected: + void signal_connect (const char *name, GCallback func); + void signal_connect (const char *name, GCallback func, gpointer data); + void signal_connect (GladeWindowCallbacks *callbacks); + void enable_widget (const char *name, unsigned char state); + void set_button_label (const char *name, const char *label); + unsigned char get_check (const char *name); + unsigned int get_entry_value (const char *name); + const char *get_entry_text (const char *name); + unsigned char get_combo (const char *name); + unsigned int get_spin (const char *name); + float get_slider (const char *name); + void set_check (const char *name, unsigned char value); + void set_entry_value (const char *name, unsigned int value); + void set_entry_text (const char *name, const char *text); + void set_combo (const char *name, unsigned char value); + void set_spin (const char *name, unsigned int value); + void set_slider (const char *name, float value); + int has_focus (const char *widget); + + GtkWidget *window; + GladeXML *glade; +}; + +#endif /* __GTK_GLADE_WINDOW_H */ diff --git a/gtk/src/gtk_icon.h b/gtk/src/gtk_icon.h new file mode 100644 index 00000000..88d3aa8a --- /dev/null +++ b/gtk/src/gtk_icon.h @@ -0,0 +1,50 @@ +/* GdkPixbuf RGBA C-Source image dump 1-byte-run-length-encoded */ + +#ifdef __SUNPRO_C +#pragma align 4 (app_icon) +#endif +#ifdef __GNUC__ +static const guint8 app_icon[] __attribute__ ((__aligned__ (4))) = +#else +static const guint8 app_icon[] = +#endif +{ "" + /* Pixbuf magic (0x47646b50) */ + "GdkP" + /* length: header (24) + pixel_data (623) */ + "\0\0\2\207" + /* pixdata_type (0x2010002) */ + "\2\1\0\2" + /* rowstride (64) */ + "\0\0\0@" + /* width (16) */ + "\0\0\0\20" + /* height (16) */ + "\0\0\0\20" + /* pixel_data: */ + "\205\0\0\0\0\6\320\315\345\24\216\213\237\234a^s\367ZWo\367sn\217\226" + "\231\224\302\16\212\0\0\0\0\2\216\213\237\234\215\212\243\377\202\305" + "\302\332\377\2\212\206\241\377jf\207\210\212\0\0\0\0\2b_r\367\262\255" + "\316\377\202\247\240\315\377\2\262\255\316\377OKd\355\212\0\0\0\0\2[" + "Xp\367\230\221\276\377\202\241\232\312\377\2\230\221\276\377JG`\360\212" + "\0\0\0\0\2sn\220\233oj\213\377\202\230\221\276\377\2gc\202\377VRs\224" + "\205\0\0\0\0\22\320\315\345\24\216\213\237\234a^s\367ZWo\367sn\217\226" + "\232\224\304\"mh\210\235QLe\361JH`\357XRt\223\217\203\261%l]\210\234" + "@1`\3677#^\367A&y\226V*\246\16\216\213\237\234\215\212\243\377\202\305" + "\302\332\377\2\212\206\241\377jf\207\210\204\0\0\0\0\2l]\210\234jV\223" + "\377\202\240\214\311\377\4cM\217\3777\31t\210b_r\367\262\255\316\377" + "\202\247\240\315\377\2\262\255\316\377OKd\355\204\0\0\0\0\2@1`\367\201" + "f\270\377\202e@\257\377\4\201f\270\377*\20W\355[Xp\367\230\221\276\377" + "\202\241\232\312\377\2\230\221\276\377JG`\360\204\0\0\0\0\2""9&`\367" + "V1\240\377\202[4\252\377\4V1\240\377$\13S\360sn\220\233oj\213\377\202" + "\230\221\276\377\2gc\202\377VRs\224\204\0\0\0\0\2F)z\233\77$u\377\202" + "V1\240\377\22""7\32q\377(\14\\\224\234\226\304\25mh\210\235QLe\361JH" + "`\357XRt\223\217\203\261%l]\210\234@1`\3677#^\367A&y\226T-\245\":\34" + "v\235*\21W\361#\14U\357(\14\\\2233\21y\22\205\0\0\0\0\2l]\210\234jV\223" + "\377\202\240\214\311\377\2cM\217\3777\31t\210\212\0\0\0\0\2@1`\367\201" + "f\270\377\202e@\257\377\2\201f\270\377*\20W\355\212\0\0\0\0\2""9&`\367" + "V1\240\377\202[4\252\377\2V1\240\377$\13S\360\212\0\0\0\0\2F)z\233\77" + "$u\377\202V1\240\377\2""7\32q\377(\14\\\224\212\0\0\0\0\6W/\247\25:\34" + "v\235*\21W\361#\14U\357(\14\\\2233\21y\22\205\0\0\0\0"}; + + diff --git a/gtk/src/gtk_netplay.cpp b/gtk/src/gtk_netplay.cpp new file mode 100644 index 00000000..6b0fb085 --- /dev/null +++ b/gtk/src/gtk_netplay.cpp @@ -0,0 +1,349 @@ +#include + +#include "gtk_s9x.h" +#include "gtk_netplay_dialog.h" +#include "gtk_netplay.h" +#include "gtk_sound.h" + +uint16 MovieGetJoypad (int i); +void MovieSetJoypad (int i, uint16 buttons); + +static uint32 local_joypads[8], joypads[8]; +static GThread *npthread; + +extern SNPServer NPServer; + +static void +S9xNetplayPreconnect (void) +{ + S9xNetplayDisconnect (); + + if (gui_config->rom_loaded) + { + S9xAutoSaveSRAM (); + } + + NetPlay.MaxBehindFrameCount = gui_config->netplay_max_frame_loss; + NetPlay.Waiting4EmulationThread = FALSE; + + return; +} + +static void +S9xNetplayConnect (void) +{ + GtkWidget *msg; + + S9xNetplayPreconnect (); + + uint32 flags = CPU.Flags; + + if (*(gui_config->netplay_last_rom) && + top_level->try_open_rom (gui_config->netplay_last_rom)) + { + return; + } + + if (!S9xNPConnectToServer (gui_config->netplay_last_host, + gui_config->netplay_last_port, + Memory.ROMName)) + { + msg = gtk_message_dialog_new (NULL, + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Couldn't connect to server: %s:%d", + gui_config->netplay_last_host, + gui_config->netplay_last_port); + + gtk_dialog_run (GTK_DIALOG (msg)); + gtk_widget_destroy (msg); + } + + gui_config->netplay_activated = TRUE; + + /* If no rom is specified, assume we'll get it from the server */ + if (*(gui_config->netplay_last_rom) == 0) + { + Settings.StopEmulation = FALSE; + S9xROMLoaded (); + } + + S9xReset (); + + CPU.Flags = flags; + + top_level->configure_widgets (); + + return; +} + +void +S9xNetplaySyncClients (void) +{ + if (Settings.NetPlay && Settings.NetPlayServer) + S9xNPServerQueueSyncAll (); + + return; +} + +void +S9xNetplayStopServer (void) +{ + S9xNPStopServer (); + + g_thread_join (npthread); + Settings.NetPlayServer = FALSE; + gui_config->netplay_server_up = FALSE; + + return; +} + +void +S9xNetplayDisconnect (void) +{ + if (Settings.NetPlay) + { + if (NetPlay.Connected) + S9xNPDisconnect (); + } + + if (gui_config->netplay_server_up) + { + S9xNetplayStopServer (); + } + + gui_config->netplay_activated = FALSE; + NetPlay.Paused = FALSE; + + top_level->configure_widgets (); + + return; +} + +static gpointer +S9xNetplayServerThread (gpointer) +{ + S9xNPStartServer (gui_config->netplay_default_port); + + return NULL; +} + +void +S9xNetplayStartServer (void) +{ + uint32 flags; + + S9xNetplayPreconnect (); + + flags = CPU.Flags; + + if (*(gui_config->netplay_last_rom) == 0 || + top_level->try_open_rom (gui_config->netplay_last_rom)) + { + return; + } + + Settings.NetPlayServer = TRUE; + NPServer.SyncByReset = gui_config->netplay_sync_reset; + NPServer.SendROMImageOnConnect = gui_config->netplay_send_rom; + + npthread = g_thread_create (S9xNetplayServerThread, + NULL, + TRUE, + NULL); + + /* Sleep to let the server create itself */ + usleep (10000); + + S9xNPConnectToServer ("127.0.0.1", + gui_config->netplay_default_port, + Memory.ROMName); + + S9xReset (); + + S9xROMLoaded (); + + gui_config->netplay_activated = TRUE; + gui_config->netplay_server_up = TRUE; + + CPU.Flags = flags; + + top_level->configure_widgets (); + + return; +} + +void +S9xNetplayDialogOpen (void) +{ + Snes9xNetplayDialog *np_dialog; + + top_level->pause_from_focus_change (); + + np_dialog = new Snes9xNetplayDialog (gui_config); + + gtk_window_set_transient_for (np_dialog->get_window (), + top_level->get_window ()); + + if (np_dialog->show ()) + { + if (!gui_config->netplay_is_server) + { + S9xNetplayConnect (); + } + else + { + S9xNetplayStartServer (); + } + + S9xSoundStart (); + } + + delete np_dialog; + + top_level->unpause_from_focus_change (); + + return; +} + +int +S9xNetplaySyncSpeed (void) +{ + if (!Settings.NetPlay || !NetPlay.Connected) + return 0; + + // Send 1st joypad's position update to server + S9xNPSendJoypadUpdate (local_joypads[0]); + + // set input from network + for (int i = 0; i < NP_MAX_CLIENTS; i++) + joypads[i] = S9xNPGetJoypad (i); + + if (!S9xNPCheckForHeartBeat ()) + { + // No heartbeats already arrived, have to wait for one. + NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay (100); + + IPPU.RenderThisFrame = TRUE; + IPPU.SkippedFrames = 0; + } + else + { + int difference = (int) (NetPlay.MySequenceNum) - + (int) (NetPlay.ServerSequenceNum); + + if (difference < 0) + difference += 256; + + if (NetPlay.Waiting4EmulationThread) + { + if ((unsigned int) difference <= (NetPlay.MaxBehindFrameCount / 2)) + { + NetPlay.Waiting4EmulationThread = FALSE; + S9xNPSendPause (FALSE); + } + } + else + { + if ((unsigned int) difference >= (NetPlay.MaxBehindFrameCount)) + { + NetPlay.Waiting4EmulationThread = TRUE; + S9xNPSendPause (TRUE); + } + } + + NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay (200); + + if (IPPU.SkippedFrames < NetPlay.MaxFrameSkip) + { + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = FALSE; + } + else + { + IPPU.RenderThisFrame = TRUE; + IPPU.SkippedFrames = 0; + } + } + + if (!NetPlay.PendingWait4Sync) + { + NetPlay.FrameCount++; + S9xNPStepJoypadHistory (); + } + + return 1; +} + +int +S9xNetplayPush (void) +{ + static int statusbar_state = FALSE; + + if (gui_config->netplay_activated && + (!Settings.NetPlay || !NetPlay.Connected)) + S9xNetplayDisconnect (); + + if (!Settings.NetPlay) + return 0; + + if (NetPlay.PendingWait4Sync && !S9xNPWaitForHeartBeatDelay (100)) + { + S9xProcessEvents (FALSE); + + S9xSoundStop (); + NetPlay.Paused = TRUE; + + if (statusbar_state == FALSE) + { + top_level->update_statusbar (); + statusbar_state = TRUE; + } + + return 1; + } + + NetPlay.Paused = FALSE; + + if (statusbar_state) + { + top_level->update_statusbar (); + statusbar_state = FALSE; + } + + S9xSoundStart (); + + /* Save the joypad input */ + for (int i = 0; i < 8; i++) + { + local_joypads[i] = MovieGetJoypad (i); + + MovieSetJoypad (i, joypads[i]); + } + + if (NetPlay.PendingWait4Sync) + { + NetPlay.PendingWait4Sync = FALSE; + NetPlay.FrameCount++; + S9xNPStepJoypadHistory (); + } + + return 0; +} + +void +S9xNetplayPop (void) +{ + if (!Settings.NetPlay) + return; + + for (int i = 0; i < 8; i++) + MovieSetJoypad (i, local_joypads[i]); + + return; +} + + + + diff --git a/gtk/src/gtk_netplay.h b/gtk/src/gtk_netplay.h new file mode 100644 index 00000000..750352b9 --- /dev/null +++ b/gtk/src/gtk_netplay.h @@ -0,0 +1,11 @@ +#ifndef __GTK_NETPLAY_H +#define __GTK_NETPLAY_H + +void S9xNetplayDialogOpen (void); +int S9xNetplayPush (void); +void S9xNetplayPop (void); +int S9xNetplaySyncSpeed (void); +void S9xNetplaySyncClients (void); +void S9xNetplayDisconnect (void); + +#endif /* __GTK_NETPLAY_H */ diff --git a/gtk/src/gtk_netplay_dialog.cpp b/gtk/src/gtk_netplay_dialog.cpp new file mode 100644 index 00000000..e19945b1 --- /dev/null +++ b/gtk/src/gtk_netplay_dialog.cpp @@ -0,0 +1,145 @@ +#include "gtk_netplay_dialog.h" +#include "gtk_s9x.h" +#include "gtk_file.h" + +static void +event_browse_clicked (GtkButton *button, gpointer data) +{ + char *filename; + Snes9xNetplayDialog *np_dialog = (Snes9xNetplayDialog *) data; + + filename = S9xOpenROMDialog (); + + if (filename) + { + gtk_entry_set_text (GTK_ENTRY (np_dialog->get_widget ("rom_image")), + filename); + + g_free (filename); + } + + return; +} + +static void +event_clear_clicked (GtkButton *button, gpointer data) +{ + Snes9xNetplayDialog *np_dialog = (Snes9xNetplayDialog *) data; + + gtk_entry_set_text (GTK_ENTRY (np_dialog->get_widget ("rom_image")), ""); + + return; +} + +static void +event_server_toggled (GtkToggleButton *toggle, gpointer data) +{ + Snes9xNetplayDialog *np_dialog = (Snes9xNetplayDialog *) data; + + np_dialog->update_state (); +} + +Snes9xNetplayDialog::Snes9xNetplayDialog (Snes9xConfig *config) : + GladeWindow (snes9x_glade, snes9x_glade_size, "netplay_dialog") +{ + GladeWindowCallbacks callbacks[] = + { + { "server_toggled", G_CALLBACK (event_server_toggled) }, + { "browse_clicked", G_CALLBACK (event_browse_clicked) }, + { "clear_clicked", G_CALLBACK (event_clear_clicked) }, + { NULL, NULL } + }; + + signal_connect (callbacks); + + this->config = config; + + return; +} + +void +Snes9xNetplayDialog::update_state (void) +{ + if (get_check ("host_radio")) + { + enable_widget ("connect_box", FALSE); + enable_widget ("default_port_box", TRUE); + enable_widget ("sync_reset", TRUE); + enable_widget ("send_image", TRUE); + } + + else + { + enable_widget ("connect_box", TRUE); + enable_widget ("default_port_box", FALSE); + enable_widget ("sync_reset", FALSE); + enable_widget ("send_image", FALSE); + } + + return; +} + +void +Snes9xNetplayDialog::settings_to_dialog (void) +{ + set_entry_text ("rom_image", config->netplay_last_rom); + set_entry_text ("ip_entry", config->netplay_last_host); + set_check ("sync_reset", config->netplay_sync_reset); + set_check ("send_image", config->netplay_send_rom); + set_spin ("port", config->netplay_last_port); + set_spin ("default_port", config->netplay_default_port); + set_spin ("frames_behind", config->netplay_max_frame_loss); + set_check ("connect_radio", !config->netplay_is_server); + set_check ("host_radio", config->netplay_is_server); + + update_state (); + + return; +} + +void +Snes9xNetplayDialog::settings_from_dialog (void) +{ + strncpy (config->netplay_last_rom, get_entry_text ("rom_image"), PATH_MAX); + strncpy (config->netplay_last_host, get_entry_text ("ip_entry"), PATH_MAX); + config->netplay_sync_reset = get_check ("sync_reset"); + config->netplay_send_rom = get_check ("send_image"); + config->netplay_last_port = get_spin ("port"); + config->netplay_default_port = get_spin ("default_port"); + config->netplay_max_frame_loss = get_spin ("frames_behind"); + config->netplay_is_server = get_check ("host_radio"); + + config->save_config_file (); + + return; +} + +int +Snes9xNetplayDialog::show (void) +{ + int result; + + settings_to_dialog (); + + result = gtk_dialog_run (GTK_DIALOG (window)); + + gtk_widget_hide (window); + + if (result == GTK_RESPONSE_OK) + { + settings_from_dialog (); + + return TRUE; + } + + else + { + return FALSE; + } + +} + +Snes9xNetplayDialog::~Snes9xNetplayDialog (void) +{ + gtk_widget_destroy (window); +} diff --git a/gtk/src/gtk_netplay_dialog.h b/gtk/src/gtk_netplay_dialog.h new file mode 100644 index 00000000..e6499469 --- /dev/null +++ b/gtk/src/gtk_netplay_dialog.h @@ -0,0 +1,22 @@ +#ifndef __GTK_NETPLAY_DIALOG_H +#define __GTK_NETPLAY_DIALOG_H + +#include "gtk_glade_window.h" +#include "gtk_config.h" + +class Snes9xNetplayDialog : public GladeWindow +{ + public: + Snes9xNetplayDialog (Snes9xConfig *config); + ~Snes9xNetplayDialog (void); + int show (void); + void update_state (void); + + private: + Snes9xConfig *config; + void settings_to_dialog (void); + void settings_from_dialog (void); +}; + + +#endif /* __GTK_NETPLAY_DIALOG_H */ diff --git a/gtk/src/gtk_preferences.cpp b/gtk/src/gtk_preferences.cpp new file mode 100644 index 00000000..c0a84b85 --- /dev/null +++ b/gtk/src/gtk_preferences.cpp @@ -0,0 +1,1064 @@ +#include +#include +#include + +#include "gtk_preferences.h" +#include "gtk_config.h" +#include "gtk_s9xcore.h" +#include "gtk_control.h" +#include "gtk_sound.h" +#include "gtk_display.h" +#include "gtk_binding.h" + +gboolean +snes9x_preferences_open (GtkWidget *widget, + gpointer data) +{ + Snes9xPreferences *preferences; + Snes9xWindow *window = ((Snes9xWindow *) data); + Snes9xConfig *config = window->config; + + window->pause_from_focus_change (); + + preferences = new Snes9xPreferences (config); + gtk_window_set_transient_for (preferences->get_window (), + window->get_window ()); + +#ifdef USE_JOYSTICK + config->set_joystick_mode (JOY_MODE_GLOBAL); +#endif + + preferences->show (); + window->unpause_from_focus_change (); + +#ifdef USE_JOYSTICK + config->set_joystick_mode (JOY_MODE_INDIVIDUAL); +#endif + + config->reconfigure (); + window->update_accels (); + + delete preferences; + + return TRUE; +} + +static void +event_sram_folder_browse (GtkButton *widget, gpointer data) +{ + ((Snes9xPreferences *) data)->browse_folder_dialog (); + + return; +} + +#ifdef USE_JOYSTICK +static void +event_calibrate (GtkButton *widget, gpointer data) +{ + ((Snes9xPreferences *) data)->calibration_dialog (); + + return; +} +#endif + +static void +event_style_set (GtkWidget *widget, GtkStyle *previous_style, gpointer data) +{ + ((Snes9xPreferences *) data)->fix_style (); + + return; +} + +static void +event_control_toggle (GtkToggleButton *widget, gpointer data) +{ + Snes9xPreferences *window = (Snes9xPreferences *) data; + static unsigned char toggle_lock = 0; + const gchar *name; + bool state; + + if (toggle_lock) + { + return; + } + + window->last_toggled = widget; + name = gtk_widget_get_name (GTK_WIDGET (widget)); + state = gtk_toggle_button_get_active (widget); + + toggle_lock = 1; + + for (int i = 0; b_links[i].button_name; i++) + { + if (strcasecmp (name, b_links[i].button_name)) + { + gtk_toggle_button_set_active ( + GTK_TOGGLE_BUTTON (window->get_widget (b_links[i].button_name)), + FALSE); + } + } + + gtk_toggle_button_set_active (widget, state); + + toggle_lock = 0; + + return; +} + +static gboolean +event_key_press (GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + Binding key_binding; + int focus; + GtkNotebook *notebook; + GtkToggleButton *toggle; + Snes9xPreferences *window = (Snes9xPreferences *) user_data; + + if ((focus = window->get_focused_binding ()) < 0) + { + return FALSE; /* Don't keep key for ourselves */ + } + + /* Allow modifier keys to be used if page is set to the joypad bindings. */ + notebook = GTK_NOTEBOOK (window->get_widget ("preferences_notebook")); + toggle = GTK_TOGGLE_BUTTON (window->get_widget ("use_modifiers")); + + if (gtk_notebook_get_current_page (notebook) != 4 || + !gtk_toggle_button_get_active (toggle)) + { + /* Don't allow modifiers that we track to be bound */ + if (event->keyval == GDK_Control_L || + event->keyval == GDK_Control_R || + event->keyval == GDK_Shift_L || + event->keyval == GDK_Shift_R || + event->keyval == GDK_Alt_L || + event->keyval == GDK_Alt_R) + { + return FALSE; + } + } + + key_binding = Binding (event); + + /* Allows ESC key to clear the key binding */ + if (event->keyval == GDK_Escape) + { + if (event->state & GDK_SHIFT_MASK) + { + key_binding.clear (); + } + else + { + window->focus_next (); + return TRUE; + } + } + + window->store_binding (b_links[focus].button_name, key_binding); + + return TRUE; +} + +static void +event_ntsc_composite_preset (GtkButton *widget, gpointer data) +{ + Snes9xPreferences *window = (Snes9xPreferences *) data; + window->config->ntsc_setup = snes_ntsc_composite; + window->load_ntsc_settings (); + + return; +} + +static void +event_ntsc_svideo_preset (GtkButton *widget, gpointer data) +{ + Snes9xPreferences *window = (Snes9xPreferences *) data; + window->config->ntsc_setup = snes_ntsc_svideo; + window->load_ntsc_settings (); + + return; +} + +static void +event_ntsc_rgb_preset (GtkButton *widget, gpointer data) +{ + Snes9xPreferences *window = (Snes9xPreferences *) data; + window->config->ntsc_setup = snes_ntsc_rgb; + window->load_ntsc_settings (); + + return; +} + +static void +event_ntsc_monochrome_preset (GtkButton *widget, gpointer data) +{ + Snes9xPreferences *window = (Snes9xPreferences *) data; + window->config->ntsc_setup = snes_ntsc_monochrome; + window->load_ntsc_settings (); + + return; +} + + +static void +event_swap_with (GtkButton *widget, gpointer data) +{ + ((Snes9xPreferences *) data)->swap_with (); + + return; +} + +static void +event_reset_current_joypad (GtkButton *widget, gpointer data) +{ + ((Snes9xPreferences *) data)->reset_current_joypad (); + + return; +} + +static void +event_hw_accel_changed (GtkComboBox *widget, gpointer data) +{ + Snes9xPreferences *window = (Snes9xPreferences *) data; + GtkComboBox *combo = + GTK_COMBO_BOX (window->get_widget ("hw_accel")); + int value = gtk_combo_box_get_active (combo); + + value = window->hw_accel_value (value); + + switch (value) + { + case HWA_NONE: + gtk_widget_hide (window->get_widget ("opengl_frame")); + gtk_widget_hide (window->get_widget ("xv_frame")); + break; + case HWA_OPENGL: + gtk_widget_show (window->get_widget ("opengl_frame")); + gtk_widget_hide (window->get_widget ("xv_frame")); + break; + case HWA_XV: + gtk_widget_show (window->get_widget ("xv_frame")); + gtk_widget_hide (window->get_widget ("opengl_frame")); + break; + } + + return; +} + +static void +event_scale_method_changed (GtkComboBox *widget, gpointer user_data) +{ + Snes9xPreferences *window = (Snes9xPreferences *) user_data; + GtkComboBox *combo = + GTK_COMBO_BOX (window->get_widget ("scale_method_combo")); + + if (gtk_combo_box_get_active (combo) == FILTER_NTSC) + { + gtk_widget_show (window->get_widget ("ntsc_frame")); + } + else + { + gtk_widget_hide (window->get_widget ("ntsc_frame")); + } + + if (gtk_combo_box_get_active (combo) == FILTER_SCANLINES) + { + gtk_widget_show (window->get_widget ("scanline_filter_frame")); + } + else + { + gtk_widget_hide (window->get_widget ("scanline_filter_frame")); + } + + + return; +} + +static void +event_control_combo_changed (GtkComboBox *widget, gpointer user_data) +{ + Snes9xPreferences *window = (Snes9xPreferences *) user_data; + + window->bindings_to_dialog (gtk_combo_box_get_active (widget)); + + return; +} + +static void +event_switch_page (GtkNotebook *notebook, + GtkNotebookPage *page, + guint page_num, + gpointer data) +{ + return; +} + +#ifdef USE_JOYSTICK + +static gboolean +poll_joystick (gpointer data) +{ + Snes9xPreferences *window = (Snes9xPreferences *) data; + JoyEvent event; + Binding binding; + int i, focus; + + for (i = 0; window->config->joystick[i]; i++) + { + while (window->config->joystick[i]->get_event (&event)) + { + if (event.state == JOY_PRESSED) + { + if ((focus = window->get_focused_binding ()) >= 0) + { + binding = Binding (i, + event.parameter, + window->config->joystick_threshold); + + window->store_binding (b_links[focus].button_name, + binding); + + window->config->flush_joysticks (); + return TRUE; + } + + } + } + } + + return TRUE; +} + +void +Snes9xPreferences::calibration_dialog (void) +{ + GtkWidget *dialog; + + config->joystick_register_centers (); + dialog = gtk_message_dialog_new (NULL, + (GtkDialogFlags) 0, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + _("Current joystick centers have been saved.")); + + gtk_dialog_run (GTK_DIALOG (dialog)); + + gtk_widget_destroy (dialog); + + return; +} + +#endif + +Snes9xPreferences::Snes9xPreferences (Snes9xConfig *config) : + GladeWindow (snes9x_glade, snes9x_glade_size, "preferences_window") +{ + GladeWindowCallbacks callbacks[] = + { + { "control_toggle", G_CALLBACK (event_control_toggle) }, + { "on_key_press", G_CALLBACK (event_key_press) }, + { "control_combo_changed", G_CALLBACK (event_control_combo_changed) }, + { "change_current_page", G_CALLBACK (event_switch_page) }, + { "sram_folder_browse", G_CALLBACK (event_sram_folder_browse) }, + { "scale_method_changed", G_CALLBACK (event_scale_method_changed) }, + { "hw_accel_changed", G_CALLBACK (event_hw_accel_changed) }, + { "reset_current_joypad", G_CALLBACK (event_reset_current_joypad) }, + { "swap_with", G_CALLBACK (event_swap_with) }, + { "style_set", G_CALLBACK (event_style_set) }, + { "ntsc_composite_preset", G_CALLBACK (event_ntsc_composite_preset) }, + { "ntsc_svideo_preset", G_CALLBACK (event_ntsc_svideo_preset) }, + { "ntsc_rgb_preset", G_CALLBACK (event_ntsc_rgb_preset) }, + { "ntsc_monochrome_preset", G_CALLBACK (event_ntsc_monochrome_preset) }, +#ifdef USE_JOYSTICK + { "calibrate", G_CALLBACK (event_calibrate) }, +#endif + { NULL, NULL } + }; + + std::string version_string; + + ((version_string += _("GTK port version: ")) += SNES9X_GTK_VERSION) += "\n"; + (version_string += SNES9X_GTK_AUTHORS) += "\n"; + (version_string += _("English localization by Brandon Wright")) += "\n"; + +#if defined(USE_OPENGL) || defined(USE_XV) || defined(USE_XRANDR) \ + || defined(USE_JOYSTICK) || defined(NETPLAY_SUPPORT) + version_string += _("\nFeatures enabled:"); +#else + version_string += _(" Only barebones features enabled"); +#endif +#ifdef USE_OPENGL + version_string += _(" OpenGL"); +#endif +#ifdef USE_XV + version_string += _(" XVideo"); +#endif +#ifdef USE_XRANDR + version_string += _(" XRandR"); +#endif +#ifdef USE_JOYSTICK + version_string += _(" Joystick"); +#endif +#ifdef NETPLAY_SUPPORT + version_string += _(" NetPlay"); +#endif + (version_string += _("\n\nSnes9x version: ")) += VERSION; + + gtk_label_set_label (GTK_LABEL (get_widget ("version_string_label")), + version_string.c_str ()); + + last_toggled = NULL; + this->config = config; + + size_group[0] = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + gtk_size_group_add_widget (size_group[0], get_widget ("resolution_combo")); + gtk_size_group_add_widget (size_group[0], get_widget ("scale_method_combo")); + size_group[1] = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + gtk_size_group_add_widget (size_group[1], get_widget ("change_display_resolution")); + gtk_size_group_add_widget (size_group[1], get_widget ("scale_method_label")); + + gtk_image_set_from_pixbuf (GTK_IMAGE (get_widget ("preferences_splash")), + top_level->splash); + + fix_style (); + + gtk_widget_realize (window); + + signal_connect (callbacks); + + return; +} + +Snes9xPreferences::~Snes9xPreferences (void) +{ + g_object_unref (glade); + g_object_unref (size_group[0]); + g_object_unref (size_group[1]); + + return; +} + +void +Snes9xPreferences::load_ntsc_settings (void) +{ + set_slider ("ntsc_artifacts", config->ntsc_setup.artifacts); + set_slider ("ntsc_bleed", config->ntsc_setup.bleed); + set_slider ("ntsc_brightness", config->ntsc_setup.brightness); + set_slider ("ntsc_contrast", config->ntsc_setup.contrast); + set_slider ("ntsc_fringing", config->ntsc_setup.fringing); + set_slider ("ntsc_gamma", config->ntsc_setup.gamma); + set_slider ("ntsc_hue", config->ntsc_setup.hue); + set_check ("ntsc_merge_fields", config->ntsc_setup.merge_fields); + set_slider ("ntsc_resolution", config->ntsc_setup.resolution); + set_slider ("ntsc_saturation", config->ntsc_setup.saturation); + set_slider ("ntsc_sharpness", config->ntsc_setup.sharpness); + + return; +} + +void +Snes9xPreferences::store_ntsc_settings (void) +{ + config->ntsc_setup.artifacts = get_slider ("ntsc_artifacts"); + config->ntsc_setup.bleed = get_slider ("ntsc_bleed"); + config->ntsc_setup.brightness = get_slider ("ntsc_brightness"); + config->ntsc_setup.contrast = get_slider ("ntsc_contrast"); + config->ntsc_setup.fringing = get_slider ("ntsc_fringing"); + config->ntsc_setup.gamma = get_slider ("ntsc_gamma"); + config->ntsc_setup.hue = get_slider ("ntsc_hue"); + config->ntsc_setup.merge_fields = get_check ("ntsc_merge_fields"); + config->ntsc_setup.resolution = get_slider ("ntsc_resolution"); + config->ntsc_setup.saturation = get_slider ("ntsc_saturation"); + config->ntsc_setup.sharpness = get_slider ("ntsc_sharpness"); + + return; +} + +void +Snes9xPreferences::fix_style (void) +{ + GtkStyle *style = gtk_rc_get_style (get_widget ("preferences_notebook")); + + gtk_widget_set_style (get_widget ("display_viewport"), style); + gtk_widget_set_style (get_widget ("sound_viewport"), style); + gtk_widget_set_style (get_widget ("emulation_viewport"), style); + gtk_widget_set_style (get_widget ("shortcut_viewport1"), style); + gtk_widget_set_style (get_widget ("shortcut_viewport2"), style); + gtk_widget_set_style (get_widget ("shortcut_viewport3"), style); + gtk_widget_set_style (get_widget ("shortcut_viewport4"), style); + + return; +} + +void +Snes9xPreferences::move_settings_to_dialog (void) +{ + set_check ("full_screen_on_open", config->full_screen_on_open); + set_check ("show_frame_rate", Settings.DisplayFrameRate); + set_check ("change_display_resolution", config->change_display_resolution); + set_check ("scale_to_fit", config->scale_to_fit); + set_check ("overscan", config->overscan); + set_check ("multithreading", config->multithreading); + set_check ("force_hires", config->force_hires); + set_check ("maintain_aspect_ratio", config->maintain_aspect_ratio); + set_combo ("aspect_ratio", config->aspect_ratio); + set_check ("rom_folder_radio", config->data_location==DIR_ROM); + set_check ("config_folder_radio", config->data_location==DIR_CONFIG); + set_check ("custom_folder_radio", config->data_location==DIR_CUSTOM); + set_entry_text ("custom_folder_entry", config->custom_sram_directory); + set_combo ("resolution_combo", config->xrr_index); + set_combo ("scale_method_combo", config->scale_method); + set_entry_value ("save_sram_after_sec", Settings.AutoSaveDelay); + set_check ("block_invalid_vram_access", Settings.BlockInvalidVRAMAccessMaster); + set_check ("upanddown", Settings.UpAndDown); + set_combo ("default_esc_behavior", config->default_esc_behavior); + set_check ("prevent_screensaver", config->prevent_screensaver); + set_check ("force_inverted_byte_order", config->force_inverted_byte_order); + set_check ("hdma_check", !(Settings.DisableHDMA)); + set_check ("stereo_check", Settings.Stereo); + set_combo ("playback_combo", 7 - config->sound_playback_rate); + set_combo ("hw_accel", combo_value (config->hw_accel)); + set_check ("pause_emulation_on_switch", config->pause_emulation_on_switch); + set_spin ("num_threads", config->num_threads); + set_check ("mute_sound_check", config->mute_sound); + set_spin ("sound_buffer_size", config->sound_buffer_size); + set_slider ("sound_input_rate", config->sound_input_rate); + set_check ("sync_sound", Settings.SoundSync); + + int num_sound_drivers = 0; +#ifdef USE_PORTAUDIO + num_sound_drivers++; +#endif +#ifdef USE_OSS + num_sound_drivers++; +#endif +#ifdef USE_JOYSTICK + num_sound_drivers++; +#endif +#ifdef USE_ALSA + num_sound_drivers++; +#endif +#ifdef USE_PULSEAUDIO + num_sound_drivers++; +#endif + + if (config->sound_driver >= num_sound_drivers) + config->sound_driver = 0; + + set_combo ("sound_driver", config->sound_driver); + + if (config->scale_method == FILTER_NTSC) + { + gtk_widget_show (get_widget ("ntsc_frame")); + } + else + { + gtk_widget_hide (get_widget ("ntsc_frame")); + } + + if (config->scale_method == FILTER_SCANLINES) + { + gtk_widget_show (get_widget ("scanline_filter_frame")); + } + else + { + gtk_widget_hide (get_widget ("scanline_filter_frame")); + } + + load_ntsc_settings (); + set_combo ("ntsc_scanline_intensity", config->ntsc_scanline_intensity); + set_combo ("scanline_filter_intensity", config->scanline_filter_intensity); + + set_combo ("frameskip_combo", + Settings.SkipFrames == AUTO_FRAMERATE ? + 0 : Settings.SkipFrames + 1); +#ifdef USE_OPENGL + set_check ("bilinear_filter", config->bilinear_filter); + set_check ("sync_to_vblank", config->sync_to_vblank); + set_check ("use_pbos", config->use_pbos); + set_combo ("pixel_format", config->pbo_format); + set_check ("npot_textures", config->npot_textures); +#endif + +#ifdef USE_JOYSTICK + set_spin ("joystick_threshold", config->joystick_threshold); +#else + gtk_widget_set_sensitive (get_widget ("joystick_box"), FALSE); +#endif + + /* Control bindings */ + memcpy (pad, config->pad, (sizeof (JoypadBinding)) * NUM_JOYPADS); + memcpy (shortcut, config->shortcut, (sizeof (Binding)) * NUM_EMU_LINKS); + bindings_to_dialog (0); + + set_combo ("joypad_to_swap_with", 0); + + return; +} + +void +Snes9xPreferences::get_settings_from_dialog (void) +{ + int sound_needs_restart = 0; + int gfx_needs_restart = 0; + + if ((config->sound_driver != get_combo ("sound_driver")) || + (config->mute_sound != get_check ("mute_sound_check")) || + (config->sound_buffer_size != (int) get_spin ("sound_buffer_size"))|| + (Settings.Stereo != get_check ("stereo_check")) || + (config->sound_playback_rate != + (7 - (get_combo ("playback_combo")))) || + (config->sound_input_rate != get_slider ("sound_input_rate")) || + (Settings.SoundSync != get_check ("sync_sound")) + ) + { + sound_needs_restart = 1; + } + +#ifdef USE_XRANDR + if ((config->change_display_resolution != get_check ("change_display_resolution") || + (config->change_display_resolution && + (config->xrr_index != get_combo ("resolution_combo")))) && + config->fullscreen) + { + top_level->leave_fullscreen_mode (); + config->xrr_index = get_combo ("resolution_combo"); + config->xrr_width = config->xrr_sizes[config->xrr_index].width; + config->xrr_height = config->xrr_sizes[config->xrr_index].height; + config->change_display_resolution = get_check ("change_display_resolution"); + top_level->enter_fullscreen_mode (); + } + else + { + config->xrr_index = get_combo ("resolution_combo"); + config->xrr_width = config->xrr_sizes[config->xrr_index].width; + config->xrr_height = config->xrr_sizes[config->xrr_index].height; + } +#endif + + config->change_display_resolution = get_check ("change_display_resolution"); + + if (config->multithreading != get_check ("multithreading")) + gfx_needs_restart = 1; + + if (config->hw_accel != hw_accel_value (get_combo ("hw_accel"))) + gfx_needs_restart = 1; + + if (config->force_inverted_byte_order != get_check ("force_inverted_byte_order")) + gfx_needs_restart = 1; + +#ifdef USE_OPENGL +#endif + + config->full_screen_on_open = get_check ("full_screen_on_open"); + Settings.DisplayFrameRate = get_check ("show_frame_rate"); + config->scale_to_fit = get_check ("scale_to_fit"); + config->overscan = get_check ("overscan"); + config->maintain_aspect_ratio = get_check ("maintain_aspect_ratio"); + config->aspect_ratio = get_combo ("aspect_ratio"); + config->scale_method = get_combo ("scale_method_combo"); + config->force_hires = get_check ("force_hires"); + config->force_inverted_byte_order = get_check ("force_inverted_byte_order"); + Settings.AutoSaveDelay = get_entry_value ("save_sram_after_sec"); + config->multithreading = get_check ("multithreading"); + config->data_location = get_check ("rom_folder_radio") ? + DIR_ROM : config->data_location; + config->data_location = get_check ("config_folder_radio") ? + DIR_CONFIG : config->data_location; + config->data_location = get_check ("custom_folder_radio") ? + DIR_CUSTOM : config->data_location; + config->pause_emulation_on_switch = get_check ("pause_emulation_on_switch"); + Settings.SkipFrames = get_combo ("frameskip_combo"); + Settings.DisableHDMA = !(get_check ("hdma_check")); + Settings.BlockInvalidVRAMAccessMaster = get_check ("block_invalid_vram_access"); + Settings.UpAndDown = get_check ("upanddown"); + config->sound_driver = get_combo ("sound_driver"); + Settings.Stereo = get_check ("stereo_check"); + config->sound_playback_rate = 7 - (get_combo ("playback_combo")); + config->sound_buffer_size = get_spin ("sound_buffer_size"); + config->sound_input_rate = get_slider ("sound_input_rate"); + Settings.SoundSync = get_check ("sync_sound"); + config->mute_sound = get_check ("mute_sound_check"); + + store_ntsc_settings (); + config->ntsc_scanline_intensity = get_combo ("ntsc_scanline_intensity"); + config->scanline_filter_intensity = get_combo ("scanline_filter_intensity"); + config->hw_accel = hw_accel_value (get_combo ("hw_accel")); + config->num_threads = get_spin ("num_threads"); + config->default_esc_behavior = get_combo ("default_esc_behavior"); + config->prevent_screensaver = get_check ("prevent_screensaver"); + +#ifdef USE_JOYSTICK + config->joystick_threshold = get_spin ("joystick_threshold"); +#endif + +#ifdef USE_OPENGL + if (config->sync_to_vblank != get_check ("sync_to_vblank") || + config->npot_textures != get_check ("npot_textures") || + config->use_pbos != get_check ("use_pbos") || + config->pbo_format != get_combo ("pixel_format")) + { + gfx_needs_restart = 1; + } + + config->bilinear_filter = get_check ("bilinear_filter"); + config->sync_to_vblank = get_check ("sync_to_vblank"); + config->use_pbos = get_check ("use_pbos"); + config->npot_textures = get_check ("npot_textures"); + + config->pbo_format = get_combo ("pixel_format"); + +#endif + + strncpy (config->custom_sram_directory, + get_entry_text ("custom_folder_entry"), + PATH_MAX); + + if (Settings.SkipFrames == 0) + Settings.SkipFrames = AUTO_FRAMERATE; + else + Settings.SkipFrames--; + + memcpy (config->pad, pad, (sizeof (JoypadBinding)) * NUM_JOYPADS); + memcpy (config->shortcut, shortcut, (sizeof (Binding)) * NUM_EMU_LINKS); + + if (sound_needs_restart) + { + S9xPortSoundReinit (); + } + + if (gfx_needs_restart) + { + S9xReinitDisplay (); + } + else + { + S9xDisplayReconfigure (); + S9xDisplayRefresh (top_level->last_width, top_level->last_height); + + if (config->rom_loaded) + S9xDeinitUpdate (top_level->last_width, top_level->last_height); + } + + top_level->configure_widgets (); + + if (config->default_esc_behavior != ESC_TOGGLE_MENUBAR) + top_level->leave_fullscreen_mode (); + + return; +} + +int +Snes9xPreferences::hw_accel_value (int combo_value) +{ + if (config->allow_opengl && config->allow_xv) + return combo_value; + else if (!config->allow_opengl && !config->allow_xv) + return 0; + else if (!config->allow_opengl && config->allow_xv) + return combo_value ? 2 : 0; + else + return combo_value ? 1 : 0; +} + +int +Snes9xPreferences::combo_value (int hw_accel) +{ + if (config->allow_opengl && config->allow_xv) + return hw_accel; + else if (!config->allow_opengl && !config->allow_xv) + return 0; + else if (!config->allow_opengl && config->allow_xv) + return hw_accel == HWA_XV ? 1 : 0; + else + return hw_accel == HWA_OPENGL ? 1 : 0; +} + + +void +Snes9xPreferences::browse_folder_dialog (void) +{ + GtkWidget *dialog; + char *filename; + gint result; + + dialog = gtk_file_chooser_dialog_new (_("Select Folder"), + GTK_WINDOW (this->window), + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), + S9xGetDirectory (HOME_DIR)); + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_hide_all (dialog); + + if (result == GTK_RESPONSE_ACCEPT) + { + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + gtk_entry_set_text (GTK_ENTRY (get_widget ("custom_folder_entry")), + filename); + + g_free (filename); + } + + else + { + } + + gtk_widget_destroy (dialog); + + return; +} + +void +Snes9xPreferences::show (void) +{ + gint result; + GtkWidget *combo; + int close_dialog; +#ifdef USE_JOYSTICK + guint source_id = -1; +#endif + + if (config->allow_xrandr) + { +#ifdef USE_XRANDR + char size_string[256]; + + combo = get_widget ("resolution_combo"); + + config->xrr_index = 0; + + for (int i = 0; i < config->xrr_num_sizes; i++) + { + if (config->xrr_width == config->xrr_sizes[i].width && + config->xrr_height == config->xrr_sizes[i].height) + config->xrr_index = i; + + snprintf (size_string, + 256, + "%dx%d", + config->xrr_sizes[i].width, + config->xrr_sizes[i].height); + + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), size_string); + } +#endif + } + else + { + gtk_widget_hide (get_widget ("resolution_box")); + } + + combo = get_widget ("hw_accel"); + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), + _("None - Use software scaler")); + + if (config->allow_opengl) + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), + _("OpenGL - Use 3D graphics hardware")); + + if (config->allow_xv) + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), + _("XVideo - Use hardware video blitter")); + + combo = get_widget ("sound_driver"); + +#ifdef USE_PORTAUDIO + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), + _("PortAudio")); +#endif +#ifdef USE_OSS + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), + _("Open Sound System")); +#endif +#ifdef USE_JOYSTICK + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), + _("SDL")); +#endif +#ifdef USE_ALSA + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), + _("ALSA")); +#endif +#ifdef USE_PULSEAUDIO + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), + _("PulseAudio")); +#endif + + move_settings_to_dialog (); + +#ifdef USE_JOYSTICK + S9xGrabJoysticks (); + source_id = g_timeout_add (100, poll_joystick, (gpointer) this); +#endif + + if (config->preferences_width > 0 && config->preferences_height > 0) + resize (config->preferences_width, config->preferences_height); + + for (close_dialog = 0; !close_dialog; ) + { + gtk_widget_show (window); + result = gtk_dialog_run (GTK_DIALOG (window)); + + config->preferences_width = get_width (); + config->preferences_height = get_height (); + + switch (result) + { + case GTK_RESPONSE_OK: + get_settings_from_dialog (); + config->save_config_file (); + close_dialog = 1; + gtk_widget_hide (window); + break; + + case GTK_RESPONSE_APPLY: + get_settings_from_dialog (); + config->save_config_file (); + break; + + default: + gtk_widget_hide (window); + close_dialog = 1; + break; + } + } + +#ifdef USE_JOYSTICK + g_source_remove (source_id); + S9xReleaseJoysticks (); +#endif + + gtk_widget_destroy (window); + + return; +} + +void +Snes9xPreferences::focus_next (void) +{ + int next = get_focused_binding () + 1; + + for (int i = 0; b_breaks [i] != -1; i++) + { + if (b_breaks[i] == next) + next = -1; + } + + if (next > 0) + gtk_widget_grab_focus (get_widget (b_links [next].button_name)); + else + gtk_widget_grab_focus (get_widget ("cancel_button")); + + return; +} + +void +Snes9xPreferences::swap_with (void) +{ + JoypadBinding mediator; + int source_joypad = get_combo ("control_combo"); + int dest_joypad = get_combo ("joypad_to_swap_with"); + + memcpy (&mediator, &pad[source_joypad], sizeof (JoypadBinding)); + memcpy (&pad[source_joypad], &pad[dest_joypad], sizeof (JoypadBinding)); + memcpy (&pad[dest_joypad], &mediator, sizeof (JoypadBinding)); + + bindings_to_dialog (source_joypad); + + return; +} + +void +Snes9xPreferences::reset_current_joypad (void) +{ + int joypad = get_combo ("control_combo"); + + memset (&pad[joypad], 0, sizeof (JoypadBinding)); + + bindings_to_dialog (joypad); + + return; +} + +void +Snes9xPreferences::store_binding (const char *string, Binding binding) +{ + int current_joypad = get_combo ("control_combo"); + Binding *pad_bindings = (Binding *) (&pad[current_joypad]); + + for (int i = 0; i < NUM_JOYPAD_LINKS; i++) + { + if (!strcmp (b_links[i].button_name, string)) + { + pad_bindings[i] = binding; + } + else + { + if (pad_bindings[i].matches (binding)) + { + pad_bindings[i].clear (); + } + } + } + + for (int i = NUM_JOYPAD_LINKS; b_links[i].button_name; i++) + { + if (!strcmp (b_links[i].button_name, string)) + { + shortcut[i - NUM_JOYPAD_LINKS] = binding; + } + else + { + if (shortcut[i - NUM_JOYPAD_LINKS].matches (binding)) + { + shortcut[i - NUM_JOYPAD_LINKS].clear (); + } + } + } + + focus_next (); + + bindings_to_dialog (get_combo ("control_combo")); + + return; +} + +int +Snes9xPreferences::get_focused_binding (void) +{ + for (int i = 0; b_links[i].button_name; i++) + { + if (has_focus (b_links[i].button_name)) + return i; + } + + return -1; +} + +void +Snes9xPreferences::bindings_to_dialog (int joypad) +{ + char name[256]; + Binding *bindings = (Binding *) &pad[joypad]; + + set_combo ("control_combo", joypad); + + for (int i = 0; i < NUM_JOYPAD_LINKS; i++) + { + bindings[i].to_string (name); + set_entry_text (b_links[i].button_name, name); + } + + for (int i = NUM_JOYPAD_LINKS; b_links[i].button_name; i++) + { + shortcut[i - NUM_JOYPAD_LINKS].to_string (name); + set_entry_text (b_links[i].button_name, name); + } + + return; +} diff --git a/gtk/src/gtk_preferences.h b/gtk/src/gtk_preferences.h new file mode 100644 index 00000000..3dcb8af7 --- /dev/null +++ b/gtk/src/gtk_preferences.h @@ -0,0 +1,53 @@ +#ifndef __GTK_PREFERENCES_H +#define __GTK_PREFERENCES_H + +#include +#include +#include "gtk_s9x.h" +#include "gtk_glade_window.h" + +gboolean snes9x_preferences_open (GtkWidget *widget, + gpointer data); + +gboolean snes9x_preferences_close (GtkWidget *widget, + GdkEvent *event, + gpointer data); + +class Snes9xPreferences : public GladeWindow +{ + public: + Snes9xPreferences (Snes9xConfig *config); + ~Snes9xPreferences (void); + void show (void); + void bindings_to_dialog (int joypad); + int get_focused_binding (void); + void store_binding (const char *string, Binding binding); + void browse_folder_dialog (void); + int hw_accel_value (int combo_value); + int combo_value (int hw_accel); + void focus_next (void); + void swap_with (void); + void fix_style (void); + void reset_current_joypad (void); + void load_ntsc_settings (void); + void store_ntsc_settings (void); + +#ifdef USE_JOYSTICK + void calibration_dialog (void); +#endif + + Snes9xConfig *config; + GtkToggleButton *last_toggled; + int awaiting_key; + int polling_joystick; + JoypadBinding pad[NUM_JOYPADS]; + Binding shortcut[NUM_EMU_LINKS]; + + private: + void get_settings_from_dialog (void); + void move_settings_to_dialog (void); + + GtkSizeGroup *size_group[2]; +}; + +#endif /* __GTK_PREFERENCES_H */ diff --git a/gtk/src/gtk_s9x.cpp b/gtk/src/gtk_s9x.cpp new file mode 100644 index 00000000..a149dc0f --- /dev/null +++ b/gtk/src/gtk_s9x.cpp @@ -0,0 +1,736 @@ +#include +#include +#include +#include +#include + +#include "gtk_s9x.h" +#include "gtk_control.h" +#include "gtk_sound.h" +#include "gtk_display.h" + +#ifdef NETPLAY_SUPPORT +#include "gtk_netplay.h" +#endif + +#define IDLE_FUNC_PRIORITY (G_PRIORITY_DEFAULT_IDLE) + +void S9xPostRomInit (void); +void S9xSyncSpeedFinish (void); +static gboolean S9xIdleFunc (gpointer data); +static gboolean S9xScreenSaverCheckFunc (gpointer data); + +Snes9xWindow *top_level; +Snes9xConfig *gui_config; +static struct timeval next_frame_time = { 0, 0 }; +static struct timeval now; +static int needs_fullscreening = FALSE; +int syncing; +guint idle_func_id; + +void +S9xTerm (int signal) +{ + S9xExit (); + + return; +} + +int +main (int argc, char *argv[]) +{ + struct sigaction sig_callback; + + g_thread_init (NULL); + gdk_threads_init (); + + gtk_init (&argc, &argv); + glade_init (); + + bindtextdomain (GETTEXT_PACKAGE, SNES9XLOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + ZeroMemory (&Settings, sizeof (Settings)); + + /* Allow original config file for backend settings */ + S9xLoadConfigFiles (argv, argc); + + /* Perform our config here */ + gui_config = new Snes9xConfig (); + + S9xInitInputDevices (); + + gui_config->load_config_file (); + + char *rom_filename = S9xParseArgs (argv, argc); + + S9xReportControllers (); + + if (!Memory.Init () || !S9xInitAPU ()) + exit (3); + + g_set_application_name ("Snes9x"); + + top_level = new Snes9xWindow (gui_config); + top_level->show (); + + S9xInitDisplay (argc, argv); + + Memory.PostRomInitFunc = S9xPostRomInit; + + S9xPortSoundInit (); + + gui_config->reconfigure (); + top_level->update_accels (); + + Settings.Paused = TRUE; + syncing = 0; + idle_func_id = g_idle_add_full (IDLE_FUNC_PRIORITY, + S9xIdleFunc, + NULL, + NULL); + + g_timeout_add (10000, S9xScreenSaverCheckFunc, NULL); + + S9xNoROMLoaded (); + + if (rom_filename) + { + top_level->try_open_rom (rom_filename); + } + + memset (&sig_callback, 0, sizeof (struct sigaction)); + sig_callback.sa_handler = S9xTerm; + + sigaction (15 /* SIGTERM */, &sig_callback, NULL); + sigaction (3 /* SIGQUIT */, &sig_callback, NULL); + sigaction (2 /* SIGINT */, &sig_callback, NULL); + + if (gui_config->fullscreen) + { + gui_config->fullscreen = 0; + needs_fullscreening = 1; + } + +#ifdef USE_JOYSTICK + gui_config->flush_joysticks (); +#endif + + gdk_threads_lock (); + + gtk_main (); + + return 0; +} + +int +S9xOpenROM (const char *rom_filename) +{ + uint32 flags; + bool8 loaded; + + if (gui_config->rom_loaded) + { + S9xAutoSaveSRAM (); + } + +#ifdef NETPLAY_SUPPORT + S9xNetplayDisconnect (); +#endif + + flags = CPU.Flags; + + loaded = FALSE; + + if (Settings.Multi) + loaded = Memory.LoadMultiCart (Settings.CartAName, Settings.CartBName); + else if (rom_filename) + loaded = Memory.LoadROM (rom_filename); + + Settings.StopEmulation = !loaded; + + if (!loaded && rom_filename) + { + 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]; + + _splitpath (rom_filename, drive, dir, name, ext); + _makepath (fname, drive, dir, name, ext); + + strcpy (fname, S9xGetDirectory (ROM_DIR)); + strcat (fname, SLASH_STR); + strcat (fname, name); + + if (ext [0]) + { + strcat (fname, "."); + strcat (fname, ext); + } + + _splitpath (fname, drive, dir, name, ext); + _makepath (fname, drive, dir, name, ext); + + if ((Settings.StopEmulation = !Memory.LoadROM (fname))) + { + fprintf (stderr, _("Error opening: %s\n"), rom_filename); + + loaded = FALSE; + } + else + loaded = TRUE; + } + + if (loaded) + { + Memory.LoadSRAM (S9xGetFilename (".srm", SRAM_DIR)); + S9xLoadCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + } + else + { + S9xReset (); + + CPU.Flags = flags; + Settings.Paused = 1; + + S9xNoROMLoaded (); + top_level->refresh (); + + return 1; + } + + CPU.Flags = flags; + + S9xROMLoaded (); + + return 0; +} + +void +S9xROMLoaded (void) +{ + gui_config->rom_loaded = TRUE; + top_level->configure_widgets (); + + top_level->last_width = top_level->last_height = SIZE_FLAG_DIRTY; + + if (gui_config->full_screen_on_open) + { + Settings.Paused = FALSE; + top_level->enter_fullscreen_mode (); + } + + S9xSoundStart (); + + return; +} + +void +S9xNoROMLoaded (void) +{ + S9xSoundStop (); + gui_config->rom_loaded = FALSE; + S9xDisplayRefresh (-1, -1); + top_level->configure_widgets (); + top_level->update_statusbar (); + + return; +} + +/* +static inline void check_messages (void) +{ + static unsigned int current_timeout = 0; + + if (GFX.InfoStringTimeout > current_timeout) + { + top_level->show_status_message (GFX.InfoString); + } + + current_timeout = GFX.InfoStringTimeout; + + return; +} +*/ + +gboolean +S9xPauseFunc (gpointer data) +{ + S9xProcessEvents (TRUE); + + if (!gui_config->rom_loaded) + return TRUE; + +#ifdef NETPLAY_SUPPORT + if (!S9xNetplayPush ()) + { + S9xNetplayPop (); + } +#endif + + if (!Settings.Paused) /* Coming out of pause */ + { +#ifdef USE_JOYSTICK + /* Clear joystick queues */ + gui_config->flush_joysticks (); +#endif + + S9xSetSoundMute (FALSE); + S9xSoundStart (); + +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlay && NetPlay.Connected) + { + S9xNPSendPause (FALSE); + } +#endif + + /* Resume high-performance callback */ + idle_func_id = g_idle_add_full (IDLE_FUNC_PRIORITY, + S9xIdleFunc, + NULL, + NULL); + top_level->update_statusbar (); + return FALSE; + } + + return TRUE; +} + +gboolean +S9xIdleFunc (gpointer data) +{ + if (needs_fullscreening) + { + top_level->enter_fullscreen_mode(); + needs_fullscreening = FALSE; + } + + if (Settings.Paused) + { + S9xSetSoundMute (gui_config->mute_sound); + S9xSoundStop (); + +#ifdef USE_JOYSTICK + gui_config->flush_joysticks (); +#endif + +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlay && NetPlay.Connected) + { + S9xNPSendPause (TRUE); + } +#endif + + /* Move to a timer-based function to use less CPU */ + g_timeout_add (100, S9xPauseFunc, NULL); + top_level->update_statusbar (); + return FALSE; + } + + if (syncing) + S9xSyncSpeedFinish (); + + S9xProcessEvents (TRUE); + +#ifdef NETPLAY_SUPPORT + if (!S9xNetplayPush ()) + { +#endif + S9xMainLoop (); + S9xMixSound (); + +#ifdef NETPLAY_SUPPORT + S9xNetplayPop (); + } +#endif + + return TRUE; +} + +gboolean +S9xScreenSaverCheckFunc (gpointer data) +{ + + if (!Settings.Paused && + (gui_config->screensaver_needs_reset || + gui_config->prevent_screensaver)) + top_level->reset_screensaver (); + + return TRUE; +} + +/* Snes9x core hooks */ +void +S9xMessage (int type, int number, const char *message) +{ + /* + fprintf (stderr, "%s\n", message); + */ + return; +} + +/* Varies from ParseArgs because this one is for the OS port to handle */ +void +S9xParseArg (char **argv, int &i, int argc) +{ + if (!strcasecmp (argv[i], "-filter")) + { + if ((++i) < argc) + { + if (!strcasecmp (argv[i], "none")) + { + gui_config->scale_method = FILTER_NONE; + } + else if (!strcasecmp (argv[i], "supereagle")) + { + gui_config->scale_method = FILTER_SUPEREAGLE; + } + else if (!strcasecmp (argv[i], "2xsai")) + { + gui_config->scale_method = FILTER_2XSAI; + } + else if (!strcasecmp (argv[i], "super2xsai")) + { + gui_config->scale_method = FILTER_SUPER2XSAI; + } + else if (!strcasecmp (argv[i], "hq2x")) + { + gui_config->scale_method = FILTER_HQ2X; + } + else if (!strcasecmp (argv[i], "hq3x")) + { + gui_config->scale_method = FILTER_HQ3X; + } + else if (!strcasecmp (argv[i], "hq4x")) + { + gui_config->scale_method = FILTER_HQ4X; + } + else if (!strcasecmp (argv[i], "epx")) + { + gui_config->scale_method = FILTER_EPX; + } + else if (!strcasecmp (argv[i], "ntsc")) + { + gui_config->scale_method = FILTER_NTSC; + } + else + { + gui_config->scale_method = FILTER_NONE; + } + } + } + else if (!strcasecmp (argv[i], "-mutesound")) + { + gui_config->mute_sound = TRUE; + } + + return; +} + +#undef TIMER_DIFF +#define TIMER_DIFF(a, b) ((((a).tv_sec - (b).tv_sec) * 1000000) + (a).tv_usec - (b).tv_usec) +/* Finishes syncing by using more accurate system sleep functions*/ +void +S9xSyncSpeedFinish (void) +{ + if (!syncing) + return; + + gettimeofday (&now, NULL); + + if (Settings.SoundSync) + { + while (!S9xSyncSound ()) + { + usleep (100); + + gettimeofday (&next_frame_time, NULL); + + /* If we can't sync sound within a second, we're probably deadlocked */ + if (TIMER_DIFF (next_frame_time, now) > 1000000) + { + /* Flush out our sample buffer and give up. */ + S9xClearSamples (); + + break; + } + } + + next_frame_time = now; + return; + } + + if (TIMER_DIFF (next_frame_time, now) < -500000) + { + next_frame_time = now; + } + + while (timercmp (&next_frame_time, &now, >)) + { + int time_left = TIMER_DIFF (next_frame_time, now); + + if (time_left > 500000) + { + next_frame_time = now; + break; + } + + usleep (time_left); + + gettimeofday (&now, NULL); + } + + next_frame_time.tv_usec += Settings.FrameTime; + + if (next_frame_time.tv_usec >= 1000000) + { + next_frame_time.tv_sec += next_frame_time.tv_usec / 1000000; + next_frame_time.tv_usec %= 1000000; + } + + syncing = 0; + + return; +} + +/* SyncSpeed Handles delays between frames, similar to unix.cpp version, + * cleaned up for clarity, adjusted for GUI event loop */ +void +S9xSyncSpeed (void) +{ + unsigned int limit; + int lag; + +#ifdef NETPLAY_SUPPORT + if (S9xNetplaySyncSpeed ()) + return; +#endif + + if (Settings.HighSpeedSeek > 0) + { + Settings.HighSpeedSeek--; + IPPU.RenderThisFrame = FALSE; + IPPU.SkippedFrames = 0; + + gettimeofday (&now, NULL); + next_frame_time = now; + + syncing = 0; + + return; + } + + else if (Settings.TurboMode) + { + if ((++IPPU.FrameSkip >= Settings.TurboSkipFrames) + && !Settings.HighSpeedSeek) + { + IPPU.FrameSkip = 0; + IPPU.SkippedFrames = 0; + IPPU.RenderThisFrame = TRUE; + } + else + { + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = FALSE; + } + + return; + } + + gettimeofday (&now, NULL); + + if (next_frame_time.tv_sec == 0) + { + next_frame_time = now; + ++next_frame_time.tv_usec; + } + + if (Settings.SkipFrames == AUTO_FRAMERATE && !Settings.SoundSync) + { + lag = TIMER_DIFF (now, next_frame_time); + + /* We compensate for the frame time by a frame in case it's just a CPU + * discrepancy. We can recover lost time in the next frame anyway. */ + if (lag > (int) (Settings.FrameTime)) + { + if (lag > (int) Settings.FrameTime * 10) + { + /* Running way too slowly */ + next_frame_time = now; + IPPU.RenderThisFrame = 1; + IPPU.SkippedFrames = 0; + } + else + { + IPPU.RenderThisFrame = 0; + IPPU.SkippedFrames++; + } + } + + else + { + IPPU.RenderThisFrame = 1; + IPPU.SkippedFrames = 0; + } + } + else + { + limit = Settings.SoundSync ? 1 : Settings.SkipFrames + 1; + + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = 0; + + if (IPPU.SkippedFrames >= limit) + { + IPPU.RenderThisFrame = 1; + IPPU.SkippedFrames = 0; + } + } + + syncing = 1; + + return; +} + +/* Final exit point, issues exit (0) */ +void +S9xExit (void) +{ + gui_config->save_config_file (); + + top_level->leave_fullscreen_mode (); + + S9xPortSoundDeinit (); + + Settings.StopEmulation = TRUE; + + if (gui_config->rom_loaded) + { + S9xAutoSaveSRAM (); + } + + S9xDeinitAPU (); + + S9xDeinitInputDevices (); + S9xDeinitDisplay (); + + gtk_main_quit (); + + delete top_level; + delete gui_config; + + exit (0); + + return; +} + +void +S9xPostRomInit (void) +{ + //First plug in both, they'll change later as needed + S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0); + top_level->set_menu_item_selected ("joypad1"); + top_level->set_menu_item_selected ("joypad2"); + + if (!strncmp ((const char *) Memory.NSRTHeader + 24, "NSRT", 4)) + { + switch (Memory.NSRTHeader[29]) + { + case 0: //Everything goes + break; + + case 0x10: //Mouse in Port 0 + S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0); + top_level->set_menu_item_selected ("mouse1"); + break; + + case 0x01: //Mouse in Port 1 + S9xSetController (1, CTL_MOUSE, 1, 0, 0, 0); + top_level->set_menu_item_selected ("mouse2"); + break; + + case 0x03: //Super Scope in Port 1 + S9xSetController (1, CTL_SUPERSCOPE, 0, 0, 0, 0); + top_level->set_menu_item_selected ("superscope1"); + break; + + case 0x06: //Multitap in Port 1 + S9xSetController (1, CTL_MP5, 1, 2, 3, 4); + top_level->set_menu_item_selected ("multitap1"); + break; + + case 0x66: //Multitap in Ports 0 and 1 + S9xSetController (0, CTL_MP5, 0, 1, 2, 3); + S9xSetController (1, CTL_MP5, 4, 5, 6, 7); + top_level->set_menu_item_selected ("multitap1"); + top_level->set_menu_item_selected ("multitap2"); + break; + + case 0x08: //Multitap in Port 1, Mouse in new Port 1 + S9xSetController (1, CTL_MOUSE, 1, 0, 0, 0); + //There should be a toggle here for putting in Multitap instead + top_level->set_menu_item_selected ("mouse2"); + break; + + case 0x04: //Pad or Super Scope in Port 1 + S9xSetController (1, CTL_SUPERSCOPE, 0, 0, 0, 0); + top_level->set_menu_item_selected ("superscope2"); + //There should be a toggle here for putting in a pad instead + break; + + case 0x05: //Justifier - Must ask user... + S9xSetController (1, CTL_JUSTIFIER, 1, 0, 0, 0); + //There should be a toggle here for how many justifiers + break; + + case 0x20: //Pad or Mouse in Port 0 + S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0); + //There should be a toggle here for putting in a pad instead + break; + + case 0x22: //Pad or Mouse in Port 0 & 1 + S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0); + S9xSetController (1, CTL_MOUSE, 1, 0, 0, 0); + //There should be a toggles here for putting in pads instead + break; + + case 0x24: //Pad or Mouse in Port 0, Pad or Super Scope in Port 1 + //There should be a toggles here for what to put in, I'm leaving it at gamepad for now + break; + + case 0x27: //Pad or Mouse in Port 0, Pad or Mouse or Super Scope in Port 1 + //There should be a toggles here for what to put in, I'm leaving it at gamepad for now + break; + + //Not Supported yet + case 0x99: break; //Lasabirdie + case 0x0A: break; //Barcode Battler + } + } + + return; +} + +const char * +S9xStringInput(const char *message) +{ + return NULL; +} + +void +S9xExtraUsage (void) +{ + printf ("GTK port options:\n" + "-filter [option] Use a filter to scale the image.\n" + " [option] is one of: none supereagle 2xsai\n" + " super2xsai hq2x hq3x hq4x epx ntsc\n" + "\n" + "-mutesound Disables sound output.\n"); + return; +} diff --git a/gtk/src/gtk_s9x.h b/gtk/src/gtk_s9x.h new file mode 100644 index 00000000..01cbcfa9 --- /dev/null +++ b/gtk/src/gtk_s9x.h @@ -0,0 +1,46 @@ +#ifndef __GTK_S9X_H +#define __GTK_S9X_H + +#include + +#include "gtk_config.h" +#include "gtk_s9xcore.h" +#include "gtk_s9xwindow.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifdef ENABLE_NLS +#include +#define _(String) gettext(String) +#ifdef gettext_noop +#define N_(String) gettext_noop(String) +#else +#define N_(String) (String) +#endif +#else /* NLS is disabled */ +#define _(String) (String) +#define N_(String) (String) +#define textdomain(String) (String) +#define gettext(String) (String) +#define dgettext(Domain,String) (String) +#define dcgettext(Domain,String,Type) (String) +#define bindtextdomain(Domain,Directory) (Domain) +#define bind_textdomain_codeset(Domain,Codeset) (Codeset) +#endif /* ENABLE_NLS */ + +#define SNES9X_GTK_AUTHORS "(c) Copyright 2007 - 2010 Brandon Wright (bearoso@gmail.com)" +#define SNES9X_GTK_VERSION "79" + +extern Snes9xWindow *top_level; +extern Snes9xConfig *gui_config; + +extern const char snes9x_glade[]; +extern const int snes9x_glade_size; + +int S9xOpenROM (const char *filename); +void S9xNoROMLoaded (void); +void S9xROMLoaded (void); + +#endif /* __GTK_S9X_H */ diff --git a/gtk/src/gtk_s9xcore.h b/gtk/src/gtk_s9xcore.h new file mode 100644 index 00000000..b7cb4aa9 --- /dev/null +++ b/gtk/src/gtk_s9xcore.h @@ -0,0 +1,28 @@ +#ifndef __GTK_S9XCORE_H +#define __GTK_S9XCORE_H + +#include "snes9x.h" +#include "memmap.h" +#include "debug.h" +#include "cpuexec.h" +#include "ppu.h" +#include "snapshot.h" +#include "apu/apu.h" +#include "display.h" +#include "gfx.h" +#include "spc7110.h" +#include "controls.h" +#include "logger.h" +#include "cheats.h" +#include "movie.h" +#include "conffile.h" + +#include +#include +#include + +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif + +#endif /* __GTK_S9XCORE_H */ diff --git a/gtk/src/gtk_s9xwindow.cpp b/gtk/src/gtk_s9xwindow.cpp new file mode 100644 index 00000000..14726bc0 --- /dev/null +++ b/gtk/src/gtk_s9xwindow.cpp @@ -0,0 +1,1991 @@ +#include +#include +#include +#include + +#ifdef USE_XV +#include +#include +#include +#endif + +#include "gtk_s9x.h" +#include "gtk_preferences.h" +#include "gtk_icon.h" +#include "gtk_splash.h" +#include "gtk_display.h" +#include "gtk_file.h" +#include "gtk_sound.h" +#include "gtk_control.h" +#include "gtk_cheat.h" +#ifdef NETPLAY_SUPPORT +#include "gtk_netplay.h" +#endif + +static gboolean +event_main_window_delete (GtkWidget *widget, + GdkEvent *event, + gpointer data) +{ + S9xExit (); + + return TRUE; +} + +static gboolean +event_main_window_state_event (GtkWidget *widget, + GdkEventWindowState *event, + gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + window->fullscreen_state = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; + window->maximized_state = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED; + + return FALSE; +} + +static gboolean +event_continue_item_activate (GtkWidget *widget, gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + + window->unpause_from_user (); + + return TRUE; +} + +static gboolean +event_open_cheats (GtkWidget *widget, gpointer data) +{ + Snes9xCheats *cheats; + cheats = new Snes9xCheats (); + + cheats->show (); + delete cheats; + + return TRUE; +} + +static gboolean +event_open_multicart (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->open_multicart_dialog (); + + return TRUE; +} + +static gboolean +event_rom_info (GtkWidget *widget, gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + + window->show_rom_info (); + + return TRUE; +} + +static gboolean +event_toggle_interface (GtkWidget *widget, gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + + window->toggle_ui (); + + return TRUE; +} + +static gboolean +event_show_statusbar (GtkWidget *widget, gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + + window->config->statusbar_visible = !window->config->statusbar_visible; + window->configure_widgets (); + + return TRUE; +} + +static gboolean +event_sync_clients (GtkWidget *widget, gpointer data) +{ +#ifdef NETPLAY_SUPPORT + S9xNetplaySyncClients (); +#endif + + return TRUE; +} + +static gboolean +event_pause_item_activate (GtkWidget *widget, gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + + window->pause_from_user (); + + return TRUE; +} + +static gboolean +event_open_netplay (GtkWidget *widget, gpointer data) +{ +#ifdef NETPLAY_SUPPORT + S9xNetplayDialogOpen (); +#endif + return TRUE; +} + +static gboolean +event_drawingarea_expose (GtkWidget *widget, + GdkEventExpose *event, + gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + + if ((!window->config->rom_loaded || window->last_width < 0) + && window->last_width != SIZE_FLAG_DIRTY) + { + if (!(window->config->fullscreen) && !(window->maximized_state)) + { + window->config->window_width = window->get_width (); + window->config->window_height = window->get_height (); + } + + window->draw_background (event->area.x, + event->area.y, + event->area.width, + event->area.height); + } + else + { + if (window->last_width > 0 || !window->is_paused ()) + S9xDisplayRefresh (window->last_width, window->last_height); + + if (!(window->config->fullscreen)) + { + window->config->window_width = window->get_width (); + window->config->window_height = window->get_height (); + } + + if (window->is_paused () +#ifdef NETPLAY_SUPPORT + || NetPlay.Paused +#endif + ) + { + S9xDeinitUpdate (window->last_width, window->last_height); + } + } + + return FALSE; +} + +static gboolean +event_key (GtkWidget *widget, GdkEventKey *event, gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + static unsigned int keyval = 0; + static GdkEventType type = GDK_NOTHING; + Binding b; + s9xcommand_t cmd; + + /* Ignore multiple identical keypresses to discard repeating keys */ + if (event->keyval == keyval && event->type == type) + { + return TRUE; + } + + /* Provide escape key to get out of fullscreen */ + if (event->keyval == GDK_Escape && event->type == GDK_KEY_RELEASE) + { + if (window->config->default_esc_behavior == ESC_EXIT_FULLSCREEN) + window->leave_fullscreen_mode (); + else if (window->config->default_esc_behavior == ESC_EXIT_SNES9X) + S9xExit (); + else + window->toggle_ui (); + } + + keyval = event->keyval; + type = event->type; + + b = Binding (event); + + /* If no mapping for modifier version exists, try non-modifier */ + cmd = S9xGetMapping (b.hex ()); + if (cmd.type == S9xNoMapping) + b = Binding (event->keyval, false, false, false); + + S9xReportButton (b.hex (), (event->type == GDK_KEY_PRESS)); + + return FALSE; /* Pass the key to GTK */ +} + +gboolean +event_motion_notify (GtkWidget *widget, + GdkEventMotion *event, + gpointer user_data) +{ + Snes9xWindow *window = (Snes9xWindow *) user_data; + int c_width, c_height; + + if (!window->config->rom_loaded || + window->last_width <= 0 || + window->last_height <= 0) + { + return FALSE; + } + + c_width = GTK_WIDGET (window->drawing_area)->allocation.width; + c_height = GTK_WIDGET (window->drawing_area)->allocation.height; + + window->mouse_loc_x = (uint16) + ((int) (event->x) - window->mouse_region_x) * 256 / + (window->mouse_region_width <= 0 ? 1 : window->mouse_region_width); + + window->mouse_loc_y = (uint16) + ((int) (event->y) - window->mouse_region_y) * SNES_HEIGHT_EXTENDED / + (window->mouse_region_height <= 0 ? 1 : window->mouse_region_height); + + return FALSE; +} + +gboolean +event_button_press (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + switch (event->button) + { + case 1: + S9xReportButton (BINDING_MOUSE_BUTTON0, 1); + break; + case 2: + S9xReportButton (BINDING_MOUSE_BUTTON1, 1); + break; + case 3: + S9xReportButton (BINDING_MOUSE_BUTTON2, 1); + break; + } + + return FALSE; +} + +gboolean +event_button_release (GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + switch (event->button) + { + case 1: + S9xReportButton (BINDING_MOUSE_BUTTON0, 0); + break; + case 2: + S9xReportButton (BINDING_MOUSE_BUTTON1, 0); + break; + case 3: + S9xReportButton (BINDING_MOUSE_BUTTON2, 0); + break; + } + + return FALSE; +} + +static void +event_fullscreen (GtkWidget *widget, gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + + if (!window->config->fullscreen) + window->enter_fullscreen_mode (); + else + window->leave_fullscreen_mode (); + + return; +} + + +static void +event_exact_pixels_1x (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->resize_viewport (256, 224); + + return; +} + +static void +event_exact_pixels_2x (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->resize_viewport (256 * 2, 224 * 2); + + return; +} + +static void +event_exact_pixels_3x (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->resize_viewport (256 * 3, 224 * 3); + + return; +} + +static void +event_exact_pixels_4x (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->resize_viewport (256 * 4, 224 * 4); + + return; +} + +static void +event_exact_pixels_5x (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->resize_viewport (256 * 5, 224 * 5); + + return; +} + +static void +event_correct_aspect_1x (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->resize_viewport (224 * 4 / 3, 224); + + return; +} + +static void +event_correct_aspect_2x (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->resize_viewport (224 * 4 * 2 / 3, 224 * 2); + + return; +} + +static void +event_correct_aspect_3x (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->resize_viewport (224 * 4 * 3 / 3, 224 * 3); + + return; +} + +static void +event_correct_aspect_4x (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->resize_viewport (224 * 4 * 4 / 3, 224 * 4); + + return; +} + +static void +event_correct_aspect_5x (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->resize_viewport (224 * 4 * 5 / 3, 224 * 5); + + return; +} + +static void +event_record_movie (GtkWidget *widget, gpointer data) +{ + if (S9xMovieActive ()) + S9xMovieStop (FALSE); + + S9xMovieCreate (S9xChooseMovieFilename (FALSE), + 0xFF, + MOVIE_OPT_FROM_RESET, + NULL, + 0); + return; +} + +static void +event_open_movie (GtkWidget *widget, gpointer data) +{ + if (S9xMovieActive ()) + S9xMovieStop (FALSE); + + S9xMovieOpen (S9xChooseMovieFilename (TRUE), FALSE); + + return; +} + +static void +event_stop_recording (GtkWidget *widget, gpointer data) +{ + if (S9xMovieActive ()) + S9xMovieStop (FALSE); + + return; +} + +static void +event_jump_to_frame (GtkWidget *widget, gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + + window->movie_seek_dialog (); + + return; +} + +static void +event_reset (GtkWidget *widget, gpointer data) +{ + S9xSoftReset (); + + return; +} + +static void +event_hard_reset (GtkWidget *widget, gpointer data) +{ + S9xReset (); + + return; +} + +static void +event_save_state (GtkWidget *widget, gpointer data) +{ + int slot; + char *name = (char *) gtk_widget_get_name (widget); + + slot = atoi (&(name[11])); + + S9xQuickSaveSlot (slot); + + return; +} + +static void +event_save_state_file (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->save_state_dialog (); + + return; +} + +static void +event_load_state (GtkWidget *widget, gpointer data) +{ + int slot; + char *name = (char *) gtk_widget_get_name (widget); + + slot = atoi (&(name[11])); + + S9xQuickLoadSlot (slot); + + return; +} + +static void +event_load_state_file (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->load_state_dialog (); + + return; +} + +static void +event_open_rom (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->open_rom_dialog (); + + return; +} + +static void +event_recent_open (GtkRecentChooser *chooser, gpointer data) +{ + Snes9xWindow *window = (Snes9xWindow *) data; + gchar *uri = gtk_recent_chooser_get_current_uri (chooser); + gchar *filename = g_filename_from_uri (uri, NULL, NULL); + + window->try_open_rom (filename); + + g_free (filename); + g_free (uri); + + return; +} + +static void +event_save_spc (GtkWidget *widget, gpointer data) +{ + ((Snes9xWindow *) data)->save_spc_dialog (); + + return; +} + +static gboolean +event_focus_in (GtkWidget *widget, GdkEventFocus *event, gpointer data) +{ + ((Snes9xWindow *) data)->focus_notify (TRUE); + + return FALSE; +} + +static gboolean +event_focus_out (GtkWidget *widget, GdkEventFocus *event, gpointer data) +{ + ((Snes9xWindow *) data)->focus_notify (FALSE); + + return FALSE; +} + +static void +event_port (GtkWidget *widget, gpointer data) +{ + const gchar *name = gtk_widget_get_name (widget); + + if (!(gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))) + return; + + if (!strcasecmp (name, "joypad1")) + { + S9xSetController (0, CTL_JOYPAD, 0, 0, 0, 0); + } + + else if (!strcasecmp (name, "joypad2")) + { + S9xSetController (1, CTL_JOYPAD, 1, 0, 0, 0); + } + + else if (!strcasecmp (name, "mouse1")) + { + S9xSetController (0, CTL_MOUSE, 0, 0, 0, 0); + } + + else if (!strcasecmp (name, "mouse2")) + { + S9xSetController (1, CTL_MOUSE, 0, 0, 0, 0); + } + + else if (!strcasecmp (name, "superscope1")) + { + S9xSetController (0, CTL_SUPERSCOPE, 0, 0, 0, 0); + } + + else if (!strcasecmp (name, "superscope2")) + { + S9xSetController (1, CTL_SUPERSCOPE, 0, 0, 0, 0); + } + +/* else if (!strcasecmp (name, "multitap1")) + { + S9xSetController (0, CTL_MP5, 0, 1, 2, 3); + } */ + + else if (!strcasecmp (name, "multitap2")) + { + S9xSetController (1, CTL_MP5, 1, 2, 3, 4); + } + + return; +} + +Snes9xWindow::Snes9xWindow (Snes9xConfig *config) : + GladeWindow (snes9x_glade, snes9x_glade_size, "main_window") +{ + GladeWindowCallbacks callbacks[] = + { + { "main_window_delete_event", G_CALLBACK (event_main_window_delete) }, + { "main_window_state_event", G_CALLBACK (event_main_window_state_event) }, + { "on_continue_item_activate", G_CALLBACK (event_continue_item_activate) }, + { "on_pause_item_activate", G_CALLBACK (event_pause_item_activate) }, + { "on_drawingarea_expose", G_CALLBACK (event_drawingarea_expose) }, + { "main_window_key_press_event", G_CALLBACK (event_key) }, + { "main_window_key_release_event", G_CALLBACK (event_key) }, + { "on_fullscreen_item_activate", G_CALLBACK (event_fullscreen) }, + { "on_open_rom_activate", G_CALLBACK (event_open_rom) }, + { "on_reset_item_activate", G_CALLBACK (event_reset) }, + { "hard_reset", G_CALLBACK (event_hard_reset) }, + { "on_port_activate", G_CALLBACK (event_port) }, + { "load_save_state", G_CALLBACK (event_load_state) }, + { "load_state_file", G_CALLBACK (event_load_state_file) }, + { "save_save_state", G_CALLBACK (event_save_state) }, + { "save_state_file", G_CALLBACK (event_save_state_file) }, + { "drawingarea_button_press", G_CALLBACK (event_button_press) }, + { "drawingarea_button_release", G_CALLBACK (event_button_release) }, + { "drawingarea_motion_notify", G_CALLBACK (event_motion_notify) }, + { "save_spc", G_CALLBACK (event_save_spc) }, + { "open_movie", G_CALLBACK (event_open_movie) }, + { "stop_recording", G_CALLBACK (event_stop_recording) }, + { "jump_to_frame", G_CALLBACK (event_jump_to_frame) }, + { "record_movie", G_CALLBACK (event_record_movie) }, + { "open_cheats", G_CALLBACK (event_open_cheats) }, + { "on_preferences_item_activate", G_CALLBACK (snes9x_preferences_open) }, + { "focus_in_event", G_CALLBACK (event_focus_in) }, + { "focus_out_event", G_CALLBACK (event_focus_out) }, + { "open_netplay", G_CALLBACK (event_open_netplay) }, + { "rom_info", G_CALLBACK (event_rom_info) }, + { "sync_clients", G_CALLBACK (event_sync_clients) }, + { "toggle_interface", G_CALLBACK (event_toggle_interface) }, + { "show_statusbar", G_CALLBACK (event_show_statusbar) }, + { "exact_1x", G_CALLBACK (event_exact_pixels_1x) }, + { "exact_2x", G_CALLBACK (event_exact_pixels_2x) }, + { "exact_3x", G_CALLBACK (event_exact_pixels_3x) }, + { "exact_4x", G_CALLBACK (event_exact_pixels_4x) }, + { "exact_5x", G_CALLBACK (event_exact_pixels_5x) }, + { "correct_1x", G_CALLBACK (event_correct_aspect_1x) }, + { "correct_2x", G_CALLBACK (event_correct_aspect_2x) }, + { "correct_3x", G_CALLBACK (event_correct_aspect_3x) }, + { "correct_4x", G_CALLBACK (event_correct_aspect_4x) }, + { "correct_5x", G_CALLBACK (event_correct_aspect_5x) }, + { "open_multicart", G_CALLBACK (event_open_multicart) }, + + { NULL, NULL } + }; + + user_pause = 0; + sys_pause = 0; + last_width = -1; + last_height = -1; + this->config = config; + cursor = NULL; + recent_menu = NULL; + fullscreen_state = 0; + maximized_state = 0; + focused = 1; + paused_from_focus_loss = 0; + + splash = gdk_pixbuf_new_from_inline (-1, image_splash, FALSE, NULL); + + if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), "snes9x")) + { + gtk_window_set_default_icon_name ("snes9x"); + } + else + { + icon = gdk_pixbuf_new_from_inline (-1, app_icon, FALSE, NULL); + gtk_window_set_default_icon (icon); + } + + drawing_area = GTK_DRAWING_AREA (get_widget ("drawingarea")); + gtk_widget_set_double_buffered (GTK_WIDGET (drawing_area), FALSE); + + gtk_widget_realize (window); + gtk_widget_realize (GTK_WIDGET (drawing_area)); + gdk_window_set_back_pixmap (window->window, NULL, FALSE); + gdk_window_set_back_pixmap (GTK_WIDGET (drawing_area)->window, NULL, FALSE); + + gtk_check_menu_item_set_active ( + GTK_CHECK_MENU_ITEM (get_widget ("show_statusbar_item")), + config->statusbar_visible ? 1 : 0); + +#ifdef NETPLAY_SUPPORT +#else + gtk_widget_hide (get_widget ("open_netplay_item")); + gtk_widget_hide (get_widget ("netplay_separator")); + gtk_widget_hide (get_widget ("sync_clients_item")); + gtk_widget_hide (get_widget ("sync_clients_separator")); +#endif + + signal_connect (callbacks); + + if (config->window_width < 100 || config->window_height < 100) + { + config->window_width = 256; + config->window_height = 224; + } + + resize (config->window_width, config->window_height); + + return; +} + +void +Snes9xWindow::focus_notify (int state) +{ + focused = state ? 1 : 0; + + if (!state && config->pause_emulation_on_switch) + { + sys_pause++; + propagate_pause_state (); + paused_from_focus_loss = TRUE; + } + + if (state && paused_from_focus_loss) + { + unpause_from_focus_change (); + paused_from_focus_loss = FALSE; + } + + return; +} + +void +Snes9xWindow::open_multicart_dialog (void) +{ + int result; + GladeWindow *dialog = new GladeWindow (snes9x_glade, snes9x_glade_size, "multicart_dialog"); + GtkFileChooser *slota, *slotb; + GtkWidget *multicart_dialog = GTK_WIDGET (dialog->get_window ()); + + gtk_window_set_transient_for (dialog->get_window (), get_window ()); + + pause_from_focus_change (); + + slota = GTK_FILE_CHOOSER (dialog->get_widget ("multicart_slota")); + slotb = GTK_FILE_CHOOSER (dialog->get_widget ("multicart_slotb")); + + gtk_file_chooser_set_current_folder (slota, config->last_directory); + gtk_file_chooser_set_current_folder (slotb, config->last_directory); + + result = gtk_dialog_run (GTK_DIALOG (multicart_dialog)); + + gtk_widget_hide (multicart_dialog); + + if (result == GTK_RESPONSE_OK) + { + const gchar *filename; + + filename = gtk_file_chooser_get_filename (slota); + if (filename) + strncpy (Settings.CartAName, filename, PATH_MAX); + else + Settings.CartAName[0] = '\0'; + + filename = gtk_file_chooser_get_filename (slotb); + if (filename) + strncpy (Settings.CartBName, filename, PATH_MAX); + else + Settings.CartBName[0] = '\0'; + + Settings.Multi = TRUE; + + if (S9xOpenROM (NULL)) + { + GtkWidget *msg; + + msg = gtk_message_dialog_new (GTK_WINDOW (this->window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + _("Couldn't load files.")); + gtk_dialog_run (GTK_DIALOG (msg)); + gtk_widget_destroy (msg); + } + } + + gtk_widget_destroy (multicart_dialog); + + unpause_from_focus_change (); + + delete dialog; + + return; +} + +const char * +Snes9xWindow::open_movie_dialog (bool readonly) +{ + GtkWidget *dialog; + GtkFileFilter *filter; + char *filename; + gint result; + const char *extensions[] = + { + "*.smv", "*.SMV", + NULL + }; + + this->pause_from_focus_change (); + + if (readonly) + { + dialog = gtk_file_chooser_dialog_new (_("Open SNES Movie"), + GTK_WINDOW (this->window), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + } + else + { + char def[PATH_MAX]; + char default_name[PATH_MAX]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char ext[_MAX_EXT]; + + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + + sprintf (default_name, "%s.smv", def); + + dialog = gtk_file_chooser_dialog_new (_("New SNES Movie"), + GTK_WINDOW (this->window), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), + default_name); + + } + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("SNES Movies")); + for (int i = 0; extensions[i]; i++) + { + gtk_file_filter_add_pattern (filter, extensions[i]); + } + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("All Files")); + gtk_file_filter_add_pattern (filter, "*.*"); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), + S9xGetDirectory (SRAM_DIR)); + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_hide_all (dialog); + + if (result == GTK_RESPONSE_ACCEPT) + { + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + } + else + { + filename = strdup (""); + } + + gtk_widget_destroy (dialog); + + this->unpause_from_focus_change (); + + return filename; +} + +void +Snes9xWindow::open_rom_dialog () +{ + char *filename; + + pause_from_focus_change (); + + filename = S9xOpenROMDialog (); + + if (filename) + { + Settings.Multi = FALSE; + try_open_rom (filename); + + g_free (filename); + } + + unpause_from_focus_change (); + + return; +} + +int +Snes9xWindow::try_open_rom (const char *filename) +{ + pause_from_focus_change (); + + Settings.Multi = FALSE; + + if (S9xOpenROM (filename)) + { + GtkWidget *msg; + + msg = gtk_message_dialog_new (GTK_WINDOW (this->window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + _("Couldn't load file '%s'"), + filename); + gtk_dialog_run (GTK_DIALOG (msg)); + gtk_widget_destroy (msg); + + unpause_from_focus_change (); + + return 1; + } + else + { + GtkRecentData recent_data = + { + NULL, + (gchar *) "SNES ROM", + (gchar *) "application/x-snes-rom", + (gchar *) "Snes9x", + NULL, + NULL, + FALSE + }; + gchar *u_filename; + + u_filename = g_filename_to_uri (filename, NULL, NULL); + + recent_data.app_exec = g_strjoin (" ", + g_get_prgname (), + "%f", + NULL); + + gtk_recent_manager_add_full (gtk_recent_manager_get_default (), + u_filename, + &recent_data); + + g_free (recent_data.app_exec); + g_free (u_filename); + + this->unpause_from_user (); + + } + + this->unpause_from_focus_change (); + + return 0; +} + +void +Snes9xWindow::load_state_dialog () +{ + GtkWidget *dialog; + GtkFileFilter *filter; + char *filename; + gint result; + + this->pause_from_focus_change (); + + dialog = gtk_file_chooser_dialog_new (_("Load Saved State"), + GTK_WINDOW (this->window), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), + S9xGetDirectory (SNAPSHOT_DIR)); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("Save States")); + gtk_file_filter_add_pattern (filter, "*.sst"); + gtk_file_filter_add_pattern (filter, "*.zst"); + gtk_file_filter_add_pattern (filter, "*.ZST"); + gtk_file_filter_add_pattern (filter, "*.000"); + gtk_file_filter_add_pattern (filter, "*.001"); + gtk_file_filter_add_pattern (filter, "*.002"); + gtk_file_filter_add_pattern (filter, "*.003"); + gtk_file_filter_add_pattern (filter, "*.004"); + gtk_file_filter_add_pattern (filter, "*.005"); + gtk_file_filter_add_pattern (filter, "*.006"); + gtk_file_filter_add_pattern (filter, "*.007"); + gtk_file_filter_add_pattern (filter, "*.008"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("All Files")); + gtk_file_filter_add_pattern (filter, "*.*"); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_hide_all (dialog); + + if (result == GTK_RESPONSE_ACCEPT) + { + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + S9xLoadState (filename); + + g_free (filename); + } + + else + { + } + + gtk_widget_destroy (dialog); + + this->unpause_from_focus_change (); + + return; +} + +void +Snes9xWindow::movie_seek_dialog (void) +{ + GladeXML *seek_dialog_xml; + GtkWidget *seek_dialog; + char str[1024]; + gint result; + + if (!S9xMovieActive ()) + return; + + pause_from_focus_change (); + + seek_dialog_xml = glade_xml_new_from_buffer (snes9x_glade, + snes9x_glade_size, + "frame_advance_dialog", + NULL); + + seek_dialog = glade_xml_get_widget (seek_dialog_xml, + "frame_advance_dialog"); + + snprintf (str, 1024, + _("The current frame in the movie is %d."), + S9xMovieGetFrameCounter ()); + gtk_label_set_label (GTK_LABEL ( + glade_xml_get_widget (seek_dialog_xml, + "current_frame_label")), + str); + + snprintf (str, 1024, + "%d", + S9xMovieGetFrameCounter ()); + gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget (seek_dialog_xml, + "frame_entry")), + str); + + gtk_window_set_transient_for (GTK_WINDOW (seek_dialog), + get_window ()); + + result = gtk_dialog_run (GTK_DIALOG (seek_dialog)); + + int entry_value = + atoi ( + gtk_entry_get_text ( + GTK_ENTRY ( + glade_xml_get_widget ( + seek_dialog_xml, "frame_entry")))); + + switch (result) + { + case GTK_RESPONSE_OK: + + if (entry_value > 0 && + entry_value > (int) S9xMovieGetFrameCounter ()) + { + Settings.HighSpeedSeek = + entry_value - S9xMovieGetFrameCounter (); + } + + break; + } + + gtk_widget_destroy (seek_dialog); + + unpause_from_focus_change (); + + return; +} + +void +Snes9xWindow::save_state_dialog () +{ + GtkWidget *dialog; + GtkFileFilter *filter; + char *filename; + gint result; + char def[PATH_MAX]; + char default_name[PATH_MAX]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char ext[_MAX_EXT]; + + this->pause_from_focus_change (); + + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + + sprintf (default_name, "%s.sst", def); + + dialog = gtk_file_chooser_dialog_new (_("Save State"), + GTK_WINDOW (this->window), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), + S9xGetDirectory (SNAPSHOT_DIR)); + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), + default_name); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("Save States")); + gtk_file_filter_add_pattern (filter, "*.sst"); + gtk_file_filter_add_pattern (filter, "*.zst"); + gtk_file_filter_add_pattern (filter, "*.ZST"); + gtk_file_filter_add_pattern (filter, "*.000"); + gtk_file_filter_add_pattern (filter, "*.001"); + gtk_file_filter_add_pattern (filter, "*.002"); + gtk_file_filter_add_pattern (filter, "*.003"); + gtk_file_filter_add_pattern (filter, "*.004"); + gtk_file_filter_add_pattern (filter, "*.005"); + gtk_file_filter_add_pattern (filter, "*.006"); + gtk_file_filter_add_pattern (filter, "*.007"); + gtk_file_filter_add_pattern (filter, "*.008"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("All Files")); + gtk_file_filter_add_pattern (filter, "*.*"); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + + gtk_widget_hide_all (dialog); + + if (result == GTK_RESPONSE_ACCEPT) + { + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + S9xSaveState (filename); + + g_free (filename); + } + + else + { + } + + gtk_widget_destroy (dialog); + + this->unpause_from_focus_change (); + + return; +} + +void +Snes9xWindow::save_spc_dialog () +{ + GtkWidget *dialog; + GtkFileFilter *filter; + char *filename; + gint result; + char def[PATH_MAX]; + char default_name[PATH_MAX]; + char drive[_MAX_DRIVE]; + char dir[_MAX_DIR]; + char ext[_MAX_EXT]; + + this->pause_from_focus_change (); + + _splitpath (Memory.ROMFilename, drive, dir, def, ext); + + sprintf (default_name, "%s.spc", def); + + dialog = gtk_file_chooser_dialog_new (_("Save SPC file..."), + GTK_WINDOW (this->window), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), + S9xGetDirectory (SNAPSHOT_DIR)); + gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), + default_name); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("SPC Files")); + gtk_file_filter_add_pattern (filter, "*.spc"); + gtk_file_filter_add_pattern (filter, "*.SPC"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("All Files")); + gtk_file_filter_add_pattern (filter, "*.*"); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + result = gtk_dialog_run (GTK_DIALOG (dialog)); + + gtk_widget_hide_all (dialog); + + if (result == GTK_RESPONSE_ACCEPT) + { + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + + if (S9xSPCDump (filename)) + { + /* Success ? */ + } + else + { + GtkWidget *msg; + + msg = gtk_message_dialog_new (GTK_WINDOW (this->window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + _("Couldn't save SPC file '%s'"), + filename); + gtk_dialog_run (GTK_DIALOG (msg)); + gtk_widget_destroy (msg); + } + + g_free (filename); + } + + else + { + } + + gtk_widget_destroy (dialog); + + this->unpause_from_focus_change (); + + return; +} + +void +Snes9xWindow::set_menu_item_selected (const char *name) +{ + GtkCheckMenuItem *item; + + item = GTK_CHECK_MENU_ITEM (get_widget (name)); + + gtk_check_menu_item_set_active (item, 1); + + return; +} + +static gboolean +statusbar_timeout (gpointer data) +{ + gtk_statusbar_pop (GTK_STATUSBAR (data), + gtk_statusbar_get_context_id (GTK_STATUSBAR (data), + "info")); + + return FALSE; +} + +void +Snes9xWindow::show_status_message (const char *message) +{ + GtkStatusbar *statusbar = GTK_STATUSBAR (get_widget ("statusbar")); + + gtk_statusbar_pop (statusbar, gtk_statusbar_get_context_id (statusbar, "info")); + gtk_statusbar_push (statusbar, gtk_statusbar_get_context_id (statusbar, "info"), message); + + g_timeout_add_seconds (2, statusbar_timeout, statusbar); + + return; +} + +void +Snes9xWindow::update_statusbar (void) +{ + GtkStatusbar *bar = GTK_STATUSBAR (get_widget ("statusbar")); + char status_string[256]; + char title_string[1024]; + + if (!config->rom_loaded) + { + snprintf (title_string, 1024, "Snes9x"); + status_string[0] = '\0'; + } + else + { +#ifdef NETPLAY_SUPPORT + if (config->netplay_activated) + { + if (config->netplay_server_up) + { + snprintf (status_string, + 256, + _("%sHosting NetPlay - %s"), + is_paused () || NetPlay.Paused ? _("Paused - ") : "", + S9xBasenameNoExt (Memory.ROMFilename)); + } + else + { + snprintf (status_string, + 256, + _("%s%s on NetPlay %s:%d - Player %d"), + is_paused () || NetPlay.Paused ? _("Paused - ") : "", + S9xBasenameNoExt (Memory.ROMFilename), + NetPlay.ServerHostName, + NetPlay.Port, + NetPlay.Player); + } + + } + else +#endif + { + snprintf (status_string, + 256, + "%s%s", + is_paused () ? _("Paused - ") : "", + S9xBasenameNoExt (Memory.ROMFilename)); + } + + snprintf (title_string, 1024, "%s - Snes9x", S9xBasenameNoExt (Memory.ROMFilename)); + } + + gtk_window_set_title (GTK_WINDOW (window), title_string); + gtk_statusbar_pop (bar, gtk_statusbar_get_context_id (bar, "none")); + gtk_statusbar_push (bar, gtk_statusbar_get_context_id (bar, "none"), status_string); + + return; +} + +void +Snes9xWindow::show_rom_info (void) +{ + GtkWidget *msg; + + pause_from_focus_change (); + + msg = gtk_message_dialog_new_with_markup (GTK_WINDOW (window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, + _("Information for %s\n\n" + "Name: %s\n" + "Speed: %02X/%s\n" + "Map: %s\n" + "Type: %02x\n" + "Contents: %s\n" + "ROM Size: %s\n" + "Calculated Size: %d\n" + "SRAM Size: %s\n" + "Header Checksum: %04X\n" + "Checksum Compliment: %04X\n" + "Actual Checksum: %04X\n" + "Video: %s\n" + "CRC32: %08X\n" + "Revision: %s" + "%s"), + Memory.ROMFilename, + Memory.ROMName, + Memory.ROMSpeed, + ((Memory.ROMSpeed & 0x10) != 0) ? + "FastROM" : "SlowROM", + (Memory.HiROM) ? + "HiROM" : "LoROM", + Memory.ROMType, + Memory.KartContents (), + Memory.Size (), + Memory.CalculatedSize / 0x20000, + Memory.StaticRAMSize (), + Memory.ROMChecksum, + Memory.ROMComplementChecksum, + Memory.CalculatedChecksum, + (Memory.ROMRegion > 12 || + Memory.ROMRegion < 2) ? + "NTSC 60Hz" : "PAL 50Hz", + Memory.ROMCRC32, + Memory.Revision (), + (Memory.ROMChecksum != + Memory.CalculatedChecksum) ? + _("\n\nThis ROM has been modified or damaged") + : ""); + + gtk_dialog_run (GTK_DIALOG (msg)); + + unpause_from_focus_change (); + + gtk_widget_destroy (msg); + + return; +} + +void +Snes9xWindow::configure_widgets (void) +{ + enable_widget ("continue_item", config->rom_loaded); + enable_widget ("pause_item", config->rom_loaded); + enable_widget ("reset_item", config->rom_loaded); + enable_widget ("controller_ports_item", config->rom_loaded); + enable_widget ("load_state_item", config->rom_loaded); + enable_widget ("save_state_item", config->rom_loaded); + enable_widget ("save_spc_item", config->rom_loaded); + enable_widget ("hard_reset_item", config->rom_loaded); + enable_widget ("record_movie_item", config->rom_loaded); + enable_widget ("stop_recording_item", config->rom_loaded); + enable_widget ("open_movie_item", config->rom_loaded); + enable_widget ("jump_to_frame_item", config->rom_loaded); + enable_widget ("cheats_item", config->rom_loaded); + enable_widget ("rom_info_item", config->rom_loaded); + +#ifdef NETPLAY_SUPPORT + enable_widget ("sync_clients_item", + config->rom_loaded && + Settings.NetPlay && + Settings.NetPlayServer); +#endif + + if (config->default_esc_behavior != ESC_TOGGLE_MENUBAR) + { + enable_widget ("fullscreen_item", config->rom_loaded); + + config->ui_visible = TRUE; + + if (!config->fullscreen) + { + gtk_widget_show (get_widget ("menubar")); + + if (config->statusbar_visible) + gtk_widget_show (get_widget ("statusbar")); + else + gtk_widget_hide (get_widget ("statusbar")); + } + else + { + gtk_widget_hide (get_widget ("menubar")); + gtk_widget_hide (get_widget ("statusbar")); + } + + gtk_widget_hide (get_widget ("hide_ui")); + } + else + { + enable_widget ("fullscreen_item", TRUE); + + gtk_widget_show (get_widget ("hide_ui")); + + if (config->ui_visible) + { + gtk_widget_show (get_widget ("menubar")); + if (config->statusbar_visible) + gtk_widget_show (get_widget ("statusbar")); + else + gtk_widget_hide (get_widget ("statusbar")); + } + else + { + gtk_widget_hide (get_widget ("menubar")); + gtk_widget_hide (get_widget ("statusbar")); + } + } + + if (config->rom_loaded) + hide_mouse_cursor (); + else + show_mouse_cursor (); + + propagate_pause_state (); + + return; +} + +void +Snes9xWindow::set_mouseable_area (int x, int y, int width, int height) +{ + mouse_region_x = x; + mouse_region_y = y; + mouse_region_width = width; + mouse_region_height = height; + + return; +} + +void +Snes9xWindow::reset_screensaver (void) +{ + static int xdg_screen_saver_works = TRUE; + + if (!focused) + return; + + /* XTest method breaks in new X.org */ + if (!xdg_screen_saver_works || + !g_spawn_command_line_async ("/usr/bin/xdg-screensaver reset", NULL)) + { + xdg_screen_saver_works = FALSE; + } + + XResetScreenSaver (GDK_DISPLAY ()); + + config->screensaver_needs_reset = FALSE; + + return; +} + +void +Snes9xWindow::toggle_fullscreen_mode (void) +{ + if (config->fullscreen) + leave_fullscreen_mode (); + else + enter_fullscreen_mode (); +} + +void +Snes9xWindow::enter_fullscreen_mode (void) +{ + int rom_loaded = config->rom_loaded; + + if (config->fullscreen) + return; + + S9xSoundStop (); + + config->rom_loaded = 0; + + nfs_width = config->window_width; + nfs_height = config->window_height; + + gtk_window_get_position (GTK_WINDOW (window), &nfs_x, &nfs_y); + + /* Make sure everything is done synchronously */ + gdk_display_sync (gdk_display_get_default ()); + gtk_window_fullscreen (GTK_WINDOW (window)); + +#ifdef USE_XRANDR + if (config->change_display_resolution) + { + int mode = -1; + + for (int i = 0; i < config->xrr_num_sizes; i++) + { + if (config->xrr_sizes[i].width == config->xrr_width && + config->xrr_sizes[i].height == config->xrr_height) + { + mode = i; + } + } + + if (mode < 0) + { + config->change_display_resolution = 0; + } + else + { + Display *display = gdk_x11_drawable_get_xdisplay (GDK_DRAWABLE (window->window)); + GdkScreen *screen = gtk_widget_get_screen (window); + GdkWindow *root = gdk_screen_get_root_window (screen); + + gdk_display_sync (gdk_display_get_default ()); + XRRSetScreenConfig (display, + config->xrr_config, + GDK_WINDOW_XWINDOW (root), + (SizeID) mode, + config->xrr_rotation, + CurrentTime); + } + } +#endif + + gdk_display_sync (gdk_display_get_default ()); + gdk_window_raise (GTK_WIDGET (window)->window); + + S9xSoundStart (); + + config->fullscreen = 1; + config->rom_loaded = rom_loaded; + + /* If we're running a game, disable ui when entering fullscreen */ + if (!Settings.Paused && config->rom_loaded) + config->ui_visible = FALSE; + + configure_widgets (); + + return; +} + +void +Snes9xWindow::leave_fullscreen_mode (void) +{ + int rom_loaded = config->rom_loaded; + + if (!config->fullscreen) + return; + + S9xSoundStop (); + + config->rom_loaded = 0; + +#ifdef USE_XRANDR + if (config->change_display_resolution) + { + gtk_widget_hide (window); + + Display *display = gdk_x11_drawable_get_xdisplay (GDK_DRAWABLE (window->window)); + GdkScreen *screen = gtk_widget_get_screen (window); + GdkWindow *root = gdk_screen_get_root_window (screen); + + XRRSetScreenConfig (display, + config->xrr_config, + GDK_WINDOW_XWINDOW (root), + (SizeID) config->xrr_original_size, + config->xrr_rotation, + CurrentTime); + } +#endif + + gtk_window_unfullscreen (GTK_WINDOW (window)); + +#ifdef USE_XRANDR + if (config->change_display_resolution) + { + gtk_widget_show (window); + } +#endif + + resize (nfs_width, nfs_height); + gtk_window_move (GTK_WINDOW (window), nfs_x, nfs_y); + + S9xSoundStart (); + + config->rom_loaded = rom_loaded; + + config->fullscreen = 0; + + configure_widgets (); + + return; +} + +void +Snes9xWindow::draw_background (int rect_x, int rect_y, int rect_w, int rect_h) +{ + GtkWidget *widget = GTK_WIDGET (drawing_area); + GdkGC *gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)]; + int w = widget->allocation.width; + int h = widget->allocation.height; + GdkColor sel = widget->style->bg[GTK_STATE_SELECTED]; + cairo_pattern_t *pattern; + cairo_t *cr; + GdkRectangle rect; + + if (rect_x < 0) + { + rect.x = 0; + rect.y = 0; + rect.width = w; + rect.height = h; + } + else + { + rect.x = rect_x; + rect.y = rect_y; + rect.width = rect_w; + rect.height = rect_h; + } + + gdk_window_begin_paint_rect (widget->window, &rect); + + /* Draw a fancy-pants gradient */ + cr = gdk_cairo_create (widget->window); + pattern = cairo_pattern_create_linear (0.0, + 0.0, + 0.0, + (double) h); + + cairo_pattern_add_color_stop_rgb (pattern, + 0.0, + (double) sel.red * 1.0 / 65535, + (double) sel.green * 1.0 / 65535, + (double) sel.blue * 1.0 / 65535); + cairo_pattern_add_color_stop_rgb (pattern, + 1.0, + (double) sel.red * 0.6 / 65535, + (double) sel.green * 0.6 / 65535, + (double) sel.blue * 0.6 / 65535); + + cairo_rectangle (cr, + (double) rect.x, + (double) rect.y, + (double) rect.width, + (double) rect.height); + + cairo_clip (cr); + + cairo_set_source (cr, pattern); + + cairo_rectangle (cr, 0.0, 0.0, (double) w, (double) h); + cairo_fill (cr); + + /* Put the Snes9x logo in the center */ + gdk_draw_pixbuf (widget->window, + gc, + splash, + 0, + 0, + (w - gdk_pixbuf_get_width (splash)) / 2, + (h - gdk_pixbuf_get_height (splash)) / 2, + gdk_pixbuf_get_width (splash), + gdk_pixbuf_get_height (splash), + GDK_RGB_DITHER_NORMAL, + 0, + 0); + + cairo_pattern_destroy (pattern); + cairo_destroy (cr); + + gdk_window_end_paint (widget->window); + + return; +} + +void +Snes9xWindow::resize_viewport (int width, int height) +{ + GtkWidget *item; + int y_padding = 0; + + item = get_widget ("menubar"); + y_padding += GTK_WIDGET_VISIBLE (item) ? item->allocation.height : 0; + + item = get_widget ("statusbar"); + y_padding += GTK_WIDGET_VISIBLE (item) ? item->allocation.height : 0; + + resize (width, height + y_padding); + + return; +} + +void +Snes9xWindow::hide_mouse_cursor (void) +{ + GdkPixmap *cursor_pixmap; + GdkGC *gc; + GdkColor fg = { 0, 0, 0, 0 }; + GdkColor bg = { 0, 0, 0, 0 }; + + if (!cursor) + { + cursor_pixmap = gdk_pixmap_new (NULL, 1, 1, 1); + gc = gdk_gc_new (GDK_DRAWABLE (cursor_pixmap)); + gdk_gc_set_foreground (gc, &fg); + gdk_draw_point (GDK_DRAWABLE (cursor_pixmap), + gc, + 0, 0); + + cursor = gdk_cursor_new_from_pixmap (cursor_pixmap, + cursor_pixmap, + &fg, &bg, + 0, 0); + g_object_unref (gc); + g_object_unref (cursor_pixmap); + } + + gdk_window_set_cursor (GTK_WIDGET (drawing_area)->window, cursor); + + return; +} + +void +Snes9xWindow::show_mouse_cursor (void) +{ + gdk_window_set_cursor (GTK_WIDGET (drawing_area)->window, NULL); + + return; +} + +void +Snes9xWindow::show (void) +{ + gtk_widget_show (window); + + if (!recent_menu) + { + /* Add recent menu after showing window to avoid "No items" bug */ + recent_menu = gtk_recent_chooser_menu_new_for_manager ( + gtk_recent_manager_get_default ()); + + GtkRecentFilter *filter = gtk_recent_filter_new (); + GtkRecentChooser *chooser = GTK_RECENT_CHOOSER (recent_menu); + + gtk_recent_filter_add_application (filter, "Snes9x"); + gtk_recent_chooser_set_local_only (chooser, TRUE); + gtk_recent_chooser_set_show_icons (chooser, FALSE); + gtk_recent_chooser_set_sort_type (chooser, GTK_RECENT_SORT_MRU); + gtk_recent_chooser_add_filter (chooser, filter); + + gtk_menu_item_set_submenu ( + GTK_MENU_ITEM (get_widget ("open_recent_item")), + recent_menu); + + g_signal_connect (G_OBJECT (recent_menu), + "item-activated", + G_CALLBACK (event_recent_open), + (gpointer) this); + } + + return; +} + +void +Snes9xWindow::propagate_pause_state (void) +{ + int oldpause = Settings.Paused; + + Settings.Paused = (sys_pause || user_pause || !(config->rom_loaded)); + + if (Settings.Paused != oldpause) + { + if (!is_paused ()) + { + S9xSoundStart (); + if (config->rom_loaded) + enable_widget ("pause_item", TRUE); + + hide_mouse_cursor (); + + S9xDisplayClearBuffers (); + } + else + { + S9xSoundStop (); + enable_widget ("pause_item", FALSE); + + show_mouse_cursor (); + } + + update_statusbar (); + } + return; +} + +void +Snes9xWindow::toggle_ui (void) +{ + config->ui_visible = !config->ui_visible; + + configure_widgets (); + + return; +} + +/* gui_[un]pause Handles when system needs to pause the emulator */ +void +Snes9xWindow::pause_from_focus_change (void) +{ + sys_pause++; + + propagate_pause_state (); + + return; +} + +void +Snes9xWindow::unpause_from_focus_change (void) +{ + sys_pause--; + propagate_pause_state (); + + return; +} + +/* client_[un]pause Handles when user manually chooses to pause */ +void +Snes9xWindow::pause_from_user (void) +{ + user_pause = TRUE; + propagate_pause_state (); + + return; +} + +void +Snes9xWindow::unpause_from_user (void) +{ + user_pause = FALSE; + propagate_pause_state (); + + return; +} + +unsigned char +Snes9xWindow::is_paused (void) +{ + if (user_pause || sys_pause || Settings.Paused || !(config->rom_loaded)) + return TRUE; + + return FALSE; +} + +void +Snes9xWindow::set_menu_item_accel_to_binding (const char *name, + const char *binding) +{ + Binding bin; + char str[255]; + + if (!strcmp (binding, "Escape Key")) + { + bin = Binding (GDK_Escape, false, false, false); + } + else + { + bin = S9xGetBindingByName (binding); + } + + snprintf (str, 255, "/%s", name); + if (!(bin.is_key ())) + { + gtk_accel_map_change_entry (str, + 0, + (GdkModifierType) 0, + TRUE); + return; + } + + gtk_widget_set_accel_path (get_widget (name), + str, + glade_xml_ensure_accel (glade)); + + + if (!gtk_accel_map_lookup_entry (str, NULL)) + { + gtk_accel_map_add_entry (str, + bin.get_key (), + bin.get_gdk_modifiers ()); + + } + else + { + gtk_accel_map_change_entry (str, + bin.get_key (), + bin.get_gdk_modifiers (), + TRUE); + } + + return; +} + +void +Snes9xWindow::update_accels (void) +{ + set_menu_item_accel_to_binding ("fullscreen_item", "GTK_fullscreen"); + set_menu_item_accel_to_binding ("reset_item", "SoftReset"); + set_menu_item_accel_to_binding ("save_state_0", "QuickSave000"); + set_menu_item_accel_to_binding ("save_state_1", "QuickSave001"); + set_menu_item_accel_to_binding ("save_state_2", "QuickSave002"); + set_menu_item_accel_to_binding ("save_state_3", "QuickSave003"); + set_menu_item_accel_to_binding ("save_state_4", "QuickSave004"); + set_menu_item_accel_to_binding ("save_state_5", "QuickSave005"); + set_menu_item_accel_to_binding ("save_state_6", "QuickSave006"); + set_menu_item_accel_to_binding ("save_state_7", "QuickSave007"); + set_menu_item_accel_to_binding ("save_state_8", "QuickSave008"); + set_menu_item_accel_to_binding ("load_state_0", "QuickLoad000"); + set_menu_item_accel_to_binding ("load_state_1", "QuickLoad001"); + set_menu_item_accel_to_binding ("load_state_2", "QuickLoad002"); + set_menu_item_accel_to_binding ("load_state_3", "QuickLoad003"); + set_menu_item_accel_to_binding ("load_state_4", "QuickLoad004"); + set_menu_item_accel_to_binding ("load_state_5", "QuickLoad005"); + set_menu_item_accel_to_binding ("load_state_6", "QuickLoad006"); + set_menu_item_accel_to_binding ("load_state_7", "QuickLoad007"); + set_menu_item_accel_to_binding ("load_state_8", "QuickLoad008"); + set_menu_item_accel_to_binding ("pause_item", "GTK_pause"); + set_menu_item_accel_to_binding ("save_spc_item", "GTK_save_spc"); + set_menu_item_accel_to_binding ("open_rom_item", "GTK_open_rom"); + set_menu_item_accel_to_binding ("record_movie_item", "BeginRecordingMovie"); + set_menu_item_accel_to_binding ("open_movie_item", "LoadMovie"); + set_menu_item_accel_to_binding ("stop_recording_item", "EndRecordingMovie"); + set_menu_item_accel_to_binding ("jump_to_frame_item", "GTK_seek_to_frame"); + set_menu_item_accel_to_binding ("reset_item", "SoftReset"); + set_menu_item_accel_to_binding ("hard_reset_item", "Reset"); + set_menu_item_accel_to_binding ("exit_item", "GTK_quit"); + + /* Special UI assignment */ + set_menu_item_accel_to_binding ("hide_ui", "Escape Key"); + + return; +} diff --git a/gtk/src/gtk_s9xwindow.h b/gtk/src/gtk_s9xwindow.h new file mode 100644 index 00000000..58b6884c --- /dev/null +++ b/gtk/src/gtk_s9xwindow.h @@ -0,0 +1,89 @@ +#ifndef __GTK_S9XWINDOW_H +#define __GTK_S9XWINDOW_H + +#include + +#ifdef USE_OPENGL +#include +#endif + +#include + +#include "gtk_s9x.h" +#include "gtk_glade_window.h" + +#define SIZE_FLAG_NO_DRAWING -1 +#define SIZE_FLAG_DIRTY -2 + +class Snes9xWindow : public GladeWindow +{ + public: + Snes9xWindow (Snes9xConfig *config); + + /* Pause related functions */ + void pause_from_focus_change (void); + void unpause_from_focus_change (void); + void focus_notify (int state); + void pause_from_user (void); + void unpause_from_user (void); + unsigned char is_paused (void); + void propagate_pause_state (void); + + /* Fullscreen functions */ + void enter_fullscreen_mode (void); + void leave_fullscreen_mode (void); + void toggle_fullscreen_mode (void); + void finish_fullscreen (void); + + /* Cursor modifying functions */ + void show_mouse_cursor (void); + void hide_mouse_cursor (void); + + /* Rom-related functions */ + void open_rom_dialog (void); + void save_state_dialog (void); + void load_state_dialog (void); + void configure_widgets (void); + void save_spc_dialog (void); + int try_open_rom (const char *filename); + const char *open_movie_dialog (bool readonly); + void movie_seek_dialog (void); + void open_multicart_dialog (void); + void show_rom_info (void); + + /* GTK-base-related functions */ + void show (void); + void show_status_message (const char *message); + void update_statusbar (void); + void draw_background (int rect_x = -1, + int rect_y = -1, + int rect_w = -1, + int rect_h = -1); + void set_menu_item_selected (const char *name); + void set_mouseable_area (int x, int y, int width, int height); + void set_menu_item_accel_to_binding (const char *name, + const char *binding); + void reset_screensaver (void); + void update_accels (void); + void toggle_ui (void); + void resize_viewport (int width, int height); + + Snes9xConfig *config; + unsigned char user_pause; + unsigned char sys_pause; + int last_width, last_height; + int mouse_region_x, mouse_region_y; + int mouse_region_width, mouse_region_height; + int nfs_width, nfs_height, nfs_x, nfs_y; + int fullscreen_state; + int maximized_state; + int focused; + int paused_from_focus_loss; + uint16 mouse_loc_x, mouse_loc_y; + GdkPixbuf *icon, *splash; + GdkCursor *cursor; + GtkDrawingArea *drawing_area; + GtkWidget *recent_menu; +}; + +#endif /* __GTK_S9XWINDOW_H */ diff --git a/gtk/src/gtk_sound.cpp b/gtk/src/gtk_sound.cpp new file mode 100644 index 00000000..0a313887 --- /dev/null +++ b/gtk/src/gtk_sound.cpp @@ -0,0 +1,226 @@ +#include +#include + +#include "gtk_s9x.h" +#include "gtk_sound.h" +#include "gtk_sound_driver.h" + +#ifdef USE_PORTAUDIO +#include "gtk_sound_driver_portaudio.h" +#endif +#ifdef USE_OSS +#include "gtk_sound_driver_oss.h" +#endif +#ifdef USE_JOYSTICK +#include "gtk_sound_driver_sdl.h" +#endif +#ifdef USE_ALSA +#include "gtk_sound_driver_alsa.h" +#endif +#ifdef USE_PULSEAUDIO +#include "gtk_sound_driver_pulse.h" +#endif + +int playback_rates[8] = +{ + 0, 8000, 11025, 16000, 22050, 32000, 44100, 48000 +}; + +double d_playback_rates[8] = +{ + 0.0, 8000.0, 11025.0, 16000.0, 22050.0, 32000.0, 44100.0, 48000.0 +}; + +S9xSoundDriver *driver; + +int +S9xSoundBase2log (int num) +{ + int power; + + if (num < 1) + return 0; + + for (power = 0; num > 1; power++) + { + num >>= 1; + } + + return power; +} + +int +S9xSoundPowerof2 (int num) +{ + return (1 << num); +} + +void +S9xPortSoundInit (void) +{ + int pao_driver = 0; + int sdl_driver = 0; + int oss_driver = 0; + int alsa_driver = 0; + int pulse_driver = 0; + int max_driver = 0; + + driver = NULL; + +#ifdef USE_PORTAUDIO + sdl_driver++; + oss_driver++; + alsa_driver++; + pulse_driver++; + + max_driver++; +#endif + +#ifdef USE_OSS + sdl_driver++; + alsa_driver++; + pulse_driver++; + + max_driver++; +#endif + +#ifdef USE_JOYSTICK + alsa_driver++; + pulse_driver++; + + max_driver++; +#endif + +#ifdef USE_ALSA + max_driver++; + pulse_driver++; +#endif + +#ifdef USE_PULSEAUDIO + max_driver++; +#endif + + if (gui_config->sound_driver >= max_driver) + gui_config->sound_driver = 0; + +#ifdef USE_PORTAUDIO + if (gui_config->sound_driver == pao_driver) + driver = new S9xPortAudioSoundDriver (); +#endif + +#ifdef USE_OSS + if (gui_config->sound_driver == oss_driver) + driver = new S9xOSSSoundDriver (); +#endif + +#ifdef USE_JOYSTICK + if (gui_config->sound_driver == sdl_driver) + driver = new S9xSDLSoundDriver (); +#endif + +#ifdef USE_ALSA + if (gui_config->sound_driver == alsa_driver) + driver = new S9xAlsaSoundDriver (); +#endif + +#ifdef USE_PULSEAUDIO + if (gui_config->sound_driver == pulse_driver) + driver = new S9xPulseSoundDriver (); +#endif + + if (driver != NULL) + { + driver->init (); + + Settings.SoundInputRate = CLAMP (gui_config->sound_input_rate, 8000, 48000); + + Settings.SoundPlaybackRate = playback_rates[gui_config->sound_playback_rate]; + + S9xInitSound (gui_config->sound_buffer_size, 0); + + S9xSetSoundMute (FALSE); + } + else + { + S9xSetSoundMute (gui_config->mute_sound); + } + + return; +} + +void +S9xPortSoundReinit (void) +{ + S9xPortSoundDeinit (); + + /* Ensure the sound device is released before trying to reopen it. */ + sync (); + + S9xPortSoundInit (); +} + +void +S9xPortSoundDeinit (void) +{ + S9xSoundStop (); + + driver->terminate (); + + delete driver; + + return; +} + +void +S9xSoundStart (void) +{ + driver->start (); + + return; +} + +void +S9xSoundStop (void) +{ + driver->stop (); + + return; +} + +void +S9xMixSound (void) +{ + driver->mix (); + + return; +} + +bool8 +S9xOpenSoundDevice (void) +{ + if (gui_config->mute_sound) + return FALSE; + + if (gui_config->sound_buffer_size < 2) + gui_config->sound_buffer_size = 2; + if (gui_config->sound_buffer_size > 256) + gui_config->sound_buffer_size = 256; + + return driver->open_device (); +} + +/* This really shouldn't be in the port layer */ +void +S9xToggleSoundChannel (int c) +{ + static int sound_switch = 255; + + if (c == 8) + sound_switch = 255; + else + sound_switch ^= 1 << c; + + S9xSetSoundControl (sound_switch); + + return; +} diff --git a/gtk/src/gtk_sound.h b/gtk/src/gtk_sound.h new file mode 100644 index 00000000..af47a36e --- /dev/null +++ b/gtk/src/gtk_sound.h @@ -0,0 +1,18 @@ +#ifndef __GTK_SOUND_H +#define __GTK_SOUND_H + +void S9xPortSoundInit (void); +void S9xPortSoundDeinit (void); +void S9xPortSoundReinit (void); +void S9xSoundStart (void); +void S9xSoundStop (void); +void S9xMixSound (void); + +int S9xSoundBase2log (int num); +int S9xSoundPowerof2 (int num); + +extern int playback_rates[8]; +extern int buffer_sizes[8]; +extern double d_playback_rates[8]; + +#endif /* __GTK_SOUND_H */ diff --git a/gtk/src/gtk_sound_driver.h b/gtk/src/gtk_sound_driver.h new file mode 100644 index 00000000..1c66ccd8 --- /dev/null +++ b/gtk/src/gtk_sound_driver.h @@ -0,0 +1,18 @@ +#ifndef __GTK_SOUND_DRIVER_H +#define __GTK_SOUND_DRIVER_H + +#include "gtk_s9x.h" + +class S9xSoundDriver +{ + public: + virtual void init (void) = 0; + virtual void terminate (void) = 0; + virtual bool8 open_device (void) = 0; + virtual void start (void) = 0; + virtual void stop (void) = 0; + virtual void mix (void) = 0; +}; + + +#endif /* __GTK_SOUND_DRIVER_H */ diff --git a/gtk/src/gtk_sound_driver_alsa.cpp b/gtk/src/gtk_sound_driver_alsa.cpp new file mode 100644 index 00000000..8f033d15 --- /dev/null +++ b/gtk/src/gtk_sound_driver_alsa.cpp @@ -0,0 +1,195 @@ +#include "gtk_s9x.h" +#include "gtk_sound_driver_alsa.h" + +#include +#include +#include + +static void +alsa_samples_available (void *data) +{ + ((S9xAlsaSoundDriver *) data)->samples_available (); +} + +S9xAlsaSoundDriver::S9xAlsaSoundDriver (void) +{ + pcm = NULL; + sound_buffer = NULL; + sound_buffer_size = 0; + + return; +} + +void +S9xAlsaSoundDriver::init (void) +{ + return; +} + +void +S9xAlsaSoundDriver::terminate (void) +{ + stop (); + + S9xSetSamplesAvailableCallback (NULL, NULL); + + if (pcm) + { + snd_pcm_drain (pcm); + snd_pcm_close (pcm); + pcm = NULL; + } + + if (sound_buffer) + { + free (sound_buffer); + sound_buffer = NULL; + } + + return; +} + +void +S9xAlsaSoundDriver::start (void) +{ + return; +} + +void +S9xAlsaSoundDriver::stop (void) +{ + return; +} + +bool8 +S9xAlsaSoundDriver::open_device (void) +{ + int err; + snd_pcm_sw_params_t *sw_params; + snd_pcm_uframes_t alsa_buffer_size, alsa_period_size; + + printf ("ALSA sound driver initializing...\n"); + printf (" --> (Device: default)..."); + + if ((err = snd_pcm_open (&pcm, + "default", + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK) < 0)) + { + goto fail; + } + + printf ("OK\n"); + + printf (" --> (%s, %s, %dhz, %d ms)...", + Settings.SixteenBitSound ? "16-bit" : "8-bit", + Settings.Stereo ? "Stereo" : "Mono", + Settings.SoundPlaybackRate, + gui_config->sound_buffer_size); + + if ((err = snd_pcm_set_params (pcm, + Settings.SixteenBitSound ? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U8, + SND_PCM_ACCESS_RW_INTERLEAVED, + Settings.Stereo ? 2 : 1, + Settings.SoundPlaybackRate, + 1 /* Allow software resampling */, + gui_config->sound_buffer_size * 1000)) + < 0) + { + goto close_fail; + } + + snd_pcm_sw_params_alloca (&sw_params); + snd_pcm_sw_params_current (pcm, sw_params); + snd_pcm_get_params (pcm, &alsa_buffer_size, &alsa_period_size); + /* Don't start until we're [nearly] full */ + snd_pcm_sw_params_set_start_threshold (pcm, + sw_params, + (alsa_buffer_size / alsa_period_size) * alsa_period_size); + /* Transfer in blocks of period-size */ + snd_pcm_sw_params_set_avail_min (pcm, sw_params, alsa_period_size); + err = snd_pcm_sw_params (pcm, sw_params); + if (err < 0) + goto close_fail; + + printf ("OK\n"); + + S9xSetSamplesAvailableCallback (alsa_samples_available, this); + + return TRUE; + +close_fail: + snd_pcm_drain (pcm); + snd_pcm_close (pcm); + pcm = NULL; + +fail: + printf ("Failed: %s\n", snd_strerror (err)); + + return FALSE; +} + +void +S9xAlsaSoundDriver::mix (void) +{ + return; +} + +void +S9xAlsaSoundDriver::samples_available (void) +{ + snd_pcm_sframes_t frames_written, frames; + int bytes; + + S9xFinalizeSamples (); + + frames = snd_pcm_avail_update (pcm); + if (frames < 0) + { + frames = snd_pcm_recover (pcm, frames, 1); + } + + frames = MIN (frames, S9xGetSampleCount () >> (Settings.Stereo ? 1 : 0)); + + bytes = snd_pcm_frames_to_bytes (pcm, frames); + if (bytes <= 0) + { + return; + } + + if (sound_buffer_size < bytes || sound_buffer == NULL) + { + sound_buffer = (uint8 *) realloc (sound_buffer, bytes); + sound_buffer_size = bytes; + } + + S9xMixSamples (sound_buffer, frames << (Settings.Stereo ? 1 : 0)); + + frames_written = 0; + + while (frames_written < frames) + { + int result; + + result = snd_pcm_writei (pcm, + sound_buffer + + snd_pcm_frames_to_bytes (pcm, frames_written), + frames - frames_written); + + if (result < 0) + { + result = snd_pcm_recover (pcm, result, 1); + + if (result < 0) + { + break; + } + } + else + { + frames_written += result; + } + } + + return; +} diff --git a/gtk/src/gtk_sound_driver_alsa.h b/gtk/src/gtk_sound_driver_alsa.h new file mode 100644 index 00000000..d7dab5bc --- /dev/null +++ b/gtk/src/gtk_sound_driver_alsa.h @@ -0,0 +1,26 @@ +#ifndef __GTK_SOUND_DRIVER_ALSA_H +#define __GTK_SOUND_DRIVER_ALSA_H + +#include "gtk_sound.h" +#include "gtk_sound_driver.h" +#include "alsa/asoundlib.h" + +class S9xAlsaSoundDriver : public S9xSoundDriver +{ + public: + S9xAlsaSoundDriver (void); + void init (void); + void terminate (void); + bool8 open_device (void); + void start (void); + void stop (void); + void mix (void); + void samples_available (void); + + private: + snd_pcm_t *pcm; + int sound_buffer_size; + uint8 *sound_buffer; +}; + +#endif /* __GTK_SOUND_DRIVER_ALSA_H */ diff --git a/gtk/src/gtk_sound_driver_oss.cpp b/gtk/src/gtk_sound_driver_oss.cpp new file mode 100644 index 00000000..f7527941 --- /dev/null +++ b/gtk/src/gtk_sound_driver_oss.cpp @@ -0,0 +1,216 @@ +#include "gtk_s9x.h" +#include "gtk_sound_driver_oss.h" + +#include +#include +#include +#include + +static void +oss_samples_available (void *data) +{ + ((S9xOSSSoundDriver *) data)->samples_available (); +} + +S9xOSSSoundDriver::S9xOSSSoundDriver (void) +{ + filedes = -1; + sound_buffer = NULL; + sound_buffer_size = 0; + + return; +} + +void +S9xOSSSoundDriver::init (void) +{ + return; +} + +void +S9xOSSSoundDriver::terminate (void) +{ + stop (); + + S9xSetSamplesAvailableCallback (NULL, NULL); + + if (filedes >= 0) + { + close (filedes); + } + + if (sound_buffer) + { + free (sound_buffer); + sound_buffer = NULL; + } + + return; +} + +void +S9xOSSSoundDriver::start (void) +{ + return; +} + +void +S9xOSSSoundDriver::stop (void) +{ + return; +} + +bool8 +S9xOSSSoundDriver::open_device (void) +{ + int temp; + int output_buffer_size; + + output_buffer_size = (gui_config->sound_buffer_size * Settings.SoundPlaybackRate) / 1000; + + if (Settings.Stereo) + output_buffer_size *= 2; + if (Settings.SixteenBitSound) + output_buffer_size *= 2; + if (output_buffer_size > 65536) + output_buffer_size = 65536; + if (output_buffer_size < 256) + output_buffer_size = 256; + + printf ("OSS sound driver initializing...\n"); + + printf (" --> (Device: /dev/dsp)..."); + + filedes = open ("/dev/dsp", O_WRONLY | O_NONBLOCK); + + if (filedes < 0) + goto fail; + + printf ("OK\n"); + + + if (Settings.SixteenBitSound) + { + printf (" --> (Format: 16-bit)..."); + + temp = AFMT_S16_LE; + if (ioctl (filedes, SNDCTL_DSP_SETFMT, &temp) < 0) + goto close_fail; + } + else + { + printf (" --> (Format: 8-bit)..."); + + temp = AFMT_U8; + if (ioctl (filedes, SNDCTL_DSP_SETFMT, &temp) < 0) + goto close_fail; + } + + printf ("OK\n"); + + if (Settings.Stereo) + { + temp = 2; + printf (" --> (Stereo)..."); + } + else + { + temp = 1; + printf (" --> (Mono)..."); + } + + if (ioctl (filedes, SNDCTL_DSP_CHANNELS, &temp) < 0) + goto close_fail; + + printf ("OK\n"); + + printf (" --> (Frequency: %d)...", Settings.SoundPlaybackRate); + if (ioctl (filedes, SNDCTL_DSP_SPEED, &Settings.SoundPlaybackRate) < 0) + goto close_fail; + + printf ("OK\n"); + + /* OSS requires a power-of-two buffer size, first 16 bits are the number + * of fragments to generate, second 16 are the respective power-of-two. */ + temp = (2 << 16) | (S9xSoundBase2log (output_buffer_size)); + + output_buffer_size = S9xSoundPowerof2 (temp & 0xffff); + + printf (" --> (Buffer size: %d bytes, %dms latency)...", + output_buffer_size, + (((output_buffer_size * 1000) >> (Settings.Stereo ? 1 : 0)) + >> (Settings.SixteenBitSound ? 1 : 0)) + / (Settings.SoundPlaybackRate)); + + if (ioctl (filedes, SNDCTL_DSP_SETFRAGMENT, &temp) < 0) + goto close_fail; + + printf ("OK\n"); + + S9xSetSamplesAvailableCallback (oss_samples_available, this); + + return TRUE; + +close_fail: + + close (filedes); + +fail: + printf ("failed\n"); + + return FALSE; +} + +void +S9xOSSSoundDriver::mix (void) +{ + return; +} + +void +S9xOSSSoundDriver::samples_available (void) +{ + audio_buf_info info; + int samples_to_write; + int bytes_to_write; + int bytes_written; + + S9xFinalizeSamples (); + + samples_to_write = S9xGetSampleCount (); + + ioctl (filedes, SNDCTL_DSP_GETOSPACE, &info); + + samples_to_write = MIN (info.bytes >> (Settings.SixteenBitSound ? 1 : 0), + samples_to_write); + + if (samples_to_write < 0) + return; + + if (sound_buffer_size < samples_to_write << (Settings.SixteenBitSound ? 1 : 0)) + { + sound_buffer = (uint8 *) realloc (sound_buffer, samples_to_write << (Settings.SixteenBitSound ? 1 : 0)); + sound_buffer_size = samples_to_write << (Settings.SixteenBitSound ? 1 : 0); + } + + S9xMixSamples (sound_buffer, samples_to_write); + + bytes_written = 0; + bytes_to_write = samples_to_write << (Settings.SixteenBitSound ? 1 : 0); + + while (bytes_to_write > bytes_written) + { + int result; + + result = write (filedes, + ((char *) sound_buffer) + bytes_written, + bytes_to_write - bytes_written); + + if (result < 0) + break; + + bytes_written += result; + } + + return; +} diff --git a/gtk/src/gtk_sound_driver_oss.h b/gtk/src/gtk_sound_driver_oss.h new file mode 100644 index 00000000..8ae772df --- /dev/null +++ b/gtk/src/gtk_sound_driver_oss.h @@ -0,0 +1,27 @@ +#ifndef __GTK_SOUND_DRIVER_OSS_H +#define __GTK_SOUND_DRIVER_OSS_H + +#include "gtk_sound.h" +#include "gtk_sound_driver.h" + +class S9xOSSSoundDriver : public S9xSoundDriver +{ + public: + S9xOSSSoundDriver (void); + void init (void); + void terminate (void); + bool8 open_device (void); + void start (void); + void stop (void); + void mix (void); + void samples_available (void); + + private: + int filedes; + uint8 *sound_buffer; + int sound_buffer_size; +}; + + + +#endif /* __GTK_SOUND_DRIVER_OSS_H */ diff --git a/gtk/src/gtk_sound_driver_portaudio.cpp b/gtk/src/gtk_sound_driver_portaudio.cpp new file mode 100644 index 00000000..295055ab --- /dev/null +++ b/gtk/src/gtk_sound_driver_portaudio.cpp @@ -0,0 +1,223 @@ +#include "gtk_s9x.h" +#include "gtk_sound_driver_portaudio.h" + +static int +port_audio_callback (const void *input, + void *output, + unsigned long frameCount, + const PaStreamCallbackTimeInfo* timeInfo, + PaStreamCallbackFlags statusFlags, + void *userData) +{ + ((S9xPortAudioSoundDriver *) userData)->mix ((unsigned char *) output, frameCount * (Settings.Stereo ? 2 : 1) * (Settings.SixteenBitSound ? 2 : 1)); + + return 0; +} + +static void +port_audio_samples_available_callback (void *data) +{ + ((S9xPortAudioSoundDriver *) data)->samples_available (); + + return; +} + +void +S9xPortAudioSoundDriver::mix (unsigned char *output, int bytes) +{ + g_mutex_lock (mutex); + + S9xMixSamples (output, bytes >> (Settings.SixteenBitSound ? 1 : 0)); + + g_mutex_unlock (mutex); + + return; +} + +S9xPortAudioSoundDriver::S9xPortAudioSoundDriver(void) +{ + audio_stream = NULL; + mutex = NULL; + + return; +} + +void +S9xPortAudioSoundDriver::init (void) +{ + PaError err; + + err = Pa_Initialize (); + + if (err != paNoError) + fprintf (stderr, + "Couldn't initialize PortAudio: %s\n", + Pa_GetErrorText (err)); + + return; +} + +void +S9xPortAudioSoundDriver::terminate (void) +{ + stop (); + + if (mutex) + { + g_mutex_free (mutex); + mutex = NULL; + } + + S9xSetSamplesAvailableCallback (NULL, NULL); + + Pa_Terminate (); + + return; +} + +void +S9xPortAudioSoundDriver::start (void) +{ + PaError err; + + if (audio_stream != NULL && !(gui_config->mute_sound)) + { + if ((Pa_IsStreamActive (audio_stream))) + return; + + err = Pa_StartStream (audio_stream); + + if (err != paNoError) + { + fprintf (stderr, "Error: %s\n", Pa_GetErrorText (err)); + } + } + + return; +} + +void +S9xPortAudioSoundDriver::stop (void) +{ + if (audio_stream != NULL) + { + Pa_StopStream (audio_stream); + } + + return; +} + +bool8 +S9xPortAudioSoundDriver::open_device (void) +{ + PaStreamParameters param; + const PaDeviceInfo *device_info; + const PaHostApiInfo *hostapi_info; + PaError err = paNoError; + + if (audio_stream != NULL) + { + printf ("Shutting down sound for reset\n"); + err = Pa_CloseStream (audio_stream); + + if (err != paNoError) + { + fprintf (stderr, + "Couldn't reset audio stream.\nError: %s\n", + Pa_GetErrorText (err)); + return TRUE; + } + + audio_stream = NULL; + } + + param.channelCount = Settings.Stereo ? 2 : 1; + param.sampleFormat = Settings.SixteenBitSound ? paInt16 : paUInt8; + param.hostApiSpecificStreamInfo = NULL; + + printf ("PortAudio sound driver initializing...\n"); + + for (int i = 0; i < Pa_GetHostApiCount (); i++) + { + printf (" --> "); + + hostapi_info = Pa_GetHostApiInfo (i); + if (!hostapi_info) + { + printf ("Host API #%d has no info\n", i); + err = paNotInitialized; + continue; + } + + device_info = Pa_GetDeviceInfo (hostapi_info->defaultOutputDevice); + if (!device_info) + { + printf ("(%s)...No device info available.\n", hostapi_info->name); + err = paNotInitialized; + continue; + } + + param.device = hostapi_info->defaultOutputDevice; + param.suggestedLatency = gui_config->sound_buffer_size * 0.001; + + printf ("(%s : %s, latency %dms)...", + hostapi_info->name, + device_info->name, + (int) (param.suggestedLatency * 1000.0)); + + fflush (stdout); + + err = Pa_OpenStream (&audio_stream, + NULL, + ¶m, + Settings.SoundPlaybackRate, + 0, + paNoFlag, + port_audio_callback, + this); + + if (err == paNoError) + { + printf ("OK\n"); + break; + } + else + { + printf ("Failed (%s)\n", + Pa_GetErrorText (err)); + } + } + + if (err != paNoError || Pa_GetHostApiCount () < 1) + { + fprintf (stderr, + "Couldn't initialize sound\n"); + return FALSE; + } + + mutex = g_mutex_new (); + S9xSetSamplesAvailableCallback (port_audio_samples_available_callback, this); + + fflush (stdout); + fflush (stderr); + + return TRUE; +} + +void +S9xPortAudioSoundDriver::samples_available (void) +{ + g_mutex_lock (mutex); + + S9xFinalizeSamples (); + + g_mutex_unlock (mutex); + + return; +} + +void +S9xPortAudioSoundDriver::mix (void) +{ + return; +} diff --git a/gtk/src/gtk_sound_driver_portaudio.h b/gtk/src/gtk_sound_driver_portaudio.h new file mode 100644 index 00000000..1fc79645 --- /dev/null +++ b/gtk/src/gtk_sound_driver_portaudio.h @@ -0,0 +1,29 @@ +#ifndef __GTK_SOUND_DRIVER_PORTAUDIO_H +#define __GTK_SOUND_DRIVER_PORTAUDIO_H + +#include +#include + +#include "gtk_sound.h" +#include "gtk_sound_driver.h" + +class S9xPortAudioSoundDriver : public S9xSoundDriver +{ + public: + S9xPortAudioSoundDriver (void); + void init (void); + void terminate (void); + bool8 open_device (void); + void start (void); + void stop (void); + void mix (void); + void mix (unsigned char *output, int bytes); + void samples_available (void); + + private: + PaStream *audio_stream; + GMutex *mutex; +}; + + +#endif /* __GTK_SOUND_DRIVER_PORTAUDIO_H */ diff --git a/gtk/src/gtk_sound_driver_pulse.cpp b/gtk/src/gtk_sound_driver_pulse.cpp new file mode 100644 index 00000000..4331a945 --- /dev/null +++ b/gtk/src/gtk_sound_driver_pulse.cpp @@ -0,0 +1,145 @@ +#include "gtk_s9x.h" +#include "gtk_sound_driver_pulse.h" + +#include +#include +#include + +static void +pulse_samples_available (void *data) +{ + ((S9xPulseSoundDriver *) data)->samples_available (); +} + +S9xPulseSoundDriver::S9xPulseSoundDriver (void) +{ + pulse = NULL; + buffer = NULL; + buffer_size = 0; + + return; +} + +void +S9xPulseSoundDriver::init (void) +{ + return; +} + +void +S9xPulseSoundDriver::terminate (void) +{ + stop (); + + S9xSetSamplesAvailableCallback (NULL, NULL); + + if (pulse) + { + pa_simple_free (pulse); + } + + if (buffer) + { + delete[] buffer; + buffer = NULL; + } + + return; +} + +void +S9xPulseSoundDriver::start (void) +{ + return; +} + +void +S9xPulseSoundDriver::stop (void) +{ + return; +} + +bool8 +S9xPulseSoundDriver::open_device (void) +{ + int err; + pa_sample_spec ss; + pa_buffer_attr buffer_attr; + + ss.channels = Settings.Stereo ? 2 : 1; + ss.format = Settings.SixteenBitSound ? PA_SAMPLE_S16NE : PA_SAMPLE_U8; + ss.rate = Settings.SoundPlaybackRate; + + buffer_attr.fragsize = -1; + buffer_attr.tlength = pa_usec_to_bytes (gui_config->sound_buffer_size * 1000, &ss); + buffer_attr.maxlength = -1; + buffer_attr.minreq = -1; + buffer_attr.prebuf = -1; + + printf ("PulseAudio sound driver initializing...\n"); + + printf (" --> (%dhz, %s %s, %dms)...", + Settings.SoundPlaybackRate, + Settings.SixteenBitSound ? "16-bit" : "8-bit", + Settings.Stereo ? "Stereo" : "Mono", + gui_config->sound_buffer_size); + + pulse = pa_simple_new (NULL, + "Snes9x", + PA_STREAM_PLAYBACK, + NULL, + "Game", + &ss, + NULL, + &buffer_attr, + &err); + + if (!pulse) + { + printf ("Failed: %s\n", pa_strerror (err)); + return FALSE; + } + + printf ("OK\n"); + + S9xSetSamplesAvailableCallback (pulse_samples_available, this); + + return TRUE; +} + +void +S9xPulseSoundDriver::mix (void) +{ + return; +} + +void +S9xPulseSoundDriver::samples_available (void) +{ + int bytes, err; + + S9xFinalizeSamples (); + + bytes = (S9xGetSampleCount () << (Settings.SixteenBitSound ? 1 : 0)); + + if (bytes <= 128) + return; + + if (buffer_size < bytes || buffer == NULL) + { + delete[] buffer; + buffer = new uint8[bytes]; + buffer_size = bytes; + } + + S9xMixSamples (buffer, bytes >> (Settings.SixteenBitSound ? 1 : 0)); + + /* PulseAudio-simple has no write indicator, so we don't know when the + buffer is full. So we just drop the audio when we're in Turbo Mode. */ + if (Settings.TurboMode) + return; + + pa_simple_write (pulse, buffer, bytes, &err); + + return; +} diff --git a/gtk/src/gtk_sound_driver_pulse.h b/gtk/src/gtk_sound_driver_pulse.h new file mode 100644 index 00000000..878716cf --- /dev/null +++ b/gtk/src/gtk_sound_driver_pulse.h @@ -0,0 +1,28 @@ +#ifndef __GTK_SOUND_DRIVER_PULSE_H +#define __GTK_SOUND_DRIVER_PULSE_H + +#include "gtk_sound.h" +#include "gtk_sound_driver.h" +#include "pulse/simple.h" +#include "pulse/error.h" + +class S9xPulseSoundDriver : public S9xSoundDriver +{ + public: + S9xPulseSoundDriver (void); + void init (void); + void terminate (void); + bool8 open_device (void); + void start (void); + void stop (void); + void mix (void); + void samples_available (void); + + private: + pa_simple *pulse; + uint8 *buffer; + int buffer_size; + +}; + +#endif /* __GTK_SOUND_DRIVER_PULSE_H */ diff --git a/gtk/src/gtk_sound_driver_sdl.cpp b/gtk/src/gtk_sound_driver_sdl.cpp new file mode 100644 index 00000000..b9b88907 --- /dev/null +++ b/gtk/src/gtk_sound_driver_sdl.cpp @@ -0,0 +1,128 @@ +#include "gtk_s9x.h" +#include "gtk_sound_driver_sdl.h" + +static void +sdl_audio_callback (void *userdata, Uint8 *stream, int len) +{ + ((S9xSDLSoundDriver *) userdata)->mix ((unsigned char *) stream, len); + + return; +} + +static void +samples_available (void *data) +{ + SDL_LockAudio (); + S9xFinalizeSamples (); + SDL_UnlockAudio (); + + return; +} + +void +S9xSDLSoundDriver::mix (unsigned char *output, int bytes) +{ + SDL_LockAudio (); + S9xMixSamples (output, bytes >> (Settings.SixteenBitSound ? 1 : 0)); + SDL_UnlockAudio (); + + return; +} + +S9xSDLSoundDriver::S9xSDLSoundDriver (void) +{ + audiospec = NULL; + + return; +} + +void +S9xSDLSoundDriver::init (void) +{ + SDL_InitSubSystem (SDL_INIT_AUDIO); + stop (); + + return; +} + +void +S9xSDLSoundDriver::terminate (void) +{ + stop (); + + if (audiospec) + { + SDL_CloseAudio (); + free (audiospec); + audiospec = NULL; + } + + SDL_QuitSubSystem (SDL_INIT_AUDIO); + + return; +} + +void +S9xSDLSoundDriver::start (void) +{ + if (!gui_config->mute_sound) + { + if (audiospec) + { + SDL_PauseAudio (0); + } + } + + return; +} + +void +S9xSDLSoundDriver::stop (void) +{ + if (audiospec) + { + SDL_PauseAudio (1); + } + + return; +} + +bool8 +S9xSDLSoundDriver::open_device (void) +{ + audiospec = (SDL_AudioSpec *) malloc (sizeof (SDL_AudioSpec)); + + audiospec->freq = Settings.SoundPlaybackRate; + audiospec->channels = Settings.Stereo ? 2 : 1; + audiospec->format = Settings.SixteenBitSound ? AUDIO_S16SYS : AUDIO_U8; + audiospec->samples = (gui_config->sound_buffer_size * audiospec->freq / 1000) >> 1; + audiospec->callback = sdl_audio_callback; + audiospec->userdata = this; + + printf ("SDL sound driver initializing...\n"); + printf (" --> (Frequency: %dhz, Latency: %dms)...", + audiospec->freq, + (audiospec->samples * 1000 / audiospec->freq) << 1); + + if (SDL_OpenAudio (audiospec, NULL) < 0) + { + printf ("Failed\n"); + + free (audiospec); + audiospec = NULL; + + return FALSE; + } + + printf ("OK\n"); + + S9xSetSamplesAvailableCallback (samples_available, NULL); + + return TRUE; +} + +void +S9xSDLSoundDriver::mix (void) +{ + return; +} diff --git a/gtk/src/gtk_sound_driver_sdl.h b/gtk/src/gtk_sound_driver_sdl.h new file mode 100644 index 00000000..8fb3f6bf --- /dev/null +++ b/gtk/src/gtk_sound_driver_sdl.h @@ -0,0 +1,26 @@ +#ifndef __GTK_SOUND_DRIVER_SDL_H +#define __GTK_SOUND_DRIVER_SDL_H + +#include "SDL.h" + +#include "gtk_sound.h" +#include "gtk_sound_driver.h" + +class S9xSDLSoundDriver : public S9xSoundDriver +{ + public: + S9xSDLSoundDriver (void); + void init (void); + void terminate (void); + bool8 open_device (void); + void start (void); + void stop (void); + void mix (void); + void mix (unsigned char *output, int bytes); + + private: + SDL_AudioSpec *audiospec; +}; + + +#endif /* __GTK_SOUND_DRIVER_SDL_H */ diff --git a/gtk/src/gtk_splash.h b/gtk/src/gtk_splash.h new file mode 100644 index 00000000..cb2953c5 --- /dev/null +++ b/gtk/src/gtk_splash.h @@ -0,0 +1,2820 @@ +/* GdkPixbuf RGBA C-Source image dump */ + +#ifdef __SUNPRO_C +#pragma align 4 (image_splash) +#endif +#ifdef __GNUC__ +static const guint8 image_splash[] __attribute__ ((__aligned__ (4))) = +#else +static const guint8 image_splash[] = +#endif +{ "" + /* Pixbuf magic (0x47646b50) */ + "GdkP" + /* length: header (24) + pixel_data (75776) */ + "\0\1(\30" + /* pixdata_type (0x1010002) */ + "\1\1\0\2" + /* rowstride (1024) */ + "\0\0\4\0" + /* width (256) */ + "\0\0\1\0" + /* height (74) */ + "\0\0\0J" + /* pixel_data: */ + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\5\0\0\0\12\0\0\0\22\0\0\0\33\0\0\0" + "!\0\0\2$\0\0\1#\0\0\0\36\0\0\0\27\0\0\0\20\0\0\0\10\0\0\0\3\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\1\0\0\0\10\0\0\0\25\0\0\0$\0\0\0""8\0\0\0N\0\0\0" + "d\0\0\0r\0\0\0w\0\0\0u\0\0\0m\0\0\0\\\0\0\0H\0\0\0/\0\0\0\31\0\0\0\12" + "\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\3\0\0\0\24\0\0\0-\0\0\0Q\1\1\2r\0\0\0\216\0\0\0\250\5" + "\5\4\300\10\10#\322\7\7""2\331\4\4'\327\1\1\17\315\0\0\0\272\0\0\0\242" + "\0\0\1\177\0\0\0[\0\0\0""5\0\0\0\26\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\23\0\0\0:\0\0\0l\0\0\0\234\0" + "\0\0\301\32\32;\337&&\200\362!!\276\374\31\31\340\377\24\24\350\377\22" + "\22\342\377\16\16\314\377\12\12\224\373\3\3=\354\0\0\0\316\0\0\0\251" + "\0\0\0y\0\0\0C\0\0\0\34\0\0\0\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\2\0\0\0\25\0\0\0;\1\1\2x\0\0\0\256\21\21*\336>>\267\372''\365\377" + "\13\13\376\377\1\1\373\377\0\0\366\376\0\0\363\376\0\0\364\376\0\0\367" + "\377\3\3\375\377\7\7\364\377\6\6\241\376\0\0\37\347\0\0\0\275\0\0\1\205" + "\0\0\0K\0\0\0\32\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\12\0\0\0/" + "\0\0\0n\0\0\0\262\31\31""2\345JJ\344\377\17\17\377\377\0\0\363\376\0" + "\0\362\377\0\0\364\377\0\0\364\377\0\0\362\377\0\0\362\377\0\0\361\377" + "\0\0\357\377\0\0\364\377\2\2\377\377\4\4\317\377\0\0)\362\0\0\0\277\0" + "\0\2\200\0\0\0;\0\0\0\20\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\4\0\0\0\6\0\0\0\11\0\0" + "\0\14\0\0\0\16\0\0\0\17\0\0\0\21\0\0\0\21\0\0\0\21\0\0\0\20\0\0\0\17" + "\0\0\0\16\0\0\0\15\0\0\0\11\0\0\0\7\0\0\0\5\0\0\0\4\0\0\0\3\0\0\0\1\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\10\0\0\0\14\0\0\0\20\0\0" + "\0\23\0\0\0\24\0\0\0\24\0\0\0\24\0\0\0\24\0\0\0\23\0\0\0\22\0\0\0\17" + "\0\0\0\12\0\0\0\6\0\0\0\3\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\2\0\0\0\30\0\0\1S\0\0\0\234\17\17!\336UU\342\377\7\7\372\376\0\0\361" + "\377\0\0\364\377\0\0\364\377\0\0\364\377\0\0\363\377\0\0\362\377\0\0" + "\361\377\0\0\362\377\0\0\361\377\0\0\362\377\0\0\357\377\0\0\373\376" + "\3\3\315\377\0\0\30\350\0\0\0\257\0\0\2c\0\0\0\"\0\0\0\4\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\6\0\0\0\17\0\0\0\34\0\0\0(\0\0" + "\0""8\0\0\0F\1\2\2J\3\3\4L\4\4\4P\4\4\4X\4\4\4]\4\4\4a\4\4\4_\4\4\4Z" + "\4\4\4T\4\4\4P\3\3\3M\2\2\3J\1\1\1H\0\0\1G\0\0\0=\0\0\0""0\0\0\0)\0\0" + "\0%\0\0\0\36\0\0\0\24\0\0\0\15\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\3\0\0\0\13\0\0\0\27\0\0\0%\0\0\0:\0\0\0F\3\3\3L\4\4\4[\5\5\5j\5" + "\5\5o\5\5\5q\5\5\5r\5\5\5p\4\4\4m\4\4\4d\3\3\3T\1\1\1J\0\0\0B\0\0\0""0" + "\0\0\0\40\0\0\0\22\0\0\0\7\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\10\0\0\0-\2\2\5y\0\0" + "\0\303GG\250\371\32\32\377\377\0\0\361\377\0\0\363\377\0\0\364\377\0" + "\0\364\377\0\0\364\377\0\0\364\377\0\0\363\377\0\0\362\377\0\0\362\377" + "\0\0\361\377\0\0\363\377\0\0\362\377\0\0\360\377\0\0\377\377\1\1\216" + "\375\0\0\0\322\0\0\3\206\0\0\0""8\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\4\0\0\0\22\0\0\0+\0\0\0I\0\0\0h\0\0\0\202\0\0\0\225\0\0\0\255" + "\0\0\0\266\0\0\0\265\0\0\0\266\0\0\0\267\0\0\0\272\0\0\0\273\0\0\0\273" + "\0\0\0\270\0\0\0\266\0\0\0\266\0\0\0\265\0\0\0\266\0\0\0\266\0\0\0\257" + "\0\0\0\233\0\0\0\216\0\0\0\214\0\0\0\204\0\0\0m\0\0\0R\0\0\0""3\0\0\0" + "\21\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\1\0\0\0\11\0\0\0\35\0\0\0:\0\0\0[\0\0\0z\0\0\0\227" + "\0\0\0\257\0\0\0\265\0\0\0\271\0\0\0\310\0\0\0\322\0\0\0\325\0\0\0\326" + "\0\0\0\324\0\0\0\313\0\0\0\277\0\0\0\267\0\0\0\264\0\0\0\245\0\0\0\213" + "\0\0\0o\0\0\0O\0\0\0/\0\0\0\24\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\15\0\0\0C\0\0\0\226\26\26" + "*\340FF\362\377\0\0\363\377\1\1\364\377\0\0\363\377\0\0\364\377\0\0\365" + "\377\0\0\365\377\0\0\364\377\0\0\363\377\0\0\363\377\0\0\362\377\0\0" + "\362\377\0\0\362\377\0\0\362\377\0\0\361\377\0\0\370\377\1\1\340\377" + "\0\0\36\352\0\0\0\242\0\0\0Q\0\0\0\25\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\12\0\0" + "\0\37\0\0\0J\1\1\1{\0\0\0\244\0\0\0\304\0\0\0\334\24\24\26\350012\362" + "JKM\371ghk\372qrt\372vwz\372z{~\372}~\201\372}~\201\372{|\177\372xy{" + "\372rsu\373abe\372STV\371BCD\370335\363\36\37\40\352\22\23\24\351\5\5" + "\6\351\1\1\1\336\0\0\0\314\0\0\0\247\0\0\0i\0\0\0%\0\0\0\2\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\2\0\0\0\1\0" + "\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\3\0\0\0\5\0\0\0\6\0" + "\0\0\6\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\6\0\0\0\5\0\0\0\4\0\0\0" + "\2\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0" + "\2\0\0\0\4\0\0\0\4\0\0\0\5\0\0\0\5\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\1\0" + "\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0" + "\21\0\0\0.\0\0\0a\3\3\3\216\0\0\0\265\0\0\0\324\24\24\25\350;;=\362e" + "fh\371\203\204\207\371\226\227\230\373\237\237\240\375\236\236\240\376" + "\236\237\240\376\231\233\234\375\212\213\216\373z|~\372abd\372779\370" + "\25\25\27\356\0\0\0\342\0\0\0\313\0\0\0\252\0\0\0\200\0\0\0L\0\0\0\36" + "\0\0\0\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\23\0\0\0U\0\0\0\25377v\361$$\377\377\0\0\361\377\0\0\366\377\0" + "\0\364\377\0\0\364\377\0\0\365\377\0\0\363\377\0\0\363\377\0\0\363\377" + "\0\0\362\377\0\0\362\377\0\0\362\377\0\0\362\377\0\0\362\377\0\0\362" + "\377\0\0\364\377\0\0\373\377\1\1b\371\0\0\0\275\0\0\2i\0\0\0!\0\0\0\2" + "\0\0\0\0\0\0\0\3\0\0\0\10\0\0\0\15\0\0\0\22\0\0\0\26\0\0\0\35\0\0\0\"" + "\0\0\0\"\0\0\0\35\0\0\0\25\0\0\0\17\0\0\0\7\0\0\0\2\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\6\0\0\0\40\0\0\0P\0\0\0\220\0\0\0\306\2\3\4\347hik\371" + "\301\302\306\376\350\351\352\377\367\370\372\377\367\371\374\377\360" + "\362\365\377\353\354\357\377\352\353\356\377\352\354\357\377\353\354" + "\357\377\353\355\357\377\354\355\360\377\353\355\360\377\354\355\360" + "\377\354\354\361\377\361\362\366\377\365\367\370\377\355\356\361\377" + "\345\346\351\377\333\335\337\377\311\313\316\377\223\225\230\377@@B\376" + "\0\0\0\317\0\0\0\177\0\0\0*\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0" + "\16\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\15\0\0\0\10\0\0\0\11\0" + "\0\0\23\0\0\0\35\0\0\0\40\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\40\0\0\0" + "\31\0\0\0\15\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1" + "\0\0\0\6\0\0\0\15\0\0\0\27\0\0\0\37\0\0\0$\0\0\0""1\0\0\0;\0\0\0\77\0" + "\0\0@\0\0\0A\0\0\0A\0\0\0\77\0\0\0=\0\0\0""7\0\0\0*\0\0\0!\0\0\0\32\0" + "\0\0\21\0\0\0\10\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\2\0\0\0\7\0\0\0\15\0\0\0\27\0\0\0\36\0\0\0\"\0\0\0#\0\0\0" + "'\0\0\0,\0\0\0""1\0\0\0""2\0\0\0-\0\0\0'\0\0\0#\0\0\0#\0\0\0\"\0\0\0" + "\40\0\0\0\36\0\0\0\31\0\0\0\21\0\0\0\14\0\0\0\11\0\0\0\20\0\0\0""3\1" + "\1\1m\0\0\0\253\0\0\0\33099;\361\256\257\261\375\351\351\352\377\377" + "\377\377\377\377\377\377\377\367\370\373\377\355\356\361\377\344\344" + "\347\377\341\342\344\377\337\341\343\377\341\341\343\377\342\344\346" + "\377\350\351\353\377\353\353\356\377\350\351\354\377\323\324\327\377" + "\225\225\231\377EFH\373\3\3\3\351\0\0\0\312\0\0\0\224\0\0\0P\0\0\0\33" + "\0\0\0\15\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0" + "\16\0\0\0\16\0\0\0\16\0\0\0\15\0\0\0\12\0\0\0\4\0\0\0\2\0\0\0\7\0\0\0" + "\13\0\0\0\15\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\16\0" + "\0\0\16\0\0\0\16\0\0\0\16\0\0\0\15\0\0\0\15\0\0\0\10\0\0\0\3\0\0\0\0" + "\0\0\0\0\0\0\0\1\0\0\0\30\0\0\0^\0\0\0\272>>\236\367\20\20\376\377\0" + "\0\363\377\0\0\365\377\0\0\364\377\0\0\363\377\0\0\364\377\0\0\363\377" + "\0\0\363\377\0\0\363\377\0\0\362\377\0\0\362\377\0\0\362\377\0\0\362" + "\377\0\0\361\377\0\0\362\377\0\0\363\377\0\0\376\377\0\0\223\377\0\0" + "\0\320\0\0\4{\0\0\0*\0\0\0\7\0\0\0\14\0\0\0\35\0\0\0""1\0\0\0B\0\0\0" + "P\0\0\0_\0\0\0j\0\0\0p\0\0\0q\0\0\0h\0\0\0V\0\0\0A\0\0\0+\0\0\0\26\0" + "\0\0\10\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\32\0\0\0S\0\0\0\226\0\0\0\320;;>\365" + "\344\345\347\377\375\376\377\377\321\323\326\377\261\264\270\377\243" + "\246\254\377\235\240\247\377\236\240\247\377\236\241\250\377\241\242" + "\251\377\242\244\252\377\242\245\254\377\243\245\253\377\242\245\252" + "\377\241\243\251\377\242\244\251\377\241\244\252\377\242\244\251\377" + "\242\245\252\377\246\250\255\377\254\256\262\377\264\266\271\377\304" + "\306\312\377\221\223\226\377!\"#\375\0\0\0\312\1\1\1|\0\0\0^\0\0\0a\0" + "\0\0b\0\0\0a\0\0\0a\0\0\0a\0\0\0a\0\0\0a\0\0\0b\0\0\0a\0\0\0Y\0\0\0>" + "\0\0\0B\0\0\0^\0\0\0w\0\0\0\207\0\0\0\215\0\0\0\214\0\0\0\214\0\0\0\215" + "\0\0\0\203\0\0\0l\0\0\0Q\0\0\0/\0\0\0\24\0\0\0\4\0\0\0\0\0\0\0\1\0\0" + "\0\12\0\0\0\34\0\0\0""6\0\0\0P\0\0\0h\0\0\0~\0\0\0\213\0\0\0\222\0\0" + "\0\237\0\0\0\250\0\0\0\256\0\0\0\261\0\0\0\256\0\0\0\251\0\0\0\244\0" + "\0\0\231\0\0\0\216\0\0\0\206\0\0\0r\0\0\0[\0\0\0B\0\0\0)\0\0\0\24\0\0" + "\0\6\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\23\0\0\0%\0\0\0=\0\0\0T\0\0\0h\0\0" + "\0|\0\0\0\211\0\0\0\215\0\0\0\214\0\0\0\216\0\0\0\222\0\0\0\222\0\0\0" + "\216\0\0\0\214\0\0\0\214\0\0\0\215\0\0\0\214\0\0\0\205\0\0\0{\0\0\0m" + "\0\0\0a\0\0\0\\\0\0\0R\0\0\0I\0\0\0q\0\0\0\264\2\2\3\343\234\235\237" + "\376\377\377\377\377\365\366\370\377\322\324\331\377\272\274\301\377" + "\256\261\267\377\253\255\262\377\250\253\260\377\247\251\256\377\245" + "\250\254\377\243\245\252\377\242\244\250\377\237\241\246\377\235\237" + "\243\377\235\237\242\377\241\243\247\377\260\261\265\377\306\310\313" + "\377\313\314\320\377~\177\202\377\26\26\27\367\0\0\0\317\1\1\1\215\0" + "\0\0Y\0\0\0`\0\0\0b\0\0\0a\0\0\0a\0\0\0a\0\0\0a\0\0\0a\0\0\0a\0\0\0b" + "\0\0\0a\0\0\0[\0\0\0E\0\0\0!\0\0\0\22\0\0\0""4\0\0\0V\0\0\0a\0\0\0a\0" + "\0\0a\0\0\0a\0\0\0a\0\0\0a\0\0\0a\0\0\0a\0\0\0a\0\0\0b\0\0\0a\0\0\0S" + "\0\0\0""0\0\0\0\20\0\0\0\2\0\0\0\0\0\0\0\1\0\0\0\31\0\0\0a\0\0\0\277" + "::\246\371\13\13\375\377\0\0\362\377\0\0\371\377\0\0\372\377\0\0\370" + "\377\0\0\367\377\0\0\364\377\0\0\362\377\0\0\363\377\0\0\362\377\0\0" + "\362\377\0\0\362\377\0\0\364\377\0\0\361\377\0\0\362\377\0\0\363\377" + "\0\0\377\377\1\1\243\377\0\0\0\324\0\0\3\205\0\0\0""6\0\0\0!\0\0\0;\0" + "\0\0b\0\0\0\207\0\0\0\243\0\0\0\262\0\6\6\301\21\13\12\317%\14\13\325" + "\34\7\7\326\10\1\1\314\0\0\0\264\0\0\0\234\0\0\0z\0\0\0T\0\0\0/\0\0\0" + "\24\0\0\0\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\16\0\0\0""9\1\1\2\207\0\0\0\31278:\366\377\377\377\377\330" + "\331\334\376\227\232\241\377\227\231\240\377\237\242\250\377\245\250" + "\256\377\250\253\261\377\252\255\263\377\253\256\263\377\253\256\263" + "\377\255\257\264\377\255\257\264\377\254\256\263\377\254\257\263\377" + "\253\255\262\377\254\256\263\377\252\254\261\377\251\253\257\377\250" + "\251\255\377\246\250\254\377\244\246\252\377\243\245\251\377\247\250" + "\254\377`ad\377\14\14\15\364\0\0\0\264\1\1\1\230\0\0\0\303\0\0\0\315" + "\0\0\0\314\0\0\0\314\0\0\0\314\0\0\0\314\0\0\0\314\0\0\0\314\0\0\0\315" + "\0\0\0\315\0\0\0\273\0\0\0\216\0\0\0\234\0\0\0\274\0\0\0\317\0\0\0\340" + "\14\15\15\351\17\21\22\351\16\16\17\351\3\4\5\351\0\0\0\332\0\0\0\306" + "\0\0\0\250\0\0\0{\0\0\0H\0\0\0\31\0\0\0\4\0\0\0\22\0\0\0""0\0\0\0\\\0" + "\0\0\210\0\0\0\256\0\0\0\311\0\0\0\324\3\3\4\345\23\24\25\350))*\352" + "012\356557\361:<=\364668\362.//\355((*\354\27\27\30\351\4\5\6\350\0\0" + "\0\335\0\0\0\316\0\0\0\275\0\0\0\235\0\0\0y\0\0\0L\0\0\0\40\0\0\0\7\0" + "\0\0\11\0\0\0\40\0\0\0H\1\1\1p\0\0\0\227\0\0\0\265\0\0\0\311\0\0\0\323" + "\0\0\0\341\15\16\16\351\22\22\23\350\31\32\33\351\35\36\37\351\36\37" + "!\351\32\32\34\351\26\25\30\350\20\20\21\351\12\13\14\351\2\2\3\347\0" + "\0\0\333\0\0\0\322\0\0\0\314\0\0\0\315\0\0\0\302\0\0\0\257\0\0\0\222" + "\0\0\0\254\0\0\0\344\275\275\300\376\377\377\377\377\312\314\321\377" + "\263\265\274\377\261\263\271\377\262\264\271\377\262\264\271\377\261" + "\263\270\377\256\260\265\377\254\256\262\377\253\255\261\377\251\252" + "\257\377\246\250\254\377\245\247\253\377\244\246\251\377\242\243\250" + "\377\243\244\250\377\240\241\245\377\235\236\242\377\246\250\254\377" + "\263\265\272\377nor\377\14\14\14\357\0\0\0\270\0\0\0\254\0\0\0\312\0" + "\0\0\314\0\0\0\314\0\0\0\314\0\0\0\314\0\0\0\314\0\0\0\314\0\0\0\314" + "\0\0\0\315\0\0\0\315\0\0\0\277\0\0\0\220\0\0\0G\0\0\0""4\0\0\0y\0\0\0" + "\263\0\0\0\313\0\0\0\314\0\0\0\314\0\0\0\314\0\0\0\314\0\0\0\314\0\0" + "\0\314\0\0\0\314\0\0\0\314\0\0\0\315\1\1\1\315\0\0\0\260\0\0\0e\0\0\0" + "\37\0\0\0\4\0\0\0\0\0\0\0\1\0\0\0\27\0\0\0b\0\0\0\30333\244\373\22\22" + "\377\377\0\0\376\377\0\0\350\377\1\1\325\377\1\1\325\377\3\3\352\377" + "\2\2\374\377\0\0\374\377\0\0\362\377\0\0\362\377\0\0\362\377\0\0\361" + "\377\0\0\363\377\0\0\361\377\0\0\361\377\0\0\362\377\0\0\377\377\0\0" + "\227\377\0\0\0\325\0\0\4\205\0\0\0I\0\0\0T\0\0\0\202\0\0\0\256\20\13" + "\13\324j-+\356\2431.\371\304($\375\335$!\377\350\35\31\377\346\33\27" + "\377\315\30\24\377\222\22\17\367:\6\5\347\0\0\0\306\0\0\0\236\1\0\0q" + "\0\0\0\77\0\0\0\30\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\3\0\0\0!\0\0\0d\0\0\0\265\11\12\13\353\353\354\356\377\332" + "\334\336\376\223\225\234\377\241\243\251\377\245\247\255\377\247\252" + "\260\377\251\253\261\377\253\256\263\377\254\256\264\377\254\257\265" + "\377\254\256\263\377\255\257\264\377\254\257\264\377\253\255\262\377" + "\253\255\262\377\252\254\261\377\251\253\261\377\247\252\256\377\246" + "\250\254\377\244\246\252\377\245\247\253\377\246\250\253\377\251\252" + "\257\377\241\243\247\377DEG\377\0\0\0\345\2\2\2\247\0\0\0\273MNO\365" + "\264\265\266\377\231\232\234\376\233\234\235\376\233\234\237\376\233" + "\235\236\376\235\236\237\376\236\237\241\376\230\230\233\376bcf\377\15" + "\15\16\347\0\0\0\313\4\4\6\345efi\367\261\261\263\376\330\331\332\377" + "\354\354\356\377\353\354\356\377\347\350\353\377\325\327\333\377\240" + "\242\246\377GHK\373\5\6\6\351\0\0\0\303\0\0\0\207\0\0\0;\0\0\0\31\0\0" + "\0B\0\0\0z\0\0\0\253\0\0\0\330./1\360\214\215\217\374\302\302\304\377" + "\340\341\343\377\357\360\361\377\367\370\372\377\366\367\371\377\365" + "\366\370\377\364\366\367\377\364\365\367\377\362\363\365\377\354\355" + "\357\377\337\340\343\377\316\317\322\377\254\255\257\377pps\376112\370" + "\2\2\2\346\0\0\0\312\0\0\0\236\0\0\0]\0\0\0%\0\0\0(\0\0\0^\0\0\0\235" + "\0\0\0\305\1\1\3\343SSU\365\226\227\231\375\301\302\303\377\333\333\335" + "\377\354\355\356\377\355\356\360\377\360\362\364\377\363\364\367\377" + "\363\365\370\377\362\363\367\377\360\361\364\377\354\355\357\377\344" + "\345\347\377\332\332\335\377\315\316\320\377\272\274\277\377\241\242" + "\246\377\216\220\222\376bdf\372002\360\0\0\0\301\0\0\0\323\217\220\223" + "\375\377\377\377\377\304\306\314\377\261\262\271\377\266\267\274\377" + "\263\265\272\377\261\263\270\377\257\261\266\377\254\256\263\377\254" + "\257\263\377\261\262\267\377\255\257\263\377\254\256\262\377\254\256" + "\261\377\242\244\251\377\241\242\246\377\240\242\246\377\241\242\247" + "\377\243\244\250\377\243\244\250\377\240\242\247\377\250\251\256\377" + "\235\236\242\377;;>\376\0\0\0\326\0\0\0\324\200\200\201\375\267\270\271" + "\376\226\227\231\376\230\231\233\376\230\231\233\376\230\230\233\376" + "\230\231\233\376\230\231\234\376\227\232\235\376qrw\377\31\30\32\364" + "\0\0\0\273\0\0\0e\0\0\0h\0\0\0\261\0\1\2\347\233\234\240\376\240\241" + "\244\376\231\232\235\376\231\233\235\376\230\232\235\376\231\232\234" + "\376\230\231\234\376\230\232\235\376\236\237\243\376}~\202\377ABD\377" + "\0\0\0\332\1\1\1~\0\0\0&\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\25\0\0\0b\0\0" + "\0\301\31\31~\371\23\23\316\377\0\0f\374\0\0""4\355\0\0\31\336\1\1\35" + "\334\1\1""1\345\5\5r\367\11\11\317\377\5\5\373\377\0\0\363\377\0\0\361" + "\377\0\0\362\377\0\0\363\377\0\0\362\377\0\0\361\377\0\0\363\377\0\0" + "\377\377\0\0k\377\0\0\0\315\0\0\2\206\0\0\0o\0\0\0\224\0\0\0\305f20\357" + "\337GC\377\377!\36\377\377\10\7\377\377\1\0\377\377\0\0\377\376\0\0\377" + "\375\0\0\377\377\2\0\377\377\10\4\377\370\16\12\377\245\15\13\374\40" + "\1\1\343\0\0\0\264\1\0\0\177\0\0\0F\0\0\0\31\0\0\0\5\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\11\0\0\0""9\0\0\0\211\0\0\0\323\214\216" + "\221\374\374\374\376\377\235\237\246\377\244\246\254\377\246\251\257" + "\377\250\252\261\377\253\255\264\377\253\256\265\377\255\260\265\377" + "\256\260\266\377\254\257\264\377\257\261\267\377\262\264\272\377\263" + "\265\272\377\262\264\271\377\262\263\270\377\257\261\265\377\256\260" + "\265\377\254\256\262\377\253\255\261\377\251\253\257\377\247\251\255" + "\377\245\250\253\377\255\256\263\377\214\215\220\377&'(\377\0\0\0\322" + "\6\6\6\242\0\0\0\322\250\251\252\375\377\377\377\376\340\342\344\377" + "\343\344\347\377\343\344\347\377\344\345\350\377\344\345\350\377\350" + "\350\353\377\322\324\330\377^_b\376\0\0\0\354QQS\365\350\350\351\377" + "\377\377\377\377\355\357\361\377\322\323\330\376\303\305\313\377\276" + "\301\307\377\277\302\307\377\306\311\316\376\332\334\341\377\305\307" + "\314\377klp\377\11\11\11\352\0\0\0\264\0\0\0b\0\0\0@\0\0\0~\0\0\0\272" + "\4\5\5\343\236\237\241\374\377\377\377\377\367\370\372\377\330\332\335" + "\376\300\302\306\376\264\265\272\377\251\253\260\377\246\247\253\377" + "\243\245\251\377\242\244\251\377\241\242\247\377\240\242\246\377\243" + "\244\250\377\251\252\256\377\262\264\270\377\302\304\307\376\323\324" + "\330\377\314\316\321\377\204\206\211\377&&'\371\0\0\0\332\1\1\1\241\0" + "\0\0X\0\0\0b\0\0\0\246\0\0\0\332TUV\367\343\344\346\377\377\377\377\377" + "\367\370\372\377\340\342\346\376\321\322\327\376\307\312\317\377\304" + "\306\314\377\303\306\314\377\303\306\314\377\304\307\315\377\306\310" + "\317\377\306\310\317\377\310\312\321\377\314\317\326\377\323\326\333" + "\377\331\334\340\376\340\342\350\376\350\352\356\377\365\367\374\377" + "\251\253\260\377..1\371\0\0\0\326**,\357\377\377\377\377\324\326\332" + "\377\257\262\270\377\265\267\275\377\262\263\271\377\260\262\267\377" + "\256\260\264\377\253\256\262\377\256\260\264\377\243\244\250\377vwy\377" + "[\\^\377bbe\377\207\210\213\377\254\256\262\377\240\242\246\377\241\242" + "\246\377\241\242\250\377\242\244\251\377\242\244\251\377\244\246\251" + "\377\243\245\252\377\253\256\262\377_`c\377\6\6\6\347\0\0\0\311689\362" + "\372\373\375\377\351\352\355\376\335\337\342\377\336\340\344\377\336" + "\340\344\377\337\340\345\377\336\337\344\377\345\347\354\377\262\264" + "\272\37778:\377\0\0\0\317\1\1\1\212\0\0\0\243\0\0\0\336\240\241\245\375" + "\377\377\377\377\343\345\351\377\337\341\345\377\337\340\344\377\336" + "\340\344\377\336\341\344\377\336\340\344\377\337\340\346\377\266\270" + "\275\377MNQ\377\10\10\11\357\0\0\0\302\0\0\0p\0\0\0\"\0\0\0\4\0\0\0\0" + "\0\0\0\0\0\0\0\20\0\0\0P\0\0\0\236\0\0\27\322\0\0\35\336\0\0\0\301\0" + "\0\0\237\0\0\0\203\0\0\0\200\0\0\0\223\0\0\0\264\0\0\30\332\16\16\227" + "\372\13\13\371\377\0\0\361\377\0\0\362\377\0\0\362\377\0\0\362\377\0" + "\0\361\377\0\0\370\377\0\0\344\377\0\0*\364\0\0\0\272\0\0\0\221\0\0\0" + "\235\3\0\0\312\230HF\367\37753\377\376\1\0\377\367\0\0\377\371\2\0\377" + "\371\3\0\377\371\3\0\377\371\3\0\377\371\3\0\377\371\3\0\377\370\2\0" + "\377\373\1\0\376\377\6\2\377\327\13\7\3776\2\2\354\0\0\0\270\2\0\0~\0" + "\0\0>\0\0\0\22\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\22\0\0\0" + "P\0\0\0\250\21\21\23\352\352\353\355\377\312\314\320\377\235\240\247" + "\377\251\254\262\377\253\255\263\377\254\257\265\377\257\261\270\377" + "\260\262\270\377\257\262\270\377\260\263\270\377\266\271\277\377\252" + "\255\262\377\225\227\234\377\210\212\215\377\205\206\211\377\204\205" + "\211\377\202\204\207\377\202\203\206\377\200\201\204\377\205\205\210" + "\377\220\221\225\377\231\232\236\377\240\242\245\377\254\255\261\377" + "ijm\377\20\20\21\372\0\0\0\275\3\3\3\251\2\2\3\346\351\351\353\377\320" + "\322\325\377\241\243\251\377\250\252\257\377\250\253\260\377\251\253" + "\260\377\252\254\262\377\255\260\265\377\252\254\262\3779:<\374hhh\371" + "\377\377\377\377\351\352\354\377\266\270\277\377\254\257\266\377\256" + "\261\267\377\257\262\270\377\257\262\270\377\257\262\270\377\254\260" + "\266\377\250\253\262\377\270\273\301\377\240\242\247\37789;\375\0\0\0" + "\326\2\2\2~\1\1\1s\0\0\0\270\13\14\14\347\324\324\326\377\377\377\377" + "\377\300\301\306\377\243\245\253\377\243\245\252\377\245\247\254\377" + "\246\250\255\377\246\250\254\377\250\250\255\377\252\253\260\377\253" + "\255\261\377\253\255\260\377\246\250\254\377\242\244\247\377\237\241" + "\245\377\235\237\243\377\232\234\240\377\230\232\236\377\245\247\253" + "\377\274\275\301\377\215\217\222\377\40!\"\372\0\0\0\312\1\1\1\205\3" + "\3\3\230\0\0\0\330vwy\373\377\377\377\377\337\341\343\377\267\272\300" + "\377\255\261\270\377\257\261\270\377\263\266\274\377\266\270\300\377" + "\267\271\301\377\267\272\301\377\270\273\303\377\271\274\305\377\271" + "\274\304\377\271\274\304\377\273\275\305\377\270\274\303\377\267\272" + "\303\377\271\273\302\377\266\271\300\377\264\266\276\377\275\277\307" + "\377dfi\377\12\12\12\356\0\0\0\333\237\241\243\374\376\376\377\377\263" + "\265\274\377\262\265\272\377\261\262\270\377\256\260\266\377\255\257" + "\263\377\253\255\261\377\256\257\263\377\235\236\243\377DEF\377\16\15" + "\16\371\3\3\3\356\3\3\3\353\14\15\15\362\202\203\206\376\301\303\307" + "\377\236\236\242\377\243\244\251\377\242\245\251\377\243\246\251\377" + "\244\246\252\377\244\246\253\377\256\260\266\377rsv\377\17\17\17\353" + "\0\0\0\272\0\0\0\340\220\222\226\377\321\323\331\377\231\234\243\377" + "\241\243\252\377\240\243\251\377\240\243\252\377\240\244\252\377\243" + "\245\255\377\247\252\260\377WY\\\377\0\0\0\342\2\2\2\261\0\0\0\320tu" + "y\373\377\377\377\377\273\275\303\377\236\241\250\377\240\243\253\377" + "\237\243\251\377\240\242\252\377\236\241\250\377\253\255\265\377\212" + "\214\221\377567\377\0\0\0\355\0\0\0\300\0\0\0\203\0\0\0A\0\0\0\23\0\0" + "\0\2\0\0\0\0\0\0\0\0\0\0\0\11\0\0\0/\0\0\0`\0\0\0\203\0\0\0\212\0\0\3" + "s\0\0\2K\0\0\2""0\0\0\2+\0\0\2A\0\0\3i\0\0\0\231\0\0\0\316\30\30\232" + "\372\14\14\376\377\0\0\361\377\0\0\361\377\0\0\362\377\0\0\361\377\0" + "\0\377\377\0\0\211\377\0\0\0\335\0\0\2\252\0\0\0\241\0\0\0\307\215HE" + "\366\3770-\377\370\0\0\377\371\3\0\377\372\3\0\377\372\3\0\377\371\2" + "\0\377\372\3\0\377\373\2\0\377\372\2\0\377\372\3\0\377\372\3\0\377\372" + "\3\0\377\371\2\0\377\377\3\0\377\330\10\5\377$\0\1\352\0\0\0\263\2\0" + "\0j\0\0\0)\0\0\0\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\32\2\2\2h\0" + "\0\0\274OPR\365\377\377\377\377\253\256\264\377\250\253\262\377\254\257" + "\264\377\256\261\266\377\260\262\271\377\262\263\272\377\261\263\271" + "\377\261\263\271\377\267\271\276\377\177\201\205\3779;<\375!\"\"\372" + "\31\31\32\362\25\25\26\355\24\24\25\356\22\22\23\356\23\22\24\356\23" + "\24\24\356\31\31\31\362\"\"#\371,,-\375;;<\375IKM\377<=>\377\5\5\6\353" + "\0\0\0\256\0\0\0\271BCE\365\377\377\377\377\271\273\300\377\256\260\265" + "\377\260\262\267\377\262\263\271\377\262\264\272\377\262\265\272\377" + "\263\264\272\377\271\273\301\377\204\205\210\375\377\377\377\377\326" + "\327\334\377\260\262\271\377\263\266\274\377\265\270\277\377\264\267" + "\275\377\261\264\272\377\261\264\272\377\260\262\271\377\261\263\272" + "\377\261\264\272\377\262\264\272\377\245\250\254\377CDF\377\0\0\0\334" + "\0\0\0\217\0\0\0\250\0\0\0\345\304\304\306\376\376\377\377\377\256\260" + "\265\377\246\250\254\377\254\255\261\377\253\254\261\377\253\255\260" + "\377\250\252\256\377\254\255\262\377\253\254\261\377\234\235\240\377" + "\221\223\225\377\217\221\224\377\231\233\237\377\252\253\260\377\242" + "\244\250\377\241\243\246\377\242\244\250\377\242\243\247\377\240\242" + "\246\377\241\243\250\377\253\254\260\377XY\\\377\2\2\3\345\0\0\0\255" + "\0\0\0\303CCF\365\377\377\377\377\322\323\327\377\253\256\265\377\263" + "\266\274\377\267\272\300\377\267\272\301\377\271\273\303\377\271\274" + "\303\377\271\274\304\377\272\275\305\377\301\304\313\377\300\302\312" + "\377\302\304\314\377\303\306\316\377\302\306\315\377\302\305\315\377" + "\302\305\314\377\302\305\314\377\300\303\312\377\302\305\313\377\264" + "\265\273\377CEG\377\0\0\0\344\10\11\11\344\342\342\344\377\336\337\342" + "\377\255\260\265\377\260\262\267\377\256\257\263\377\254\256\263\377" + "\253\254\260\377\251\253\257\377\252\253\257\377WXZ\377\7\7\10\363\0" + "\0\0\306\0\0\0\236\0\0\0\227\0\0\0\30489;\367\355\355\360\377\240\242" + "\246\377\244\246\252\377\243\246\252\377\244\246\253\377\246\246\254" + "\377\244\247\253\377\257\260\266\377sux\377\25\25\26\363\0\0\0\274\0" + "\0\0\310@BD\372\340\342\347\377\257\262\270\377\252\254\262\377\252\254" + "\263\377\253\255\264\377\252\254\263\377\251\255\263\377\257\262\272" + "\377y{\200\377\25\25\26\360\0\0\0\323FGI\363\377\377\377\377\312\315" + "\321\377\243\246\255\377\252\254\262\377\251\253\262\377\251\253\262" + "\377\250\252\261\377\257\262\271\377\225\230\234\377<=\77\377\5\5\6\364" + "\0\0\0\310\0\0\0\212\0\0\0G\0\0\0\31\0\0\0\6\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\1\0\0\0\16\0\0\0\40\0\0\2.\0\0\3""1\0\0\0(\0\0\0\24\0\0\0\7\0" + "\0\0\6\0\0\0\20\0\0\0)\0\0\2\\\0\0\0\230\5\5\25\331&&\332\377\0\0\367" + "\377\0\0\362\377\0\0\362\377\0\0\375\377\0\0\304\377\0\0\30\353\0\0\0" + "\272\0\0\1\240\0\0\0\264I(&\352\376GD\377\371\0\0\376\372\5\2\377\372" + "\3\0\377\372\3\0\377\373\2\0\377\372\3\0\377\372\2\0\377\372\3\0\377" + "\372\3\0\377\372\3\0\377\372\3\0\377\372\2\0\377\373\3\0\377\370\3\0" + "\377\377\4\0\377\250\6\3\377\0\0\0\330\2\0\0\217\0\0\0B\0\0\0\16\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\37\4\5\5w\0\0\0\321\211\212\214\374" + "\373\373\376\377\244\250\257\377\256\261\267\377\257\262\270\377\261" + "\262\270\377\262\264\272\377\262\266\273\377\262\265\272\377\264\267" + "\274\377\260\261\266\377//1\373\0\0\0\341\0\0\0\325\0\0\0\314\0\0\0\303" + "\0\0\0\304\0\0\0\303\0\0\0\301\0\0\0\274\0\0\0\274\0\0\0\305\0\0\0\304" + "\0\0\0\312\0\0\0\336\5\5\5\346\0\0\0\310\0\0\0\234\0\0\0\316\210\212" + "\214\374\374\374\376\377\253\254\263\377\260\262\267\377\257\261\267" + "\377\261\262\270\377\261\263\271\377\262\265\273\377\264\266\274\377" + "\261\263\272\377\301\304\311\377\304\307\315\377\257\261\271\377\264" + "\267\275\377\264\267\275\377\264\266\276\377\263\266\274\377\262\265" + "\274\377\261\263\273\377\260\263\272\377\260\262\270\377\260\263\271" + "\377\261\264\272\377\245\247\254\377CCE\377\2\2\2\332\1\1\1\243\0\0\0" + "\321\200\200\203\374\377\377\377\377\265\267\273\377\250\252\257\377" + "\254\255\261\377\252\253\260\377\252\254\261\377\251\253\257\377\260" + "\262\265\377\234\236\241\377Y[\\\377,,.\377\35\35\35\370\31\31\33\367" + "%&&\372mnq\377\271\272\276\377\240\242\247\377\242\244\251\377\242\244" + "\250\377\243\245\251\377\242\244\252\377\256\260\265\377sty\377\17\17" + "\20\361\0\0\0\277\0\0\0\336\314\314\315\377\361\362\364\377\255\260\267" + "\377\265\267\276\377\266\271\300\377\266\271\300\377\270\272\301\377" + "\270\273\302\377\271\274\303\377\275\301\310\377\276\301\311\377\251" + "\254\263\377\236\240\246\377\224\226\234\377\211\213\221\377\215\217" + "\224\377\227\232\240\377\240\243\250\377\245\250\255\377\260\262\270" + "\377\266\270\276\377\211\213\220\377&&(\374\0\0\0\332**,\355\367\366" + "\367\377\307\310\314\377\254\256\263\377\256\257\264\377\252\254\260" + "\377\250\252\257\377\246\251\255\377\253\254\260\377\226\227\233\377" + "001\377\0\0\0\333\2\2\2\216\0\0\0K\0\0\0f\0\0\0\2679:<\366\374\375\375" + "\377\243\245\251\377\243\246\252\377\245\247\254\377\246\250\255\377" + "\246\251\256\377\246\250\256\377\260\262\270\377vw{\377\25\26\26\365" + "\0\0\0\272\1\1\1\257\3\3\4\353\266\271\276\377\313\315\323\377\245\247" + "\256\377\252\255\264\377\251\254\262\377\250\253\262\377\250\252\262" + "\377\255\261\270\377\234\237\245\377)*,\370\7\6\7\355\367\370\370\377" + "\337\340\344\377\241\244\253\377\250\253\261\377\247\251\260\377\247" + "\251\260\377\247\251\260\377\261\264\272\377\224\227\234\377>\77A\377" + "\5\5\6\362\0\0\0\314\0\0\0\217\0\0\0N\0\0\0\33\0\0\0\5\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\2\0\0\0\5\0\0\0\6\0\0\0\10\0\0\0\12\0\0\0\13\0\0\0\12" + "\0\0\0\7\0\0\0\5\0\0\0\3\0\0\0\2\0\0\0\11\0\0\0+\0\0\0j\0\0\0\270''\217" + "\366\16\16\377\377\0\0\370\377\0\0\377\377\0\0\277\377\0\0&\365\0\0\0" + "\303\0\0\1\227\0\0\0\234\0\0\0\314\274NK\374\377\13\11\377\371\2\0\377" + "\373\3\0\377\372\3\0\377\372\2\0\377\373\3\0\377\372\2\0\377\372\3\0" + "\377\372\2\0\377\372\2\0\377\372\2\0\377\372\3\0\377\373\2\0\377\372" + "\3\0\377\372\3\0\377\375\2\0\377\362\6\1\3779\2\1\361\0\0\0\253\1\0\0" + "U\0\0\0\26\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\37\6\6\6y\0\0\0\326" + "\237\240\243\376\355\356\360\377\250\253\261\377\261\264\272\377\262" + "\265\273\377\262\266\274\377\263\266\273\377\264\267\274\377\262\265" + "\273\377\262\265\271\377\273\275\302\377\202\204\206\376>>@\36589:\363" + "678\362678\362567\363567\363223\360%&'\352\21\21\21\344\0\0\0\332\0\0" + "\0\307\1\1\1\254\1\1\1\221\0\0\0\204\0\0\0v\0\0\0\233\0\1\1\343\316\316" + "\317\377\341\343\346\377\252\254\262\377\262\264\272\377\261\262\271" + "\377\263\264\272\377\262\265\273\377\264\266\274\377\264\266\275\377" + "\265\270\276\377\264\267\275\377\263\266\273\377\265\270\275\377\264" + "\267\275\377\264\266\275\377\265\270\275\377\263\267\275\377\263\266" + "\274\377\261\264\272\377\262\263\272\377\261\262\272\377\260\262\267" + "\377\264\265\273\377\234\236\243\377356\377\0\0\0\327\0\0\0\274\26\27" + "\30\355\376\376\377\377\320\321\324\377\247\250\255\377\255\256\263\377" + "\253\254\261\377\252\254\260\377\252\254\257\377\253\255\261\377\240" + "\242\245\377DDF\377\6\6\7\357\0\0\0\323\0\0\0\267\0\0\0\255\0\0\0\302" + "\0\0\0\350\262\263\266\377\301\302\306\377\237\241\245\377\244\246\253" + "\377\245\247\254\377\246\250\255\377\260\263\267\377tvy\377\22\23\23" + "\361\0\0\0\314679\357\377\377\377\377\305\307\314\377\261\264\273\377" + "\266\271\300\377\267\272\300\377\267\272\301\377\270\273\302\377\272" + "\275\304\377\273\277\306\377\264\266\275\377_`d\377+,.\371\37\40!\367" + "\33\34\35\367\31\31\32\365\33\34\34\365\37\37!\367!\"#\367*+,\370679" + "\371>\77A\376>>@\377\20\21\21\363\0\0\0\313569\355\372\373\374\377\271" + "\273\277\377\253\255\261\377\252\254\261\377\250\251\256\377\246\247" + "\253\377\243\246\252\377\251\253\257\377\221\223\226\377))*\377\0\0\0" + "\324\2\2\2}\0\0\0b\2\2\2\232\0\0\0\322\224\224\226\374\366\367\371\377" + "\236\240\245\377\247\252\256\377\247\251\256\377\246\250\256\377\247" + "\252\257\377\246\251\257\377\262\264\273\377stx\377\17\17\20\357\0\0" + "\0\253\2\2\2\221\0\0\0\323dfj\375\347\350\357\377\246\250\260\377\252" + "\255\265\377\251\254\263\377\250\253\262\377\251\253\263\377\250\253" + "\262\377\265\270\277\377\210\212\216\375\272\271\270\375\367\370\371" + "\377\245\247\257\377\250\252\261\377\250\252\261\377\250\252\260\377" + "\250\252\261\377\261\263\271\377\232\235\241\377@AC\377\7\7\7\362\0\0" + "\0\303\0\0\0\213\0\0\0I\0\0\0\32\0\0\0\6\0\0\0\5\0\0\0\14\0\0\0\30\0" + "\0\0$\0\0\0/\0\0\0=\0\0\0H\0\0\0N\0\0\0N\0\0\0N\0\0\0O\0\0\0K\0\0\0C" + "\0\0\0""5\0\0\0(\0\0\0\35\0\0\0$\0\0\0P\0\0\0\237\36\36O\351$$\377\377" + "\0\0\342\377\0\0\211\377\0\0\27\350\0\0\0\300\0\0\2\217\0\0\0t\0\0\0" + "\242#\25\25\341\366C@\377\371\0\0\376\372\3\0\377\372\2\0\377\372\2\0" + "\377\372\3\0\377\372\2\0\377\371\3\0\377\373\2\0\377\371\3\0\377\371" + "\3\0\377\373\3\0\377\372\2\0\377\371\3\0\377\372\2\0\377\371\3\0\377" + "\373\3\0\377\377\4\0\377s\2\1\374\0\0\0\300\2\0\0m\0\0\0!\0\0\0\2\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\37\5\5\6y\0\0\0\326\232\232\236\377\360\362" + "\363\377\252\255\263\377\265\267\275\377\264\267\275\377\264\267\275" + "\377\265\267\274\377\264\267\275\377\264\266\274\377\264\265\272\377" + "\261\263\267\377\311\313\321\377\354\355\361\377\366\370\372\377\370" + "\371\372\377\366\367\371\377\366\367\371\377\366\367\371\377\362\364" + "\365\377\346\347\352\377\314\315\320\377\215\216\222\377457\375\0\0\0" + "\336\0\0\0\252\0\0\0b\0\0\0Y\0\0\0\263##%\360\377\377\377\377\301\303" + "\307\377\255\257\265\377\262\265\272\377\262\265\273\377\262\266\273" + "\377\263\266\275\377\265\270\276\377\265\270\276\377\273\275\303\377" + "\277\302\311\377\277\302\311\377\277\302\310\377\267\271\277\377\263" + "\265\273\377\265\270\275\377\263\265\274\377\262\265\273\377\262\264" + "\273\377\263\265\273\377\261\262\271\377\260\263\270\377\266\267\276" + "\377\210\212\216\377\37\37!\373\0\0\0\307\0\0\0\316\215\216\222\374\377" + "\377\377\377\253\255\262\377\254\255\262\377\253\255\261\377\253\255" + "\262\377\253\255\260\377\251\252\257\377\260\262\266\377z{~\377\2\3\3" + "\366\0\0\0\327\0\0\0\304\0\0\0\275\0\0\0\272\0\0\0\300\0\0\0\335\277" + "\277\277\376\326\330\333\377\235\237\244\377\246\250\256\377\246\250" + "\256\377\247\251\256\377\260\263\267\377cdg\377\13\14\13\357\0\0\0\327" + "tvy\372\377\377\377\377\261\264\273\377\266\270\277\377\266\271\300\377" + "\267\273\301\377\271\274\303\377\273\275\304\377\272\275\305\377\302" + "\305\315\377\232\234\242\377\13\14\15\365\0\0\0\333\0\0\0\327\0\0\0\330" + "\0\0\0\327\0\0\0\326\0\0\0\330\0\0\0\330\0\0\0\323\0\0\0\310\0\0\0\321" + "\0\0\0\331\0\0\0\312\0\0\0\270113\356\370\371\372\377\264\266\272\377" + "\247\251\256\377\250\252\255\377\245\247\252\377\244\245\251\377\242" + "\243\247\377\242\244\250\377\243\245\251\377OPR\377\0\0\0\343\0\0\0\276" + "\0\0\0\276\0\0\0\326WXY\365\377\377\377\377\272\274\300\377\243\245\251" + "\377\247\252\257\377\250\252\260\377\251\253\260\377\251\253\260\377" + "\251\253\261\377\262\264\272\377ddh\377\11\11\11\355\0\0\0\240\0\0\0" + "v\0\0\0\270\34\34\36\363\321\323\331\377\275\300\307\377\246\251\260" + "\377\252\255\263\377\251\254\262\377\250\253\262\377\250\253\262\377" + "\247\251\260\377\277\302\311\377\321\323\331\377\251\253\262\377\246" + "\251\257\377\250\252\260\377\250\251\260\377\250\253\261\377\262\264" + "\272\377\240\243\250\377EFH\377\10\10\10\366\0\0\0\320\0\0\0\221\0\0" + "\0O\0\0\0\34\0\0\0\12\0\0\0\23\0\0\0)\0\0\0C\0\0\0`\0\0\0|\0\0\0\223" + "\0\0\0\235\0\0\0\256\0\0\0\272\0\0\0\274\0\0\0\274\0\0\0\274\0\0\0\264" + "\0\0\0\243\0\0\0\226\0\0\0\210\0\0\0k\0\0\0V\0\0\0b\0\0\0\233\11\11""6" + "\336\16\16\207\377\0\0/\364\0\0\0\326\0\0\0\251\0\0\1}\0\0\0T\0\0\0Z" + "\0\0\0\242P%#\353\377,)\377\370\0\0\377\375\3\0\377\375\2\0\377\372\2" + "\0\377\371\3\0\377\372\2\0\377\372\2\0\377\371\2\0\377\373\3\0\377\371" + "\2\0\377\373\3\0\377\373\2\0\377\372\3\0\377\372\3\0\377\372\2\0\377" + "\372\3\0\377\377\3\0\377\240\3\1\377\0\0\0\321\3\0\0\200\0\0\0(\0\0\0" + "\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\36\3\3\3v\0\0\0\317deh\374\363\365\371" + "\377\266\270\276\377\265\267\275\377\266\270\276\377\265\270\275\377" + "\266\267\274\377\264\267\274\377\264\266\273\377\263\265\272\377\261" + "\263\267\377\254\255\262\377\251\253\260\377\252\254\261\377\250\252" + "\256\377\245\247\254\377\245\246\252\377\244\246\251\377\244\246\252" + "\377\251\252\256\377\267\270\274\377\312\313\317\377\247\250\254\377" + "\77@B\375\0\0\0\335\1\1\1\222\0\0\0z\0\0\0\310opq\372\377\377\377\377" + "\256\260\266\377\261\264\272\377\263\265\273\377\263\267\275\377\264" + "\266\275\377\266\270\277\377\266\271\300\377\275\277\306\377\250\252" + "\261\377z|\200\377gil\377\210\211\216\377\276\300\306\377\267\272\300" + "\377\263\267\275\377\263\266\274\377\264\266\273\377\262\264\273\377" + "\262\264\272\377\261\263\271\377\261\263\271\377\265\267\275\377jkn\377" + "\13\13\13\360\0\0\0\304\11\12\12\344\343\344\345\377\332\333\337\377" + "\247\250\255\377\254\256\262\377\253\254\261\377\252\255\260\377\252" + "\253\257\377\251\252\257\377\254\255\262\377\244\246\251\377wwy\373|" + "}\177\371z{}\373yz|\374wy{\374~~\201\373\246\246\247\373\374\374\374" + "\377\264\265\272\377\243\245\253\377\250\251\257\377\250\252\260\377" + "\253\255\263\377\252\255\262\377IIM\377\5\5\5\342\0\0\0\320\230\231\235" + "\375\367\370\373\377\257\263\273\377\270\273\301\377\267\272\301\377" + "\271\274\303\377\273\276\306\377\273\276\305\377\273\276\306\377\274" + "\277\307\377\303\305\314\377\226\230\234\375vxz\371|~\200\370\203\205" + "\210\371\215\216\222\372\224\226\230\372\221\222\225\372qru\3719:<\364" + "\4\5\5\341\0\0\0\305\1\1\1\235\0\0\0y\0\0\0\247\30\30\32\360\327\330" + "\333\377\302\304\310\377\241\243\247\377\245\247\253\377\242\243\250" + "\377\242\243\247\377\240\241\246\377\236\240\244\377\243\244\251\377" + "\253\254\260\377yz}\376OPR\372``b\372\260\257\260\375\377\377\377\377" + "\313\314\320\377\243\245\253\377\250\253\257\377\250\253\260\377\252" + "\254\262\377\252\254\262\377\252\255\263\377\255\257\266\377\255\257" + "\266\377KMP\377\2\2\2\351\0\0\0\233\0\0\0Y\0\0\0\227\0\0\0\342\210\213" + "\217\377\332\334\343\377\246\251\260\377\254\256\265\377\252\255\263" + "\377\252\254\263\377\251\254\263\377\250\253\261\377\244\246\255\377" + "\242\244\253\377\246\251\257\377\250\252\261\377\251\253\261\377\251" + "\254\261\377\261\262\271\377\241\243\250\377JLN\377\12\12\13\365\0\0" + "\0\315\0\0\0\226\0\0\0S\0\0\0\40\0\0\0\22\0\0\0#\0\0\0M\0\0\0z\0\0\0" + "\237\0\0\0\276\0\0\0\326\15\32\16\351\37;!\355)N+\360(P*\366%M'\367&" + "O(\370%N'\370\40G\"\362\27""8\32\356\12\33\12\353\0\0\0\337\0\0\0\313" + "\0\0\0\256\0\0\0\236\0\0\0\246\0\0\2\271\0\0\0\301\0\0\0\255\0\0\2\215" + "\0\0\1a\0\0\0""7\0\0\0+\0\0\0[\0\0\0\256u)'\361\377\"\40\377\377\0\0" + "\377\376\4\0\377\377\4\0\377\377\4\0\377\377\3\0\377\377\2\0\377\371" + "\3\0\377\373\3\0\377\374\2\0\377\372\3\0\377\372\2\0\377\373\3\0\377" + "\372\2\0\377\372\2\0\377\372\3\0\377\372\4\0\377\377\3\0\377\270\3\0" + "\377\0\0\0\327\3\0\0\203\0\0\0,\0\0\0\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\30\0\0\0c\0\0\0\264\27\30\31\357\244\246\253\377\310\312\320\376\274" + "\277\304\377\272\275\303\377\270\272\277\377\266\270\275\377\265\270" + "\274\377\264\266\273\377\261\264\270\377\260\262\267\377\255\257\264" + "\377\253\254\261\377\252\254\260\377\247\251\255\377\245\247\252\377" + "\243\245\251\377\242\243\250\377\243\245\251\377\242\243\247\377\236" + "\240\244\377\235\237\243\377\261\262\267\377oos\377\16\16\16\363\0\0" + "\0\254\0\0\0\224\0\0\0\335\301\302\305\377\347\350\352\377\254\256\265" + "\377\264\267\274\377\264\267\275\377\265\270\276\377\265\267\276\377" + "\265\270\277\377\275\300\307\377\223\225\232\37778:\377\10\10\11\362" + "\0\0\0\346\4\5\5\356~\200\203\376\337\340\346\377\262\264\272\377\264" + "\267\274\377\262\266\273\377\262\265\273\377\262\265\272\377\262\263" + "\271\377\264\266\273\377\251\253\260\377DFG\377\0\0\0\341\0\0\0\305G" + "HJ\364\377\377\377\377\270\271\276\377\252\254\260\377\253\254\260\377" + "\252\253\257\377\252\252\260\377\251\252\256\377\247\251\255\377\244" + "\246\253\377\253\255\261\377\324\325\330\377\346\347\351\377\350\350" + "\353\377\347\350\353\377\350\351\354\377\350\350\353\377\341\342\347" + "\377\262\264\271\377\241\243\250\377\246\250\256\377\247\250\256\377" + "\250\252\260\377\261\264\271\377\225\227\234\377*+-\376\1\1\1\324\0\0" + "\0\311\206\210\214\375\365\367\372\377\260\263\273\377\271\274\303\377" + "\272\274\303\377\272\275\304\377\271\273\303\377\273\276\306\377\275" + "\277\307\377\273\276\305\377\275\300\307\377\333\336\344\377\364\365" + "\371\377\365\366\372\377\365\366\371\377\364\365\370\377\363\365\367" + "\377\363\364\367\377\366\366\372\377\343\345\351\377~\177\203\377\20" + "\20\21\361\0\0\0\273\0\0\0s\0\0\0\224\0\0\0\340z{~\377\316\320\323\377" + "\243\245\251\377\237\241\245\377\237\241\245\377\237\241\244\377\240" + "\241\245\377\236\240\244\377\236\237\243\377\242\244\250\377\307\311" + "\314\377\346\350\352\377\363\364\365\377\337\340\343\377\261\263\270" + "\377\243\245\252\377\250\252\257\377\250\252\260\377\252\254\262\377" + "\253\256\263\377\253\256\263\377\254\257\264\377\261\264\272\377\232" + "\235\243\377012\377\0\0\0\327\0\0\0\210\0\0\0@\0\0\0p\0\0\0\3079;>\370" + "\343\346\353\377\260\262\271\377\251\254\264\377\252\255\263\377\252" + "\254\263\377\251\253\262\377\250\253\261\377\250\253\261\377\251\253" + "\262\377\250\253\261\377\251\253\261\377\251\253\261\377\254\256\263" + "\377\256\260\265\377TUW\377\14\14\14\365\0\0\0\312\0\0\0\217\0\0\0O\0" + "\0\0\36\0\0\0\16\0\0\0'\0\0\0[\2\2\2\232\0\0\0\312\17\33\17\346>qA\370" + "M\240Q\377D\251G\3772\2375\377#\224&\377\32\214\34\377\27\212\31\377" + "\30\213\32\377\27\212\31\377\31\215\33\377\37\221\"\377'\224)\377'\207" + ",\377\35]\37\375\10\34\10\357\0\0\0\333\0\0\0\304\0\0\0\245\0\0\3\177" + "\0\0\2]\0\0\0<\0\0\0\"\0\0\0\14\0\0\0\30\0\0\0\\\0\0\0\262l\26\24\361" + "\313\26\23\377\200\0\0\373g\3\0\364Z\2\0\361p\3\1\370\246\7\3\375\350" + "\10\4\377\377\5\1\377\371\2\0\377\372\3\0\377\372\3\0\377\372\2\0\377" + "\373\3\0\377\373\3\0\377\372\2\0\377\372\2\0\377\373\3\0\377\377\3\0" + "\377\253\3\0\377\0\0\0\330\2\0\0\202\0\0\0+\0\0\0\6\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\3\0\0\0\20\0\0\0\77\0\0\0\216\0\0\0\324%%&\371uvz\377\232\233\237" + "\377\252\254\260\377\262\264\271\377\266\270\275\377\267\271\277\377" + "\267\271\276\377\264\266\273\377\262\264\270\377\263\265\271\377\261" + "\264\270\377\245\247\253\377\246\247\254\377\243\245\251\377\242\245" + "\251\377\242\242\250\377\242\243\247\377\242\245\251\377\241\244\247" + "\377\242\244\250\377\255\260\264\377wx{\377\26\26\27\367\0\0\0\257\0" + "\0\0\251\30\31\33\355\362\363\364\377\315\316\323\377\260\262\270\377" + "\265\270\276\377\266\270\276\377\266\271\277\377\267\272\301\377\274" + "\277\305\377\256\260\267\377BCE\377\0\0\0\354\0\0\0\275\1\1\1\232\0\0" + "\0\300>@B\365\374\376\377\377\264\266\274\377\264\267\275\377\263\266" + "\273\377\263\265\273\377\262\265\273\377\261\263\270\377\270\271\276" + "\377\223\225\230\377(()\376\0\0\0\322\0\0\0\316\211\211\213\373\377\377" + "\377\377\247\251\255\377\254\254\261\377\252\253\260\377\251\253\257" + "\377\250\252\257\377\247\251\255\377\246\250\254\377\250\252\256\377" + "\253\255\262\377\245\247\254\377\245\246\253\377\244\246\253\377\245" + "\247\253\377\245\247\254\377\245\246\254\377\245\246\255\377\253\255" + "\263\377\260\262\270\377\261\264\272\377\263\265\273\377\267\271\277" + "\377\271\274\302\377opt\377\23\23\23\367\0\0\0\303\0\0\0\306FGJ\373\346" + "\351\356\377\306\311\321\377\272\275\304\377\274\276\306\377\273\276" + "\305\377\275\300\307\377\274\277\307\377\275\300\310\377\276\302\311" + "\377\275\300\307\377\270\272\302\377\267\272\301\377\266\271\300\377" + "\266\271\300\377\265\270\276\377\263\266\275\377\263\265\274\377\262" + "\264\272\377\301\304\312\377\261\262\267\377GGI\375\0\0\0\332\2\2\2\211" + "\0\0\0t\0\0\0\304\25\26\26\365\212\214\217\377\261\263\266\377\251\253" + "\256\377\243\244\250\377\241\244\250\377\241\242\247\377\241\242\247" + "\377\242\244\250\377\243\245\251\377\243\244\251\377\247\250\255\377" + "\243\245\251\377\246\250\255\377\243\245\252\377\253\254\261\377\251" + "\254\261\377\253\254\262\377\253\256\264\377\253\256\264\377\254\256" + "\265\377\255\260\266\377\265\267\276\377}\200\204\377\31\32\32\372\0" + "\0\0\310\0\0\0m\0\0\0""8\0\0\1i\0\0\0\264\0\0\0\353\357\360\361\377\275" + "\277\305\377\246\252\260\377\252\254\263\377\251\253\262\377\251\253" + "\262\377\251\253\261\377\251\253\260\377\252\254\261\377\252\254\261" + "\377\252\255\262\377\253\255\262\377\261\263\272\377\234\236\242\377" + "\40!\"\373\0\0\0\327\1\1\1\232\0\0\0S\0\0\0\40\0\0\0\12\0\0\0\36\0\0" + "\0Z\0\0\0\233\0\0\0\325@hC\370`\275d\377&\225)\377\5t\5\377\0g\0\377" + "\0g\0\377\0h\0\377\0k\0\377\0k\0\377\0l\1\377\0k\0\377\0j\0\377\0i\0" + "\377\0i\0\377\0p\2\377\15\201\17\377\33\212\37\377\22Q\25\376\0\0\0\352" + "\0\0\0\301\0\0\0|\0\0\0""9\0\0\0\17\0\0\0\5\0\0\0\0\0\0\0\20\0\0\0J\0" + "\0\0\225\24\0\0\317\26\0\0\333\0\0\0\277\0\0\0\255\0\0\0\253\0\0\0\266" + "\0\0\0\313.\3\2\351\257\15\11\376\377\12\6\377\374\1\0\377\372\3\0\377" + "\371\2\0\377\373\2\0\377\372\2\0\377\372\3\0\377\372\3\0\377\372\2\0" + "\377\377\3\0\377\203\1\0\377\0\0\0\315\3\0\0}\0\0\0(\0\0\0\5\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\14\0\0\0-\0\0\0L\1\1\1]\0\0\0q\0\0\1\233\0\0\0\306\3\3\3\343\36" + "\37\40\364335\374>>@\377JKM\377LMN\377LLN\377JKM\377IIK\377PQT\377\222" + "\223\227\377\266\270\274\377\241\243\250\377\243\244\251\377\241\244" + "\250\377\241\242\247\377\241\243\247\377\242\244\247\377\243\245\252" + "\377\244\245\252\377\260\262\267\377vxz\377\26\26\30\365\0\0\0\267\0" + "\0\0\277XY\\\367\377\377\377\377\271\274\302\377\263\267\275\377\266" + "\270\277\377\267\272\300\377\267\272\300\377\270\273\302\377\301\304" + "\313\377\203\205\211\377\31\31\32\371\0\0\0\312\1\2\2\200\0\0\0w\0\0" + "\0\307wxz\371\377\377\377\377\263\266\273\377\265\267\274\377\263\266" + "\273\377\262\264\272\377\262\264\272\377\261\263\271\377\271\273\300" + "\377oqs\377\21\21\22\365\0\0\0\305\0\0\0\330\301\301\303\377\341\342" + "\343\377\242\243\250\377\251\253\260\377\250\252\256\377\250\251\256" + "\377\247\251\254\377\245\246\252\377\251\252\255\377\234\235\241\377" + "|}\200\377uwy\377vw{\377wwz\377vwz\377ww{\377vx{\377vw|\377vx|\377xz" + "}\377z{\177\377z|\200\377}\177\204\377qrv\377\77@B\377\1\1\1\347\0\0" + "\0\247\0\0\0\253\6\7\6\347mot\377\254\257\265\377\271\274\302\377\276" + "\301\310\377\300\303\313\377\301\305\313\377\301\304\313\377\277\301" + "\311\377\276\302\311\377\302\305\314\377\275\300\306\377\275\300\307" + "\377\275\277\305\377\274\276\304\377\273\276\303\377\271\273\301\377" + "\271\273\300\377\266\270\275\377\264\266\273\377\261\263\270\377VWY\377" + "\3\3\3\350\0\0\0\217\0\0\0X\0\0\0\216\0\0\0\310\23\22\23\362TUV\377~" + "\177\202\377\221\223\226\377\233\234\241\377\237\241\245\377\240\242" + "\245\377\241\242\246\377\236\241\244\377\223\224\230\377wx{\377YY]\377" + "WXZ\373\322\323\327\377\250\252\260\377\254\256\264\377\255\257\265\377" + "\255\257\266\377\255\260\267\377\255\260\266\377\261\263\272\377\254" + "\257\264\377PRU\377\5\5\6\356\0\0\0\254\0\0\0[\0\0\0k\0\0\0\255\0\0\0" + "\335\231\231\232\373\377\377\377\377\254\257\265\377\251\254\262\377" + "\251\253\262\377\251\254\262\377\251\254\262\377\251\254\261\377\252" + "\253\262\377\252\254\262\377\253\256\263\377\254\256\263\377\255\257" + "\264\377\263\266\273\377\257\261\265\377FGI\377\0\0\0\337\1\1\1\227\0" + "\0\0A\0\0\0\16\0\0\0\6\0\0\0""2\0\0\0\214\0\0\0\321;h=\370S\267V\377" + "\0d\0\376\0j\0\377\0o\3\377\1r\6\377\1q\5\377\0p\4\377\0p\4\377\0p\4" + "\377\0q\5\377\0p\4\377\0p\4\377\0q\5\377\1q\5\377\0o\4\377\0l\1\377\0" + "k\0\377\13\203\16\377\12K\15\377\0\0\0\343\0\1\0\227\0\0\0<\0\0\0\7\0" + "\0\0\0\0\0\0\0\0\0\0\12\0\0\0)\0\0\0V\0\0\0u\0\0\0|\5\0\0e\6\0\0M\6\0" + "\0H\7\0\0W\3\0\0x\0\0\0\240\0\0\0\317\217\21\17\370\377\16\11\377\371" + "\1\0\377\371\3\0\377\372\3\0\377\372\2\0\377\372\2\0\377\371\3\0\377" + "\375\4\0\377\356\3\0\3778\0\0\364\0\0\0\263\1\0\0e\0\0\0\37\0\0\0\2\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\33\0\0\0`\1\0\0\251\0\0\0\304\0\0\0\266\0\0\0\245\0\0\0" + "\256\0\0\0\270\0\0\0\275\0\0\0\312\0\0\0\321\0\0\0\321\0\0\0\322\0\0" + "\0\322\0\0\0\322\0\0\0\321\0\0\0\332\"#$\364\355\355\360\377\240\243" + "\246\377\241\243\247\377\241\242\246\377\241\242\246\377\241\243\250" + "\377\241\244\250\377\244\245\253\377\245\247\254\377\262\264\271\377" + "qrv\377\20\20\21\364\0\0\0\275\0\0\0\321\243\243\246\376\374\375\376" + "\377\260\263\272\377\267\272\300\377\267\272\300\377\270\273\302\377" + "\270\272\301\377\271\273\303\377\277\302\311\377abe\377\6\6\7\356\0\0" + "\0\257\0\0\0b\0\0\0\213\0\0\0\334\302\303\305\377\353\355\357\377\260" + "\264\271\377\265\270\275\377\263\265\273\377\262\264\271\377\262\264" + "\270\377\263\265\273\377\261\262\267\377OQS\377\4\5\4\352\2\2\2\274\0" + "\1\1\336\343\344\346\377\312\313\316\377\243\244\250\377\250\251\256" + "\377\245\250\254\377\245\246\253\377\244\246\252\377\244\245\250\377" + "\247\250\254\377KLN\376\12\12\12\357\16\16\17\352\16\16\17\353\16\16" + "\17\355\16\16\17\354\16\16\17\353\16\17\17\353\16\17\17\353\17\17\17" + "\352\17\17\20\351\17\17\20\351\17\20\20\352\15\15\16\352\17\20\20\353" + "\14\14\15\354\0\0\0\311\0\0\0\206\0\0\0\200\0\0\0\272\2\3\3\341/02\370" + "QRU\377cei\377lnr\377lmq\377klp\377dei\377bbg\377\215\217\224\377\316" + "\320\327\377\274\276\305\377\272\274\302\377\272\274\301\377\267\272" + "\300\377\267\271\276\377\264\267\273\377\262\264\271\377\263\265\272" + "\377\260\261\266\377RRU\377\4\4\4\346\0\0\0\231\0\0\0\210\0\0\0\232\0" + "\0\0\244\0\0\0\301\0\0\0\335\22\22\23\362*+,\372<=\77\376DEG\377FGI\377" + "EFH\377=>\77\377+,-\371\22\21\22\365\0\0\0\360\253\252\252\373\362\362" + "\366\377\245\247\255\377\255\260\265\377\255\257\266\377\255\260\266" + "\377\256\261\267\377\255\257\267\377\267\272\301\377\216\220\226\377" + "''*\377\0\0\0\332\1\1\1\213\0\0\0f\0\0\0\246\0\0\0\334\213\214\216\374" + "\377\377\377\377\277\302\307\377\246\251\257\377\251\254\262\377\251" + "\254\261\377\251\253\261\377\251\252\261\377\253\255\263\377\252\255" + "\262\377\254\256\263\377\256\261\266\377\257\261\266\377\260\261\267" + "\377\260\263\270\377\277\301\306\377z{~\377\14\14\15\363\0\0\0\270\0" + "\0\0_\0\0\0\33\0\0\0\11\0\0\0""8\0\0\0\240\0\0\0\352E\256J\377\3o\3\376" + "\1q\5\377\0o\4\377\0o\3\377\0p\4\377\0p\4\377\0o\3\377\0o\3\377\0o\3" + "\377\0p\4\377\0o\3\377\0o\3\377\0o\4\377\0o\3\377\0o\3\377\0p\4\377\0" + "p\4\377\0s\1\377\5f\10\377\0\2\0\360\0\0\0\246\0\0\0A\0\0\0\7\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\11\0\0\0\31\1\0\0%\1\0\0'\0\0\0\37\0\0\0\21\0" + "\0\0\16\0\0\0\27\0\0\0""2\2\0\0[\0\0\0\227\2\0\0\323\273\37\33\375\377" + "\5\3\377\370\1\0\377\373\3\0\377\373\3\0\377\371\2\0\377\372\3\0\377" + "\377\4\0\377\235\2\0\377\0\0\0\335\2\0\0\226\0\0\0G\0\0\0\23\0\0\0\1" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\4\0\0\0,\0\0\0~\0\0\0\325hij\372deh\36789:\362$%'\361\30\30\32" + "\351\14\14\15\334\4\4\5\330\0\0\0\330\0\0\0\330\0\0\0\330\0\0\0\330\0" + "\0\0\330\0\0\0\330\21\21\22\344\226\226\226\372\371\371\372\377\233\234" + "\240\377\237\241\244\377\240\241\246\377\237\241\246\377\240\243\247" + "\377\244\246\253\377\245\251\255\377\250\252\257\377\256\261\267\377" + "XY[\377\7\10\7\351\0\0\0\277\4\5\6\344\346\347\351\377\331\332\336\377" + "\262\265\274\377\272\275\302\377\271\273\301\377\272\274\302\377\271" + "\273\302\377\277\301\307\377\260\262\270\377==@\377\0\0\0\336\1\1\1\222" + "\0\0\0`\0\0\0\251\35\36\40\354\365\365\366\377\321\323\327\377\261\264" + "\272\377\265\267\274\377\263\265\272\377\262\263\271\377\261\262\267" + "\377\267\271\276\377\235\237\243\377013\377\0\0\0\327\2\2\2\266\7\7\7" + "\346\350\351\353\377\301\302\305\377\243\245\251\377\244\247\253\377" + "\244\245\252\377\242\244\250\377\241\243\250\377\242\244\250\377\245" + "\246\253\377@@B\376\0\0\0\333\0\0\0\272\0\0\0\260\0\0\0\253\0\0\0\257" + "\0\0\0\262\0\0\0\266\0\0\0\266\0\0\0\273\0\0\0\304\0\0\0\310\0\0\0\325" + "\4\5\5\337\6\6\6\315\0\0\0\251\0\0\0\216\0\0\0\241\0\0\0\267\0\0\0\277" + "\0\0\0\312\0\0\0\323\0\0\0\334\0\0\0\337\0\0\0\337\0\0\0\337\0\0\0\337" + "\0\0\0\337\0\0\0\342\0\0\0\355\354\355\357\377\310\312\320\377\267\272" + "\277\377\271\273\300\377\267\271\276\377\263\266\273\377\262\264\272" + "\377\257\261\266\377\260\262\267\377\243\245\251\377ABC\377\0\0\0\340" + "\2\2\2\254\0\0\0\320!!\"\353\0\0\0\336\0\0\0\316\0\0\0\307\0\0\0\320" + "\0\0\0\316\0\0\0\327\0\0\0\340\0\0\0\337\0\0\0\340\0\0\0\340\0\0\0\336" + "\16\16\17\352\242\242\242\373\377\377\377\377\272\274\302\377\253\256" + "\264\377\256\260\266\377\256\261\267\377\256\261\270\377\257\261\270" + "\377\257\263\272\377\261\265\274\377SUX\377\10\10\10\363\0\0\0\267\0" + "\0\0}\0\0\0\235\0\0\0\327\204\205\210\371\377\377\377\377\302\305\312" + "\377\245\250\257\377\252\254\262\377\252\254\262\377\251\254\261\377" + "\253\255\263\377\260\262\270\377\264\267\274\377\257\261\267\377\255" + "\257\263\377\260\262\267\377\262\263\271\377\264\265\273\377\266\270" + "\274\377\300\302\306\377\250\252\255\37788:\377\0\0\0\324\2\2\2\205\0" + "\0\0""4\0\0\0\17\0\0\0""5\0\0\0\226\0\0\0\334\17K\22\375\20\205\23\377" + "\0o\1\377\0o\3\377\0p\4\377\0p\4\377\0p\4\377\0p\4\377\0p\4\377\0p\4" + "\377\0p\4\377\0p\4\377\0p\4\377\0o\3\377\0p\4\377\0p\4\377\0o\4\377\0" + "o\3\377\2{\6\377\2@\4\377\0\0\0\350\0\1\0\236\0\0\0@\0\0\0\15\0\0\0\11" + "\0\0\0\13\0\0\0\13\0\0\0\14\0\0\0\15\0\0\0\16\0\0\0\15\0\0\0\13\0\0\0" + "\7\0\0\0\3\0\0\0\3\0\0\0\14\0\0\0&\0\0\0b\0\0\0\252@\21\20\351\373\40" + "\34\377\370\0\0\377\372\4\0\377\372\3\0\377\372\2\0\377\377\3\0\377\320" + "\2\0\377\35\0\0\355\0\0\0\267\1\0\0n\0\0\0*\0\0\0\10\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\11" + "\0\0\0\77\0\0\0\231\0\0\0\343\355\355\356\377\377\377\377\377\365\367" + "\371\377\361\362\364\377\346\347\351\377\325\326\331\377\313\314\316" + "\377\272\273\276\377\263\263\266\377\260\261\263\377\260\261\262\377" + "\272\273\275\377\314\315\316\377\355\355\356\377\375\375\376\377\257" + "\260\264\377\234\236\242\377\237\241\244\377\237\241\245\377\241\241" + "\247\377\242\246\252\377\246\250\255\377\247\252\256\377\257\262\267" + "\377\235\237\244\377668\377\0\0\0\332\0\0\0\302>\77A\362\377\377\377" + "\377\301\304\311\377\270\273\301\377\273\276\303\377\273\276\304\377" + "\273\276\303\377\273\275\304\377\303\306\315\377\224\226\232\377!!\"" + "\374\0\0\0\314\0\0\0v\0\0\0k\0\0\0\301VWY\367\377\377\377\377\273\275" + "\303\377\264\266\272\377\263\265\272\377\262\265\272\377\261\262\267" + "\377\257\261\266\377\267\271\276\377\200\201\204\377\30\30\30\372\0\0" + "\0\304\2\2\2\260\5\5\6\346\343\344\345\377\277\300\303\377\240\242\246" + "\377\243\245\251\377\241\243\247\377\241\242\246\377\240\242\246\377" + "\236\240\244\377\250\251\257\377\221\221\225\377446\370\2\2\3\346\0\0" + "\0\330\0\0\0\321\0\0\0\327\0\0\0\335\5\6\7\345\27\30\31\347-.0\353OP" + "Q\365vwy\371\242\244\247\374{|\201\377\20\20\21\353\0\0\0\242\0\0\0\221" + "\6\6\6\327\213\213\217\374vxz\373QRV\367>\77A\360**,\352\"\"$\350\37" + "\40!\350\36\36\40\350\"\"$\350$$&\350JKL\357\261\261\261\372\374\375" + "\376\377\275\300\306\377\270\272\277\377\266\270\276\377\263\266\273" + "\377\261\262\270\377\257\260\266\377\253\255\261\377\261\263\267\377" + "\215\217\222\377&'(\377\0\0\0\317\3\3\3\260\2\2\2\344\343\344\346\377" + "\274\275\300\377{|\177\376VXY\371::;\363&&(\353\34\34\35\350\32\32\33" + "\350\33\33\34\350++,\352OPP\362\230\231\232\373\362\362\362\377\377\377" + "\377\377\276\300\306\377\253\255\263\377\257\262\270\377\257\261\270" + "\377\261\263\272\377\257\262\271\377\257\262\271\377\272\275\304\377" + "\200\202\207\377\37\40!\376\0\0\0\326\1\1\1\230\1\1\1\242\0\0\0\331x" + "y{\372\377\377\377\377\307\311\316\377\246\251\257\377\254\256\264\377" + "\253\256\263\377\253\255\263\377\253\256\263\377\262\266\273\377\200" + "\201\205\377BCD\375\311\313\320\377\266\267\275\377\262\263\271\377\264" + "\266\274\377\267\271\275\377\272\273\300\377\276\277\304\377\300\302" + "\306\377jln\377\3\3\3\353\0\0\0\250\0\0\0Q\0\0\0\31\0\0\0$\0\0\0i\0\0" + "\0\253\0\0\0\340\12C\14\376\12x\16\377\2z\6\377\0v\4\377\0r\4\377\0p" + "\3\377\0o\3\377\0o\3\377\0o\3\377\0p\4\377\0o\3\377\0p\3\377\0p\3\377" + "\0r\4\377\0u\4\377\0y\5\377\2t\6\377\2B\4\377\0\2\0\361\0\0\0\307\0\0" + "\0\211\0\0\0O\0\0\0""7\0\0\0C\0\0\0O\0\0\0T\0\0\0T\0\0\0T\0\0\0T\0\0" + "\0P\0\0\0E\0\0\0""5\0\0\0*\0\0\0\33\0\0\0\17\0\0\0\22\0\0\0:\0\0\0\206" + "\22\6\6\324\337-)\377\375\1\0\377\372\3\0\377\377\2\0\377\377\3\0\377" + "\313\2\0\377*\0\0\365\0\0\0\303\1\0\0\211\0\0\0D\0\0\0\24\0\0\0\2\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\1\0\0\0\23\0\0\0X\0\0\0\262557\361\374\374\374\377\315\317\323\377" + "\270\272\277\377\300\302\307\377\304\306\312\377\312\314\320\377\316" + "\320\324\377\325\326\331\377\331\333\336\377\331\333\335\377\327\331" + "\334\377\322\324\327\377\306\307\312\377\262\263\267\377\232\234\240" + "\377\234\235\242\377\236\240\245\377\236\240\245\377\241\242\247\377" + "\242\245\251\377\247\250\255\377\251\253\257\377\254\257\264\377\265" + "\267\275\377jln\377\22\22\23\367\0\0\0\305\0\0\0\316\224\224\227\374" + "\373\374\375\377\270\273\301\377\273\276\305\377\275\300\306\377\275" + "\277\306\377\274\276\306\377\275\300\306\377\303\305\313\377nor\377\15" + "\16\16\364\0\0\0\265\0\0\0a\1\2\2\204\0\0\0\326\243\244\246\375\375\375" + "\377\377\256\261\266\377\264\266\273\377\263\264\272\377\261\262\270" + "\377\257\262\267\377\255\260\265\377\263\264\271\377\\]_\377\5\5\5\357" + "\0\0\0\256\2\2\2\235\0\0\0\337\262\263\266\377\317\321\324\377\233\235" + "\241\377\241\243\247\377\237\241\245\377\237\240\244\377\237\240\244" + "\377\236\240\244\377\234\236\242\377\253\254\261\377\307\311\315\377" + "\315\316\322\377\306\310\313\377\307\310\312\377\321\322\323\377\325" + "\325\330\377\343\345\347\377\361\361\364\377\372\373\376\377\376\376" + "\377\377\372\373\376\377\253\255\262\377$$&\376\0\0\0\324\1\1\1\222\0" + "\0\0\251!\"#\356\377\377\377\377\377\377\377\377\374\375\377\377\373" + "\374\377\377\367\370\373\377\367\370\372\377\366\367\372\377\365\366" + "\371\377\367\367\372\377\374\375\377\377\377\377\377\377\361\362\365" + "\377\303\306\313\377\267\271\276\377\266\270\276\377\264\266\273\377" + "\261\263\270\377\256\260\264\377\252\254\261\377\251\253\260\377\256" + "\260\264\377Y[\\\377\12\12\13\363\0\0\0\272\0\0\0\272446\363\377\377" + "\377\377\314\316\321\377\322\323\327\377\341\342\345\377\347\351\354" + "\377\346\350\352\377\351\352\354\377\353\353\356\377\354\355\357\377" + "\367\371\373\377\377\377\377\377\355\356\360\377\315\317\323\377\254" + "\256\264\377\253\256\264\377\257\262\270\377\256\261\270\377\261\263" + "\273\377\260\263\272\377\262\264\273\377\275\300\307\377\227\230\237" + "\37778:\377\1\1\1\352\0\0\0\255\0\0\0\237\0\0\0\325nnq\372\377\377\377" + "\377\314\316\322\377\246\251\260\377\256\257\265\377\254\256\264\377" + "\254\255\264\377\255\257\264\377\264\266\273\377}~\202\377%%'\374\0\0" + "\0\356\261\263\266\377\335\336\342\377\260\261\267\377\271\275\300\377" + "\272\275\301\377\276\300\304\377\277\301\305\377\313\315\322\377\236" + "\240\243\377'((\372\0\0\0\306\1\1\1u\0\0\0)\0\0\0\21\0\0\0""2\0\0\0o" + "\0\0\0\252\0\0\0\331\1\23\2\365\6A\10\377\6`\11\377\4r\11\377\4w\10\377" + "\2x\6\377\1w\5\377\1v\5\377\1w\5\377\1w\4\377\1w\6\377\2v\6\377\2p\7" + "\377\2b\6\377\2A\4\377\0\26\1\372\0\0\0\350\0\0\0\311\0\0\0\250\0\0\0" + "\223\0\0\0\222\0\0\0\235\0\0\0\247\0\0\0\267\0\0\0\303\0\0\0\305\0\0" + "\0\305\0\0\0\303\0\0\0\271\0\0\0\251\0\0\0\235\0\0\0\213\0\0\0p\0\0\0" + "P\0\0\0""5\0\0\0;\5\2\2{\0\0\0\314\312;7\375\377\5\4\377\377\3\0\377" + "\357\3\0\377\221\2\0\377\32\0\0\351\0\0\0\275\2\0\0\210\0\0\0P\0\0\0" + "\36\0\0\0\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\6\0\0\0\"\0\0\0q\0\0\0\310uuw\371\377\377\377" + "\377\270\273\300\377\267\271\276\377\264\267\274\377\263\265\272\377" + "\257\261\266\377\254\256\263\377\250\252\257\377\244\246\252\377\237" + "\241\246\377\235\237\243\377\232\233\241\377\231\233\237\377\233\235" + "\241\377\236\241\244\377\240\242\246\377\236\241\245\377\240\242\247" + "\377\243\246\253\377\245\247\254\377\250\252\257\377\256\261\265\377" + "\270\272\300\377\203\204\210\377*+,\377\0\0\0\336\0\0\0\265\1\2\3\340" + "\332\333\335\377\344\345\352\377\267\271\301\377\274\276\304\377\274" + "\277\306\377\274\276\304\377\273\276\304\377\300\303\311\377\266\270" + "\276\377IJM\377\0\0\0\346\1\1\1\232\0\0\0\\\1\1\0\237\3\3\4\347\345\344" + "\347\377\331\332\335\377\255\257\264\377\263\264\271\377\260\261\266" + "\377\257\261\265\377\255\257\264\377\256\260\265\377\243\244\250\377" + "::;\377\0\0\0\340\0\0\0\222\1\1\1\206\0\0\0\323XXZ\374\317\321\324\377" + "\244\246\252\377\234\236\242\377\235\236\243\377\235\237\243\377\235" + "\240\244\377\235\237\243\377\236\240\244\377\232\234\241\377\235\237" + "\244\377\255\257\264\377\274\277\303\376\302\303\311\376\301\303\307" + "\376\277\302\306\376\273\275\302\376\263\266\274\377\255\257\266\377" + "\255\260\267\377\244\247\256\377\77AC\377\3\3\3\355\0\0\0\254\0\0\0~" + "\0\0\0\300^`c\367\377\377\377\377\272\275\305\377\267\272\301\377\276" + "\301\310\377\302\306\313\377\304\306\314\377\303\305\315\377\304\305" + "\314\377\303\305\312\377\301\303\311\377\271\274\302\377\265\267\275" + "\377\267\271\276\377\267\271\276\377\263\266\273\377\261\263\270\377" + "\255\257\264\377\252\253\260\377\253\255\261\377\253\254\260\377stv\377" + "!!\"\376\0\0\0\332\0\0\0\250\0\0\0\315\200\201\202\374\364\364\365\377" + "\222\224\230\377\226\231\234\377\230\233\237\377\236\240\244\377\247" + "\251\256\377\255\257\264\377\257\261\266\377\260\262\267\377\255\260" + "\265\377\250\252\260\377\247\252\260\377\252\254\264\377\257\262\270" + "\377\260\262\271\377\257\262\271\377\260\262\272\377\257\263\271\377" + "\265\267\276\377\270\273\302\377\226\230\236\377@AD\377\6\6\7\361\0\0" + "\0\276\1\1\1\246\0\0\0\317efh\366\377\377\377\377\315\317\323\377\250" + "\252\260\377\255\257\265\377\254\256\264\377\254\256\264\377\253\255" + "\262\377\267\271\277\377\212\214\220\377012\377\0\0\0\344\0\0\0\326p" + "qt\374\364\365\371\377\265\267\273\377\274\277\302\377\276\277\304\377" + "\300\302\307\377\302\304\310\377\310\312\316\377\305\307\312\377XZ[\377" + "\0\0\0\337\1\1\1\232\0\0\0E\0\0\0\22\0\0\0\21\0\0\0""3\0\0\0a\0\2\0\220" + "\0\0\0\264\0\0\0\325\0\1\0\347\1\22\1\363\2\"\3\367\2""5\4\375\3@\5\377" + "\2@\5\377\2@\5\377\2A\5\377\1""6\4\376\1&\3\372\0\23\1\365\0\3\0\356" + "\0\0\0\335\0\0\0\314\0\1\0\277\3\3\2\271\0\0\0\273\0\0\0\316\13\13\6" + "\336//\40\354[[<\360mmM\364rrN\371rrL\371rrM\371ssK\370nnA\364YY/\361" + "00\27\356\14\14\4\336\0\0\0\314\0\0\0\254\4\4\1\210\0\0\0r\2\0\0\221" + "\3\0\0\325\265*&\377\301\4\2\377\177\2\0\3743\0\0\355\0\0\0\320\0\0\0" + "\247\2\0\0y\0\0\0H\0\0\0\37\0\0\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\14\0\0\0>" + "\0\0\0\221\0\0\0\332\300\301\303\377\372\372\375\377\273\275\303\377" + "\277\301\305\377\272\274\301\377\266\271\275\377\262\264\271\377\257" + "\261\265\377\253\255\261\377\247\251\256\377\245\247\253\377\243\245" + "\251\377\241\243\247\377\237\241\245\377\237\240\244\377\237\241\246" + "\377\240\243\247\377\242\243\250\377\245\247\254\377\253\255\261\377" + "\260\262\270\377\267\271\277\377\260\262\267\377xz}\377--/\377\1\1\1" + "\355\0\0\0\271\0\0\0\264668\360\377\377\377\377\324\327\335\377\303\305" + "\315\377\307\311\320\377\307\311\317\377\305\311\317\377\307\311\317" + "\377\317\322\327\377\237\241\245\377+,.\377\0\0\0\324\2\2\2\200\0\0\0" + "b\0\0\0\271<>\77\365\377\377\377\377\307\310\315\377\270\272\277\377" + "\270\271\277\377\267\271\275\377\265\267\273\377\263\265\271\377\270" + "\273\276\377\206\207\213\377\36\36\37\375\0\0\0\316\0\0\0x\0\0\0i\0\0" + "\0\270\12\12\13\357tux\377\255\257\262\377\247\250\254\377\241\242\247" + "\377\235\240\244\377\236\237\244\377\234\236\243\377\235\237\244\377" + "\235\237\245\377\237\240\246\377\236\240\246\377\240\242\250\377\240" + "\243\251\377\244\247\255\377\251\254\263\377\256\261\267\377\263\266" + "\275\377\270\272\302\377\265\267\276\377uvz\377\31\32\33\373\0\0\0\317" + "\1\1\1\204\0\0\0\205\0\0\0\325\264\265\270\376\376\377\377\377\301\305" + "\314\377\305\310\317\377\304\307\315\377\302\305\314\377\301\304\312" + "\377\277\302\310\377\277\301\307\377\275\300\306\377\276\300\305\377" + "\274\276\303\377\273\276\303\377\271\273\300\377\266\270\276\377\264" + "\266\273\377\262\264\272\377\263\264\271\377\257\261\266\377\237\241" + "\244\377eeh\377#$$\377\0\0\0\351\0\0\0\261\0\0\0\237\0\0\0\341\311\313" + "\315\377\335\336\341\377\241\242\247\377\250\252\256\377\247\250\255" + "\377\247\251\255\377\250\252\257\377\251\253\260\377\252\253\261\377" + "\253\255\263\377\255\257\265\377\261\261\270\377\261\264\272\377\263" + "\265\273\377\263\265\275\377\264\267\276\377\270\272\301\377\273\276" + "\305\377\275\300\307\377\252\254\263\377stz\377013\377\5\4\5\360\0\0" + "\0\311\0\0\0\256\0\0\0\322bbd\370\377\377\377\377\331\332\337\377\260" + "\263\272\377\266\270\276\377\264\267\274\377\265\270\276\377\266\270" + "\276\377\272\274\301\377\234\236\242\377;=>\377\3\3\3\357\0\0\0\274\0" + "\0\0\274./0\364\347\351\354\377\321\324\331\377\306\310\314\377\313\315" + "\322\377\315\317\324\377\317\321\326\377\321\323\330\377\334\337\343" + "\377\226\230\233\377\22\23\23\360\0\0\0\273\1\1\1f\0\0\0\36\0\0\0\5\0" + "\0\0\13\0\0\0\40\0\0\0<\0\0\0[\0\1\0|\0\0\0\232\0\0\0\252\0\0\0\271\0" + "\0\0\317\0\0\0\343\0\0\0\347\0\0\0\347\0\0\0\347\0\0\0\330\0\0\0\301" + "\0\0\0\257\0\0\0\245\0\0\0\233\0\0\0\244\0\0\0\273\0\0\0\324++\37\354" + "\234\234u\373\333\333\217\377\377\377\214\377\377\377~\377\377\377s\377" + "\377\377j\377\377\377i\377\377\377i\377\377\377h\377\377\377k\377\377" + "\377p\377\377\377u\377\334\334i\377\235\235J\375//\21\360\0\0\0\323\0" + "\0\0\265\0\0\0\256\6\0\0\315\35\0\0\350\7\0\0\346\0\0\0\310\0\0\0\243" + "\1\0\0\203\1\0\0^\0\0\0""6\0\0\0\30\0\0\0\7\0\0\0\1\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\17\0\0\0L\0\0\0\245\30\30\30\351\244\246\252\377\221\222\226\377" + "\220\222\225\377\235\237\242\377\244\246\252\377\247\251\255\377\252" + "\254\260\377\251\252\257\377\251\253\257\377\247\251\255\377\245\247" + "\253\377\243\245\251\377\243\245\251\377\245\246\253\377\245\246\253" + "\377\244\247\253\377\246\250\255\377\247\251\256\377\250\251\256\377" + "\243\245\252\377\230\232\236\377y{~\377IJL\377\32\32\33\374\0\0\0\346" + "\0\0\0\267\1\1\1\225\0\0\0\314qsu\374\333\333\340\377\234\236\244\377" + "\235\237\243\377\235\236\244\377\234\235\241\377\233\236\242\377\234" + "\235\242\377\233\234\241\377ikm\377\23\23\24\372\0\0\0\300\0\0\0i\0\0" + "\0v\0\0\0\321\200\201\204\374\313\315\320\377\222\224\227\377\220\221" + "\225\377\217\220\224\377\216\217\222\377\214\216\221\377\214\215\221" + "\377\205\206\212\377TUX\377\15\16\16\365\0\0\0\271\0\0\0\\\0\0\0A\0\0" + "\0\204\0\0\0\304\14\14\14\357LLN\377wx|\377\217\221\225\377\232\233\240" + "\377\235\237\244\377\237\241\246\377\242\243\250\377\242\243\250\377" + "\243\245\252\377\244\246\254\377\245\247\255\377\244\246\254\377\242" + "\244\252\377\235\237\244\377\220\222\227\377\201\202\210\377lmr\377N" + "OR\377--/\377\1\1\1\345\0\0\0\247\0\0\0c\0\0\0\224\15\16\17\350\263\265" + "\272\377\250\252\257\377\234\236\243\377\246\251\256\377\260\263\270" + "\377\261\263\272\377\267\272\300\377\273\275\303\377\272\274\302\377" + "\270\271\277\377\267\271\276\377\265\265\273\377\263\265\271\377\261" + "\262\267\377\256\260\264\377\246\250\253\377\231\232\235\377\207\207" + "\213\377cdf\377789\377\22\22\22\372\0\0\0\341\0\0\0\270\0\0\0\203\0\0" + "\0\251\25\25\26\361uvy\377pqt\377{|\201\377\216\217\223\377\232\234\240" + "\377\242\243\250\377\251\252\257\377\256\257\265\377\260\262\270\377" + "\262\264\272\377\264\266\274\377\265\267\275\377\266\270\276\377\266" + "\270\277\377\265\267\276\377\257\262\271\377\245\247\256\377\217\221" + "\226\377klp\377:;>\377\22\23\24\370\0\0\0\342\0\0\0\270\0\0\0\237\0\0" + "\0\322efh\372\372\372\373\377\261\263\266\377\214\216\223\377\221\223" + "\227\377\217\220\225\377\216\220\224\377\217\221\225\377\221\222\226" + "\377\204\206\211\377IJL\377\11\11\11\361\0\0\0\307\0\0\0\212\0\0\0\235" + "\5\5\5\346\225\227\232\377\251\253\256\377\236\237\243\377\240\242\245" + "\377\242\244\250\377\244\245\251\377\245\247\252\377\251\253\256\377" + "\220\221\224\377CEF\376\0\0\0\326\2\2\2}\0\0\0)\0\0\0\5\0\0\0\0\0\0\0" + "\4\0\0\0\14\0\0\0\26\0\0\0'\0\0\0""5\0\1\0F\0\2\0Z\0\2\0v\0\2\0\211\0" + "\2\0\212\0\2\0\212\0\2\0\212\0\2\0\177\0\2\0d\0\1\0P\0\0\0T\0\0\0x\0" + "\0\1\257\0\0\0\337\212\212l\372\377\377\247\377\377\377j\377\377\377" + "M\376\373\373F\377\372\372G\377\370\370H\377\372\372I\377\371\371J\377" + "\372\372I\377\372\372J\377\371\371J\377\370\370I\377\373\373I\377\377" + "\377O\376\377\377^\377\377\377k\377\211\2114\374\0\0\0\341\0\0\0\301" + "\0\0\0\252\0\1\1\230\1\0\0\210\3\0\0r\3\0\0S\0\0\0""4\0\0\0\36\0\0\0" + "\16\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\15\0\0\0D\0\0\0\223" + "\6\6\7\315\15\15\16\354\13\14\14\366\27\27\30\367\"#%\373+,-\377668\377" + "\77@B\377FGH\377RRT\377VWY\377VWY\377WWZ\377\\]`\377hil\377ghl\377_`" + "c\377[\\_\377WXZ\377KLN\37789;\377$$&\377\17\17\20\370\2\2\2\354\0\0" + "\0\321\0\0\0\253\0\0\0p\1\1\1z\0\0\0\320002\365$$%\367\33\34\34\367\34" + "\34\35\367\33\34\35\366\33\33\34\366\33\33\34\366\33\33\34\366\32\33" + "\34\366\31\32\32\367\3\3\3\344\0\0\0\240\0\0\0T\0\0\0w\0\0\0\324-./\367" + "\36\36\37\370\31\31\32\370\30\31\31\370\30\30\31\370\30\30\31\370\30" + "\30\31\367\27\30\31\367\27\27\27\367\25\25\26\371\2\2\2\342\0\0\0\233" + "\0\0\0E\0\0\0\40\0\0\0G\0\0\0\205\0\0\0\276\0\0\0\345\17\17\17\366&&" + "'\37699;\377HIK\377RSV\377TUX\377VWZ\377UWZ\377UVZ\377NNQ\377ABE\377" + "89;\377*,-\377\34\35\36\374\21\21\22\367\7\7\10\365\3\3\2\346\0\0\0\337" + "\0\0\0\277\0\0\0x\0\0\0I\0\0\0\217\11\11\11\337\27\26\27\365\25\26\27" + "\366\36\36\40\366))+\375/01\37778:\377DEG\377GHK\377HIK\377KLN\377KL" + "N\377KLN\377JJL\377HHJ\377BCD\377789\377''(\377\27\30\30\373\10\11\11" + "\365\0\0\0\346\0\0\0\310\0\0\0\241\0\0\0k\0\0\0R\0\0\0\227\0\0\0\325" + "\1\1\1\344\7\7\10\360\20\20\21\367\37\37!\373./0\377<=\77\377IKM\377" + "YZ\\\377__c\377`ae\377bcf\377deh\377cei\377`ae\377VW[\377DFH\377002\377" + "\32\32\33\375\10\10\10\365\0\0\0\342\0\0\0\303\1\0\1\240\0\0\0n\0\0\0" + "\201\11\11\11\327PQS\366$%'\366\30\30\31\366\32\32\33\366\31\31\32\367" + "\31\31\32\370\31\31\32\370\31\32\32\370\31\31\32\370\30\31\31\370\14" + "\14\14\367\0\0\0\323\0\0\0\221\0\0\0T\0\0\0}\0\0\0\313!\"\"\364\40!\"" + "\367\34\34\35\367\35\35\35\367\35\35\37\367\35\35\36\367\35\35\36\366" + "\35\35\36\366\40!\"\366\40!\"\365\2\2\2\324\0\0\0z\0\0\0(\0\0\0\5\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\6\0\0\0\13\0\0\0\24\0\0\0" + "\37\0\0\0$\0\0\0$\0\0\0$\0\0\0%\0\0\0!\0\0\0\27\0\0\0\24\0\0\0>\0\0\0" + "\222\0\0\0\323\212\212k\373\377\377\230\377\371\371<\377\374\374J\377" + "\375\375P\377\374\374P\377\375\375O\377\373\373O\377\376\376O\377\374" + "\374O\377\375\375O\377\374\374O\377\374\374O\377\374\374O\377\374\374" + "O\377\374\374O\377\373\373L\377\374\374J\377\377\377a\377yy+\374\0\0" + "\0\331\2\2\0\236\0\0\0U\0\0\0,\0\0\0\37\0\0\0\25\0\0\0\13\0\0\0\3\0\0" + "\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\4\0\0\0\11\0\0\0\17\0\0\0\23\0\0\0\24" + "\0\0\0\24\0\0\0\24\0\0\0\23\0\0\0\21\0\0\0\15\0\0\0\10\0\0\0\5\0\0\0" + "\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\6\0\0\0" + "'\0\0\0W\0\0\0~\0\0\0\234\0\0\0\247\0\0\0\254\0\0\0\276\0\0\0\314\0\0" + "\0\315\0\0\0\315\0\0\0\323\0\0\0\336\0\1\1\346\4\4\4\351\10\7\7\351\12" + "\12\12\351\14\14\14\352\13\13\13\351\12\12\12\351\10\10\10\352\2\2\2" + "\350\0\0\0\336\0\0\0\320\0\0\0\316\0\0\0\274\0\0\0\244\1\1\1\203\0\0" + "\0Z\0\0\0""9\0\0\0Y\0\0\0\223\0\0\0\251\0\0\0\254\0\0\0\254\0\0\0\254" + "\0\0\0\261\0\0\0\266\0\0\0\267\0\0\0\270\0\0\0\270\0\0\0\270\0\0\0\254" + "\0\0\0v\0\0\0""8\0\0\0Q\0\0\0\220\0\0\0\247\0\0\0\250\0\0\0\251\0\0\0" + "\251\0\0\0\251\0\0\0\251\0\0\0\252\0\0\0\253\0\0\0\254\0\0\0\256\0\0" + "\0\240\0\0\0k\0\0\0)\0\0\0\12\0\0\0\27\0\0\0=\1\1\1j\1\1\1\223\0\0\0" + "\261\0\0\0\311\0\0\0\316\0\0\0\330\1\1\1\344\1\1\1\351\3\4\3\351\2\2" + "\2\351\1\1\1\350\0\0\0\341\0\0\0\323\0\0\0\315\0\0\0\316\0\0\0\304\0" + "\0\0\257\0\0\0\246\0\0\0\221\1\1\1{\0\0\0k\0\0\0F\0\0\0:\0\0\0p\0\0\0" + "\242\0\0\0\257\0\0\0\256\0\0\0\270\0\0\0\310\0\0\0\317\0\0\0\315\0\0" + "\0\315\0\0\0\315\0\0\0\316\0\0\0\321\0\0\0\324\0\0\0\330\0\0\0\326\0" + "\0\0\322\0\0\0\316\0\0\0\316\0\0\0\316\0\0\0\304\0\0\0\255\0\0\0\232" + "\1\1\1v\0\0\0S\0\0\0/\0\0\0.\0\0\0[\0\0\0y\1\1\1\215\0\0\0\243\0\0\0" + "\253\0\0\0\300\0\0\0\315\0\0\0\315\0\0\0\324\0\0\0\341\2\2\2\350\7\7" + "\10\351\12\12\12\351\14\14\15\352\12\12\12\352\5\5\6\352\0\0\0\346\0" + "\0\0\327\0\0\0\316\0\0\0\307\0\0\0\257\1\1\1\217\1\1\1k\0\0\0G\0\0\0" + "7\0\0\0d\0\0\0\233\0\0\0\255\0\0\0\256\0\0\0\257\0\0\0\257\0\0\0\255" + "\0\0\0\253\0\0\0\251\0\0\0\250\0\0\0\251\0\0\0\250\0\0\0\250\0\0\0\221" + "\0\0\0V\0\0\0+\0\0\0Q\0\0\0\215\0\0\0\250\0\0\0\253\0\0\0\253\0\0\0\252" + "\0\0\0\255\0\0\0\263\0\0\0\266\0\0\0\267\0\0\0\270\0\0\0\265\0\0\0\242" + "\0\0\0f\0\0\0%\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\7\0\0\0B\0\0\0\254\"\"\13\357\377\377\232\377\372\372D\376" + "\374\374R\377\375\375O\377\375\375N\377\375\375N\377\375\375N\377\374" + "\374O\377\375\375N\377\374\374O\377\375\375O\377\375\375O\377\375\375" + "O\377\374\374N\377\375\375N\377\375\375N\377\375\375O\377\374\374O\377" + "\377\377R\377\277\277@\377\0\0\0\347\2\2\0\234\0\0\0;\0\0\0\11\0\0\0" + "\2\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\22\0\0\0)\0\0\0" + ">\0\0\0Q\0\0\0c\0\0\0k\0\0\0m\0\0\0l\0\0\0f\0\0\0[\0\0\0L\0\0\0B\0\0" + "\0.\0\0\0\17\0\0\0\4\0\0\0\4\0\0\0\3\0\0\0\3\0\0\0\4\0\0\0\4\0\0\0\4" + "\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\4\0\0\0\5\0\0\0\11\0\0\0\14\0\0\0\14\0" + "\0\0\14\0\0\0\24\0\0\0\37\0\0\0,\0\0\0;\0\0\0C\0\0\0Q\1\1\1a\1\1\1g\2" + "\2\2h\2\2\2m\2\2\2y\1\1\1\205\1\1\1\214\0\0\0\216\0\0\0\220\0\0\0\225" + "\0\0\0\235\0\0\0\242\0\0\0\234\0\0\0\225\0\0\0\217\1\1\1\207\2\2\2w\1" + "\1\1t\0\0\0{\0\0\0s\0\0\0d\0\0\0V\0\0\0O\0\0\0^\0\0\0i\1\1\1s\0\0\0y" + "\0\0\0x\0\0\0x\0\0\0\202\0\0\0\241\0\0\0\262\0\0\0\264\0\0\0\264\0\0" + "\0\260\0\0\0\233\0\0\0`\0\0\0\40\0\0\0#\0\0\0>\1\1\1J\1\1\1K\0\0\0K\0" + "\0\0H\0\0\0G\0\0\0Q\0\0\0g\0\0\0t\0\0\0x\0\0\0x\0\0\0p\0\0\0N\0\0\0\34" + "\0\0\0\5\0\0\0\11\0\0\0\27\0\0\0(\0\0\0\77\0\0\0V\1\1\1e\2\2\2q\1\1\2" + "\201\1\1\1\213\0\0\0\215\0\0\0\215\0\0\0\215\0\0\0\215\1\1\1\211\2\2" + "\2\200\2\2\2n\1\1\1h\0\0\0b\0\0\0N\0\0\0>\0\0\0""8\0\0\0*\0\0\0%\0\0" + "\0;\0\0\0e\0\0\0\201\0\0\0\214\0\0\0\220\0\0\0\223\0\0\0\225\1\1\1\205" + "\1\1\1m\2\2\2h\2\2\2k\2\2\2l\2\2\2s\2\2\2z\1\2\2|\1\1\1\201\1\1\1\177" + "\2\2\2~\2\2\2\202\1\1\1\211\1\1\1\213\0\0\0\211\0\0\0y\0\0\0l\0\0\0^" + "\0\0\0R\0\0\0J\0\0\0K\0\0\0Q\0\0\0L\0\0\0D\0\0\0>\0\0\0J\1\1\1_\1\1\1" + "g\2\2\2o\2\2\2\201\1\1\1\212\0\0\0\216\0\0\0\221\0\0\0\227\0\0\0\235" + "\0\0\0\226\0\0\0\217\1\1\1\214\2\2\2\200\1\1\1m\0\0\0b\0\0\0O\0\0\0""7" + "\0\0\0#\0\0\0\22\0\0\0.\0\0\0i\0\0\0\213\0\0\0\224\0\0\0\224\0\0\0\224" + "\0\0\0\221\0\0\0}\0\0\0[\0\0\0K\0\1\0K\0\0\0I\0\1\1G\0\0\0E\0\0\0""8" + "\0\0\0\40\0\0\0\24\0\0\0""7\0\0\0c\0\0\0t\0\0\0v\0\0\0t\0\0\0i\0\0\0" + "m\1\1\1\221\0\0\0\251\0\0\0\257\0\0\0\260\0\0\0\257\0\0\0\236\0\0\0d" + "\0\0\0$\0\0\0\14\0\0\0\13\0\0\0\13\0\0\0\12\0\0\0\10\0\0\0\3\0\0\0\3" + "\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\6\0\0\0\10\0\0\0\12\0\0\0\11\0" + "\0\0\6\0\0\0\12\0\0\0\77\0\0\0\242\6\6\0\344\305\305S\377\377\377\\\377" + "\374\374L\377\375\375N\377\375\375O\377\374\374N\377\375\375O\377\373" + "\373O\377\375\375O\377\374\374O\377\375\375N\377\374\374O\377\374\374" + "N\377\374\374O\377\374\374O\377\375\375O\377\374\374N\377\376\376N\377" + "\377\377Y\377\214\214-\377\0\0\0\341\2\2\0\230\0\0\0""6\0\0\0\5\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\30\0\0\0D\0\0\0z\0\0\0\242" + "\0\0\0\266\0\0\0\303\0\0\0\317\0\0\0\323\0\0\0\322\0\0\0\306\0\0\0\272" + "\0\0\0\265\0\0\0\254\0\0\0x\0\0\0A\0\0\0""9\0\0\0""8\0\0\0""5\0\0\0""8" + "\0\0\0""9\0\0\0""9\0\0\0""8\0\0\0""5\0\0\0""8\0\0\0""9\0\0\0""9\0\0\0" + "9\0\0\0J\0\0\0Y\0\0\0]\0\0\0U\0\0\0A\0\0\0(\0\0\0/\0\0\0B\0\0\0U\0\0" + "\0_\0\0\0c\0\0\0b\0\0\0[\0\0\0O\0\0\0G\0\0\0M\0\0\0W\0\0\0Z\0\0\0^\0" + "\0\0c\0\0\0p\0\0\0{\0\0\0x\0\0\0g\0\0\0J\0\0\0.\0\0\0.\0\0\0X\1\1\1\227" + "\0\0\0\264\0\0\0\265\0\0\0\265\0\0\0\265\0\0\0\265\1\1\1\244\0\0\0\254" + "\0\0\0\267\0\0\0\270\0\0\0\267\0\0\0\261\0\0\0\312\21\21\21\351\30\30" + "\31\355\26\26\27\356\11\11\12\344\0\0\0\272\0\0\0i\0\0\0<\0\0\0<\0\0" + "\0\77\0\0\0K\0\0\0T\0\0\0Q\0\0\0C\0\0\0""5\0\0\0J\0\0\0\206\0\0\0\260" + "\0\0\0\270\0\0\0\271\0\0\0\253\0\0\0p\0\0\0<\0\0\0""2\0\0\0;\0\0\0M\0" + "\0\0Y\0\0\0_\0\0\0`\0\0\0[\0\0\0R\0\0\0H\0\0\0L\0\0\0U\0\0\0W\0\0\0W" + "\0\0\0U\0\0\0V\0\0\0_\0\0\0a\0\0\0Z\0\0\0H\0\0\0""3\0\0\0""5\0\0\0E\0" + "\0\0R\0\0\0R\0\0\0h\0\0\0\262\0\0\0\325\0\0\0\330\0\0\0\330\3\3\3\332" + "\0\0\0\301\0\0\0}\0\0\0W\0\0\0b\0\0\0h\0\0\0i\0\0\0d\0\0\0X\0\0\0L\0" + "\0\0=\0\0\0/\0\0\0\77\0\0\0o\0\0\0\244\0\0\0\271\0\0\0\271\0\0\0\270" + "\0\0\0\267\0\0\0\266\0\0\0\265\0\0\0\265\0\0\0\265\0\0\0\257\0\0\0\206" + "\0\0\0P\0\0\0>\0\0\0A\0\0\0F\0\0\0V\0\0\0a\0\0\0a\0\0\0T\0\0\0V\0\0\0" + "h\0\0\0t\0\0\0s\0\0\0c\0\0\0U\0\0\0U\0\0\0T\0\0\0O\0\0\0H\0\0\0>\0\0" + "\0;\0\0\0<\0\0\0""6\0\0\0K\0\0\0\225\0\0\0\316\0\0\0\331\0\0\0\331\0" + "\0\0\331\1\1\1\320\0\0\0\231\0\0\0[\0\0\0W\0\0\0V\0\0\0G\0\0\0@\0\0\0" + "A\0\0\0\77\0\0\0:\0\0\0""8\0\0\0[\0\0\0\230\0\0\0\265\0\0\0\271\0\0\0" + "\260\0\0\0\214\0\0\0v\0\0\0\256\4\4\4\332\27\27\27\346\26\25\26\347\16" + "\16\16\345\0\0\0\307\0\0\0u\0\0\0M\0\0\0U\0\0\0X\0\0\0W\0\0\0O\0\0\0" + "B\0\0\0/\0\0\0*\0\0\0""7\0\0\0:\0\0\0:\0\0\0""9\0\0\0""9\0\0\0F\0\0\0" + "O\0\0\0L\0\0\0>\0\0\0.\0\0\0>\0\0\0{\0\0\0\275\20\20\3\356\304\304I\377" + "\377\377Y\377\377\377R\377\377\377O\377\376\376N\377\376\376N\377\374" + "\374N\377\375\375N\377\374\374N\377\375\375N\377\375\375N\377\375\375" + "N\377\374\374N\377\375\375N\377\377\377O\377\377\377S\377\377\377V\377" + "\255\2558\377\13\13\2\366\0\0\0\306\0\0\0{\0\0\0+\0\0\0\4\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\13\0\0\0:\1\1\1\202\0\0\0\303\22\22\23" + "\350tuv\370\243\244\246\372\257\260\263\375\257\260\264\376\256\257\262" + "\376\237\240\243\374\213\214\217\372STX\373\7\10\10\351\0\0\0\271\0\0" + "\0\250\0\0\0\252\0\0\0\246\1\1\1\237\0\0\0\247\0\0\0\251\0\0\0\252\0" + "\0\0\246\1\1\1\237\0\0\0\247\0\0\0\252\0\0\0\251\0\0\0\242\0\0\0\252" + "\0\0\0\300\0\0\0\310\0\0\0\271\0\0\0\230\0\0\0s\5\5\5\212\0\0\0\247\0" + "\0\0\262\0\0\0\275\0\0\0\301\0\0\0\273\0\0\0\257\0\0\0\243\1\1\1\204" + "\0\0\0\222\0\0\0\251\0\0\0\252\0\0\0\253\0\0\0\244\0\0\0\252\0\0\0\265" + "\0\0\0\261\0\0\0\225\0\0\0^\0\0\0\40\0\0\0!\0\0\0j\0\0\0\304DDE\364\215" + "\216\220\372~\177\202\371~\200\202\372\77\77B\370\0\0\0\333\40\40\40" + "\346\215\216\217\373\205\207\210\372qsw\373\31\31\33\354\37\37\40\347" + "\353\354\355\377\345\347\351\377\267\271\277\377114\367\0\0\0\311\0\0" + "\0\252\0\0\0\251\0\0\0\247\2\2\2\241\0\0\0\251\0\0\0\256\0\0\0\255\0" + "\0\0\242\0\0\0\202\5\5\5\221\0\0\0\306\30\31\32\356\203\204\207\372Q" + "RU\374\0\0\0\343\0\0\0\264\0\0\0\242\3\3\3\225\0\0\0\243\0\0\0\257\0" + "\0\0\272\0\0\0\301\0\0\0\274\0\0\0\260\0\0\0\243\1\1\1\206\2\2\2\210" + "\0\0\0\244\0\0\0\251\0\0\0\251\0\0\0\245\0\0\0\241\0\0\0\254\0\0\0\261" + "\0\0\0\257\0\0\0\240\0\0\0{\4\4\4\212\0\0\0\250\0\0\0\263\0\0\0\265\0" + "\0\0\256\0\0\0\324\224\224\226\376\333\334\336\377\277\301\305\377`a" + "f\377\0\0\0\336\1\1\1\255\0\0\0\254\0\0\0\270\0\0\0\277\0\0\0\274\0\0" + "\0\263\0\0\0\251\1\1\1\223\0\0\0h\0\0\0<\0\0\0D\0\0\0\215\0\0\0\326m" + "np\371rsu\372mnq\372nnq\372mop\372oor\372pqs\372ikn\372-..\363\0\0\0" + "\300\0\0\0\250\0\0\0\251\0\0\0\246\0\0\0\240\0\0\0\253\0\0\0\260\0\0" + "\0\254\2\1\2\232\2\2\2\231\0\0\0\254\0\0\0\260\0\0\0\256\0\0\0\233\1" + "\1\2\217\0\0\0\243\0\0\0\251\0\0\0\251\0\0\0\247\1\1\1\226\0\0\0\236" + "\0\0\0\252\0\0\0\250\0\0\0\246\0\0\0\273<=>\363\325\325\331\377\275\275" + "\301\377z{\177\377\16\16\16\361\1\1\1\272\0\0\0\251\0\0\0\262\0\0\0\260" + "\0\0\0\242\0\0\0\241\0\0\0\250\0\0\0\250\0\0\0\246\2\2\2\225\0\0\0\245" + "\0\0\0\327STU\366nnp\373\36\36\37\360\0\0\0\304\0\0\0\256\0\0\0\324\246" + "\247\251\375\355\356\360\377\313\315\323\377WX[\377\0\0\0\327\0\0\0\251" + "\0\0\0\254\0\0\0\270\0\0\0\276\0\0\0\273\0\0\0\260\0\0\0\247\1\1\1\212" + "\1\1\1}\0\0\0\240\0\0\0\250\0\0\0\250\0\0\0\246\2\2\2\240\0\0\0\252\0" + "\0\0\260\0\0\0\255\0\0\0\240\0\0\0}\0\0\0N\0\0\0M\1\1\0\202\0\0\0\274" + "\6\6\0\346gg#\373\310\310D\377\366\366Q\377\377\377U\377\377\377T\377" + "\377\377R\377\377\377Q\377\377\377Q\377\377\377Q\377\377\377Q\377\377" + "\377R\377\377\377T\377\377\377T\377\364\364O\377\300\300\77\377ZZ\35" + "\375\2\2\0\354\0\0\0\310\0\0\0\216\0\0\0K\0\0\0\27\0\0\0\2\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\26\0\0\0^\0\0\0\257\24\24\25\347\343" + "\343\345\377\377\377\377\377\344\346\353\377\347\352\361\377\344\347" + "\355\377\343\344\354\377\351\353\363\377\363\366\374\377uw{\377\0\0\0" + "\355NOO\362[[]\365QRT\366*+-\362\0\0\0\343ABD\362\\\\_\365QRT\365346" + "\363\0\0\0\343OOQ\363YZ[\365STV\365\33\33\35\355...\357\211\211\214\371" + "\215\216\221\374CDG\366\0\0\0\332\0\0\0\272\0\0\0\32599;\361vwx\366\213" + "\215\217\367\223\224\227\371\177\200\204\370OPS\366\16\16\17\355\0\0" + "\0\310\0\0\0\324HHI\365XY[\364NOP\366\30\30\31\355445\360z{~\367\77\77" + "B\366\0\0\0\314\1\1\1\204\0\0\0/\0\0\0""2\0\0\0\205\0\0\0\326\275\275" + "\277\376\377\377\377\377\342\344\352\377\356\360\367\377stz\377\0\0\0" + "\345kln\364\377\377\377\377\360\363\367\377\243\245\252\377\13\13\14" + "\360000\356\204\205\206\374bce\372DEH\375\0\0\0\351;;;\353_`b\365RSU" + "\365336\362\1\1\2\352]]_\364tvx\366LMO\367\10\11\11\352\0\0\0\310\0\0" + "\0\326STU\364\356\356\357\377\360\361\366\377\260\262\270\377JKL\370" + "NNQ\364#$%\357\0\0\0\330'()\356nnq\365\205\206\211\367\220\221\224\371" + "\200\202\205\370VWY\366\26\27\27\357\0\0\0\321\0\0\0\311EFF\357^^`\365" + "VWZ\365,-/\361\13\14\14\353hik\366{|~\366MNQ\367\7\7\10\350\0\0\0\277" + "\0\0\0\317223\361{}\177\366wy|\367:;=\362\0\0\1\354\352\352\351\376\332" + "\334\342\377\266\270\276\377./1\372\0\0\0\333\22\22\24\350aac\365z{}" + "\366\200\200\203\370{|~\370abd\366&&(\363\0\0\0\336\0\0\0\260\0\0\0m" + "\0\0\0e\0\0\0\251!!#\354\377\377\377\377\336\340\344\377\336\337\344" + "\377\346\350\355\377\347\350\356\377\346\351\357\377\360\361\370\377" + "\273\276\303\377\34\35\36\365\"\"\"\351fgh\366UVX\365BCE\363\12\12\12" + "\351efg\364|}\200\366AAD\365\0\0\0\340\0\0\0\337^_a\364|}\177\366HHK" + "\367\5\5\5\340\0\0\0\314556\354abc\365WYZ\365:;=\365\0\0\0\333--.\350" + "__a\366STV\36599<\364\0\0\0\342\216\217\220\370\353\354\356\377\260\261" + "\270\377VWZ\377\0\0\0\343\0\0\0\336WWX\364vwy\366[\\_\367\11\11\12\352" + ",--\353YY[\366KKM\365112\364\0\0\0\331\5\5\6\345\247\247\250\374\375" + "\375\377\377\331\332\337\377pqt\374RST\364EFH\362\12\11\12\351||}\373" + "llo\372WW[\375\27\30\30\363\0\0\0\327$$%\351pqr\365\206\207\210\367\217" + "\217\222\371\210\211\213\370hhl\366&&(\362\0\0\0\320\0\0\0\274000\351" + "eeg\366VWY\3659:<\363\2\2\2\350`ac\364}}\177\366QSU\366\11\11\12\347" + "\0\0\0\270\0\0\0p\0\0\0""6\0\0\0D\1\1\0w\1\1\0\252\0\0\0\317\5\5\0\350" + "00\20\366ee!\376\220\2200\377\265\265<\377\313\313B\377\311\311B\377" + "\312\312B\377\313\313B\377\264\264:\377\215\215.\377aa\37\377,,\15\370" + "\2\2\0\353\0\0\0\322\1\1\0\261\0\0\0\203\0\0\0J\0\0\0\34\0\0\0\6\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\37\1\1\2p\0\0\0\314\214" + "\214\216\373\377\377\377\377\266\272\303\377\301\304\314\377ux}\376<" + "=@\374;<>\373HJN\374XY]\375'(*\370\14\14\15\356\372\373\373\377\366\367" + "\372\377\314\315\325\377447\372\0\0\0\353\342\343\345\377\374\375\377" + "\377\327\332\340\377EGI\373\13\14\13\357\377\377\377\377\357\361\365" + "\377\362\363\372\377\264\267\272\376\365\366\370\377\356\357\364\377" + "\360\362\370\377\304\307\316\377-.0\364\0\0\0\337\220\221\222\372\377" + "\377\377\377\360\362\365\377\316\320\325\377\265\267\274\377\343\346" + "\354\377\353\355\364\377\243\246\254\377\25\26\26\357\7\7\10\347\361" + "\362\364\377\356\357\362\377\343\346\354\377\245\246\252\377\365\366" + "\370\377\333\334\341\377FGI\377\0\0\0\324\2\2\2\203\0\0\0""1\0\0\0I\0" + "\0\0\242\25\25\26\347\353\353\354\377\302\304\314\377\264\267\300\377" + "\304\306\317\377\214\216\223\377\0\0\0\360\277\277\277\374\343\347\354" + "\377\273\276\310\377VW[\376\0\0\0\354\262\262\263\373\377\377\377\377" + "\353\355\361\377stz\376\0\0\0\356\324\324\324\375\372\374\377\377\357" + "\361\367\377\263\265\271\376\317\317\320\377\370\371\374\377\344\347" + "\354\377\327\332\340\377UVZ\375\21\21\21\356\264\264\265\374\373\373" + "\375\377\302\304\313\377\250\252\263\377\277\301\311\377\352\355\363" + "\377\307\310\317\377\37\40\"\370rrr\370\377\377\377\377\356\357\364\377" + "\316\320\326\377\257\260\266\377\334\336\344\377\357\362\370\377\266" + "\271\277\377!!\"\364\0\0\1\350\337\337\340\377\374\375\377\377\367\371" + "\377\377\265\267\274\376\341\342\342\376\371\372\375\377\361\362\370" + "\377\335\340\347\377MMQ\374\0\0\0\344ijk\366\377\377\377\377\357\360" + "\365\377\353\356\363\377\344\347\360\377\267\267\271\377\341\342\346" + "\377\267\272\302\377\210\212\220\377\5\5\6\363DDE\362\367\367\370\377" + "\354\356\361\377\342\343\351\377\340\342\346\377\331\332\337\377\334" + "\335\343\377\307\311\317\377DDG\376\0\0\0\322\1\1\1\224\0\0\0\205\0\0" + "\0\277opr\366\352\353\356\377\243\245\255\377\234\237\244\377QRW\375" + "KMQ\374MNR\374OQU\374<>A\374\0\0\0\353\236\236\240\371\377\377\377\377" + "\347\351\356\377\316\320\326\377\314\314\316\376\371\372\375\377\350" + "\352\357\377\334\337\347\377lnr\373\276\276\276\375\376\377\377\377\350" + "\353\360\377\327\331\340\377CDG\371\0\0\0\342\300\300\300\375\374\375" + "\377\377\343\345\353\377STX\375\0\0\0\347\261\261\261\373\373\374\377" + "\377\333\334\342\377YZ]\375\0\0\0\357\335\336\340\377\265\267\275\377" + "\226\227\234\377++,\372\0\0\0\350\305\305\307\375\356\357\362\377\317" + "\317\324\377\322\324\331\377\255\255\262\377\311\311\314\376\347\347" + "\353\377\316\316\324\377EEH\374SSS\366\354\354\355\377\334\335\341\377" + "\245\247\256\377\256\260\267\377\325\330\336\377\355\357\365\377jlq\376" + "EED\366\377\377\377\377\361\363\366\377\261\263\270\377\10\10\11\361" + "\\\\]\362\375\375\376\377\363\365\371\377\355\357\365\377\353\356\363" + "\377\344\346\354\377\347\351\357\377\312\314\323\3779:<\366\0\0\0\335" + "\265\265\267\374\377\377\377\377\347\351\357\377\275\277\304\377\315" + "\316\317\376\367\370\373\377\345\347\355\377\332\335\343\377UWZ\377\0" + "\0\0\331\2\2\2\213\0\0\0.\0\0\0\26\0\0\0.\0\0\0Q\5\5\1v\1\1\0\227\0\0" + "\0\263\0\0\0\303\0\0\0\320\0\0\0\342\10\10\1\360\10\10\1\361\10\10\1" + "\362\10\10\1\361\0\0\0\345\0\0\0\322\0\0\0\305\0\0\0\267\2\2\0\234\4" + "\4\1|\0\0\0X\0\0\0""5\0\0\0\26\0\0\0\6\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\5\0\0\0\"\3\3\4s\0\0\0\320\273\275\300\377\355\357" + "\364\377\305\311\322\377\320\323\333\377\204\205\211\375opq\371yz{\372" + "MNQ\370\2\2\2\356\0\0\0\334NNP\363\377\377\377\377\262\266\300\376}\177" + "\203\377\2\3\2\357--.\357\377\377\377\377\266\272\302\377\215\216\226" + "\377\2\2\2\364aab\364\370\370\373\377\265\271\302\377\257\262\272\377" + "\206\210\215\377\240\243\251\377\303\307\320\377\276\301\311\377\273" + "\276\306\377347\370LLL\364\377\377\377\377\306\312\322\377\256\261\271" + "\377\36\36\40\371\0\0\0\361\203\203\204\373\345\347\357\377\256\260\267" + "\377''*\367III\364\377\377\377\377\244\247\257\377\256\261\270\377\303" + "\305\315\377\305\310\320\377\216\220\226\377\23\24\24\372\0\0\0\304\0" + "\0\0j\0\0\0+\0\0\0c\0\0\0\273QQT\364\377\377\377\377\272\275\306\377" + "\313\316\326\377\312\315\326\377\273\276\305\377767\372\375\374\374\377" + "\314\317\327\377\264\267\276\377024\372\0\0\0\354\362\362\363\377\316" + "\322\331\377\252\255\265\377%&(\371\34\34\35\357\366\366\367\377\271" + "\274\304\377\264\267\277\377\271\274\303\377\305\307\317\377\251\255" + "\265\377\252\255\264\377\265\270\300\377GIK\374aac\372\372\373\377\377" + "\262\264\274\377\262\264\273\377\257\261\270\377uw|\377ghm\377XY^\377" + ":::\371\377\377\377\377\307\312\321\377\263\266\277\377,-/\372\0\0\0" + "\361XXY\371\365\370\375\377\267\272\302\37767:\373333\363\377\377\377" + "\377\276\301\312\377\303\306\317\377\310\313\323\377\321\323\334\377" + "\272\276\307\377\275\300\311\377\276\301\311\377FGJ\374\30\30\30\363" + "\377\377\377\377\307\312\321\377\264\267\277\377\177\201\207\377\202" + "\204\211\377\311\314\324\377\263\266\276\377\272\274\304\377fhk\376\2" + "\2\2\363\364\364\364\377\312\313\322\377\241\243\253\377ghm\377OQU\377" + "\245\246\255\377\253\255\265\377\262\265\273\376jko\377\0\0\0\340\2\2" + "\2\251\0\0\0\235\0\0\0\322\272\272\273\376\321\323\330\377\260\262\271" + "\377\250\252\260\377mop\371|||\370}}|\370uuu\371--/\364\0\0\0\345\344" + "\345\347\377\306\311\317\377\270\273\304\377\267\272\301\377\306\310" + "\320\377\266\271\302\377\267\272\301\377\303\305\316\377\323\325\335" + "\377\326\330\336\377\267\272\302\377\270\273\303\377\272\274\304\377" + "679\372\23\23\25\355\365\365\366\377\272\274\304\377\230\232\240\377" + "\30\30\31\364\2\2\3\347\351\352\354\377\261\262\271\377\222\223\232\377" + "\31\31\32\366++-\357\367\367\371\377\242\243\252\377\204\204\211\377" + "\0\0\0\362\223\223\224\370\354\354\357\377\225\226\235\377\201\201\207" + "\377QQU\377\227\227\234\377\247\250\257\377\233\234\243\377\213\214\221" + "\377\23\23\24\372\267\267\271\376\312\313\321\377\241\243\252\377\271" + "\274\302\377\216\220\225\377ijo\377cei\377\25\26\30\371\234\234\233\371" + "\350\352\357\377\276\302\313\377cei\376\22\22\22\363\375\375\374\377" + "\321\324\333\377\267\272\302\377egj\377UW[\375\274\277\307\377\272\275" + "\305\377\302\305\315\377^_c\374\1\1\0\354\366\366\367\377\270\273\302" + "\377\265\271\301\377\264\267\276\377\302\303\313\377\262\265\275\377" + "\265\271\300\377\273\276\305\377IJL\377\0\0\0\330\2\2\2\212\0\0\0+\0" + "\0\0\4\0\0\0\10\0\0\0\24\0\0\0&\0\0\0<\1\1\0P\2\2\0c\3\3\1z\2\2\1\227" + "\1\1\0\253\1\1\0\254\1\1\0\255\1\1\0\254\2\2\0\235\3\3\1~\2\2\0g\1\1" + "\0T\0\0\0@\0\0\0)\0\0\0\27\0\0\0\11\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\15\0\0\0""7\1\1\1\202\0\0\0\314QRV\371" + "\262\264\272\377\253\256\264\377\261\264\273\377\336\340\350\377\355" + "\360\365\377\363\365\370\377\351\354\361\377iko\376\0\0\0\352\254\255" + "\256\372\345\347\354\377\264\267\300\377TUX\376\0\0\0\350\211\211\213" + "\367\355\356\361\377\273\276\306\377ikn\377\0\0\0\357\265\265\266\373" + "\345\346\353\377\275\301\312\377QRU\376\0\0\0\347\30\31\32\356\356\357" + "\362\377\306\311\322\377\267\273\301\377\36\37!\370\275\275\274\374\343" + "\346\353\377\275\300\311\377\304\307\316\377\266\270\276\377\321\321" + "\325\376\325\326\331\377\301\304\314\377\205\207\215\377\3\4\5\366\257" + "\256\256\372\342\343\347\377\260\262\271\377\251\253\262\377ijo\377[" + "]`\377HIK\377\5\5\6\360\0\0\0\254\0\0\0M\0\0\0/\2\2\2\200\0\0\0\321\240" + "\241\242\373\356\357\364\377\300\304\315\377\220\223\231\377\254\256" + "\264\376\324\327\337\377\275\277\304\376\337\341\346\377\310\314\325" + "\377\220\223\230\377\2\2\2\361MNP\362\372\373\374\377\305\310\322\377" + "\222\225\232\377\0\0\0\363ggi\365\375\376\377\377\270\273\304\377\225" + "\227\235\377%%'\371LMO\371\327\332\337\377\263\266\275\377\246\251\257" + "\377##%\367\0\0\0\344\223\224\227\373\332\334\342\377\272\274\305\377" + "]^b\377\0\0\0\350\0\0\0\325\0\0\0\343\241\241\241\374\354\356\363\377" + "\270\273\303\377\305\310\320\377\263\265\274\376\321\323\327\376\326" + "\327\331\377\323\325\334\377\232\234\243\377\20\21\23\367\204\203\203" + "\371\373\374\377\377\304\306\317\377\223\225\232\377\"#$\370ceh\372\346" + "\351\360\377\302\305\316\377\251\253\262\377\22\23\25\370\222\221\220" + "\371\362\363\366\377\270\274\304\377rtx\377\5\4\4\357\0\0\0\352\315\317" + "\321\377\305\307\317\377\253\255\263\377/03\373__^\367\366\366\371\377" + "\255\257\270\377opu\377\3\3\3\356\0\0\0\337\224\225\230\374\330\331\337" + "\377\257\260\270\377NPS\377\0\0\0\332\1\1\1\255\0\0\0\263\22\23\23\347" + "\355\356\361\377\264\267\275\377\261\263\271\377\244\246\254\377\262" + "\264\271\377\274\276\303\377\301\303\310\377\251\253\260\377%&'\365;" + "<=\360\371\372\373\377\302\305\316\377\231\234\242\377\32\32\34\367]" + "_`\371\341\344\352\377\301\304\315\377\244\247\255\377##%\371EFH\367" + "\342\344\352\377\276\301\311\377\240\242\251\377\15\15\16\364__`\363" + "\373\373\376\377\262\265\275\377uw|\377\0\0\0\351IIK\356\365\366\370" + "\377\246\247\256\376wx}\377\0\0\0\356\207\210\212\366\335\336\342\377" + "\236\237\246\377[[^\377\14\15\15\361\353\353\354\376\251\252\260\377" + "\222\224\231\377\"\"#\371\0\0\0\342MMO\365\322\322\326\377\244\246\255" + "\377efi\377\0\0\0\350\20\21\22\354\340\341\345\377\264\265\275\377\236" + "\241\246\377\25\25\27\366\0\0\0\331\0\0\0\326\4\5\6\351\335\335\336\377" + "\323\325\335\377\300\302\312\377-.0\372qqq\370\374\375\377\377\277\302" + "\312\377kmq\377\0\0\0\347\0\0\0\340\263\263\265\376\324\327\336\377\272" + "\275\304\377;=\77\373OOM\365\370\371\373\377\271\274\305\377\232\234" + "\241\377\"#$\370\77@C\367\337\342\347\377\276\301\312\377\255\257\266" + "\377\40!\"\374\0\0\0\306\0\0\0r\0\0\0\"\0\0\0\2\0\0\0\0\0\0\0\1\0\0\0" + "\4\0\0\0\11\0\0\0\17\0\0\0\27\0\0\0%\0\0\0""4\1\1\0;\1\1\0<\1\1\0<\1" + "\1\0<\0\0\0""7\0\0\0'\0\0\0\31\0\0\0\20\0\0\0\11\0\0\0\5\0\0\0\1\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0" + "\0\33\0\0\0]\0\0\0\261\7\7\7\342\10\10\11\355\15\15\15\363\24\24\25\370" + "\15\15\16\370qrs\374\334\337\345\377\261\264\275\377\300\304\313\377" + "^`c\377\7\7\7\365\364\363\363\376\306\310\320\377\264\266\276\377236" + "\371\0\0\0\352\336\335\335\376\325\326\335\377\267\272\301\37778;\374" + "\15\15\16\357\353\353\354\377\312\315\324\377\300\303\312\377;;>\372" + "\0\0\0\341zyx\365\370\371\374\377\315\320\332\377\210\212\220\377\16" + "\16\17\367\377\377\377\376\311\313\323\377\310\312\323\377]_c\375\27" + "\27\31\366\40!\"\366\32\33\35\367()+\371!\"#\365\3\2\3\356\352\352\352" + "\376\305\310\316\377\257\261\271\377@AC\376\0\0\0\352\0\0\0\341\0\1\1" + "\345\0\0\0\315\0\0\0\216\0\0\0""9\0\0\0A\3\3\3\235\0\0\0\343\352\352" + "\354\377\323\326\335\377\272\275\305\377*+-\373tux\372\357\362\367\377" + "\301\303\315\377\301\303\314\377\316\321\331\377acg\377\0\0\0\355\233" + "\234\235\371\356\360\365\377\302\305\316\377fhk\377\0\0\0\356\271\271" + "\272\374\340\342\347\377\266\271\302\377IJM\376\0\0\0\342\77\77@\360" + "\367\370\374\377\265\270\301\377\204\205\214\377\10\11\11\357\4\4\5\343" + "\332\332\334\377\312\314\323\377\273\275\306\377<>@\374\0\0\0\342\7\7" + "\7\320\4\4\6\336\322\322\324\377\326\331\337\377\310\313\324\377tuz\376" + "\30\30\31\367\40!$\366\36\37\"\366*+-\371124\371\0\0\0\360\327\327\327" + "\375\336\340\347\377\275\301\311\377@AD\376\0\0\0\341_`a\364\374\376" + "\377\377\300\303\313\377\200\202\207\377\0\0\0\364\325\325\325\375\332" + "\333\340\377\273\275\306\377`bf\376\0\0\0\346JJI\361\372\373\374\377" + "\271\273\303\377\221\223\230\377\3\3\5\365\216\217\221\371\351\353\356" + "\377\255\257\267\377^_c\377\0\0\0\345\11\11\11\345\347\347\350\377\312" + "\314\323\377\242\245\254\377$$&\377\0\0\0\325\0\0\0\253\0\0\0\306ZZ[" + "\366\366\367\371\377\251\254\263\377\266\270\277\377779\373\40\40\40" + "\365##$\366&%%\367\34\34\35\366\0\0\0\343\214\214\217\367\357\361\365" + "\377\277\303\314\377OPS\376\0\0\0\341hik\362\363\364\367\377\303\307" + "\320\377bcg\377\0\0\0\343JKL\356\372\373\376\377\275\300\311\377vwz\377" + "\0\0\0\355\272\272\275\372\333\335\342\377\260\263\272\377jko\376\0\0" + "\0\352\275\274\275\373\323\325\331\377\245\247\256\377HHK\377\0\0\0\352" + "\321\322\322\374\271\272\300\377\234\236\244\377-.0\371)*+\360\362\362" + "\365\377\233\234\242\377\227\230\236\377\"\"#\364\16\16\17\345\312\312" + "\312\374\305\306\313\377\243\244\253\377<<\77\374\0\0\0\335`ac\363\365" + "\366\371\377\262\264\275\377\223\224\232\377\7\7\10\357\11\11\11\325" + "\2\1\2\315446\354\376\377\377\377\310\314\325\377\237\242\250\377\3\4" + "\4\365\251\252\253\373\355\356\363\377\301\304\314\377ijn\377\0\0\0\343" + "444\353\372\373\375\377\310\313\323\376\237\241\247\377\12\13\14\367" + "\253\252\252\371\344\344\351\377\275\300\310\377RSU\376\0\0\0\341GGH" + "\360\365\367\370\377\305\307\321\377\210\213\220\377\6\6\6\363\0\0\0" + "\262\0\0\0Z\0\0\0\25\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\3\0\0\0\3\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\5\0\0\0\4\0\0" + "\0\3\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\12\0\0\0/\0\0\0\200\0\0\0" + "\321\261\261\262\375\377\377\377\377\343\344\351\376\337\337\341\375" + "\335\335\335\375\355\355\357\377\323\325\335\377\311\315\325\377\234" + "\235\243\377\37\40!\373\"#$\363\345\347\352\377\303\306\316\377\300\302" + "\312\377\277\301\307\377\332\333\335\376\355\357\364\377\275\277\310" + "\377{}\202\377\7\7\10\364EEF\363\377\377\377\377\271\275\306\377\307" + "\313\322\377\311\314\323\377\333\335\337\377\377\377\377\377\326\331" + "\341\377\253\255\264\377224\374\0\0\0\355\321\322\330\377\326\331\341" + "\377\313\316\326\377\253\255\263\376|}\200\370\221\222\224\370\260\260" + "\260\371\205\206\212\376\0\0\0\351EFH\360\377\377\377\377\301\304\314" + "\377\210\212\217\377\14\14\14\365\0\0\0\275\1\1\2\211\0\0\0\200\0\0\0" + "t\0\0\0N\0\0\0*\0\0\0\\\0\0\0\267EEG\361\377\377\377\377\321\324\336" + "\377\223\226\233\377\11\11\12\363235\363\365\367\374\377\313\316\327" + "\377\320\323\334\377\275\300\307\377013\373\3\3\4\353\345\345\346\376" + "\334\336\346\377\266\272\302\377669\373\11\12\12\356\377\377\377\377" + "\317\322\331\377\243\246\254\377$%&\370\0\0\0\336\240\240\243\373\364" + "\366\372\377\270\273\303\377WX[\377\0\0\0\344013\356\377\377\377\377" + "\302\305\315\377\310\313\324\377\304\306\314\376\261\263\270\376lns\377" + "\3\3\4\357\263\265\271\376\340\343\352\377\316\321\332\377\270\272\301" + "\376\201\202\206\371\222\223\224\367\254\254\254\371\241\242\244\375" + "\33\34\34\365\"#$\357\377\377\377\377\326\330\341\377\243\245\254\377" + "\31\32\33\366\0\0\0\341\306\306\310\375\356\360\365\377\275\300\310\377" + "KLO\376\0\0\0\356\273\274\301\377\335\337\345\377\272\275\305\377\307" + "\311\320\377\303\305\312\377\360\360\363\377\313\316\324\377\274\276" + "\306\377bch\377\0\0\0\352GHK\366\326\327\336\377\263\265\274\377\275" + "\277\307\377\260\261\265\376\346\347\350\377\343\345\352\377\257\261" + "\271\377SUY\377\2\2\3\356\0\0\0\277\0\0\0\256\0\0\0\327\267\271\273\376" + "\340\342\347\377\270\272\302\377\300\301\312\377\340\343\351\377\367" + "\367\373\377\370\371\374\377\372\373\377\377lmq\376\3\3\4\354\340\340" + "\341\376\337\341\350\377\255\260\267\377&&'\371\0\0\0\342\307\311\312" + "\375\350\353\361\377\266\271\300\377568\374\0\0\0\340\255\256\260\372" + "\361\363\370\377\263\267\276\377@AD\376\0\0\0\345\255\256\262\376\320" + "\322\330\377\261\263\272\377\274\276\305\377\327\330\333\377\342\343" + "\347\377\252\253\262\377wx}\377\13\13\14\366++-\357\365\365\367\377\251" + "\252\261\377\205\206\213\377\14\15\15\362!!\"\354\323\324\331\377\247" + "\250\256\377\255\256\264\377\266\267\275\377\305\305\310\377\325\325" + "\332\377\260\260\267\377\224\225\233\377\34\33\35\364\0\0\0\332\247\250" + "\252\375\347\350\355\377\272\274\305\377\313\316\325\377\314\316\324" + "\377\246\250\256\377\32\33\35\365\230\230\230\370\377\377\377\377\313" + "\315\327\377lmq\377\0\0\0\352SUX\370\342\344\352\377\306\312\322\377" + "\323\326\336\377\322\323\327\377\370\372\374\377\331\334\342\377\246" + "\250\261\377;;>\377\17\17\20\361\364\364\365\377\317\323\333\377\255" + "\257\267\377'')\370\0\0\0\340\252\253\255\373\361\363\370\377\310\313" + "\324\377TVY\377\0\0\0\341\1\1\1\224\0\0\0>\0\0\0\13\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\15\0\0\0;\0\0\0\222\17\17\20\337\216\220\225\377\212\213\220\377" + "\215\217\225\377\230\233\240\377\243\245\253\377\223\226\235\377\202" + "\205\211\377iko\377))+\375\0\0\0\337\0\0\0\335FHK\373{}\201\377\210\212" + "\217\377\226\230\236\377\217\220\226\377tu{\377NOQ\377\24\25\26\365\0" + "\0\0\343\237\237\241\372\357\361\365\377\302\305\317\377suz\377@AD\372" + "\230\232\240\377\213\215\223\377xy\177\377235\377\0\0\0\345\0\0\0\325" + "346\367\177\201\207\377\207\211\217\377\222\225\232\377\247\251\257\377" + "\234\236\243\377}~\202\377,-/\372\0\0\0\344_`c\371\215\216\223\377ii" + "m\377ABE\377\2\3\3\352\0\0\0\240\0\0\0H\0\0\0!\0\0\0\34\0\0\0\21\0\0" + "\0\37\0\0\0p\0\0\0\316ikn\374\222\223\230\377rty\377FGJ\377\1\1\1\346" + "\11\11\12\346\203\204\212\377tw|\377tuz\377]^b\377\21\21\21\362\"#$\355" + "\242\244\250\377oqu\377]^b\377\20\20\21\36689;\365\234\236\243\377jm" + "q\377RTW\377\14\14\15\357\0\0\0\345\220\221\226\377wy}\377cdi\377&'(" + "\375\0\0\0\330\37\37\40\353\221\223\230\377\211\213\221\377\207\211\216" + "\377\206\207\215\377tv{\377\33\33\35\365\0\0\0\332%&(\363{}\202\377\212" + "\214\222\377\225\227\235\377\254\257\264\377\246\250\255\377\210\212" + "\217\377\77AC\374\0\0\0\350TUX\371\231\233\237\377rty\377OPS\377\2\1" + "\2\353\13\14\14\352\232\234\240\377vx}\377bch\377\36\36\40\371\0\0\0" + "\33477;\365\206\207\214\377\177\201\205\377fhl\377<<\77\374RSW\376km" + "q\377dei\377++-\376\0\0\0\334\0\0\0\343IKM\376tv{\377\201\203\207\377" + "\226\227\234\377\207\210\217\377jlq\377<=\77\377\7\7\10\357\0\0\0\312" + "\0\0\0\232\0\0\0\242\13\13\13\340uw{\376Y[_\376WX[\376XY\\\376UV[\376" + "TUY\376VX\\\376QSW\377\27\30\30\364\26\27\30\352\200\202\206\377\\]`" + "\376KLM\377\12\12\13\355\13\13\13\342\200\200\205\377^_b\375NOR\377\21" + "\21\22\360\0\0\0\332vw{\375``d\376MNQ\377\26\25\27\363\0\0\0\320\34\34" + "\36\356YZ\\\377mnr\377yy~\377pqv\377Y[^\377>>A\377\17\20\20\366\0\0\0" + "\33388:\362hil\377JKN\376578\377\3\3\2\344\0\0\0\332ABD\373hhl\377^^" + "b\37778:\375\27\27\31\366RSV\376RSV\376>\77A\377\6\7\6\351\0\0\0\323" + "FHI\370}\177\204\377suy\377rty\377jkp\377568\373\0\0\0\343xy}\372hjn" + "\376XZ]\376*+-\375\0\0\0\326\1\1\1\336\77@C\374npt\377\200\202\207\377" + "\213\216\223\377ux}\377Z[_\377%&'\375\0\0\0\344**,\350~\200\204\377X" + "Z]\376HJM\377\14\14\15\355\5\5\5\337z{~\375cei\376VX[\377\40!\"\372\0" + "\0\0\314\1\1\1v\0\0\0(\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\14\0\0\0""6\0\0" + "\0\203\0\0\0\304\0\0\0\342\0\0\0\347\6\6\6\346\11\12\12\347\15\15\16" + "\352\13\13\14\352\7\7\10\347\0\0\0\346\0\0\0\325\0\0\0\254\0\0\0\252" + "\0\0\0\324\2\2\2\345\12\12\13\347\14\14\15\353\10\10\10\350\4\4\4\350" + "\0\0\0\337\0\0\0\306\0\0\0\342\326\330\334\377\306\310\317\377\242\245" + "\253\377-.0\375\0\0\0\341\6\6\6\344\13\13\13\350\4\4\4\346\0\0\0\332" + "\0\0\0\265\0\0\0\250\0\0\0\315\0\0\0\344\11\11\11\346\10\11\11\350\3" + "\3\4\347\0\0\0\346\0\0\0\345\0\0\0\315\1\1\1\301\4\4\4\340\0\0\0\347" + "\0\0\0\347\1\1\1\344\0\0\0\321\0\0\0\212\0\0\0""3\0\0\0\7\0\0\0\0\0\0" + "\0\0\0\0\0\32\0\0\0f\1\1\1\275\4\5\5\343\0\0\0\346\0\0\0\347\1\1\1\346" + "\0\0\0\314\0\0\0\310\1\1\1\345\0\0\0\347\0\0\0\346\0\1\0\350\0\0\0\325" + "\4\4\5\322\0\0\0\347\0\0\0\346\1\0\1\347\0\0\0\331\4\5\5\336\0\0\0\347" + "\0\0\0\347\1\1\1\350\0\0\0\324\3\3\3\320\1\1\2\347\0\0\0\346\0\0\0\347" + "\1\1\1\341\0\0\0\275\0\0\0\310\3\3\3\344\12\12\13\347\7\7\10\347\3\3" + "\3\347\0\0\0\350\0\0\0\323\1\1\1\257\0\0\0\310\0\0\0\345\11\11\11\347" + "\12\12\12\350\5\5\6\347\0\0\0\347\0\0\0\345\0\0\0\321\0\0\0\304\5\5\5" + "\340\0\0\0\347\0\0\0\347\1\1\1\347\0\0\0\320\4\4\4\324\0\0\1\347\0\0" + "\0\346\0\0\0\347\0\0\0\335\0\0\0\272\0\0\0\313\4\4\4\345\10\10\10\346" + "\1\1\1\346\0\0\0\333\2\2\3\343\0\0\0\347\0\0\0\350\1\1\1\337\0\0\0\273" + "\0\0\0\263\0\0\0\327\2\2\3\346\11\11\12\347\12\12\12\351\10\10\10\347" + "\3\3\3\346\0\0\0\334\0\0\0\275\0\0\0\223\0\0\0l\0\0\0~\0\0\0\265\0\0" + "\0\313\0\0\0\313\0\0\0\313\0\0\0\313\0\0\0\313\0\0\0\313\0\0\0\313\0" + "\0\0\314\0\0\0\300\0\0\0\270\0\0\0\313\0\0\0\313\0\0\0\315\0\0\0\276" + "\0\0\0\267\0\0\0\314\0\0\0\312\0\0\0\315\0\0\0\277\0\0\0\263\0\0\0\310" + "\0\0\0\313\0\0\0\315\0\0\0\300\0\0\0\236\0\0\0\267\0\0\0\324\2\2\2\343" + "\10\10\10\345\5\5\5\345\0\0\0\342\0\0\0\323\0\0\0\277\1\1\1\253\0\0\0" + "\303\0\0\0\315\0\0\0\313\0\0\0\313\0\0\0\262\0\0\0\252\0\0\0\316\2\2" + "\2\344\1\1\1\345\0\0\0\322\0\0\0\302\0\0\0\312\0\0\0\313\0\0\0\313\0" + "\0\0\271\0\0\0\253\0\0\0\316\2\2\2\343\5\4\5\345\0\0\0\345\0\0\0\332" + "\0\0\0\310\1\1\2\265\0\0\0\305\0\0\0\314\0\0\0\314\0\0\0\311\0\0\0\247" + "\0\0\0\244\0\0\0\311\0\0\0\336\7\7\7\346\11\11\11\346\5\5\5\346\0\0\0" + "\336\0\0\0\313\1\1\1\260\0\0\0\267\0\0\0\313\0\0\0\313\0\0\0\314\0\0" + "\0\275\0\0\0\266\0\0\0\312\0\0\0\313\0\0\0\314\0\0\0\304\0\0\0\242\0" + "\0\0X\0\0\0\30\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\7\0\0\0\36\0\0\0L\0\0\0" + "q\3\3\3\201\2\2\2\204\0\0\0\212\0\0\0\225\0\0\0\235\0\0\0\235\0\0\0\224" + "\1\1\1\210\1\1\1{\0\0\0Y\0\0\0Y\3\3\3z\1\1\1\207\0\0\0\224\0\0\0\233" + "\0\0\0\227\0\1\1\214\2\2\2\177\0\0\0\227\31\32\33\337KLO\375/02\374/" + "/2\376\16\17\17\360\0\0\0\267\0\1\1\221\0\0\0\225\0\0\0\215\1\2\2~\0" + "\0\0`\0\0\0T\2\2\2s\2\2\2\205\0\0\0\217\0\0\0\226\1\1\0\220\2\2\2\210" + "\3\3\3\204\1\1\1t\0\0\0m\0\0\0\201\3\3\3\204\1\1\2\204\0\0\0\203\0\0" + "\0x\0\0\0P\0\0\0\35\0\0\0\3\0\0\0\0\0\0\0\0\0\0\0\16\0\0\0:\0\0\0l\0" + "\0\0\202\3\3\3\204\2\2\2\204\0\0\0\204\0\0\0v\0\0\0s\2\1\2\203\2\2\2" + "\204\2\2\2\204\1\1\1\204\0\0\0{\0\0\0x\2\2\2\203\2\2\2\204\1\1\1\204" + "\0\0\0}\0\0\0\177\3\3\3\204\2\2\2\204\1\1\1\204\0\0\0z\0\0\0x\1\1\1\203" + "\2\2\2\204\1\1\1\204\0\0\0\202\0\0\0m\1\1\1t\1\1\1\212\0\0\0\220\0\0" + "\0\215\1\1\1\206\2\2\2\205\0\0\0y\0\0\0b\2\2\2r\2\2\2\206\0\0\0\220\0" + "\0\0\230\0\0\0\224\2\2\2\212\3\3\3\204\2\2\2w\0\0\0o\0\0\0\200\3\3\3" + "\204\2\2\2\204\1\1\1\204\0\0\0w\0\0\0z\2\2\2\204\2\2\2\204\1\1\1\204" + "\0\0\0\200\0\0\0k\2\2\2v\1\1\1\212\0\0\0\217\1\1\1\211\2\2\2~\0\0\0\201" + "\2\2\2\204\1\1\1\204\0\0\0\200\0\0\0j\0\0\0]\3\3\3y\1\1\1\210\0\0\0\222" + "\0\0\0\231\0\0\0\224\1\1\1\211\2\2\2\177\0\0\0f\0\0\0B\0\0\0""1\0\0\0" + "A\0\0\0c\4\5\5n\4\4\4m\3\4\4n\4\4\4m\3\4\4n\3\4\4m\4\4\4n\3\3\4n\1\1" + "\1i\0\0\0d\5\5\5n\4\4\4m\3\3\3n\0\0\0b\0\0\0d\5\5\5o\4\4\4m\3\3\3o\0" + "\0\0i\0\0\0d\4\4\5o\4\4\4m\3\3\3n\0\0\0i\0\0\0R\1\1\1\\\3\3\3v\1\1\1" + "\206\0\0\0\217\0\0\0\215\1\1\1\204\2\2\2t\1\1\1\\\0\0\0W\1\2\2m\4\4\5" + "o\3\3\3n\2\2\2n\0\0\0^\0\0\0W\2\3\3u\1\1\1\202\1\1\1\203\2\2\2v\0\0\0" + "h\3\3\3n\3\3\3m\2\2\2m\0\0\0`\0\0\0Z\3\3\3u\1\1\1\204\0\0\0\204\1\2\2" + "\203\3\3\3|\2\2\2j\0\0\0a\5\5\5k\5\5\5n\3\4\4n\1\1\2k\0\0\0V\0\0\0P\3" + "\3\3k\2\2\2\202\0\0\0\221\0\0\0\230\0\0\0\217\2\2\2\201\2\2\2l\0\0\0" + "X\1\1\1e\5\5\6m\4\4\4m\3\3\3n\0\0\0c\0\0\0c\5\5\5n\4\4\4n\3\3\3n\1\1" + "\1j\0\0\0R\0\0\0,\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\7\0" + "\0\0\23\0\0\0\34\0\0\0!\0\0\0'\0\0\0""0\0\0\0""7\0\0\0:\0\0\0:\0\0\0" + "7\0\0\0-\0\0\0\"\0\0\0\25\0\0\0\26\0\0\0!\0\0\0.\0\0\0""7\0\0\0:\0\0" + "\0""8\0\0\0""1\0\0\0\77\1\1\1{\0\0\0\260\0\0\0\302\0\0\0\303\0\0\0\304" + "\0\0\0\274\0\0\0\212\0\0\0H\0\0\0""7\0\0\0""2\0\0\0'\0\0\0\32\0\0\0\24" + "\0\0\0\40\0\0\0+\0\0\0""4\0\0\0""8\0\0\0""5\0\0\0-\0\0\0$\0\0\0\35\0" + "\0\0\33\0\0\0\40\0\0\0!\0\0\0\"\0\0\0!\0\0\0\36\0\0\0\23\0\0\0\7\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\16\0\0\0\33\0\0\0\40\0\0\0\"\0\0\0" + "\"\0\0\0!\0\0\0\35\0\0\0\35\0\0\0!\0\0\0\"\0\0\0\"\0\0\0\"\0\0\0\36\0" + "\0\0\37\0\0\0!\0\0\0\"\0\0\0!\0\0\0\37\0\0\0\40\0\0\0\"\0\0\0\"\0\0\0" + "!\0\0\0\36\0\0\0\36\0\0\0!\0\0\0\"\0\0\0\"\0\0\0\40\0\0\0\34\0\0\0#\0" + "\0\0""0\0\0\0""6\0\0\0""2\0\0\0,\0\0\0&\0\0\0\37\0\0\0\31\0\0\0\36\0" + "\0\0*\0\0\0""4\0\0\0""8\0\0\0""7\0\0\0/\0\0\0&\0\0\0\36\0\0\0\33\0\0" + "\0\40\0\0\0\"\0\0\0\"\0\0\0!\0\0\0\36\0\0\0\36\0\0\0\"\0\0\0\"\0\0\0" + "!\0\0\0\37\0\0\0\33\0\0\0#\0\0\0""0\0\0\0""4\0\0\0/\0\0\0%\0\0\0!\0\0" + "\0\"\0\0\0\"\0\0\0\40\0\0\0\33\0\0\0\27\0\0\0\"\0\0\0-\0\0\0""6\0\0\0" + "9\0\0\0""7\0\0\0/\0\0\0&\0\0\0\32\0\0\0\15\0\0\0\11\0\0\0\17\0\0\0\30" + "\0\0\0\34\0\0\0\34\0\0\0\34\0\0\0\34\0\0\0\34\0\0\0\33\0\0\0\34\0\0\0" + "\34\0\0\0\32\0\0\0\31\0\0\0\33\0\0\0\34\0\0\0\34\0\0\0\30\0\0\0\31\0" + "\0\0\34\0\0\0\34\0\0\0\34\0\0\0\33\0\0\0\31\0\0\0\34\0\0\0\33\0\0\0\34" + "\0\0\0\32\0\0\0\24\0\0\0\27\0\0\0!\0\0\0,\0\0\0""4\0\0\0""3\0\0\0*\0" + "\0\0\40\0\0\0\26\0\0\0\25\0\0\0\34\0\0\0\34\0\0\0\34\0\0\0\34\0\0\0\27" + "\0\0\0\26\0\0\0\40\0\0\0%\0\0\0&\0\0\0\40\0\0\0\32\0\0\0\34\0\0\0\34" + "\0\0\0\33\0\0\0\30\0\0\0\27\0\0\0\40\0\0\0)\0\0\0*\0\0\0%\0\0\0\40\0" + "\0\0\33\0\0\0\31\0\0\0\33\0\0\0\34\0\0\0\34\0\0\0\32\0\0\0\25\0\0\0\22" + "\0\0\0\34\0\0\0*\0\0\0""6\0\0\0""8\0\0\0""4\0\0\0(\0\0\0\34\0\0\0\25" + "\0\0\0\31\0\0\0\33\0\0\0\34\0\0\0\33\0\0\0\30\0\0\0\31\0\0\0\33\0\0\0" + "\34\0\0\0\34\0\0\0\32\0\0\0\24\0\0\0\12\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\1\0\0\0\5\0\0\0\13\0\0\0\16\1\1\1\22\0\0\0\30\0\0\0\37\0\0\0" + "#\0\0\0$\0\0\0#\0\0\0\37\0\0\0\30\0\0\0\15\0\0\0\10\0\0\0\14\0\0\0\26" + "\0\0\0\37\0\0\0#\0\0\0#\0\0\0\35\0\0\0\34\0\0\0J\2\2\2\213\0\0\0\253" + "\2\2\2\262\1\1\1\262\1\1\1\263\0\0\0\243\0\0\0r\0\0\0""9\0\0\0!\0\0\0" + "\33\0\0\0\22\0\0\0\11\1\1\1\12\0\0\0\24\0\0\0\33\0\0\0\"\0\0\0\"\0\0" + "\0\36\0\0\0\30\0\0\0\20\0\0\0\15\0\0\0\16\0\0\0\20\0\0\1\20\0\0\0\20" + "\0\0\0\20\0\0\0\14\0\0\0\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\0" + "\0\0\11\0\0\0\16\0\0\0\20\1\1\1\20\0\0\0\20\0\0\0\16\0\0\0\16\0\0\0\16" + "\0\0\0\20\0\0\0\20\0\0\0\20\0\0\0\17\0\0\0\16\0\0\0\17\0\0\0\20\0\0\0" + "\20\0\0\0\17\0\0\0\17\0\0\0\20\1\1\1\21\0\0\0\20\0\0\0\17\0\0\0\16\0" + "\0\0\17\0\0\0\20\0\0\0\21\0\0\0\20\0\0\0\15\0\0\0\17\0\0\0\30\0\0\0\37" + "\0\0\0\40\0\0\0\34\0\0\0\30\0\0\0\23\0\0\0\15\0\0\0\13\1\1\1\23\0\0\0" + "\34\0\0\0\"\0\0\0#\0\0\0\37\0\0\0\31\0\0\0\22\0\0\0\15\0\0\0\15\0\0\0" + "\20\1\1\1\21\0\0\0\20\0\0\0\17\0\0\0\16\0\0\0\17\0\0\0\21\0\0\0\20\0" + "\0\0\17\0\0\0\15\0\0\0\16\0\0\0\30\0\0\0\37\0\0\0\37\0\0\0\30\0\0\0\22" + "\0\0\0\20\0\0\0\21\0\0\0\20\0\0\0\16\0\0\0\12\1\1\1\13\0\0\0\25\0\0\0" + "\36\0\0\0\"\0\0\0#\0\0\0\37\0\0\0\32\0\0\0\22\0\0\0\7\0\0\0\2\0\0\0\3" + "\0\0\0\10\1\1\1\13\2\3\3\14\2\2\2\14\2\2\2\14\2\2\2\14\2\2\2\13\2\2\2" + "\13\2\2\2\14\1\1\1\13\0\0\0\12\1\1\1\12\3\3\3\13\2\2\2\14\0\0\0\12\0" + "\0\0\11\1\1\1\13\3\3\3\14\2\2\2\14\0\0\0\14\0\0\0\13\1\1\1\13\3\3\3\14" + "\2\2\2\13\0\0\0\13\0\0\0\11\0\0\0\7\1\1\1\14\0\0\0\25\0\0\0\36\0\0\0" + "\40\0\0\0\34\0\0\0\26\0\0\0\14\0\0\0\7\0\0\0\12\1\2\2\14\2\2\3\14\1\1" + "\1\14\0\0\0\12\0\0\0\10\0\0\0\14\0\0\0\22\0\0\0\26\0\0\0\23\0\0\0\16" + "\0\0\0\14\2\2\2\14\1\1\1\13\0\0\0\12\0\0\0\11\1\1\1\14\0\0\0\24\0\0\0" + "\30\0\0\0\30\0\0\1\23\1\0\1\16\0\0\0\13\1\1\0\12\3\3\3\14\2\3\3\14\1" + "\1\2\13\0\0\0\11\0\0\0\6\1\1\1\10\1\1\1\22\0\0\0\34\0\0\0\"\0\0\0\"\0" + "\0\0\34\0\0\0\24\0\0\0\13\0\0\0\11\2\2\2\13\3\3\3\13\2\2\2\13\1\1\1\12" + "\0\0\0\11\1\1\1\13\3\3\3\13\2\2\2\14\1\1\1\13\0\0\0\11\0\0\0\5\0\0\0" + "\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\16\1\1\1""5\1\1\1e\0\0\0\201" + "\0\0\0\210\0\0\0\212\0\0\0\216\0\0\0\223\0\0\0\226\0\0\0\223\0\0\0\217" + "\0\0\0\206\0\0\0n\1\1\1[\0\0\0m\0\0\0\205\0\0\0\216\0\0\0\223\0\0\0\224" + "\0\0\0\221\0\0\0\210\0\0\0\200\0\0\0\226RSV\274\206\210\214\302jko\302" + "79:\302\0\0\0\260\0\0\0\224\0\0\0\220\0\0\0\221\0\0\0\212\0\0\0t\1\1" + "\1]\0\0\0i\0\0\0\202\0\0\0\214\0\0\0\217\0\0\0\221\0\0\0\216\0\0\0\213" + "\0\0\0\201\0\0\0r\0\0\0{\0\0\0\212\0\0\0\213\0\0\0\213\0\0\0\210\0\0" + "\0l\0\0\0""7\0\0\0\12\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\"\2\2\2X\0\0\0\200" + "\0\0\0\212\0\0\0\213\0\0\0\213\0\0\0\202\0\1\0v\0\0\0\177\0\0\0\213\0" + "\0\0\213\0\0\0\213\0\0\0\205\1\0\1|\0\0\0\203\0\0\0\213\0\0\0\213\0\0" + "\0\205\0\0\0\202\0\0\0\210\0\0\0\213\0\0\0\213\0\0\0\204\2\2\2|\0\0\0" + "\203\0\0\0\213\0\0\0\213\0\0\0\213\0\0\0{\0\0\0p\0\0\0\201\0\0\0\216" + "\0\0\0\216\0\0\0\214\0\0\0\214\0\0\0\206\0\0\0o\0\0\0j\0\0\0\200\0\0" + "\0\216\0\0\0\220\0\0\0\221\0\0\0\217\0\0\0\214\0\0\0\202\0\0\0u\0\0\0" + "{\0\0\0\212\0\0\0\213\0\0\0\213\0\0\0\202\3\3\3|\0\0\0\205\0\0\0\213" + "\0\0\0\213\0\0\0\211\0\0\0x\0\0\0o\0\0\0\202\0\0\0\217\0\0\0\216\0\0" + "\0\206\0\0\0\204\0\0\0\211\0\0\0\214\0\0\0\212\0\0\0y\0\0\0f\0\0\0o\0" + "\0\0\206\0\0\0\216\0\0\0\222\0\0\0\223\0\0\0\216\0\0\0\211\0\0\0z\0\0" + "\0\\\0\0\0>\0\0\0:\1\1\1X\0\0\0r\0\0\0v\0\0\0t\0\0\0t\0\0\0u\0\0\0u\0" + "\0\0u\0\0\0v\0\0\0r\0\0\0k\0\0\0o\0\0\0v\0\0\0w\0\0\0q\0\0\0i\0\0\0p" + "\0\0\0v\0\0\0u\0\0\0r\0\0\0j\0\0\0m\0\0\0v\0\0\0v\0\0\0t\0\0\0b\0\0\0" + "[\0\0\0p\0\0\0\204\0\0\0\213\0\0\0\216\0\0\0\213\0\0\0\202\0\0\0q\0\0" + "\0a\0\0\0h\0\0\0u\0\0\0v\0\0\0w\0\0\0m\1\1\1^\0\0\0j\0\0\0\203\0\0\0" + "\213\0\0\0\203\0\0\0s\0\0\0q\0\0\0u\0\0\0v\0\0\0n\1\1\1b\0\0\0k\0\0\0" + "\202\0\0\0\213\0\0\0\211\0\0\0\207\0\0\0z\0\0\0k\0\0\0k\0\0\0t\0\0\0" + "w\0\0\0v\0\0\0i\0\0\0W\0\0\0d\0\0\0}\0\0\0\213\0\0\0\221\0\0\0\221\0" + "\0\0\213\0\0\0}\0\0\0i\0\0\0c\0\0\0p\0\0\0v\0\0\0v\0\0\0q\0\0\0i\0\0" + "\0n\0\0\0u\0\0\0w\0\0\0v\0\0\0i\0\0\0G\0\0\0\34\0\0\0\3\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\21\0\0\0D\0\0\0\205UVX\255\264\265\270\262\266\267\274" + "\262\262\264\272\262\276\300\304\262\274\276\303\262\241\244\252\262" + "\212\215\222\262bcg\262\32\32\33\252\0\0\0\23479;\247{}\201\262\215\217" + "\224\262\235\237\245\262\260\262\267\262\242\244\251\261z{\200\262AB" + "E\261\0\0\0\245@@@\245\333\333\335\260\357\361\371\262\241\244\255\261" + "lns\261\220\221\226\262\272\274\301\262\240\242\247\262hjo\261!\"#\254" + "\0\0\0\234#$%\243uw|\262\224\227\235\262\226\230\236\262\237\241\246" + "\262\244\245\252\262\241\242\245\262rsv\262\26\26\30\247!\"#\245\211" + "\212\216\262\232\232\237\261dei\262!\"#\262\0\0\0\221\3\2\3S\12\12\13" + "'\3\3\3\34\0\0\0\25\0\0\0\15\0\0\0+\0\0\0n./0\245\215\216\221\262\241" + "\242\247\262mot\262\"\"$\253\0\0\0\241WW[\253\230\233\241\262\210\213" + "\221\262\177\201\206\262<=\77\260\1\2\2\250kln\254\250\252\256\261|~" + "\203\26289<\260\16\16\17\254vwy\257\245\250\254\262qtx\262134\257\0\0" + "\0\243OOQ\251\241\242\247\262\210\212\217\262NOR\262\13\13\13\245\2\2" + "\2\234lmo\256\245\247\254\262\220\222\231\262\230\232\240\262\235\236" + "\244\262cei\262\16\16\17\245\25\26\26\243lnr\261\227\231\237\262\232" + "\234\243\262\243\246\253\262\252\254\261\262\247\250\254\262\202\204" + "\207\261()*\252\27\30\31\250\203\204\207\261\246\250\254\262tv{\262)" + "*,\255\0\0\0\243]^`\254\250\252\257\262\205\207\215\261HHL\262\3\2\3" + "\245\40\40\"\243z{\200\262\225\227\234\262\205\207\214\262stx\262uuy" + "\262\200\201\206\262|~\203\262VVZ\262\22\22\23\247\0\0\0\234679\252u" + "w|\262\211\213\221\262\236\237\244\262\256\257\264\262\233\235\243\262" + "klq\262/02\262\2\2\3\241\0\0\0\177\0\0\0k\0\0\0\207LMN\253\205\210\214" + "\262not\262him\262wy~\262\211\212\217\262\220\221\225\262\224\226\232" + "\262`ad\261\20\21\22\250VWY\254\224\226\231\262nps\262/01\256\0\0\0\241" + "STU\250\224\225\231\262suy\26278:\257\0\0\0\240GHI\245\217\220\224\262" + "uvz\262;;>\261\1\0\1\236\27\27\30\235YZ\\\260vw{\262\202\203\210\262" + "\226\226\234\262\214\215\221\262fgk\26289;\262\5\6\6\245\20\20\21\241" + "ggj\257{|\200\262QSV\262\36\37\40\252\0\0\0\234224\245opt\262tuy\262" + "ggk\262TUX\261^^a\261lmq\262]^b\262))+\255\0\0\0\232-./\241~\200\203" + "\262\212\214\221\262\202\204\211\262\220\222\230\262yz\177\262%%'\254" + "@@B\251\220\221\224\262\203\205\211\262RSW\262\23\24\24\245\0\0\0\231" + "569\251suy\262\214\217\224\262\244\246\254\262\253\255\262\262\214\216" + "\223\262WX\\\262\31\31\33\253\4\4\4\242ggj\254\220\223\227\262hko\262" + "014\256\0\0\0\240JJK\247\221\222\226\262}\177\204\262IKM\262\16\16\17" + "\250\0\0\0w\2\2\2""8\6\6\6\15\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\6\0\0\0&\0" + "\0\0^\31\30\30\213AAA\235HHI\237EEF\242<;;\242iii\244\315\317\323\246" + "\342\346\357\247\325\331\341\250\224\227\234\247\31\32\33\244\212\212" + "\211\244\375\376\377\247\311\314\326\247\200\202\210\246012\236\232\231" + "\231\240\371\371\376\247\321\324\334\247fhm\246\0\0\0\240\210\210\207" + "\241\360\362\366\247\316\322\332\247\225\227\235\24689:\235YXV\232\327" + "\327\330\244\370\373\377\247\244\247\257\247$$'\244\206\206\206\244\377" + "\377\377\247\327\332\343\247\241\243\252\246MNQ\243;;<\240MNO\241MNP" + "\244)*,\242\0\0\0\234\214\214\213\240\373\375\377\247\304\310\320\247" + "pqv\247\17\20\20\235\0\0\0\215\0\0\0\214\0\0\0\212\0\0\0m\0\0\0""6\0" + "\0\0\36\0\0\0H\0\0\0\204\212\211\211\243\377\377\377\247\324\330\341" + "\246]_d\245)*+\243\270\272\275\244\366\371\377\247\317\322\334\247\327" + "\332\343\247\230\233\240\247\15\16\17\237LLK\237\351\352\355\246\357" + "\362\373\247\217\222\231\250\17\20\20\241aa`\237\364\365\367\250\337" + "\342\352\247{}\203\247\5\5\6\233\11\10\7\226\267\270\272\243\367\372" + "\377\247\242\244\255\247558\242\0\0\0\225|{|\235\354\355\361\247\323" + "\326\337\247\217\222\230\247;=>\236\35\36\36\220\0\0\0\216qqr\236\360" + "\362\367\247\340\344\354\247\255\257\267\246YY]\24499;\241NOQ\241TTV" + "\242<=\77\245\0\0\0\236vvt\241\377\377\377\247\340\343\355\247wz\177" + "\250\0\0\0\233\37\37\36\227\314\316\316\244\375\377\377\247\237\242\251" + "\247\35\36\40\242hhg\242\367\367\372\247\332\334\344\247\233\236\245" + "\247KMO\237EED\233\302\302\303\243\357\361\366\247\253\255\265\24701" + "4\242112\241\316\317\323\245\343\345\353\250\223\224\234\247ABE\237\35" + "\35\34\227\242\242\242\237\365\366\373\250\276\300\310\250STX\247\3\3" + "\4\231\0\0\0x\0\0\0v333\225\307\310\311\247\346\350\356\250\274\276\307" + "\247\226\230\236\246ggi\243llm\242vvx\243YY[\244\11\12\13\233LKL\233" + "\345\346\352\246\362\366\376\247\203\206\214\247\2\2\2\233%%$\227\320" + "\321\323\244\374\377\377\247\223\226\235\247\17\17\20\235\15\15\14\226" + "\302\303\305\243\377\377\377\247\230\232\241\247\31\32\32\240[Z[\236" + "\352\353\357\246\327\332\341\247\226\231\237\247MNP\240\207\207\207\237" + "\346\347\353\246\310\312\321\247ghm\247\3\3\4\236}}}\236\353\353\357" + "\247\266\267\277\247VW[\245\13\14\15\236\237\237\241\242\341\341\347" + "\247\241\243\252\247qrv\244778\233\217\217\220\235\337\337\342\246\305" + "\306\315\247klq\246\3\2\3\230%&&\225\302\303\305\244\353\355\363\247" + "\264\266\277\247lmq\244012\227\16\16\20\213\24\23\24\221\273\273\273" + "\242\377\377\377\247\273\277\310\24767:\242>>>\241\336\337\343\246\362" + "\365\375\250\245\250\257\247NNQ\236;;:\227\276\277\300\241\371\374\377" + "\247\261\263\274\247125\244\\[Z\242\357\357\361\245\350\352\363\247\205" + "\207\215\247\10\10\10\233\16\16\15\226\274\276\276\242\377\377\377\247" + "\256\261\272\24789;\247\0\0\0\214\0\0\0T\7\10\10\36\0\0\0\3\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\12\0\0\0.\0\0\0dBCE\221\273\275\302\234\322\325" + "\335\234\304\310\320\235\300\302\312\235\262\263\270\233\273\274\276" + "\232\267\271\274\233dfi\230\0\0\0\215...\217\313\314\315\233\347\352" + "\361\235\213\216\226\235\35\36\36\226\21\21\21\220\271\271\272\231\357" + "\361\366\234\233\236\247\234''*\227322\226\322\322\324\232\346\350\360" + "\234\230\234\244\235TUY\23189<\226\226\231\236\233\330\333\342\234\310" + "\314\325\234jmr\233BBC\231\313\314\314\234\354\357\365\235\300\304\316" + "\235\217\221\230\233\\\\^\231\212\212\213\232\327\330\336\234\320\322" + "\333\234OPU\233222\227\307\306\306\233\332\333\340\235\250\253\263\234" + "\253\255\264\234\241\243\252\234\206\210\216\234679\234\0\0\0\212\0\0" + "\0S\5\5\5\37\0\0\0)\0\0\0a334\215\304\304\306\235\346\350\356\234\263" + "\266\277\235\270\273\303\234\310\313\324\235\233\235\242\233\271\270" + "\272\233\354\356\364\235\277\303\313\235SUX\232\0\0\0\223\227\227\227" + "\227\373\375\377\234\274\300\311\234HJN\231\10\7\10\224\251\251\252\231" + "\356\360\365\235\257\262\273\234\207\211\217\235xz\177\234\244\247\255" + "\234\270\274\303\235\266\272\301\235qsx\233!!\"\225\201\201\203\226\324" + "\326\334\234\302\304\315\235\237\241\250\235Z[_\231'(*\221\36\36!\220" + "==>\227\302\302\302\234\356\360\366\234\300\304\315\234\224\227\236\234" + "abe\230z{|\231\323\324\330\233\345\350\360\234bdj\234$$$\230\267\267" + "\267\233\363\364\372\235\267\272\303\234\216\220\226\234\204\206\213" + "\233\266\271\301\233\314\317\331\234\304\307\320\234kmr\234%%&\231\265" + "\265\264\232\370\373\377\234\252\256\266\235[\\a\233\"#%\225\202\204" + "\210\231\320\323\333\234\277\302\312\234z|\201\233!\"\"\230\236\236\235" + "\231\367\370\375\234\244\246\257\234OPU\232\17\20\22\224QRV\226\265\266" + "\275\235\307\311\320\234\220\222\230\234-.0\225\0\0\0w\0\0\0d\0\0\0v" + "ttu\225\333\335\341\234\270\272\301\234\251\253\262\234\236\240\245\233" + "\233\235\240\233\253\254\256\233\252\253\255\234[\\^\230\1\1\2\221\214" + "\215\215\225\360\362\367\235\272\276\307\235\203\205\214\233uw{\233\257" + "\262\271\233\305\311\321\234\274\277\307\234\236\240\246\235\204\205" + "\212\233\255\257\265\234\310\313\323\234\277\302\313\235cej\232\15\15" + "\16\226\243\243\244\227\361\363\370\234\240\243\253\23578:\226\0\0\0" + "\216\226\227\230\226\347\350\355\235\233\234\244\23478;\230\30\30\30" + "\224\261\261\263\231\332\333\340\234\206\206\214\235!!#\230^^]\227\343" + "\343\345\235\272\274\302\234fgl\235$$&\22788:\225\234\234\241\234\271" + "\272\301\234\216\220\226\235124\230$$%\225\251\252\255\233\311\312\321" + "\235\255\257\266\234|~\203\23367:\225''*\217\3\5\6\221]]]\227\342\343" + "\346\234\336\341\352\234{~\205\234''(\230\253\253\252\231\377\377\377" + "\235\257\263\273\234QSV\230\11\12\12\222bcg\226\310\313\321\234\322\326" + "\336\234\212\214\222\234\37\37\37\226\223\223\221\230\355\357\364\235" + "\262\266\276\235\206\211\216\234opu\233\244\246\255\233\305\310\320\234" + "\301\305\315\235yz\177\234\23\23\23\223\0\0\0k\3\3\4""2\14\14\14\10\0" + "\0\0\0\0\0\0\0\0\0\0\4\0\0\0\13\0\0\0\23\0\0\0\33\0\0\0&\0\0\0""4\0\0" + "\0A\0\0\0F\0\0\0F\0\0\0G\0\0\0D\0\0\0""8\0\0\0)\0\0\0\36\0\0\0\25\0\0" + "\0\14\0\0\0\6\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0$\0\0\0Z223\204\314\314\315\222\375" + "\376\377\221\322\325\335\221\255\260\267\221rtx\221Z[^\217dej\220z|\202" + "\217]_b\216\11\11\13\210nnn\214\352\353\354\222\321\322\330\221not\221" + "\0\0\0\213\\\\]\214\340\341\343\222\331\333\337\221{}\201\221\10\12\12" + "\215nnn\216\344\345\347\222\326\330\335\222\256\257\265\221\254\256\260" + "\222\332\332\336\222\351\352\360\222\320\323\331\221dfj\220\0\0\0\203" + "...\203\254\254\255\221\336\337\341\222\307\311\314\222\246\250\254\222" + "\265\267\274\222\324\326\334\221\256\260\266\221CDG\215\0\0\0\203klm" + "\213\336\337\341\221\313\315\321\222\233\235\241\222\251\251\254\222" + "\335\336\342\222\217\220\224\221\32\33\34\215\0\0\0f\4\3\4""0\2\2\2\31" + "\0\0\0>\0\0\0q\202\202\202\215\363\363\366\222\322\325\334\221\326\330" + "\342\221\272\274\304\222./1\213GGF\213\345\347\351\221\365\370\377\222" + "\240\243\252\222\40\40\"\214===\211\305\305\305\217\331\332\334\221\213" + "\214\221\220\21\21\24\213NML\211\326\327\330\221\333\335\342\222\262" + "\264\271\221\231\232\235\222\275\275\277\222\331\333\337\222\316\321" + "\327\221~\200\204\222\27\30\31\214KKK\211\276\276\300\221\342\343\346" + "\221\322\324\333\222\304\306\317\222\316\321\327\222\310\312\320\222" + "^_d\221'''\215\231\231\231\217\335\335\340\222\306\307\314\221\243\244" + "\251\221\254\256\263\222\321\323\331\222\273\276\303\221QRU\216\0\0\0" + "\205^^^\212\333\334\335\221\336\340\344\222\265\267\275\222\242\243\246" + "\222\307\310\311\221\342\343\347\222\330\333\341\221\200\201\206\222" + "\11\11\12\210\27\27\27\203\232\232\232\217\341\341\344\222\340\342\347" + "\222\317\323\331\221\241\242\247\222\273\273\274\220\337\341\346\222" + "\257\262\272\221\77@D\217\6\6\6\210\202\202\203\213\325\326\330\221\323" + "\325\331\222\321\322\327\222\320\321\325\221\313\314\321\221\271\273" + "\301\221mmq\222\24\23\24\207\0\0\0b\0\0\0G\0\0\0V&&'~\267\270\272\221" + "\352\353\360\222\270\272\301\221\223\225\232\220rsx\220tvz\220}\177\203" + "\220suy\221#$&\212555\211\274\274\275\221\335\337\341\221\276\300\306" + "\221\247\250\254\222\275\275\277\221\336\337\343\221\315\320\326\222" + "\204\206\214\221pqr\216\277\277\277\222\342\344\346\222\321\323\331\222" + "vw|\221\0\0\1\205JJJ\210\317\317\320\221\342\344\347\221\213\215\222" + "\221\20\20\22\213>>>\210\307\307\311\222\335\336\343\222\210\211\216" + "\221\16\17\20\215eff\213\337\341\344\221\270\272\300\222__c\221\0\0\0" + "\210HGH\207\302\302\304\221\317\320\323\221\301\302\307\222\240\241\245" + "\221\221\221\224\221\272\272\275\222\311\311\316\221vvz\222445\217\177" + "\177\177\216\321\322\324\221\326\327\334\222\306\310\317\220\306\311" + "\317\221\323\326\333\221\232\234\241\22299;\217\211\210\207\216\342\342" + "\344\221\261\263\267\2229:=\214\15\15\15\206\222\221\222\214\337\340" + "\342\222\337\341\345\222\336\340\345\221\335\337\345\222\330\331\337" + "\221\301\303\311\221him\220\0\0\0\201FFF\204\311\311\312\222\334\335" + "\340\222\264\267\274\221\236\237\242\221\274\275\277\222\334\335\341" + "\222\323\326\333\222\203\205\211\222\32\33\34\213\0\0\0h\3\3\3""2\6\6" + "\7\17\0\0\0\24\10\10\3+\0\0\0A\0\0\0V\0\0\0g\0\0\0t\23\23\6{\40\40\13" + "\202,,\16\21222\17\21511\17\21522\17\217--\16\214\40\40\12\204\22\22" + "\5|\0\0\0w\0\0\0l\0\0\0Z\0\0\0F\6\6\2""0\0\0\0\32\0\0\0\11\2\2\0\2\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\21\0\0\0""5" + "\0\0\0]\25\25\26zooo\206\251\251\252\207\271\272\276\207\303\304\311" + "\207\305\307\313\207\301\302\307\207\272\274\300\207\212\214\220\207" + "-.0\207\0\0\0v\2\2\3f\10\10\10d\11\12\12d\6\6\7`\0\0\0`\2\2\3d\5\5\6" + "e\11\11\12d\7\7\7`\0\0\0`\4\4\4e\6\7\7e\0\0\0a\0\0\0a\6\6\7j\37\37\40" + "s\20\20\21r\0\0\0d\0\0\0L\0\0\0G\0\0\0Y\3\3\3e\31\32\32i\"\"\"m\37\37" + "\40k\16\16\16h\0\0\0a\0\0\0R\0\0\0K\0\0\0Y\3\3\4a\6\6\6`\0\0\0^\0\0\0" + "]\6\7\7d\27\27\30h\11\11\11_\0\0\0E\0\0\0\35\1\1\1\7\0\0\0\37\0\0\0S" + "((){\210\210\211\207\250\251\253\206\235\237\242\207stx\207\32\32\34" + "\177\2\2\2xnnn\203\261\263\263\207\231\233\236\207EFI\202\0\0\0|ppq\202" + "\314\316\317\207\255\257\263\207[\\`\206\11\11\12z\0\0\0h\10\10\11b\2" + "\2\3c\0\0\0^\0\0\0_\21\21\21d\16\17\17f\0\0\0b\0\0\0R\0\0\0J\0\0\0_%" + "&&{\205\205\207\206\217\220\224\207-./\204\0\0\0r\12\12\12c\3\4\4Z\0" + "\0\0[\0\0\0d\26\26\27i\40!!l\37\37\40m\17\20\20h\0\0\0b\0\0\0T\0\0\0" + "I\2\2\2T\4\4\5`\7\7\10`\0\1\1_\0\0\0\\\0\0\0^\24\25\25e\16\17\17e\0\0" + "\0a\0\0\0O\0\0\0G\0\0\0X\4\4\5f\30\31\31i\2\2\2f\0\0\0kGGG\201\314\315" + "\316\207\331\332\336\206\212\214\221\207#$&\202\0\0\0j\0\0\0_\22\22\23" + "d\26\26\27j\30\30\30k\23\24\24h\0\0\0e\0\0\0[\0\0\0I\1\1\1+\0\0\0\33" + "\0\0\0""4\0\0\0bJJK\201\230\231\233\207\216\217\222\206\216\217\223\207" + "\226\227\232\206\226\227\232\207\233\234\240\207\227\230\234\207XZ\\" + "\207\14\14\14y\0\0\0f\13\13\14a\5\5\5a\0\0\0\\\0\0\0^\25\25\25d\15\15" + "\16e\0\0\0\\\0\0\0T\0\0\0[\22\23\23d\17\17\17e\0\0\0]\0\0\0Q\0\0\0U\3" + "\3\4^\7\10\10a\13\13\13a\10\10\10Z\0\0\0W\1\1\2_\7\7\7d\10\10\10a\0\0" + "\0c\30\30\30v\227\227\231\207\332\332\336\206\232\233\237\207;;=\207" + "\0\0\0s\0\0\0b\23\23\23d\24\24\24g\0\0\0a\0\0\0\\\0\0\0_\7\7\7b\11\11" + "\11b\2\2\2Z\0\0\0W\0\0\0kZ[[\200\224\225\226\207ZZ\\\207\12\12\12x\0" + "\0\0f\0\0\0iDDE~\260\261\263\207\275\276\303\206xy}\206\34\34\35\177" + "\0\0\0h\0\0\0`\26\26\26h\32\31\31n\34\34\34o\26\26\27k\0\0\1g\0\0\0Z" + "\0\0\0J\0\0\0S\4\4\4c\11\11\12d\4\4\4d\0\0\0_\0\0\0a\23\23\24g\21\21" + "\21i\0\0\0e\0\0\0V\0\0\0""9\1\1\1#\2\2\1-\0\0\0M\0\0\0k##\14~vv(\206" + "\264\264<\206\326\326F\207\350\350L\207\366\366P\207\377\377R\206\377" + "\377S\207\377\377S\207\377\377S\207\377\377R\206\367\367P\206\351\351" + "L\207\327\327E\207\262\2629\207oo$\207\35\35\11\201\0\0\0r\0\0\0V\4\4" + "\1""3\1\1\0\24\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\1\0\0\0\13\5\5\5\34\0\0\0/\0\0\0<\0\0\0E\0\0\0L\0\0\0P\0\0\0Q\0" + "\0\0N\0\0\0H\0\0\0B\0\0\0\77\2\2\2""3\5\5\5\33\7\7\10\13\0\0\0\12\0\0" + "\0\12\10\10\7\12\16\16\16\12\12\12\12\13\1\1\1\13\0\0\0\12\10\10\10\12" + "\15\15\15\13\12\12\12\13\17\17\17\12\21\22\22\16\5\5\5\23\0\0\0\26\1" + "\1\1\25\5\5\5\22\1\1\1\15\7\7\7\14\14\14\14\21\4\4\4\31\0\0\0\37\0\0" + "\0%\0\0\0(\0\0\0(\2\2\2&\0\0\0&\0\0\0*\0\0\0.\0\0\0""0\0\0\0""1\0\0\0" + "4\0\0\0""8\0\0\0>\0\0\0\77\0\0\0;\0\0\0""4\0\0\0+\0\0\0$\0\0\0&\1\1\1" + "5\0\0\0B\0\0\0B\0\0\0>\0\0\0=\0\0\0\77\0\0\0\77\0\0\0>\0\0\0C\0\0\0E" + "\0\0\0D\0\0\0C\0\0\0M\0\0\0]\0\0\0d\0\0\0e\0\0\0e\1\1\1\\\1\1\1@\3\3" + "\3\34\10\10\10\16\14\14\14\23\6\6\6\31\0\0\0\36\0\0\0\36\1\1\1\33\0\0" + "\0\26\3\3\3\30\5\5\5(\0\0\0<\0\0\0E\0\0\0F\0\0\0E\3\3\3""7\0\0\0\34\1" + "\1\1\12\33\33\33\11\14\14\14\17\0\0\0\25\0\0\0\33\0\0\0!\0\0\0%\2\2\2" + "'\0\0\0(\0\0\0,\0\0\0/\0\0\0""0\0\0\0""0\0\0\0""0\0\0\0/\1\1\0/\0\0\0" + "-\0\0\0)\0\0\0$\0\0\0\34\0\1\0\24\12\12\12\24\5\5\5\26\0\0\0\23\4\4\5" + "\31\7\7\10""4\0\0\0N\0\0\0T\0\0\0T\0\0\0V\0\0\0V\3\3\3F\2\2\2.\0\0\0" + "&\0\0\0*\0\0\0,\0\0\0,\0\0\0,\0\0\0*\0\0\0)\0\0\0&\0\0\0&\0\0\0.\0\0" + "\0=\0\0\0G\0\0\0J\0\0\0G\0\0\0C\0\0\0@\0\0\0>\0\0\0<\0\0\0=\0\0\0=\0" + "\0\0""6\4\4\4%\3\3\3\26\3\3\3\25\5\5\5\34\3\3\3#\0\0\0(\0\0\0.\0\0\0" + "0\0\0\0/\0\0\0""3\0\0\0""8\0\0\0<\0\0\0:\0\0\0""3\0\0\0""0\0\0\0.\0\0" + "\0)\0\0\0#\0\0\0\36\2\2\2\26\10\10\10\21\12\12\12\12\3\3\3\15\1\1\1)" + "\0\0\0I\0\0\0U\0\0\0V\0\0\0V\0\0\0W\1\1\2K\3\3\3""1\0\0\0\40\0\0\0\37" + "\2\3\2\35\6\6\6\31\3\3\3\30\3\3\3\26\0\0\1\21\1\1\1\14\17\17\17\23\4" + "\4\4,\0\0\0@\0\0\0E\0\0\0D\0\0\0;\0\0\0""0\0\0\0;\0\0\0T\0\0\0`\0\0\0" + "b\0\0\0c\1\1\0_\3\3\3F\5\5\5#\0\0\0\23\0\0\0\24\0\0\0\25\0\0\0\24\10" + "\10\10\21\15\15\15\13\2\2\2\10\6\6\6\11\13\13\13\13\10\10\10\13\11\11" + "\11\13\25\25\25\13\20\20\20\15\1\1\1\21\1\1\1\22\10\10\10\17\6\6\6\11" + "\0\0\0\20\0\0\0""0\0\0\0X**\16s\257\257A|\377\377\\|\377\377U|\377\377" + "P|\377\377N|\375\375M|\373\373N|\372\372M|\372\372M|\372\372M|\373\373" + "M|\372\372M|\373\373M|\374\374N|\377\377N|\377\377Q|\377\377W|\377\377" + "W|\226\2262|\31\31\7v\0\0\0Z\3\3\1.\12\12\3\12\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1""223\3GGH\5HI" + "J\6JJL\6KKM\6HHI\6DEF\6BCE\4+,.\2\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\10\1\1\1\37\1\1\1""6\0" + "\0\0F\0\0\0O\0\0\0R\0\0\0V\0\0\0]\0\0\0`\3\3\4`\6\6\7a\12\12\12e\14\15" + "\15i\16\17\17k\21\21\21j\25\24\25j\31\32\32j\34\34\35j\31\31\32j\26\26" + "\27j\22\22\22j\14\14\14j\6\7\7d\0\0\0a\0\0\0]\0\0\0T\0\0\0G\7\7\7""6" + "\14\14\14\40\10\10\10\36\0\0\0""7\4\3\4N\0\0\0S\0\0\0R\0\0\0R\0\0\0S" + "\0\0\0U\0\0\0V\0\0\0V\0\0\0V\0\0\0W\0\0\0V\0\0\0F\0\0\0&\0\0\0\34\0\0" + "\0""7\2\2\2O\0\0\0R\0\0\0R\0\0\0R\0\0\0R\0\0\0R\0\0\0R\0\0\0R\0\0\0R" + "\0\0\0T\1\0\1S\0\0\0B\0\0\0#\0\0\0\11\0\0\0\6\0\0\0\24\2\2\3)\0\0\0>" + "\0\0\0O\0\0\0Z\1\1\1`\7\7\7b\14\14\14g\15\15\16j\16\17\17j\17\20\20j" + "\16\16\17j\14\14\15i\10\10\11e\5\5\5a\1\1\1`\0\0\0_\0\0\0Z\0\0\0S\0\0" + "\0M\0\0\0C\0\0\0;\0\0\0+\0\0\0\31\5\5\5#\12\12\12A\1\0\0Q\0\0\0R\0\0" + "\0S\0\0\0Z\0\0\0`\0\0\0`\4\4\4_\6\6\7`\6\7\7`\7\10\10b\10\10\10b\10\10" + "\11d\10\10\10e\10\10\10c\7\7\7b\4\4\4`\2\2\2`\0\0\0^\0\0\0W\0\0\0O\1" + "\1\1B\7\7\7""1\12\12\13\36\20\20\20\22\7\7\10\37\0\0\0""5\0\0\0B\0\0" + "\0J\0\0\0Q\0\0\0W\0\0\0^\2\3\3`\7\7\7a\13\13\14f\17\17\17i\22\22\23j" + "\25\26\27k\30\30\31k\30\31\32j\25\25\27k\17\17\20j\11\11\12g\3\3\3b\0" + "\0\0`\0\0\0Z\0\0\0N\0\0\0>\2\1\2-\1\1\2\35\0\0\0!\2\2\2<\24\24\24P\7" + "\7\10T\0\0\0R\0\0\0S\0\0\0S\0\0\0S\0\0\0R\0\0\0R\0\0\0R\0\0\0R\0\0\0" + "T\0\0\0P\0\0\0""9\0\0\0\33\0\0\0\31\0\0\0""5\0\0\0L\0\0\0S\0\0\0R\0\0" + "\0R\0\0\0R\0\0\0T\0\0\0V\0\0\0V\0\0\0V\2\3\3W\3\3\3T\0\0\0@\0\0\0\37" + "\0\0\0\6\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\13\0\0\0""3\0\0\0]\211\211Xp\377\377\210q\377\377Hp\363\363\77" + "q\372\372Nq\374\374Qq\375\375Pq\374\374Pr\374\374Or\375\375Oq\374\374" + "Pr\375\375Pq\375\375Pq\374\374Oq\374\374Oq\374\374Oq\372\372Lq\366\366" + "Hq\377\377Sq\363\363Sr\\\\\37p\0\0\0Y\0\0\0""0\26\23\6\15\0\0\0\1\0\2" + "\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\20\0\0\0""1\0\0\0SPQSd\203\204\210fpqtgxz|g\206\210\213" + "g\215\216\222g\222\224\227g\225\227\233g\231\232\236g\233\235\241f\232" + "\234\240g\230\232\236f\230\232\236g\234\236\242g\237\240\245g\234\236" + "\243g\233\235\241f\234\236\242f\233\234\241f\224\226\232g\211\212\217" + "fsuxfOPRg##$f\0\0\0`\0\0\0O\0\0\0:\0\0\0D012a\225\226\231g\236\237\243" + "gy{\177f~\177\203f\177\200\204f~\177\202f\177\200\204g\203\204\210fo" + "qsf./0f\0\0\0[\0\0\0""7\0\0\0&\0\0\0B779c\224\226\230f\221\223\225fp" + "qtfsswfstwfrsufrsvfstwf\\\\_f#$%g\0\0\0Y\0\0\0""4\3\3\3\27\1\1\1\40\0" + "\0\0>\0\0\0V\34\33\34dNOQgmnrg\200\201\205f\212\214\220f\221\222\227" + "g\225\226\233g\227\230\235g\227\231\236g\230\232\237f\226\230\236f\221" + "\223\230g\214\216\223f\207\211\216g|~\202gnptf_`egKLOf./0g\14\14\14e" + "\0\0\0O\0\0\0-\0\0\0+\0\0\0NRSUg\226\227\233f\201\203\207g\202\204\210" + "f\220\222\227g\225\230\235g\233\235\243f\242\244\251g\243\245\252f\242" + "\244\251f\242\244\250f\242\243\250f\241\242\246g\237\240\244g\233\235" + "\241f\225\226\231f\211\212\214fyy|g`acg<=>g\27\30\30f\0\0\0_\0\0\0N\0" + "\0\0""6\0\0\0""6\0\0\0T88:f_`bfZ[^fkkog}\177\202g\211\212\216f\222\223" + "\230g\234\235\242f\243\244\252g\245\246\254f\246\250\256f\251\252\260" + "g\252\254\262f\253\255\263g\251\253\262f\242\244\252f\225\230\236g\203" + "\205\212gghlgABEf\31\31\33e\0\0\0^\0\0\0M\0\0\0=\0\0\0G--.b\237\240\242" + "f\276\276\300g\200\201\205fklqfstxgtuyfsuxfvx{fvwzfVWYf\31\32\32g\0\0" + "\0W\0\0\0=\0\0\0""3\0\0\0K;<=d\213\215\217g\210\211\214f\177\200\202" + "f\202\204\207g\204\205\211g\205\206\211g\212\214\217g\211\212\215g^`" + "bf\33\34\34d\0\0\0I\1\1\1!\12\12\12\7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2" + "\0\0\0\7\0\0\0\14\0\0\0\21\0\0\0\30\0\0\0\"\0\0\0,\0\0\0/\0\0\0/\0\0" + "\0/\0\0\0.\0\0\0&\0\0\0\33\0\0\0\31\0\0\0$\0\0\0;\0\0\0RWWKc\327\327" + "\215f\377\377}f\377\377^f\377\377Sg\377\377Pf\377\377Mf\377\377Mf\377" + "\377Mg\377\377Mg\377\377Mf\377\377Ng\377\377Og\377\377Pf\377\377Tf\377" + "\377[f\377\377cf\327\327TfXX\"d\0\0\0X\0\0\0I\0\0\0=\0\0\0""3\0\0\0+" + "\0\0\0\40\0\0\0\25\2\0\0\13\0\0\0\5\0\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\7\0\0\0\36\0\0\0>NOOV\346\346\350[\353\354\360[" + "\266\271\276[\271\273\300\\\267\271\276\\\262\264\271[\255\257\264\\" + "\251\253\260\\\244\246\253\\\237\241\246\\\234\237\243[\232\234\240\\" + "\227\231\236[\227\231\235\\\232\234\240\\\235\240\244\\\237\241\245\\" + "\240\242\247\\\245\247\254\\\253\255\262[\262\264\272[\273\276\303\\" + "\265\267\274\\\177\200\204\\-./\\\0\0\0R\0\0\0A\0\0\0H\217\217\220Y\376" + "\377\377\\\321\323\333\\\276\300\310\\\307\311\317\\\306\311\317[\305" + "\310\316[\317\322\330\\\311\314\322\\tuy\\\22\22\23Y\0\0\0A\1\1\1$\0" + "\0\0+\0\0\0L\223\223\224[\374\374\377[\303\305\312[\263\265\272\\\271" + "\272\300[\267\271\275\\\265\267\274\\\273\276\302\\\262\264\270\\``c" + "[\14\14\14V\0\0\0=\0\0\0(\0\0\0""7\10\10\10Rijl\\\270\272\276[\256\260" + "\264\\\241\242\247\\\236\240\245\\\235\240\244[\235\237\243\\\234\236" + "\243\\\233\235\242\\\232\234\242[\241\242\250\\\254\256\263\\\263\265" + "\273\\\265\267\275[\267\272\277\\\271\274\301\\\270\273\302[\270\273" + "\303[\275\277\310\\\254\257\266\\XZ^\\\10\10\10Y\0\0\0C\0\0\0-\0\0\0" + "8BCET\332\333\334\\\357\362\365\\\271\275\305[\276\302\311\\\304\310" + "\316[\304\307\316\\\303\305\314\\\302\304\314\\\302\304\312\\\301\303" + "\311[\275\277\305[\266\271\277[\265\270\275\\\267\271\277[\266\271\276" + "\\\264\267\274\\\264\266\273\\\265\266\273\\\265\266\273\\\245\246\252" + "[mnp\\$$%\\\0\0\0Q\0\0\0=\0\0\0AZ[\\U\344\345\347[\314\315\321\\\224" + "\226\232\\\235\237\243\\\240\242\246[\243\245\252\\\250\252\260\\\252" + "\254\262[\254\255\263[\253\256\263[\251\253\261[\247\251\260\\\250\253" + "\261[\254\257\266\\\261\263\273[\264\267\276[\270\272\302[\275\300\310" + "[\277\302\311[\262\264\273\\\204\206\213[;<\77[\5\5\6W\0\0\0F\0\0\0=" + "\0\0\0IvvwX\361\362\363\\\351\353\357\\\261\264\273\\\257\261\267\\\265" + "\270\276\\\265\267\276\\\271\273\301\\\276\300\305\\\220\222\227\\57" + "8[\0\0\0S\0\0\0G\31\32\33P\251\252\255[\355\357\364\\\304\307\313\\\305" + "\307\313[\313\315\322\\\314\316\323\\\321\323\327\\\341\343\347[\265" + "\270\273[<=>[\0\0\0K\0\0\0/\7\7\7\22\1\1\1\3\0\0\0\4\0\0\0\16\0\0\0\34" + "\0\0\0)\0\0\0""7\0\0\0C\0\0\0J\0\4\0N\1\20\1R\1\31\2X\1\33\2Y\1\33\2" + "Z\1\34\2[\0\32\2Y\0\22\1U\0\6\0P\0\0\0L\0\0\0F\0\0\0A\0\0\0@\0\0\0C\0" + "\0\0I%%#PaaLW\211\211YZ\247\247`\\\270\270f[\276\276e\\\276\276a\\\276" + "\276a[\277\277a\\\277\277^\\\271\271Y\\\251\251P\\\213\213D\\cc2Y))\23" + "S\0\0\0G\0\0\0""9\0\1\0""5\0\0\0A;\13\12Un\14\12[P\0\0X\35\0\0P\0\0\0" + "E\0\0\0""7\0\0\0&\2\0\0\26\0\0\0\11\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\15\0\0\0(\0\0\0C\231\230\231P\377\377\377Q\335\337\343P" + "\325\327\334Q\336\337\343Q\334\336\342Q\333\335\341Q\333\335\340Q\333" + "\335\340Q\333\335\340Q\332\333\336Q\331\333\335Q\330\331\334Q\326\327" + "\332Q\310\311\314Q\247\250\254Q\230\232\237Q\235\240\244Q\237\240\245" + "P\240\241\246Q\242\244\250P\244\246\252Q\252\254\261Q\272\274\302Q\236" + "\240\245QBCEQ\0\0\0G\0\0\0>>>@H\315\315\317Q\343\345\350P\262\266\274" + "Q\270\273\301Q\274\276\304Q\272\274\303P\273\276\304Q\307\312\321Q\244" + "\246\253P<=\77Q\0\0\0G\0\0\0+\0\0\0\37\0\0\0""5EEFL\327\327\331Q\336" + "\340\343P\252\254\261Q\260\262\267P\261\262\270P\256\260\266Q\255\260" + "\265Q\270\272\277Q\222\223\227Q/00Q\0\0\0B\0\0\0""2\0\0\0(((<223>{{{B\334\333\334F\311\312\315F\226" + "\230\233F\235\237\243G\240\241\246F\237\241\246F\241\244\251F\244\247" + "\254F\250\253\257F\264\267\275F\206\210\214F&''D\0\0\0""9\0\0\0""9\205" + "\206\207D\364\365\370G\303\305\313F\260\264\272F\272\275\302F\272\274" + "\302F\271\273\302F\300\303\312F\301\304\312FrswF\21\21\22C\0\0\0""1\0" + "\0\0\34\0\0\0\"\0\0\0:\226\226\227F\366\367\371F\275\277\305G\256\260" + "\265F\264\266\273F\262\264\271F\261\262\267F\271\272\277F\262\264\271" + "FabeF\14\14\15A\0\0\0""4\0\0\0""7\201\202\203D\346\347\351F\257\260\264" + "G\236\240\244F\244\246\252F\242\244\250F\240\242\247F\242\244\250F\255" + "\257\263F\177\200\204F\33\33\34B\0\0\0""9\0\0\0""3\0\0\0""1\0\0\0""1" + "\0\0\0""2\0\0\0""3\0\0\0""4\0\0\0""5\0\0\0""7\0\0\0""9\24\24\24;%&'\77" + "\22\23\24>\0\0\0""4\0\0\0(\0\0\0)\20\20\21""3\32\33\34""7\3\4\5""8\0" + "\0\0;\0\0\0<\0\0\0=\0\0\0>\0\0\0=\0\0\0>\0\0\0=\0\0\0=\0\0\0@\225\225" + "\225D\356\360\364F\274\277\305F\263\266\273F\267\271\277F\264\266\274" + "F\261\264\271F\257\261\266F\261\263\270F\262\264\271GrsvF\30\30\31B\0" + "\0\0""4\0\0\0""4++,@HHIA$$%<\10\10\11""9\0\0\0:\0\0\0:\0\0\0:\0\0\0=" + "\0\0\0=\0\0\0=\0\0\0>\0\0\0>!!!@}}|C\345\345\345F\337\340\343F\255\257" + "\265F\252\255\262G\257\261\267F\256\261\270F\254\257\266F\263\266\275" + "F\272\276\306F~\201\206F\36\36\37F\0\0\0:\2\2\2'\0\0\0&\0\0\0""6UUVD" + "\336\336\340F\353\355\360F\255\260\267F\241\244\252F\252\254\262F\250" + "\253\260F\254\257\264F\257\261\267F\243\245\252F\251\254\261F\262\264" + "\271F\255\257\264F\261\262\270F\263\264\272F\265\266\273F\277\301\305" + "F\304\306\312Fz{~F\27\27\30D\0\0\0""3\3\3\3\32\7\7\7\7\0\0\0\6\0\0\0" + "\32\0\0\0""3\7\34\10A\14^\17F\6}\10F\1z\4G\0s\3F\0p\3F\0n\3F\0m\3F\0" + "m\3F\0m\3F\0n\3F\0n\3F\0m\3F\0m\2F\0m\2F\0o\3F\0t\4F\0z\4G\1|\4F\1U\3" + "F\0\25\1E\0\0\0""7\0\1\0\36\5\12\3\11\"!\25\3\34\34\22\5\33\33\22\5\36" + "\36\23\5!!\25\4$#\26\4%%\25\4$%\24\4&+\25\2N`+\1\0\0\0\0\0\0\0\0\11\2" + "\1\2\0\0\0\15\0\0\0!\0\7\7""6\231\35\32D\377\21\17F\371\0\0F\365\2\0" + "F\377\2\0F\377\2\0F\342\2\0FZ\0\0E\0\0\0:\0\0\0&\10\0\0\22\3\0\0\4\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\1\0\1\1\12\3\2\2\30\0\0\0\40\0\0\0!\0\0\0!\0\0\0" + "&\0\0\0+\0\0\0""0\6\6\7""4\21\20\21""5\30\30\31""6\35\35\36""5\35\35" + "\36""5\34\34\35""5\32\32\32""6\23\23\24""7**,8\227\230\233;\304\306\312" + "<\236\240\245;\237\241\245;\241\242\247;\240\242\246<\240\243\247<\242" + "\244\250;\244\245\253;\262\263\271<\234\236\242;BBE<\0\0\0""1\0\0\0+" + ";;=5\315\315\316;\345\347\352<\255\261\270<\263\266\274<\270\272\301" + ";\267\272\300<\270\273\302<\306\311\320;\242\244\251<88:<\0\0\0""4\0" + "\0\0\40\0\0\0\27\0\0\0%JJK7\330\331\332<\335\340\342;\255\260\266<\262" + "\265\272;\263\265\272;\261\263\270<\263\265\273<\275\277\305;\221\223" + "\226;-//:\0\0\0""1\0\0\0/ttu7\347\347\351;\274\275\300;\237\240\245<" + "\247\251\256<\247\250\255;\246\247\253<\245\247\252;\254\254\260;\222" + "\223\226;VWY:<=>9@@B:@@C:@@B;@@B;@AC;@AC:@AC9ABD9BCE9ABD9@BD9@AC9/02" + "<\16\16\17""8\0\0\0*\0\0\0\36\0\0\0'\16\17\20""5PQU:\201\203\207<\223" + "\225\232;\234\236\245;\237\242\247;\237\241\247<\233\235\243<\225\226" + "\235;\241\244\252<\273\276\305;\300\302\311<\272\274\303;\272\274\301" + "<\271\273\301;\267\272\277;\266\270\275;\264\266\273;\264\266\273;\273" + "\275\302;\212\213\220<(()<\0\0\0,\0\1\1\33\0\0\0\32\0\0\0#\0\0\0.\14" + "\14\14""66679TUW\77A$\3\3\4!\0\0\0\33\0\0\0\23\0\0\0\23\0\0\0\36opr&\332\333\337&\265" + "\267\273&\232\234\240&\240\242\246&\241\242\246&\240\241\245&\235\237" + "\243&\237\241\245%\252\253\257&\236\237\243&|~\200%uvw%\235\234\235&" + "\335\335\336&\345\346\351%\261\262\270%\237\241\247&\250\253\260&\251" + "\254\261&\252\254\262&\252\255\262&\256\261\267%\266\270\277&|~\203&" + "\34\35\36%\0\0\0\34\1\0\1\17\0\0\0\17\0\0\0\33""467%\270\273\300%\312" + "\315\324&\244\247\256&\251\254\262%\252\255\263&\251\253\262&\247\252" + "\261&\250\253\261&\250\252\262&\242\244\254&\243\246\254&\250\252\261" + "&\251\253\260%\262\264\272%\255\256\264&jlo%\30\30\31&\0\0\0\40\0\0\0" + "\31\1\1\1\17\0\0\1\6\0\0\0\2\0\0\0\3\5\10\5\11\0\0\0\21\0\0\0\30\4\3" + "\4\35\31%\32!\36""9\40$$M&%)]+%'`*&#\\%&\"[$&#]%&![#&\35V\40$\30G\32" + "%\21""1\22$\14\35\15\"\4\6\4\37\0\0\0\33\0\0\0\30\0\1\1\31\0\0\0\32\0" + "\0\0\32\0\0\0\25\0\0\0\17\0\0\0\10\0\0\1\4\0\0\0\10\0\0\0\24""7\27\26" + "\40\310(%&\377\17\16%\343\0\0&\333\3\0&\336\4\0%\353\4\0%\377\4\1&\377" + "\3\0%\372\2\0%\370\2\0&\372\2\0&\372\2\0&\372\2\0&\372\2\0%\372\2\0&" + "\371\2\0&\373\3\0%\377\3\0&\350\3\0&\\\1\0%\0\0\0\33\0\0\0\15\34\0\0" + "\3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\7\0\0\0\22PPR\32\327\330\332" + "\33\321\323\326\33\246\251\257\33\262\264\272\33\263\267\275\33\263\266" + "\274\33\264\267\274\33\263\266\274\33\262\265\272\33\265\267\274\33\263" + "\265\272\33\246\247\253\33\240\241\243\33\243\244\245\33\242\243\245" + "\33\241\242\244\33\241\242\244\33\241\242\243\32\232\233\234\32\207\210" + "\212\32abd\32++-\31\0\1\1\26\0\0\0\22\0\0\0\15\0\0\0\11\0\0\0\15\0\0" + "\0\26\201\201\201\33\362\363\365\32\275\277\304\33\250\253\260\33\262" + "\264\272\33\262\264\272\33\262\265\273\33\263\266\274\33\263\265\273" + "\33\266\270\277\33\276\301\307\33\300\303\312\33\277\303\311\33\272\275" + "\303\32\263\265\273\33\264\266\273\33\264\267\275\33\262\265\274\33\261" + "\264\272\33\262\264\272\33\261\262\272\33\260\262\270\33\267\271\277" + "\33\256\257\265\33^`c\33\13\14\14\30\0\0\0\25\31\32\34\27\271\272\273" + "\33\365\366\370\33\253\254\261\33\244\245\252\33\254\256\263\33\253\254" + "\261\33\252\254\257\33\261\263\267\33\246\250\253\32LMO\33\0\0\0\31\0" + "\0\0\26\0\0\0\23\0\0\0\22\0\0\0\22\0\0\0\25NNO\32\324\325\327\33\273" + "\275\301\33\233\235\242\32\244\246\254\33\247\251\256\33\263\265\272" + "\33\230\232\236\33:;<\32\0\0\0\30\35\36\37\30\274\274\275\33\355\356" + "\361\33\257\262\271\33\261\263\273\33\267\273\301\33\267\272\301\33\270" + "\273\302\33\272\274\304\33\302\305\315\33\275\300\307\33cei\33\6\6\7" + "\31\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\0\0\0\30\11" + "\11\11\30\24\24\25\30\31\31\32\31\16\16\16\31\0\0\0\26\12\12\14\26\244" + "\245\247\32\346\350\352\33\252\254\261\33\245\247\254\33\250\252\256" + "\33\245\246\252\33\243\244\250\33\247\251\255\33\251\253\257\33ikm\33" + "\15\15\16\32\0\0\0\23\0\0\0\16\0\0\0\21\0\0\0\26\202\202\202\32\351\352" + "\353\33\276\277\303\32\235\237\244\33\247\251\256\33\250\252\257\33\247" + "\251\256\33\250\252\260\33\264\267\275\33\230\231\236\32""88;\33\0\0" + "\0\25\0\0\0\16\0\0\0\21\16\16\20\30\225\226\233\33\330\332\342\33\251" + "\254\263\33\245\250\257\33\251\254\262\33\250\253\262\33\247\251\261" + "\33\253\256\265\33\254\257\266\33\304\305\311\33\334\335\340\33\271\273" + "\301\33\236\241\250\33\247\251\260\33\247\251\260\33\254\256\264\33\267" + "\272\300\33\231\233\240\33DEG\33\5\5\5\32\0\0\0\26\0\0\0\17\1\1\1\10" + "\0\0\0\2\0\0\0\0\13\21\13\1\13\23\13\2\0\4\0\5\0\0\0\7\0\0\0\11\0\0\0" + "\13\0\0\0\14\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\15\0" + "\0\0\13\0\0\0\12\0\0\0\10\0\1\0\5\0\3\0\6\0\0\0\14\12\12\24\25\32\32" + "\216\33\16\16\271\33\0\0d\33\0\0\23\30\0\0\0\23\0\0\0\16\0\0\1\12\0\0" + "\0\15\11\20\17\25\2411/\32\377\35\33\33\374\0\0\33\373\1\0\33\374\2\0" + "\33\371\2\0\33\367\2\0\33\367\2\0\33\371\2\0\33\372\2\0\32\371\2\0\33" + "\371\2\0\33\373\2\0\33\371\2\0\32\371\2\0\33\371\2\0\33\373\2\0\33\377" + "\3\0\33\320\3\0\32C\1\0\31\0\0\0\22\1\0\0\10\35\0\0\1\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\12::;\17\314\314\316\20\332\334\341\21" + "\241\245\254\21\254\257\265\20\260\262\270\20\261\262\270\20\262\264" + "\272\20\261\265\272\20\265\270\275\20\276\301\306\21|}\201\20\22\22\23" + "\20\0\0\0\16\0\0\0\16\0\0\0\16\0\0\0\15\0\0\0\15\0\0\0\15\0\0\0\15\0" + "\0\0\14\0\0\0\15\0\0\0\15\3\3\3\15\10\10\10\16\14\15\15\17\10\10\10\16" + "\0\0\0\13\0\0\0\13""8:;\16\312\312\314\20\340\341\345\20\251\253\261" + "\20\257\261\266\20\263\264\272\20\263\264\272\20\263\265\273\21\264\266" + "\274\20\263\265\274\20\263\266\273\20\315\317\323\20\310\312\320\21\253" + "\255\265\20\257\263\271\21\266\271\300\20\265\270\277\21\263\266\274" + "\20\261\264\273\20\260\263\272\20\260\262\271\20\261\264\272\20\264\267" + "\275\20\264\266\274\20wx|\20\34\35\35\17\0\0\0\13\0\0\0\13''(\16\276" + "\276\277\20\364\365\366\20\257\261\265\21\236\240\245\20\253\254\260" + "\20\255\256\263\20\252\254\260\20\257\262\265\20\260\262\265\21\212\214" + "\217\20UWY\20;;=\20""334\20""456\20Z[]\21\235\236\242\20\256\260\264" + "\20\240\242\246\20\243\245\251\20\243\245\251\20\240\242\247\20\255\257" + "\265\20\231\233\237\21==@\21\0\0\0\16\0\0\0\14YYZ\17\352\352\353\20\337" + "\340\344\20\246\250\260\20\257\262\271\21\270\273\302\20\270\273\302" + "\20\271\273\302\20\270\273\302\20\273\277\306\21\302\305\315\20\271\274" + "\304\21\251\253\262\20\241\243\251\20\232\234\242\20\227\231\237\20\235" + "\240\245\20\245\247\255\20\251\254\261\20\256\261\267\20\273\275\303" + "\20\260\262\270\20_`c\20\5\5\6\17\0\0\0\16\227\226\230\17\361\361\364" + "\20\271\273\277\20\250\252\257\20\255\256\262\20\251\253\260\21\247\252" + "\256\20\254\256\262\20\253\255\261\21ghj\20\21\21\22\17\0\0\0\14\11\11" + "\11\7\15\15\15\5\0\0\0\11\5\6\7\16\237\237\240\20\341\342\344\21\235" + "\240\244\20\240\243\247\20\246\250\255\21\245\247\255\20\246\250\256" + "\20\261\263\271\20\233\234\242\20BCE\20\2\2\2\15\0\0\0\13\0\0\0\15gi" + "l\20\324\326\334\20\272\274\302\20\245\247\256\20\253\256\265\20\253" + "\255\264\20\252\254\263\20\260\263\273\21\255\261\270\20\\^a\20\0\0\0" + "\17ppp\17\371\372\373\20\316\320\325\20\234\240\247\20\246\251\257\20" + "\252\253\262\20\250\251\260\20\261\264\272\21\261\264\272\21z}\200\20" + "()*\20\0\0\0\20\0\0\0\14\3\3\3\10\0\0\0\4\0\0\0\1\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\34""9$\1\25+%\1\25-\34\1\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\1\0\0\0\5\0\0\0\11\31\31E\16\36" + "\36\327\20\4\4\377\20\0\0\377\20\0\0\356\20\0\0\210\21\0\0\26\16\0\0" + "\0\13\0\0\0\12\0\0\0\13Q,+\16\34274\20\377\7\5\20\367\0\0\21\371\4\1" + "\20\372\2\0\20\372\2\0\20\372\2\0\20\372\2\0\20\371\2\0\21\371\2\0\20" + "\371\2\0\20\371\2\0\20\372\2\0\20\372\2\0\20\371\3\0\20\377\2\0\20\377" + "\4\0\20\216\4\1\20\7\0\0\15\0\0\0\10\12\0\0\3\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\3\0\0\0\5\220\220\222\5\362\363\366\6" + "\255\257\266\5\233\237\245\6\254\257\264\5\254\257\265\5\256\260\267" + "\6\260\261\270\5\257\261\270\6\261\264\271\5\265\270\275\5\245\250\255" + "\5\207\211\215\6uvy\6nor\5mmp\5klo\5jkm\6hik\5iil\5qqt\5{|\177\6\206" + "\207\212\5\232\233\237\5\206\207\213\5""335\5\0\0\0\4\0\0\0\3\0\0\0\4" + "\205\205\206\5\366\367\371\6\276\300\305\6\247\251\257\5\261\263\270" + "\5\261\264\271\6\261\263\271\6\266\270\276\5\274\276\304\6tuy\6XXX\5" + "\314\313\313\5\377\377\377\5\327\331\336\6\267\271\300\5\260\263\272" + "\5\255\260\267\6\254\257\265\5\254\257\265\6\253\256\265\5\255\260\267" + "\6\275\300\306\5\300\302\310\5rtw\6\25\25\26\5\0\0\0\3\2\2\2\3\0\0\0" + "\4\1\2\2\4\214\214\215\5\373\373\374\5\345\346\351\5\270\271\277\5\250" + "\252\257\5\245\247\254\5\242\244\251\6\237\241\246\6\244\245\252\5\252" + "\252\260\5\252\253\260\6\250\253\256\5\250\252\256\6\245\247\253\6\235" + "\236\242\6\231\233\237\5\234\236\242\6\237\241\245\6\251\253\257\6\276" + "\300\304\6\263\265\270\6^_a\5\14\15\15\5\0\0\0\3\0\0\0\3\0\0\0\4DDF\6" + "\321\321\322\5\371\373\374\5\322\325\331\5\272\276\304\6\265\270\277" + "\6\263\266\275\5\264\266\276\5\263\266\276\5\262\265\274\6\263\267\276" + "\6\267\272\303\5\271\273\304\5\273\276\306\5\274\277\310\6\274\277\307" + "\5\272\276\306\6\273\276\306\6\274\276\306\5\275\300\307\6\314\316\326" + "\5\236\240\246\5-.0\5\0\0\0\4UVW\5\352\353\354\5\340\341\345\6\250\253" + "\261\5\256\260\266\6\260\261\267\5\255\256\263\6\253\255\261\5\260\262" + "\266\5\250\251\256\6efi\5\30\30\31\6\0\0\0\6\0\0\0\5\0\0\0\4""89;\6\251" + "\252\255\5\273\274\300\6\235\235\242\5\241\243\250\6\242\246\251\5\243" + "\245\251\5\244\246\252\5\260\262\270\5\232\234\241\5AAC\5\0\0\0\5\0\0" + "\0\5\77@B\5\300\302\307\6\310\312\321\6\241\243\252\6\250\252\261\5\251" + "\254\263\6\250\253\262\6\253\256\265\5\265\270\300\5\214\217\224\6-." + "0\5\0\0\0\5\0\0\0\5EFH\6\330\331\332\6\353\354\357\5\255\257\266\6\244" + "\247\256\6\251\254\263\5\247\251\260\6\250\252\262\5\264\267\277\5\244" + "\246\255\5XY\\\5\16\16\17\5\0\0\0\5\0\0\0\3\2\2\2\2\0\0\0\1\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3\1\0\0\0\2\0\0\0\3\0\0\0\2\0\0\0" + "\2\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\2\0\0\0\4\14\14""4\5\26\26\306" + "\5\10\10\377\6\0\0\360\5\0\0\354\5\0\0\365\6\0\0\377\5\0\0\300\5\0\0" + ",\5\0\0\0\4\0\0\0\3\0\0\0\4Q/-\5\335B\77\5\377\24\23\6\377\0\0\6\370" + "\0\0\6\371\1\0\6\371\2\0\5\371\2\0\5\372\2\0\5\372\2\0\6\371\2\0\5\371" + "\2\0\5\370\1\0\6\375\1\0\5\377\2\0\5\377\6\2\5\220\4\3\6\17\0\0\5\0\0" + "\0\3\7\0\0\2\7\0\0\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}; + + diff --git a/gtk/src/mini_icon.png b/gtk/src/mini_icon.png new file mode 100644 index 00000000..a8e85ac0 Binary files /dev/null and b/gtk/src/mini_icon.png differ diff --git a/gtk/src/snes9x.glade b/gtk/src/snes9x.glade new file mode 100644 index 00000000..b1ed054b --- /dev/null +++ b/gtk/src/snes9x.glade @@ -0,0 +1,6886 @@ + + + + + + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK + Snes9x + + + + + + + + + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + _File + True + + + + + _Open ROM Image... + True + True + False + + + + True + gtk-open + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Open Recent + True + + + + + True + + + + + Open with _NetPlay... + True + Open a ROM to use with NetPlay + True + False + + + + True + gtk-network + 1 + + + + + + + True + Open _MultiCart... + True + + + + + + True + + + + + True + _Load State + True + + + + + + True + Slot _0 + True + + + + + + True + Slot _1 + True + + + + + + True + Slot _2 + True + + + + + + True + Slot _3 + True + + + + + + True + Slot _4 + True + + + + + + True + Slot _5 + True + + + + + + True + Slot _6 + True + + + + + + True + Slot _7 + True + + + + + + True + Slot _8 + True + + + + + + True + + + + + True + From _File... + True + + + + + + + + + + True + _Save State + True + + + + + + True + Slot _0 + True + + + + + + True + Slot _1 + True + + + + + + True + Slot _2 + True + + + + + + True + Slot _3 + True + + + + + + True + Slot _4 + True + + + + + + True + Slot _5 + True + + + + + + True + Slot _6 + True + + + + + + True + Slot _7 + True + + + + + + True + Slot _8 + True + + + + + + True + + + + + True + To _File... + True + + + + + + + + + + True + + + + + Save SPC... + True + True + False + + + + True + gtk-save + 1 + + + + + + + True + + + + + Show ROM _Info... + True + True + False + + + + True + gtk-dialog-info + 1 + + + + + + + True + + + + + _Quit + True + True + False + + + + True + gtk-quit + 1 + + + + + + + + + + + True + _Emulation + True + + + + + Run / _Continue + True + True + False + + + + True + gtk-go-forward + 1 + + + + + + + _Pause + True + True + False + + + + True + gtk-media-pause + 1 + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + Load _Movie... + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + + + + True + gtk-open + 1 + + + + + + + R_ecord Movie... + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + + + + True + gtk-media-record + 1 + + + + + + + _Stop Recording + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + + + + True + gtk-media-stop + 1 + + + + + + + _Jump to Frame... + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + + + + True + gtk-media-next + 1 + + + + + + + True + + + + + Sy_nc Clients + True + True + False + + + + True + gtk-revert-to-saved + 1 + + + + + + + True + + + + + Reset + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + False + + + + True + gtk-redo + 1 + + + + + + + Soft _Reset + True + True + False + + + + True + gtk-refresh + 1 + + + + + + + + + + + True + _View + True + + + + + + _Hide Menu + True + True + False + + + + True + gtk-leave-fullscreen + 1 + + + + + + + True + _Status Bar + True + + + + + + True + + + + + _Change Size + True + True + False + + + True + + + True + False + Exact Pixels + True + + + + + True + _1x + True + + + + + + True + _2x + True + + + + + + True + _3x + True + + + + + + True + _4x + True + + + + + + True + _5x + True + + + + + + True + + + + + True + False + Correct Aspect + True + + + + + True + 1x + True + + + + + + True + 2x + True + + + + + + True + 3x + True + + + + + + True + 4x + True + + + + + + True + 5x + True + + + + + + + + True + gtk-zoom-in + 1 + + + + + + + True + + + + + _Fullscreen + True + True + False + + + + True + gtk-fullscreen + 1 + + + + + + + + + + + True + _Options + True + + + + + True + Controller Ports + True + + + + + True + SNES Port 1 + True + + + + + + True + Joypad + True + + + + + + True + Mouse + True + joypad1 + + + + + + True + Superscope + True + True + joypad1 + + + + + + + + + + True + SNES Port 2 + True + + + + + + True + Joypad + True + + + + + + True + Mouse + True + joypad2 + + + + + + True + Multitap + True + joypad2 + + + + + + True + Superscope + True + True + joypad2 + + + + + + + + + + + + + + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Cheats... + True + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + _Preferences... + True + True + False + + + + True + gtk-preferences + 1 + + + + + + + + + + + False + 0 + + + + + 256 + 224 + True + True + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK | GDK_SUBSTRUCTURE_MASK + + + + + + + + 1 + + + + + True + + + False + 2 + + + + + + + GDK_KEY_PRESS_MASK + Snes9x Preferences + center + 480 + dialog + True + False + + + + + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + left + 1 + 1 + 1 + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + never + automatic + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + queue + none + + + True + 5 + + + True + 0 + none + + + True + 5 + 5 + 12 + + + True + 5 + + + Use fullscreen on ROM open + True + True + False + Go to fullscreen mode immediately after opening a ROM + True + True + + + False + False + 0 + + + + + Show frame rate + True + True + False + True + True + + + False + False + 1 + + + + + Use overscanned height + True + True + False + Use SNES extended height. Will probably cause letterboxing + True + True + + + False + False + 2 + + + + + True + 12 + + + Change fullscreen resolution: + True + True + False + Changes the screen resolution when running Snes9x in fullscreen mode + True + True + + + False + False + 0 + + + + + True + + + + 1 + + + + + False + False + 3 + + + + + + + + + True + <b>Basic Settings</b> + True + + + label_item + + + + + False + 0 + + + + + True + 0 + none + + + True + 5 + 5 + 12 + + + True + 5 + + + Scale image to fit window + True + True + False + Scales the image so no black bars are present + True + True + + + False + False + 0 + + + + + True + 12 + + + Maintain aspect-ratio: + True + True + False + Scales the image as large as possible without distortion + True + True + + + False + False + 0 + + + + + True + 8:7 Square pixels +4:3 SNES correct aspect + + + False + 1 + + + + + 1 + + + + + Force SNES-hires output + True + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Detects frames that are not output by Snes9x in hires, and scales them + True + + + 2 + + + + + True + 5 + + + Use + True + True + False + Allows scaling and filtering to use multiple processors + True + True + + + False + False + 0 + + + + + True + True + 2 2 8 1 1 0 + True + True + + + False + 1 + + + + + True + threads for filtering and scaling + + + False + 2 + + + + + 3 + + + + + True + 12 + + + True + 0 + Apply scaling filter: + + + False + 0 + + + + + True + None +SuperEagle +2xSaI +Super2xSaI +hq2x +hq3x +hq4x +EPX +EPX Smooth +Blargg's NTSC +Scanlines + + + + 1 + + + + + False + False + 4 + + + + + + + + + True + <b>Image Adjustments</b> + True + + + label_item + + + + + False + 1 + + + + + True + 0 + none + + + True + 5 + 5 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Video preset: + + + False + 0 + + + + + True + + + Composite + True + True + True + + + + False + 0 + + + + + S-Video + True + True + True + + + + False + 1 + + + + + RGB + True + True + True + + + + False + 2 + + + + + Monochrome + True + True + True + + + + False + 3 + + + + + False + 1 + + + + + 0 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 11 + 2 + 12 + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Artifacts: + + + 6 + 7 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Sharpness: + + + 4 + 5 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Brightness: + + + 3 + 4 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Contrast: + + + 2 + 3 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Saturation: + + + 1 + 2 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Hue: + + + GTK_FILL + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 -1 1 0.01 0.10000000000000001 0 + False + -1 + 2 + left + + + 1 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 -1 1 0.01 0.10000000000000001 0 + False + -1 + 2 + left + + + 1 + 2 + 1 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 -1 1 0.01 0.10000000000000001 0 + False + -1 + 2 + left + + + 1 + 2 + 2 + 3 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 -1 1 0.01 0.10000000000000001 0 + False + -1 + 2 + left + + + 1 + 2 + 3 + 4 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1.0408340855860843e-17 -1 1 0.01 0.10000000000000001 0 + False + -1 + 2 + left + + + 1 + 2 + 4 + 5 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 -1 1 0.01 0.10000000000000001 0 + False + -1 + 2 + left + + + 1 + 2 + 6 + 7 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 -1 1 0.01 0.10000000000000001 0 + False + -1 + 2 + left + + + 1 + 2 + 7 + 8 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 -1 1 0.01 0.10000000000000001 0 + False + -1 + 2 + left + + + 1 + 2 + 8 + 9 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 -1 1 0.01 0.10000000000000001 0 + False + -1 + 2 + left + + + 1 + 2 + 9 + 10 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 -1 1 0.01 0.10000000000000001 0 + False + -1 + 2 + left + + + 1 + 2 + 10 + 11 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Gamma: + + + 7 + 8 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Fringing: + + + 8 + 9 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Bleed: + + + 9 + 10 + GTK_FILL + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Resolution: + + + 10 + 11 + GTK_FILL + + + + + True + + + 2 + 5 + 6 + + + + + 1 + + + + + Merge odd and even fields + True + True + False + True + + + 2 + + + + + True + 12 + + + True + 0 + Scanline intensity: + + + False + 0 + + + + + True + 0% +12.5% +25% +50% +100% + + + False + 1 + + + + + 3 + + + + + + + + + True + <b>NTSC Filter</b> + True + + + label_item + + + + + False + 2 + + + + + True + 0 + none + + + True + 5 + 5 + 12 + + + True + 12 + + + True + 0 + Scanline intensity: + + + False + 0 + + + + + True + 12.5% +25% +50% +100% + + + False + 1 + + + + + + + + + True + <b>Scanline Filter</b> + True + + + label_item + + + + + False + 3 + + + + + True + 0 + none + + + True + 5 + 5 + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + 0 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + Bilinear-filter output + True + True + False + Smoothens (blurs) the image + True + True + + + 0 + + + + + Sync to vertical blank + True + True + False + Sync the image to the vertical retrace to stop tearing + True + True + + + False + False + 1 + + + + + Allow non-power-of-two textures + True + True + False + Prevents edge artifacts, but can slow performance + True + + + 2 + + + + + Use pixel-buffer objects + True + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Can be faster or slower depending on drivers + True + + + 3 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Different formats can yield highly different performance + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Pixel-buffer format: + + + False + 0 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 16-bit (GL_BGRA) +24-bit (GL_RGB) +32-bit (GL_BGRA) + + + False + 1 + + + + + + + 4 + + + + + 1 + + + + + True + + + Force an inverted byte-ordering + True + True + False + Forces a swapped byte-ordering for cases where the system's endian is used instead of the video card + True + + + 0 + + + + + 2 + + + + + + + + + True + <b>Hardware Acceleration</b> + True + + + label_item + + + + + False + 4 + + + + + + + + + + + True + + + True + video-display + + + 0 + + + + + True + Display + True + + + False + False + 1 + + + + + False + tab + + + + + True + True + never + automatic + + + True + queue + none + + + True + 5 + 0 + none + + + True + 12 + + + True + 5 + 5 + + + True + 12 + + + True + Sound driver: + + + False + False + 0 + + + + + True + + + + False + False + 1 + + + + + False + False + 0 + + + + + Synchronize with sound + True + True + False + Base emulation speed on the rate sound is output + True + + + False + False + 1 + + + + + Mute sound output + True + True + False + Disables output of sound + True + True + + + False + False + 2 + + + + + Stereo + True + True + False + Output two channels, left and right + True + True + + + False + False + 3 + + + + + True + 3 + 2 + 10 + 5 + + + True + 0 + Playback rate: + + + GTK_FILL + + + + + + True + 5 + + + True + True + 2 2 256 1 1 0 + True + True + + + False + 0 + + + + + True + milliseconds + + + False + 1 + + + + + 1 + 2 + 2 + 3 + GTK_FILL + GTK_FILL + + + + + True + 0 + Buffer size: + + + 2 + 3 + GTK_FILL + GTK_FILL + + + + + True + 0 + Input rate: + + + 1 + 2 + GTK_FILL + + + + + True + True + Adjust to produce more or less data. Decrease the rate if experiencing crackling. Increase the rate if experiencing frame-rate stuttering. Best used with the "Synchronize with sound" option + 31990 31500 32500 1 10 0 + False + 0 + left + + + 1 + 2 + 1 + 2 + + + + + True + + + True + 48000 hz +44100 hz +32000 hz (SNES Default) +22050 hz +16000 hz +11025 hz +8000 hz +0 hz + + + False + False + 0 + + + + + 1 + 2 + GTK_FILL + + + + + False + 4 + + + + + + + + + True + <b>Sound Settings</b> + True + + + label_item + + + + + + + + + 1 + + + + + True + + + True + audio-x-generic + + + 0 + + + + + True + Sound + True + + + False + False + 1 + + + + + 1 + False + tab + + + + + True + True + automatic + automatic + + + True + queue + none + + + True + + + True + 5 + 0 + none + + + True + 12 + + + True + 5 + 5 + + + True + 10 + + + True + Frameskip: + + + False + False + 0 + + + + + True + Automatic +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + + + False + False + 1 + + + + + False + 0 + + + + + Enable HDMA + True + True + False + Enable HDMA. Required feature for compatibility with some games + True + True + + + False + False + 1 + + + + + Block invalid VRAM access + True + True + False + True + + + 2 + + + + + Allow opposing dpad directions + True + True + False + Let left and right or up and down be pressed at the same time + True + + + 3 + + + + + + + + + True + <b>Accuracy</b> + True + + + label_item + + + + + False + 0 + + + + + True + 5 + 0 + none + + + True + 12 + + + True + 5 + 5 + + + Pause emulation when switching away from Snes9x + True + True + False + True + + + 0 + + + + + True + 12 + + + True + The ESC key should: + + + False + 0 + + + + + True + Toggle the menu bar +Exit fullscreen mode +Quit Snes9x + + + False + 1 + + + + + 1 + + + + + + + + + True + <b>Window Switching</b> + True + + + label_item + + + + + False + 1 + + + + + True + 5 + 0 + none + + + True + 12 + + + True + 5 + + + Prevent the screensaver from activating + True + True + False + True + + + 0 + + + + + + + + + True + <b>Screensaver</b> + True + + + label_item + + + + + False + 2 + + + + + + + + + 2 + + + + + True + + + True + utilities-terminal + + + 0 + + + + + True + Emulation + True + + + False + False + 1 + + + + + 2 + False + tab + + + + + True + + + True + 5 + 0 + none + + + True + 12 + + + True + 2 + 2 + 5 + 10 + + + True + 5 + + + True + True + Automatically save the game's SRAM at this interval. Setting this to 0 will only save when quitting or changing ROMs + 4 + + + 0 + + + + + True + seconds after change + + + False + False + 1 + + + + + 1 + 2 + 1 + 2 + + + + + + + True + + + ROM folder + True + True + False + Store data in the same folder as the ROM file used + True + True + + + False + False + 0 + + + + + Snes9x configuration folder + True + True + False + Store data in $HOME/.snes9x/sram + True + True + rom_folder_radio + + + False + False + 1 + + + + + Custom folder: + True + True + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + rom_folder_radio + + + False + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 9 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + + + 0 + + + + + Browse... + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + False + 1 + + + + + 3 + + + + + 1 + 2 + + + + + + True + 0 + Save SRAM: + + + 1 + 2 + + + + + + + True + 0 + Save data in: + + + + + + + + + + + + + True + <b>Game Data</b> + True + + + label_item + + + + + False + 0 + + + + + 3 + + + + + True + + + True + folder + + + 0 + + + + + True + Files + True + + + False + False + 1 + + + + + 3 + False + tab + + + + + True + 5 + 5 + + + True + 5 + + + True + 5 + <b>Joypad:</b> + True + + + False + False + 0 + + + + + True + 1 +2 +3 +4 +5 +1+ +2+ +3+ +4+ +5+ + + + + False + 1 + + + + + True + + + False + 2 + + + + + _Reset + True + True + True + True + + + + False + False + 3 + + + + + True + + + False + 4 + + + + + True + Swap with: + + + False + 5 + + + + + True + 1 +2 +3 +4 +5 +1+ +2+ +3+ +4+ +5+ + + + False + 6 + + + + + _Swap + True + True + True + True + + + + False + 7 + + + + + False + 0 + + + + + Use modifier keys (CTRL, SHIFT, ALT) directly + True + True + False + Allow using modifier keys as independent keys instead of modifiers + True + True + + + False + False + 1 + + + + + True + True + + + + True + 10 + 12 + + + True + 6 + 2 + 10 + 5 + + + True + 0 + Up + + + GTK_FILL + + + + + + True + 0 + Down + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + Left + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + Right + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + Start + + + 4 + 5 + GTK_FILL + + + + + + True + 0 + Select + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + + + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 0 + + + + + True + 6 + 2 + 10 + 5 + + + True + 0 + A + + + GTK_FILL + + + + + + True + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + GTK_FILL + + + + + 1 + + + + + + + True + Buttons + + + False + tab + + + + + True + 5 + 2 + 2 + 5 + + + True + 5 + 6 + 2 + 10 + 5 + + + True + 0 + A + + + GTK_FILL + + + + + + True + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + GTK_FILL + + + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + 5 + 6 + 2 + 10 + 5 + + + True + 0 + A + + + GTK_FILL + + + + + + True + 0 + B + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + X + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + Y + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + L + + + 4 + 5 + GTK_FILL + + + + + + True + 0 + R + + + 5 + 6 + GTK_FILL + + + + + + 50 + True + True + False + + + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 1 + 2 + GTK_FILL + + + + + True + 0 + <b>Sticky</b> + True + center + + + 1 + 2 + + + + + + + True + 0 + <b>Turbo</b> + True + center + + + + + + + + + 1 + False + + + + + True + Turbo / Sticky Buttons + + + 1 + False + tab + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 0 + none + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + 5 + 5 + + + True + Set new axis bindings at: + + + False + False + 0 + + + + + True + True + Changes the amount a joystick should be tilted to register a button press + 50 1 100 1 10 0 + 1 + True + + + False + False + 1 + + + + + True + percent + + + False + False + 2 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Joystick Axis Threshold</b> + True + + + label_item + + + + + False + 0 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + none + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 12 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Center all axes on all joysticks and press Calibrate. + + + False + False + 0 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + Cali_brate + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + False + False + 0 + + + + + + + + False + False + 1 + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <b>Calibration</b> + True + + + label_item + + + + + 1 + + + + + 2 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Joystick Options + + + 2 + False + tab + + + + + 2 + + + + + True + <small>Click an entry and then press the desired keys or joystick button +<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> + True + fill + True + + + False + 3 + + + + + 4 + + + + + True + + + True + input-gaming + + + 0 + + + + + True + Joypads + True + + + False + False + 1 + + + + + 4 + False + tab + + + + + True + 5 + 5 + + + True + 0 + 5 + <b>Snes9x Emulator Shortcut Keys</b> + True + + + False + False + 0 + + + + + True + + + False + False + 1 + + + + + True + True + + + + True + True + never + automatic + + + True + queue + none + + + True + 10 + 11 + 2 + 10 + 5 + + + True + 0 + Soft reset + + + 9 + 10 + GTK_FILL + + + + + + True + 0 + Hardware reset + + + 8 + 9 + GTK_FILL + + + + + + True + 0 + Increase frame time + + + 7 + 8 + GTK_FILL + + + + + + True + 0 + Decrease frame time + + + 6 + 7 + GTK_FILL + + + + + + True + 0 + Increase frame rate + + + 5 + 6 + GTK_FILL + + + + + + True + 0 + Decrease frame rate + + + 4 + 5 + GTK_FILL + + + + + + True + 0 + Pause + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + Toggle turbo + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + Enable turbo + + + 1 + 2 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Open ROM + + + GTK_FILL + + + + + + True + 0 + Quit Snes9x + + + 10 + 11 + GTK_FILL + GTK_FILL + + + + + True + True + False + + + 1 + 2 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 9 + 10 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 10 + 11 + GTK_FILL + + + + + + + + + + + True + Emulation + + + False + tab + + + + + True + True + never + automatic + + + True + queue + none + + + True + 10 + 8 + 2 + 10 + 5 + + + True + 0 + Toggle BG layer 0 + + + GTK_FILL + + + + + + True + 0 + Toggle BG layer 1 + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + Toggle BG layer 2 + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + Toggle BG layer 3 + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + Toggle sprites + + + 4 + 5 + GTK_FILL + + + + + + True + 0 + BG layering hack + + + 5 + 6 + GTK_FILL + + + + + + True + 0 + Screenshot + + + 6 + 7 + GTK_FILL + + + + + + True + 0 + Toggle fullscreen + + + 7 + 8 + GTK_FILL + + + + + + True + True + False + + + 1 + 2 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + + + + + 1 + + + + + True + Graphics + + + 1 + False + tab + + + + + True + True + never + automatic + + + True + queue + none + + + True + 10 + 10 + 4 + 10 + 5 + + + True + 0 + <b>Quick save state</b> + True + center + + + 2 + + + + + + + True + 0 + <b>Quick load state</b> + True + + + 2 + 4 + + + + + + + True + 0 + Slot 1 + + + 2 + 3 + + + + + + + True + 0 + Slot 0 + + + 1 + 2 + + + + + + + True + 0 + Slot 2 + + + 3 + 4 + + + + + + + True + 0 + Slot 3 + + + 4 + 5 + + + + + + + True + 0 + Slot 4 + + + 5 + 6 + + + + + + + True + 0 + Slot 5 + + + 6 + 7 + + + + + + + True + 0 + Slot 6 + + + 7 + 8 + + + + + + + True + 0 + Slot 7 + + + 8 + 9 + + + + + + + True + 0 + Slot 0 + + + 2 + 3 + 1 + 2 + + + + + + + True + 0 + Slot 1 + + + 2 + 3 + 2 + 3 + + + + + + + True + 0 + Slot 2 + + + 2 + 3 + 3 + 4 + + + + + + + True + 0 + Slot 3 + + + 2 + 3 + 4 + 5 + + + + + + + True + 0 + Slot 4 + + + 2 + 3 + 5 + 6 + + + + + + + True + 0 + Slot 5 + + + 2 + 3 + 6 + 7 + + + + + + + True + 0 + Slot 6 + + + 2 + 3 + 7 + 8 + + + + + + + True + 0 + Slot 7 + + + 2 + 3 + 8 + 9 + + + + + + + True + 0 + Slot 8 + + + 2 + 3 + 9 + 10 + + + + + + + True + 0 + Slot 8 + + + 9 + 10 + + + + + + + 50 + True + True + False + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + 50 + True + True + False + + + 1 + 2 + 9 + 10 + GTK_FILL + + + + + 50 + True + True + False + + + 3 + 4 + 1 + 2 + GTK_FILL + + + + + 50 + True + True + False + + + 3 + 4 + 3 + 4 + GTK_FILL + + + + + 50 + True + True + False + + + 3 + 4 + 2 + 3 + GTK_FILL + + + + + 50 + True + True + False + + + 3 + 4 + 4 + 5 + GTK_FILL + + + + + 50 + True + True + False + + + 3 + 4 + 5 + 6 + GTK_FILL + + + + + 50 + True + True + False + + + 3 + 4 + 9 + 10 + GTK_FILL + + + + + 50 + True + True + False + + + 3 + 4 + 7 + 8 + GTK_FILL + + + + + 50 + True + True + False + + + 3 + 4 + 6 + 7 + GTK_FILL + + + + + 50 + True + True + False + + + 3 + 4 + 8 + 9 + GTK_FILL + + + + + + + + + 2 + + + + + True + Save States + + + 2 + False + tab + + + + + True + True + never + automatic + + + True + queue + none + + + True + 10 + 9 + 2 + 10 + 5 + + + True + 0 + Toggle sound channel 0 + + + GTK_FILL + + + + + + True + 0 + Toggle sound channel 1 + + + 1 + 2 + GTK_FILL + + + + + + True + 0 + Toggle sound channel 2 + + + 2 + 3 + GTK_FILL + + + + + + True + 0 + Toggle sound channel 3 + + + 3 + 4 + GTK_FILL + + + + + + True + 0 + Toggle sound channel 4 + + + 4 + 5 + GTK_FILL + + + + + + True + 0 + Toggle sound channel 5 + + + 5 + 6 + GTK_FILL + + + + + + True + 0 + Toggle sound channel 6 + + + 6 + 7 + GTK_FILL + + + + + + True + 0 + Toggle sound channel 7 + + + 7 + 8 + GTK_FILL + + + + + + True + 0 + Toggle all sound channels + + + 8 + 9 + GTK_FILL + + + + + + True + True + False + + + 1 + 2 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 8 + 9 + GTK_FILL + + + + + + + + + 3 + + + + + True + Sound + + + 3 + False + tab + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + 6 + 2 + 10 + 5 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Seek to frame + + + 4 + 5 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Load Movie + + + 3 + 4 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Stop movie recording + + + 2 + 3 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Begin movie recording + + + 1 + 2 + GTK_FILL + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Save SPC + + + GTK_FILL + + + + + + True + True + False + + + 1 + 2 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + True + False + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + 0 + Swap controllers 1 & 2 + + + 5 + 6 + GTK_FILL + + + + + + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + 4 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Misc + + + 4 + False + tab + + + + + 2 + + + + + True + <small>Click an entry and then press the desired keys or joystick button +<i>Escape</i>: Move to next<i> Shift-Escape</i>: Clear selected</small> + True + fill + True + + + False + False + 3 + + + + + 5 + + + + + True + + + True + input-keyboard + + + 0 + + + + + True + Shortcuts + True + + + False + False + 1 + + + + + 5 + False + tab + + + + + True + 5 + + + True + 5 + + + True + gtk-missing-image + + + + + False + 0 + + + + + True + 0 + 10 + 10 + label106 + True + center + True + + + False + False + 1 + + + + + True + True + 5 + automatic + + + True + queue + out + + + True + True + False + False + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + + + + + + + 2 + + + + + 6 + + + + + True + + + True + dialog-information + + + 0 + + + + + True + Version Info + True + + + False + False + 1 + + + + + 6 + False + tab + + + + + + + 2 + + + + + True + end + + + gtk-cancel + -6 + True + True + True + False + True + + + False + False + 0 + + + + + gtk-apply + -10 + True + True + True + False + True + + + + False + False + 1 + + + + + gtk-ok + -5 + True + True + True + False + True + + + False + False + 2 + + + + + False + end + 0 + + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Advance to Frame + center-on-parent + dialog + True + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + The current frame in the movie is + True + + + 0 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 10 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + Fast-forward to frame + + + 0 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + 1 + + + + + 1 + + + + + False + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + end + + + gtk-cancel + -6 + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + False + False + 0 + + + + + gtk-ok + -5 + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + False + False + 1 + + + + + False + end + 0 + + + + + + + 512 + 350 + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 5 + Snes9x Cheats + center-on-parent + dialog + True + False + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + 5 + + + True + 0 + in + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + + label_item + + + + + 0 + + + + + True + 5 + 5 + + + True + 0 + Type: + + + False + 0 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Game Genie +Pro Action Replay +Goldfinger + + + False + False + 1 + + + + + True + 0 + Description: + + + False + 2 + + + + + True + True + 21 + + + False + 3 + + + + + True + 0 + Code: + + + False + 4 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + False + 5 + + + + + gtk-add + True + True + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + False + False + 6 + + + + + True + + + False + 7 + + + + + gtk-remove + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + + False + False + 8 + + + + + False + False + 1 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + end + + + gtk-close + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + False + False + 0 + + + + + False + end + 0 + + + + + + + 5 + Snes9x NetPlay + center-on-parent + dialog + False + + + True + 2 + + + True + 5 + 5 + + + True + 0 + none + + + True + 12 + + + True + 5 + 5 + + + True + True + The game chosen will be loaded before connecting. This field can be blank if the server will send the ROM image + False + + + 0 + + + + + Browse... + True + True + True + + + + False + 1 + + + + + True + True + True + + + + True + Clear entry + gtk-clear + 1 + + + + + False + 2 + + + + + + + + + True + <b>ROM Image</b> + True + + + label_item + + + + + False + 0 + + + + + True + 0 + none + + + True + 5 + 12 + + + True + + + Connect to another computer + True + True + False + Connect to another computer that is running Snes9x NetPlay as a server + True + True + + + 0 + + + + + True + 5 + 5 + + + True + Name or IP address: + + + False + 0 + + + + + True + True + Domain name or internet protocol address of a remote computer + + + 1 + + + + + True + Port: + + + False + 2 + + + + + True + True + Connect to specified TCP port on remote computer + 6096 1 9999 1 1 0 + True + True + + + False + 3 + + + + + 1 + + + + + Act as a server + True + True + False + Host a game on this computer as Player 1, requiring extra throughput to support multitple users + True + True + connect_radio + + + + 2 + + + + + + + + + True + <b>Server</b> + True + + + label_item + + + + + False + 1 + + + + + True + 0 + none + + + True + 12 + + + True + 5 + 5 + + + Sync using reset + True + True + False + Reset the game when players join instead of transferring potentially unreliable freeze states + True + + + False + 0 + + + + + Send ROM image to clients + True + True + False + Send the running game image to players instead of requiring them to have their own copies + True + + + False + 1 + + + + + True + 5 + + + True + Default port: + + + False + 0 + + + + + True + True + TCP port used as a connection point for remote clients + 6096 1 9999 1 1 0 + True + True + + + False + 1 + + + + + False + 2 + + + + + True + 5 + + + True + Ask server to pause when + + + False + 0 + + + + + True + True + 1 1 60 1 1 0 + True + True + + + False + 1 + + + + + True + frames behind + + + False + 2 + + + + + False + 3 + + + + + + + + + True + <b>Settings</b> + True + + + label_item + + + + + 2 + + + + + 1 + + + + + True + end + + + gtk-cancel + -6 + True + True + True + True + + + False + False + 0 + + + + + gtk-connect + -5 + True + True + True + True + True + + + False + False + 1 + + + + + False + end + 0 + + + + + + + 5 + Open Multiple ROM Images (MultiCart) + center-on-parent + 320 + dialog + False + + + True + + + True + 5 + + + True + 12 + + + True + Slot A: + + + False + 0 + + + + + True + False + Select an Image for Slot A + + + 1 + + + + + False + 0 + + + + + True + 12 + + + True + Slot B: + + + False + 0 + + + + + True + False + Select an Image for Slot B + + + 1 + + + + + False + 1 + + + + + 1 + + + + + True + end + + + gtk-cancel + -6 + True + True + True + True + + + False + False + 0 + + + + + gtk-ok + -5 + True + True + True + True + + + False + False + 1 + + + + + False + end + 0 + + + + + + diff --git a/gtk/src/snes_ntsc.c b/gtk/src/snes_ntsc.c new file mode 100644 index 00000000..bdab87d9 --- /dev/null +++ b/gtk/src/snes_ntsc.c @@ -0,0 +1,271 @@ +/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */ + +#include "snes_ntsc.h" + +/* Copyright (C) 2006-2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +snes_ntsc_setup_t const snes_ntsc_monochrome = { 0,-1, 0, 0,.2, 0,.2,-.2,-.2,-1, 1, 0, 0 }; +snes_ntsc_setup_t const snes_ntsc_composite = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; +snes_ntsc_setup_t const snes_ntsc_svideo = { 0, 0, 0, 0,.2, 0,.2, -1, -1, 0, 1, 0, 0 }; +snes_ntsc_setup_t const snes_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1, 1, 0, 0 }; + +#define alignment_count 3 +#define burst_count 3 +#define rescale_in 8 +#define rescale_out 7 + +#define artifacts_mid 1.0f +#define fringing_mid 1.0f +#define std_decoder_hue 0 + +#define rgb_bits 7 /* half normal range to allow for doubled hires pixels */ +#define gamma_size 32 + +#include "snes_ntsc_impl.h" + +unsigned int scanline_offset = 0; +unsigned short scanline_mask = 0xffff; + +/* 3 input pixels -> 8 composite samples */ +pixel_info_t const snes_ntsc_pixels [alignment_count] = { + { PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } }, + { PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } }, + { PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } }, +}; + +static void merge_kernel_fields( snes_ntsc_rgb_t* io ) +{ + int n; + for ( n = burst_size; n; --n ) + { + snes_ntsc_rgb_t p0 = io [burst_size * 0] + rgb_bias; + snes_ntsc_rgb_t p1 = io [burst_size * 1] + rgb_bias; + snes_ntsc_rgb_t p2 = io [burst_size * 2] + rgb_bias; + /* merge colors without losing precision */ + io [burst_size * 0] = + ((p0 + p1 - ((p0 ^ p1) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + io [burst_size * 1] = + ((p1 + p2 - ((p1 ^ p2) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + io [burst_size * 2] = + ((p2 + p0 - ((p2 ^ p0) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + ++io; + } +} + +static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ) +{ + int n; + for ( n = burst_count; n; --n ) + { + unsigned i; + for ( i = 0; i < rgb_kernel_size / 2; i++ ) + { + snes_ntsc_rgb_t error = color - + out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] - + out [i + 7] - out [i + 5 +14] - out [i + 3 +28]; + DISTRIBUTE_ERROR( i+3+28, i+5+14, i+7 ); + } + out += alignment_count * rgb_kernel_size; + } +} + +void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ) +{ + int merge_fields; + int entry; + init_t impl; + if ( !setup ) + setup = &snes_ntsc_composite; + init( &impl, setup ); + + merge_fields = setup->merge_fields; + if ( setup->artifacts <= -1 && setup->fringing <= -1 ) + merge_fields = 1; + + for ( entry = 0; entry < snes_ntsc_palette_size; entry++ ) + { + /* Reduce number of significant bits of source color. Clearing the + low bits of R and B were least notictable. Modifying green was too + noticeable. */ + int ir = entry >> 8 & 0x1E; + int ig = entry >> 4 & 0x1F; + int ib = entry << 1 & 0x1E; + + #if SNES_NTSC_BSNES_COLORTBL + if ( setup->bsnes_colortbl ) + { + int bgr15 = (ib << 10) | (ig << 5) | ir; + unsigned long rgb16 = setup->bsnes_colortbl [bgr15]; + ir = rgb16 >> 11 & 0x1E; + ig = rgb16 >> 6 & 0x1F; + ib = rgb16 & 0x1E; + } + #endif + + { + float rr = impl.to_float [ir]; + float gg = impl.to_float [ig]; + float bb = impl.to_float [ib]; + + float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i ); + + int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g ); + snes_ntsc_rgb_t rgb = PACK_RGB( r, g, b ); + + snes_ntsc_rgb_t* out = ntsc->table [entry]; + gen_kernel( &impl, y, i, q, out ); + if ( merge_fields ) + merge_kernel_fields( out ); + correct_errors( rgb, out ); + } + } +} + +#ifndef SNES_NTSC_NO_BLITTERS + +/* 12.5% scanlines like in snes_ntsc example instead of zsnes's 25% */ +#define PIXEL_OUT( x ) \ + SNES_NTSC_RGB_OUT( x, value, 15 ); \ + line_outa[x] = value; \ + line_outb[x] = value - (value >> scanline_offset & scanline_mask); + +void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, + int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) +{ + unsigned value; + int chunk_count = (in_width - 1) / snes_ntsc_in_chunk; + for ( ; in_height; --in_height ) + { + SNES_NTSC_IN_T const* line_in = input; + SNES_NTSC_BEGIN_ROW( ntsc, burst_phase, + snes_ntsc_black, snes_ntsc_black, SNES_NTSC_ADJ_IN( *line_in ) ); + snes_ntsc_out_t * restrict line_outa = (snes_ntsc_out_t *) rgb_out; + snes_ntsc_out_t * restrict line_outb = (snes_ntsc_out_t *) ((char *) line_outa + out_pitch); + int n; + ++line_in; + + for ( n = chunk_count; n; --n ) + { + /* order of input and output pixels must not be altered */ + SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) ); + PIXEL_OUT (0); + PIXEL_OUT (1); + + SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) ); + PIXEL_OUT (2); + PIXEL_OUT (3); + + SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) ); + PIXEL_OUT (4); + PIXEL_OUT (5); + PIXEL_OUT (6); + + line_in += 3; + line_outa += 7; + line_outb += 7; + } + + /* finish final pixels */ + SNES_NTSC_COLOR_IN( 0, snes_ntsc_black ); + PIXEL_OUT (0); + PIXEL_OUT (1); + + SNES_NTSC_COLOR_IN( 1, snes_ntsc_black ); + PIXEL_OUT (2); + PIXEL_OUT (3); + + SNES_NTSC_COLOR_IN( 2, snes_ntsc_black ); + PIXEL_OUT (4); + PIXEL_OUT (5); + PIXEL_OUT (6); + + burst_phase = (burst_phase + 1) % snes_ntsc_burst_count; + input += in_row_width; + rgb_out = (char*) rgb_out + 2 * out_pitch; + } +} + +#define PIXEL_OUT_HIRES( x ) \ + SNES_NTSC_HIRES_OUT( x, value, 15 ); \ + line_outa[x] = value; \ + line_outb[x] = value - (value >> scanline_offset & scanline_mask); + +void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, + int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) +{ + int chunk_count = (in_width - 2) / (snes_ntsc_in_chunk * 2); + unsigned value; + for ( ; in_height; --in_height ) + { + SNES_NTSC_IN_T const* line_in = input; + SNES_NTSC_HIRES_ROW( ntsc, burst_phase, + snes_ntsc_black, snes_ntsc_black, snes_ntsc_black, + SNES_NTSC_ADJ_IN( line_in [0] ), + SNES_NTSC_ADJ_IN( line_in [1] ) ); + snes_ntsc_out_t* restrict line_outa = (snes_ntsc_out_t*) rgb_out; + snes_ntsc_out_t* restrict line_outb = (snes_ntsc_out_t*) ((char *) line_outa + out_pitch); + int n; + line_in += 2; + + for ( n = chunk_count; n; --n ) + { + /* twice as many input pixels per chunk */ + SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) ); + PIXEL_OUT_HIRES (0); + + SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) ); + PIXEL_OUT_HIRES (1); + + SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) ); + PIXEL_OUT_HIRES (2); + + SNES_NTSC_COLOR_IN( 3, SNES_NTSC_ADJ_IN( line_in [3] ) ); + PIXEL_OUT_HIRES (3); + + SNES_NTSC_COLOR_IN( 4, SNES_NTSC_ADJ_IN( line_in [4] ) ); + PIXEL_OUT_HIRES (4); + + SNES_NTSC_COLOR_IN( 5, SNES_NTSC_ADJ_IN( line_in [5] ) ); + PIXEL_OUT_HIRES (5); + PIXEL_OUT_HIRES (6); + + line_in += 6; + line_outa += 7; + line_outb += 7; + } + + SNES_NTSC_COLOR_IN( 0, snes_ntsc_black ); + PIXEL_OUT_HIRES (0); + + SNES_NTSC_COLOR_IN( 1, snes_ntsc_black ); + PIXEL_OUT_HIRES (1); + + SNES_NTSC_COLOR_IN( 2, snes_ntsc_black ); + PIXEL_OUT_HIRES (2); + + SNES_NTSC_COLOR_IN( 3, snes_ntsc_black ); + PIXEL_OUT_HIRES (3); + + SNES_NTSC_COLOR_IN( 4, snes_ntsc_black ); + PIXEL_OUT_HIRES (4); + + SNES_NTSC_COLOR_IN( 5, snes_ntsc_black ); + PIXEL_OUT_HIRES (5); + PIXEL_OUT_HIRES (6); + + burst_phase = (burst_phase + 1) % snes_ntsc_burst_count; + input += in_row_width; + rgb_out = (char*) rgb_out + out_pitch * 2; + } +} + +#endif diff --git a/gtk/src/snes_ntsc.h b/gtk/src/snes_ntsc.h new file mode 100644 index 00000000..eb150af9 --- /dev/null +++ b/gtk/src/snes_ntsc.h @@ -0,0 +1,210 @@ +/* SNES NTSC video filter */ + +/* snes_ntsc 0.2.2 */ +#ifndef SNES_NTSC_H +#define SNES_NTSC_H + +#include "snes_ntsc_config.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown +in parenthesis and should remain fairly stable in future versions. */ +typedef struct snes_ntsc_setup_t +{ + /* Basic parameters */ + double hue; /* -1 = -180 degrees +1 = +180 degrees */ + double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */ + double contrast; /* -1 = dark (0.5) +1 = light (1.5) */ + double brightness; /* -1 = dark (0.5) +1 = light (1.5) */ + double sharpness; /* edge contrast enhancement/blurring */ + + /* Advanced parameters */ + double gamma; /* -1 = dark (1.5) +1 = light (0.5) */ + double resolution; /* image resolution */ + double artifacts; /* artifacts caused by color changes */ + double fringing; /* color artifacts caused by brightness changes */ + double bleed; /* color bleed (color resolution reduction) */ + int merge_fields; /* if 1, merges even and odd fields together to reduce flicker */ + float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */ + + unsigned long const* bsnes_colortbl; /* undocumented; set to 0 */ +} snes_ntsc_setup_t; + +/* Video format presets */ +extern snes_ntsc_setup_t const snes_ntsc_composite; /* color bleeding + artifacts */ +extern snes_ntsc_setup_t const snes_ntsc_svideo; /* color bleeding only */ +extern snes_ntsc_setup_t const snes_ntsc_rgb; /* crisp image */ +extern snes_ntsc_setup_t const snes_ntsc_monochrome;/* desaturated + artifacts */ + +/* Initializes and adjusts parameters. Can be called multiple times on the same +snes_ntsc_t object. Can pass NULL for either parameter. */ +typedef struct snes_ntsc_t snes_ntsc_t; +void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ); + +/* Filters one or more rows of pixels. Input pixel format is set by SNES_NTSC_IN_FORMAT +and output RGB depth is set by SNES_NTSC_OUT_DEPTH. Both default to 16-bit RGB. +In_row_width is the number of pixels to get to the next input row. Out_pitch +is the number of *bytes* to get to the next output row. */ +void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, + long in_row_width, int burst_phase, int in_width, int in_height, + void* rgb_out, long out_pitch ); + +void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, + long in_row_width, int burst_phase, int in_width, int in_height, + void* rgb_out, long out_pitch ); + +/* Number of output pixels written by low-res blitter for given input width. Width +might be rounded down slightly; use SNES_NTSC_IN_WIDTH() on result to find rounded +value. Guaranteed not to round 256 down at all. */ +#define SNES_NTSC_OUT_WIDTH( in_width ) \ + ((((in_width) - 1) / snes_ntsc_in_chunk + 1) * snes_ntsc_out_chunk) + +/* Number of low-res input pixels that will fit within given output width. Might be +rounded down slightly; use SNES_NTSC_OUT_WIDTH() on result to find rounded +value. */ +#define SNES_NTSC_IN_WIDTH( out_width ) \ + (((out_width) / snes_ntsc_out_chunk - 1) * snes_ntsc_in_chunk + 1) + + +/* Interface for user-defined custom blitters */ + +enum { snes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */ +enum { snes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */ +enum { snes_ntsc_black = 0 }; /* palette index for black */ +enum { snes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */ + +/* Begins outputting row and starts three pixels. First pixel will be cut off a bit. +Use snes_ntsc_black for unused pixels. Declares variables, so must be before first +statement in a block (unless you're using C++). */ +#define SNES_NTSC_BEGIN_ROW( ntsc, burst, pixel0, pixel1, pixel2 ) \ + char const* ktable = \ + (char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\ + SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, SNES_NTSC_IN_FORMAT, ktable ) + +/* Begins input pixel */ +#define SNES_NTSC_COLOR_IN( index, color ) \ + SNES_NTSC_COLOR_IN_( index, color, SNES_NTSC_IN_FORMAT, ktable ) + +/* Generates output pixel. Bits can be 24, 16, 15, 14, 32 (treated as 24), or 0: +24: RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8 RGB) +16: RRRRRGGG GGGBBBBB (5-6-5 RGB) +15: RRRRRGG GGGBBBBB (5-5-5 RGB) +14: BBBBBGG GGGRRRRR (5-5-5 BGR, native SNES format) + 0: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format; x = junk bits) */ +#define SNES_NTSC_RGB_OUT( index, rgb_out, bits ) \ + SNES_NTSC_RGB_OUT_14_( index, rgb_out, bits, 1 ) + +/* Hires equivalents */ +#define SNES_NTSC_HIRES_ROW( ntsc, burst, pixel1, pixel2, pixel3, pixel4, pixel5 ) \ + char const* ktable = \ + (char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\ + unsigned const snes_ntsc_pixel1_ = (pixel1);\ + snes_ntsc_rgb_t const* kernel1 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel1_ );\ + unsigned const snes_ntsc_pixel2_ = (pixel2);\ + snes_ntsc_rgb_t const* kernel2 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel2_ );\ + unsigned const snes_ntsc_pixel3_ = (pixel3);\ + snes_ntsc_rgb_t const* kernel3 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel3_ );\ + unsigned const snes_ntsc_pixel4_ = (pixel4);\ + snes_ntsc_rgb_t const* kernel4 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel4_ );\ + unsigned const snes_ntsc_pixel5_ = (pixel5);\ + snes_ntsc_rgb_t const* kernel5 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel5_ );\ + snes_ntsc_rgb_t const* kernel0 = kernel1;\ + snes_ntsc_rgb_t const* kernelx0;\ + snes_ntsc_rgb_t const* kernelx1 = kernel1;\ + snes_ntsc_rgb_t const* kernelx2 = kernel1;\ + snes_ntsc_rgb_t const* kernelx3 = kernel1;\ + snes_ntsc_rgb_t const* kernelx4 = kernel1;\ + snes_ntsc_rgb_t const* kernelx5 = kernel1 + +#define SNES_NTSC_HIRES_OUT( x, rgb_out, bits ) {\ + snes_ntsc_rgb_t raw_ =\ + kernel0 [ x ] + kernel2 [(x+5)%7+14] + kernel4 [(x+3)%7+28] +\ + kernelx0 [(x+7)%7+7] + kernelx2 [(x+5)%7+21] + kernelx4 [(x+3)%7+35] +\ + kernel1 [(x+6)%7 ] + kernel3 [(x+4)%7+14] + kernel5 [(x+2)%7+28] +\ + kernelx1 [(x+6)%7+7] + kernelx3 [(x+4)%7+21] + kernelx5 [(x+2)%7+35];\ + SNES_NTSC_CLAMP_( raw_, 0 );\ + SNES_NTSC_RGB_OUT_( rgb_out, (bits), 0 );\ +} + + +/* private */ +enum { snes_ntsc_entry_size = 128 }; +enum { snes_ntsc_palette_size = 0x2000 }; +typedef unsigned long snes_ntsc_rgb_t; +struct snes_ntsc_t { + snes_ntsc_rgb_t table [snes_ntsc_palette_size] [snes_ntsc_entry_size]; +}; +enum { snes_ntsc_burst_size = snes_ntsc_entry_size / snes_ntsc_burst_count }; + +#define SNES_NTSC_RGB16( ktable, n ) \ + (snes_ntsc_rgb_t const*) (ktable + ((n & 0x001E) | (n >> 1 & 0x03E0) | (n >> 2 & 0x3C00)) * \ + (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t))) + +#define SNES_NTSC_RGB15( ktable, n ) \ + (snes_ntsc_rgb_t const*) (ktable + ((n & 0x001E) | (n >> 0 & 0x03E0) | (n >> 1 & 0x3C00)) * \ + (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t))) + +#define SNES_NTSC_BGR15( ktable, n ) \ + (snes_ntsc_rgb_t const*) (ktable + (n & 0x7BFE) * \ + (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t))) + +/* common 3->7 ntsc macros */ +#define SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, ENTRY, table ) \ + unsigned const snes_ntsc_pixel0_ = (pixel0);\ + snes_ntsc_rgb_t const* kernel0 = ENTRY( table, snes_ntsc_pixel0_ );\ + unsigned const snes_ntsc_pixel1_ = (pixel1);\ + snes_ntsc_rgb_t const* kernel1 = ENTRY( table, snes_ntsc_pixel1_ );\ + unsigned const snes_ntsc_pixel2_ = (pixel2);\ + snes_ntsc_rgb_t const* kernel2 = ENTRY( table, snes_ntsc_pixel2_ );\ + snes_ntsc_rgb_t const* kernelx0;\ + snes_ntsc_rgb_t const* kernelx1 = kernel0;\ + snes_ntsc_rgb_t const* kernelx2 = kernel0 + +#define SNES_NTSC_RGB_OUT_14_( x, rgb_out, bits, shift ) {\ + snes_ntsc_rgb_t raw_ =\ + kernel0 [x ] + kernel1 [(x+12)%7+14] + kernel2 [(x+10)%7+28] +\ + kernelx0 [(x+7)%14] + kernelx1 [(x+ 5)%7+21] + kernelx2 [(x+ 3)%7+35];\ + SNES_NTSC_CLAMP_( raw_, shift );\ + SNES_NTSC_RGB_OUT_( rgb_out, bits, shift );\ +} + +/* common ntsc macros */ +#define snes_ntsc_rgb_builder ((1L << 21) | (1 << 11) | (1 << 1)) +#define snes_ntsc_clamp_mask (snes_ntsc_rgb_builder * 3 / 2) +#define snes_ntsc_clamp_add (snes_ntsc_rgb_builder * 0x101) +#define SNES_NTSC_CLAMP_( io, shift ) {\ + snes_ntsc_rgb_t sub = (io) >> (9-(shift)) & snes_ntsc_clamp_mask;\ + snes_ntsc_rgb_t clamp = snes_ntsc_clamp_add - sub;\ + io |= clamp;\ + clamp -= sub;\ + io &= clamp;\ +} + +#define SNES_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\ + unsigned color_;\ + kernelx##index = kernel##index;\ + kernel##index = (color_ = (color), ENTRY( table, color_ ));\ +} + +/* x is always zero except in snes_ntsc library */ +#define SNES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\ + if ( bits == 16 )\ + rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\ + if ( bits == 24 || bits == 32 )\ + rgb_out = (raw_>>(5-x)&0xFF0000)|(raw_>>(3-x)&0xFF00)|(raw_>>(1-x)&0xFF);\ + if ( bits == 15 )\ + rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\ + if ( bits == 14 )\ + rgb_out = (raw_>>(24-x)& 0x001F)|(raw_>>(9-x)&0x03E0)|(raw_<<(6+x)&0x7C00);\ + if ( bits == 0 )\ + rgb_out = raw_ << x;\ +} + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/gtk/src/snes_ntsc_config.h b/gtk/src/snes_ntsc_config.h new file mode 100644 index 00000000..68350896 --- /dev/null +++ b/gtk/src/snes_ntsc_config.h @@ -0,0 +1,27 @@ +/* Configure library by modifying this file */ + +#ifndef SNES_NTSC_CONFIG_H +#define SNES_NTSC_CONFIG_H + +/* Format of source pixels */ +/* #define SNES_NTSC_IN_FORMAT SNES_NTSC_RGB16 +#define SNES_NTSC_IN_FORMAT SNES_NTSC_BGR15 */ +#define SNES_NTSC_IN_FORMAT SNES_NTSC_RGB15 + +/* The following affect the built-in blitter only; a custom blitter can +handle things however it wants. */ + +/* Bits per pixel of output. Can be 15, 16, 32, or 24 (same as 32). */ +#define SNES_NTSC_OUT_DEPTH 15 + +/* Type of input pixel values */ +#define SNES_NTSC_IN_T unsigned short + +/* Each raw pixel input value is passed through this. You might want to mask +the pixel index if you use the high bits as flags, etc. */ +#define SNES_NTSC_ADJ_IN( in ) in + +/* For each pixel, this is the basic operation: +output_color = SNES_NTSC_ADJ_IN( SNES_NTSC_IN_T ) */ + +#endif diff --git a/gtk/src/snes_ntsc_impl.h b/gtk/src/snes_ntsc_impl.h new file mode 100644 index 00000000..1d7adc78 --- /dev/null +++ b/gtk/src/snes_ntsc_impl.h @@ -0,0 +1,439 @@ +/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */ + +/* Common implementation of NTSC filters */ + +#include +#include + +/* Copyright (C) 2006 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#define DISABLE_CORRECTION 0 + +#undef PI +#define PI 3.14159265358979323846f + +#ifndef LUMA_CUTOFF + #define LUMA_CUTOFF 0.20 +#endif +#ifndef gamma_size + #define gamma_size 1 +#endif +#ifndef rgb_bits + #define rgb_bits 8 +#endif +#ifndef artifacts_max + #define artifacts_max (artifacts_mid * 1.5f) +#endif +#ifndef fringing_max + #define fringing_max (fringing_mid * 2) +#endif +#ifndef STD_HUE_CONDITION + #define STD_HUE_CONDITION( setup ) 1 +#endif + +#define ext_decoder_hue (std_decoder_hue + 15) +#define rgb_unit (1 << rgb_bits) +#define rgb_offset (rgb_unit * 2 + 0.5f) + +enum { burst_size = snes_ntsc_entry_size / burst_count }; +enum { kernel_half = 16 }; +enum { kernel_size = kernel_half * 2 + 1 }; + +typedef struct init_t +{ + float to_rgb [burst_count * 6]; + float to_float [gamma_size]; + float contrast; + float brightness; + float artifacts; + float fringing; + float kernel [rescale_out * kernel_size * 2]; +} init_t; + +#define ROTATE_IQ( i, q, sin_b, cos_b ) {\ + float t;\ + t = i * cos_b - q * sin_b;\ + q = i * sin_b + q * cos_b;\ + i = t;\ +} + +static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup ) +{ +#if rescale_out > 1 + float kernels [kernel_size * 2]; +#else + float* const kernels = impl->kernel; +#endif + + /* generate luma (y) filter using sinc kernel */ + { + /* sinc with rolloff (dsf) */ + float const rolloff = 1 + (float) setup->sharpness * (float) 0.032; + float const maxh = 32; + float const pow_a_n = (float) pow( rolloff, maxh ); + float sum; + int i; + /* quadratic mapping to reduce negative (blurring) range */ + float to_angle = (float) setup->resolution + 1; + to_angle = PI / maxh * (float) LUMA_CUTOFF * (to_angle * to_angle + 1); + + kernels [kernel_size * 3 / 2] = maxh; /* default center value */ + for ( i = 0; i < kernel_half * 2 + 1; i++ ) + { + int x = i - kernel_half; + float angle = x * to_angle; + /* instability occurs at center point with rolloff very close to 1.0 */ + if ( x || pow_a_n > (float) 1.056 || pow_a_n < (float) 0.981 ) + { + float rolloff_cos_a = rolloff * (float) cos( angle ); + float num = 1 - rolloff_cos_a - + pow_a_n * (float) cos( maxh * angle ) + + pow_a_n * rolloff * (float) cos( (maxh - 1) * angle ); + float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff; + float dsf = num / den; + kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - (float) 0.5; + } + } + + /* apply blackman window and find sum */ + sum = 0; + for ( i = 0; i < kernel_half * 2 + 1; i++ ) + { + float x = PI * 2 / (kernel_half * 2) * i; + float blackman = 0.42f - 0.5f * (float) cos( x ) + 0.08f * (float) cos( x * 2 ); + sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman); + } + + /* normalize kernel */ + sum = 1.0f / sum; + for ( i = 0; i < kernel_half * 2 + 1; i++ ) + { + int x = kernel_size * 3 / 2 - kernel_half + i; + kernels [x] *= sum; + assert( kernels [x] == kernels [x] ); /* catch numerical instability */ + } + } + + /* generate chroma (iq) filter using gaussian kernel */ + { + float const cutoff_factor = -0.03125f; + float cutoff = (float) setup->bleed; + int i; + + if ( cutoff < 0 ) + { + /* keep extreme value accessible only near upper end of scale (1.0) */ + cutoff *= cutoff; + cutoff *= cutoff; + cutoff *= cutoff; + cutoff *= -30.0f / 0.65f; + } + cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff; + + for ( i = -kernel_half; i <= kernel_half; i++ ) + kernels [kernel_size / 2 + i] = (float) exp( i * i * cutoff ); + + /* normalize even and odd phases separately */ + for ( i = 0; i < 2; i++ ) + { + float sum = 0; + int x; + for ( x = i; x < kernel_size; x += 2 ) + sum += kernels [x]; + + sum = 1.0f / sum; + for ( x = i; x < kernel_size; x += 2 ) + { + kernels [x] *= sum; + assert( kernels [x] == kernels [x] ); /* catch numerical instability */ + } + } + } + + /* + printf( "luma:\n" ); + for ( i = kernel_size; i < kernel_size * 2; i++ ) + printf( "%f\n", kernels [i] ); + printf( "chroma:\n" ); + for ( i = 0; i < kernel_size; i++ ) + printf( "%f\n", kernels [i] ); + */ + + /* generate linear rescale kernels */ + #if rescale_out > 1 + { + float weight = 1.0f; + float* out = impl->kernel; + int n = rescale_out; + do + { + float remain = 0; + int i; + weight -= 1.0f / rescale_in; + for ( i = 0; i < kernel_size * 2; i++ ) + { + float cur = kernels [i]; + float m = cur * weight; + *out++ = m + remain; + remain = cur - m; + } + } + while ( --n ); + } + #endif +} + +static float const default_decoder [6] = + { 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f }; + +static void init( init_t* impl, snes_ntsc_setup_t const* setup ) +{ + impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset; + impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit; + #ifdef default_palette_contrast + if ( !setup->palette ) + impl->contrast *= default_palette_contrast; + #endif + + impl->artifacts = (float) setup->artifacts; + if ( impl->artifacts > 0 ) + impl->artifacts *= artifacts_max - artifacts_mid; + impl->artifacts = impl->artifacts * artifacts_mid + artifacts_mid; + + impl->fringing = (float) setup->fringing; + if ( impl->fringing > 0 ) + impl->fringing *= fringing_max - fringing_mid; + impl->fringing = impl->fringing * fringing_mid + fringing_mid; + + init_filters( impl, setup ); + + /* generate gamma table */ + if ( gamma_size > 1 ) + { + float const to_float = 1.0f / (gamma_size - (gamma_size > 1)); + float const gamma = 1.1333f - (float) setup->gamma * 0.5f; + /* match common PC's 2.2 gamma to TV's 2.65 gamma */ + int i; + for ( i = 0; i < gamma_size; i++ ) + impl->to_float [i] = + (float) pow( i * to_float, gamma ) * impl->contrast + impl->brightness; + } + + /* setup decoder matricies */ + { + float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue; + float sat = (float) setup->saturation + 1; + float const* decoder = setup->decoder_matrix; + if ( !decoder ) + { + decoder = default_decoder; + if ( STD_HUE_CONDITION( setup ) ) + hue += PI / 180 * (std_decoder_hue - ext_decoder_hue); + } + + { + float s = (float) sin( hue ) * sat; + float c = (float) cos( hue ) * sat; + float* out = impl->to_rgb; + int n; + + n = burst_count; + do + { + float const* in = decoder; + int n = 3; + do + { + float i = *in++; + float q = *in++; + *out++ = i * c - q * s; + *out++ = i * s + q * c; + } + while ( --n ); + if ( burst_count <= 1 ) + break; + ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */ + } + while ( --n ); + } + } +} + +/* kernel generation */ + +#define RGB_TO_YIQ( r, g, b, y, i ) (\ + (y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\ + (i = (r) * 0.596f - (g) * 0.275f - (b) * 0.321f),\ + ((r) * 0.212f - (g) * 0.523f + (b) * 0.311f)\ +) + +#define YIQ_TO_RGB( y, i, q, to_rgb, type, r, g ) (\ + r = (type) (y + to_rgb [0] * i + to_rgb [1] * q),\ + g = (type) (y + to_rgb [2] * i + to_rgb [3] * q),\ + (type) (y + to_rgb [4] * i + to_rgb [5] * q)\ +) + +#define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1) + +enum { rgb_kernel_size = burst_size / alignment_count }; +enum { rgb_bias = rgb_unit * 2 * snes_ntsc_rgb_builder }; + +typedef struct pixel_info_t +{ + int offset; + float negate; + float kernel [4]; +} pixel_info_t; + +#if rescale_in > 1 + #define PIXEL_OFFSET_( ntsc, scaled ) \ + (kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \ + (kernel_size * 2 * scaled)) + + #define PIXEL_OFFSET( ntsc, scaled ) \ + PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\ + (((scaled) + rescale_out * 10) % rescale_out) ),\ + (1.0f - (((ntsc) + 100) & 2)) +#else + #define PIXEL_OFFSET( ntsc, scaled ) \ + (kernel_size / 2 + (ntsc) - (scaled)),\ + (1.0f - (((ntsc) + 100) & 2)) +#endif + +extern pixel_info_t const snes_ntsc_pixels [alignment_count]; + +/* Generate pixel at all burst phases and column alignments */ +static void gen_kernel( init_t* impl, float y, float i, float q, snes_ntsc_rgb_t* out ) +{ + /* generate for each scanline burst phase */ + float const* to_rgb = impl->to_rgb; + int burst_remain = burst_count; + y -= rgb_offset; + do + { + /* Encode yiq into *two* composite signals (to allow control over artifacting). + Convolve these with kernels which: filter respective components, apply + sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack + into integer. Based on algorithm by NewRisingSun. */ + pixel_info_t const* pixel = snes_ntsc_pixels; + int alignment_remain = alignment_count; + do + { + /* negate is -1 when composite starts at odd multiple of 2 */ + float const yy = y * impl->fringing * pixel->negate; + float const ic0 = (i + yy) * pixel->kernel [0]; + float const qc1 = (q + yy) * pixel->kernel [1]; + float const ic2 = (i - yy) * pixel->kernel [2]; + float const qc3 = (q - yy) * pixel->kernel [3]; + + float const factor = impl->artifacts * pixel->negate; + float const ii = i * factor; + float const yc0 = (y + ii) * pixel->kernel [0]; + float const yc2 = (y - ii) * pixel->kernel [2]; + + float const qq = q * factor; + float const yc1 = (y + qq) * pixel->kernel [1]; + float const yc3 = (y - qq) * pixel->kernel [3]; + + float const* k = &impl->kernel [pixel->offset]; + int n; + ++pixel; + for ( n = rgb_kernel_size; n; --n ) + { + float i = k[0]*ic0 + k[2]*ic2; + float q = k[1]*qc1 + k[3]*qc3; + float y = k[kernel_size+0]*yc0 + k[kernel_size+1]*yc1 + + k[kernel_size+2]*yc2 + k[kernel_size+3]*yc3 + rgb_offset; + if ( rescale_out <= 1 ) + k--; + else if ( k < &impl->kernel [kernel_size * 2 * (rescale_out - 1)] ) + k += kernel_size * 2 - 1; + else + k -= kernel_size * 2 * (rescale_out - 1) + 2; + { + int r, g, b = YIQ_TO_RGB( y, i, q, to_rgb, int, r, g ); + *out++ = PACK_RGB( r, g, b ) - rgb_bias; + } + } + } + while ( alignment_count > 1 && --alignment_remain ); + + if ( burst_count <= 1 ) + break; + + to_rgb += 6; + + ROTATE_IQ( i, q, -0.866025f, -0.5f ); /* -120 degrees */ + } + while ( --burst_remain ); +} + +static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ); + +#if DISABLE_CORRECTION + #define CORRECT_ERROR( a ) { out [i] += rgb_bias; } + #define DISTRIBUTE_ERROR( a, b, c ) { out [i] += rgb_bias; } +#else + #define CORRECT_ERROR( a ) { out [a] += error; } + #define DISTRIBUTE_ERROR( a, b, c ) {\ + snes_ntsc_rgb_t fourth = (error + 2 * snes_ntsc_rgb_builder) >> 2;\ + fourth &= (rgb_bias >> 1) - snes_ntsc_rgb_builder;\ + fourth -= rgb_bias >> 2;\ + out [a] += fourth;\ + out [b] += fourth;\ + out [c] += fourth;\ + out [i] += error - (fourth * 3);\ + } +#endif + +#define RGB_PALETTE_OUT( rgb, out_ )\ +{\ + unsigned char* out = (out_);\ + snes_ntsc_rgb_t clamped = (rgb);\ + SNES_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\ + out [0] = (unsigned char) (clamped >> 21);\ + out [1] = (unsigned char) (clamped >> 11);\ + out [2] = (unsigned char) (clamped >> 1);\ +} + +/* blitter related */ + +#ifndef restrict + #if defined (__GNUC__) + #define restrict __restrict__ + #elif defined (_MSC_VER) && _MSC_VER > 1300 + #define restrict __restrict + #else + /* no support for restricted pointers */ + #define restrict + #endif +#endif + +#include + +#if SNES_NTSC_OUT_DEPTH <= 16 + #if USHRT_MAX == 0xFFFF + typedef unsigned short snes_ntsc_out_t; + #else + #error "Need 16-bit int type" + #endif + +#else + #if UINT_MAX == 0xFFFFFFFF + typedef unsigned int snes_ntsc_out_t; + #elif ULONG_MAX == 0xFFFFFFFF + typedef unsigned long snes_ntsc_out_t; + #else + #error "Need 32-bit int type" + #endif + +#endif diff --git a/gtk/src/sourcify.c b/gtk/src/sourcify.c new file mode 100644 index 00000000..1ca16ea3 --- /dev/null +++ b/gtk/src/sourcify.c @@ -0,0 +1,57 @@ +#include +#include + +int +main (int argc, + char *argv[]) +{ + FILE *infile, *outfile; + unsigned char inchar; + unsigned int counter; + struct stat file_info; + + if (argc != 4) + { + fprintf (stderr, "Usage: %s infile outfile identifier\n", argv[0]); + return 1; + } + + stat (argv[1], &file_info); + + infile = fopen (argv[1], "r"); + + if (!infile) + { + fprintf (stderr, "Input file doesn't exist.\n"); + return 2; + } + + outfile = fopen (argv[2], "w+"); + + fprintf (outfile, + "int %s_size = %d;\n\n", + argv[3], + (int) file_info.st_size); + fprintf (outfile, "char %s [] = \n{\n ", argv[3]); + + counter = 0; + + while (fread (&inchar, 1, 1, infile)) + { + if (counter >= 32) + { + counter = 0; + fprintf (outfile, "\n "); + } + + fprintf (outfile, "%d,", inchar); + counter++; + } + + /* Erase extra "," */ + fseek (outfile, -1, SEEK_CUR); + + fprintf (outfile, "\n};\n"); + + return 0; +} diff --git a/gtk/src/splash.png b/gtk/src/splash.png new file mode 100644 index 00000000..ffafa70f Binary files /dev/null and b/gtk/src/splash.png differ diff --git a/i386/c4.asm b/i386/c4.asm new file mode 100644 index 00000000..cf1b5de5 --- /dev/null +++ b/i386/c4.asm @@ -0,0 +1,2390 @@ +%include "macros.mac" +;******************************************************* +; Register & Memory Access Banks (0 - 3F) / (80 - BF) +;******************************************************* +; enter : BL = bank number, CX = address location +; leave : AL = value read + +EXTSYM C4WFXVal,C4WFYVal,C4WFX2Val,C4WFY2Val,C4CalcWireFrame,C4WFDist,C4WFScale,C4TransfWireFrame +EXTSYM C4TransfWireFrame2,C4WFZVal,C41FXVal,C41FYVal,C41FAngleRes,C41FDist,C4Op1F,C4Op15,C41FDistVal +EXTSYM C4Op0D,C4LoaDMem + +%ifdef ZSNES_FX +EXTSYM romdata +%else +NEWSYM romdata, dd 0 ; rom data (4MB = 4194304) +%endif + +EXTSYM pressed,vidbuffer,oamram +EXTSYM C4Ram,C4RamR,C4RamW + +C4ProcessVectors: + mov esi,[C4Ram] + mov edi,esi + add edi,1F8Ch + xor edx,edx + mov dx,[esi+1F8Ah] + cmp dx,128 + ja .ret + cmp dx,0 + jne .nozero +.ret + ret +.nozero + cmp dx,10h + jb .less + mov dx,10h +.less + mov esi,[C4Ram] + add esi,800h +.loop + mov ecx,100h + xor ebx,ebx + xor eax,eax + movsx bx,byte[edi] +.spotloop + add ah,80h + mov byte[esi],ah + sub ah,80h + add ax,bx + inc esi + loop .spotloop + add edi,3 + dec dx + jnz .loop + ret + +SECTION .data +C4ObjDisp dd 0 +C4ColRot db 1 +NEWSYM C4ObjSelec, db 0 +NEWSYM C4SObjSelec, db 0 +NEWSYM C4Pause, db 0 +C4DataCopy times 64 db 0 +;NEWSYM C4Data times 64*4096 db 0 ; 15 sprites, 4 bytes each + ; x,y,oamptr,stat (b0=oamb8,b1=16x16) + ; 4 byte header (#sobj,?,?,?) +CObjNum dw 0 +C4Temp dd 0 + +SECTION .text + +C4Edit: + ; C4 editing routines + ; Register keyboard presses + ; [ = prev object, ] = next object + ; p = pause/unpause + cmp byte[pressed+1Ah],0 + je .notpressed + mov byte[pressed+1Ah],0 + inc byte[C4ObjSelec] + inc byte[C4Temp] +.notpressed + cmp byte[pressed+1Bh],0 + je .notpressed2 + mov byte[pressed+1Bh],0 + dec byte[C4ObjSelec] + dec byte[C4Temp] +.notpressed2 + cmp byte[pressed+19h],0 + je .notpressed3 + mov byte[pressed+19h],0 + xor byte[C4Pause],1 +.notpressed3 + + ; Setup variables + mov esi,[C4Ram] + add byte[C4ColRot],16 + mov al,[esi+620h] + cmp byte[C4ObjSelec],0FFh + jne .notneg + dec al + mov byte[C4ObjSelec],al + jmp .notof +.notneg + cmp byte[C4ObjSelec],al + jb .notof + xor al,al + mov [C4ObjSelec],al +.notof + + ; Draw the dots on-screen + xor eax,eax + mov al,[C4ObjSelec] + shl eax,4 + add eax,[C4Ram] + add eax,220h + mov byte[.flipped],0 + test byte[eax+6],40h + jz .notflip + mov byte[.flipped],1 +.notflip + +; 00/01 - x position relative to BG scroll value +; 02/03 - y position relative to BG scroll value +; 04 - palette/priority settings +; 05 - OAM pointer value +; 06 - flip settings : b6 = flipx, b7 = flipy +; 07 - looks like some sprite displacement values +; 08/09 - ??? +; 0A-0F - unused + xor ebx,ebx + mov bx,[eax+8] + mov [CObjNum],bx + cmp bx,4096 + jae near .skipall + shl ebx,6 + add ebx,[C4Data] + + ; t,f,g,h = move current object + ; q = copy current object structure, w = paste current object structure + cmp byte[pressed+14h],0 + je .notmove + mov byte[pressed+14h],0 + pushad + mov ecx,15 +.next + add ebx,4 + dec byte[ebx+1] + loop .next + popad +.notmove + cmp byte[pressed+21h],0 + je .notmove2 + mov byte[pressed+21h],0 + pushad + mov ecx,15 +.next2 + add ebx,4 + cmp byte[.flipped],0 + je .noflipx + add byte[ebx],2 +.noflipx + dec byte[ebx] + loop .next2 + popad +.notmove2 + cmp byte[pressed+22h],0 + je .notmove3 + mov byte[pressed+22h],0 + pushad + mov ecx,15 +.next3 + add ebx,4 + inc byte[ebx+1] + loop .next3 + popad +.notmove3 + cmp byte[pressed+23h],0 + je .notmove4 + mov byte[pressed+23h],0 + pushad + mov ecx,15 +.next4 + add ebx,4 + cmp byte[.flipped],0 + je .noflipx2 + sub byte[ebx],2 +.noflipx2 + inc byte[ebx] + loop .next4 + popad +.notmove4 + cmp byte[pressed+10h],0 + je .notcopy + mov byte[pressed+10h],0 + pushad + mov edx,C4DataCopy + mov ecx,64 +.copylp + mov al,[ebx] + mov [edx],al + inc ebx + inc edx + loop .copylp + popad +.notcopy + cmp byte[pressed+11h],0 + je .notpaste + mov byte[pressed+11h],0 + pushad + mov edx,C4DataCopy + mov ecx,64 +.pastelp + mov al,[edx] + mov [ebx],al + inc ebx + inc edx + loop .pastelp + popad +.notpaste + + ; - = remove sub-object, + = add sub-object + ; ; = previous sub-object, ' = next sub-object + cmp byte[pressed+0Ch],0 + je .notpressed4 + mov byte[pressed+0Ch],0 + cmp byte[ebx],0 + je .notpressed4 + dec byte[ebx] +.notpressed4 + cmp byte[pressed+0Dh],0 + je .notpressed5 + mov byte[pressed+0Dh],0 + cmp byte[ebx],15 + je .notpressed5 + inc byte[ebx] +.notpressed5 + cmp byte[pressed+27h],0 + je .notpressed6 + mov byte[pressed+27h],0 + dec byte[C4SObjSelec] +.notpressed6 + cmp byte[pressed+28h],0 + je .notpressed7 + mov byte[pressed+28h],0 + inc byte[C4SObjSelec] +.notpressed7 + + ; get current sub-object displacement (0 if no sub-objects) + xor ecx,ecx + cmp byte[ebx],0 + je near .nosubobjs + + mov cl,[ebx] + cmp byte[C4ObjSelec],0FFh + jne .sobjokay2 + dec cl + mov byte[C4SObjSelec],cl + jmp .sobjokay +.sobjokay2 + cmp byte[C4SObjSelec],cl + jb .sobjokay + mov byte[C4SObjSelec],0 +.sobjokay + + xor ecx,ecx + mov cl,byte[C4SObjSelec] + shl ecx,2 + add ebx,ecx + add ebx,4 + + ; i,j,k,l = move current sub-object (17,24,25,26) + ; u = toggle between 8x8 and 16x16 tiles + ; o = toggle between high/low oam value + ; . = decrease oam value, / = increase oam value of sub-object + cmp byte[pressed+17h],0 + je .notpressed8 + mov byte[pressed+17h],0 + dec byte[ebx+1] +.notpressed8 + cmp byte[pressed+24h],0 + je .notpressed9 + mov byte[pressed+24h],0 + dec byte[ebx] + cmp byte[.flipped],0 + je .notpressed9 + add byte[ebx],2 +.notpressed9 + cmp byte[pressed+26h],0 + je .notpressed11 + mov byte[pressed+26h],0 + inc byte[ebx] + cmp byte[.flipped],0 + je .notpressed11 + sub byte[ebx],2 +.notpressed11 + cmp byte[pressed+25h],0 + je .notpressed10 + mov byte[pressed+25h],0 + inc byte[ebx+1] +.notpressed10 + cmp byte[pressed+16h],0 + je .notpressed12 + mov byte[pressed+16h],0 + xor byte[ebx+3],2 +.notpressed12 + cmp byte[pressed+18h],0 + je .notpressed13 + mov byte[pressed+18h],0 + xor byte[ebx+3],1 +.notpressed13 + cmp byte[pressed+34h],0 + je .notpressed14 + mov byte[pressed+34h],0 + dec byte[ebx+2] +.notpressed14 + cmp byte[pressed+35h],0 + je .notpressed15 + mov byte[pressed+35h],0 + inc byte[ebx+2] +.notpressed15 + + mov cl,[ebx] + mov ch,[ebx+1] +.nosubobjs + mov edx,ecx + xor ebx,ebx + xor ecx,ecx + mov bl,[eax] + sub bl,[esi+621h] + add bl,dl + mov cl,[eax+2] + sub cl,[esi+623h] + add cl,dh + mov esi,[vidbuffer] + add esi,16*2+256*2+32*2 + add esi,ebx + add esi,ebx + mov ebx,ecx + shl ebx,9 + shl ecx,6 + add esi,ebx + add esi,ecx + mov al,[C4ColRot] + mov ah,al + xor ah,0FFh + mov [esi],ax + mov [esi+16],ax + mov [esi+288*8*2],ax + mov [esi+16+288*8*2],ax +.skipall + ret + +SECTION .data +.flipped db 0 +SECTION .text + +C4AddSprite: + cmp dword[C4count],0 + je near .nosprite + mov [edi],ax + mov [edi+2],bx + mov ebx,[C4usprptr] + and [ebx],dl + mov al,dl + xor al,0FFh + and dh,al + or [ebx],dh + add edi,4 + rol dl,2 + rol dh,2 + dec dword[C4count] + cmp dl,0FCh + jne .nosprite + inc dword[C4usprptr] +.nosprite + ret + +C4ConvOAM: + inc byte[C4Timer] + and byte[C4Timer],15 + inc byte[C4Timer2] + and byte[C4Timer2],7 + mov esi,[C4Ram] + xor ecx,ecx + mov edi,esi + mov cl,[esi+620h] + mov bx,[esi+621h] + mov [.addx],bx + mov bx,[esi+623h] + mov [.addy],bx + mov [C4usprptr],esi + add dword[C4usprptr],200h + mov eax,[C4ObjDisp] + add edi,eax + shr eax,4 + add dword[C4usprptr],eax + add esi,220h + ; Convert from esi to edi + mov dl,0FCh + push ecx + mov cl,byte[C4sprites] + and cl,3 + add cl,cl + rol dl,cl + pop ecx + cmp cl,0 + je near .none + mov dword[C4count],128 + mov eax,[C4sprites] + sub dword[C4count],eax + +.loop + push ecx + push esi +; 00/01 - x position relative to BG scroll value +; 02/03 - y position relative to BG scroll value +; 04 - palette/priority settings +; 05 - OAM pointer value +; 06 - flip settings : b6 = flipx, b7 = flipy +; 07 - ??? +; 08/09 - Pointer to Sprite Structure +; 0A-0F - unused +;bit 1-3 = palette number bit 4,5 = playfield priority +;bit 6 = horizontal flip bit 7 = horizonal flip + mov ax,[esi] + sub ax,[.addx] + mov [C4SprX],ax + mov ax,[esi+2] + sub ax,[.addy] + mov [C4SprY],ax + mov al,[esi+5] + mov [C4SprOAM],al + mov al,[esi+4] + mov ah,al + and ah,0Eh + cmp ah,0 + jmp .notstage2 + jne .notstage1 + cmp byte[C4Timer],0 + je .flash + jmp .noflash +.notstage1 + jmp .notstage2 + cmp ah,4 + jne .notstage2 + cmp byte[C4Timer2],0 + je .flash +.noflash + and al,0F1h + or al,2 + jmp .notstage2 +.flash + and al,0F1h +.notstage2 + mov [C4SprAttr],al + mov al,[esi+6] + or [C4SprAttr],al +; mov [C4SprFlip],al + + xor ecx,ecx + mov cl,[esi+9] + shl ecx,16 + mov cx,[esi+7] + add cx,cx + shr ecx,1 + add ecx,[romdata] + + mov al,[ecx] + or al,al + jz near .singlespr + mov [C4SprCnt],al + inc ecx +.nextspr + xor ebx,ebx + movsx bx,byte[ecx+1] + test byte[C4SprAttr],40h + jz .notflipx + neg bx + sub bx,8 +.notflipx + add bx,[C4SprX] + xor dh,dh + test byte[ecx],20h + jz .no16x16 + or dh,10101010b + test byte[C4SprAttr],40h + jz .no16x16 + sub bx,8 +.no16x16 + cmp bx,-16 + jl near .nosprite + cmp bx,272 + jg near .nosprite + mov al,bl + test bx,100h + jz .not512b + or dh,01010101b +.not512b + xor ebx,ebx + movsx bx,byte[ecx+2] + test byte[C4SprAttr],80h + jz .notflipy + neg bx + sub bx,8 +.notflipy + add bx,[C4SprY] + test byte[ecx],20h + jz .no16x16b + test byte[C4SprAttr],80h + jz .no16x16b + sub bx,8 +.no16x16b + cmp bx,-16 + jl near .nosprite + cmp bx,224 + jg near .nosprite + mov ah,bl + mov bh,[C4SprAttr] + mov bl,[ecx] + and bl,0C0h + xor bh,bl + mov bl,[C4SprOAM] + add bl,[ecx+3] + call C4AddSprite +.nosprite + add ecx,4 + dec byte[C4SprCnt] + jnz near .nextspr + jmp .donemultispr +.singlespr + mov dh,10101010b + test byte[C4SprX+1],1 + jz .not512 + or dh,01010101b +.not512 + mov al,[C4SprX] + mov ah,[C4SprY] + mov bl,[C4SprOAM] + mov bh,[C4SprAttr] + call C4AddSprite +.donemultispr + pop esi + pop ecx + +;NEWSYM C4Data times 64*4096 db 0 ; 15 sprites, 4 bytes each + ; x,y,oamptr,stat (b0=oamb8,b1=16x16) + ; 4 byte header (#sobj,?,?,?) + + add esi,16 + dec cl + jnz near .loop +.none + mov esi,oamram + mov edi,[C4Ram] + mov ecx,544 +.next + mov al,[edi] + mov [esi],al + inc edi + inc esi + loop .next + ret + +SECTION .data +.addx dw 0 +.addy dw 0 + +C4count dd 0 +C4usprptr dd 0 +C4SprX dw 0 +C4SprY dw 0 +C4SprCnt db 0 +C4SprAttr db 0 +C4SprOAM db 0 +C4SprFlip db 0 +C4Timer db 0 +C4Timer2 db 0 + +SECTION .text + +NEWSYM C4VBlank + ret +NEWSYM C4ProcessSprites + push ecx + push esi + push edi + push ebx + push edx +; call C4ProcessVectors + +; call C4Edit + + mov esi,[C4Ram] + mov dword[C4count],8 + mov cl,[esi+626h] + mov byte[C4sprites],cl + mov ecx,[C4sprites] + shl ecx,2 + mov dword[C4ObjDisp],ecx + mov ecx,128 +; cmp byte[esi+65],50h +; jne .noincdisp + mov dword[C4count],32 + sub ecx,[C4sprites] +.noincdisp + add esi,[C4ObjDisp] + ; Clear OAM to-be ram +.next + mov byte[esi+1],0E0h + add esi,4 + dec ecx + jnz .next + + call C4ConvOAM + + pop edx + pop ebx + pop edi + pop esi + pop ecx + ret + +SECTION .data +NEWSYM SprValAdd, db 0 +C4Data dd 0 +C4sprites dd 0 +SECTION .text + +NEWSYM InitC4 + pushad + mov esi,[romdata] + add esi,4096*1024 + mov [C4Data],esi + add dword[C4Data],128*1024 + mov [C4RamR],esi + mov [C4RamW],esi + mov [C4Ram],esi + add dword[C4RamW],8192*4 + add dword[C4Ram],8192*8 + mov ecx,8192 +.c4loop + mov dword[esi],C4ReadReg + mov dword[esi+8192*4],C4WriteReg + mov dword[esi+8192*8],0 + add esi,4 + dec ecx + jnz .c4loop + mov esi,[C4RamW] + mov dword[esi+1F4Fh*4],C4RegFunction + mov esi,[C4Data] + mov ecx,16*4096 +.c4loopb + mov dword[esi],0 + add esi,4 + loop .c4loopb + popad + ret + +C4ClearSpr: + mov esi,ebx + mov edi,eax +; xor ecx,ecx +; mov cx,[eax+1F44h] +; sub cx,6000h +; add eax,ecx + shl ch,3 +.scloop2 + mov cl,byte[C4SprPos] + shl cl,2 +.scloop + mov byte[edi],0 + mov byte[edi+2000h],0 + inc edi + dec cl + jnz .scloop + dec ch + jnz .scloop2 + ret + +C4SprBitPlane: + mov edi,eax + shl ebx,2 +.scloop3 + mov ch,[C4SprPos] + push esi +.scloop4 + push esi + mov cl,8 +.loop + mov dh,8 + mov dl,80h + mov eax,[esi] +.nextd + test al,1 + jz .not0 + or byte[edi],dl +.not0 + test al,2 + jz .not1 + or byte[edi+1],dl +.not1 + test al,4 + jz .not2 + or byte[edi+16],dl +.not2 + test al,8 + jz .not3 + or byte[edi+17],dl +.not3 + shr eax,4 + shr dl,1 + dec dh + jnz .nextd + add esi,ebx + add edi,2 + dec cl + jnz .loop + add edi,16 + pop esi + add esi,4 + dec ch + jnz .scloop4 + pop esi + shl ebx,3 + add esi,ebx + add edi,dword[C4SprPtrInc] + shr ebx,3 + dec byte[C4SprPos+1] + jnz .scloop3 +.end + ret + +SECTION .data +C4XXScale dw 0 +C4XYScale dw 0 +C4YXScale dw 0 +C4YYScale dw 0 +C4CXPos dw 0 +C4CYPos dw 0 +C4CXMPos dd 0 +C4CYMPos dd 0 +C4PCXMPos dd 0 +C4PCYMPos dd 0 +SECTION .text + +DoScaleRotate: + pushad + mov esi,eax + ; Calculate X scaler + mov ax,[esi+1F80h] + and eax,01FFh + mov ax,[CosTable+eax*2] + mov bx,[esi+1F8Fh] + test bx,8000h + jz .notover + mov bx,7FFFh +.notover + imul bx + add ax,ax + adc dx,dx + mov [C4XXScale],dx + mov ax,[esi+1F80h] + and eax,01FFh + mov ax,[SinTable+eax*2] + imul bx + add ax,ax + adc dx,dx + mov [C4XYScale],dx + ; Calculate Y scaler + mov ax,[esi+1F80h] + and eax,01FFh + mov ax,[CosTable+eax*2] + mov bx,[esi+1F92h] + test bx,8000h + jz .notoverb + mov bx,7FFFh +.notoverb + imul bx + add ax,ax + add dx,dx + mov [C4YYScale],dx + mov ax,[esi+1F80h] + and eax,01FFh + mov ax,[SinTable+eax*2] + imul bx + add ax,ax + adc dx,dx + neg dx + mov [C4YXScale],dx + cmp word[esi+1F80h],0 + jne .effect + cmp word[esi+1F92h],1000h + jne .effect + mov word[C4YYScale],1000h + mov word[C4YXScale],0 +.effect + ; Calculate Pixel Resolution + mov cl,byte[C4SprPos] + shl cl,3 + mov byte[C4SprPos+2],cl + mov cl,byte[C4SprPos+1] + shl cl,3 + mov byte[C4SprPos+3],cl + ; Calculate Positions + ; (1-scale)*(pos/2) + xor eax,eax + mov al,[C4SprPos+2] + shl eax,11 + mov [C4PCXMPos],eax + xor eax,eax + mov al,[C4SprPos+3] + shl eax,11 + mov [C4PCYMPos],eax + + mov bx,[C4XXScale] + xor eax,eax + mov al,[C4SprPos+2] + shr ax,1 + imul bx + shl edx,16 + mov dx,ax + sub [C4PCXMPos],edx + mov bx,[C4YXScale] + xor eax,eax + mov al,[C4SprPos+3] + shr ax,1 + imul bx + shl edx,16 + mov dx,ax + sub [C4PCXMPos],edx + + mov bx,[C4XYScale] + xor eax,eax + mov al,[C4SprPos+2] + shr ax,1 + imul bx + shl edx,16 + mov dx,ax + sub [C4PCYMPos],edx + mov bx,[C4YYScale] + xor eax,eax + mov al,[C4SprPos+3] + shr ax,1 + imul bx + shl edx,16 + mov dx,ax + sub [C4PCYMPos],edx + + ; Start loop + mov word[C4CYPos],0 + xor edi,edi +.loop + mov ecx,[C4PCXMPos] + mov [C4CXMPos],ecx + mov ecx,[C4PCYMPos] + mov [C4CYMPos],ecx + mov al,[C4SprPos+2] + mov byte[C4CXPos],al +.loop2 + xor eax,eax + mov al,[C4SprPos+2] + mov ebx,[C4CXMPos] + sar ebx,12 + cmp ebx,eax + jae near .blank + xor eax,eax + mov al,[C4SprPos+3] + mov ebx,[C4CYMPos] + sar ebx,12 + cmp ebx,eax + jae near .blank + ; Get pixel value + mov ebx,[C4CYMPos] + xor eax,eax + shr ebx,12 + mov al,[C4SprPos+2] + mul ebx + mov ebx,[C4CXMPos] + shr ebx,12 + add eax,ebx + mov ebx,[C4SprPtr] + test al,1 + jnz .upperb + shr eax,1 + add ebx,eax + mov al,[ebx] + jmp .lowerb +.upperb + shr eax,1 + add ebx,eax + mov al,[ebx] + shr al,4 +.lowerb + mov ebx,edi + shr ebx,1 + add ebx,esi + test edi,1 + jnz .upperb2 + and al,0Fh + and byte[ebx+2000h],0F0h + or byte[ebx+2000h],al + jmp .done +.upperb2 + shl al,4 + and byte[ebx+2000h],0Fh + or byte[ebx+2000h],al + jmp .done +.blank + mov eax,edi + shr eax,1 + add eax,esi + test edi,1 + jnz .upper + and byte[eax+2000h],0F0h + jmp .done +.upper + and byte[eax+2000h],0Fh +.done + movsx eax,word[C4XXScale] + add [C4CXMPos],eax + movsx eax,word[C4XYScale] + add [C4CYMPos],eax + inc edi + dec byte[C4CXPos] + jne near .loop2 + movsx eax,word[C4YXScale] + add [C4PCXMPos],eax + movsx eax,word[C4YYScale] + add [C4PCYMPos],eax + inc word[C4CYPos] + mov al,[C4SprPos+3] + cmp byte[C4CYPos],al + jne near .loop +.noimage + popad + ret + +DoScaleRotate2: + pushad + xor ebx,ebx + mov bx,[eax+1F8Fh] + cmp bx,1000h + ja .scaled + mov bx,1000h +.scaled + mov [C4SprScale],ebx + xor ebx,ebx + mov bx,[eax+1F92h] + cmp bx,1000h + ja .scaledb + mov bx,1000h +.scaledb + mov [C4SprScaleY],ebx + mov cl,[C4SprPos] + shl cl,3 + mov ch,cl + xor ebx,ebx +.leftovercheck + dec ch + add ebx,[C4SprScale] +.leftovercheckb + cmp ebx,1000h + jb .leftovercheck + sub ebx,1000h + dec cl + jz .donecheck + jmp .leftovercheckb +.donecheck + shr ch,1 + mov cl,ch + and ecx,0FFh + mov esi,ecx + + mov cl,[C4SprPos+1] + shl cl,3 + mov ch,cl + xor ebx,ebx +.leftovercheckc + dec ch + add ebx,[C4SprScaleY] +.leftovercheckd + cmp ebx,1000h + jb .leftovercheckc + sub ebx,1000h + dec cl + jz .donecheckc + jmp .leftovercheckd +.donecheckc + shr ch,1 + mov cl,ch + and ecx,0FFh + push eax + xor eax,eax + mov al,[C4SprPos] + shl al,3 + mul ecx + add esi,eax + pop eax + + mov dword[C4SprScalerY],0 + xor edi,edi + mov cl,[C4SprPos+1] + shl cl,3 + mov [C4SprPos+3],cl +.next + push esi + push edi + xor ecx,ecx + mov cl,[C4SprPos] + shl cl,3 + mov ch,cl + mov dword[C4SprScaler],0 + xor edx,edx +.loop + mov edx,edi + shr edx,1 + add edx,[C4SprPtr] + mov bl,[edx] + test esi,1 + jz .notupper + shr bl,4 +.notupper + and bl,0Fh + mov edx,esi + shr edx,1 + test esi,1 + jz .notupperb + shl bl,4 + or byte[eax+edx+2000h],bl + jmp .notlowerb +.notupperb + or byte[eax+edx+2000h],bl +.notlowerb + inc esi + mov ebx,[C4SprScale] + add dword[C4SprScaler],ebx + dec ch +.nextcheck + cmp dword[C4SprScaler],1000h + jb near .loop + sub dword[C4SprScaler],1000h + inc edi + dec cl + jz .done + jmp .nextcheck +.done + pop edi + pop esi + xor edx,edx + mov dl,[C4SprPos] + shl dl,3 + add esi,edx + + mov ebx,[C4SprScaleY] + add dword[C4SprScalerY],ebx +.nextcheckb + cmp dword[C4SprScalerY],1000h + jb near .next + sub dword[C4SprScalerY],1000h + add edi,edx + dec byte[C4SprPos+3] + jz .doneb + jmp .nextcheckb +.doneb + + popad + ret + +C4SprScaleR: + push ecx + push ebx + push edx + push esi + push edi + mov dword[C4SprPtrInc],0 + xor ebx,ebx + mov bl,[eax+1F42h] + shl ebx,16 + mov bx,[eax+1F40h] + add bx,bx + shr ebx,1 + add ebx,[romdata] + mov ch,[eax+1F8Ch] + shr ch,3 + mov cl,[eax+1F89h] + shr cl,3 + mov [C4SprPos],cx + mov [C4SprPtr],ebx + + call C4ClearSpr + + call DoScaleRotate + + mov esi,eax + add esi,2000h + xor ebx,ebx + mov bl,[C4SprPos] + call C4SprBitPlane + pop edi + pop esi + pop edx + pop ebx + pop ecx + ret + +C4SprRotateR: + push ecx + push ebx + push edx + push esi + push edi + xor ebx,ebx + mov ebx,600h + add ebx,[C4Ram] + mov [C4SprPtr],esi + mov ch,[eax+1F8Ch] + shr ch,3 + mov cl,[eax+1F89h] + shr cl,3 + add ch,2 + mov [C4SprPos],cx + mov dword[C4SprPtrInc],64 + mov [C4SprPtr],ebx + sub byte[C4SprPos+1],2 + call C4ClearSpr + + call DoScaleRotate + mov esi,eax + add esi,2000h + xor ebx,ebx + mov bl,[C4SprPos] + add byte[C4SprPos+1],2 + call C4SprBitPlane + pop edi + pop esi + pop edx + pop ebx + pop ecx + ret + +C4SprDisintegrate: + pushad + mov dword[C4SprPtrInc],0 + xor ebx,ebx + mov bl,[eax+1F42h] + shl ebx,16 + mov bx,[eax+1F40h] + add bx,bx + shr ebx,1 + add ebx,[romdata] + mov ch,[eax+1F8Ch] + shr ch,3 + mov cl,[eax+1F89h] + shr cl,3 + mov [C4SprPos],cx + mov [C4SprPtr],ebx + + call C4ClearSpr + + mov esi,[C4Ram] + xor ebx,ebx + mov bx,[esi+1F86h] + xor eax,eax + mov al,[esi+1F89h] + shr al,1 + mul ebx + neg eax + xor ebx,ebx + mov bl,[esi+1F89h] + shr bl,1 + shl ebx,8 + add eax,ebx + push eax + xor ebx,ebx + mov bx,[esi+1F8Fh] + xor eax,eax + mov al,[esi+1F8Ch] + shr al,1 + mul ebx + neg eax + xor ebx,ebx + mov bl,[esi+1F8Ch] + shr bl,1 + shl ebx,8 + add ebx,eax + mov edx,ebx + pop ebx + mov esi,[C4Ram] + mov cl,[esi+1F89h] + mov ch,[esi+1F8Ch] + mov [C4SprPos+2],cx + movsx eax,word[esi+1F86h] + mov [.scalex],eax + movsx eax,word[esi+1F8Fh] + mov [.scaley],eax + mov esi,[C4SprPtr] + mov edi,[C4Ram] + add edi,2000h + + ; convert to 8-bit bitmap + mov cx,[C4SprPos+2] + shr cl,1 +.loop2 + mov al,[esi] + mov [edi],al + mov al,[esi] + shr al,4 + mov [edi+1],al + inc esi + add edi,2 + dec cl + jnz .loop2 + dec ch + jnz .loop2 + + mov edi,[C4Ram] + add edi,4000h + mov ecx,2000h +.lp + mov byte[edi],0 + inc edi + loop .lp + + mov esi,[C4Ram] + add esi,2000h + mov edi,[C4Ram] + add edi,4000h + + mov cx,[C4SprPos+2] +.next2 + push ebx +.next + xor eax,eax + mov ah,[C4SprPos+2] + cmp ebx,eax + jae .fail + xor eax,eax + mov ah,[C4SprPos+3] + cmp edx,eax + jae .fail + push ecx + push edx + xor eax,eax + mov al,[C4SprPos+2] + xor ecx,ecx + mov cl,dh + mul ecx + mov ecx,ebx + shr ecx,8 + add eax,ecx + mov dl,[esi] + cmp eax,2000h + jae .skipdisi + mov [edi+eax],dl +.skipdisi + pop edx + pop ecx +.fail + inc esi + add ebx,[.scalex] + dec cl + jnz near .next + pop ebx + add edx,[.scaley] + mov cl,[C4SprPos+2] + dec ch + jnz near .next2 + +.skipall + ; convert to 4-bit bitmap + mov esi,[C4Ram] + add esi,4000h + mov edi,[C4Ram] + add edi,6000h + mov cx,[C4SprPos+2] + shr cl,1 +.loop + mov al,[esi] + mov [edi],al + mov al,[esi+1] + shl al,4 + or [edi],al + inc edi + add esi,2 + dec cl + jnz .loop + dec ch + jnz .loop + + mov esi,[C4Ram] + add esi,6000h +; mov esi,[C4SprPtr] + mov eax,[C4Ram] + xor ebx,ebx + mov bl,[C4SprPos] + call C4SprBitPlane + + popad + ret + +SECTION .data +.scalex dd 0 +.scaley dd 0 +SECTION .text + +C4BitPlaneWave: + pushad + mov esi,[C4Ram] + mov dword[.temp],10h + xor eax,eax + mov al,[esi+1F83h] + mov dword[.waveptr],eax + mov word[.temp+4],0C0C0h + mov word[.temp+6],03F3Fh +.bmloopb + mov edi,[C4Ram] + add edi,[.waveptr] + xor eax,eax + movsx ax,byte[edi+$0B00] + neg ax + sub ax,16 + mov edi,[C4Ram] + add edi,0A00h + xor ecx,ecx +.bmloopa + mov ebx,[.bmptr+ecx*4] + mov dx,[.temp+6] + and [esi+ebx],dx + xor dx,dx + cmp ax,0 + jl .less + mov dx,0FF00h + cmp ax,8 + jae .less + mov dx,[edi+eax*2] +.less + and dx,[.temp+4] + or [esi+ebx],dx + inc ax + inc ecx + cmp ecx,28h + jne .bmloopa + add dword[.waveptr],1 + and dword[.waveptr],07Fh + ror word[.temp+4],2 + ror word[.temp+6],2 + cmp word[.temp+4],0C0C0h + jne near .bmloopb + add esi,16 +.bmloopa2b + mov edi,[C4Ram] + add edi,[.waveptr] + xor eax,eax + movsx ax,byte[edi+$0B00] + neg ax + sub ax,16 + mov edi,[C4Ram] + add edi,0A00h + xor ecx,ecx +.bmloopa2 + mov ebx,[.bmptr+ecx*4] + mov dx,[.temp+6] + and [esi+ebx],dx + xor dx,dx + cmp ax,0 + jl .less2 + mov dx,0FF00h + cmp ax,8 + jae .less2 + mov dx,[edi+eax*2+16] +.less2 + and dx,[.temp+4] + or [esi+ebx],dx + inc ax + inc ecx + cmp ecx,28h + jne .bmloopa2 + add dword[.waveptr],1 + and dword[.waveptr],07Fh + ror word[.temp+4],2 + ror word[.temp+6],2 + cmp word[.temp+4],0C0C0h + jne near .bmloopa2b + add esi,16 + dec dword[.temp] + jnz near .bmloopb + mov esi,[C4Ram] +; mov cx,[esi+1F80h] +; mov [C4values],cx +; mov cx,[esi+1F83h] +; mov [C4values+2],cx + popad + ret + +SECTION .data +.bmptr dd 0000h,0002h,0004h,0006h,0008h,000Ah,000Ch,000Eh + dd 0200h,0202h,0204h,0206h,0208h,020Ah,020Ch,020Eh + dd 0400h,0402h,0404h,0406h,0408h,040Ah,040Ch,040Eh + dd 0600h,0602h,0604h,0606h,0608h,060Ah,060Ch,060Eh + dd 0800h,0802h,0804h,0806h,0808h,080Ah,080Ch,080Eh +.temp dd 0,0 +.waveptr dd 0 +;C4X1 dw 0 +;C4Y1 dw 0 +;C4Z1 dw 0 +;C4X2 dw 0 +;C4Y2 dw 0 +;C4Z2 dw 0 +;C4Col dw 0 + +SECTION .text +C4DrawLine: + pushad + + ; transform both coordinates + push esi + mov ax,word[C4X1] + mov [C4WFXVal],ax + mov ax,word[C4Y1] + mov [C4WFYVal],ax + mov ax,word[C4Z1] + mov [C4WFZVal],ax + mov al,[esi+1F90h] + mov [C4WFScale],al + mov al,[esi+1F86h] + mov [C4WFX2Val],al + mov al,[esi+1F87h] + mov [C4WFY2Val],al + mov al,[esi+1F88h] + mov [C4WFDist],al + call C4TransfWireFrame2 + mov ax,[C4WFXVal] + mov word[C4X1],ax + mov ax,[C4WFYVal] + mov word[C4Y1],ax + + mov ax,word[C4X2] + mov [C4WFXVal],ax + mov ax,word[C4Y2] + mov [C4WFYVal],ax + mov ax,word[C4Z2] + mov [C4WFZVal],ax + call C4TransfWireFrame2 + mov ax,[C4WFXVal] + mov word[C4X2],ax + mov ax,[C4WFYVal] + mov word[C4Y2],ax + + add word[C4X1],48 + add word[C4Y1],48 + add word[C4X2],48 + add word[C4Y2],48 + shl dword[C4X1],8 + shl dword[C4X2],8 + shl dword[C4Y1],8 + shl dword[C4Y2],8 + ; get line info + mov ax,[C4X1+1] + mov [C4WFXVal],ax + mov ax,[C4Y1+1] + mov [C4WFYVal],ax + mov ax,[C4X2+1] + mov [C4WFX2Val],ax + mov ax,[C4Y2+1] + mov [C4WFY2Val],ax + call C4CalcWireFrame + xor ecx,ecx + mov cx,[C4WFDist] + or ecx,ecx + jnz .not0 + mov ecx,1 +.not0 + movsx eax,word[C4WFXVal] + mov [C4X2],eax + movsx eax,word[C4WFYVal] + mov [C4Y2],eax + pop esi + ; render line +.loop + ; plot pixel + cmp word[C4X1+1],0 + jl near .noplot + cmp word[C4Y1+1],0 + jl near .noplot + cmp word[C4X1+1],95 + jg near .noplot + cmp word[C4Y1+1],95 + jg near .noplot + xor eax,eax + mov dx,[C4Y1+1] + shr dx,3 + mov ax,dx + shl ax,6 + shl dx,8 + sub dx,ax + mov ax,[C4X1+1] + shr ax,3 + shl ax,4 + add ax,dx + mov dx,[C4Y1+1] + and dx,07h + add dx,dx + add ax,dx + mov dl,07Fh + push ecx + mov cl,[C4X1+1] + and cl,07h + ror dl,cl + pop ecx + and byte[esi+eax+300h],dl + and byte[esi+eax+301h],dl + xor dl,0FFh + test byte[C4Col],1 + jz .nocolor0 + or byte[esi+eax+300h],dl +.nocolor0 + test byte[C4Col],2 + jz .nocolor1 + or byte[esi+eax+301h],dl +.nocolor1 +.noplot + mov eax,[C4X2] + add [C4X1],eax + mov eax,[C4Y2] + add [C4Y1],eax + dec ecx + jnz near .loop + popad + ret + +DrawWireFrame: + mov esi,[C4Ram] + mov edi,esi + xor ebx,ebx + mov bl,[esi+1F82h] + shl ebx,16 + mov bx,[esi+1F80h] + add bx,bx + shr ebx,1 + add ebx,[romdata] + mov edi,ebx + xor ecx,ecx + mov cl,[esi+295h] +.loop + xor eax,eax + mov al,[esi+1F82h] + shl eax,16 + mov al,[edi+1] + mov ah,[edi+0] + mov edx,edi +.nextprev + cmp ax,0FFFFh + jne .notprev + sub edx,5 + mov al,[edx+3] + mov ah,[edx+2] + jmp .nextprev +.notprev + add ax,ax + shr eax,1 + add eax,[romdata] + xor edx,edx + mov dl,[esi+1F82h] + shl edx,16 + mov dl,[edi+3] + mov dh,[edi+2] +; mov [C4values+6],dx + add dx,dx + shr edx,1 + add edx,[romdata] + xor ebx,ebx + mov bh,[eax] + mov bl,[eax+1] + mov [C4X1],ebx + mov bh,[eax+2] + mov bl,[eax+3] + mov [C4Y1],ebx + mov bh,[eax+4] + mov bl,[eax+5] + mov [C4Z1],ebx + mov bh,[edx] + mov bl,[edx+1] + mov [C4X2],ebx + mov bh,[edx+2] + mov bl,[edx+3] + mov [C4Y2],ebx + mov bh,[edx+4] + mov bl,[edx+5] + mov [C4Z2],ebx + mov al,[edi+4] + mov [C4Col],al + add edi,5 + call C4DrawLine + dec ecx + jnz near .loop + ret + +SECTION .data +C4X1 dd 0 +C4Y1 dd 0 +C4Z1 dd 0 +C4X2 dd 0 +C4Y2 dd 0 +C4Z2 dd 0 +C4Col dd 0 +SECTION .text + +WireFrameB: + pushad + ; 28EECA + ; 7F80 (3bytes) = pointer to data + ; 7F86-7F88 = rotation, 7F90 = scale (/7A?) + ; 6295 = # of lines, 7FA5 = ??? + mov esi,[C4Ram] + add esi,300h + mov ecx,16*12*3 +.loop + mov dword[esi],0 + add esi,4 + loop .loop + call DrawWireFrame + + mov esi,[C4Ram] + mov cx,[esi+1FA5h] +; mov [C4values],cx +; mov cx,[esi+1F86h] +; mov [C4values],cx +; mov cx,[esi+1F88h] +; mov [C4values+2],cx +; mov cx,[esi+1F90h] +; mov [C4values+4],cx + popad + ret + +WireFrameB2: + pushad + call DrawWireFrame + popad + ret + +C4WireFrame: + pushad + mov esi,[C4Ram] + mov ax,[esi+1F83h] + and ax,0FFh + mov [C4WFX2Val],ax +; mov [C4values],ax + mov ax,[esi+1F86h] + and ax,0FFh + mov [C4WFY2Val],ax +; mov [C4values+2],ax + mov ax,[esi+1F89h] + and ax,0FFh + mov [C4WFDist],ax +; mov [C4values+4],ax + mov ax,[esi+1F8Ch] + and ax,0FFh + mov [C4WFScale],ax +; mov [C4values+6],ax + + ; transform vertices (MMX2 - 36 vertices, 54 lines) + xor ecx,ecx + mov cx,[esi+1F80h] + xor al,al +.loop + mov ax,[esi+1] + mov [C4WFXVal],ax + mov ax,[esi+5] + mov [C4WFYVal],ax + mov ax,[esi+9] + mov [C4WFZVal],ax + push esi + push ecx + call C4TransfWireFrame + pop ecx + pop esi + ; Displace + mov ax,[C4WFXVal] + add ax,80h + mov [esi+1],ax + mov ax,[C4WFYVal] + add ax,50h + mov [esi+5],ax + add esi,10h + loop .loop + ; Uses 6001,6005,6600,6602,6605 + + mov esi,[C4Ram] + mov word[esi+$600],23 + mov word[esi+$602],60h + mov word[esi+$605],40h + mov word[esi+$600+8],23 + mov word[esi+$602+8],60h + mov word[esi+$605+8],40h + + xor ecx,ecx + mov cx,[esi+0B00h] + mov edi,esi + add edi,0B02h +.lineloop + xor eax,eax + mov al,[edi] + shl eax,4 + add eax,[C4Ram] + mov bx,[eax+1] + mov [C4WFXVal],bx + mov bx,[eax+5] + mov [C4WFYVal],bx + xor eax,eax + mov al,[edi+1] + shl eax,4 + add eax,[C4Ram] + mov bx,[eax+1] + mov [C4WFX2Val],bx + mov bx,[eax+5] + mov [C4WFY2Val],bx + push esi + push edi + push ecx + call C4CalcWireFrame + pop ecx + pop edi + pop esi + mov ax,[C4WFDist] + or ax,ax + jnz .yeswire + mov ax,1 +.yeswire + mov word[esi+$600],ax + mov ax,[C4WFXVal] + mov word[esi+$602],ax + mov ax,[C4WFYVal] + mov word[esi+$605],ax + add edi,2 + add esi,8 + dec ecx + jnz near .lineloop +.done + popad + ret + +C4Transform: + ; 7F81,4,7,9,A,B,0,1,D + pushad + mov esi,[C4Ram] + mov ax,word[esi+1F81h] + mov [C4WFXVal],ax + mov ax,word[esi+1F84h] + mov [C4WFYVal],ax + mov ax,word[esi+1F87h] + mov [C4WFZVal],ax + mov al,[esi+1F90h] + mov [C4WFScale],al + mov al,[esi+1F89h] + mov [C4WFX2Val],al + mov al,[esi+1F8Ah] + mov [C4WFY2Val],al + mov al,[esi+1F8Bh] + mov [C4WFDist],al + call C4TransfWireFrame2 + mov ax,[C4WFXVal] + mov word[esi+1F80h],ax + mov ax,[C4WFYVal] + mov word[esi+1F83h],ax + popad + ret + +SECTION .data +C4SprPos dd 0 +C4SprScale dd 0 +C4SprScaleY dd 0 +C4SprScaler dd 0 +C4SprScalerY dd 0 +C4SprPtr dd 0 +C4SprPtrInc dd 0 +NEWSYM C4values, dd 0,0,0 +SECTION .text + +C4activate: + cmp ecx,1F4Fh + jne .noc4test + push esi + mov esi,[C4Ram] + cmp byte[esi+1F4Dh],0Eh + jne .befnoc4test + test al,0C3h + jnz .befnoc4test + shr al,2 + mov [esi+1F80h],al + pop esi + ret +.befnoc4test + pop esi +.noc4test + cmp al,00h + je near .dosprites + cmp al,01h + je near .dowireframe + cmp al,05h ; ? + je near .propulsion + cmp al,0Dh ; ? + je near .equatevelocity + cmp al,10h ; supply angle+distance, return x/y displacement + je near .direction + cmp al,13h ; Convert polar coordinates to rectangular 2 (similar to 10) + je near .polarcord2 + cmp al,15h ; ? + je near .calcdistance + cmp al,1Fh ; supply x/y displacement, return angle (+distance?) + je near .calcangle + cmp al,22h ; supply x/y displacement, return angle (+distance?) + je near .linearray + cmp al,25h + je near .multiply + cmp al,2Dh ; ??? + je near .transform + cmp al,40h + je near .sum + cmp al,54h + je near .square + cmp al,5Ch + je near .immediatereg + cmp al,89h + je near .immediaterom + ret +.dowireframe + call WireFrameB + ret +.linearray + pushad + ; C,F,0,3,6,9 -> 6800 (E1h bytes) + ; 0,3 = screen scroll coordinates + ; 6,9 = light source coordinates + ; C,F = angle of both arrays + mov esi,[C4Ram] + xor ecx,ecx +.loopline + ; process position + xor eax,eax + mov al,[esi+1F8Ch] + or ecx,ecx + jz .secondlineb + mov al,[esi+1F8Fh] +.secondlineb + test al,80h + jz .notua + or ah,1 +.notua + movsx ebx,word[CosTable+eax*2] + mov ax,word[SinTable+eax*2] + shl eax,16 + cmp ebx,0 + je near .finish + xor edx,edx + test eax,80000000h + jz .notnegline + mov edx,0FFFFFFFFh +.notnegline + idiv ebx + mov [C4Temp],eax + xor edx,edx + mov bx,[esi+1F83h] + sub bx,[esi+1F89h] + dec bx + movsx ebx,bx +.nextline + test ebx,80000000h + jnz .none + mov eax,[C4Temp] + imul eax,ebx + sar eax,16 + sub ax,[esi+1F80h] + add ax,[esi+1F86h] + inc ax + add ax,cx + cmp ax,0 + jge .not0line + xor ax,ax + or ecx,ecx + jz .not0line + mov byte[esi+edx+$800],1 +.not0line + cmp ax,255 + jl .not255line + mov ax,255 +.not255line + jmp .doneline +.none + mov al,1 + sub al,cl +.doneline + or ecx,ecx + jnz .secondline + mov [esi+edx+$800],al + jmp .firstline +.secondline + mov [esi+edx+$900],al +.firstline + inc ebx + inc edx + cmp edx,0E1h + jne .nextline + or ecx,ecx + jnz .finish + mov ecx,1 + jmp .loopline +.finish + mov cx,[C4Temp] +; mov [C4values],cx + mov cx,[C4Temp+2] +; mov [C4values+2],cx + mov cx,[esi+1F8Ch] +; mov [C4values+4],cx + mov cx,[esi+1F8Fh] +; mov [C4values+6],cx + popad + ret +.propulsion + pushad + ; 81 = 5B, 83 = 0x300 + ; 0x300 = /1, 0x280 = /4 + mov esi,[C4Ram] + + mov cx,[esi+1F83h] + mov [C4values+2],cx + mov cx,[esi+1F81h] + mov [C4values],cx + xor bx,bx + +; mov ax,256*256 + xor ax,ax + mov dx,1 + mov bx,[esi+1F83h] + or dx,dx + jz .done + idiv bx + mov [C4values+6],ax + mov bx,[esi+1F81h] + imul bx + shl edx,16 + mov dx,ax + sar edx,8 +.done + mov word[esi+1F80h],dx + mov [C4values+4],dx + +; and eax,1FFh +; mov bx,[SinTable+eax*2] +; mov ax,[esi+1F81h] ; distance? +; imul bx +; mov ax,dx +; shl ax,1 +; shl dx,3 +; add dx,ax + + popad + ret +.polarcord2 + pushad + mov esi,[C4Ram] + xor ecx,ecx + mov cx,[esi+1F80h] + and ecx,1FFh + movsx eax,word[esi+1F83h] + add eax,eax + movsx ebx,word[CosTable+ecx*2] + imul ebx,eax + sar ebx,8 + adc ebx,0 + mov [esi+1F86h],ebx + movsx ebx,word[SinTable+ecx*2] + imul ebx,eax + sar ebx,8 + adc ebx,0 + mov [esi+1F89h],bx + sar ebx,16 + mov [esi+1F8Bh],bl + popad + ret +.dosprites +; mov byte[debstop3],0 + push eax + mov eax,[C4Ram] + cmp byte[eax+1F4Dh],0 + je near .sprites + cmp byte[eax+1F4Dh],3 + je near .scaler + cmp byte[eax+1F4Dh],5 + je near .lines + cmp byte[eax+1F4Dh],7 + je near .rotater + cmp byte[eax+1F4Dh],8 + je near .wireframeb + cmp byte[eax+1F4Dh],0Bh + je near .disintegrate + cmp byte[eax+1F4Dh],0Ch + je near .bitmap + pop eax + ret +.wireframeb + pop eax + call WireFrameB2 + ret +.sprites + pop eax + call C4ProcessSprites + ret +.disintegrate + call C4SprDisintegrate + pop eax + ret +.dolines +; mov byte[debstop3],0 + ret +.bitmap + call C4BitPlaneWave + pop eax + ret +.calcdistance + pushad + mov esi,[C4Ram] + mov bx,[esi+1F80h] + mov [C41FXVal],bx + mov bx,[esi+1F83h] + mov [C41FYVal],bx +; mov eax,[C4Ram] +; mov cx,[eax+1F80h] +; mov [C4values+0],cx +; mov cx,[eax+1F83h] +; mov [C4values+2],cx + call C4Op15 + mov eax,[C4Ram] + mov bx,[C41FDist] + mov [eax+1F80h],bx +; mov word[eax+1F80h],50 +; mov cx,[eax+1F80h] +; mov [C4values+4],cx + popad + ret +.calcangle + pushad + mov esi,[C4Ram] + mov bx,[esi+1F80h] + mov [C41FXVal],bx + mov bx,[esi+1F83h] + mov [C41FYVal],bx + call C4Op1F + mov eax,[C4Ram] + mov bx,[C41FAngleRes] + mov [eax+1F86h],bx +; mov esi,[C4Ram] +; mov cx,[esi+1F86h] +; mov [C4values],cx +; mov cx,[esi+1F80h] +; mov [C4values+2],cx +; mov cx,[esi+1F83h] +; mov [C4values+4],cx + popad + ret +.transform + ; 7F81,4,7,9,A,B,0,1,D +; mov byte[debstop3],0 + pushad +; mov eax,[C4Ram] + call C4Transform +; mov word[eax+1F80h],0 +; mov word[eax+1F83h],0 + popad + ret +.multiply + pushad + mov esi,[C4Ram] + mov eax,[esi+1F80h] + and eax,0FFFFFFh + mov ebx,[esi+1F83h] + and ebx,0FFFFFFh + imul eax,ebx + mov [esi+1F80h],eax + popad + ret +.sum + pushad + xor eax,eax + xor ebx,ebx + mov esi,[C4Ram] + mov ecx,800h +.sumloop + mov bl,byte[esi] + inc esi + add ax,bx + dec ecx + jnz .sumloop + mov [esi+1F80h-0800h],ax + popad + ret +.square + pushad + xor edx,edx + mov esi,[C4Ram] + mov eax,[esi+1F80h] + shl eax,8 + sar eax,8 + imul eax + mov [esi+1F83h],eax + mov [esi+1F87h],dx + popad + ret +.equatevelocity + pushad + mov esi,[C4Ram] + mov bx,[esi+1F80h] + mov [C41FXVal],bx + mov bx,[esi+1F83h] + mov [C41FYVal],bx + mov bx,[esi+1F86h] + mov [C41FDistVal],bx + call C4Op0D + mov bx,[C41FXVal] + mov [esi+1F89h],bx + mov bx,[C41FYVal] + mov [esi+1F8Ch],bx + popad + ret + + + pushad + mov esi,[C4Ram] + mov cx,[esi+$1F86] + cmp cx,40h + jb .nomult + shr cx,7 +.nomult + mov ax,[esi+$1F80] +; imul cx + shl ax,4 + mov word[esi+$1F89],ax + mov ax,[esi+$1F83] +; imul cx + shl ax,4 + mov word[esi+$1F8C],ax +; mov cx,[esi+$1F80] +; mov [C4values],cx +; mov cx,[esi+$1F83] +; mov [C4values+2],cx +; mov cx,[esi+$1F86] +; mov [C4values+4],cx + popad + ret +.lines + call C4WireFrame + pop eax + ret +.scaler + push esi + push ecx + mov esi,[C4Ram] +; mov cx,[esi+1F8Fh] +; mov [C4values],cx +; mov cx,[esi+1F92h] +; mov [C4values+2],cx +; mov cx,[esi+1F80h] +; mov [C4values+4],cx + pop ecx + pop esi + call C4SprScaleR + pop eax + ret +.rotater + push esi + push ecx + mov esi,[C4Ram] +; mov cx,[esi+1F8Fh] +; mov [C4values],cx +; mov cx,[esi+1F92h] +; mov [C4values+2],cx +; mov cx,[esi+1F80h] +; mov [C4values+4],cx + pop ecx + pop esi + call C4SprRotateR + pop eax + ret +.direction + push eax + push ebx + push esi + push edx + push ecx + mov esi,[C4Ram] + xor ecx,ecx + mov ax,[esi+1F80h] + and eax,1FFh + mov bx,[CosTable+eax*2] + mov ax,[esi+1F83h] + imul bx + add ax,ax + adc dx,dx + mov ax,dx + movsx edx,dx + mov [esi+1F86h],edx + mov ax,[esi+1F80h] + and eax,1FFh + mov bx,[SinTable+eax*2] + mov ax,[esi+1F83h] + imul bx + add ax,ax + adc dx,dx + mov ax,dx + movsx edx,dx + mov eax,edx + sar eax,6 + sub edx,eax + mov al,[esi+198Ch] + mov [esi+1F89h],edx + mov [esi+198Ch],al +; mov cx,[esi+1F80h] +; mov [C4values],cx +; mov cx,[esi+1F83h] +; mov [C4values+2],cx +; mov cx,[esi+1F86h] +; mov [C4values+4],cx + pop ecx + pop edx + pop esi + pop ebx + pop eax + ret +.immediaterom + push eax + mov eax,[C4Ram] + mov byte[eax+1F80h],36h + mov byte[eax+1F81h],43h + mov byte[eax+1F82h],05h + pop eax + ret +.immediatereg + push eax + mov eax,[C4Ram] + mov dword[eax+0*4],0FF000000h + mov dword[eax+1*4],0FF00FFFFh + mov dword[eax+2*4],0FF000000h + mov dword[eax+3*4],00000FFFFh + mov dword[eax+4*4],00000FFFFh + mov dword[eax+5*4],07FFFFF80h + mov dword[eax+6*4],0FF008000h + mov dword[eax+7*4],07FFF007Fh + mov dword[eax+8*4],0FFFF7FFFh + mov dword[eax+9*4],0FF010000h + mov dword[eax+10*4],00100FEFFh + mov dword[eax+11*4],000FEFF00h + pop eax + ret + +;NEWSYM C4RegFunction + add ecx,[C4Ram] + mov [ecx],al + sub ecx,[C4Ram] + cmp ecx,1F4Fh + je near C4activate + ret + +NEWSYM C4ReadReg + add ecx,[C4Ram] + mov al,[ecx] + sub ecx,[C4Ram] + ret + +NEWSYM C4RegFunction +NEWSYM C4WriteReg + add ecx,[C4Ram] + mov [ecx],al + sub ecx,[C4Ram] + cmp ecx,1F4Fh + je near C4activate + cmp ecx,1F47h + je .C4Memcpy + ret + +.C4Memcpy + pushad + push dword [C4Ram] + call C4LoaDMem + pop eax + popad + ret + +SECTION .data +SinTable: +dw $00000,$00192,$00324,$004B6,$00647,$007D9,$0096A,$00AFB,$00C8B,$00E1B,$00FAB +dw $01139,$012C8,$01455,$015E2,$0176D,$018F8,$01A82,$01C0B,$01D93,$01F19,$0209F +dw $02223,$023A6,$02528,$026A8,$02826,$029A3,$02B1F,$02C98,$02E11,$02F87,$030FB +dw $0326E,$033DE,$0354D,$036BA,$03824,$0398C,$03AF2,$03C56,$03DB8,$03F17,$04073 +dw $041CE,$04325,$0447A,$045CD,$0471C,$04869,$049B4,$04AFB,$04C3F,$04D81,$04EBF +dw $04FFB,$05133,$05269,$0539B,$054CA,$055F5,$0571D,$05842,$05964,$05A82,$05B9D +dw $05CB4,$05DC7,$05ED7,$05FE3,$060EC,$061F1,$062F2,$063EF,$064E8,$065DD,$066CF +dw $067BD,$068A6,$0698C,$06A6D,$06B4A,$06C24,$06CF9,$06DCA,$06E96,$06F5F,$07023 +dw $070E2,$0719E,$07255,$07307,$073B5,$0745F,$07504,$075A5,$07641,$076D9,$0776C +dw $077FA,$07884,$07909,$0798A,$07A05,$07A7D,$07AEF,$07B5D,$07BC5,$07C29,$07C89 +dw $07CE3,$07D39,$07D8A,$07DD6,$07E1D,$07E5F,$07E9D,$07ED5,$07F09,$07F38,$07F62 +dw $07F87,$07FA7,$07FC2,$07FD8,$07FE9,$07FF6,$07FFD,$07FFF,$07FFD,$07FF6,$07FE9 +dw $07FD8,$07FC2,$07FA7,$07F87,$07F62,$07F38,$07F09,$07ED5,$07E9D,$07E5F,$07E1D +dw $07DD6,$07D8A,$07D39,$07CE3,$07C89,$07C29,$07BC5,$07B5D,$07AEF,$07A7D,$07A05 +dw $0798A,$07909,$07884,$077FA,$0776C,$076D9,$07641,$075A5,$07504,$0745F,$073B5 +dw $07307,$07255,$0719E,$070E2,$07023,$06F5F,$06E96,$06DCA,$06CF9,$06C24,$06B4A +dw $06A6D,$0698C,$068A6,$067BD,$066CF,$065DD,$064E8,$063EF,$062F2,$061F1,$060EC +dw $05FE3,$05ED7,$05DC7,$05CB4,$05B9D,$05A82,$05964,$05842,$0571D,$055F5,$054CA +dw $0539B,$05269,$05133,$04FFB,$04EBF,$04D81,$04C3F,$04AFB,$049B4,$04869,$0471C +dw $045CD,$0447A,$04325,$041CE,$04073,$03F17,$03DB8,$03C56,$03AF2,$0398C,$03824 +dw $036BA,$0354D,$033DE,$0326E,$030FB,$02F87,$02E11,$02C98,$02B1F,$029A3,$02826 +dw $026A8,$02528,$023A6,$02223,$0209F,$01F19,$01D93,$01C0B,$01A82,$018F8,$0176D +dw $015E2,$01455,$012C8,$01139,$00FAB,$00E1B,$00C8B,$00AFB,$0096A,$007D9,$00647 +dw $004B6,$00324,$00192 +dw $00000,$0FE6E,$0FCDC,$0FB4A,$0F9B9,$0F827,$0F696,$0F505,$0F375,$0F1E5,$0F055 +dw $0EEC7,$0ED38,$0EBAB,$0EA1E,$0E893,$0E708,$0E57E,$0E3F5,$0E26D,$0E0E7,$0DF61 +dw $0DDDD,$0DC5A,$0DAD8,$0D958,$0D7DA,$0D65D,$0D4E1,$0D368,$0D1EF,$0D079,$0CF05 +dw $0CD92,$0CC22,$0CAB3,$0C946,$0C7DC,$0C674,$0C50E,$0C3AA,$0C248,$0C0E9,$0BF8D +dw $0BE32,$0BCDB,$0BB86,$0BA33,$0B8E4,$0B797,$0B64C,$0B505,$0B3C1,$0B27F,$0B141 +dw $0B005,$0AECD,$0AD97,$0AC65,$0AB36,$0AA0B,$0A8E3,$0A7BE,$0A69C,$0A57E,$0A463 +dw $0A34C,$0A239,$0A129,$0A01D,$09F14,$09E0F,$09D0E,$09C11,$09B18,$09A23,$09931 +dw $09843,$0975A,$09674,$09593,$094B6,$093DC,$09307,$09236,$0916A,$090A1,$08FDD +dw $08F1E,$08E62,$08DAB,$08CF9,$08C4B,$08BA1,$08AFC,$08A5B,$089BF,$08927,$08894 +dw $08806,$0877C,$086F7,$08676,$085FB,$08583,$08511,$084A3,$0843B,$083D7,$08377 +dw $0831D,$082C7,$08276,$0822A,$081E3,$081A1,$08163,$0812B,$080F7,$080C8,$0809E +dw $08079,$08059,$0803E,$08028,$08017,$0800A,$08003,$08001,$08003,$0800A,$08017 +dw $08028,$0803E,$08059,$08079,$0809E,$080C8,$080F7,$0812B,$08163,$081A1,$081E3 +dw $0822A,$08276,$082C7,$0831D,$08377,$083D7,$0843B,$084A3,$08511,$08583,$085FB +dw $08676,$086F7,$0877C,$08806,$08894,$08927,$089BF,$08A5B,$08AFC,$08BA1,$08C4B +dw $08CF9,$08DAB,$08E62,$08F1E,$08FDD,$090A1,$0916A,$09236,$09307,$093DC,$094B6 +dw $09593,$09674,$0975A,$09843,$09931,$09A23,$09B18,$09C11,$09D0E,$09E0F,$09F14 +dw $0A01D,$0A129,$0A239,$0A34C,$0A463,$0A57E,$0A69C,$0A7BE,$0A8E3,$0AA0B,$0AB36 +dw $0AC65,$0AD97,$0AECD,$0B005,$0B141,$0B27F,$0B3C1,$0B505,$0B64C,$0B797,$0B8E4 +dw $0BA33,$0BB86,$0BCDB,$0BE32,$0BF8D,$0C0E9,$0C248,$0C3AA,$0C50E,$0C674,$0C7DC +dw $0C946,$0CAB3,$0CC22,$0CD92,$0CF05,$0D079,$0D1EF,$0D368,$0D4E1,$0D65D,$0D7DA +dw $0D958,$0DAD8,$0DC5A,$0DDDD,$0DF61,$0E0E7,$0E26D,$0E3F5,$0E57E,$0E708,$0E893 +dw $0EA1E,$0EBAB,$0ED38,$0EEC7,$0F055,$0F1E5,$0F375,$0F505,$0F696,$0F827,$0F9B9 +dw $0FB4A,$0FCDC,$0FE6E + + +CosTable: +dw $07FFF,$07FFD,$07FF6,$07FE9,$07FD8,$07FC2,$07FA7,$07F87,$07F62,$07F38,$07F09 +dw $07ED5,$07E9D,$07E5F,$07E1D,$07DD6,$07D8A,$07D39,$07CE3,$07C89,$07C29,$07BC5 +dw $07B5D,$07AEF,$07A7D,$07A05,$0798A,$07909,$07884,$077FA,$0776C,$076D9,$07641 +dw $075A5,$07504,$0745F,$073B5,$07307,$07255,$0719E,$070E2,$07023,$06F5F,$06E96 +dw $06DCA,$06CF9,$06C24,$06B4A,$06A6D,$0698C,$068A6,$067BD,$066CF,$065DD,$064E8 +dw $063EF,$062F2,$061F1,$060EC,$05FE3,$05ED7,$05DC7,$05CB4,$05B9D,$05A82,$05964 +dw $05842,$0571D,$055F5,$054CA,$0539B,$05269,$05133,$04FFB,$04EBF,$04D81,$04C3F +dw $04AFB,$049B4,$04869,$0471C,$045CD,$0447A,$04325,$041CE,$04073,$03F17,$03DB8 +dw $03C56,$03AF2,$0398C,$03824,$036BA,$0354D,$033DE,$0326E,$030FB,$02F87,$02E11 +dw $02C98,$02B1F,$029A3,$02826,$026A8,$02528,$023A6,$02223,$0209F,$01F19,$01D93 +dw $01C0B,$01A82,$018F8,$0176D,$015E2,$01455,$012C8,$01139,$00FAB,$00E1B,$00C8B +dw $00AFB,$0096A,$007D9,$00647,$004B6,$00324,$00192,$00000,$0FE6E,$0FCDC,$0FB4A +dw $0F9B9,$0F827,$0F696,$0F505,$0F375,$0F1E5,$0F055,$0EEC7,$0ED38,$0EBAB,$0EA1E +dw $0E893,$0E708,$0E57E,$0E3F5,$0E26D,$0E0E7,$0DF61,$0DDDD,$0DC5A,$0DAD8,$0D958 +dw $0D7DA,$0D65D,$0D4E1,$0D368,$0D1EF,$0D079,$0CF05,$0CD92,$0CC22,$0CAB3,$0C946 +dw $0C7DC,$0C674,$0C50E,$0C3AA,$0C248,$0C0E9,$0BF8D,$0BE32,$0BCDB,$0BB86,$0BA33 +dw $0B8E4,$0B797,$0B64C,$0B505,$0B3C1,$0B27F,$0B141,$0B005,$0AECD,$0AD97,$0AC65 +dw $0AB36,$0AA0B,$0A8E3,$0A7BE,$0A69C,$0A57E,$0A463,$0A34C,$0A239,$0A129,$0A01D +dw $09F14,$09E0F,$09D0E,$09C11,$09B18,$09A23,$09931,$09843,$0975A,$09674,$09593 +dw $094B6,$093DC,$09307,$09236,$0916A,$090A1,$08FDD,$08F1E,$08E62,$08DAB,$08CF9 +dw $08C4B,$08BA1,$08AFC,$08A5B,$089BF,$08927,$08894,$08806,$0877C,$086F7,$08676 +dw $085FB,$08583,$08511,$084A3,$0843B,$083D7,$08377,$0831D,$082C7,$08276,$0822A +dw $081E3,$081A1,$08163,$0812B,$080F7,$080C8,$0809E,$08079,$08059,$0803E,$08028 +dw $08017,$0800A,$08003 +dw $08001,$08003,$0800A,$08017,$08028,$0803E,$08059,$08079,$0809E,$080C8,$080F7, +dw $0812B,$08163,$081A1,$081E3,$0822A,$08276,$082C7,$0831D,$08377,$083D7,$0843B, +dw $084A3,$08511,$08583,$085FB,$08676,$086F7,$0877C,$08806,$08894,$08927,$089BF, +dw $08A5B,$08AFC,$08BA1,$08C4B,$08CF9,$08DAB,$08E62,$08F1E,$08FDD,$090A1,$0916A, +dw $09236,$09307,$093DC,$094B6,$09593,$09674,$0975A,$09843,$09931,$09A23,$09B18, +dw $09C11,$09D0E,$09E0F,$09F14,$0A01D,$0A129,$0A239,$0A34C,$0A463,$0A57E,$0A69C, +dw $0A7BE,$0A8E3,$0AA0B,$0AB36,$0AC65,$0AD97,$0AECD,$0B005,$0B141,$0B27F,$0B3C1, +dw $0B505,$0B64C,$0B797,$0B8E4,$0BA33,$0BB86,$0BCDB,$0BE32,$0BF8D,$0C0E9,$0C248, +dw $0C3AA,$0C50E,$0C674,$0C7DC,$0C946,$0CAB3,$0CC22,$0CD92,$0CF05,$0D079,$0D1EF, +dw $0D368,$0D4E1,$0D65D,$0D7DA,$0D958,$0DAD8,$0DC5A,$0DDDD,$0DF61,$0E0E7,$0E26D, +dw $0E3F5,$0E57E,$0E708,$0E893,$0EA1E,$0EBAB,$0ED38,$0EEC7,$0F055,$0F1E5,$0F375, +dw $0F505,$0F696,$0F827,$0F9B9,$0FB4A,$0FCDC,$0FE6E,$00000,$00192,$00324,$004B6, +dw $00647,$007D9,$0096A,$00AFB,$00C8B,$00E1B,$00FAB,$01139,$012C8,$01455,$015E2, +dw $0176D,$018F8,$01A82,$01C0B,$01D93,$01F19,$0209F,$02223,$023A6,$02528,$026A8, +dw $02826,$029A3,$02B1F,$02C98,$02E11,$02F87,$030FB,$0326E,$033DE,$0354D,$036BA, +dw $03824,$0398C,$03AF2,$03C56,$03DB8,$03F17,$04073,$041CE,$04325,$0447A,$045CD, +dw $0471C,$04869,$049B4,$04AFB,$04C3F,$04D81,$04EBF,$04FFB,$05133,$05269,$0539B, +dw $054CA,$055F5,$0571D,$05842,$05964,$05A82,$05B9D,$05CB4,$05DC7,$05ED7,$05FE3, +dw $060EC,$061F1,$062F2,$063EF,$064E8,$065DD,$066CF,$067BD,$068A6,$0698C,$06A6D, +dw $06B4A,$06C24,$06CF9,$06DCA,$06E96,$06F5F,$07023,$070E2,$0719E,$07255,$07307, +dw $073B5,$0745F,$07504,$075A5,$07641,$076D9,$0776C,$077FA,$07884,$07909,$0798A, +dw $07A05,$07A7D,$07AEF,$07B5D,$07BC5,$07C29,$07C89,$07CE3,$07D39,$07D8A,$07DD6, +dw $07E1D,$07E5F,$07E9D,$07ED5,$07F09,$07F38,$07F62,$07F87,$07FA7,$07FC2,$07FD8, +dw $07FE9,$07FF6,$07FFD + +SECTION .text diff --git a/i386/fxemu2.asm b/i386/fxemu2.asm new file mode 100644 index 00000000..76de7b41 --- /dev/null +++ b/i386/fxemu2.asm @@ -0,0 +1,2692 @@ +;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com ) +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;as published by the Free Software Foundation; either +;version 2 of the License, or (at your option) any later +;version. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +%include "macros.mac" + +EXTSYM FxTable,FxTableb,FxTablec,FxTabled,SfxMemTable,flagnz,fxbit01,fxbit23 +EXTSYM fxxand,sfx128lineloc,sfx160lineloc,sfx192lineloc,sfxobjlineloc +EXTSYM sfxramdata,fxbit45,fxbit67,SFXProc,ChangeOps +EXTSYM PLOTJmpa,PLOTJmpb + +NEWSYM FxEmu2AsmStart + +%include "fxemu2.mac" + + + + + + +; * Optimise PLOT, COLOR! +SECTION .text +NEWSYM FlushCache + ; Copy 512 bytes from pb:eax to SfxCACHERAM + ret + +SECTION .bss +NEWSYM tempsfx, resb 3 + +SECTION .data ;ALIGN=32 + +; FxChip emulation by _Demo_ +; Optimised by zsKnight +; based on fxemu by lestat + +NEWSYM SfxR0, dd 0 ; default source/destination register +NEWSYM SfxR1, dd 0 ; pixel plot X position register +NEWSYM SfxR2, dd 0 ; pixel plot Y position register +NEWSYM SfxR3, dd 0 ; +NEWSYM SfxR4, dd 0 ; lower 16 bit result of lmult +NEWSYM SfxR5, dd 0 ; +NEWSYM SfxR6, dd 0 ; multiplier for fmult and lmult +NEWSYM SfxR7, dd 0 ; fixed point texel X position for merge +NEWSYM SfxR8, dd 0 ; fixed point texel Y position for merge +NEWSYM SfxR9, dd 0 ; +NEWSYM SfxR10, dd 0 ; +NEWSYM SfxR11, dd 0 ; return address set by link +NEWSYM SfxR12, dd 0 ; loop counter +NEWSYM SfxR13, dd 0 ; loop point address +NEWSYM SfxR14, dd 0 ; rom address for getb, getbh, getbl, getbs +NEWSYM SfxR15, dd 0 ; program counter + +NEWSYM SfxSFR, dd 0 ; status flag register (16bit) +;SFR status flag register bits: +; 0 - +; 1 Z Zero flag +; 2 CY Carry flag +; 3 S Sign flag +; 4 OV Overflow flag +; 5 G Go flag (set to 1 when the GSU is running) +; 6 R Set to 1 when reading ROM using R14 address +; 7 - +; 8 ALT1 Mode set-up flag for the next instruction +; 9 ALT2 Mode set-up flag for the next instruction +;10 IL Immediate lower 8-bit flag +;11 IH Immediate higher 8-bit flag +;12 B Set to 1 when the WITH instruction is executed +;13 - +;14 - +;15 IRQ Set to 1 when GSU caused an interrupt +; Set to 0 when read by 658c16 + +NEWSYM SfxBRAMR, dd 0 ; backup ram read only on/off (8bit) +NEWSYM SfxPBR, dd 0 ; program bank register (8bit) +NEWSYM SfxROMBR, dd 0 ; rom bank register (8bit) +NEWSYM SfxCFGR, dd 0 ; control flags register (8bit) +NEWSYM SfxSCBR, dd 0 ; screen bank register (8bit) +NEWSYM SfxCLSR, dd 0 ; clock speed register (8bit) +NEWSYM SfxSCMR, dd 0 ; screen mode register (8bit) +NEWSYM SfxVCR, dd 0 ; version code register (8bit) +NEWSYM SfxRAMBR, dd 0 ; ram bank register (8bit) +NEWSYM SfxCBR, dd 0 ; cache base register (16bit) + +NEWSYM SfxCOLR, dd 0 ; Internal color register +NEWSYM SfxPOR, dd 0 ; Plot option register + +NEWSYM SfxCacheFlags, dd 0 ; Saying what parts of the cache was written to +NEWSYM SfxLastRamAdr, dd 0 ; Last RAM address accessed +NEWSYM SfxDREG, dd 0 ; Current destination register index +NEWSYM SfxSREG, dd 0 ; Current source register index +NEWSYM SfxRomBuffer, dd 0 ; Current byte read by R14 +NEWSYM SfxPIPE, dd 0 ; Instructionset pipe +NEWSYM SfxPipeAdr, dd 0 ; The address of where the pipe was read from + +NEWSYM SfxnRamBanks, dd 4 ; Number of 64kb-banks in FxRam (Don't confuse it with SNES-Ram!!!) +NEWSYM SfxnRomBanks, dd 0 ; Number of 32kb-banks in Cart-ROM + +NEWSYM SfxvScreenHeight, dd 0 ; 128, 160 or 192 +NEWSYM SfxvScreenSize, dd 0 + +NEWSYM SfxCacheActive, dd 0 ; Cache Active + +NEWSYM SfxCarry, dd 0 ; Carry flag +NEWSYM SfxSignZero, dd 1 ; Sign and Zero flag +NEWSYM SfxB, dd 0 ; B flag (1 when with instruction executed) +NEWSYM SfxOverflow, dd 0 ; Overflow flag + +NEWSYM SfxCACHERAM, times 512 db 0 ; 512 bytes of GSU cache memory +num2writesfxreg equ $-SfxR0 +; pharos equ hack *sigh* +NEWSYM PHnum2writesfxreg, dd num2writesfxreg + +NEWSYM SfxCPB, dd 0 +NEWSYM SfxCROM, dd 0 +NEWSYM SfxRAMMem, dd 0 +NEWSYM withr15sk, dd 0 +NEWSYM sfxclineloc, dd 0 +NEWSYM SCBRrel, dd 0 +NEWSYM fxbit01pcal, dd 0 +NEWSYM fxbit23pcal, dd 0 +NEWSYM fxbit45pcal, dd 0 +NEWSYM fxbit67pcal, dd 0 + +;SfxRAM times 256*1024 db 0 + +; If we need this later... + +SECTION .text +NEWSYM FxOp00 ; STOP stop GSU execution (and maybe generate an IRQ) ; Verified. + FETCHPIPE + mov [SfxPIPE],cl + and dword [SfxSFR],0FFFFh-32 ; Clear Go flag (set to 1 when the GSU is running) + test dword [SfxCFGR],080h ; Check if the interrupt generation is on + jnz .NoIRQ + or dword [SfxSFR],08000h ; Set IRQ Flag +.NoIRQ + CLRFLAGS + inc ebp + mov eax,[NumberOfOpcodes] + add eax,0F0000000h + add [ChangeOps],eax + mov dword [NumberOfOpcodes],1 + mov dword[SFXProc],0 + xor cl,cl + ret + +NEWSYM FxOp01 ; NOP no operation ; Verified. + FETCHPIPE + CLRFLAGS + inc ebp ; Increase program counter + ret + +NEWSYM FxOp02 ; CACHE reintialize GSU cache + mov eax,ebp + FETCHPIPE + sub eax,[SfxCPB] + and eax,0FFF0h + cmp dword [SfxCBR],eax + je .SkipUpdate + cmp byte [SfxCacheActive],1 + je .SkipUpdate + mov dword [SfxCBR],eax + mov dword [SfxCacheActive],1 + call FlushCache +.SkipUpdate + CLRFLAGS + inc ebp ; Increase program counter + ret + +NEWSYM FxOp03 ; LSR logic shift right ; Verified. + mov eax,[esi] ; Read Source + FETCHPIPE + mov [SfxCarry],al + and byte[SfxCarry],1 + shr ax,1 ; logic shift right + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov dword [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOp04 ; ROL rotate left (RCL?) ; V + shr byte[SfxCarry],1 + mov eax,[esi] ; Read Source + FETCHPIPE + rcl ax,1 + rcl byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOp05 ; BRA branch always ; Verified. + movsx eax,byte[ebp] + mov cl,[ebp+1] + inc ebp + add ebp,eax + call [FxTable+ecx*4] + ret + +NEWSYM FxOp06 ; BGE branch on greater or equals ; Verified. + movsx eax,byte[ebp] + mov ebx,[SfxSignZero] + shr ebx,15 + inc ebp + xor bl,[SfxOverflow] + mov cl,[ebp] + test bl,01h + jnz .nojump + add ebp,eax + call [FxTable+ecx*4] + ret +.nojump + inc ebp + call [FxTable+ecx*4] + ret + +NEWSYM FxOp07 ; BLT branch on lesss than ; Verified. + movsx eax,byte[ebp] + mov ebx,[SfxSignZero] + shr ebx,15 + inc ebp + xor bl,[SfxOverflow] + mov cl,[ebp] + test bl,01h + jz .nojump + add ebp,eax + call [FxTable+ecx*4] + ret +.nojump + inc ebp + call [FxTable+ecx*4] + ret + +NEWSYM FxOp08 ; BNE branch on not equal ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],0FFFFh + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTable+ecx*4] + ret +.nojump + inc ebp + call [FxTable+ecx*4] + ret + +NEWSYM FxOp09 ; BEQ branch on equal (z=1) ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],0FFFFh + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTable+ecx*4] + ret +.nojump + inc ebp + call [FxTable+ecx*4] + ret + +NEWSYM FxOp0A ; BPL branch on plus ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],088000h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTable+ecx*4] + ret +.nojump + inc ebp + call [FxTable+ecx*4] + ret + +NEWSYM FxOp0B ; BMI branch on minus ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],088000h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTable+ecx*4] + ret +.nojump + inc ebp + call [FxTable+ecx*4] + ret + +NEWSYM FxOp0C ; BCC branch on carry clear ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxCarry],01h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTable+ecx*4] + ret +.nojump + inc ebp + call [FxTable+ecx*4] + ret + +NEWSYM FxOp0D ; BCS branch on carry set ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxCarry],01h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTable+ecx*4] + ret +.nojump + inc ebp + call [FxTable+ecx*4] + ret + +NEWSYM FxOp0E ; BVC branch on overflow clear ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxOverflow],01h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTable+ecx*4] + ret +.nojump + inc ebp + call [FxTable+ecx*4] + ret + +NEWSYM FxOp0F ; BVS branch on overflow set ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxOverflow],01h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTable+ecx*4] + ret +.nojump + inc ebp + call [FxTable+ecx*4] + ret + +NEWSYM FxOp10 ; TO RN set register n as destination register + TORN 0 +NEWSYM FxOp11 ; TO RN set register n as destination register + TORN 1 +NEWSYM FxOp12 ; TO RN set register n as destination register + TORN 2 +NEWSYM FxOp13 ; TO RN set register n as destination register + TORN 3 +NEWSYM FxOp14 ; TO RN set register n as destination register + TORN 4 +NEWSYM FxOp15 ; TO RN set register n as destination register + TORN 5 +NEWSYM FxOp16 ; TO RN set register n as destination register + TORN 6 +NEWSYM FxOp17 ; TO RN set register n as destination register + TORN 7 +NEWSYM FxOp18 ; TO RN set register n as destination register + TORN 8 +NEWSYM FxOp19 ; TO RN set register n as destination register + TORN 9 +NEWSYM FxOp1A ; TO RN set register n as destination register + TORN 10 +NEWSYM FxOp1B ; TO RN set register n as destination register + TORN 11 +NEWSYM FxOp1C ; TO RN set register n as destination register + TORN 12 +NEWSYM FxOp1D ; TO RN set register n as destination register + TORN 13 +NEWSYM FxOp1E ; TO RN set register n as destination register + FETCHPIPE + mov edi,SfxR0+14*4 + inc ebp + call [FxTable+ecx*4] + mov edi,SfxR0 + UpdateR14 + ret +NEWSYM FxOp1F ; TO RN set register n as destination register + FETCHPIPE + mov edi,SfxR0+15*4 + inc ebp + call [FxTable+ecx*4] + mov ebp,[SfxCPB] + add ebp,[SfxR15] + mov edi,SfxR0 + ret + +NEWSYM FxOp20 ; WITH set register n as source and destination register + WITH 0 +NEWSYM FxOp21 ; WITH set register n as source and destination register + WITH 1 +NEWSYM FxOp22 ; WITH set register n as source and destination register + WITH 2 +NEWSYM FxOp23 ; WITH set register n as source and destination register + WITH 3 +NEWSYM FxOp24 ; WITH set register n as source and destination register + WITH 4 +NEWSYM FxOp25 ; WITH set register n as source and destination register + WITH 5 +NEWSYM FxOp26 ; WITH set register n as source and destination register + WITH 6 +NEWSYM FxOp27 ; WITH set register n as source and destination register + WITH 7 +NEWSYM FxOp28 ; WITH set register n as source and destination register + WITH 8 +NEWSYM FxOp29 ; WITH set register n as source and destination register + WITH 9 +NEWSYM FxOp2A ; WITH set register n as source and destination register + WITH 10 +NEWSYM FxOp2B ; WITH set register n as source and destination register + WITH 11 +NEWSYM FxOp2C ; WITH set register n as source and destination register + WITH 12 +NEWSYM FxOp2D ; WITH set register n as source and destination register + WITH 13 +NEWSYM FxOp2E ; WITH set register n as source and destination register + FETCHPIPE + mov esi,SfxR0+14*4 + mov edi,SfxR0+14*4 + mov dword [SfxB],1 + inc ebp + call [FxTablec+ecx*4] + mov dword [SfxB],0 ; Clear B Flag + mov esi,SfxR0 + mov edi,SfxR0 + UpdateR14 + ret +NEWSYM FxOp2F ; WITH set register n as source and destination register + FETCHPIPE + mov esi,SfxR0+15*4 + mov edi,SfxR0+15*4 + mov dword [SfxB],1 + inc ebp + mov eax,ebp + sub eax,[SfxCPB] + mov dword[withr15sk],0 + mov [SfxR15],eax + call [FxTableb+ecx*4] + cmp dword[withr15sk],1 + je .skip + mov ebp,[SfxCPB] + add ebp,[SfxR15] +.skip + mov dword [SfxB],0 ; Clear B Flag + mov esi,SfxR0 + mov edi,SfxR0 + ret + +NEWSYM FxOp30 ; STW RN store word + STWRN 0 +NEWSYM FxOp31 ; STW RN store word + STWRN 1 +NEWSYM FxOp32 ; STW RN store word + STWRN 2 +NEWSYM FxOp33 ; STW RN store word + STWRN 3 +NEWSYM FxOp34 ; STW RN store word + STWRN 4 +NEWSYM FxOp35 ; STW RN store word + STWRN 5 +NEWSYM FxOp36 ; STW RN store word + STWRN 6 +NEWSYM FxOp37 ; STW RN store word + STWRN 7 +NEWSYM FxOp38 ; STW RN store word + STWRN 8 +NEWSYM FxOp39 ; STW RN store word + STWRN 9 +NEWSYM FxOp3A ; STW RN store word + STWRN 10 +NEWSYM FxOp3B ; STW RN store word + STWRN 11 + +NEWSYM FxOp30A1 ; STB RN store byte + STBRN 0 +NEWSYM FxOp31A1 ; STB RN store byte + STBRN 1 +NEWSYM FxOp32A1 ; STB RN store byte + STBRN 2 +NEWSYM FxOp33A1 ; STB RN store byte + STBRN 3 +NEWSYM FxOp34A1 ; STB RN store byte + STBRN 4 +NEWSYM FxOp35A1 ; STB RN store byte + STBRN 5 +NEWSYM FxOp36A1 ; STB RN store byte + STBRN 6 +NEWSYM FxOp37A1 ; STB RN store byte + STBRN 7 +NEWSYM FxOp38A1 ; STB RN store byte + STBRN 8 +NEWSYM FxOp39A1 ; STB RN store byte + STBRN 9 +NEWSYM FxOp3AA1 ; STB RN store byte + STBRN 10 +NEWSYM FxOp3BA1 ; STB RN store byte + STBRN 11 + +NEWSYM FxOp3C ; LOOP decrement loop counter, and branch on not zero ; V + dec word [SfxR12] ; decrement loop counter + FETCHPIPE + mov eax,[SfxR12] + mov [SfxSignZero],eax + or eax,eax + jz .NoBranch + mov eax,dword [SfxR13] + mov ebp,[SfxCPB] + add ebp,eax + CLRFLAGS + ret +.NoBranch + inc ebp + CLRFLAGS + ret + +NEWSYM FxOp3D ; ALT1 set alt1 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,01h + inc ebp + call [FxTable+ecx*4] + xor ch,ch + ret + +NEWSYM FxOp3E ; ALT2 set alt1 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,02h + inc ebp + call [FxTable+ecx*4] + xor ch,ch + ret + +NEWSYM FxOp3F ; ALT3 set alt3 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,03h + inc ebp + call [FxTable+ecx*4] + xor ch,ch + ret + +NEWSYM FxOp40 ; LDW RN load word from RAM + LDWRN 0 +NEWSYM FxOp41 ; LDW RN load word from RAM + LDWRN 1 +NEWSYM FxOp42 ; LDW RN load word from RAM + LDWRN 2 +NEWSYM FxOp43 ; LDW RN load word from RAM + LDWRN 3 +NEWSYM FxOp44 ; LDW RN load word from RAM + LDWRN 4 +NEWSYM FxOp45 ; LDW RN load word from RAM + LDWRN 5 +NEWSYM FxOp46 ; LDW RN load word from RAM + LDWRN 6 +NEWSYM FxOp47 ; LDW RN load word from RAM + LDWRN 7 +NEWSYM FxOp48 ; LDW RN load word from RAM + LDWRN 8 +NEWSYM FxOp49 ; LDW RN load word from RAM + LDWRN 9 +NEWSYM FxOp4A ; LDW RN load word from RAM + LDWRN 10 +NEWSYM FxOp4B ; LDW RN load word from RAM + LDWRN 11 + +NEWSYM FxOp40A1 ; LDB RN load byte from RAM + LDBRN 0 +NEWSYM FxOp41A1 ; LDB RN load byte from RAM + LDBRN 1 +NEWSYM FxOp42A1 ; LDB RN load byte from RAM + LDBRN 2 +NEWSYM FxOp43A1 ; LDB RN load byte from RAM + LDBRN 3 +NEWSYM FxOp44A1 ; LDB RN load byte from RAM + LDBRN 4 +NEWSYM FxOp45A1 ; LDB RN load byte from RAM + LDBRN 5 +NEWSYM FxOp46A1 ; LDB RN load byte from RAM + LDBRN 6 +NEWSYM FxOp47A1 ; LDB RN load byte from RAM + LDBRN 7 +NEWSYM FxOp48A1 ; LDB RN load byte from RAM + LDBRN 8 +NEWSYM FxOp49A1 ; LDB RN load byte from RAM + LDBRN 9 +NEWSYM FxOp4AA1 ; LDB RN load byte from RAM + LDBRN 10 +NEWSYM FxOp4BA1 ; LDB RN load byte from RAM + LDBRN 11 + +NEWSYM FxOp4C1284b ; PLOT 4bit + plotlines4b plotb +NEWSYM FxOp4C1284bz ; PLOT 4bit, zero check + plotlines4b plotbz +NEWSYM FxOp4C1284bd ; PLOT 4bit, dither + plotlines4b plotbd +NEWSYM FxOp4C1284bzd ; PLOT 4bit, zero check + dither + plotlines4b plotbzd + +NEWSYM FxOp4C1282b ; PLOT 2bit + plotlines2b plotb +NEWSYM FxOp4C1282bz ; PLOT 2bit, zero check + plotlines2b plotbz +NEWSYM FxOp4C1282bd ; PLOT 2bit, dither + plotlines2b plotbd +NEWSYM FxOp4C1282bzd ; PLOT 2bit, zero check + dither + plotlines2b plotbzd + +NEWSYM FxOp4C1288b ; PLOT 8bit + plotlines8b plotb +NEWSYM FxOp4C1288bz ; PLOT 8bit, zero check + plotlines8b plotbz +NEWSYM FxOp4C1288bd ; PLOT 8bit, dither + plotlines8b plotbd +NEWSYM FxOp4C1288bzd ; PLOT 8bit, zero check + dither + plotlines8b plotbzd + +NEWSYM FxOp4C1288bl ; PLOT 8bit + plotlines8bl plotb +NEWSYM FxOp4C1288bzl ; PLOT 8bit, zero check + plotlines8bl plotbz +NEWSYM FxOp4C1288bdl ; PLOT 8bit, dither + plotlines8bl plotbd +NEWSYM FxOp4C1288bzdl ; PLOT 8bit, zero check + dither + plotlines8bl plotbzd + +NEWSYM FxOp4C ; PLOT plot pixel with R1,R2 as x,y and the color register as the color + jmp FxOp4C1284b + FETCHPIPE + inc ebp + CLRFLAGS + mov ebx,[SfxR2] + mov bh,[SfxR1] + mov eax,[sfxclineloc] + mov ebx,[eax+ebx*4] + cmp ebx,0FFFFFFFFh + je near .nodraw + xor eax,eax + ; bits 5/2 : 00 = 128 pixels, 01 = 160 pixels, 10 = 192 pixels, 11 = obj + ; bits 1/0 : 00 = 4 color, 01 = 16-color, 10 = not used, 11 = 256 color + ; 192 pixels = 24 tiles, 160 pixels = 20 tiles, 128 pixels = 16 tiles + ; 16+8(4/3) 16+4(4/2) 16(4/0) + push ecx + mov al,[SfxSCMR] + and al,00000011b ; 4 + 32 + cmp al,0 + je near .colors4 + cmp al,3 + je near .colors256 + + shl ebx,5 ; x32 (16 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + mov bh,bl + xor bh,0FFh + pop ecx + test byte[SfxPOR],01h + jnz .nozerocheck_16 + test byte[SfxCOLR],0Fh + jz .nodraw +.nozerocheck_16 + mov dl,[SfxCOLR] + test byte[SfxPOR],02h + jz .nodither4b + mov dh,[SfxR1] + xor dh,[SfxR2] + test dh,01h + jz .nodither4b + shr dh,4 +.nodither4b + and byte[eax],bh + and byte[eax+1],bh + and byte[eax+16],bh + and byte[eax+17],bh + test dl,01h + jz .nodraw_16 + or byte[eax], bl +.nodraw_16 + test dl,02h + jz .nodraw2_16 + or byte[eax+1], bl +.nodraw2_16 + test dl,04h + jz .nodraw3_16 + or byte[eax+16],bl +.nodraw3_16 + test dl,08h + jz .nodraw4_16 + or byte[eax+17],bl +.nodraw4_16 +.nodraw + inc word [SfxR1] + ret + +.colors4 + shl ebx,4 ; x16 (4 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + mov bh,bl + xor bh,0FFh + pop ecx + test byte[SfxPOR],01h + jnz .nozerocheck_4 + test byte[SfxCOLR],03h + jz .noplot_4 +.nozerocheck_4 + mov dl,[SfxCOLR] + test byte[SfxPOR],02h + jz .nodither2b + mov dh,[SfxR1] + xor dh,[SfxR2] + test dh,01h + jz .nodither2b + shr dh,4 +.nodither2b + and byte[eax],bh + and byte[eax+1],bh + test dl,01h + jz .nodraw_4 + or byte[eax], bl +.nodraw_4 + test dl,02h + jz .nodraw2_4 + or byte[eax+1], bl +.nodraw2_4 +.noplot_4 + inc word [SfxR1] + ret + +.colors256 + shl ebx,6 ; x64 (256 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + mov bh,bl + xor bh,0FFh + pop ecx + test byte[SfxPOR],01h + jnz .nozerocheck_256 + mov dl,0FFh + test byte[SfxPOR],08h + jz .nozerocheckb_256 + mov dl,0Fh +.nozerocheckb_256 + test byte[SfxCOLR],dl + jz .noplot_256 +.nozerocheck_256 + mov dl,[SfxCOLR] + and byte[eax],bh + and byte[eax+1],bh + and byte[eax+16],bh + and byte[eax+17],bh + and byte[eax+32],bh + and byte[eax+33],bh + and byte[eax+48],bh + and byte[eax+49],bh + test dl,01h + jz .nodraw_256 + or byte[eax], bl +.nodraw_256 + test dl,02h + jz .nodraw2_256 + or byte[eax+1], bl +.nodraw2_256 + test dl,04h + jz .nodraw3_256 + or byte[eax+16],bl +.nodraw3_256 + test dl,08h + jz .nodraw4_256 + or byte[eax+17],bl +.nodraw4_256 + test dl,10h + jz .nodraw5_256 + or byte[eax+32], bl +.nodraw5_256 + test dl,20h + jz .nodraw6_256 + or byte[eax+33], bl +.nodraw6_256 + test dl,40h + jz .nodraw7_256 + or byte[eax+48],bl +.nodraw7_256 + test dl,80h + jz .nodraw8_256 + or byte[eax+49],bl +.nodraw8_256 +.noplot_256 + inc word [SfxR1] + ret + +SECTION .bss +.prevx resw 1 +.prevy resw 1 + +sfxwarning resb 1 + +SECTION .text + +NEWSYM FxOp4CA1 ; RPIX read color of the pixel with R1,R2 as x,y + FETCHPIPE + mov ebx,[SfxR2] + mov bh,[SfxR1] + test byte[SfxPOR],10h + jnz .objmode + mov al,[SfxSCMR] + and al,00100100b ; 4 + 32 + cmp al,4 + je .lines160 + cmp al,32 + je .lines192 + cmp al,36 + je .objmode + mov eax,[sfx128lineloc] + jmp .donelines +.lines160 + mov eax,[sfx160lineloc] + jmp .donelines +.lines192 + mov eax,[sfx192lineloc] + jmp .donelines +.objmode + mov eax,[sfxobjlineloc] +.donelines + mov ebx,[eax+ebx*4] + cmp ebx,0FFFFFFFFh + je near .nodraw + xor eax,eax + ; bits 5/2 : 00 = 128 pixels, 01 = 160 pixels, 10 = 192 pixels, 11 = obj + ; bits 1/0 : 00 = 4 color, 01 = 16-color, 10 = not used, 11 = 256 color + ; 192 pixels = 24 tiles, 160 pixels = 20 tiles, 128 pixels = 16 tiles + ; 16+8(4/3) 16+4(4/2) 16(4/0) + push ecx + mov al,[SfxSCMR] + and al,00000011b ; 4 + 32 + + cmp al,0 + je near .colors4 + cmp al,3 + je near .colors256 + + shl ebx,5 ; x32 (16 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + pop ecx + xor bh,bh + test byte[eax],bl + jz .nodraw_16 + or bh,01h +.nodraw_16 + test byte[eax+1],bl + jz .nodraw2_16 + or bh,02h +.nodraw2_16 + test byte[eax+16],bl + jz .nodraw3_16 + or bh,04h +.nodraw3_16 + test byte[eax+17],bl + jz .nodraw4_16 + or bh,08h +.nodraw4_16 +.nodraw + mov bl,bh + and ebx,0FFh + inc ebp +; UpdateR14 + CLRFLAGS + mov [edi],ebx ; Write Destination + mov [flagnz],ebx + ret + +.colors4 + shl ebx,4 ; x16 (4 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + mov bh,bl + xor bh,0FFh + pop ecx + xor bh,bh + test byte[eax],bl + jz .nodraw_4 + or bh,01h +.nodraw_4 + test byte[eax+1],bl + jz .nodraw2_4 + or bh,02h +.nodraw2_4 + mov bl,bh + and ebx,0FFh + inc ebp +; UpdateR14 + CLRFLAGS + mov [edi],ebx ; Write Destination + mov [flagnz],ebx + ret + +.colors256 + shl ebx,6 ; x64 (256 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + mov bh,bl + xor bh,0FFh + pop ecx + xor bh,bh + test byte[eax],bl + jz .nodraw_256 + or bh,01h +.nodraw_256 + test byte[eax+1],bl + jz .nodraw2_256 + or bh,02h +.nodraw2_256 + test byte[eax+16],bl + jz .nodraw3_256 + or bh,04h +.nodraw3_256 + test byte[eax+17],bl + jz .nodraw4_256 + or bh,08h +.nodraw4_256 + test byte[eax+32],bl + jz .nodraw5_256 + or bh,10h +.nodraw5_256 + test byte[eax+33],bl + jz .nodraw6_256 + or bh,20h +.nodraw6_256 + test byte[eax+48],bl + jz .nodraw7_256 + or bh,40h +.nodraw7_256 + test byte[eax+49],bl + jz .nodraw8_256 + or bh,80h +.nodraw8_256 + mov bl,bh + and ebx,0FFh + inc ebp +; UpdateR14 + CLRFLAGS + mov [edi],ebx ; Write Destination + mov [flagnz],ebx + ret + +NEWSYM FxOp4D ; SWAP swap upper and lower byte of a register ; V + mov eax,[esi] ; Read Source + FETCHPIPE + ror ax,8 + inc ebp ; Increase program counter + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret + +NEWSYM FxOp4E ; COLOR copy source register to color register ; V + FETCHPIPE + mov eax,[esi] ; Read Source + ; if bit 3 of SfxPOR is set, then don't modify the upper 4 bits + test byte[SfxPOR],04h + jz .nohighnibble + mov bl,al + shr bl,4 + and al,0F0h + or al,bl +.nohighnibble + test byte[SfxPOR],08h + jnz .preserveupper + cmp [SfxCOLR],al + je .nocolchange + mov [SfxCOLR],al + and eax,0FFh + mov ebx,[fxbit01+eax*4] + mov [fxbit01pcal],ebx + mov ebx,[fxbit23+eax*4] + mov [fxbit23pcal],ebx + mov ebx,[fxbit45+eax*4] + mov [fxbit45pcal],ebx + mov ebx,[fxbit67+eax*4] + mov [fxbit67pcal],ebx +.nocolchange + CLRFLAGS + inc ebp ; Increase program counter + ret +.preserveupper + mov bl,[SfxCOLR] + and al,0Fh + and bl,0F0h + or al,bl + cmp [SfxCOLR],al + je .nocolchange + mov [SfxCOLR],al + and eax,0FFh + mov ebx,[fxbit01+eax*4] + mov [fxbit01pcal],ebx + mov ebx,[fxbit23+eax*4] + mov [fxbit23pcal],ebx + mov ebx,[fxbit45+eax*4] + mov [fxbit45pcal],ebx + mov ebx,[fxbit67+eax*4] + mov [fxbit67pcal],ebx + CLRFLAGS + inc ebp ; Increase program counter + ret + +NEWSYM FxOp4EA1 ; CMODE set plot option register ; V + FETCHPIPE + mov eax,[esi] ; Read Source + inc ebp ; Increase program counter + mov dword [SfxPOR],eax + + test byte[SfxPOR],10h + jnz .objmode + mov al,[SfxSCMR] + and al,00100100b ; 4 + 32 + cmp al,4 + je .lines160 + cmp al,32 + je .lines192 + cmp al,36 + je .objmode + mov eax,[sfx128lineloc] + jmp .donelines +.lines160 + mov eax,[sfx160lineloc] + jmp .donelines +.lines192 + mov eax,[sfx192lineloc] + jmp .donelines +.objmode + mov eax,[sfxobjlineloc] +.donelines + mov [sfxclineloc],eax + + + push ebx + mov al,[SfxSCMR] + and eax,00000011b + mov bl,[SfxPOR] + and bl,0Fh + shl bl,2 + or al,bl + mov ebx,[PLOTJmpb+eax*4] + mov eax,[PLOTJmpa+eax*4] + mov dword [FxTable+4Ch*4],eax + mov dword [FxTableb+4Ch*4],eax + mov dword [FxTablec+4Ch*4],eax + mov dword [FxTabled+4Ch*4],ebx + pop ebx + + CLRFLAGS + ret + +NEWSYM FxOp4F ; NOT perform exclusive exor with 1 on all bits ; V + mov eax,[esi] ; Read Source + FETCHPIPE + xor eax,0FFFFh + inc ebp ; Increase program counter + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret + +NEWSYM FxOp50 ; ADD RN add, register + register + ADDRN 0 +NEWSYM FxOp51 ; ADD RN add, register + register + ADDRN 1 +NEWSYM FxOp52 ; ADD RN add, register + register + ADDRN 2 +NEWSYM FxOp53 ; ADD RN add, register + register + ADDRN 3 +NEWSYM FxOp54 ; ADD RN add, register + register + ADDRN 4 +NEWSYM FxOp55 ; ADD RN add, register + register + ADDRN 5 +NEWSYM FxOp56 ; ADD RN add, register + register + ADDRN 6 +NEWSYM FxOp57 ; ADD RN add, register + register + ADDRN 7 +NEWSYM FxOp58 ; ADD RN add, register + register + ADDRN 8 +NEWSYM FxOp59 ; ADD RN add, register + register + ADDRN 9 +NEWSYM FxOp5A ; ADD RN add, register + register + ADDRN 10 +NEWSYM FxOp5B ; ADD RN add, register + register + ADDRN 11 +NEWSYM FxOp5C ; ADD RN add, register + register + ADDRN 12 +NEWSYM FxOp5D ; ADD RN add, register + register + ADDRN 13 +NEWSYM FxOp5E ; ADD RN add, register + register + ADDRN 14 +NEWSYM FxOp5F ; ADD RN add, register + register + FETCHPIPE + mov eax, [esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + add ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + ret + +NEWSYM FxOp50A1 ; ADC RN add with carry, register + register + ADCRN 0 +NEWSYM FxOp51A1 ; ADC RN add with carry, register + register + ADCRN 1 +NEWSYM FxOp52A1 ; ADC RN add with carry, register + register + ADCRN 2 +NEWSYM FxOp53A1 ; ADC RN add with carry, register + register + ADCRN 3 +NEWSYM FxOp54A1 ; ADC RN add with carry, register + register + ADCRN 4 +NEWSYM FxOp55A1 ; ADC RN add with carry, register + register + ADCRN 5 +NEWSYM FxOp56A1 ; ADC RN add with carry, register + register + ADCRN 6 +NEWSYM FxOp57A1 ; ADC RN add with carry, register + register + ADCRN 7 +NEWSYM FxOp58A1 ; ADC RN add with carry, register + register + ADCRN 8 +NEWSYM FxOp59A1 ; ADC RN add with carry, register + register + ADCRN 9 +NEWSYM FxOp5AA1 ; ADC RN add with carry, register + register + ADCRN 10 +NEWSYM FxOp5BA1 ; ADC RN add with carry, register + register + ADCRN 11 +NEWSYM FxOp5CA1 ; ADC RN add with carry, register + register + ADCRN 12 +NEWSYM FxOp5DA1 ; ADC RN add with carry, register + register + ADCRN 13 +NEWSYM FxOp5EA1 ; ADC RN add with carry, register + register + ADCRN 14 +NEWSYM FxOp5FA1 ; ADC RN add with carry, register + register + FETCHPIPE + mov eax, [esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + shr byte[SfxCarry],1 + adc ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + ret + +; Weird opcode (FxOp50A2, add 0, wow!) +NEWSYM FxOp50A2 ; ADI RN add, register + immediate + ADIRN 0 +NEWSYM FxOp51A2 ; ADI RN add, register + immediate + ADIRN 1 +NEWSYM FxOp52A2 ; ADI RN add, register + immediate + ADIRN 2 +NEWSYM FxOp53A2 ; ADI RN add, register + immediate + ADIRN 3 +NEWSYM FxOp54A2 ; ADI RN add, register + immediate + ADIRN 4 +NEWSYM FxOp55A2 ; ADI RN add, register + immediate + ADIRN 5 +NEWSYM FxOp56A2 ; ADI RN add, register + immediate + ADIRN 6 +NEWSYM FxOp57A2 ; ADI RN add, register + immediate + ADIRN 7 +NEWSYM FxOp58A2 ; ADI RN add, register + immediate + ADIRN 8 +NEWSYM FxOp59A2 ; ADI RN add, register + immediate + ADIRN 9 +NEWSYM FxOp5AA2 ; ADI RN add, register + immediate + ADIRN 10 +NEWSYM FxOp5BA2 ; ADI RN add, register + immediate + ADIRN 11 +NEWSYM FxOp5CA2 ; ADI RN add, register + immediate + ADIRN 12 +NEWSYM FxOp5DA2 ; ADI RN add, register + immediate + ADIRN 13 +NEWSYM FxOp5EA2 ; ADI RN add, register + immediate + ADIRN 14 +NEWSYM FxOp5FA2 ; ADI RN add, register + immediate + ADIRN 15 + +; Another very useful opcode +NEWSYM FxOp50A3 ; ADCIRN add with carry, register + immediate + ADCIRN 0 +NEWSYM FxOp51A3 ; ADCIRN add with carry, register + immediate + ADCIRN 1 +NEWSYM FxOp52A3 ; ADCIRN add with carry, register + immediate + ADCIRN 2 +NEWSYM FxOp53A3 ; ADCIRN add with carry, register + immediate + ADCIRN 3 +NEWSYM FxOp54A3 ; ADCIRN add with carry, register + immediate + ADCIRN 4 +NEWSYM FxOp55A3 ; ADCIRN add with carry, register + immediate + ADCIRN 5 +NEWSYM FxOp56A3 ; ADCIRN add with carry, register + immediate + ADCIRN 6 +NEWSYM FxOp57A3 ; ADCIRN add with carry, register + immediate + ADCIRN 7 +NEWSYM FxOp58A3 ; ADCIRN add with carry, register + immediate + ADCIRN 8 +NEWSYM FxOp59A3 ; ADCIRN add with carry, register + immediate + ADCIRN 9 +NEWSYM FxOp5AA3 ; ADCIRN add with carry, register + immediate + ADCIRN 10 +NEWSYM FxOp5BA3 ; ADCIRN add with carry, register + immediate + ADCIRN 11 +NEWSYM FxOp5CA3 ; ADCIRN add with carry, register + immediate + ADCIRN 12 +NEWSYM FxOp5DA3 ; ADCIRN add with carry, register + immediate + ADCIRN 13 +NEWSYM FxOp5EA3 ; ADCIRN add with carry, register + immediate + ADCIRN 14 +NEWSYM FxOp5FA3 ; ADCIRN add with carry, register + immediate + ADCIRN 15 + +NEWSYM FxOp60 ; SUBRN subtract, register - register + SUBRN 0 +NEWSYM FxOp61 ; SUBRN subtract, register - register + SUBRN 1 +NEWSYM FxOp62 ; SUBRN subtract, register - register + SUBRN 2 +NEWSYM FxOp63 ; SUBRN subtract, register - register + SUBRN 3 +NEWSYM FxOp64 ; SUBRN subtract, register - register + SUBRN 4 +NEWSYM FxOp65 ; SUBRN subtract, register - register + SUBRN 5 +NEWSYM FxOp66 ; SUBRN subtract, register - register + SUBRN 6 +NEWSYM FxOp67 ; SUBRN subtract, register - register + SUBRN 7 +NEWSYM FxOp68 ; SUBRN subtract, register - register + SUBRN 8 +NEWSYM FxOp69 ; SUBRN subtract, register - register + SUBRN 9 +NEWSYM FxOp6A ; SUBRN subtract, register - register + SUBRN 10 +NEWSYM FxOp6B ; SUBRN subtract, register - register + SUBRN 11 +NEWSYM FxOp6C ; SUBRN subtract, register - register + SUBRN 12 +NEWSYM FxOp6D ; SUBRN subtract, register - register + SUBRN 13 +NEWSYM FxOp6E ; SUBRN subtract, register - register + SUBRN 14 +NEWSYM FxOp6F ; SUBRN subtract, register - register + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + sub ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOp60A1 ; SBCRN subtract with carry, register - register + SBCRN 0 +NEWSYM FxOp61A1 ; SBCRN subtract with carry, register - register + SBCRN 1 +NEWSYM FxOp62A1 ; SBCRN subtract with carry, register - register + SBCRN 2 +NEWSYM FxOp63A1 ; SBCRN subtract with carry, register - register + SBCRN 3 +NEWSYM FxOp64A1 ; SBCRN subtract with carry, register - register + SBCRN 4 +NEWSYM FxOp65A1 ; SBCRN subtract with carry, register - register + SBCRN 5 +NEWSYM FxOp66A1 ; SBCRN subtract with carry, register - register + SBCRN 6 +NEWSYM FxOp67A1 ; SBCRN subtract with carry, register - register + SBCRN 7 +NEWSYM FxOp68A1 ; SBCRN subtract with carry, register - register + SBCRN 8 +NEWSYM FxOp69A1 ; SBCRN subtract with carry, register - register + SBCRN 9 +NEWSYM FxOp6AA1 ; SBCRN subtract with carry, register - register + SBCRN 10 +NEWSYM FxOp6BA1 ; SBCRN subtract with carry, register - register + SBCRN 11 +NEWSYM FxOp6CA1 ; SBCRN subtract with carry, register - register + SBCRN 12 +NEWSYM FxOp6DA1 ; SBCRN subtract with carry, register - register + SBCRN 13 +NEWSYM FxOp6EA1 ; SBCRN subtract with carry, register - register + SBCRN 14 +NEWSYM FxOp6FA1 ; SBCRN subtract with carry, register - register + mov eax,[esi] ; Read Source + mov ebx,ebp + FETCHPIPE + sub ebx,[SfxCPB] + cmp byte[SfxCarry],1 + sbb ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOp60A2 ; SUBIRN subtract, register - immediate + SUBIRN 0 +NEWSYM FxOp61A2 ; SUBIRN subtract, register - immediate + SUBIRN 1 +NEWSYM FxOp62A2 ; SUBIRN subtract, register - immediate + SUBIRN 2 +NEWSYM FxOp63A2 ; SUBIRN subtract, register - immediate + SUBIRN 3 +NEWSYM FxOp64A2 ; SUBIRN subtract, register - immediate + SUBIRN 4 +NEWSYM FxOp65A2 ; SUBIRN subtract, register - immediate + SUBIRN 5 +NEWSYM FxOp66A2 ; SUBIRN subtract, register - immediate + SUBIRN 6 +NEWSYM FxOp67A2 ; SUBIRN subtract, register - immediate + SUBIRN 7 +NEWSYM FxOp68A2 ; SUBIRN subtract, register - immediate + SUBIRN 8 +NEWSYM FxOp69A2 ; SUBIRN subtract, register - immediate + SUBIRN 9 +NEWSYM FxOp6AA2 ; SUBIRN subtract, register - immediate + SUBIRN 10 +NEWSYM FxOp6BA2 ; SUBIRN subtract, register - immediate + SUBIRN 11 +NEWSYM FxOp6CA2 ; SUBIRN subtract, register - immediate + SUBIRN 12 +NEWSYM FxOp6DA2 ; SUBIRN subtract, register - immediate + SUBIRN 13 +NEWSYM FxOp6EA2 ; SUBIRN subtract, register - immediate + SUBIRN 14 +NEWSYM FxOp6FA2 ; SUBIRN subtract, register - immediate + SUBIRN 15 + +NEWSYM FxOp60A3 ; CMPRN compare, register, register + CMPRN 0 +NEWSYM FxOp61A3 ; CMPRN compare, register, register + CMPRN 1 +NEWSYM FxOp62A3 ; CMPRN compare, register, register + CMPRN 2 +NEWSYM FxOp63A3 ; CMPRN compare, register, register + CMPRN 3 +NEWSYM FxOp64A3 ; CMPRN compare, register, register + CMPRN 4 +NEWSYM FxOp65A3 ; CMPRN compare, register, register + CMPRN 5 +NEWSYM FxOp66A3 ; CMPRN compare, register, register + CMPRN 6 +NEWSYM FxOp67A3 ; CMPRN compare, register, register + CMPRN 7 +NEWSYM FxOp68A3 ; CMPRN compare, register, register + CMPRN 8 +NEWSYM FxOp69A3 ; CMPRN compare, register, register + CMPRN 9 +NEWSYM FxOp6AA3 ; CMPRN compare, register, register + CMPRN 10 +NEWSYM FxOp6BA3 ; CMPRN compare, register, register + CMPRN 11 +NEWSYM FxOp6CA3 ; CMPRN compare, register, register + CMPRN 12 +NEWSYM FxOp6DA3 ; CMPRN compare, register, register + CMPRN 13 +NEWSYM FxOp6EA3 ; CMPRN compare, register, register + CMPRN 14 +NEWSYM FxOp6FA3 ; CMPRN compare, register, register + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + sub ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + mov [SfxSignZero],eax + CLRFLAGS + inc ebp ; Increase program counter + ret + +NEWSYM FxOp70 ; MERGE R7 as upper byte, R8 as lower byte (used for texture-mapping) */ + ; V + xor eax,eax + FETCHPIPE + mov ah,byte [SfxR7+1] + mov al,byte [SfxR8+1] + inc ebp + mov [edi],eax ; Write Destination + mov dword[SfxSignZero],0001h + test eax,0F0F0h + jz .nozero + mov dword[SfxSignZero],0000h +.nozero + test eax,08080h + jz .nosign + or dword [SfxSignZero],80000h +.nosign + mov dword [SfxOverflow],1 + test ax,0c0c0h + jnz .Overflow + mov dword [SfxOverflow],0 +.Overflow + mov dword [SfxCarry],1 + test ax,0e0e0h + jnz .Carry + mov dword [SfxCarry],0 +.Carry + CLRFLAGS + ret + +NEWSYM FxOp71 ; AND RN register & register + ANDRN 1 +NEWSYM FxOp72 ; AND RN register & register + ANDRN 2 +NEWSYM FxOp73 ; AND RN register & register + ANDRN 3 +NEWSYM FxOp74 ; AND RN register & register + ANDRN 4 +NEWSYM FxOp75 ; AND RN register & register + ANDRN 5 +NEWSYM FxOp76 ; AND RN register & register + ANDRN 6 +NEWSYM FxOp77 ; AND RN register & register + ANDRN 7 +NEWSYM FxOp78 ; AND RN register & register + ANDRN 8 +NEWSYM FxOp79 ; AND RN register & register + ANDRN 9 +NEWSYM FxOp7A ; AND RN register & register + ANDRN 10 +NEWSYM FxOp7B ; AND RN register & register + ANDRN 11 +NEWSYM FxOp7C ; AND RN register & register + ANDRN 12 +NEWSYM FxOp7D ; AND RN register & register + ANDRN 13 +NEWSYM FxOp7E ; AND RN register & register + ANDRN 14 +NEWSYM FxOp7F ; AND RN register & register + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + and eax,ebx + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret + +NEWSYM FxOp71A1 ; BIC RN register & ~register + BICRN 1 +NEWSYM FxOp72A1 ; BIC RN register & ~register + BICRN 2 +NEWSYM FxOp73A1 ; BIC RN register & ~register + BICRN 3 +NEWSYM FxOp74A1 ; BIC RN register & ~register + BICRN 4 +NEWSYM FxOp75A1 ; BIC RN register & ~register + BICRN 5 +NEWSYM FxOp76A1 ; BIC RN register & ~register + BICRN 6 +NEWSYM FxOp77A1 ; BIC RN register & ~register + BICRN 7 +NEWSYM FxOp78A1 ; BIC RN register & ~register + BICRN 8 +NEWSYM FxOp79A1 ; BIC RN register & ~register + BICRN 9 +NEWSYM FxOp7AA1 ; BIC RN register & ~register + BICRN 10 +NEWSYM FxOp7BA1 ; BIC RN register & ~register + BICRN 11 +NEWSYM FxOp7CA1 ; BIC RN register & ~register + BICRN 12 +NEWSYM FxOp7DA1 ; BIC RN register & ~register + BICRN 13 +NEWSYM FxOp7EA1 ; BIC RN register & ~register + BICRN 14 +NEWSYM FxOp7FA1 ; BIC RN register & ~register + FETCHPIPE + mov ebx,ebp + sub ebx,[SfxCPB] + mov eax,[esi] ; Read Source + xor ebx,0FFFFh + and eax,ebx + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret + +NEWSYM FxOp71A2 ; ANDIRN and #n - register & immediate + ANDIRN 1 +NEWSYM FxOp72A2 ; ANDIRN and #n - register & immediate + ANDIRN 2 +NEWSYM FxOp73A2 ; ANDIRN and #n - register & immediate + ANDIRN 3 +NEWSYM FxOp74A2 ; ANDIRN and #n - register & immediate + ANDIRN 4 +NEWSYM FxOp75A2 ; ANDIRN and #n - register & immediate + ANDIRN 5 +NEWSYM FxOp76A2 ; ANDIRN and #n - register & immediate + ANDIRN 6 +NEWSYM FxOp77A2 ; ANDIRN and #n - register & immediate + ANDIRN 7 +NEWSYM FxOp78A2 ; ANDIRN and #n - register & immediate + ANDIRN 8 +NEWSYM FxOp79A2 ; ANDIRN and #n - register & immediate + ANDIRN 9 +NEWSYM FxOp7AA2 ; ANDIRN and #n - register & immediate + ANDIRN 10 +NEWSYM FxOp7BA2 ; ANDIRN and #n - register & immediate + ANDIRN 11 +NEWSYM FxOp7CA2 ; ANDIRN and #n - register & immediate + ANDIRN 12 +NEWSYM FxOp7DA2 ; ANDIRN and #n - register & immediate + ANDIRN 13 +NEWSYM FxOp7EA2 ; ANDIRN and #n - register & immediate + ANDIRN 14 +NEWSYM FxOp7FA2 ; ANDIRN and #n - register & immediate + ANDIRN 15 + +NEWSYM FxOp71A3 ; BICIRN register & ~immediate + BICIRN 1 ^ 0FFFFh +NEWSYM FxOp72A3 ; BICIRN register & ~immediate + BICIRN 2 ^ 0FFFFh +NEWSYM FxOp73A3 ; BICIRN register & ~immediate + BICIRN 3 ^ 0FFFFh +NEWSYM FxOp74A3 ; BICIRN register & ~immediate + BICIRN 4 ^ 0FFFFh +NEWSYM FxOp75A3 ; BICIRN register & ~immediate + BICIRN 5 ^ 0FFFFh +NEWSYM FxOp76A3 ; BICIRN register & ~immediate + BICIRN 6 ^ 0FFFFh +NEWSYM FxOp77A3 ; BICIRN register & ~immediate + BICIRN 7 ^ 0FFFFh +NEWSYM FxOp78A3 ; BICIRN register & ~immediate + BICIRN 8 ^ 0FFFFh +NEWSYM FxOp79A3 ; BICIRN register & ~immediate + BICIRN 9 ^ 0FFFFh +NEWSYM FxOp7AA3 ; BICIRN register & ~immediate + BICIRN 10 ^ 0FFFFh +NEWSYM FxOp7BA3 ; BICIRN register & ~immediate + BICIRN 11 ^ 0FFFFh +NEWSYM FxOp7CA3 ; BICIRN register & ~immediate + BICIRN 12 ^ 0FFFFh +NEWSYM FxOp7DA3 ; BICIRN register & ~immediate + BICIRN 13 ^ 0FFFFh +NEWSYM FxOp7EA3 ; BICIRN register & ~immediate + BICIRN 14 ^ 0FFFFh +NEWSYM FxOp7FA3 ; BICIRN register & ~immediate + BICIRN 15 ^ 0FFFFh + +NEWSYM FxOp80 ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 0 +NEWSYM FxOp81 ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 1 +NEWSYM FxOp82 ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 2 +NEWSYM FxOp83 ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 3 +NEWSYM FxOp84 ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 4 +NEWSYM FxOp85 ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 5 +NEWSYM FxOp86 ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 6 +NEWSYM FxOp87 ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 7 +NEWSYM FxOp88 ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 8 +NEWSYM FxOp89 ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 9 +NEWSYM FxOp8A ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 10 +NEWSYM FxOp8B ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 11 +NEWSYM FxOp8C ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 12 +NEWSYM FxOp8D ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 13 +NEWSYM FxOp8E ; MULTRN 8 bit to 16 bit signed multiply, register * register + MULTRN 14 +NEWSYM FxOp8F ; MULTRN 8 bit to 16 bit signed multiply, register * register + FETCHPIPE + mov ebx,ebp + mov al,byte [esi] ; Read Source + sub ebx,[SfxCPB] + imul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret + +NEWSYM FxOp80A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 0 +NEWSYM FxOp81A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 1 +NEWSYM FxOp82A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 2 +NEWSYM FxOp83A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 3 +NEWSYM FxOp84A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 4 +NEWSYM FxOp85A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 5 +NEWSYM FxOp86A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 6 +NEWSYM FxOp87A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 7 +NEWSYM FxOp88A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 8 +NEWSYM FxOp89A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 9 +NEWSYM FxOp8AA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 10 +NEWSYM FxOp8BA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 11 +NEWSYM FxOp8CA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 12 +NEWSYM FxOp8DA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 13 +NEWSYM FxOp8EA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRN 14 +NEWSYM FxOp8FA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + FETCHPIPE + mov ebx,ebp + mov al,byte [esi] ; Read Source + sub ebx,[SfxCPB] + mul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret + +NEWSYM FxOp80A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 0 +NEWSYM FxOp81A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 1 +NEWSYM FxOp82A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 2 +NEWSYM FxOp83A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 3 +NEWSYM FxOp84A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 4 +NEWSYM FxOp85A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 5 +NEWSYM FxOp86A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 6 +NEWSYM FxOp87A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 7 +NEWSYM FxOp88A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 8 +NEWSYM FxOp89A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 9 +NEWSYM FxOp8AA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 10 +NEWSYM FxOp8BA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 11 +NEWSYM FxOp8CA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 12 +NEWSYM FxOp8DA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 13 +NEWSYM FxOp8EA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 14 +NEWSYM FxOp8FA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRN 15 + +NEWSYM FxOp80A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 0 +NEWSYM FxOp81A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 1 +NEWSYM FxOp82A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 2 +NEWSYM FxOp83A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 3 +NEWSYM FxOp84A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 4 +NEWSYM FxOp85A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 5 +NEWSYM FxOp86A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 6 +NEWSYM FxOp87A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 7 +NEWSYM FxOp88A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 8 +NEWSYM FxOp89A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 9 +NEWSYM FxOp8AA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 10 +NEWSYM FxOp8BA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 11 +NEWSYM FxOp8CA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 12 +NEWSYM FxOp8DA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 13 +NEWSYM FxOp8EA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 14 +NEWSYM FxOp8FA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRN 15 + +NEWSYM FxOp90 ; SBK store word to last accessed RAM address ; V + mov ebx,[SfxLastRamAdr] ; Load last ram address + mov eax,[esi] ; Read Source + FETCHPIPE + mov [ebx],al ; Store Word + sub ebx,[SfxRAMMem] + xor ebx,1 + add ebx,[SfxRAMMem] + inc ebp ; Increase program counter + mov [ebx],ah ; Store Word + CLRFLAGS + ret + +NEWSYM FxOp91 ; LINK#n R11 = R15 + immediate + LINK 1 +NEWSYM FxOp92 ; LINK#n R11 = R15 + immediate + LINK 2 +NEWSYM FxOp93 ; LINK#n R11 = R15 + immediate + LINK 3 +NEWSYM FxOp94 ; LINK#n R11 = R15 + immediate + LINK 4 + +NEWSYM FxOp95 ; SEX sign extend 8 bit to 16 bit ; V + movsx eax, byte [esi] ; Read Source + FETCHPIPE + and eax,0FFFFh + inc ebp + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOp96 ; ASR aritmethic shift right by one ; V + mov eax,[esi] ; Read Source + FETCHPIPE + mov [SfxCarry],al + and byte[SfxCarry],1 + sar ax,1 ; logic shift right + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov dword [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOp96A1 ; DIV2 aritmethic shift right by one ; V + mov eax,[esi] ; Read Source + FETCHPIPE + cmp ax,-1 + je .minusone + mov [SfxCarry],al + and byte[SfxCarry],1 + sar ax,1 ; logic shift right + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov dword [SfxSignZero],eax + CLRFLAGS + ret +.minusone + mov byte[SfxCarry],1 + xor eax,eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov dword [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOp97 ; ROR rotate right by one ; V + FETCHPIPE + mov eax,[esi] ; Read Source + shr byte[SfxCarry],1 + rcr ax,1 + setc byte[SfxCarry] + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOp98 ; JMPRN jump to address of register + JMPRN 8 +NEWSYM FxOp99 ; JMPRN jump to address of register + JMPRN 9 +NEWSYM FxOp9A ; JMPRN jump to address of register + JMPRN 10 +NEWSYM FxOp9B ; JMPRN jump to address of register + JMPRN 11 +NEWSYM FxOp9C ; JMPRN jump to address of register + JMPRN 12 +NEWSYM FxOp9D ; JMPRN jump to address of register + JMPRN 13 + +NEWSYM FxOp98A1 ; LJMPRN set program bank to source register and jump to address of register + LJMPRN 8 +NEWSYM FxOp99A1 ; LJMPRN set program bank to source register and jump to address of register + LJMPRN 9 +NEWSYM FxOp9AA1 ; LJMPRN set program bank to source register and jump to address of register + LJMPRN 10 +NEWSYM FxOp9BA1 ; LJMPRN set program bank to source register and jump to address of register + LJMPRN 11 +NEWSYM FxOp9CA1 ; LJMPRN set program bank to source register and jump to address of register + LJMPRN 12 +NEWSYM FxOp9DA1 ; LJMPRN set program bank to source register and jump to address of register + LJMPRN 13 + +NEWSYM FxOp9E ; LOB set upper byte to zero (keep low byte) ; V + mov eax,[esi] ; Read Source + FETCHPIPE + and eax,0FFh + inc ebp + mov [edi],eax ; Write Destination + shl eax,8 + mov dword [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOp9F ; FMULT 16 bit to 32 bit signed multiplication, upper 16 bits only + ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR6] + FETCHPIPE + imul bx + inc ebp + and edx,0FFFFh + mov [SfxSignZero],edx + mov [edi],edx ; Write Destination + shr ax,15 + mov [SfxCarry],al + CLRFLAGS + ret + +NEWSYM FxOp9FA1 ; LMULT 16 bit to 32 bit signed multiplication ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR6] + FETCHPIPE + imul bx + and edx,0FFFFh + inc ebp + mov [edi],edx ; Write Destination + mov [SfxR4],ax + mov [SfxSignZero],edx + shr ax,15 + mov [SfxCarry],al + CLRFLAGS + ret + +NEWSYM FxOpA0 ; IBTRN,#PP immediate byte transfer + IBTRN 0 +NEWSYM FxOpA1 ; IBTRN,#PP immediate byte transfer + IBTRN 1 +NEWSYM FxOpA2 ; IBTRN,#PP immediate byte transfer + IBTRN 2 +NEWSYM FxOpA3 ; IBTRN,#PP immediate byte transfer + IBTRN 3 +NEWSYM FxOpA4 ; IBTRN,#PP immediate byte transfer + IBTRN 4 +NEWSYM FxOpA5 ; IBTRN,#PP immediate byte transfer + IBTRN 5 +NEWSYM FxOpA6 ; IBTRN,#PP immediate byte transfer + IBTRN 6 +NEWSYM FxOpA7 ; IBTRN,#PP immediate byte transfer + IBTRN 7 +NEWSYM FxOpA8 ; IBTRN,#PP immediate byte transfer + IBTRN 8 +NEWSYM FxOpA9 ; IBTRN,#PP immediate byte transfer + IBTRN 9 +NEWSYM FxOpAA ; IBTRN,#PP immediate byte transfer + IBTRN 10 +NEWSYM FxOpAB ; IBTRN,#PP immediate byte transfer + IBTRN 11 +NEWSYM FxOpAC ; IBTRN,#PP immediate byte transfer + IBTRN 12 +NEWSYM FxOpAD ; IBTRN,#PP immediate byte transfer + IBTRN 13 +NEWSYM FxOpAE ; IBTRN,#PP immediate byte transfer + movsx eax,byte[ebp] + mov cl,[ebp+1] + add ebp,2 + mov [SfxR0+14*4],ax + UpdateR14 + CLRFLAGS + ret +NEWSYM FxOpAF ; IBTRN,#PP immediate byte transfer + movsx eax,byte[ebp] + mov cl,[ebp+1] + and eax,0FFFFh + mov ebp,[SfxCPB] + add ebp,eax + CLRFLAGS + ret + +NEWSYM FxOpA0A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 0 +NEWSYM FxOpA1A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 1 +NEWSYM FxOpA2A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 2 +NEWSYM FxOpA3A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 3 +NEWSYM FxOpA4A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 4 +NEWSYM FxOpA5A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 5 +NEWSYM FxOpA6A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 6 +NEWSYM FxOpA7A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 7 +NEWSYM FxOpA8A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 8 +NEWSYM FxOpA9A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 9 +NEWSYM FxOpAAA1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 10 +NEWSYM FxOpABA1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 11 +NEWSYM FxOpACA1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 12 +NEWSYM FxOpADA1 ; LMS rn,(yy) load word from RAM (short address) + LMSRN 13 +NEWSYM FxOpAEA1 ; LMS rn,(yy) load word from RAM (short address) + xor eax,eax + mov al,[ebp] + add eax,eax + inc ebp + add eax,[SfxRAMMem] + mov cl,[ebp] + mov dword [SfxLastRamAdr],eax + mov ebx,[eax] ; Read word from ram + inc ebp + mov [SfxR0+14*4],bx ; Write data + UpdateR14 + CLRFLAGS + ret +NEWSYM FxOpAFA1 ; LMS rn,(yy) load word from RAM (short address) + xor eax,eax + mov al,[ebp] + add eax,eax + inc ebp + add eax,[SfxRAMMem] + mov cl,[ebp] + mov dword [SfxLastRamAdr],eax + mov ebx,[eax] ; Read word from ram + and ebx,0FFFFh + mov ebp,[SfxCPB] + add ebp,ebx + CLRFLAGS + ret + +NEWSYM FxOpA0A2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 0 +NEWSYM FxOpA1A2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 1 +NEWSYM FxOpA2A2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 2 +NEWSYM FxOpA3A2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 3 +NEWSYM FxOpA4A2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 4 +NEWSYM FxOpA5A2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 5 +NEWSYM FxOpA6A2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 6 +NEWSYM FxOpA7A2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 7 +NEWSYM FxOpA8A2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 8 +NEWSYM FxOpA9A2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 9 +NEWSYM FxOpAAA2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 10 +NEWSYM FxOpABA2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 11 +NEWSYM FxOpACA2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 12 +NEWSYM FxOpADA2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 13 +NEWSYM FxOpAEA2 ; SMS (yy),rn store word in RAM (short address) + SMSRN 14 +NEWSYM FxOpAFA2 ; SMS (yy),rn store word in RAM (short address) + xor eax,eax + mov ebx,ebp + sub ebx,[SfxCPB] + mov al,[ebp] + inc ebp + add eax,eax + FETCHPIPE + add eax,[SfxRAMMem] + mov dword [SfxLastRamAdr],eax + inc ebp + mov [eax],bx ; Write word to ram + CLRFLAGS + ret + +NEWSYM FxOpB0 ; FROM rn set source register + FROMRN 0 +NEWSYM FxOpB1 ; FROM rn set source register + FROMRN 1 +NEWSYM FxOpB2 ; FROM rn set source register + FROMRN 2 +NEWSYM FxOpB3 ; FROM rn set source register + FROMRN 3 +NEWSYM FxOpB4 ; FROM rn set source register + FROMRN 4 +NEWSYM FxOpB5 ; FROM rn set source register + FROMRN 5 +NEWSYM FxOpB6 ; FROM rn set source register + FROMRN 6 +NEWSYM FxOpB7 ; FROM rn set source register + FROMRN 7 +NEWSYM FxOpB8 ; FROM rn set source register + FROMRN 8 +NEWSYM FxOpB9 ; FROM rn set source register + FROMRN 9 +NEWSYM FxOpBA ; FROM rn set source register + FROMRN 10 +NEWSYM FxOpBB ; FROM rn set source register + FROMRN 11 +NEWSYM FxOpBC ; FROM rn set source register + FROMRN 12 +NEWSYM FxOpBD ; FROM rn set source register + FROMRN 13 +NEWSYM FxOpBE ; FROM rn set source register + FROMRN 14 +NEWSYM FxOpBF ; FROM rn set source register + FETCHPIPE + mov esi,SfxR0+15*4 + inc ebp ; Increase program counter + mov eax,ebp + sub eax,[SfxCPB] + mov [SfxR15],eax + call [FxTableb+ecx*4] + mov esi,SfxR0 + ret + +NEWSYM FxOpC0 ; HIB move high-byte to low-byte ; V + mov eax,[esi] ; Read Source + FETCHPIPE + and eax,0FF00h + mov dword [SfxSignZero],eax + shr eax,8 + inc ebp + mov [edi],eax + CLRFLAGS + ret + +NEWSYM FxOpC1 ; OR rn or rn + ORRN 1 +NEWSYM FxOpC2 ; OR rn or rn + ORRN 2 +NEWSYM FxOpC3 ; OR rn or rn + ORRN 3 +NEWSYM FxOpC4 ; OR rn or rn + ORRN 4 +NEWSYM FxOpC5 ; OR rn or rn + ORRN 5 +NEWSYM FxOpC6 ; OR rn or rn + ORRN 6 +NEWSYM FxOpC7 ; OR rn or rn + ORRN 7 +NEWSYM FxOpC8 ; OR rn or rn + ORRN 8 +NEWSYM FxOpC9 ; OR rn or rn + ORRN 9 +NEWSYM FxOpCA ; OR rn or rn + ORRN 10 +NEWSYM FxOpCB ; OR rn or rn + ORRN 11 +NEWSYM FxOpCC ; OR rn or rn + ORRN 12 +NEWSYM FxOpCD ; OR rn or rn + ORRN 13 +NEWSYM FxOpCE ; OR rn or rn + ORRN 14 +NEWSYM FxOpCF ; OR rn or rn + mov eax,[esi] ; Read Source + mov ebx,ebp + FETCHPIPE + sub ebx,[SfxCPB] + or eax,ebx + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOpC1A1 ; XOR rn xor rn + XORRN 1 +NEWSYM FxOpC2A1 ; XOR rn xor rn + XORRN 2 +NEWSYM FxOpC3A1 ; XOR rn xor rn + XORRN 3 +NEWSYM FxOpC4A1 ; XOR rn xor rn + XORRN 4 +NEWSYM FxOpC5A1 ; XOR rn xor rn + XORRN 5 +NEWSYM FxOpC6A1 ; XOR rn xor rn + XORRN 6 +NEWSYM FxOpC7A1 ; XOR rn xor rn + XORRN 7 +NEWSYM FxOpC8A1 ; XOR rn xor rn + XORRN 8 +NEWSYM FxOpC9A1 ; XOR rn xor rn + XORRN 9 +NEWSYM FxOpCAA1 ; XOR rn xor rn + XORRN 10 +NEWSYM FxOpCBA1 ; XOR rn xor rn + XORRN 11 +NEWSYM FxOpCCA1 ; XOR rn xor rn + XORRN 12 +NEWSYM FxOpCDA1 ; XOR rn xor rn + XORRN 13 +NEWSYM FxOpCEA1 ; XOR rn xor rn + XORRN 14 +NEWSYM FxOpCFA1 ; XOR rn xor rn + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + xor eax,ebx + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + ret + +NEWSYM FxOpC1A2 ; OR #n OR #n + ORI 1 +NEWSYM FxOpC2A2 ; OR #n OR #n + ORI 2 +NEWSYM FxOpC3A2 ; OR #n OR #n + ORI 3 +NEWSYM FxOpC4A2 ; OR #n OR #n + ORI 4 +NEWSYM FxOpC5A2 ; OR #n OR #n + ORI 5 +NEWSYM FxOpC6A2 ; OR #n OR #n + ORI 6 +NEWSYM FxOpC7A2 ; OR #n OR #n + ORI 7 +NEWSYM FxOpC8A2 ; OR #n OR #n + ORI 8 +NEWSYM FxOpC9A2 ; OR #n OR #n + ORI 9 +NEWSYM FxOpCAA2 ; OR #n OR #n + ORI 10 +NEWSYM FxOpCBA2 ; OR #n OR #n + ORI 11 +NEWSYM FxOpCCA2 ; OR #n OR #n + ORI 12 +NEWSYM FxOpCDA2 ; OR #n OR #n + ORI 13 +NEWSYM FxOpCEA2 ; OR #n OR #n + ORI 14 +NEWSYM FxOpCFA2 ; OR #n OR #n + ORI 15 + +NEWSYM FxOpC1A3 ; XOR #n xor #n + XORI 1 +NEWSYM FxOpC2A3 ; XOR #n xor #n + XORI 2 +NEWSYM FxOpC3A3 ; XOR #n xor #n + XORI 3 +NEWSYM FxOpC4A3 ; XOR #n xor #n + XORI 4 +NEWSYM FxOpC5A3 ; XOR #n xor #n + XORI 5 +NEWSYM FxOpC6A3 ; XOR #n xor #n + XORI 6 +NEWSYM FxOpC7A3 ; XOR #n xor #n + XORI 7 +NEWSYM FxOpC8A3 ; XOR #n xor #n + XORI 8 +NEWSYM FxOpC9A3 ; XOR #n xor #n + XORI 9 +NEWSYM FxOpCAA3 ; XOR #n xor #n + XORI 10 +NEWSYM FxOpCBA3 ; XOR #n xor #n + XORI 11 +NEWSYM FxOpCCA3 ; XOR #n xor #n + XORI 12 +NEWSYM FxOpCDA3 ; XOR #n xor #n + XORI 13 +NEWSYM FxOpCEA3 ; XOR #n xor #n + XORI 14 +NEWSYM FxOpCFA3 ; XOR #n xor #n + XORI 15 + +NEWSYM FxOpD0 ; INC rn increase by one + INCRN 0 +NEWSYM FxOpD1 ; INC rn increase by one + INCRN 1 +NEWSYM FxOpD2 ; INC rn increase by one + INCRN 2 +NEWSYM FxOpD3 ; INC rn increase by one + INCRN 3 +NEWSYM FxOpD4 ; INC rn increase by one + INCRN 4 +NEWSYM FxOpD5 ; INC rn increase by one + INCRN 5 +NEWSYM FxOpD6 ; INC rn increase by one + INCRN 6 +NEWSYM FxOpD7 ; INC rn increase by one + INCRN 7 +NEWSYM FxOpD8 ; INC rn increase by one + INCRN 8 +NEWSYM FxOpD9 ; INC rn increase by one + INCRN 9 +NEWSYM FxOpDA ; INC rn increase by one + INCRN 10 +NEWSYM FxOpDB ; INC rn increase by one + INCRN 11 +NEWSYM FxOpDC ; INC rn increase by one + INCRN 12 +NEWSYM FxOpDD ; INC rn increase by one + INCRN 13 +NEWSYM FxOpDE ; INC rn increase by one + FETCHPIPE + mov eax,[SfxR0+14*4] ; Read Source + inc ax + mov [SfxR0+14*4],eax + mov [SfxSignZero],eax + CLRFLAGS + inc ebp + UpdateR14 + ret + +NEWSYM FxOpDF ; GETC transfer ROM buffer to color register + mov eax,[SfxRomBuffer] + FETCHPIPE + mov eax,[eax] + test byte[SfxPOR],04h + jz .nohighnibble + mov bl,al + shr bl,4 + and al,0F0h + or al,bl +.nohighnibble + test byte[SfxPOR],08h + jnz .preserveupper + cmp [SfxCOLR],al + je .nocolchange + mov [SfxCOLR],al + and eax,0FFh + mov ebx,[fxbit01+eax*4] + mov [fxbit01pcal],ebx + mov ebx,[fxbit23+eax*4] + mov [fxbit23pcal],ebx + mov ebx,[fxbit45+eax*4] + mov [fxbit45pcal],ebx + mov ebx,[fxbit67+eax*4] + mov [fxbit67pcal],ebx +.nocolchange + CLRFLAGS + inc ebp ; Increase program counter + ret +.preserveupper + mov bl,[SfxCOLR] + and al,0Fh + and bl,0F0h + or al,bl + cmp [SfxCOLR],al + je .nocolchange + mov [SfxCOLR],al + and eax,0FFh + mov ebx,[fxbit01+eax*4] + mov [fxbit01pcal],ebx + mov ebx,[fxbit23+eax*4] + mov [fxbit23pcal],ebx + mov ebx,[fxbit45+eax*4] + mov [fxbit45pcal],ebx + mov ebx,[fxbit67+eax*4] + mov [fxbit67pcal],ebx + CLRFLAGS + inc ebp ; Increase program counter + ret + +NEWSYM FxOpDFA2 ; RAMB set current RAM bank ; Verified + mov eax,[esi] ; Read Source + mov ebx,[SfxnRamBanks] + FETCHPIPE + dec ebx + and eax,ebx + mov dword [SfxRAMBR],eax + shl eax,16 + add eax,[sfxramdata] + mov dword [SfxRAMMem],eax + CLRFLAGS + inc ebp + ret + +NEWSYM FxOpDFA3 ; ROMB set current ROM bank ; Verified + mov eax,[esi] ; Read Source + and eax,07Fh + FETCHPIPE + mov dword [SfxROMBR],eax + mov eax,[SfxMemTable+eax*4] + mov [SfxCROM],eax + CLRFLAGS + inc ebp + ret + +NEWSYM FxOpE0 ; DEC rn decrement by one + DECRN 0 +NEWSYM FxOpE1 ; DEC rn decrement by one + DECRN 1 +NEWSYM FxOpE2 ; DEC rn decrement by one + DECRN 2 +NEWSYM FxOpE3 ; DEC rn decrement by one + DECRN 3 +NEWSYM FxOpE4 ; DEC rn decrement by one + DECRN 4 +NEWSYM FxOpE5 ; DEC rn decrement by one + DECRN 5 +NEWSYM FxOpE6 ; DEC rn decrement by one + DECRN 6 +NEWSYM FxOpE7 ; DEC rn decrement by one + DECRN 7 +NEWSYM FxOpE8 ; DEC rn decrement by one + DECRN 8 +NEWSYM FxOpE9 ; DEC rn decrement by one + DECRN 9 +NEWSYM FxOpEA ; DEC rn decrement by one + DECRN 10 +NEWSYM FxOpEB ; DEC rn decrement by one + DECRN 11 +NEWSYM FxOpEC ; DEC rn decrement by one + DECRN 12 +NEWSYM FxOpED ; DEC rn decrement by one + DECRN 13 +NEWSYM FxOpEE ; DEC rn decrement by one + dec word[SfxR0+14*4] + FETCHPIPE + mov eax,[SfxR0+14*4] ; Read Source + mov [SfxSignZero],eax + UpdateR14 + CLRFLAGS + inc ebp + ret + +NEWSYM FxOpEF ; getb get byte from ROM at address R14 ; V + FETCHPIPE + mov eax,[SfxRomBuffer] + inc ebp + mov eax,[eax] + and eax,0FFh +; cmp edi,SfxR15 +; je .nor15 + mov [edi],eax ; Write DREG + CLRFLAGS + ret +.nor15 +; mov eax,ebp +; sub eax,[SfxCPB] +; mov [SfxR15],al + or eax,8000h + mov [edi],eax ; Write DREG + CLRFLAGS + ret + +NEWSYM FxOpEFA1 ; getbh get high-byte from ROM at address R14 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxRomBuffer] + and eax,0FFh + FETCHPIPE + mov ah,[ebx] + inc ebp + mov [edi],eax ; Write DREG + CLRFLAGS + ret + +NEWSYM FxOpEFA2 ; getbl get low-byte from ROM at address R14 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxRomBuffer] + and eax,0FF00h + FETCHPIPE + mov al,[ebx] + inc ebp + mov [edi],eax ; Write DREG + CLRFLAGS + ret + +NEWSYM FxOpEFA3 ; getbs get sign extended byte from ROM at address R14 ; V + mov ebx,[SfxRomBuffer] + FETCHPIPE + movsx eax,byte[ebx] + inc ebp + mov [edi],ax ; Write DREG + CLRFLAGS + ret + +NEWSYM FxOpF0 ; IWT RN,#xx immediate word transfer to register + IWTRN 0 +NEWSYM FxOpF1 ; IWT RN,#xx immediate word transfer to register + IWTRN 1 +NEWSYM FxOpF2 ; IWT RN,#xx immediate word transfer to register + IWTRN 2 +NEWSYM FxOpF3 ; IWT RN,#xx immediate word transfer to register + IWTRN 3 +NEWSYM FxOpF4 ; IWT RN,#xx immediate word transfer to register + IWTRN 4 +NEWSYM FxOpF5 ; IWT RN,#xx immediate word transfer to register + IWTRN 5 +NEWSYM FxOpF6 ; IWT RN,#xx immediate word transfer to register + IWTRN 6 +NEWSYM FxOpF7 ; IWT RN,#xx immediate word transfer to register + IWTRN 7 +NEWSYM FxOpF8 ; IWT RN,#xx immediate word transfer to register + IWTRN 8 +NEWSYM FxOpF9 ; IWT RN,#xx immediate word transfer to register + IWTRN 9 +NEWSYM FxOpFA ; IWT RN,#xx immediate word transfer to register + IWTRN 10 +NEWSYM FxOpFB ; IWT RN,#xx immediate word transfer to register + IWTRN 11 +NEWSYM FxOpFC ; IWT RN,#xx immediate word transfer to register + IWTRN 12 +NEWSYM FxOpFD ; IWT RN,#xx immediate word transfer to register + IWTRN 13 +NEWSYM FxOpFE ; IWT RN,#xx immediate word transfer to register + mov eax,[ebp] + mov cl,[ebp+2] + and eax,0FFFFh + add ebp,3 + mov [SfxR0+14*4],eax + UpdateR14 + CLRFLAGS + ret +NEWSYM FxOpFF ; IWT RN,#xx immediate word transfer to register + mov eax,[ebp] + mov cl,[ebp+2] + and eax,0FFFFh + mov ebp,[SfxCPB] + add ebp,eax + CLRFLAGS + ret + +NEWSYM FxOpF0A1 ; LM RN,(XX) load word from RAM + LMRN 0 +NEWSYM FxOpF1A1 ; LM RN,(XX) load word from RAM + LMRN 1 +NEWSYM FxOpF2A1 ; LM RN,(XX) load word from RAM + LMRN 2 +NEWSYM FxOpF3A1 ; LM RN,(XX) load word from RAM + LMRN 3 +NEWSYM FxOpF4A1 ; LM RN,(XX) load word from RAM + LMRN 4 +NEWSYM FxOpF5A1 ; LM RN,(XX) load word from RAM + LMRN 5 +NEWSYM FxOpF6A1 ; LM RN,(XX) load word from RAM + LMRN 6 +NEWSYM FxOpF7A1 ; LM RN,(XX) load word from RAM + LMRN 7 +NEWSYM FxOpF8A1 ; LM RN,(XX) load word from RAM + LMRN 8 +NEWSYM FxOpF9A1 ; LM RN,(XX) load word from RAM + LMRN 9 +NEWSYM FxOpFAA1 ; LM RN,(XX) load word from RAM + LMRN 10 +NEWSYM FxOpFBA1 ; LM RN,(XX) load word from RAM + LMRN 11 +NEWSYM FxOpFCA1 ; LM RN,(XX) load word from RAM + LMRN 12 +NEWSYM FxOpFDA1 ; LM RN,(XX) load word from RAM + LMRN 13 +NEWSYM FxOpFEA1 ; LM RN,(XX) load word from RAM + xor eax,eax + mov cl,[ebp+2] + mov ax,[ebp] + mov ebx,[SfxRAMMem] + mov [SfxLastRamAdr],eax + add [SfxLastRamAdr],ebx + mov dl,[eax+ebx] + xor eax,1 + add ebp,3 + mov dh,[eax+ebx] + mov word [SfxR0+14*4],dx ; Store Word + UpdateR14 + CLRFLAGS + ret +NEWSYM FxOpFFA1 ; LM RN,(XX) load word from RAM + FETCHPIPE + mov eax,ecx + inc ebp + FETCHPIPE + inc ebp + mov ah,cl + FETCHPIPE + mov ebx,[SfxRAMMem] + mov [SfxLastRamAdr],eax + add [SfxLastRamAdr],ebx + mov dl,[eax+ebx] + xor eax,1 + mov dh,[eax+ebx] + and edx,0FFFFh + mov ebp,[SfxCPB] + add ebp,edx + CLRFLAGS + ret + +NEWSYM FxOpF0A2 ; SM (XX),RN store word in RAM + SMRN 0 +NEWSYM FxOpF1A2 ; SM (XX),RN store word in RAM + SMRN 1 +NEWSYM FxOpF2A2 ; SM (XX),RN store word in RAM + SMRN 2 +NEWSYM FxOpF3A2 ; SM (XX),RN store word in RAM + SMRN 3 +NEWSYM FxOpF4A2 ; SM (XX),RN store word in RAM + SMRN 4 +NEWSYM FxOpF5A2 ; SM (XX),RN store word in RAM + SMRN 5 +NEWSYM FxOpF6A2 ; SM (XX),RN store word in RAM + SMRN 6 +NEWSYM FxOpF7A2 ; SM (XX),RN store word in RAM + SMRN 7 +NEWSYM FxOpF8A2 ; SM (XX),RN store word in RAM + SMRN 8 +NEWSYM FxOpF9A2 ; SM (XX),RN store word in RAM + SMRN 9 +NEWSYM FxOpFAA2 ; SM (XX),RN store word in RAM + SMRN 10 +NEWSYM FxOpFBA2 ; SM (XX),RN store word in RAM + SMRN 11 +NEWSYM FxOpFCA2 ; SM (XX),RN store word in RAM + SMRN 12 +NEWSYM FxOpFDA2 ; SM (XX),RN store word in RAM + SMRN 13 +NEWSYM FxOpFEA2 ; SM (XX),RN store word in RAM + SMRN 14 +NEWSYM FxOpFFA2 ; SM (XX),RN store word in RAM + FETCHPIPE + mov ebx,ebp + sub ebx,[SfxCPB] + mov eax,ecx + inc ebp + FETCHPIPE + inc ebp + mov ah,cl + FETCHPIPE + mov dx,bx + mov ebx,[SfxRAMMem] + mov [SfxLastRamAdr],eax + add [SfxLastRamAdr],ebx + mov [eax+ebx],dl + xor eax,1 + inc ebp + mov [eax+ebx],dh + CLRFLAGS + ret + +SECTION .bss ;ALIGN=32 + +NEWSYM NumberOfOpcodes, resd 1 ; Number of opcodes to execute +NEWSYM NumberOfOpcodesBU, resd 1 ; Number of opcodes to execute backup value +NEWSYM sfxwarningb, resb 1 + +SECTION .text + +NEWSYM MainLoop + mov eax,[SfxPBR] + and eax,0FFh +; mov byte[fxtrace+eax],1 + mov ebp,[SfxCPB] + add ebp,[SfxR15] + xor ecx,ecx + mov cl,[SfxPIPE] + mov ch,[SfxSFR+1] + and ch,03h + ; pack esi/edi + PackEsiEdi + jmp [FxTabled+ecx*4] + jmp .LoopAgain +ALIGN16 +.LoopAgain + call [FxTable+ecx*4] + dec dword [NumberOfOpcodes] + jnz .LoopAgain +.EndLoop +NEWSYM FXEndLoop + sub ebp,[SfxCPB] + mov [SfxR15],ebp + mov [SfxPIPE],cl + and byte[SfxSFR+1],0FFh-03h + or [SfxSFR+1],ch + UnPackEsiEdi + ret + +SECTION .data +NEWSYM fxtrace, db 0; times 65536 db 0 +SECTION .text + +NEWSYM FxEmu2AsmEnd diff --git a/i386/fxemu2.mac b/i386/fxemu2.mac new file mode 100644 index 00000000..9ec7671b --- /dev/null +++ b/i386/fxemu2.mac @@ -0,0 +1,834 @@ +;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com ) +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;as published by the Free Software Foundation; either +;version 2 of the License, or (at your option) any later +;version. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + + + + + + + + +%macro FETCHPIPE 0 +; mov edx,[SfxPBR] +; mov edx,[SfxMemTable+edx*4] +; mov edx,[SfxCPB] +; mov edx,[SfxR15] + mov cl,[ebp] +%endmacro + +%macro UpdateR14 0 +; mov edx,[SfxROMBR] +; mov edx,[SfxMemTable+edx*4] + mov eax,[SfxCROM] +; and dword[SfxR14],0FFFFh + add eax,[SfxR14] + mov [SfxRomBuffer],eax +%endmacro + +%macro UpdateR15 0 + mov ebp,[SfxCPB] + add ebp,[SfxR15] +%endmacro + +%macro CLRFLAGS 0 + ;and dword [SfxSFR],0FFFFh-0100h-0200h-1000h ; Clear ALT1,ALT2 and B Flags +; xor ch,ch +; mov dword [SfxB],0 ; Clear B Flag +; mov esi,SfxR0 +; mov edi,SfxR0 +%endmacro + +%macro TORN 1 ; V + FETCHPIPE + mov edi, SfxR0+%1*4 + inc ebp ; Increase program counter + call [FxTable+ecx*4] + mov edi,SfxR0 + ret +%endmacro + +%macro WITH 1 ; Verified. + FETCHPIPE + mov esi,SfxR0+%1*4 + mov edi,SfxR0+%1*4 + mov dword [SfxB],1 + inc ebp ; Increase program counter + call [FxTablec+ecx*4] + mov esi,SfxR0 + mov edi,SfxR0 + mov dword [SfxB],0 ; Clear B Flag + ret +%endmacro + +%macro STWRN 1 ; V + mov eax,[SfxR0+%1*4] ; Read register + mov ebx,[SfxRAMMem] + mov dword [SfxLastRamAdr],eax ; Save last ram address + add dword [SfxLastRamAdr],ebx ; Save last ram address + mov edx,[esi] ; Read Source + FETCHPIPE + mov [ebx+eax],dl ; Store Word + xor eax,1 + inc ebp ; Increase program counter + mov [ebx+eax],dh ; Store Word + CLRFLAGS + ret +%endmacro + +%macro STBRN 1 ; V + mov eax,[SfxR0+%1*4] ; Read register + FETCHPIPE + add eax,[SfxRAMMem] + mov dword [SfxLastRamAdr],eax ; Save last ram address + mov ebx,[esi] ; Read Source + mov byte [eax],bl ; Store Byte + CLRFLAGS + inc ebp ; Increase program counter + ret +%endmacro + +%macro LDWRN 1 ; V + mov eax,[SfxR0+%1*4] ; Read register + mov ebx,[SfxRAMMem] + mov dword [SfxLastRamAdr],eax ; Save last ram address + FETCHPIPE + mov dl,[ebx+eax] ; Store Word + add dword [SfxLastRamAdr],ebx ; Save last ram address + xor eax,1 + and edx,0FFFFh + inc ebp ; Increase program counter + mov dh,[ebx+eax] ; Store Word + mov [edi],edx ; Read Source + CLRFLAGS + ret +%endmacro + +%macro LDBRN 1 ; V + mov eax,[SfxR0+%1*4] ; Read register + FETCHPIPE + add eax,[SfxRAMMem] + xor ebx,ebx + mov dword [SfxLastRamAdr],eax ; Save last ram address + mov bl,[eax] ; Read Byte + inc ebp ; Increase program counter + mov [edi],ebx ; Store Result + CLRFLAGS + ret +%endmacro + +; test byte[SfxPOR],01h +; jnz .nozerocheck +; test byte[SfxPOR],02h +; jz .nodither + +; **** Can pre-calculate [SfxSCBR] << 10 + [sfxramdata] +; Pre-calculate fxbit values from color register + +%macro drawpix4b 0 + and [eax],edx + and [eax+16],edx + xor edx,0FFFFFFFFh + mov ebx,[fxbit01pcal] + and ebx,edx + or [eax], ebx + and edx,[fxbit23pcal] + or [eax+16], edx +%endmacro + +%macro drawpix4bd 0 + and [eax],edx + and [eax+16],edx + xor edx,0FFFFFFFFh + mov ebx,[fxbit45pcal] + and ebx,edx + or [eax], ebx + and edx,[fxbit67pcal] + or [eax+16], edx +%endmacro + +%macro drawpix2b 0 + and [eax],edx + xor edx,0FFFFFFFFh + and edx,[fxbit01pcal] + or [eax], edx +%endmacro + +%macro drawpix2bd 0 + and [eax],edx + xor edx,0FFFFFFFFh + and edx,[fxbit45pcal] + or [eax], edx +%endmacro + +%macro drawpix8b 0 + and [eax],edx + and [eax+16],edx + and [eax+32],edx + and [eax+48],edx + xor edx,0FFFFFFFFh + mov ebx,[fxbit01pcal] + and ebx,edx + or [eax], ebx + mov ebx,[fxbit23pcal] + and ebx,edx + or [eax+16], ebx + mov ebx,[fxbit45pcal] + and ebx,edx + or [eax+32], ebx + and edx,[fxbit67pcal] + or [eax+48], edx +%endmacro + +%macro drawpix8bd 0 + and [eax],edx + and [eax+16],edx + and [eax+32],edx + and [eax+48],edx + xor edx,0FFFFFFFFh + mov ebx,[fxbit45pcal] + and ebx,edx + or [eax], ebx + mov ebx,[fxbit67pcal] + and ebx,edx + or [eax+16], ebx + mov ebx,[fxbit01pcal] + and ebx,edx + or [eax+32], ebx + and edx,[fxbit23pcal] + or [eax+48], edx +%endmacro + +%macro plotb 5 + shl eax,%3 + and ebx,07h + add ebx,ebx + add eax,ebx + add eax,[SCBRrel] + mov bl,[SfxR1] + mov edx,[fxxand+ebx*4] + %2 +%endmacro + +%macro plotbz 5 + shl eax,%3 + and ebx,07h + add ebx,ebx + add eax,ebx + add eax,[SCBRrel] + mov bl,[SfxR1] + mov edx,[fxxand+ebx*4] + test byte[SfxCOLR],%5 + jz .nodraw + %2 +%endmacro + +%macro plotbd 5 + shl eax,%3 + and ebx,07h + add ebx,ebx + add eax,ebx + add eax,[SCBRrel] + mov bl,[SfxR1] + mov edx,[fxxand+ebx*4] + mov bl,[SfxR1] + xor bl,[SfxR2] + test bl,01h + jz near .nodither4b + %4 + inc word [SfxR1] + %1 +.nodither4b + %2 +%endmacro + +%macro plotbzd 5 + shl eax,%3 + and ebx,07h + add ebx,ebx + add eax,ebx + add eax,[SCBRrel] + mov bl,[SfxR1] + mov edx,[fxxand+ebx*4] + test byte[SfxCOLR],%5 + jz near .nodraw + mov bl,[SfxR1] + xor bl,[SfxR2] + test bl,01h + jz .nodither4b + %4 + inc word [SfxR1] + %1 +.nodither4b + %2 +%endmacro + +%macro plotlines4b 1 + mov ebx,[SfxR2] + FETCHPIPE + mov bh,[SfxR1] + mov eax,[sfxclineloc] + inc ebp + mov eax,[eax+ebx*4] + cmp eax,0FFFFFFFFh + je near .nodraw + %1 ret, drawpix4b, 5, drawpix4bd, 0Fh +.nodraw + inc word [SfxR1] + ret +%endmacro + +%macro plotlines4bb 1 + mov ebx,[SfxR2] + FETCHPIPE + mov bh,[SfxR1] + mov eax,[sfxclineloc] + inc ebp + mov eax,[eax+ebx*4] + cmp eax,0FFFFFFFFh + je near .nodraw + %1 FXReturn, drawpix4b, 5, drawpix4bd, 0Fh +.nodraw + inc word [SfxR1] + FXReturn +%endmacro + +%macro plotlines2b 1 + mov ebx,[SfxR2] + FETCHPIPE + mov bh,[SfxR1] + mov eax,[sfxclineloc] + inc ebp + mov eax,[eax+ebx*4] + cmp eax,0FFFFFFFFh + je near .nodraw + %1 ret, drawpix2b, 4, drawpix2bd, 03h +.nodraw + inc word [SfxR1] + ret +%endmacro + +%macro plotlines2bb 1 + mov ebx,[SfxR2] + FETCHPIPE + mov bh,[SfxR1] + mov eax,[sfxclineloc] + inc ebp + mov eax,[eax+ebx*4] + cmp eax,0FFFFFFFFh + je near .nodraw + %1 FXReturn, drawpix2b, 4, drawpix2bd, 03h +.nodraw + inc word [SfxR1] + FXReturn +%endmacro + +%macro plotlines8b 1 + mov ebx,[SfxR2] + FETCHPIPE + mov bh,[SfxR1] + mov eax,[sfxclineloc] + inc ebp + mov eax,[eax+ebx*4] + cmp eax,0FFFFFFFFh + je near .nodraw + %1 ret, drawpix8b, 6, drawpix8bd, 0FFh +.nodraw + inc word [SfxR1] + ret +%endmacro + +%macro plotlines8bb 1 + mov ebx,[SfxR2] + FETCHPIPE + mov bh,[SfxR1] + mov eax,[sfxclineloc] + inc ebp + mov eax,[eax+ebx*4] + cmp eax,0FFFFFFFFh + je near .nodraw + %1 FXReturn, drawpix8b, 6, drawpix8bd, 0FFh +.nodraw + inc word [SfxR1] + FXReturn +%endmacro + +%macro plotlines8bl 1 + mov ebx,[SfxR2] + FETCHPIPE + mov bh,[SfxR1] + mov eax,[sfxclineloc] + inc ebp + mov eax,[eax+ebx*4] + cmp eax,0FFFFFFFFh + je near .nodraw + %1 ret, drawpix8b, 6, drawpix8bd, 0Fh +.nodraw + inc word [SfxR1] + ret +%endmacro + +%macro plotlines8bbl 1 + mov ebx,[SfxR2] + FETCHPIPE + mov bh,[SfxR1] + mov eax,[sfxclineloc] + inc ebp + mov eax,[eax+ebx*4] + cmp eax,0FFFFFFFFh + je near .nodraw + %1 FXReturn, drawpix8b, 6, drawpix8bd, 0Fh +.nodraw + inc word [SfxR1] + FXReturn +%endmacro + +%macro ADDRN 1 ; V + mov eax, [esi] ; Read Source + mov ebx, [SfxR0+%1*4] + FETCHPIPE + add ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro ADCRN 1 ; V + FETCHPIPE + mov eax, [esi] ; Read Source + mov ebx, [SfxR0+%1*4] + shr byte[SfxCarry],1 + adc ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro ADIRN 1 ; V + mov eax, [esi] ; Read Source + FETCHPIPE + add ax,%1 + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro ADCIRN 1 ; V + FETCHPIPE + mov eax, [esi] ; Read Source + shr byte[SfxCarry],1 + adc ax,%1 + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro SUBRN 1 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] + FETCHPIPE + sub ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + ret +%endmacro + +%macro SBCRN 1 ; V + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] + cmp byte[SfxCarry],1 + sbb ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + ret +%endmacro + +%macro SUBIRN 1 ; V + mov eax,[esi] ; Read Source + FETCHPIPE + sub ax,%1 + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + ret +%endmacro + +%macro CMPRN 1 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] + FETCHPIPE + sub ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + mov [SfxSignZero],eax + CLRFLAGS + inc ebp ; Increase program counter + ret +%endmacro + +%macro ANDRN 1 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] ; Read RN + FETCHPIPE + and eax,ebx + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro BICRN 1 ; V + mov ebx,[SfxR0+%1*4] ; Read RN + mov eax,[esi] ; Read Source + xor ebx,0FFFFh + FETCHPIPE + and eax,ebx + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro ANDIRN 1 ; V + mov eax,[esi] ; Read Source + FETCHPIPE + and eax,%1 + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro BICIRN 1 ; V + mov eax,[esi] ; Read Source + FETCHPIPE + and eax,%1 + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro MULTRN 1 ; V + mov al,byte [esi] ; Read Source + mov bl,byte [SfxR0+%1*4] ; Read RN + FETCHPIPE + imul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro UMULTRN 1 ; V + mov al,byte [esi] ; Read Source + mov bl,byte [SfxR0+%1*4] ; Read RN + FETCHPIPE + mul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro MULTIRN 1 ; V + mov al,byte [esi] ; Read Source + mov bl,%1 ; Read RN + FETCHPIPE + imul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro UMULTIRN 1 ; V + mov al,byte [esi] ; Read Source + mov bl,%1 ; Read RN + FETCHPIPE + mul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + ret +%endmacro + +%macro LINK 1 ; Verified. + mov eax,ebp + sub eax,[SfxCPB] + add eax,%1 + FETCHPIPE + mov word [SfxR11],ax + CLRFLAGS + inc ebp + ret +%endmacro + +%macro JMPRN 1 ; V + FETCHPIPE + mov eax,[SfxR0+%1*4] ; Read RN + mov ebp,[SfxCPB] + add ebp,eax + CLRFLAGS + ret +%endmacro + +%macro LJMPRN 1 ; V + FETCHPIPE + mov eax,[SfxR0+%1*4] + and eax,07Fh + mov byte[SfxPBR],al +; mov byte[fxtrace+eax],1 + mov eax,[SfxMemTable+eax*4] + mov [SfxCPB],eax + mov ebp,eax + add ebp,[esi] ; Read RN + mov dword [SfxCacheActive],0 + push ecx + call FxOp02 + pop ecx + dec ebp + ret +%endmacro + +%macro IBTRN 1 ; V + movsx eax,byte[ebp] + mov cl,[ebp+1] + add ebp,2 + mov [SfxR0+%1*4],ax + CLRFLAGS + ret +%endmacro + +%macro LMSRN 1 ; Verified. + xor eax,eax + mov al,[ebp] + add eax,eax + inc ebp + add eax,[SfxRAMMem] + mov cl,[ebp] + mov dword [SfxLastRamAdr],eax + mov ebx,[eax] ; Read word from ram + inc ebp + mov [SfxR0+%1*4],bx ; Write data + CLRFLAGS + ret +%endmacro + +%macro SMSRN 1 ; Verified. + xor eax,eax + mov al,[ebp] + inc ebp + add eax,eax + mov cl,[ebp] + add eax,[SfxRAMMem] + mov ebx,[SfxR0+%1*4] ; Read data + mov dword [SfxLastRamAdr],eax + inc ebp + mov [eax],bx ; Write word to ram + CLRFLAGS + ret +%endmacro + +%macro FROMRN 1 ; V + FETCHPIPE + mov esi,SfxR0+%1*4 + inc ebp ; Increase program counter + call [FxTable+ecx*4] + mov esi,SfxR0 + ret +%endmacro + +%macro ORRN 1 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] ; Read + FETCHPIPE + or eax,ebx + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + ret +%endmacro + +%macro XORRN 1 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] ; Read + FETCHPIPE + xor eax,ebx + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + ret +%endmacro + +%macro ORI 1 ; V + mov eax,[esi] ; Read Source + FETCHPIPE + or eax,%1 + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + ret +%endmacro + +%macro XORI 1 ; V + mov eax,[esi] ; Read Source + FETCHPIPE + xor eax,%1 + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + ret +%endmacro + +%macro INCRN 1 ; Verified + inc word[SfxR0+%1*4] + FETCHPIPE + mov eax,[SfxR0+%1*4] ; Read Source + mov [SfxSignZero],eax + CLRFLAGS + inc ebp + ret +%endmacro + +%macro DECRN 1 ; Verified + dec word[SfxR0+%1*4] + FETCHPIPE + mov eax,[SfxR0+%1*4] ; Read Source + mov [SfxR0+%1*4],eax + mov [SfxSignZero],eax + CLRFLAGS + inc ebp + ret +%endmacro + +%macro IWTRN 1 ; aka LEA ; Verified. + mov eax,[ebp] + mov cl,[ebp+2] + and eax,0FFFFh + add ebp,3 + mov [SfxR0+%1*4],eax + CLRFLAGS + ret +%endmacro + +%macro LMRN 1 ; Verified! + xor eax,eax + mov cl,[ebp+2] + mov ax,[ebp] + mov ebx,[SfxRAMMem] + mov [SfxLastRamAdr],eax + add [SfxLastRamAdr],ebx + mov dl,[eax+ebx] + xor eax,1 + add ebp,3 + mov dh,[eax+ebx] + mov word [SfxR0+%1*4],dx ; Store Word + CLRFLAGS + ret +%endmacro + +%macro SMRN 1 ; Verified + mov ebx,[SfxR0+%1*4] + mov eax,[ebp] + mov cl,[ebp+2] + and eax,0FFFFh + mov dx,bx + mov ebx,[SfxRAMMem] + mov [SfxLastRamAdr],eax + add [SfxLastRamAdr],ebx + mov [eax+ebx],dl + xor eax,1 + add ebp,3 + mov [eax+ebx],dh + CLRFLAGS + ret +%endmacro + +%macro PackEsiEdi 0 + mov eax,[SfxSREG] + shl eax,2 + add eax,SfxR0 + mov esi,eax + mov eax,[SfxDREG] + shl eax,2 + add eax,SfxR0 + mov edi,eax + mov eax,[SfxRAMBR] + shl eax,16 + add eax,[sfxramdata] + mov dword [SfxRAMMem],eax +%endmacro + +%macro UnPackEsiEdi 0 + mov eax,esi + sub eax,SfxR0 + shr eax,2 + mov [SfxSREG],eax + mov eax,edi + sub eax,SfxR0 + shr eax,2 + mov [SfxDREG],eax +%endmacro diff --git a/i386/fxemu2b.asm b/i386/fxemu2b.asm new file mode 100644 index 00000000..a3234d83 --- /dev/null +++ b/i386/fxemu2b.asm @@ -0,0 +1,617 @@ +;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com ) +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;as published by the Free Software Foundation; either +;version 2 of the License, or (at your option) any later +;version. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +%include "macros.mac" + +EXTSYM FxTable,FxTableb,FxTablec,SfxB,SfxCPB,SfxCROM,SfxCarry,SfxOverflow +EXTSYM SfxR0,SfxR14,SfxR15,SfxRomBuffer,SfxSignZero,withr15sk + +NEWSYM FxEmu2BAsmStart + +%include "fxemu2.mac" +%include "fxemu2b.mac" + + + + + + +NEWSYM FxOpb05 ; BRA branch always ; Verified. + movsx eax,byte[ebp] + mov cl,[ebp+1] + inc ebp + add ebp,eax + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb06 ; BGE branch on greater or equals ; Verified. + movsx eax,byte[ebp] + mov ebx,[SfxSignZero] + shr ebx,15 + inc ebp + xor bl,[SfxOverflow] + mov cl,[ebp] + test bl,01h + jnz .nojump + add ebp,eax + call [FxTableb+ecx*4] + ret +.nojump + inc ebp + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb07 ; BLT branch on lesss than ; Verified. + movsx eax,byte[ebp] + mov ebx,[SfxSignZero] + shr ebx,15 + inc ebp + xor bl,[SfxOverflow] + mov cl,[ebp] + test bl,01h + jz .nojump + add ebp,eax + call [FxTableb+ecx*4] + ret +.nojump + inc ebp + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb08 ; BNE branch on not equal ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],0FFFFh + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTableb+ecx*4] + ret +.nojump + inc ebp + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb09 ; BEQ branch on equal (z=1) ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],0FFFFh + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTableb+ecx*4] + ret +.nojump + inc ebp + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb0A ; BPL branch on plus ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],088000h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTableb+ecx*4] + ret +.nojump + inc ebp + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb0B ; BMI branch on minus ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],088000h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTableb+ecx*4] + ret +.nojump + inc ebp + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb0C ; BCC branch on carry clear ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxCarry],01h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTableb+ecx*4] + ret +.nojump + inc ebp + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb0D ; BCS branch on carry set ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxCarry],01h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTableb+ecx*4] + ret +.nojump + inc ebp + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb0E ; BVC branch on overflow clear ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxOverflow],01h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTableb+ecx*4] + ret +.nojump + inc ebp + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb0F ; BVS branch on overflow set ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxOverflow],01h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTableb+ecx*4] + ret +.nojump + inc ebp + call [FxTableb+ecx*4] + ret + +NEWSYM FxOpb10 ; TO RN set register n as destination register + TORNb 0 +NEWSYM FxOpb11 ; TO RN set register n as destination register + TORNb 1 +NEWSYM FxOpb12 ; TO RN set register n as destination register + TORNb 2 +NEWSYM FxOpb13 ; TO RN set register n as destination register + TORNb 3 +NEWSYM FxOpb14 ; TO RN set register n as destination register + TORNb 4 +NEWSYM FxOpb15 ; TO RN set register n as destination register + TORNb 5 +NEWSYM FxOpb16 ; TO RN set register n as destination register + TORNb 6 +NEWSYM FxOpb17 ; TO RN set register n as destination register + TORNb 7 +NEWSYM FxOpb18 ; TO RN set register n as destination register + TORNb 8 +NEWSYM FxOpb19 ; TO RN set register n as destination register + TORNb 9 +NEWSYM FxOpb1A ; TO RN set register n as destination register + TORNb 10 +NEWSYM FxOpb1B ; TO RN set register n as destination register + TORNb 11 +NEWSYM FxOpb1C ; TO RN set register n as destination register + TORNb 12 +NEWSYM FxOpb1D ; TO RN set register n as destination register + TORNb 13 +NEWSYM FxOpb1E ; TO RN set register n as destination register + FETCHPIPE + test dword [SfxB],1 + jnz .VersionB + mov edi,SfxR0+14*4 + inc ebp + mov eax,ebp + sub eax,[SfxCPB] + mov dword[withr15sk],1 + mov [SfxR15],eax + call [FxTableb+ecx*4] + mov edi,SfxR0 + UpdateR14 + ret +.VersionB + mov eax,[esi] ; Read Source + mov dword[withr15sk],1 + mov [SfxR0+14*4],eax ; Write + CLRFLAGS + UpdateR14 + inc ebp ; Increase program counter + ret +NEWSYM FxOpb1F ; TO RN set register n as destination register + FETCHPIPE + test dword [SfxB],1 + jnz .VersionB + mov edi,SfxR0+15*4 + inc ebp + mov eax,ebp + sub eax,[SfxCPB] + mov [SfxR15],eax + call [FxTableb+ecx*4] + mov ebp,[SfxCPB] + mov dword[withr15sk],1 + add ebp,[SfxR15] + mov edi,SfxR0 + ret +.VersionB + mov eax,[esi] ; Read Source + mov ebp,[SfxCPB] + mov dword[withr15sk],1 + add ebp,eax + CLRFLAGS + ret + +NEWSYM FxOpb3D ; ALT1 set alt1 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,01h + inc ebp + mov eax,ebp + sub eax,[SfxCPB] + mov [SfxR15],eax + call [FxTableb+ecx*4] + xor ch,ch + ret + +NEWSYM FxOpb3E ; ALT2 set alt1 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,02h + inc ebp + mov eax,ebp + sub eax,[SfxCPB] + mov [SfxR15],eax + call [FxTable+ecx*4] + xor ch,ch + ret + +NEWSYM FxOpb3F ; ALT3 set alt3 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,03h + inc ebp + mov eax,ebp + sub eax,[SfxCPB] + mov [SfxR15],eax + call [FxTable+ecx*4] + xor ch,ch + ret + +NEWSYM FxOpbB0 ; FROM rn set source register + FROMRNb 0 +NEWSYM FxOpbB1 ; FROM rn set source register + FROMRNb 1 +NEWSYM FxOpbB2 ; FROM rn set source register + FROMRNb 2 +NEWSYM FxOpbB3 ; FROM rn set source register + FROMRNb 3 +NEWSYM FxOpbB4 ; FROM rn set source register + FROMRNb 4 +NEWSYM FxOpbB5 ; FROM rn set source register + FROMRNb 5 +NEWSYM FxOpbB6 ; FROM rn set source register + FROMRNb 6 +NEWSYM FxOpbB7 ; FROM rn set source register + FROMRNb 7 +NEWSYM FxOpbB8 ; FROM rn set source register + FROMRNb 8 +NEWSYM FxOpbB9 ; FROM rn set source register + FROMRNb 9 +NEWSYM FxOpbBA ; FROM rn set source register + FROMRNb 10 +NEWSYM FxOpbBB ; FROM rn set source register + FROMRNb 11 +NEWSYM FxOpbBC ; FROM rn set source register + FROMRNb 12 +NEWSYM FxOpbBD ; FROM rn set source register + FROMRNb 13 +NEWSYM FxOpbBE ; FROM rn set source register + FROMRNb 14 +NEWSYM FxOpbBF ; FROM rn set source register + test dword [SfxB],1 + jnz .VersionB + mov esi,SfxR0+15*4 + inc ebp ; Increase program counter + mov eax,ebp + sub eax,[SfxCPB] + mov [SfxR15],eax + call [FxTableb+ecx*4] + mov esi,SfxR0 + ret +.VersionB + FETCHPIPE + mov eax,ebp + sub eax,[SfxCPB] + inc ebp + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + shr al,7 + mov byte[SfxOverflow],al + CLRFLAGS + ret + +NEWSYM FxOpc05 ; BRA branch always ; Verified. + movsx eax,byte[ebp] + mov cl,[ebp+1] + inc ebp + add ebp,eax + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc06 ; BGE branch on greater or equals ; Verified. + movsx eax,byte[ebp] + mov ebx,[SfxSignZero] + shr ebx,15 + inc ebp + xor bl,[SfxOverflow] + mov cl,[ebp] + test bl,01h + jnz .nojump + add ebp,eax + call [FxTablec+ecx*4] + ret +.nojump + inc ebp + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc07 ; BLT branch on lesss than ; Verified. + movsx eax,byte[ebp] + mov ebx,[SfxSignZero] + shr ebx,15 + inc ebp + xor bl,[SfxOverflow] + mov cl,[ebp] + test bl,01h + jz .nojump + add ebp,eax + call [FxTablec+ecx*4] + ret +.nojump + inc ebp + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc08 ; BNE branch on not equal ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],0FFFFh + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTablec+ecx*4] + ret +.nojump + inc ebp + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc09 ; BEQ branch on equal (z=1) ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],0FFFFh + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTablec+ecx*4] + ret +.nojump + inc ebp + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc0A ; BPL branch on plus ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],088000h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTablec+ecx*4] + ret +.nojump + inc ebp + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc0B ; BMI branch on minus ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],088000h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTablec+ecx*4] + ret +.nojump + inc ebp + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc0C ; BCC branch on carry clear ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxCarry],01h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTablec+ecx*4] + ret +.nojump + inc ebp + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc0D ; BCS branch on carry set ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxCarry],01h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTablec+ecx*4] + ret +.nojump + inc ebp + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc0E ; BVC branch on overflow clear ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxOverflow],01h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTablec+ecx*4] + ret +.nojump + inc ebp + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc0F ; BVS branch on overflow set ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxOverflow],01h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTablec+ecx*4] + ret +.nojump + inc ebp + call [FxTablec+ecx*4] + ret + +NEWSYM FxOpc10 ; TO RN set register n as destination register + TORNc 0 +NEWSYM FxOpc11 ; TO RN set register n as destination register + TORNc 1 +NEWSYM FxOpc12 ; TO RN set register n as destination register + TORNc 2 +NEWSYM FxOpc13 ; TO RN set register n as destination register + TORNc 3 +NEWSYM FxOpc14 ; TO RN set register n as destination register + TORNc 4 +NEWSYM FxOpc15 ; TO RN set register n as destination register + TORNc 5 +NEWSYM FxOpc16 ; TO RN set register n as destination register + TORNc 6 +NEWSYM FxOpc17 ; TO RN set register n as destination register + TORNc 7 +NEWSYM FxOpc18 ; TO RN set register n as destination register + TORNc 8 +NEWSYM FxOpc19 ; TO RN set register n as destination register + TORNc 9 +NEWSYM FxOpc1A ; TO RN set register n as destination register + TORNc 10 +NEWSYM FxOpc1B ; TO RN set register n as destination register + TORNc 11 +NEWSYM FxOpc1C ; TO RN set register n as destination register + TORNc 12 +NEWSYM FxOpc1D ; TO RN set register n as destination register + TORNc 13 +NEWSYM FxOpc1E ; TO RN set register n as destination register + FETCHPIPE + mov eax,[esi] ; Read Source + mov [SfxR0+14*4],eax ; Write + CLRFLAGS + UpdateR14 + inc ebp ; Increase program counter + ret +NEWSYM FxOpc1F ; TO RN set register n as destination register + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebp,[SfxCPB] + mov [SfxR15],eax + add ebp,eax + CLRFLAGS + ret + +NEWSYM FxOpc3D ; ALT1 set alt1 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,01h + inc ebp + call [FxTablec+ecx*4] + xor ch,ch + ret + +NEWSYM FxOpc3E ; ALT2 set alt1 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,02h + inc ebp + call [FxTablec+ecx*4] + xor ch,ch + ret + +NEWSYM FxOpc3F ; ALT3 set alt3 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,03h + inc ebp + call [FxTablec+ecx*4] + xor ch,ch + ret + +NEWSYM FxOpcB0 ; FROM rn set source register + FROMRNc 0 +NEWSYM FxOpcB1 ; FROM rn set source register + FROMRNc 1 +NEWSYM FxOpcB2 ; FROM rn set source register + FROMRNc 2 +NEWSYM FxOpcB3 ; FROM rn set source register + FROMRNc 3 +NEWSYM FxOpcB4 ; FROM rn set source register + FROMRNc 4 +NEWSYM FxOpcB5 ; FROM rn set source register + FROMRNc 5 +NEWSYM FxOpcB6 ; FROM rn set source register + FROMRNc 6 +NEWSYM FxOpcB7 ; FROM rn set source register + FROMRNc 7 +NEWSYM FxOpcB8 ; FROM rn set source register + FROMRNc 8 +NEWSYM FxOpcB9 ; FROM rn set source register + FROMRNc 9 +NEWSYM FxOpcBA ; FROM rn set source register + FROMRNc 10 +NEWSYM FxOpcBB ; FROM rn set source register + FROMRNc 11 +NEWSYM FxOpcBC ; FROM rn set source register + FROMRNc 12 +NEWSYM FxOpcBD ; FROM rn set source register + FROMRNc 13 +NEWSYM FxOpcBE ; FROM rn set source register + FROMRNc 14 +NEWSYM FxOpcBF ; FROM rn set source register + FETCHPIPE + mov eax,ebp + sub eax,[SfxCPB] + inc ebp + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + shr al,7 + mov byte[SfxOverflow],al + CLRFLAGS + ret + +NEWSYM FxEmu2BAsmEnd diff --git a/i386/fxemu2b.mac b/i386/fxemu2b.mac new file mode 100644 index 00000000..758feb68 --- /dev/null +++ b/i386/fxemu2b.mac @@ -0,0 +1,88 @@ +;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com ) +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;as published by the Free Software Foundation; either +;version 2 of the License, or (at your option) any later +;version. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + + + + + + + + +%macro TORNb 1 ; V + FETCHPIPE + test dword [SfxB],1 + jnz .VersionB + mov edi, SfxR0+%1*4 + inc ebp ; Increase program counter + mov eax,ebp + sub eax,[SfxCPB] + mov dword[withr15sk],1 + mov [SfxR15],eax + call [FxTableb+ecx*4] + mov edi,SfxR0 + ret +.VersionB + mov eax,[esi] ; Read Source + mov dword[withr15sk],1 + inc ebp ; Increase program counter + mov [SfxR0+%1*4],eax ; Write + CLRFLAGS + ret +%endmacro + +%macro FROMRNb 1 ; V + FETCHPIPE + test dword [SfxB],1 + jnz .VersionB + mov esi,SfxR0+%1*4 + inc ebp ; Increase program counter + call [FxTable+ecx*4] + mov esi,SfxR0 + ret +.VersionB + mov eax,[SfxR0+%1*4] ; Read + inc ebp + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + shr al,7 + mov byte[SfxOverflow],al + CLRFLAGS + ret +%endmacro + +%macro TORNc 1 ; V + FETCHPIPE + mov eax,[esi] ; Read Source + inc ebp ; Increase program counter + mov [SfxR0+%1*4],eax ; Write + CLRFLAGS + ret +%endmacro + + +%macro FROMRNc 1 ; V + FETCHPIPE + mov eax,[SfxR0+%1*4] ; Read + inc ebp + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + shr al,7 + mov byte[SfxOverflow],al + CLRFLAGS + ret +%endmacro diff --git a/i386/fxemu2c.asm b/i386/fxemu2c.asm new file mode 100644 index 00000000..f41caf10 --- /dev/null +++ b/i386/fxemu2c.asm @@ -0,0 +1,2557 @@ +;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com ) +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;as published by the Free Software Foundation; either +;version 2 of the License, or (at your option) any later +;version. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +%include "macros.mac" + +EXTSYM FXEndLoop,FlushCache,FxOp02,FxTable,FxTableb,FxTablec,FxTabled +EXTSYM NumberOfOpcodes,SfxB,SfxCBR,SfxCFGR,SfxCOLR,SfxCPB,SfxCROM +EXTSYM SfxCacheActive,SfxCarry,SfxLastRamAdr,SfxMemTable,SfxOverflow +EXTSYM SfxPBR,SfxPIPE,SfxPOR,SfxR0,SfxR1,SfxR11,SfxR12,SfxR13,SfxR14 +EXTSYM SfxR15,SfxR2,SfxR4,SfxR6,SfxR7,SfxR8,SfxRAMBR,SfxRAMMem,SfxROMBR +EXTSYM SfxRomBuffer,SfxSCBR,SfxSCMR,SfxSFR,SfxSignZero,SfxnRamBanks,flagnz +EXTSYM sfx128lineloc,sfx160lineloc,sfx192lineloc,sfxobjlineloc,sfxramdata +EXTSYM withr15sk,sfxclineloc,SCBRrel,ChangeOps +EXTSYM fxbit01pcal,fxbit23pcal,fxbit45pcal,fxbit67pcal +EXTSYM fxbit01,fxbit23,fxbit45,fxbit67 +EXTSYM fxxand +EXTSYM PLOTJmpa,PLOTJmpb + +NEWSYM FxEmu2CAsmStart + +%include "fxemu2.mac" +%include "fxemu2b.mac" +%include "fxemu2c.mac" + + + + +SECTION .text ;ALIGN=32 + +ALIGN32 +NEWSYM FxOpd00 ; STOP stop GSU execution (and maybe generate an IRQ) ; Verified. + FETCHPIPE + mov [SfxPIPE],cl + and dword [SfxSFR],0FFFFh-32 ; Clear Go flag (set to 1 when the GSU is running) + test dword [SfxCFGR],080h ; Check if the interrupt generation is on + jnz .NoIRQ + or dword [SfxSFR],08000h ; Set IRQ Flag +.NoIRQ + CLRFLAGS + inc ebp + mov eax,[NumberOfOpcodes] + add eax,0F0000000h + add [ChangeOps],eax + mov dword [NumberOfOpcodes],1 + jmp FXEndLoop + FXReturn + +NEWSYM FxOpd01 ; NOP no operation ; Verified. + FETCHPIPE + CLRFLAGS + inc ebp ; Increase program counter + FXReturn + +NEWSYM FxOpd02 ; CACHE reintialize GSU cache + mov eax,ebp + FETCHPIPE + sub eax,[SfxCPB] + and eax,0FFF0h + cmp dword [SfxCBR],eax + je .SkipUpdate + cmp byte [SfxCacheActive],1 + je .SkipUpdate + mov dword [SfxCBR],eax + mov dword [SfxCacheActive],1 + call FlushCache +.SkipUpdate + CLRFLAGS + inc ebp ; Increase program counter + FXReturn + +NEWSYM FxOpd03 ; LSR logic shift right ; Verified. + mov eax,[esi] ; Read Source + FETCHPIPE + mov [SfxCarry],al + and byte[SfxCarry],1 + shr ax,1 ; logic shift right + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov dword [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpd04 ; ROL rotate left (RCL?) ; V + shr byte[SfxCarry],1 + mov eax,[esi] ; Read Source + FETCHPIPE + rcl ax,1 + rcl byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpd05 ; BRA branch always ; Verified. + movsx eax,byte[ebp] + mov cl,[ebp+1] + inc ebp + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd06 ; BGE branch on greater or equals ; Verified. + movsx eax,byte[ebp] + mov ebx,[SfxSignZero] + shr ebx,15 + inc ebp + xor bl,[SfxOverflow] + mov cl,[ebp] + test bl,01h + jnz .nojump + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 +.nojump + inc ebp + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd07 ; BLT branch on lesss than ; Verified. + movsx eax,byte[ebp] + mov ebx,[SfxSignZero] + shr ebx,15 + inc ebp + xor bl,[SfxOverflow] + mov cl,[ebp] + test bl,01h + jz .nojump + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 +.nojump + inc ebp + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd08 ; BNE branch on not equal ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],0FFFFh + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 +.nojump + inc ebp + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd09 ; BEQ branch on equal (z=1) ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],0FFFFh + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 +.nojump + inc ebp + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd0A ; BPL branch on plus ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],088000h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 +.nojump + inc ebp + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd0B ; BMI branch on minus ; Verified. + movsx eax,byte[ebp] + inc ebp + test dword[SfxSignZero],088000h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 +.nojump + inc ebp + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd0C ; BCC branch on carry clear ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxCarry],01h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 +.nojump + inc ebp + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd0D ; BCS branch on carry set ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxCarry],01h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 +.nojump + inc ebp + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd0E ; BVC branch on overflow clear ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxOverflow],01h + mov cl,[ebp] + jnz .nojump + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 +.nojump + inc ebp + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd0F ; BVS branch on overflow set ; Verified. + movsx eax,byte[ebp] + inc ebp + test byte[SfxOverflow],01h + mov cl,[ebp] + jz .nojump + add ebp,eax + call [FxTable+ecx*4] + FXReturn2 +.nojump + inc ebp + call [FxTable+ecx*4] + FXReturn2 + +NEWSYM FxOpd10 ; TO RN set register n as destination register + TORNd 0 +NEWSYM FxOpd11 ; TO RN set register n as destination register + TORNd 1 +NEWSYM FxOpd12 ; TO RN set register n as destination register + TORNd 2 +NEWSYM FxOpd13 ; TO RN set register n as destination register + TORNd 3 +NEWSYM FxOpd14 ; TO RN set register n as destination register + TORNd 4 +NEWSYM FxOpd15 ; TO RN set register n as destination register + TORNd 5 +NEWSYM FxOpd16 ; TO RN set register n as destination register + TORNd 6 +NEWSYM FxOpd17 ; TO RN set register n as destination register + TORNd 7 +NEWSYM FxOpd18 ; TO RN set register n as destination register + TORNd 8 +NEWSYM FxOpd19 ; TO RN set register n as destination register + TORNd 9 +NEWSYM FxOpd1A ; TO RN set register n as destination register + TORNd 10 +NEWSYM FxOpd1B ; TO RN set register n as destination register + TORNd 11 +NEWSYM FxOpd1C ; TO RN set register n as destination register + TORNd 12 +NEWSYM FxOpd1D ; TO RN set register n as destination register + TORNd 13 +NEWSYM FxOpd1E ; TO RN set register n as destination register + FETCHPIPE + mov edi,SfxR0+14*4 + inc ebp + call [FxTable+ecx*4] + mov edi,SfxR0 + UpdateR14 + FXReturn +NEWSYM FxOpd1F ; TO RN set register n as destination register + FETCHPIPE + mov edi,SfxR0+15*4 + inc ebp + call [FxTable+ecx*4] + mov ebp,[SfxCPB] + add ebp,[SfxR15] + mov edi,SfxR0 + FXReturn + +NEWSYM FxOpd20 ; WITH set register n as source and destination register + WITHc 0 +NEWSYM FxOpd21 ; WITH set register n as source and destination register + WITHc 1 +NEWSYM FxOpd22 ; WITH set register n as source and destination register + WITHc 2 +NEWSYM FxOpd23 ; WITH set register n as source and destination register + WITHc 3 +NEWSYM FxOpd24 ; WITH set register n as source and destination register + WITHc 4 +NEWSYM FxOpd25 ; WITH set register n as source and destination register + WITHc 5 +NEWSYM FxOpd26 ; WITH set register n as source and destination register + WITHc 6 +NEWSYM FxOpd27 ; WITH set register n as source and destination register + WITHc 7 +NEWSYM FxOpd28 ; WITH set register n as source and destination register + WITHc 8 +NEWSYM FxOpd29 ; WITH set register n as source and destination register + WITHc 9 +NEWSYM FxOpd2A ; WITH set register n as source and destination register + WITHc 10 +NEWSYM FxOpd2B ; WITH set register n as source and destination register + WITHc 11 +NEWSYM FxOpd2C ; WITH set register n as source and destination register + WITHc 12 +NEWSYM FxOpd2D ; WITH set register n as source and destination register + WITHc 13 +NEWSYM FxOpd2E ; WITH set register n as source and destination register + FETCHPIPE + mov esi,SfxR0+14*4 + mov edi,SfxR0+14*4 + mov dword [SfxB],1 + inc ebp + call [FxTablec+ecx*4] + mov dword [SfxB],0 ; Clear B Flag + mov esi,SfxR0 + mov edi,SfxR0 + UpdateR14 + FXReturn +NEWSYM FxOpd2F ; WITH set register n as source and destination register + FETCHPIPE + mov esi,SfxR0+15*4 + mov edi,SfxR0+15*4 + mov dword [SfxB],1 + inc ebp + mov eax,ebp + sub eax,[SfxCPB] + mov dword[withr15sk],0 + mov [SfxR15],eax + call [FxTableb+ecx*4] + cmp dword[withr15sk],1 + je .skip + mov ebp,[SfxCPB] + add ebp,[SfxR15] +.skip + mov dword [SfxB],0 ; Clear B Flag + mov esi,SfxR0 + mov edi,SfxR0 + FXReturn + +NEWSYM FxOpd30 ; STW RN store word + STWRNc 0 +NEWSYM FxOpd31 ; STW RN store word + STWRNc 1 +NEWSYM FxOpd32 ; STW RN store word + STWRNc 2 +NEWSYM FxOpd33 ; STW RN store word + STWRNc 3 +NEWSYM FxOpd34 ; STW RN store word + STWRNc 4 +NEWSYM FxOpd35 ; STW RN store word + STWRNc 5 +NEWSYM FxOpd36 ; STW RN store word + STWRNc 6 +NEWSYM FxOpd37 ; STW RN store word + STWRNc 7 +NEWSYM FxOpd38 ; STW RN store word + STWRNc 8 +NEWSYM FxOpd39 ; STW RN store word + STWRNc 9 +NEWSYM FxOpd3A ; STW RN store word + STWRNc 10 +NEWSYM FxOpd3B ; STW RN store word + STWRNc 11 + +NEWSYM FxOpd30A1 ; STB RN store byte + STBRNc 0 +NEWSYM FxOpd31A1 ; STB RN store byte + STBRNc 1 +NEWSYM FxOpd32A1 ; STB RN store byte + STBRNc 2 +NEWSYM FxOpd33A1 ; STB RN store byte + STBRNc 3 +NEWSYM FxOpd34A1 ; STB RN store byte + STBRNc 4 +NEWSYM FxOpd35A1 ; STB RN store byte + STBRNc 5 +NEWSYM FxOpd36A1 ; STB RN store byte + STBRNc 6 +NEWSYM FxOpd37A1 ; STB RN store byte + STBRNc 7 +NEWSYM FxOpd38A1 ; STB RN store byte + STBRNc 8 +NEWSYM FxOpd39A1 ; STB RN store byte + STBRNc 9 +NEWSYM FxOpd3AA1 ; STB RN store byte + STBRNc 10 +NEWSYM FxOpd3BA1 ; STB RN store byte + STBRNc 11 + +NEWSYM FxOpd3C ; LOOP decrement loop counter, and branch on not zero ; V + dec word [SfxR12] ; decrement loop counter + FETCHPIPE + mov eax,[SfxR12] + mov [SfxSignZero],eax + or eax,eax + jz .NoBranch + mov eax,dword [SfxR13] + mov ebp,[SfxCPB] + add ebp,eax + CLRFLAGS + FXReturn +.NoBranch + inc ebp + CLRFLAGS + FXReturn + +NEWSYM FxOpd3D ; ALT1 set alt1 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,01h + inc ebp + call [FxTable+ecx*4] + xor ch,ch + FXReturn + +NEWSYM FxOpd3E ; ALT2 set alt1 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,02h + inc ebp + call [FxTable+ecx*4] + xor ch,ch + FXReturn + +NEWSYM FxOpd3F ; ALT3 set alt3 mode ; Verified. + FETCHPIPE + mov dword [SfxB],0 + or ch,03h + inc ebp + call [FxTable+ecx*4] + xor ch,ch + FXReturn + +NEWSYM FxOpd40 ; LDW RN load word from RAM + LDWRNc 0 +NEWSYM FxOpd41 ; LDW RN load word from RAM + LDWRNc 1 +NEWSYM FxOpd42 ; LDW RN load word from RAM + LDWRNc 2 +NEWSYM FxOpd43 ; LDW RN load word from RAM + LDWRNc 3 +NEWSYM FxOpd44 ; LDW RN load word from RAM + LDWRNc 4 +NEWSYM FxOpd45 ; LDW RN load word from RAM + LDWRNc 5 +NEWSYM FxOpd46 ; LDW RN load word from RAM + LDWRNc 6 +NEWSYM FxOpd47 ; LDW RN load word from RAM + LDWRNc 7 +NEWSYM FxOpd48 ; LDW RN load word from RAM + LDWRNc 8 +NEWSYM FxOpd49 ; LDW RN load word from RAM + LDWRNc 9 +NEWSYM FxOpd4A ; LDW RN load word from RAM + LDWRNc 10 +NEWSYM FxOpd4B ; LDW RN load word from RAM + LDWRNc 11 + +NEWSYM FxOpd40A1 ; LDB RN load byte from RAM + LDBRNc 0 +NEWSYM FxOpd41A1 ; LDB RN load byte from RAM + LDBRNc 1 +NEWSYM FxOpd42A1 ; LDB RN load byte from RAM + LDBRNc 2 +NEWSYM FxOpd43A1 ; LDB RN load byte from RAM + LDBRNc 3 +NEWSYM FxOpd44A1 ; LDB RN load byte from RAM + LDBRNc 4 +NEWSYM FxOpd45A1 ; LDB RN load byte from RAM + LDBRNc 5 +NEWSYM FxOpd46A1 ; LDB RN load byte from RAM + LDBRNc 6 +NEWSYM FxOpd47A1 ; LDB RN load byte from RAM + LDBRNc 7 +NEWSYM FxOpd48A1 ; LDB RN load byte from RAM + LDBRNc 8 +NEWSYM FxOpd49A1 ; LDB RN load byte from RAM + LDBRNc 9 +NEWSYM FxOpd4AA1 ; LDB RN load byte from RAM + LDBRNc 10 +NEWSYM FxOpd4BA1 ; LDB RN load byte from RAM + LDBRNc 11 + + +NEWSYM FxOpd4C1284b ; PLOT 4bit + plotlines4bb plotb +NEWSYM FxOpd4C1284bz ; PLOT 4bit, zero check + plotlines4bb plotbz +NEWSYM FxOpd4C1284bd ; PLOT 4bit, dither + plotlines4bb plotbd +NEWSYM FxOpd4C1284bzd ; PLOT 4bit, zero check + dither + plotlines4bb plotbzd + +NEWSYM FxOpd4C1282b ; PLOT 2bit + plotlines2bb plotb +NEWSYM FxOpd4C1282bz ; PLOT 2bit, zero check + plotlines2bb plotbz +NEWSYM FxOpd4C1282bd ; PLOT 2bit, dither + plotlines2bb plotbd +NEWSYM FxOpd4C1282bzd ; PLOT 2bit, zero check + dither + plotlines2bb plotbzd + +NEWSYM FxOpd4C1288b ; PLOT 8bit + plotlines8bb plotb +NEWSYM FxOpd4C1288bz ; PLOT 8bit, zero check + plotlines8bb plotbz +NEWSYM FxOpd4C1288bd ; PLOT 8bit, dither + plotlines8bb plotb +NEWSYM FxOpd4C1288bzd ; PLOT 8bit, zero check + dither + plotlines8bb plotbz + +NEWSYM FxOpd4C1288bl ; PLOT 8bit + plotlines8bbl plotb +NEWSYM FxOpd4C1288bzl ; PLOT 8bit, zero check + plotlines8bbl plotbz +NEWSYM FxOpd4C1288bdl ; PLOT 8bit, dither + plotlines8bbl plotb +NEWSYM FxOpd4C1288bzdl ; PLOT 8bit, zero check + dither + plotlines8bbl plotbz + +NEWSYM FxOpd4C ; PLOT plot pixel with R1,R2 as x,y and the color register as the color + jmp FxOpd4C1284b + + FETCHPIPE + inc ebp + CLRFLAGS + mov ebx,[SfxR2] + mov bh,[SfxR1] + mov eax,[sfxclineloc] + mov ebx,[eax+ebx*4] + cmp ebx,0FFFFFFFFh + je near .nodraw + xor eax,eax + ; bits 5/2 : 00 = 128 pixels, 01 = 160 pixels, 10 = 192 pixels, 11 = obj + ; bits 1/0 : 00 = 4 color, 01 = 16-color, 10 = not used, 11 = 256 color + ; 192 pixels = 24 tiles, 160 pixels = 20 tiles, 128 pixels = 16 tiles + ; 16+8(4/3) 16+4(4/2) 16(4/0) + push ecx + mov al,[SfxSCMR] + and al,00000011b ; 4 + 32 + cmp al,0 + je near .colors4 + cmp al,3 + je near .colors256 + + shl ebx,5 ; x32 (16 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + mov bh,bl + xor bh,0FFh + pop ecx + test byte[SfxPOR],01h + jnz .nozerocheck_16 + test byte[SfxCOLR],0Fh + jz .nodraw +.nozerocheck_16 + mov dl,[SfxCOLR] + test byte[SfxPOR],02h + jz .nodither4b + mov dh,[SfxR1] + xor dh,[SfxR2] + test dh,01h + jz .nodither4b + shr dh,4 +.nodither4b + and byte[eax],bh + and byte[eax+1],bh + and byte[eax+16],bh + and byte[eax+17],bh + test dl,01h + jz .nodraw_16 + or byte[eax], bl +.nodraw_16 + test dl,02h + jz .nodraw2_16 + or byte[eax+1], bl +.nodraw2_16 + test dl,04h + jz .nodraw3_16 + or byte[eax+16],bl +.nodraw3_16 + test dl,08h + jz .nodraw4_16 + or byte[eax+17],bl +.nodraw4_16 +.nodraw + inc word [SfxR1] + FXReturn + +.colors4 + shl ebx,4 ; x16 (4 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + mov bh,bl + xor bh,0FFh + pop ecx + test byte[SfxPOR],01h + jnz .nozerocheck_4 + test byte[SfxCOLR],03h + jz .noplot_4 +.nozerocheck_4 + mov dl,[SfxCOLR] + test byte[SfxPOR],02h + jz .nodither2b + mov dh,[SfxR1] + xor dh,[SfxR2] + test dh,01h + jz .nodither2b + shr dh,4 +.nodither2b + and byte[eax],bh + and byte[eax+1],bh + test dl,01h + jz .nodraw_4 + or byte[eax], bl +.nodraw_4 + test dl,02h + jz .nodraw2_4 + or byte[eax+1], bl +.nodraw2_4 +.noplot_4 + inc word [SfxR1] + FXReturn + +.colors256 + shl ebx,6 ; x64 (256 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + mov bh,bl + xor bh,0FFh + pop ecx + test byte[SfxPOR],01h + jnz .nozerocheck_256 + mov dl,0FFh + test byte[SfxPOR],08h + jz .nozerocheckb_256 + mov dl,0Fh +.nozerocheckb_256 + test byte[SfxCOLR],dl + jz .noplot_256 +.nozerocheck_256 + mov dl,[SfxCOLR] + and byte[eax],bh + and byte[eax+1],bh + and byte[eax+16],bh + and byte[eax+17],bh + and byte[eax+32],bh + and byte[eax+33],bh + and byte[eax+48],bh + and byte[eax+49],bh + test dl,01h + jz .nodraw_256 + or byte[eax], bl +.nodraw_256 + test dl,02h + jz .nodraw2_256 + or byte[eax+1], bl +.nodraw2_256 + test dl,04h + jz .nodraw3_256 + or byte[eax+16],bl +.nodraw3_256 + test dl,08h + jz .nodraw4_256 + or byte[eax+17],bl +.nodraw4_256 + test dl,10h + jz .nodraw5_256 + or byte[eax+32], bl +.nodraw5_256 + test dl,20h + jz .nodraw6_256 + or byte[eax+33], bl +.nodraw6_256 + test dl,40h + jz .nodraw7_256 + or byte[eax+48],bl +.nodraw7_256 + test dl,80h + jz .nodraw8_256 + or byte[eax+49],bl +.nodraw8_256 +.noplot_256 + inc word [SfxR1] + FXReturn + +SECTION .bss +.prevx resw 1 +.prevy resw 1 + +SECTION .text + +NEWSYM FxOpd4CA1 ; RPIX read color of the pixel with R1,R2 as x,y + FETCHPIPE + mov ebx,[SfxR2] + mov bh,[SfxR1] + test byte[SfxPOR],10h + jnz .objmode + mov al,[SfxSCMR] + and al,00100100b ; 4 + 32 + cmp al,4 + je .lines160 + cmp al,32 + je .lines192 + cmp al,36 + je .objmode + mov eax,[sfx128lineloc] + jmp .donelines +.lines160 + mov eax,[sfx160lineloc] + jmp .donelines +.lines192 + mov eax,[sfx192lineloc] + jmp .donelines +.objmode + mov eax,[sfxobjlineloc] +.donelines + mov ebx,[eax+ebx*4] + cmp ebx,0FFFFFFFFh + je near .nodraw + xor eax,eax + ; bits 5/2 : 00 = 128 pixels, 01 = 160 pixels, 10 = 192 pixels, 11 = obj + ; bits 1/0 : 00 = 4 color, 01 = 16-color, 10 = not used, 11 = 256 color + ; 192 pixels = 24 tiles, 160 pixels = 20 tiles, 128 pixels = 16 tiles + ; 16+8(4/3) 16+4(4/2) 16(4/0) + push ecx + mov al,[SfxSCMR] + and al,00000011b ; 4 + 32 + + cmp al,0 + je near .colors4 + cmp al,3 + je near .colors256 + + shl ebx,5 ; x32 (16 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + pop ecx + xor bh,bh + test byte[eax],bl + jz .nodraw_16 + or bh,01h +.nodraw_16 + test byte[eax+1],bl + jz .nodraw2_16 + or bh,02h +.nodraw2_16 + test byte[eax+16],bl + jz .nodraw3_16 + or bh,04h +.nodraw3_16 + test byte[eax+17],bl + jz .nodraw4_16 + or bh,08h +.nodraw4_16 +.nodraw + mov bl,bh + and ebx,0FFh + inc ebp +; UpdateR14 + CLRFLAGS + mov [edi],ebx ; Write Destination + mov [flagnz],ebx + FXReturn + +.colors4 + shl ebx,4 ; x16 (4 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + mov bh,bl + xor bh,0FFh + pop ecx + xor bh,bh + test byte[eax],bl + jz .nodraw_4 + or bh,01h +.nodraw_4 + test byte[eax+1],bl + jz .nodraw2_4 + or bh,02h +.nodraw2_4 + mov bl,bh + and ebx,0FFh + inc ebp +; UpdateR14 + CLRFLAGS + mov [edi],ebx ; Write Destination + mov [flagnz],ebx + FXReturn + +.colors256 + shl ebx,6 ; x64 (256 colors) + mov al,[SfxSCBR] + shl eax,10 ; Get SFX address + add eax,ebx + add eax,[sfxramdata] + mov ebx,[SfxR2] + and ebx,07h + shl ebx,1 + add eax,ebx + mov cl,[SfxR1] + and cl,07h + xor cl,07h + mov bl,1 + shl bl,cl + mov bh,bl + xor bh,0FFh + pop ecx + xor bh,bh + test byte[eax],bl + jz .nodraw_256 + or bh,01h +.nodraw_256 + test byte[eax+1],bl + jz .nodraw2_256 + or bh,02h +.nodraw2_256 + test byte[eax+16],bl + jz .nodraw3_256 + or bh,04h +.nodraw3_256 + test byte[eax+17],bl + jz .nodraw4_256 + or bh,08h +.nodraw4_256 + test byte[eax+32],bl + jz .nodraw5_256 + or bh,10h +.nodraw5_256 + test byte[eax+33],bl + jz .nodraw6_256 + or bh,20h +.nodraw6_256 + test byte[eax+48],bl + jz .nodraw7_256 + or bh,40h +.nodraw7_256 + test byte[eax+49],bl + jz .nodraw8_256 + or bh,80h +.nodraw8_256 + mov bl,bh + and ebx,0FFh + inc ebp +; UpdateR14 + CLRFLAGS + mov [edi],ebx ; Write Destination + mov [flagnz],ebx + FXReturn + +NEWSYM FxOpd4D ; SWAP swap upper and lower byte of a register ; V + mov eax,[esi] ; Read Source + FETCHPIPE + ror ax,8 + inc ebp ; Increase program counter + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn + +NEWSYM FxOpd4E ; COLOR copy source register to color register ; V + FETCHPIPE + mov eax,[esi] ; Read Source + ; if bit 3 of SfxPOR is set, then don't modify the upper 4 bits + test byte[SfxPOR],04h + jz .nohighnibble + mov bl,al + shr bl,4 + and al,0F0h + or al,bl +.nohighnibble + test byte[SfxPOR],08h + jnz .preserveupper + cmp [SfxCOLR],al + je .nocolchange + mov [SfxCOLR],al + and eax,0FFh + mov ebx,[fxbit01+eax*4] + mov [fxbit01pcal],ebx + mov ebx,[fxbit23+eax*4] + mov [fxbit23pcal],ebx + mov ebx,[fxbit45+eax*4] + mov [fxbit45pcal],ebx + mov ebx,[fxbit67+eax*4] + mov [fxbit67pcal],ebx +.nocolchange + CLRFLAGS + inc ebp ; Increase program counter + FXReturn +.preserveupper + mov bl,[SfxCOLR] + and al,0Fh + and bl,0F0h + or al,bl + cmp [SfxCOLR],al + je .nocolchange + mov [SfxCOLR],al + and eax,0FFh + mov ebx,[fxbit01+eax*4] + mov [fxbit01pcal],ebx + mov ebx,[fxbit23+eax*4] + mov [fxbit23pcal],ebx + mov ebx,[fxbit45+eax*4] + mov [fxbit45pcal],ebx + mov ebx,[fxbit67+eax*4] + mov [fxbit67pcal],ebx + CLRFLAGS + inc ebp ; Increase program counter + FXReturn + +NEWSYM FxOpd4EA1 ; CMODE set plot option register ; V + FETCHPIPE + mov eax,[esi] ; Read Source + inc ebp ; Increase program counter + mov dword [SfxPOR],eax + + test byte[SfxPOR],10h + jnz .objmode + mov al,[SfxSCMR] + and al,00100100b ; 4 + 32 + cmp al,4 + je .lines160 + cmp al,32 + je .lines192 + cmp al,36 + je .objmode + mov eax,[sfx128lineloc] + jmp .donelines +.lines160 + mov eax,[sfx160lineloc] + jmp .donelines +.lines192 + mov eax,[sfx192lineloc] + jmp .donelines +.objmode + mov eax,[sfxobjlineloc] +.donelines + mov [sfxclineloc],eax + + + push ebx + mov al,[SfxSCMR] + and eax,00000011b + mov bl,[SfxPOR] + and bl,0Fh + shl bl,2 + or al,bl + mov ebx,[PLOTJmpb+eax*4] + mov eax,[PLOTJmpa+eax*4] + + mov dword [FxTable+4Ch*4],eax + mov dword [FxTableb+4Ch*4],eax + mov dword [FxTablec+4Ch*4],eax + mov dword [FxTabled+4Ch*4],ebx + pop ebx + + CLRFLAGS + FXReturn + +NEWSYM FxOpd4F ; NOT perform exclusive exor with 1 on all bits ; V + mov eax,[esi] ; Read Source + FETCHPIPE + xor eax,0FFFFh + inc ebp ; Increase program counter + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn + +NEWSYM FxOpd50 ; ADD RN add, register + register + ADDRNc 0 +NEWSYM FxOpd51 ; ADD RN add, register + register + ADDRNc 1 +NEWSYM FxOpd52 ; ADD RN add, register + register + ADDRNc 2 +NEWSYM FxOpd53 ; ADD RN add, register + register + ADDRNc 3 +NEWSYM FxOpd54 ; ADD RN add, register + register + ADDRNc 4 +NEWSYM FxOpd55 ; ADD RN add, register + register + ADDRNc 5 +NEWSYM FxOpd56 ; ADD RN add, register + register + ADDRNc 6 +NEWSYM FxOpd57 ; ADD RN add, register + register + ADDRNc 7 +NEWSYM FxOpd58 ; ADD RN add, register + register + ADDRNc 8 +NEWSYM FxOpd59 ; ADD RN add, register + register + ADDRNc 9 +NEWSYM FxOpd5A ; ADD RN add, register + register + ADDRNc 10 +NEWSYM FxOpd5B ; ADD RN add, register + register + ADDRNc 11 +NEWSYM FxOpd5C ; ADD RN add, register + register + ADDRNc 12 +NEWSYM FxOpd5D ; ADD RN add, register + register + ADDRNc 13 +NEWSYM FxOpd5E ; ADD RN add, register + register + ADDRNc 14 +NEWSYM FxOpd5F ; ADD RN add, register + register + FETCHPIPE + mov eax, [esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + add ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn + +NEWSYM FxOpd50A1 ; ADC RN add with carry, register + register + ADCRNc 0 +NEWSYM FxOpd51A1 ; ADC RN add with carry, register + register + ADCRNc 1 +NEWSYM FxOpd52A1 ; ADC RN add with carry, register + register + ADCRNc 2 +NEWSYM FxOpd53A1 ; ADC RN add with carry, register + register + ADCRNc 3 +NEWSYM FxOpd54A1 ; ADC RN add with carry, register + register + ADCRNc 4 +NEWSYM FxOpd55A1 ; ADC RN add with carry, register + register + ADCRNc 5 +NEWSYM FxOpd56A1 ; ADC RN add with carry, register + register + ADCRNc 6 +NEWSYM FxOpd57A1 ; ADC RN add with carry, register + register + ADCRNc 7 +NEWSYM FxOpd58A1 ; ADC RN add with carry, register + register + ADCRNc 8 +NEWSYM FxOpd59A1 ; ADC RN add with carry, register + register + ADCRNc 9 +NEWSYM FxOpd5AA1 ; ADC RN add with carry, register + register + ADCRNc 10 +NEWSYM FxOpd5BA1 ; ADC RN add with carry, register + register + ADCRNc 11 +NEWSYM FxOpd5CA1 ; ADC RN add with carry, register + register + ADCRNc 12 +NEWSYM FxOpd5DA1 ; ADC RN add with carry, register + register + ADCRNc 13 +NEWSYM FxOpd5EA1 ; ADC RN add with carry, register + register + ADCRNc 14 +NEWSYM FxOpd5FA1 ; ADC RN add with carry, register + register + FETCHPIPE + mov eax, [esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + shr byte[SfxCarry],1 + adc ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn + +; Weird Opdode (FxOpd50A2, add 0, wow!) +NEWSYM FxOpd50A2 ; ADI RN add, register + immediate + ADIRNc 0 +NEWSYM FxOpd51A2 ; ADI RN add, register + immediate + ADIRNc 1 +NEWSYM FxOpd52A2 ; ADI RN add, register + immediate + ADIRNc 2 +NEWSYM FxOpd53A2 ; ADI RN add, register + immediate + ADIRNc 3 +NEWSYM FxOpd54A2 ; ADI RN add, register + immediate + ADIRNc 4 +NEWSYM FxOpd55A2 ; ADI RN add, register + immediate + ADIRNc 5 +NEWSYM FxOpd56A2 ; ADI RN add, register + immediate + ADIRNc 6 +NEWSYM FxOpd57A2 ; ADI RN add, register + immediate + ADIRNc 7 +NEWSYM FxOpd58A2 ; ADI RN add, register + immediate + ADIRNc 8 +NEWSYM FxOpd59A2 ; ADI RN add, register + immediate + ADIRNc 9 +NEWSYM FxOpd5AA2 ; ADI RN add, register + immediate + ADIRNc 10 +NEWSYM FxOpd5BA2 ; ADI RN add, register + immediate + ADIRNc 11 +NEWSYM FxOpd5CA2 ; ADI RN add, register + immediate + ADIRNc 12 +NEWSYM FxOpd5DA2 ; ADI RN add, register + immediate + ADIRNc 13 +NEWSYM FxOpd5EA2 ; ADI RN add, register + immediate + ADIRNc 14 +NEWSYM FxOpd5FA2 ; ADI RN add, register + immediate + ADIRNc 15 + +; Another very useful Opdode +NEWSYM FxOpd50A3 ; ADCIRN add with carry, register + immediate + ADCIRNc 0 +NEWSYM FxOpd51A3 ; ADCIRN add with carry, register + immediate + ADCIRNc 1 +NEWSYM FxOpd52A3 ; ADCIRN add with carry, register + immediate + ADCIRNc 2 +NEWSYM FxOpd53A3 ; ADCIRN add with carry, register + immediate + ADCIRNc 3 +NEWSYM FxOpd54A3 ; ADCIRN add with carry, register + immediate + ADCIRNc 4 +NEWSYM FxOpd55A3 ; ADCIRN add with carry, register + immediate + ADCIRNc 5 +NEWSYM FxOpd56A3 ; ADCIRN add with carry, register + immediate + ADCIRNc 6 +NEWSYM FxOpd57A3 ; ADCIRN add with carry, register + immediate + ADCIRNc 7 +NEWSYM FxOpd58A3 ; ADCIRN add with carry, register + immediate + ADCIRNc 8 +NEWSYM FxOpd59A3 ; ADCIRN add with carry, register + immediate + ADCIRNc 9 +NEWSYM FxOpd5AA3 ; ADCIRN add with carry, register + immediate + ADCIRNc 10 +NEWSYM FxOpd5BA3 ; ADCIRN add with carry, register + immediate + ADCIRNc 11 +NEWSYM FxOpd5CA3 ; ADCIRN add with carry, register + immediate + ADCIRNc 12 +NEWSYM FxOpd5DA3 ; ADCIRN add with carry, register + immediate + ADCIRNc 13 +NEWSYM FxOpd5EA3 ; ADCIRN add with carry, register + immediate + ADCIRNc 14 +NEWSYM FxOpd5FA3 ; ADCIRN add with carry, register + immediate + ADCIRNc 15 + +NEWSYM FxOpd60 ; SUBRN subtract, register - register + SUBRNc 0 +NEWSYM FxOpd61 ; SUBRN subtract, register - register + SUBRNc 1 +NEWSYM FxOpd62 ; SUBRN subtract, register - register + SUBRNc 2 +NEWSYM FxOpd63 ; SUBRN subtract, register - register + SUBRNc 3 +NEWSYM FxOpd64 ; SUBRN subtract, register - register + SUBRNc 4 +NEWSYM FxOpd65 ; SUBRN subtract, register - register + SUBRNc 5 +NEWSYM FxOpd66 ; SUBRN subtract, register - register + SUBRNc 6 +NEWSYM FxOpd67 ; SUBRN subtract, register - register + SUBRNc 7 +NEWSYM FxOpd68 ; SUBRN subtract, register - register + SUBRNc 8 +NEWSYM FxOpd69 ; SUBRN subtract, register - register + SUBRNc 9 +NEWSYM FxOpd6A ; SUBRN subtract, register - register + SUBRNc 10 +NEWSYM FxOpd6B ; SUBRN subtract, register - register + SUBRNc 11 +NEWSYM FxOpd6C ; SUBRN subtract, register - register + SUBRNc 12 +NEWSYM FxOpd6D ; SUBRN subtract, register - register + SUBRNc 13 +NEWSYM FxOpd6E ; SUBRN subtract, register - register + SUBRNc 14 +NEWSYM FxOpd6F ; SUBRN subtract, register - register + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + sub ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpd60A1 ; SBCRN subtract with carry, register - register + SBCRNc 0 +NEWSYM FxOpd61A1 ; SBCRN subtract with carry, register - register + SBCRNc 1 +NEWSYM FxOpd62A1 ; SBCRN subtract with carry, register - register + SBCRNc 2 +NEWSYM FxOpd63A1 ; SBCRN subtract with carry, register - register + SBCRNc 3 +NEWSYM FxOpd64A1 ; SBCRN subtract with carry, register - register + SBCRNc 4 +NEWSYM FxOpd65A1 ; SBCRN subtract with carry, register - register + SBCRNc 5 +NEWSYM FxOpd66A1 ; SBCRN subtract with carry, register - register + SBCRNc 6 +NEWSYM FxOpd67A1 ; SBCRN subtract with carry, register - register + SBCRNc 7 +NEWSYM FxOpd68A1 ; SBCRN subtract with carry, register - register + SBCRNc 8 +NEWSYM FxOpd69A1 ; SBCRN subtract with carry, register - register + SBCRNc 9 +NEWSYM FxOpd6AA1 ; SBCRN subtract with carry, register - register + SBCRNc 10 +NEWSYM FxOpd6BA1 ; SBCRN subtract with carry, register - register + SBCRNc 11 +NEWSYM FxOpd6CA1 ; SBCRN subtract with carry, register - register + SBCRNc 12 +NEWSYM FxOpd6DA1 ; SBCRN subtract with carry, register - register + SBCRNc 13 +NEWSYM FxOpd6EA1 ; SBCRN subtract with carry, register - register + SBCRNc 14 +NEWSYM FxOpd6FA1 ; SBCRN subtract with carry, register - register + mov eax,[esi] ; Read Source + mov ebx,ebp + FETCHPIPE + sub ebx,[SfxCPB] + cmp byte[SfxCarry],1 + sbb ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpd60A2 ; SUBIRN subtract, register - immediate + SUBIRNc 0 +NEWSYM FxOpd61A2 ; SUBIRN subtract, register - immediate + SUBIRNc 1 +NEWSYM FxOpd62A2 ; SUBIRN subtract, register - immediate + SUBIRNc 2 +NEWSYM FxOpd63A2 ; SUBIRN subtract, register - immediate + SUBIRNc 3 +NEWSYM FxOpd64A2 ; SUBIRN subtract, register - immediate + SUBIRNc 4 +NEWSYM FxOpd65A2 ; SUBIRN subtract, register - immediate + SUBIRNc 5 +NEWSYM FxOpd66A2 ; SUBIRN subtract, register - immediate + SUBIRNc 6 +NEWSYM FxOpd67A2 ; SUBIRN subtract, register - immediate + SUBIRNc 7 +NEWSYM FxOpd68A2 ; SUBIRN subtract, register - immediate + SUBIRNc 8 +NEWSYM FxOpd69A2 ; SUBIRN subtract, register - immediate + SUBIRNc 9 +NEWSYM FxOpd6AA2 ; SUBIRN subtract, register - immediate + SUBIRNc 10 +NEWSYM FxOpd6BA2 ; SUBIRN subtract, register - immediate + SUBIRNc 11 +NEWSYM FxOpd6CA2 ; SUBIRN subtract, register - immediate + SUBIRNc 12 +NEWSYM FxOpd6DA2 ; SUBIRN subtract, register - immediate + SUBIRNc 13 +NEWSYM FxOpd6EA2 ; SUBIRN subtract, register - immediate + SUBIRNc 14 +NEWSYM FxOpd6FA2 ; SUBIRN subtract, register - immediate + SUBIRNc 15 + +NEWSYM FxOpd60A3 ; CMPRN compare, register, register + CMPRNc 0 +NEWSYM FxOpd61A3 ; CMPRN compare, register, register + CMPRNc 1 +NEWSYM FxOpd62A3 ; CMPRN compare, register, register + CMPRNc 2 +NEWSYM FxOpd63A3 ; CMPRN compare, register, register + CMPRNc 3 +NEWSYM FxOpd64A3 ; CMPRN compare, register, register + CMPRNc 4 +NEWSYM FxOpd65A3 ; CMPRN compare, register, register + CMPRNc 5 +NEWSYM FxOpd66A3 ; CMPRN compare, register, register + CMPRNc 6 +NEWSYM FxOpd67A3 ; CMPRN compare, register, register + CMPRNc 7 +NEWSYM FxOpd68A3 ; CMPRN compare, register, register + CMPRNc 8 +NEWSYM FxOpd69A3 ; CMPRN compare, register, register + CMPRNc 9 +NEWSYM FxOpd6AA3 ; CMPRN compare, register, register + CMPRNc 10 +NEWSYM FxOpd6BA3 ; CMPRN compare, register, register + CMPRNc 11 +NEWSYM FxOpd6CA3 ; CMPRN compare, register, register + CMPRNc 12 +NEWSYM FxOpd6DA3 ; CMPRN compare, register, register + CMPRNc 13 +NEWSYM FxOpd6EA3 ; CMPRN compare, register, register + CMPRNc 14 +NEWSYM FxOpd6FA3 ; CMPRN compare, register, register + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + sub ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + mov [SfxSignZero],eax + CLRFLAGS + inc ebp ; Increase program counter + FXReturn + +NEWSYM FxOpd70 ; MERGE R7 as upper byte, R8 as lower byte (used for texture-mapping) */ + ; V + xor eax,eax + FETCHPIPE + mov ah,byte [SfxR7+1] + mov al,byte [SfxR8+1] + inc ebp + mov [edi],eax ; Write Destination + mov dword[SfxSignZero],0001h + test eax,0F0F0h + jz .nozero + mov dword[SfxSignZero],0000h +.nozero + test eax,08080h + jz .nosign + or dword [SfxSignZero],80000h +.nosign + mov dword [SfxOverflow],1 + test ax,0c0c0h + jnz .Overflow + mov dword [SfxOverflow],0 +.Overflow + mov dword [SfxCarry],1 + test ax,0e0e0h + jnz .Carry + mov dword [SfxCarry],0 +.Carry + CLRFLAGS + FXReturn + +NEWSYM FxOpd71 ; AND RN register & register + ANDRNc 1 +NEWSYM FxOpd72 ; AND RN register & register + ANDRNc 2 +NEWSYM FxOpd73 ; AND RN register & register + ANDRNc 3 +NEWSYM FxOpd74 ; AND RN register & register + ANDRNc 4 +NEWSYM FxOpd75 ; AND RN register & register + ANDRNc 5 +NEWSYM FxOpd76 ; AND RN register & register + ANDRNc 6 +NEWSYM FxOpd77 ; AND RN register & register + ANDRNc 7 +NEWSYM FxOpd78 ; AND RN register & register + ANDRNc 8 +NEWSYM FxOpd79 ; AND RN register & register + ANDRNc 9 +NEWSYM FxOpd7A ; AND RN register & register + ANDRNc 10 +NEWSYM FxOpd7B ; AND RN register & register + ANDRNc 11 +NEWSYM FxOpd7C ; AND RN register & register + ANDRNc 12 +NEWSYM FxOpd7D ; AND RN register & register + ANDRNc 13 +NEWSYM FxOpd7E ; AND RN register & register + ANDRNc 14 +NEWSYM FxOpd7F ; AND RN register & register + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + and eax,ebx + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn + +NEWSYM FxOpd71A1 ; BIC RN register & ~register + BICRNc 1 +NEWSYM FxOpd72A1 ; BIC RN register & ~register + BICRNc 2 +NEWSYM FxOpd73A1 ; BIC RN register & ~register + BICRNc 3 +NEWSYM FxOpd74A1 ; BIC RN register & ~register + BICRNc 4 +NEWSYM FxOpd75A1 ; BIC RN register & ~register + BICRNc 5 +NEWSYM FxOpd76A1 ; BIC RN register & ~register + BICRNc 6 +NEWSYM FxOpd77A1 ; BIC RN register & ~register + BICRNc 7 +NEWSYM FxOpd78A1 ; BIC RN register & ~register + BICRNc 8 +NEWSYM FxOpd79A1 ; BIC RN register & ~register + BICRNc 9 +NEWSYM FxOpd7AA1 ; BIC RN register & ~register + BICRNc 10 +NEWSYM FxOpd7BA1 ; BIC RN register & ~register + BICRNc 11 +NEWSYM FxOpd7CA1 ; BIC RN register & ~register + BICRNc 12 +NEWSYM FxOpd7DA1 ; BIC RN register & ~register + BICRNc 13 +NEWSYM FxOpd7EA1 ; BIC RN register & ~register + BICRNc 14 +NEWSYM FxOpd7FA1 ; BIC RN register & ~register + FETCHPIPE + mov ebx,ebp + sub ebx,[SfxCPB] + mov eax,[esi] ; Read Source + xor ebx,0FFFFh + and eax,ebx + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn + +NEWSYM FxOpd71A2 ; ANDIRNc and #n - register & immediate + ANDIRNc 1 +NEWSYM FxOpd72A2 ; ANDIRNc and #n - register & immediate + ANDIRNc 2 +NEWSYM FxOpd73A2 ; ANDIRNc and #n - register & immediate + ANDIRNc 3 +NEWSYM FxOpd74A2 ; ANDIRNc and #n - register & immediate + ANDIRNc 4 +NEWSYM FxOpd75A2 ; ANDIRNc and #n - register & immediate + ANDIRNc 5 +NEWSYM FxOpd76A2 ; ANDIRNc and #n - register & immediate + ANDIRNc 6 +NEWSYM FxOpd77A2 ; ANDIRNc and #n - register & immediate + ANDIRNc 7 +NEWSYM FxOpd78A2 ; ANDIRNc and #n - register & immediate + ANDIRNc 8 +NEWSYM FxOpd79A2 ; ANDIRNc and #n - register & immediate + ANDIRNc 9 +NEWSYM FxOpd7AA2 ; ANDIRNc and #n - register & immediate + ANDIRNc 10 +NEWSYM FxOpd7BA2 ; ANDIRNc and #n - register & immediate + ANDIRNc 11 +NEWSYM FxOpd7CA2 ; ANDIRNc and #n - register & immediate + ANDIRNc 12 +NEWSYM FxOpd7DA2 ; ANDIRNc and #n - register & immediate + ANDIRNc 13 +NEWSYM FxOpd7EA2 ; ANDIRNc and #n - register & immediate + ANDIRNc 14 +NEWSYM FxOpd7FA2 ; ANDIRNc and #n - register & immediate + ANDIRNc 15 + +NEWSYM FxOpd71A3 ; BICIRNc register & ~immediate + BICIRNc 1 ^ 0FFFFh +NEWSYM FxOpd72A3 ; BICIRNc register & ~immediate + BICIRNc 2 ^ 0FFFFh +NEWSYM FxOpd73A3 ; BICIRNc register & ~immediate + BICIRNc 3 ^ 0FFFFh +NEWSYM FxOpd74A3 ; BICIRNc register & ~immediate + BICIRNc 4 ^ 0FFFFh +NEWSYM FxOpd75A3 ; BICIRNc register & ~immediate + BICIRNc 5 ^ 0FFFFh +NEWSYM FxOpd76A3 ; BICIRNc register & ~immediate + BICIRNc 6 ^ 0FFFFh +NEWSYM FxOpd77A3 ; BICIRNc register & ~immediate + BICIRNc 7 ^ 0FFFFh +NEWSYM FxOpd78A3 ; BICIRNc register & ~immediate + BICIRNc 8 ^ 0FFFFh +NEWSYM FxOpd79A3 ; BICIRNc register & ~immediate + BICIRNc 9 ^ 0FFFFh +NEWSYM FxOpd7AA3 ; BICIRNc register & ~immediate + BICIRNc 10 ^ 0FFFFh +NEWSYM FxOpd7BA3 ; BICIRNc register & ~immediate + BICIRNc 11 ^ 0FFFFh +NEWSYM FxOpd7CA3 ; BICIRNc register & ~immediate + BICIRNc 12 ^ 0FFFFh +NEWSYM FxOpd7DA3 ; BICIRNc register & ~immediate + BICIRNc 13 ^ 0FFFFh +NEWSYM FxOpd7EA3 ; BICIRNc register & ~immediate + BICIRNc 14 ^ 0FFFFh +NEWSYM FxOpd7FA3 ; BICIRNc register & ~immediate + BICIRNc 15 ^ 0FFFFh + +NEWSYM FxOpd80 ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 0 +NEWSYM FxOpd81 ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 1 +NEWSYM FxOpd82 ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 2 +NEWSYM FxOpd83 ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 3 +NEWSYM FxOpd84 ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 4 +NEWSYM FxOpd85 ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 5 +NEWSYM FxOpd86 ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 6 +NEWSYM FxOpd87 ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 7 +NEWSYM FxOpd88 ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 8 +NEWSYM FxOpd89 ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 9 +NEWSYM FxOpd8A ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 10 +NEWSYM FxOpd8B ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 11 +NEWSYM FxOpd8C ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 12 +NEWSYM FxOpd8D ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 13 +NEWSYM FxOpd8E ; MULTRNc 8 bit to 16 bit signed multiply, register * register + MULTRNc 14 +NEWSYM FxOpd8F ; MULTRNc 8 bit to 16 bit signed multiply, register * register + FETCHPIPE + mov ebx,ebp + mov al,byte [esi] ; Read Source + sub ebx,[SfxCPB] + imul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn + +NEWSYM FxOpd80A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 0 +NEWSYM FxOpd81A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 1 +NEWSYM FxOpd82A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 2 +NEWSYM FxOpd83A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 3 +NEWSYM FxOpd84A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 4 +NEWSYM FxOpd85A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 5 +NEWSYM FxOpd86A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 6 +NEWSYM FxOpd87A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 7 +NEWSYM FxOpd88A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 8 +NEWSYM FxOpd89A1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 9 +NEWSYM FxOpd8AA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 10 +NEWSYM FxOpd8BA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 11 +NEWSYM FxOpd8CA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 12 +NEWSYM FxOpd8DA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 13 +NEWSYM FxOpd8EA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + UMULTRNc 14 +NEWSYM FxOpd8FA1 ; UMULRN 8 bit to 16 bit unsigned multiply, register * register + FETCHPIPE + mov ebx,ebp + mov al,byte [esi] ; Read Source + sub ebx,[SfxCPB] + mul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn + +NEWSYM FxOpd80A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 0 +NEWSYM FxOpd81A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 1 +NEWSYM FxOpd82A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 2 +NEWSYM FxOpd83A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 3 +NEWSYM FxOpd84A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 4 +NEWSYM FxOpd85A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 5 +NEWSYM FxOpd86A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 6 +NEWSYM FxOpd87A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 7 +NEWSYM FxOpd88A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 8 +NEWSYM FxOpd89A2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 9 +NEWSYM FxOpd8AA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 10 +NEWSYM FxOpd8BA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 11 +NEWSYM FxOpd8CA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 12 +NEWSYM FxOpd8DA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 13 +NEWSYM FxOpd8EA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 14 +NEWSYM FxOpd8FA2 ; MULIRN 8 bit to 16 bit signed multiply, register * immediate + MULTIRNc 15 + +NEWSYM FxOpd80A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 0 +NEWSYM FxOpd81A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 1 +NEWSYM FxOpd82A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 2 +NEWSYM FxOpd83A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 3 +NEWSYM FxOpd84A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 4 +NEWSYM FxOpd85A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 5 +NEWSYM FxOpd86A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 6 +NEWSYM FxOpd87A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 7 +NEWSYM FxOpd88A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 8 +NEWSYM FxOpd89A3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 9 +NEWSYM FxOpd8AA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 10 +NEWSYM FxOpd8BA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 11 +NEWSYM FxOpd8CA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 12 +NEWSYM FxOpd8DA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 13 +NEWSYM FxOpd8EA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 14 +NEWSYM FxOpd8FA3 ;UMULIRN 8 bit to 16 bit unsigned multiply, register * immediate + UMULTIRNc 15 + +NEWSYM FxOpd90 ; SBK store word to last accessed RAM address ; V + mov ebx,[SfxLastRamAdr] ; Load last ram address + mov eax,[esi] ; Read Source + FETCHPIPE + mov [ebx],al ; Store Word + sub ebx,[SfxRAMMem] + xor ebx,1 + add ebx,[SfxRAMMem] + inc ebp ; Increase program counter + mov [ebx],ah ; Store Word + CLRFLAGS + FXReturn + +NEWSYM FxOpd91 ; LINKc#n R11 = R15 + immediate + LINKc 1 +NEWSYM FxOpd92 ; LINKc#n R11 = R15 + immediate + LINKc 2 +NEWSYM FxOpd93 ; LINKc#n R11 = R15 + immediate + LINKc 3 +NEWSYM FxOpd94 ; LINKc#n R11 = R15 + immediate + LINKc 4 + +NEWSYM FxOpd95 ; SEX sign extend 8 bit to 16 bit ; V + movsx eax, byte [esi] ; Read Source + FETCHPIPE + and eax,0FFFFh + inc ebp + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpd96 ; ASR aritmethic shift right by one ; V + mov eax,[esi] ; Read Source + FETCHPIPE + mov [SfxCarry],al + and byte[SfxCarry],1 + sar ax,1 ; logic shift right + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov dword [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpd96A1 ; DIV2 aritmethic shift right by one ; V + mov eax,[esi] ; Read Source + FETCHPIPE + cmp ax,-1 + je .minusone + mov [SfxCarry],al + and byte[SfxCarry],1 + sar ax,1 ; logic shift right + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov dword [SfxSignZero],eax + CLRFLAGS + FXReturn +.minusone + mov byte[SfxCarry],1 + xor eax,eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov dword [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpd97 ; ROR rotate right by one ; V + FETCHPIPE + mov eax,[esi] ; Read Source + shr byte[SfxCarry],1 + rcr ax,1 + setc byte[SfxCarry] + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpd98 ; JMPRNc jump to address of register + JMPRNc 8 +NEWSYM FxOpd99 ; JMPRNc jump to address of register + JMPRNc 9 +NEWSYM FxOpd9A ; JMPRNc jump to address of register + JMPRNc 10 +NEWSYM FxOpd9B ; JMPRNc jump to address of register + JMPRNc 11 +NEWSYM FxOpd9C ; JMPRNc jump to address of register + JMPRNc 12 +NEWSYM FxOpd9D ; JMPRNc jump to address of register + JMPRNc 13 + +NEWSYM FxOpd98A1 ; LJMPRNc set program bank to source register and jump to address of register + LJMPRNc 8 +NEWSYM FxOpd99A1 ; LJMPRNc set program bank to source register and jump to address of register + LJMPRNc 9 +NEWSYM FxOpd9AA1 ; LJMPRNc set program bank to source register and jump to address of register + LJMPRNc 10 +NEWSYM FxOpd9BA1 ; LJMPRNc set program bank to source register and jump to address of register + LJMPRNc 11 +NEWSYM FxOpd9CA1 ; LJMPRNc set program bank to source register and jump to address of register + LJMPRNc 12 +NEWSYM FxOpd9DA1 ; LJMPRNc set program bank to source register and jump to address of register + LJMPRNc 13 + +NEWSYM FxOpd9E ; LOB set upper byte to zero (keep low byte) ; V + mov eax,[esi] ; Read Source + FETCHPIPE + and eax,0FFh + inc ebp + mov [edi],eax ; Write Destination + shl eax,8 + mov dword [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpd9F ; FMULT 16 bit to 32 bit signed multiplication, upper 16 bits only + ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR6] + FETCHPIPE + imul bx + inc ebp + and edx,0FFFFh + mov [SfxSignZero],edx + mov [edi],edx ; Write Destination + shr ax,15 + mov [SfxCarry],al + CLRFLAGS + FXReturn + +NEWSYM FxOpd9FA1 ; LMULT 16 bit to 32 bit signed multiplication ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR6] + FETCHPIPE + imul bx + and edx,0FFFFh + inc ebp + mov [edi],edx ; Write Destination + mov [SfxR4],ax + mov [SfxSignZero],edx + shr ax,15 + mov [SfxCarry],al + CLRFLAGS + FXReturn + +NEWSYM FxOpdA0 ; IBTRNc,#PP immediate byte transfer + IBTRNc 0 +NEWSYM FxOpdA1 ; IBTRNc,#PP immediate byte transfer + IBTRNc 1 +NEWSYM FxOpdA2 ; IBTRNc,#PP immediate byte transfer + IBTRNc 2 +NEWSYM FxOpdA3 ; IBTRNc,#PP immediate byte transfer + IBTRNc 3 +NEWSYM FxOpdA4 ; IBTRNc,#PP immediate byte transfer + IBTRNc 4 +NEWSYM FxOpdA5 ; IBTRNc,#PP immediate byte transfer + IBTRNc 5 +NEWSYM FxOpdA6 ; IBTRNc,#PP immediate byte transfer + IBTRNc 6 +NEWSYM FxOpdA7 ; IBTRNc,#PP immediate byte transfer + IBTRNc 7 +NEWSYM FxOpdA8 ; IBTRNc,#PP immediate byte transfer + IBTRNc 8 +NEWSYM FxOpdA9 ; IBTRNc,#PP immediate byte transfer + IBTRNc 9 +NEWSYM FxOpdAA ; IBTRNc,#PP immediate byte transfer + IBTRNc 10 +NEWSYM FxOpdAB ; IBTRNc,#PP immediate byte transfer + IBTRNc 11 +NEWSYM FxOpdAC ; IBTRNc,#PP immediate byte transfer + IBTRNc 12 +NEWSYM FxOpdAD ; IBTRNc,#PP immediate byte transfer + IBTRNc 13 +NEWSYM FxOpdAE ; IBTRNc,#PP immediate byte transfer + movsx eax,byte[ebp] + mov cl,[ebp+1] + add ebp,2 + mov [SfxR0+14*4],ax + UpdateR14 + CLRFLAGS + FXReturn +NEWSYM FxOpdAF ; IBTRNc,#PP immediate byte transfer + movsx eax,byte[ebp] + mov cl,[ebp+1] + and eax,0FFFFh + mov ebp,[SfxCPB] + add ebp,eax + CLRFLAGS + FXReturn + +NEWSYM FxOpdA0A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 0 +NEWSYM FxOpdA1A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 1 +NEWSYM FxOpdA2A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 2 +NEWSYM FxOpdA3A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 3 +NEWSYM FxOpdA4A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 4 +NEWSYM FxOpdA5A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 5 +NEWSYM FxOpdA6A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 6 +NEWSYM FxOpdA7A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 7 +NEWSYM FxOpdA8A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 8 +NEWSYM FxOpdA9A1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 9 +NEWSYM FxOpdAAA1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 10 +NEWSYM FxOpdABA1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 11 +NEWSYM FxOpdACA1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 12 +NEWSYM FxOpdADA1 ; LMS rn,(yy) load word from RAM (short address) + LMSRNc 13 +NEWSYM FxOpdAEA1 ; LMS rn,(yy) load word from RAM (short address) + xor eax,eax + mov al,[ebp] + add eax,eax + inc ebp + add eax,[SfxRAMMem] + mov cl,[ebp] + mov dword [SfxLastRamAdr],eax + mov ebx,[eax] ; Read word from ram + inc ebp + mov [SfxR0+14*4],bx ; Write data + UpdateR14 + CLRFLAGS + FXReturn +NEWSYM FxOpdAFA1 ; LMS rn,(yy) load word from RAM (short address) + xor eax,eax + mov al,[ebp] + add eax,eax + inc ebp + add eax,[SfxRAMMem] + mov cl,[ebp] + mov dword [SfxLastRamAdr],eax + mov ebx,[eax] ; Read word from ram + and ebx,0FFFFh + mov ebp,[SfxCPB] + add ebp,ebx + CLRFLAGS + FXReturn + +NEWSYM FxOpdA0A2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 0 +NEWSYM FxOpdA1A2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 1 +NEWSYM FxOpdA2A2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 2 +NEWSYM FxOpdA3A2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 3 +NEWSYM FxOpdA4A2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 4 +NEWSYM FxOpdA5A2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 5 +NEWSYM FxOpdA6A2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 6 +NEWSYM FxOpdA7A2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 7 +NEWSYM FxOpdA8A2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 8 +NEWSYM FxOpdA9A2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 9 +NEWSYM FxOpdAAA2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 10 +NEWSYM FxOpdABA2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 11 +NEWSYM FxOpdACA2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 12 +NEWSYM FxOpdADA2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 13 +NEWSYM FxOpdAEA2 ; SMS (yy),rn store word in RAM (short address) + SMSRNc 14 +NEWSYM FxOpdAFA2 ; SMS (yy),rn store word in RAM (short address) + xor eax,eax + mov ebx,ebp + sub ebx,[SfxCPB] + mov al,[ebp] + inc ebp + add eax,eax + FETCHPIPE + add eax,[SfxRAMMem] + mov dword [SfxLastRamAdr],eax + inc ebp + mov [eax],bx ; Write word to ram + CLRFLAGS + FXReturn + +NEWSYM FxOpdB0 ; FROM rn set source register + FROMRNd 0 +NEWSYM FxOpdB1 ; FROM rn set source register + FROMRNd 1 +NEWSYM FxOpdB2 ; FROM rn set source register + FROMRNd 2 +NEWSYM FxOpdB3 ; FROM rn set source register + FROMRNd 3 +NEWSYM FxOpdB4 ; FROM rn set source register + FROMRNd 4 +NEWSYM FxOpdB5 ; FROM rn set source register + FROMRNd 5 +NEWSYM FxOpdB6 ; FROM rn set source register + FROMRNd 6 +NEWSYM FxOpdB7 ; FROM rn set source register + FROMRNd 7 +NEWSYM FxOpdB8 ; FROM rn set source register + FROMRNd 8 +NEWSYM FxOpdB9 ; FROM rn set source register + FROMRNd 9 +NEWSYM FxOpdBA ; FROM rn set source register + FROMRNd 10 +NEWSYM FxOpdBB ; FROM rn set source register + FROMRNd 11 +NEWSYM FxOpdBC ; FROM rn set source register + FROMRNd 12 +NEWSYM FxOpdBD ; FROM rn set source register + FROMRNd 13 +NEWSYM FxOpdBE ; FROM rn set source register + FROMRNd 14 +NEWSYM FxOpdBF ; FROM rn set source register + FETCHPIPE + mov esi,SfxR0+15*4 + inc ebp ; Increase program counter + mov eax,ebp + sub eax,[SfxCPB] + mov [SfxR15],eax + call [FxTableb+ecx*4] + mov esi,SfxR0 + FXReturn + +NEWSYM FxOpdC0 ; HIB move high-byte to low-byte ; V + mov eax,[esi] ; Read Source + FETCHPIPE + and eax,0FF00h + mov dword [SfxSignZero],eax + shr eax,8 + inc ebp + mov [edi],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpdC1 ; OR rn or rn + ORRNc 1 +NEWSYM FxOpdC2 ; OR rn or rn + ORRNc 2 +NEWSYM FxOpdC3 ; OR rn or rn + ORRNc 3 +NEWSYM FxOpdC4 ; OR rn or rn + ORRNc 4 +NEWSYM FxOpdC5 ; OR rn or rn + ORRNc 5 +NEWSYM FxOpdC6 ; OR rn or rn + ORRNc 6 +NEWSYM FxOpdC7 ; OR rn or rn + ORRNc 7 +NEWSYM FxOpdC8 ; OR rn or rn + ORRNc 8 +NEWSYM FxOpdC9 ; OR rn or rn + ORRNc 9 +NEWSYM FxOpdCA ; OR rn or rn + ORRNc 10 +NEWSYM FxOpdCB ; OR rn or rn + ORRNc 11 +NEWSYM FxOpdCC ; OR rn or rn + ORRNc 12 +NEWSYM FxOpdCD ; OR rn or rn + ORRNc 13 +NEWSYM FxOpdCE ; OR rn or rn + ORRNc 14 +NEWSYM FxOpdCF ; OR rn or rn + mov eax,[esi] ; Read Source + mov ebx,ebp + FETCHPIPE + sub ebx,[SfxCPB] + or eax,ebx + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpdC1A1 ; XOR rn xor rn + XORRNc 1 +NEWSYM FxOpdC2A1 ; XOR rn xor rn + XORRNc 2 +NEWSYM FxOpdC3A1 ; XOR rn xor rn + XORRNc 3 +NEWSYM FxOpdC4A1 ; XOR rn xor rn + XORRNc 4 +NEWSYM FxOpdC5A1 ; XOR rn xor rn + XORRNc 5 +NEWSYM FxOpdC6A1 ; XOR rn xor rn + XORRNc 6 +NEWSYM FxOpdC7A1 ; XOR rn xor rn + XORRNc 7 +NEWSYM FxOpdC8A1 ; XOR rn xor rn + XORRNc 8 +NEWSYM FxOpdC9A1 ; XOR rn xor rn + XORRNc 9 +NEWSYM FxOpdCAA1 ; XOR rn xor rn + XORRNc 10 +NEWSYM FxOpdCBA1 ; XOR rn xor rn + XORRNc 11 +NEWSYM FxOpdCCA1 ; XOR rn xor rn + XORRNc 12 +NEWSYM FxOpdCDA1 ; XOR rn xor rn + XORRNc 13 +NEWSYM FxOpdCEA1 ; XOR rn xor rn + XORRNc 14 +NEWSYM FxOpdCFA1 ; XOR rn xor rn + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebx,ebp + sub ebx,[SfxCPB] + xor eax,ebx + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpdC1A2 ; OR #n OR #n + ORIc 1 +NEWSYM FxOpdC2A2 ; OR #n OR #n + ORIc 2 +NEWSYM FxOpdC3A2 ; OR #n OR #n + ORIc 3 +NEWSYM FxOpdC4A2 ; OR #n OR #n + ORIc 4 +NEWSYM FxOpdC5A2 ; OR #n OR #n + ORIc 5 +NEWSYM FxOpdC6A2 ; OR #n OR #n + ORIc 6 +NEWSYM FxOpdC7A2 ; OR #n OR #n + ORIc 7 +NEWSYM FxOpdC8A2 ; OR #n OR #n + ORIc 8 +NEWSYM FxOpdC9A2 ; OR #n OR #n + ORIc 9 +NEWSYM FxOpdCAA2 ; OR #n OR #n + ORIc 10 +NEWSYM FxOpdCBA2 ; OR #n OR #n + ORIc 11 +NEWSYM FxOpdCCA2 ; OR #n OR #n + ORIc 12 +NEWSYM FxOpdCDA2 ; OR #n OR #n + ORIc 13 +NEWSYM FxOpdCEA2 ; OR #n OR #n + ORIc 14 +NEWSYM FxOpdCFA2 ; OR #n OR #n + ORIc 15 + +NEWSYM FxOpdC1A3 ; XOR #n xor #n + XORIc 1 +NEWSYM FxOpdC2A3 ; XOR #n xor #n + XORIc 2 +NEWSYM FxOpdC3A3 ; XOR #n xor #n + XORIc 3 +NEWSYM FxOpdC4A3 ; XOR #n xor #n + XORIc 4 +NEWSYM FxOpdC5A3 ; XOR #n xor #n + XORIc 5 +NEWSYM FxOpdC6A3 ; XOR #n xor #n + XORIc 6 +NEWSYM FxOpdC7A3 ; XOR #n xor #n + XORIc 7 +NEWSYM FxOpdC8A3 ; XOR #n xor #n + XORIc 8 +NEWSYM FxOpdC9A3 ; XOR #n xor #n + XORIc 9 +NEWSYM FxOpdCAA3 ; XOR #n xor #n + XORIc 10 +NEWSYM FxOpdCBA3 ; XOR #n xor #n + XORIc 11 +NEWSYM FxOpdCCA3 ; XOR #n xor #n + XORIc 12 +NEWSYM FxOpdCDA3 ; XOR #n xor #n + XORIc 13 +NEWSYM FxOpdCEA3 ; XOR #n xor #n + XORIc 14 +NEWSYM FxOpdCFA3 ; XOR #n xor #n + XORIc 15 + +NEWSYM FxOpdD0 ; INC rn increase by one + INCRNc 0 +NEWSYM FxOpdD1 ; INC rn increase by one + INCRNc 1 +NEWSYM FxOpdD2 ; INC rn increase by one + INCRNc 2 +NEWSYM FxOpdD3 ; INC rn increase by one + INCRNc 3 +NEWSYM FxOpdD4 ; INC rn increase by one + INCRNc 4 +NEWSYM FxOpdD5 ; INC rn increase by one + INCRNc 5 +NEWSYM FxOpdD6 ; INC rn increase by one + INCRNc 6 +NEWSYM FxOpdD7 ; INC rn increase by one + INCRNc 7 +NEWSYM FxOpdD8 ; INC rn increase by one + INCRNc 8 +NEWSYM FxOpdD9 ; INC rn increase by one + INCRNc 9 +NEWSYM FxOpdDA ; INC rn increase by one + INCRNc 10 +NEWSYM FxOpdDB ; INC rn increase by one + INCRNc 11 +NEWSYM FxOpdDC ; INC rn increase by one + INCRNc 12 +NEWSYM FxOpdDD ; INC rn increase by one + INCRNc 13 +NEWSYM FxOpdDE ; INC rn increase by one + FETCHPIPE + mov eax,[SfxR0+14*4] ; Read Source + inc ax + mov [SfxR0+14*4],eax + mov [SfxSignZero],eax + CLRFLAGS + inc ebp + UpdateR14 + FXReturn + +NEWSYM FxOpdDF ; GETC transfer ROM buffer to color register + mov eax,[SfxRomBuffer] + FETCHPIPE + mov eax,[eax] + test byte[SfxPOR],04h + jz .nohighnibble + mov bl,al + shr bl,4 + and al,0F0h + or al,bl +.nohighnibble + test byte[SfxPOR],08h + jnz .preserveupper + cmp [SfxCOLR],al + je .nocolchange + mov [SfxCOLR],al + and eax,0FFh + mov ebx,[fxbit01+eax*4] + mov [fxbit01pcal],ebx + mov ebx,[fxbit23+eax*4] + mov [fxbit23pcal],ebx + mov ebx,[fxbit45+eax*4] + mov [fxbit45pcal],ebx + mov ebx,[fxbit67+eax*4] + mov [fxbit67pcal],ebx +.nocolchange + CLRFLAGS + inc ebp ; Increase program counter + FXReturn +.preserveupper + mov bl,[SfxCOLR] + and al,0Fh + and bl,0F0h + or al,bl + cmp [SfxCOLR],al + je .nocolchange + mov [SfxCOLR],al + and eax,0FFh + mov ebx,[fxbit01+eax*4] + mov [fxbit01pcal],ebx + mov ebx,[fxbit23+eax*4] + mov [fxbit23pcal],ebx + mov ebx,[fxbit45+eax*4] + mov [fxbit45pcal],ebx + mov ebx,[fxbit67+eax*4] + mov [fxbit67pcal],ebx + CLRFLAGS + inc ebp ; Increase program counter + FXReturn + +NEWSYM FxOpdDFA2 ; RAMB set current RAM bank ; Verified + mov eax,[esi] ; Read Source + mov ebx,[SfxnRamBanks] + FETCHPIPE + dec ebx + and eax,ebx + mov dword [SfxRAMBR],eax + shl eax,16 + add eax,[sfxramdata] + mov dword [SfxRAMMem],eax + CLRFLAGS + inc ebp + FXReturn + +NEWSYM FxOpdDFA3 ; ROMB set current ROM bank ; Verified + mov eax,[esi] ; Read Source + and eax,07Fh + FETCHPIPE + mov dword [SfxROMBR],eax + mov eax,[SfxMemTable+eax*4] + mov [SfxCROM],eax + CLRFLAGS + inc ebp + FXReturn + +NEWSYM FxOpdE0 ; DEC rn decrement by one + DECRNc 0 +NEWSYM FxOpdE1 ; DEC rn decrement by one + DECRNc 1 +NEWSYM FxOpdE2 ; DEC rn decrement by one + DECRNc 2 +NEWSYM FxOpdE3 ; DEC rn decrement by one + DECRNc 3 +NEWSYM FxOpdE4 ; DEC rn decrement by one + DECRNc 4 +NEWSYM FxOpdE5 ; DEC rn decrement by one + DECRNc 5 +NEWSYM FxOpdE6 ; DEC rn decrement by one + DECRNc 6 +NEWSYM FxOpdE7 ; DEC rn decrement by one + DECRNc 7 +NEWSYM FxOpdE8 ; DEC rn decrement by one + DECRNc 8 +NEWSYM FxOpdE9 ; DEC rn decrement by one + DECRNc 9 +NEWSYM FxOpdEA ; DEC rn decrement by one + DECRNc 10 +NEWSYM FxOpdEB ; DEC rn decrement by one + DECRNc 11 +NEWSYM FxOpdEC ; DEC rn decrement by one + DECRNc 12 +NEWSYM FxOpdED ; DEC rn decrement by one + DECRNc 13 +NEWSYM FxOpdEE ; DEC rn decrement by one + dec word[SfxR0+14*4] + FETCHPIPE + mov eax,[SfxR0+14*4] ; Read Source + mov [SfxSignZero],eax + UpdateR14 + CLRFLAGS + inc ebp + FXReturn + +NEWSYM FxOpdEF ; getb get byte from ROM at address R14 ; V + FETCHPIPE + mov eax,[SfxRomBuffer] + inc ebp + mov eax,[eax] + and eax,0FFh +; cmp edi,SfxR15 +; je .nor15 + mov [edi],eax ; Write DREG + CLRFLAGS + FXReturn +.nor15 + or eax,8000h + mov [edi],eax ; Write DREG + CLRFLAGS + FXReturn + + add eax,ebp + sub eax,[SfxCPB] + mov [SfxR15],eax + CLRFLAGS + FXReturn + +NEWSYM FxOpdEFA1 ; getbh get high-byte from ROM at address R14 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxRomBuffer] + and eax,0FFh + FETCHPIPE + mov ah,[ebx] + inc ebp + mov [edi],eax ; Write DREG + CLRFLAGS + FXReturn + +NEWSYM FxOpdEFA2 ; getbl get low-byte from ROM at address R14 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxRomBuffer] + and eax,0FF00h + FETCHPIPE + mov al,[ebx] + inc ebp + mov [edi],eax ; Write DREG + CLRFLAGS + FXReturn + +NEWSYM FxOpdEFA3 ; getbs get sign extended byte from ROM at address R14 ; V + mov ebx,[SfxRomBuffer] + FETCHPIPE + movsx eax,byte[ebx] + inc ebp + mov [edi],ax ; Write DREG + CLRFLAGS + FXReturn + +NEWSYM FxOpdF0 ; IWT RN,#xx immediate word transfer to register + IWTRNc 0 +NEWSYM FxOpdF1 ; IWT RN,#xx immediate word transfer to register + IWTRNc 1 +NEWSYM FxOpdF2 ; IWT RN,#xx immediate word transfer to register + IWTRNc 2 +NEWSYM FxOpdF3 ; IWT RN,#xx immediate word transfer to register + IWTRNc 3 +NEWSYM FxOpdF4 ; IWT RN,#xx immediate word transfer to register + IWTRNc 4 +NEWSYM FxOpdF5 ; IWT RN,#xx immediate word transfer to register + IWTRNc 5 +NEWSYM FxOpdF6 ; IWT RN,#xx immediate word transfer to register + IWTRNc 6 +NEWSYM FxOpdF7 ; IWT RN,#xx immediate word transfer to register + IWTRNc 7 +NEWSYM FxOpdF8 ; IWT RN,#xx immediate word transfer to register + IWTRNc 8 +NEWSYM FxOpdF9 ; IWT RN,#xx immediate word transfer to register + IWTRNc 9 +NEWSYM FxOpdFA ; IWT RN,#xx immediate word transfer to register + IWTRNc 10 +NEWSYM FxOpdFB ; IWT RN,#xx immediate word transfer to register + IWTRNc 11 +NEWSYM FxOpdFC ; IWT RN,#xx immediate word transfer to register + IWTRNc 12 +NEWSYM FxOpdFD ; IWT RN,#xx immediate word transfer to register + IWTRNc 13 +NEWSYM FxOpdFE ; IWT RN,#xx immediate word transfer to register + mov eax,[ebp] + mov cl,[ebp+2] + and eax,0FFFFh + add ebp,3 + mov [SfxR0+14*4],eax + UpdateR14 + CLRFLAGS + FXReturn +NEWSYM FxOpdFF ; IWT RN,#xx immediate word transfer to register + mov eax,[ebp] + mov cl,[ebp+2] + and eax,0FFFFh + mov ebp,[SfxCPB] + add ebp,eax + CLRFLAGS + FXReturn + +NEWSYM FxOpdF0A1 ; LM RN,(XX) load word from RAM + LMRNc 0 +NEWSYM FxOpdF1A1 ; LM RN,(XX) load word from RAM + LMRNc 1 +NEWSYM FxOpdF2A1 ; LM RN,(XX) load word from RAM + LMRNc 2 +NEWSYM FxOpdF3A1 ; LM RN,(XX) load word from RAM + LMRNc 3 +NEWSYM FxOpdF4A1 ; LM RN,(XX) load word from RAM + LMRNc 4 +NEWSYM FxOpdF5A1 ; LM RN,(XX) load word from RAM + LMRNc 5 +NEWSYM FxOpdF6A1 ; LM RN,(XX) load word from RAM + LMRNc 6 +NEWSYM FxOpdF7A1 ; LM RN,(XX) load word from RAM + LMRNc 7 +NEWSYM FxOpdF8A1 ; LM RN,(XX) load word from RAM + LMRNc 8 +NEWSYM FxOpdF9A1 ; LM RN,(XX) load word from RAM + LMRNc 9 +NEWSYM FxOpdFAA1 ; LM RN,(XX) load word from RAM + LMRNc 10 +NEWSYM FxOpdFBA1 ; LM RN,(XX) load word from RAM + LMRNc 11 +NEWSYM FxOpdFCA1 ; LM RN,(XX) load word from RAM + LMRNc 12 +NEWSYM FxOpdFDA1 ; LM RN,(XX) load word from RAM + LMRNc 13 +NEWSYM FxOpdFEA1 ; LM RN,(XX) load word from RAM + xor eax,eax + mov cl,[ebp+2] + mov ax,[ebp] + mov ebx,[SfxRAMMem] + mov [SfxLastRamAdr],eax + add [SfxLastRamAdr],ebx + mov dl,[eax+ebx] + xor eax,1 + add ebp,3 + mov dh,[eax+ebx] + mov word [SfxR0+14*4],dx ; Store Word + UpdateR14 + CLRFLAGS + FXReturn +NEWSYM FxOpdFFA1 ; LM RN,(XX) load word from RAM + FETCHPIPE + mov eax,ecx + inc ebp + FETCHPIPE + inc ebp + mov ah,cl + FETCHPIPE + mov ebx,[SfxRAMMem] + mov [SfxLastRamAdr],eax + add [SfxLastRamAdr],ebx + mov dl,[eax+ebx] + xor eax,1 + mov dh,[eax+ebx] + and edx,0FFFFh + mov ebp,[SfxCPB] + add ebp,edx + CLRFLAGS + FXReturn + +NEWSYM FxOpdF0A2 ; SM (XX),RN store word in RAM + SMRNc 0 +NEWSYM FxOpdF1A2 ; SM (XX),RN store word in RAM + SMRNc 1 +NEWSYM FxOpdF2A2 ; SM (XX),RN store word in RAM + SMRNc 2 +NEWSYM FxOpdF3A2 ; SM (XX),RN store word in RAM + SMRNc 3 +NEWSYM FxOpdF4A2 ; SM (XX),RN store word in RAM + SMRNc 4 +NEWSYM FxOpdF5A2 ; SM (XX),RN store word in RAM + SMRNc 5 +NEWSYM FxOpdF6A2 ; SM (XX),RN store word in RAM + SMRNc 6 +NEWSYM FxOpdF7A2 ; SM (XX),RN store word in RAM + SMRNc 7 +NEWSYM FxOpdF8A2 ; SM (XX),RN store word in RAM + SMRNc 8 +NEWSYM FxOpdF9A2 ; SM (XX),RN store word in RAM + SMRNc 9 +NEWSYM FxOpdFAA2 ; SM (XX),RN store word in RAM + SMRNc 10 +NEWSYM FxOpdFBA2 ; SM (XX),RN store word in RAM + SMRNc 11 +NEWSYM FxOpdFCA2 ; SM (XX),RN store word in RAM + SMRNc 12 +NEWSYM FxOpdFDA2 ; SM (XX),RN store word in RAM + SMRNc 13 +NEWSYM FxOpdFEA2 ; SM (XX),RN store word in RAM + SMRNc 14 +NEWSYM FxOpdFFA2 ; SM (XX),RN store word in RAM + FETCHPIPE + mov ebx,ebp + sub ebx,[SfxCPB] + mov eax,ecx + inc ebp + FETCHPIPE + inc ebp + mov ah,cl + FETCHPIPE + mov dx,bx + mov ebx,[SfxRAMMem] + mov [SfxLastRamAdr],eax + add [SfxLastRamAdr],ebx + mov [eax+ebx],dl + xor eax,1 + inc ebp + mov [eax+ebx],dh + CLRFLAGS + FXReturn + +NEWSYM FxEmu2CAsmEnd diff --git a/i386/fxemu2c.mac b/i386/fxemu2c.mac new file mode 100644 index 00000000..4595e121 --- /dev/null +++ b/i386/fxemu2c.mac @@ -0,0 +1,528 @@ +;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com ) +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;as published by the Free Software Foundation; either +;version 2 of the License, or (at your option) any later +;version. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + + + + + + + + +%macro FXReturn 0 + dec dword [NumberOfOpcodes] + jmp [FxTabled+ecx*4] + ALIGN32 +%endmacro + +%macro FXReturn2 0 + dec dword [NumberOfOpcodes] + js %%endloop + jmp [FxTabled+ecx*4] +%%endloop + jmp FXEndLoop +; jmp [FxTabled+ecx*4] + ALIGN32 +%endmacro + +%macro TORNd 1 ; V + FETCHPIPE + mov edi, SfxR0+%1*4 + inc ebp ; Increase program counter + call [FxTable+ecx*4] + mov edi,SfxR0 + FXReturn +%endmacro + +%macro WITHc 1 ; Verified. + FETCHPIPE + mov esi,SfxR0+%1*4 + mov edi,SfxR0+%1*4 + mov dword [SfxB],1 + inc ebp ; Increase program counter + call [FxTablec+ecx*4] + mov esi,SfxR0 + mov edi,SfxR0 + mov dword [SfxB],0 ; Clear B Flag + FXReturn +%endmacro + +%macro STWRNc 1 ; V + mov eax,[SfxR0+%1*4] ; Read register + mov ebx,[SfxRAMMem] + mov dword [SfxLastRamAdr],eax ; Save last ram address + add dword [SfxLastRamAdr],ebx ; Save last ram address + mov edx,[esi] ; Read Source + FETCHPIPE + mov [ebx+eax],dl ; Store Word + xor eax,1 + inc ebp ; Increase program counter + mov [ebx+eax],dh ; Store Word + CLRFLAGS + FXReturn +%endmacro + +%macro STBRNc 1 ; V + mov eax,[SfxR0+%1*4] ; Read register + FETCHPIPE + add eax,[SfxRAMMem] + mov dword [SfxLastRamAdr],eax ; Save last ram address + mov ebx,[esi] ; Read Source + mov byte [eax],bl ; Store Byte + CLRFLAGS + inc ebp ; Increase program counter + FXReturn +%endmacro + +%macro LDWRNc 1 ; V + mov eax,[SfxR0+%1*4] ; Read register + mov ebx,[SfxRAMMem] + mov dword [SfxLastRamAdr],eax ; Save last ram address + FETCHPIPE + mov dl,[ebx+eax] ; Store Word + add dword [SfxLastRamAdr],ebx ; Save last ram address + xor eax,1 + and edx,0FFFFh + inc ebp ; Increase program counter + mov dh,[ebx+eax] ; Store Word + mov [edi],edx ; Read Source + CLRFLAGS + FXReturn +%endmacro + +%macro LDBRNc 1 ; V + mov eax,[SfxR0+%1*4] ; Read register + FETCHPIPE + add eax,[SfxRAMMem] + xor ebx,ebx + mov dword [SfxLastRamAdr],eax ; Save last ram address + mov bl,[eax] ; Read Byte + inc ebp ; Increase program counter + mov [edi],ebx ; Store Result + CLRFLAGS + FXReturn +%endmacro + +%macro ADDRNc 1 ; V + mov eax, [esi] ; Read Source + mov ebx, [SfxR0+%1*4] + FETCHPIPE + add ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro ADCRNc 1 ; V + FETCHPIPE + mov eax, [esi] ; Read Source + mov ebx, [SfxR0+%1*4] + shr byte[SfxCarry],1 + adc ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro ADIRNc 1 ; V + mov eax, [esi] ; Read Source + FETCHPIPE + add ax,%1 + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro ADCIRNc 1 ; V + FETCHPIPE + mov eax, [esi] ; Read Source + shr byte[SfxCarry],1 + adc ax,%1 + seto byte[SfxOverflow] + setc byte[SfxCarry] + mov [SfxSignZero],eax + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro SUBRNc 1 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] + FETCHPIPE + sub ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + FXReturn +%endmacro + +%macro SBCRNc 1 ; V + FETCHPIPE + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] + cmp byte[SfxCarry],1 + sbb ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + FXReturn +%endmacro + +%macro SUBIRNc 1 ; V + mov eax,[esi] ; Read Source + FETCHPIPE + sub ax,%1 + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + inc ebp ; Increase program counter + mov [edi],eax ; Write Destination + mov [SfxSignZero],eax + CLRFLAGS + FXReturn +%endmacro + +%macro CMPRNc 1 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] + FETCHPIPE + sub ax,bx + seto byte[SfxOverflow] + setc byte[SfxCarry] + xor byte[SfxCarry],1 + mov [SfxSignZero],eax + CLRFLAGS + inc ebp ; Increase program counter + FXReturn +%endmacro + +%macro ANDRNc 1 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] ; Read RN + FETCHPIPE + and eax,ebx + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro BICRNc 1 ; V + mov ebx,[SfxR0+%1*4] ; Read RN + mov eax,[esi] ; Read Source + xor ebx,0FFFFh + FETCHPIPE + and eax,ebx + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro ANDIRNc 1 ; V + mov eax,[esi] ; Read Source + FETCHPIPE + and eax,%1 + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro BICIRNc 1 ; V + mov eax,[esi] ; Read Source + FETCHPIPE + and eax,%1 + inc ebp + mov dword [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro MULTRNc 1 ; V + mov al,byte [esi] ; Read Source + mov bl,byte [SfxR0+%1*4] ; Read RN + FETCHPIPE + imul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro UMULTRNc 1 ; V + mov al,byte [esi] ; Read Source + mov bl,byte [SfxR0+%1*4] ; Read RN + FETCHPIPE + mul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro MULTIRNc 1 ; V + mov al,byte [esi] ; Read Source + mov bl,%1 ; Read RN + FETCHPIPE + imul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro UMULTIRNc 1 ; V + mov al,byte [esi] ; Read Source + mov bl,%1 ; Read RN + FETCHPIPE + mul bl + inc ebp + and eax,0FFFFh + mov [SfxSignZero],eax + mov [edi],eax ; Write Destination + CLRFLAGS + FXReturn +%endmacro + +%macro LINKc 1 ; Verified. + mov eax,ebp + sub eax,[SfxCPB] + add eax,%1 + FETCHPIPE + mov word [SfxR11],ax + CLRFLAGS + inc ebp + FXReturn +%endmacro + +%macro JMPRNc 1 ; V + FETCHPIPE + mov eax,[SfxR0+%1*4] ; Read RN + mov ebp,[SfxCPB] + add ebp,eax + CLRFLAGS + FXReturn +%endmacro + +%macro LJMPRNc 1 ; V + FETCHPIPE + mov eax,[SfxR0+%1*4] + and eax,07Fh + mov byte[SfxPBR],al +; mov byte[fxtrace+eax],1 + mov eax,[SfxMemTable+eax*4] + mov [SfxCPB],eax + mov ebp,eax + add ebp,[esi] ; Read RN + mov dword [SfxCacheActive],0 + push ecx + call FxOp02 + pop ecx + dec ebp + FXReturn +%endmacro + +%macro IBTRNc 1 ; V + movsx eax,byte[ebp] + mov cl,[ebp+1] + add ebp,2 + mov [SfxR0+%1*4],ax + CLRFLAGS + FXReturn +%endmacro + +%macro LMSRNc 1 ; Verified. + xor eax,eax + mov al,[ebp] + add eax,eax + inc ebp + add eax,[SfxRAMMem] + mov cl,[ebp] + mov dword [SfxLastRamAdr],eax + mov ebx,[eax] ; Read word from ram + inc ebp + mov [SfxR0+%1*4],bx ; Write data + CLRFLAGS + FXReturn +%endmacro + +%macro SMSRNc 1 ; Verified. + xor eax,eax + mov al,[ebp] + inc ebp + add eax,eax + mov cl,[ebp] + add eax,[SfxRAMMem] + mov ebx,[SfxR0+%1*4] ; Read data + mov dword [SfxLastRamAdr],eax + inc ebp + mov [eax],bx ; Write word to ram + CLRFLAGS + FXReturn +%endmacro + +%macro FROMRNd 1 ; V + FETCHPIPE + mov esi,SfxR0+%1*4 + inc ebp ; Increase program counter + call [FxTable+ecx*4] + mov esi,SfxR0 + FXReturn +%endmacro + +%macro ORRNc 1 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] ; Read + FETCHPIPE + or eax,ebx + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + FXReturn +%endmacro + +%macro XORRNc 1 ; V + mov eax,[esi] ; Read Source + mov ebx,[SfxR0+%1*4] ; Read + FETCHPIPE + xor eax,ebx + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + FXReturn +%endmacro + +%macro ORIc 1 ; V + mov eax,[esi] ; Read Source + FETCHPIPE + or eax,%1 + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + FXReturn +%endmacro + +%macro XORIc 1 ; V + mov eax,[esi] ; Read Source + FETCHPIPE + xor eax,%1 + inc ebp + mov [edi],eax ; Write DREG + mov [SfxSignZero],eax + CLRFLAGS + FXReturn +%endmacro + +%macro INCRNc 1 ; Verified + inc word[SfxR0+%1*4] + FETCHPIPE + mov eax,[SfxR0+%1*4] ; Read Source + mov [SfxSignZero],eax + CLRFLAGS + inc ebp + FXReturn +%endmacro + +%macro DECRNc 1 ; Verified + dec word[SfxR0+%1*4] + FETCHPIPE + mov eax,[SfxR0+%1*4] ; Read Source + mov [SfxR0+%1*4],eax + mov [SfxSignZero],eax + CLRFLAGS + inc ebp + FXReturn +%endmacro + +%macro IWTRNc 1 ; aka LEA ; Verified. + mov eax,[ebp] + mov cl,[ebp+2] + and eax,0FFFFh + add ebp,3 + mov [SfxR0+%1*4],eax + CLRFLAGS + FXReturn +%endmacro + +%macro LMRNc 1 ; Verified! + xor eax,eax + mov cl,[ebp+2] + mov ax,[ebp] + mov ebx,[SfxRAMMem] + mov [SfxLastRamAdr],eax + add [SfxLastRamAdr],ebx + mov dl,[eax+ebx] + xor eax,1 + add ebp,3 + mov dh,[eax+ebx] + mov word [SfxR0+%1*4],dx ; Store Word + CLRFLAGS + FXReturn +%endmacro + +%macro SMRNc 1 ; Verified + mov ebx,[SfxR0+%1*4] + mov eax,[ebp] + mov cl,[ebp+2] + and eax,0FFFFh + mov dx,bx + mov ebx,[SfxRAMMem] + mov [SfxLastRamAdr],eax + add [SfxLastRamAdr],ebx + mov [eax+ebx],dl + xor eax,1 + add ebp,3 + mov [eax+ebx],dh + CLRFLAGS + FXReturn +%endmacro diff --git a/i386/fxtable.asm b/i386/fxtable.asm new file mode 100644 index 00000000..e41d3c92 --- /dev/null +++ b/i386/fxtable.asm @@ -0,0 +1,3557 @@ +; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. +; +; Super FX assembler emulator code +; (c) Copyright 1998, 1999 zsKnight and _Demo_. +; +; 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 "macros.mac" +EXTSYM FxTable,FxTableA1,FxTableA2,FxTableA3,FxTableb,FxTablebA1,FxTablebA2 +EXTSYM FxTablebA3,FxTablec,FxTablecA1,FxTablecA2,FxTablecA3,FxTabled +EXTSYM FxTabledA1,FxTabledA2,FxTabledA3,SfxMemTable,romdata,sfxramdata +EXTSYM sfxplottable + +EXTSYM FxOp00,FxOp01,FxOp02,FxOp03,FxOp04,FxOp05,FxOp06,FxOp07,FxOp08 +EXTSYM FxOp09,FxOp0A,FxOp0B,FxOp0C,FxOp0D,FxOp0E,FxOp0F,FxOp10,FxOp11 +EXTSYM FxOp12,FxOp13,FxOp14,FxOp15,FxOp16,FxOp17,FxOp18,FxOp19,FxOp1A +EXTSYM FxOp1B,FxOp1C,FxOp1D,FxOp1E,FxOp1F,FxOp20,FxOp21,FxOp22,FxOp23 +EXTSYM FxOp24,FxOp25,FxOp26,FxOp27,FxOp28,FxOp29,FxOp2A,FxOp2B,FxOp2C +EXTSYM FxOp2D,FxOp2E,FxOp2F,FxOp30,FxOp30A1,FxOp31,FxOp31A1,FxOp32 +EXTSYM FxOp32A1,FxOp33,FxOp33A1,FxOp34,FxOp34A1,FxOp35,FxOp35A1,FxOp36 +EXTSYM FxOp36A1,FxOp37,FxOp37A1,FxOp38,FxOp38A1,FxOp39,FxOp39A1,FxOp3A +EXTSYM FxOp3AA1,FxOp3B,FxOp3BA1,FxOp3C,FxOp3D,FxOp3E,FxOp3F,FxOp40 +EXTSYM FxOp40A1,FxOp41,FxOp41A1,FxOp42,FxOp42A1,FxOp43,FxOp43A1,FxOp44 +EXTSYM FxOp44A1,FxOp45,FxOp45A1,FxOp46,FxOp46A1,FxOp47,FxOp47A1,FxOp48 +EXTSYM FxOp48A1,FxOp49,FxOp49A1,FxOp4A,FxOp4AA1,FxOp4B,FxOp4BA1,FxOp4C +EXTSYM FxOp4CA1,FxOp4D,FxOp4E,FxOp4EA1,FxOp4F,FxOp50,FxOp50A1,FxOp50A2 +EXTSYM FxOp50A3,FxOp51,FxOp51A1,FxOp51A2,FxOp51A3,FxOp52,FxOp52A1,FxOp52A2 +EXTSYM FxOp52A3,FxOp53,FxOp53A1,FxOp53A2,FxOp53A3,FxOp54,FxOp54A1,FxOp54A2 +EXTSYM FxOp54A3,FxOp55,FxOp55A1,FxOp55A2,FxOp55A3,FxOp56,FxOp56A1,FxOp56A2 +EXTSYM FxOp56A3,FxOp57,FxOp57A1,FxOp57A2,FxOp57A3,FxOp58,FxOp58A1,FxOp58A2 +EXTSYM FxOp58A3,FxOp59,FxOp59A1,FxOp59A2,FxOp59A3,FxOp5A,FxOp5AA1,FxOp5AA2 +EXTSYM FxOp5AA3,FxOp5B,FxOp5BA1,FxOp5BA2,FxOp5BA3,FxOp5C,FxOp5CA1,FxOp5CA2 +EXTSYM FxOp5CA3,FxOp5D,FxOp5DA1,FxOp5DA2,FxOp5DA3,FxOp5E,FxOp5EA1,FxOp5EA2 +EXTSYM FxOp5EA3,FxOp5F,FxOp5FA1,FxOp5FA2,FxOp5FA3,FxOp60,FxOp60A1,FxOp60A2 +EXTSYM FxOp60A3,FxOp61,FxOp61A1,FxOp61A2,FxOp61A3,FxOp62,FxOp62A1,FxOp62A2 +EXTSYM FxOp62A3,FxOp63,FxOp63A1,FxOp63A2,FxOp63A3,FxOp64,FxOp64A1,FxOp64A2 +EXTSYM FxOp64A3,FxOp65,FxOp65A1,FxOp65A2,FxOp65A3,FxOp66,FxOp66A1,FxOp66A2 +EXTSYM FxOp66A3,FxOp67,FxOp67A1,FxOp67A2,FxOp67A3,FxOp68,FxOp68A1,FxOp68A2 +EXTSYM FxOp68A3,FxOp69,FxOp69A1,FxOp69A2,FxOp69A3,FxOp6A,FxOp6AA1,FxOp6AA2 +EXTSYM FxOp6AA3,FxOp6B,FxOp6BA1,FxOp6BA2,FxOp6BA3,FxOp6C,FxOp6CA1,FxOp6CA2 +EXTSYM FxOp6CA3,FxOp6D,FxOp6DA1,FxOp6DA2,FxOp6DA3,FxOp6E,FxOp6EA1,FxOp6EA2 +EXTSYM FxOp6EA3,FxOp6F,FxOp6FA1,FxOp6FA2,FxOp6FA3,FxOp70,FxOp71,FxOp71A1 +EXTSYM FxOp71A2,FxOp71A3,FxOp72,FxOp72A1,FxOp72A2,FxOp72A3,FxOp73,FxOp73A1 +EXTSYM FxOp73A2,FxOp73A3,FxOp74,FxOp74A1,FxOp74A2,FxOp74A3,FxOp75,FxOp75A1 +EXTSYM FxOp75A2,FxOp75A3,FxOp76,FxOp76A1,FxOp76A2,FxOp76A3,FxOp77,FxOp77A1 +EXTSYM FxOp77A2,FxOp77A3,FxOp78,FxOp78A1,FxOp78A2,FxOp78A3,FxOp79,FxOp79A1 +EXTSYM FxOp79A2,FxOp79A3,FxOp7A,FxOp7AA1,FxOp7AA2,FxOp7AA3,FxOp7B,FxOp7BA1 +EXTSYM FxOp7BA2,FxOp7BA3,FxOp7C,FxOp7CA1,FxOp7CA2,FxOp7CA3,FxOp7D,FxOp7DA1 +EXTSYM FxOp7DA2,FxOp7DA3,FxOp7E,FxOp7EA1,FxOp7EA2,FxOp7EA3,FxOp7F,FxOp7FA1 +EXTSYM FxOp7FA2,FxOp7FA3,FxOp80,FxOp80A1,FxOp80A2,FxOp80A3,FxOp81,FxOp81A1 +EXTSYM FxOp81A2,FxOp81A3,FxOp82,FxOp82A1,FxOp82A2,FxOp82A3,FxOp83,FxOp83A1 +EXTSYM FxOp83A2,FxOp83A3,FxOp84,FxOp84A1,FxOp84A2,FxOp84A3,FxOp85,FxOp85A1 +EXTSYM FxOp85A2,FxOp85A3,FxOp86,FxOp86A1,FxOp86A2,FxOp86A3,FxOp87,FxOp87A1 +EXTSYM FxOp87A2,FxOp87A3,FxOp88,FxOp88A1,FxOp88A2,FxOp88A3,FxOp89,FxOp89A1 +EXTSYM FxOp89A2,FxOp89A3,FxOp8A,FxOp8AA1,FxOp8AA2,FxOp8AA3,FxOp8B,FxOp8BA1 +EXTSYM FxOp8BA2,FxOp8BA3,FxOp8C,FxOp8CA1,FxOp8CA2,FxOp8CA3,FxOp8D,FxOp8DA1 +EXTSYM FxOp8DA2,FxOp8DA3,FxOp8E,FxOp8EA1,FxOp8EA2,FxOp8EA3,FxOp8F,FxOp8FA1 +EXTSYM FxOp8FA2,FxOp8FA3,FxOp90,FxOp91,FxOp92,FxOp93,FxOp94,FxOp95,FxOp96 +EXTSYM FxOp96A1,FxOp97,FxOp98,FxOp98A1,FxOp99,FxOp99A1,FxOp9A,FxOp9AA1,FxOp9B +EXTSYM FxOp9BA1,FxOp9C,FxOp9CA1,FxOp9D,FxOp9DA1,FxOp9E,FxOp9F,FxOp9FA1,FxOpA0 +EXTSYM FxOpA0A1,FxOpA0A2,FxOpA1,FxOpA1A1,FxOpA1A2,FxOpA2,FxOpA2A1,FxOpA2A2 +EXTSYM FxOpA3,FxOpA3A1,FxOpA3A2,FxOpA4,FxOpA4A1,FxOpA4A2,FxOpA5,FxOpA5A1 +EXTSYM FxOpA5A2,FxOpA6,FxOpA6A1,FxOpA6A2,FxOpA7,FxOpA7A1,FxOpA7A2,FxOpA8 +EXTSYM FxOpA8A1,FxOpA8A2,FxOpA9,FxOpA9A1,FxOpA9A2,FxOpAA,FxOpAAA1,FxOpAAA2 +EXTSYM FxOpAB,FxOpABA1,FxOpABA2,FxOpAC,FxOpACA1,FxOpACA2,FxOpAD,FxOpADA1 +EXTSYM FxOpADA2,FxOpAE,FxOpAEA1,FxOpAEA2,FxOpAF,FxOpAFA1,FxOpAFA2,FxOpB0 +EXTSYM FxOpB1,FxOpB2,FxOpB3,FxOpB4,FxOpB5,FxOpB6,FxOpB7,FxOpB8,FxOpB9,FxOpBA +EXTSYM FxOpBB,FxOpBC,FxOpBD,FxOpBE,FxOpBF,FxOpC0,FxOpC1,FxOpC1A1,FxOpC1A2 +EXTSYM FxOpC1A3,FxOpC2,FxOpC2A1,FxOpC2A2,FxOpC2A3,FxOpC3,FxOpC3A1,FxOpC3A2 +EXTSYM FxOpC3A3,FxOpC4,FxOpC4A1,FxOpC4A2,FxOpC4A3,FxOpC5,FxOpC5A1,FxOpC5A2 +EXTSYM FxOpC5A3,FxOpC6,FxOpC6A1,FxOpC6A2,FxOpC6A3,FxOpC7,FxOpC7A1,FxOpC7A2 +EXTSYM FxOpC7A3,FxOpC8,FxOpC8A1,FxOpC8A2,FxOpC8A3,FxOpC9,FxOpC9A1,FxOpC9A2 +EXTSYM FxOpC9A3,FxOpCA,FxOpCAA1,FxOpCAA2,FxOpCAA3,FxOpCB,FxOpCBA1,FxOpCBA2 +EXTSYM FxOpCBA3,FxOpCC,FxOpCCA1,FxOpCCA2,FxOpCCA3,FxOpCD,FxOpCDA1,FxOpCDA2 +EXTSYM FxOpCDA3,FxOpCE,FxOpCEA1,FxOpCEA2,FxOpCEA3,FxOpCF,FxOpCFA1,FxOpCFA2 +EXTSYM FxOpCFA3,FxOpD0,FxOpD1,FxOpD2,FxOpD3,FxOpD4,FxOpD5,FxOpD6,FxOpD7 +EXTSYM FxOpD8,FxOpD9,FxOpDA,FxOpDB,FxOpDC,FxOpDD,FxOpDE,FxOpDF,FxOpDFA2 +EXTSYM FxOpDFA3,FxOpE0,FxOpE1,FxOpE2,FxOpE3,FxOpE4,FxOpE5,FxOpE6,FxOpE7 +EXTSYM FxOpE8,FxOpE9,FxOpEA,FxOpEB,FxOpEC,FxOpED,FxOpEE,FxOpEF,FxOpEFA1 +EXTSYM FxOpEFA2,FxOpEFA3,FxOpF0,FxOpF0A1,FxOpF0A2,FxOpF1,FxOpF1A1,FxOpF1A2 +EXTSYM FxOpF2,FxOpF2A1,FxOpF2A2,FxOpF3,FxOpF3A1,FxOpF3A2,FxOpF4,FxOpF4A1 +EXTSYM FxOpF4A2,FxOpF5,FxOpF5A1,FxOpF5A2,FxOpF6,FxOpF6A1,FxOpF6A2,FxOpF7 +EXTSYM FxOpF7A1,FxOpF7A2,FxOpF8,FxOpF8A1,FxOpF8A2,FxOpF9,FxOpF9A1,FxOpF9A2 +EXTSYM FxOpFA,FxOpFAA1,FxOpFAA2,FxOpFB,FxOpFBA1,FxOpFBA2,FxOpFC,FxOpFCA1 +EXTSYM FxOpFCA2,FxOpFD,FxOpFDA1,FxOpFDA2,FxOpFE,FxOpFEA1,FxOpFEA2,FxOpFF +EXTSYM FxOpFFA1,FxOpFFA2,FxOpb05,FxOpb06,FxOpb07,FxOpb08,FxOpb09,FxOpb0A +EXTSYM FxOpb0B,FxOpb0C,FxOpb0D,FxOpb0E,FxOpb0F,FxOpb10,FxOpb11,FxOpb12 +EXTSYM FxOpb13,FxOpb14,FxOpb15,FxOpb16,FxOpb17,FxOpb18,FxOpb19,FxOpb1A,FxOpb1B +EXTSYM FxOpb1C,FxOpb1D,FxOpb1E,FxOpb1F,FxOpb3D,FxOpb3E,FxOpb3F,FxOpbB0,FxOpbB1 +EXTSYM FxOpbB2,FxOpbB3,FxOpbB4,FxOpbB5,FxOpbB6,FxOpbB7,FxOpbB8,FxOpbB9,FxOpbBA +EXTSYM FxOpbBB,FxOpbBC,FxOpbBD,FxOpbBE,FxOpbBF,FxOpc05,FxOpc06,FxOpc07,FxOpc08 +EXTSYM FxOpc09,FxOpc0A,FxOpc0B,FxOpc0C,FxOpc0D,FxOpc0E,FxOpc0F,FxOpc10,FxOpc11 +EXTSYM FxOpc12,FxOpc13,FxOpc14,FxOpc15,FxOpc16,FxOpc17,FxOpc18,FxOpc19,FxOpc1A +EXTSYM FxOpc1B,FxOpc1C,FxOpc1D,FxOpc1E,FxOpc1F,FxOpc3D,FxOpc3E,FxOpc3F,FxOpcB0 +EXTSYM FxOpcB1,FxOpcB2,FxOpcB3,FxOpcB4,FxOpcB5,FxOpcB6,FxOpcB7,FxOpcB8,FxOpcB9 +EXTSYM FxOpcBA,FxOpcBB,FxOpcBC,FxOpcBD,FxOpcBE,FxOpcBF,FxOpd00,FxOpd01,FxOpd02 +EXTSYM FxOpd03,FxOpd04,FxOpd05,FxOpd06,FxOpd07,FxOpd08,FxOpd09,FxOpd0A,FxOpd0B +EXTSYM FxOpd0C,FxOpd0D,FxOpd0E,FxOpd0F,FxOpd10,FxOpd11,FxOpd12,FxOpd13,FxOpd14 +EXTSYM FxOpd15,FxOpd16,FxOpd17,FxOpd18,FxOpd19,FxOpd1A,FxOpd1B,FxOpd1C,FxOpd1D +EXTSYM FxOpd1E,FxOpd1F,FxOpd20,FxOpd21,FxOpd22,FxOpd23,FxOpd24,FxOpd25,FxOpd26 +EXTSYM FxOpd27,FxOpd28,FxOpd29,FxOpd2A,FxOpd2B,FxOpd2C,FxOpd2D,FxOpd2E,FxOpd2F +EXTSYM FxOpd30,FxOpd30A1,FxOpd31,FxOpd31A1,FxOpd32,FxOpd32A1,FxOpd33,FxOpd33A1 +EXTSYM FxOpd34,FxOpd34A1,FxOpd35,FxOpd35A1,FxOpd36,FxOpd36A1,FxOpd37,FxOpd37A1 +EXTSYM FxOpd38,FxOpd38A1,FxOpd39,FxOpd39A1,FxOpd3A,FxOpd3AA1,FxOpd3B,FxOpd3BA1 +EXTSYM FxOpd3C,FxOpd3D,FxOpd3E,FxOpd3F,FxOpd40,FxOpd40A1,FxOpd41,FxOpd41A1 +EXTSYM FxOpd42,FxOpd42A1,FxOpd43,FxOpd43A1,FxOpd44,FxOpd44A1,FxOpd45,FxOpd45A1 +EXTSYM FxOpd46,FxOpd46A1,FxOpd47,FxOpd47A1,FxOpd48,FxOpd48A1,FxOpd49,FxOpd49A1 +EXTSYM FxOpd4A,FxOpd4AA1,FxOpd4B,FxOpd4BA1,FxOpd4C,FxOpd4CA1,FxOpd4D,FxOpd4E +EXTSYM FxOpd4EA1,FxOpd4F,FxOpd50,FxOpd50A1,FxOpd50A2,FxOpd50A3,FxOpd51,FxOpd51A1 +EXTSYM FxOpd51A2,FxOpd51A3,FxOpd52,FxOpd52A1,FxOpd52A2,FxOpd52A3,FxOpd53 +EXTSYM FxOpd53A1,FxOpd53A2,FxOpd53A3,FxOpd54,FxOpd54A1,FxOpd54A2,FxOpd54A3 +EXTSYM FxOpd55,FxOpd55A1,FxOpd55A2,FxOpd55A3,FxOpd56,FxOpd56A1,FxOpd56A2 +EXTSYM FxOpd56A3,FxOpd57,FxOpd57A1,FxOpd57A2,FxOpd57A3,FxOpd58,FxOpd58A1 +EXTSYM FxOpd58A2,FxOpd58A3,FxOpd59,FxOpd59A1,FxOpd59A2,FxOpd59A3,FxOpd5A +EXTSYM FxOpd5AA1,FxOpd5AA2,FxOpd5AA3,FxOpd5B,FxOpd5BA1,FxOpd5BA2,FxOpd5BA3 +EXTSYM FxOpd5C,FxOpd5CA1,FxOpd5CA2,FxOpd5CA3,FxOpd5D,FxOpd5DA1,FxOpd5DA2 +EXTSYM FxOpd5DA3,FxOpd5E,FxOpd5EA1,FxOpd5EA2,FxOpd5EA3,FxOpd5F,FxOpd5FA1 +EXTSYM FxOpd5FA2,FxOpd5FA3,FxOpd60,FxOpd60A1,FxOpd60A2,FxOpd60A3,FxOpd61 +EXTSYM FxOpd61A1,FxOpd61A2,FxOpd61A3,FxOpd62,FxOpd62A1,FxOpd62A2,FxOpd62A3 +EXTSYM FxOpd63,FxOpd63A1,FxOpd63A2,FxOpd63A3,FxOpd64,FxOpd64A1,FxOpd64A2 +EXTSYM FxOpd64A3,FxOpd65,FxOpd65A1,FxOpd65A2,FxOpd65A3,FxOpd66,FxOpd66A1 +EXTSYM FxOpd66A2,FxOpd66A3,FxOpd67,FxOpd67A1,FxOpd67A2,FxOpd67A3,FxOpd68 +EXTSYM FxOpd68A1,FxOpd68A2,FxOpd68A3,FxOpd69,FxOpd69A1,FxOpd69A2,FxOpd69A3 +EXTSYM FxOpd6A,FxOpd6AA1,FxOpd6AA2,FxOpd6AA3,FxOpd6B,FxOpd6BA1,FxOpd6BA2 +EXTSYM FxOpd6BA3,FxOpd6C,FxOpd6CA1,FxOpd6CA2,FxOpd6CA3,FxOpd6D,FxOpd6DA1 +EXTSYM FxOpd6DA2,FxOpd6DA3,FxOpd6E,FxOpd6EA1,FxOpd6EA2,FxOpd6EA3,FxOpd6F +EXTSYM FxOpd6FA1,FxOpd6FA2,FxOpd6FA3,FxOpd70,FxOpd71,FxOpd71A1,FxOpd71A2 +EXTSYM FxOpd71A3,FxOpd72,FxOpd72A1,FxOpd72A2,FxOpd72A3,FxOpd73,FxOpd73A1 +EXTSYM FxOpd73A2,FxOpd73A3,FxOpd74,FxOpd74A1,FxOpd74A2,FxOpd74A3,FxOpd75 +EXTSYM FxOpd75A1,FxOpd75A2,FxOpd75A3,FxOpd76,FxOpd76A1,FxOpd76A2,FxOpd76A3 +EXTSYM FxOpd77,FxOpd77A1,FxOpd77A2,FxOpd77A3,FxOpd78,FxOpd78A1,FxOpd78A2 +EXTSYM FxOpd78A3,FxOpd79,FxOpd79A1,FxOpd79A2,FxOpd79A3,FxOpd7A,FxOpd7AA1 +EXTSYM FxOpd7AA2,FxOpd7AA3,FxOpd7B,FxOpd7BA1,FxOpd7BA2,FxOpd7BA3,FxOpd7C +EXTSYM FxOpd7CA1,FxOpd7CA2,FxOpd7CA3,FxOpd7D,FxOpd7DA1,FxOpd7DA2,FxOpd7DA3 +EXTSYM FxOpd7E,FxOpd7EA1,FxOpd7EA2,FxOpd7EA3,FxOpd7F,FxOpd7FA1,FxOpd7FA2 +EXTSYM FxOpd7FA3,FxOpd80,FxOpd80A1,FxOpd80A2,FxOpd80A3,FxOpd81,FxOpd81A1 +EXTSYM FxOpd81A2,FxOpd81A3,FxOpd82,FxOpd82A1,FxOpd82A2,FxOpd82A3,FxOpd83 +EXTSYM FxOpd83A1,FxOpd83A2,FxOpd83A3,FxOpd84,FxOpd84A1,FxOpd84A2,FxOpd84A3 +EXTSYM FxOpd85,FxOpd85A1,FxOpd85A2,FxOpd85A3,FxOpd86,FxOpd86A1,FxOpd86A2 +EXTSYM FxOpd86A3,FxOpd87,FxOpd87A1,FxOpd87A2,FxOpd87A3,FxOpd88,FxOpd88A1 +EXTSYM FxOpd88A2,FxOpd88A3,FxOpd89,FxOpd89A1,FxOpd89A2,FxOpd89A3,FxOpd8A +EXTSYM FxOpd8AA1,FxOpd8AA2,FxOpd8AA3,FxOpd8B,FxOpd8BA1,FxOpd8BA2,FxOpd8BA3 +EXTSYM FxOpd8C,FxOpd8CA1,FxOpd8CA2,FxOpd8CA3,FxOpd8D,FxOpd8DA1,FxOpd8DA2 +EXTSYM FxOpd8DA3,FxOpd8E,FxOpd8EA1,FxOpd8EA2,FxOpd8EA3,FxOpd8F,FxOpd8FA1 +EXTSYM FxOpd8FA2,FxOpd8FA3,FxOpd90,FxOpd91,FxOpd92,FxOpd93,FxOpd94,FxOpd95 +EXTSYM FxOpd96,FxOpd96A1,FxOpd97,FxOpd98,FxOpd98A1,FxOpd99,FxOpd99A1,FxOpd9A +EXTSYM FxOpd9AA1,FxOpd9B,FxOpd9BA1,FxOpd9C,FxOpd9CA1,FxOpd9D,FxOpd9DA1,FxOpd9E +EXTSYM FxOpd9F,FxOpd9FA1,FxOpdA0,FxOpdA0A1,FxOpdA0A2,FxOpdA1,FxOpdA1A1,FxOpdA1A2 +EXTSYM FxOpdA2,FxOpdA2A1,FxOpdA2A2,FxOpdA3,FxOpdA3A1,FxOpdA3A2,FxOpdA4,FxOpdA4A1 +EXTSYM FxOpdA4A2,FxOpdA5,FxOpdA5A1,FxOpdA5A2,FxOpdA6,FxOpdA6A1,FxOpdA6A2,FxOpdA7 +EXTSYM FxOpdA7A1,FxOpdA7A2,FxOpdA8,FxOpdA8A1,FxOpdA8A2,FxOpdA9,FxOpdA9A1 +EXTSYM FxOpdA9A2,FxOpdAA,FxOpdAAA1,FxOpdAAA2,FxOpdAB,FxOpdABA1,FxOpdABA2 +EXTSYM FxOpdAC,FxOpdACA1,FxOpdACA2,FxOpdAD,FxOpdADA1,FxOpdADA2,FxOpdAE +EXTSYM FxOpdAEA1,FxOpdAEA2,FxOpdAF,FxOpdAFA1,FxOpdAFA2,FxOpdB0,FxOpdB1,FxOpdB2 +EXTSYM FxOpdB3,FxOpdB4,FxOpdB5,FxOpdB6,FxOpdB7,FxOpdB8,FxOpdB9,FxOpdBA,FxOpdBB +EXTSYM FxOpdBC,FxOpdBD,FxOpdBE,FxOpdBF,FxOpdC0,FxOpdC1,FxOpdC1A1,FxOpdC1A2 +EXTSYM FxOpdC1A3,FxOpdC2,FxOpdC2A1,FxOpdC2A2,FxOpdC2A3,FxOpdC3,FxOpdC3A1 +EXTSYM FxOpdC3A2,FxOpdC3A3,FxOpdC4,FxOpdC4A1,FxOpdC4A2,FxOpdC4A3,FxOpdC5 +EXTSYM FxOpdC5A1,FxOpdC5A2,FxOpdC5A3,FxOpdC6,FxOpdC6A1,FxOpdC6A2,FxOpdC6A3 +EXTSYM FxOpdC7,FxOpdC7A1,FxOpdC7A2,FxOpdC7A3,FxOpdC8,FxOpdC8A1,FxOpdC8A2 +EXTSYM FxOpdC8A3,FxOpdC9,FxOpdC9A1,FxOpdC9A2,FxOpdC9A3,FxOpdCA,FxOpdCAA1 +EXTSYM FxOpdCAA2,FxOpdCAA3,FxOpdCB,FxOpdCBA1,FxOpdCBA2,FxOpdCBA3,FxOpdCC +EXTSYM FxOpdCCA1,FxOpdCCA2,FxOpdCCA3,FxOpdCD,FxOpdCDA1,FxOpdCDA2,FxOpdCDA3 +EXTSYM FxOpdCE,FxOpdCEA1,FxOpdCEA2,FxOpdCEA3,FxOpdCF,FxOpdCFA1,FxOpdCFA2 +EXTSYM FxOpdCFA3,FxOpdD0,FxOpdD1,FxOpdD2,FxOpdD3,FxOpdD4,FxOpdD5,FxOpdD6 +EXTSYM FxOpdD7,FxOpdD8,FxOpdD9,FxOpdDA,FxOpdDB,FxOpdDC,FxOpdDD,FxOpdDE,FxOpdDF +EXTSYM FxOpdDFA2,FxOpdDFA3,FxOpdE0,FxOpdE1,FxOpdE2,FxOpdE3,FxOpdE4,FxOpdE5 +EXTSYM FxOpdE6,FxOpdE7,FxOpdE8,FxOpdE9,FxOpdEA,FxOpdEB,FxOpdEC,FxOpdED,FxOpdEE +EXTSYM FxOpdEF,FxOpdEFA1,FxOpdEFA2,FxOpdEFA3,FxOpdF0,FxOpdF0A1,FxOpdF0A2,FxOpdF1 +EXTSYM FxOpdF1A1,FxOpdF1A2,FxOpdF2,FxOpdF2A1,FxOpdF2A2,FxOpdF3,FxOpdF3A1,FxOpdF3A2 +EXTSYM FxOpdF4,FxOpdF4A1,FxOpdF4A2,FxOpdF5,FxOpdF5A1,FxOpdF5A2,FxOpdF6,FxOpdF6A1 +EXTSYM FxOpdF6A2,FxOpdF7,FxOpdF7A1,FxOpdF7A2,FxOpdF8,FxOpdF8A1,FxOpdF8A2,FxOpdF9 +EXTSYM FxOpdF9A1,FxOpdF9A2,FxOpdFA,FxOpdFAA1,FxOpdFAA2,FxOpdFB,FxOpdFBA1,FxOpdFBA2 +EXTSYM FxOpdFC,FxOpdFCA1,FxOpdFCA2,FxOpdFD,FxOpdFDA1,FxOpdFDA2,FxOpdFE,FxOpdFEA1 +EXTSYM FxOpdFEA2,FxOpdFF,FxOpdFFA1,FxOpdFFA2,PLOTJmpa,PLOTJmpb + +EXTSYM FxOp4C1284b,FxOp4C1284bz,FxOp4C1284bd,FxOp4C1284bzd +EXTSYM FxOp4C1282b,FxOp4C1282bz,FxOp4C1282bd,FxOp4C1282bzd +EXTSYM FxOp4C1288b,FxOp4C1288bz,FxOp4C1288bd,FxOp4C1288bzd +EXTSYM FxOp4C1288bl,FxOp4C1288bzl,FxOp4C1288bdl,FxOp4C1288bzdl +EXTSYM FxOpd4C1284b,FxOpd4C1284bz,FxOpd4C1284bd,FxOpd4C1284bzd +EXTSYM FxOpd4C1282b,FxOpd4C1282bz,FxOpd4C1282bd,FxOpd4C1282bzd +EXTSYM FxOpd4C1288b,FxOpd4C1288bz,FxOpd4C1288bd,FxOpd4C1288bzd +EXTSYM FxOpd4C1288bl,FxOpd4C1288bzl,FxOpd4C1288bdl,FxOpd4C1288bzdl + + +EXTSYM fxxand,fxbit01,fxbit23,fxbit45,fxbit67 + +NEWSYM FxTableAsmStart + +SECTION .bss ;ALIGN=32 +NEWSYM sfx128lineloc, resd 1 +NEWSYM sfx160lineloc, resd 1 +NEWSYM sfx192lineloc, resd 1 +NEWSYM sfxobjlineloc, resd 1 + +SECTION .text + +NEWSYM InitFxTables + +; cmp al,0 +; je near .colors4 +; cmp al,3 +; je near .colors256 +; test byte[SfxPOR],01h +; jz .zerocheck +; test byte[SfxPOR],02h +; jz .nodither4b + ; Initiate PLOT jump tables + xor ebx,ebx + mov ecx,64 + mov eax,PLOTJmpa +.ploop + mov edx,ebx + push ebx + and edx,03h + test bl,04h + jz near .zerocheck + test bl,08h + jnz .dither + cmp dl,0 + je .colors4 + cmp dl,3 + je .colors256 + mov ebx,FxOp4C1284b + jmp .end +.colors4 + mov ebx,FxOp4C1282b + jmp .end +.colors256 + test bl,20h + jnz .lowercheck + mov ebx,FxOp4C1288b + jmp .end +.lowercheck + mov ebx,FxOp4C1288bl + jmp .end +.dither + cmp dl,0 + je .colors4d + cmp dl,3 + je .colors256d + mov ebx,FxOp4C1284bd + jmp .end +.colors4d + mov ebx,FxOp4C1282bd + jmp .end +.colors256d + test bl,20h + jnz .lowercheckd + mov ebx,FxOp4C1288bd + jmp .end +.lowercheckd + mov ebx,FxOp4C1288bdl + jmp .end +.zerocheck + test bl,08h + jnz .ditherz + cmp dl,0 + je .colors4z + cmp dl,3 + je .colors256z + mov ebx,FxOp4C1284bz + jmp .end +.colors4z + mov ebx,FxOp4C1282bz + jmp .end +.colors256z + test bl,20h + jnz .lowercheckz + mov ebx,FxOp4C1288bz + jmp .end +.lowercheckz + mov ebx,FxOp4C1288bzl + jmp .end +.ditherz + cmp dl,0 + je .colors4dz + cmp dl,3 + je .colors256dz + mov ebx,FxOp4C1284bzd + jmp .end +.colors4dz + mov ebx,FxOp4C1282bzd + jmp .end +.colors256dz + test bl,20h + jnz .lowercheckdz + mov ebx,FxOp4C1288bzd + jmp .end +.lowercheckdz + mov ebx,FxOp4C1288bzdl +.end + mov [eax],ebx + pop ebx + inc ebx + add eax,4 + dec ecx + jnz near .ploop + + xor ebx,ebx + mov ecx,64 + mov eax,PLOTJmpb +.ploop2 + mov edx,ebx + push ebx + and edx,03h + test bl,04h + jz near .zerocheck2 + test bl,08h + jnz .dither2 + cmp dl,0 + je .colors42 + cmp dl,3 + je .colors2562 + mov ebx,FxOpd4C1284b + jmp .end2 +.colors42 + mov ebx,FxOpd4C1282b + jmp .end2 +.colors2562 + test bl,20h + jnz .lowercheck2 + mov ebx,FxOpd4C1288b + jmp .end2 +.lowercheck2 + mov ebx,FxOpd4C1288bl + jmp .end2 +.dither2 + cmp dl,0 + je .colors4d2 + cmp dl,3 + je .colors256d2 + mov ebx,FxOpd4C1284bd + jmp .end2 +.colors4d2 + mov ebx,FxOpd4C1282bd + jmp .end2 +.colors256d2 + test bl,20h + jnz .lowercheckd2 + mov ebx,FxOpd4C1288bd + jmp .end2 +.lowercheckd2 + mov ebx,FxOpd4C1288bdl + jmp .end2 +.zerocheck2 + test bl,08h + jnz .ditherz2 + cmp dl,0 + je .colors4z2 + cmp dl,3 + je .colors256z2 + mov ebx,FxOpd4C1284bz + jmp .end2 +.colors4z2 + mov ebx,FxOpd4C1282bz + jmp .end2 +.colors256z2 + test bl,20h + jnz .lowercheckz2 + mov ebx,FxOpd4C1288bz + jmp .end2 +.lowercheckz2 + mov ebx,FxOpd4C1288bzl + jmp .end2 +.ditherz2 + cmp dl,0 + je .colors4dz2 + cmp dl,3 + je .colors256dz2 + mov ebx,FxOpd4C1284bzd + jmp .end2 +.colors4dz2 + mov ebx,FxOpd4C1282bzd + jmp .end2 +.colors256dz2 + test bl,20h + jnz .lowercheckdz2 + mov ebx,FxOpd4C1288bzd + jmp .end2 +.lowercheckdz2 + mov ebx,FxOpd4C1288bzdl +.end2 + mov [eax],ebx + pop ebx + inc ebx + add eax,4 + dec ecx + jnz near .ploop2 + + ; Initiate AND and bit tables + mov eax,fxxand + mov ecx,256 + xor ebx,ebx +.loopat + push ecx + mov ecx,ebx + and ecx,07h + xor ecx,07h + mov edx,0101h + shl edx,cl + xor edx,0FFFFFFFFh + pop ecx + mov [eax],edx + inc ebx + add eax,4 + dec ecx + jnz .loopat + ; bit tables + mov eax,fxbit01 + mov ecx,256 + xor ebx,ebx +.loopb01 + xor edx,edx + test ebx,01h + jz .nob0 + or edx,0FFh +.nob0 + test ebx,02h + jz .nob1 + or edx,0FF00h +.nob1 + mov [eax],edx + xor edx,edx + test ebx,04h + jz .nob2 + or edx,0FFh +.nob2 + test ebx,08h + jz .nob3 + or edx,0FF00h +.nob3 + mov [eax+256*4],edx + xor edx,edx + test ebx,10h + jz .nob4 + or edx,0FFh +.nob4 + test ebx,20h + jz .nob5 + or edx,0FF00h +.nob5 + mov [eax+256*8],edx + xor edx,edx + test ebx,40h + jz .nob6 + or edx,0FFh +.nob6 + test ebx,80h + jz .nob7 + or edx,0FF00h +.nob7 + mov [eax+256*12],edx + add eax,4 + inc ebx + dec ecx + jnz near .loopb01 + + ; Initialize PLOT tables +; mov esi,[sfxramdata] + mov esi,[sfxplottable] +; add esi,1024*1024 + ; Create 4 * 256k plot tables + ; 128 line mode + mov [sfx128lineloc],esi + xor eax,eax + xor ebx,ebx +.nexty +.nextx + cmp eax,128 + jae .over + push eax + push ebx + shr eax,3 + shr ebx,3 + shl ebx,4 + add ebx,eax + mov [esi],ebx + add esi,4 + pop ebx + pop eax + jmp .notover +.over + mov dword[esi],0FFFFFFFFh + add esi,4 +.notover + inc al + jnz .nextx + inc bl + jnz .nexty + ; 160 line mode + mov [sfx160lineloc],esi +.nexty2 +.nextx2 + cmp eax,160 + jae .over2 + push eax + push ebx + shr eax,3 + shr ebx,3 + mov edx,ebx + shl ebx,4 + shl edx,2 + add ebx,eax + add ebx,edx + mov [esi],ebx + add esi,4 + pop ebx + pop eax + jmp .notover2 +.over2 + mov dword[esi],0FFFFFFFFh + add esi,4 +.notover2 + inc al + jnz .nextx2 + inc bl + jnz .nexty2 + ; 192 line mode + mov [sfx192lineloc],esi +.nexty3 +.nextx3 + cmp eax,192 + jae .over3 + push eax + push ebx + shr eax,3 + shr ebx,3 + mov edx,ebx + shl ebx,4 + shl edx,3 + add ebx,eax + add ebx,edx + mov [esi],ebx + add esi,4 + pop ebx + pop eax + jmp .notover3 +.over3 + mov dword[esi],0FFFFFFFFh + add esi,4 +.notover3 + inc al + jnz .nextx3 + inc bl + jnz .nexty3 + ; obj mode + mov [sfxobjlineloc],esi +.nexty4 +.nextx4 + push eax + push ebx + and ebx,80h + and eax,80h + shl ebx,1 + shl eax,2 + add ebx,eax + mov edx,ebx + pop ebx + pop eax + push eax + push ebx + and ebx,78h + and eax,78h + shr ebx,3 + shl eax,1 + add ebx,eax + add edx,ebx + pop ebx + pop eax + mov [esi],edx + add esi,4 + inc al + jnz .nextx4 + inc bl + jnz .nexty4 + + mov eax,[romdata] + xor ebx,ebx + mov ecx,256 +.loopc + mov [SfxMemTable+ebx*4],eax + inc ebx + dec ecx + jnz .loopc + + mov eax,[romdata] + add eax,200000h + xor ebx,ebx + mov ecx,64 +.loop + mov [SfxMemTable+ebx*4],eax + add eax,65536 + inc ebx + dec ecx + jnz .loop + + mov eax,[romdata] + mov ecx,64 +.loop2 + mov [SfxMemTable+ebx*4],eax + add eax,65536 + inc ebx + dec ecx + jnz .loop2 + + mov eax,[sfxramdata] + mov [SfxMemTable+70h*4],eax + add eax,65536 + mov [SfxMemTable+71h*4],eax + add eax,65536 + mov [SfxMemTable+72h*4],eax + add eax,65536 + mov [SfxMemTable+73h*4],eax + + mov eax,[romdata] + add eax,200000h + + xor ebx,ebx + mov ebx,80h + mov ecx,64 +.loops + mov [SfxMemTable+ebx*4],eax + add eax,65536 + inc ebx + dec ecx + jnz .loops + + mov eax,[romdata] + mov ecx,64 +.loop2s + mov [SfxMemTable+ebx*4],eax + add eax,65536 + inc ebx + dec ecx + jnz .loop2s + mov eax,[sfxramdata] + mov [SfxMemTable+0F0h*4],eax + add eax,65536 + mov [SfxMemTable+0F1h*4],eax + add eax,65536 + mov [SfxMemTable+0F2h*4],eax + add eax,65536 + mov [SfxMemTable+0F3h*4],eax + + mov dword [FxTable+00h*4],FxOp00 + mov dword [FxTable+01h*4],FxOp01 + mov dword [FxTable+02h*4],FxOp02 + mov dword [FxTable+03h*4],FxOp03 + mov dword [FxTable+04h*4],FxOp04 + mov dword [FxTable+05h*4],FxOp05 + mov dword [FxTable+06h*4],FxOp06 + mov dword [FxTable+07h*4],FxOp07 + mov dword [FxTable+08h*4],FxOp08 + mov dword [FxTable+09h*4],FxOp09 + mov dword [FxTable+0Ah*4],FxOp0A + mov dword [FxTable+0Bh*4],FxOp0B + mov dword [FxTable+0Ch*4],FxOp0C + mov dword [FxTable+0Dh*4],FxOp0D + mov dword [FxTable+0Eh*4],FxOp0E + mov dword [FxTable+0Fh*4],FxOp0F + + mov dword [FxTable+10h*4],FxOp10 + mov dword [FxTable+11h*4],FxOp11 + mov dword [FxTable+12h*4],FxOp12 + mov dword [FxTable+13h*4],FxOp13 + mov dword [FxTable+14h*4],FxOp14 + mov dword [FxTable+15h*4],FxOp15 + mov dword [FxTable+16h*4],FxOp16 + mov dword [FxTable+17h*4],FxOp17 + mov dword [FxTable+18h*4],FxOp18 + mov dword [FxTable+19h*4],FxOp19 + mov dword [FxTable+1Ah*4],FxOp1A + mov dword [FxTable+1Bh*4],FxOp1B + mov dword [FxTable+1Ch*4],FxOp1C + mov dword [FxTable+1Dh*4],FxOp1D + mov dword [FxTable+1Eh*4],FxOp1E + mov dword [FxTable+1Fh*4],FxOp1F + + mov dword [FxTable+20h*4],FxOp20 + mov dword [FxTable+21h*4],FxOp21 + mov dword [FxTable+22h*4],FxOp22 + mov dword [FxTable+23h*4],FxOp23 + mov dword [FxTable+24h*4],FxOp24 + mov dword [FxTable+25h*4],FxOp25 + mov dword [FxTable+26h*4],FxOp26 + mov dword [FxTable+27h*4],FxOp27 + mov dword [FxTable+28h*4],FxOp28 + mov dword [FxTable+29h*4],FxOp29 + mov dword [FxTable+2Ah*4],FxOp2A + mov dword [FxTable+2Bh*4],FxOp2B + mov dword [FxTable+2Ch*4],FxOp2C + mov dword [FxTable+2Dh*4],FxOp2D + mov dword [FxTable+2Eh*4],FxOp2E + mov dword [FxTable+2Fh*4],FxOp2F + + mov dword [FxTable+30h*4],FxOp30 + mov dword [FxTable+31h*4],FxOp31 + mov dword [FxTable+32h*4],FxOp32 + mov dword [FxTable+33h*4],FxOp33 + mov dword [FxTable+34h*4],FxOp34 + mov dword [FxTable+35h*4],FxOp35 + mov dword [FxTable+36h*4],FxOp36 + mov dword [FxTable+37h*4],FxOp37 + mov dword [FxTable+38h*4],FxOp38 + mov dword [FxTable+39h*4],FxOp39 + mov dword [FxTable+3Ah*4],FxOp3A + mov dword [FxTable+3Bh*4],FxOp3B + mov dword [FxTable+3Ch*4],FxOp3C + mov dword [FxTable+3Dh*4],FxOp3D + mov dword [FxTable+3Eh*4],FxOp3E + mov dword [FxTable+3Fh*4],FxOp3F + + mov dword [FxTable+40h*4],FxOp40 + mov dword [FxTable+41h*4],FxOp41 + mov dword [FxTable+42h*4],FxOp42 + mov dword [FxTable+43h*4],FxOp43 + mov dword [FxTable+44h*4],FxOp44 + mov dword [FxTable+45h*4],FxOp45 + mov dword [FxTable+46h*4],FxOp46 + mov dword [FxTable+47h*4],FxOp47 + mov dword [FxTable+48h*4],FxOp48 + mov dword [FxTable+49h*4],FxOp49 + mov dword [FxTable+4Ah*4],FxOp4A + mov dword [FxTable+4Bh*4],FxOp4B + mov dword [FxTable+4Ch*4],FxOp4C + mov dword [FxTable+4Dh*4],FxOp4D + mov dword [FxTable+4Eh*4],FxOp4E + mov dword [FxTable+4Fh*4],FxOp4F + + mov dword [FxTable+50h*4],FxOp50 + mov dword [FxTable+51h*4],FxOp51 + mov dword [FxTable+52h*4],FxOp52 + mov dword [FxTable+53h*4],FxOp53 + mov dword [FxTable+54h*4],FxOp54 + mov dword [FxTable+55h*4],FxOp55 + mov dword [FxTable+56h*4],FxOp56 + mov dword [FxTable+57h*4],FxOp57 + mov dword [FxTable+58h*4],FxOp58 + mov dword [FxTable+59h*4],FxOp59 + mov dword [FxTable+5Ah*4],FxOp5A + mov dword [FxTable+5Bh*4],FxOp5B + mov dword [FxTable+5Ch*4],FxOp5C + mov dword [FxTable+5Dh*4],FxOp5D + mov dword [FxTable+5Eh*4],FxOp5E + mov dword [FxTable+5Fh*4],FxOp5F + + mov dword [FxTable+60h*4],FxOp60 + mov dword [FxTable+61h*4],FxOp61 + mov dword [FxTable+62h*4],FxOp62 + mov dword [FxTable+63h*4],FxOp63 + mov dword [FxTable+64h*4],FxOp64 + mov dword [FxTable+65h*4],FxOp65 + mov dword [FxTable+66h*4],FxOp66 + mov dword [FxTable+67h*4],FxOp67 + mov dword [FxTable+68h*4],FxOp68 + mov dword [FxTable+69h*4],FxOp69 + mov dword [FxTable+6Ah*4],FxOp6A + mov dword [FxTable+6Bh*4],FxOp6B + mov dword [FxTable+6Ch*4],FxOp6C + mov dword [FxTable+6Dh*4],FxOp6D + mov dword [FxTable+6Eh*4],FxOp6E + mov dword [FxTable+6Fh*4],FxOp6F + + mov dword [FxTable+70h*4],FxOp70 + mov dword [FxTable+71h*4],FxOp71 + mov dword [FxTable+72h*4],FxOp72 + mov dword [FxTable+73h*4],FxOp73 + mov dword [FxTable+74h*4],FxOp74 + mov dword [FxTable+75h*4],FxOp75 + mov dword [FxTable+76h*4],FxOp76 + mov dword [FxTable+77h*4],FxOp77 + mov dword [FxTable+78h*4],FxOp78 + mov dword [FxTable+79h*4],FxOp79 + mov dword [FxTable+7Ah*4],FxOp7A + mov dword [FxTable+7Bh*4],FxOp7B + mov dword [FxTable+7Ch*4],FxOp7C + mov dword [FxTable+7Dh*4],FxOp7D + mov dword [FxTable+7Eh*4],FxOp7E + mov dword [FxTable+7Fh*4],FxOp7F + + mov dword [FxTable+80h*4],FxOp80 + mov dword [FxTable+81h*4],FxOp81 + mov dword [FxTable+82h*4],FxOp82 + mov dword [FxTable+83h*4],FxOp83 + mov dword [FxTable+84h*4],FxOp84 + mov dword [FxTable+85h*4],FxOp85 + mov dword [FxTable+86h*4],FxOp86 + mov dword [FxTable+87h*4],FxOp87 + mov dword [FxTable+88h*4],FxOp88 + mov dword [FxTable+89h*4],FxOp89 + mov dword [FxTable+8Ah*4],FxOp8A + mov dword [FxTable+8Bh*4],FxOp8B + mov dword [FxTable+8Ch*4],FxOp8C + mov dword [FxTable+8Dh*4],FxOp8D + mov dword [FxTable+8Eh*4],FxOp8E + mov dword [FxTable+8Fh*4],FxOp8F + + mov dword [FxTable+90h*4],FxOp90 + mov dword [FxTable+91h*4],FxOp91 + mov dword [FxTable+92h*4],FxOp92 + mov dword [FxTable+93h*4],FxOp93 + mov dword [FxTable+94h*4],FxOp94 + mov dword [FxTable+95h*4],FxOp95 + mov dword [FxTable+96h*4],FxOp96 + mov dword [FxTable+97h*4],FxOp97 + mov dword [FxTable+98h*4],FxOp98 + mov dword [FxTable+99h*4],FxOp99 + mov dword [FxTable+9Ah*4],FxOp9A + mov dword [FxTable+9Bh*4],FxOp9B + mov dword [FxTable+9Ch*4],FxOp9C + mov dword [FxTable+9Dh*4],FxOp9D + mov dword [FxTable+9Eh*4],FxOp9E + mov dword [FxTable+9Fh*4],FxOp9F + + mov dword [FxTable+0A0h*4],FxOpA0 + mov dword [FxTable+0A1h*4],FxOpA1 + mov dword [FxTable+0A2h*4],FxOpA2 + mov dword [FxTable+0A3h*4],FxOpA3 + mov dword [FxTable+0A4h*4],FxOpA4 + mov dword [FxTable+0A5h*4],FxOpA5 + mov dword [FxTable+0A6h*4],FxOpA6 + mov dword [FxTable+0A7h*4],FxOpA7 + mov dword [FxTable+0A8h*4],FxOpA8 + mov dword [FxTable+0A9h*4],FxOpA9 + mov dword [FxTable+0AAh*4],FxOpAA + mov dword [FxTable+0ABh*4],FxOpAB + mov dword [FxTable+0ACh*4],FxOpAC + mov dword [FxTable+0ADh*4],FxOpAD + mov dword [FxTable+0AEh*4],FxOpAE + mov dword [FxTable+0AFh*4],FxOpAF + + mov dword [FxTable+0B0h*4],FxOpB0 + mov dword [FxTable+0B1h*4],FxOpB1 + mov dword [FxTable+0B2h*4],FxOpB2 + mov dword [FxTable+0B3h*4],FxOpB3 + mov dword [FxTable+0B4h*4],FxOpB4 + mov dword [FxTable+0B5h*4],FxOpB5 + mov dword [FxTable+0B6h*4],FxOpB6 + mov dword [FxTable+0B7h*4],FxOpB7 + mov dword [FxTable+0B8h*4],FxOpB8 + mov dword [FxTable+0B9h*4],FxOpB9 + mov dword [FxTable+0BAh*4],FxOpBA + mov dword [FxTable+0BBh*4],FxOpBB + mov dword [FxTable+0BCh*4],FxOpBC + mov dword [FxTable+0BDh*4],FxOpBD + mov dword [FxTable+0BEh*4],FxOpBE + mov dword [FxTable+0BFh*4],FxOpBF + + mov dword [FxTable+0C0h*4],FxOpC0 + mov dword [FxTable+0C1h*4],FxOpC1 + mov dword [FxTable+0C2h*4],FxOpC2 + mov dword [FxTable+0C3h*4],FxOpC3 + mov dword [FxTable+0C4h*4],FxOpC4 + mov dword [FxTable+0C5h*4],FxOpC5 + mov dword [FxTable+0C6h*4],FxOpC6 + mov dword [FxTable+0C7h*4],FxOpC7 + mov dword [FxTable+0C8h*4],FxOpC8 + mov dword [FxTable+0C9h*4],FxOpC9 + mov dword [FxTable+0CAh*4],FxOpCA + mov dword [FxTable+0CBh*4],FxOpCB + mov dword [FxTable+0CCh*4],FxOpCC + mov dword [FxTable+0CDh*4],FxOpCD + mov dword [FxTable+0CEh*4],FxOpCE + mov dword [FxTable+0CFh*4],FxOpCF + + mov dword [FxTable+0D0h*4],FxOpD0 + mov dword [FxTable+0D1h*4],FxOpD1 + mov dword [FxTable+0D2h*4],FxOpD2 + mov dword [FxTable+0D3h*4],FxOpD3 + mov dword [FxTable+0D4h*4],FxOpD4 + mov dword [FxTable+0D5h*4],FxOpD5 + mov dword [FxTable+0D6h*4],FxOpD6 + mov dword [FxTable+0D7h*4],FxOpD7 + mov dword [FxTable+0D8h*4],FxOpD8 + mov dword [FxTable+0D9h*4],FxOpD9 + mov dword [FxTable+0DAh*4],FxOpDA + mov dword [FxTable+0DBh*4],FxOpDB + mov dword [FxTable+0DCh*4],FxOpDC + mov dword [FxTable+0DDh*4],FxOpDD + mov dword [FxTable+0DEh*4],FxOpDE + mov dword [FxTable+0DFh*4],FxOpDF + + mov dword [FxTable+0E0h*4],FxOpE0 + mov dword [FxTable+0E1h*4],FxOpE1 + mov dword [FxTable+0E2h*4],FxOpE2 + mov dword [FxTable+0E3h*4],FxOpE3 + mov dword [FxTable+0E4h*4],FxOpE4 + mov dword [FxTable+0E5h*4],FxOpE5 + mov dword [FxTable+0E6h*4],FxOpE6 + mov dword [FxTable+0E7h*4],FxOpE7 + mov dword [FxTable+0E8h*4],FxOpE8 + mov dword [FxTable+0E9h*4],FxOpE9 + mov dword [FxTable+0EAh*4],FxOpEA + mov dword [FxTable+0EBh*4],FxOpEB + mov dword [FxTable+0ECh*4],FxOpEC + mov dword [FxTable+0EDh*4],FxOpED + mov dword [FxTable+0EEh*4],FxOpEE + mov dword [FxTable+0EFh*4],FxOpEF + + mov dword [FxTable+0F0h*4],FxOpF0 + mov dword [FxTable+0F1h*4],FxOpF1 + mov dword [FxTable+0F2h*4],FxOpF2 + mov dword [FxTable+0F3h*4],FxOpF3 + mov dword [FxTable+0F4h*4],FxOpF4 + mov dword [FxTable+0F5h*4],FxOpF5 + mov dword [FxTable+0F6h*4],FxOpF6 + mov dword [FxTable+0F7h*4],FxOpF7 + mov dword [FxTable+0F8h*4],FxOpF8 + mov dword [FxTable+0F9h*4],FxOpF9 + mov dword [FxTable+0FAh*4],FxOpFA + mov dword [FxTable+0FBh*4],FxOpFB + mov dword [FxTable+0FCh*4],FxOpFC + mov dword [FxTable+0FDh*4],FxOpFD + mov dword [FxTable+0FEh*4],FxOpFE + mov dword [FxTable+0FFh*4],FxOpFF + + + mov dword [FxTableA1+00h*4],FxOp00 + mov dword [FxTableA1+01h*4],FxOp01 + mov dword [FxTableA1+02h*4],FxOp02 + mov dword [FxTableA1+03h*4],FxOp03 + mov dword [FxTableA1+04h*4],FxOp04 + mov dword [FxTableA1+05h*4],FxOp05 + mov dword [FxTableA1+06h*4],FxOp06 + mov dword [FxTableA1+07h*4],FxOp07 + mov dword [FxTableA1+08h*4],FxOp08 + mov dword [FxTableA1+09h*4],FxOp09 + mov dword [FxTableA1+0Ah*4],FxOp0A + mov dword [FxTableA1+0Bh*4],FxOp0B + mov dword [FxTableA1+0Ch*4],FxOp0C + mov dword [FxTableA1+0Dh*4],FxOp0D + mov dword [FxTableA1+0Eh*4],FxOp0E + mov dword [FxTableA1+0Fh*4],FxOp0F + + mov dword [FxTableA1+10h*4],FxOp10 + mov dword [FxTableA1+11h*4],FxOp11 + mov dword [FxTableA1+12h*4],FxOp12 + mov dword [FxTableA1+13h*4],FxOp13 + mov dword [FxTableA1+14h*4],FxOp14 + mov dword [FxTableA1+15h*4],FxOp15 + mov dword [FxTableA1+16h*4],FxOp16 + mov dword [FxTableA1+17h*4],FxOp17 + mov dword [FxTableA1+18h*4],FxOp18 + mov dword [FxTableA1+19h*4],FxOp19 + mov dword [FxTableA1+1Ah*4],FxOp1A + mov dword [FxTableA1+1Bh*4],FxOp1B + mov dword [FxTableA1+1Ch*4],FxOp1C + mov dword [FxTableA1+1Dh*4],FxOp1D + mov dword [FxTableA1+1Eh*4],FxOp1E + mov dword [FxTableA1+1Fh*4],FxOp1F + + mov dword [FxTableA1+20h*4],FxOp20 + mov dword [FxTableA1+21h*4],FxOp21 + mov dword [FxTableA1+22h*4],FxOp22 + mov dword [FxTableA1+23h*4],FxOp23 + mov dword [FxTableA1+24h*4],FxOp24 + mov dword [FxTableA1+25h*4],FxOp25 + mov dword [FxTableA1+26h*4],FxOp26 + mov dword [FxTableA1+27h*4],FxOp27 + mov dword [FxTableA1+28h*4],FxOp28 + mov dword [FxTableA1+29h*4],FxOp29 + mov dword [FxTableA1+2Ah*4],FxOp2A + mov dword [FxTableA1+2Bh*4],FxOp2B + mov dword [FxTableA1+2Ch*4],FxOp2C + mov dword [FxTableA1+2Dh*4],FxOp2D + mov dword [FxTableA1+2Eh*4],FxOp2E + mov dword [FxTableA1+2Fh*4],FxOp2F + + mov dword [FxTableA1+30h*4],FxOp30A1 + mov dword [FxTableA1+31h*4],FxOp31A1 + mov dword [FxTableA1+32h*4],FxOp32A1 + mov dword [FxTableA1+33h*4],FxOp33A1 + mov dword [FxTableA1+34h*4],FxOp34A1 + mov dword [FxTableA1+35h*4],FxOp35A1 + mov dword [FxTableA1+36h*4],FxOp36A1 + mov dword [FxTableA1+37h*4],FxOp37A1 + mov dword [FxTableA1+38h*4],FxOp38A1 + mov dword [FxTableA1+39h*4],FxOp39A1 + mov dword [FxTableA1+3Ah*4],FxOp3AA1 + mov dword [FxTableA1+3Bh*4],FxOp3BA1 + mov dword [FxTableA1+3Ch*4],FxOp3C + mov dword [FxTableA1+3Dh*4],FxOp3D + mov dword [FxTableA1+3Eh*4],FxOp3E + mov dword [FxTableA1+3Fh*4],FxOp3F + + mov dword [FxTableA1+40h*4],FxOp40A1 + mov dword [FxTableA1+41h*4],FxOp41A1 + mov dword [FxTableA1+42h*4],FxOp42A1 + mov dword [FxTableA1+43h*4],FxOp43A1 + mov dword [FxTableA1+44h*4],FxOp44A1 + mov dword [FxTableA1+45h*4],FxOp45A1 + mov dword [FxTableA1+46h*4],FxOp46A1 + mov dword [FxTableA1+47h*4],FxOp47A1 + mov dword [FxTableA1+48h*4],FxOp48A1 + mov dword [FxTableA1+49h*4],FxOp49A1 + mov dword [FxTableA1+4Ah*4],FxOp4AA1 + mov dword [FxTableA1+4Bh*4],FxOp4BA1 + mov dword [FxTableA1+4Ch*4],FxOp4CA1 + mov dword [FxTableA1+4Dh*4],FxOp4D + mov dword [FxTableA1+4Eh*4],FxOp4EA1 + mov dword [FxTableA1+4Fh*4],FxOp4F + + mov dword [FxTableA1+50h*4],FxOp50A1 + mov dword [FxTableA1+51h*4],FxOp51A1 + mov dword [FxTableA1+52h*4],FxOp52A1 + mov dword [FxTableA1+53h*4],FxOp53A1 + mov dword [FxTableA1+54h*4],FxOp54A1 + mov dword [FxTableA1+55h*4],FxOp55A1 + mov dword [FxTableA1+56h*4],FxOp56A1 + mov dword [FxTableA1+57h*4],FxOp57A1 + mov dword [FxTableA1+58h*4],FxOp58A1 + mov dword [FxTableA1+59h*4],FxOp59A1 + mov dword [FxTableA1+5Ah*4],FxOp5AA1 + mov dword [FxTableA1+5Bh*4],FxOp5BA1 + mov dword [FxTableA1+5Ch*4],FxOp5CA1 + mov dword [FxTableA1+5Dh*4],FxOp5DA1 + mov dword [FxTableA1+5Eh*4],FxOp5EA1 + mov dword [FxTableA1+5Fh*4],FxOp5FA1 + + mov dword [FxTableA1+60h*4],FxOp60A1 + mov dword [FxTableA1+61h*4],FxOp61A1 + mov dword [FxTableA1+62h*4],FxOp62A1 + mov dword [FxTableA1+63h*4],FxOp63A1 + mov dword [FxTableA1+64h*4],FxOp64A1 + mov dword [FxTableA1+65h*4],FxOp65A1 + mov dword [FxTableA1+66h*4],FxOp66A1 + mov dword [FxTableA1+67h*4],FxOp67A1 + mov dword [FxTableA1+68h*4],FxOp68A1 + mov dword [FxTableA1+69h*4],FxOp69A1 + mov dword [FxTableA1+6Ah*4],FxOp6AA1 + mov dword [FxTableA1+6Bh*4],FxOp6BA1 + mov dword [FxTableA1+6Ch*4],FxOp6CA1 + mov dword [FxTableA1+6Dh*4],FxOp6DA1 + mov dword [FxTableA1+6Eh*4],FxOp6EA1 + mov dword [FxTableA1+6Fh*4],FxOp6FA1 + + mov dword [FxTableA1+70h*4],FxOp70 + mov dword [FxTableA1+71h*4],FxOp71A1 + mov dword [FxTableA1+72h*4],FxOp72A1 + mov dword [FxTableA1+73h*4],FxOp73A1 + mov dword [FxTableA1+74h*4],FxOp74A1 + mov dword [FxTableA1+75h*4],FxOp75A1 + mov dword [FxTableA1+76h*4],FxOp76A1 + mov dword [FxTableA1+77h*4],FxOp77A1 + mov dword [FxTableA1+78h*4],FxOp78A1 + mov dword [FxTableA1+79h*4],FxOp79A1 + mov dword [FxTableA1+7Ah*4],FxOp7AA1 + mov dword [FxTableA1+7Bh*4],FxOp7BA1 + mov dword [FxTableA1+7Ch*4],FxOp7CA1 + mov dword [FxTableA1+7Dh*4],FxOp7DA1 + mov dword [FxTableA1+7Eh*4],FxOp7EA1 + mov dword [FxTableA1+7Fh*4],FxOp7FA1 + + mov dword [FxTableA1+80h*4],FxOp80A1 + mov dword [FxTableA1+81h*4],FxOp81A1 + mov dword [FxTableA1+82h*4],FxOp82A1 + mov dword [FxTableA1+83h*4],FxOp83A1 + mov dword [FxTableA1+84h*4],FxOp84A1 + mov dword [FxTableA1+85h*4],FxOp85A1 + mov dword [FxTableA1+86h*4],FxOp86A1 + mov dword [FxTableA1+87h*4],FxOp87A1 + mov dword [FxTableA1+88h*4],FxOp88A1 + mov dword [FxTableA1+89h*4],FxOp89A1 + mov dword [FxTableA1+8Ah*4],FxOp8AA1 + mov dword [FxTableA1+8Bh*4],FxOp8BA1 + mov dword [FxTableA1+8Ch*4],FxOp8CA1 + mov dword [FxTableA1+8Dh*4],FxOp8DA1 + mov dword [FxTableA1+8Eh*4],FxOp8EA1 + mov dword [FxTableA1+8Fh*4],FxOp8FA1 + + mov dword [FxTableA1+90h*4],FxOp90 + mov dword [FxTableA1+91h*4],FxOp91 + mov dword [FxTableA1+92h*4],FxOp92 + mov dword [FxTableA1+93h*4],FxOp93 + mov dword [FxTableA1+94h*4],FxOp94 + mov dword [FxTableA1+95h*4],FxOp95 + mov dword [FxTableA1+96h*4],FxOp96A1 + mov dword [FxTableA1+97h*4],FxOp97 + mov dword [FxTableA1+98h*4],FxOp98A1 + mov dword [FxTableA1+99h*4],FxOp99A1 + mov dword [FxTableA1+9Ah*4],FxOp9AA1 + mov dword [FxTableA1+9Bh*4],FxOp9BA1 + mov dword [FxTableA1+9Ch*4],FxOp9CA1 + mov dword [FxTableA1+9Dh*4],FxOp9DA1 + mov dword [FxTableA1+9Eh*4],FxOp9E + mov dword [FxTableA1+9Fh*4],FxOp9FA1 + + mov dword [FxTableA1+0A0h*4],FxOpA0A1 + mov dword [FxTableA1+0A1h*4],FxOpA1A1 + mov dword [FxTableA1+0A2h*4],FxOpA2A1 + mov dword [FxTableA1+0A3h*4],FxOpA3A1 + mov dword [FxTableA1+0A4h*4],FxOpA4A1 + mov dword [FxTableA1+0A5h*4],FxOpA5A1 + mov dword [FxTableA1+0A6h*4],FxOpA6A1 + mov dword [FxTableA1+0A7h*4],FxOpA7A1 + mov dword [FxTableA1+0A8h*4],FxOpA8A1 + mov dword [FxTableA1+0A9h*4],FxOpA9A1 + mov dword [FxTableA1+0AAh*4],FxOpAAA1 + mov dword [FxTableA1+0ABh*4],FxOpABA1 + mov dword [FxTableA1+0ACh*4],FxOpACA1 + mov dword [FxTableA1+0ADh*4],FxOpADA1 + mov dword [FxTableA1+0AEh*4],FxOpAEA1 + mov dword [FxTableA1+0AFh*4],FxOpAFA1 + + mov dword [FxTableA1+0B0h*4],FxOpB0 + mov dword [FxTableA1+0B1h*4],FxOpB1 + mov dword [FxTableA1+0B2h*4],FxOpB2 + mov dword [FxTableA1+0B3h*4],FxOpB3 + mov dword [FxTableA1+0B4h*4],FxOpB4 + mov dword [FxTableA1+0B5h*4],FxOpB5 + mov dword [FxTableA1+0B6h*4],FxOpB6 + mov dword [FxTableA1+0B7h*4],FxOpB7 + mov dword [FxTableA1+0B8h*4],FxOpB8 + mov dword [FxTableA1+0B9h*4],FxOpB9 + mov dword [FxTableA1+0BAh*4],FxOpBA + mov dword [FxTableA1+0BBh*4],FxOpBB + mov dword [FxTableA1+0BCh*4],FxOpBC + mov dword [FxTableA1+0BDh*4],FxOpBD + mov dword [FxTableA1+0BEh*4],FxOpBE + mov dword [FxTableA1+0BFh*4],FxOpBF + + mov dword [FxTableA1+0C0h*4],FxOpC0 + mov dword [FxTableA1+0C1h*4],FxOpC1A1 + mov dword [FxTableA1+0C2h*4],FxOpC2A1 + mov dword [FxTableA1+0C3h*4],FxOpC3A1 + mov dword [FxTableA1+0C4h*4],FxOpC4A1 + mov dword [FxTableA1+0C5h*4],FxOpC5A1 + mov dword [FxTableA1+0C6h*4],FxOpC6A1 + mov dword [FxTableA1+0C7h*4],FxOpC7A1 + mov dword [FxTableA1+0C8h*4],FxOpC8A1 + mov dword [FxTableA1+0C9h*4],FxOpC9A1 + mov dword [FxTableA1+0CAh*4],FxOpCAA1 + mov dword [FxTableA1+0CBh*4],FxOpCBA1 + mov dword [FxTableA1+0CCh*4],FxOpCCA1 + mov dword [FxTableA1+0CDh*4],FxOpCDA1 + mov dword [FxTableA1+0CEh*4],FxOpCEA1 + mov dword [FxTableA1+0CFh*4],FxOpCFA1 + + mov dword [FxTableA1+0D0h*4],FxOpD0 + mov dword [FxTableA1+0D1h*4],FxOpD1 + mov dword [FxTableA1+0D2h*4],FxOpD2 + mov dword [FxTableA1+0D3h*4],FxOpD3 + mov dword [FxTableA1+0D4h*4],FxOpD4 + mov dword [FxTableA1+0D5h*4],FxOpD5 + mov dword [FxTableA1+0D6h*4],FxOpD6 + mov dword [FxTableA1+0D7h*4],FxOpD7 + mov dword [FxTableA1+0D8h*4],FxOpD8 + mov dword [FxTableA1+0D9h*4],FxOpD9 + mov dword [FxTableA1+0DAh*4],FxOpDA + mov dword [FxTableA1+0DBh*4],FxOpDB + mov dword [FxTableA1+0DCh*4],FxOpDC + mov dword [FxTableA1+0DDh*4],FxOpDD + mov dword [FxTableA1+0DEh*4],FxOpDE + mov dword [FxTableA1+0DFh*4],FxOpDF + + mov dword [FxTableA1+0E0h*4],FxOpE0 + mov dword [FxTableA1+0E1h*4],FxOpE1 + mov dword [FxTableA1+0E2h*4],FxOpE2 + mov dword [FxTableA1+0E3h*4],FxOpE3 + mov dword [FxTableA1+0E4h*4],FxOpE4 + mov dword [FxTableA1+0E5h*4],FxOpE5 + mov dword [FxTableA1+0E6h*4],FxOpE6 + mov dword [FxTableA1+0E7h*4],FxOpE7 + mov dword [FxTableA1+0E8h*4],FxOpE8 + mov dword [FxTableA1+0E9h*4],FxOpE9 + mov dword [FxTableA1+0EAh*4],FxOpEA + mov dword [FxTableA1+0EBh*4],FxOpEB + mov dword [FxTableA1+0ECh*4],FxOpEC + mov dword [FxTableA1+0EDh*4],FxOpED + mov dword [FxTableA1+0EEh*4],FxOpEE + mov dword [FxTableA1+0EFh*4],FxOpEFA1 + + mov dword [FxTableA1+0F0h*4],FxOpF0A1 + mov dword [FxTableA1+0F1h*4],FxOpF1A1 + mov dword [FxTableA1+0F2h*4],FxOpF2A1 + mov dword [FxTableA1+0F3h*4],FxOpF3A1 + mov dword [FxTableA1+0F4h*4],FxOpF4A1 + mov dword [FxTableA1+0F5h*4],FxOpF5A1 + mov dword [FxTableA1+0F6h*4],FxOpF6A1 + mov dword [FxTableA1+0F7h*4],FxOpF7A1 + mov dword [FxTableA1+0F8h*4],FxOpF8A1 + mov dword [FxTableA1+0F9h*4],FxOpF9A1 + mov dword [FxTableA1+0FAh*4],FxOpFAA1 + mov dword [FxTableA1+0FBh*4],FxOpFBA1 + mov dword [FxTableA1+0FCh*4],FxOpFCA1 + mov dword [FxTableA1+0FDh*4],FxOpFDA1 + mov dword [FxTableA1+0FEh*4],FxOpFEA1 + mov dword [FxTableA1+0FFh*4],FxOpFFA1 + + + mov dword [FxTableA2+00h*4],FxOp00 + mov dword [FxTableA2+01h*4],FxOp01 + mov dword [FxTableA2+02h*4],FxOp02 + mov dword [FxTableA2+03h*4],FxOp03 + mov dword [FxTableA2+04h*4],FxOp04 + mov dword [FxTableA2+05h*4],FxOp05 + mov dword [FxTableA2+06h*4],FxOp06 + mov dword [FxTableA2+07h*4],FxOp07 + mov dword [FxTableA2+08h*4],FxOp08 + mov dword [FxTableA2+09h*4],FxOp09 + mov dword [FxTableA2+0Ah*4],FxOp0A + mov dword [FxTableA2+0Bh*4],FxOp0B + mov dword [FxTableA2+0Ch*4],FxOp0C + mov dword [FxTableA2+0Dh*4],FxOp0D + mov dword [FxTableA2+0Eh*4],FxOp0E + mov dword [FxTableA2+0Fh*4],FxOp0F + + mov dword [FxTableA2+10h*4],FxOp10 + mov dword [FxTableA2+11h*4],FxOp11 + mov dword [FxTableA2+12h*4],FxOp12 + mov dword [FxTableA2+13h*4],FxOp13 + mov dword [FxTableA2+14h*4],FxOp14 + mov dword [FxTableA2+15h*4],FxOp15 + mov dword [FxTableA2+16h*4],FxOp16 + mov dword [FxTableA2+17h*4],FxOp17 + mov dword [FxTableA2+18h*4],FxOp18 + mov dword [FxTableA2+19h*4],FxOp19 + mov dword [FxTableA2+1Ah*4],FxOp1A + mov dword [FxTableA2+1Bh*4],FxOp1B + mov dword [FxTableA2+1Ch*4],FxOp1C + mov dword [FxTableA2+1Dh*4],FxOp1D + mov dword [FxTableA2+1Eh*4],FxOp1E + mov dword [FxTableA2+1Fh*4],FxOp1F + + mov dword [FxTableA2+20h*4],FxOp20 + mov dword [FxTableA2+21h*4],FxOp21 + mov dword [FxTableA2+22h*4],FxOp22 + mov dword [FxTableA2+23h*4],FxOp23 + mov dword [FxTableA2+24h*4],FxOp24 + mov dword [FxTableA2+25h*4],FxOp25 + mov dword [FxTableA2+26h*4],FxOp26 + mov dword [FxTableA2+27h*4],FxOp27 + mov dword [FxTableA2+28h*4],FxOp28 + mov dword [FxTableA2+29h*4],FxOp29 + mov dword [FxTableA2+2Ah*4],FxOp2A + mov dword [FxTableA2+2Bh*4],FxOp2B + mov dword [FxTableA2+2Ch*4],FxOp2C + mov dword [FxTableA2+2Dh*4],FxOp2D + mov dword [FxTableA2+2Eh*4],FxOp2E + mov dword [FxTableA2+2Fh*4],FxOp2F + + mov dword [FxTableA2+30h*4],FxOp30 + mov dword [FxTableA2+31h*4],FxOp31 + mov dword [FxTableA2+32h*4],FxOp32 + mov dword [FxTableA2+33h*4],FxOp33 + mov dword [FxTableA2+34h*4],FxOp34 + mov dword [FxTableA2+35h*4],FxOp35 + mov dword [FxTableA2+36h*4],FxOp36 + mov dword [FxTableA2+37h*4],FxOp37 + mov dword [FxTableA2+38h*4],FxOp38 + mov dword [FxTableA2+39h*4],FxOp39 + mov dword [FxTableA2+3Ah*4],FxOp3A + mov dword [FxTableA2+3Bh*4],FxOp3B + mov dword [FxTableA2+3Ch*4],FxOp3C + mov dword [FxTableA2+3Dh*4],FxOp3D + mov dword [FxTableA2+3Eh*4],FxOp3E + mov dword [FxTableA2+3Fh*4],FxOp3F + + mov dword [FxTableA2+40h*4],FxOp40 + mov dword [FxTableA2+41h*4],FxOp41 + mov dword [FxTableA2+42h*4],FxOp42 + mov dword [FxTableA2+43h*4],FxOp43 + mov dword [FxTableA2+44h*4],FxOp44 + mov dword [FxTableA2+45h*4],FxOp45 + mov dword [FxTableA2+46h*4],FxOp46 + mov dword [FxTableA2+47h*4],FxOp47 + mov dword [FxTableA2+48h*4],FxOp48 + mov dword [FxTableA2+49h*4],FxOp49 + mov dword [FxTableA2+4Ah*4],FxOp4A + mov dword [FxTableA2+4Bh*4],FxOp4B + mov dword [FxTableA2+4Ch*4],FxOp4C + mov dword [FxTableA2+4Dh*4],FxOp4D + mov dword [FxTableA2+4Eh*4],FxOp4E + mov dword [FxTableA2+4Fh*4],FxOp4F + + mov dword [FxTableA2+50h*4],FxOp50A2 + mov dword [FxTableA2+51h*4],FxOp51A2 + mov dword [FxTableA2+52h*4],FxOp52A2 + mov dword [FxTableA2+53h*4],FxOp53A2 + mov dword [FxTableA2+54h*4],FxOp54A2 + mov dword [FxTableA2+55h*4],FxOp55A2 + mov dword [FxTableA2+56h*4],FxOp56A2 + mov dword [FxTableA2+57h*4],FxOp57A2 + mov dword [FxTableA2+58h*4],FxOp58A2 + mov dword [FxTableA2+59h*4],FxOp59A2 + mov dword [FxTableA2+5Ah*4],FxOp5AA2 + mov dword [FxTableA2+5Bh*4],FxOp5BA2 + mov dword [FxTableA2+5Ch*4],FxOp5CA2 + mov dword [FxTableA2+5Dh*4],FxOp5DA2 + mov dword [FxTableA2+5Eh*4],FxOp5EA2 + mov dword [FxTableA2+5Fh*4],FxOp5FA2 + + mov dword [FxTableA2+60h*4],FxOp60A2 + mov dword [FxTableA2+61h*4],FxOp61A2 + mov dword [FxTableA2+62h*4],FxOp62A2 + mov dword [FxTableA2+63h*4],FxOp63A2 + mov dword [FxTableA2+64h*4],FxOp64A2 + mov dword [FxTableA2+65h*4],FxOp65A2 + mov dword [FxTableA2+66h*4],FxOp66A2 + mov dword [FxTableA2+67h*4],FxOp67A2 + mov dword [FxTableA2+68h*4],FxOp68A2 + mov dword [FxTableA2+69h*4],FxOp69A2 + mov dword [FxTableA2+6Ah*4],FxOp6AA2 + mov dword [FxTableA2+6Bh*4],FxOp6BA2 + mov dword [FxTableA2+6Ch*4],FxOp6CA2 + mov dword [FxTableA2+6Dh*4],FxOp6DA2 + mov dword [FxTableA2+6Eh*4],FxOp6EA2 + mov dword [FxTableA2+6Fh*4],FxOp6FA2 + + mov dword [FxTableA2+70h*4],FxOp70 + mov dword [FxTableA2+71h*4],FxOp71A2 + mov dword [FxTableA2+72h*4],FxOp72A2 + mov dword [FxTableA2+73h*4],FxOp73A2 + mov dword [FxTableA2+74h*4],FxOp74A2 + mov dword [FxTableA2+75h*4],FxOp75A2 + mov dword [FxTableA2+76h*4],FxOp76A2 + mov dword [FxTableA2+77h*4],FxOp77A2 + mov dword [FxTableA2+78h*4],FxOp78A2 + mov dword [FxTableA2+79h*4],FxOp79A2 + mov dword [FxTableA2+7Ah*4],FxOp7AA2 + mov dword [FxTableA2+7Bh*4],FxOp7BA2 + mov dword [FxTableA2+7Ch*4],FxOp7CA2 + mov dword [FxTableA2+7Dh*4],FxOp7DA2 + mov dword [FxTableA2+7Eh*4],FxOp7EA2 + mov dword [FxTableA2+7Fh*4],FxOp7FA2 + + mov dword [FxTableA2+80h*4],FxOp80A2 + mov dword [FxTableA2+81h*4],FxOp81A2 + mov dword [FxTableA2+82h*4],FxOp82A2 + mov dword [FxTableA2+83h*4],FxOp83A2 + mov dword [FxTableA2+84h*4],FxOp84A2 + mov dword [FxTableA2+85h*4],FxOp85A2 + mov dword [FxTableA2+86h*4],FxOp86A2 + mov dword [FxTableA2+87h*4],FxOp87A2 + mov dword [FxTableA2+88h*4],FxOp88A2 + mov dword [FxTableA2+89h*4],FxOp89A2 + mov dword [FxTableA2+8Ah*4],FxOp8AA2 + mov dword [FxTableA2+8Bh*4],FxOp8BA2 + mov dword [FxTableA2+8Ch*4],FxOp8CA2 + mov dword [FxTableA2+8Dh*4],FxOp8DA2 + mov dword [FxTableA2+8Eh*4],FxOp8EA2 + mov dword [FxTableA2+8Fh*4],FxOp8FA2 + + mov dword [FxTableA2+90h*4],FxOp90 + mov dword [FxTableA2+91h*4],FxOp91 + mov dword [FxTableA2+92h*4],FxOp92 + mov dword [FxTableA2+93h*4],FxOp93 + mov dword [FxTableA2+94h*4],FxOp94 + mov dword [FxTableA2+95h*4],FxOp95 + mov dword [FxTableA2+96h*4],FxOp96 + mov dword [FxTableA2+97h*4],FxOp97 + mov dword [FxTableA2+98h*4],FxOp98 + mov dword [FxTableA2+99h*4],FxOp99 + mov dword [FxTableA2+9Ah*4],FxOp9A + mov dword [FxTableA2+9Bh*4],FxOp9B + mov dword [FxTableA2+9Ch*4],FxOp9C + mov dword [FxTableA2+9Dh*4],FxOp9D + mov dword [FxTableA2+9Eh*4],FxOp9E + mov dword [FxTableA2+9Fh*4],FxOp9F + + mov dword [FxTableA2+0A0h*4],FxOpA0A2 + mov dword [FxTableA2+0A1h*4],FxOpA1A2 + mov dword [FxTableA2+0A2h*4],FxOpA2A2 + mov dword [FxTableA2+0A3h*4],FxOpA3A2 + mov dword [FxTableA2+0A4h*4],FxOpA4A2 + mov dword [FxTableA2+0A5h*4],FxOpA5A2 + mov dword [FxTableA2+0A6h*4],FxOpA6A2 + mov dword [FxTableA2+0A7h*4],FxOpA7A2 + mov dword [FxTableA2+0A8h*4],FxOpA8A2 + mov dword [FxTableA2+0A9h*4],FxOpA9A2 + mov dword [FxTableA2+0AAh*4],FxOpAAA2 + mov dword [FxTableA2+0ABh*4],FxOpABA2 + mov dword [FxTableA2+0ACh*4],FxOpACA2 + mov dword [FxTableA2+0ADh*4],FxOpADA2 + mov dword [FxTableA2+0AEh*4],FxOpAEA2 + mov dword [FxTableA2+0AFh*4],FxOpAFA2 + + mov dword [FxTableA2+0B0h*4],FxOpB0 + mov dword [FxTableA2+0B1h*4],FxOpB1 + mov dword [FxTableA2+0B2h*4],FxOpB2 + mov dword [FxTableA2+0B3h*4],FxOpB3 + mov dword [FxTableA2+0B4h*4],FxOpB4 + mov dword [FxTableA2+0B5h*4],FxOpB5 + mov dword [FxTableA2+0B6h*4],FxOpB6 + mov dword [FxTableA2+0B7h*4],FxOpB7 + mov dword [FxTableA2+0B8h*4],FxOpB8 + mov dword [FxTableA2+0B9h*4],FxOpB9 + mov dword [FxTableA2+0BAh*4],FxOpBA + mov dword [FxTableA2+0BBh*4],FxOpBB + mov dword [FxTableA2+0BCh*4],FxOpBC + mov dword [FxTableA2+0BDh*4],FxOpBD + mov dword [FxTableA2+0BEh*4],FxOpBE + mov dword [FxTableA2+0BFh*4],FxOpBF + + mov dword [FxTableA2+0C0h*4],FxOpC0 + mov dword [FxTableA2+0C1h*4],FxOpC1A2 + mov dword [FxTableA2+0C2h*4],FxOpC2A2 + mov dword [FxTableA2+0C3h*4],FxOpC3A2 + mov dword [FxTableA2+0C4h*4],FxOpC4A2 + mov dword [FxTableA2+0C5h*4],FxOpC5A2 + mov dword [FxTableA2+0C6h*4],FxOpC6A2 + mov dword [FxTableA2+0C7h*4],FxOpC7A2 + mov dword [FxTableA2+0C8h*4],FxOpC8A2 + mov dword [FxTableA2+0C9h*4],FxOpC9A2 + mov dword [FxTableA2+0CAh*4],FxOpCAA2 + mov dword [FxTableA2+0CBh*4],FxOpCBA2 + mov dword [FxTableA2+0CCh*4],FxOpCCA2 + mov dword [FxTableA2+0CDh*4],FxOpCDA2 + mov dword [FxTableA2+0CEh*4],FxOpCEA2 + mov dword [FxTableA2+0CFh*4],FxOpCFA2 + + mov dword [FxTableA2+0D0h*4],FxOpD0 + mov dword [FxTableA2+0D1h*4],FxOpD1 + mov dword [FxTableA2+0D2h*4],FxOpD2 + mov dword [FxTableA2+0D3h*4],FxOpD3 + mov dword [FxTableA2+0D4h*4],FxOpD4 + mov dword [FxTableA2+0D5h*4],FxOpD5 + mov dword [FxTableA2+0D6h*4],FxOpD6 + mov dword [FxTableA2+0D7h*4],FxOpD7 + mov dword [FxTableA2+0D8h*4],FxOpD8 + mov dword [FxTableA2+0D9h*4],FxOpD9 + mov dword [FxTableA2+0DAh*4],FxOpDA + mov dword [FxTableA2+0DBh*4],FxOpDB + mov dword [FxTableA2+0DCh*4],FxOpDC + mov dword [FxTableA2+0DDh*4],FxOpDD + mov dword [FxTableA2+0DEh*4],FxOpDE + mov dword [FxTableA2+0DFh*4],FxOpDFA2 + + mov dword [FxTableA2+0E0h*4],FxOpE0 + mov dword [FxTableA2+0E1h*4],FxOpE1 + mov dword [FxTableA2+0E2h*4],FxOpE2 + mov dword [FxTableA2+0E3h*4],FxOpE3 + mov dword [FxTableA2+0E4h*4],FxOpE4 + mov dword [FxTableA2+0E5h*4],FxOpE5 + mov dword [FxTableA2+0E6h*4],FxOpE6 + mov dword [FxTableA2+0E7h*4],FxOpE7 + mov dword [FxTableA2+0E8h*4],FxOpE8 + mov dword [FxTableA2+0E9h*4],FxOpE9 + mov dword [FxTableA2+0EAh*4],FxOpEA + mov dword [FxTableA2+0EBh*4],FxOpEB + mov dword [FxTableA2+0ECh*4],FxOpEC + mov dword [FxTableA2+0EDh*4],FxOpED + mov dword [FxTableA2+0EEh*4],FxOpEE + mov dword [FxTableA2+0EFh*4],FxOpEFA2 + + mov dword [FxTableA2+0F0h*4],FxOpF0A2 + mov dword [FxTableA2+0F1h*4],FxOpF1A2 + mov dword [FxTableA2+0F2h*4],FxOpF2A2 + mov dword [FxTableA2+0F3h*4],FxOpF3A2 + mov dword [FxTableA2+0F4h*4],FxOpF4A2 + mov dword [FxTableA2+0F5h*4],FxOpF5A2 + mov dword [FxTableA2+0F6h*4],FxOpF6A2 + mov dword [FxTableA2+0F7h*4],FxOpF7A2 + mov dword [FxTableA2+0F8h*4],FxOpF8A2 + mov dword [FxTableA2+0F9h*4],FxOpF9A2 + mov dword [FxTableA2+0FAh*4],FxOpFAA2 + mov dword [FxTableA2+0FBh*4],FxOpFBA2 + mov dword [FxTableA2+0FCh*4],FxOpFCA2 + mov dword [FxTableA2+0FDh*4],FxOpFDA2 + mov dword [FxTableA2+0FEh*4],FxOpFEA2 + mov dword [FxTableA2+0FFh*4],FxOpFFA2 + + mov dword [FxTableA3+00h*4],FxOp00 + mov dword [FxTableA3+01h*4],FxOp01 + mov dword [FxTableA3+02h*4],FxOp02 + mov dword [FxTableA3+03h*4],FxOp03 + mov dword [FxTableA3+04h*4],FxOp04 + mov dword [FxTableA3+05h*4],FxOp05 + mov dword [FxTableA3+06h*4],FxOp06 + mov dword [FxTableA3+07h*4],FxOp07 + mov dword [FxTableA3+08h*4],FxOp08 + mov dword [FxTableA3+09h*4],FxOp09 + mov dword [FxTableA3+0Ah*4],FxOp0A + mov dword [FxTableA3+0Bh*4],FxOp0B + mov dword [FxTableA3+0Ch*4],FxOp0C + mov dword [FxTableA3+0Dh*4],FxOp0D + mov dword [FxTableA3+0Eh*4],FxOp0E + mov dword [FxTableA3+0Fh*4],FxOp0F + + mov dword [FxTableA3+10h*4],FxOp10 + mov dword [FxTableA3+11h*4],FxOp11 + mov dword [FxTableA3+12h*4],FxOp12 + mov dword [FxTableA3+13h*4],FxOp13 + mov dword [FxTableA3+14h*4],FxOp14 + mov dword [FxTableA3+15h*4],FxOp15 + mov dword [FxTableA3+16h*4],FxOp16 + mov dword [FxTableA3+17h*4],FxOp17 + mov dword [FxTableA3+18h*4],FxOp18 + mov dword [FxTableA3+19h*4],FxOp19 + mov dword [FxTableA3+1Ah*4],FxOp1A + mov dword [FxTableA3+1Bh*4],FxOp1B + mov dword [FxTableA3+1Ch*4],FxOp1C + mov dword [FxTableA3+1Dh*4],FxOp1D + mov dword [FxTableA3+1Eh*4],FxOp1E + mov dword [FxTableA3+1Fh*4],FxOp1F + + mov dword [FxTableA3+20h*4],FxOp20 + mov dword [FxTableA3+21h*4],FxOp21 + mov dword [FxTableA3+22h*4],FxOp22 + mov dword [FxTableA3+23h*4],FxOp23 + mov dword [FxTableA3+24h*4],FxOp24 + mov dword [FxTableA3+25h*4],FxOp25 + mov dword [FxTableA3+26h*4],FxOp26 + mov dword [FxTableA3+27h*4],FxOp27 + mov dword [FxTableA3+28h*4],FxOp28 + mov dword [FxTableA3+29h*4],FxOp29 + mov dword [FxTableA3+2Ah*4],FxOp2A + mov dword [FxTableA3+2Bh*4],FxOp2B + mov dword [FxTableA3+2Ch*4],FxOp2C + mov dword [FxTableA3+2Dh*4],FxOp2D + mov dword [FxTableA3+2Eh*4],FxOp2E + mov dword [FxTableA3+2Fh*4],FxOp2F + + mov dword [FxTableA3+30h*4],FxOp30 + mov dword [FxTableA3+31h*4],FxOp31 + mov dword [FxTableA3+32h*4],FxOp32 + mov dword [FxTableA3+33h*4],FxOp33 + mov dword [FxTableA3+34h*4],FxOp34 + mov dword [FxTableA3+35h*4],FxOp35 + mov dword [FxTableA3+36h*4],FxOp36 + mov dword [FxTableA3+37h*4],FxOp37 + mov dword [FxTableA3+38h*4],FxOp38 + mov dword [FxTableA3+39h*4],FxOp39 + mov dword [FxTableA3+3Ah*4],FxOp3A + mov dword [FxTableA3+3Bh*4],FxOp3B + mov dword [FxTableA3+3Ch*4],FxOp3C + mov dword [FxTableA3+3Dh*4],FxOp3D + mov dword [FxTableA3+3Eh*4],FxOp3E + mov dword [FxTableA3+3Fh*4],FxOp3F + + mov dword [FxTableA3+40h*4],FxOp40 + mov dword [FxTableA3+41h*4],FxOp41 + mov dword [FxTableA3+42h*4],FxOp42 + mov dword [FxTableA3+43h*4],FxOp43 + mov dword [FxTableA3+44h*4],FxOp44 + mov dword [FxTableA3+45h*4],FxOp45 + mov dword [FxTableA3+46h*4],FxOp46 + mov dword [FxTableA3+47h*4],FxOp47 + mov dword [FxTableA3+48h*4],FxOp48 + mov dword [FxTableA3+49h*4],FxOp49 + mov dword [FxTableA3+4Ah*4],FxOp4A + mov dword [FxTableA3+4Bh*4],FxOp4B + mov dword [FxTableA3+4Ch*4],FxOp4C + mov dword [FxTableA3+4Dh*4],FxOp4D + mov dword [FxTableA3+4Eh*4],FxOp4E + mov dword [FxTableA3+4Fh*4],FxOp4F + + mov dword [FxTableA3+50h*4],FxOp50A3 + mov dword [FxTableA3+51h*4],FxOp51A3 + mov dword [FxTableA3+52h*4],FxOp52A3 + mov dword [FxTableA3+53h*4],FxOp53A3 + mov dword [FxTableA3+54h*4],FxOp54A3 + mov dword [FxTableA3+55h*4],FxOp55A3 + mov dword [FxTableA3+56h*4],FxOp56A3 + mov dword [FxTableA3+57h*4],FxOp57A3 + mov dword [FxTableA3+58h*4],FxOp58A3 + mov dword [FxTableA3+59h*4],FxOp59A3 + mov dword [FxTableA3+5Ah*4],FxOp5AA3 + mov dword [FxTableA3+5Bh*4],FxOp5BA3 + mov dword [FxTableA3+5Ch*4],FxOp5CA3 + mov dword [FxTableA3+5Dh*4],FxOp5DA3 + mov dword [FxTableA3+5Eh*4],FxOp5EA3 + mov dword [FxTableA3+5Fh*4],FxOp5FA3 + + mov dword [FxTableA3+60h*4],FxOp60A3 + mov dword [FxTableA3+61h*4],FxOp61A3 + mov dword [FxTableA3+62h*4],FxOp62A3 + mov dword [FxTableA3+63h*4],FxOp63A3 + mov dword [FxTableA3+64h*4],FxOp64A3 + mov dword [FxTableA3+65h*4],FxOp65A3 + mov dword [FxTableA3+66h*4],FxOp66A3 + mov dword [FxTableA3+67h*4],FxOp67A3 + mov dword [FxTableA3+68h*4],FxOp68A3 + mov dword [FxTableA3+69h*4],FxOp69A3 + mov dword [FxTableA3+6Ah*4],FxOp6AA3 + mov dword [FxTableA3+6Bh*4],FxOp6BA3 + mov dword [FxTableA3+6Ch*4],FxOp6CA3 + mov dword [FxTableA3+6Dh*4],FxOp6DA3 + mov dword [FxTableA3+6Eh*4],FxOp6EA3 + mov dword [FxTableA3+6Fh*4],FxOp6FA3 + + mov dword [FxTableA3+70h*4],FxOp70 + mov dword [FxTableA3+71h*4],FxOp71A3 + mov dword [FxTableA3+72h*4],FxOp72A3 + mov dword [FxTableA3+73h*4],FxOp73A3 + mov dword [FxTableA3+74h*4],FxOp74A3 + mov dword [FxTableA3+75h*4],FxOp75A3 + mov dword [FxTableA3+76h*4],FxOp76A3 + mov dword [FxTableA3+77h*4],FxOp77A3 + mov dword [FxTableA3+78h*4],FxOp78A3 + mov dword [FxTableA3+79h*4],FxOp79A3 + mov dword [FxTableA3+7Ah*4],FxOp7AA3 + mov dword [FxTableA3+7Bh*4],FxOp7BA3 + mov dword [FxTableA3+7Ch*4],FxOp7CA3 + mov dword [FxTableA3+7Dh*4],FxOp7DA3 + mov dword [FxTableA3+7Eh*4],FxOp7EA3 + mov dword [FxTableA3+7Fh*4],FxOp7FA3 + + mov dword [FxTableA3+80h*4],FxOp80A3 + mov dword [FxTableA3+81h*4],FxOp81A3 + mov dword [FxTableA3+82h*4],FxOp82A3 + mov dword [FxTableA3+83h*4],FxOp83A3 + mov dword [FxTableA3+84h*4],FxOp84A3 + mov dword [FxTableA3+85h*4],FxOp85A3 + mov dword [FxTableA3+86h*4],FxOp86A3 + mov dword [FxTableA3+87h*4],FxOp87A3 + mov dword [FxTableA3+88h*4],FxOp88A3 + mov dword [FxTableA3+89h*4],FxOp89A3 + mov dword [FxTableA3+8Ah*4],FxOp8AA3 + mov dword [FxTableA3+8Bh*4],FxOp8BA3 + mov dword [FxTableA3+8Ch*4],FxOp8CA3 + mov dword [FxTableA3+8Dh*4],FxOp8DA3 + mov dword [FxTableA3+8Eh*4],FxOp8EA3 + mov dword [FxTableA3+8Fh*4],FxOp8FA3 + + mov dword [FxTableA3+90h*4],FxOp90 + mov dword [FxTableA3+91h*4],FxOp91 + mov dword [FxTableA3+92h*4],FxOp92 + mov dword [FxTableA3+93h*4],FxOp93 + mov dword [FxTableA3+94h*4],FxOp94 + mov dword [FxTableA3+95h*4],FxOp95 + mov dword [FxTableA3+96h*4],FxOp96 + mov dword [FxTableA3+97h*4],FxOp97 + mov dword [FxTableA3+98h*4],FxOp98 + mov dword [FxTableA3+99h*4],FxOp99 + mov dword [FxTableA3+9Ah*4],FxOp9A + mov dword [FxTableA3+9Bh*4],FxOp9B + mov dword [FxTableA3+9Ch*4],FxOp9C + mov dword [FxTableA3+9Dh*4],FxOp9D + mov dword [FxTableA3+9Eh*4],FxOp9E + mov dword [FxTableA3+9Fh*4],FxOp9F + + mov dword [FxTableA3+0A0h*4],FxOpA0 + mov dword [FxTableA3+0A1h*4],FxOpA1 + mov dword [FxTableA3+0A2h*4],FxOpA2 + mov dword [FxTableA3+0A3h*4],FxOpA3 + mov dword [FxTableA3+0A4h*4],FxOpA4 + mov dword [FxTableA3+0A5h*4],FxOpA5 + mov dword [FxTableA3+0A6h*4],FxOpA6 + mov dword [FxTableA3+0A7h*4],FxOpA7 + mov dword [FxTableA3+0A8h*4],FxOpA8 + mov dword [FxTableA3+0A9h*4],FxOpA9 + mov dword [FxTableA3+0AAh*4],FxOpAA + mov dword [FxTableA3+0ABh*4],FxOpAB + mov dword [FxTableA3+0ACh*4],FxOpAC + mov dword [FxTableA3+0ADh*4],FxOpAD + mov dword [FxTableA3+0AEh*4],FxOpAE + mov dword [FxTableA3+0AFh*4],FxOpAF + + mov dword [FxTableA3+0B0h*4],FxOpB0 + mov dword [FxTableA3+0B1h*4],FxOpB1 + mov dword [FxTableA3+0B2h*4],FxOpB2 + mov dword [FxTableA3+0B3h*4],FxOpB3 + mov dword [FxTableA3+0B4h*4],FxOpB4 + mov dword [FxTableA3+0B5h*4],FxOpB5 + mov dword [FxTableA3+0B6h*4],FxOpB6 + mov dword [FxTableA3+0B7h*4],FxOpB7 + mov dword [FxTableA3+0B8h*4],FxOpB8 + mov dword [FxTableA3+0B9h*4],FxOpB9 + mov dword [FxTableA3+0BAh*4],FxOpBA + mov dword [FxTableA3+0BBh*4],FxOpBB + mov dword [FxTableA3+0BCh*4],FxOpBC + mov dword [FxTableA3+0BDh*4],FxOpBD + mov dword [FxTableA3+0BEh*4],FxOpBE + mov dword [FxTableA3+0BFh*4],FxOpBF + + mov dword [FxTableA3+0C0h*4],FxOpC0 + mov dword [FxTableA3+0C1h*4],FxOpC1A3 + mov dword [FxTableA3+0C2h*4],FxOpC2A3 + mov dword [FxTableA3+0C3h*4],FxOpC3A3 + mov dword [FxTableA3+0C4h*4],FxOpC4A3 + mov dword [FxTableA3+0C5h*4],FxOpC5A3 + mov dword [FxTableA3+0C6h*4],FxOpC6A3 + mov dword [FxTableA3+0C7h*4],FxOpC7A3 + mov dword [FxTableA3+0C8h*4],FxOpC8A3 + mov dword [FxTableA3+0C9h*4],FxOpC9A3 + mov dword [FxTableA3+0CAh*4],FxOpCAA3 + mov dword [FxTableA3+0CBh*4],FxOpCBA3 + mov dword [FxTableA3+0CCh*4],FxOpCCA3 + mov dword [FxTableA3+0CDh*4],FxOpCDA3 + mov dword [FxTableA3+0CEh*4],FxOpCEA3 + mov dword [FxTableA3+0CFh*4],FxOpCFA3 + + mov dword [FxTableA3+0D0h*4],FxOpD0 + mov dword [FxTableA3+0D1h*4],FxOpD1 + mov dword [FxTableA3+0D2h*4],FxOpD2 + mov dword [FxTableA3+0D3h*4],FxOpD3 + mov dword [FxTableA3+0D4h*4],FxOpD4 + mov dword [FxTableA3+0D5h*4],FxOpD5 + mov dword [FxTableA3+0D6h*4],FxOpD6 + mov dword [FxTableA3+0D7h*4],FxOpD7 + mov dword [FxTableA3+0D8h*4],FxOpD8 + mov dword [FxTableA3+0D9h*4],FxOpD9 + mov dword [FxTableA3+0DAh*4],FxOpDA + mov dword [FxTableA3+0DBh*4],FxOpDB + mov dword [FxTableA3+0DCh*4],FxOpDC + mov dword [FxTableA3+0DDh*4],FxOpDD + mov dword [FxTableA3+0DEh*4],FxOpDE + mov dword [FxTableA3+0DFh*4],FxOpDFA3 + + mov dword [FxTableA3+0E0h*4],FxOpE0 + mov dword [FxTableA3+0E1h*4],FxOpE1 + mov dword [FxTableA3+0E2h*4],FxOpE2 + mov dword [FxTableA3+0E3h*4],FxOpE3 + mov dword [FxTableA3+0E4h*4],FxOpE4 + mov dword [FxTableA3+0E5h*4],FxOpE5 + mov dword [FxTableA3+0E6h*4],FxOpE6 + mov dword [FxTableA3+0E7h*4],FxOpE7 + mov dword [FxTableA3+0E8h*4],FxOpE8 + mov dword [FxTableA3+0E9h*4],FxOpE9 + mov dword [FxTableA3+0EAh*4],FxOpEA + mov dword [FxTableA3+0EBh*4],FxOpEB + mov dword [FxTableA3+0ECh*4],FxOpEC + mov dword [FxTableA3+0EDh*4],FxOpED + mov dword [FxTableA3+0EEh*4],FxOpEE + mov dword [FxTableA3+0EFh*4],FxOpEFA3 + + mov dword [FxTableA3+0F0h*4],FxOpF0 + mov dword [FxTableA3+0F1h*4],FxOpF1 + mov dword [FxTableA3+0F2h*4],FxOpF2 + mov dword [FxTableA3+0F3h*4],FxOpF3 + mov dword [FxTableA3+0F4h*4],FxOpF4 + mov dword [FxTableA3+0F5h*4],FxOpF5 + mov dword [FxTableA3+0F6h*4],FxOpF6 + mov dword [FxTableA3+0F7h*4],FxOpF7 + mov dword [FxTableA3+0F8h*4],FxOpF8 + mov dword [FxTableA3+0F9h*4],FxOpF9 + mov dword [FxTableA3+0FAh*4],FxOpFA + mov dword [FxTableA3+0FBh*4],FxOpFB + mov dword [FxTableA3+0FCh*4],FxOpFC + mov dword [FxTableA3+0FDh*4],FxOpFD + mov dword [FxTableA3+0FEh*4],FxOpFE + mov dword [FxTableA3+0FFh*4],FxOpFF + + ; Transfer FxTable to FxTableb and FxTablec + mov esi,FxTable + mov edi,FxTableb + mov ecx,256*4 + rep movsd + mov esi,FxTable + mov edi,FxTablec + mov ecx,256*4 + rep movsd + + mov dword [FxTableb+05h*4],FxOpb05 + mov dword [FxTableb+06h*4],FxOpb06 + mov dword [FxTableb+07h*4],FxOpb07 + mov dword [FxTableb+08h*4],FxOpb08 + mov dword [FxTableb+09h*4],FxOpb09 + mov dword [FxTableb+0Ah*4],FxOpb0A + mov dword [FxTableb+0Bh*4],FxOpb0B + mov dword [FxTableb+0Ch*4],FxOpb0C + mov dword [FxTableb+0Dh*4],FxOpb0D + mov dword [FxTableb+0Eh*4],FxOpb0E + mov dword [FxTableb+0Fh*4],FxOpb0F + mov dword [FxTableb+10h*4],FxOpb10 + mov dword [FxTableb+11h*4],FxOpb11 + mov dword [FxTableb+12h*4],FxOpb12 + mov dword [FxTableb+13h*4],FxOpb13 + mov dword [FxTableb+14h*4],FxOpb14 + mov dword [FxTableb+15h*4],FxOpb15 + mov dword [FxTableb+16h*4],FxOpb16 + mov dword [FxTableb+17h*4],FxOpb17 + mov dword [FxTableb+18h*4],FxOpb18 + mov dword [FxTableb+19h*4],FxOpb19 + mov dword [FxTableb+1Ah*4],FxOpb1A + mov dword [FxTableb+1Bh*4],FxOpb1B + mov dword [FxTableb+1Ch*4],FxOpb1C + mov dword [FxTableb+1Dh*4],FxOpb1D + mov dword [FxTableb+1Eh*4],FxOpb1E + mov dword [FxTableb+1Fh*4],FxOpb1F + mov dword [FxTableb+3Dh*4],FxOpb3D + mov dword [FxTableb+3Eh*4],FxOpb3E + mov dword [FxTableb+3Fh*4],FxOpb3F + mov dword [FxTableb+0B0h*4],FxOpbB0 + mov dword [FxTableb+0B1h*4],FxOpbB1 + mov dword [FxTableb+0B2h*4],FxOpbB2 + mov dword [FxTableb+0B3h*4],FxOpbB3 + mov dword [FxTableb+0B4h*4],FxOpbB4 + mov dword [FxTableb+0B5h*4],FxOpbB5 + mov dword [FxTableb+0B6h*4],FxOpbB6 + mov dword [FxTableb+0B7h*4],FxOpbB7 + mov dword [FxTableb+0B8h*4],FxOpbB8 + mov dword [FxTableb+0B9h*4],FxOpbB9 + mov dword [FxTableb+0BAh*4],FxOpbBA + mov dword [FxTableb+0BBh*4],FxOpbBB + mov dword [FxTableb+0BCh*4],FxOpbBC + mov dword [FxTableb+0BDh*4],FxOpbBD + mov dword [FxTableb+0BEh*4],FxOpbBE + mov dword [FxTableb+0BFh*4],FxOpbBF + + mov dword [FxTablebA1+05h*4],FxOpb05 + mov dword [FxTablebA1+06h*4],FxOpb06 + mov dword [FxTablebA1+07h*4],FxOpb07 + mov dword [FxTablebA1+08h*4],FxOpb08 + mov dword [FxTablebA1+09h*4],FxOpb09 + mov dword [FxTablebA1+0Ah*4],FxOpb0A + mov dword [FxTablebA1+0Bh*4],FxOpb0B + mov dword [FxTablebA1+0Ch*4],FxOpb0C + mov dword [FxTablebA1+0Dh*4],FxOpb0D + mov dword [FxTablebA1+0Eh*4],FxOpb0E + mov dword [FxTablebA1+0Fh*4],FxOpb0F + mov dword [FxTablebA1+10h*4],FxOpb10 + mov dword [FxTablebA1+11h*4],FxOpb11 + mov dword [FxTablebA1+12h*4],FxOpb12 + mov dword [FxTablebA1+13h*4],FxOpb13 + mov dword [FxTablebA1+14h*4],FxOpb14 + mov dword [FxTablebA1+15h*4],FxOpb15 + mov dword [FxTablebA1+16h*4],FxOpb16 + mov dword [FxTablebA1+17h*4],FxOpb17 + mov dword [FxTablebA1+18h*4],FxOpb18 + mov dword [FxTablebA1+19h*4],FxOpb19 + mov dword [FxTablebA1+1Ah*4],FxOpb1A + mov dword [FxTablebA1+1Bh*4],FxOpb1B + mov dword [FxTablebA1+1Ch*4],FxOpb1C + mov dword [FxTablebA1+1Dh*4],FxOpb1D + mov dword [FxTablebA1+1Eh*4],FxOpb1E + mov dword [FxTablebA1+1Fh*4],FxOpb1F + mov dword [FxTablebA1+3Dh*4],FxOpb3D + mov dword [FxTablebA1+3Eh*4],FxOpb3E + mov dword [FxTablebA1+3Fh*4],FxOpb3F + mov dword [FxTablebA1+0B0h*4],FxOpbB0 + mov dword [FxTablebA1+0B1h*4],FxOpbB1 + mov dword [FxTablebA1+0B2h*4],FxOpbB2 + mov dword [FxTablebA1+0B3h*4],FxOpbB3 + mov dword [FxTablebA1+0B4h*4],FxOpbB4 + mov dword [FxTablebA1+0B5h*4],FxOpbB5 + mov dword [FxTablebA1+0B6h*4],FxOpbB6 + mov dword [FxTablebA1+0B7h*4],FxOpbB7 + mov dword [FxTablebA1+0B8h*4],FxOpbB8 + mov dword [FxTablebA1+0B9h*4],FxOpbB9 + mov dword [FxTablebA1+0BAh*4],FxOpbBA + mov dword [FxTablebA1+0BBh*4],FxOpbBB + mov dword [FxTablebA1+0BCh*4],FxOpbBC + mov dword [FxTablebA1+0BDh*4],FxOpbBD + mov dword [FxTablebA1+0BEh*4],FxOpbBE + mov dword [FxTablebA1+0BFh*4],FxOpbBF + + mov dword [FxTablebA2+05h*4],FxOpb05 + mov dword [FxTablebA2+06h*4],FxOpb06 + mov dword [FxTablebA2+07h*4],FxOpb07 + mov dword [FxTablebA2+08h*4],FxOpb08 + mov dword [FxTablebA2+09h*4],FxOpb09 + mov dword [FxTablebA2+0Ah*4],FxOpb0A + mov dword [FxTablebA2+0Bh*4],FxOpb0B + mov dword [FxTablebA2+0Ch*4],FxOpb0C + mov dword [FxTablebA2+0Dh*4],FxOpb0D + mov dword [FxTablebA2+0Eh*4],FxOpb0E + mov dword [FxTablebA2+0Fh*4],FxOpb0F + mov dword [FxTablebA2+10h*4],FxOpb10 + mov dword [FxTablebA2+11h*4],FxOpb11 + mov dword [FxTablebA2+12h*4],FxOpb12 + mov dword [FxTablebA2+13h*4],FxOpb13 + mov dword [FxTablebA2+14h*4],FxOpb14 + mov dword [FxTablebA2+15h*4],FxOpb15 + mov dword [FxTablebA2+16h*4],FxOpb16 + mov dword [FxTablebA2+17h*4],FxOpb17 + mov dword [FxTablebA2+18h*4],FxOpb18 + mov dword [FxTablebA2+19h*4],FxOpb19 + mov dword [FxTablebA2+1Ah*4],FxOpb1A + mov dword [FxTablebA2+1Bh*4],FxOpb1B + mov dword [FxTablebA2+1Ch*4],FxOpb1C + mov dword [FxTablebA2+1Dh*4],FxOpb1D + mov dword [FxTablebA2+1Eh*4],FxOpb1E + mov dword [FxTablebA2+1Fh*4],FxOpb1F + mov dword [FxTablebA2+3Dh*4],FxOpb3D + mov dword [FxTablebA2+3Eh*4],FxOpb3E + mov dword [FxTablebA2+3Fh*4],FxOpb3F + mov dword [FxTablebA2+0B0h*4],FxOpbB0 + mov dword [FxTablebA2+0B1h*4],FxOpbB1 + mov dword [FxTablebA2+0B2h*4],FxOpbB2 + mov dword [FxTablebA2+0B3h*4],FxOpbB3 + mov dword [FxTablebA2+0B4h*4],FxOpbB4 + mov dword [FxTablebA2+0B5h*4],FxOpbB5 + mov dword [FxTablebA2+0B6h*4],FxOpbB6 + mov dword [FxTablebA2+0B7h*4],FxOpbB7 + mov dword [FxTablebA2+0B8h*4],FxOpbB8 + mov dword [FxTablebA2+0B9h*4],FxOpbB9 + mov dword [FxTablebA2+0BAh*4],FxOpbBA + mov dword [FxTablebA2+0BBh*4],FxOpbBB + mov dword [FxTablebA2+0BCh*4],FxOpbBC + mov dword [FxTablebA2+0BDh*4],FxOpbBD + mov dword [FxTablebA2+0BEh*4],FxOpbBE + mov dword [FxTablebA2+0BFh*4],FxOpbBF + + mov dword [FxTablebA3+05h*4],FxOpb05 + mov dword [FxTablebA3+06h*4],FxOpb06 + mov dword [FxTablebA3+07h*4],FxOpb07 + mov dword [FxTablebA3+08h*4],FxOpb08 + mov dword [FxTablebA3+09h*4],FxOpb09 + mov dword [FxTablebA3+0Ah*4],FxOpb0A + mov dword [FxTablebA3+0Bh*4],FxOpb0B + mov dword [FxTablebA3+0Ch*4],FxOpb0C + mov dword [FxTablebA3+0Dh*4],FxOpb0D + mov dword [FxTablebA3+0Eh*4],FxOpb0E + mov dword [FxTablebA3+0Fh*4],FxOpb0F + mov dword [FxTablebA3+10h*4],FxOpb10 + mov dword [FxTablebA3+11h*4],FxOpb11 + mov dword [FxTablebA3+12h*4],FxOpb12 + mov dword [FxTablebA3+13h*4],FxOpb13 + mov dword [FxTablebA3+14h*4],FxOpb14 + mov dword [FxTablebA3+15h*4],FxOpb15 + mov dword [FxTablebA3+16h*4],FxOpb16 + mov dword [FxTablebA3+17h*4],FxOpb17 + mov dword [FxTablebA3+18h*4],FxOpb18 + mov dword [FxTablebA3+19h*4],FxOpb19 + mov dword [FxTablebA3+1Ah*4],FxOpb1A + mov dword [FxTablebA3+1Bh*4],FxOpb1B + mov dword [FxTablebA3+1Ch*4],FxOpb1C + mov dword [FxTablebA3+1Dh*4],FxOpb1D + mov dword [FxTablebA3+1Eh*4],FxOpb1E + mov dword [FxTablebA3+1Fh*4],FxOpb1F + mov dword [FxTablebA3+3Dh*4],FxOpb3D + mov dword [FxTablebA3+3Eh*4],FxOpb3E + mov dword [FxTablebA3+3Fh*4],FxOpb3F + mov dword [FxTablebA3+0B0h*4],FxOpbB0 + mov dword [FxTablebA3+0B1h*4],FxOpbB1 + mov dword [FxTablebA3+0B2h*4],FxOpbB2 + mov dword [FxTablebA3+0B3h*4],FxOpbB3 + mov dword [FxTablebA3+0B4h*4],FxOpbB4 + mov dword [FxTablebA3+0B5h*4],FxOpbB5 + mov dword [FxTablebA3+0B6h*4],FxOpbB6 + mov dword [FxTablebA3+0B7h*4],FxOpbB7 + mov dword [FxTablebA3+0B8h*4],FxOpbB8 + mov dword [FxTablebA3+0B9h*4],FxOpbB9 + mov dword [FxTablebA3+0BAh*4],FxOpbBA + mov dword [FxTablebA3+0BBh*4],FxOpbBB + mov dword [FxTablebA3+0BCh*4],FxOpbBC + mov dword [FxTablebA3+0BDh*4],FxOpbBD + mov dword [FxTablebA3+0BEh*4],FxOpbBE + mov dword [FxTablebA3+0BFh*4],FxOpbBF + + mov dword [FxTablec+05h*4],FxOpc05 + mov dword [FxTablec+06h*4],FxOpc06 + mov dword [FxTablec+07h*4],FxOpc07 + mov dword [FxTablec+08h*4],FxOpc08 + mov dword [FxTablec+09h*4],FxOpc09 + mov dword [FxTablec+0Ah*4],FxOpc0A + mov dword [FxTablec+0Bh*4],FxOpc0B + mov dword [FxTablec+0Ch*4],FxOpc0C + mov dword [FxTablec+0Dh*4],FxOpc0D + mov dword [FxTablec+0Eh*4],FxOpc0E + mov dword [FxTablec+0Fh*4],FxOpc0F + mov dword [FxTablec+10h*4],FxOpc10 + mov dword [FxTablec+11h*4],FxOpc11 + mov dword [FxTablec+12h*4],FxOpc12 + mov dword [FxTablec+13h*4],FxOpc13 + mov dword [FxTablec+14h*4],FxOpc14 + mov dword [FxTablec+15h*4],FxOpc15 + mov dword [FxTablec+16h*4],FxOpc16 + mov dword [FxTablec+17h*4],FxOpc17 + mov dword [FxTablec+18h*4],FxOpc18 + mov dword [FxTablec+19h*4],FxOpc19 + mov dword [FxTablec+1Ah*4],FxOpc1A + mov dword [FxTablec+1Bh*4],FxOpc1B + mov dword [FxTablec+1Ch*4],FxOpc1C + mov dword [FxTablec+1Dh*4],FxOpc1D + mov dword [FxTablec+1Eh*4],FxOpc1E + mov dword [FxTablec+1Fh*4],FxOpc1F + mov dword [FxTablec+3Dh*4],FxOpc3D + mov dword [FxTablec+3Eh*4],FxOpc3E + mov dword [FxTablec+3Fh*4],FxOpc3F + mov dword [FxTablec+0B0h*4],FxOpcB0 + mov dword [FxTablec+0B1h*4],FxOpcB1 + mov dword [FxTablec+0B2h*4],FxOpcB2 + mov dword [FxTablec+0B3h*4],FxOpcB3 + mov dword [FxTablec+0B4h*4],FxOpcB4 + mov dword [FxTablec+0B5h*4],FxOpcB5 + mov dword [FxTablec+0B6h*4],FxOpcB6 + mov dword [FxTablec+0B7h*4],FxOpcB7 + mov dword [FxTablec+0B8h*4],FxOpcB8 + mov dword [FxTablec+0B9h*4],FxOpcB9 + mov dword [FxTablec+0BAh*4],FxOpcBA + mov dword [FxTablec+0BBh*4],FxOpcBB + mov dword [FxTablec+0BCh*4],FxOpcBC + mov dword [FxTablec+0BDh*4],FxOpcBD + mov dword [FxTablec+0BEh*4],FxOpcBE + mov dword [FxTablec+0BFh*4],FxOpcBF + + mov dword [FxTablecA1+05h*4],FxOpc05 + mov dword [FxTablecA1+06h*4],FxOpc06 + mov dword [FxTablecA1+07h*4],FxOpc07 + mov dword [FxTablecA1+08h*4],FxOpc08 + mov dword [FxTablecA1+09h*4],FxOpc09 + mov dword [FxTablecA1+0Ah*4],FxOpc0A + mov dword [FxTablecA1+0Bh*4],FxOpc0B + mov dword [FxTablecA1+0Ch*4],FxOpc0C + mov dword [FxTablecA1+0Dh*4],FxOpc0D + mov dword [FxTablecA1+0Eh*4],FxOpc0E + mov dword [FxTablecA1+0Fh*4],FxOpc0F + mov dword [FxTablecA1+10h*4],FxOpc10 + mov dword [FxTablecA1+11h*4],FxOpc11 + mov dword [FxTablecA1+12h*4],FxOpc12 + mov dword [FxTablecA1+13h*4],FxOpc13 + mov dword [FxTablecA1+14h*4],FxOpc14 + mov dword [FxTablecA1+15h*4],FxOpc15 + mov dword [FxTablecA1+16h*4],FxOpc16 + mov dword [FxTablecA1+17h*4],FxOpc17 + mov dword [FxTablecA1+18h*4],FxOpc18 + mov dword [FxTablecA1+19h*4],FxOpc19 + mov dword [FxTablecA1+1Ah*4],FxOpc1A + mov dword [FxTablecA1+1Bh*4],FxOpc1B + mov dword [FxTablecA1+1Ch*4],FxOpc1C + mov dword [FxTablecA1+1Dh*4],FxOpc1D + mov dword [FxTablecA1+1Eh*4],FxOpc1E + mov dword [FxTablecA1+1Fh*4],FxOpc1F + mov dword [FxTablecA1+3Dh*4],FxOpc3D + mov dword [FxTablecA1+3Eh*4],FxOpc3E + mov dword [FxTablecA1+3Fh*4],FxOpc3F + mov dword [FxTablecA1+0B0h*4],FxOpcB0 + mov dword [FxTablecA1+0B1h*4],FxOpcB1 + mov dword [FxTablecA1+0B2h*4],FxOpcB2 + mov dword [FxTablecA1+0B3h*4],FxOpcB3 + mov dword [FxTablecA1+0B4h*4],FxOpcB4 + mov dword [FxTablecA1+0B5h*4],FxOpcB5 + mov dword [FxTablecA1+0B6h*4],FxOpcB6 + mov dword [FxTablecA1+0B7h*4],FxOpcB7 + mov dword [FxTablecA1+0B8h*4],FxOpcB8 + mov dword [FxTablecA1+0B9h*4],FxOpcB9 + mov dword [FxTablecA1+0BAh*4],FxOpcBA + mov dword [FxTablecA1+0BBh*4],FxOpcBB + mov dword [FxTablecA1+0BCh*4],FxOpcBC + mov dword [FxTablecA1+0BDh*4],FxOpcBD + mov dword [FxTablecA1+0BEh*4],FxOpcBE + mov dword [FxTablecA1+0BFh*4],FxOpcBF + + mov dword [FxTablecA2+05h*4],FxOpc05 + mov dword [FxTablecA2+06h*4],FxOpc06 + mov dword [FxTablecA2+07h*4],FxOpc07 + mov dword [FxTablecA2+08h*4],FxOpc08 + mov dword [FxTablecA2+09h*4],FxOpc09 + mov dword [FxTablecA2+0Ah*4],FxOpc0A + mov dword [FxTablecA2+0Bh*4],FxOpc0B + mov dword [FxTablecA2+0Ch*4],FxOpc0C + mov dword [FxTablecA2+0Dh*4],FxOpc0D + mov dword [FxTablecA2+0Eh*4],FxOpc0E + mov dword [FxTablecA2+0Fh*4],FxOpc0F + mov dword [FxTablecA2+10h*4],FxOpc10 + mov dword [FxTablecA2+11h*4],FxOpc11 + mov dword [FxTablecA2+12h*4],FxOpc12 + mov dword [FxTablecA2+13h*4],FxOpc13 + mov dword [FxTablecA2+14h*4],FxOpc14 + mov dword [FxTablecA2+15h*4],FxOpc15 + mov dword [FxTablecA2+16h*4],FxOpc16 + mov dword [FxTablecA2+17h*4],FxOpc17 + mov dword [FxTablecA2+18h*4],FxOpc18 + mov dword [FxTablecA2+19h*4],FxOpc19 + mov dword [FxTablecA2+1Ah*4],FxOpc1A + mov dword [FxTablecA2+1Bh*4],FxOpc1B + mov dword [FxTablecA2+1Ch*4],FxOpc1C + mov dword [FxTablecA2+1Dh*4],FxOpc1D + mov dword [FxTablecA2+1Eh*4],FxOpc1E + mov dword [FxTablecA2+1Fh*4],FxOpc1F + mov dword [FxTablecA2+3Dh*4],FxOpc3D + mov dword [FxTablecA2+3Eh*4],FxOpc3E + mov dword [FxTablecA2+3Fh*4],FxOpc3F + mov dword [FxTablecA2+0B0h*4],FxOpcB0 + mov dword [FxTablecA2+0B1h*4],FxOpcB1 + mov dword [FxTablecA2+0B2h*4],FxOpcB2 + mov dword [FxTablecA2+0B3h*4],FxOpcB3 + mov dword [FxTablecA2+0B4h*4],FxOpcB4 + mov dword [FxTablecA2+0B5h*4],FxOpcB5 + mov dword [FxTablecA2+0B6h*4],FxOpcB6 + mov dword [FxTablecA2+0B7h*4],FxOpcB7 + mov dword [FxTablecA2+0B8h*4],FxOpcB8 + mov dword [FxTablecA2+0B9h*4],FxOpcB9 + mov dword [FxTablecA2+0BAh*4],FxOpcBA + mov dword [FxTablecA2+0BBh*4],FxOpcBB + mov dword [FxTablecA2+0BCh*4],FxOpcBC + mov dword [FxTablecA2+0BDh*4],FxOpcBD + mov dword [FxTablecA2+0BEh*4],FxOpcBE + mov dword [FxTablecA2+0BFh*4],FxOpcBF + + mov dword [FxTablecA3+05h*4],FxOpc05 + mov dword [FxTablecA3+06h*4],FxOpc06 + mov dword [FxTablecA3+07h*4],FxOpc07 + mov dword [FxTablecA3+08h*4],FxOpc08 + mov dword [FxTablecA3+09h*4],FxOpc09 + mov dword [FxTablecA3+0Ah*4],FxOpc0A + mov dword [FxTablecA3+0Bh*4],FxOpc0B + mov dword [FxTablecA3+0Ch*4],FxOpc0C + mov dword [FxTablecA3+0Dh*4],FxOpc0D + mov dword [FxTablecA3+0Eh*4],FxOpc0E + mov dword [FxTablecA3+0Fh*4],FxOpc0F + mov dword [FxTablecA3+10h*4],FxOpc10 + mov dword [FxTablecA3+11h*4],FxOpc11 + mov dword [FxTablecA3+12h*4],FxOpc12 + mov dword [FxTablecA3+13h*4],FxOpc13 + mov dword [FxTablecA3+14h*4],FxOpc14 + mov dword [FxTablecA3+15h*4],FxOpc15 + mov dword [FxTablecA3+16h*4],FxOpc16 + mov dword [FxTablecA3+17h*4],FxOpc17 + mov dword [FxTablecA3+18h*4],FxOpc18 + mov dword [FxTablecA3+19h*4],FxOpc19 + mov dword [FxTablecA3+1Ah*4],FxOpc1A + mov dword [FxTablecA3+1Bh*4],FxOpc1B + mov dword [FxTablecA3+1Ch*4],FxOpc1C + mov dword [FxTablecA3+1Dh*4],FxOpc1D + mov dword [FxTablecA3+1Eh*4],FxOpc1E + mov dword [FxTablecA3+1Fh*4],FxOpc1F + mov dword [FxTablecA3+3Dh*4],FxOpc3D + mov dword [FxTablecA3+3Eh*4],FxOpc3E + mov dword [FxTablecA3+3Fh*4],FxOpc3F + mov dword [FxTablecA3+0B0h*4],FxOpcB0 + mov dword [FxTablecA3+0B1h*4],FxOpcB1 + mov dword [FxTablecA3+0B2h*4],FxOpcB2 + mov dword [FxTablecA3+0B3h*4],FxOpcB3 + mov dword [FxTablecA3+0B4h*4],FxOpcB4 + mov dword [FxTablecA3+0B5h*4],FxOpcB5 + mov dword [FxTablecA3+0B6h*4],FxOpcB6 + mov dword [FxTablecA3+0B7h*4],FxOpcB7 + mov dword [FxTablecA3+0B8h*4],FxOpcB8 + mov dword [FxTablecA3+0B9h*4],FxOpcB9 + mov dword [FxTablecA3+0BAh*4],FxOpcBA + mov dword [FxTablecA3+0BBh*4],FxOpcBB + mov dword [FxTablecA3+0BCh*4],FxOpcBC + mov dword [FxTablecA3+0BDh*4],FxOpcBD + mov dword [FxTablecA3+0BEh*4],FxOpcBE + mov dword [FxTablecA3+0BFh*4],FxOpcBF + + mov dword [FxTabled+00h*4],FxOpd00 + mov dword [FxTabled+01h*4],FxOpd01 + mov dword [FxTabled+02h*4],FxOpd02 + mov dword [FxTabled+03h*4],FxOpd03 + mov dword [FxTabled+04h*4],FxOpd04 + mov dword [FxTabled+05h*4],FxOpd05 + mov dword [FxTabled+06h*4],FxOpd06 + mov dword [FxTabled+07h*4],FxOpd07 + mov dword [FxTabled+08h*4],FxOpd08 + mov dword [FxTabled+09h*4],FxOpd09 + mov dword [FxTabled+0Ah*4],FxOpd0A + mov dword [FxTabled+0Bh*4],FxOpd0B + mov dword [FxTabled+0Ch*4],FxOpd0C + mov dword [FxTabled+0Dh*4],FxOpd0D + mov dword [FxTabled+0Eh*4],FxOpd0E + mov dword [FxTabled+0Fh*4],FxOpd0F + + mov dword [FxTabled+10h*4],FxOpd10 + mov dword [FxTabled+11h*4],FxOpd11 + mov dword [FxTabled+12h*4],FxOpd12 + mov dword [FxTabled+13h*4],FxOpd13 + mov dword [FxTabled+14h*4],FxOpd14 + mov dword [FxTabled+15h*4],FxOpd15 + mov dword [FxTabled+16h*4],FxOpd16 + mov dword [FxTabled+17h*4],FxOpd17 + mov dword [FxTabled+18h*4],FxOpd18 + mov dword [FxTabled+19h*4],FxOpd19 + mov dword [FxTabled+1Ah*4],FxOpd1A + mov dword [FxTabled+1Bh*4],FxOpd1B + mov dword [FxTabled+1Ch*4],FxOpd1C + mov dword [FxTabled+1Dh*4],FxOpd1D + mov dword [FxTabled+1Eh*4],FxOpd1E + mov dword [FxTabled+1Fh*4],FxOpd1F + + mov dword [FxTabled+20h*4],FxOpd20 + mov dword [FxTabled+21h*4],FxOpd21 + mov dword [FxTabled+22h*4],FxOpd22 + mov dword [FxTabled+23h*4],FxOpd23 + mov dword [FxTabled+24h*4],FxOpd24 + mov dword [FxTabled+25h*4],FxOpd25 + mov dword [FxTabled+26h*4],FxOpd26 + mov dword [FxTabled+27h*4],FxOpd27 + mov dword [FxTabled+28h*4],FxOpd28 + mov dword [FxTabled+29h*4],FxOpd29 + mov dword [FxTabled+2Ah*4],FxOpd2A + mov dword [FxTabled+2Bh*4],FxOpd2B + mov dword [FxTabled+2Ch*4],FxOpd2C + mov dword [FxTabled+2Dh*4],FxOpd2D + mov dword [FxTabled+2Eh*4],FxOpd2E + mov dword [FxTabled+2Fh*4],FxOpd2F + + mov dword [FxTabled+30h*4],FxOpd30 + mov dword [FxTabled+31h*4],FxOpd31 + mov dword [FxTabled+32h*4],FxOpd32 + mov dword [FxTabled+33h*4],FxOpd33 + mov dword [FxTabled+34h*4],FxOpd34 + mov dword [FxTabled+35h*4],FxOpd35 + mov dword [FxTabled+36h*4],FxOpd36 + mov dword [FxTabled+37h*4],FxOpd37 + mov dword [FxTabled+38h*4],FxOpd38 + mov dword [FxTabled+39h*4],FxOpd39 + mov dword [FxTabled+3Ah*4],FxOpd3A + mov dword [FxTabled+3Bh*4],FxOpd3B + mov dword [FxTabled+3Ch*4],FxOpd3C + mov dword [FxTabled+3Dh*4],FxOpd3D + mov dword [FxTabled+3Eh*4],FxOpd3E + mov dword [FxTabled+3Fh*4],FxOpd3F + + mov dword [FxTabled+40h*4],FxOpd40 + mov dword [FxTabled+41h*4],FxOpd41 + mov dword [FxTabled+42h*4],FxOpd42 + mov dword [FxTabled+43h*4],FxOpd43 + mov dword [FxTabled+44h*4],FxOpd44 + mov dword [FxTabled+45h*4],FxOpd45 + mov dword [FxTabled+46h*4],FxOpd46 + mov dword [FxTabled+47h*4],FxOpd47 + mov dword [FxTabled+48h*4],FxOpd48 + mov dword [FxTabled+49h*4],FxOpd49 + mov dword [FxTabled+4Ah*4],FxOpd4A + mov dword [FxTabled+4Bh*4],FxOpd4B + mov dword [FxTabled+4Ch*4],FxOpd4C + mov dword [FxTabled+4Dh*4],FxOpd4D + mov dword [FxTabled+4Eh*4],FxOpd4E + mov dword [FxTabled+4Fh*4],FxOpd4F + + mov dword [FxTabled+50h*4],FxOpd50 + mov dword [FxTabled+51h*4],FxOpd51 + mov dword [FxTabled+52h*4],FxOpd52 + mov dword [FxTabled+53h*4],FxOpd53 + mov dword [FxTabled+54h*4],FxOpd54 + mov dword [FxTabled+55h*4],FxOpd55 + mov dword [FxTabled+56h*4],FxOpd56 + mov dword [FxTabled+57h*4],FxOpd57 + mov dword [FxTabled+58h*4],FxOpd58 + mov dword [FxTabled+59h*4],FxOpd59 + mov dword [FxTabled+5Ah*4],FxOpd5A + mov dword [FxTabled+5Bh*4],FxOpd5B + mov dword [FxTabled+5Ch*4],FxOpd5C + mov dword [FxTabled+5Dh*4],FxOpd5D + mov dword [FxTabled+5Eh*4],FxOpd5E + mov dword [FxTabled+5Fh*4],FxOpd5F + + mov dword [FxTabled+60h*4],FxOpd60 + mov dword [FxTabled+61h*4],FxOpd61 + mov dword [FxTabled+62h*4],FxOpd62 + mov dword [FxTabled+63h*4],FxOpd63 + mov dword [FxTabled+64h*4],FxOpd64 + mov dword [FxTabled+65h*4],FxOpd65 + mov dword [FxTabled+66h*4],FxOpd66 + mov dword [FxTabled+67h*4],FxOpd67 + mov dword [FxTabled+68h*4],FxOpd68 + mov dword [FxTabled+69h*4],FxOpd69 + mov dword [FxTabled+6Ah*4],FxOpd6A + mov dword [FxTabled+6Bh*4],FxOpd6B + mov dword [FxTabled+6Ch*4],FxOpd6C + mov dword [FxTabled+6Dh*4],FxOpd6D + mov dword [FxTabled+6Eh*4],FxOpd6E + mov dword [FxTabled+6Fh*4],FxOpd6F + + mov dword [FxTabled+70h*4],FxOpd70 + mov dword [FxTabled+71h*4],FxOpd71 + mov dword [FxTabled+72h*4],FxOpd72 + mov dword [FxTabled+73h*4],FxOpd73 + mov dword [FxTabled+74h*4],FxOpd74 + mov dword [FxTabled+75h*4],FxOpd75 + mov dword [FxTabled+76h*4],FxOpd76 + mov dword [FxTabled+77h*4],FxOpd77 + mov dword [FxTabled+78h*4],FxOpd78 + mov dword [FxTabled+79h*4],FxOpd79 + mov dword [FxTabled+7Ah*4],FxOpd7A + mov dword [FxTabled+7Bh*4],FxOpd7B + mov dword [FxTabled+7Ch*4],FxOpd7C + mov dword [FxTabled+7Dh*4],FxOpd7D + mov dword [FxTabled+7Eh*4],FxOpd7E + mov dword [FxTabled+7Fh*4],FxOpd7F + + mov dword [FxTabled+80h*4],FxOpd80 + mov dword [FxTabled+81h*4],FxOpd81 + mov dword [FxTabled+82h*4],FxOpd82 + mov dword [FxTabled+83h*4],FxOpd83 + mov dword [FxTabled+84h*4],FxOpd84 + mov dword [FxTabled+85h*4],FxOpd85 + mov dword [FxTabled+86h*4],FxOpd86 + mov dword [FxTabled+87h*4],FxOpd87 + mov dword [FxTabled+88h*4],FxOpd88 + mov dword [FxTabled+89h*4],FxOpd89 + mov dword [FxTabled+8Ah*4],FxOpd8A + mov dword [FxTabled+8Bh*4],FxOpd8B + mov dword [FxTabled+8Ch*4],FxOpd8C + mov dword [FxTabled+8Dh*4],FxOpd8D + mov dword [FxTabled+8Eh*4],FxOpd8E + mov dword [FxTabled+8Fh*4],FxOpd8F + + mov dword [FxTabled+90h*4],FxOpd90 + mov dword [FxTabled+91h*4],FxOpd91 + mov dword [FxTabled+92h*4],FxOpd92 + mov dword [FxTabled+93h*4],FxOpd93 + mov dword [FxTabled+94h*4],FxOpd94 + mov dword [FxTabled+95h*4],FxOpd95 + mov dword [FxTabled+96h*4],FxOpd96 + mov dword [FxTabled+97h*4],FxOpd97 + mov dword [FxTabled+98h*4],FxOpd98 + mov dword [FxTabled+99h*4],FxOpd99 + mov dword [FxTabled+9Ah*4],FxOpd9A + mov dword [FxTabled+9Bh*4],FxOpd9B + mov dword [FxTabled+9Ch*4],FxOpd9C + mov dword [FxTabled+9Dh*4],FxOpd9D + mov dword [FxTabled+9Eh*4],FxOpd9E + mov dword [FxTabled+9Fh*4],FxOpd9F + + mov dword [FxTabled+0A0h*4],FxOpdA0 + mov dword [FxTabled+0A1h*4],FxOpdA1 + mov dword [FxTabled+0A2h*4],FxOpdA2 + mov dword [FxTabled+0A3h*4],FxOpdA3 + mov dword [FxTabled+0A4h*4],FxOpdA4 + mov dword [FxTabled+0A5h*4],FxOpdA5 + mov dword [FxTabled+0A6h*4],FxOpdA6 + mov dword [FxTabled+0A7h*4],FxOpdA7 + mov dword [FxTabled+0A8h*4],FxOpdA8 + mov dword [FxTabled+0A9h*4],FxOpdA9 + mov dword [FxTabled+0AAh*4],FxOpdAA + mov dword [FxTabled+0ABh*4],FxOpdAB + mov dword [FxTabled+0ACh*4],FxOpdAC + mov dword [FxTabled+0ADh*4],FxOpdAD + mov dword [FxTabled+0AEh*4],FxOpdAE + mov dword [FxTabled+0AFh*4],FxOpdAF + + mov dword [FxTabled+0B0h*4],FxOpdB0 + mov dword [FxTabled+0B1h*4],FxOpdB1 + mov dword [FxTabled+0B2h*4],FxOpdB2 + mov dword [FxTabled+0B3h*4],FxOpdB3 + mov dword [FxTabled+0B4h*4],FxOpdB4 + mov dword [FxTabled+0B5h*4],FxOpdB5 + mov dword [FxTabled+0B6h*4],FxOpdB6 + mov dword [FxTabled+0B7h*4],FxOpdB7 + mov dword [FxTabled+0B8h*4],FxOpdB8 + mov dword [FxTabled+0B9h*4],FxOpdB9 + mov dword [FxTabled+0BAh*4],FxOpdBA + mov dword [FxTabled+0BBh*4],FxOpdBB + mov dword [FxTabled+0BCh*4],FxOpdBC + mov dword [FxTabled+0BDh*4],FxOpdBD + mov dword [FxTabled+0BEh*4],FxOpdBE + mov dword [FxTabled+0BFh*4],FxOpdBF + + mov dword [FxTabled+0C0h*4],FxOpdC0 + mov dword [FxTabled+0C1h*4],FxOpdC1 + mov dword [FxTabled+0C2h*4],FxOpdC2 + mov dword [FxTabled+0C3h*4],FxOpdC3 + mov dword [FxTabled+0C4h*4],FxOpdC4 + mov dword [FxTabled+0C5h*4],FxOpdC5 + mov dword [FxTabled+0C6h*4],FxOpdC6 + mov dword [FxTabled+0C7h*4],FxOpdC7 + mov dword [FxTabled+0C8h*4],FxOpdC8 + mov dword [FxTabled+0C9h*4],FxOpdC9 + mov dword [FxTabled+0CAh*4],FxOpdCA + mov dword [FxTabled+0CBh*4],FxOpdCB + mov dword [FxTabled+0CCh*4],FxOpdCC + mov dword [FxTabled+0CDh*4],FxOpdCD + mov dword [FxTabled+0CEh*4],FxOpdCE + mov dword [FxTabled+0CFh*4],FxOpdCF + + mov dword [FxTabled+0D0h*4],FxOpdD0 + mov dword [FxTabled+0D1h*4],FxOpdD1 + mov dword [FxTabled+0D2h*4],FxOpdD2 + mov dword [FxTabled+0D3h*4],FxOpdD3 + mov dword [FxTabled+0D4h*4],FxOpdD4 + mov dword [FxTabled+0D5h*4],FxOpdD5 + mov dword [FxTabled+0D6h*4],FxOpdD6 + mov dword [FxTabled+0D7h*4],FxOpdD7 + mov dword [FxTabled+0D8h*4],FxOpdD8 + mov dword [FxTabled+0D9h*4],FxOpdD9 + mov dword [FxTabled+0DAh*4],FxOpdDA + mov dword [FxTabled+0DBh*4],FxOpdDB + mov dword [FxTabled+0DCh*4],FxOpdDC + mov dword [FxTabled+0DDh*4],FxOpdDD + mov dword [FxTabled+0DEh*4],FxOpdDE + mov dword [FxTabled+0DFh*4],FxOpdDF + + mov dword [FxTabled+0E0h*4],FxOpdE0 + mov dword [FxTabled+0E1h*4],FxOpdE1 + mov dword [FxTabled+0E2h*4],FxOpdE2 + mov dword [FxTabled+0E3h*4],FxOpdE3 + mov dword [FxTabled+0E4h*4],FxOpdE4 + mov dword [FxTabled+0E5h*4],FxOpdE5 + mov dword [FxTabled+0E6h*4],FxOpdE6 + mov dword [FxTabled+0E7h*4],FxOpdE7 + mov dword [FxTabled+0E8h*4],FxOpdE8 + mov dword [FxTabled+0E9h*4],FxOpdE9 + mov dword [FxTabled+0EAh*4],FxOpdEA + mov dword [FxTabled+0EBh*4],FxOpdEB + mov dword [FxTabled+0ECh*4],FxOpdEC + mov dword [FxTabled+0EDh*4],FxOpdED + mov dword [FxTabled+0EEh*4],FxOpdEE + mov dword [FxTabled+0EFh*4],FxOpdEF + + mov dword [FxTabled+0F0h*4],FxOpdF0 + mov dword [FxTabled+0F1h*4],FxOpdF1 + mov dword [FxTabled+0F2h*4],FxOpdF2 + mov dword [FxTabled+0F3h*4],FxOpdF3 + mov dword [FxTabled+0F4h*4],FxOpdF4 + mov dword [FxTabled+0F5h*4],FxOpdF5 + mov dword [FxTabled+0F6h*4],FxOpdF6 + mov dword [FxTabled+0F7h*4],FxOpdF7 + mov dword [FxTabled+0F8h*4],FxOpdF8 + mov dword [FxTabled+0F9h*4],FxOpdF9 + mov dword [FxTabled+0FAh*4],FxOpdFA + mov dword [FxTabled+0FBh*4],FxOpdFB + mov dword [FxTabled+0FCh*4],FxOpdFC + mov dword [FxTabled+0FDh*4],FxOpdFD + mov dword [FxTabled+0FEh*4],FxOpdFE + mov dword [FxTabled+0FFh*4],FxOpdFF + + + mov dword [FxTabledA1+00h*4],FxOpd00 + mov dword [FxTabledA1+01h*4],FxOpd01 + mov dword [FxTabledA1+02h*4],FxOpd02 + mov dword [FxTabledA1+03h*4],FxOpd03 + mov dword [FxTabledA1+04h*4],FxOpd04 + mov dword [FxTabledA1+05h*4],FxOpd05 + mov dword [FxTabledA1+06h*4],FxOpd06 + mov dword [FxTabledA1+07h*4],FxOpd07 + mov dword [FxTabledA1+08h*4],FxOpd08 + mov dword [FxTabledA1+09h*4],FxOpd09 + mov dword [FxTabledA1+0Ah*4],FxOpd0A + mov dword [FxTabledA1+0Bh*4],FxOpd0B + mov dword [FxTabledA1+0Ch*4],FxOpd0C + mov dword [FxTabledA1+0Dh*4],FxOpd0D + mov dword [FxTabledA1+0Eh*4],FxOpd0E + mov dword [FxTabledA1+0Fh*4],FxOpd0F + + mov dword [FxTabledA1+10h*4],FxOpd10 + mov dword [FxTabledA1+11h*4],FxOpd11 + mov dword [FxTabledA1+12h*4],FxOpd12 + mov dword [FxTabledA1+13h*4],FxOpd13 + mov dword [FxTabledA1+14h*4],FxOpd14 + mov dword [FxTabledA1+15h*4],FxOpd15 + mov dword [FxTabledA1+16h*4],FxOpd16 + mov dword [FxTabledA1+17h*4],FxOpd17 + mov dword [FxTabledA1+18h*4],FxOpd18 + mov dword [FxTabledA1+19h*4],FxOpd19 + mov dword [FxTabledA1+1Ah*4],FxOpd1A + mov dword [FxTabledA1+1Bh*4],FxOpd1B + mov dword [FxTabledA1+1Ch*4],FxOpd1C + mov dword [FxTabledA1+1Dh*4],FxOpd1D + mov dword [FxTabledA1+1Eh*4],FxOpd1E + mov dword [FxTabledA1+1Fh*4],FxOpd1F + + mov dword [FxTabledA1+20h*4],FxOpd20 + mov dword [FxTabledA1+21h*4],FxOpd21 + mov dword [FxTabledA1+22h*4],FxOpd22 + mov dword [FxTabledA1+23h*4],FxOpd23 + mov dword [FxTabledA1+24h*4],FxOpd24 + mov dword [FxTabledA1+25h*4],FxOpd25 + mov dword [FxTabledA1+26h*4],FxOpd26 + mov dword [FxTabledA1+27h*4],FxOpd27 + mov dword [FxTabledA1+28h*4],FxOpd28 + mov dword [FxTabledA1+29h*4],FxOpd29 + mov dword [FxTabledA1+2Ah*4],FxOpd2A + mov dword [FxTabledA1+2Bh*4],FxOpd2B + mov dword [FxTabledA1+2Ch*4],FxOpd2C + mov dword [FxTabledA1+2Dh*4],FxOpd2D + mov dword [FxTabledA1+2Eh*4],FxOpd2E + mov dword [FxTabledA1+2Fh*4],FxOpd2F + + mov dword [FxTabledA1+30h*4],FxOpd30A1 + mov dword [FxTabledA1+31h*4],FxOpd31A1 + mov dword [FxTabledA1+32h*4],FxOpd32A1 + mov dword [FxTabledA1+33h*4],FxOpd33A1 + mov dword [FxTabledA1+34h*4],FxOpd34A1 + mov dword [FxTabledA1+35h*4],FxOpd35A1 + mov dword [FxTabledA1+36h*4],FxOpd36A1 + mov dword [FxTabledA1+37h*4],FxOpd37A1 + mov dword [FxTabledA1+38h*4],FxOpd38A1 + mov dword [FxTabledA1+39h*4],FxOpd39A1 + mov dword [FxTabledA1+3Ah*4],FxOpd3AA1 + mov dword [FxTabledA1+3Bh*4],FxOpd3BA1 + mov dword [FxTabledA1+3Ch*4],FxOpd3C + mov dword [FxTabledA1+3Dh*4],FxOpd3D + mov dword [FxTabledA1+3Eh*4],FxOpd3E + mov dword [FxTabledA1+3Fh*4],FxOpd3F + + mov dword [FxTabledA1+40h*4],FxOpd40A1 + mov dword [FxTabledA1+41h*4],FxOpd41A1 + mov dword [FxTabledA1+42h*4],FxOpd42A1 + mov dword [FxTabledA1+43h*4],FxOpd43A1 + mov dword [FxTabledA1+44h*4],FxOpd44A1 + mov dword [FxTabledA1+45h*4],FxOpd45A1 + mov dword [FxTabledA1+46h*4],FxOpd46A1 + mov dword [FxTabledA1+47h*4],FxOpd47A1 + mov dword [FxTabledA1+48h*4],FxOpd48A1 + mov dword [FxTabledA1+49h*4],FxOpd49A1 + mov dword [FxTabledA1+4Ah*4],FxOpd4AA1 + mov dword [FxTabledA1+4Bh*4],FxOpd4BA1 + mov dword [FxTabledA1+4Ch*4],FxOpd4CA1 + mov dword [FxTabledA1+4Dh*4],FxOpd4D + mov dword [FxTabledA1+4Eh*4],FxOpd4EA1 + mov dword [FxTabledA1+4Fh*4],FxOpd4F + + mov dword [FxTabledA1+50h*4],FxOpd50A1 + mov dword [FxTabledA1+51h*4],FxOpd51A1 + mov dword [FxTabledA1+52h*4],FxOpd52A1 + mov dword [FxTabledA1+53h*4],FxOpd53A1 + mov dword [FxTabledA1+54h*4],FxOpd54A1 + mov dword [FxTabledA1+55h*4],FxOpd55A1 + mov dword [FxTabledA1+56h*4],FxOpd56A1 + mov dword [FxTabledA1+57h*4],FxOpd57A1 + mov dword [FxTabledA1+58h*4],FxOpd58A1 + mov dword [FxTabledA1+59h*4],FxOpd59A1 + mov dword [FxTabledA1+5Ah*4],FxOpd5AA1 + mov dword [FxTabledA1+5Bh*4],FxOpd5BA1 + mov dword [FxTabledA1+5Ch*4],FxOpd5CA1 + mov dword [FxTabledA1+5Dh*4],FxOpd5DA1 + mov dword [FxTabledA1+5Eh*4],FxOpd5EA1 + mov dword [FxTabledA1+5Fh*4],FxOpd5FA1 + + mov dword [FxTabledA1+60h*4],FxOpd60A1 + mov dword [FxTabledA1+61h*4],FxOpd61A1 + mov dword [FxTabledA1+62h*4],FxOpd62A1 + mov dword [FxTabledA1+63h*4],FxOpd63A1 + mov dword [FxTabledA1+64h*4],FxOpd64A1 + mov dword [FxTabledA1+65h*4],FxOpd65A1 + mov dword [FxTabledA1+66h*4],FxOpd66A1 + mov dword [FxTabledA1+67h*4],FxOpd67A1 + mov dword [FxTabledA1+68h*4],FxOpd68A1 + mov dword [FxTabledA1+69h*4],FxOpd69A1 + mov dword [FxTabledA1+6Ah*4],FxOpd6AA1 + mov dword [FxTabledA1+6Bh*4],FxOpd6BA1 + mov dword [FxTabledA1+6Ch*4],FxOpd6CA1 + mov dword [FxTabledA1+6Dh*4],FxOpd6DA1 + mov dword [FxTabledA1+6Eh*4],FxOpd6EA1 + mov dword [FxTabledA1+6Fh*4],FxOpd6FA1 + + mov dword [FxTabledA1+70h*4],FxOpd70 + mov dword [FxTabledA1+71h*4],FxOpd71A1 + mov dword [FxTabledA1+72h*4],FxOpd72A1 + mov dword [FxTabledA1+73h*4],FxOpd73A1 + mov dword [FxTabledA1+74h*4],FxOpd74A1 + mov dword [FxTabledA1+75h*4],FxOpd75A1 + mov dword [FxTabledA1+76h*4],FxOpd76A1 + mov dword [FxTabledA1+77h*4],FxOpd77A1 + mov dword [FxTabledA1+78h*4],FxOpd78A1 + mov dword [FxTabledA1+79h*4],FxOpd79A1 + mov dword [FxTabledA1+7Ah*4],FxOpd7AA1 + mov dword [FxTabledA1+7Bh*4],FxOpd7BA1 + mov dword [FxTabledA1+7Ch*4],FxOpd7CA1 + mov dword [FxTabledA1+7Dh*4],FxOpd7DA1 + mov dword [FxTabledA1+7Eh*4],FxOpd7EA1 + mov dword [FxTabledA1+7Fh*4],FxOpd7FA1 + + mov dword [FxTabledA1+80h*4],FxOpd80A1 + mov dword [FxTabledA1+81h*4],FxOpd81A1 + mov dword [FxTabledA1+82h*4],FxOpd82A1 + mov dword [FxTabledA1+83h*4],FxOpd83A1 + mov dword [FxTabledA1+84h*4],FxOpd84A1 + mov dword [FxTabledA1+85h*4],FxOpd85A1 + mov dword [FxTabledA1+86h*4],FxOpd86A1 + mov dword [FxTabledA1+87h*4],FxOpd87A1 + mov dword [FxTabledA1+88h*4],FxOpd88A1 + mov dword [FxTabledA1+89h*4],FxOpd89A1 + mov dword [FxTabledA1+8Ah*4],FxOpd8AA1 + mov dword [FxTabledA1+8Bh*4],FxOpd8BA1 + mov dword [FxTabledA1+8Ch*4],FxOpd8CA1 + mov dword [FxTabledA1+8Dh*4],FxOpd8DA1 + mov dword [FxTabledA1+8Eh*4],FxOpd8EA1 + mov dword [FxTabledA1+8Fh*4],FxOpd8FA1 + + mov dword [FxTabledA1+90h*4],FxOpd90 + mov dword [FxTabledA1+91h*4],FxOpd91 + mov dword [FxTabledA1+92h*4],FxOpd92 + mov dword [FxTabledA1+93h*4],FxOpd93 + mov dword [FxTabledA1+94h*4],FxOpd94 + mov dword [FxTabledA1+95h*4],FxOpd95 + mov dword [FxTabledA1+96h*4],FxOpd96A1 + mov dword [FxTabledA1+97h*4],FxOpd97 + mov dword [FxTabledA1+98h*4],FxOpd98A1 + mov dword [FxTabledA1+99h*4],FxOpd99A1 + mov dword [FxTabledA1+9Ah*4],FxOpd9AA1 + mov dword [FxTabledA1+9Bh*4],FxOpd9BA1 + mov dword [FxTabledA1+9Ch*4],FxOpd9CA1 + mov dword [FxTabledA1+9Dh*4],FxOpd9DA1 + mov dword [FxTabledA1+9Eh*4],FxOpd9E + mov dword [FxTabledA1+9Fh*4],FxOpd9FA1 + + mov dword [FxTabledA1+0A0h*4],FxOpdA0A1 + mov dword [FxTabledA1+0A1h*4],FxOpdA1A1 + mov dword [FxTabledA1+0A2h*4],FxOpdA2A1 + mov dword [FxTabledA1+0A3h*4],FxOpdA3A1 + mov dword [FxTabledA1+0A4h*4],FxOpdA4A1 + mov dword [FxTabledA1+0A5h*4],FxOpdA5A1 + mov dword [FxTabledA1+0A6h*4],FxOpdA6A1 + mov dword [FxTabledA1+0A7h*4],FxOpdA7A1 + mov dword [FxTabledA1+0A8h*4],FxOpdA8A1 + mov dword [FxTabledA1+0A9h*4],FxOpdA9A1 + mov dword [FxTabledA1+0AAh*4],FxOpdAAA1 + mov dword [FxTabledA1+0ABh*4],FxOpdABA1 + mov dword [FxTabledA1+0ACh*4],FxOpdACA1 + mov dword [FxTabledA1+0ADh*4],FxOpdADA1 + mov dword [FxTabledA1+0AEh*4],FxOpdAEA1 + mov dword [FxTabledA1+0AFh*4],FxOpdAFA1 + + mov dword [FxTabledA1+0B0h*4],FxOpdB0 + mov dword [FxTabledA1+0B1h*4],FxOpdB1 + mov dword [FxTabledA1+0B2h*4],FxOpdB2 + mov dword [FxTabledA1+0B3h*4],FxOpdB3 + mov dword [FxTabledA1+0B4h*4],FxOpdB4 + mov dword [FxTabledA1+0B5h*4],FxOpdB5 + mov dword [FxTabledA1+0B6h*4],FxOpdB6 + mov dword [FxTabledA1+0B7h*4],FxOpdB7 + mov dword [FxTabledA1+0B8h*4],FxOpdB8 + mov dword [FxTabledA1+0B9h*4],FxOpdB9 + mov dword [FxTabledA1+0BAh*4],FxOpdBA + mov dword [FxTabledA1+0BBh*4],FxOpdBB + mov dword [FxTabledA1+0BCh*4],FxOpdBC + mov dword [FxTabledA1+0BDh*4],FxOpdBD + mov dword [FxTabledA1+0BEh*4],FxOpdBE + mov dword [FxTabledA1+0BFh*4],FxOpdBF + + mov dword [FxTabledA1+0C0h*4],FxOpdC0 + mov dword [FxTabledA1+0C1h*4],FxOpdC1A1 + mov dword [FxTabledA1+0C2h*4],FxOpdC2A1 + mov dword [FxTabledA1+0C3h*4],FxOpdC3A1 + mov dword [FxTabledA1+0C4h*4],FxOpdC4A1 + mov dword [FxTabledA1+0C5h*4],FxOpdC5A1 + mov dword [FxTabledA1+0C6h*4],FxOpdC6A1 + mov dword [FxTabledA1+0C7h*4],FxOpdC7A1 + mov dword [FxTabledA1+0C8h*4],FxOpdC8A1 + mov dword [FxTabledA1+0C9h*4],FxOpdC9A1 + mov dword [FxTabledA1+0CAh*4],FxOpdCAA1 + mov dword [FxTabledA1+0CBh*4],FxOpdCBA1 + mov dword [FxTabledA1+0CCh*4],FxOpdCCA1 + mov dword [FxTabledA1+0CDh*4],FxOpdCDA1 + mov dword [FxTabledA1+0CEh*4],FxOpdCEA1 + mov dword [FxTabledA1+0CFh*4],FxOpdCFA1 + + mov dword [FxTabledA1+0D0h*4],FxOpdD0 + mov dword [FxTabledA1+0D1h*4],FxOpdD1 + mov dword [FxTabledA1+0D2h*4],FxOpdD2 + mov dword [FxTabledA1+0D3h*4],FxOpdD3 + mov dword [FxTabledA1+0D4h*4],FxOpdD4 + mov dword [FxTabledA1+0D5h*4],FxOpdD5 + mov dword [FxTabledA1+0D6h*4],FxOpdD6 + mov dword [FxTabledA1+0D7h*4],FxOpdD7 + mov dword [FxTabledA1+0D8h*4],FxOpdD8 + mov dword [FxTabledA1+0D9h*4],FxOpdD9 + mov dword [FxTabledA1+0DAh*4],FxOpdDA + mov dword [FxTabledA1+0DBh*4],FxOpdDB + mov dword [FxTabledA1+0DCh*4],FxOpdDC + mov dword [FxTabledA1+0DDh*4],FxOpdDD + mov dword [FxTabledA1+0DEh*4],FxOpdDE + mov dword [FxTabledA1+0DFh*4],FxOpdDF + + mov dword [FxTabledA1+0E0h*4],FxOpdE0 + mov dword [FxTabledA1+0E1h*4],FxOpdE1 + mov dword [FxTabledA1+0E2h*4],FxOpdE2 + mov dword [FxTabledA1+0E3h*4],FxOpdE3 + mov dword [FxTabledA1+0E4h*4],FxOpdE4 + mov dword [FxTabledA1+0E5h*4],FxOpdE5 + mov dword [FxTabledA1+0E6h*4],FxOpdE6 + mov dword [FxTabledA1+0E7h*4],FxOpdE7 + mov dword [FxTabledA1+0E8h*4],FxOpdE8 + mov dword [FxTabledA1+0E9h*4],FxOpdE9 + mov dword [FxTabledA1+0EAh*4],FxOpdEA + mov dword [FxTabledA1+0EBh*4],FxOpdEB + mov dword [FxTabledA1+0ECh*4],FxOpdEC + mov dword [FxTabledA1+0EDh*4],FxOpdED + mov dword [FxTabledA1+0EEh*4],FxOpdEE + mov dword [FxTabledA1+0EFh*4],FxOpdEFA1 + + mov dword [FxTabledA1+0F0h*4],FxOpdF0A1 + mov dword [FxTabledA1+0F1h*4],FxOpdF1A1 + mov dword [FxTabledA1+0F2h*4],FxOpdF2A1 + mov dword [FxTabledA1+0F3h*4],FxOpdF3A1 + mov dword [FxTabledA1+0F4h*4],FxOpdF4A1 + mov dword [FxTabledA1+0F5h*4],FxOpdF5A1 + mov dword [FxTabledA1+0F6h*4],FxOpdF6A1 + mov dword [FxTabledA1+0F7h*4],FxOpdF7A1 + mov dword [FxTabledA1+0F8h*4],FxOpdF8A1 + mov dword [FxTabledA1+0F9h*4],FxOpdF9A1 + mov dword [FxTabledA1+0FAh*4],FxOpdFAA1 + mov dword [FxTabledA1+0FBh*4],FxOpdFBA1 + mov dword [FxTabledA1+0FCh*4],FxOpdFCA1 + mov dword [FxTabledA1+0FDh*4],FxOpdFDA1 + mov dword [FxTabledA1+0FEh*4],FxOpdFEA1 + mov dword [FxTabledA1+0FFh*4],FxOpdFFA1 + + + mov dword [FxTabledA2+00h*4],FxOpd00 + mov dword [FxTabledA2+01h*4],FxOpd01 + mov dword [FxTabledA2+02h*4],FxOpd02 + mov dword [FxTabledA2+03h*4],FxOpd03 + mov dword [FxTabledA2+04h*4],FxOpd04 + mov dword [FxTabledA2+05h*4],FxOpd05 + mov dword [FxTabledA2+06h*4],FxOpd06 + mov dword [FxTabledA2+07h*4],FxOpd07 + mov dword [FxTabledA2+08h*4],FxOpd08 + mov dword [FxTabledA2+09h*4],FxOpd09 + mov dword [FxTabledA2+0Ah*4],FxOpd0A + mov dword [FxTabledA2+0Bh*4],FxOpd0B + mov dword [FxTabledA2+0Ch*4],FxOpd0C + mov dword [FxTabledA2+0Dh*4],FxOpd0D + mov dword [FxTabledA2+0Eh*4],FxOpd0E + mov dword [FxTabledA2+0Fh*4],FxOpd0F + + mov dword [FxTabledA2+10h*4],FxOpd10 + mov dword [FxTabledA2+11h*4],FxOpd11 + mov dword [FxTabledA2+12h*4],FxOpd12 + mov dword [FxTabledA2+13h*4],FxOpd13 + mov dword [FxTabledA2+14h*4],FxOpd14 + mov dword [FxTabledA2+15h*4],FxOpd15 + mov dword [FxTabledA2+16h*4],FxOpd16 + mov dword [FxTabledA2+17h*4],FxOpd17 + mov dword [FxTabledA2+18h*4],FxOpd18 + mov dword [FxTabledA2+19h*4],FxOpd19 + mov dword [FxTabledA2+1Ah*4],FxOpd1A + mov dword [FxTabledA2+1Bh*4],FxOpd1B + mov dword [FxTabledA2+1Ch*4],FxOpd1C + mov dword [FxTabledA2+1Dh*4],FxOpd1D + mov dword [FxTabledA2+1Eh*4],FxOpd1E + mov dword [FxTabledA2+1Fh*4],FxOpd1F + + mov dword [FxTabledA2+20h*4],FxOpd20 + mov dword [FxTabledA2+21h*4],FxOpd21 + mov dword [FxTabledA2+22h*4],FxOpd22 + mov dword [FxTabledA2+23h*4],FxOpd23 + mov dword [FxTabledA2+24h*4],FxOpd24 + mov dword [FxTabledA2+25h*4],FxOpd25 + mov dword [FxTabledA2+26h*4],FxOpd26 + mov dword [FxTabledA2+27h*4],FxOpd27 + mov dword [FxTabledA2+28h*4],FxOpd28 + mov dword [FxTabledA2+29h*4],FxOpd29 + mov dword [FxTabledA2+2Ah*4],FxOpd2A + mov dword [FxTabledA2+2Bh*4],FxOpd2B + mov dword [FxTabledA2+2Ch*4],FxOpd2C + mov dword [FxTabledA2+2Dh*4],FxOpd2D + mov dword [FxTabledA2+2Eh*4],FxOpd2E + mov dword [FxTabledA2+2Fh*4],FxOpd2F + + mov dword [FxTabledA2+30h*4],FxOpd30 + mov dword [FxTabledA2+31h*4],FxOpd31 + mov dword [FxTabledA2+32h*4],FxOpd32 + mov dword [FxTabledA2+33h*4],FxOpd33 + mov dword [FxTabledA2+34h*4],FxOpd34 + mov dword [FxTabledA2+35h*4],FxOpd35 + mov dword [FxTabledA2+36h*4],FxOpd36 + mov dword [FxTabledA2+37h*4],FxOpd37 + mov dword [FxTabledA2+38h*4],FxOpd38 + mov dword [FxTabledA2+39h*4],FxOpd39 + mov dword [FxTabledA2+3Ah*4],FxOpd3A + mov dword [FxTabledA2+3Bh*4],FxOpd3B + mov dword [FxTabledA2+3Ch*4],FxOpd3C + mov dword [FxTabledA2+3Dh*4],FxOpd3D + mov dword [FxTabledA2+3Eh*4],FxOpd3E + mov dword [FxTabledA2+3Fh*4],FxOpd3F + + mov dword [FxTabledA2+40h*4],FxOpd40 + mov dword [FxTabledA2+41h*4],FxOpd41 + mov dword [FxTabledA2+42h*4],FxOpd42 + mov dword [FxTabledA2+43h*4],FxOpd43 + mov dword [FxTabledA2+44h*4],FxOpd44 + mov dword [FxTabledA2+45h*4],FxOpd45 + mov dword [FxTabledA2+46h*4],FxOpd46 + mov dword [FxTabledA2+47h*4],FxOpd47 + mov dword [FxTabledA2+48h*4],FxOpd48 + mov dword [FxTabledA2+49h*4],FxOpd49 + mov dword [FxTabledA2+4Ah*4],FxOpd4A + mov dword [FxTabledA2+4Bh*4],FxOpd4B + mov dword [FxTabledA2+4Ch*4],FxOpd4C + mov dword [FxTabledA2+4Dh*4],FxOpd4D + mov dword [FxTabledA2+4Eh*4],FxOpd4E + mov dword [FxTabledA2+4Fh*4],FxOpd4F + + mov dword [FxTabledA2+50h*4],FxOpd50A2 + mov dword [FxTabledA2+51h*4],FxOpd51A2 + mov dword [FxTabledA2+52h*4],FxOpd52A2 + mov dword [FxTabledA2+53h*4],FxOpd53A2 + mov dword [FxTabledA2+54h*4],FxOpd54A2 + mov dword [FxTabledA2+55h*4],FxOpd55A2 + mov dword [FxTabledA2+56h*4],FxOpd56A2 + mov dword [FxTabledA2+57h*4],FxOpd57A2 + mov dword [FxTabledA2+58h*4],FxOpd58A2 + mov dword [FxTabledA2+59h*4],FxOpd59A2 + mov dword [FxTabledA2+5Ah*4],FxOpd5AA2 + mov dword [FxTabledA2+5Bh*4],FxOpd5BA2 + mov dword [FxTabledA2+5Ch*4],FxOpd5CA2 + mov dword [FxTabledA2+5Dh*4],FxOpd5DA2 + mov dword [FxTabledA2+5Eh*4],FxOpd5EA2 + mov dword [FxTabledA2+5Fh*4],FxOpd5FA2 + + mov dword [FxTabledA2+60h*4],FxOpd60A2 + mov dword [FxTabledA2+61h*4],FxOpd61A2 + mov dword [FxTabledA2+62h*4],FxOpd62A2 + mov dword [FxTabledA2+63h*4],FxOpd63A2 + mov dword [FxTabledA2+64h*4],FxOpd64A2 + mov dword [FxTabledA2+65h*4],FxOpd65A2 + mov dword [FxTabledA2+66h*4],FxOpd66A2 + mov dword [FxTabledA2+67h*4],FxOpd67A2 + mov dword [FxTabledA2+68h*4],FxOpd68A2 + mov dword [FxTabledA2+69h*4],FxOpd69A2 + mov dword [FxTabledA2+6Ah*4],FxOpd6AA2 + mov dword [FxTabledA2+6Bh*4],FxOpd6BA2 + mov dword [FxTabledA2+6Ch*4],FxOpd6CA2 + mov dword [FxTabledA2+6Dh*4],FxOpd6DA2 + mov dword [FxTabledA2+6Eh*4],FxOpd6EA2 + mov dword [FxTabledA2+6Fh*4],FxOpd6FA2 + + mov dword [FxTabledA2+70h*4],FxOpd70 + mov dword [FxTabledA2+71h*4],FxOpd71A2 + mov dword [FxTabledA2+72h*4],FxOpd72A2 + mov dword [FxTabledA2+73h*4],FxOpd73A2 + mov dword [FxTabledA2+74h*4],FxOpd74A2 + mov dword [FxTabledA2+75h*4],FxOpd75A2 + mov dword [FxTabledA2+76h*4],FxOpd76A2 + mov dword [FxTabledA2+77h*4],FxOpd77A2 + mov dword [FxTabledA2+78h*4],FxOpd78A2 + mov dword [FxTabledA2+79h*4],FxOpd79A2 + mov dword [FxTabledA2+7Ah*4],FxOpd7AA2 + mov dword [FxTabledA2+7Bh*4],FxOpd7BA2 + mov dword [FxTabledA2+7Ch*4],FxOpd7CA2 + mov dword [FxTabledA2+7Dh*4],FxOpd7DA2 + mov dword [FxTabledA2+7Eh*4],FxOpd7EA2 + mov dword [FxTabledA2+7Fh*4],FxOpd7FA2 + + mov dword [FxTabledA2+80h*4],FxOpd80A2 + mov dword [FxTabledA2+81h*4],FxOpd81A2 + mov dword [FxTabledA2+82h*4],FxOpd82A2 + mov dword [FxTabledA2+83h*4],FxOpd83A2 + mov dword [FxTabledA2+84h*4],FxOpd84A2 + mov dword [FxTabledA2+85h*4],FxOpd85A2 + mov dword [FxTabledA2+86h*4],FxOpd86A2 + mov dword [FxTabledA2+87h*4],FxOpd87A2 + mov dword [FxTabledA2+88h*4],FxOpd88A2 + mov dword [FxTabledA2+89h*4],FxOpd89A2 + mov dword [FxTabledA2+8Ah*4],FxOpd8AA2 + mov dword [FxTabledA2+8Bh*4],FxOpd8BA2 + mov dword [FxTabledA2+8Ch*4],FxOpd8CA2 + mov dword [FxTabledA2+8Dh*4],FxOpd8DA2 + mov dword [FxTabledA2+8Eh*4],FxOpd8EA2 + mov dword [FxTabledA2+8Fh*4],FxOpd8FA2 + + mov dword [FxTabledA2+90h*4],FxOpd90 + mov dword [FxTabledA2+91h*4],FxOpd91 + mov dword [FxTabledA2+92h*4],FxOpd92 + mov dword [FxTabledA2+93h*4],FxOpd93 + mov dword [FxTabledA2+94h*4],FxOpd94 + mov dword [FxTabledA2+95h*4],FxOpd95 + mov dword [FxTabledA2+96h*4],FxOpd96 + mov dword [FxTabledA2+97h*4],FxOpd97 + mov dword [FxTabledA2+98h*4],FxOpd98 + mov dword [FxTabledA2+99h*4],FxOpd99 + mov dword [FxTabledA2+9Ah*4],FxOpd9A + mov dword [FxTabledA2+9Bh*4],FxOpd9B + mov dword [FxTabledA2+9Ch*4],FxOpd9C + mov dword [FxTabledA2+9Dh*4],FxOpd9D + mov dword [FxTabledA2+9Eh*4],FxOpd9E + mov dword [FxTabledA2+9Fh*4],FxOpd9F + + mov dword [FxTabledA2+0A0h*4],FxOpdA0A2 + mov dword [FxTabledA2+0A1h*4],FxOpdA1A2 + mov dword [FxTabledA2+0A2h*4],FxOpdA2A2 + mov dword [FxTabledA2+0A3h*4],FxOpdA3A2 + mov dword [FxTabledA2+0A4h*4],FxOpdA4A2 + mov dword [FxTabledA2+0A5h*4],FxOpdA5A2 + mov dword [FxTabledA2+0A6h*4],FxOpdA6A2 + mov dword [FxTabledA2+0A7h*4],FxOpdA7A2 + mov dword [FxTabledA2+0A8h*4],FxOpdA8A2 + mov dword [FxTabledA2+0A9h*4],FxOpdA9A2 + mov dword [FxTabledA2+0AAh*4],FxOpdAAA2 + mov dword [FxTabledA2+0ABh*4],FxOpdABA2 + mov dword [FxTabledA2+0ACh*4],FxOpdACA2 + mov dword [FxTabledA2+0ADh*4],FxOpdADA2 + mov dword [FxTabledA2+0AEh*4],FxOpdAEA2 + mov dword [FxTabledA2+0AFh*4],FxOpdAFA2 + + mov dword [FxTabledA2+0B0h*4],FxOpdB0 + mov dword [FxTabledA2+0B1h*4],FxOpdB1 + mov dword [FxTabledA2+0B2h*4],FxOpdB2 + mov dword [FxTabledA2+0B3h*4],FxOpdB3 + mov dword [FxTabledA2+0B4h*4],FxOpdB4 + mov dword [FxTabledA2+0B5h*4],FxOpdB5 + mov dword [FxTabledA2+0B6h*4],FxOpdB6 + mov dword [FxTabledA2+0B7h*4],FxOpdB7 + mov dword [FxTabledA2+0B8h*4],FxOpdB8 + mov dword [FxTabledA2+0B9h*4],FxOpdB9 + mov dword [FxTabledA2+0BAh*4],FxOpdBA + mov dword [FxTabledA2+0BBh*4],FxOpdBB + mov dword [FxTabledA2+0BCh*4],FxOpdBC + mov dword [FxTabledA2+0BDh*4],FxOpdBD + mov dword [FxTabledA2+0BEh*4],FxOpdBE + mov dword [FxTabledA2+0BFh*4],FxOpdBF + + mov dword [FxTabledA2+0C0h*4],FxOpdC0 + mov dword [FxTabledA2+0C1h*4],FxOpdC1A2 + mov dword [FxTabledA2+0C2h*4],FxOpdC2A2 + mov dword [FxTabledA2+0C3h*4],FxOpdC3A2 + mov dword [FxTabledA2+0C4h*4],FxOpdC4A2 + mov dword [FxTabledA2+0C5h*4],FxOpdC5A2 + mov dword [FxTabledA2+0C6h*4],FxOpdC6A2 + mov dword [FxTabledA2+0C7h*4],FxOpdC7A2 + mov dword [FxTabledA2+0C8h*4],FxOpdC8A2 + mov dword [FxTabledA2+0C9h*4],FxOpdC9A2 + mov dword [FxTabledA2+0CAh*4],FxOpdCAA2 + mov dword [FxTabledA2+0CBh*4],FxOpdCBA2 + mov dword [FxTabledA2+0CCh*4],FxOpdCCA2 + mov dword [FxTabledA2+0CDh*4],FxOpdCDA2 + mov dword [FxTabledA2+0CEh*4],FxOpdCEA2 + mov dword [FxTabledA2+0CFh*4],FxOpdCFA2 + + mov dword [FxTabledA2+0D0h*4],FxOpdD0 + mov dword [FxTabledA2+0D1h*4],FxOpdD1 + mov dword [FxTabledA2+0D2h*4],FxOpdD2 + mov dword [FxTabledA2+0D3h*4],FxOpdD3 + mov dword [FxTabledA2+0D4h*4],FxOpdD4 + mov dword [FxTabledA2+0D5h*4],FxOpdD5 + mov dword [FxTabledA2+0D6h*4],FxOpdD6 + mov dword [FxTabledA2+0D7h*4],FxOpdD7 + mov dword [FxTabledA2+0D8h*4],FxOpdD8 + mov dword [FxTabledA2+0D9h*4],FxOpdD9 + mov dword [FxTabledA2+0DAh*4],FxOpdDA + mov dword [FxTabledA2+0DBh*4],FxOpdDB + mov dword [FxTabledA2+0DCh*4],FxOpdDC + mov dword [FxTabledA2+0DDh*4],FxOpdDD + mov dword [FxTabledA2+0DEh*4],FxOpdDE + mov dword [FxTabledA2+0DFh*4],FxOpdDFA2 + + mov dword [FxTabledA2+0E0h*4],FxOpdE0 + mov dword [FxTabledA2+0E1h*4],FxOpdE1 + mov dword [FxTabledA2+0E2h*4],FxOpdE2 + mov dword [FxTabledA2+0E3h*4],FxOpdE3 + mov dword [FxTabledA2+0E4h*4],FxOpdE4 + mov dword [FxTabledA2+0E5h*4],FxOpdE5 + mov dword [FxTabledA2+0E6h*4],FxOpdE6 + mov dword [FxTabledA2+0E7h*4],FxOpdE7 + mov dword [FxTabledA2+0E8h*4],FxOpdE8 + mov dword [FxTabledA2+0E9h*4],FxOpdE9 + mov dword [FxTabledA2+0EAh*4],FxOpdEA + mov dword [FxTabledA2+0EBh*4],FxOpdEB + mov dword [FxTabledA2+0ECh*4],FxOpdEC + mov dword [FxTabledA2+0EDh*4],FxOpdED + mov dword [FxTabledA2+0EEh*4],FxOpdEE + mov dword [FxTabledA2+0EFh*4],FxOpdEFA2 + + mov dword [FxTabledA2+0F0h*4],FxOpdF0A2 + mov dword [FxTabledA2+0F1h*4],FxOpdF1A2 + mov dword [FxTabledA2+0F2h*4],FxOpdF2A2 + mov dword [FxTabledA2+0F3h*4],FxOpdF3A2 + mov dword [FxTabledA2+0F4h*4],FxOpdF4A2 + mov dword [FxTabledA2+0F5h*4],FxOpdF5A2 + mov dword [FxTabledA2+0F6h*4],FxOpdF6A2 + mov dword [FxTabledA2+0F7h*4],FxOpdF7A2 + mov dword [FxTabledA2+0F8h*4],FxOpdF8A2 + mov dword [FxTabledA2+0F9h*4],FxOpdF9A2 + mov dword [FxTabledA2+0FAh*4],FxOpdFAA2 + mov dword [FxTabledA2+0FBh*4],FxOpdFBA2 + mov dword [FxTabledA2+0FCh*4],FxOpdFCA2 + mov dword [FxTabledA2+0FDh*4],FxOpdFDA2 + mov dword [FxTabledA2+0FEh*4],FxOpdFEA2 + mov dword [FxTabledA2+0FFh*4],FxOpdFFA2 + + mov dword [FxTabledA3+00h*4],FxOpd00 + mov dword [FxTabledA3+01h*4],FxOpd01 + mov dword [FxTabledA3+02h*4],FxOpd02 + mov dword [FxTabledA3+03h*4],FxOpd03 + mov dword [FxTabledA3+04h*4],FxOpd04 + mov dword [FxTabledA3+05h*4],FxOpd05 + mov dword [FxTabledA3+06h*4],FxOpd06 + mov dword [FxTabledA3+07h*4],FxOpd07 + mov dword [FxTabledA3+08h*4],FxOpd08 + mov dword [FxTabledA3+09h*4],FxOpd09 + mov dword [FxTabledA3+0Ah*4],FxOpd0A + mov dword [FxTabledA3+0Bh*4],FxOpd0B + mov dword [FxTabledA3+0Ch*4],FxOpd0C + mov dword [FxTabledA3+0Dh*4],FxOpd0D + mov dword [FxTabledA3+0Eh*4],FxOpd0E + mov dword [FxTabledA3+0Fh*4],FxOpd0F + + mov dword [FxTabledA3+10h*4],FxOpd10 + mov dword [FxTabledA3+11h*4],FxOpd11 + mov dword [FxTabledA3+12h*4],FxOpd12 + mov dword [FxTabledA3+13h*4],FxOpd13 + mov dword [FxTabledA3+14h*4],FxOpd14 + mov dword [FxTabledA3+15h*4],FxOpd15 + mov dword [FxTabledA3+16h*4],FxOpd16 + mov dword [FxTabledA3+17h*4],FxOpd17 + mov dword [FxTabledA3+18h*4],FxOpd18 + mov dword [FxTabledA3+19h*4],FxOpd19 + mov dword [FxTabledA3+1Ah*4],FxOpd1A + mov dword [FxTabledA3+1Bh*4],FxOpd1B + mov dword [FxTabledA3+1Ch*4],FxOpd1C + mov dword [FxTabledA3+1Dh*4],FxOpd1D + mov dword [FxTabledA3+1Eh*4],FxOpd1E + mov dword [FxTabledA3+1Fh*4],FxOpd1F + + mov dword [FxTabledA3+20h*4],FxOpd20 + mov dword [FxTabledA3+21h*4],FxOpd21 + mov dword [FxTabledA3+22h*4],FxOpd22 + mov dword [FxTabledA3+23h*4],FxOpd23 + mov dword [FxTabledA3+24h*4],FxOpd24 + mov dword [FxTabledA3+25h*4],FxOpd25 + mov dword [FxTabledA3+26h*4],FxOpd26 + mov dword [FxTabledA3+27h*4],FxOpd27 + mov dword [FxTabledA3+28h*4],FxOpd28 + mov dword [FxTabledA3+29h*4],FxOpd29 + mov dword [FxTabledA3+2Ah*4],FxOpd2A + mov dword [FxTabledA3+2Bh*4],FxOpd2B + mov dword [FxTabledA3+2Ch*4],FxOpd2C + mov dword [FxTabledA3+2Dh*4],FxOpd2D + mov dword [FxTabledA3+2Eh*4],FxOpd2E + mov dword [FxTabledA3+2Fh*4],FxOpd2F + + mov dword [FxTabledA3+30h*4],FxOpd30 + mov dword [FxTabledA3+31h*4],FxOpd31 + mov dword [FxTabledA3+32h*4],FxOpd32 + mov dword [FxTabledA3+33h*4],FxOpd33 + mov dword [FxTabledA3+34h*4],FxOpd34 + mov dword [FxTabledA3+35h*4],FxOpd35 + mov dword [FxTabledA3+36h*4],FxOpd36 + mov dword [FxTabledA3+37h*4],FxOpd37 + mov dword [FxTabledA3+38h*4],FxOpd38 + mov dword [FxTabledA3+39h*4],FxOpd39 + mov dword [FxTabledA3+3Ah*4],FxOpd3A + mov dword [FxTabledA3+3Bh*4],FxOpd3B + mov dword [FxTabledA3+3Ch*4],FxOpd3C + mov dword [FxTabledA3+3Dh*4],FxOpd3D + mov dword [FxTabledA3+3Eh*4],FxOpd3E + mov dword [FxTabledA3+3Fh*4],FxOpd3F + + mov dword [FxTabledA3+40h*4],FxOpd40 + mov dword [FxTabledA3+41h*4],FxOpd41 + mov dword [FxTabledA3+42h*4],FxOpd42 + mov dword [FxTabledA3+43h*4],FxOpd43 + mov dword [FxTabledA3+44h*4],FxOpd44 + mov dword [FxTabledA3+45h*4],FxOpd45 + mov dword [FxTabledA3+46h*4],FxOpd46 + mov dword [FxTabledA3+47h*4],FxOpd47 + mov dword [FxTabledA3+48h*4],FxOpd48 + mov dword [FxTabledA3+49h*4],FxOpd49 + mov dword [FxTabledA3+4Ah*4],FxOpd4A + mov dword [FxTabledA3+4Bh*4],FxOpd4B + mov dword [FxTabledA3+4Ch*4],FxOpd4C + mov dword [FxTabledA3+4Dh*4],FxOpd4D + mov dword [FxTabledA3+4Eh*4],FxOpd4E + mov dword [FxTabledA3+4Fh*4],FxOpd4F + + mov dword [FxTabledA3+50h*4],FxOpd50A3 + mov dword [FxTabledA3+51h*4],FxOpd51A3 + mov dword [FxTabledA3+52h*4],FxOpd52A3 + mov dword [FxTabledA3+53h*4],FxOpd53A3 + mov dword [FxTabledA3+54h*4],FxOpd54A3 + mov dword [FxTabledA3+55h*4],FxOpd55A3 + mov dword [FxTabledA3+56h*4],FxOpd56A3 + mov dword [FxTabledA3+57h*4],FxOpd57A3 + mov dword [FxTabledA3+58h*4],FxOpd58A3 + mov dword [FxTabledA3+59h*4],FxOpd59A3 + mov dword [FxTabledA3+5Ah*4],FxOpd5AA3 + mov dword [FxTabledA3+5Bh*4],FxOpd5BA3 + mov dword [FxTabledA3+5Ch*4],FxOpd5CA3 + mov dword [FxTabledA3+5Dh*4],FxOpd5DA3 + mov dword [FxTabledA3+5Eh*4],FxOpd5EA3 + mov dword [FxTabledA3+5Fh*4],FxOpd5FA3 + + mov dword [FxTabledA3+60h*4],FxOpd60A3 + mov dword [FxTabledA3+61h*4],FxOpd61A3 + mov dword [FxTabledA3+62h*4],FxOpd62A3 + mov dword [FxTabledA3+63h*4],FxOpd63A3 + mov dword [FxTabledA3+64h*4],FxOpd64A3 + mov dword [FxTabledA3+65h*4],FxOpd65A3 + mov dword [FxTabledA3+66h*4],FxOpd66A3 + mov dword [FxTabledA3+67h*4],FxOpd67A3 + mov dword [FxTabledA3+68h*4],FxOpd68A3 + mov dword [FxTabledA3+69h*4],FxOpd69A3 + mov dword [FxTabledA3+6Ah*4],FxOpd6AA3 + mov dword [FxTabledA3+6Bh*4],FxOpd6BA3 + mov dword [FxTabledA3+6Ch*4],FxOpd6CA3 + mov dword [FxTabledA3+6Dh*4],FxOpd6DA3 + mov dword [FxTabledA3+6Eh*4],FxOpd6EA3 + mov dword [FxTabledA3+6Fh*4],FxOpd6FA3 + + mov dword [FxTabledA3+70h*4],FxOpd70 + mov dword [FxTabledA3+71h*4],FxOpd71A3 + mov dword [FxTabledA3+72h*4],FxOpd72A3 + mov dword [FxTabledA3+73h*4],FxOpd73A3 + mov dword [FxTabledA3+74h*4],FxOpd74A3 + mov dword [FxTabledA3+75h*4],FxOpd75A3 + mov dword [FxTabledA3+76h*4],FxOpd76A3 + mov dword [FxTabledA3+77h*4],FxOpd77A3 + mov dword [FxTabledA3+78h*4],FxOpd78A3 + mov dword [FxTabledA3+79h*4],FxOpd79A3 + mov dword [FxTabledA3+7Ah*4],FxOpd7AA3 + mov dword [FxTabledA3+7Bh*4],FxOpd7BA3 + mov dword [FxTabledA3+7Ch*4],FxOpd7CA3 + mov dword [FxTabledA3+7Dh*4],FxOpd7DA3 + mov dword [FxTabledA3+7Eh*4],FxOpd7EA3 + mov dword [FxTabledA3+7Fh*4],FxOpd7FA3 + + mov dword [FxTabledA3+80h*4],FxOpd80A3 + mov dword [FxTabledA3+81h*4],FxOpd81A3 + mov dword [FxTabledA3+82h*4],FxOpd82A3 + mov dword [FxTabledA3+83h*4],FxOpd83A3 + mov dword [FxTabledA3+84h*4],FxOpd84A3 + mov dword [FxTabledA3+85h*4],FxOpd85A3 + mov dword [FxTabledA3+86h*4],FxOpd86A3 + mov dword [FxTabledA3+87h*4],FxOpd87A3 + mov dword [FxTabledA3+88h*4],FxOpd88A3 + mov dword [FxTabledA3+89h*4],FxOpd89A3 + mov dword [FxTabledA3+8Ah*4],FxOpd8AA3 + mov dword [FxTabledA3+8Bh*4],FxOpd8BA3 + mov dword [FxTabledA3+8Ch*4],FxOpd8CA3 + mov dword [FxTabledA3+8Dh*4],FxOpd8DA3 + mov dword [FxTabledA3+8Eh*4],FxOpd8EA3 + mov dword [FxTabledA3+8Fh*4],FxOpd8FA3 + + mov dword [FxTabledA3+90h*4],FxOpd90 + mov dword [FxTabledA3+91h*4],FxOpd91 + mov dword [FxTabledA3+92h*4],FxOpd92 + mov dword [FxTabledA3+93h*4],FxOpd93 + mov dword [FxTabledA3+94h*4],FxOpd94 + mov dword [FxTabledA3+95h*4],FxOpd95 + mov dword [FxTabledA3+96h*4],FxOpd96 + mov dword [FxTabledA3+97h*4],FxOpd97 + mov dword [FxTabledA3+98h*4],FxOpd98 + mov dword [FxTabledA3+99h*4],FxOpd99 + mov dword [FxTabledA3+9Ah*4],FxOpd9A + mov dword [FxTabledA3+9Bh*4],FxOpd9B + mov dword [FxTabledA3+9Ch*4],FxOpd9C + mov dword [FxTabledA3+9Dh*4],FxOpd9D + mov dword [FxTabledA3+9Eh*4],FxOpd9E + mov dword [FxTabledA3+9Fh*4],FxOpd9F + + mov dword [FxTabledA3+0A0h*4],FxOpdA0 + mov dword [FxTabledA3+0A1h*4],FxOpdA1 + mov dword [FxTabledA3+0A2h*4],FxOpdA2 + mov dword [FxTabledA3+0A3h*4],FxOpdA3 + mov dword [FxTabledA3+0A4h*4],FxOpdA4 + mov dword [FxTabledA3+0A5h*4],FxOpdA5 + mov dword [FxTabledA3+0A6h*4],FxOpdA6 + mov dword [FxTabledA3+0A7h*4],FxOpdA7 + mov dword [FxTabledA3+0A8h*4],FxOpdA8 + mov dword [FxTabledA3+0A9h*4],FxOpdA9 + mov dword [FxTabledA3+0AAh*4],FxOpdAA + mov dword [FxTabledA3+0ABh*4],FxOpdAB + mov dword [FxTabledA3+0ACh*4],FxOpdAC + mov dword [FxTabledA3+0ADh*4],FxOpdAD + mov dword [FxTabledA3+0AEh*4],FxOpdAE + mov dword [FxTabledA3+0AFh*4],FxOpdAF + + mov dword [FxTabledA3+0B0h*4],FxOpdB0 + mov dword [FxTabledA3+0B1h*4],FxOpdB1 + mov dword [FxTabledA3+0B2h*4],FxOpdB2 + mov dword [FxTabledA3+0B3h*4],FxOpdB3 + mov dword [FxTabledA3+0B4h*4],FxOpdB4 + mov dword [FxTabledA3+0B5h*4],FxOpdB5 + mov dword [FxTabledA3+0B6h*4],FxOpdB6 + mov dword [FxTabledA3+0B7h*4],FxOpdB7 + mov dword [FxTabledA3+0B8h*4],FxOpdB8 + mov dword [FxTabledA3+0B9h*4],FxOpdB9 + mov dword [FxTabledA3+0BAh*4],FxOpdBA + mov dword [FxTabledA3+0BBh*4],FxOpdBB + mov dword [FxTabledA3+0BCh*4],FxOpdBC + mov dword [FxTabledA3+0BDh*4],FxOpdBD + mov dword [FxTabledA3+0BEh*4],FxOpdBE + mov dword [FxTabledA3+0BFh*4],FxOpdBF + + mov dword [FxTabledA3+0C0h*4],FxOpdC0 + mov dword [FxTabledA3+0C1h*4],FxOpdC1A3 + mov dword [FxTabledA3+0C2h*4],FxOpdC2A3 + mov dword [FxTabledA3+0C3h*4],FxOpdC3A3 + mov dword [FxTabledA3+0C4h*4],FxOpdC4A3 + mov dword [FxTabledA3+0C5h*4],FxOpdC5A3 + mov dword [FxTabledA3+0C6h*4],FxOpdC6A3 + mov dword [FxTabledA3+0C7h*4],FxOpdC7A3 + mov dword [FxTabledA3+0C8h*4],FxOpdC8A3 + mov dword [FxTabledA3+0C9h*4],FxOpdC9A3 + mov dword [FxTabledA3+0CAh*4],FxOpdCAA3 + mov dword [FxTabledA3+0CBh*4],FxOpdCBA3 + mov dword [FxTabledA3+0CCh*4],FxOpdCCA3 + mov dword [FxTabledA3+0CDh*4],FxOpdCDA3 + mov dword [FxTabledA3+0CEh*4],FxOpdCEA3 + mov dword [FxTabledA3+0CFh*4],FxOpdCFA3 + + mov dword [FxTabledA3+0D0h*4],FxOpdD0 + mov dword [FxTabledA3+0D1h*4],FxOpdD1 + mov dword [FxTabledA3+0D2h*4],FxOpdD2 + mov dword [FxTabledA3+0D3h*4],FxOpdD3 + mov dword [FxTabledA3+0D4h*4],FxOpdD4 + mov dword [FxTabledA3+0D5h*4],FxOpdD5 + mov dword [FxTabledA3+0D6h*4],FxOpdD6 + mov dword [FxTabledA3+0D7h*4],FxOpdD7 + mov dword [FxTabledA3+0D8h*4],FxOpdD8 + mov dword [FxTabledA3+0D9h*4],FxOpdD9 + mov dword [FxTabledA3+0DAh*4],FxOpdDA + mov dword [FxTabledA3+0DBh*4],FxOpdDB + mov dword [FxTabledA3+0DCh*4],FxOpdDC + mov dword [FxTabledA3+0DDh*4],FxOpdDD + mov dword [FxTabledA3+0DEh*4],FxOpdDE + mov dword [FxTabledA3+0DFh*4],FxOpdDFA3 + + mov dword [FxTabledA3+0E0h*4],FxOpdE0 + mov dword [FxTabledA3+0E1h*4],FxOpdE1 + mov dword [FxTabledA3+0E2h*4],FxOpdE2 + mov dword [FxTabledA3+0E3h*4],FxOpdE3 + mov dword [FxTabledA3+0E4h*4],FxOpdE4 + mov dword [FxTabledA3+0E5h*4],FxOpdE5 + mov dword [FxTabledA3+0E6h*4],FxOpdE6 + mov dword [FxTabledA3+0E7h*4],FxOpdE7 + mov dword [FxTabledA3+0E8h*4],FxOpdE8 + mov dword [FxTabledA3+0E9h*4],FxOpdE9 + mov dword [FxTabledA3+0EAh*4],FxOpdEA + mov dword [FxTabledA3+0EBh*4],FxOpdEB + mov dword [FxTabledA3+0ECh*4],FxOpdEC + mov dword [FxTabledA3+0EDh*4],FxOpdED + mov dword [FxTabledA3+0EEh*4],FxOpdEE + mov dword [FxTabledA3+0EFh*4],FxOpdEFA3 + + mov dword [FxTabledA3+0F0h*4],FxOpdF0 + mov dword [FxTabledA3+0F1h*4],FxOpdF1 + mov dword [FxTabledA3+0F2h*4],FxOpdF2 + mov dword [FxTabledA3+0F3h*4],FxOpdF3 + mov dword [FxTabledA3+0F4h*4],FxOpdF4 + mov dword [FxTabledA3+0F5h*4],FxOpdF5 + mov dword [FxTabledA3+0F6h*4],FxOpdF6 + mov dword [FxTabledA3+0F7h*4],FxOpdF7 + mov dword [FxTabledA3+0F8h*4],FxOpdF8 + mov dword [FxTabledA3+0F9h*4],FxOpdF9 + mov dword [FxTabledA3+0FAh*4],FxOpdFA + mov dword [FxTabledA3+0FBh*4],FxOpdFB + mov dword [FxTabledA3+0FCh*4],FxOpdFC + mov dword [FxTabledA3+0FDh*4],FxOpdFD + mov dword [FxTabledA3+0FEh*4],FxOpdFE + mov dword [FxTabledA3+0FFh*4],FxOpdFF + ret + +; normal +SECTION .data +NEWSYM sfxnametab + db 'STOP NOP CACHE LSR ' + db 'ROL BRA BLT BGE ' + db 'BNE BEQ BPL BMI ' + db 'BCC BCS BVC BVS ' + + db 'TO R0 TO R1 TO R2 TO R3 ' ; MOVE when B=1 + db 'TO R4 TO R5 TO R6 TO R7 ' + db 'TO R8 TO R9 TO R10 TO R11 ' + db 'TO R12 TO R13 TO R14 TO R15 ' + + db 'WITH R0 WITH R1 WITH R2 WITH R3 ' + db 'WITH R4 WITH R5 WITH R6 WITH R7 ' + db 'WITH R8 WITH R9 WITH R10WITH R11' + db 'WITH R12WITH R13WITH R14WITH R15' + + db 'STW(R0) STW(R1) STW(R2) STW(R3) ' + db 'STW(R4) STW(R5) STW(R6) STW(R7) ' + db 'STW(R8) STW(R9) STW(R10)STW(R11)' + db 'LOOP ALT1 ALT2 ALT3 ' + + db 'LDW(R0) LDW(R1) LDW(R2) LDW(R3) ' + db 'LDW(R4) LDW(R5) LDW(R6) LDW(R7) ' + db 'LDW(R8) LDW(R9) LDW(R10)LDW(R11)' + db 'PLOT SWAP COLOR NOT ' + + db 'ADD R0 ADD R1 ADD R2 ADD R3 ' + db 'ADD R4 ADD R5 ADD R6 ADD R7 ' + db 'ADD R8 ADD R9 ADD R10 ADD R11 ' + db 'ADD R12 ADD R13 ADD R14 ADD R15 ' + + db 'SUB R0 SUB R1 SUB R2 SUB R3 ' + db 'SUB R4 SUB R5 SUB R6 SUB R7 ' + db 'SUB R8 SUB R9 SUB R10 SUB R11 ' + db 'SUB R12 SUB R13 SUB R14 SUB R15 ' + + db 'MERGE AND R1 AND R2 AND R3 ' + db 'AND R4 AND R5 AND R6 AND R7 ' + db 'AND R8 AND R9 AND R10 AND R11 ' + db 'AND R12 AND R13 AND R14 AND R15 ' + + db 'MULT R0 MULT R1 MULT R2 MULT R3 ' + db 'MULT R4 MULT R5 MULT R6 MULT R7 ' + db 'MULT R8 MULT R9 MULT R10MULT R11' + db 'MULT R12MULT R13MULT R14MULT R15' + + db 'SBK LINK #$1LINK #$2LINK #$3' + db 'LINK #$4SEX ASR ROR ' + db 'JMP R8 JMP R9 JMP R10 JMP R11 ' + db 'JMP R12 JMP R13 LOB FMULT ' + + db 'IBT R0 IBT R1 IBT R2 IBT R3 ' + db 'IBT R4 IBT R5 IBT R6 IBT R7 ' + db 'IBT R8 IBT R9 IBT R10 IBT R11 ' + db 'IBT R12 IBT R13 IBT R14 IBT R15 ' + + db 'FROM R0 FROM R1 FROM R2 FROM R3 ' ; MOVES if B=1 + db 'FROM R4 FROM R5 FROM R6 FROM R7 ' + db 'FROM R8 FROM R9 FROM R10FROM R11' + db 'FROM R12FROM R13FROM R14FROM R15' + + db 'HIB OR R1 OR R2 OR R3 ' + db 'OR R4 OR R5 OR R6 OR R7 ' + db 'OR R8 OR R9 OR R10 OR R11 ' + db 'OR R12 OR R13 OR R14 OR R15 ' + + db 'INC R0 INC R1 INC R2 INC R3 ' + db 'INC R4 INC R5 INC R6 INC R7 ' + db 'INC R8 INC R9 INC R10 INC R11 ' + db 'INC R12 INC R13 INC R14 GETC ' + + db 'DEC R0 DEC R1 DEC R2 DEC R3 ' + db 'DEC R4 DEC R5 DEC R6 DEC R7 ' + db 'DEC R8 DEC R9 DEC R10 DEC R11 ' + db 'DEC R12 DEC R13 DEC R14 GETB ' + + db 'IWT R0 IWT R1 IWT R2 IWT R3 ' + db 'IWT R4 IWT R5 IWT R6 IWT R7 ' + db 'IWT R8 IWT R9 IWT R10 IWT R11 ' + db 'IWT R12 IWT R13 IWT R14 IWT R15 ' + +;A1 + db 'STOP NOP CACHE LSR ' + db 'ROL BRA BLT BGE ' + db 'BNE BEQ BPL BMI ' + db 'BCC BCS BVC BVS ' + + db 'TO R0 TO R1 TO R2 TO R3 ' ; MOVE when B=1 + db 'TO R4 TO R5 TO R6 TO R7 ' + db 'TO R8 TO R9 TO R10 TO R11 ' + db 'TO R12 TO R13 TO R14 TO R15 ' + + db 'WITH R0 WITH R1 WITH R2 WITH R3 ' + db 'WITH R4 WITH R5 WITH R6 WITH R7 ' + db 'WITH R8 WITH R9 WITH R10WITH R11' + db 'WITH R12WITH R13WITH R14WITH R15' + + db 'STB(R0) STB(R1) STB(R2) STB(R3) ' + db 'STB(R4) STB(R5) STB(R6) STB(R7) ' + db 'STB(R8) STB(R9) STB(R10)STB(R11)' + db 'LOOP ALT1 ALT2 ALT3 ' + + db 'LDB(R0) LDB(R1) LDB(R2) LDB(R3) ' + db 'LDB(R4) LDB(R5) LDB(R6) LDB(R7) ' + db 'LDB(R8) LDB(R9) LDB(R10)LDB(R11)' + db 'PLOT SWAP CMODE NOT ' + + db 'ADC R0 ADC R1 ADC R2 ADC R3 ' + db 'ADC R4 ADC R5 ADC R6 ADC R7 ' + db 'ADC R8 ADC R9 ADC R10 ADC R11 ' + db 'ADC R12 ADC R13 ADC R14 ADC R15 ' + + db 'SBC R0 SBC R1 SBC R2 SBC R3 ' + db 'SBC R4 SBC R5 SBC R6 SBC R7 ' + db 'SBC R8 SBC R9 SBC R10 SBC R11 ' + db 'SBC R12 SBC R13 SBC R14 SBC R15 ' + + db 'MERGE BIC R1 BIC R2 BIC R3 ' + db 'BIC R4 BIC R5 BIC R6 BIC R7 ' + db 'BIC R8 BIC R9 BIC R10 BIC R11 ' + db 'BIC R12 BIC R13 BIC R14 BIC R15 ' + + db 'UMULTR0 UMULTR1 UMULTR2 UMULTR3 ' + db 'UMULTR4 UMULTR5 UMULTR6 UMULTR7 ' + db 'UMULTR8 UMULTR9 UMULTR10UMULTR11' + db 'UMULTR12UMULTR13UMULTR14UMULTR15' + + db 'SBK LINK #$1LINK #$2LINK #$3' + db 'LINK #$4SEX DIV2 ROR ' + db 'LJMP R8 LJMP R9 LJMP R10LJMP R11' + db 'LJMP R12LJMP R13LOB LMULT ' + + db 'LMS R0 LMS R1 LMS R2 LMS R3 ' + db 'LMS R4 LMS R5 LMS R6 LMS R7 ' + db 'LMS R8 LMS R9 LMS R10 LMS R11 ' + db 'LMS R12 LMS R13 LMS R14 LMS R15 ' + + db 'FROM R0 FROM R1 FROM R2 FROM R3 ' ; MOVES if B=1 + db 'FROM R4 FROM R5 FROM R6 FROM R7 ' + db 'FROM R8 FROM R9 FROM R10FROM R11' + db 'FROM R12FROM R13FROM R14FROM R15' + + db 'HIB XOR R1 XOR R2 XOR R3 ' + db 'XOR R4 XOR R5 XOR R6 XOR R7 ' + db 'XOR R8 XOR R9 XOR R10 XOR R11 ' + db 'XOR R12 XOR R13 XOR R14 XOR R15 ' + + db 'INC R0 INC R1 INC R2 INC R3 ' + db 'INC R4 INC R5 INC R6 INC R7 ' + db 'INC R8 INC R9 INC R10 INC R11 ' + db 'INC R12 INC R13 INC R14 GETC ' + + db 'DEC R0 DEC R1 DEC R2 DEC R3 ' + db 'DEC R4 DEC R5 DEC R6 DEC R7 ' + db 'DEC R8 DEC R9 DEC R10 DEC R11 ' + db 'DEC R12 DEC R13 DEC R14 GETBH ' + + db 'LM R0 LM R1 LM R2 LM R3 ' + db 'LM R4 LM R5 LM R6 LM R7 ' + db 'LM R8 LM R9 LM R10 LM R11 ' + db 'LM R12 LM R13 LM R14 LM R15 ' +;A2 + db 'STOP NOP CACHE LSR ' + db 'ROL BRA BLT BGE ' + db 'BNE BEQ BPL BMI ' + db 'BCC BCS BVC BVS ' + + db 'TO R0 TO R1 TO R2 TO R3 ' ; MOVE when B=1 + db 'TO R4 TO R5 TO R6 TO R7 ' + db 'TO R8 TO R9 TO R10 TO R11 ' + db 'TO R12 TO R13 TO R14 TO R15 ' + + db 'WITH R0 WITH R1 WITH R2 WITH R3 ' + db 'WITH R4 WITH R5 WITH R6 WITH R7 ' + db 'WITH R8 WITH R9 WITH R10WITH R11' + db 'WITH R12WITH R13WITH R14WITH R15' + + db 'STW(R0) STW(R1) STW(R2) STW(R3) ' + db 'STW(R4) STW(R5) STW(R6) STW(R7) ' + db 'STW(R8) STW(R9) STW(R10)STW(R11)' + db 'LOOP ALT1 ALT2 ALT3 ' + + db 'LDW(R0) LDW(R1) LDW(R2) LDW(R3) ' + db 'LDW(R4) LDW(R5) LDW(R6) LDW(R7) ' + db 'LDW(R8) LDW(R9) LDW(R10)LDW(R11)' + db 'PLOT SWAP COLOR NOT ' + + db 'ADD #$0 ADD #$1 ADD #$2 ADD #$3 ' + db 'ADD #$4 ADD #$5 ADD #$6 ADD #$7 ' + db 'ADD #$8 ADD #$9 ADD #$A ADD #$B ' + db 'ADD #$C ADD #$D ADD #$E ADD #$F ' + + db 'SUB #$0 SUB #$1 SUB #$2 SUB #$3 ' + db 'SUB #$4 SUB #$5 SUB #$6 SUB #$7 ' + db 'SUB #$8 SUB #$9 SUB #$A SUB #$B ' + db 'SUB #$C SUB #$D SUB #$E SUB #$F ' + + db 'MERGE AND #$1 AND #$2 AND #$3 ' + db 'AND #$4 AND #$5 AND #$6 AND #$7 ' + db 'AND #$8 AND #$9 AND #$A AND #$B ' + db 'AND #$C AND #$D AND #$E AND #$F ' + + db 'MULTIR0 MULTIR1 MULTIR2 MULTIR3 ' + db 'MULTIR4 MULTIR5 MULTIR6 MULTIR7 ' + db 'MULTIR8 MULTIR9 MULTIR10MULTIR11' + db 'MULTIR12MULTIR13MULTIR14MULTIR15' + + db 'SBK LINK #$1LINK #$2LINK #$3' + db 'LINK #$4SEX ASR ROR ' + db 'JMP R8 JMP R9 JMP R10 JMP R11 ' + db 'JMP R12 JMP R13 LOB FMULT ' + + db 'SMS R0 SMS R1 SMS R2 SMS R3 ' + db 'SMS R4 SMS R5 SMS R6 SMS R7 ' + db 'SMS R8 SMS R9 SMS R10 SMS R11 ' + db 'SMS R12 SMS R13 SMS R14 SMS R15 ' + + db 'FROM R0 FROM R1 FROM R2 FROM R3 ' ; MOVES if B=1 + db 'FROM R4 FROM R5 FROM R6 FROM R7 ' + db 'FROM R8 FROM R9 FROM R10FROM R11' + db 'FROM R12FROM R13FROM R14FROM R15' + + db 'HIB OR #$1 OR #$2 OR #$3 ' + db 'OR #$4 OR #$5 OR #$6 OR #$7 ' + db 'OR #$8 OR #$9 OR #$A OR #$B ' + db 'OR #$C OR #$D OR #$E OR #$F ' + + db 'INC R0 INC R1 INC R2 INC R3 ' + db 'INC R4 INC R5 INC R6 INC R7 ' + db 'INC R8 INC R9 INC R10 INC R11 ' + db 'INC R12 INC R13 INC R14 RAMB ' + + db 'DEC R0 DEC R1 DEC R2 DEC R3 ' + db 'DEC R4 DEC R5 DEC R6 DEC R7 ' + db 'DEC R8 DEC R9 DEC R10 DEC R11 ' + db 'DEC R12 DEC R13 DEC R14 GETBL ' + + db 'SM R0 SM R1 SM R2 SM R3 ' + db 'SM R4 SM R5 SM R6 SM R7 ' + db 'SM R8 SM R9 SM R10 SM R11 ' + db 'SM R12 SM R13 SM R14 SM R15 ' +;A3 + db 'STOP NOP CACHE LSR ' + db 'ROL BRA BLT BGE ' + db 'BNE BEQ BPL BMI ' + db 'BCC BCS BVC BVS ' + + db 'TO R0 TO R1 TO R2 TO R3 ' ; MOVE when B=1 + db 'TO R4 TO R5 TO R6 TO R7 ' + db 'TO R8 TO R9 TO R10 TO R11 ' + db 'TO R12 TO R13 TO R14 TO R15 ' + + db 'WITH R0 WITH R1 WITH R2 WITH R3 ' + db 'WITH R4 WITH R5 WITH R6 WITH R7 ' + db 'WITH R8 WITH R9 WITH R10WITH R11' + db 'WITH R12WITH R13WITH R14WITH R15' + + db 'STW(R0) STW(R1) STW(R2) STW(R3) ' + db 'STW(R4) STW(R5) STW(R6) STW(R7) ' + db 'STW(R8) STW(R9) STW(R10)STW(R11)' + db 'LOOP ALT1 ALT2 ALT3 ' + + db 'LDW(R0) LDW(R1) LDW(R2) LDW(R3) ' + db 'LDW(R4) LDW(R5) LDW(R6) LDW(R7) ' + db 'LDW(R8) LDW(R9) LDW(R10)LDW(R11)' + db 'PLOT SWAP COLOR NOT ' + + db 'ADC #$0 ADC #$1 ADC #$2 ADC #$3 ' + db 'ADC #$4 ADC #$5 ADC #$6 ADC #$7 ' + db 'ADC #$8 ADC #$9 ADC #$A ADC #$B ' + db 'ADC #$C ADC #$D ADC #$E ADC #$F ' + + db 'CMP R0 CMP R1 CMP R2 CMP R3 ' + db 'CMP R4 CMP R5 CMP R6 CMP R7 ' + db 'CMP R8 CMP R9 CMP R10 CMP R11 ' + db 'CMP R12 CMP R13 CMP R14 CMP R15 ' + + db 'MERGE BIC #$1 BIC #$2 BIC #$3 ' + db 'BIC #$4 BIC #$5 BIC #$6 BIC #$7 ' + db 'BIC #$8 BIC #$9 BIC #$A BIC #$B ' + db 'BIC #$C BIC #$D BIC #$E BIC #$F ' + + db 'UMULIR0 UMULIR1 UMULIR2 UMULIR3 ' + db 'UMULIR4 UMULIR5 UMULIR6 UMULIR7 ' + db 'UMULIR8 UMULIR9 UMULIR10UMULIR11' + db 'UMULIR12UMULIR13UMULIR14UMULIR15' + + db 'SBK LINK #$1LINK #$2LINK #$3' + db 'LINK #$4SEX ASR ROR ' + db 'JMP R8 JMP R9 JMP R10 JMP R11 ' + db 'JMP R12 JMP R13 LOB FMULT ' + + db 'IBT R0 IBT R1 IBT R2 IBT R3 ' + db 'IBT R4 IBT R5 IBT R6 IBT R7 ' + db 'IBT R8 IBT R9 IBT R10 IBT R11 ' + db 'IBT R12 IBT R13 IBT R14 IBT R15 ' + + db 'FROM R0 FROM R1 FROM R2 FROM R3 ' ; MOVES if B=1 + db 'FROM R4 FROM R5 FROM R6 FROM R7 ' + db 'FROM R8 FROM R9 FROM R10FROM R11' + db 'FROM R12FROM R13FROM R14FROM R15' + + db 'HIB XOR #$1 XOR #$2 XOR #$3 ' + db 'XOR #$4 XOR #$5 XOR #$6 XOR #$7 ' + db 'XOR #$8 XOR #$9 XOR #$A XOR #$B ' + db 'XOR #$C XOR #$D XOR #$E XOR #$F ' + + db 'INC R0 INC R1 INC R2 INC R3 ' + db 'INC R4 INC R5 INC R6 INC R7 ' + db 'INC R8 INC R9 INC R10 INC R11 ' + db 'INC R12 INC R13 INC R14 ROMB ' + + db 'DEC R0 DEC R1 DEC R2 DEC R3 ' + db 'DEC R4 DEC R5 DEC R6 DEC R7 ' + db 'DEC R8 DEC R9 DEC R10 DEC R11 ' + db 'DEC R12 DEC R13 DEC R14 GETBS ' + + db 'IWT R0 IWT R1 IWT R2 IWT R3 ' + db 'IWT R4 IWT R5 IWT R6 IWT R7 ' + db 'IWT R8 IWT R9 IWT R10 IWT R11 ' + db 'IWT R12 IWT R13 IWT R14 IWT R15 ' + +SECTION .text +NEWSYM FxTableAsmEnd diff --git a/i386/macros.mac b/i386/macros.mac new file mode 100644 index 00000000..5866f0b6 --- /dev/null +++ b/i386/macros.mac @@ -0,0 +1,80 @@ +;Copyright (C) 1997-2006 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach ) +; +;http://www.zsnes.com +;http://sourceforge.net/projects/zsnes +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;version 2 as published by the Free Software Foundation. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + +%ifidn __OUTPUT_FORMAT__,elf +section .note.GNU-stack noalloc noexec nowrite progbits +%endif + +%ifdef __AMD64__ +bits 64 +%else +bits 32 +%endif + +section .text +; Zsnes required macros + +%define ZVERSION 'Pre 1.43' + + +%ifdef MACHO +section .text align=16 +section .data align=4 +section .bss align=4 +%endif + +%ifdef ELF + +%imacro newsym 1 + GLOBAL %1 + %1: +%endmacro +%imacro newsym 2+ + GLOBAL %1 + %1: %2 +%endmacro +%define EXTSYM EXTERN + +%else + +%imacro newsym 1 + GLOBAL _%1 + _%1: + %1: +%endmacro +%imacro newsym 2+ + GLOBAL _%1 + _%1: + %1: %2 +%endmacro +%imacro EXTSYM 1-* +%rep %0 + EXTERN _%1 + %define %1 _%1 +%rotate 1 +%endrep +%endmacro +%endif + +%macro ALIGN32 0 + times ($$-$) & 1Fh nop ; Long word alignment +%endmacro +%macro ALIGN16 0 + times ($$-$) & 1Fh nop ; Long word alignment +%endmacro diff --git a/i386/regs.mac b/i386/regs.mac new file mode 100644 index 00000000..cb8d312b --- /dev/null +++ b/i386/regs.mac @@ -0,0 +1,101 @@ +; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. +; +; Super FX assembler emulator code +; (c) Copyright 1998, 1999 zsKnight and _Demo_. +; +; 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. +; +;******************************************************* +; InitReg Initializes Registers +;******************************************************* + +%macro setreg 2 + mov edi,%1 + add edi,[regptr] + mov eax,%2 + mov [edi],eax +%endmacro + +;******************************************************* +; Registers Note : Remember to restore AH, ECX, & DX +;******************************************************* + +%macro checkmultchange 0 + ; execute multiplication + cmp byte[multchange],0 + je .nomult + push edx + push eax + xor bh,bh + mov bl,[mode7B+1] + mov ax,[mode7A] + test bl,80h + jz .noneg + mov bh,0FFh +.noneg + imul bx + mov [compmult],ax + mov [compmult+2],dl + pop eax + pop edx + mov byte[multchange],0 +.nomult +%endmacro + +%macro mouse4016doxA 2 + cmp byte[JoyAPos],%1 + jne .nx7 + mov bx,[mousexpos] + shr bx,%2 + and bx,1 + mov al,bl +.nx7 +%endmacro + +%macro mouse4016doyA 2 + cmp byte[JoyAPos],%1 + jne .ny7 + mov bx,[mouseypos] + shr bx,%2 + and bx,1 + mov al,bl +.ny7 +%endmacro + +%macro mouse4017dox 2 + cmp byte[JoyBPos],%1 + jne .nx7 + mov bx,[mousexpos] + shr bx,%2 + and bx,1 + mov al,bl +.nx7 +%endmacro + +%macro mouse4017doy 2 + cmp byte[JoyBPos],%1 + jne .ny7 + mov bx,[mouseypos] + shr bx,%2 + and bx,1 + mov al,bl +.ny7 +%endmacro diff --git a/i386/regsw.mac b/i386/regsw.mac new file mode 100644 index 00000000..a95d47a2 --- /dev/null +++ b/i386/regsw.mac @@ -0,0 +1,51 @@ +; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. +; +; Super FX assembler emulator code +; (c) Copyright 1998, 1999 zsKnight and _Demo_. +; +; 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. +; +;******************************************************* +; InitRegW Initializes Write Registers +;******************************************************* + +%macro reenablespc 0 + cmp dword[cycpbl],1000000h + jb %%enspc + mov dword[cycpbl],0 + test byte[curexecstate],02h + jnz %%enspc + or byte[curexecstate],02h + push ebx + xor ebx,ebx + mov bl,dl + EXTSYM tableadc + mov edi,[tableadc+ebx*4] + pop ebx +%%enspc +%endmacro + +%macro setregw 2 + mov edi,%1 + add edi,[regptw] + mov eax,%2 + mov [edi],eax +%endmacro diff --git a/i386/sfxproc.asm b/i386/sfxproc.asm new file mode 100644 index 00000000..4b6a5c2c --- /dev/null +++ b/i386/sfxproc.asm @@ -0,0 +1,678 @@ +;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com ) +; +;This program is free software; you can redistribute it and/or +;modify it under the terms of the GNU General Public License +;as published by the Free Software Foundation; either +;version 2 of the License, or (at your option) any later +;version. +; +;This program is distributed in the hope that it will be useful, +;but WITHOUT ANY WARRANTY; without even the implied warranty of +;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;GNU General Public License for more details. +; +;You should have received a copy of the GNU General Public License +;along with this program; if not, write to the Free Software +;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +%include "macros.mac" + +EXTSYM NumberOfOpcodes,SfxB,SfxBRAMR,SfxCBR,SfxCFGR,SfxCLSR,SfxCPB,SfxCROM +EXTSYM SfxCarry,SfxMemTable,SfxOverflow,SfxPBR,SfxPIPE,SfxR0,SfxR1,SfxR10 +EXTSYM SfxR11,SfxR12,SfxR13,SfxR14,SfxR15,SfxR2,SfxR3,SfxR4,SfxR5,SfxR6 +EXTSYM SfxR7,SfxR8,SfxR9,SfxRAMBR,SfxRAMMem,SfxROMBR,SfxSCBR,SfxSCMR,SfxSFR +EXTSYM SfxSignZero,SfxnRamBanks,StartSFX,regptr,regptw,sfxramdata +EXTSYM SfxPOR,sfxclineloc,UpdatePORSCMR,UpdateCLSR,UpdateSCBRCOLR,SfxAC +EXTSYM sfx128lineloc,sfx160lineloc,sfx192lineloc,sfxobjlineloc + +NEWSYM SfxProcAsmStart + +%include "regs.mac" +%include "regsw.mac" + + + + + + +%macro AssembleSFXFlags 0 + and word[SfxSFR],8F60h + test byte[SfxCarry],1 + jz .nosfxcarry + or word[SfxSFR],04h +.nosfxcarry + cmp word[SfxSignZero],0 + jne .nozero + or word[SfxSFR],02h +.nozero + test word[SfxSignZero],8000h + jz .noneg + or word[SfxSFR],08h +.noneg + cmp byte[SfxOverflow],0 + je .noof + or word[SfxSFR],10h +.noof + cmp byte[SfxB],0 + je .bzero + or word[SfxSFR],1000h +.bzero +%endmacro + + +NEWSYM initsfxregsr + setreg 3000h*4,reg3000r + setreg 3001h*4,reg3001r + setreg 3002h*4,reg3002r + setreg 3003h*4,reg3003r + setreg 3004h*4,reg3004r + setreg 3005h*4,reg3005r + setreg 3006h*4,reg3006r + setreg 3007h*4,reg3007r + setreg 3008h*4,reg3008r + setreg 3009h*4,reg3009r + setreg 300Ah*4,reg300Ar + setreg 300Bh*4,reg300Br + setreg 300Ch*4,reg300Cr + setreg 300Dh*4,reg300Dr + setreg 300Eh*4,reg300Er + setreg 300Fh*4,reg300Fr + setreg 3010h*4,reg3010r + setreg 3011h*4,reg3011r + setreg 3012h*4,reg3012r + setreg 3013h*4,reg3013r + setreg 3014h*4,reg3014r + setreg 3015h*4,reg3015r + setreg 3016h*4,reg3016r + setreg 3017h*4,reg3017r + setreg 3018h*4,reg3018r + setreg 3019h*4,reg3019r + setreg 301Ah*4,reg301Ar + setreg 301Bh*4,reg301Br + setreg 301Ch*4,reg301Cr + setreg 301Dh*4,reg301Dr + setreg 301Eh*4,reg301Er + setreg 301Fh*4,reg301Fr + setreg 3030h*4,reg3030r + setreg 3031h*4,reg3031r + setreg 3032h*4,reg3032r + setreg 3033h*4,reg3033r + setreg 3034h*4,reg3034r + setreg 3035h*4,reg3035r + setreg 3036h*4,reg3036r + setreg 3037h*4,reg3037r + setreg 3038h*4,reg3038r + setreg 3039h*4,reg3039r + setreg 303Ah*4,reg303Ar + setreg 303Bh*4,reg303Br + setreg 303Ch*4,reg303Cr + setreg 303Dh*4,reg303Dr + setreg 303Eh*4,reg303Er + setreg 303Fh*4,reg303Fr + ; set 3100-31FF to cacheregr + mov edi,3100h*4 + add edi,[regptr] + mov eax,cacheregr + mov ecx,200h +.loop + mov [edi],eax + add edi,4 + dec ecx + jnz .loop + ret + +NEWSYM initsfxregsw + setregw 3000h*4,reg3000w + setregw 3001h*4,reg3001w + setregw 3002h*4,reg3002w + setregw 3003h*4,reg3003w + setregw 3004h*4,reg3004w + setregw 3005h*4,reg3005w + setregw 3006h*4,reg3006w + setregw 3007h*4,reg3007w + setregw 3008h*4,reg3008w + setregw 3009h*4,reg3009w + setregw 300Ah*4,reg300Aw + setregw 300Bh*4,reg300Bw + setregw 300Ch*4,reg300Cw + setregw 300Dh*4,reg300Dw + setregw 300Eh*4,reg300Ew + setregw 300Fh*4,reg300Fw + setregw 3010h*4,reg3010w + setregw 3011h*4,reg3011w + setregw 3012h*4,reg3012w + setregw 3013h*4,reg3013w + setregw 3014h*4,reg3014w + setregw 3015h*4,reg3015w + setregw 3016h*4,reg3016w + setregw 3017h*4,reg3017w + setregw 3018h*4,reg3018w + setregw 3019h*4,reg3019w + setregw 301Ah*4,reg301Aw + setregw 301Bh*4,reg301Bw + setregw 301Ch*4,reg301Cw + setregw 301Dh*4,reg301Dw + setregw 301Eh*4,reg301Ew + setregw 301Fh*4,reg301Fw + setregw 3030h*4,reg3030w + setregw 3031h*4,reg3031w + setregw 3032h*4,reg3032w + setregw 3033h*4,reg3033w + setregw 3034h*4,reg3034w + setregw 3035h*4,reg3035w + setregw 3036h*4,reg3036w + setregw 3037h*4,reg3037w + setregw 3038h*4,reg3038w + setregw 3039h*4,reg3039w + setregw 303Ah*4,reg303Aw + setregw 303Bh*4,reg303Bw + setregw 303Ch*4,reg303Cw + setregw 303Dh*4,reg303Dw + setregw 303Eh*4,reg303Ew + setregw 303Fh*4,reg303Fw + ; set 3100-31FF to cacheregw + mov edi,3100h*4 + add edi,[regptw] + mov eax,cacheregw + mov ecx,200h +.loop + mov [edi],eax + add edi,4 + dec ecx + jnz .loop + ret + +NEWSYM cacheregr + or byte[cachewarning],1 + ret + +NEWSYM cacheregw + or byte[cachewarning],2 + ret + +SECTION .bss +NEWSYM cachewarning, resb 1 +NEWSYM SFXProc, resd 1 +NEWSYM ChangeOps, resd 1 + +SECTION .text + +; SFX Registers + +NEWSYM reg3000r + mov al,[SfxR0] + ret +NEWSYM reg3001r + mov al,[SfxR0+1] + ret +NEWSYM reg3002r + mov al,[SfxR1] + ret +NEWSYM reg3003r + mov al,[SfxR1+1] + ret +NEWSYM reg3004r + mov al,[SfxR2] + ret +NEWSYM reg3005r + mov al,[SfxR2+1] + ret +NEWSYM reg3006r + mov al,[SfxR3] + ret +NEWSYM reg3007r + mov al,[SfxR3+1] + ret +NEWSYM reg3008r + mov al,[SfxR4] + ret +NEWSYM reg3009r + mov al,[SfxR4+1] + ret +NEWSYM reg300Ar + mov al,[SfxR5] + ret +NEWSYM reg300Br + mov al,[SfxR5+1] + ret +NEWSYM reg300Cr + mov al,[SfxR6] + ret +NEWSYM reg300Dr + mov al,[SfxR6+1] + ret +NEWSYM reg300Er + mov al,[SfxR7] + ret +NEWSYM reg300Fr + mov al,[SfxR7+1] + ret +NEWSYM reg3010r + mov al,[SfxR8] + ret +NEWSYM reg3011r + mov al,[SfxR8+1] + ret +NEWSYM reg3012r + mov al,[SfxR9] + ret +NEWSYM reg3013r + mov al,[SfxR9+1] + ret +NEWSYM reg3014r + mov al,[SfxR10] + ret +NEWSYM reg3015r + mov al,[SfxR10+1] + ret +NEWSYM reg3016r + mov al,[SfxR11] + ret +NEWSYM reg3017r + mov al,[SfxR11+1] + ret +NEWSYM reg3018r + mov al,[SfxR12] + ret +NEWSYM reg3019r + mov al,[SfxR12+1] + ret +NEWSYM reg301Ar + mov al,[SfxR13] + ret +NEWSYM reg301Br + mov al,[SfxR13+1] + ret +NEWSYM reg301Cr + mov al,[SfxR14] + ret +NEWSYM reg301Dr + mov al,[SfxR14+1] + ret +NEWSYM reg301Er + mov al,[SfxR15] + ret +NEWSYM reg301Fr + mov al,[SfxR15+1] + ret + +; Other SFX stuff + +NEWSYM reg3030r + AssembleSFXFlags + mov al,[SfxSFR] + ret +NEWSYM reg3031r + cmp byte[SfxAC],1 + je .alwaysclear + cmp dword[ChangeOps],-350*240 + jl .noclear +.alwaysclear + and byte[SfxSFR+1],07fh ; clear IRQ flag + jmp .cleared +.noclear + cmp dword[ChangeOps],-350*240*4 + jge .clear + mov dword[ChangeOps],-350*240*4 + jmp .cleared +.clear + add dword[ChangeOps],350*240 +.cleared + mov al,[SfxSFR+1] + ret +SECTION .bss +.test resb 1 +SECTION .text + +NEWSYM reg3032r ; Unused + xor al,al + ret +NEWSYM reg3033r ; BRAMR Backup Ram Read only on/off (bits 1-15 unused) + mov al,[SfxBRAMR] + ret +NEWSYM reg3034r ; PBR (Program Bank) + mov al,[SfxPBR] + ret +NEWSYM reg3035r ; Unused + xor al,al + ret +NEWSYM reg3036r ; ROMBR (Gamepak Rom Bank Register) + mov al,[SfxROMBR] + ret +NEWSYM reg3037r ; CFGR (Control Flags Register) + mov al,[SfxCFGR] + ret +NEWSYM reg3038r ; SCBR (Screen Bank Register) + mov al,[SfxSCBR] + ret +NEWSYM reg3039r ; CLSR (Clock Speed Register) + mov al,[SfxCLSR] + ret +NEWSYM reg303Ar ; SCMR (Screen Mode Register) + mov al,[SfxSCMR] + test byte[SfxPOR],10h + jnz .objmode + mov al,[SfxSCMR] + and al,00100100b ; 4 + 32 + cmp al,4 + je .lines160 + cmp al,32 + je .lines192 + cmp al,36 + je .objmode + mov eax,[sfx128lineloc] + jmp .donelines +.lines160 + mov eax,[sfx160lineloc] + jmp .donelines +.lines192 + mov eax,[sfx192lineloc] + jmp .donelines +.objmode + mov eax,[sfxobjlineloc] +.donelines + mov [sfxclineloc],eax + ret +NEWSYM reg303Br ; VCR (Version Code Register) + mov al,20h + ret +NEWSYM reg303Cr ; RAMBR (Ram bank register) + mov al,[SfxRAMBR] + ret +NEWSYM reg303Dr ; Unused + xor al,al + ret +NEWSYM reg303Er ; CBR (Cache Base Register), lower byte + mov al,[SfxCBR] + ret +NEWSYM reg303Fr ; CBR (Cache Base Register), upper byte + mov al,[SfxCBR+1] + ret + +; SFX Write Registers + +NEWSYM reg3000w + mov [SfxR0],al + ret +NEWSYM reg3001w + mov [SfxR0+1],al + ret +NEWSYM reg3002w + mov [SfxR1],al + ret +NEWSYM reg3003w + mov [SfxR1+1],al + ret +NEWSYM reg3004w + mov [SfxR2],al + ret +NEWSYM reg3005w + mov [SfxR2+1],al + ret +NEWSYM reg3006w + mov [SfxR3],al + ret +NEWSYM reg3007w + mov [SfxR3+1],al + ret +NEWSYM reg3008w + mov [SfxR4],al + ret +NEWSYM reg3009w + mov [SfxR4+1],al + ret +NEWSYM reg300Aw + mov [SfxR5],al + ret +NEWSYM reg300Bw + mov [SfxR5+1],al + ret +NEWSYM reg300Cw + mov [SfxR6],al + ret +NEWSYM reg300Dw + mov [SfxR6+1],al + ret +NEWSYM reg300Ew + mov [SfxR7],al + ret +NEWSYM reg300Fw + mov [SfxR7+1],al + ret +NEWSYM reg3010w + mov [SfxR8],al + ret +NEWSYM reg3011w + mov [SfxR8+1],al + ret +NEWSYM reg3012w + mov [SfxR9],al + ret +NEWSYM reg3013w + mov [SfxR9+1],al + ret +NEWSYM reg3014w + mov [SfxR10],al + ret +NEWSYM reg3015w + mov [SfxR10+1],al + ret +NEWSYM reg3016w + mov [SfxR11],al + ret +NEWSYM reg3017w + mov [SfxR11+1],al + ret +NEWSYM reg3018w + mov [SfxR12],al + ret +NEWSYM reg3019w + mov [SfxR12+1],al + ret +NEWSYM reg301Aw + mov [SfxR13],al + ret +NEWSYM reg301Bw + mov [SfxR13+1],al + ret +NEWSYM reg301Cw + mov [SfxR14],al + ret +NEWSYM reg301Dw + mov [SfxR14+1],al + ret +NEWSYM reg301Ew + mov [SfxR15],al + ret +NEWSYM reg301Fw + mov [SfxR15+1],al + ; start execution + push edx + mov edx,[SfxPBR] + mov edx,[SfxMemTable+edx*4] + add edx,[SfxR15] + mov dl,[edx] + mov [SfxPIPE],dl + pop edx + inc word[SfxR15] + or byte[SfxSFR],20h + or dword [SfxSFR],08000h ; Set IRQ Flag + mov dword[SFXProc],1 +; call StartSFXret + ret + +; Other SFX stuff + +NEWSYM reg3030w + mov [SfxSFR],al +; mov dh,10 + ; Disassemble Flags + test al,20h + jz .noexec + mov dword [NumberOfOpcodes],100 + call StartSFX +.noexec + ret +NEWSYM reg3031w + mov [SfxSFR+1],al + ret +NEWSYM reg3032w ; Unused + ret +NEWSYM reg3033w ; BRAMR Backup Ram Read only on/off (bits 1-15 unused) + and al,0FEh + mov [SfxBRAMR],al + ret +NEWSYM reg3034w ; PBR (Program Bank) + mov [SfxPBR],al + xor ebx,ebx + mov bl,al + mov ebx,[SfxMemTable+ebx*4] + mov [SfxCPB],ebx + ret +NEWSYM reg3035w ; Unused + ret +NEWSYM reg3036w ; ROMBR (Gamepak Rom Bank Register) + mov [SfxROMBR],al + xor ebx,ebx + mov bl,al + mov ebx,[SfxMemTable+ebx*4] + mov [SfxCROM],ebx + ret +NEWSYM reg3037w ; CFGR (Control Flags Register) + mov [SfxCFGR],al + ret +NEWSYM reg3038w ; SCBR (Screen Bank Register) + mov [SfxSCBR],al + call UpdateSCBRCOLR + ret +NEWSYM reg3039w ; CLSR (Clock Speed Register) + and al,0FEh + mov [SfxCLSR],al + call UpdateCLSR + ret +NEWSYM reg303Aw ; SCMR (Screen Mode Register) + mov [SfxSCMR],al + call UpdatePORSCMR + ret +NEWSYM reg303Bw ; VCR (Version Code Register) + ret +NEWSYM reg303Cw ; RAMBR (Ram bank register) + mov bl,[SfxnRamBanks] + dec bl + and al,bl + mov ebx,[SfxnRamBanks] + dec ebx + and eax,ebx + mov [SfxRAMBR],eax + xor ebx,ebx + mov bl,al + shl ebx,16 + add ebx,[sfxramdata] + mov dword [SfxRAMMem],ebx + ret +NEWSYM reg303Dw ; Unused + ret +NEWSYM reg303Ew ; CBR (Cache Base Register), lower byte + mov [SfxCBR],al + ret +NEWSYM reg303Fw ; CBR (Cache Base Register), upper byte + mov [SfxCBR+1],al + ret + +NEWSYM sfxaccessbankr8 + mov ebx,[sfxramdata] + mov al,[ebx+ecx] + xor ebx,ebx + ret + +NEWSYM sfxaccessbankw8 + mov ebx,[sfxramdata] + mov [ebx+ecx],al + xor ebx,ebx + ret + +NEWSYM sfxaccessbankr16 + mov ebx,[sfxramdata] + mov ax,[ebx+ecx] + xor ebx,ebx + ret + +NEWSYM sfxaccessbankw16 + mov ebx,[sfxramdata] + mov [ebx+ecx],ax + xor ebx,ebx + ret + +NEWSYM sfxaccessbankr8b + mov ebx,[sfxramdata] + mov al,[ebx+ecx+65536] + xor ebx,ebx + ret + +NEWSYM sfxaccessbankw8b + mov ebx,[sfxramdata] + mov [ebx+ecx+65536],al + xor ebx,ebx + ret + +NEWSYM sfxaccessbankr16b + mov ebx,[sfxramdata] + mov ax,[ebx+ecx+65536] + xor ebx,ebx + ret + +NEWSYM sfxaccessbankw16b + mov ebx,[sfxramdata] + mov [ebx+ecx+65536],ax + xor ebx,ebx + ret + +NEWSYM sfxaccessbankr8c + mov ebx,[sfxramdata] + mov al,[ebx+ecx+65536*2] + xor ebx,ebx + ret + +NEWSYM sfxaccessbankw8c + mov ebx,[sfxramdata] + mov [ebx+ecx+65536*2],al + xor ebx,ebx + ret + +NEWSYM sfxaccessbankr16c + mov ebx,[sfxramdata] + mov ax,[ebx+ecx+65536*2] + xor ebx,ebx + ret + +NEWSYM sfxaccessbankw16c + mov ebx,[sfxramdata] + mov [ebx+ecx+65536*2],ax + xor ebx,ebx + ret + +NEWSYM sfxaccessbankr8d + mov ebx,[sfxramdata] + mov al,[ebx+ecx+65536*3] + xor ebx,ebx + ret + +NEWSYM sfxaccessbankw8d + mov ebx,[sfxramdata] + mov [ebx+ecx+65536*3],al + xor ebx,ebx + ret + +NEWSYM sfxaccessbankr16d + mov ebx,[sfxramdata] + mov ax,[ebx+ecx+65536*3] + xor ebx,ebx + ret + +NEWSYM sfxaccessbankw16d + mov ebx,[sfxramdata] + mov [ebx+ecx+65536*3],ax + xor ebx,ebx + ret + +NEWSYM SfxProcAsmEnd diff --git a/i386/zsnes.asm b/i386/zsnes.asm new file mode 100644 index 00000000..d1bcd040 --- /dev/null +++ b/i386/zsnes.asm @@ -0,0 +1,376 @@ +; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. +; +; Super FX assembler emulator code +; (c) Copyright 1998, 1999 zsKnight and _Demo_. +; +; 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. +; +; ZSNES SuperFX emulation code and wrappers +; (C) Copyright 1997-8 zsKnight and _Demo_ + +; Used with the kind permission of the copyright holders. +; + +%include "macros.mac" + +EXTSYM SfxR1,SfxR2,InitFxTables,SfxSFR,SfxSCMR,initsfxregsw,initsfxregsr +EXTSYM SfxPBR,NumberOfOpcodes,SfxCLSR,MainLoop,SfxCROM +EXTSYM SfxRomBuffer,SfxRAMMem,SfxLastRamAdr,SfxR0 +EXTSYM PHnum2writesfxreg, SfxCPB, SfxROMBR, SfxRAMBR, SfxnRamBanks +EXTSYM SfxSignZero + +[BITS 32] +SECTION .data + +NEWSYM flagnz, dd 0 +NEWSYM romdata, dd 0 ; rom data (4MB = 4194304) + +NEWSYM regptr, dd 0 ; pointer to registers +NEWSYM regptw, dd 0 ; pointer to registers +NEWSYM regptra, times 49152 db 0 +NEWSYM regptwa, times 49152 db 0 + +NEWSYM debstop, db 0 +NEWSYM sfxramdata, dd 0 ; SuperFX Ram Data +NEWSYM sfxplottable, dd 0 +NEWSYM FxTable, times 256 dd 0 +NEWSYM FxTableA1, times 256 dd 0 +NEWSYM FxTableA2, times 256 dd 0 +NEWSYM FxTableA3, times 256 dd 0 +NEWSYM FxTableb, times 256 dd 0 +NEWSYM FxTablebA1, times 256 dd 0 +NEWSYM FxTablebA2, times 256 dd 0 +NEWSYM FxTablebA3, times 256 dd 0 +NEWSYM FxTablec, times 256 dd 0 +NEWSYM FxTablecA1, times 256 dd 0 +NEWSYM FxTablecA2, times 256 dd 0 +NEWSYM FxTablecA3, times 256 dd 0 +NEWSYM FxTabled, times 256 dd 0 +NEWSYM FxTabledA1, times 256 dd 0 +NEWSYM FxTabledA2, times 256 dd 0 +NEWSYM FxTabledA3, times 256 dd 0 +NEWSYM SfxMemTable, times 256 dd 0 +NEWSYM fxxand, times 256 dd 0 +NEWSYM fxbit01, times 256 dd 0 +NEWSYM fxbit23, times 256 dd 0 +NEWSYM fxbit45, times 256 dd 0 +NEWSYM fxbit67, times 256 dd 0 +NEWSYM PLOTJmpa, times 64 dd 0 +NEWSYM PLOTJmpb, times 64 dd 0 + +NEWSYM NumberOfOpcodes2, dd 350 +NEWSYM SFXCounter, dd 0 +NEWSYM SfxAC, dd 0 + +;%INCLUDE "fxtable.asm" +;%INCLUDE "sfxproc.asm" +;%INCLUDE "fxemu2.asm" +;%INCLUDE "fxemu2b.asm" +;%INCLUDE "fxemu2c.asm" + +; +; Snes9x wrapper functions for the zsnes SuperFX code +; (C) Copyright 1998 Gary Henderson + +SECTION .data + +EXTSYM SRAM,ROM,RegRAM,SFXPlotTable + +SECTION .text + +NEWSYM StartSFX +NEWSYM StartSFXret + jmp S9xSuperFXExec + +NEWSYM S9xResetSuperFX + push ebx + push esi + push edi + push ebp + + mov dword[SfxR1],0 + mov dword[SfxR2],0 + mov dword[SfxSignZero],1 ; clear z flag + + mov eax,dword[SRAM] + mov dword[sfxramdata],eax + mov eax,dword[ROM] + mov dword[romdata],eax + mov eax,dword[SFXPlotTable] + mov dword[sfxplottable],eax + + call InitFxTables + + mov dword[SfxSFR],0 + mov byte[SfxSCMR],0 + mov dword[regptr],regptra + sub dword[regptr],8000h ; Since register address starts @ 2000h + mov dword[regptw],regptwa + sub dword[regptw],8000h ; Since register address starts @ 2000h + call initsfxregsw + call initsfxregsr + +NEWSYM preparesfx + mov byte[SFXCounter],0 + mov esi,[romdata] + add esi,07FC0h + cmp dword[esi],'FX S' + je .yessfxcounter + cmp dword[esi],'Stun' + jne .nosfxcounter +.yessfxcounter + mov byte[SFXCounter],1 +.nosfxcounter + + ; make table + mov byte[SfxAC],0 + mov eax,[romdata] + cmp dword[eax+02B80h],0AB6CAB6Ch + jne .noac + mov byte[SfxAC],1 +.noac + call UpdateSFX + + pop ebp + pop edi + pop esi + pop ebx + ret + +NEWSYM S9xSuperFXWriteReg + mov eax,dword[esp+4] + mov ecx,dword[esp+8] + push ebx + push esi + push edi + push ebp + test dword[regptwa+ecx*4-8000h], ~0 + jz .skipwrite + call dword[regptwa+ecx*4-8000h] +.skipwrite: + pop ebp + pop edi + pop esi + pop ebx + ret + +NEWSYM S9xSuperFXReadReg + mov ecx,dword[esp+4] + push ebx + push esi + push edi + push ebp + test dword[regptra+ecx*4-8000h], ~0 + jz .skipread + call dword[regptra+ecx*4-8000h] +.skipread: + pop ebp + pop edi + pop esi + pop ebx + and eax, 255 +endfx: + ret + +EXTSYM SCBRrel,SfxSCBR,SfxCOLR,SfxPOR +EXTSYM sfx128lineloc,sfx160lineloc,sfx192lineloc,sfxobjlineloc,sfxclineloc +EXTSYM fxbit01pcal,fxbit23pcal,fxbit45pcal,fxbit67pcal + +NEWSYM S9xSuperFXExec + test byte[SfxSFR],20h + jz endfx + + push ebx + push esi + push edi + push ebp + + xor ebx,ebx + mov bl,[SfxPBR] + mov al,[SfxSCMR] + and bl,7Fh + cmp bl,70h + jae .ram + test al,10h + jz .noaccess + jmp .noram +.ram + test al,08h + jz .noaccess +.noram + mov eax,[NumberOfOpcodes2] + mov [NumberOfOpcodes],eax + call MainLoop +.noaccess + pop ebp + pop edi + pop esi + pop edx + ret + +NEWSYM S9xSuperFXPreSaveState + mov ecx,dword[SfxCROM] + sub dword[SfxRomBuffer],ecx + mov ecx,dword[SfxRAMMem] + sub dword[SfxLastRamAdr],ecx +; Copy num2writesfxreg bytes from SfxR0 to a free area in RegRAM. + push ebx + mov ecx,SfxR0 + mov edx,dword[RegRAM] + add edx,7000h + mov ebx,[PHnum2writesfxreg] +.loop + mov al,[ecx] + mov [edx],al + inc ecx + inc edx + dec ebx + jnz .loop + pop ebx + mov ecx,dword[SfxCROM] + add dword[SfxRomBuffer],ecx + mov ecx,dword[SfxRAMMem] + add dword[SfxLastRamAdr],ecx + ret + +NEWSYM S9xSuperFXPostSaveState + ret + +NEWSYM S9xSuperFXPostLoadState +; Copy num2writesfxreg bytes from a free area in RegRAM to SfxR0 + push ebx + mov ecx,SfxR0 + mov edx,dword[RegRAM] + add edx,7000h + mov ebx,[PHnum2writesfxreg] +.loop + mov al,[edx] + mov [ecx],al + inc ecx + inc edx + dec ebx + jnz .loop + pop ebx + xor ecx,ecx + mov cl,byte[SfxPBR] + mov ecx,dword[SfxMemTable+ecx*4] + mov dword[SfxCPB],ecx + + xor ecx,ecx + mov cl,byte[SfxROMBR] + mov ecx,dword[SfxMemTable+ecx*4] + mov dword[SfxCROM],ecx + + xor ecx,ecx + mov cl,byte[SfxRAMBR] + shl ecx,16 + add ecx,dword[sfxramdata] + mov dword [SfxRAMMem],ecx + + mov ecx,dword[SfxCROM] + add dword[SfxRomBuffer],ecx + mov ecx,dword[SfxRAMMem] + add dword[SfxLastRamAdr],ecx +; Fix for mystery zeroing of SfxnRamBanks, allowing junk RAMBR values to be +; set in turn causing a crash when the code tries to access the junk RAM bank. + mov dword [SfxnRamBanks], 4 + call UpdateSFX + ret + +NEWSYM UpdatePORSCMR + push ebx + push eax + test byte[SfxPOR],10h + jnz .objmode + mov al,[SfxSCMR] + and al,00100100b ; 4 + 32 + cmp al,4 + je .lines160 + cmp al,32 + je .lines192 + cmp al,36 + je .objmode + mov eax,[sfx128lineloc] + jmp .donelines +.lines160 + mov eax,[sfx160lineloc] + jmp .donelines +.lines192 + mov eax,[sfx192lineloc] + jmp .donelines +.objmode + mov eax,[sfxobjlineloc] +.donelines + mov [sfxclineloc],eax + + mov al,[SfxSCMR] + and eax,00000011b + mov bl,[SfxPOR] + and bl,0Fh + shl bl,2 + or al,bl + mov ebx,[PLOTJmpb+eax*4] + mov eax,[PLOTJmpa+eax*4] + mov dword [FxTable+4Ch*4],eax + mov dword [FxTableb+4Ch*4],eax + mov dword [FxTablec+4Ch*4],eax + mov dword [FxTabled+4Ch*4],ebx + pop eax + pop ebx + ret + +NEWSYM UpdateSCBRCOLR + push eax + push ebx + mov ebx,[SfxSCBR] + shl ebx,10 + add ebx,[sfxramdata] + mov [SCBRrel],ebx + mov eax,[SfxCOLR] + mov ebx,[fxbit01+eax*4] + mov [fxbit01pcal],ebx + mov ebx,[fxbit23+eax*4] + mov [fxbit23pcal],ebx + mov ebx,[fxbit45+eax*4] + mov [fxbit45pcal],ebx + mov ebx,[fxbit67+eax*4] + mov [fxbit67pcal],ebx + pop ebx + pop eax + ret + +NEWSYM UpdateCLSR + mov dword [NumberOfOpcodes2],350 ; 0FFFFFFFh;350 + test byte[SfxCLSR],01h + jz .nohighsfx + mov dword [NumberOfOpcodes2],700 ;700 +.nohighsfx + cmp byte[SFXCounter],1 + je .noyi + mov dword [NumberOfOpcodes2],0FFFFFFFh +.noyi + ret + +NEWSYM UpdateSFX + call UpdatePORSCMR + call UpdatePORSCMR + call UpdateCLSR + ret diff --git a/i386/zsnesc4.asm b/i386/zsnesc4.asm new file mode 100644 index 00000000..9059b5d6 --- /dev/null +++ b/i386/zsnesc4.asm @@ -0,0 +1,92 @@ +; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. +; +; Super FX assembler emulator code +; (c) Copyright 1998, 1999 zsKnight and _Demo_. +; +; 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. +; +; ZSNES SuperFX emulation code and wrappers +; (C) Copyright 1997-8 zsKnight and _Demo_ + +; Used with the kind permission of the copyright holders. +; + +%include "macros.mac" + +EXTSYM InitC4, C4RegFunction, C4ReadReg, C4WriteReg +EXTSYM romdata + +[BITS 32] +SECTION .data + +NEWSYM C4Ram, dd 0 +NEWSYM C4RamR, dd 0 +NEWSYM C4RamW, dd 0 + +NEWSYM pressed, dd 0 ; used by C4Edit (unused function) +NEWSYM vidbuffer,dd 0 ; used by C4Edit +NEWSYM oamram, times 544 db 0 ; Sprite PPU data used by C4 routines + +; +; Snes9x wrapper functions for the zsnes C4 code +; (C) Copyright 2000 Gary Henderson + +SECTION .data + +EXTSYM ROM,RegRAM + +SECTION .text + +NEWSYM S9xInitC4 + pushad + mov eax,dword[ROM] + mov dword[romdata],eax + call InitC4 +; mov eax,dword[RegRAM] +; add eax,06000h +; mov dword[C4Ram],eax + popad + ret + +NEWSYM S9xSetC4 +NEWSYM S9xSetC4RAM + mov ecx, dword[esp+8] + mov eax, dword[esp+4] + and ecx, 0ffffh + push ebx + push esi + push edi + push ebp + sub ecx, 6000h + call C4RegFunction + pop ebp + pop edi + pop esi + pop ebx + ret + +NEWSYM S9xGetC4 +NEWSYM S9xGetC4RAM + mov ecx, dword[esp+4] + xor eax, eax + and ecx, 0ffffh + sub ecx, 06000h + jmp C4ReadReg diff --git a/jma/7z.h b/jma/7z.h new file mode 100644 index 00000000..40b92519 --- /dev/null +++ b/jma/7z.h @@ -0,0 +1,28 @@ +/* +Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com ) +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __7Z_H +#define __7Z_H + +#include "iiostrm.h" + +bool decompress_lzma_7z(ISequentialInStream& in, unsigned in_size, ISequentialOutStream& out, unsigned out_size) throw (); +bool decompress_lzma_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) throw (); + +#endif + diff --git a/jma/7zlzma.cpp b/jma/7zlzma.cpp new file mode 100644 index 00000000..ddaa395a --- /dev/null +++ b/jma/7zlzma.cpp @@ -0,0 +1,50 @@ +/* +Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com ) +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "7z.h" + +#include "lzmadec.h" + +bool decompress_lzma_7z(ISequentialInStream& in, unsigned in_size, ISequentialOutStream& out, unsigned out_size) throw () +{ + try + { + NCompress::NLZMA::CDecoder cc; + + UINT64 in_size_l = in_size; + UINT64 out_size_l = out_size; + + if (cc.ReadCoderProperties(&in) != S_OK) { return(false); } + if (cc.Code(&in, &out, &in_size_l, &out_size_l) != S_OK) { return(false); } + if (out.size_get() != out_size || out.overflow_get()) { return(false); } + + return(true); + } + catch (...) + { + return(false); + } +} + +bool decompress_lzma_7z(const unsigned char* in_data, unsigned int in_size, unsigned char* out_data, unsigned int out_size) throw () +{ + ISequentialInStream_Array in(reinterpret_cast(in_data), in_size); + ISequentialOutStream_Array out(reinterpret_cast(out_data), out_size); + + return(decompress_lzma_7z(in, in_size, out, out_size)); +} diff --git a/jma/aribitcd.h b/jma/aribitcd.h new file mode 100644 index 00000000..1fb421ba --- /dev/null +++ b/jma/aribitcd.h @@ -0,0 +1,73 @@ +#ifndef __COMPRESSION_BITCODER_H +#define __COMPRESSION_BITCODER_H + +#include "rngcoder.h" + +namespace NCompression { +namespace NArithmetic { + +const int kNumBitModelTotalBits = 11; +const UINT32 kBitModelTotal = (1 << kNumBitModelTotalBits); + +const int kNumMoveReducingBits = 2; + +///////////////////////////// +// CBitModel + +template +class CBitModel +{ +public: + UINT32 m_Probability; + void UpdateModel(UINT32 aSymbol) + { + /* + m_Probability -= (m_Probability + ((aSymbol - 1) & ((1 << aNumMoveBits) - 1))) >> aNumMoveBits; + m_Probability += (1 - aSymbol) << (kNumBitModelTotalBits - aNumMoveBits); + */ + if (aSymbol == 0) + m_Probability += (kBitModelTotal - m_Probability) >> aNumMoveBits; + else + m_Probability -= (m_Probability) >> aNumMoveBits; + } +public: + void Init() { m_Probability = kBitModelTotal / 2; } +}; + +template +class CBitDecoder: public CBitModel +{ +public: + UINT32 Decode(CRangeDecoder *aRangeDecoder) + { + UINT32 aNewBound = (aRangeDecoder->m_Range >> kNumBitModelTotalBits) * CBitModel::m_Probability; + if (aRangeDecoder->m_Code < aNewBound) + { + aRangeDecoder->m_Range = aNewBound; + CBitModel::m_Probability += (kBitModelTotal - CBitModel::m_Probability) >> aNumMoveBits; + if (aRangeDecoder->m_Range < kTopValue) + { + aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | aRangeDecoder->m_Stream.ReadByte(); + aRangeDecoder->m_Range <<= 8; + } + return 0; + } + else + { + aRangeDecoder->m_Range -= aNewBound; + aRangeDecoder->m_Code -= aNewBound; + CBitModel::m_Probability -= (CBitModel::m_Probability) >> aNumMoveBits; + if (aRangeDecoder->m_Range < kTopValue) + { + aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | aRangeDecoder->m_Stream.ReadByte(); + aRangeDecoder->m_Range <<= 8; + } + return 1; + } + } +}; + +}} + + +#endif diff --git a/jma/ariconst.h b/jma/ariconst.h new file mode 100644 index 00000000..751b2b7c --- /dev/null +++ b/jma/ariconst.h @@ -0,0 +1,29 @@ +/* +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __ARICONST_H +#define __ARICONST_H + +#include "aribitcd.h" + + +typedef NCompression::NArithmetic::CRangeDecoder CMyRangeDecoder; +template class CMyBitDecoder: + public NCompression::NArithmetic::CBitDecoder {}; + +#endif diff --git a/jma/ariprice.h b/jma/ariprice.h new file mode 100644 index 00000000..ccc398e1 --- /dev/null +++ b/jma/ariprice.h @@ -0,0 +1,12 @@ +#ifndef __COMPRESSION_ARIPRICE_H +#define __COMPRESSION_ARIPRICE_H + +namespace NCompression { +namespace NArithmetic { + +const UINT32 kNumBitPriceShiftBits = 6; +const UINT32 kBitPrice = 1 << kNumBitPriceShiftBits; + +}} + +#endif diff --git a/jma/btreecd.h b/jma/btreecd.h new file mode 100644 index 00000000..acce3664 --- /dev/null +++ b/jma/btreecd.h @@ -0,0 +1,126 @@ +/* +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __BITTREECODER_H +#define __BITTREECODER_H + +#include "aribitcd.h" +#include "rcdefs.h" + + +////////////////////////// +// CBitTreeDecoder + +template +class CBitTreeDecoder +{ + CMyBitDecoder m_Models[1 << m_NumBitLevels]; +public: + void Init() + { + for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++) + m_Models[i].Init(); + } + UINT32 Decode(CMyRangeDecoder *aRangeDecoder) + { + UINT32 aModelIndex = 1; + RC_INIT_VAR + for(UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0; aBitIndex--) + { + // aModelIndex = (aModelIndex << 1) + m_Models[aModelIndex].Decode(aRangeDecoder); + RC_GETBIT(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex) + } + RC_FLUSH_VAR + return aModelIndex - (1 << m_NumBitLevels); + }; +}; + +//////////////////////////////// +// CReverseBitTreeDecoder + +template +class CReverseBitTreeDecoder2 +{ + CMyBitDecoder *m_Models; + UINT32 m_NumBitLevels; +public: + CReverseBitTreeDecoder2(): m_Models(0) { } + ~CReverseBitTreeDecoder2() { delete []m_Models; } + bool Create(UINT32 aNumBitLevels) + { + m_NumBitLevels = aNumBitLevels; + m_Models = new CMyBitDecoder[1 << aNumBitLevels]; + return (m_Models != 0); + } + void Init() + { + UINT32 aNumModels = 1 << m_NumBitLevels; + for(UINT32 i = 1; i < aNumModels; i++) + m_Models[i].Init(); + } + UINT32 Decode(CMyRangeDecoder *aRangeDecoder) + { + UINT32 aModelIndex = 1; + UINT32 aSymbol = 0; + RC_INIT_VAR + for(UINT32 aBitIndex = 0; aBitIndex < m_NumBitLevels; aBitIndex++) + { + // UINT32 aBit = m_Models[aModelIndex].Decode(aRangeDecoder); + // aModelIndex <<= 1; + // aModelIndex += aBit; + // aSymbol |= (aBit << aBitIndex); + RC_GETBIT2(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex, ; , aSymbol |= (1 << aBitIndex)) + } + RC_FLUSH_VAR + return aSymbol; + }; +}; +//////////////////////////// +// CReverseBitTreeDecoder2 + +template +class CReverseBitTreeDecoder +{ + CMyBitDecoder m_Models[1 << m_NumBitLevels]; +public: + void Init() + { + for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++) + m_Models[i].Init(); + } + UINT32 Decode(CMyRangeDecoder *aRangeDecoder) + { + UINT32 aModelIndex = 1; + UINT32 aSymbol = 0; + RC_INIT_VAR + for(UINT32 aBitIndex = 0; aBitIndex < m_NumBitLevels; aBitIndex++) + { + // UINT32 aBit = m_Models[aModelIndex].Decode(aRangeDecoder); + // aModelIndex <<= 1; + // aModelIndex += aBit; + // aSymbol |= (aBit << aBitIndex); + RC_GETBIT2(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex, ; , aSymbol |= (1 << aBitIndex)) + } + RC_FLUSH_VAR + return aSymbol; + } +}; + + + +#endif diff --git a/jma/crc32.cpp b/jma/crc32.cpp new file mode 100644 index 00000000..3265f915 --- /dev/null +++ b/jma/crc32.cpp @@ -0,0 +1,81 @@ +/* +Copyright (C) 2004-2006 NSRT Team ( http://nsrt.edgeemu.com ) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include "crc32.h" + +namespace CRC32lib +{ + //Don't ask questions, this is the PKZip CRC32 table + const unsigned int 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 + unsigned int CRC32(const unsigned char *array, size_t size, register unsigned int crc32) + { + const unsigned char *end_p = array+size; + for (register const unsigned char *p = array; p < end_p; p++) + { + crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ *p) & 0xFF]; + } + + return(~crc32); + } +} diff --git a/jma/crc32.h b/jma/crc32.h new file mode 100644 index 00000000..c2e72c68 --- /dev/null +++ b/jma/crc32.h @@ -0,0 +1,26 @@ +/* +Copyright (C) 2004-2006 NSRT Team ( http://nsrt.edgeemu.com ) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef CRC32_H +#define CRC32_H + +namespace CRC32lib +{ + unsigned int CRC32(const unsigned char *, size_t, register unsigned int crc32 = 0xFFFFFFFF); +} + +#endif diff --git a/jma/iiostrm.cpp b/jma/iiostrm.cpp new file mode 100644 index 00000000..0d27b9c1 --- /dev/null +++ b/jma/iiostrm.cpp @@ -0,0 +1,132 @@ +/* +Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com ) +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "portable.h" +#include "iiostrm.h" +#include "crc32.h" + +HRESULT ISequentialInStream_Array::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + if (aSize > size) + { + aSize = size; + } + + *aProcessedSize = aSize; + memcpy(aData, data, aSize); + size -= aSize; + data += aSize; + return(S_OK); +} + +HRESULT ISequentialOutStream_Array::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + if (aSize > size) + { + overflow = true; + aSize = size; + } + + *aProcessedSize = aSize; + memcpy(data, aData, aSize); + size -= aSize; + data += aSize; + total += aSize; + return(S_OK); +} + +HRESULT ISequentialInStream_String::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + if (aSize > data.size()) + { + aSize = data.size(); + } + + *aProcessedSize = aSize; + memcpy(aData, data.c_str(), aSize); + data.erase(0, aSize); + return(S_OK); +} + +HRESULT ISequentialOutStream_String::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + *aProcessedSize = aSize; + data.append((const char *)aData, aSize); + total += aSize; + return(S_OK); +} + +HRESULT ISequentialInStream_Istream::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + data.read((char *)aData, aSize); + *aProcessedSize = data.gcount(); + return(S_OK); +} + +HRESULT ISequentialOutStream_Ostream::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + *aProcessedSize = aSize; + data.write((char *)aData, aSize); + total += aSize; + return(S_OK); +} + + + +HRESULT ISequentialInStreamCRC32_Array::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + ISequentialInStream_Array::Read(aData, aSize, aProcessedSize); + crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); + return(S_OK); +} + +HRESULT ISequentialOutStreamCRC32_Array::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + ISequentialOutStream_Array::Write(aData, aSize, aProcessedSize); + crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); + return(S_OK); +} + +HRESULT ISequentialInStreamCRC32_String::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + ISequentialInStream_String::Read(aData, aSize, aProcessedSize); + crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); + return(S_OK); +} + +HRESULT ISequentialOutStreamCRC32_String::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + ISequentialOutStream_String::Write(aData, aSize, aProcessedSize); + crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); + return(S_OK); +} + +HRESULT ISequentialInStreamCRC32_Istream::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + ISequentialInStream_Istream::Read(aData, aSize, aProcessedSize); + crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); + return(S_OK); +} + +HRESULT ISequentialOutStreamCRC32_Ostream::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) +{ + ISequentialOutStream_Ostream::Write(aData, aSize, aProcessedSize); + crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); + return(S_OK); +} diff --git a/jma/iiostrm.h b/jma/iiostrm.h new file mode 100644 index 00000000..bef0f003 --- /dev/null +++ b/jma/iiostrm.h @@ -0,0 +1,210 @@ +/* +Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com ) +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __IINOUTSTREAMS_H +#define __IINOUTSTREAMS_H + +#include +#include + +#include "portable.h" + + +class ISequentialInStream +{ +public: + virtual HRESULT Read(void *, UINT32, UINT32 *) = 0; + + virtual ~ISequentialInStream() {} +}; + + +class ISequentialInStream_Array : public ISequentialInStream +{ + const char *data; + unsigned int size; +public: + ISequentialInStream_Array(const char *Adata, unsigned Asize) : data(Adata), size(Asize) { } + + HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialInStream_Array() {} +}; + +class ISequentialInStream_String : public ISequentialInStream +{ + std::string& data; +public: + ISequentialInStream_String(std::string& Adata) : data(Adata) { } + + HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialInStream_String() {} +}; + +class ISequentialInStream_Istream : public ISequentialInStream +{ + std::istream& data; +public: + ISequentialInStream_Istream(std::istream& Adata) : data(Adata) { } + + HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialInStream_Istream() {} +}; + + + +class ISequentialOutStream +{ +public: + virtual bool overflow_get() const = 0; + virtual unsigned int size_get() const = 0; + + virtual HRESULT Write(const void *, UINT32, UINT32 *) = 0; + + virtual ~ISequentialOutStream() {} +}; + + +class ISequentialOutStream_Array : public ISequentialOutStream +{ + char *data; + unsigned int size; + bool overflow; + unsigned int total; +public: + ISequentialOutStream_Array(char *Adata, unsigned Asize) : data(Adata), size(Asize), overflow(false), total(0) { } + + bool overflow_get() const { return(overflow); } + unsigned int size_get() const { return(total); } + + HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialOutStream_Array() {} +}; + +class ISequentialOutStream_String : public ISequentialOutStream +{ + std::string& data; + unsigned int total; +public: + ISequentialOutStream_String(std::string& Adata) : data(Adata), total(0) { } + + bool overflow_get() const { return(false); } + unsigned int size_get() const { return(total); } + + HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialOutStream_String() {} +}; + + +class ISequentialOutStream_Ostream : public ISequentialOutStream +{ + std::ostream& data; + unsigned int total; +public: + ISequentialOutStream_Ostream(std::ostream& Adata) : data(Adata), total(0) { } + + bool overflow_get() const { return(false); } + unsigned int size_get() const { return(total); } + + HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialOutStream_Ostream() {} +}; + + + +class ISequentialStreamCRC32 +{ +protected: + unsigned int crc32; +public: + ISequentialStreamCRC32() : crc32(0) {} + unsigned int crc32_get() const { return(crc32); } + + virtual ~ISequentialStreamCRC32() {} +}; + + +class ISequentialInStreamCRC32_Array : public ISequentialInStream_Array, public ISequentialStreamCRC32 +{ +public: + ISequentialInStreamCRC32_Array(const char *Adata, unsigned Asize) : ISequentialInStream_Array(Adata, Asize) { } + + HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialInStreamCRC32_Array() {} +}; + +class ISequentialInStreamCRC32_String : public ISequentialInStream_String, public ISequentialStreamCRC32 +{ +public: + ISequentialInStreamCRC32_String(std::string& Adata) : ISequentialInStream_String(Adata) { } + + HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialInStreamCRC32_String() {} +}; + +class ISequentialInStreamCRC32_Istream : public ISequentialInStream_Istream, public ISequentialStreamCRC32 +{ +public: + ISequentialInStreamCRC32_Istream(std::istream& Adata) : ISequentialInStream_Istream(Adata) { } + + HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialInStreamCRC32_Istream() {} +}; + + +class ISequentialOutStreamCRC32_Array : public ISequentialOutStream_Array, public ISequentialStreamCRC32 +{ +public: + ISequentialOutStreamCRC32_Array(char *Adata, unsigned Asize) : ISequentialOutStream_Array(Adata, Asize) { } + + HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialOutStreamCRC32_Array() {} +}; + +class ISequentialOutStreamCRC32_String : public ISequentialOutStream_String, public ISequentialStreamCRC32 +{ +public: + ISequentialOutStreamCRC32_String(std::string& Adata) : ISequentialOutStream_String(Adata) { } + + HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialOutStreamCRC32_String() {} +}; + + +class ISequentialOutStreamCRC32_Ostream : public ISequentialOutStream_Ostream, public ISequentialStreamCRC32 +{ +public: + ISequentialOutStreamCRC32_Ostream(std::ostream& Adata) : ISequentialOutStream_Ostream(Adata) { } + + HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); + + virtual ~ISequentialOutStreamCRC32_Ostream() {} +}; + +#endif diff --git a/jma/inbyte.cpp b/jma/inbyte.cpp new file mode 100644 index 00000000..d4bc3894 --- /dev/null +++ b/jma/inbyte.cpp @@ -0,0 +1,60 @@ +/* +Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com ) +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "inbyte.h" + +namespace NStream{ + +CInByte::CInByte(UINT32 aBufferSize): + m_BufferBase(0), + m_BufferSize(aBufferSize) +{ + m_BufferBase = new BYTE[m_BufferSize]; +} + +CInByte::~CInByte() +{ + delete []m_BufferBase; +} + +void CInByte::Init(ISequentialInStream *aStream) +{ + m_Stream = aStream; + m_ProcessedSize = 0; + m_Buffer = m_BufferBase; + m_BufferLimit = m_Buffer; + m_StreamWasExhausted = false; +} + +bool CInByte::ReadBlock() +{ + if (m_StreamWasExhausted) + return false; + m_ProcessedSize += (m_Buffer - m_BufferBase); + UINT32 aNumProcessedBytes; + HRESULT aResult = m_Stream->Read(m_BufferBase, m_BufferSize, &aNumProcessedBytes); + if (aResult != S_OK) + throw aResult; + m_Buffer = m_BufferBase; + m_BufferLimit = m_Buffer + aNumProcessedBytes; + m_StreamWasExhausted = (aNumProcessedBytes == 0); + return (!m_StreamWasExhausted); +} + +} diff --git a/jma/inbyte.h b/jma/inbyte.h new file mode 100644 index 00000000..53afa171 --- /dev/null +++ b/jma/inbyte.h @@ -0,0 +1,76 @@ +/* +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __STREAM_INBYTE_H +#define __STREAM_INBYTE_H + +#include "iiostrm.h" + +namespace NStream { + +class CInByte +{ + UINT64 m_ProcessedSize; + BYTE *m_BufferBase; + UINT32 m_BufferSize; + BYTE *m_Buffer; + BYTE *m_BufferLimit; + ISequentialInStream* m_Stream; + bool m_StreamWasExhausted; + + bool ReadBlock(); + +public: + CInByte(UINT32 aBufferSize = 0x100000); + ~CInByte(); + + void Init(ISequentialInStream *aStream); + + bool ReadByte(BYTE &aByte) + { + if(m_Buffer >= m_BufferLimit) + if(!ReadBlock()) + return false; + aByte = *m_Buffer++; + return true; + } + BYTE ReadByte() + { + if(m_Buffer >= m_BufferLimit) + if(!ReadBlock()) + return 0x0; + return *m_Buffer++; + } + void ReadBytes(void *aData, UINT32 aSize, UINT32 &aProcessedSize) + { + for(aProcessedSize = 0; aProcessedSize < aSize; aProcessedSize++) + if (!ReadByte(((BYTE *)aData)[aProcessedSize])) + return; + } + bool ReadBytes(void *aData, UINT32 aSize) + { + UINT32 aProcessedSize; + ReadBytes(aData, aSize, aProcessedSize); + return (aProcessedSize == aSize); + } + UINT64 GetProcessedSize() const { return m_ProcessedSize + (m_Buffer - m_BufferBase); } +}; + +} + +#endif diff --git a/jma/jma.cpp b/jma/jma.cpp new file mode 100644 index 00000000..df7ea862 --- /dev/null +++ b/jma/jma.cpp @@ -0,0 +1,550 @@ +/* +Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com ) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include "jma.h" +using namespace std; + +#include "portable.h" +#include "7z.h" +#include "crc32.h" + +namespace JMA +{ + const char jma_magic[] = { 'J', 'M', 'A', 0, 'N' }; + const unsigned int jma_header_length = 5; + const unsigned char jma_version = 1; + const unsigned int jma_version_length = 1; + const unsigned int jma_total_header_length = jma_header_length + jma_version_length + UINT_SIZE; + + //Convert DOS/zip/JMA integer time to to time_t + time_t uint_to_time(unsigned short date, unsigned short time) + { + tm formatted_time; + + formatted_time.tm_mday = date & 0x1F; + formatted_time.tm_mon = ((date >> 5) & 0xF) - 1; + formatted_time.tm_year = ((date >> 9) & 0x7f) + 80; + formatted_time.tm_sec = (time & 0x1F) * 2; + formatted_time.tm_min = (time >> 5) & 0x3F; + formatted_time.tm_hour = (time >> 11) & 0x1F; + + return(mktime(&formatted_time)); + } + + + //Retreive the file block, what else? + void jma_open::retrieve_file_block() throw(jma_errors) + { + unsigned char uint_buffer[UINT_SIZE]; + unsigned char ushort_buffer[USHORT_SIZE]; + + //File block size is the last UINT in the file + stream.seekg(-UINT_SIZE,ios::end); + stream.read((char *)uint_buffer, UINT_SIZE); + size_t file_block_size = charp_to_uint(uint_buffer); + + //Currently at the end of the file, so that's the file size + size_t jma_file_size = (size_t) stream.tellg(); + + //The file block can't be larger than the JMA file without it's header. + //This if can probably be improved + if (file_block_size >= jma_file_size-jma_total_header_length) + { + throw(JMA_BAD_FILE); + } + + //Seek to before file block so we can read the file block + stream.seekg(-((int)file_block_size+UINT_SIZE),ios::end); + + //This is needed if the file block is compressed + stringstream decompressed_file_block; + //Pointer to where to read file block from (file or decompressed buffer) + istream *file_block_stream; + + //Setup file info buffer and byte to read with + jma_file_info file_info; + char byte; + + stream.get(byte); + if (!byte) //If file block is compressed + { + //Compressed size isn't counting the byte we just read or the UINT for compressed size + size_t compressed_size = file_block_size - (1+UINT_SIZE); + + //Read decompressed size / true file block size + stream.read((char *)uint_buffer, UINT_SIZE); + file_block_size = charp_to_uint(uint_buffer); + + //Setup access methods for decompression + ISequentialInStream_Istream compressed_data(stream); + ISequentialOutStream_Ostream decompressed_data(decompressed_file_block); + + //Decompress the data + if (!decompress_lzma_7z(compressed_data, compressed_size, decompressed_data, file_block_size)) + { + throw(JMA_DECOMPRESS_FAILED); + } + + //Go to beginning, setup pointer to buffer + decompressed_file_block.seekg(0, ios::beg); + file_block_stream = &decompressed_file_block; + } + else + { + stream.putback(byte); //Putback byte, byte is part of filename, not compressed indicator + file_block_stream = &stream; + } + + + //Minimum file name length is 2 bytes, a char and a null + //Minimum comment length is 1 byte, a null + //There are currently 2 UINTs and 2 USHORTs per file + while (file_block_size >= 2+1+UINT_SIZE*2+USHORT_SIZE*2) //This does allow for a gap, but that's okay + { + //First stored in the file block is the file name null terminated + file_info.name = ""; + + file_block_stream->get(byte); + while (byte) + { + file_info.name += byte; + file_block_stream->get(byte); + } + + //There must be a file name or the file is bad + if (!file_info.name.length()) + { + throw(JMA_BAD_FILE); + } + + //Same trick as above for the comment + file_info.comment = ""; + + file_block_stream->get(byte); + while (byte) + { + file_info.comment += byte; + file_block_stream->get(byte); + } + + //Next is a UINT representing the file's size + file_block_stream->read((char *)uint_buffer, UINT_SIZE); + file_info.size = charp_to_uint(uint_buffer); + + //Followed by CRC32 + file_block_stream->read((char *)uint_buffer, UINT_SIZE); + file_info.crc32 = charp_to_uint(uint_buffer); + + //Special USHORT representation of file's date + file_block_stream->read((char *)ushort_buffer, USHORT_SIZE); + file_info.date = charp_to_ushort(ushort_buffer); + + //Special USHORT representation of file's time + file_block_stream->read((char *)ushort_buffer, USHORT_SIZE); + file_info.time = charp_to_ushort(ushort_buffer); + + file_info.buffer = 0; //Pointing to null till we decompress files + + files.push_back(file_info); //Put file info into our structure + + //Subtract size of the file info we just read + file_block_size -= file_info.name.length()+file_info.comment.length()+2+UINT_SIZE*2+USHORT_SIZE*2; + } + } + + //Constructor for opening JMA files for reading + jma_open::jma_open(const char *compressed_file_name) throw (jma_errors) + { + decompressed_buffer = 0; + compressed_buffer = 0; + + stream.open(compressed_file_name, ios::in | ios::binary); + if (!stream.is_open()) + { + throw(JMA_NO_OPEN); + } + + //Header is "JMA\0N" + unsigned char header[jma_header_length]; + stream.read((char *)header, jma_header_length); + if (memcmp(jma_magic, header, jma_header_length)) + { + throw(JMA_BAD_FILE); + } + + //Not the cleanest code but logical + stream.read((char *)header, 5); + if (*header <= jma_version) + { + chunk_size = charp_to_uint(header+1); //Chunk size is a UINT that follows version # + retrieve_file_block(); + } + else + { + throw(JMA_UNSUPPORTED_VERSION); + } + } + + //Destructor only has to close the stream if neccesary + jma_open::~jma_open() + { + if (stream.is_open()) + { + stream.close(); + } + } + + //Return a vector containing useful info about the files in the JMA + vector jma_open::get_files_info() + { + vector file_info_vector; + jma_public_file_info file_info; + + for (vector::iterator i = files.begin(); i != files.end(); i++) + { + file_info.name = i->name; + file_info.comment = i->comment; + file_info.size = i->size; + file_info.datetime = uint_to_time(i->date, i->time); + file_info.crc32 = i->crc32; + file_info_vector.push_back(file_info); + } + + return(file_info_vector); + } + + //Skip forward a given number of chunks + void jma_open::chunk_seek(unsigned int chunk_num) throw(jma_errors) + { + //Check the stream is open + if (!stream.is_open()) + { + throw(JMA_NO_OPEN); + } + + //Clear possible errors so the seek will work + stream.clear(); + + //Move forward over header + stream.seekg(jma_total_header_length, ios::beg); + + unsigned char int4_buffer[UINT_SIZE]; + + while (chunk_num--) + { + //Read in size of chunk + stream.read((char *)int4_buffer, UINT_SIZE); + + //Skip chunk plus it's CRC32 + stream.seekg(charp_to_uint(int4_buffer)+UINT_SIZE, ios::cur); + } + } + + //Return a vector of pointers to each file in the JMA, the buffer to hold all the files + //must be initilized outside. + vector jma_open::get_all_files(unsigned char *buffer) throw(jma_errors) + { + //If there's no stream we can't read from it, so exit + if (!stream.is_open()) + { + throw(JMA_NO_OPEN); + } + + //Seek to the first chunk + chunk_seek(0); + + //Set the buffer that decompressed data goes to + decompressed_buffer = buffer; + + //If the JMA is not solid + if (chunk_size) + { + unsigned char int4_buffer[UINT_SIZE]; + size_t size = get_total_size(files); + + //For each chunk in the file... + for (size_t remaining_size = size; remaining_size; remaining_size -= chunk_size) + { + //Read the compressed size + stream.read((char *)int4_buffer, UINT_SIZE); + size_t compressed_size = charp_to_uint(int4_buffer); + + //Allocate memory of the correct size to hold the compressed data in the JMA + //Throw error on failure as that is unrecoverable from + try + { + compressed_buffer = new unsigned char[compressed_size]; + } + catch (bad_alloc xa) + { + throw(JMA_NO_MEM_ALLOC); + } + + //Read all the compressed data in + stream.read((char *)compressed_buffer, compressed_size); + + //Read the expected CRC of compressed data from the file + stream.read((char *)int4_buffer, UINT_SIZE); + + //If it doesn't match, throw error and cleanup memory + if (CRC32lib::CRC32(compressed_buffer, compressed_size) != charp_to_uint(int4_buffer)) + { + delete[] compressed_buffer; + throw(JMA_BAD_FILE); + } + + //Decompress the data, cleanup memory on failure + if (!decompress_lzma_7z(compressed_buffer, compressed_size, + decompressed_buffer+size-remaining_size, + (remaining_size > chunk_size) ? chunk_size : remaining_size)) + { + delete[] compressed_buffer; + throw(JMA_DECOMPRESS_FAILED); + } + delete[] compressed_buffer; + + if (remaining_size <= chunk_size) //If we just decompressed the remainder + { + break; + } + } + } + else //Solidly compressed JMA + { + unsigned char int4_buffer[UINT_SIZE]; + + //Read the size of the compressed data + stream.read((char *)int4_buffer, UINT_SIZE); + size_t compressed_size = charp_to_uint(int4_buffer); + + //Get decompressed size + size_t size = get_total_size(files); + + //Setup access methods for decompression + ISequentialInStream_Istream compressed_data(stream); + ISequentialOutStream_Array decompressed_data(reinterpret_cast(decompressed_buffer), size); + + //Decompress the data + if (!decompress_lzma_7z(compressed_data, compressed_size, decompressed_data, size)) + { + throw(JMA_DECOMPRESS_FAILED); + } + + /* + //Allocate memory of the right size to hold the compressed data in the JMA + try + { + compressed_buffer = new unsigned char[compressed_size]; + } + catch (bad_alloc xa) + { + throw(JMA_NO_MEM_ALLOC); + } + + //Copy the compressed data into memory + stream.read((char *)compressed_buffer, compressed_size); + size_t size = get_total_size(files); + + //Read the CRC of the compressed data + stream.read((char *)int4_buffer, UINT_SIZE); + + //If it doesn't match, complain + if (CRC32lib::CRC32(compressed_buffer, compressed_size) != charp_to_uint(int4_buffer)) + { + delete[] compressed_buffer; + throw(JMA_BAD_FILE); + } + + //Decompress the data + if (!decompress_lzma_7z(compressed_buffer, compressed_size, decompressed_buffer, size)) + { + delete[] compressed_buffer; + throw(JMA_DECOMPRESS_FAILED); + } + delete[] compressed_buffer; + */ + } + + vector file_pointers; + size_t size = 0; + + //For each file, add it's pointer to the vector, size is pointer offset in the buffer + for (vector::iterator i = files.begin(); i != files.end(); i++) + { + i->buffer = decompressed_buffer+size; + file_pointers.push_back(decompressed_buffer+size); + size += i->size; + } + + //Return the vector of pointers + return(file_pointers); + } + + //Extracts the file with a given name found in the archive to the given buffer + void jma_open::extract_file(string& name, unsigned char *buffer) throw(jma_errors) + { + if (!stream.is_open()) + { + throw(JMA_NO_OPEN); + } + + size_t size_to_skip = 0; + size_t our_file_size = 0; + + //Search through the vector of file information + for (vector::iterator i = files.begin(); i != files.end(); i++) + { + if (i->name == name) + { + //Set the variable so we can tell we found it + our_file_size = i->size; + break; + } + + //Keep a running total of size + size_to_skip += i->size; + } + + if (!our_file_size) //File with the specified name was not found in the archive + { + throw(JMA_FILE_NOT_FOUND); + } + + //If the JMA only contains one file, we can skip a lot of overhead + if (files.size() == 1) + { + get_all_files(buffer); + return; + } + + if (chunk_size) //we are using non-solid archive.. + { + unsigned int chunks_to_skip = size_to_skip / chunk_size; + + //skip over requisite number of chunks + chunk_seek(chunks_to_skip); + + //Allocate memory for compressed and decompressed data + unsigned char *comp_buffer = 0, *decomp_buffer = 0; + try + { + //Compressed data size is <= non compressed size + unsigned char *combined_buffer = new unsigned char[chunk_size*2]; + comp_buffer = combined_buffer; + decomp_buffer = combined_buffer+chunk_size; + } + catch (bad_alloc xa) + { + throw(JMA_NO_MEM_ALLOC); + } + + size_t first_chunk_offset = size_to_skip % chunk_size; + unsigned char int4_buffer[UINT_SIZE]; + for (size_t i = 0; i < our_file_size;) + { + //Get size + stream.read((char *)int4_buffer, UINT_SIZE); + size_t compressed_size = charp_to_uint(int4_buffer); + + //Read all the compressed data in + stream.read((char *)comp_buffer, compressed_size); + + //Read the CRC of the compressed data + stream.read((char *)int4_buffer, UINT_SIZE); + + //If it doesn't match, complain + if (CRC32lib::CRC32(comp_buffer, compressed_size) != charp_to_uint(int4_buffer)) + { + delete[] comp_buffer; + throw(JMA_BAD_FILE); + } + + //Decompress chunk + if (!decompress_lzma_7z(comp_buffer, compressed_size, decomp_buffer, chunk_size)) + { + delete[] comp_buffer; + throw(JMA_DECOMPRESS_FAILED); + } + + size_t copy_amount = our_file_size-i > chunk_size-first_chunk_offset ? chunk_size-first_chunk_offset : our_file_size-i; + + memcpy(buffer+i, decomp_buffer+first_chunk_offset, copy_amount); + first_chunk_offset = 0; //Set to zero since this is only for the first iteration + i += copy_amount; + } + delete[] comp_buffer; + } + else //Solid JMA + { + unsigned char *decomp_buffer = 0; + try + { + decomp_buffer = new unsigned char[get_total_size(files)]; + } + catch (bad_alloc xa) + { + throw(JMA_NO_MEM_ALLOC); + } + + get_all_files(decomp_buffer); + + memcpy(buffer, decomp_buffer+size_to_skip, our_file_size); + + delete[] decomp_buffer; + } + } + + bool jma_open::is_solid() + { + return(chunk_size ? false : true); + } + + const char *jma_error_text(jma_errors error) + { + switch (error) + { + case JMA_NO_CREATE: + return("JMA could not be created"); + + case JMA_NO_MEM_ALLOC: + return("Memory for JMA could be allocated"); + + case JMA_NO_OPEN: + return("JMA could not be opened"); + + case JMA_BAD_FILE: + return("Invalid/Corrupt JMA"); + + case JMA_UNSUPPORTED_VERSION: + return("JMA version not supported"); + + case JMA_COMPRESS_FAILED: + return("JMA compression failed"); + + case JMA_DECOMPRESS_FAILED: + return("JMA decompression failed"); + + case JMA_FILE_NOT_FOUND: + return("File not found in JMA"); + } + return("Unknown error"); + } + +} + + diff --git a/jma/jma.h b/jma/jma.h new file mode 100644 index 00000000..7e9b0fda --- /dev/null +++ b/jma/jma.h @@ -0,0 +1,89 @@ +/* +Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com ) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef JMA_H +#define JMA_H + +#include +#include +#include +#include + +namespace JMA +{ + enum jma_errors { JMA_NO_CREATE, JMA_NO_MEM_ALLOC, JMA_NO_OPEN, JMA_BAD_FILE, + JMA_UNSUPPORTED_VERSION, JMA_COMPRESS_FAILED, JMA_DECOMPRESS_FAILED, + JMA_FILE_NOT_FOUND }; + + struct jma_file_info_base + { + std::string name; + std::string comment; + size_t size; + unsigned int crc32; + }; + + struct jma_public_file_info : jma_file_info_base + { + time_t datetime; + }; + + struct jma_file_info : jma_file_info_base + { + unsigned short date; + unsigned short time; + const unsigned char *buffer; + }; + + template + inline size_t get_total_size(std::vector& files) + { + size_t size = 0; + for (typename std::vector::iterator i = files.begin(); i != files.end(); i++) + { + size += i->size; //We do have a problem if this wraps around + } + + return(size); + } + + class jma_open + { + public: + jma_open(const char *) throw(jma_errors); + ~jma_open(); + + std::vector get_files_info(); + std::vector get_all_files(unsigned char *) throw(jma_errors); + void extract_file(std::string& name, unsigned char *) throw(jma_errors); + bool is_solid(); + + private: + std::ifstream stream; + std::vector files; + size_t chunk_size; + unsigned char *decompressed_buffer; + unsigned char *compressed_buffer; + + void chunk_seek(unsigned int) throw(jma_errors); + void retrieve_file_block() throw(jma_errors); + }; + + time_t uint_to_time(unsigned short, unsigned short); + const char *jma_error_text(jma_errors); +} +#endif diff --git a/jma/lencoder.h b/jma/lencoder.h new file mode 100644 index 00000000..33051ee4 --- /dev/null +++ b/jma/lencoder.h @@ -0,0 +1,93 @@ +/* +Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com ) +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LENCODER_H +#define __LENCODER_H + +#include "btreecd.h" + +namespace NLength { + +const UINT32 kNumPosStatesBitsMax = 4; +const int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + + +const int kNumPosStatesBitsEncodingMax = 4; +const int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + + +const int kNumMoveBits = 5; + +const int kNumLenBits = 3; +const int kNumLowSymbols = 1 << kNumLenBits; +const int kNumMidBits = 3; +const int kNumMidSymbols = 1 << kNumMidBits; + +const int kNumHighBits = 8; + +const int kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); + +const int kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; + +class CDecoder +{ + CMyBitDecoder m_Choice; + CBitTreeDecoder m_LowCoder[kNumPosStatesMax]; + CMyBitDecoder m_Choice2; + CBitTreeDecoder m_MidCoder[kNumPosStatesMax]; + CBitTreeDecoder m_HighCoder; + UINT32 m_NumPosStates; +public: + void Create(UINT32 aNumPosStates) + { m_NumPosStates = aNumPosStates; } + void Init() + { + m_Choice.Init(); + for (UINT32 aPosState = 0; aPosState < m_NumPosStates; aPosState++) + { + m_LowCoder[aPosState].Init(); + m_MidCoder[aPosState].Init(); + } + m_Choice2.Init(); + m_HighCoder.Init(); + } + UINT32 Decode(CMyRangeDecoder *aRangeDecoder, UINT32 aPosState) + { + if(m_Choice.Decode(aRangeDecoder) == 0) + return m_LowCoder[aPosState].Decode(aRangeDecoder); + else + { + UINT32 aSymbol = kNumLowSymbols; + if(m_Choice2.Decode(aRangeDecoder) == 0) + aSymbol += m_MidCoder[aPosState].Decode(aRangeDecoder); + else + { + aSymbol += kNumMidSymbols; + aSymbol += m_HighCoder.Decode(aRangeDecoder); + } + return aSymbol; + } + } + +}; + +} + + +#endif diff --git a/jma/license.txt b/jma/license.txt new file mode 100644 index 00000000..e59ec7a3 --- /dev/null +++ b/jma/license.txt @@ -0,0 +1,7 @@ +Some of the code in this directory is under the LGPL v2. + +Other bits of the code is under GPL v2. +The authors of the GPL portions have granted an exception to Snes9x (but not to Snes9x derivitives) +to use their code. + +s9x-jma.h and s9x-jma.cpp are under Snes9x license. diff --git a/jma/litcoder.h b/jma/litcoder.h new file mode 100644 index 00000000..639d6c55 --- /dev/null +++ b/jma/litcoder.h @@ -0,0 +1,122 @@ +/* +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LITERALCODER_H +#define __LITERALCODER_H + +#include "aribitcd.h" +#include "rcdefs.h" + +namespace NLiteral { + +const int kNumMoveBits = 5; + +class CDecoder2 +{ + CMyBitDecoder m_Decoders[3][1 << 8]; +public: + void Init() + { + for (int i = 0; i < 3; i++) + for (int j = 1; j < (1 << 8); j++) + m_Decoders[i][j].Init(); + } + + BYTE DecodeNormal(CMyRangeDecoder *aRangeDecoder) + { + UINT32 aSymbol = 1; + RC_INIT_VAR + do + { + // aSymbol = (aSymbol << 1) | m_Decoders[0][aSymbol].Decode(aRangeDecoder); + RC_GETBIT(kNumMoveBits, m_Decoders[0][aSymbol].m_Probability, aSymbol) + } + while (aSymbol < 0x100); + RC_FLUSH_VAR + return aSymbol; + } + + BYTE DecodeWithMatchByte(CMyRangeDecoder *aRangeDecoder, BYTE aMatchByte) + { + UINT32 aSymbol = 1; + RC_INIT_VAR + do + { + UINT32 aMatchBit = (aMatchByte >> 7) & 1; + aMatchByte <<= 1; + // UINT32 aBit = m_Decoders[1 + aMatchBit][aSymbol].Decode(aRangeDecoder); + // aSymbol = (aSymbol << 1) | aBit; + UINT32 aBit; + RC_GETBIT2(kNumMoveBits, m_Decoders[1 + aMatchBit][aSymbol].m_Probability, aSymbol, + aBit = 0, aBit = 1) + if (aMatchBit != aBit) + { + while (aSymbol < 0x100) + { + // aSymbol = (aSymbol << 1) | m_Decoders[0][aSymbol].Decode(aRangeDecoder); + RC_GETBIT(kNumMoveBits, m_Decoders[0][aSymbol].m_Probability, aSymbol) + } + break; + } + } + while (aSymbol < 0x100); + RC_FLUSH_VAR + return aSymbol; + } +}; + +class CDecoder +{ + CDecoder2 *m_Coders; + UINT32 m_NumPrevBits; + UINT32 m_NumPosBits; + UINT32 m_PosMask; +public: + CDecoder(): m_Coders(0) {} + ~CDecoder() { Free(); } + void Free() + { + delete []m_Coders; + m_Coders = 0; + } + void Create(UINT32 aNumPosBits, UINT32 aNumPrevBits) + { + Free(); + m_NumPosBits = aNumPosBits; + m_PosMask = (1 << aNumPosBits) - 1; + m_NumPrevBits = aNumPrevBits; + UINT32 aNumStates = 1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new CDecoder2[aNumStates]; + } + void Init() + { + UINT32 aNumStates = 1 << (m_NumPrevBits + m_NumPosBits); + for (UINT32 i = 0; i < aNumStates; i++) + m_Coders[i].Init(); + } + UINT32 GetState(UINT32 aPos, BYTE aPrevByte) const + { return ((aPos & m_PosMask) << m_NumPrevBits) + (aPrevByte >> (8 - m_NumPrevBits)); } + BYTE DecodeNormal(CMyRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte) + { return m_Coders[GetState(aPos, aPrevByte)].DecodeNormal(aRangeDecoder); } + BYTE DecodeWithMatchByte(CMyRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte, BYTE aMatchByte) + { return m_Coders[GetState(aPos, aPrevByte)].DecodeWithMatchByte(aRangeDecoder, aMatchByte); } +}; + +} + +#endif diff --git a/jma/lzma.cpp b/jma/lzma.cpp new file mode 100644 index 00000000..d020ed27 --- /dev/null +++ b/jma/lzma.cpp @@ -0,0 +1,41 @@ +/* +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "lzma.h" + +namespace NCompress { +namespace NLZMA { + +UINT32 kDistStart[kDistTableSizeMax]; + +static class CConstInit +{ +public: + CConstInit() + { + UINT32 aStartValue = 0; + int i; + for (i = 0; i < kDistTableSizeMax; i++) + { + kDistStart[i] = aStartValue; + aStartValue += (1 << kDistDirectBits[i]); + } + } +} g_ConstInit; + +}} diff --git a/jma/lzma.h b/jma/lzma.h new file mode 100644 index 00000000..e7c4d5af --- /dev/null +++ b/jma/lzma.h @@ -0,0 +1,124 @@ +/* +Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com ) +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "lencoder.h" + +#ifndef __LZMA_H +#define __LZMA_H + +namespace NCompress { +namespace NLZMA { + +const UINT32 kNumRepDistances = 4; + +const BYTE kNumStates = 12; + +const BYTE kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +const BYTE kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +const BYTE kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +const BYTE kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +class CState +{ +public: + BYTE m_Index; + void Init() + { m_Index = 0; } + void UpdateChar() + { m_Index = kLiteralNextStates[m_Index]; } + void UpdateMatch() + { m_Index = kMatchNextStates[m_Index]; } + void UpdateRep() + { m_Index = kRepNextStates[m_Index]; } + void UpdateShortRep() + { m_Index = kShortRepNextStates[m_Index]; } +}; + +class CBaseCoder +{ +protected: + CState m_State; + BYTE m_PreviousByte; + bool m_PeviousIsMatch; + UINT32 m_RepDistances[kNumRepDistances]; + void Init() + { + m_State.Init(); + m_PreviousByte = 0; + m_PeviousIsMatch = false; + for(UINT32 i = 0 ; i < kNumRepDistances; i++) + m_RepDistances[i] = 0; + } +}; + +const int kNumPosSlotBits = 6; +const int kDicLogSizeMax = 28; +const int kDistTableSizeMax = kDicLogSizeMax * 2; + +extern UINT32 kDistStart[kDistTableSizeMax]; +const BYTE kDistDirectBits[kDistTableSizeMax] = +{ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, + 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26 +}; + +const UINT32 kNumLenToPosStates = 4; +inline UINT32 GetLenToPosState(UINT32 aLen) +{ + aLen -= 2; + if (aLen < kNumLenToPosStates) + return aLen; + return kNumLenToPosStates - 1; +} + +const int kMatchMinLen = 2; + +const int kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; + +const int kNumAlignBits = 4; +const int kAlignTableSize = 1 << kNumAlignBits; +const UINT32 kAlignMask = (kAlignTableSize - 1); + +const int kStartPosModelIndex = 4; +const int kEndPosModelIndex = 14; +const int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + +const int kNumFullDistances = 1 << (kEndPosModelIndex / 2); + + +const int kMainChoiceLiteralIndex = 0; +const int kMainChoiceMatchIndex = 1; + +const int kMatchChoiceDistanceIndex= 0; +const int kMatchChoiceRepetitionIndex = 1; + +const int kNumMoveBitsForMainChoice = 5; +const int kNumMoveBitsForPosCoders = 5; + +const int kNumMoveBitsForAlignCoders = 5; + +const int kNumMoveBitsForPosSlotCoder = 5; + +const int kNumLitPosStatesBitsEncodingMax = 4; +const int kNumLitContextBitsMax = 8; + +}} + +#endif diff --git a/jma/lzmadec.cpp b/jma/lzmadec.cpp new file mode 100644 index 00000000..d76352a5 --- /dev/null +++ b/jma/lzmadec.cpp @@ -0,0 +1,298 @@ +/* +Copyright (C) 2005-2006 NSRT Team ( http://nsrt.edgeemu.com ) +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "portable.h" +#include "lzmadec.h" + +#define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; } + +namespace NCompress { +namespace NLZMA { + +HRESULT CDecoder::SetDictionarySize(UINT32 aDictionarySize) +{ + if (aDictionarySize > (1 << kDicLogSizeMax)) + return E_INVALIDARG; + + UINT32 aWindowReservSize = MyMax(aDictionarySize, UINT32(1 << 21)); + + if (m_DictionarySize != aDictionarySize) + { + m_OutWindowStream.Create(aDictionarySize, kMatchMaxLen, aWindowReservSize); + m_DictionarySize = aDictionarySize; + } + return S_OK; +} + +HRESULT CDecoder::SetLiteralProperties( + UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits) +{ + if (aLiteralPosStateBits > 8) + return E_INVALIDARG; + if (aLiteralContextBits > 8) + return E_INVALIDARG; + m_LiteralDecoder.Create(aLiteralPosStateBits, aLiteralContextBits); + return S_OK; +} + +HRESULT CDecoder::SetPosBitsProperties(UINT32 aNumPosStateBits) +{ + if (aNumPosStateBits > NLength::kNumPosStatesBitsMax) + return E_INVALIDARG; + UINT32 aNumPosStates = 1 << aNumPosStateBits; + m_LenDecoder.Create(aNumPosStates); + m_RepMatchLenDecoder.Create(aNumPosStates); + m_PosStateMask = aNumPosStates - 1; + return S_OK; +} + +CDecoder::CDecoder(): + m_DictionarySize((UINT32)-1) +{ + Create(); +} + +HRESULT CDecoder::Create() +{ + for(int i = 0; i < kNumPosModels; i++) + { + RETURN_E_OUTOFMEMORY_IF_FALSE( + m_PosDecoders[i].Create(kDistDirectBits[kStartPosModelIndex + i])); + } + return S_OK; +} + + +HRESULT CDecoder::Init(ISequentialInStream *anInStream, + ISequentialOutStream *anOutStream) +{ + m_RangeDecoder.Init(anInStream); + + m_OutWindowStream.Init(anOutStream); + + int i; + for(i = 0; i < kNumStates; i++) + { + for (UINT32 j = 0; j <= m_PosStateMask; j++) + { + m_MainChoiceDecoders[i][j].Init(); + m_MatchRepShortChoiceDecoders[i][j].Init(); + } + m_MatchChoiceDecoders[i].Init(); + m_MatchRepChoiceDecoders[i].Init(); + m_MatchRep1ChoiceDecoders[i].Init(); + m_MatchRep2ChoiceDecoders[i].Init(); + } + + m_LiteralDecoder.Init(); + + // m_RepMatchLenDecoder.Init(); + + for (i = 0; (UINT32) i < kNumLenToPosStates; i++) + m_PosSlotDecoder[i].Init(); + + for(i = 0; i < kNumPosModels; i++) + m_PosDecoders[i].Init(); + + m_LenDecoder.Init(); + m_RepMatchLenDecoder.Init(); + + m_PosAlignDecoder.Init(); + return S_OK; + +} + +HRESULT CDecoder::CodeReal(ISequentialInStream *anInStream, + ISequentialOutStream *anOutStream, + const UINT64 *anInSize, const UINT64 *anOutSize) +{ + if (anOutSize == NULL) + return E_INVALIDARG; + + Init(anInStream, anOutStream); + + CState aState; + aState.Init(); + bool aPeviousIsMatch = false; + BYTE aPreviousByte = 0; + UINT32 aRepDistances[kNumRepDistances]; + for(UINT32 i = 0 ; i < kNumRepDistances; i++) + aRepDistances[i] = 0; + + UINT64 aNowPos64 = 0; + UINT64 aSize = *anOutSize; + while(aNowPos64 < aSize) + { + UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize); + while(aNowPos64 < aNext) + { + UINT32 aPosState = UINT32(aNowPos64) & m_PosStateMask; + if (m_MainChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == (UINT32) kMainChoiceLiteralIndex) + { + // aCounts[0]++; + aState.UpdateChar(); + if(aPeviousIsMatch) + { + BYTE aMatchByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1); + aPreviousByte = m_LiteralDecoder.DecodeWithMatchByte(&m_RangeDecoder, + UINT32(aNowPos64), aPreviousByte, aMatchByte); + aPeviousIsMatch = false; + } + else + aPreviousByte = m_LiteralDecoder.DecodeNormal(&m_RangeDecoder, + UINT32(aNowPos64), aPreviousByte); + m_OutWindowStream.PutOneByte(aPreviousByte); + aNowPos64++; + } + else + { + aPeviousIsMatch = true; + UINT32 aDistance, aLen; + if(m_MatchChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == + (UINT32) kMatchChoiceRepetitionIndex) + { + if(m_MatchRepChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) + { + if(m_MatchRepShortChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == 0) + { + aState.UpdateShortRep(); + aPreviousByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1); + m_OutWindowStream.PutOneByte(aPreviousByte); + aNowPos64++; + // aCounts[3 + 4]++; + continue; + } + // aCounts[3 + 0]++; + aDistance = aRepDistances[0]; + } + else + { + if(m_MatchRep1ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) + { + aDistance = aRepDistances[1]; + aRepDistances[1] = aRepDistances[0]; + // aCounts[3 + 1]++; + } + else + { + if (m_MatchRep2ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) + { + // aCounts[3 + 2]++; + aDistance = aRepDistances[2]; + } + else + { + // aCounts[3 + 3]++; + aDistance = aRepDistances[3]; + aRepDistances[3] = aRepDistances[2]; + } + aRepDistances[2] = aRepDistances[1]; + aRepDistances[1] = aRepDistances[0]; + } + aRepDistances[0] = aDistance; + } + aLen = m_RepMatchLenDecoder.Decode(&m_RangeDecoder, aPosState) + kMatchMinLen; + // aCounts[aLen]++; + aState.UpdateRep(); + } + else + { + aLen = kMatchMinLen + m_LenDecoder.Decode(&m_RangeDecoder, aPosState); + aState.UpdateMatch(); + UINT32 aPosSlot = m_PosSlotDecoder[GetLenToPosState(aLen)].Decode(&m_RangeDecoder); + // aCounts[aPosSlot]++; + if (aPosSlot >= (UINT32) kStartPosModelIndex) + { + aDistance = kDistStart[aPosSlot]; + if (aPosSlot < (UINT32) kEndPosModelIndex) + aDistance += m_PosDecoders[aPosSlot - kStartPosModelIndex].Decode(&m_RangeDecoder); + else + { + aDistance += (m_RangeDecoder.DecodeDirectBits(kDistDirectBits[aPosSlot] - + kNumAlignBits) << kNumAlignBits); + aDistance += m_PosAlignDecoder.Decode(&m_RangeDecoder); + } + } + else + aDistance = aPosSlot; + + + aRepDistances[3] = aRepDistances[2]; + aRepDistances[2] = aRepDistances[1]; + aRepDistances[1] = aRepDistances[0]; + + aRepDistances[0] = aDistance; + // UpdateStat(aLen, aPosSlot); + } + if (aDistance >= aNowPos64) + throw E_INVALIDDATA; + m_OutWindowStream.CopyBackBlock(aDistance, aLen); + aNowPos64 += aLen; + aPreviousByte = m_OutWindowStream.GetOneByte(0 - 1); + } + } + } + return Flush(); +} + +HRESULT CDecoder::Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize) +{ + try { + return CodeReal(anInStream, anOutStream, anInSize, anOutSize); + } catch (HRESULT& e) { + return e; + } catch (...) { + return E_FAIL; + } +} + +HRESULT CDecoder::ReadCoderProperties(ISequentialInStream *anInStream) +{ + UINT32 aNumPosStateBits; + UINT32 aLiteralPosStateBits; + UINT32 aLiteralContextBits; + UINT32 aDictionarySize; + + UINT32 aProcessesedSize; + + BYTE aByte; + RETURN_IF_NOT_S_OK(anInStream->Read(&aByte, sizeof(aByte), &aProcessesedSize)); + if (aProcessesedSize != sizeof(aByte)) + return E_INVALIDARG; + + aLiteralContextBits = aByte % 9; + BYTE aRemainder = aByte / 9; + aLiteralPosStateBits = aRemainder % 5; + aNumPosStateBits = aRemainder / 5; + + UINT8 uint_buffer[UINT_SIZE]; + RETURN_IF_NOT_S_OK(anInStream->Read(uint_buffer, sizeof(aDictionarySize), &aProcessesedSize)); + aDictionarySize = charp_to_uint(uint_buffer); + + if (aProcessesedSize != sizeof(aDictionarySize)) + return E_INVALIDARG; + + RETURN_IF_NOT_S_OK(SetDictionarySize(aDictionarySize)); + RETURN_IF_NOT_S_OK(SetLiteralProperties(aLiteralPosStateBits, aLiteralContextBits)); + RETURN_IF_NOT_S_OK(SetPosBitsProperties(aNumPosStateBits)); + + return S_OK; +} + +}} diff --git a/jma/lzmadec.h b/jma/lzmadec.h new file mode 100644 index 00000000..bb91912e --- /dev/null +++ b/jma/lzmadec.h @@ -0,0 +1,82 @@ +/* +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LZARITHMETIC_DECODER_H +#define __LZARITHMETIC_DECODER_H + +#include "winout.h" +#include "lzma.h" +#include "lencoder.h" +#include "litcoder.h" + +namespace NCompress { +namespace NLZMA { + +typedef CMyBitDecoder CMyBitDecoder2; + +class CDecoder +{ + NStream::NWindow::COut m_OutWindowStream; + CMyRangeDecoder m_RangeDecoder; + + CMyBitDecoder2 m_MainChoiceDecoders[kNumStates][NLength::kNumPosStatesMax]; + CMyBitDecoder2 m_MatchChoiceDecoders[kNumStates]; + CMyBitDecoder2 m_MatchRepChoiceDecoders[kNumStates]; + CMyBitDecoder2 m_MatchRep1ChoiceDecoders[kNumStates]; + CMyBitDecoder2 m_MatchRep2ChoiceDecoders[kNumStates]; + CMyBitDecoder2 m_MatchRepShortChoiceDecoders[kNumStates][NLength::kNumPosStatesMax]; + + CBitTreeDecoder m_PosSlotDecoder[kNumLenToPosStates]; + + CReverseBitTreeDecoder2 m_PosDecoders[kNumPosModels]; + CReverseBitTreeDecoder m_PosAlignDecoder; + // CBitTreeDecoder2 m_PosDecoders[kNumPosModels]; + // CBitTreeDecoder m_PosAlignDecoder; + + NLength::CDecoder m_LenDecoder; + NLength::CDecoder m_RepMatchLenDecoder; + + NLiteral::CDecoder m_LiteralDecoder; + + UINT32 m_DictionarySize; + + UINT32 m_PosStateMask; + + HRESULT Create(); + + HRESULT Init(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream); + + HRESULT Flush() { return m_OutWindowStream.Flush(); } + + HRESULT CodeReal(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize); + +public: + + CDecoder(); + + HRESULT Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize); + HRESULT ReadCoderProperties(ISequentialInStream *anInStream); + + HRESULT SetDictionarySize(UINT32 aDictionarySize); + HRESULT SetLiteralProperties(UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits); + HRESULT SetPosBitsProperties(UINT32 aNumPosStateBits); +}; + +}} + +#endif diff --git a/jma/portable.h b/jma/portable.h new file mode 100644 index 00000000..d6ca1da6 --- /dev/null +++ b/jma/portable.h @@ -0,0 +1,87 @@ +/* +Copyright (C) 2004-2006 NSRT Team ( http://nsrt.edgeemu.com ) +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 2 as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __PORTABLE_H +#define __PORTABLE_H + +#include + +typedef signed char INT8; +typedef unsigned char UINT8; +typedef short INT16; +typedef unsigned short UINT16; +typedef long INT32; +typedef unsigned long UINT32; + +//Not correct, but should work for Snes9x +typedef int INT64; +typedef unsigned int UINT64; +//typedef long long INT64; +//typedef unsigned long long UINT64; + +typedef UINT8 BYTE; +typedef UINT16 WORD; +typedef UINT32 DWORD; + +typedef unsigned UINT_PTR; + +typedef int BOOL; +#define FALSE 0 +#define TRUE 1 + +#define HRESULT int +#define S_OK 0 +#define E_INVALIDARG -1 +#define E_OUTOFMEMORY -2 +#define E_FAIL -3 +#define E_INTERNAL_ERROR -4 +#define E_INVALIDDATA -5 + +template inline T MyMin(T a, T b) { + return a < b ? a : b; +} + +template inline T MyMax(T a, T b) { + return a > b ? a : b; +} + +#define RETURN_IF_NOT_S_OK(x) { HRESULT __aResult_ = (x); if(__aResult_ != S_OK) return __aResult_; } + + +#define UINT_SIZE (4) +#define USHORT_SIZE (2) + +//Convert an array of 4 bytes back into an integer +inline unsigned int charp_to_uint(const unsigned char buffer[UINT_SIZE]) +{ + unsigned int num = (unsigned int)buffer[3]; + num |= ((unsigned int)buffer[2]) << 8; + num |= ((unsigned int)buffer[1]) << 16; + num |= ((unsigned int)buffer[0]) << 24; + return(num); +} + +//Convert an array of 2 bytes back into a short integer +inline unsigned short charp_to_ushort(const unsigned char buffer[USHORT_SIZE]) +{ + unsigned short num = (unsigned short)buffer[1]; + num |= ((unsigned short)buffer[0]) << 8; + return(num); +} + +#endif diff --git a/jma/rcdefs.h b/jma/rcdefs.h new file mode 100644 index 00000000..6106b57a --- /dev/null +++ b/jma/rcdefs.h @@ -0,0 +1,60 @@ +/* +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __RCDEFS_H +#define __RCDEFS_H + +#include "aribitcd.h" +#include "ariconst.h" + +#define RC_INIT_VAR \ + UINT32 aRange = aRangeDecoder->m_Range; \ + UINT32 aCode = aRangeDecoder->m_Code; + +#define RC_FLUSH_VAR \ + aRangeDecoder->m_Range = aRange; \ + aRangeDecoder->m_Code = aCode; + +#define RC_NORMALIZE \ + if (aRange < NCompression::NArithmetic::kTopValue) \ + { \ + aCode = (aCode << 8) | aRangeDecoder->m_Stream.ReadByte(); \ + aRange <<= 8; } + +#define RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, Action0, Action1) \ + {UINT32 aNewBound = (aRange >> NCompression::NArithmetic::kNumBitModelTotalBits) * aProb; \ + if (aCode < aNewBound) \ + { \ + Action0; \ + aRange = aNewBound; \ + aProb += (NCompression::NArithmetic::kBitModelTotal - aProb) >> aNumMoveBits; \ + aModelIndex <<= 1; \ + } \ + else \ + { \ + Action1; \ + aRange -= aNewBound; \ + aCode -= aNewBound; \ + aProb -= (aProb) >> aNumMoveBits; \ + aModelIndex = (aModelIndex << 1) + 1; \ + }} \ + RC_NORMALIZE + +#define RC_GETBIT(aNumMoveBits, aProb, aModelIndex) RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, ; , ;) + +#endif diff --git a/jma/rngcoder.h b/jma/rngcoder.h new file mode 100644 index 00000000..711c2de8 --- /dev/null +++ b/jma/rngcoder.h @@ -0,0 +1,143 @@ +/* +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __COMPRESSION_RANGECODER_H +#define __COMPRESSION_RANGECODER_H + +#include "inbyte.h" + +namespace NCompression { +namespace NArithmetic { + +const UINT32 kNumTopBits = 24; +const UINT32 kTopValue = (1 << kNumTopBits); + +class CRangeDecoder +{ +public: + NStream::CInByte m_Stream; + UINT32 m_Range; + UINT32 m_Code; + UINT32 m_Word; + void Normalize() + { + while (m_Range < kTopValue) + { + m_Code = (m_Code << 8) | m_Stream.ReadByte(); + m_Range <<= 8; + } + } + + void Init(ISequentialInStream *aStream) + { + m_Stream.Init(aStream); + m_Code = 0; + m_Range = UINT32(-1); + for(int i = 0; i < 5; i++) + m_Code = (m_Code << 8) | m_Stream.ReadByte(); + } + + UINT32 GetThreshold(UINT32 aTotal) + { + return (m_Code) / ( m_Range /= aTotal); + } + + void Decode(UINT32 aStart, UINT32 aSize, UINT32 aTotal) + { + m_Code -= aStart * m_Range; + m_Range *= aSize; + Normalize(); + } + + /* + UINT32 DecodeDirectBitsDiv(UINT32 aNumTotalBits) + { + m_Range >>= aNumTotalBits; + UINT32 aThreshold = m_Code / m_Range; + m_Code -= aThreshold * m_Range; + + Normalize(); + return aThreshold; + } + + UINT32 DecodeDirectBitsDiv2(UINT32 aNumTotalBits) + { + if (aNumTotalBits <= kNumBottomBits) + return DecodeDirectBitsDiv(aNumTotalBits); + UINT32 aResult = DecodeDirectBitsDiv(aNumTotalBits - kNumBottomBits) << kNumBottomBits; + return (aResult | DecodeDirectBitsDiv(kNumBottomBits)); + } + */ + + UINT32 DecodeDirectBits(UINT32 aNumTotalBits) + { + UINT32 aRange = m_Range; + UINT32 aCode = m_Code; + UINT32 aResult = 0; + for (UINT32 i = aNumTotalBits; i > 0; i--) + { + aRange >>= 1; + /* + aResult <<= 1; + if (aCode >= aRange) + { + aCode -= aRange; + aResult |= 1; + } + */ + UINT32 t = (aCode - aRange) >> 31; + aCode -= aRange & (t - 1); + // aRange = aRangeTmp + ((aRange & 1) & (1 - t)); + aResult = (aResult << 1) | (1 - t); + + if (aRange < kTopValue) + { + aCode = (aCode << 8) | m_Stream.ReadByte(); + aRange <<= 8; + } + } + m_Range = aRange; + m_Code = aCode; + return aResult; + } + + UINT32 DecodeBit(UINT32 aSize0, UINT32 aNumTotalBits) + { + UINT32 aNewBound = (m_Range >> aNumTotalBits) * aSize0; + UINT32 aSymbol; + if (m_Code < aNewBound) + { + aSymbol = 0; + m_Range = aNewBound; + } + else + { + aSymbol = 1; + m_Code -= aNewBound; + m_Range -= aNewBound; + } + Normalize(); + return aSymbol; + } + + UINT64 GetProcessedSize() {return m_Stream.GetProcessedSize(); } +}; + +}} + +#endif diff --git a/jma/s9x-jma.cpp b/jma/s9x-jma.cpp new file mode 100644 index 00000000..4c4c9cb6 --- /dev/null +++ b/jma/s9x-jma.cpp @@ -0,0 +1,223 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +// JMA compressed file support +// (c) Copyright 2004-2006 NSRT Team (http://nsrt.edgeemu.com) + + +#include "snes9x.h" +#include "memmap.h" + +#include +using namespace std; + +#include "s9x-jma.h" +#include "jma.h" + +size_t load_jma_file(const char *filename, unsigned char *buffer) +{ + try + { + JMA::jma_open JMAFile(filename); + vector file_info = JMAFile.get_files_info(); + + string our_file_name; + size_t our_file_size = 0; + + for (vector::iterator i = file_info.begin(); i != file_info.end(); i++) + { + //Check for valid ROM based on size + if ((i->size <= CMemory::MAX_ROM_SIZE+512) && (i->size > our_file_size)) + { + our_file_name = i->name; + our_file_size = i->size; + } + } + + if (!our_file_size) + { + return(0); + } + + JMAFile.extract_file(our_file_name, buffer); + + return(our_file_size); + } + catch (JMA::jma_errors jma_error) + { + return(0); + } +} diff --git a/jma/s9x-jma.h b/jma/s9x-jma.h new file mode 100644 index 00000000..97392ddc --- /dev/null +++ b/jma/s9x-jma.h @@ -0,0 +1,187 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +// JMA compressed file support +// (c) Copyright 2004-2006 NSRT Team (http://nsrt.edgeemu.com) + + +#ifdef __cplusplus +extern "C" { +#endif +size_t load_jma_file(const char *filename, unsigned char *buffer); +#ifdef __cplusplus +} +#endif diff --git a/jma/winout.cpp b/jma/winout.cpp new file mode 100644 index 00000000..1f33885c --- /dev/null +++ b/jma/winout.cpp @@ -0,0 +1,89 @@ +/* +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "winout.h" + +namespace NStream { +namespace NWindow { + +void COut::Create(UINT32 aKeepSizeBefore, UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv) +{ + m_Pos = 0; + m_PosLimit = aKeepSizeReserv + aKeepSizeBefore; + m_KeepSizeBefore = aKeepSizeBefore; + m_KeepSizeAfter = aKeepSizeAfter; + m_KeepSizeReserv = aKeepSizeReserv; + m_StreamPos = 0; + m_MoveFrom = m_KeepSizeReserv; + m_WindowSize = aKeepSizeBefore; + UINT32 aBlockSize = m_KeepSizeBefore + m_KeepSizeAfter + m_KeepSizeReserv; + delete []m_Buffer; + m_Buffer = new BYTE[aBlockSize]; +} + +COut::~COut() +{ + delete []m_Buffer; +} + +void COut::SetWindowSize(UINT32 aWindowSize) +{ + m_WindowSize = aWindowSize; + m_MoveFrom = m_KeepSizeReserv + m_KeepSizeBefore - aWindowSize; +} + +void COut::Init(ISequentialOutStream *aStream, bool aSolid) +{ + m_Stream = aStream; + + if(aSolid) + m_StreamPos = m_Pos; + else + { + m_Pos = 0; + m_PosLimit = m_KeepSizeReserv + m_KeepSizeBefore; + m_StreamPos = 0; + } +} + +HRESULT COut::Flush() +{ + UINT32 aSize = m_Pos - m_StreamPos; + if(aSize == 0) + return S_OK; + UINT32 aProcessedSize; + HRESULT aResult = m_Stream->Write(m_Buffer + m_StreamPos, aSize, &aProcessedSize); + if (aResult != S_OK) + return aResult; + if (aSize != aProcessedSize) + return E_FAIL; + m_StreamPos = m_Pos; + return S_OK; +} + +void COut::MoveBlockBackward() +{ + HRESULT aResult = Flush(); + if (aResult != S_OK) + throw aResult; + memmove(m_Buffer, m_Buffer + m_MoveFrom, m_WindowSize + m_KeepSizeAfter); + m_Pos -= m_MoveFrom; + m_StreamPos -= m_MoveFrom; +} + +}} diff --git a/jma/winout.h b/jma/winout.h new file mode 100644 index 00000000..38e06bdf --- /dev/null +++ b/jma/winout.h @@ -0,0 +1,89 @@ +/* +Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) +Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License version 2.1 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __STREAM_WINDOWOUT_H +#define __STREAM_WINDOWOUT_H + +#include "iiostrm.h" + +namespace NStream { +namespace NWindow { + +// m_KeepSizeBefore: how mach BYTEs must be in buffer before m_Pos; +// m_KeepSizeAfter: how mach BYTEs must be in buffer after m_Pos; +// m_KeepSizeReserv: how mach BYTEs must be in buffer for Moving Reserv; +// must be >= aKeepSizeAfter; // test it + +class COut +{ + BYTE *m_Buffer; + UINT32 m_Pos; + UINT32 m_PosLimit; + UINT32 m_KeepSizeBefore; + UINT32 m_KeepSizeAfter; + UINT32 m_KeepSizeReserv; + UINT32 m_StreamPos; + + UINT32 m_WindowSize; + UINT32 m_MoveFrom; + + ISequentialOutStream *m_Stream; + + virtual void MoveBlockBackward(); +public: + COut(): m_Buffer(0), m_Stream(0) {} + virtual ~COut(); + void Create(UINT32 aKeepSizeBefore, + UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv = (1<<17)); + void SetWindowSize(UINT32 aWindowSize); + + void Init(ISequentialOutStream *aStream, bool aSolid = false); + HRESULT Flush(); + + UINT32 GetCurPos() const { return m_Pos; } + const BYTE *GetPointerToCurrentPos() const { return m_Buffer + m_Pos;}; + + void CopyBackBlock(UINT32 aDistance, UINT32 aLen) + { + if (m_Pos >= m_PosLimit) + MoveBlockBackward(); + BYTE *p = m_Buffer + m_Pos; + aDistance++; + for(UINT32 i = 0; i < aLen; i++) + p[i] = p[i - aDistance]; + m_Pos += aLen; + } + + void PutOneByte(BYTE aByte) + { + if (m_Pos >= m_PosLimit) + MoveBlockBackward(); + m_Buffer[m_Pos++] = aByte; + } + + BYTE GetOneByte(UINT32 anIndex) const + { + return m_Buffer[m_Pos + anIndex]; + } + + BYTE *GetBuffer() const { return m_Buffer; } +}; + +}} + +#endif diff --git a/language.h b/language.h new file mode 100644 index 00000000..49a30ae1 --- /dev/null +++ b/language.h @@ -0,0 +1,202 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _LANGUAGE_H_ +#define _LANGUAGE_H_ + +// Movie Messages +#define MOVIE_ERR_SNAPSHOT_WRONG_MOVIE "Snapshot not from this movie" +#define MOVIE_ERR_SNAPSHOT_NOT_MOVIE "Not a movie snapshot" +#define MOVIE_INFO_REPLAY "Movie replay" +#define MOVIE_INFO_RECORD "Movie record" +#define MOVIE_INFO_RERECORD "Movie re-record" +#define MOVIE_INFO_REWIND "Movie rewind" +#define MOVIE_INFO_STOP "Movie stop" +#define MOVIE_INFO_END "Movie end" +#define MOVIE_INFO_SNAPSHOT "Movie snapshot" +#define MOVIE_ERR_SNAPSHOT_INCONSISTENT "Snapshot inconsistent with movie" + +// Snapshot Messages +#define SAVE_INFO_SNAPSHOT "Saved" +#define SAVE_INFO_LOAD "Loaded" +#define SAVE_INFO_OOPS "Auto-saving 'oops' snapshot" +#define SAVE_ERR_WRONG_FORMAT "File not in Snes9x snapshot format" +#define SAVE_ERR_WRONG_VERSION "Incompatable snapshot version" +#define SAVE_ERR_ROM_NOT_FOUND "ROM image \"%s\" for snapshot not found" +#define SAVE_ERR_SAVE_NOT_FOUND "Snapshot %s does not exist" + +#endif diff --git a/loadzip.cpp b/loadzip.cpp new file mode 100644 index 00000000..ac91a961 --- /dev/null +++ b/loadzip.cpp @@ -0,0 +1,320 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 UNZIP_SUPPORT + +#include +#include +#include "unzip/unzip.h" +#include "snes9x.h" +#include "memmap.h" + + +bool8 LoadZip (const char *zipname, int32 *TotalFileSize, int32 *headers, uint8 *buffer) +{ + *TotalFileSize = 0; + *headers = 0; + + unzFile file = unzOpen(zipname); + if (file == NULL) + return (FALSE); + + // find largest file in zip file (under MAX_ROM_SIZE) or a file with extension .1 + char filename[132]; + int filesize = 0; + int port = unzGoToFirstFile(file); + + unz_file_info info; + + while (port == UNZ_OK) + { + char name[132]; + unzGetCurrentFileInfo(file, &info, name, 128, NULL, 0, NULL, 0); + + if (info.uncompressed_size > CMemory::MAX_ROM_SIZE + 512) + { + port = unzGoToNextFile(file); + continue; + } + + if ((int) info.uncompressed_size > filesize) + { + strcpy(filename, name); + filesize = info.uncompressed_size; + } + + int len = strlen(name); + if (len > 2 && name[len - 2] == '.' && name[len - 1] == '1') + { + strcpy(filename, name); + filesize = info.uncompressed_size; + break; + } + + port = unzGoToNextFile(file); + } + + if (!(port == UNZ_END_OF_LIST_OF_FILE || port == UNZ_OK) || filesize == 0) + { + assert(unzClose(file) == UNZ_OK); + return (FALSE); + } + + // find extension + char tmp[2] = { 0, 0 }; + char *ext = strrchr(filename, '.'); + if (ext) + ext++; + else + ext = tmp; + + uint8 *ptr = buffer; + bool8 more = FALSE; + + unzLocateFile(file, filename, 1); + unzGetCurrentFileInfo(file, &info, filename, 128, NULL, 0, NULL, 0); + + if (unzOpenCurrentFile(file) != UNZ_OK) + { + unzClose(file); + return (FALSE); + } + + do + { + assert(info.uncompressed_size <= CMemory::MAX_ROM_SIZE + 512); + + int FileSize = info.uncompressed_size; + int l = unzReadCurrentFile(file, ptr, FileSize); + + if (unzCloseCurrentFile(file) == UNZ_CRCERROR) + { + unzClose(file); + return (FALSE); + } + + if (l <= 0 || l != FileSize) + { + unzClose(file); + return (FALSE); + } + + FileSize = (int) Memory.HeaderRemove((uint32) FileSize, *headers, ptr); + ptr += FileSize; + *TotalFileSize += FileSize; + + int len; + + if (ptr - Memory.ROM < CMemory::MAX_ROM_SIZE + 512 && (isdigit(ext[0]) && ext[1] == 0 && ext[0] < '9')) + { + more = TRUE; + ext[0]++; + } + else + if (ptr - Memory.ROM < CMemory::MAX_ROM_SIZE + 512) + { + if (ext == tmp) + len = strlen(filename); + else + len = ext - filename - 1; + + if ((len == 7 || len == 8) && strncasecmp(filename, "sf", 2) == 0 && + isdigit(filename[2]) && isdigit(filename[3]) && isdigit(filename[4]) && + isdigit(filename[5]) && isalpha(filename[len - 1])) + { + more = TRUE; + filename[len - 1]++; + } + } + else + more = FALSE; + + if (more) + { + if (unzLocateFile(file, filename, 1) != UNZ_OK || + unzGetCurrentFileInfo(file, &info, filename, 128, NULL, 0, NULL, 0) != UNZ_OK || + unzOpenCurrentFile(file) != UNZ_OK) + break; + } + } while (more); + + unzClose(file); + + return (TRUE); +} + +#endif diff --git a/logger.cpp b/logger.cpp new file mode 100644 index 00000000..235c5335 --- /dev/null +++ b/logger.cpp @@ -0,0 +1,267 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "movie.h" +#include "logger.h" + +static int resetno = 0; +static int framecounter = 0; +static FILE *video = NULL; +static FILE *audio = NULL; + + +void S9xResetLogger (void) +{ + if (!Settings.DumpStreams) + return; + + char buffer[128]; + + S9xCloseLogger(); + framecounter = 0; + + sprintf(buffer, "videostream%d.dat", resetno); + video = fopen(buffer, "wb"); + if (!video) + { + printf("Opening %s failed. Logging cancelled.\n", buffer); + return; + } + + sprintf(buffer, "audiostream%d.dat", resetno); + audio = fopen(buffer, "wb"); + if (!audio) + { + printf("Opening %s failed. Logging cancelled.\n", buffer); + fclose(video); + return; + } + + resetno++; +} + +void S9xCloseLogger (void) +{ + if (video) + { + fclose(video); + video = NULL; + } + + if (audio) + { + fclose(audio); + audio = NULL; + } +} + +void S9xVideoLogger (void *pixels, int width, int height, int depth, int bytes_per_line) +{ + int fc = S9xMovieGetFrameCounter(); + if (fc > 0) + framecounter = fc; + else + framecounter++; + + if (video) + { + char *data = (char *) pixels; + size_t ignore; + + for (int i = 0; i < height; i++) + ignore = fwrite(data + i * bytes_per_line, depth, width, video); + fflush(video); + fflush(audio); + + if (Settings.DumpStreamsMaxFrames > 0 && framecounter >= Settings.DumpStreamsMaxFrames) + { + printf("Logging ended.\n"); + S9xCloseLogger(); + } + + } +} + +void S9xAudioLogger (void *samples, int length) +{ + if (audio) + { + size_t ignore; + ignore = fwrite(samples, 1, length, audio); + } +} diff --git a/logger.h b/logger.h new file mode 100644 index 00000000..63aa30b7 --- /dev/null +++ b/logger.h @@ -0,0 +1,186 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _LOGGER_H_ +#define _LOGGER_H_ + +void S9xResetLogger(void); +void S9xCloseLogger(void); +void S9xVideoLogger(void *, int, int, int, int); +void S9xAudioLogger(void *, int); + +#endif diff --git a/macosx/APPL.icns b/macosx/APPL.icns new file mode 100644 index 00000000..b5f6fa31 Binary files /dev/null and b/macosx/APPL.icns differ diff --git a/macosx/CART.icns b/macosx/CART.icns new file mode 100644 index 00000000..93c198d3 Binary files /dev/null and b/macosx/CART.icns differ diff --git a/macosx/English.lproj/InfoPlist.strings b/macosx/English.lproj/InfoPlist.strings new file mode 100644 index 00000000..f8f81d20 --- /dev/null +++ b/macosx/English.lproj/InfoPlist.strings @@ -0,0 +1,5 @@ +/* Localized versions of Info.plist keys */ + +CFBundleName = "Snes9x"; +CFBundleShortVersionString = "1.52"; +CFBundleGetInfoString = "Snes9x 1.52, Copyright 1996-2010 Snes9x developers."; diff --git a/macosx/English.lproj/Localizable.strings b/macosx/English.lproj/Localizable.strings new file mode 100644 index 00000000..18f40ec4 --- /dev/null +++ b/macosx/English.lproj/Localizable.strings @@ -0,0 +1,49 @@ +"Address" = "Address"; +"Value" = "Value"; +"Description" = "Description"; + +// Mes: replace ROM name with @ +// Pos: position of @ (UniChar count) + +"OpenROMMes" = "Choose a ROM image"; +"FreezeToMes" = "Save the @ freeze file"; +"FreezeToPos" = "10"; +"DefrostFromMes" = "Choose a @ freeze file"; +"DefrostFromPos" = "10"; +"NPROMNameMes" = "Server requests @."; +"NPROMNamePos" = "17"; +"RecordToMes" = "Save the @ movie file"; +"RecordToPos" = "10"; +"PlayFromMes" = "Choose a @ movie file"; +"PlayFromPos" = "10"; +"QTRecordMes" = "Save the @ QuickTime movie"; +"QTRecordPos" = "10"; + +"MoviePrevMes" = "Date :\nTime :\nLength :\nFrames :"; // indexes of info area +"MoviePrevWidth" = "120"; // width of info area +"MoviePrevBorder" = "45"; // width of indexes column + +"ClearMenu" = "Clear Menu"; + +"NPReady" = "Ready"; +"NPConnecting" = "Connecting"; +"NPServerName" = "Server"; + +"AlertMes_03" = "The folders for saving files could not be created."; +"AlertMes_04" = "Some features will not work properly without these folders."; +"AlertMes_05" = "This ROM image has bad checksum, so might not work properly."; +"AlertMes_06" = "Or failed to detect map / interleave."; +"AlertMes_07" = "No enough space in Cheat Entry."; +"AlertMes_08" = "Delete some cheats before."; +"AlertMes_09" = "Snes9x cannot run on your system."; +"AlertMes_10" = "System requirements: Mac OS X 10.3.9 or later, QuickTime 7 or later."; + +"PresetNum" = "Preset #%ld"; + +"RunMenu" = "Run"; +"PauseMenu" = "Pause"; + +"ResetCIFilter" = "Reset All Parameters"; + +"SoundEffectDlg" = "Sound Effect"; +"CreateMetalDlg" = "NO"; // "YES" to metalize above dialogs diff --git a/macosx/English.lproj/Snes9x Help/Snes9x Help.helpindex b/macosx/English.lproj/Snes9x Help/Snes9x Help.helpindex new file mode 100644 index 00000000..181ce7a4 Binary files /dev/null and b/macosx/English.lproj/Snes9x Help/Snes9x Help.helpindex differ diff --git a/macosx/English.lproj/Snes9x Help/gfx/s9xic128.png b/macosx/English.lproj/Snes9x Help/gfx/s9xic128.png new file mode 100644 index 00000000..8dadc3cc Binary files /dev/null and b/macosx/English.lproj/Snes9x Help/gfx/s9xic128.png differ diff --git a/macosx/English.lproj/Snes9x Help/gfx/s9xic16.png b/macosx/English.lproj/Snes9x Help/gfx/s9xic16.png new file mode 100644 index 00000000..7144135b Binary files /dev/null and b/macosx/English.lproj/Snes9x Help/gfx/s9xic16.png differ diff --git a/macosx/English.lproj/Snes9x Help/index.html b/macosx/English.lproj/Snes9x Help/index.html new file mode 100644 index 00000000..3f19f6b5 --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/index.html @@ -0,0 +1,37 @@ + + + + + + + + + + Snes9x Help + + + + + diff --git a/macosx/English.lproj/Snes9x Help/pgs/01.html b/macosx/English.lproj/Snes9x Help/pgs/01.html new file mode 100644 index 00000000..c0eb0bed --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/01.html @@ -0,0 +1,41 @@ + + + + + + + + Introduction + + +

Introduction

+

What is Snes9x?

+

+ Snes9x is a portable, freeware Super Nintendo Entertainment System (SNES) emulator. It basically allows you to play most games designed for the SNES and Super Famicom Nintendo game systems on your Mac, Linux, Windows and so on. The games include some real gems that were only ever released in Japan. +

+

+ The original Snes9x project was founded by Gary Henderson and Jerremy Koot as a collaboration of their earlier attempts at SNES emulation (Snes96 and Snes97.) Over the years the project has grown and has collected some of the greatest talent in the emulation community (at least of the SNES variety) some of which have been listed in the credits section, others have helped but have been loss in the course of time. +

+

Why Emulate the SNES?

+

+ Well, there are many reasons for this. The main reason is for nostalgic purposes. In this day and age, it's hard to find an SNES and many good games. Plus, many of us over the course of time have lost our beloved consoles (may they R.I.P) but still have our original carts. With no other means to play them, we turn to emulators. Besides this there are many conveniences of doing this on the computer instead of dragging out your old system. +

+

Advantages consist of :

+
    +
  • ability to save in any location of the game, despite how the game was designed. It's amazingly useful when you don't want to redo the same level over and over.
  • +
  • built-in peripherals. This is anything from multi-taps, to super scopes, to cheat devices.
  • +
  • ability to rip sprites and music for your own personal use.
  • +
  • easier to organize and no stacks of cartridges.
  • +
  • filters can be used to enhance graphics and sounds on old games.
  • +
+

As with all things there are disadvantages though :

+
    +
  • if you have an ancient computer, you aren't likely to get a playable experience.
  • +
  • some games are still unemulated (though this a very tiny minority.)
  • +
  • the emulator can be difficult for new users to configure.
  • +
+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/02.html b/macosx/English.lproj/Snes9x Help/pgs/02.html new file mode 100644 index 00000000..c66d0731 --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/02.html @@ -0,0 +1,131 @@ + + + + + + + + + Getting Started + + +

Getting Started

+

+ Copy the Snes9x application from the disk image (.dmg) to your hard disk and double-click it. +

+

Loading Games

+

+ Choose 'Open ROM Image...' in 'File' menu, select the game and start it. You can also drag and drop the ROM image onto the Snes9x icon. You may open a ROM image by double clicking on its icon in the Finder as well. +

+

+ SNES ROM images come in lots of different formats. Snes9x supports zipped ROMs as long as there is only 1 per zip file. Also Snes9x can open gzip/jma compressed file. +

+

Game Color System

+

+ By default, Snes9x displays the ROM information when a ROM is first loaded. Depending on the colors used you can tell whether or not a ROM is a good working ROM, or if it's been altered or is corrupted. +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + +
    whitethe ROM should be a perfect working copy.
    greenthe ROM is mode 1 interleaved.
    orangethe ROM is mode 2 interleaved.
    aquathe ROM is Game Doctor 24M interleaved.
    yellowthe ROM has probably been altered. Either it's a translation, PD ROM, hacked, or possibly a bad ROM. It may also be an overdumped ROM.
    redthe ROM is definitely hacked and that a proper version should be exist. Some ROM Tools such as NSRT can also fix these ROMs.
  • +
+

+ When asking for help on the Snes9x forums, please list the color and CRC32 that is displayed. This will help to find out what the problem is. +

+

+ These colors do NOT signify whether a game will work or not. It is just a means for reference so we can understand what may or may not be a problem. Most often the problem with games that don't work it's because they are corrupt or are a bad dump and should be redumped. +

+

SNES Joypad Emulation

+

+ The default key mapping for joypad 1 is as follows: +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    up arrowUp direction
    down arrowDown direction
    left arrowLeft direction
    right arrowRight direction
    commandA button
    optionB button
    controlX button
    shiftY button
    ZL button
    XR button
    tabSelect button
    returnStart button
  • +
+

Pausing and Resuming the Game

+

+ To pause the game, press pause key (esc key by default), choose 'Pause' in 'Emulation' menu, or click the game screen in case you aren't playing the game that uses a mouse. Double-click the game window or choose 'Resume' in 'Emulation' menu to resume the game. +

+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/03.html b/macosx/English.lproj/Snes9x Help/pgs/03.html new file mode 100644 index 00000000..519ad0b0 --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/03.html @@ -0,0 +1,31 @@ + + + + + + + + Requirements + + +

Requirements

+

System Requirements

+

+ Mac OS X 10.3.9 or later
+ QuickTime 7.0 or later
+ PowerPC G3 300MHz or later
+ G-Force/ATI Rage 128 or later +

+

+ Certain games use added hardware which will require a faster Mac. The specs listed above is the minimum to use Snes9x in any playable form. It is recommended that you get a semi-modern Mac with a 800MHz PowerPC processor if you want good results. A 1GHz PowerPC or Intel Mac is recommended for those that want a near perfect experience. +

+

Software

+

+ You will need access to SNES ROM images in .smc, .sfc, .fig, etc., format otherwise you will have nothing to run! Some home-brewed ROM images can be downloaded from http://www.zophar.com/.
+ Please note, it is illegal in most countries to have commercial ROM images without also owning the actual SNES ROM cartridges, and even then you may be liable under various EULAs. +

+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/04.html b/macosx/English.lproj/Snes9x Help/pgs/04.html new file mode 100644 index 00000000..31f05bfe --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/04.html @@ -0,0 +1,196 @@ + + + + + + + + + Controllers Support + + +

Controllers Support

+

+ The real SNES has two ports to connect input devices. Usually 1P and 2P SNES joypads are connected but various devices and adopters can be plugged. +

+
    +
  • + + + + + + + + + + + + + + + + + + +
    Multi Player 5known as Multi Tap; a five player adapter, allowing up to five people to play at once on games that supported it.
    SNES Mousea 2-button mouse, originally supplied with a paint program.
    Super Scopea light-gun; it used infrared to provide wireless communication between the gun and the console unit.
    Justifiera gun similar to Super Scope, supported with one gun-shooting game.
  • +
+

+ Snes9x can emulate those input devices with the keyboard, mouse and gamepad. +

+

Configuring Keyboard

+

+ Choose 'Configure Keyboard...' in 'Config' menu. Drag and drop each icon onto the key which you want to assign. Blue icons are for 1P joypad, orange icons are for 2P joypad, and green icons are for other input devices and additional functions. To restore to the default key mapping, press 'Default' button. +

+

Configuring Gamepad and Mouse

+

+ Choose 'Configure Controllers...' in 'Config' menu. Click the button in the dialog, and within 2.5 seconds press your gamepad or mouse (or keyboard) button that you want to assign. To remove the assignment, click the button and do nothing for 2.5 seconds. To clear all the settings, click 'Clear All' button. Additionally, you can switch controller settings quickly by selecting a preset by 'Controllers Preset' in 'Config' menu. +

+

Automatic Fire

+

+ The 'Automatic Fire...' dialog in the 'Config' menu provides five configuration options for simulating autofire controllers: +

+
+
Enable Automatic Fire
+
If this option is enabled for a given controller button, holding down that button will produce a rapid-fire effect (barring the use of the 'Automatic Fire is Active Only While TC is Pressed' option - see below).
+
Allow Alt to Toggle Enable/Disable Automatic Fire
+
If this option is enabled for a given controller button, pressing Snes9x's Alt key in conjunction with that controller button in-game will toggle that button's 'Enable Automatic Fire' setting.
+
Automatic Fire is Active Only While TC is Pressed
+
If this option is enabled for a given controller button, you must hold down Snes9x's TC key in conjunction with that controller button in-game to produce a rapid-fire effect, provided that 'Enable Automatic Fire' is toggled on for that controller button. If TC is not depressed, that controller button will function as normal. Note that when 'Enable Automatic Fire' is toggled off for a controller button, its 'Automatic Fire is Active Only While TC is Pressed' setting has no effect.
+
Button Input is Inverted
+
If this option is enabled for a given controller button, Snes9x behaves as though you are pushing that controller button if and only if you are not pushing it. This option is most often used in conjunction with 'Enable Automatic Fire', producing a rapidly-firing controller button without any player intervention.
+
Automatic Fire Speed
+
This option controls the rate at which autofire controller buttons cycle their fire.
+
+

+ Snes9x's Alt and TC buttons can be mapped to both keyboard keys and joypad buttons, in the 'Configure Keyboard...' and 'Configure Controllers...' dialogs respectively. +

+

Changing Input Devices

+

+ Select the device in 'Input Device' in 'Emulation' menu at any time.
+ If a ROM image has NSRT header, the most appropriate device is automatically chosen when you open the image.
+ Devices that Snes9x supports are: SNES Mouse, Super Scope, Justifier, SNES joypads and Multi Player 5. +

+

SNES Mouse

+

+ Assign your Mac's mouse (or gamepad) buttons to SNES Mouse buttons in 'Configure Controllers' dialog. To move SNES Mouse cursor, move your Mac's mouse. +

+

Super Scope

+

+ Assign your Mac's gamepad buttons or keyboard to Super Scope turbo/cursor/pause buttons in 'Configure Controllers' or 'Configure Keyboard' dialog. Note that the turbo button acts as a toggle button. To move the gunsight, move your mouse. Use SNES Mouse left button to fire. +

+

Justifier

+

+ Similar to Super Scope. Assign your Mac's gamepad buttons or keyboard to 'offscreen' button in 'Configure Controllers' or 'Configure Keyboard' dialog. To shoot offscreen, shoot anywhere while pressing the 'offscreen' button. +

+

Multi Player 5

+

+ Configure 3rd, 4th and 5th players in 'Configure Controllers' dialog. Note that 3rd, 4th and 5th players need gamepads.
+ Incidentally, there exist 6th, 7th and 8th players in that dialog, in case you have or make home-brewed games that can use two Multi Player 5 units. +

+

Additional Keyboard Controls

+

+ You can remap the buttons for the functions listed below in 'Configure Keyboard' dialog. The default mapping is: +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    escpauses the game and exits from the emulation loop.
    1saves a freeze file.
    0loads a freeze file, restoring a game to an exact position.
    `takes a screenshot.
    Rdumps a SPC file.
    \turbo mode (fast forward) - for skipping long intros and so on.
    Qdecreases turbo mode speed.
    Wincreases turbo mode speed.
    ,Snes9x's TC key - used for some options in the 'Automatic Fire...' dialog.
    .Snes9x's Alt key - used for some options in the 'Automatic Fire...' dialog.
    /Snes9x's Fn key - press this button with the keys below.
  • +
+

+ These functions below work with 'Fn' button: +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    F1-F4toggles background 1-4 on/off.
    F5toggles sprites on/off.
    F6swaps 1P and 2P controllers.
    1-8toggles sound channel on/off.
    9enables all sound channels.
    0toggles displaying pressed buttons.
    -toggles displaying frame counts in movies.
    Qincreases emulated frame time - slowing down the game.
    Wdecreases emulated frame time - speeding up the game.
  • +
+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/05.html b/macosx/English.lproj/Snes9x Help/pgs/05.html new file mode 100644 index 00000000..a899c53b --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/05.html @@ -0,0 +1,56 @@ + + + + + + + + Peripherals Support + + +

Peripherals Support

+

Satellaview

+

+ Snes9x partially emulates Satellaview system, so-called BS-X. To play BS games or read BS magazines with the BS-X base cartridge, do the following. +

+
    +
  • If you have .srm files of BS games which were created by Snes9x 1.43 or earlier, trash them first.
  • +
  • Prepare the BS-X ROM image. Make sure the file is uncompressed and doesn't have a header.
  • +
  • Rename the BS-X ROM image to 'BS-X.bin'.
  • +
  • Put BS-X.bin in the proper directory. 'BIOSes' folder by default.
  • +
  • Launch BS-X.bin as you usually play SNES games.
  • +
  • Set your name and gender.
  • +
  • Launch a BS game. The game is launched for the first time and its .srm doesn't exist, so BS-X.srm is loaded instead.
  • +
  • Once you launched the game, its .srm is created and loaded from the next time.
  • +
+

+ If you launch a BS game for the first time without BS-X.srm, maybe the game doesn't work properly.
+ To boot up BS games from BS-X town, turn on 'Boot Up BS Games from BS-X' option in 'Preferences' dialog. +

+

Sufami Turbo

+

+ To play Sufami Turbo games, do the following. +

+
    +
  • Prepare the Sufami Turbo base cartridge ROM image. Make sure the file is uncompressed and doesn't have a header.
  • +
  • Rename the base cartridge ROM image to 'STBIOS.bin'.
  • +
  • Put STBIOS.bin in the proper directory. 'BIOSes' folder by default.
  • +
  • Choose 'Open Multiple ROM Images...' from 'File' menu.
  • +
  • Set game(s) into each slot with 'Choose...', 'Clear' and 'Swap' buttons. You can also drag and drop the ROM image onto each slot.
  • +
  • Press 'OK' button and the Sufami Turbo system will run.
  • +
+

+ Note that the base cartridge can initialize SRAM for only the game in slot A, so you have to set every game in slot A and launch at least once.
+ If no games are set in the slots, only the base cartridge runs.
+ If you have a combined ROM image, split it to each games and the base cartridge. NSRT will help you. +

+

Other Multiple Cartridge Games

+

+ In 'Open Multiple ROM Images' dialog, put the main cartridge in slot A and the add-on cartridge in slot B.
+ Currently supported: Same Game +

+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/06.html b/macosx/English.lproj/Snes9x Help/pgs/06.html new file mode 100644 index 00000000..861e423c --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/06.html @@ -0,0 +1,43 @@ + + + + + + + + Game Saving + + +

Game Saving

+

+ Many SNES games take a very long time to complete from start to finish, so they allowed your progress to be saved at the predefined places chosen by the game designers. The game cartridge contains a battery-backed RAM, known as SRAM, and your save data remain in this SRAM until the battery shutoff. +

+

+ Snes9x has two methods for saving games. One is the same as of the real SNES shown above; emulating SRAM. The SRAM contents are saved into a file (.srm) so you don't need to be worried about the battery shutoff. The other is more convenient way than the real SNES; 'freezing' or 'snapshotting' the game. It means saving the whole game state anywhere you want, beyond the game designers' intent - ideal for saving your game just before a tricky bit! +

+

Using the SRAM File

+

+ It's easy enough, just save the game as you do with the real SNES. Snes9x outputs the contents of the emulated SRAM into a file (.srm) when you load a new game or quit Snes9x. This file is automatically loaded the next time you play the game. +

+

+ To avoid losing your progress if Snes9x or your system crashes before the .srm file is saved, Snes9x provides auto-saving .srm option - the .srm file is always updated when the SRAM contents are modified. See into 'File' tab in 'Preferences' dialog to turn on this option. You can also update .srm file manually by choosing 'Save SRAM File Now' in 'Option' menu. +

+

Freezing and Defrosting the Game State

+

+ Snes9x provides 12 slots for freezing the whole of your game state. During the game, press 'Freeze' key and you can see the slots numbered from 0 to C in the game screen. Press 0-C key (or move the yellow square cursor by the joypad and press start button) to save the game state to each slot. To load it, press 'Defrost' key and choose the slot in the same way. The most recent freeze file (.frz) is automatically pointed by the yellow cursor when you entered the freeze/defrost screen. Thumbnails and time stamps will be your help. If you mistakenly entered the freeze/defrost screen, press esc key and exit.
+ Additionally, you can manually save/load the freeze file by using 'Freeze State to...' and 'Defrost State from...' in 'Option' menu. +

+

Real-Time Clock Emulation

+

+ Some games have a battery-backed real-time clock (RTC) in their cartridge to bring a real-time event in the game. Snes9x saves the state of RTC into a file (.rtc) and also into a freeze file.
+ Note that because it's a 'real-time' clock, when these files are loaded, the emulated clock is automatically advanced in reference to your Mac's time and date. +

+

Fool-Proof System

+

+ If you quit the game by error without saving your long-time progress, try to find '.oops' file in the same folder as freeze files. If it exists, rename its extension to '.frz' and try to load it. It's a freeze file automatically generated if you don't save anything for a long time. +

+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/07.html b/macosx/English.lproj/Snes9x Help/pgs/07.html new file mode 100644 index 00000000..71656fad --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/07.html @@ -0,0 +1,59 @@ + + + + + + + + Cheat Support + + +

Cheat Support

+

+ Cheat codes allow you to cheat at games. They might give you more lives, infinite health, enable special powers normally only activated when a special item is found, and etc. Two major formats are well-known: Game Genie and Pro-Action Reply (PAR). Many existing Game Genie and PAR codes can be found via Internet. +

+

+ Snes9x supports both Game Genie and PAR by 'Cheat Entry' dialog. Also you can find your own cheat code with 'Cheat Finder' dialog. Cheats are saved in .cht files and are automatically loaded the next time a game with the same filename is loaded. +

+

+ Technically, a cheat code consists of two elements; an address in SNES memory map where you want to overwrite, and a value which is overwritten on the address.
+ Beware of cheat codes designed for a ROM from a different region compared to the one you are playing or for a different version of the ROM; the source of the cheats should tell you which region and for which version of the game they were designed for. If you use a code designed for a different region or version of your game, the game might crash or do other weird things because the cheat address might be different between regions and versions. +

+

Cheat Entry

+

+ Open 'Cheat Entry' dialog from 'Cheat' menu to enter Game Genie or PAR cheat codes. To add a cheat code, press 'New' button. A new empty entry appears in the list. Click '000000' in the address column and the string will be highlighted and editable. Input Game Genie or PAR code directly; it's translated to general style (an address and a value pair) automatically. Of course you can also input an address and a value in hex format instead of a cheat code. You may add your comment in the description column.
+ To enable each cheat code, click each check box and turn on. To enable/disable the entire cheat function itself, choose 'Apply Cheats' in 'Cheat' menu. +

+

Cheat Finder

+

+ Tutorial: let's give infinite lives on R-TYPE 3 (J). +

+

+ Load up the game and begin to play the first stage. You'll notice the game starts with 2 lives. +

+

+ Pause the game and open 'Cheat Finder' dialog from 'Cheat' menu for the first time. Press 'Restore List' button just in case you've used the dialog before. Leave any controls at their default values. Press 'Store Current Values' button and close the dialog. +

+

+ Play the game until you lose a life by just crashing into an enemy, then the game restarts and the life counter displays 1. Open 'Cheat Finder' dialog again. +

+

+ Choose 'not equal' in 'Comparison' menu, click 'Stored Value' radio box, and press 'Search' button. The number of items in the list will reduce. The current values shown in the list are different from the previous values which were stored when you pressed 'Store Current Values' button. What we're looking for is the memory location where the game stores its life counter. Choose 'equal' in 'Comparison' menu, click 'This Value' radio box, type '1' in the text box, and press 'Search' button. The number of items in the list will reduce again. One of the items might be the life counter. +

+

+ Again, crash into an enemy. The game restarts and the life counter displays 0. Open 'Cheat Finder' dialog. You'll find the value 0 in line 7E03B7. The previous value was 1 and the current value is 0. Is this address life counter? Select the line 7E03B7, press 'Watch' button, and close the dialog. Now you can see the value in the address 7E03B7 at the top left corner of the game screen. +

+

+ Play the game again, and crash into an enemy while watching the value. Yes, this value should be the life counter. Now you want to get infinite lives. Open 'Cheat Finder' dialog again, select the line 7E03B7 and press 'Add to Cheat Entry...' button. Enter the value 5 (don't care for now) into 'Cheat Value' text box, your comment into 'Description' text box and press 'Add' button. Your new cheat code will be sent to 'Cheat Entry' dialog. Close 'Cheat Finder' dialog. +

+

+ Open 'Cheat Entry' dialog and confirm your cheat codes are added. Make sure the cheat codes are turned on and close the dialog. Turn on 'Apply Cheats' in 'Cheat' menu. +

+

+ Now you'll find that the number of lives is 5 and the value doesn't decrease even you crash into an enemy. Snes9x keeps the value constant, so even if you do lose a life and life counter goes down by one, less than 20ms later, Snes9x resets the counter back to the value you chose! +

+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/08.html b/macosx/English.lproj/Snes9x Help/pgs/08.html new file mode 100644 index 00000000..fd0f2d4b --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/08.html @@ -0,0 +1,39 @@ + + + + + + + + Movie Support + + +

Movie Support

+

+ Movie support allows you to record your actions while playing a game. This can be used for your own personal playback or to show other people that you can do something without them having to be around when you did it. +

+

+ Snes9x also supports QuickTime export feature. Your realtime play or the recorded movie is exported to a QuickTime movie file. +

+

Recording the Movie

+

+ To record a movie, choose 'Record Movie...' in 'Option' menu and choose the location where the movie file (.smv) will be saved. Here you can decide when to start recording. If you want to record from the very start of a game, turn on 'Reset' check box. If you want to start recording from where you are already in a game, turn it off. You can also choose which players to be recorded. If you are playing by yourself leave 1P as the only one selected. The more players you choose to be recorded the larger the file size will be. To stop recording, pause the game. +

+

Playing Back the Movie

+

+ To play back the movie you recorded, choose 'Play Movie...' in 'Option' menu and choose the movie file. Make sure the movie was recorded with the same ROM that you have loaded. +

+

Re-recording the Movie

+

+ If you make a mistake while recording a movie, there is a movie re-record function. Simply freeze/defrost a game state anytime while recording. To re-record the movie that has already finished recording, choose 'Play Movie...' in 'Option' menu, turn off 'Read Only' check box, defrost during playing the movie, and it changes to re-recording mode. +

+

QuickTime Movie Export

+

+ Note that during the QuickTime recording there is no sound, but the exported QuickTime movie has sound. Choose 'Export to QuickTime Movie...' in 'Option' menu and choose the location where the QuickTime movie file will be saved. Press 'Compression...' button and set the compression settings by the general QuickTime dialog. 'Double Size' check box makes the movie size from 256x224/239 to 512x448/478. 'Overscan' check box is for games that use 239 or 478 lines. 'Frame Skip' menu decides frame rate of the movie, for example when the value is 1, NTSC games which have 60 fps are exported as 30 fps movie.
+ To make a QuickTime movie from .smv, choose 'Play Movie...' in 'Option' menu and turn on 'Export to QuickTime movie at a Time' check box. +

+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/09.html b/macosx/English.lproj/Snes9x Help/pgs/09.html new file mode 100644 index 00000000..3e07abca --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/09.html @@ -0,0 +1,104 @@ + + + + + + + + + Netplay Support + + +

Netplay Support

+

+ Netplay support allows up to five players to sit in front of different computers and simultaneously play the same game, or just watch someone else play a game. All the computers have to be connected to a network that allows TCP/IP traffic to flow between them; this includes a local Ethernet-style network, a direct-cable connection, or, if you're lucky and have short ping times, the Internet. +

+

+ Snes9x netplay inevitably synchronizes all the computers at the sacrifice of the speed of input response. Note that netplay is not compatible between platforms - You can't play via network with Windows users. +

+

How to Netplay

+

+ The player with the fastest Mac should act as the server. The others are clients. Server should open the port 6096/TCP.
+ Here is the workflow to netplay with up to five players. +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ServerIf you guys want to play with Multi Player 5, choose 'Multi Tap' in 'Input Device' in 'Emulation' menu. (Clients don't need to select it.)
    ServerOpen the ROM image. Pause the game.
    ServerChoose 'Server...' in 'Netplay' menu. The clients list appears. The first client is yourself.
    ClientChoose 'Client...' in 'Netplay' menu.
    ClientInput server's IP address and your name. Press 'Connect' button.
    ServerThe clients appear in the clients list with 'Connecting' status.
    ClientA ROM load dialog appears. Open the same ROM image as server's.
    ServerWait until all clients become 'Ready'. Press 'Play' button.
    ClientThe players list dialog appears. Press 'OK' button.
    ClientNetplay starts.
    ServerThe game is reset and netplay starts.
    ServerAdjust the timing by '2P-L' and '2P-R' button. If 'Show Onscreen Information' is active in 'Preferences' dialog, a value appears in both the server's and client's game screen. Increasing this value will smooth the frame rate, but also delay the input response.
    Server, ClientAll functions (screenshot, etc.) are unusable.
    ClientClients cannot stop netplay by themselves.
    ServerNetplay stops when server pauses the game.
    ServerSRAM file may be overwritten by this play.
    ClientSRAM file won't be overwritten by this play.
  • +
+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/10.html b/macosx/English.lproj/Snes9x Help/pgs/10.html new file mode 100644 index 00000000..3b1b8303 --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/10.html @@ -0,0 +1,82 @@ + + + + + + + + + Miscellaneous + + +

Miscellaneous

+

Where the Files are Stored

+

+ You can choose where Snes9x will look for BIOS images, patches (.ips), cheats (.cht), SRAM files (.srm), RTC files (.rtc) and freeze files (.frz) in 'File' tab in 'Preferences' dialog. +

+
+
Snes9x Folder
+
the subdirectories will be searched in the same folder as Snes9x.
+
ROM Folder
+
the files will all be in the same folder as the ROM image being used.
+
Application Support Folder (default)
+
the subdirectories will be created in /Users/yourname/Library/Application Support/Snes9x and searched.
+
+

Which Display is Used in Full Screen Mode

+

+ If you use two or more displays, in full screen mode Snes9x uses the display where the game window is shown. +

+

Handling the Game Window

+

+ The zoom button changes the window size as follows: 1x, 1x(wide), 2x, 2x(wide), 3x, 3x(wide), 4x, 4x(wide). 'wide' is mainly for the NTSC filters.
+ Dragging the resize control changes the window size manually. Dragging with pressing shift key keeps the aspect ratio of the window. +

+

+ The toolbar control appears when 'Keep Overscanned Height' in 'Preferences' dialog is off. It toggles the behavior when the SNES screen resolution changes: keeping the aspect ratio of the pixels with two black bars on the top and bottom of the window / always filling the window with the SNES screen without considering the aspect ratio of the pixels. +

+

Using IPS or UPS Patch

+

+ Snes9x automatically patches without overwriting the ROM image. +

+
    +
  • Put the IPS or UPS file into the proper directory. 'Patches' folder by default.
  • +
  • Rename the name to the same as the ROM image (except extension, it is '.ips' or '.ups').
  • +
  • (IPS only) If you want to use multiple IPS files at a time, set their extensions to '.000.ips', '.001.ips', ...
  • +
  • Make sure 'Use IPS / UPS Patch' is checked in 'Others' tab in 'Preferences' dialog.
  • +
  • Open and load the ROM image.
  • +
+

SPC File Dumping

+

+ SPC file (.spc) is the freeze state of only sound part, so it is known as SNES music data file. Dump the SPC file by Snes9x and play the file by SPC players like Audio Overload and PSFPlay.
+ Assign your gamepad button or keyboard to 'SPC' button in 'Configure Controllers' or 'Configure Keyboard' dialog. To dump a SPC file, press 'SPC' button while playing a game, or choose 'Save SPC File at Next Note-on' in 'Option' menu and resume the game.
+ Note that the actual dumping occurs at the next note-on event so that you can dump the BGM from just the beginning. +

+

Music Box

+

+ Music Box is to play the game music without playing the game. Pause the game and enter Music Box by 'Music Box...' in 'Option' menu, and you can enjoy the music with doing other things like surfing Internet.
+ There are two modes for playing music. Select in 'Others' tab in 'Preferences' dialog. +

+
+
Sound Emulation Only
+
in a shooting game, you may listen BGM endlessly.
+
Whole Emulation
+
in a shooting game, you may hear explosion sound and game over music.
+
+

+ Each mode stores the emulated state before entering Music Box, and restores after closing Music Box. 'Whole Emulation' makes a temporal freeze file. +

+

Sound Effect

+

+ You can use Apple's Matrix Reverb and/or Graphic Equalizer to enhance the game sounds. Call 'Sound Effect' dialog from 'Preferences' or 'Music Box' dialog. +

+

Core Image Filters

+

+ In Mac OS X 10.4 or later, some of the Core Image filters can be applied to the game screen. Turn on 'Use Core Image' in 'Preferences' dialog and choose 'Core Image Filter...' menu while playing a game. +

+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/11.html b/macosx/English.lproj/Snes9x Help/pgs/11.html new file mode 100644 index 00000000..11475122 --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/11.html @@ -0,0 +1,24 @@ + + + + + + + + Compatibility + + +

Compatibility

+

Compatibility with Other Ports

+

+ All the files generated by Snes9x are compatible between platforms, except for the extension of the freeze files. The only one difference is that Mac port puts the thumbnail screenshot into the resource fork of freeze and movie files, but the resource fork is usually deleted or separated when you send the file to your friends who use a PC. +

+

Compatibility with Other SNES Emulators

+

+ Cheat files (.cht) are common between Snes9x and ZSNES. RTC files (.rtc) are common between Snes9x and bsnes. SRAM files (.srm) should be common among all SNES emulators. +

+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/12.html b/macosx/English.lproj/Snes9x Help/pgs/12.html new file mode 100644 index 00000000..1cd67b20 --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/12.html @@ -0,0 +1,62 @@ + + + + + + + + + Problems + + +

Problems

+

Problems with ROMs

+

+ If Snes9x just displays a black screen for over 10 seconds after you've loaded a ROM image, then one of the following could be true: +

+
    +
  • You just loaded some random ROM image and it isn't even a SNES game or you only have part of the image. Snes9x only emulates games designed for the Super NES, not NES, or Master System, or Game Boy, or <insert your favorite old games system here>.
  • +
  • Someone has edited the Nintendo ROM information area inside the ROM image and Snes9x can't work out what format the ROM image is in. Try playing around with the ROM format options on the ROM load dialog.
  • +
  • The ROM image is corrupt. If you're loading from CD, I know it might sound silly, but is the CD dirty? Clean, unhacked ROM images will display [checksum ok] when first loaded, corrupt or hacked ROMs display [bad checksum].
  • +
  • The original SNES ROM cartridge had additional hardware inside that is not emulated yet and might never be.
  • +
  • You might be using a file that is compressed in a way Snes9x does not understand.
  • +
+

+ The following ROMs are known to currently not to work with any version of Snes9x: +

+
    +
  • + + + + + + + + + + + + + + +
    SD Gundam GXDSP-3
    Hayazashi Nidan Morita ShougiSeta-11
    Hayazashi Nidan Morita Shougi 2Seta-18
  • +
+

Problems with Sounds

+

+ If you hear crackling noise during the game, try the following to eliminate the noise: +

+
    +
  • Set 'Frame Skip' to 'Auto'.
  • +
  • Set 'Mix Buffer Length' to a larger value.
  • +
  • Turn on 'Allow Lag'.
  • +
  • Set 'Output Interval' to a larger value. Make sure it's smaller than 'Mix Buffer Length'.
  • +
  • Slightly adjust 'Input Rate' to a smaller value.
  • +
+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/13.html b/macosx/English.lproj/Snes9x Help/pgs/13.html new file mode 100644 index 00000000..b3c98b31 --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/13.html @@ -0,0 +1,87 @@ + + + + + + + + Technical Information + + +

Technical Information

+

What's Emulated?

+
    +
  • 65c816 main CPU.
  • +
  • Variable length machine cycles.
  • +
  • 8 channel DMA and H-DMA.
  • +
  • H-IRQ, V-IRQ and NMI.
  • +
  • Sony SPC700 sound CPU.
  • +
  • Sound DSP, with eight 16-bit, stereo channels, compressed samples, hardware envelope processing, echo, pitch modulation and digital FIR sound filter.
  • +
  • SRAM, a battery-backed RAM.
  • +
  • All background modes, 0 to 7.
  • +
  • All screen resolutions, 256x224, 256x239, 512x224, 512x239, 512x448 and 512x478.
  • +
  • Pseudo hi-res mode.
  • +
  • 8x8, 16x8 and 16x16 tile sizes, flipped in either direction.
  • +
  • 32x32, 32x64, 64x32 and 64x64 screen tile sizes.
  • +
  • Vertical and horizontal offset-per-tile.
  • +
  • 128 8x8, 16x16, 32x32 and 64x64 sprites, flipped in either direction.
  • +
  • Sub-screen and fixed color blending effects.
  • +
  • Mosaic effects.
  • +
  • Mode 7 screen rotation, scaling and screen flipping.
  • +
  • Single and dual graphic clip windows, with all four logic combination modes.
  • +
  • Color blending effects only inside or outside a window.
  • +
  • Palette changes during frame.
  • +
  • Direct color mode - uses tile and palette-group data directly as RGB value.
  • +
  • SNES Mouse.
  • +
  • Super Scope, emulated using computer mouse.
  • +
  • Justifier, by Konami, similar to the Super Scope and used only in Lethal Enforcers.
  • +
  • Multi Player 5, allowing up to five people to play games simultaneously on games that support that many players.
  • +
  • Super FX, a fast RISC CPU used in several games.
  • +
  • SA-1, a faster version of main CPU with some functions, used in several games.
  • +
  • DSP-1, a custom chip used in several games, mainly racing games.
  • +
  • DSP-2, a custom chip used only in Dungeon Master.
  • +
  • DSP-4, a custom chip used only in Top Gear 3000.
  • +
  • C4, a sprite scaler/rotator/line drawer/simple maths co-processor chip used only in Megaman X2 and X3.
  • +
  • Seta-10, a custom chip used only in F1 Race of Champions 2.
  • +
  • OBC1, a sprite management chip used only in Metal Combat.
  • +
  • S-DD1, a data decompression chip used only in Star Ocean and Street Fighter 2 Alpha.
  • +
  • SPC7110, similar in use to S-DD1, used in a few Hadoson games.
  • +
  • S-RTC, a real-time clock chip, used only in Dai Kaijyu Monogatari 2.
  • +
  • Satellaview and BS-X, only partially.
  • +
+

What's Not?

+
    +
  • Exact sub-cycle timings of communication among most of parts - main CPU, sound CPU, DMA, H-DMA, IRQ, NMI, and so on. Snes9x cannot run games that require severe timings!
  • +
  • Any other odd chips that manufactures sometimes placed inside the cartridge to enhance games and as a nice side-effect, also act as an anti-piracy measure. (DSP-3, Seta-11 and Seta-18, as examples)
  • +
  • The expansion slot found in many carts.
  • +
+

Custom Chips

+

Super FX

+

+ The Super FX is a 10.5/21MHz RISC CPU developed by Argonaut Software used as a game enhancer by several game titles. Released SNES Super FX games included Yoshi's Island, Doom, Winter Gold, Dirt Trax FX, StarFox, Stunt Race FX and Vortex. +

+

SA-1

+

+ The SA-1 is a fast, custom 65c816 8/16-bit processor, the same as inside the SNES itself, but clocked at 10MHz compared to a maximum of 3.58MHz for the CPU inside the SNES. The SA-1 isn't just a CPU; it also contains some extra circuits developed by Nintendo which includes some very fast RAM, a memory mapper, DMA and, several real-time timers. +

+

C4

+

+ The C4 is custom Capcom chip used only in the Megaman X2 and Megaman X3 games. It can scale and rotate images, draw line-vector objects and do some simple maths to rotate them. +

+

S-DD1

+

+ The S-DD1 is a custom data decompression chip that can decompress data in real-time as the SNES DMA's data from the ROM to RAM. Only two games use the chip: Star Ocean and Street Fighter Alpha 2. +

+

SPC7110

+

+ The SPC7110 is a compression and memory mapping chip. It provides a few extra features as well. It functions as an RTC interface, and has a multiply/divide unit that has more precision than the SNES. The SPC7110 is found only in 4 games: Super Power League 4, Far East of Eden Zero, Far East of Eden Zero - Shounen Jump no Shou and Momotaro Dentetsu Happy. +

+

Others

+

+ Other known custom chips: DSP-1, DSP-2, DSP-3, DSP-4, Seta-10, Seta-11, Seta-18, OBC1 and S-RTC. +

+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/14.html b/macosx/English.lproj/Snes9x Help/pgs/14.html new file mode 100644 index 00000000..e157ce9e --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/14.html @@ -0,0 +1,118 @@ + + + + + + + + References + + +

References

+

Preferences Dialog

+

Graphics Tab

+
+
Full Screen Mode
+
Toggles full screen/windowed mode. Press esc key to hide full screen window and pause the game.
+
Switch Monitor Resolution
+
Toggles between scaling full screen graphics to the current screen resolution or changing the screen resolution to fit Snes9x's needs.
+
Show Frame Rate
+
Toggles display of the frame rate on/off.
+
Transparency Effects
+
Toggles transparency effects on/off. Transparency effect is used in almost all games so this option is just for hack.
+
Video Mode
+
Choose the image scaling filter which is applied to the raw SNES image.
+
Multitask
+
When this option is on, the rendering process is separated from the emulation thread (except blocky and smooth modes).
+
Keep Overscanned Height
+
Keeps the screen height always 239/478, for some games that change screen height frequently.
+
Sync to Vertical Blank
+
Synchronizes the render timing to the monitor's vertical refresh rate.
+
Stretch Image in Full Screen Mode
+
Stretches the image to fill the screen in full screen mode.
+
Aspect Ratio
+
The aspect ratio of above option: the left is proportional and the right is full width of the monitor.
+
Use Core Image
+
Applies additional Core Image effect after the image filter is applied.
+
Filter...
+
Choose the Core Image filter.
+
Use 32 Bit Color
+
Uses 16,777,216 colors.
+
Use Screen Curvature
+
Adds a warp effect like a CRT-based television.
+
Warp
+
The degree of curvature.
+
+

Sound Tab

+
+
Synchronize
+
Tries and ensures all available samples are buffered so there are no overruns.
+
16 Bit Playback
+
Enables 16-bit playback instead of 8-bit.
+
Stereo
+
Enables stereo sound instead of mono.
+
Reverse Stereo
+
Swaps the left and right stereo channels.
+
Effect...
+
Opens 'Sound Effect' dialog.
+
Playback Rate
+
The real SNES is 32000 Hz. Any values other than 32000 Hz will cause resampling.
+
Output Interval
+
Make sure this value is smaller than the mix buffer length.
+
Mix Buffer Length
+
Too short length will cause crackling noise.
+
Allow Lag
+
Safer from crackling noise, but time-lag becomes more noticeable.
+
Volume
+
Volume of the whole Snes9x sounds.
+
Input Rate
+
Adjusts the sound rate through resampling. For every Input Rate samples generated by the SNES, Playback Rate samples will be produced.
+
+

File Tab

+
+
Save Data in
+
Choose the folder where Snes9x will look for files.
+
Auto Save SRAM
+
Updates SRAM file when SRAM contents are modified. This may cause frequent disk access.
+
+

Accuracy Tab

+
+
HDMA Timing Hack
+
Changes HDMA timing and will 'fix' some games' glitches, but breaks many other games. The default value is 100.
+
Skip CPU Emulation Until the Next Event Comes
+
Skips internal CPU emulation for speed-ups until the next event comes.
+
Allow Invalid VRAM Access
+
Allows to write to VRAM outside blank periods.
+
Apply Specific Game Hacks
+
Applies special hacks for games that can't be emulated correctly.
+
Frame Skip
+
Adjust this value if your Mac is slow.
+
Speed in Turbo Mode
+
The speed when turbo mode is on. Modify in-game with Fn+T, Fn+Y.
+
+

Others Tab

+
+
Toggle Turbo Button
+
Sets 'Turbo' button as a toggle switch.
+
Show Onscreen Information
+
Shows messages from Snes9x on the game screen. When off, messages are put in the standard console.
+
Open Choose ROM Image Dialog at Startup
+
Choose whether open dialog should be shown when Snes9x is launched.
+
Show Dates and Times in Freeze State Selection Screen
+
Shows time stamps on thumbnails in freeze/defrost screen.
+
Save Window Size and Position
+
Saves the sizes and positions of the game window and dialogs so they come back to the same place.
+
Use IPS / UPS Patch
+
When this option is on, Snes9x automatically loads the .ips or .ups file and patch the ROM image.
+
Boot Up BS Games from BS-X
+
When this option is on, BS-X ROM is loaded first, then you launch BS games from the menu in BS-X.
+
When in Background
+
Choose the behavior of Snes9x when it is in back of other applications.
+
Music Box
+
Choose the behavior of Music Box: 'Sound Emulation Only' to only emulate the music system, and 'Whole Emulation' to also emulate the CPU. Music that depends on the CPU running will not sound right without 'Whole Emulation.'
+
+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/pgs/15.html b/macosx/English.lproj/Snes9x Help/pgs/15.html new file mode 100644 index 00000000..e8b5e491 --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/pgs/15.html @@ -0,0 +1,69 @@ + + + + + + + + Credits + + +

Credits

+
    +
  • Jerremy Koot for all his hard work on previous versions of Snes96, Snes97 and Snes9x.
  • +
  • Ivar for the original Super FX C emulation, DSP-1 emulation work and information on both chips.
  • +
  • zsKnight and _Demo_ for the Intel Super FX assembler, DSP-1 and C4 emulation code.
  • +
  • zsKnight and _Demo_ for all the other ideas and code I've nicked off them; they've nicked lots of my ideas and information too!
  • +
  • John Weidman and Darkforce for the S-RTC emulation information and code.
  • +
  • Kreed and Maxim Stepin for excellent image enhancer routines.
  • +
  • Nose000 for code changes to support various Japanese SNES games.
  • +
  • Neill Corlett for the IPS patching support code.
  • +
  • DiskDude's SNES Kart v1.6 document for the Game Genie(TM) and Pro-Action Replay cheat system information.
  • +
  • Lord ESNES for some nice chats and generally useful stuff.
  • +
  • Lee Hyde (lee@jlp1.demon.co.uk) for his quest for sound information and the Windows 95 icon.
  • +
  • Shawn Hargreaves for the rather good Allegro 3.0 DOS library.
  • +
  • Robert Grubbs for the SideWinder information - although I didn't use his actual driver in the end.
  • +
  • Steve Snake for his insights into SNES sound sample decompression.
  • +
  • Vojtech Pavlik for the Linux joystick driver patches.
  • +
  • Maciej Babinski for the basics of Linux's DGA X server extensions.
  • +
  • Alexander Larsson for the GGI Linux port code.
  • +
  • Harald Fielker for the original sound interpolation code (never used directly due to problems).
  • +
  • Takehiro TOMINAGA for many speed up suggestions and bug fixes.
  • +
  • Predicador for the Windows icon.
  • +
  • Lindsey Dubb for the mode 7 bi-linear filter code and the improved color addition and subtraction code.
  • +
  • Anti Resonance for his super-human efforts to help get his fast sound CPU core and sound DSP core working in Snes9x.
  • +
  • Brad Martin and TRAC for better and refined sound emulation.
  • +
  • ernstp and entonne for patches and testing on Linux PPC.
  • +
  • byuu for the most exact timing information and tons of the newest technical findings.
  • +
  • Blargg for the most accurate timings between sound CPU and DSP and exact sound emulation codes.
  • +
  • pagefault, TRAC, Dark Force, byuu, and others who have donated ideas and/or code to the project.
  • +
+

+ Nintendo is a trademark.
+ Super NES, Super Famicon, Super Scope and Super FX are trademarks of Nintendo.
+ Sufami Turbo is a trademark of Bandai Co., Ltd.
+ Game Genie is a trademark of Lewis Galoob Toys, Inc.
+ Pro Action Replay is a trademark of Datel Inc.
+ Macintosh, Mac and Mac OS X are trademarks of Apple Computer, Inc.
+ UNIX is a trademark of The Open Group.
+ Linux is a trademark of Linus Torvalds.
+ Windows is a trademark of Microsoft Corp.
+ Intel is a trademark of Intel Corp.
+ PowerPC is a trademark of International Business Machines Corp.
+ Sony is a trademark of Sony Corp.
+ Konami and Justifier are trademarks of Konami Corp.
+ Hudson is a trademark of Husdon Soft Co., Ltd.
+ Capcom is a trademark of Capcom Co., Ltd. +

+

+ Gary Henderson +

+

+ Edited for Mac port by: zones (kasumitokoduck@yahoo.com)
+ Updated most recently by: 2009/12/20 zones +

+

+ <Prev  Top  Next> +

+ + diff --git a/macosx/English.lproj/Snes9x Help/sty/style.css b/macosx/English.lproj/Snes9x Help/sty/style.css new file mode 100644 index 00000000..2d568be6 --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/sty/style.css @@ -0,0 +1,62 @@ +/* */ + +a:hover +{ + text-decoration: underline; +} + +h1 +{ + font-size: 14pt; + font-family: "Lucida Grande", Helvetica, Arial; +} + +h2 +{ + font-size: 12pt; + font-family: "Lucida Grande", Helvetica, Arial; +} + +h3 +{ + font-size: 10pt; + font-family: "Lucida Grande", Helvetica, Arial; + margin-top: 3em; +} + +h4 +{ + font-size: 9pt; + font-family: "Lucida Grande", Helvetica, Arial; +} + +p +{ + font-size: 9pt; + font-family: "Lucida Grande", Helvetica, Arial; +} + +table +{ + font-size: 9pt; + font-family: "Lucida Grande", Helvetica, Arial; +} + +ul +{ + font-size: 9pt; + font-family: "Lucida Grande", Helvetica, Arial; + padding-left: 3em; +} + +dl +{ + font-size: 9pt; + font-family: "Lucida Grande", Helvetica, Arial; + padding-left: 3em; +} + +dd +{ + margin-bottom: 0.5em; +} diff --git a/macosx/English.lproj/Snes9x Help/sty/top.css b/macosx/English.lproj/Snes9x Help/sty/top.css new file mode 100644 index 00000000..f446c1ac --- /dev/null +++ b/macosx/English.lproj/Snes9x Help/sty/top.css @@ -0,0 +1,68 @@ +/* */ + +a +{ + color: gray; + font-family: "Lucida Grande", Helvetica, Arial; + text-decoration: none; +} + +a:hover +{ + text-decoration: underline; +} + +h1 +{ + color: gray; + font-size: 20pt; + font-family: "Lucida Grande", Helvetica, Arial; + margin: 0px 10px 10px 10px; + letter-spacing: -1pt; + padding-top: 20px; +} + +h2 +{ + color: gray; + font-weight: 300; + font-size: 8pt; + font-family: "Lucida Grande", Helvetica, Arial; + margin-bottom: -12px; + padding-left: 6px; +} + +ul +{ + color: gray; + font-size: 12pt; + font-family: "Lucida Grande", Helvetica, Arial; + margin-left: -8px; + padding-top: 18px; + padding-bottom: 18px; + border-left: 1px solid gray; + list-style-type: none; +} + +#contentleft +{ + float: left; + margin-top: 76px; + width: 230px; +} + +#contentright +{ + float: left; + margin-top: 14px; + width: 230px; +} + +#frame +{ + text-align: left; + margin-top: 10px; + margin-right: auto; + margin-left: auto; + width: 460px; +} diff --git a/macosx/English.lproj/Snes9x.nib/classes.nib b/macosx/English.lproj/Snes9x.nib/classes.nib new file mode 100644 index 00000000..c4b887e7 --- /dev/null +++ b/macosx/English.lproj/Snes9x.nib/classes.nib @@ -0,0 +1,8 @@ + + + + + IBVersion + 1 + + diff --git a/macosx/English.lproj/Snes9x.nib/info.nib b/macosx/English.lproj/Snes9x.nib/info.nib new file mode 100644 index 00000000..61b902d4 --- /dev/null +++ b/macosx/English.lproj/Snes9x.nib/info.nib @@ -0,0 +1,20 @@ + + + + + IBFramework Version + 740 + IBLastKnownRelativeProjectPath + ../ntsctest.xcodeproj + IBOldestOS + 6 + IBOpenObjects + + 265 + + IBSystem Version + 10C540 + targetFramework + IBCarbonFramework + + diff --git a/macosx/English.lproj/Snes9x.nib/objects.xib b/macosx/English.lproj/Snes9x.nib/objects.xib new file mode 100644 index 00000000..13a158b0 --- /dev/null +++ b/macosx/English.lproj/Snes9x.nib/objects.xib @@ -0,0 +1,7648 @@ + + + + + + + 7__Y + 7__Y + 0 + 1304 + 4 + TRUE + 32768 + 202 70 28 28 + 368 222 396 250 + + + 4Srt + 4Srt + 0 + 1010 + 4 + TRUE + 32768 + 155 70 28 28 + 222 175 250 203 + + + 4_Rt + 4_Rt + 0 + 1003 + 4 + TRUE + 32768 + 72 70 28 28 + 222 92 250 120 + + + Force not Interleaved + TRUE + + + osx_ + 804 + Sets 'Turbo' button as a toggle switch. + Toggle Turbo Button + 18 20 207 18 + 62 39 80 246 + + + 1 + Licensee : + -1 + 20 314 128 13 + 314 20 327 148 + + + Sele + 11 + 0 + 811 + 4 + 33024 + 123 74 28 28 + 122 494 150 522 + + + CNSL + CNSL + 2 + Cancel + 265 152 70 20 + 152 265 172 335 + + + RLst + 1 + RLst + Last Value + 11 158 92 14 + 158 253 172 345 + + + AChk + 2222 + 0 + 819 + 4 + 33024 + 266 74 28 28 + 280 637 308 665 + + + Outp + 1 + output + -2 + 156 272 186 13 + 272 156 285 342 + + + LChk + 111 + 0 + 808 + 4 + 33024 + 102 30 28 28 + 236 143 264 171 + + + NTSC+TV S-Video + TRUE + + + #3 + TRUE + CPr3 + + + grap + 6 + Uses 16,777,216 colors. + Use 32 Bit Color + 326 183 193 18 + 225 347 243 540 + + + CCTL + 106 + 1 + Interleave Mode : + -1 + 10 213 23 307 + + + 1 + SRAM Size : + -1 + 20 188 128 13 + 188 20 201 148 + + + grap + 5 + Toggles transparency effects on/off. Transparency effect is used in almost all games so this option is just for hack. + Transparency Effects + 18 86 192 18 + 128 39 146 231 + + + Window + _NSWindowsMenu + + + Minimize + m + TRUE + TRUE + mini + + + Minimize All + m + TRUE + TRUE + 1572864 + mina + + + Zoom + TRUE + zoom + + + TRUE + + + Bring All to Front + TRUE + TRUE + bfrt + + + Arrange in Front + TRUE + TRUE + 1572864 + frnt + + + + + Righ + 222 + 0 + 815 + 4 + 33024 + 76 74 28 28 + 280 117 308 145 + + + Pad + TRUE + EIp1 + + + Num_ + 2 + 1 + 10 + -1 + 242 35 19 13 + 399 283 412 302 + + + Cheat Entry... + TRUE + Hent + + + 8_Up + 8_Up + 0 + 1400 + 4 + TRUE + 32768 + 42 40 28 28 + 338 384 366 412 + + + BRem + 1 + BRem + Remove from List + 34 32 152 20 + 378 276 398 428 + + + 5Sel + 5Sel + 0 + 1111 + 4 + TRUE + 32768 + 119 70 28 28 + 222 461 250 489 + + + NAME + Snes9x + 1 + 62 85 184 18 + 85 62 103 246 + + + grap + 4 + Applies additional Core Image effect after the image filter is applied. + Use Core Image + 326 161 120 18 + 203 347 221 467 + + + grap + 12 + Keeps the screen height always 239/478, for some games that change screen height frequently. + Keep Overscanned Height + 326 86 193 18 + 128 347 146 540 + + + AEtx + 1 + TRUE + TRUE + 110 74 90 13 + 74 110 87 200 + + + PANE + 1000 + 2 + + + PCTL + 101 + 1 + Read Only + 10 7 24 90 + + + PCTL + 102 + 1 + Export to QuickTime Movie at a Time + 10 99 24 335 + + + 0 0 34 433 + + + > + TRUE + + + 3__X + 3__X + 0 + 906 + 4 + TRUE + 32768 + 232 40 28 28 + 46 896 74 924 + + + NEW_ + NEW_ + + 1 + 2 + + New + 432 20 103 20 + 20 432 40 535 + + + SizC + 1 + calculated rom size + -2 + 156 146 186 13 + 146 156 159 342 + + + 4P : + 20 92 28 16 + 92 20 108 48 + + + PLNM + 2 + 56 68 122 16 + 68 56 84 178 + + + BRes + 1 + BRes + Restore List + 34 57 152 20 + 403 276 423 428 + + + ScoT + ScoT + 0 + 829 + 4 + TRUE + 32768 + 190 100 28 28 + 398 854 426 882 + + + msc2 + 601 + TRUE + TRUE + 165 60 77 16 + 102 186 118 263 + + + BMrk + All frames are drawn without adjusting times. Make sure 'Synchronize' in 'Sound' tab in 'Preferences' dialog is turned off. + Benchmark Test + 18 20 133 18 + 20 18 38 151 + + + YChk + 22 + 0 + 816 + 4 + 33024 + 206 74 28 28 + 122 577 150 605 + + + Name : + -1 + 20 52 62 16 + 52 20 68 82 + + + Music Box + TRUE + Ombx + + + 1 + Player 8 + FALSE + 342 298 302 140 + + + 8_Lf + 8_Lf + 0 + 1402 + 4 + TRUE + 32768 + 12 70 28 28 + 368 354 396 382 + + + + 8_Dn + 8_Dn + 0 + 1401 + 4 + TRUE + 32768 + 42 100 28 28 + 398 384 426 412 + + + 8_Rt + 8_Rt + 0 + 1403 + 4 + TRUE + 32768 + 72 70 28 28 + 368 414 396 442 + + + 8__A + 8__A + 0 + 1407 + 4 + TRUE + 32768 + 262 70 28 28 + 368 604 396 632 + + + 8__Y + 8__Y + 0 + 1404 + 4 + TRUE + 32768 + 202 70 28 28 + 368 544 396 572 + + + 8__B + 8__B + 0 + 1405 + 4 + TRUE + 32768 + 232 100 28 28 + 398 574 426 602 + + + 8Sel + 8Sel + 0 + 1411 + 4 + TRUE + 32768 + 119 70 28 28 + 368 461 396 489 + + + 8Srt + 8Srt + 0 + 1410 + 4 + TRUE + 32768 + 155 70 28 28 + 368 497 396 525 + + + 8__X + 8__X + 0 + 1406 + 4 + TRUE + 32768 + 232 40 28 28 + 338 574 366 602 + + + 8__L + 8__L + 0 + 1408 + 4 + TRUE + 32768 + 98 26 28 28 + 324 440 352 468 + + + 8__R + 8__R + 0 + 1409 + 4 + TRUE + 32768 + 176 26 28 28 + 324 518 352 546 + + + 298 342 438 644 + + + : + 70 22 7 16 + 22 70 38 77 + + + 7_Up + 7_Up + 0 + 1300 + 4 + TRUE + 32768 + 42 40 28 28 + 338 62 366 90 + + + Pane + + 1 + 1 + 2 + 2 + + 2 + 20 20 213 401 + 20 20 421 233 + + + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + TRUE + FALSE + 11 + 53 + 7 + Add to Entry + + 0 0 328 166 + + + 1 + Address : + -1 + 16 20 83 13 + 20 16 33 99 + + + AEad + 1 + address + 107 20 96 13 + 20 107 33 203 + + + + 1 + Current Value : + -1 + 16 47 83 13 + 47 16 60 99 + + + 1 + Cheat Value : + -1 + 16 74 83 13 + 74 16 87 99 + + + AEcv + 1 + current value + 107 47 96 13 + 47 107 60 203 + + + SHTa + 1 + SHTa + 1 + Add + 237 128 70 20 + 128 237 148 307 + + + SHTc + 1 + SHTc + 2 + Cancel + 157 128 70 20 + 128 157 148 227 + + + 1 + Description : + -1 + 16 101 83 13 + 101 16 114 99 + + + AEde + 1 + TRUE + TRUE + 110 101 195 13 + 101 110 114 305 + + + 0 0 166 328 + + 80 40 246 368 + 0 0 768 1024 + + + Cheat Finder... + TRUE + Hfnd + + + FFUp + FFUp + 0 + 836 + 4 + TRUE + 32768 + 262 26 28 28 + 324 926 352 954 + + + msc2 + 604 + 10 + -1 + 173 243 20 16 + 285 194 301 214 + + + AChk + 2 + 0 + 819 + 4 + 33024 + 266 74 28 28 + 122 307 150 335 + + + Up + 1111 + 0 + 800 + 4 + 33024 + 46 44 28 28 + 250 417 278 445 + + + Choose the behavior of Snes9x when it is in back of other applications. + When in Background : + 20 134 146 16 + 176 41 192 187 + + + 1 + Player 4 + FALSE + 20 152 302 140 + + + 4_Lf + 4_Lf + 0 + 1002 + 4 + TRUE + 32768 + 12 70 28 28 + 222 32 250 60 + + + 4_Up + 4_Up + 0 + 1000 + 4 + TRUE + 32768 + 42 40 28 28 + 192 62 220 90 + + + 4_Dn + 4_Dn + 0 + 1001 + 4 + TRUE + 32768 + 42 100 28 28 + 252 62 280 90 + + + + 4__A + 4__A + 0 + 1007 + 4 + TRUE + 32768 + 262 70 28 28 + 222 282 250 310 + + + 4__Y + 4__Y + 0 + 1004 + 4 + TRUE + 32768 + 202 70 28 28 + 222 222 250 250 + + + 4__B + 4__B + 0 + 1005 + 4 + TRUE + 32768 + 232 100 28 28 + 252 252 280 280 + + + 4Sel + 4Sel + 0 + 1011 + 4 + TRUE + 32768 + 119 70 28 28 + 222 139 250 167 + + + + 4__X + 4__X + 0 + 1006 + 4 + TRUE + 32768 + 232 40 28 28 + 192 252 220 280 + + + 4__L + 4__L + 0 + 1008 + 4 + TRUE + 32768 + 98 26 28 28 + 178 118 206 146 + + + 4__R + 4__R + 0 + 1009 + 4 + TRUE + 32768 + 176 26 28 28 + 178 196 206 224 + + + 152 20 292 322 + + + snd_ + 205 + 4 + + Popup: + + + 48000 Hz + TRUE + + + 44100 Hz + TRUE + + + 35000 Hz + TRUE + + + 32000 Hz + TRUE + TRUE + + + 30000 Hz + TRUE + + + 22050 Hz + TRUE + + + 16000 Hz + TRUE + + + 11025 Hz + TRUE + + + 8000 Hz + TRUE + + + + 415 19 127 20 + 61 436 81 563 + + + Tr_i + Tr_i + 18 39 13 14 + 39 18 53 31 + + + Popup: + + + Blocky + TRUE + + + TV + TRUE + + + Smooth + TRUE + TRUE + + + Super Eagle + TRUE + + + 2xSaI + TRUE + + + Super 2xSaI + TRUE + + + EPX + TRUE + + + hq2x + TRUE + + + hq3x + TRUE + + + hq4x + TRUE + + + NTSC Composite + TRUE + + + NTSC S-Video + TRUE + + + NTSC RGB + TRUE + + + NTSC Monochrome + TRUE + + + NTSC+TV Composite + TRUE + + + + NTSC+TV RGB + TRUE + + + NTSC+TV Monochrome + TRUE + + + + + 60 ms + TRUE + + + Note : These Hacks Need to Reopen ROM Image to Achieve Effects. + 20 21 456 16 + 63 41 79 497 + + + 4 + TRUE + + + 6_Rt + 6_Rt + 0 + 1203 + 4 + TRUE + 32768 + 72 70 28 28 + 222 736 250 764 + + + 5 + TRUE + + + Righ + 11 + 0 + 803 + 4 + 33024 + 76 74 28 28 + 122 447 150 475 + + + Name + 4 + 219 116 118 16 + 116 219 132 337 + + + 3__Y + 3__Y + 0 + 904 + 4 + TRUE + 32768 + 202 70 28 28 + 76 866 104 894 + + + LChk + 1 + 0 + 808 + 4 + 33024 + 102 30 28 28 + 78 143 106 171 + + + 6__L + 6__L + 0 + 1208 + 4 + TRUE + 32768 + 98 26 28 28 + 178 762 206 790 + + + ROM Folder + TRUE + + + Private + TRUE + + + Storage Hint : + 36 178 90 16 + 178 36 194 126 + + + grap + 3 + Toggles display of the frame rate on/off. + Show Frame Rate + 18 64 192 18 + 106 39 124 231 + + + Cheat + 132 + + + Apply Cheats + TRUE + Hapl + + + TRUE + + + + + + + Up + 11 + 0 + 800 + 4 + 33024 + 46 44 28 28 + 92 417 120 445 + + + Star + 2222 + 0 + 822 + 4 + 33024 + 159 74 28 28 + 280 530 308 558 + + + bar2 + bar2 + 0 + 2 + 256 + 34 6 12 12 + 214 55 226 67 + + + Updates SRAM file when SRAM contents are modified. This may cause frequent disk access. + Auto Save SRAM : + -1 + 79 62 112 16 + 104 100 120 212 + + + YChk + 2 + 0 + 816 + 4 + 33024 + 206 74 28 28 + 122 247 150 275 + + + 1__X + 1__X + 0 + 806 + 4 + TRUE + 32768 + 232 40 28 28 + 46 252 74 280 + + + BWat + BWat + 0 + 3 + Watch + 512 + 127 269 60 17 + 269 369 286 429 + + + + TRUE + TRUE + + + Popup: + + + 20 ms + TRUE + + + 40 ms + TRUE + + + + 80 ms + TRUE + + + 100 ms + TRUE + TRUE + + + 120 ms + TRUE + + + 140 ms + TRUE + + + 160 ms + TRUE + + + 180 ms + TRUE + + + 200 ms + TRUE + + + + + 4 Bytes + TRUE + + + TRUE + + + BSea + 1 + BSea + 1 + Search + 109 204 77 20 + 204 351 224 428 + + + RCTL + 109 + 1 + Comment : + 34 6 47 66 + + + bard + bard + 0 + 5 + 256 + 206 6 12 12 + 214 227 226 239 + + + 1 + Common + FALSE + 664 298 302 140 + + + _DeF + _DeF + 0 + 826 + 4 + TRUE + 32768 + 48 63 28 28 + 361 712 389 740 + + + + __FF + __FF + 0 + 824 + 4 + TRUE + 32768 + 190 26 28 28 + 324 854 352 882 + + + MouR + MouR + 0 + 851 + 4 + TRUE + 32768 + 48 100 28 28 + 398 712 426 740 + + + ScoC + ScoC + 0 + 831 + 4 + TRUE + 32768 + 262 100 28 28 + 398 926 426 954 + + + _SPC + _SPC + 0 + 828 + 4 + TRUE + 32768 + 190 63 28 28 + 361 854 389 882 + + + ScoP + ScoP + 0 + 830 + 4 + TRUE + 32768 + 226 100 28 28 + 398 890 426 918 + + + _Snp + _Snp + 0 + 827 + 4 + TRUE + 32768 + 226 63 28 28 + 361 890 389 918 + + + _Esc + _Esc + 0 + 837 + 4 + TRUE + 32768 + 262 63 28 28 + 361 926 389 954 + + + MouL + MouL + 0 + 850 + 4 + TRUE + 32768 + 12 100 28 28 + 398 676 426 704 + + + _Frz + _Frz + 0 + 825 + 4 + TRUE + 32768 + 12 63 28 28 + 361 676 389 704 + + + Ofsc + Ofsc + 0 + 832 + 4 + TRUE + 32768 + 154 100 28 28 + 398 818 426 846 + + + __Fn + __Fn + 0 + 833 + 4 + TRUE + 32768 + 12 26 28 28 + 324 676 352 704 + + + _Alt + _Alt + 0 + 834 + 4 + TRUE + 32768 + 48 26 28 28 + 324 712 352 740 + + + __TC + __TC + 0 + 838 + 4 + TRUE + 32768 + 84 26 28 28 + 324 748 352 776 + + + + FFDn + FFDn + 0 + 835 + 4 + TRUE + 32768 + 226 26 28 28 + 324 890 352 918 + + + 298 664 438 966 + + + 32 ms + TRUE + + + + S9xMenu + _NSMainMenu + + + Snes9x + + Snes9x + 128 + _NSAppleMenu + + + About Snes9x + TRUE + 0 + abou + + + + + + File + + File + 129 + + + Open ROM Image... + o + TRUE + open + + + Open Multiple ROM Images... + O + TRUE + 1179648 + Mult + + + Open Recent + TRUE + Frec + + + TRUE + + + Close + w + TRUE + clos + + + TRUE + + + ROM Information + i + TRUE + Finf + + + + + + Edit + + Edit + 130 + + + Undo + z + TRUE + undo + + + Redo + Z + TRUE + redo + + + TRUE + + + Cut + x + TRUE + cut + + + Copy + c + TRUE + copy + + + Paste + v + TRUE + past + + + Delete + TRUE + clea + + + Select All + a + TRUE + sall + + + + + + Emulation + + Emulation + 131 + + + Run + r + TRUE + Erun + + + TRUE + + + Software Reset + TRUE + Esrs + + + Hardware Reset + TRUE + Erst + + + TRUE + + + Input Device + TRUE + + Input Device + 202 + + + + Mouse (Port 1) + TRUE + EIp2 + + + Mouse (Port 2) + TRUE + EIp3 + + + Super Scope + TRUE + EIp4 + + + Multi Tap + TRUE + EIp5 + + + Multi Taps (Both Ports) + TRUE + EIp6 + + + Justifier + TRUE + EIp7 + + + Justifiers (Two Players) + TRUE + EIp8 + + + + + + + + + Config + + Config + 134 + + + Configure Keyboard... + TRUE + Ckey + + + Configure Controllers... + TRUE + Cpad + + + TRUE + + + Automatic Fire... + TRUE + Caut + + + TRUE + + + Controllers Preset + TRUE + + Controllers Preset + 201 + + + #1 + TRUE + CPr1 + + + #2 + TRUE + CPr2 + + + + #4 + TRUE + CPr4 + + + #5 + TRUE + CPr5 + + + + + + + + + Netplay + + Netplay + 135 + + + Server... + TRUE + Nser + + + Client... + TRUE + Ncli + + + + + + Cheat + + + + Option + + Option + 133 + + + Freeze State + f + TRUE + Ofrz + + + Defrost State + d + TRUE + Odfr + + + TRUE + + + Freeze State to... + F + TRUE + 1179648 + Ofrd + + + Defrost State from... + D + TRUE + 1179648 + Odfd + + + TRUE + + + Record Movie... + TRUE + MVrc + + + Play Movie... + TRUE + MVpl + + + TRUE + + + Export to QuickTime Movie... + TRUE + QTmv + + + TRUE + + + Save SPC File at Next Note-on + TRUE + Ospc + + + Save SRAM File Now + TRUE + Osrm + + + TRUE + + + Core Image Filter... + TRUE + Ocif + + + TRUE + + + + + + + Window + + + + + + Up + 22 + 0 + 812 + 4 + 33024 + 46 44 28 28 + 92 417 120 445 + + + RThs + 1 + RThs + This Value : + 11 176 92 14 + 176 253 190 345 + + + CCTL + 101 + 1 + + Popup: + + + Auto Detect + TRUE + TRUE + + + TRUE + + + Force LoROM + TRUE + + + Force HiROM + TRUE + + + + 8 95 25 205 + + + + ≠ + TRUE + + + Popup: + + + = + TRUE + TRUE + + + + + ≥ + TRUE + + + < + TRUE + + + ≤ + TRUE + + + + + RCTL + 105 + 1 + 5 + 8 264 22 296 + + + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + ROM Information + + 0 0 362 422 + + + 1 + Cart Name : + -1 + 20 20 128 13 + 20 20 33 148 + + + + 1 + Contents : + -1 + 20 62 128 13 + 62 20 75 148 + + + 1 + Size (header) : + -1 + 20 167 128 13 + 167 20 180 148 + + + 1 + Size (calculated) : + -1 + 20 146 128 13 + 146 20 159 148 + + + 1 + Speed : + -1 + 20 104 128 13 + 104 20 117 148 + + + 1 + Game Code : + -1 + 20 41 128 13 + 41 20 54 148 + + + + 1 + Checksum (calculated) : + -1 + 20 209 128 13 + 209 20 222 148 + + + 1 + Checksum (header) : + -1 + 20 230 128 13 + 230 20 243 148 + + + 1 + Complement (header) : + -1 + 20 251 128 13 + 251 20 264 148 + + + 1 + Video Output : + -1 + 20 272 128 13 + 272 20 285 148 + + + 1 + Revision : + -1 + 20 293 128 13 + 293 20 306 148 + + + 1 + Region : + -1 + 20 335 128 13 + 335 20 348 148 + + + 1 + Map : + -1 + 20 83 128 13 + 83 20 96 148 + + + Name + 1 + name + -2 + 156 20 186 13 + 20 156 33 342 + + + Code + 1 + code + -2 + 156 41 186 13 + 41 156 54 342 + + + Lice + 1 + licensee + -2 + 156 314 186 13 + 314 156 327 342 + + + Regi + 1 + region + -2 + 156 335 186 13 + 335 156 348 342 + + + + Vers + 1 + revision + -2 + 156 293 186 13 + 293 156 306 342 + + + Cont + 1 + contents + -2 + 156 62 186 13 + 62 156 75 342 + + + Map + 1 + map + -2 + 156 83 186 13 + 83 156 96 342 + + + Spee + 1 + speed + -2 + 156 104 186 13 + 104 156 117 342 + + + SizH + 1 + rom size written in header + -2 + 156 167 186 13 + 167 156 180 342 + + + + SRAM + 1 + sram size + -2 + 156 188 186 13 + 188 156 201 342 + + + SumH + 1 + checksum written in header + -2 + 156 230 186 13 + 230 156 243 342 + + + ComH + 1 + complement written in header + -2 + 156 251 186 13 + 251 156 264 342 + + + SumC + 1 + calculated checksum + -2 + 156 209 186 13 + 209 156 222 342 + + + 1 + Type : + -1 + 20 125 128 13 + 125 20 138 148 + + + Type + 1 + type + -2 + 156 125 186 13 + 125 156 138 342 + + + 1 + CRC32 : + -1 + 20 356 128 13 + 356 20 369 148 + + + CRC + 1 + crc32 + -2 + 156 356 186 13 + 356 156 369 342 + + + Clip + 1 + Clip + Copy to Clipboard + 204 384 137 20 + 384 204 404 341 + + + 0 0 422 362 + + 80 40 502 402 + 0 0 768 1024 + + + Cached + TRUE + TRUE + + + snd_ + 211 + 2 + + Popup: + + + 8 ms + TRUE + + + 16 ms + TRUE + TRUE + + + + 64 ms + TRUE + + + + System + TRUE + + + + 415 49 127 20 + 91 436 111 563 + + + snd_ + 204 + Swaps the left and right stereo channels. + Reverse Stereo + 34 102 136 18 + 144 55 162 191 + + + + + + 0 + TRUE + + + + 5__A + 5__A + 0 + 1107 + 4 + TRUE + 32768 + 262 70 28 28 + 222 604 250 632 + + + 7__L + 7__L + 0 + 1308 + 4 + TRUE + 32768 + 98 26 28 28 + 324 118 352 146 + + + UI_T + + 1 + 2 + + 2 + 242 0 207 329 + + + Drwr + Drwr + 0 + 3 + Screen + 256 + 127 302 60 17 + 302 369 319 429 + + + + + Mode + 1 + Mode + 3 + 3 + + + Hexadecimal + + + Signed Decimal + + + Unsigned Decimal + + + 11 45 117 62 + 45 253 107 370 + + + Math + 1 + Math + + 108 115 79 17 + 115 350 132 429 + + + 1 + Address : + 11 270 53 14 + 270 253 284 306 + + + CTxt + 1 + TRUE + TRUE + 111 177 73 14 + 177 353 191 426 + + + BSto + 1 + BSto + Store Current Values + 34 229 152 20 + 229 276 249 428 + + + WTxt + 1 + 000000 + 64 270 48 14 + 270 306 284 354 + + + 1 + Comparison : + 11 117 87 16 + 117 253 133 340 + + + RSto + 1 + RSto + Stored Value + 11 140 92 14 + 140 253 154 345 + + + + + 1 + Value Size : + 11 22 68 16 + 22 253 38 321 + + + Size + 1 + Size + + Popup: + + + 1 Byte + TRUE + TRUE + + + 2 Bytes + TRUE + + + 3 Bytes + TRUE + + + + + 108 20 79 17 + 20 350 37 429 + + + 0 242 329 449 + + + 2 + TRUE + + + LChk + 1111 + 0 + 808 + 4 + 33024 + 102 30 28 28 + 236 473 264 501 + + + + 1 + (0 : Disable) + -1 + 414 64 69 16 + 106 435 122 504 + + + 5_Dn + 5_Dn + 0 + 1101 + 4 + TRUE + 32768 + 42 100 28 28 + 252 384 280 412 + + + + 1 + Player 2 + FALSE + 342 6 302 140 + + + 2_Lf + 2_Lf + 0 + 814 + 4 + TRUE + 32768 + 12 70 28 28 + 76 354 104 382 + + + 2_Up + 2_Up + 0 + 812 + 4 + TRUE + 32768 + 42 40 28 28 + 46 384 74 412 + + + 2_Dn + 2_Dn + 0 + 813 + 4 + TRUE + 32768 + 42 100 28 28 + 106 384 134 412 + + + 2_Rt + 2_Rt + 0 + 815 + 4 + TRUE + 32768 + 72 70 28 28 + 76 414 104 442 + + + 2__A + 2__A + 0 + 819 + 4 + TRUE + 32768 + 262 70 28 28 + 76 604 104 632 + + + 2__Y + 2__Y + 0 + 816 + 4 + TRUE + 32768 + 202 70 28 28 + 76 544 104 572 + + + 2__B + 2__B + 0 + 817 + 4 + TRUE + 32768 + 232 100 28 28 + 106 574 134 602 + + + 2Sel + 2Sel + 0 + 823 + 4 + TRUE + 32768 + 119 70 28 28 + 76 461 104 489 + + + 2Srt + 2Srt + 0 + 822 + 4 + TRUE + 32768 + 155 70 28 28 + 76 497 104 525 + + + 2__X + 2__X + 0 + 818 + 4 + TRUE + 32768 + 232 40 28 28 + 46 574 74 602 + + + 2__L + 2__L + 0 + 820 + 4 + TRUE + 32768 + 98 26 28 28 + 32 440 60 468 + + + 2__R + 2__R + 0 + 821 + 4 + TRUE + 32768 + 176 26 28 28 + 32 518 60 546 + + + 6 342 146 644 + + + + XChk + 1111 + 0 + 806 + 4 + 33024 + 236 44 28 28 + 250 607 278 635 + + + + 1 + Player 3 + FALSE + 664 6 302 140 + + + 3_Lf + 3_Lf + 0 + 902 + 4 + TRUE + 32768 + 12 70 28 28 + 76 676 104 704 + + + 3_Up + 3_Up + 0 + 900 + 4 + TRUE + 32768 + 42 40 28 28 + 46 706 74 734 + + + 3_Dn + 3_Dn + 0 + 901 + 4 + TRUE + 32768 + 42 100 28 28 + 106 706 134 734 + + + 3_Rt + 3_Rt + 0 + 903 + 4 + TRUE + 32768 + 72 70 28 28 + 76 736 104 764 + + + 3__A + 3__A + 0 + 907 + 4 + TRUE + 32768 + 262 70 28 28 + 76 926 104 954 + + + + 3__B + 3__B + 0 + 905 + 4 + TRUE + 32768 + 232 100 28 28 + 106 896 134 924 + + + 3Sel + 3Sel + 0 + 911 + 4 + TRUE + 32768 + 119 70 28 28 + 76 783 104 811 + + + 3Srt + 3Srt + 0 + 910 + 4 + TRUE + 32768 + 155 70 28 28 + 76 819 104 847 + + + + 3__L + 3__L + 0 + 908 + 4 + TRUE + 32768 + 98 26 28 28 + 32 762 60 790 + + + 3__R + 3__R + 0 + 909 + 4 + TRUE + 32768 + 176 26 28 28 + 32 840 60 868 + + + 6 664 146 966 + + + Righ + 2222 + 0 + 815 + 4 + 33024 + 76 74 28 28 + 280 447 308 475 + + + CCTL + 103 + 1 + + Popup: + + + Auto Detect + TRUE + TRUE + + + TRUE + + + Force PAL + TRUE + + + Force NTSC + TRUE + + + + 33 95 50 205 + + + Up + 111 + 0 + 800 + 4 + 33024 + 46 44 28 28 + 250 87 278 115 + + + 0 0 986 491 + + + 1 + Player 1 + FALSE + 20 6 302 140 + + + 1_Lf + 1_Lf + 0 + 802 + 4 + TRUE + 32768 + 12 70 28 28 + 76 32 104 60 + + + 1_Up + 1_Up + 0 + 800 + 4 + TRUE + 32768 + 42 40 28 28 + 46 62 74 90 + + + 1_Dn + 1_Dn + 0 + 801 + 4 + TRUE + 32768 + 42 100 28 28 + 106 62 134 90 + + + 1_Rt + 1_Rt + 0 + 803 + 4 + TRUE + 32768 + 72 70 28 28 + 76 92 104 120 + + + 1__A + 1__A + 0 + 807 + 4 + TRUE + 32768 + 262 70 28 28 + 76 282 104 310 + + + 1__Y + 1__Y + 0 + 804 + 4 + TRUE + 32768 + 202 70 28 28 + 76 222 104 250 + + + 1__B + 1__B + 0 + 805 + 4 + TRUE + 32768 + 232 100 28 28 + 106 252 134 280 + + + 1Sel + 1Sel + 0 + 811 + 4 + TRUE + 32768 + 119 70 28 28 + 76 139 104 167 + + + 1Srt + 1Srt + 0 + 810 + 4 + TRUE + 32768 + 155 70 28 28 + 76 175 104 203 + + + + 1__L + 1__L + 0 + 808 + 4 + TRUE + 32768 + 98 26 28 28 + 32 118 60 146 + + + 1__R + 1__R + 0 + 809 + 4 + TRUE + 32768 + 176 26 28 28 + 32 196 60 224 + + + 6 20 146 322 + + + + + + 1 + Player 5 + FALSE + 342 152 302 140 + + + 5_Lf + 5_Lf + 0 + 1102 + 4 + TRUE + 32768 + 12 70 28 28 + 222 354 250 382 + + + 5_Up + 5_Up + 0 + 1100 + 4 + TRUE + 32768 + 42 40 28 28 + 192 384 220 412 + + + + 5_Rt + 5_Rt + 0 + 1103 + 4 + TRUE + 32768 + 72 70 28 28 + 222 414 250 442 + + + + 5__Y + 5__Y + 0 + 1104 + 4 + TRUE + 32768 + 202 70 28 28 + 222 544 250 572 + + + 5__B + 5__B + 0 + 1105 + 4 + TRUE + 32768 + 232 100 28 28 + 252 574 280 602 + + + + 5Srt + 5Srt + 0 + 1110 + 4 + TRUE + 32768 + 155 70 28 28 + 222 497 250 525 + + + 5__X + 5__X + 0 + 1106 + 4 + TRUE + 32768 + 232 40 28 28 + 192 574 220 602 + + + 5__L + 5__L + 0 + 1108 + 4 + TRUE + 32768 + 98 26 28 28 + 178 440 206 468 + + + 5__R + 5__R + 0 + 1109 + 4 + TRUE + 32768 + 176 26 28 28 + 178 518 206 546 + + + 152 342 292 644 + + + + CLRa + 1 + CLRa + Clear All + 21 453 85 20 + 453 21 473 106 + + + PRES + 1 + Preset #n + 130 456 95 13 + 456 130 469 225 + + + 1 + Player 6 + FALSE + 664 152 302 140 + + + 6_Lf + 6_Lf + 0 + 1202 + 4 + TRUE + 32768 + 12 70 28 28 + 222 676 250 704 + + + 6_Up + 6_Up + 0 + 1200 + 4 + TRUE + 32768 + 42 40 28 28 + 192 706 220 734 + + + 6_Dn + 6_Dn + 0 + 1201 + 4 + TRUE + 32768 + 42 100 28 28 + 252 706 280 734 + + + + 6__A + 6__A + 0 + 1207 + 4 + TRUE + 32768 + 262 70 28 28 + 222 926 250 954 + + + 6__Y + 6__Y + 0 + 1204 + 4 + TRUE + 32768 + 202 70 28 28 + 222 866 250 894 + + + 6__B + 6__B + 0 + 1205 + 4 + TRUE + 32768 + 232 100 28 28 + 252 896 280 924 + + + 6Sel + 6Sel + 0 + 1211 + 4 + TRUE + 32768 + 119 70 28 28 + 222 783 250 811 + + + 6Srt + 6Srt + 0 + 1210 + 4 + TRUE + 32768 + 155 70 28 28 + 222 819 250 847 + + + 6__X + 6__X + 0 + 1206 + 4 + TRUE + 32768 + 232 40 28 28 + 192 896 220 924 + + + + 6__R + 6__R + 0 + 1209 + 4 + TRUE + 32768 + 176 26 28 28 + 178 840 206 868 + + + 152 664 292 966 + + + 1 + Player 7 + FALSE + 20 298 302 140 + + + 7_Lf + 7_Lf + 0 + 1302 + 4 + TRUE + 32768 + 12 70 28 28 + 368 32 396 60 + + + + 7_Dn + 7_Dn + 0 + 1301 + 4 + TRUE + 32768 + 42 100 28 28 + 398 62 426 90 + + + 7_Rt + 7_Rt + 0 + 1303 + 4 + TRUE + 32768 + 72 70 28 28 + 368 92 396 120 + + + 7__A + 7__A + 0 + 1307 + 4 + TRUE + 32768 + 262 70 28 28 + 368 282 396 310 + + + + 7__B + 7__B + 0 + 1305 + 4 + TRUE + 32768 + 232 100 28 28 + 398 252 426 280 + + + 7Sel + 7Sel + 0 + 1311 + 4 + TRUE + 32768 + 119 70 28 28 + 368 139 396 167 + + + 7Srt + 7Srt + 0 + 1310 + 4 + TRUE + 32768 + 155 70 28 28 + 368 175 396 203 + + + 7__X + 7__X + 0 + 1306 + 4 + TRUE + 32768 + 232 40 28 28 + 338 252 366 280 + + + + 7__R + 7__R + 0 + 1309 + 4 + TRUE + 32768 + 176 26 28 28 + 324 196 352 224 + + + 298 20 438 322 + + + + 0 0 491 986 + + + 3 + TRUE + + + Stat + 2 + 345 68 72 16 + 68 345 84 417 + + + MNAM + 1 + Cart B name + 8 3 290 16 + 62 93 78 383 + + + + + osx_ + 806 + Saves the sizes and positions of the game window and dialogs so they come back to the same place. + Save Window Size and Position + 326 20 221 18 + 62 347 80 568 + + + 1 + TRUE + + + + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + Connect to Server + + 0 0 292 132 + + + SVIP + TRUE + TRUE + 97 23 172 16 + 23 97 39 269 + + + NOT_ + NOT_ + 2 + Cancel + 110 92 70 20 + 92 110 112 180 + + + OK__ + OK__ + 1 + Connect + 192 92 80 20 + 92 192 112 272 + + + CLNM + TRUE + TRUE + 97 53 172 16 + 53 97 69 269 + + + Server IP : + -1 + 20 22 62 16 + 22 20 38 82 + + + + CHAS + 20 96 16 16 + 96 20 112 36 + + + 0 0 132 292 + + 80 40 212 332 + 0 0 768 1024 + + + 0 0 437 192 + + + IP__ + 86 20 118 16 + 20 86 36 204 + + + 1 : + 20 20 19 16 + 20 20 36 39 + + + 2 : + 20 44 19 16 + 44 20 60 39 + + + 3 : + 20 68 19 16 + 68 20 84 39 + + + 4 : + 20 92 19 16 + 92 20 108 39 + + + 5 : + 20 116 19 16 + 116 20 132 39 + + + IP__ + 1 + 86 44 118 16 + 44 86 60 204 + + + IP__ + 2 + 86 68 118 16 + 68 86 84 204 + + + IP__ + 3 + 86 92 118 16 + 92 86 108 204 + + + IP__ + 4 + 86 116 118 16 + 116 86 132 204 + + + Stat + 345 20 72 16 + 20 345 36 417 + + + Stat + 1 + 345 44 72 16 + 44 345 60 417 + + + + Stat + 3 + 345 92 72 16 + 92 345 108 417 + + + Stat + 4 + 345 116 72 16 + 116 345 132 417 + + + Name + 219 20 118 16 + 20 219 36 337 + + + Name + 1 + 219 44 118 16 + 44 219 60 337 + + + Name + 2 + 219 68 118 16 + 68 219 84 337 + + + Name + 3 + 219 92 118 16 + 92 219 108 337 + + + + OKAY + OKAY + 1 + Play + 347 152 70 20 + 152 347 172 417 + + + + Pnum + 52 20 26 16 + 20 52 36 78 + + + Pnum + 1 + 52 44 26 16 + 44 52 60 78 + + + Pnum + 2 + 52 68 26 16 + 68 52 84 78 + + + Pnum + 3 + 52 92 26 16 + 92 52 108 78 + + + Pnum + 4 + 52 116 26 16 + 116 52 132 78 + + + Chse + 20 156 16 16 + 156 20 172 36 + + + 0 0 192 437 + + + + RChk + 222 + 0 + 821 + 4 + 33024 + 180 30 28 28 + 236 221 264 249 + + + AChk + 11 + 0 + 807 + 4 + 33024 + 266 74 28 28 + 122 637 150 665 + + + + Popup: + + + Auto Detect + TRUE + TRUE + + + TRUE + + + + Force Mode 1 + TRUE + + + Force Mode 2 + TRUE + + + Force GD24 + TRUE + + + + + 0 0 605 371 + + + tabs + 128 + 21 5 562 346 + + + tabs + 129 + 2 + 0 37 562 309 + + + grap + 2 + Toggles between scaling full screen graphics to the current screen resolution or changing the screen resolution to fit Snes9x's needs. + Switch Monitor Resolution + 18 42 192 18 + 84 39 102 231 + + + grap + 1 + Toggles full screen/windowed mode. Press esc key to hide full screen window and pause the game. + Full Screen Mode + 18 20 192 18 + 62 39 80 231 + + + + + + grap + 7 + G__7 + Stretches the image to fill the screen in full screen mode. + Stretch Image in Full Screen Mode + 18 205 241 18 + 247 39 265 280 + + + OpenGL Option : + 20 155 111 16 + 197 41 213 152 + + + grap + 9 + 3 + + 327 19 215 20 + 61 348 81 563 + + + Choose the image scaling filter which is applied to the raw SNES image. + Video Mode : + -1 + 228 21 89 16 + 63 249 79 338 + + + grap + 11 + Synchronizes the render timing to the monitor's vertical refresh rate. + Sync to Vertical Blank + 18 183 241 18 + 225 39 243 280 + + + grap + 10 + When this option is on, the rendering process is separated from the emulation thread (except blocky and smooth modes). + Multitask + 326 64 193 18 + 106 347 124 540 + + + + grap + 13 + G_13 + Adds a warp effect like a CRT-based television. + Use Screen Curvature + 326 205 193 18 + 247 347 265 540 + + + grap + 14 + 2 + 10 + 397 226 144 22 + 268 418 290 562 + + + The degree of curvature. + Warp : + -2 + 345 228 45 16 + 270 366 286 411 + + + 12 131 538 4 + 173 33 177 571 + + + grap + 15 + 2 + 10 + 135 226 144 22 + 268 156 290 300 + + + The aspect ratio of above option: the left is proportional and the right is full width of the monitor. + Aspect Ratio : + 38 228 88 16 + 270 59 286 147 + + + grap + 8 + G_FL + Choose the Core Image filter. + Filter... + 460 160 82 20 + 202 481 222 563 + + + + 42 21 351 583 + + + tabs + 130 + 2 + 0 37 562 309 + + + snd_ + 203 + S__3 + Enables stereo sound instead of mono. + Stereo + 18 80 152 18 + 122 39 140 191 + + + + snd_ + 202 + Enables 16-bit playback instead of 8-bit. + 16 Bit Playback + 18 58 152 18 + 100 39 118 191 + + + snd_ + 201 + Tries and ensures all available samples are buffered so there are no overruns. + Synchronize + 18 20 152 18 + 62 39 80 191 + + + snd_ + 210 + Safer from crackling noise, but time-lag becomes more noticeable. + Allow Lag + 414 109 85 18 + 151 435 169 520 + + + + snd_ + 206 + 5 + + 415 79 127 20 + 121 436 141 563 + + + + The real SNES is 32000 Hz. Any values other than 32000 Hz will cause resampling. + Playback Rate : + -1 + 275 21 130 16 + 63 296 79 426 + + + Make sure this value is smaller than the mix buffer length. + Output Interval : + -1 + 275 51 130 16 + 93 296 109 426 + + + Too short length will cause crackling noise. + Mix Buffer Length : + -1 + 275 81 130 16 + 123 296 139 426 + + + snd_ + 207 + 2 + 80 + 322 140 219 22 + 182 343 204 562 + + + snd_ + 208 + TRUE + 10 + 2 + 32000 + 31000 + 33000 + 322 170 219 22 + 212 343 234 562 + + + Volume of the whole Snes9x sounds. + Volume : + -1 + 226 142 85 16 + 184 247 200 332 + + + 1 + Hz + -1 + 526 192 16 16 + 234 547 250 563 + + + Adjusts the sound rate through resampling. For every Input Rate samples generated by the SNES, Playback Rate samples will be produced. + Input Rate : + -1 + 226 172 85 16 + 214 247 230 332 + + + snd_ + 209 + 1 + 32000 + -1 + 465 192 59 16 + 234 486 250 545 + + + S_EF + S_EF + Opens 'Sound Effect' dialog. + Effect... + 20 140 100 20 + 182 41 202 141 + + + 42 21 351 583 + + + tabs + 131 + 2 + 0 37 562 309 + + + othe + 401 + 3 + + Popup: + + + Snes9x Folder + TRUE + + + + Application Support Folder + TRUE + TRUE + + + + 201 19 222 20 + 61 222 81 444 + + + othe + 402 + TRUE + TRUE + 205 63 74 16 + 105 226 121 300 + + + Choose the folder where Snes9x will look for files. + Save Data in : + -1 + 79 21 112 16 + 63 100 79 212 + + + sec after Modified + -1 + 289 62 116 16 + 104 310 120 426 + + + + + 42 21 351 583 + + + tabs + 132 + 2 + 0 37 562 309 + + + Changes HDMA timing and will 'fix' some games' glitches, but breaks many other games. The default value is 100. + HDMA Timing Hack : + 20 59 133 16 + 101 41 117 174 + + + msc2 + 602 + Skips internal CPU emulation for speed-ups until the next event comes. + Skip CPU Emulation Until the Next Event Comes + 18 89 361 18 + 131 39 149 400 + + + + + msc2 + 603 + Turb + 3 + 1 + 15 + 201 241 13 22 + 283 222 305 235 + + + The speed when turbo mode is on. Modify in-game with Fn+T, Fn+Y. + Speed in Turbo Mode : + 20 243 145 16 + 285 41 301 186 + + + + 12 180 538 1 + 222 33 223 571 + + + msc2 + 605 + + Popup + + + Auto + TRUE + TRUE + + + + + 1 + TRUE + + + + + + + 107 207 107 20 + 249 128 269 235 + + + Adjust this value if your Mac is slow. + Frame Skip : + 20 209 79 16 + 251 41 267 120 + + + msc2 + 606 + Allows to write to VRAM outside blank periods. + Allow Invalid VRAM Access + 18 111 361 18 + 153 39 171 400 + + + msc2 + 607 + Applies special hacks for games that can't be emulated correctly. + Apply Specific Game Hacks + 18 133 361 18 + 175 39 193 400 + + + 42 21 351 583 + + + tabs + 133 + 2 + 0 37 562 309 + + + osx_ + 801 + Choose whether open dialog should be shown when Snes9x is launched. + Open Choose ROM Image Dialog at Startup + 18 64 302 18 + 106 39 124 341 + + + osx_ + 802 + Shows time stamps on thumbnails in freeze/defrost screen. + Show Dates and Times in Freese State Selection Screen + 18 86 374 18 + 128 39 146 413 + + + Choose the behavior of Music Box: 'Sound Emulation Only' to only emulate the music system, and 'Whole Emulation' to also emulate the CPU. Music that depends on the CPU running will not sound right without 'Whole Emulation.' + Music Box : + 328 134 76 16 + 176 349 192 425 + + + osx_ + 803 + + + Sound Emulation Only + + + Whole Emulation + + + 326 158 177 39 + 200 347 239 524 + + + + osx_ + 807 + When this option is on, Snes9x automatically loads the .ips or .ups file and patch the ROM image. + Use IPS / UPS Patch + 326 42 221 18 + 84 347 102 568 + + + osx_ + 808 + Shows messages from Snes9x on the game screen. When off, messages are put in the standard console. + Show Onscreen Information + 18 42 207 18 + 84 39 102 246 + + + osx_ + 809 + 3 + + + Keep on Emulation, Receive All Inputs + + + Keep on Emulation, Reject Any Inputs + + + Pause and Exit from Emulation Loop + + + 18 158 266 59 + 200 39 259 305 + + + + + osx_ + 805 + When this option is on, BS-X ROM is loaded first, then you launch BS games from the menu in BS-X. + Boot Up BS Games from BS-X + 326 64 221 18 + 106 347 124 568 + + + 42 21 351 583 + + + 5 21 351 583 + + + contentResID + 0 + tabEnabled + 1 + tabName + Graphics + userPane + + + + contentResID + 0 + tabEnabled + 1 + tabName + Sound + userPane + + + + contentResID + 0 + tabEnabled + 1 + tabName + File + userPane + + + + contentResID + 0 + tabEnabled + 1 + tabName + Accuracy + userPane + + + + contentResID + 0 + tabEnabled + 1 + tabName + Others + userPane + + + + + + 0 0 371 605 + + + + + + + 0 + TRUE + TRUE + + + ok + 1 + OK + 507 110 70 20 + 110 507 130 577 + + + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + Preferences + + 80 39 451 644 + 0 0 768 1024 + + + + RCTL + 101 + 1 + 1 + 8 112 22 144 + + + Apple's Graphic Equalizer + TRUE + GrEQ + + + 1 + Set whether a button's input is inverted - that is, Snes9x acts as though the button is pressed if and only if it is not pressed. + Button Input is Inverted + FALSE + 350 164 310 148 + + + Left + 1111 + 0 + 802 + 4 + 33024 + 16 74 28 28 + 280 387 308 415 + + + + Down + 1111 + 0 + 801 + 4 + 33024 + 46 104 28 28 + 310 417 338 445 + + + Righ + 1111 + 0 + 803 + 4 + 33024 + 76 74 28 28 + 280 447 308 475 + + + AChk + 1111 + 0 + 807 + 4 + 33024 + 266 74 28 28 + 280 637 308 665 + + + YChk + 1111 + 0 + 804 + 4 + 33024 + 206 74 28 28 + 280 577 308 605 + + + BChk + 1111 + 0 + 805 + 4 + 33024 + 236 104 28 28 + 310 607 338 635 + + + Sele + 1111 + 0 + 811 + 4 + 33024 + 123 74 28 28 + 280 494 308 522 + + + Star + 1111 + 0 + 810 + 4 + 33024 + 159 74 28 28 + 280 530 308 558 + + + + + RChk + 1111 + 0 + 809 + 4 + 33024 + 180 30 28 28 + 236 551 264 579 + + + 206 371 354 681 + + + + + + + + LChk + 222 + 0 + 820 + 4 + 33024 + 102 30 28 28 + 236 143 264 171 + + + + + + + + Up + 2222 + 0 + 812 + 4 + 33024 + 46 44 28 28 + 250 417 278 445 + + + + + + PANE + 1000 + 2 + + + RCTL + 108 + 1 + Players to Record : + 8 6 21 109 + + + + RCTL + 107 + 1 + TRUE + TRUE + 34 74 47 422 + + + + RCTL + 102 + 1 + 2 + 8 150 22 182 + + + RCTL + 103 + 1 + 3 + 8 188 22 220 + + + RCTL + 104 + 1 + 4 + 8 226 22 258 + + + + RCTL + 106 + 1 + Reset + 8 355 22 405 + + + 0 0 58 433 + + + 0 0 58 433 + + + + + + + + QCTL + 101 + 1 + Double Size + 10 7 24 90 + + + + + bar3 + bar3 + 0 + 3 + 256 + 48 6 12 12 + 214 69 226 81 + + + + 0 0 449 441 + + + + + UI_B + + 2 + 2 + + 2 + 242 346 207 95 + + + BAdd + 1 + BAdd + Add to Cheat Entry... + 34 7 152 20 + 353 276 373 428 + + + + + 346 242 441 449 + + + 0 0 441 449 + + + + + + + Star + 22 + 0 + 822 + 4 + 33024 + 159 74 28 28 + 122 530 150 558 + + + + Lgnd + 0.000000 + TRUE + 145 214 16 16 + 214 145 230 161 + + + + + + PANE + 1000 + 2 + + + + QCTL + 102 + 1 + Overscan + 10 99 24 175 + + + QCTL + 103 + 1 + Compression... + 7 319 27 424 + + + QCTL + 104 + 1 + + Popup: + + + + + 2 + TRUE + + + 3 + TRUE + + + 4 + TRUE + + + + + 8 260 25 301 + + + QCTL + 105 + 1 + Frame Skip : + -1 + 10 185 23 254 + + + 0 0 34 433 + + + 0 0 34 433 + + + + + + + + Down + 11 + 0 + 801 + 4 + 33024 + 46 104 28 28 + 152 417 180 445 + + + + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + Open Multiple ROM Images + + 0 0 597 150 + + + Slot A + 20 22 42 16 + 22 20 38 62 + + + Slot B + 20 62 42 16 + 62 20 78 62 + + + + : + 70 62 7 16 + 62 70 78 77 + + + Cho0 + Cho0 + Choose... + 407 20 88 20 + 20 407 40 495 + + + Cho1 + Cho1 + Choose... + 407 60 88 20 + 60 407 80 495 + + + Cle0 + Cle0 + Clear + 507 20 70 20 + 20 507 40 577 + + + Cle1 + Cle1 + Clear + 507 60 70 20 + 60 507 80 577 + + + + not! + 2 + Cancel + 425 110 70 20 + 110 425 130 495 + + + MPan + 4098 + 85 19 309 22 + + + MNAM + Cart A name + 8 3 290 16 + 22 93 38 383 + + + 19 85 41 394 + + + MPan + 1 + 4098 + 85 59 309 22 + + + + 59 85 81 394 + + + SWAP + SWAP + Swap + 20 110 70 20 + 110 20 130 90 + + + 0 0 150 597 + + 80 40 230 637 + 0 0 768 1024 + + + 0 0 198 192 + + + 1P : + 20 20 28 16 + 20 20 36 48 + + + 2P : + 20 44 28 16 + 44 20 60 48 + + + 3P : + 20 68 28 16 + 68 20 84 48 + + + + 5P : + 20 116 28 16 + 116 20 132 48 + + + PLNM + 56 20 122 16 + 20 56 36 178 + + + PLNM + 1 + 56 44 122 16 + 44 56 60 178 + + + + PLNM + 3 + 56 92 122 16 + 92 56 108 178 + + + PLNM + 4 + 56 116 122 16 + 116 56 132 178 + + + ok + 1 + OK + 108 152 70 20 + 152 108 172 178 + + + 0 0 192 198 + + + + + Left + 222 + 0 + 814 + 4 + 33024 + 16 74 28 28 + 280 57 308 85 + + + + + 0 0 555 272 + + + BRSR + + 1 + 1 + 2 + 2 + + 40 + + + CHK_ + chbx + 327681 + 1 + 30 + 30 + + + ADDR + 327681 + 1 + 84 + 84 + Address + + + VALU + 327681 + 1 + 65 + 65 + Value + + + DESC + 327681 + 1 + 196 + 196 + -2 + Description + + + 1 + FALSE + FALSE + 17 + 20 20 396 232 + 20 20 252 416 + + + + DEL_ + DEL_ + + 1 + 2 + + Delete + 432 52 103 20 + 52 432 72 535 + + + ALL_ + ALL_ + + 1 + 2 + + Enable All + 432 92 103 20 + 92 432 112 535 + + + 0 0 272 555 + + + YChk + 222 + 0 + 816 + 4 + 33024 + 206 74 28 28 + 280 247 308 275 + + + + + + bar4 + bar4 + 0 + 4 + 256 + 62 6 12 12 + 214 83 226 95 + + + LChk + 11 + 0 + 808 + 4 + 33024 + 102 30 28 28 + 78 473 106 501 + + + + + Star + 2 + 0 + 822 + 4 + 33024 + 159 74 28 28 + 122 200 150 228 + + + + + + Hint + Sets GL_TEXTURE_STORAGE_HINT_APPLE. + 2 + + Popup: + + + + + Shared + TRUE + + + + 134 176 103 20 + 176 134 196 237 + + + bar1 + bar1 + 0 + 1 + 256 + 20 6 12 12 + 214 41 226 53 + + + + + + 1 + Set whether a button's input is inverted - that is, Snes9x acts as though the button is pressed if and only if it is not pressed. + Button Input is Inverted + FALSE + 350 164 310 148 + + + Left + 2222 + 0 + 814 + 4 + 33024 + 16 74 28 28 + 280 387 308 415 + + + + Down + 2222 + 0 + 813 + 4 + 33024 + 46 104 28 28 + 310 417 338 445 + + + + + YChk + 2222 + 0 + 816 + 4 + 33024 + 206 74 28 28 + 280 577 308 605 + + + BChk + 2222 + 0 + 817 + 4 + 33024 + 236 104 28 28 + 310 607 338 635 + + + Sele + 2222 + 0 + 823 + 4 + 33024 + 123 74 28 28 + 280 494 308 522 + + + + XChk + 2222 + 0 + 818 + 4 + 33024 + 236 44 28 28 + 250 607 278 635 + + + LChk + 2222 + 0 + 820 + 4 + 33024 + 102 30 28 28 + 236 473 264 501 + + + RChk + 2222 + 0 + 821 + 4 + 33024 + 180 30 28 28 + 236 551 264 579 + + + 206 371 354 681 + + + + + 0 0 257 216 + + + + NoTR + GL_TEXTURE_2D is used even if GL_TEXTURE_RECTANGLE_EXT is available. + Don't Use Rectangle Texture + 34 104 203 18 + 104 34 122 237 + + + AGPT + Sets GL_TEXTURE_PRIORITY to 0.0. + AGP Texturing + 34 148 203 18 + 148 34 166 237 + + + + CSAp + Sets GL_STORAGE_SHARED_APPLE to 1. + Client Stroage + 34 126 203 18 + 126 34 144 237 + + + + OpenGL Settings : + 20 80 131 16 + 80 20 96 151 + + + 12 58 233 1 + 58 12 59 245 + + + 0 0 216 257 + + + CCTL + 102 + 1 + + 8 315 25 425 + + + + 132 + 1095782476 + 2117687422 + 122 12 64 64 + 12 122 76 186 + + + + BChk + 11 + 0 + 805 + 4 + 33024 + 236 104 28 28 + 152 607 180 635 + + + + + + + bar7 + bar7 + 0 + 7 + 256 + 104 6 12 12 + 214 125 226 137 + + + + + + + 0 0 373 81 + + + Filter : + 20 22 44 16 + 22 20 38 64 + + + 12 60 349 1 + 60 12 61 361 + + + 0 0 81 373 + + + + CCTL + 104 + 1 + + Popup: + + + Auto Detect + TRUE + TRUE + + + TRUE + + + Force no Header + TRUE + + + Force Header + TRUE + + + + 33 315 50 425 + + + + Popup: + + + Apple's Matrix Reverb + TRUE + TRUE + Revb + + + + + + + + + + 0 0 276 260 + 0 0 260 276 + + + + + + + + + + + + + + + + + XChk + 22 + 0 + 818 + 4 + 33024 + 236 44 28 28 + 92 607 120 635 + + + + + + + + + bar0 + bar0 + 0 + 8 + 256 + 248 6 12 12 + 214 269 226 281 + + + + + + + + + + + + + + + + Down + 2 + 0 + 813 + 4 + 33024 + 46 104 28 28 + 152 87 180 115 + + + + YChk + 111 + 0 + 804 + 4 + 33024 + 206 74 28 28 + 280 247 308 275 + + + + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + + + 0 0 308 242 + + + 3 + COPY + © Copyright 1996-2010 Snes9x developers Snes9x is a Super Nintendo Entertainment System emulator that allows you to play most games designed for the SNES on your PC. Please visit http://www.snes9x.com/ for up-to-the-minute information and help on Snes9x. Nintendo is a trade mark. + 1 + 20 134 268 88 + 134 20 222 288 + + + + VERS + 1 + versionstr + 1 + 51 110 206 16 + 110 51 126 257 + + + + 0 0 242 308 + + 80 40 322 348 + 0 0 768 1024 + + + + + + + + + + Kart + ROMName + 83 22 167 16 + 22 83 38 250 + + + + + + + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + Keyboard Layout + + 0 0 593 251 + + + DFLT + DFLT + Defaults + 20 211 93 20 + 211 20 231 113 + + + 1 + Player 1 + 169 215 48 13 + 215 169 228 217 + + + 1 + Player 2 + 251 215 48 13 + 215 251 228 299 + + + + Lgnd + 1 + 0.000000 + TRUE + 227 214 16 16 + 214 227 230 243 + + + 0 0 251 593 + + 80 40 331 633 + 0 0 768 1024 + + + BChk + 22 + 0 + 817 + 4 + 33024 + 236 104 28 28 + 152 607 180 635 + + + + + + 0 0 512 478 + + + Pict + + 1 + 1 + 2 + 2 + + 0 0 512 478 + 0 0 478 512 + + + 0 0 478 512 + + + + + + 1 + / sec + 265 35 29 13 + 399 306 412 335 + + + + + Num_ + 1 + 1 + 10 + -1 + 242 35 19 13 + 399 283 412 302 + + + Slid + 2 + TRUE + 16 + 10 + 1 + 16 + 16 28 215 26 + 392 57 418 272 + + + + + + + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + Automatic Fire + + 0 0 723 472 + + + Ftab + 256 + 21 5 680 449 + + + Ftab + 257 + 2 + 0 37 680 412 + + + 1 + Set whether automatic fire is enabled for each controller button. + Enable Automatic Fire + FALSE + 20 6 310 148 + + + Left + 1 + 0 + 802 + 4 + 33024 + 16 74 28 28 + 122 57 150 85 + + + Up + 1 + 0 + 800 + 4 + 33024 + 46 44 28 28 + 92 87 120 115 + + + Down + 1 + 0 + 801 + 4 + 33024 + 46 104 28 28 + 152 87 180 115 + + + Righ + 1 + 0 + 803 + 4 + 33024 + 76 74 28 28 + 122 117 150 145 + + + AChk + 1 + 0 + 807 + 4 + 33024 + 266 74 28 28 + 122 307 150 335 + + + YChk + 1 + 0 + 804 + 4 + 33024 + 206 74 28 28 + 122 247 150 275 + + + BChk + 1 + 0 + 805 + 4 + 33024 + 236 104 28 28 + 152 277 180 305 + + + Sele + 1 + 0 + 811 + 4 + 33024 + 123 74 28 28 + 122 164 150 192 + + + Star + 1 + 0 + 810 + 4 + 33024 + 159 74 28 28 + 122 200 150 228 + + + XChk + 1 + 0 + 806 + 4 + 33024 + 236 44 28 28 + 92 277 120 305 + + + + RChk + 1 + 0 + 809 + 4 + 33024 + 180 30 28 28 + 78 221 106 249 + + + 48 41 196 351 + + + 1 + Set whether pressing 'Alt' in conjunction with a controller button in-game toggles its automatic fire on/off. + Allow 'Alt' to Toggle Enable/Disable Automatic Fire + FALSE + 350 6 310 148 + + + Left + 11 + 0 + 802 + 4 + 33024 + 16 74 28 28 + 122 387 150 415 + + + + + + + YChk + 11 + 0 + 804 + 4 + 33024 + 206 74 28 28 + 122 577 150 605 + + + + + Star + 11 + 0 + 810 + 4 + 33024 + 159 74 28 28 + 122 530 150 558 + + + XChk + 11 + 0 + 806 + 4 + 33024 + 236 44 28 28 + 92 607 120 635 + + + + RChk + 11 + 0 + 809 + 4 + 33024 + 180 30 28 28 + 78 551 106 579 + + + 48 371 196 681 + + + 1 + Set whether, when automatic fire is enabled, 'TC' must also be held down to activate automatic fire. + Automatic Fire is Active Only While 'TC' is Pressed + FALSE + 20 164 310 148 + + + Left + 111 + 0 + 802 + 4 + 33024 + 16 74 28 28 + 280 57 308 85 + + + + Down + 111 + 0 + 801 + 4 + 33024 + 46 104 28 28 + 310 87 338 115 + + + Righ + 111 + 0 + 803 + 4 + 33024 + 76 74 28 28 + 280 117 308 145 + + + AChk + 111 + 0 + 807 + 4 + 33024 + 266 74 28 28 + 280 307 308 335 + + + + BChk + 111 + 0 + 805 + 4 + 33024 + 236 104 28 28 + 310 277 338 305 + + + Sele + 111 + 0 + 811 + 4 + 33024 + 123 74 28 28 + 280 164 308 192 + + + Star + 111 + 0 + 810 + 4 + 33024 + 159 74 28 28 + 280 200 308 228 + + + XChk + 111 + 0 + 806 + 4 + 33024 + 236 44 28 28 + 250 277 278 305 + + + + RChk + 111 + 0 + 809 + 4 + 33024 + 180 30 28 28 + 236 221 264 249 + + + 206 41 354 351 + + + + 1 + Set the number of presses per second that an automatic fire button receives. + Automatic Fire Speed + FALSE + 20 322 310 70 + + + Slid + 1 + TRUE + 16 + 10 + 1 + 16 + 16 28 215 26 + 392 57 418 272 + + + + + 364 41 434 351 + + + DEF1 + DEF1 + Restores the default settings. + Defaults + 579 372 81 20 + 414 600 434 681 + + + 42 21 454 701 + + + Ftab + 258 + 2 + 0 37 680 412 + + + 1 + Set whether pressing 'Alt' in conjunction with a controller button in-game toggles its automatic fire on/off. + Allow 'Alt' to Toggle Enable/Disable Automatic Fire + FALSE + 350 6 310 148 + + + Left + 22 + 0 + 814 + 4 + 33024 + 16 74 28 28 + 122 387 150 415 + + + + Down + 22 + 0 + 813 + 4 + 33024 + 46 104 28 28 + 152 417 180 445 + + + Righ + 22 + 0 + 815 + 4 + 33024 + 76 74 28 28 + 122 447 150 475 + + + AChk + 22 + 0 + 819 + 4 + 33024 + 266 74 28 28 + 122 637 150 665 + + + + + Sele + 22 + 0 + 823 + 4 + 33024 + 123 74 28 28 + 122 494 150 522 + + + + + LChk + 22 + 0 + 820 + 4 + 33024 + 102 30 28 28 + 78 473 106 501 + + + RChk + 22 + 0 + 821 + 4 + 33024 + 180 30 28 28 + 78 551 106 579 + + + 48 371 196 681 + + + 1 + Set whether automatic fire is enabled for each controller button. + Enable Automatic Fire + FALSE + 20 6 310 148 + + + Left + 2 + 0 + 814 + 4 + 33024 + 16 74 28 28 + 122 57 150 85 + + + Up + 2 + 0 + 812 + 4 + 33024 + 46 44 28 28 + 92 87 120 115 + + + + Righ + 2 + 0 + 815 + 4 + 33024 + 76 74 28 28 + 122 117 150 145 + + + + + BChk + 2 + 0 + 817 + 4 + 33024 + 236 104 28 28 + 152 277 180 305 + + + Sele + 2 + 0 + 823 + 4 + 33024 + 123 74 28 28 + 122 164 150 192 + + + + XChk + 2 + 0 + 818 + 4 + 33024 + 236 44 28 28 + 92 277 120 305 + + + LChk + 2 + 0 + 820 + 4 + 33024 + 102 30 28 28 + 78 143 106 171 + + + RChk + 2 + 0 + 821 + 4 + 33024 + 180 30 28 28 + 78 221 106 249 + + + 48 41 196 351 + + + 1 + Set whether, when automatic fire is enabled, 'TC' must also be held down to activate automatic fire. + Automatic Fire is Active Only While 'TC' is Pressed + FALSE + 20 164 310 148 + + + + Up + 222 + 0 + 812 + 4 + 33024 + 46 44 28 28 + 250 87 278 115 + + + Down + 222 + 0 + 813 + 4 + 33024 + 46 104 28 28 + 310 87 338 115 + + + + AChk + 222 + 0 + 819 + 4 + 33024 + 266 74 28 28 + 280 307 308 335 + + + + BChk + 222 + 0 + 817 + 4 + 33024 + 236 104 28 28 + 310 277 338 305 + + + Sele + 222 + 0 + 823 + 4 + 33024 + 123 74 28 28 + 280 164 308 192 + + + Star + 222 + 0 + 822 + 4 + 33024 + 159 74 28 28 + 280 200 308 228 + + + XChk + 222 + 0 + 818 + 4 + 33024 + 236 44 28 28 + 250 277 278 305 + + + + + 206 41 354 351 + + + + 1 + Set the number of presses per second that an automatic fire button receives. + Automatic Fire Speed + FALSE + 20 322 310 70 + + + + + 1 + / sec + 265 35 29 13 + 399 306 412 335 + + + 364 41 434 351 + + + DEF2 + DEF2 + Restores the default settings. + Defaults + 579 372 81 20 + 414 600 434 681 + + + 42 21 454 701 + + + 5 21 454 701 + + + contentResID + 0 + tabEnabled + 1 + tabName + Player 1 + userPane + + + + contentResID + 0 + tabEnabled + 1 + tabName + Player 2 + userPane + + + + + + 0 0 472 723 + + 80 40 552 763 + 0 0 768 1024 + + + + + + + + + + + + + + S_EF + S_EF + 2 + 0 + 202 + -1 + 32768 + 2 67 30 20 + 137 302 157 332 + + + Choose the Effect to Configure : + 22 20 38 224 + + + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + 1 + 7 + SoundEffectUI + + + + SfUI + 2 + + + Enab + Enab + Enable this Effect + 73 18 91 154 + + + Epop + + 20 234 40 447 + + + + LINE + 60 12 61 455 + + + 0 0 99 467 + + + 0 0 99 467 + + 80 40 179 507 + 0 0 768 1024 + + + + + barb + barb + 0 + 3 + 256 + 178 6 12 12 + 214 199 226 211 + + + + + bara + bara + 0 + 2 + 256 + 164 6 12 12 + 214 185 226 197 + + + + + + + + + + CCTL + 107 + 1 + Video System : + -1 + 35 6 48 87 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CCTL + 105 + 1 + Memory Type : + -1 + 10 6 23 87 + + + + + + FALSE + TRUE + TRUE + FALSE + 1 + 7 + Cheat Finder + + 80 40 521 489 + 0 0 768 1024 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + barc + barc + 0 + 4 + 256 + 192 6 12 12 + 214 213 226 225 + + + + + + + + + + + + + + + + + + + + + + + + + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + Extra Options + + 80 40 296 297 + 0 0 768 1024 + + + + + + + + + + + + + + + + + + + + + bar8 + bar8 + 0 + 8 + 256 + 118 6 12 12 + 214 139 226 151 + + + + 0 0 352 246 + + + Playing : + 20 22 61 16 + 22 20 38 81 + + + DONE + 2 + Done + 258 20 74 20 + 20 258 40 332 + + + + + Pane + 36 70 250 130 + 70 36 200 286 + + + rCTL + 2 + 300 70 34 92 + + + Paus + Paus + 2 + 0 + 200 + -1 + 33024 + 2 3 30 20 + 73 302 93 332 + + + HEAD + FALSE + HEAD + 2 + 0 + 201 + -1 + 32768 + 2 29 30 20 + 99 302 119 332 + + + + 70 300 162 334 + + + bCTL + 2 + 21 208 280 25 + + + + + bar9 + bar9 + 0 + 1 + 256 + 150 6 12 12 + 214 171 226 183 + + + + + + bare + bare + 0 + 6 + 256 + 220 6 12 12 + 214 241 226 253 + + + + barf + barf + 0 + 7 + 256 + 234 6 12 12 + 214 255 226 267 + + + bar6 + bar6 + 0 + 6 + 256 + 90 6 12 12 + 214 111 226 123 + + + + + bar5 + bar5 + 0 + 5 + 256 + 76 6 12 12 + 214 97 226 109 + + + + + + PILT + 132 + 1835623278 + 2117687422 + 132 4 16 16 + 212 153 228 169 + + + 208 21 233 301 + + + 0 0 246 352 + + + + + + + + + + + + + + FALSE + FALSE + TRUE + FALSE + TRUE + FALSE + 20 + 51 + 7 + CFDrawer + + 80 40 340 316 + 0 0 768 1024 + + + + + + + + + + + + + + + + + + + + + + + + + + + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + 1 + 7 + PlaySMVControl + + + + + 0 0 34 433 + + 80 40 114 473 + 0 0 768 1024 + + + + + + + + + + + + + + + + + + + + + + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + TRUE + FALSE + 11 + 53 + 7 + Players List + + 80 40 272 238 + 0 0 768 1024 + + + + + + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + Core Image Filter Setting + + 80 40 161 413 + 0 0 768 1024 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + Configure Controllers + + 80 40 571 1026 + 0 0 768 1024 + + + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + Clients List + + 80 40 272 477 + 0 0 768 1024 + + + + + PANE + 1000 + 2 + + + + + + + + + CCTL + 108 + 1 + Header : + -1 + 35 213 48 307 + + + + 0 0 58 433 + + + 0 0 58 433 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + 1 + 7 + RecordSMVControl + + 80 40 138 473 + 0 0 768 1024 + + + + + + + + + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + FALSE + 1 + 7 + Music Box + + 80 40 326 392 + 0 0 768 1024 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + 1 + 7 + OpenROMControl + + 80 40 138 473 + 0 0 768 1024 + + + + + + + + + + + + + + + + + + + + + + + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + FALSE + TRUE + 1 + 7 + QTMovControl + + 80 40 114 473 + 0 0 768 1024 + + + FALSE + TRUE + TRUE + FALSE + 1 + 7 + Cheat Entry + + 80 40 352 595 + 0 0 768 1024 + 555 + 272 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FALSE + FALSE + TRUE + TRUE + TRUE + FALSE + -1 + 1 + Game Window + + 80 40 558 552 + 0 0 768 1024 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + About + + AutoFire + + CFAddEntry + + CFDrawer + + CIFilter + + CheatEntry + + CheatFinder + + ClientList + + Connect + + Controllers + + ExtraOptions + + File's Owner + + GameWindow + + Keyboard + + MenuBar + + MultiCart + + MusicBox + + OpenROM + + PlaySMV + + PlayerList + + Preferences + + QTMovie + + RecordSMV + + RomInfo + + SoundEffect + + + IBCarbonFramework + 2243 + diff --git a/macosx/HID_Utilities_External.h b/macosx/HID_Utilities_External.h new file mode 100644 index 00000000..d890bfcc --- /dev/null +++ b/macosx/HID_Utilities_External.h @@ -0,0 +1,542 @@ +/* +* File: HID_Utilities_External.h +* +* Contains: Definition of the HID Utilities exported functions +* External interface for HID Utilities, can be used with either library or source +* Check notes below for usage. Some type casting is required so library is framework and carbon free +* +* Copyright: Copyright © 2005 Apple Computer, Inc., All Rights Reserved +* +* Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. +* ( "Apple" ) in consideration of your agreement to the following terms, and your +* use, installation, modification or redistribution of this Apple software +* constitutes acceptance of these terms. If you do not agree with these terms, +* please do not use, install, modify or redistribute this Apple software. +* +* In consideration of your agreement to abide by the following terms, and subject +* to these terms, Apple grants you a personal, non-exclusive license, under AppleƠs +* copyrights in this original Apple software ( the "Apple Software" ), to use, +* reproduce, modify and redistribute the Apple Software, with or without +* modifications, in source and/or binary forms; provided that if you redistribute +* the Apple Software in its entirety and without modifications, you must retain +* this notice and the following text and disclaimers in all such redistributions of +* the Apple Software. Neither the name, trademarks, service marks or logos of +* Apple Computer, Inc. may be used to endorse or promote products derived from the +* Apple Software without specific prior written permission from Apple. Except as +* expressly stated in this notice, no other rights or licenses, express or implied, +* are granted by Apple herein, including but not limited to any patent rights that +* may be infringed by your derivative works or by other works in which the Apple +* Software may be incorporated. +* +* The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO +* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +* PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN +* COMBINATION WITH YOUR PRODUCTS. +* +* IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR +* CONSEQUENTIAL DAMAGES ( INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) +* ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION +* OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT +* ( INCLUDING NEGLIGENCE ), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HID_Utilities_External_h_ +#define _HID_Utilities_External_h_ + +/*****************************************************/ +#pragma mark - includes & imports +/*****************************************************/ +#if !TARGET_RT_MAC_CFM +#include +#endif TARGET_RT_MAC_CFM + +//#include +#if 0 // NOTE: These are now in +#include "PID.h" +#include "IOHIDPowerUsage.h" +#endif + +#include + +/*****************************************************/ +#if PRAGMA_ONCE +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if PRAGMA_IMPORT +#pragma import on +#endif + +#if PRAGMA_STRUCT_ALIGN +#pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH +#pragma pack( push, 2 ) +#elif PRAGMA_STRUCT_PACK +#pragma pack( 2 ) +#endif + +/*****************************************************/ +#pragma mark - typedef's, struct's, enums, defines, etc. +/*****************************************************/ +#if TARGET_RT_MAC_CFM +// from IOHIDKeys.h( IOKit ) +// this can't be included since the original file has framework includes +// developers may need to add definitions here +typedef enum IOHIDElementType { + kIOHIDElementTypeInput_Misc = 1, + kIOHIDElementTypeInput_Button = 2, + kIOHIDElementTypeInput_Axis = 3, + kIOHIDElementTypeInput_ScanCodes = 4, + kIOHIDElementTypeOutput = 129, + kIOHIDElementTypeFeature = 257, + kIOHIDElementTypeCollection = 513 +}IOHIDElementType; + +typedef enum IOHIDReportType { + kIOHIDReportTypeInput = 0, + kIOHIDReportTypeOutput, + kIOHIDReportTypeFeature, + kIOHIDReportTypeCount +}IOHIDReportType; + +// Notes: This is a MachO function pointer. If you're using CFM you have to call MachOFunctionPointerForCFMFunctionPointer. +typedef void( *IOHIDCallbackFunction ) ( void* target, unsigned long result, void* refcon, void* sender ); +typedef void* IOHIDEventStruct; +#endif TARGET_RT_MAC_CFM + +// Device and Element Interfaces + +typedef enum HIDElementTypeMask +{ + kHIDElementTypeInput = 1 << 1, + kHIDElementTypeOutput = 1 << 2, + kHIDElementTypeFeature = 1 << 3, + kHIDElementTypeCollection = 1 << 4, + kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature, + kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection +}HIDElementTypeMask; + +struct hu_element_t +{ + unsigned long type; // the type defined by IOHIDElementType in IOHIDKeys.h + long usage; // usage within above page from IOUSBHIDParser.h which defines specific usage + long usagePage; // usage page from IOUSBHIDParser.h which defines general usage + void* cookie; // unique value( within device of specific vendorID and productID ) which identifies element, will NOT change + long min; // reported min value possible + long max; // reported max value possible + long scaledMin; // reported scaled min value possible + long scaledMax; // reported scaled max value possible + long size; // size in bits of data return from element + unsigned char relative; // are reports relative to last report( deltas ) + unsigned char wrapping; // does element wrap around( one value higher than max is min ) + unsigned char nonLinear; // are the values reported non-linear relative to element movement + unsigned char preferredState; // does element have a preferred state( such as a button ) + unsigned char nullState; // does element have null state + long units; // units value is reported in( not used very often ) + long unitExp; // exponent for units( also not used very often ) + char name[256]; // name of element( c string ) + + // runtime variables + long initialCenter; // center value at start up + unsigned char hasCenter; // whether or not to use center for calibration + long minReport; // min returned value + long maxReport; // max returned value( calibrate call ) + long userMin; // user set value to scale to( scale call ) + long userMax; + + struct hu_element_t* pPrevious; // previous element( NULL at list head ) + struct hu_element_t* pChild; // next child( only of collections ) + struct hu_element_t* pSibling; // next sibling( for elements and collections ) + + long depth; +}; +typedef struct hu_element_t hu_element_t; + +struct hu_device_t +{ + void* interface; // interface to device, NULL = no interface + void* queue; // device queue, NULL = no queue + void* runLoopSource; // device run loop source, NULL == no source + void* queueRunLoopSource; // device queue run loop source, NULL == no source + void* transaction; // output transaction interface, NULL == no interface + void* notification; // notifications + char transport[256]; // device transport( c string ) + long vendorID; // id for device vendor, unique across all devices + long productID; // id for particular product, unique across all of a vendors devices + long version; // version of product + char manufacturer[256]; // name of manufacturer + char product[256]; // name of product + char serial[256]; // serial number of specific product, can be assumed unique across specific product or specific vendor( not used often ) + long locID; // long representing location in USB( or other I/O ) chain which device is pluged into, can identify specific device on machine + long usage; // usage page from IOUSBHID Parser.h which defines general usage + long usagePage; // usage within above page from IOUSBHID Parser.h which defines specific usage + long totalElements; // number of total elements( should be total of all elements on device including collections ) ( calculated, not reported by device ) + long features; // number of elements of type kIOHIDElementTypeFeature + long inputs; // number of elements of type kIOHIDElementTypeInput_Misc or kIOHIDElementTypeInput_Button or kIOHIDElementTypeInput_Axis or kIOHIDElementTypeInput_ScanCodes + long outputs; // number of elements of type kIOHIDElementTypeOutput + long collections; // number of elements of type kIOHIDElementTypeCollection + long axis; // number of axis( calculated, not reported by device ) + long buttons; // number of buttons( calculated, not reported by device ) + long hats; // number of hat switches( calculated, not reported by device ) + long sliders; // number of sliders( calculated, not reported by device ) + long dials; // number of dials( calculated, not reported by device ) + long wheels; // number of wheels( calculated, not reported by device ) + hu_element_t* pListElements; // head of linked list of elements + struct hu_device_t* pNext; // next device +}; +typedef struct hu_device_t hu_device_t; + +// this is the procedure type for a client hot plug callback +typedef OSStatus ( *HotPlugCallbackProcPtr )( io_iterator_t inIODeviceIterator ); + +/*****************************************************/ +#pragma mark - exported globals +/*****************************************************/ +#pragma mark - exported function prototypes +/*****************************************************/ +#pragma mark HID Utilities interface +/*****************************************************/ +// Create and open an interface to device, required prior to extracting values or building queues +// Notes: appliction now owns the device and must close and release it prior to exiting +extern unsigned long HIDCreateOpenDeviceInterface( UInt32 inHIDDevice, hu_device_t* inDevice ); + +// builds list of device with elements( allocates memory and captures devices ) +// list is allocated internally within HID Utilites and can be accessed via accessor functions +// structures within list are considered flat and user accessable, but not user modifiable +// can be called again to rebuild list to account for new devices( will do the right thing in case of disposing existing list ) +// inUsagePage, usage are each a inNumDeviceTypes sized array of matching usage and usage pages +// returns TRUE if successful + +extern Boolean HIDBuildMultiDeviceList( UInt32 *inUsagePage, UInt32 *inUsage, UInt32 inNumDeviceTypes ); + +// same as above but this uses a single inUsagePage and usage + +extern Boolean HIDBuildDeviceList( UInt32 inUsagePage, UInt32 inUsage ); + +// updates the current device list for any new/removed devices +// if this is called before HIDBuildDeviceList the it functions like HIDBuildMultiDeviceList +// inUsagePage, usage are each a inNumDeviceTypes sized array of matching usage and usage pages +// returns TRUE if successful which means if any device were added or removed( the device config changed ) + +extern Boolean HIDUpdateDeviceList( UInt32 *inUsagePage, UInt32 *inUsage, UInt32 inNumDeviceTypes ); + +// release list built by above function +// MUST be called prior to application exit to properly release devices +// if not called( or app crashes ) devices can be recovered by pluging into different location in USB chain +extern void HIDReleaseDeviceList( void ); + +// does a device list exist +extern Boolean HIDHaveDeviceList( void ); + +// how many HID devices have been found +// returns 0 if no device list exist +extern UInt32 HIDCountDevices( void ); + +// how many elements does a specific device have +// returns 0 if device is invalid or NULL +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get non-collection elements +extern UInt32 HIDCountDeviceElements( const hu_device_t* inDevice, HIDElementTypeMask inTypeMask ); + +// get the first device in the device list +// returns NULL if no list exists +extern hu_device_t* HIDGetFirstDevice( void ); + +// get next device in list given current device as parameter +// returns NULL if end of list +extern hu_device_t* HIDGetNextDevice( const hu_device_t* inDevice ); + +// get the first element of device passed in as parameter +// returns NULL if no list exists or device does not exists or is NULL +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality +extern hu_element_t* HIDGetFirstDeviceElement( const hu_device_t* inDevice, HIDElementTypeMask inTypeMask ); + +// get next element of given device in list given current element as parameter +// will walk down each collection then to next element or collection( depthwise traverse ) +// returns NULL if end of list +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality +extern hu_element_t* HIDGetNextDeviceElement( hu_element_t* inElement, HIDElementTypeMask inTypeMask ); + +// get previous element of given device in list given current element as parameter +// this walks directly up the tree to the top element and does not search at each level +// returns NULL if beginning of list +// uses mask of HIDElementTypeMask to restrict element found +// use kHIDElementTypeIO to get non-collection elements +extern hu_element_t* HIDGetPreviousDeviceElement( const hu_element_t* inElement, HIDElementTypeMask inTypeMask ); + +// Sets the client hot plug callback routine +extern OSStatus HIDSetHotPlugCallback( HotPlugCallbackProcPtr inHotPlugCallbackProcPtr ); + +/*****************************************************/ +#pragma mark Name Lookup Interfaces +/*****************************************************/ + +// get vendor name from vendor ID +extern Boolean HIDGetVendorNameFromVendorID( long inVendorID, char* outCStrName ); + +// get product name from vendor/product ID +extern Boolean HIDGetProductNameFromVendorProductID( long inVendorID, long inProductID, char* outCStrName ); + +// set name from vendor id/product id look up( using cookies ) +extern Boolean HIDGetElementNameFromVendorProductCookie( long inVendorID, long inProductID, long inCookie, char* inCStrName ); + +// set name from vendor id/product id look up( using usage page & usage ) +extern Boolean HIDGetElementNameFromVendorProductUsage( long inVendorID, long inProductID, long inUsagePage, long inUsage, char* inCStrName ); + +// Add device to usage & cookie db's +extern Boolean HIDAddDeviceToXML( const hu_device_t* inDevice ); + +// Add element to usage & cookie db's +extern Boolean HIDAddDeviceElementToXML( const hu_device_t* inDevice, const hu_element_t* inElement ); + +// returns C string type name given a type enumeration passed in as parameter( see IOHIDKeys.h ) +// returns empty string for invalid types +extern void HIDGetTypeName( IOHIDElementType inIOHIDElementType, char* inCStrName ); + +// returns C string usage given usage page and usage passed in as parameters( see IOUSBHIDParser.h ) +// returns usage page and usage values in string form for unknown values +extern void HIDGetUsageName( long inUsagePage, long inUsage, char* inCStrName ); + +/*****************************************************/ +// convert an element type to a mask +extern HIDElementTypeMask HIDConvertElementTypeToMask( IOHIDElementType inIOHIDElementType ); + +// find this device +extern Boolean HIDFindDevice( const hu_device_t* inSearchDevice, hu_device_t **outFoundDevice ); + +// find the device and element for this action +// Device: serial, vendorID, productID, location, inUsagePage, usage +// Element: cookie, inUsagePage, usage, +extern Boolean HIDFindActionDeviceAndElement( const hu_device_t* inSearchDevice, const hu_element_t* inSearchElement, hu_device_t **outFoundDevice, hu_element_t **outFoundElement ); + +// find the device and element for this action +// Device: serial, vendorID, productID, location, inUsagePage, usage +// Element: cookie, inUsagePage, usage, + +extern Boolean HIDFindSubElement( const hu_element_t* inStartElement, const hu_element_t* inSearchElement, hu_element_t **outFoundElement ); + +// print out all of an elements information +extern int HIDPrintElement( const hu_element_t* inElement ); + +// return TRUE if this is a valid device pointer +extern Boolean HIDIsValidDevice( const hu_device_t* inDevice ); + +// return TRUE if this is a valid element pointer for this device +extern Boolean HIDIsValidElement( const hu_device_t* inDevice, const hu_element_t* inElement ); + +/*****************************************************/ +#pragma mark Element Event Queue and Value Interfaces +/*****************************************************/ +enum +{ + kDefaultUserMin = 0, // default user min and max used for scaling + kDefaultUserMax = 255 +}; + +enum +{ + kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible + // but should account for the maximum possible events in the queue + // USB updates will likely occur at 100 Hz so one must account for this rate of + // if states change quickly( updates are only posted on state changes ) +}; + +/*****************************************************/ +// queues specific element, performing any device queue set up required +extern unsigned long HIDQueueElement( hu_device_t* inDevice, const hu_element_t* inElement ); + +// adds all elements to queue, performing any device queue set up required +extern unsigned long HIDQueueDevice( hu_device_t* inDevice ); + +// removes element for queue, if last element in queue will release queue and device +extern unsigned long HIDDequeueElement( hu_device_t* inDevice, const hu_element_t* inElement ); + +// completely removes all elements from queue and releases queue and device +extern unsigned long HIDDequeueDevice( hu_device_t* inDevice ); + +// releases all device queues for quit or rebuild( must be called ) +extern unsigned long HIDReleaseAllDeviceQueues( void ); + +// releases interface to device, should be done prior to exiting application( called from HIDReleaseDeviceList ) +extern unsigned long HIDCloseReleaseInterface( hu_device_t* inDevice ); + +// returns TRUE if an event is avialable for the element and fills out *outHIDEvent structure, returns FALSE otherwise +// outHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned char HIDGetEvent( const hu_device_t* inDevice, void* outHIDEvent ); + +// returns current value for element, creating device interface as required, polling element +extern long HIDGetElementEvent( const hu_device_t* inDevice, hu_element_t* inElement, IOHIDEventStruct* outIOHIDEvent ); + +// returns current value for element, creating device interface as required, polling element +extern long HIDGetElementValue( const hu_device_t* inDevice, hu_element_t* inElement ); + +// Set an elements value +// NOTE: This should only be used when a single element report needs to be sent. +// If multiple elements reports are to be send then transactions should be used. +// outIOHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern long HIDSetElementValue( const hu_device_t* inDevice, const hu_element_t* inElement, void* outIOHIDEvent ); + +// Set a callback to be called when a queue goes from empty to non-empty +// Notes: This is a MachO function pointer. If you're using CFM you have to call MachOFunctionPointerForCFMFunctionPointer. +extern long HIDSetQueueCallback( hu_device_t* inDevice, IOHIDCallbackFunction inIOHIDCallback, void* inCallbackTarget, void* inCallbackRefcon ); + +#if defined( AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER ) +// Get a report from a device +extern long HIDGetReport( const hu_device_t* inDevice, IOHIDReportType inIOHIDReportType, unsigned long inReportID, void* inReportBuffer, unsigned long* inReportBufferSize ) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER; + +// Send a report to a device +extern long HIDSetReport( const hu_device_t* inDevice, IOHIDReportType inIOHIDReportType, unsigned long inReportID, void* inReportBuffer, unsigned long inReportBufferSize ) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER; +#endif // defined( AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER ) + +#if defined( AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER ) +// copy matching elements +extern long HIDCopyMatchingElements( const hu_device_t* inDevice, CFDictionaryRef inMatchingDict, CFArrayRef* inElements ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; +// Set a callback to be called when a report comes in the interrupt pipe +// Notes: This is a MachO function pointer. If you're using CFM you have to call MachOFunctionPointerForCFMFunctionPointer. +extern long HIDSetInterruptReportHandlerCallback( const hu_device_t* inDevice, void* inReportBuffer, UInt32 inReportBufferSize, IOHIDReportCallbackFunction inIOHIDReportCallback, void* inCallbackTarget, void* inCallbackRefcon ) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER; +#endif // defined( AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER ) + +/*****************************************************/ +#pragma mark calibration & scale routines +/*****************************************************/ +// returns calibrated value given raw value passed in +// calibrated value is equal to min and max values returned by HIDGetElementValue since device list built scaled to element reported min and max values +extern SInt32 HIDCalibrateValue( SInt32 inValue, hu_element_t* inElement ); + +// returns scaled value given raw value passed in +// scaled value is equal to current value assumed to be in the range of element reported min and max values scaled to user min and max scaled values +extern SInt32 HIDScaleValue( SInt32 inValue, const hu_element_t* inElement ); + +/*****************************************************/ +#pragma mark Conguration and Save Interfaces +/*****************************************************/ +#define kPercentMove 10 // precent of overall range a element must move to register + +typedef struct hu_SaveRec_t +{ + long actionCookie; + // device( need to add serial number when I have a test case ) + long vendorID; + long productID; + long locID; + long usage; + long usagePage; + // elements + long usagePageE; + long usageE; + void* cookie; +}hu_SaveRec_t; + +// polls all devices and elements for a change greater than kPercentMove. Times out after given time +// returns TRUE and pointer to device and element if found +// returns FALSE and NULL for both parameters if not found +extern Boolean HIDConfigureAction( hu_device_t **outDevice, hu_element_t **outElement, float inTimeout ); + +// -- These are routines to use if the applcation wants HID Utilities to do the file handling -- +// Notes: the FILE* is a MachO posix FILE and will not work with the MWCW MSL FILE* type. + +// take input records, save required info +// assume file is open and at correct position. +extern void HIDSaveElementConfig( FILE* inFILE, const hu_device_t* inDevice, const hu_element_t* inElement, long inActionCookie ); + +// take file, read one record( assume file position is correct and file is open ) +// search for matching device +// return inDevice, inElement and cookie for action +extern long HIDRestoreElementConfig( FILE* inFILE, hu_device_t **outDevice, hu_element_t **outElement ); + +// -- These routines use the CFPreferences API's. + +// Save the device & element values into the specified key in the specified applications preferences +extern Boolean HIDSaveElementPref( CFStringRef inKeyCFStringRef, CFStringRef inAppCFStringRef, const hu_device_t* inDevice, const hu_element_t* inElement ); + +// Find the specified preference in the specified application +// search for matching device and element +// return inDevice, inElement that matches + +extern Boolean HIDRestoreElementPref( CFStringRef inKeyCFStringRef, CFStringRef inAppCFStringRef, hu_device_t **outDevice, hu_element_t **outElement ); + +// -- These are routines to use if the client wants to use their own file handling -- + +// Set up a config record for saving +// takes an input records, returns record user can save as they want +// Notes: the save rec must be pre-allocated by the calling app and will be filled out +extern void HIDSetElementConfig( hu_SaveRec_t* inConfigRec, const hu_device_t* inDevice, const hu_element_t* inElement, long inActionCookie ); + +// Get matching element from config record +// takes a pre-allocated and filled out config record +// search for matching device +// return inDevice, inElement and cookie for action +extern long HIDGetElementConfig( hu_SaveRec_t* inConfigRec, hu_device_t **outDevice, hu_element_t **outElement ); + +/*****************************************************/ +#pragma mark Output Transaction interface +/*****************************************************/ +// Create and open an transaction interface to device, required prior to extracting values or building Transactions +extern unsigned long HIDTransactionAddElement( hu_device_t* inDevice, const hu_element_t* inElement ); + +// removes an element from a Transaction +extern unsigned long HIDTransactionRemoveElement( hu_device_t* inDevice, const hu_element_t* inElement ); + +// return TRUE if this transaction contains this element +extern Boolean HIDTransactionHasElement( hu_device_t* inDevice, const hu_element_t* inElement ); + +/* This changes the default value of an element, when the values of the */ +/* elements are cleared, on clear or commit, they are reset to the */ +/* default value */ +/* This call can be made on elements that are not in the transaction, but */ +/* has undefined behavior if made on elements not in the transaction */ +/* which are later added to the transaction. */ +/* In other words, an element should be added before its default is */ +/* set, for well defined behavior. */ +// outHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionSetElementDefault( hu_device_t* inDevice, const hu_element_t* inElement, IOHIDEventStruct* inValueEvent ); + +/* Get the current setting of an element's default value */ +// outHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionGetElementDefault( hu_device_t* inDevice, const hu_element_t* inElement, IOHIDEventStruct* inValueEvent ); + +/* Add a change to the transaction, by setting an element value */ +/* The change is not actually made until it is commited */ +/* The element must be part of the transaction or this call will fail */ +// outHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionSetElementValue( hu_device_t* inDevice, const hu_element_t* inElement, IOHIDEventStruct* inValueEvent ); + +/* Get the current setting of an element value */ +// outHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required +extern unsigned long HIDTransactionGetElementValue( hu_device_t* inDevice, const hu_element_t* inElement, IOHIDEventStruct* inValueEvent ); + +/* Commit the transaction, or clear all the changes and start over */ +extern unsigned long HIDTransactionCommit( hu_device_t* inDevice ); + +/* Clear all the changes and start over */ +extern unsigned long HIDTransactionClear( hu_device_t* inDevice ); + +/*****************************************************/ +#if PRAGMA_STRUCT_ALIGN +#pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH +#pragma pack( pop ) +#elif PRAGMA_STRUCT_PACK +#pragma pack( ) +#endif + +#ifdef PRAGMA_IMPORT_OFF +#pragma import off +#elif PRAGMA_IMPORT +#pragma import reset +#endif + +#ifdef __cplusplus +} +#endif +/*****************************************************/ +#endif // _HID_Utilities_External_h_ diff --git a/macosx/Info.plist b/macosx/Info.plist new file mode 100644 index 00000000..94f0d52c --- /dev/null +++ b/macosx/Info.plist @@ -0,0 +1,189 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + jma + + CFBundleTypeName + JMA archive + CFBundleTypeOSTypes + + JMAf + + CFBundleTypeRole + Viewer + LSTypeIsPackage + + + + CFBundleTypeExtensions + + sfc + smc + swc + fig + gd3 + + CFBundleTypeIconFile + CART.icns + CFBundleTypeName + Snes9x ROM Image + CFBundleTypeOSTypes + + CART + + CFBundleTypeRole + Viewer + LSTypeIsPackage + + + + CFBundleTypeExtensions + + srm + + CFBundleTypeIconFile + SRAM.icns + CFBundleTypeName + Snes9x SRAM Data + CFBundleTypeOSTypes + + SRAM + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + frz + + CFBundleTypeIconFile + SAVE.icns + CFBundleTypeName + Snes9x Freeze Data + CFBundleTypeOSTypes + + SAVE + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + smv + + CFBundleTypeName + Snes9x Movie Data + CFBundleTypeOSTypes + + SMOV + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + spc + + CFBundleTypeName + Snes9x SPC Data + CFBundleTypeOSTypes + + SSPC + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + cht + + CFBundleTypeName + Snes9x Cheat Data + CFBundleTypeOSTypes + + SCHT + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + rtc + + CFBundleTypeName + Snes9x RTC Data + CFBundleTypeOSTypes + + SRTC + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + * + + CFBundleTypeOSTypes + + **** + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleExecutable + Snes9x + CFBundleGetInfoString + Snes9x 1.52, Copyright 1996-2010 Snes9x developers. + CFBundleHelpBookFolder + Snes9x Help + CFBundleHelpBookName + Snes9x Help + CFBundleIconFile + APPL.icns + CFBundleIdentifier + com.snes9x.macos.snes9x + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Snes9x + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.52 + CFBundleSignature + ~9X~ + CFBundleVersion + 1.52 + CSResourcesFileMapped + + + diff --git a/macosx/Info_i386.plist b/macosx/Info_i386.plist new file mode 100644 index 00000000..5184e4d3 --- /dev/null +++ b/macosx/Info_i386.plist @@ -0,0 +1,189 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + jma + + CFBundleTypeName + JMA archive + CFBundleTypeOSTypes + + JMAf + + CFBundleTypeRole + Viewer + LSTypeIsPackage + + + + CFBundleTypeExtensions + + sfc + smc + swc + fig + gd3 + + CFBundleTypeIconFile + CART.icns + CFBundleTypeName + Snes9x ROM Image + CFBundleTypeOSTypes + + CART + + CFBundleTypeRole + Viewer + LSTypeIsPackage + + + + CFBundleTypeExtensions + + srm + + CFBundleTypeIconFile + SRAM.icns + CFBundleTypeName + Snes9x SRAM Data + CFBundleTypeOSTypes + + SRAM + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + frz + + CFBundleTypeIconFile + SAVE.icns + CFBundleTypeName + Snes9x Freeze Data + CFBundleTypeOSTypes + + SAVE + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + smv + + CFBundleTypeName + Snes9x Movie Data + CFBundleTypeOSTypes + + SMOV + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + spc + + CFBundleTypeName + Snes9x SPC Data + CFBundleTypeOSTypes + + SSPC + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + cht + + CFBundleTypeName + Snes9x Cheat Data + CFBundleTypeOSTypes + + SCHT + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + rtc + + CFBundleTypeName + Snes9x RTC Data + CFBundleTypeOSTypes + + SRTC + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + * + + CFBundleTypeOSTypes + + **** + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleExecutable + Snes9x (i386) + CFBundleGetInfoString + Snes9x 1.52, Copyright 1996-2010 Snes9x developers. + CFBundleHelpBookFolder + Snes9x Help + CFBundleHelpBookName + Snes9x Help + CFBundleIconFile + APPL.icns + CFBundleIdentifier + com.snes9x.macos.snes9x + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Snes9x + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.52 + CFBundleSignature + ~9X~ + CFBundleVersion + 1.52 + CSResourcesFileMapped + + + diff --git a/macosx/Info_ppc.plist b/macosx/Info_ppc.plist new file mode 100644 index 00000000..26179de6 --- /dev/null +++ b/macosx/Info_ppc.plist @@ -0,0 +1,189 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + jma + + CFBundleTypeName + JMA archive + CFBundleTypeOSTypes + + JMAf + + CFBundleTypeRole + Viewer + LSTypeIsPackage + + + + CFBundleTypeExtensions + + sfc + smc + swc + fig + gd3 + + CFBundleTypeIconFile + CART.icns + CFBundleTypeName + Snes9x ROM Image + CFBundleTypeOSTypes + + CART + + CFBundleTypeRole + Viewer + LSTypeIsPackage + + + + CFBundleTypeExtensions + + srm + + CFBundleTypeIconFile + SRAM.icns + CFBundleTypeName + Snes9x SRAM Data + CFBundleTypeOSTypes + + SRAM + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + frz + + CFBundleTypeIconFile + SAVE.icns + CFBundleTypeName + Snes9x Freeze Data + CFBundleTypeOSTypes + + SAVE + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + smv + + CFBundleTypeName + Snes9x Movie Data + CFBundleTypeOSTypes + + SMOV + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + spc + + CFBundleTypeName + Snes9x SPC Data + CFBundleTypeOSTypes + + SSPC + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + cht + + CFBundleTypeName + Snes9x Cheat Data + CFBundleTypeOSTypes + + SCHT + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + rtc + + CFBundleTypeName + Snes9x RTC Data + CFBundleTypeOSTypes + + SRTC + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleTypeExtensions + + * + + CFBundleTypeOSTypes + + **** + + CFBundleTypeRole + None + LSTypeIsPackage + + + + CFBundleExecutable + Snes9x (ppc) + CFBundleGetInfoString + Snes9x 1.52, Copyright 1996-2010 Snes9x developers. + CFBundleHelpBookFolder + Snes9x Help + CFBundleHelpBookName + Snes9x Help + CFBundleIconFile + APPL.icns + CFBundleIdentifier + com.snes9x.macos.snes9x + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Snes9x + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.52 + CFBundleSignature + ~9X~ + CFBundleVersion + 1.52 + CSResourcesFileMapped + + + diff --git a/macosx/SAVE.icns b/macosx/SAVE.icns new file mode 100644 index 00000000..99d504fa Binary files /dev/null and b/macosx/SAVE.icns differ diff --git a/macosx/SRAM.icns b/macosx/SRAM.icns new file mode 100644 index 00000000..2e596501 Binary files /dev/null and b/macosx/SRAM.icns differ diff --git a/macosx/docs/FAQ.rtf b/macosx/docs/FAQ.rtf new file mode 100644 index 00000000..bc475465 --- /dev/null +++ b/macosx/docs/FAQ.rtf @@ -0,0 +1,97 @@ +{\rtf1\ansi\ansicpg932\cocoartf1038\cocoasubrtf250 +{\fonttbl\f0\fnil\fcharset0 LucidaGrande;} +{\colortbl;\red255\green255\blue255;\red153\green102\blue51;\red0\green0\blue255;} +\paperw11900\paperh16840\margl1440\margr1440\vieww11500\viewh12780\viewkind0 +\pard\tx285\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\ql\qnatural + +\f0\fs24 \cf0 \ + +\b\fs28 FAQ for Mac port +\b0\fs24 \ +\ +\ +\pard\tx285\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\ql\qnatural + +\b\fs26 \cf2 Differences and similarities among the Mac port and other ports +\b0\fs24 \cf0 \ +\ +\pard\tx285\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\ql\qnatural +\cf3 Files created by Snes9x\cf0 \ + These files are compatible, except for the extension of the snapshot file. The only one difference is that the Mac port puts the thumbnail screenshot into the resource fork of .frz and .smv files, but the resource fork is usually deleted or separated when you send these files to your friends who don't use Mac.\ +\ +\cf3 Key mapping\cf0 \ + The default settings of key mapping are different. For example, the A-button is the command key on Mac, while it's the D key in Windows.\ +\ +\cf3 User interface\cf0 \ + All of the menus and dialogs are different.\ +\ +\cf3 AVI or QuickTime export\cf0 \ + Mac port supports QuickTime export instead of AVI export in Windows port.\ +\ +\cf3 Sound effect and Core Image filter\cf0 \ + These features are for Mac only because they use Mac OS X's own technologies.\ +\ +\cf3 Netplay\cf0 \ + Snes9x's netplay is incompatible between ports.\ +\ +\cf3 Command-line options\cf0 \ + Mac port doesn't support command-line options.\ +\ +\cf3 Preferences file\cf0 \ + Mac port doesn't support 'snes9x.conf' file.\ +\ +\ +\pard\tx285\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\ql\qnatural + +\b\fs26 \cf2 Emulator Specific Questions +\b0\fs24 \cf0 \ +\ +\pard\tx285\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\ql\qnatural +\cf3 Everything is fine when I play the game, but the next time I play, my save data is not there. Why?\cf0 \ + Saving files into a locked volume and folders where you don't have permission to write will fail. Make sure where you are saving files in 'Preferences' dialog. The most common case for Mac beginners is launching Snes9x directly from the disk image with choosing 'Snes9x folder' for saving destination.\ +\ +\cf3 Why can't I press many buttons at once? Especially in Chrono Trigger.\cf0 \ + Some keyboards can only output two pressed keys at a time, except for modifier keys (shift, command, option and control). Set modifier keys to some of the necessary buttons.\ +\ +\cf3 How can I enter the Game Genie / PAR code in 'Cheat Entry' dialog?\cf0 \ + Simply enter the code directly into the address column. Snes9x automatically translates it to the general format.\ +\ +\cf3 I recently purchased a gamepad controller. Will it work on Snes9x?\ +\pard\tx285\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\ql\qnatural +\cf0 If your gamepad is conformable to USB Device Class Definition for Human Interface Devices, it may work. Note that most gamepads don't officially support Mac OS X even if they work without problems.\cf3 \ +\ +I connected my gamepad but it doesn't work.\cf0 \ + Gamepads cannot be used until you configure its settings in 'Configure Controllers' dialog.\ +\ +\pard\tx285\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\ql\qnatural +\cf3 I think my options in Snes9x got screwed up, how do I reset them?\cf0 \ + Quit Snes9x and trash the preferences file 'com.snes9x.macos.snes9x.plist' in ~/Library/Preferences.\ +\ +\cf3 I had a bad checksummed game that didn't work so I adjusted the header, but it still doesn't work :( Why?\cf0 \ + It should be noted that while it is possible to plop a ROM into Snestool, or several other programs, and adjust the header size to be the same as a proper 'good checksum' ROM, this merely mimics the appearance of a good ROM. Any problems still found within its evil will remain. One could compare it to covering up a circumorbital haematoma with a paper bag.\ +\ +\cf3 Why doesn't game X work?\cf0 \ + There are four possible answers to this question, depending on the scenario. Answer one is that it does work, but your ROM dump is incorrect (this MAY be fixed by reattaching your cartridge to your copier and redumping). Answer two is that we have found a solution or a hack to the problem, but have not yet implemented a fix. Answer three, a subsidiary of answer two, is that we do NOT know what is wrong with it, and as such have not yet implemented a fix. Answer four is that Snes9x CANNOT emulate the game correctly due to its poor implementation around timings between emulated units.\ +\ +\cf3 When is the next version of Snes9x coming out?\cf0 \ + Chances are it will be coming out when enough changes have been made to suitably make a release. You can generally guesstimate the release date by paying attention to the Developers forum at snes9x.com. But don't ask them when the next release will be.\ +\ +\ +\pard\tx285\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\ql\qnatural + +\b\fs26 \cf2 Miscellaneous Questions +\b0\fs24 \cf0 \ +\ +\pard\tx285\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\ql\qnatural +\cf3 Is it legal?\cf0 \ + This has been asked time and again, and the answer is yes. Developing, downloading, or using the emulator, Snes9x, is completely legal. Downloading games, called ROMS, however is not. If you own the original cartridge of a game, you are still not entitled to download the ROM image of that game. You may create a single backup image of your own cartridge via proper hardware, but it must be YOUR cartridge and is only usable in place of the original... so only one may be active at any time. Many sites claim that you may legally download ROMs for up to 24 hours before they must be deleted. This is also wrong; you can't legally download these for "trial" purposes. You can't download ROMs for educational purposes either. If you wish to use Super Nintendo Entertainment System games for educational purposes, contact your closest Nintendo Outlet and discuss educational programming with them. Finally, a small number of ROMs are labeled "(PD)". This means public domain, and these games are not under copyright. As such they are legal to download at your hearts content. These include programs created by internet users such as yourself for use in Super Nintendo emulators. As of this time there are no commercial videogames in the public domain.\ +\ +\cf3 My friend, Tibby, says that you are wrong and that game companies don't care if you download games!\cf0 \ + Whilst not actually a question, and more of a statement, I am afraid Tibby is incorrect. Feel free to peruse the various legal documentation sprawled throughout the World Wide Web or your local constituency. As for the blatant generalization that companies do not care; At least one does, and truthfully many more do as well, as such the statement is obviously a fallacy. For those who think it is not fair, or shouldn't be the way it is... perhaps not, though as holders of a copyright it is up to Nintendo to decide how and when their products are distributed. \ +\ +\cf3 I just purchased your fine program off eBay for $19.89, but my friend says I can download it for free. Can you guys give me my money back?\cf0 \ + Okay, this question hasn't actually been asked, however our free downloadable program does seem to get sold on eBay more often than it should, which is to say at all. We cannot reimburse anyone who was unlucky enough to be scammed into purchasing Snes9x, just as McDonalds cannot reimburse you if you purchased 100 Happy Meals from a random stranger and he gave you a frozen fish. If you find yourself in this situation... Purchasing Snes9x, not frozen fish... Please take the time to inform eBay via their heavily disguised investigations department, and leave any negative feedback that you wish. It would also be appreciated by the Snes9x team if you could mention where and when this happened so that we can take measures to stop it from happening again. While the fact we aren't making money from the program in no way bothers us (It is freeware after all), that some grubby bastards are does.\ +\ +\cf3 So err, where exactly do I contact y'all, eh?\cf0 \ + The most convenient way to contact us would be via www.snes9x.com. There is a forum that is checked at least 12 times a day by regulars, and at least a few of us can actually give some advice. E-mail is also a possibility, though it is much slower, and you'll hafta find the e-mail addresses on your own. Be sure to read the FAQ and Read me before posting, as things already answered many a time will probably result in random insults or heavy sarcasm.\ +} \ No newline at end of file diff --git a/macosx/docs/readme-mac.txt b/macosx/docs/readme-mac.txt new file mode 100644 index 00000000..43588960 --- /dev/null +++ b/macosx/docs/readme-mac.txt @@ -0,0 +1 @@ +The manual is in 'Help' menu - 'Snes9x Help'. \ No newline at end of file diff --git a/macosx/folder_Freezes.icns b/macosx/folder_Freezes.icns new file mode 100644 index 00000000..d8c683a3 Binary files /dev/null and b/macosx/folder_Freezes.icns differ diff --git a/macosx/folder_SRAMs.icns b/macosx/folder_SRAMs.icns new file mode 100644 index 00000000..d245d79b Binary files /dev/null and b/macosx/folder_SRAMs.icns differ diff --git a/macosx/freeze_defrost.aiff b/macosx/freeze_defrost.aiff new file mode 100644 index 00000000..22d4e409 Binary files /dev/null and b/macosx/freeze_defrost.aiff differ diff --git a/macosx/icons.png b/macosx/icons.png new file mode 100644 index 00000000..0fb973bc Binary files /dev/null and b/macosx/icons.png differ diff --git a/macosx/libHIDUtilities_u.a b/macosx/libHIDUtilities_u.a new file mode 100644 index 00000000..5197c1a5 Binary files /dev/null and b/macosx/libHIDUtilities_u.a differ diff --git a/macosx/libz_u.a b/macosx/libz_u.a new file mode 100644 index 00000000..82761c5f Binary files /dev/null and b/macosx/libz_u.a differ diff --git a/macosx/logo_defrost.png b/macosx/logo_defrost.png new file mode 100644 index 00000000..fea4873d Binary files /dev/null and b/macosx/logo_defrost.png differ diff --git a/macosx/logo_freeze.png b/macosx/logo_freeze.png new file mode 100644 index 00000000..3ea50877 Binary files /dev/null and b/macosx/logo_freeze.png differ diff --git a/macosx/mac-appleevent.cpp b/macosx/mac-appleevent.cpp new file mode 100644 index 00000000..2c8a2b18 --- /dev/null +++ b/macosx/mac-appleevent.cpp @@ -0,0 +1,337 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "port.h" + +#include "mac-prefix.h" +#include "mac-os.h" +#include "mac-snes9x.h" +#include "mac-appleevent.h" + +static AEEventHandlerUPP oappUPP, rappUPP, pdocUPP, quitUPP, odocUPP; + +static pascal OSErr AEoapp (const AppleEvent *, AppleEvent *, long); +static pascal OSErr AErapp (const AppleEvent *, AppleEvent *, long); +static pascal OSErr AEpdoc (const AppleEvent *, AppleEvent *, long); +static pascal OSErr AEquit (const AppleEvent *, AppleEvent *, long); +static pascal OSErr AEodoc (const AppleEvent *, AppleEvent *, long); + + +static pascal OSErr AEoapp (const AppleEvent *theEvent, AppleEvent *theReply, long refCon) +{ + if (running) + return (noErr); + + if (startopendlog) + { + if (SNES9X_OpenCart(NULL)) + { + SNES9X_Go(); + QuitApplicationEventLoop(); + } + else + AdjustMenus(); + } + + return (noErr); +} + +static pascal OSErr AErapp (const AppleEvent *theEvent, AppleEvent *theReply, long refCon) +{ + if (running) + return (noErr); + + if (!cartOpen) + { + if (startopendlog) + { + if (SNES9X_OpenCart(NULL)) + { + SNES9X_Go(); + QuitApplicationEventLoop(); + } + else + AdjustMenus(); + } + } + else + { + SNES9X_Go(); + QuitApplicationEventLoop(); + } + + return (noErr); +} + +static pascal OSErr AEpdoc (const AppleEvent *theEvent, AppleEvent *theReply, long refCon) +{ + return (errAEEventNotHandled); +} + +static pascal OSErr AEquit (const AppleEvent *theEvent, AppleEvent *theReply, long refCon) +{ + if (running) + return (noErr); + + SNES9X_Quit(); + QuitApplicationEventLoop(); + + return (noErr); +} + +static pascal OSErr AEodoc (const AppleEvent *theEvent, AppleEvent *theReply, long refCon) +{ + OSErr err; + FSRef ref; + AEDescList docList; + AEKeyword keywd; + DescType rtype; + Size acsize; + long count; + + if (running) + return (noErr); + + err = AEGetParamDesc(theEvent, keyDirectObject, typeAEList, &docList); + if (err) + return (noErr); + + err = AECountItems(&docList, &count); + if (err || (count != 1)) + { + err = AEDisposeDesc(&docList); + return (noErr); + } + + err = AEGetNthPtr(&docList, 1, typeFSRef, &keywd, &rtype, &ref, sizeof(FSRef), &acsize); + if (err == noErr) + { + if (SNES9X_OpenCart(&ref)) + { + SNES9X_Go(); + QuitApplicationEventLoop(); + } + else + AdjustMenus(); + } + + err = AEDisposeDesc(&docList); + + return (noErr); +} + +void InitAppleEvents (void) +{ + OSErr err; + + oappUPP = NewAEEventHandlerUPP(AEoapp); + err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, oappUPP, 0L, false); + + odocUPP = NewAEEventHandlerUPP(AEodoc); + err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, odocUPP, 0L, false); + + pdocUPP = NewAEEventHandlerUPP(AEpdoc); + err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, pdocUPP, 0L, false); + + quitUPP = NewAEEventHandlerUPP(AEquit); + err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, quitUPP, 0L, false); + + rappUPP = NewAEEventHandlerUPP(AErapp); + err = AEInstallEventHandler(kCoreEventClass, kAEReopenApplication, rappUPP, 0L, false); +} + +void DeinitAppleEvents (void) +{ + DisposeAEEventHandlerUPP(oappUPP); + DisposeAEEventHandlerUPP(odocUPP); + DisposeAEEventHandlerUPP(pdocUPP); + DisposeAEEventHandlerUPP(quitUPP); + DisposeAEEventHandlerUPP(rappUPP); +} diff --git a/macosx/mac-appleevent.h b/macosx/mac-appleevent.h new file mode 100644 index 00000000..e3013d9b --- /dev/null +++ b/macosx/mac-appleevent.h @@ -0,0 +1,197 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_appleevent_h_ +#define _mac_appleevent_h_ + +void InitAppleEvents (void); +void DeinitAppleEvents (void); + +#endif diff --git a/macosx/mac-audio.cpp b/macosx/mac-audio.cpp new file mode 100644 index 00000000..597272aa --- /dev/null +++ b/macosx/mac-audio.cpp @@ -0,0 +1,1094 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "apu.h" + +#include +#include +#include +#include + +#include "mac-prefix.h" +#include "mac-dialog.h" +#include "mac-musicbox.h" +#include "mac-os.h" +#include "mac-snes9x.h" +#include "mac-audio.h" + +#define kAUReverb (1 << 0) +#define kAUGraphEQ (1 << 1) + +int cureffect = kAUReverb; + +static AUGraph agraph; +static AUNode outNode, cnvNode, revNode, eqlNode; +static AudioUnit outAU, cnvAU, revAU, eqlAU; +static AudioUnitCarbonView carbonView = NULL; +static EventHandlerUPP carbonViewEventUPP = NULL; +static EventHandlerRef carbonViewEventRef = NULL; +static WindowRef effectWRef; +static HISize effectWSize; +static pthread_mutex_t mutex; +static UInt32 outStoredFrames, cnvStoredFrames, revStoredFrames, eqlStoredFrames, devStoredFrames; + +static void ConnectAudioUnits (void); +static void DisconnectAudioUnits (void); +static void SaveEffectPresets (void); +static void LoadEffectPresets (void); +static void SetAudioUnitSoundFormat (void); +static void SetAudioUnitVolume (void); +static void StoreBufferFrameSize (void); +static void ChangeBufferFrameSize (void); +static void ReplaceAudioUnitCarbonView (void); +static void ResizeSoundEffectsDialog (HIViewRef); +static void MacFinalizeSamplesCallBack (void *); +static OSStatus MacAURenderCallBack (void *, AudioUnitRenderActionFlags *, const AudioTimeStamp *, UInt32, UInt32, AudioBufferList *); +static pascal OSStatus SoundEffectsEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus SoundEffectsCarbonViewEventHandler (EventHandlerCallRef, EventRef, void *); + + +void InitMacSound (void) +{ + OSStatus err; + + err = NewAUGraph(&agraph); + +#ifndef MAC_LEOPARD_TIGER_PANTHER_SUPPORT + AudioComponentDescription outdesc, cnvdesc, revdesc, eqldesc; +#else + ComponentDescription outdesc, cnvdesc, revdesc, eqldesc; +#endif + + outdesc.componentType = kAudioUnitType_Output; + outdesc.componentSubType = kAudioUnitSubType_DefaultOutput; + outdesc.componentManufacturer = 0; + outdesc.componentFlags = 0; + outdesc.componentFlagsMask = 0; + + cnvdesc.componentType = kAudioUnitType_FormatConverter; + cnvdesc.componentSubType = kAudioUnitSubType_AUConverter; + cnvdesc.componentManufacturer = kAudioUnitManufacturer_Apple; + cnvdesc.componentFlags = 0; + cnvdesc.componentFlagsMask = 0; + + revdesc.componentType = kAudioUnitType_Effect; + revdesc.componentSubType = kAudioUnitSubType_MatrixReverb; + revdesc.componentManufacturer = kAudioUnitManufacturer_Apple; + revdesc.componentFlags = 0; + revdesc.componentFlagsMask = 0; + + eqldesc.componentType = kAudioUnitType_Effect; + eqldesc.componentSubType = kAudioUnitSubType_GraphicEQ; + eqldesc.componentManufacturer = kAudioUnitManufacturer_Apple; + eqldesc.componentFlags = 0; + eqldesc.componentFlagsMask = 0; + +#ifndef MAC_LEOPARD_TIGER_PANTHER_SUPPORT + err = AUGraphAddNode(agraph, &outdesc, &outNode); + err = AUGraphAddNode(agraph, &cnvdesc, &cnvNode); + err = AUGraphAddNode(agraph, &revdesc, &revNode); + err = AUGraphAddNode(agraph, &eqldesc, &eqlNode); +#else + err = AUGraphNewNode(agraph, &outdesc, 0, NULL, &outNode); + err = AUGraphNewNode(agraph, &cnvdesc, 0, NULL, &cnvNode); + err = AUGraphNewNode(agraph, &revdesc, 0, NULL, &revNode); + err = AUGraphNewNode(agraph, &eqldesc, 0, NULL, &eqlNode); +#endif + + err = AUGraphOpen(agraph); + +#ifndef MAC_LEOPARD_TIGER_PANTHER_SUPPORT + err = AUGraphNodeInfo(agraph, outNode, NULL, &outAU); + err = AUGraphNodeInfo(agraph, cnvNode, NULL, &cnvAU); + err = AUGraphNodeInfo(agraph, revNode, NULL, &revAU); + err = AUGraphNodeInfo(agraph, eqlNode, NULL, &eqlAU); +#else + err = AUGraphGetNodeInfo(agraph, outNode, NULL, NULL, NULL, &outAU); + err = AUGraphGetNodeInfo(agraph, cnvNode, NULL, NULL, NULL, &cnvAU); + err = AUGraphGetNodeInfo(agraph, revNode, NULL, NULL, NULL, &revAU); + err = AUGraphGetNodeInfo(agraph, eqlNode, NULL, NULL, NULL, &eqlAU); +#endif + + SetAudioUnitSoundFormat(); + SetAudioUnitVolume(); + StoreBufferFrameSize(); + ChangeBufferFrameSize(); + + err = AUGraphInitialize(agraph); + + ConnectAudioUnits(); + LoadEffectPresets(); + + pthread_mutex_init(&mutex, NULL); + S9xSetSamplesAvailableCallback(MacFinalizeSamplesCallBack, NULL); +} + +void DeinitMacSound (void) +{ + OSStatus err; + + pthread_mutex_destroy(&mutex); + SaveEffectPresets(); + DisconnectAudioUnits(); + err = AUGraphUninitialize(agraph); + err = AUGraphClose(agraph); + err = DisposeAUGraph(agraph); +} + +static void SetAudioUnitSoundFormat (void) +{ + OSStatus err; + AudioStreamBasicDescription format; + +#ifdef __BIG_ENDIAN__ + UInt32 endian = kLinearPCMFormatFlagIsBigEndian; +#else + UInt32 endian = 0; +#endif + + memset(&format, 0, sizeof(format)); + + format.mSampleRate = (Float64) Settings.SoundPlaybackRate; + format.mFormatID = kAudioFormatLinearPCM; + format.mFormatFlags = endian | (Settings.SixteenBitSound ? kLinearPCMFormatFlagIsSignedInteger : 0); + format.mBytesPerPacket = 2 * (Settings.SixteenBitSound ? 2 : 1); + format.mFramesPerPacket = 1; + format.mBytesPerFrame = 2 * (Settings.SixteenBitSound ? 2 : 1); + format.mChannelsPerFrame = 2; + format.mBitsPerChannel = Settings.SixteenBitSound ? 16 : 8; + + err = AudioUnitSetProperty(aueffect ? cnvAU : outAU, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof(format)); +} + +static void SetAudioUnitVolume (void) +{ + OSStatus err; + + err = AudioUnitSetParameter(outAU, kAudioUnitParameterUnit_LinearGain, kAudioUnitScope_Output, 0, (float) macSoundVolume / 100.0f, 0); +} + +static void StoreBufferFrameSize (void) +{ + OSStatus err; + UInt32 size; + AudioDeviceID device; +#ifndef MAC_PANTHER_SUPPORT + AudioObjectPropertyAddress address; + + address.mSelector = kAudioDevicePropertyBufferFrameSize; + address.mScope = kAudioObjectPropertyScopeGlobal; + address.mElement = kAudioObjectPropertyElementMaster; +#endif + + size = sizeof(AudioDeviceID); + err = AudioUnitGetProperty(outAU, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &device, &size); + + size = sizeof(UInt32); +#ifndef MAC_PANTHER_SUPPORT + err = AudioObjectGetPropertyData(device, &address, 0, NULL, &size, &devStoredFrames); +#else + err = AudioDeviceGetProperty(device, 0, false, kAudioDevicePropertyBufferFrameSize, &size, &devStoredFrames); +#endif + + size = sizeof(UInt32); + err = AudioUnitGetProperty(outAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &outStoredFrames, &size); + size = sizeof(UInt32); + err = AudioUnitGetProperty(eqlAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &eqlStoredFrames, &size); + size = sizeof(UInt32); + err = AudioUnitGetProperty(revAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &revStoredFrames, &size); + size = sizeof(UInt32); + err = AudioUnitGetProperty(cnvAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &cnvStoredFrames, &size); +} + +static void ChangeBufferFrameSize (void) +{ + OSStatus err; + UInt32 numframes, size; + AudioDeviceID device; +#ifndef MAC_PANTHER_SUPPORT + AudioObjectPropertyAddress address; + + address.mSelector = kAudioDevicePropertyBufferFrameSize; + address.mScope = kAudioObjectPropertyScopeGlobal; + address.mElement = kAudioObjectPropertyElementMaster; +#else + AudioTimeStamp ts; + + ts.mFlags = 0; +#endif + + size = sizeof(AudioDeviceID); + err = AudioUnitGetProperty(outAU, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &device, &size); + + size = sizeof(UInt32); + + if (macSoundInterval_ms == 0) + { + #ifndef MAC_PANTHER_SUPPORT + err = AudioObjectSetPropertyData(device, &address, 0, NULL, size, &devStoredFrames); + #else + err = AudioDeviceSetProperty(device, &ts, 0, false, kAudioDevicePropertyBufferFrameSize, size, &devStoredFrames); + #endif + + err = AudioUnitSetProperty(outAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &outStoredFrames, size); + err = AudioUnitSetProperty(eqlAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &eqlStoredFrames, size); + err = AudioUnitSetProperty(revAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &revStoredFrames, size); + err = AudioUnitSetProperty(cnvAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &cnvStoredFrames, size); + + printf("Interval: system, Frames: %d/%d/%d/%d/%d\n", (int) devStoredFrames, (int) outStoredFrames, (int) eqlStoredFrames, (int) revStoredFrames, (int) cnvStoredFrames); + } + else + { + numframes = macSoundInterval_ms * Settings.SoundPlaybackRate / 1000; + + #ifndef MAC_PANTHER_SUPPORT + err = AudioObjectSetPropertyData(device, &address, 0, NULL, size, &numframes); + #else + err = AudioDeviceSetProperty(device, &ts, 0, false, kAudioDevicePropertyBufferFrameSize, size, &numframes); + #endif + + err = AudioUnitSetProperty(outAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &numframes, size); + err = AudioUnitSetProperty(eqlAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &numframes, size); + err = AudioUnitSetProperty(revAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &numframes, size); + err = AudioUnitSetProperty(cnvAU, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &numframes, size); + + printf("Interval: %dms, Frames: %d\n", (int) macSoundInterval_ms, (int) numframes); + } +} + +static void ConnectAudioUnits (void) +{ + OSStatus err; + AURenderCallbackStruct callback; + + callback.inputProc = MacAURenderCallBack; + callback.inputProcRefCon = NULL; + + if (systemVersion >= 0x1050) + err = AUGraphSetNodeInputCallback(agraph, aueffect ? cnvNode : outNode, 0, &callback); +#ifdef MAC_TIGER_PANTHER_SUPPORT + else + err = AudioUnitSetProperty(aueffect ? cnvAU : outAU, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callback, sizeof(callback)); +#endif + + if ((aueffect & kAUReverb) && (aueffect & kAUGraphEQ)) + { + err = AUGraphConnectNodeInput(agraph, cnvNode, 0, revNode, 0); + err = AUGraphConnectNodeInput(agraph, revNode, 0, eqlNode, 0); + err = AUGraphConnectNodeInput(agraph, eqlNode, 0, outNode, 0); + } + else + if (aueffect & kAUReverb) + { + err = AUGraphConnectNodeInput(agraph, cnvNode, 0, revNode, 0); + err = AUGraphConnectNodeInput(agraph, revNode, 0, outNode, 0); + } + else + if (aueffect & kAUGraphEQ) + { + err = AUGraphConnectNodeInput(agraph, cnvNode, 0, eqlNode, 0); + err = AUGraphConnectNodeInput(agraph, eqlNode, 0, outNode, 0); + } +} + +static void DisconnectAudioUnits (void) +{ + OSStatus err; + + err = AUGraphClearConnections(agraph); +} + +static OSStatus MacAURenderCallBack (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData) +{ + if (Settings.Mute) + { + memset(ioData->mBuffers[0].mData, 0, ioData->mBuffers[0].mDataByteSize); + *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence; + } + else + if (Settings.Stereo) + { + unsigned int samples; + + samples = ioData->mBuffers[0].mDataByteSize; + if (Settings.SixteenBitSound) + samples >>= 1; + + pthread_mutex_lock(&mutex); + S9xMixSamples((uint8 *) ioData->mBuffers[0].mData, samples); + pthread_mutex_unlock(&mutex); + } + else // Manually map L to R + { + unsigned int monosmp; + + monosmp = ioData->mBuffers[0].mDataByteSize >> 1; + if (Settings.SixteenBitSound) + monosmp >>= 1; + + pthread_mutex_lock(&mutex); + S9xMixSamples((uint8 *) ioData->mBuffers[0].mData, monosmp); + pthread_mutex_unlock(&mutex); + + if (Settings.SixteenBitSound) + { + for (int i = monosmp - 1; i >= 0; i--) + ((int16 *) ioData->mBuffers[0].mData)[i * 2 + 1] = ((int16 *) ioData->mBuffers[0].mData)[i * 2] = ((int16 *) ioData->mBuffers[0].mData)[i]; + } + else + { + for (int i = monosmp - 1; i >= 0; i--) + ((int8 *) ioData->mBuffers[0].mData)[i * 2 + 1] = ((int8 *) ioData->mBuffers[0].mData)[i * 2] = ((int8 *) ioData->mBuffers[0].mData)[i]; + } + } + + return (noErr); +} + +static void MacFinalizeSamplesCallBack (void *userData) +{ + pthread_mutex_lock(&mutex); + S9xFinalizeSamples(); + pthread_mutex_unlock(&mutex); +} + +static void SaveEffectPresets (void) +{ + OSStatus err; + AUPreset preset; + CFPropertyListRef classData; + UInt32 size; + + preset.presetNumber = -1; // User Preset + preset.presetName = CFSTR("SNES9X Preset"); + + err = AudioUnitSetProperty(revAU, kAudioUnitProperty_CurrentPreset, kAudioUnitScope_Global, 0, &preset, sizeof(preset)); + if (err == noErr) + { + size = sizeof(classData); + err = AudioUnitGetProperty(revAU, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &classData, &size); + if (err == noErr) + { + CFPreferencesSetAppValue(CFSTR("Effect_Preset_Reverb"), classData, kCFPreferencesCurrentApplication); + CFRelease(classData); + } + } + + err = AudioUnitSetProperty(eqlAU, kAudioUnitProperty_CurrentPreset, kAudioUnitScope_Global, 0, &preset, sizeof(preset)); + if (err == noErr) + { + size = sizeof(classData); + err = AudioUnitGetProperty(eqlAU, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &classData, &size); + if (err == noErr) + { + CFPreferencesSetAppValue(CFSTR("Effect_Preset_GraphEQ"), classData, kCFPreferencesCurrentApplication); + CFRelease(classData); + } + } + + CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); +} + +static void LoadEffectPresets (void) +{ + OSStatus err; + CFPropertyListRef classData; + + classData = CFPreferencesCopyAppValue(CFSTR("Effect_Preset_Reverb"), kCFPreferencesCurrentApplication); + if (classData) + { + err = AudioUnitSetProperty(revAU, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &classData, sizeof(classData)); + CFRelease(classData); + } + + classData = CFPreferencesCopyAppValue(CFSTR("Effect_Preset_GraphEQ"), kCFPreferencesCurrentApplication); + if (classData) + { + err = AudioUnitSetProperty(eqlAU, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global, 0, &classData, sizeof(classData)); + CFRelease(classData); + } +} + +void MacStartSound (void) +{ + OSStatus err; + Boolean r = false; + + if (macQTRecord) + return; + + err = AUGraphIsRunning(agraph, &r); + if (err == noErr && r == false) + { + err = AUGraphStart(agraph); + printf("AUGraph started.\n"); + } +} + +void MacStopSound (void) +{ + OSStatus err; + Boolean r = false; + + if (macQTRecord) + return; + + err = AUGraphIsRunning(agraph, &r); + if (err == noErr && r == true) + { + err = AUGraphStop(agraph); + printf("AUGraph stopped.\n"); + } +} + +bool8 S9xOpenSoundDevice (void) +{ + OSStatus err; + + err = AUGraphUninitialize(agraph); + + SetAudioUnitSoundFormat(); + SetAudioUnitVolume(); + ChangeBufferFrameSize(); + + err = AUGraphInitialize(agraph); + + return (true); +} + +void PlayAlertSound (void) +{ + if (systemVersion >= 0x1050) + AudioServicesPlayAlertSound(kUserPreferredAlert); +#ifdef MAC_TIGER_PANTHER_SUPPORT + else + SysBeep(10); +#endif +} + +static void ReplaceAudioUnitCarbonView (void) +{ + OSStatus err; + AudioUnit editau; + Component cmp; + ComponentDescription desc; + HIViewRef pane, contentview, ctl; + HIViewID cid; + Float32Point location, size; + Rect rct; + UInt32 psize; + + if (carbonView) + { + err = RemoveEventHandler(carbonViewEventRef); + DisposeEventHandlerUPP(carbonViewEventUPP); + carbonViewEventRef = NULL; + carbonViewEventUPP = NULL; + + CloseComponent(carbonView); + carbonView = NULL; + } + + switch (cureffect) + { + case kAUGraphEQ: + editau = eqlAU; + break; + + case kAUReverb: + default: + editau = revAU; + break; + } + + desc.componentType = kAudioUnitCarbonViewComponentType; + desc.componentSubType = kAUCarbonViewSubType_Generic; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + err = AudioUnitGetPropertyInfo(editau, kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, 0, &psize, NULL); + if (err == noErr) + { + ComponentDescription *editors; + int nEditors; + + nEditors = psize / sizeof(ComponentDescription); + + editors = new ComponentDescription[nEditors]; + + err = AudioUnitGetProperty(editau, kAudioUnitProperty_GetUIComponentList, kAudioUnitScope_Global, 0, editors, &psize); + if (err == noErr) + desc = editors[0]; + + delete [] editors; + } + + HIViewFindByID(HIViewGetRoot(effectWRef), kHIViewWindowContentID, &contentview); + + cmp = FindNextComponent(NULL, &desc); + if (cmp) + { + err = OpenAComponent(cmp, &carbonView); + if (err == noErr) + { + EventTypeSpec event[] = { { kEventClassControl, kEventControlBoundsChanged } }; + + GetWindowBounds(effectWRef, kWindowContentRgn, &rct); + location.x = 20; + location.y = 96; + size.x = rct.right - rct.left; + size.y = rct.bottom - rct.top; + + err = AudioUnitCarbonViewCreate(carbonView, editau, effectWRef, contentview, &location, &size, &pane); + + carbonViewEventUPP = NewEventHandlerUPP(SoundEffectsCarbonViewEventHandler); + err = InstallControlEventHandler(pane, carbonViewEventUPP, GetEventTypeCount(event), event, (void *) effectWRef, &carbonViewEventRef); + + ResizeSoundEffectsDialog(pane); + } + else + carbonView = NULL; + } + else + carbonView = NULL; + + cid.id = 0; + cid.signature = 'Enab'; + HIViewFindByID(contentview, cid, &ctl); + SetControl32BitValue(ctl, (aueffect & cureffect) ? 1 : 0); +} + +static void ResizeSoundEffectsDialog (HIViewRef view) +{ + OSStatus err; + HIViewRef ctl, root; + HIViewID cid; + HIRect bounds; + Rect rv; + int w, h; + + root = HIViewGetRoot(effectWRef); + + cid.id = 0; + cid.signature = 'Enab'; + HIViewFindByID(root, cid, &ctl); + + err = HIViewSetVisible(ctl, false); + err = HIViewSetVisible(view, false); + + HIViewGetBounds(view, &bounds); + w = ((int) bounds.size.width + 30 > (int) effectWSize.width) ? ((int) bounds.size.width + 30) : (int) effectWSize.width; + h = (int) bounds.size.height + 122; +#ifdef MAC_PANTHER_SUPPORT + if (systemVersion < 0x1040) + h += 16; +#endif + GetWindowBounds(effectWRef, kWindowStructureRgn, &rv); + rv.right = rv.left + w; + rv.bottom = rv.top + h; + err = TransitionWindow(effectWRef, kWindowSlideTransitionEffect, kWindowResizeTransitionAction, &rv); + + err = HIViewSetVisible(ctl, true); + err = HIViewSetVisible(view, true); + +#ifdef MAC_PANTHER_SUPPORT + if (systemVersion < 0x1040) + { + HIRect frame; + Rect rct; + + GetWindowBounds(effectWRef, kWindowContentRgn, &rv); + + cid.signature = 'SfUI'; + HIViewFindByID(root, cid, &ctl); + HIViewGetFrame(ctl, &frame); + frame.size.width = (float) (rv.right - rv.left); + HIViewSetFrame(ctl, &frame); + + cid.signature = 'LINE'; + HIViewFindByID(root, cid, &ctl); + HIViewGetFrame(ctl, &frame); + frame.size.width = (float) (rv.right - rv.left - 24); + HIViewSetFrame(ctl, &frame); + + rct.top = 0; + rct.left = 0; + rct.bottom = rv.bottom - rv.top; + rct.right = rv.right - rv.left; + err = InvalWindowRect(effectWRef, &rct); + } +#endif +} + +void ConfigureSoundEffects (void) +{ + OSStatus err; + IBNibRef nibRef; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef uiparts; + + err = CreateWindowFromNib(nibRef, CFSTR("SoundEffect"), &uiparts); + if (err == noErr) + { + EventHandlerUPP eventUPP; + EventHandlerRef eventHandler; + EventTypeSpec event[] = { { kEventClassWindow, kEventWindowClose }, + { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }; + MenuRef menu; + HIViewRef ctl, userpane, contentview; + HIViewID cid; + CFStringRef str; + Rect rct; + WindowAttributes metal = 0; + + cid.id = 0; + cid.signature = 'SfUI'; + HIViewFindByID(HIViewGetRoot(uiparts), cid, &userpane); + GetWindowBounds(uiparts, kWindowContentRgn, &rct); + + if (systemVersion >= 0x1040) // AUs support compositing + { + HIRect frame; + + str = CFCopyLocalizedString(CFSTR("CreateMetalDlg"), "NO"); + if (str) + { + if (CFStringCompare(str, CFSTR("YES"), 0) == kCFCompareEqualTo) + metal = kWindowMetalAttribute; + + CFRelease(str); + } + + frame = CGRectMake(0.0f, 0.0f, (float) (rct.right - rct.left), (float) (rct.bottom - rct.top)); + err = CreateNewWindow(kDocumentWindowClass, kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | kWindowStandardHandlerAttribute | kWindowCompositingAttribute | metal, &rct, &effectWRef); + err = HIViewFindByID(HIViewGetRoot(effectWRef), kHIViewWindowContentID, &contentview); + err = HIViewAddSubview(contentview, userpane); + err = HIViewSetFrame(userpane, &frame); + } + #ifdef MAC_PANTHER_SUPPORT + else + { + err = CreateNewWindow(kDocumentWindowClass, kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | kWindowStandardHandlerAttribute, &rct, &effectWRef); + err = CreateRootControl(effectWRef, &contentview); + err = EmbedControl(userpane, contentview); + MoveControl(userpane, 0, 0); + } + #endif + + CFRelease(uiparts); + + if (!metal) + err = SetThemeWindowBackground(effectWRef, kThemeBrushDialogBackgroundActive, false); + + str = CFCopyLocalizedString(CFSTR("SoundEffectDlg"), "SoundEffect"); + if (str) + { + err = SetWindowTitleWithCFString(effectWRef, str); + CFRelease(str); + } + + if (systemVersion >= 0x1040) // AUs support compositing + { + HILayoutInfo layoutinfo; + HIViewRef separator; + + cid.signature = 'LINE'; + err = HIViewFindByID(userpane, cid, &separator); + + layoutinfo.version = kHILayoutInfoVersionZero; + err = HIViewGetLayoutInfo(userpane, &layoutinfo); + + layoutinfo.binding.top.toView = contentview; + layoutinfo.binding.top.kind = kHILayoutBindNone; + layoutinfo.binding.bottom.toView = contentview; + layoutinfo.binding.bottom.kind = kHILayoutBindNone; + layoutinfo.binding.left.toView = contentview; + layoutinfo.binding.left.kind = kHILayoutBindLeft; + layoutinfo.binding.right.toView = contentview; + layoutinfo.binding.right.kind = kHILayoutBindRight; + err = HIViewSetLayoutInfo(userpane, &layoutinfo); + + layoutinfo.version = kHILayoutInfoVersionZero; + err = HIViewGetLayoutInfo(separator, &layoutinfo); + + layoutinfo.binding.top.toView = userpane; + layoutinfo.binding.top.kind = kHILayoutBindNone; + layoutinfo.binding.bottom.toView = userpane; + layoutinfo.binding.bottom.kind = kHILayoutBindNone; + layoutinfo.binding.left.toView = userpane; + layoutinfo.binding.left.kind = kHILayoutBindLeft; + layoutinfo.binding.right.toView = userpane; + layoutinfo.binding.right.kind = kHILayoutBindRight; + err = HIViewSetLayoutInfo(separator, &layoutinfo); + } + + eventUPP = NewEventHandlerUPP(SoundEffectsEventHandler); + err = InstallWindowEventHandler(effectWRef, eventUPP, GetEventTypeCount(event), event, (void *) effectWRef, &eventHandler); + + GetWindowBounds(effectWRef, kWindowContentRgn, &rct); + effectWSize.width = (float) (rct.right - rct.left); + effectWSize.height = (float) (rct.bottom - rct.top ); + + carbonView = NULL; + ReplaceAudioUnitCarbonView(); + + cid.signature = 'Epop'; + HIViewFindByID(userpane, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + switch (cureffect) + { + case kAUReverb: + CheckMenuItem(menu, 1, true); + SetControl32BitValue(ctl, 1); + break; + + case kAUGraphEQ: + CheckMenuItem(menu, 2, true); + SetControl32BitValue(ctl, 2); + break; + } + + MoveWindowPosition(effectWRef, kWindowSoundEffect, false); + ShowWindow(effectWRef); + err = RunAppModalLoopForWindow(effectWRef); + HideWindow(effectWRef); + SaveWindowPosition(effectWRef, kWindowSoundEffect); + + if (carbonView) + { + err = RemoveEventHandler(carbonViewEventRef); + DisposeEventHandlerUPP(carbonViewEventUPP); + carbonViewEventRef = NULL; + carbonViewEventUPP = NULL; + + CloseComponent(carbonView); + carbonView = NULL; + } + + err = RemoveEventHandler(eventHandler); + DisposeEventHandlerUPP(eventUPP); + + CFRelease(effectWRef); + } + + DisposeNibReference(nibRef); + } +} + +static pascal OSStatus SoundEffectsCarbonViewEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + HIViewRef ctl; + HIRect bounds; + + switch (GetEventClass(inEvent)) + { + case kEventClassControl: + switch (GetEventKind(inEvent)) + { + case kEventControlBoundsChanged: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &ctl); + if (err == noErr) + { + err = GetEventParameter(inEvent, kEventParamCurrentBounds, typeHIRect, NULL, sizeof(HIRect), NULL, &bounds); + if (err == noErr) + { + if ((bounds.size.width > 0) && (bounds.size.height > 0)) + ResizeSoundEffectsDialog(ctl); + } + } + + result = noErr; + break; + } + + break; + } + + return (result); +} + +static pascal OSStatus SoundEffectsEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef tWindowRef = (WindowRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + switch (GetEventKind(inEvent)) + { + case kEventWindowClose: + QuitAppModalLoopForWindow(tWindowRef); + result = noErr; + break; + } + + break; + + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(true); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + switch (tHICommand.commandID) + { + case 'Enab': + { + Boolean r = false; + + mboxPause = true; + + err = AUGraphIsRunning(agraph, &r); + if (err == noErr && r) + err = AUGraphStop(agraph); + + DisconnectAudioUnits(); + err = AUGraphUninitialize(agraph); + + aueffect ^= cureffect; + + SetAudioUnitSoundFormat(); + ChangeBufferFrameSize(); + + err = AUGraphInitialize(agraph); + ConnectAudioUnits(); + + if (r) + err = AUGraphStart(agraph); + + mboxPause = false; + + result = noErr; + break; + } + + case 'Revb': + cureffect = kAUReverb; + ReplaceAudioUnitCarbonView(); + break; + + case 'GrEQ': + cureffect = kAUGraphEQ; + ReplaceAudioUnitCarbonView(); + break; + } + } + + break; + } + + break; + } + + return (result); +} diff --git a/macosx/mac-audio.h b/macosx/mac-audio.h new file mode 100644 index 00000000..e08bf9aa --- /dev/null +++ b/macosx/mac-audio.h @@ -0,0 +1,203 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_audio_h_ +#define _mac_audio_h_ + +extern int cureffect; + +void InitMacSound (void); +void DeinitMacSound (void); +void MacStartSound (void); +void MacStopSound (void); +void ConfigureSoundEffects (void); +void PlayAlertSound (void); + +#endif diff --git a/macosx/mac-cart.cpp b/macosx/mac-cart.cpp new file mode 100644 index 00000000..aab57f83 --- /dev/null +++ b/macosx/mac-cart.cpp @@ -0,0 +1,2033 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "snapshot.h" +#include "movie.h" + +#include + +#include "mac-prefix.h" +#include "mac-dialog.h" +#include "mac-os.h" +#include "mac-quicktime.h" +#include "mac-screenshot.h" +#include "mac-snes9x.h" +#include "mac-stringtools.h" +#include "mac-cart.h" + +typedef struct +{ + NavDialogRef nref; + FSRef ref; + Boolean reply; + char name[PATH_MAX + 1]; + IBNibRef customNib; + WindowRef customWindow; + HIViewRef customPane; + CFStringRef customSRef; + short customWidth, customHeight; + Boolean isSheet; +} NavState; + +extern wchar_t macRecordWChar[MOVIE_MAX_METADATA]; + +static NavEventUPP gSheetEventUPP; +static NavObjectFilterUPP gSheetFilterUPP; +static NavState gSheetNav; +static WindowRef gSheetParent; + +static void GlobalPointToWindowLocalPoint (Point *, WindowRef); +static pascal void NavOpenCartEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData); +static pascal void NavRecordMovieToEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData); +static pascal void NavPlayMovieFromEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData); +static pascal void NavQTMovieRecordToEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData); +static pascal void NavGenericOpenEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData); +static pascal void NavGenericSaveEventHandler (const NavEventCallbackMessage, NavCBRecPtr, NavCallBackUserData); +static pascal Boolean NavOpenCartFilter (AEDesc *, void *, NavCallBackUserData, NavFilterModes); +static pascal Boolean NavDefrostFromFilter (AEDesc *, void *, NavCallBackUserData, NavFilterModes); +static pascal Boolean NavPlayMovieFromFilter (AEDesc *, void *, NavCallBackUserData, NavFilterModes); +static pascal Boolean NavDefrostFromPreview (NavCBRecPtr, NavCallBackUserData); +static pascal Boolean NavPlayMovieFromPreview (NavCBRecPtr, NavCallBackUserData); + + +bool8 NavOpenROMImage (FSRef *ref) +{ + OSStatus err; + NavDialogCreationOptions dialogOptions; + NavEventUPP eventUPP; + NavObjectFilterUPP filterUPP; + NavState nav; + Rect rct; + HIViewID cid = { 'PANE', 1000 }; + + err = CreateNibReference(kMacS9XCFString, &(nav.customNib)); + if (err) + return (false); + + err = CreateWindowFromNib(nav.customNib, CFSTR("OpenROM"), &(nav.customWindow)); + if (err) + { + DisposeNibReference(nav.customNib); + return (false); + } + + nav.isSheet = false; + + GetWindowBounds(nav.customWindow, kWindowContentRgn, &rct); + nav.customWidth = rct.right - rct.left; + nav.customHeight = rct.bottom - rct.top; + + HIViewFindByID(HIViewGetRoot(nav.customWindow), cid, &(nav.customPane)); + + err = NavGetDefaultDialogCreationOptions(&dialogOptions); + dialogOptions.optionFlags &= ~kNavAllowPreviews & ~kNavAllowMultipleFiles & ~kNavAllowStationery; + dialogOptions.preferenceKey = 3; + dialogOptions.clientName = kMacS9XCFString; + dialogOptions.windowTitle = CFCopyLocalizedString(CFSTR("OpenROMMes"), "Open"); + dialogOptions.modality = kWindowModalityAppModal; + dialogOptions.parentWindow = NULL; + + eventUPP = NewNavEventUPP(NavOpenCartEventHandler); + filterUPP = NewNavObjectFilterUPP(NavOpenCartFilter); + + gSheetParent = NULL; + + err = NavCreateChooseFileDialog(&dialogOptions, NULL, eventUPP, NULL, filterUPP, &nav, &(nav.nref)); + if (err == noErr) + { + err = NavDialogRun(nav.nref); + if (err) + NavDialogDispose(nav.nref); + } + + DisposeNavObjectFilterUPP(filterUPP); + DisposeNavEventUPP(eventUPP); + + CFRelease(dialogOptions.windowTitle); + + CFRelease(nav.customWindow); + DisposeNibReference(nav.customNib); + + if (err) + return (false); + else + { + if (nav.reply) + { + *ref = nav.ref; + return (true); + } + else + return (false); + } +} + +static pascal void NavOpenCartEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD) +{ + static Boolean embedded = false; + + OSStatus err; + NavReplyRecord reply; + NavUserAction userAction; + NavState *nav; + HIViewRef ctl; + HIViewID cid; + HIViewPartCode part; + MenuRef menu; + AEDesc resultDesc; + Point pt; + SInt32 count; + + nav = (NavState *) callBackUD; + + switch (callBackSelector) + { + case kNavCBEvent: + switch (callBackParms->eventData.eventDataParms.event->what) + { + case mouseDown: + pt = callBackParms->eventData.eventDataParms.event->where; + GlobalPointToWindowLocalPoint(&pt, callBackParms->window); + + ctl = FindControlUnderMouse(pt, callBackParms->window, &part); + if (ctl) + { + GetControlID(ctl, &cid); + if (cid.signature == 'CCTL') + part = HandleControlClick(ctl, pt, callBackParms->eventData.eventDataParms.event->modifiers, (ControlActionUPP) -1L); + } + + break; + } + + break; + + case kNavCBStart: + nav->reply = false; + cid.signature = 'CCTL'; + err = NavCustomControl(callBackParms->context, kNavCtlAddControl, nav->customPane); + + cid.id = 101; + HIViewFindByID(nav->customPane, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + switch (romDetect) + { + case kAutoROMType: SetControl32BitValue(ctl, 1); break; + case kLoROMForce: SetControl32BitValue(ctl, 3); break; + case kHiROMForce: SetControl32BitValue(ctl, 4); break; + } + + cid.id = 102; + HIViewFindByID(nav->customPane, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + switch (interleaveDetect) + { + case kAutoInterleave: SetControl32BitValue(ctl, 1); break; + case kNoInterleaveForce: SetControl32BitValue(ctl, 3); break; + case kInterleaveForce: SetControl32BitValue(ctl, 4); break; + case kInterleave2Force: SetControl32BitValue(ctl, 5); break; + case kInterleaveGD24: SetControl32BitValue(ctl, 6); break; + } + + cid.id = 103; + HIViewFindByID(nav->customPane, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + switch (videoDetect) + { + case kAutoVideo: SetControl32BitValue(ctl, 1); break; + case kPALForce: SetControl32BitValue(ctl, 3); break; + case kNTSCForce: SetControl32BitValue(ctl, 4); break; + } + + cid.id = 104; + HIViewFindByID(nav->customPane, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + switch (headerDetect) + { + case kAutoHeader: SetControl32BitValue(ctl, 1); break; + case kNoHeaderForce: SetControl32BitValue(ctl, 3); break; + case kHeaderForce: SetControl32BitValue(ctl, 4); break; + } + + MoveControl(nav->customPane, ((callBackParms->customRect.right - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left, + ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top); + + embedded = true; + + break; + + case kNavCBAccept: + cid.signature = 'CCTL'; + + cid.id = 101; + HIViewFindByID(nav->customPane, cid, &ctl); + switch (GetControl32BitValue(ctl)) + { + case 1: romDetect = kAutoROMType; break; + case 3: romDetect = kLoROMForce; break; + case 4: romDetect = kHiROMForce; break; + } + + cid.id = 102; + HIViewFindByID(nav->customPane, cid, &ctl); + switch (GetControl32BitValue(ctl)) + { + case 1: interleaveDetect = kAutoInterleave; break; + case 3: interleaveDetect = kNoInterleaveForce; break; + case 4: interleaveDetect = kInterleaveForce; break; + case 5: interleaveDetect = kInterleave2Force; break; + case 6: interleaveDetect = kInterleaveGD24; break; + } + + cid.id = 103; + HIViewFindByID(nav->customPane, cid, &ctl); + switch (GetControl32BitValue(ctl)) + { + case 1: videoDetect = kAutoVideo; break; + case 3: videoDetect = kPALForce; break; + case 4: videoDetect = kNTSCForce; break; + } + + cid.id = 104; + HIViewFindByID(nav->customPane, cid, &ctl); + switch (GetControl32BitValue(ctl)) + { + case 1: headerDetect = kAutoHeader; break; + case 3: headerDetect = kNoHeaderForce; break; + case 4: headerDetect = kHeaderForce; break; + } + + break; + + case kNavCBCustomize: + if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0)) // First call + { + embedded = false; + + callBackParms->customRect.right = callBackParms->customRect.left + nav->customWidth; + callBackParms->customRect.bottom = callBackParms->customRect.top + nav->customHeight; + } + + break; + + case kNavCBAdjustRect: + if (embedded) + MoveControl(nav->customPane, ((callBackParms->customRect.right - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left, + ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top); + + break; + + case kNavCBUserAction: + userAction = NavDialogGetUserAction(callBackParms->context); + switch (userAction) + { + case kNavUserActionChoose: + err = NavDialogGetReply(callBackParms->context, &reply); + if (err == noErr) + { + err = AECountItems(&(reply.selection), &count); + if ((err == noErr) && (count == 1)) + { + err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc); + if (err == noErr) + { + err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef)); + if (err == noErr) + nav->reply = true; + + err = AEDisposeDesc(&resultDesc); + } + } + + err = NavDisposeReply(&reply); + } + + break; + } + + break; + + case kNavCBTerminate: + NavDialogDispose(nav->nref); + + if (nav->isSheet) + { + EventRef event; + HICommand cmd; + + cmd.commandID = 'NvDn'; + cmd.attributes = kEventAttributeUserEvent; + cmd.menu.menuRef = NULL; + cmd.menu.menuItemIndex = 0; + + err = CreateEvent(kCFAllocatorDefault, kEventClassCommand, kEventCommandProcess, GetCurrentEventTime(), kEventAttributeUserEvent, &event); + if (err == noErr) + { + err = SetEventParameter(event, kEventParamDirectObject, typeHICommand, sizeof(HICommand), &cmd); + if (err == noErr) + err = SendEventToWindow(event, gSheetParent); + + ReleaseEvent(event); + } + } + + break; + } +} + +static pascal Boolean NavOpenCartFilter (AEDesc *theItem, void *ninfo, NavCallBackUserData callbackUD, NavFilterModes filterMode) +{ + OSStatus err; + AEDesc resultDesc; + Boolean result = true; + + err = AECoerceDesc(theItem, typeFSRef, &resultDesc); + if (err == noErr) + { + FSRef ref; + + err = AEGetDescData(&resultDesc, &ref, sizeof(FSRef)); + if (err == noErr) + { + FSCatalogInfo catinfo; + HFSUniStr255 unistr; + + err = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags, &catinfo, &unistr, NULL, NULL); + if ((err == noErr) && !(catinfo.nodeFlags & kFSNodeIsDirectoryMask) && (unistr.length > 4)) + { + UInt16 i = unistr.length; + + if ((unistr.unicode[i - 4] == '.') && + (((unistr.unicode[i - 3] == 's') && (unistr.unicode[i - 2] == 'r') && (unistr.unicode[i - 1] == 'm')) || + ((unistr.unicode[i - 3] == 'f') && (unistr.unicode[i - 2] == 'r') && (unistr.unicode[i - 1] == 'z')) || + ((unistr.unicode[i - 3] == 's') && (unistr.unicode[i - 2] == 'm') && (unistr.unicode[i - 1] == 'v')) || + ((unistr.unicode[i - 3] == 'm') && (unistr.unicode[i - 2] == 'o') && (unistr.unicode[i - 1] == 'v')) || + ((unistr.unicode[i - 3] == 's') && (unistr.unicode[i - 2] == 'p') && (unistr.unicode[i - 1] == 'c')) || + ((unistr.unicode[i - 3] == 'r') && (unistr.unicode[i - 2] == 't') && (unistr.unicode[i - 1] == 'c')) || + ((unistr.unicode[i - 3] == 'd') && (unistr.unicode[i - 2] == 'a') && (unistr.unicode[i - 1] == 't')) || + ((unistr.unicode[i - 3] == 'o') && (unistr.unicode[i - 2] == 'u') && (unistr.unicode[i - 1] == 't')) || + ((unistr.unicode[i - 3] == 'c') && (unistr.unicode[i - 2] == 'h') && (unistr.unicode[i - 1] == 't')) || + ((unistr.unicode[i - 3] == 'i') && (unistr.unicode[i - 2] == 'p') && (unistr.unicode[i - 1] == 's')) || + ((unistr.unicode[i - 3] == 'p') && (unistr.unicode[i - 2] == 'n') && (unistr.unicode[i - 1] == 'g')))) + result = false; + } + } + + AEDisposeDesc(&resultDesc); + } + + return (result); +} + +bool8 NavFreezeTo (char *path) +{ + OSStatus err; + NavDialogCreationOptions dialogOptions; + NavEventUPP eventUPP; + NavState nav; + CFStringRef numRef, romRef, baseRef; + CFMutableStringRef mesRef, saveRef; + SInt32 replaceAt; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + romRef = CFStringCreateWithCString(kCFAllocatorDefault, fname, MAC_PATH_ENCODING); + numRef = CFCopyLocalizedString(CFSTR("FreezeToPos"), "1"); + baseRef = CFCopyLocalizedString(CFSTR("FreezeToMes"), "Freeze"); + mesRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef); + saveRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, romRef); + replaceAt = CFStringGetIntValue(numRef); + CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef); + CFStringAppendCString(saveRef, ".frz", CFStringGetSystemEncoding()); + + err = NavGetDefaultDialogCreationOptions(&dialogOptions); + dialogOptions.preferenceKey = 4; + dialogOptions.clientName = kMacS9XCFString; + dialogOptions.windowTitle = mesRef; + dialogOptions.saveFileName = saveRef; + dialogOptions.modality = kWindowModalityAppModal; + dialogOptions.parentWindow = NULL; + + eventUPP = NewNavEventUPP(NavGenericSaveEventHandler); + + err = NavCreatePutFileDialog(&dialogOptions, 'SAVE', '~9X~', eventUPP, &nav, &(nav.nref)); + if (err == noErr) + { + err = NavDialogRun(nav.nref); + if (err) + NavDialogDispose(nav.nref); + } + + DisposeNavEventUPP(eventUPP); + + CFRelease(saveRef); + CFRelease(mesRef); + CFRelease(baseRef); + CFRelease(numRef); + CFRelease(romRef); + + if (err) + return (false); + else + { + if (nav.reply) + { + char s[PATH_MAX + 1]; + + err = FSRefMakePath(&(nav.ref), (unsigned char *) s, PATH_MAX); + snprintf(path, PATH_MAX + 1, "%s%s%s", s, MAC_PATH_SEPARATOR, nav.name); + + return (true); + } + else + return (false); + } +} + +static pascal void NavGenericSaveEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD) +{ + OSStatus err; + NavReplyRecord reply; + NavUserAction userAction; + NavState *nav; + AEDesc resultDesc; + + nav = (NavState *) callBackUD; + + switch (callBackSelector) + { + case kNavCBEvent: + break; + + case kNavCBStart: + nav->reply = false; + break; + + case kNavCBUserAction: + userAction = NavDialogGetUserAction(callBackParms->context); + switch (userAction) + { + case kNavUserActionSaveAs: + err = NavDialogGetReply(callBackParms->context, &reply); + if (err == noErr) + { + err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc); + if (err == noErr) + { + err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef)); + if (err == noErr) + { + Boolean r; + + r = CFStringGetCString(reply.saveFileName, nav->name, PATH_MAX, MAC_PATH_ENCODING); + if (r) + nav->reply = true; + } + + err = AEDisposeDesc(&resultDesc); + } + + err = NavDisposeReply(&reply); + } + + break; + } + + break; + + case kNavCBTerminate: + NavDialogDispose(nav->nref); + break; + } +} + +bool8 NavDefrostFrom (char *path) +{ + OSStatus err; + NavDialogCreationOptions dialogOptions; + NavEventUPP eventUPP; + NavObjectFilterUPP filterUPP; + NavPreviewUPP previewUPP; + NavState nav; + CFStringRef numRef, romRef, baseRef; + CFMutableStringRef mesRef; + SInt32 replaceAt; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + romRef = CFStringCreateWithCString(kCFAllocatorDefault, fname, MAC_PATH_ENCODING); + numRef = CFCopyLocalizedString(CFSTR("DefrostFromPos"), "1"); + baseRef = CFCopyLocalizedString(CFSTR("DefrostFromMes"), "Defrost"); + mesRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef); + replaceAt = CFStringGetIntValue(numRef); + CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef); + + err = NavGetDefaultDialogCreationOptions(&dialogOptions); + dialogOptions.optionFlags &= ~kNavAllowMultipleFiles & ~kNavAllowStationery; + dialogOptions.preferenceKey = 5; + dialogOptions.clientName = kMacS9XCFString; + dialogOptions.windowTitle = mesRef; + dialogOptions.modality = kWindowModalityAppModal; + dialogOptions.parentWindow = NULL; + + eventUPP = NewNavEventUPP(NavGenericOpenEventHandler); + filterUPP = NewNavObjectFilterUPP(NavDefrostFromFilter); + previewUPP = NewNavPreviewUPP(NavDefrostFromPreview); + + err = NavCreateChooseFileDialog(&dialogOptions, NULL, eventUPP, previewUPP, filterUPP, &nav, &(nav.nref)); + if (err == noErr) + { + err = NavDialogRun(nav.nref); + if (err) + NavDialogDispose(nav.nref); + } + + DisposeNavPreviewUPP(previewUPP); + DisposeNavObjectFilterUPP(filterUPP); + DisposeNavEventUPP(eventUPP); + + CFRelease(mesRef); + CFRelease(baseRef); + CFRelease(numRef); + CFRelease(romRef); + + if (err) + return (false); + else + { + if (nav.reply) + { + err = FSRefMakePath(&(nav.ref), (unsigned char *) path, PATH_MAX); + return (true); + } + else + return (false); + } +} + +static pascal void NavGenericOpenEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD) +{ + OSStatus err; + NavReplyRecord reply; + NavUserAction userAction; + NavState *nav; + AEDesc resultDesc; + SInt32 count; + + nav = (NavState *) callBackUD; + + switch (callBackSelector) + { + case kNavCBEvent: + break; + + case kNavCBStart: + nav->reply = false; + break; + + case kNavCBUserAction: + userAction = NavDialogGetUserAction(callBackParms->context); + switch (userAction) + { + case kNavUserActionChoose: + err = NavDialogGetReply(callBackParms->context, &reply); + if (err == noErr) + { + err = AECountItems(&(reply.selection), &count); + if ((err == noErr) && (count == 1)) + { + err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc); + if (err == noErr) + { + err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef)); + if (err == noErr) + nav->reply = true; + + err = AEDisposeDesc(&resultDesc); + } + } + + err = NavDisposeReply(&reply); + } + + break; + } + + break; + + case kNavCBTerminate: + NavDialogDispose(nav->nref); + break; + } +} + +static pascal Boolean NavDefrostFromFilter (AEDesc *theItem, void *ninfo, NavCallBackUserData callbackUD, NavFilterModes filterMode) +{ + OSStatus err; + AEDesc resultDesc; + Boolean result = true; + + err = AECoerceDesc(theItem, typeFSRef, &resultDesc); + if (err == noErr) + { + FSRef ref; + + err = AEGetDescData(&resultDesc, &ref, sizeof(FSRef)); + if (err == noErr) + { + FSCatalogInfo catinfo; + HFSUniStr255 unistr; + + err = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &catinfo, &unistr, NULL, NULL); + if ((err == noErr) && !(catinfo.nodeFlags & kFSNodeIsDirectoryMask)) + { + if (((FileInfo *) &catinfo.finderInfo)->fileType != 'SAVE') + { + UInt16 i = unistr.length; + + if (i < 4) + result = false; + else + if ((unistr.unicode[i - 4] == '.') && (unistr.unicode[i - 3] == 'f') && (unistr.unicode[i - 2] == 'r')) + result = true; + else + result = false; + } + } + } + + AEDisposeDesc(&resultDesc); + } + + return (result); +} + +static pascal Boolean NavDefrostFromPreview (NavCBRecPtr callBackParms, NavCallBackUserData callBackUD) +{ +#ifndef MAC_TIGER_PANTHER_SUPPORT + return (true); +#else + OSStatus err; + Boolean previewShowing, result = false; + + err = NavCustomControl(callBackParms->context, kNavCtlIsPreviewShowing, &previewShowing); + if ((err == noErr) && previewShowing) + { + AEDesc resultDesc; + + err = AECoerceDesc((AEDesc *) callBackParms->eventData.eventDataParms.param, typeFSRef, &resultDesc); + if (err == noErr) + { + FSRef ref; + + err = AEGetDescData(&resultDesc, &ref, sizeof(FSRef)); + if (err == noErr) + { + FSCatalogInfo catinfo; + + err = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags | kFSCatInfoContentMod, &catinfo, NULL, NULL, NULL); + if ((err == noErr) && !(catinfo.nodeFlags & kFSNodeIsDirectoryMask)) + { + CFMutableStringRef sref; + + sref = CFStringCreateMutable(kCFAllocatorDefault, 0); + if (sref) + { + CFAbsoluteTime at; + CFDateFormatterRef format; + CFLocaleRef locale; + CFStringRef datstr; + + err = UCConvertUTCDateTimeToCFAbsoluteTime(&(catinfo.contentModDate), &at); + locale = CFLocaleCopyCurrent(); + format = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle); + datstr = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, format, at); + CFStringAppend(sref, datstr); + CFRelease(datstr); + CFRelease(format); + CFRelease(locale); + + CGContextRef ctx; + CGRect bounds; + CGrafPtr port; + Rect rct; + int rightedge; + + port = GetWindowPort(callBackParms->window); + GetWindowBounds(callBackParms->window, kWindowContentRgn, &rct); + + err = QDBeginCGContext(port, &ctx); + + rightedge = (callBackParms->previewRect.right < (rct.right - rct.left - 11)) ? callBackParms->previewRect.right : (rct.right - rct.left - 11); + + bounds.origin.x = (float) callBackParms->previewRect.left; + bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.bottom); + bounds.size.width = (float) (rightedge - callBackParms->previewRect.left); + bounds.size.height = (float) (callBackParms->previewRect.bottom - callBackParms->previewRect.top); + + CGContextClipToRect(ctx, bounds); + + CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f); + CGContextFillRect(ctx, bounds); + CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); + + bounds.origin.x = (float) (callBackParms->previewRect.left + ((callBackParms->previewRect.right - callBackParms->previewRect.left - 128) >> 1)); + bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.top - 120 - 25); + bounds.size.width = 128.0f; + bounds.size.height = 120.0f; + + DrawThumbnailResource(&ref, ctx, bounds); + + HIThemeTextInfo textinfo; + + textinfo.version = 0; + textinfo.state = kThemeStateActive; + textinfo.fontID = kThemeSmallSystemFont; + textinfo.verticalFlushness = kHIThemeTextVerticalFlushTop; + textinfo.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; + textinfo.options = 0; + textinfo.truncationPosition = kHIThemeTextTruncationMiddle; + textinfo.truncationMaxLines = 0; + textinfo.truncationHappened = false; + + bounds.origin.x = (float) (callBackParms->previewRect.left + 10); + bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.top - 153 - 20); + bounds.size.width = (float) (callBackParms->previewRect.right - callBackParms->previewRect.left - 20); + bounds.size.height = 20.0f; + + err = HIThemeDrawTextBox(sref, &bounds, &textinfo, ctx, kHIThemeOrientationInverted); + + CGContextSynchronize(ctx); + + err = QDEndCGContext(port, &ctx); + + CFRelease(sref); + + result = true; + } + } + } + + AEDisposeDesc(&resultDesc); + } + } + + return (result); +#endif +} + +bool8 NavBeginOpenROMImageSheet (WindowRef parent, CFStringRef mes) +{ + OSStatus err; + NavDialogCreationOptions dialogOptions; + Rect rct; + HIViewID cid = { 'PANE', 1000 }; + + err = CreateNibReference(kMacS9XCFString, &(gSheetNav.customNib)); + if (err) + return (false); + + err = CreateWindowFromNib(gSheetNav.customNib, CFSTR("OpenROM"), &(gSheetNav.customWindow)); + if (err) + { + DisposeNibReference(gSheetNav.customNib); + return (false); + } + + gSheetNav.isSheet = true; + + GetWindowBounds(gSheetNav.customWindow, kWindowContentRgn, &rct); + gSheetNav.customWidth = rct.right - rct.left; + gSheetNav.customHeight = rct.bottom - rct.top; + + HIViewFindByID(HIViewGetRoot(gSheetNav.customWindow), cid, &(gSheetNav.customPane)); + + err = NavGetDefaultDialogCreationOptions(&dialogOptions); + dialogOptions.optionFlags &= ~kNavAllowPreviews & ~kNavAllowMultipleFiles & ~kNavAllowStationery; + dialogOptions.preferenceKey = 3; + dialogOptions.clientName = kMacS9XCFString; + dialogOptions.windowTitle = CFCopyLocalizedString(CFSTR("OpenROMMes"), "Open"); + dialogOptions.parentWindow = parent; + dialogOptions.modality = kWindowModalityWindowModal; + dialogOptions.message = mes; + + gSheetEventUPP = NewNavEventUPP(NavOpenCartEventHandler); + gSheetFilterUPP = NewNavObjectFilterUPP(NavOpenCartFilter); + + gSheetParent = parent; + + err = NavCreateChooseFileDialog(&dialogOptions, NULL, gSheetEventUPP, NULL, gSheetFilterUPP, &gSheetNav, &(gSheetNav.nref)); + if (err == noErr) + { + err = NavDialogRun(gSheetNav.nref); + if (err) + { + NavDialogDispose(gSheetNav.nref); + DisposeNavObjectFilterUPP(gSheetFilterUPP); + DisposeNavEventUPP(gSheetEventUPP); + CFRelease(gSheetNav.customWindow); + DisposeNibReference(gSheetNav.customNib); + CFRelease(dialogOptions.windowTitle); + return (false); + } + } + else + { + DisposeNavObjectFilterUPP(gSheetFilterUPP); + DisposeNavEventUPP(gSheetEventUPP); + CFRelease(gSheetNav.customWindow); + DisposeNibReference(gSheetNav.customNib); + CFRelease(dialogOptions.windowTitle); + return (false); + } + + CFRelease(dialogOptions.windowTitle); + return (true); +} + +bool8 NavEndOpenROMImageSheet (FSRef *ref) +{ + DisposeNavObjectFilterUPP(gSheetFilterUPP); + DisposeNavEventUPP(gSheetEventUPP); + + CFRelease(gSheetNav.customWindow); + DisposeNibReference(gSheetNav.customNib); + + if (gSheetNav.reply) + { + *ref = gSheetNav.ref; + return (true); + } + else + return (false); +} + +bool8 NavRecordMovieTo (char *path) +{ + OSStatus err; + NavDialogCreationOptions dialogOptions; + NavEventUPP eventUPP; + NavState nav; + CFStringRef numRef, romRef, baseRef; + CFMutableStringRef mesRef, saveRef; + Rect rct; + SInt32 replaceAt; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + HIViewID cid = { 'PANE', 1000 }; + + err = CreateNibReference(kMacS9XCFString, &(nav.customNib)); + if (err) + return (false); + + err = CreateWindowFromNib(nav.customNib, CFSTR("RecordSMV"), &(nav.customWindow)); + if (err) + { + DisposeNibReference(nav.customNib); + return (false); + } + + nav.isSheet = false; + + GetWindowBounds(nav.customWindow, kWindowContentRgn, &rct); + nav.customWidth = rct.right - rct.left; + nav.customHeight = rct.bottom - rct.top; + + HIViewFindByID(HIViewGetRoot(nav.customWindow), cid, &(nav.customPane)); + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + romRef = CFStringCreateWithCString(kCFAllocatorDefault, fname, MAC_PATH_ENCODING); + numRef = CFCopyLocalizedString(CFSTR("RecordToPos"), "1"); + baseRef = CFCopyLocalizedString(CFSTR("RecordToMes"), "Record"); + mesRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef); + saveRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, romRef); + replaceAt = CFStringGetIntValue(numRef); + CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef); + CFStringAppendCString(saveRef, ".smv", CFStringGetSystemEncoding()); + + nav.customSRef = romRef; + + err = NavGetDefaultDialogCreationOptions(&dialogOptions); + dialogOptions.preferenceKey = 6; + dialogOptions.clientName = kMacS9XCFString; + dialogOptions.windowTitle = mesRef; + dialogOptions.saveFileName = saveRef; + dialogOptions.modality = kWindowModalityAppModal; + dialogOptions.parentWindow = NULL; + + eventUPP = NewNavEventUPP(NavRecordMovieToEventHandler); + + gSheetParent = NULL; + + err = NavCreatePutFileDialog(&dialogOptions, 'SMOV', '~9X~', eventUPP, &nav, &(nav.nref)); + if (err == noErr) + { + err = NavDialogRun(nav.nref); + if (err) + NavDialogDispose(nav.nref); + } + + DisposeNavEventUPP(eventUPP); + + CFRelease(saveRef); + CFRelease(mesRef); + CFRelease(baseRef); + CFRelease(numRef); + CFRelease(romRef); + + CFRelease(nav.customWindow); + DisposeNibReference(nav.customNib); + + if (err) + return (false); + else + { + if (nav.reply) + { + char s[PATH_MAX + 1]; + + err = FSRefMakePath(&(nav.ref), (unsigned char *) s, PATH_MAX); + snprintf(path, PATH_MAX + 1, "%s%s%s", s, MAC_PATH_SEPARATOR, nav.name); + + return (true); + } + else + return (false); + } +} + +static pascal void NavRecordMovieToEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD) +{ + static Boolean embedded = false; + + OSStatus err; + NavReplyRecord reply; + NavUserAction userAction; + NavState *nav; + HIViewRef ctl; + HIViewID cid; + HIViewPartCode part; + CFStringRef sref; + CFIndex cflen; + AEDesc resultDesc; + Point pt; + UniChar unistr[MOVIE_MAX_METADATA]; + + nav = (NavState *) callBackUD; + + switch (callBackSelector) + { + case kNavCBEvent: + switch (callBackParms->eventData.eventDataParms.event->what) + { + case mouseDown: + pt = callBackParms->eventData.eventDataParms.event->where; + GlobalPointToWindowLocalPoint(&pt, callBackParms->window); + + ctl = FindControlUnderMouse(pt, callBackParms->window, &part); + if (ctl) + { + GetControlID(ctl, &cid); + if (cid.signature == 'RCTL') + { + if (cid.id == 107) + { + HIViewRef tmp; + + err = GetKeyboardFocus(callBackParms->window, &tmp); + if ((err == noErr) && (tmp != ctl)) + err = SetKeyboardFocus(callBackParms->window, ctl, kControlFocusNextPart); + } + + part = HandleControlClick(ctl, pt, callBackParms->eventData.eventDataParms.event->modifiers, (ControlActionUPP) -1L); + } + } + + break; + } + + break; + + case kNavCBStart: + nav->reply = false; + cid.signature = 'RCTL'; + err = NavCustomControl(callBackParms->context, kNavCtlAddControl, nav->customPane); + + for (cid.id = 101; cid.id <= 106; cid.id++) + { + HIViewFindByID(nav->customPane, cid, &ctl); + SetControl32BitValue(ctl, (macRecordFlag & (1 << (cid.id - 101))) ? true : false); + } + + cid.id = 107; + HIViewFindByID(nav->customPane, cid, &ctl); + if (nav->customSRef) + SetEditTextCFString(ctl, nav->customSRef, false); + + MoveControl(nav->customPane, ((callBackParms->customRect.right - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left, + ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top); + + embedded = true; + + break; + + case kNavCBAccept: + macRecordFlag = 0; + cid.signature = 'RCTL'; + + for (cid.id = 101; cid.id <= 106; cid.id++) + { + HIViewFindByID(nav->customPane, cid, &ctl); + if (GetControl32BitValue(ctl)) + macRecordFlag |= (1 << (cid.id - 101)); + } + + cid.id = 107; + HIViewFindByID(nav->customPane, cid, &ctl); + CopyEditTextCFString(ctl, &sref); + if (sref) + { + cflen = CFStringGetLength(sref); + if (cflen > MOVIE_MAX_METADATA - 1) + cflen = MOVIE_MAX_METADATA - 1; + + CFStringGetCharacters(sref, CFRangeMake(0, cflen), unistr); + + for (int i = 0; i < cflen; i++) + macRecordWChar[i] = (wchar_t) unistr[i]; + macRecordWChar[cflen] = 0; + + CFRelease(sref); + } + else + macRecordWChar[0] = 0; + + break; + + case kNavCBCustomize: + if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0)) // First call + { + embedded = false; + + callBackParms->customRect.right = callBackParms->customRect.left + nav->customWidth; + callBackParms->customRect.bottom = callBackParms->customRect.top + nav->customHeight; + } + + break; + + case kNavCBAdjustRect: + if (embedded) + MoveControl(nav->customPane, ((callBackParms->customRect.right - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left, + ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top); + + break; + + case kNavCBUserAction: + userAction = NavDialogGetUserAction(callBackParms->context); + switch (userAction) + { + case kNavUserActionSaveAs: + err = NavDialogGetReply(callBackParms->context, &reply); + if (err == noErr) + { + err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc); + if (err == noErr) + { + err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef)); + if (err == noErr) + { + Boolean r; + + r = CFStringGetCString(reply.saveFileName, nav->name, PATH_MAX, MAC_PATH_ENCODING); + if (r) + nav->reply = true; + } + + err = AEDisposeDesc(&resultDesc); + } + + err = NavDisposeReply(&reply); + } + + break; + } + + break; + + case kNavCBTerminate: + NavDialogDispose(nav->nref); + break; + } +} + +bool8 NavPlayMovieFrom (char *path) +{ + OSStatus err; + NavDialogCreationOptions dialogOptions; + NavEventUPP eventUPP; + NavObjectFilterUPP filterUPP; + NavPreviewUPP previewUPP; + NavState nav; + CFStringRef numRef, romRef, baseRef; + CFMutableStringRef mesRef; + Rect rct; + SInt32 replaceAt; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + HIViewID cid = { 'PANE', 1000 }; + + err = CreateNibReference(kMacS9XCFString, &(nav.customNib)); + if (err) + return (false); + + err = CreateWindowFromNib(nav.customNib, CFSTR("PlaySMV"), &(nav.customWindow)); + if (err) + { + DisposeNibReference(nav.customNib); + return (false); + } + + nav.isSheet = false; + + GetWindowBounds(nav.customWindow, kWindowContentRgn, &rct); + nav.customWidth = rct.right - rct.left; + nav.customHeight = rct.bottom - rct.top; + + HIViewFindByID(HIViewGetRoot(nav.customWindow), cid, &(nav.customPane)); + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + romRef = CFStringCreateWithCString(kCFAllocatorDefault, fname, MAC_PATH_ENCODING); + numRef = CFCopyLocalizedString(CFSTR("PlayFromPos"), "1"); + baseRef = CFCopyLocalizedString(CFSTR("PlayFromMes"), "Play"); + mesRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef); + replaceAt = CFStringGetIntValue(numRef); + CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef); + + err = NavGetDefaultDialogCreationOptions(&dialogOptions); + dialogOptions.optionFlags &= ~kNavAllowMultipleFiles & ~kNavAllowStationery; + dialogOptions.preferenceKey = 6; + dialogOptions.clientName = kMacS9XCFString; + dialogOptions.windowTitle = mesRef; + dialogOptions.modality = kWindowModalityAppModal; + dialogOptions.parentWindow = NULL; + + eventUPP = NewNavEventUPP(NavPlayMovieFromEventHandler); + filterUPP = NewNavObjectFilterUPP(NavPlayMovieFromFilter); + previewUPP = NewNavPreviewUPP(NavPlayMovieFromPreview); + + gSheetParent = NULL; + + err = NavCreateChooseFileDialog(&dialogOptions, NULL, eventUPP, previewUPP, filterUPP, &nav, &(nav.nref)); + if (err == noErr) + { + err = NavDialogRun(nav.nref); + if (err) + NavDialogDispose(nav.nref); + } + + DisposeNavPreviewUPP(previewUPP); + DisposeNavObjectFilterUPP(filterUPP); + DisposeNavEventUPP(eventUPP); + + CFRelease(mesRef); + CFRelease(baseRef); + CFRelease(numRef); + CFRelease(romRef); + + CFRelease(nav.customWindow); + DisposeNibReference(nav.customNib); + + if (err) + return (false); + else + { + if (nav.reply) + { + err = FSRefMakePath(&(nav.ref), (unsigned char *) path, PATH_MAX); + return (true); + } + else + return (false); + } +} + +static pascal void NavPlayMovieFromEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD) +{ + static Boolean embedded = false; + + OSStatus err; + NavReplyRecord reply; + NavUserAction userAction; + NavState *nav; + HIViewRef ctl; + HIViewID cid; + HIViewPartCode part; + AEDesc resultDesc; + Point pt; + SInt32 count; + + nav = (NavState *) callBackUD; + + switch (callBackSelector) + { + case kNavCBEvent: + switch (callBackParms->eventData.eventDataParms.event->what) + { + case mouseDown: + pt = callBackParms->eventData.eventDataParms.event->where; + GlobalPointToWindowLocalPoint(&pt, callBackParms->window); + + ctl = FindControlUnderMouse(pt, callBackParms->window, &part); + if (ctl) + { + GetControlID(ctl, &cid); + if (cid.signature == 'PCTL') + part = HandleControlClick(ctl, pt, callBackParms->eventData.eventDataParms.event->modifiers, (ControlActionUPP) -1L); + } + + break; + } + + break; + + case kNavCBStart: + nav->reply = false; + cid.signature = 'PCTL'; + err = NavCustomControl(callBackParms->context, kNavCtlAddControl, nav->customPane); + + for (cid.id = 101; cid.id <= 102; cid.id++) + { + HIViewFindByID(nav->customPane, cid, &ctl); + SetControl32BitValue(ctl, (macPlayFlag & (1 << (cid.id - 101))) ? true : false); + } + + MoveControl(nav->customPane, ((callBackParms->customRect.right - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left, + ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top); + + embedded = true; + + break; + + case kNavCBAccept: + macPlayFlag = 0; + cid.signature = 'PCTL'; + + for (cid.id = 101; cid.id <= 102; cid.id++) + { + HIViewFindByID(nav->customPane, cid, &ctl); + if (GetControl32BitValue(ctl)) + macPlayFlag |= (1 << (cid.id - 101)); + } + + break; + + case kNavCBCustomize: + if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0)) // First call + { + embedded = false; + + callBackParms->customRect.right = callBackParms->customRect.left + nav->customWidth; + callBackParms->customRect.bottom = callBackParms->customRect.top + nav->customHeight; + } + + break; + + case kNavCBAdjustRect: + if (embedded) + MoveControl(nav->customPane, ((callBackParms->customRect.right - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left, + ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top); + + break; + + case kNavCBUserAction: + userAction = NavDialogGetUserAction(callBackParms->context); + switch (userAction) + { + case kNavUserActionChoose: + err = NavDialogGetReply(callBackParms->context, &reply); + if (err == noErr) + { + err = AECountItems(&(reply.selection), &count); + if ((err == noErr) && (count == 1)) + { + err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc); + if (err == noErr) + { + err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef)); + if (err == noErr) + nav->reply = true; + + err = AEDisposeDesc(&resultDesc); + } + } + + err = NavDisposeReply(&reply); + } + + break; + } + + break; + + case kNavCBTerminate: + NavDialogDispose(nav->nref); + break; + } +} + +static pascal Boolean NavPlayMovieFromFilter (AEDesc *theItem, void *ninfo, NavCallBackUserData callbackUD, NavFilterModes filterMode) +{ + OSStatus err; + AEDesc resultDesc; + Boolean result = true; + + err = AECoerceDesc(theItem, typeFSRef, &resultDesc); + if (err == noErr) + { + FSRef ref; + + err = AEGetDescData(&resultDesc, &ref, sizeof(FSRef)); + if (err == noErr) + { + FSCatalogInfo catinfo; + HFSUniStr255 unistr; + + err = FSGetCatalogInfo(&ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &catinfo, &unistr, NULL, NULL); + if ((err == noErr) && !(catinfo.nodeFlags & kFSNodeIsDirectoryMask)) + { + if (((FileInfo *) &catinfo.finderInfo)->fileType != 'SMOV') + { + UInt16 i = unistr.length; + + if (i < 4) + result = false; + else + if ((unistr.unicode[i - 4] == '.') && (unistr.unicode[i - 3] == 's') && (unistr.unicode[i - 2] == 'm') && (unistr.unicode[i - 1] == 'v')) + result = true; + else + result = false; + } + } + } + + AEDisposeDesc(&resultDesc); + } + + return (result); +} + +static pascal Boolean NavPlayMovieFromPreview (NavCBRecPtr callBackParms, NavCallBackUserData callBackUD) +{ +#ifndef MAC_TIGER_PANTHER_SUPPORT + return (true); +#else + OSStatus err; + Boolean previewShowing, result = false; + + err = NavCustomControl(callBackParms->context, kNavCtlIsPreviewShowing, &previewShowing); + if ((err == noErr) && previewShowing) + { + AEDesc resultDesc; + + err = AECoerceDesc((AEDesc *) callBackParms->eventData.eventDataParms.param, typeFSRef, &resultDesc); + if (err == noErr) + { + FSRef ref; + + err = AEGetDescData(&resultDesc, &ref, sizeof(FSRef)); + if (err == noErr) + { + char path[PATH_MAX + 1]; + + err = FSRefMakePath(&ref, (unsigned char *) path, PATH_MAX); + if (err == noErr) + { + MovieInfo movinfo; + int r; + + r = S9xMovieGetInfo(path, &movinfo); + if (r == SUCCESS) + { + UTCDateTime utctime; + CGContextRef ctx; + CGRect bounds; + CGrafPtr port; + Rect rct; + CFStringRef sref; + UInt64 t; + int rightedge, border, width, l, sec, min, hr, n; + char cstr[256], cbuf[512]; + UniChar unistr[MOVIE_MAX_METADATA]; + + sref = CFCopyLocalizedString(CFSTR("MoviePrevBorder"), "1"); + if (sref) + { + border = CFStringGetIntValue(sref); + CFRelease(sref); + } + else + border = 1; + + sref = CFCopyLocalizedString(CFSTR("MoviePrevWidth"), "1"); + if (sref) + { + width = CFStringGetIntValue(sref); + CFRelease(sref); + } + else + width = 1; + + // Date + + t = (UInt64) movinfo.TimeCreated + ((365 * 66 + 17) * 24 * 60 * 60); + utctime.highSeconds = (UInt16) (t >> 32); + utctime.lowSeconds = (UInt32) (t & 0xFFFFFFFF); + utctime.fraction = 0; + + CFAbsoluteTime at; + CFDateFormatterRef format; + CFLocaleRef locale; + CFStringRef datstr; + Boolean e; + + err = UCConvertUTCDateTimeToCFAbsoluteTime(&utctime, &at); + locale = CFLocaleCopyCurrent(); + format = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterShortStyle, kCFDateFormatterNoStyle); + datstr = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, format, at); + e = CFStringGetCString(datstr, cbuf, sizeof(cbuf), CFStringGetSystemEncoding()); + CFRelease(datstr); + CFRelease(format); + strcat(cbuf, "\n"); + format = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterNoStyle, kCFDateFormatterMediumStyle); + datstr = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, format, at); + e = CFStringGetCString(datstr, cstr, sizeof(cstr), CFStringGetSystemEncoding()); + CFRelease(datstr); + CFRelease(format); + strcat(cbuf, cstr); + strcat(cbuf, "\n"); + CFRelease(locale); + + // Length + + l = (movinfo.LengthFrames + 30) / ((movinfo.Opts & MOVIE_OPT_PAL) ? 50 : 60); + sec = l % 60; l /= 60; + min = l % 60; l /= 60; + hr = l % 60; + + sprintf(cstr, "%02d:%02d:%02d\n", hr, min, sec); + strcat(cbuf, cstr); + + // Frames + + sprintf(cstr, "%d\n", movinfo.LengthFrames); + strcat(cbuf, cstr); + + // + + port = GetWindowPort(callBackParms->window); + GetWindowBounds(callBackParms->window, kWindowContentRgn, &rct); + + err = QDBeginCGContext(port, &ctx); + + rightedge = (callBackParms->previewRect.right < (rct.right - rct.left - 11)) ? callBackParms->previewRect.right : (rct.right - rct.left - 11); + + bounds.origin.x = (float) callBackParms->previewRect.left; + bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.bottom); + bounds.size.width = (float) (rightedge - callBackParms->previewRect.left); + bounds.size.height = (float) (callBackParms->previewRect.bottom - callBackParms->previewRect.top); + + CGContextClipToRect(ctx, bounds); + + CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f); + CGContextFillRect(ctx, bounds); + CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); + + // Thumbnail + + bounds.origin.x = (float) (callBackParms->previewRect.left + ((callBackParms->previewRect.right - callBackParms->previewRect.left - 128) >> 1)); + bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.top - 120 - 25); + bounds.size.width = 128.0f; + bounds.size.height = 120.0f; + + DrawThumbnailResource(&ref, ctx, bounds); + + // Text + + HIThemeTextInfo textinfo; + + textinfo.version = 0; + textinfo.state = kThemeStateActive; + textinfo.fontID = kThemeSmallSystemFont; + textinfo.verticalFlushness = kHIThemeTextVerticalFlushTop; + textinfo.options = 0; + textinfo.truncationPosition = kHIThemeTextTruncationMiddle; + textinfo.truncationMaxLines = 0; + textinfo.truncationHappened = false; + + bounds.origin.x = (float) (((callBackParms->previewRect.right - callBackParms->previewRect.left - width) >> 1) + callBackParms->previewRect.left + border + 7); + bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.top - 153 - 60); + bounds.size.width = (float) callBackParms->previewRect.right - bounds.origin.x; + bounds.size.height = 60.0f; + + sref = CFStringCreateWithCString(kCFAllocatorDefault, cbuf, CFStringGetSystemEncoding()); + if (sref) + { + textinfo.horizontalFlushness = kHIThemeTextHorizontalFlushLeft; + err = HIThemeDrawTextBox(sref, &bounds, &textinfo, ctx, kHIThemeOrientationInverted); + CFRelease(sref); + } + + bounds.origin.x = (float) callBackParms->previewRect.left; + bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.top - 153 - 60); + bounds.size.width = (float) (((callBackParms->previewRect.right - callBackParms->previewRect.left - width) >> 1) + border); + bounds.size.height = 60.0f; + + sref = CFCopyLocalizedString(CFSTR("MoviePrevMes"), "MovieInfo"); + if (sref) + { + textinfo.horizontalFlushness = kHIThemeTextHorizontalFlushRight; + err = HIThemeDrawTextBox(sref, &bounds, &textinfo, ctx, kHIThemeOrientationInverted); + CFRelease(sref); + } + + bounds.origin.x = (float) (((callBackParms->previewRect.right - callBackParms->previewRect.left - 132) >> 1) + callBackParms->previewRect.left); + bounds.origin.y = (float) (rct.bottom - rct.top - callBackParms->previewRect.bottom + 10); + bounds.size.width = 132.0f; + bounds.size.height = (float) (callBackParms->previewRect.bottom - callBackParms->previewRect.top - 223 - 10); + + n = wcslen(movinfo.Metadata); + + for (int i = 0; i < n; i++) + unistr[i] = (UniChar) movinfo.Metadata[i]; + unistr[n] = 0; + + sref = CFStringCreateWithCharacters(kCFAllocatorDefault, unistr, n); + if (sref) + { + textinfo.horizontalFlushness = kHIThemeTextHorizontalFlushLeft; + err = HIThemeDrawTextBox(sref, &bounds, &textinfo, ctx, kHIThemeOrientationInverted); + CFRelease(sref); + } + + CGContextSynchronize(ctx); + + err = QDEndCGContext(port, &ctx); + + result = true; + } + } + } + + AEDisposeDesc(&resultDesc); + } + } + + return (result); +#endif +} + +bool8 NavQTMovieRecordTo (char *path) +{ + OSStatus err; + NavDialogCreationOptions dialogOptions; + NavEventUPP eventUPP; + NavState nav; + CFStringRef numRef, romRef, baseRef; + CFMutableStringRef mesRef, saveRef; + Rect rct; + SInt32 replaceAt; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + HIViewID cid = { 'PANE', 1000 }; + + err = CreateNibReference(kMacS9XCFString, &(nav.customNib)); + if (err) + return (false); + + err = CreateWindowFromNib(nav.customNib, CFSTR("QTMovie"), &(nav.customWindow)); + if (err) + { + DisposeNibReference(nav.customNib); + return (false); + } + + nav.isSheet = false; + + GetWindowBounds(nav.customWindow, kWindowContentRgn, &rct); + nav.customWidth = rct.right - rct.left; + nav.customHeight = rct.bottom - rct.top; + + HIViewFindByID(HIViewGetRoot(nav.customWindow), cid, &(nav.customPane)); + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + romRef = CFStringCreateWithCString(kCFAllocatorDefault, fname, MAC_PATH_ENCODING); + numRef = CFCopyLocalizedString(CFSTR("QTRecordPos"), "1"); + baseRef = CFCopyLocalizedString(CFSTR("QTRecordMes"), "QT"); + mesRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef); + saveRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, romRef); + replaceAt = CFStringGetIntValue(numRef); + CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef); + CFStringAppendCString(saveRef, ".mov", CFStringGetSystemEncoding()); + + nav.customSRef = romRef; + + err = NavGetDefaultDialogCreationOptions(&dialogOptions); + dialogOptions.preferenceKey = 7; + dialogOptions.clientName = kMacS9XCFString; + dialogOptions.windowTitle = mesRef; + dialogOptions.saveFileName = saveRef; + dialogOptions.modality = kWindowModalityAppModal; + dialogOptions.parentWindow = NULL; + + eventUPP = NewNavEventUPP(NavQTMovieRecordToEventHandler); + + gSheetParent = NULL; + + err = NavCreatePutFileDialog(&dialogOptions, 'MooV', 'TVOD', eventUPP, &nav, &(nav.nref)); + if (err == noErr) + { + err = NavDialogRun(nav.nref); + if (err) + NavDialogDispose(nav.nref); + } + + DisposeNavEventUPP(eventUPP); + + CFRelease(saveRef); + CFRelease(mesRef); + CFRelease(baseRef); + CFRelease(numRef); + CFRelease(romRef); + + CFRelease(nav.customWindow); + DisposeNibReference(nav.customNib); + + if (err) + return (false); + else + { + if (nav.reply) + { + char s[PATH_MAX + 1]; + + err = FSRefMakePath(&(nav.ref), (unsigned char *) s, PATH_MAX); + snprintf(path, PATH_MAX + 1, "%s%s%s", s, MAC_PATH_SEPARATOR, nav.name); + + return (true); + } + else + return (false); + } +} + +static pascal void NavQTMovieRecordToEventHandler (const NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD) +{ + static Boolean embedded = false; + + OSStatus err; + NavReplyRecord reply; + NavUserAction userAction; + NavState *nav; + HIViewRef ctl; + HIViewID cid; + HIViewPartCode part; + MenuRef menu; + AEDesc resultDesc; + Point pt; + + nav = (NavState *) callBackUD; + + switch (callBackSelector) + { + case kNavCBEvent: + switch (callBackParms->eventData.eventDataParms.event->what) + { + case mouseDown: + pt = callBackParms->eventData.eventDataParms.event->where; + GlobalPointToWindowLocalPoint(&pt, callBackParms->window); + + ctl = FindControlUnderMouse(pt, callBackParms->window, &part); + if (ctl) + { + GetControlID(ctl, &cid); + if (cid.signature == 'QCTL') + part = HandleControlClick(ctl, pt, callBackParms->eventData.eventDataParms.event->modifiers, (ControlActionUPP) -1L); + + if (cid.id == 103) + MacQTVideoConfig(NavDialogGetWindow(callBackParms->context)); + } + + break; + } + + break; + + case kNavCBStart: + nav->reply = false; + cid.signature = 'QCTL'; + err = NavCustomControl(callBackParms->context, kNavCtlAddControl, nav->customPane); + + for (cid.id = 101; cid.id <= 102; cid.id++) + { + HIViewFindByID(nav->customPane, cid, &ctl); + SetControl32BitValue(ctl, (macQTMovFlag & (1 << (cid.id - 101))) ? true : false); + } + + cid.id = 104; + HIViewFindByID(nav->customPane, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + SetControl32BitValue(ctl, ((macQTMovFlag & 0xFF00) >> 8) + 1); + + MoveControl(nav->customPane, ((callBackParms->customRect.right - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left, + ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top); + + embedded = true; + + break; + + case kNavCBAccept: + macQTMovFlag = 0; + cid.signature = 'QCTL'; + + for (cid.id = 101; cid.id <= 102; cid.id++) + { + HIViewFindByID(nav->customPane, cid, &ctl); + if (GetControl32BitValue(ctl)) + macQTMovFlag |= (1 << (cid.id - 101)); + } + + cid.id = 104; + HIViewFindByID(nav->customPane, cid, &ctl); + macQTMovFlag |= ((GetControl32BitValue(ctl) - 1) << 8); + + break; + + case kNavCBCustomize: + if ((callBackParms->customRect.right == 0) && (callBackParms->customRect.bottom == 0)) // First call + { + embedded = false; + + callBackParms->customRect.right = callBackParms->customRect.left + nav->customWidth; + callBackParms->customRect.bottom = callBackParms->customRect.top + nav->customHeight; + } + + break; + + case kNavCBAdjustRect: + if (embedded) + MoveControl(nav->customPane, ((callBackParms->customRect.right - callBackParms->customRect.left) - nav->customWidth ) / 2 + callBackParms->customRect.left, + ((callBackParms->customRect.bottom - callBackParms->customRect.top ) - nav->customHeight) / 2 + callBackParms->customRect.top); + + break; + + case kNavCBUserAction: + userAction = NavDialogGetUserAction(callBackParms->context); + switch (userAction) + { + case kNavUserActionSaveAs: + err = NavDialogGetReply(callBackParms->context, &reply); + if (err == noErr) + { + err = AEGetNthDesc(&(reply.selection), 1, typeFSRef, NULL, &resultDesc); + if (err == noErr) + { + err = AEGetDescData(&resultDesc, &(nav->ref), sizeof(FSRef)); + if (err == noErr) + { + Boolean r; + + r = CFStringGetCString(reply.saveFileName, nav->name, PATH_MAX, MAC_PATH_ENCODING); + if (r) + nav->reply = true; + } + + err = AEDisposeDesc(&resultDesc); + } + + err = NavDisposeReply(&reply); + } + + break; + } + + break; + + case kNavCBTerminate: + NavDialogDispose(nav->nref); + break; + } +} + +static void GlobalPointToWindowLocalPoint (Point *pt, WindowRef window) +{ + if (systemVersion >= 0x1040) + { + HIViewRef view; + HIPoint cpt = CGPointMake((float) pt->h, (float) pt->v); + + HIViewFindByID(HIViewGetRoot(window), kHIViewWindowContentID, &view); + HIPointConvert(&cpt, kHICoordSpace72DPIGlobal, NULL, kHICoordSpaceView, view); + pt->h = (short) cpt.x; + pt->v = (short) cpt.y; + } +#ifdef MAC_PANTHER_SUPPORT + else + QDGlobalToLocalPoint(GetWindowPort(window), pt); +#endif +} diff --git a/macosx/mac-cart.h b/macosx/mac-cart.h new file mode 100644 index 00000000..13cb30c9 --- /dev/null +++ b/macosx/mac-cart.h @@ -0,0 +1,203 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_cart_h_ +#define _mac_cart_h_ + +bool8 NavOpenROMImage (FSRef *); +bool8 NavBeginOpenROMImageSheet (WindowRef, CFStringRef); +bool8 NavEndOpenROMImageSheet (FSRef *); +bool8 NavFreezeTo (char *); +bool8 NavDefrostFrom (char *); +bool8 NavRecordMovieTo (char *); +bool8 NavPlayMovieFrom (char *); +bool8 NavQTMovieRecordTo (char *); + +#endif diff --git a/macosx/mac-cheat.cpp b/macosx/mac-cheat.cpp new file mode 100644 index 00000000..18b72610 --- /dev/null +++ b/macosx/mac-cheat.cpp @@ -0,0 +1,761 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "port.h" +#include "cheats.h" + +#define __STDC_FORMAT_MACROS +#include + +#include "mac-prefix.h" +#include "mac-dialog.h" +#include "mac-os.h" +#include "mac-stringtools.h" +#include "mac-cheat.h" + +#define kDataBrowser 'BRSR' +#define kCmCheckBox 'CHK_' +#define kCmAddress 'ADDR' +#define kCmValue 'VALU' +#define kCmDescription 'DESC' +#define kNewButton 'NEW_' +#define kDelButton 'DEL_' +#define kAllButton 'ALL_' + +extern SCheatData Cheat; + +typedef struct +{ + uint32 id; + uint32 address; + uint8 value; + bool8 valid; + bool8 enabled; + char description[22]; +} CheatItem; + +static WindowRef wRef; +static HIViewRef dbRef; +static CheatItem citem[MAX_CHEATS]; +static uint32 numofcheats; + +static void InitCheatItems (void); +static void ImportCheatItems (void); +static void DetachCheatItems (void); +static void AddCheatItem (void); +static void DeleteCheatItem (void); +static void EnableAllCheatItems (void); +static pascal void DBItemNotificationCallBack (HIViewRef, DataBrowserItemID, DataBrowserItemNotification); +static pascal Boolean DBCompareCallBack (HIViewRef, DataBrowserItemID, DataBrowserItemID, DataBrowserPropertyID); +static pascal OSStatus DBClientDataCallback (HIViewRef, DataBrowserItemID, DataBrowserPropertyID, DataBrowserItemDataRef, Boolean); +static pascal OSStatus CheatEventHandler (EventHandlerCallRef, EventRef, void *); + + +static void InitCheatItems (void) +{ + for (unsigned int i = 0; i < MAX_CHEATS; i++) + { + citem[i].id = i + 1; + citem[i].valid = false; + citem[i].enabled = false; + citem[i].address = 0; + citem[i].value = 0; + sprintf(citem[i].description, "Cheat %03" PRIu32, citem[i].id); + } +} + +static void ImportCheatItems (void) +{ + for (unsigned int i = 0; i < Cheat.num_cheats; i++) + { + citem[i].valid = true; + citem[i].enabled = Cheat.c[i].enabled; + citem[i].address = Cheat.c[i].address; + citem[i].value = Cheat.c[i].byte; + strcpy(citem[i].description, Cheat.c[i].name); + } +} + +static void DetachCheatItems (void) +{ + S9xDeleteCheats(); // Cheat.num_cheats = 0 + + for (unsigned int i = 0; i < MAX_CHEATS; i++) + { + if (citem[i].valid) + { + strcpy(Cheat.c[Cheat.num_cheats].name, citem[i].description); + S9xAddCheat(citem[i].enabled, false, citem[i].address, citem[i].value); // Cheat.num_cheats++ + } + } + + S9xApplyCheats(); +} + +void ConfigureCheat (void) +{ + if (!cartOpen) + return; + + OSStatus err; + IBNibRef nibRef; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + err = CreateWindowFromNib(nibRef, CFSTR("CheatEntry"), &wRef); + if (err == noErr) + { + DataBrowserCallbacks callbacks; + EventHandlerRef eref; + EventHandlerUPP eUPP; + EventTypeSpec events[] = { { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus }, + { kEventClassWindow, kEventWindowClose } }; + HIViewRef ctl, root; + HIViewID cid; + + root = HIViewGetRoot(wRef); + cid.id = 0; + cid.signature = kDataBrowser; + HIViewFindByID(root, cid, &dbRef); + + #ifdef MAC_PANTHER_SUPPORT + if (systemVersion < 0x1040) + { + HISize minSize; + Rect rct; + + GetWindowBounds(wRef, kWindowContentRgn, &rct); + minSize.width = (float) (rct.right - rct.left); + minSize.height = (float) (rct.bottom - rct.top ); + err = SetWindowResizeLimits(wRef, &minSize, NULL); + } + #endif + + callbacks.version = kDataBrowserLatestCallbacks; + err = InitDataBrowserCallbacks(&callbacks); + callbacks.u.v1.itemDataCallback = NewDataBrowserItemDataUPP(DBClientDataCallback); + callbacks.u.v1.itemCompareCallback = NewDataBrowserItemCompareUPP(DBCompareCallBack); + callbacks.u.v1.itemNotificationCallback = NewDataBrowserItemNotificationUPP(DBItemNotificationCallBack); + err = SetDataBrowserCallbacks(dbRef, &callbacks); + + if (systemVersion >= 0x1040) + err = DataBrowserChangeAttributes(dbRef, kDataBrowserAttributeListViewAlternatingRowColors, kDataBrowserAttributeNone); + + InitCheatItems(); + ImportCheatItems(); + + DataBrowserItemID *id; + + id = new DataBrowserItemID[MAX_CHEATS]; + if (!id) + QuitWithFatalError(0, "cheat 01"); + + numofcheats = 0; + + for (unsigned int i = 0; i < MAX_CHEATS; i++) + { + if (citem[i].valid) + { + id[numofcheats] = citem[i].id; + numofcheats++; + } + } + + if (numofcheats) + err = AddDataBrowserItems(dbRef, kDataBrowserNoItem, numofcheats, id, kDataBrowserItemNoProperty); + + delete [] id; + + cid.signature = kNewButton; + HIViewFindByID(root, cid, &ctl); + if (numofcheats == MAX_CHEATS) + err = DeactivateControl(ctl); + else + err = ActivateControl(ctl); + + cid.signature = kAllButton; + HIViewFindByID(root, cid, &ctl); + if (numofcheats == 0) + err = DeactivateControl(ctl); + else + err = ActivateControl(ctl); + + cid.signature = kDelButton; + HIViewFindByID(root, cid, &ctl); + err = DeactivateControl(ctl); + + eUPP = NewEventHandlerUPP(CheatEventHandler); + err = InstallWindowEventHandler(wRef, eUPP, GetEventTypeCount(events), events, (void *) wRef, &eref); + + err = SetKeyboardFocus(wRef, dbRef, kControlFocusNextPart); + + MoveWindowPosition(wRef, kWindowCheatEntry, true); + ShowWindow(wRef); + err = RunAppModalLoopForWindow(wRef); + HideWindow(wRef); + SaveWindowPosition(wRef, kWindowCheatEntry); + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eUPP); + + DisposeDataBrowserItemNotificationUPP(callbacks.u.v1.itemNotificationCallback); + DisposeDataBrowserItemCompareUPP(callbacks.u.v1.itemCompareCallback); + DisposeDataBrowserItemDataUPP(callbacks.u.v1.itemDataCallback); + + CFRelease(wRef); + + DetachCheatItems(); + } + + DisposeNibReference(nibRef); + } +} + +static void AddCheatItem (void) +{ + OSStatus err; + HIViewRef ctl, root; + HIViewID cid; + DataBrowserItemID id[1]; + unsigned int i; + + if (numofcheats == MAX_CHEATS) + return; + + for (i = 0; i < MAX_CHEATS; i++) + if (citem[i].valid == false) + break; + + if (i == MAX_CHEATS) + return; + + numofcheats++; + citem[i].valid = true; + citem[i].enabled = false; + citem[i].address = 0; + citem[i].value = 0; + sprintf(citem[i].description, "Cheat %03" PRIu32, citem[i].id); + + id[0] = citem[i].id; + err = AddDataBrowserItems(dbRef, kDataBrowserNoItem, 1, id, kDataBrowserItemNoProperty); + err = RevealDataBrowserItem(dbRef, id[0], kCmAddress, true); + + root = HIViewGetRoot(wRef); + cid.id = 0; + + if (numofcheats == MAX_CHEATS) + { + cid.signature = kNewButton; + HIViewFindByID(root, cid, &ctl); + err = DeactivateControl(ctl); + } + + if (numofcheats) + { + cid.signature = kAllButton; + HIViewFindByID(root, cid, &ctl); + err = ActivateControl(ctl); + } +} + +static void DeleteCheatItem (void) +{ + OSStatus err; + HIViewRef ctl, root; + HIViewID cid; + Handle selectedItems; + ItemCount selectionCount; + + selectedItems = NewHandle(0); + if (!selectedItems) + return; + + err = GetDataBrowserItems(dbRef, kDataBrowserNoItem, true, kDataBrowserItemIsSelected, selectedItems); + selectionCount = (GetHandleSize(selectedItems) / sizeof(DataBrowserItemID)); + + if (selectionCount == 0) + { + DisposeHandle(selectedItems); + return; + } + + err = RemoveDataBrowserItems(dbRef, kDataBrowserNoItem, selectionCount, (DataBrowserItemID *) *selectedItems, kDataBrowserItemNoProperty); + + for (unsigned int i = 0; i < selectionCount; i++) + { + citem[((DataBrowserItemID *) (*selectedItems))[i] - 1].valid = false; + citem[((DataBrowserItemID *) (*selectedItems))[i] - 1].enabled = false; + numofcheats--; + } + + DisposeHandle(selectedItems); + + root = HIViewGetRoot(wRef); + cid.id = 0; + + if (numofcheats < MAX_CHEATS) + { + cid.signature = kNewButton; + HIViewFindByID(root, cid, &ctl); + err = ActivateControl(ctl); + } + + if (numofcheats == 0) + { + cid.signature = kAllButton; + HIViewFindByID(root, cid, &ctl); + err = DeactivateControl(ctl); + } +} + +static void EnableAllCheatItems (void) +{ + OSStatus err; + + for (unsigned int i = 0; i < MAX_CHEATS; i++) + if (citem[i].valid) + citem[i].enabled = true; + + err = UpdateDataBrowserItems(dbRef, kDataBrowserNoItem, kDataBrowserNoItem, NULL, kDataBrowserItemNoProperty, kCmCheckBox); +} + +static pascal OSStatus DBClientDataCallback (HIViewRef browser, DataBrowserItemID itemID, DataBrowserPropertyID property, DataBrowserItemDataRef itemData, Boolean changeValue) +{ + OSStatus err, result; + CFStringRef str; + Boolean r; + uint32 address; + uint8 value; + char code[256]; + + result = noErr; + + switch (property) + { + case kCmCheckBox: + ThemeButtonValue buttonValue; + + if (changeValue) + { + err = GetDataBrowserItemDataButtonValue(itemData, &buttonValue); + citem[itemID - 1].enabled = (buttonValue == kThemeButtonOn) ? true : false; + } + else + err = SetDataBrowserItemDataButtonValue(itemData, citem[itemID - 1].enabled ? kThemeButtonOn : kThemeButtonOff); + + break; + + case kCmAddress: + if (changeValue) + { + err = GetDataBrowserItemDataText(itemData, &str); + r = CFStringGetCString(str, code, 256, CFStringGetSystemEncoding()); + CFRelease(str); + if (r) + { + Boolean translated; + + if (S9xProActionReplayToRaw(code, address, value) == NULL) + translated = true; + else + if (S9xGameGenieToRaw(code, address, value) == NULL) + translated = true; + else + { + translated = false; + if (sscanf(code, "%" SCNx32, &address) != 1) + address = 0; + else + address &= 0xFFFFFF; + } + + citem[itemID - 1].address = address; + sprintf(code, "%06" PRIX32, address); + str = CFStringCreateWithCString(kCFAllocatorDefault, code, CFStringGetSystemEncoding()); + err = SetDataBrowserItemDataText(itemData, str); + CFRelease(str); + + if (translated) + { + DataBrowserItemID id[1]; + + citem[itemID - 1].value = value; + id[0] = itemID; + err = UpdateDataBrowserItems(browser, kDataBrowserNoItem, 1, id, kDataBrowserItemNoProperty, kCmValue); + } + } + } + else + { + sprintf(code, "%06" PRIX32, citem[itemID - 1].address); + str = CFStringCreateWithCString(kCFAllocatorDefault, code, CFStringGetSystemEncoding()); + err = SetDataBrowserItemDataText(itemData, str); + CFRelease(str); + } + + break; + + case kCmValue: + if (changeValue) + { + err = GetDataBrowserItemDataText(itemData, &str); + r = CFStringGetCString(str, code, 256, CFStringGetSystemEncoding()); + CFRelease(str); + if (r) + { + uint32 byte; + + if (sscanf(code, "%" SCNx32, &byte) == 1) + citem[itemID - 1].value = (uint8) byte; + else + { + citem[itemID - 1].value = 0; + err = SetDataBrowserItemDataText(itemData, CFSTR("00")); + } + } + } + else + { + sprintf(code, "%02" PRIX8, citem[itemID - 1].value); + str = CFStringCreateWithCString(kCFAllocatorDefault, code, CFStringGetSystemEncoding()); + err = SetDataBrowserItemDataText(itemData, str); + CFRelease(str); + } + + break; + + case kCmDescription: + if (changeValue) + { + code[0] = 0; + err = GetDataBrowserItemDataText(itemData, &str); + strcpy(code, GetMultiByteCharacters(str, 19)); + CFRelease(str); + + if (code[0] == 0) + { + code[0] = ' '; + code[1] = 0; + } + + strcpy(citem[itemID - 1].description, code); + } + else + { + str = CFStringCreateWithCString(kCFAllocatorDefault, citem[itemID - 1].description, CFStringGetSystemEncoding()); + err = SetDataBrowserItemDataText(itemData, str); + CFRelease(str); + } + + break; + + case kDataBrowserItemIsActiveProperty: + err = SetDataBrowserItemDataBooleanValue(itemData, true); + break; + + case kDataBrowserItemIsEditableProperty: + err = SetDataBrowserItemDataBooleanValue(itemData, true); + break; + + default: + result = errDataBrowserPropertyNotSupported; + } + + return (result); +} + +static pascal Boolean DBCompareCallBack (HIViewRef browser, DataBrowserItemID itemOne, DataBrowserItemID itemTwo, DataBrowserPropertyID sortProperty) +{ + Boolean result = false; + + switch (sortProperty) + { + case kCmCheckBox: + result = (citem[itemOne - 1].enabled && !(citem[itemTwo - 1].enabled)) ? true : false; + break; + + case kCmAddress: + result = (citem[itemOne - 1].address < citem[itemTwo - 1].address) ? true : false; + break; + + case kCmValue: + result = (citem[itemOne - 1].value < citem[itemTwo - 1].value) ? true : false; + break; + + case kCmDescription: + result = (strcmp(citem[itemOne - 1].description, citem[itemTwo - 1].description) < 0) ? true : false; + } + + return (result); +} + +static pascal void DBItemNotificationCallBack (HIViewRef browser, DataBrowserItemID itemID, DataBrowserItemNotification message) +{ + OSStatus err; + HIViewRef ctl; + HIViewID cid = { kDelButton, 0 }; + ItemCount selectionCount; + + switch (message) + { + case kDataBrowserSelectionSetChanged: + HIViewFindByID(HIViewGetRoot(wRef), cid, &ctl); + + err = GetDataBrowserItemCount(browser, kDataBrowserNoItem, true, kDataBrowserItemIsSelected, &selectionCount); + if (selectionCount == 0) + err = DeactivateControl(ctl); + else + err = ActivateControl(ctl); + } +} + +static pascal OSStatus CheatEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef tWindowRef; + + tWindowRef = (WindowRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + switch (GetEventKind(inEvent)) + { + case kEventWindowClose: + QuitAppModalLoopForWindow(tWindowRef); + result = noErr; + break; + } + + break; + + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(true); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + switch (tHICommand.commandID) + { + case kNewButton: + AddCheatItem(); + result = noErr; + break; + + case kDelButton: + DeleteCheatItem(); + result = noErr; + break; + + case kAllButton: + EnableAllCheatItems(); + result = noErr; + } + } + } + } + + return (result); +} diff --git a/macosx/mac-cheat.h b/macosx/mac-cheat.h new file mode 100644 index 00000000..5e1a2d29 --- /dev/null +++ b/macosx/mac-cheat.h @@ -0,0 +1,196 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_cheat_h_ +#define _mac_cheat_h_ + +void ConfigureCheat (void); + +#endif diff --git a/macosx/mac-cheatfinder.cpp b/macosx/mac-cheatfinder.cpp new file mode 100644 index 00000000..d4c05ba4 --- /dev/null +++ b/macosx/mac-cheatfinder.cpp @@ -0,0 +1,2215 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "cheats.h" + +#include "mac-prefix.h" +#include "mac-audio.h" +#include "mac-dialog.h" +#include "mac-os.h" +#include "mac-screenshot.h" +#include "mac-stringtools.h" +#include "mac-cheatfinder.h" + +#define kCFNumBytesPop 'Size' +#define kCFViewModeRad 'Mode' +#define kCFCompModePop 'Math' +#define kCFCompStoredRad 'RSto' +#define kCFCompLastRad 'RLst' +#define kCFCompThisRad 'RThs' +#define kCFCompValueTxt 'CTxt' +#define kCFSearchBtn 'BSea' +#define kCFStoreValueBtn 'BSto' +#define kCFWatchBtn 'BWat' +#define kCFDrawerBtn 'Drwr' +#define kCFWatchAddrTxt 'WTxt' +#define kCFRestoreBtn 'BRes' +#define kCFRemoveBtn 'BRem' +#define kCFAddEntryBtn 'BAdd' +#define kCFUserPane 'Pane' +#define kCFSheetAddrTxt 'AEad' +#define kCFSheetCurrentValueTxt 'AEcv' +#define kCFSheetCheetValueTxt 'AEtx' +#define kCFSheetDescriptionTxt 'AEde' +#define kCFSheetAddBtn 'SHTa' +#define kCFSheetCancelBtn 'SHTc' +#define kCFListView 'List' +#define kCFUpperViews 'UI_T' +#define kCFLowerViews 'UI_B' + +#define kEventScrollableScrollThere 'ESST' +#define kEventCheatFinderList 'ECFL' +#define kControlListLinePart 172 + +#define MAIN_MEMORY_SIZE 0x20000 + +#define kCheatFinderListViewClassID CFSTR("com.snes9x.macos.snes9x.cheatfinder") + +enum +{ + kCFHexadecimal = 1, + kCFSignedDecimal, + kCFUnsignedDecimal +}; + +enum +{ + kCFCompWithStored = 1, + kCFCompWithLast, + kCFCompWithThis +}; + +enum +{ + kCFSearchEqual = 1, + kCFSearchNotEqual, + kCFSearchGreater, + kCFSearchGreaterOrEqual, + kCFSearchLess, + kCFSearchLessOrEqual +}; + +typedef struct +{ + IBNibRef nibRef; + WindowRef main; + WindowRef sheet; + WindowRef drawer; + HIViewRef list; + HIViewRef scroll; + EventHandlerRef sEref; + EventHandlerUPP sUPP; +} WindowData; + +typedef struct +{ + HIViewRef view; + HIPoint originPoint; + HISize lineSize; + Boolean inFocus; +} ListViewData; + +Boolean cfIsWatching = false; + +extern SCheatData Cheat; + +static UInt8 *cfStoredRAM; +static UInt8 *cfLastRAM; +static UInt8 *cfCurrentRAM; +static UInt8 *cfStatusFlag; +static UInt32 *cfAddress; + +static SInt32 cfNumRows; +static SInt32 cfListSelection; + +static SInt32 cfViewMode; +static SInt32 cfCompMode; +static SInt32 cfCompWith; +static UInt32 cfViewNumBytes; +static UInt32 cfWatchAddr; +static Boolean cfIsNewGame; +static Boolean cfIsStored; +static Boolean cfDrawerShow; + +static int cfListAddrColumnWidth; +static char cfWatchTextFormat[32]; +static CTFontRef cfListLineCTFontRef; +#ifdef MAC_TIGER_PANTHER_SUPPORT +static ATSUStyle cfListLineATSUStyle; +#endif + +static HIViewID kCheatFinderListViewID = { 'CHET', 'FNDR' }; + +static void CheatFinderSearch (WindowData *); +static void CheatFinderRestoreList (WindowData *); +static void CheatFinderRemoveFromList (WindowData *); +static void CheatFinderAdjustButtons (WindowData *); +static void CheatFinderBuildResultList (void); +static void CheatFinderHandleAddEntryButton (WindowData *); +static void CheatFinderMakeValueFormat (char *); +static void CheatFinderAddEntry (SInt64, char *); +static void CheatFinderBeginAddEntrySheet (WindowData *); +static void CheatFinderEndAddEntrySheet (WindowData *); +static void CheatFinderListViewScrollToThere (float, ListViewData *); +static void CheatFinderListViewDraw (CGContextRef, HIRect *, ListViewData *); +static float CheatFinderListViewSanityCheck (float, ListViewData *); +static SInt64 CheatFinderReadBytes (UInt8 *, UInt32); +static SInt64 CheatFinderGetValueEditText (ControlRef); +static Boolean CheatFinderCompare (SInt64, SInt64); +static HIViewPartCode CheatFinderListViewFindPart (EventRef, ListViewData *, SInt32 *); +static pascal OSStatus CheatFinderListViewHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus CheatFinderSheetEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus CheatFinderWindowEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus CheatFinderListFrameEventHandler (EventHandlerCallRef, EventRef, void *); + + +void InitCheatFinder (void) +{ + cfStoredRAM = new UInt8 [MAIN_MEMORY_SIZE + 10]; + cfLastRAM = new UInt8 [MAIN_MEMORY_SIZE + 10]; + cfCurrentRAM = new UInt8 [MAIN_MEMORY_SIZE + 10]; + cfStatusFlag = new UInt8 [MAIN_MEMORY_SIZE + 10]; + cfAddress = new UInt32[MAIN_MEMORY_SIZE + 10]; + + if (!cfStoredRAM || !cfLastRAM || !cfCurrentRAM || !cfStatusFlag || !cfAddress) + QuitWithFatalError(0, "cheatfinder 01"); + + memset(cfCurrentRAM, 0x00, MAIN_MEMORY_SIZE + 10); + + cfViewMode = kCFUnsignedDecimal; + cfViewNumBytes = 2; + cfCompMode = kCFSearchEqual; + cfCompWith = kCFCompWithThis; + + if (systemVersion >= 0x1050) + { + cfListLineCTFontRef = CTFontCreateWithName(CFSTR("Lucida Sans Typewriter Regular"), 11.0f, NULL); + if (cfListLineCTFontRef == NULL) + { + cfListLineCTFontRef = CTFontCreateWithName(CFSTR("Menlo"), 11.0f, NULL); + if (cfListLineCTFontRef == NULL) + { + cfListLineCTFontRef = CTFontCreateWithName(CFSTR("Monaco"), 11.0f, NULL); + if (cfListLineCTFontRef == NULL) + QuitWithFatalError(0, "cheatfinder 02"); + } + } + } +#ifdef MAC_TIGER_PANTHER_SUPPORT + else + { + OSStatus err; + + err = CreateATSUIStyleFromFontFullNameAndSize("Lucida Sans Typewriter Regular", 11, &cfListLineATSUStyle); + if (err) + { + err = CreateATSUIStyleFromFontFullNameAndSize("Menlo", 11, &cfListLineATSUStyle); + if (err) + { + err = CreateATSUIStyleFromFontFullNameAndSize("Monaco", 11, &cfListLineATSUStyle); + if (err) + QuitWithFatalError(0, "cheatfinder 02"); + } + } + } +#endif +} + +void ResetCheatFinder (void) +{ + memset(cfStoredRAM, 0x00, MAIN_MEMORY_SIZE); + memset(cfLastRAM, 0x00, MAIN_MEMORY_SIZE); + memset(cfStatusFlag, 0xFF, MAIN_MEMORY_SIZE); + + cfWatchAddr = 0; + cfIsNewGame = true; + cfIsWatching = false; + cfIsStored = false; + cfDrawerShow = false; + + CheatFinderMakeValueFormat(cfWatchTextFormat); +} + +void DeinitCheatFinder (void) +{ + if (systemVersion >= 0x1050) + CFRelease(cfListLineCTFontRef); +#ifdef MAC_TIGER_PANTHER_SUPPORT + else + ATSUDisposeStyle(cfListLineATSUStyle); +#endif + + delete [] cfStoredRAM; + delete [] cfLastRAM; + delete [] cfCurrentRAM; + delete [] cfStatusFlag; + delete [] cfAddress; +} + +void CheatFinder (void) +{ + static HIObjectClassRef cfListViewClass = NULL; + + OSStatus err; + HIViewRef ctl; + HIViewID cid; + MenuRef menu; + char num[256]; + WindowData cf; + EventHandlerRef wEref, pEref; + EventHandlerUPP wUPP, pUPP; + EventTypeSpec wEvents[] = { { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus }, + { kEventClassWindow, kEventWindowClose } }, + pEvents[] = { { kEventClassControl, kEventControlDraw } }, + cEvents[] = { { kEventClassHIObject, kEventHIObjectConstruct }, + { kEventClassHIObject, kEventHIObjectInitialize }, + { kEventClassHIObject, kEventHIObjectDestruct }, + { kEventClassScrollable, kEventScrollableGetInfo }, + { kEventClassScrollable, kEventScrollableScrollTo }, + { kEventCheatFinderList, kEventScrollableScrollThere }, + { kEventClassControl, kEventControlHitTest }, + { kEventClassControl, kEventControlTrack }, + { kEventClassControl, kEventControlValueFieldChanged }, + { kEventClassControl, kEventControlDraw } }; + + if (!cartOpen) + return; + + err = CreateNibReference(kMacS9XCFString, &(cf.nibRef)); + if (err == noErr) + { + err = CreateWindowFromNib(cf.nibRef, CFSTR("CheatFinder"), &(cf.main)); + if (err == noErr) + { + err = CreateWindowFromNib(cf.nibRef, CFSTR("CFDrawer"), &(cf.drawer)); + if (err == noErr) + { + memcpy(cfCurrentRAM, Memory.RAM, MAIN_MEMORY_SIZE); + CheatFinderBuildResultList(); + + err = noErr; + if (!cfListViewClass) + err = HIObjectRegisterSubclass(kCheatFinderListViewClassID, kHIViewClassID, 0, CheatFinderListViewHandler, GetEventTypeCount(cEvents), cEvents, NULL, &cfListViewClass); + if (err == noErr) + { + HIObjectRef hiObject; + HIViewRef userpane, scrollview, listview, imageview, root; + HILayoutInfo layoutinfo; + HIRect frame; + HISize minSize; + CGImageRef image; + Rect rct; + float pich; + + GetWindowBounds(cf.main, kWindowContentRgn, &rct); + + minSize.width = (float) (rct.right - rct.left); + minSize.height = (float) (rct.bottom - rct.top ); + err = SetWindowResizeLimits(cf.main, &minSize, NULL); + + root = HIViewGetRoot(cf.main); + cid.id = 0; + cid.signature = kCFUserPane; + HIViewFindByID(root, cid, &userpane); + + err = HIScrollViewCreate(kHIScrollViewOptionsVertScroll, &scrollview); + HIViewAddSubview(userpane, scrollview); + HIViewGetBounds(userpane, &frame); + cfListAddrColumnWidth = (int) (frame.size.width * 0.4); + frame.origin.y += 16.0f; + frame.size.height -= 16.0f; + frame = CGRectInset(frame, 1.0f, 1.0f); + HIViewSetFrame(scrollview, &frame); + HIViewSetVisible(scrollview, true); + cf.scroll = scrollview; + + layoutinfo.version = kHILayoutInfoVersionZero; + HIViewGetLayoutInfo(scrollview, &layoutinfo); + + layoutinfo.binding.top.toView = userpane; + layoutinfo.binding.top.kind = kHILayoutBindTop; + layoutinfo.binding.bottom.toView = userpane; + layoutinfo.binding.bottom.kind = kHILayoutBindBottom; + layoutinfo.binding.left.toView = userpane; + layoutinfo.binding.left.kind = kHILayoutBindLeft; + layoutinfo.binding.right.toView = userpane; + layoutinfo.binding.right.kind = kHILayoutBindRight; + HIViewSetLayoutInfo(scrollview, &layoutinfo); + + err = HIObjectCreate(kCheatFinderListViewClassID, NULL, &hiObject); + listview = (HIViewRef) hiObject; + HIViewAddSubview(scrollview, listview); + SetControl32BitMinimum(listview, 1); + SetControl32BitMaximum(listview, cfNumRows); + SetControl32BitValue(listview, 1); + HIViewSetVisible(listview, true); + cf.list = listview; + + cid.signature = kCFNumBytesPop; + HIViewFindByID(root, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + CheckMenuItem(menu, cfViewNumBytes, true); + SetControl32BitValue(ctl, cfViewNumBytes); + + cid.signature = kCFViewModeRad; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, cfViewMode); + + cid.signature = kCFCompModePop; + HIViewFindByID(root, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + CheckMenuItem(menu, cfCompMode, true); + SetControl32BitValue(ctl, cfCompMode); + + if (cfIsNewGame || (!cfIsStored && (cfCompWith == kCFCompWithStored))) + cfCompWith = kCFCompWithThis; + + cid.signature = kCFCompStoredRad; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, cfCompWith == kCFCompWithStored); + if (cfIsStored) + ActivateControl(ctl); + else + DeactivateControl(ctl); + + cid.signature = kCFCompLastRad; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, cfCompWith == kCFCompWithLast); + if (!cfIsNewGame) + ActivateControl(ctl); + else + DeactivateControl(ctl); + + cid.signature = kCFCompThisRad; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, cfCompWith == kCFCompWithThis); + + cid.signature = kCFCompValueTxt; + HIViewFindByID(root, cid, &ctl); + SetEditTextCFString(ctl, CFSTR(""), false); + err = SetKeyboardFocus(cf.main, ctl, kControlFocusNextPart); + + cid.signature = kCFWatchBtn; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, cfIsWatching); + + cid.signature = kCFDrawerBtn; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, cfDrawerShow); + + cid.signature = kCFWatchAddrTxt; + HIViewFindByID(root, cid, &ctl); + if (cfIsWatching) + { + sprintf(num, "%06lX", cfWatchAddr + 0x7E0000); + SetStaticTextCStr(ctl, num, false); + } + else + SetStaticTextCFString(ctl, CFSTR(""), false); + + CheatFinderAdjustButtons(&cf); + + pUPP = NewEventHandlerUPP(CheatFinderListFrameEventHandler); + err = InstallControlEventHandler(userpane, pUPP, GetEventTypeCount(pEvents), pEvents, (void *) userpane, &pEref); + + wUPP = NewEventHandlerUPP(CheatFinderWindowEventHandler); + err = InstallWindowEventHandler (cf.main, wUPP, GetEventTypeCount(wEvents), wEvents, (void *) &cf, &wEref); + + pich = (float) (IPPU.RenderedScreenHeight >> ((IPPU.RenderedScreenHeight > 256) ? 1 : 0)); + + err = SetDrawerParent(cf.drawer, cf.main); + err = SetDrawerOffsets(cf.drawer, 0.0f, (float) ((rct.bottom - rct.top) - (pich + 37))); + + image = CreateGameScreenCGImage(); + if (image) + { + err = HIImageViewCreate(image, &imageview); + if (err == noErr) + { + HIViewFindByID(HIViewGetRoot(cf.drawer), kHIViewWindowContentID, &ctl); + + HIViewAddSubview(ctl, imageview); + HIImageViewSetOpaque(imageview, false); + HIImageViewSetScaleToFit(imageview, true); + HIViewSetVisible(imageview, true); + + frame.origin.x = 8.0f; + frame.origin.y = 8.0f; + frame.size.width = (float) SNES_WIDTH; + frame.size.height = pich; + HIViewSetFrame(imageview, &frame); + } + } + + MoveWindowPosition(cf.main, kWindowCheatFinder, true); + ShowWindow(cf.main); + + if (cfDrawerShow) + err = OpenDrawer(cf.drawer, kWindowEdgeDefault, false); + + err = RunAppModalLoopForWindow(cf.main); + + HideWindow(cf.main); + SaveWindowPosition(cf.main, kWindowCheatFinder); + + err = RemoveEventHandler(pEref); + DisposeEventHandlerUPP(pUPP); + + err = RemoveEventHandler(wEref); + DisposeEventHandlerUPP(wUPP); + + if (image) + CGImageRelease(image); + } + + CFRelease(cf.drawer); + } + + CFRelease(cf.main); + } + + DisposeNibReference(cf.nibRef); + + memcpy(cfLastRAM, Memory.RAM, MAIN_MEMORY_SIZE); + cfIsNewGame = false; + } +} + +static SInt64 CheatFinderReadBytes (UInt8 *mem, UInt32 addr) +{ + switch (cfViewMode) + { + case kCFSignedDecimal: + { + switch (cfViewNumBytes) + { + case 1: return ((SInt64) (SInt8) mem[addr]); + case 2: return ((SInt64) (SInt16) (mem[addr] | (mem[addr + 1] << 8))); + case 4: return ((SInt64) (SInt32) (mem[addr] | (mem[addr + 1] << 8) | (mem[addr + 2] << 16) | (mem[addr + 3] << 24))); + case 3: return ((SInt64) (((SInt32) ((mem[addr] | (mem[addr + 1] << 8) | (mem[addr + 2] << 16)) << 8)) >> 8)); + } + + break; + } + + case kCFUnsignedDecimal: + case kCFHexadecimal: + { + switch (cfViewNumBytes) + { + case 1: return ((SInt64) (UInt8) mem[addr]); + case 2: return ((SInt64) (UInt16) (mem[addr] | (mem[addr + 1] << 8))); + case 3: return ((SInt64) (UInt32) (mem[addr] | (mem[addr + 1] << 8) | (mem[addr + 2] << 16))); + case 4: return ((SInt64) (UInt32) (mem[addr] | (mem[addr + 1] << 8) | (mem[addr + 2] << 16) | (mem[addr + 3] << 24))); + } + + break; + } + } + + return (0); +} + +static pascal OSStatus CheatFinderWindowEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowData *cf; + HIViewRef control, ctl, root; + HIViewID controlID, cid; + Boolean update = false; + char num[256]; + + cf = (WindowData *) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + { + switch (GetEventKind(inEvent)) + { + case kEventWindowClose: + { + QuitAppModalLoopForWindow(cf->main); + result = noErr; + break; + } + } + + break; + } + + case kEventClassCommand: + { + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(true); + result = noErr; + } + + break; + } + + case kEventCommandProcess: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + root = HIViewGetRoot(cf->main); + controlID.id = 0; + controlID.signature = tHICommand.commandID; + HIViewFindByID(root, controlID, &control); + + switch (tHICommand.commandID) + { + case kCFNumBytesPop: + { + cfViewNumBytes = GetControl32BitValue(control); + update = true; + result = noErr; + break; + } + + case kCFViewModeRad: + { + cfViewMode = GetControl32BitValue(control); + update = true; + result = noErr; + break; + } + + case kCFCompModePop: + { + cfCompMode = GetControl32BitValue(control); + result = noErr; + break; + } + + case kCFCompStoredRad: + case kCFCompLastRad: + case kCFCompThisRad: + { + if (tHICommand.commandID == kCFCompStoredRad) + cfCompWith = kCFCompWithStored; + else + if (tHICommand.commandID == kCFCompLastRad) + cfCompWith = kCFCompWithLast; + else + cfCompWith = kCFCompWithThis; + + cid.id = 0; + + cid.signature = kCFCompStoredRad; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, cfCompWith == kCFCompWithStored); + + cid.signature = kCFCompLastRad; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, cfCompWith == kCFCompWithLast); + + cid.signature = kCFCompThisRad; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, cfCompWith == kCFCompWithThis); + + result = noErr; + break; + } + + case kCFStoreValueBtn: + { + memcpy(cfStoredRAM, Memory.RAM, MAIN_MEMORY_SIZE); + cfIsStored = true; + + cid.id = 0; + cid.signature = kCFCompStoredRad; + HIViewFindByID(root, cid, &ctl); + ActivateControl(ctl); + + result = noErr; + break; + } + + case kCFSearchBtn: + { + CheatFinderSearch(cf); + update = true; + result = noErr; + break; + } + + case kCFRemoveBtn: + { + CheatFinderRemoveFromList(cf); + update = true; + result = noErr; + break; + } + + case kCFRestoreBtn: + { + CheatFinderRestoreList(cf); + update = true; + result = noErr; + break; + } + + case kCFAddEntryBtn: + { + CheatFinderHandleAddEntryButton(cf); + result = noErr; + break; + } + + case kCFDrawerBtn: + { + cfDrawerShow = !cfDrawerShow; + + if (cfDrawerShow) + err = OpenDrawer(cf->drawer, kWindowEdgeDefault, false); + else + err = CloseDrawer(cf->drawer, false); + + result = noErr; + break; + } + + case kCFWatchBtn: + { + cid.id = 0; + cid.signature = kCFWatchAddrTxt; + HIViewFindByID(root, cid, &ctl); + + if (!cfIsWatching) + { + if (cfAddress[cfListSelection] > (0x20000 - cfViewNumBytes)) + { + PlayAlertSound(); + SetControl32BitValue(control, 0); + } + else + { + cfWatchAddr = cfAddress[cfListSelection]; + cfIsWatching = true; + + sprintf(num, "%06lX", cfWatchAddr + 0x7E0000); + SetStaticTextCStr(ctl, num, true); + } + } + else + { + cfWatchAddr = 0; + cfIsWatching = false; + + SetControl32BitValue(control, 0); + SetStaticTextCFString(ctl, CFSTR(""), true); + + CheatFinderAdjustButtons(cf); + } + + result = noErr; + break; + } + } + + if (update) + { + HIViewSetNeedsDisplay(cf->list, true); + CheatFinderAdjustButtons(cf); + } + + CheatFinderMakeValueFormat(cfWatchTextFormat); + } + + break; + } + } + + break; + } + } + + return (result); +} + +static SInt64 CheatFinderGetValueEditText (HIViewRef control) +{ + SInt64 result = 0; + UInt32 uvalue; + SInt32 svalue; + char num[256]; + + GetEditTextCStr(control, num); + if (num[0] == 0) + { + SetEditTextCFString(control, CFSTR("0"), true); + return (0); + } + + switch (cfViewMode) + { + case kCFSignedDecimal: + { + if (sscanf(num, "%ld", &svalue) == 1) + { + switch (cfViewNumBytes) + { + case 1: + { + if (svalue > 127) + { + svalue = 127; + SetEditTextCFString(control, CFSTR("127"), true); + } + else + if (svalue < -128) + { + svalue = -128; + SetEditTextCFString(control, CFSTR("-128"), true); + } + + break; + } + + case 2: + { + if (svalue > 32767) + { + svalue = 32767; + SetEditTextCFString(control, CFSTR("32767"), true); + } + else + if (svalue < -32768) + { + svalue = -32768; + SetEditTextCFString(control, CFSTR("-32768"), true); + } + + break; + } + + case 3: + { + if (svalue > 8388607) + { + svalue = 8388607; + SetEditTextCFString(control, CFSTR("8388607"), true); + } + else + if (svalue < -8388608) + { + svalue = -8388608; + SetEditTextCFString(control, CFSTR("-8388608"), true); + } + + break; + } + } + } + else + { + svalue = 0; + SetEditTextCFString(control, CFSTR("0"), true); + } + + result = (SInt64) svalue; + + break; + } + + case kCFUnsignedDecimal: + { + if (sscanf(num, "%lu", &uvalue) == 1) + { + switch (cfViewNumBytes) + { + case 1: + { + if (uvalue > 255) + { + uvalue = 255; + SetEditTextCFString(control, CFSTR("255"), true); + } + + break; + } + + case 2: + { + if (uvalue > 65535) + { + uvalue = 65535; + SetEditTextCFString(control, CFSTR("65535"), true); + } + + break; + } + + case 3: + { + if (uvalue > 16777215) + { + uvalue = 16777215; + SetEditTextCFString(control, CFSTR("16777215"), true); + } + + break; + } + } + } + else + { + uvalue = 0; + SetEditTextCFString(control, CFSTR("0"), true); + } + + result = (SInt64) uvalue; + + break; + } + + case kCFHexadecimal: + { + if (sscanf(num, "%lx", &uvalue) == 1) + { + switch (cfViewNumBytes) + { + case 1: + { + if (uvalue > 0xFF) + { + uvalue = 0xFF; + SetEditTextCFString(control, CFSTR("FF"), true); + } + + break; + } + + case 2: + { + if (uvalue > 0xFFFF) + { + uvalue = 0xFFFF; + SetEditTextCFString(control, CFSTR("FFFF"), true); + } + + break; + } + + case 3: + { + if (uvalue > 0xFFFFFF) + { + uvalue = 0xFFFFFF; + SetEditTextCFString(control, CFSTR("FFFFFF"), true); + } + + break; + } + } + } + else + { + uvalue = 0; + SetEditTextCFString(control, CFSTR("0"), true); + } + + result = (SInt64) uvalue; + + break; + } + } + + return (result); +} + +static void CheatFinderSearch (WindowData *cf) +{ + SInt64 cmpvalue; + UInt8 *mem; + + if (cfCompWith == kCFCompWithThis) + { + HIViewRef ctl; + HIViewID cid = { kCFCompValueTxt, 0 }; + + HIViewFindByID(HIViewGetRoot(cf->main), cid, &ctl); + cmpvalue = CheatFinderGetValueEditText(ctl); + + for (int i = 0; i < cfNumRows; i++) + if (!CheatFinderCompare(CheatFinderReadBytes(cfCurrentRAM, cfAddress[i]), cmpvalue)) + cfStatusFlag[cfAddress[i]] = 0; + } + else + { + mem = (cfCompWith == kCFCompWithStored) ? cfStoredRAM : cfLastRAM; + + for (int i = 0; i < cfNumRows; i++) + if (!CheatFinderCompare(CheatFinderReadBytes(cfCurrentRAM, cfAddress[i]), CheatFinderReadBytes(mem, cfAddress[i]))) + cfStatusFlag[cfAddress[i]] = 0; + } + + CheatFinderBuildResultList(); + + SetControl32BitMaximum(cf->list, cfNumRows); + SetControl32BitValue(cf->list, 1); +} + +static Boolean CheatFinderCompare (SInt64 ramvalue, SInt64 cmpvalue) +{ + switch (cfCompMode) + { + case kCFSearchEqual: return (ramvalue == cmpvalue); + case kCFSearchNotEqual: return (ramvalue != cmpvalue); + case kCFSearchGreater: return (ramvalue > cmpvalue); + case kCFSearchGreaterOrEqual: return (ramvalue >= cmpvalue); + case kCFSearchLess: return (ramvalue < cmpvalue); + case kCFSearchLessOrEqual: return (ramvalue <= cmpvalue); + } + + return (false); +} + +static void CheatFinderBuildResultList (void) +{ + cfNumRows = 0; + + for (int i = 0; i < MAIN_MEMORY_SIZE; i++) + { + if (cfStatusFlag[i] == 0xFF) + { + cfAddress[cfNumRows] = i; + cfNumRows++; + } + } + + cfListSelection = 0; +} + +static void CheatFinderAdjustButtons (WindowData *cf) +{ + HIViewRef ctl, root; + HIViewID cid; + + cid.id = 0; + root = HIViewGetRoot(cf->main); + + if (cfNumRows > 0) + { + cid.signature = kCFAddEntryBtn; + HIViewFindByID(root, cid, &ctl); + ActivateControl(ctl); + + cid.signature = kCFRemoveBtn; + HIViewFindByID(root, cid, &ctl); + ActivateControl(ctl); + + cid.signature = kCFWatchBtn; + HIViewFindByID(root, cid, &ctl); + ActivateControl(ctl); + } + else + { + cid.signature = kCFAddEntryBtn; + HIViewFindByID(root, cid, &ctl); + DeactivateControl(ctl); + + cid.signature = kCFRemoveBtn; + HIViewFindByID(root, cid, &ctl); + DeactivateControl(ctl); + + if (!cfIsWatching) + { + cid.signature = kCFWatchBtn; + HIViewFindByID(root, cid, &ctl); + DeactivateControl(ctl); + } + } +} + +static void CheatFinderRemoveFromList (WindowData *cf) +{ + if (cfNumRows > 0) + { + cfStatusFlag[cfAddress[cfListSelection]] = 0; + + if (cfNumRows == 1) + { + cfNumRows = 0; + + SetControl32BitMaximum(cf->list, 0); + SetControl32BitValue(cf->list, 1); + } + else + { + for (int i = cfListSelection; i < cfNumRows - 1; i++) + cfAddress[i] = cfAddress[i + 1]; + + cfNumRows--; + if (cfListSelection >= cfNumRows) + cfListSelection = cfNumRows - 1; + + SetControl32BitMaximum(cf->list, cfNumRows); + SetControl32BitValue(cf->list, cfListSelection + 1); + } + } +} + +static void CheatFinderRestoreList (WindowData *cf) +{ + memset(cfStatusFlag, 0xFF, MAIN_MEMORY_SIZE); + CheatFinderBuildResultList(); + + SetControl32BitMaximum(cf->list, cfNumRows); + SetControl32BitValue(cf->list, 1); +} + +static void CheatFinderMakeValueFormat (char *text) +{ + switch (cfViewMode) + { + case kCFSignedDecimal: + case kCFUnsignedDecimal: + { + strcpy(text, "%lld"); + break; + } + + case kCFHexadecimal: + { + sprintf(text, "%%0%lullX", cfViewNumBytes * 2); + break; + } + } +} + +void CheatFinderDrawWatchAddr (void) +{ + static char code[256]; + + uint16 *basePtr; + int len; + + sprintf(code, cfWatchTextFormat, CheatFinderReadBytes(Memory.RAM, cfWatchAddr)); + + basePtr = GFX.Screen + 1; + len = strlen(code); + + for (int i = 0; i < len; i++) + { + S9xDisplayChar(basePtr, code[i]); + basePtr += (8 - 1); + } +} + +static void CheatFinderHandleAddEntryButton (WindowData *cf) +{ + if (cfAddress[cfListSelection] > (0x20000 - cfViewNumBytes)) + PlayAlertSound(); + else + if (Cheat.num_cheats + cfViewNumBytes > MAX_CHEATS) + AppearanceAlert(kAlertCautionAlert, kCFCantAddWarning, kCFCantAddHint); + else + CheatFinderBeginAddEntrySheet(cf); +} + +static void CheatFinderBeginAddEntrySheet (WindowData *cf) +{ + OSStatus err; + HIViewRef ctl, root; + HIViewID cid; + UInt32 addr; + char str[256], form[256]; + EventTypeSpec sEvents[] = { { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }; + + err = CreateWindowFromNib(cf->nibRef, CFSTR("CFAddEntry"), &(cf->sheet)); + if (err == noErr) + { + addr = cfAddress[cfListSelection]; + + root = HIViewGetRoot(cf->sheet); + cid.id = 0; + + cid.signature = kCFSheetAddrTxt; + HIViewFindByID(root, cid, &ctl); + sprintf(str, "%06lX", addr + 0x7E0000); + SetStaticTextCStr(ctl, str, false); + + cid.signature = kCFSheetCurrentValueTxt; + HIViewFindByID(root, cid, &ctl); + CheatFinderMakeValueFormat(form); + sprintf(str, form, CheatFinderReadBytes(cfCurrentRAM, addr)); + SetStaticTextCStr(ctl, str, false); + + cid.signature = kCFSheetCheetValueTxt; + HIViewFindByID(root, cid, &ctl); + SetEditTextCStr(ctl, str, false); + + err = ClearKeyboardFocus(cf->sheet); + err = SetKeyboardFocus(cf->sheet, ctl, kControlFocusNextPart); + + cid.signature = kCFSheetDescriptionTxt; + HIViewFindByID(root, cid, &ctl); + sprintf(str, "%06lX-%06lX", addr + 0x7E0000, addr + cfViewNumBytes - 1 + 0x7E0000); + SetStaticTextCStr(ctl, str, false); + + cf->sUPP = NewEventHandlerUPP(CheatFinderSheetEventHandler); + err = InstallWindowEventHandler(cf->sheet, cf->sUPP, GetEventTypeCount(sEvents), sEvents, (void *) cf, &(cf->sEref)); + + err = ShowSheetWindow(cf->sheet, cf->main); + } +} + +static void CheatFinderEndAddEntrySheet (WindowData *cf) +{ + if (cf->sheet) + { + OSStatus err; + + err = HideSheetWindow(cf->sheet); + + err = RemoveEventHandler(cf->sEref); + DisposeEventHandlerUPP(cf->sUPP); + + CFRelease(cf->sheet); + } +} + +static pascal OSStatus CheatFinderSheetEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowData *cf = (WindowData *) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassCommand: + { + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(false); + result = noErr; + } + + break; + } + + case kEventCommandProcess: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + switch (tHICommand.commandID) + { + case kCFSheetAddBtn: + { + HIViewRef ctl, root; + HIViewID cid; + CFStringRef str; + SInt64 rv; + char buf[256]; + + root = HIViewGetRoot(cf->sheet); + cid.id = 0; + + cid.signature = kCFSheetCheetValueTxt; + HIViewFindByID(root, cid, &ctl); + rv = CheatFinderGetValueEditText(ctl); + + cid.signature = kCFSheetDescriptionTxt; + HIViewFindByID(root, cid, &ctl); + + buf[0] = 0; + CopyEditTextCFString(ctl, &str); + if (str) + { + strcpy(buf, GetMultiByteCharacters(str, 19)); + CFRelease(str); + } + + if (buf[0] == 0) + { + buf[0] = ' '; + buf[1] = 0; + } + + CheatFinderAddEntry(rv, buf); + + CheatFinderEndAddEntrySheet(cf); + + result = noErr; + break; + } + + case kCFSheetCancelBtn: + { + CheatFinderEndAddEntrySheet(cf); + result = noErr; + break; + } + } + } + + break; + } + } + + break; + } + } + + return (result); +} + +static void CheatFinderAddEntry (SInt64 value, char *description) +{ + UInt32 addr, v; + + addr = cfAddress[cfListSelection]; + v = (UInt32) (SInt32) value; + + for (unsigned int i = 0; i < cfViewNumBytes; i++) + { + strcpy(Cheat.c[Cheat.num_cheats].name, description); + S9xAddCheat(true, true, addr + i + 0x7E0000, (UInt8) ((v & (0x000000FF << (i * 8))) >> (i * 8))); + } + + S9xApplyCheats(); +} + +static pascal OSStatus CheatFinderListFrameEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *userData) +{ + OSStatus err, result = eventNotHandledErr; + HIViewRef view = (HIViewRef) userData; + + switch (GetEventClass(inEvent)) + { + case kEventClassControl: + { + switch (GetEventKind(inEvent)) + { + case kEventControlDraw: + { + CGContextRef ctx; + HIRect bounds; + + HIViewGetBounds(view, &bounds); + cfListAddrColumnWidth = (int) (bounds.size.width * 0.4); + + err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &ctx); + if (err == noErr) + { + HIRect drawBounds; + + if (systemVersion >= 0x1040) + { + HIShapeRef shape = NULL; + + err = GetEventParameter(inEvent, kEventParamShape, typeHIShapeRef, NULL, sizeof(HIShapeRef), NULL, &shape); + if (err == noErr) + { + if (shape) + HIShapeGetBounds(shape, &drawBounds); + else + drawBounds = bounds; + } + } + #ifdef MAC_PANTHER_SUPPORT + else + { + RgnHandle rgn = NULL; + + err = GetEventParameter(inEvent, kEventParamRgnHandle, typeQDRgnHandle, NULL, sizeof(RgnHandle), NULL, &rgn); + if (err == noErr) + { + if (rgn) + { + Rect rgnBounds; + + GetRegionBounds(rgn, &rgnBounds); + drawBounds.origin.x = (float) rgnBounds.left; + drawBounds.origin.y = (float) rgnBounds.top; + drawBounds.size.width = (float) (rgnBounds.right - rgnBounds.left); + drawBounds.size.height = (float) (rgnBounds.bottom - rgnBounds.top ); + } + else + drawBounds = bounds; + } + } + #endif + + if (err == noErr) + { + if (CGRectContainsRect(drawBounds, bounds)) + { + HIRect rct; + HIThemeFrameDrawInfo frameinfo; + HIThemeButtonDrawInfo buttoninfo; + HIThemeTextInfo textinfo; + CFStringRef str; + + buttoninfo.version = 0; + buttoninfo.state = kThemeStateActive; + buttoninfo.kind = kThemeListHeaderButton; + buttoninfo.value = kThemeButtonOff; + buttoninfo.adornment = kThemeAdornmentNone; + + frameinfo.version = 0; + frameinfo.state = kThemeStateActive; + frameinfo.kind = kHIThemeFrameListBox; + frameinfo.isFocused = false; + + textinfo.version = 0; + textinfo.state = kThemeStateActive; + textinfo.fontID = kThemeSmallSystemFont; + textinfo.verticalFlushness = kHIThemeTextVerticalFlushCenter; + textinfo.options = 0; + textinfo.truncationPosition = kHIThemeTextTruncationNone; + textinfo.truncationMaxLines = 0; + textinfo.truncationHappened = false; + + CGContextSaveGState(ctx); + + rct = CGRectInset(bounds, 1.0f, 1.0f); + err = HIThemeDrawFrame(&rct, &frameinfo, ctx, kHIThemeOrientationNormal); + + rct = bounds; + rct.size.height = 16.0f; + rct.size.width = (float) cfListAddrColumnWidth + 1.0f; + err = HIThemeDrawButton(&rct, &buttoninfo, ctx, kHIThemeOrientationNormal, NULL); + + CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); + + rct.size.width = (float) cfListAddrColumnWidth; + rct.origin.y++; + textinfo.horizontalFlushness = kHIThemeTextHorizontalFlushCenter; + str = CFCopyLocalizedString(CFSTR("Address"), "address"); + if (str) + { + err = HIThemeDrawTextBox(str, &rct, &textinfo, ctx, kHIThemeOrientationNormal); + CFRelease(str); + } + + rct = bounds; + rct.size.height = 16.0f; + rct.size.width -= (float) cfListAddrColumnWidth; + rct.origin.x += (float) cfListAddrColumnWidth; + err = HIThemeDrawButton(&rct, &buttoninfo, ctx, kHIThemeOrientationNormal, NULL); + + CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); + + rct.size.width -= 28.0f; + rct.origin.y++; + textinfo.horizontalFlushness = kHIThemeTextHorizontalFlushRight; + str = CFCopyLocalizedString(CFSTR("Value"), "value"); + if (str) + { + err = HIThemeDrawTextBox(str, &rct, &textinfo, ctx, kHIThemeOrientationNormal); + CFRelease(str); + } + + rct = bounds; + rct.size.height = 16.0f; + rct.size.width = 16.0f; + rct.origin.x = bounds.size.width - 16.0f; + err = HIThemeDrawButton(&rct, &buttoninfo, ctx, kHIThemeOrientationNormal, NULL); + + CGContextRestoreGState(ctx); + } + + result = noErr; + } + } + + break; + } + } + + break; + } + } + + return (result); +} + +static void CheatFinderListViewDraw (CGContextRef ctx, HIRect *bounds, ListViewData *myData) +{ + static Boolean init = true; + + if (systemVersion >= 0x1050) + { + static CGRect aRct, vRct; + + CTLineRef line; + CFDictionaryRef attr; + CFAttributedStringRef astr; + CFStringRef str; + HIRect lineBounds; + SInt32 start, end, val, max; + float ax, vx, y, f; + char format[32], t1[64], t2[64]; + + CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName }; + CFTypeRef bval[] = { cfListLineCTFontRef, CGColorGetConstantColor(kCGColorBlack) }, + wval[] = { cfListLineCTFontRef, CGColorGetConstantColor(kCGColorWhite) }; + + CheatFinderMakeValueFormat(format); + + start = (SInt32) (myData->originPoint.y / myData->lineSize.height); + end = (SInt32) ((myData->originPoint.y + bounds->size.height) / myData->lineSize.height) + 1; + + y = start * myData->lineSize.height - myData->originPoint.y; + + lineBounds = *bounds; + lineBounds.size.height = myData->lineSize.height; + lineBounds.origin.y = y; + + val = GetControl32BitValue(myData->view) - 1; + max = GetControl32BitMaximum(myData->view); + + attr = CFDictionaryCreate(kCFAllocatorDefault, (const void **) &keys, (const void **) &bval, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + CGContextSetTextMatrix(ctx, CGAffineTransformIdentity); + + if (init) + { + CGContextSetTextPosition(ctx, 0.0f, 0.0f); + + astr = CFAttributedStringCreate(kCFAllocatorDefault, CFSTR("FFFFFF"), attr); + line = CTLineCreateWithAttributedString(astr); + aRct = CTLineGetImageBounds(line, ctx); + CFRelease(line); + CFRelease(astr); + + astr = CFAttributedStringCreate(kCFAllocatorDefault, CFSTR("FFFFFFFFFFF"), attr); + line = CTLineCreateWithAttributedString(astr); + vRct = CTLineGetImageBounds(line, ctx); + CFRelease(line); + CFRelease(astr); + + init = false; + } + + ax = (float) (int) (((float) cfListAddrColumnWidth - 2.0 - aRct.size.width) / 2.0); + vx = (float) (int) (lineBounds.origin.x + lineBounds.size.width - vRct.size.width - 12.0); + + for (int i = start; i <= end; i++) + { + if ((i == val) && cfNumRows) + CGContextSetRGBFillColor(ctx, 59.0f / 256.0f, 124.0f / 256.0f, 212.0f / 256.0f, 1.0f); + else + if ((i - start) % 2 == 0) + CGContextSetRGBFillColor(ctx, 256.0f / 256.0f, 256.0f / 256.0f, 256.0f / 256.0f, 1.0f); + else + CGContextSetRGBFillColor(ctx, 237.0f / 256.0f, 244.0f / 256.0f, 254.0f / 256.0f, 1.0f); + + CGContextFillRect(ctx, lineBounds); + + if (i < max) + { + CGContextScaleCTM(ctx, 1, -1); + + if (i == val) + { + CFRelease(attr); + attr = CFDictionaryCreate(kCFAllocatorDefault, (const void **) &keys, (const void **) &wval, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + + f = -(y + 12.0f); + + sprintf(t1, "%06lX", cfAddress[i] + 0x7E0000); + str = CFStringCreateWithCString(kCFAllocatorDefault, t1, MAC_PATH_ENCODING); + astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attr); + line = CTLineCreateWithAttributedString(astr); + CGContextSetTextPosition(ctx, ax, f); + CTLineDraw(line, ctx); + CFRelease(line); + CFRelease(astr); + CFRelease(str); + + sprintf(t2, format, CheatFinderReadBytes(cfCurrentRAM, cfAddress[i])); + strcpy(t1, " "); + t1[11 - strlen(t2)] = 0; + strcat(t1, t2); + str = CFStringCreateWithCString(kCFAllocatorDefault, t1, MAC_PATH_ENCODING); + astr = CFAttributedStringCreate(kCFAllocatorDefault, str, attr); + line = CTLineCreateWithAttributedString(astr); + CGContextSetTextPosition(ctx, vx, f); + CTLineDraw(line, ctx); + CFRelease(line); + CFRelease(astr); + CFRelease(str); + + CGContextScaleCTM(ctx, 1, -1); + + if (i == val) + { + CFRelease(attr); + attr = CFDictionaryCreate(kCFAllocatorDefault, (const void **) &keys, (const void **) &bval, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + } + + y += myData->lineSize.height; + lineBounds.origin.y += myData->lineSize.height; + } + + CFRelease(attr); + } +#ifdef MAC_TIGER_PANTHER_SUPPORT + else + { + static Rect aRect = { 0, 0, 0, 0 }, vRect = { 0, 0, 0, 0 }; + + OSStatus err; + ATSUTextLayout layout; + HIRect lineBounds; + UniCharCount runLength[1], len; + SInt32 start, end, val, max; + Fixed ax, vx, f; + float y; + UniChar unistr[64]; + char format[32], t1[64], t2[64]; + + ATSUAttributeTag theTags[] = { kATSUCGContextTag }; + ByteCount theSizes[] = { sizeof(CGContextRef) }; + ATSUAttributeValuePtr theValues[] = { &ctx }; + + CheatFinderMakeValueFormat(format); + + start = (SInt32) (myData->originPoint.y / myData->lineSize.height); + end = (SInt32) ((myData->originPoint.y + bounds->size.height) / myData->lineSize.height) + 1; + + y = start * myData->lineSize.height - myData->originPoint.y; + + lineBounds = *bounds; + lineBounds.size.height = myData->lineSize.height; + lineBounds.origin.y = y; + + val = GetControl32BitValue(myData->view) - 1; + max = GetControl32BitMaximum(myData->view); + + if (init) + { + f = Long2Fix(0); + for (unsigned int n = 0; n < 11; n++) + unistr[n] = 'F'; + + len = runLength[0] = 6; + err = ATSUCreateTextLayoutWithTextPtr(unistr, kATSUFromTextBeginning, kATSUToTextEnd, len, 1, runLength, &cfListLineATSUStyle, &layout); + err = ATSUSetLayoutControls(layout, sizeof(theTags) / sizeof(theTags[0]), theTags, theSizes, theValues); + err = ATSUMeasureTextImage(layout, kATSUFromTextBeginning, kATSUToTextEnd, f, f, &aRect); + err = ATSUDisposeTextLayout(layout); + + len = runLength[0] = 11; + err = ATSUCreateTextLayoutWithTextPtr(unistr, kATSUFromTextBeginning, kATSUToTextEnd, len, 1, runLength, &cfListLineATSUStyle, &layout); + err = ATSUSetLayoutControls(layout, sizeof(theTags) / sizeof(theTags[0]), theTags, theSizes, theValues); + err = ATSUMeasureTextImage(layout, kATSUFromTextBeginning, kATSUToTextEnd, f, f, &vRect); + err = ATSUDisposeTextLayout(layout); + + init = false; + } + + ax = Long2Fix((cfListAddrColumnWidth - 2 - (aRect.right - aRect.left)) >> 1); + vx = Long2Fix((int) (lineBounds.origin.x + lineBounds.size.width) - (vRect.right - vRect.left) - 13); + + for (int i = start; i <= end; i++) + { + if ((i == val) && cfNumRows) + CGContextSetRGBFillColor(ctx, 59.0f / 256.0f, 124.0f / 256.0f, 212.0f / 256.0f, 1.0f); + else + if ((i - start) % 2 == 0) + CGContextSetRGBFillColor(ctx, 256.0f / 256.0f, 256.0f / 256.0f, 256.0f / 256.0f, 1.0f); + else + CGContextSetRGBFillColor(ctx, 237.0f / 256.0f, 244.0f / 256.0f, 254.0f / 256.0f, 1.0f); + + CGContextFillRect(ctx, lineBounds); + + if (i < max) + { + CGContextScaleCTM(ctx, 1, -1); + + if (i == val) + CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f); + else + CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); + + f = Long2Fix(-((int) y + 12)); + + sprintf(t1, "%06lX", cfAddress[i] + 0x7E0000); + len = runLength[0] = strlen(t1); + for (unsigned int n = 0; n < len; n++) + unistr[n] = t1[n]; + err = ATSUCreateTextLayoutWithTextPtr(unistr, kATSUFromTextBeginning, kATSUToTextEnd, len, 1, runLength, &cfListLineATSUStyle, &layout); + err = ATSUSetLayoutControls(layout, sizeof(theTags) / sizeof(theTags[0]), theTags, theSizes, theValues); + err = ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd, ax, f); + err = ATSUDisposeTextLayout(layout); + + sprintf(t2, format, CheatFinderReadBytes(cfCurrentRAM, cfAddress[i])); + strcpy(t1, " "); + t1[11 - strlen(t2)] = 0; + strcat(t1, t2); + len = runLength[0] = strlen(t1); + for (unsigned int n = 0; n < len; n++) + unistr[n] = t1[n]; + err = ATSUCreateTextLayoutWithTextPtr(unistr, kATSUFromTextBeginning, kATSUToTextEnd, len, 1, runLength, &cfListLineATSUStyle, &layout); + err = ATSUSetLayoutControls(layout, sizeof(theTags) / sizeof(theTags[0]), theTags, theSizes, theValues); + err = ATSUDrawText(layout, kATSUFromTextBeginning, kATSUToTextEnd, vx, f); + err = ATSUDisposeTextLayout(layout); + + CGContextScaleCTM(ctx, 1, -1); + } + + y += myData->lineSize.height; + lineBounds.origin.y += myData->lineSize.height; + } + } +#endif +} + +static HIViewPartCode CheatFinderListViewFindPart (EventRef inEvent, ListViewData *myData, SInt32 *whichLine) +{ + OSStatus err; + HIViewPartCode part; + HIPoint hipt; + SInt32 start, line; + float y; + + part = kControlNoPart; + + start = (SInt32) (myData->originPoint.y / myData->lineSize.height); + y = start * myData->lineSize.height - myData->originPoint.y; + + err = GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(hipt), NULL, &hipt); + if (err == noErr) + { + line = start + (SInt32) ((hipt.y - y - 1) / myData->lineSize.height) + 1; + + if (line <= GetControl32BitMaximum(myData->view)) + part = kControlListLinePart; + + if (whichLine != NULL) + *whichLine = line; + } + + return (part); +} + +static float CheatFinderListViewSanityCheck (float where, ListViewData *myData) +{ + HIRect bounds; + HISize imageSize; + + HIViewGetBounds(myData->view, &bounds); + imageSize = myData->lineSize; + imageSize.height *= GetControl32BitMaximum(myData->view); + + if (where + bounds.size.height > imageSize.height) + where = imageSize.height - bounds.size.height; + if (where < 0) + where = 0; + + return (where); +} + +static void CheatFinderListViewScrollToThere (float where, ListViewData *myData) +{ + OSStatus err; + EventRef theEvent; + HIPoint whereP = { 0.0f, where }; + + err = CreateEvent(kCFAllocatorDefault, kEventCheatFinderList, kEventScrollableScrollThere, GetCurrentEventTime(), kEventAttributeUserEvent, &theEvent); + if (err == noErr) + { + err = SetEventParameter(theEvent, kEventParamOrigin, typeHIPoint, sizeof(whereP), &whereP); + if (err == noErr) + err = SendEventToEventTarget(theEvent, GetControlEventTarget(myData->view)); + + ReleaseEvent(theEvent); + } +} + +static pascal OSStatus CheatFinderListViewHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + ListViewData *myData = (ListViewData *) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassHIObject: + { + switch (GetEventKind(inEvent)) + { + case kEventHIObjectConstruct: + { + ListViewData *data; + + data = (ListViewData *) calloc(1, sizeof(ListViewData)); + if (data) + { + HIViewRef epView; + + err = GetEventParameter(inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL, sizeof(epView), NULL, &epView); + if (err == noErr) + { + data->view = epView; + data->originPoint.x = 0.0f; + data->originPoint.y = 0.0f; + data->lineSize.width = 0.0f; + data->lineSize.height = 16.0f; + data->inFocus = false; + + SetControlID(epView, &kCheatFinderListViewID); + + result = SetEventParameter(inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof(data), &data); + } + } + + break; + } + + case kEventHIObjectDestruct: + { + if (myData) + free(myData); + + result = noErr; + break; + } + + case kEventHIObjectInitialize: + { + result = CallNextEventHandler(inHandlerCallRef, inEvent); + break; + } + } + + break; + } + + case kEventClassScrollable: + { + switch (GetEventKind(inEvent)) + { + case kEventScrollableGetInfo: + { + HIRect bounds; + HISize imageSize; + + HIViewGetBounds(myData->view, &bounds); + imageSize = myData->lineSize; + imageSize.height *= GetControl32BitMaximum(myData->view); + + err = SetEventParameter(inEvent, kEventParamImageSize, typeHISize, sizeof(imageSize), &imageSize); + err = SetEventParameter(inEvent, kEventParamViewSize, typeHISize, sizeof(bounds.size), &bounds.size); + err = SetEventParameter(inEvent, kEventParamLineSize, typeHISize, sizeof(myData->lineSize), &myData->lineSize); + err = SetEventParameter(inEvent, kEventParamOrigin, typeHIPoint, sizeof(myData->originPoint), &myData->originPoint); + + result = noErr; + break; + } + + case kEventScrollableScrollTo: + { + HIPoint where; + + err = GetEventParameter(inEvent, kEventParamOrigin, typeHIPoint, NULL, sizeof(where), NULL, &where); + if (err == noErr) + { + where.y = CheatFinderListViewSanityCheck(where.y, myData); + if ((int) myData->originPoint.y == (int) where.y) + break; + myData->originPoint.y = where.y; + + HIViewSetNeedsDisplay(myData->view, true); + } + + break; + } + } + + break; + } + + case kEventCheatFinderList: + { + switch (GetEventKind(inEvent)) + { + case kEventScrollableScrollThere: + { + HIPoint where; + + err = GetEventParameter(inEvent, kEventParamOrigin, typeHIPoint, NULL, sizeof(where), NULL, &where); + if (err == noErr) + { + where.y = CheatFinderListViewSanityCheck(where.y, myData); + if ((int) myData->originPoint.y != (int) where.y) + { + myData->originPoint.y = where.y; + SetControl32BitValue(HIViewGetNextView(myData->view), (SInt32) myData->originPoint.y); + + HIViewSetNeedsDisplay(myData->view, true); + } + } + + break; + } + } + + break; + } + + case kEventClassControl: + { + switch (GetEventKind(inEvent)) + { + case kEventControlDraw: + { + CGContextRef ctx; + + err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(ctx), NULL, &ctx); + if (err == noErr) + { + HIRect bounds; + + HIViewGetBounds(myData->view, &bounds); + + CGContextSaveGState(ctx); + CheatFinderListViewDraw(ctx, &bounds, myData); + CGContextRestoreGState(ctx); + + result = noErr; + } + + break; + } + + case kEventControlHitTest: + { + HIViewPartCode part; + + part = CheatFinderListViewFindPart(inEvent, myData, NULL); + + result = SetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, sizeof(part), &part); + + break; + } + + case kEventControlTrack: + { + MouseTrackingResult trackResult; + WindowRef window; + HIViewRef contentView; + HIViewPartCode part; + HIRect frame; + SInt32 whichLine = 0; + + part = CheatFinderListViewFindPart(inEvent, myData, &whichLine); + if (part == kControlListLinePart) + SetControl32BitValue(myData->view, whichLine); + + window = GetControlOwner(myData->view); + + HIViewFindByID(HIViewGetRoot(window), kHIViewWindowContentID, &contentView); + HIViewGetFrame(myData->view, &frame); + HIViewConvertRect(&frame, myData->view, contentView); + + HIPoint hipt; + #ifdef MAC_TIGER_PANTHER_SUPPORT + CGrafPtr oldPort; + Point qdpt; + Boolean portChanged = false; + + if (systemVersion < 0x1050) + portChanged = QDSwapPort(GetWindowPort(window), &oldPort); + #endif + + if (systemVersion >= 0x1050) + err = HIViewTrackMouseLocation(contentView, 0, kEventDurationForever, 0, NULL, &hipt, NULL, NULL, &trackResult); + #ifdef MAC_TIGER_PANTHER_SUPPORT + else + TrackMouseLocation(NULL, &qdpt, &trackResult); + #endif + + while (trackResult != kMouseTrackingMouseUp) + { + SInt32 start, line = 0; + float y; + + start = (SInt32) (myData->originPoint.y / myData->lineSize.height); + y = start * myData->lineSize.height - myData->originPoint.y; + + if (systemVersion >= 0x1050) + { + line = (SInt32) ((hipt.y - frame.origin.y - y - 1) / myData->lineSize.height) + 1; + if (hipt.y < frame.origin.y) + line--; + } + #ifdef MAC_TIGER_PANTHER_SUPPORT + else + { + line = (SInt32) ((qdpt.v - frame.origin.y - y - 1) / myData->lineSize.height) + 1; + if (qdpt.v < frame.origin.y) + line--; + } + #endif + line += start; + + if (line != whichLine) + { + whichLine = line; + SetControl32BitValue(myData->view, whichLine); + + SInt32 goThere = -1; + + if (whichLine <= start) + goThere = whichLine - 1; + else + if (whichLine >= start + (SInt32) (frame.size.height / myData->lineSize.height) + 1) + goThere = whichLine - (SInt32) (frame.size.height / myData->lineSize.height) - 1; + + if (goThere != -1) + { + float where; + + where = goThere * myData->lineSize.height; + where = CheatFinderListViewSanityCheck(where, myData); + if ((int) where != (int) myData->originPoint.y) + CheatFinderListViewScrollToThere(where, myData); + } + } + + if (systemVersion >= 0x1050) + err = HIViewTrackMouseLocation(contentView, 0, kEventDurationForever, 0, NULL, &hipt, NULL, NULL, &trackResult); + #ifdef MAC_TIGER_PANTHER_SUPPORT + else + TrackMouseLocation(NULL, &qdpt, &trackResult); + #endif + } + + #ifdef MAC_TIGER_PANTHER_SUPPORT + if (systemVersion < 0x1050) + { + if (portChanged) + QDSwapPort(oldPort, NULL); + } + #endif + + err = SetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, sizeof(part), &part); + + cfListSelection = GetControl32BitValue(myData->view) - 1; + + result = noErr; + break; + } + + case kEventControlValueFieldChanged: + { + EventRef theEvent; + + myData->originPoint.y = CheatFinderListViewSanityCheck(myData->originPoint.y, myData); + + err = CreateEvent(kCFAllocatorDefault, kEventClassScrollable, kEventScrollableInfoChanged, GetCurrentEventTime(), kEventAttributeUserEvent, &theEvent); + if (err == noErr) + { + err = SendEventToEventTarget(theEvent, GetControlEventTarget(myData->view)); + ReleaseEvent(theEvent); + + HIViewSetNeedsDisplay(myData->view, true); + } + + break; + } + } + + break; + } + } + + return (result); +} diff --git a/macosx/mac-cheatfinder.h b/macosx/mac-cheatfinder.h new file mode 100644 index 00000000..536b530c --- /dev/null +++ b/macosx/mac-cheatfinder.h @@ -0,0 +1,202 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_cheatfinder_h_ +#define _mac_cheatfinder_h_ + +extern Boolean cfIsWatching; + +void CheatFinder (void); +void InitCheatFinder (void); +void ResetCheatFinder (void); +void DeinitCheatFinder (void); +void CheatFinderDrawWatchAddr (void); + +#endif diff --git a/macosx/mac-client.cpp b/macosx/mac-client.cpp new file mode 100644 index 00000000..0afbd354 --- /dev/null +++ b/macosx/mac-client.cpp @@ -0,0 +1,1456 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "apu.h" +#include "snapshot.h" +#include "cheats.h" +#include "display.h" + +#include +#include +#include + +#include "mac-prefix.h" +#include "mac-cart.h" +#include "mac-cheatfinder.h" +#include "mac-controls.h" +#include "mac-dialog.h" +#include "mac-file.h" +#include "mac-joypad.h" +#include "mac-keyboard.h" +#include "mac-os.h" +#include "mac-snes9x.h" +#include "mac-stringtools.h" +#include "mac-netplay.h" +#include "mac-client.h" + +#ifdef SELF_TEST +#include +#endif + +#define KeyIsPressed(km, k) (1 & (((unsigned char *) km) [(k) >> 3] >> ((k) & 7))) + +enum +{ + kNPCDialogNone, + kNPCDialogInit, + kNPCDialogConnect, + kNPCDialogConnectFailed, + kNPCDialogOpenBegin, + kNPCDialogOpenEnd, + kNPCDialogPrepare, + kNPCDialogPrepareFailed, + kNPCDialogShowList, + kNPCDialogDone, + kNPCDialogCancel +}; + +typedef struct +{ + volatile bool8 padloop; + volatile bool8 exitsgn; + volatile uint32 phasecount; + volatile uint32 phasespan; + volatile uint8 header; + bool8 online; + int socket; + int numplayers; + char name[256]; + char serverIP[256]; + + int savedDeviceSetting; + int savedAutoSaveDelay; + + bool8 configsaved; + bool8 dialogcancel; + bool8 dialogsheet; + int dialogprocess; +} clientState; + +typedef struct +{ + bool8 ready; + int player; + char name[256]; +} clientsInfo; + +typedef struct +{ + uint32 crc32; + int input; + int length; + char fname[PATH_MAX + 1]; +} cROMInfo; + +static char n_csememu[] = "/tmp/s9x_c_emu_semaphore", + n_csempad[] = "/tmp/s9x_c_pad_semaphore"; + +static clientState npclient; +static clientsInfo npcinfo[NP_MAX_PLAYERS]; + +static cROMInfo nprominfo; + +static uint32 npcactvpad[NP_MAX_PLAYERS][64], // [player number] + npcrecvpad[NP_MAX_PLAYERS][64], // [player number] + npcsendpad[64], + npccachpad[64]; + +static WindowRef mRef, sRef; +static sem_t *csememu, *csempad; +static pthread_t connectthread, preparethread, gamepadthread; + +static int NPClientGetMesFromServer (void); +static void NPClientDetachConnectThread (void); +static void NPClientDetachPrepareThread (void); +static void NPClientBeginPlayerListSheet (void); +static void NPClientEndPlayerListSheet (void); +static bool8 NPClientConnectToServer (int); +static bool8 NPClientSendMesToServer (int); +static bool8 NPClientSendNameToServer (void); +static bool8 NPClientGetROMInfoFromServer (void); +static bool8 NPClientBeginOpenROMImage (WindowRef); +static bool8 NPClientEndOpenROMImage (void); +static bool8 NPClientROMReadyToServer (void); +static bool8 NPClientGetSRAMFromServer (void); +static bool8 NPClientGetPlayerListFromServer (void); +static bool8 NPClientReplyPhaseSpanTest (void); +static void * NPClientConnectThread (void *); +static void * NPClientPrepareThread (void *); +static void * NPClientNetPlayThread (void *); +static pascal void NPClientDialogTimerHandler (EventLoopTimerRef, void *); +static pascal OSStatus NPClientDialogEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus NPClientSheetEventHandler (EventHandlerCallRef, EventRef, void *); + + +bool8 NPClientDialog (void) +{ + OSStatus err; + IBNibRef nibRef; + + npclient.dialogcancel = true; + npclient.dialogsheet = false; + npclient.configsaved = false; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + err = CreateWindowFromNib(nibRef, CFSTR("Connect"), &mRef); + if (err == noErr) + { + err = CreateWindowFromNib(nibRef, CFSTR("PlayerList"), &sRef); + if (err == noErr) + { + EventHandlerRef eref, seref; + EventLoopTimerRef tref; + EventHandlerUPP eventUPP, sheetUPP; + EventLoopTimerUPP timerUPP; + EventTypeSpec windowEvents[] = { { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }; + CFStringRef ref; + HIViewRef ctl, root; + HIViewID cid; + + npclient.dialogprocess = kNPCDialogInit; + + eventUPP = NewEventHandlerUPP(NPClientDialogEventHandler); + err = InstallWindowEventHandler(mRef, eventUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) mRef, &eref); + + timerUPP = NewEventLoopTimerUPP(NPClientDialogTimerHandler); + err = InstallEventLoopTimer(GetCurrentEventLoop(), 0.0f, 0.1f, timerUPP, (void *) mRef, &tref); + + sheetUPP = NewEventHandlerUPP(NPClientSheetEventHandler); + err = InstallWindowEventHandler(sRef, sheetUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) sRef, &seref); + + root = HIViewGetRoot(mRef); + cid.id = 0; + + cid.signature = 'CHAS'; + HIViewFindByID(root, cid, &ctl); + HIViewSetVisible(ctl, false); + + cid.signature = 'SVIP'; + HIViewFindByID(root, cid, &ctl); + SetEditTextCStr(ctl, npServerIP, false); + + cid.signature = 'CLNM'; + HIViewFindByID(root, cid, &ctl); + ref = CFStringCreateWithCString(kCFAllocatorDefault, npName, MAC_PATH_ENCODING); + if (ref) + { + SetEditTextCFString(ctl, ref, false); + CFRelease(ref); + } + else + SetEditTextCFString(ctl, CFSTR("unknown"), false); + + MoveWindowPosition(mRef, kWindowClient, false); + ShowWindow(mRef); + err = HIViewAdvanceFocus(root, 0); + err = RunAppModalLoopForWindow(mRef); + HideWindow(mRef); + SaveWindowPosition(mRef, kWindowClient); + + err = RemoveEventHandler(seref); + DisposeEventHandlerUPP(sheetUPP); + + err = RemoveEventLoopTimer(tref); + DisposeEventLoopTimerUPP(timerUPP); + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eventUPP); + + CFRelease(sRef); + } + + CFRelease(mRef); + } + + DisposeNibReference(nibRef); + } + + return (!npclient.dialogcancel); +} + +static pascal OSStatus NPClientDialogEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + + switch (GetEventClass(inEvent)) + { + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(false); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + switch (tHICommand.commandID) + { + case 'OK__': + CFStringRef ref; + HIViewRef ctl, root; + HIViewID cid; + + root = HIViewGetRoot(mRef); + cid.id = 0; + + cid.signature = 'SVIP'; + HIViewFindByID(root, cid, &ctl); + GetEditTextCStr(ctl, npclient.serverIP); + DeactivateControl(ctl); + if (npclient.serverIP[0] == 0) + strcpy(npclient.serverIP, "127.0.0.1"); + strcpy(npServerIP, npclient.serverIP); + printf("%s\n", npServerIP); + + cid.signature = 'CLNM'; + HIViewFindByID(root, cid, &ctl); + CopyEditTextCFString(ctl, &ref); + DeactivateControl(ctl); + if (ref) + { + Boolean r; + + r = CFStringGetCString(ref, npclient.name, 256, MAC_PATH_ENCODING); + if (!r) + strcpy(npclient.name, "unknown"); + else + if (npclient.name[0] == 0) + strcpy(npclient.name, "Guest"); + + CFRelease(ref); + } + else + strcpy(npclient.name, "unknown"); + strcpy(npName, npclient.name); + printf("%s\n", npName); + + cid.signature = 'OK__'; + HIViewFindByID(root, cid, &ctl); + DeactivateControl(ctl); + + cid.signature = 'NOT_'; + HIViewFindByID(root, cid, &ctl); + DeactivateControl(ctl); + + npclient.dialogcancel = false; + npclient.dialogprocess = kNPCDialogConnect; + + result = noErr; + break; + + case 'NOT_': + npclient.dialogcancel = true; + npclient.dialogprocess = kNPCDialogCancel; + + result = noErr; + break; + + case 'NvDn': + npclient.dialogcancel = false; + npclient.dialogprocess = kNPCDialogOpenEnd; + + result = noErr; + break; + } + } + + break; + } + + break; + } + + return (result); +} + +static pascal void NPClientDialogTimerHandler (EventLoopTimerRef inTimer, void *userData) +{ + WindowRef window = (WindowRef) userData; + HIViewRef ctl; + HIViewID cid = { 'CHAS', 0 }; + + HIViewFindByID(HIViewGetRoot(mRef), cid, &ctl); + + switch (npclient.dialogprocess) + { + case kNPCDialogNone: + break; + + case kNPCDialogCancel: + NPNotification(" kNPCDialogCancel", -1); + npclient.dialogprocess = kNPCDialogNone; + npclient.dialogcancel = true; + QuitAppModalLoopForWindow(mRef); + break; + + case kNPCDialogInit: + NPNotification(" kNPCDialogInit", -1); + npclient.dialogprocess = kNPCDialogNone; + break; + + case kNPCDialogConnect: + NPNotification(" kNPCDialogConnect", -1); + npclient.dialogprocess = kNPCDialogNone; + HIViewSetVisible(ctl, true); + NPClientDetachConnectThread(); + break; + + case kNPCDialogConnectFailed: + NPNotification(" kNPCDialogConnectFailed", -1); + npclient.dialogprocess = kNPCDialogNone; + npclient.dialogcancel = true; + QuitAppModalLoopForWindow(mRef); + break; + + case kNPCDialogOpenBegin: + NPNotification(" kNPCDialogOpenBegin", -1); + npclient.dialogprocess = kNPCDialogNone; + HIViewSetVisible(ctl, false); + NPClientStoreConfig(); + if (!NPClientBeginOpenROMImage(window)) + { + NPClientDisconnect(); + NPClientRestoreConfig(); + npclient.dialogprocess = kNPCDialogCancel; + } + + break; + + case kNPCDialogOpenEnd: + NPNotification(" kNPCDialogOpenEnd", -1); + npclient.dialogprocess = kNPCDialogNone; + if (!NPClientEndOpenROMImage()) + { + NPClientDisconnect(); + NPClientRestoreConfig(); + npclient.dialogprocess = kNPCDialogCancel; + } + else + npclient.dialogprocess = kNPCDialogPrepare; + + break; + + case kNPCDialogPrepare: + NPNotification(" kNPCDialogPrepare", -1); + npclient.dialogprocess = kNPCDialogNone; + HIViewSetVisible(ctl, true); + NPClientDetachPrepareThread(); + break; + + case kNPCDialogPrepareFailed: + NPNotification(" kNPCDialogPrepareFailed", -1); + npclient.dialogprocess = kNPCDialogNone; + NPClientRestoreConfig(); + npclient.dialogcancel = true; + QuitAppModalLoopForWindow(mRef); + break; + + case kNPCDialogShowList: + NPNotification(" kNPCDialogShowList", -1); + npclient.dialogprocess = kNPCDialogNone; + HIViewSetVisible(ctl, false); + npclient.dialogsheet = true; + NPClientBeginPlayerListSheet(); + break; + + case kNPCDialogDone: + NPNotification(" kNPCDialogDone", -1); + npclient.dialogprocess = kNPCDialogNone; + NPClientEndPlayerListSheet(); + npclient.dialogsheet = false; + npclient.dialogcancel = false; + QuitAppModalLoopForWindow(mRef); + break; + } +} + +static void NPClientDetachConnectThread (void) +{ + pthread_create(&connectthread, NULL, NPClientConnectThread, NULL); + pthread_detach(connectthread); +} + +static void * NPClientConnectThread (void *) +{ + NPNotification("Client: Entered connection thread.", -1); + + if ((NPClientConnectToServer(NP_PORT) == false) || + (NPClientSendNameToServer() == false) || + (NPClientGetROMInfoFromServer() == false)) + { + NPClientDisconnect(); + npclient.dialogprocess = kNPCDialogConnectFailed; + return (NULL); + } + + npclient.dialogprocess = kNPCDialogOpenBegin; + NPNotification("Client: Exited connection thread.", -1); + return (NULL); +} + +void NPClientInit (void) +{ + npclient.padloop = false; + npclient.exitsgn = false; + npclient.phasecount = 0; + npclient.phasespan = 0; + npclient.header = 0; + npclient.online = false; + npclient.socket = -1; + npclient.numplayers = 0; + npclient.name[0] = 0; + npclient.serverIP[0] = 0; + + nprominfo.crc32 = 0; + nprominfo.input = 0; + nprominfo.length = 0; + nprominfo.fname[0] = 0; + + for (int i = 0; i < NP_MAX_PLAYERS; i++) + { + for (int j = 0; j < 64; j++) + { + npcactvpad[i][j] = 0; + npcrecvpad[i][j] = 0; + } + } + + for (int j = 0; j < 64; j++) + { + npcsendpad[j] = 0; + npccachpad[j] = 0; + } + + for (int c = 0; c < NP_MAX_PLAYERS; c++) + { + npcinfo[c].ready = false; + npcinfo[c].player = 0; + npcinfo[c].name[0] = 0; + } +} + +static bool8 NPClientConnectToServer (int port) +{ +#ifndef SELF_TEST + struct sockaddr_in address; +#else + struct sockaddr_un address; +#endif + + NPNotification("Client: Connecting to server...", -1); + + memset(&address, 0, sizeof(address)); +#ifndef SELF_TEST + address.sin_family = AF_INET; + address.sin_addr.s_addr = inet_addr(npclient.serverIP); + address.sin_port = htons(port); +#else + address.sun_family = AF_UNIX; + strcpy(address.sun_path, SOCK_NAME); +#endif + +#ifndef SELF_TEST + if (address.sin_addr.s_addr == INADDR_NONE) + { + NPError("Client: Server IP is invalid.", 5001); + return (false); + } +#endif + +#ifndef SELF_TEST + if ((npclient.socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) +#else + if ((npclient.socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) +#endif + { + NPError("Client: Failed to create socket.", 5002); + return (false); + } + + if (connect(npclient.socket, (struct sockaddr *) &address, sizeof(address)) < 0) + { + NPError("Client: Failed to connect to server.", 5003); + return (false); + } + + npclient.online = true; + + NPNotification("Client: Connected to server.", -1); + return (true); +} + +void NPClientDisconnect (void) +{ + if (npclient.socket != -1) + { + NPNotification("Client: Disconnecting from server...", -1); + + close(npclient.socket); + npclient.socket = -1; + + NPNotification("Client: Disconnected from server.", -1); + } + + npclient.online = false; + npclient.name[0] = 0; + npclient.serverIP[0] = 0; +} + +static bool8 NPClientSendMesToServer (int num) +{ + uint8 mes[2]; + + mes[0] = NP_CLIENT_MAGIC; + mes[1] = num; + + if (socket_write(npclient.socket, mes, 2) != 2) + return (false); + + return (true); +} + +static int NPClientGetMesFromServer (void) +{ + uint8 mes[2]; + + if (socket_read(npclient.socket, mes, 2) != 2) + return (-1); + + if (mes[0] != NP_SERVER_MAGIC) + return (-1); + + return ((int) mes[1]); +} + +static bool8 NPClientSendNameToServer (void) +{ + if (!npclient.online) + return (false); + + NPNotification("Client: Sending player name to server...", -1); + + if (NPClientGetMesFromServer() != kNPServerNameRequest) + { + NPError("Client: Failed to receive messsage from server.", 5101); + return (false); + } + + uint8 mes[4]; + uint32 l; + + l = strlen(npclient.name); + WRITE_LONG(mes + 0, l); + + if (socket_write(npclient.socket, mes, 4) != 4) + { + NPError("Client: Failed to send name size to server.", 5102); + return (false); + } + + if (socket_write(npclient.socket, (uint8 *) npclient.name, l) != (int) l) + { + NPError("Client: Failed to send name to server.", 5103); + return (false); + } + + if (NPClientGetMesFromServer() != kNPServerNameReceived) + { + NPError("Client: Failed to receive messsage from server.", 5104); + return (false); + } + + if (NPClientSendMesToServer(kNPClientNameSent) == false) + { + NPError("Client: Failed to send messsage to server.", 5105); + return (false); + } + + NPNotification("Client: Sent player name to server.", -1); + return (true); +} + +static bool8 NPClientGetROMInfoFromServer (void) +{ + if (!npclient.online) + return (false); + + NPNotification("Client: Receiving ROM information from server...", -1); + + if (NPClientGetMesFromServer() != kNPServerROMInfoWillSend) + { + NPError("Client: Failed to receive messsage from server.", 5201); + return (false); + } + + if (NPClientSendMesToServer(kNPClientROMInfoWaiting) == false) + { + NPError("Client: Failed to send messsage to server.", 5202); + return (false); + } + + uint8 mes[16]; + uint32 l; + + if (socket_read(npclient.socket, mes, 16) != 16) + { + NPError("Client: Failed to receive ROM information from server.", 5203); + return (false); + } + + nprominfo.crc32 = READ_LONG(mes + 0); + nprominfo.input = READ_LONG(mes + 4); + + l = READ_LONG(mes + 12); + + if (socket_read(npclient.socket, (uint8 *) nprominfo.fname, l) != (int) l) + { + NPError("Client: Failed to receive ROM name from server.", 5204); + return (false); + } + + nprominfo.fname[l] = 0; + nprominfo.length = l; + + NPNotification("Client: Received ROM information from server.", -1); + return (true); +} + +void NPClientStoreConfig (void) +{ + npclient.savedDeviceSetting = deviceSetting; + npclient.savedAutoSaveDelay = Settings.AutoSaveDelay; + + npclient.configsaved = true; + + deviceSetting = nprominfo.input; + Settings.AutoSaveDelay = 0; + + ChangeInputDevice(); +} + +void NPClientRestoreConfig (void) +{ + if (npclient.configsaved) + { + deviceSetting = npclient.savedDeviceSetting; + Settings.AutoSaveDelay = npclient.savedAutoSaveDelay; + + npclient.configsaved = false; + + ChangeInputDevice(); + } +} + +static bool8 NPClientBeginOpenROMImage (WindowRef window) +{ + CFStringRef numRef, romRef, baseRef; + CFMutableStringRef mesRef; + SInt32 replaceAt; + bool8 r; + + DeinitGameWindow(); + + if (cartOpen) + { + SNES9X_SaveSRAM(); + S9xResetSaveTimer(false); + S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); + } + + cartOpen = false; + + ResetCheatFinder(); + + romRef = CFStringCreateWithCString(kCFAllocatorDefault, nprominfo.fname, MAC_PATH_ENCODING); + numRef = CFCopyLocalizedString(CFSTR("NPROMNamePos"), "1"); + baseRef = CFCopyLocalizedString(CFSTR("NPROMNameMes"), "NPROM"); + mesRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, baseRef); + replaceAt = CFStringGetIntValue(numRef); + CFStringReplace(mesRef, CFRangeMake(replaceAt - 1, 1), romRef); + + r = NavBeginOpenROMImageSheet(window, mesRef); + + CFRelease(mesRef); + CFRelease(baseRef); + CFRelease(numRef); + CFRelease(romRef); + + return (r); +} + +static bool8 NPClientEndOpenROMImage (void) +{ + OSStatus err; + FSCatalogInfo info; + FSRef cartRef; + char filename[PATH_MAX + 1]; + bool8 r; + + r = NavEndOpenROMImageSheet(&cartRef); + if (!r) + { + cartOpen = false; + return (false); + } + + err = FSGetCatalogInfo(&cartRef, kFSCatInfoVolume, &info, NULL, NULL, NULL); + lockedROMMedia = IsLockedMedia(info.volume); + + Settings.ForceLoROM = (romDetect == kLoROMForce ); + Settings.ForceHiROM = (romDetect == kHiROMForce ); + Settings.ForceHeader = (headerDetect == kHeaderForce ); + Settings.ForceNoHeader = (headerDetect == kNoHeaderForce ); + Settings.ForceInterleaved = (interleaveDetect == kInterleaveForce ); + Settings.ForceInterleaved2 = (interleaveDetect == kInterleave2Force ); + Settings.ForceInterleaveGD24 = (interleaveDetect == kInterleaveGD24 ); + Settings.ForceNotInterleaved = (interleaveDetect == kNoInterleaveForce); + Settings.ForcePAL = (videoDetect == kPALForce ); + Settings.ForceNTSC = (videoDetect == kNTSCForce ); + + GFX.InfoString = NULL; + GFX.InfoStringTimeout = 0; + + S9xResetSaveTimer(true); + + err = FSRefMakePath(&cartRef, (unsigned char *) filename, PATH_MAX); + + SNES9X_InitSound(); + + if (Memory.LoadROM(filename) /*&& (Memory.ROMCRC32 == nprominfo.crc32)*/) + { + ChangeTypeAndCreator(filename, 'CART', '~9X~'); + cartOpen = true; + return (true); + } + else + { + cartOpen = false; + return (false); + } +} + +static void NPClientDetachPrepareThread (void) +{ + pthread_create(&preparethread, NULL, NPClientPrepareThread, NULL); + pthread_detach(preparethread); +} + +static void * NPClientPrepareThread (void *) +{ + NPNotification("Client: Entered preparing thread.", -1); + + if ((NPClientROMReadyToServer() == false) || + (NPClientGetSRAMFromServer() == false) || + (NPClientGetPlayerListFromServer() == false) || + (NPClientReplyPhaseSpanTest() == false)) + { + NPClientDisconnect(); + npclient.dialogprocess = kNPCDialogPrepareFailed; + return (NULL); + } + + npclient.dialogprocess = kNPCDialogShowList; + NPNotification("Client: Exited preparing thread.", -1); + return (NULL); +} + +static bool8 NPClientROMReadyToServer (void) +{ + if (!npclient.online) + return (false); + + NPNotification("Client: Sending ROM ready sign to server...", -1); + + if (NPClientSendMesToServer(kNPClientROMOpened) == false) + { + NPError("Client: Failed to send messsage to server.", 5401); + return (false); + } + + NPNotification("Client: Sent ROM ready sign to server.", -1); + return (true); +} + +static bool8 NPClientGetSRAMFromServer (void) +{ + if (!npclient.online) + return (false); + + NPNotification("Client: Receiving SRAM from server...", -1); + + if (NPClientGetMesFromServer() != kNPServerSRAMWillSend) + { + NPError("Client: Failed to receive messsage from server.", 5501); + return (false); + } + + if (NPClientSendMesToServer(kNPClientSRAMWaiting) == false) + { + NPError("Client: Failed to send messsage to server.", 5502); + return (false); + } + + uint8 mes[4]; + uint32 sramsize; + + if (socket_read(npclient.socket, mes, 4) != 4) + { + NPError("Client: Failed to receive SRAM size from server.", 5503); + return (false); + } + + sramsize = READ_LONG(mes + 0); + + if (sramsize != (uint32) (Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0)) + { + NPError("Client: SRAM size mismatch.", 5504); + return (false); + } + + if (sramsize && (socket_read(npclient.socket, Memory.SRAM, sramsize) != (int) sramsize)) + { + NPError("Server: Failed to receive SRAM from server.", 5505); + return (false); + } + + if (NPClientSendMesToServer(kNPClientSRAMLoaded) == false) + { + NPError("Client: Failed to send messsage to server.", 5506); + return (false); + } + + NPNotification("Client: Received SRAM from server.", -1); + return (true); +} + +static bool8 NPClientGetPlayerListFromServer (void) +{ + if (!npclient.online) + return (false); + + NPNotification("Client: Receiving player list from server...", -1); + + if (NPClientGetMesFromServer() != kNPServerPlayerWillSend) + { + NPError("Client: Failed to receive messsage from server.", 5701); + return (false); + } + + if (NPClientSendMesToServer(kNPClientPlayerWaiting) == false) + { + NPError("Client: Failed to send messsage to server.", 5702); + return (false); + } + + for (int i = 0; i < NP_MAX_PLAYERS; i++) + { + uint8 mes[10]; + uint32 l; + + if (socket_read(npclient.socket, mes, 10) != 10) + { + NPError("Client: Failed to receive messsage from server.", 5703); + return (false); + } + + npcinfo[i].ready = READ_BYTE(mes + 1); + npcinfo[i].player = READ_LONG(mes + 2); + + l = READ_LONG(mes + 6); + + if (l && (socket_read(npclient.socket, (uint8 *) npcinfo[i].name, l) != (int) l)) + { + NPError("Client: Failed to receive messsage from server.", 5704); + return (false); + } + + npcinfo[i].name[l] = 0; + } + + npclient.numplayers = 0; + for (int i = 0; i < NP_MAX_PLAYERS; i++) + if (npcinfo[i].ready) + npclient.numplayers++; + + NPNotification("Client: Received player list from server.", -1); + NPNotification("Client: Number of players: %d", npclient.numplayers); + + return (true); +} + +static bool8 NPClientReplyPhaseSpanTest (void) +{ + uint8 mes[21]; + int l = npclient.numplayers * 4 + 1; + + NPNotification("Client: Replying sending / receiving pad states test...", -1); + + for (int n = 0; n < 5; n++) + { + if (socket_read(npclient.socket, mes, l) != l) + return (false); + + if (socket_write(npclient.socket, mes, 5) != 5) + return (false); + } + + NPNotification("Client: Replied sending / receiving pad states test.", -1); + + NPNotification("Client: Receiving phase span value from server...", -1); + + if (socket_read(npclient.socket, mes, 4) != 4) + return (false); + + npclient.phasespan = READ_LONG(mes + 0); + + NPNotification(" phase span: %d (frames)", npclient.phasespan); + + NPNotification("Client: Received phase span value from server.", -1); + + return (true); +} + +static void NPClientBeginPlayerListSheet (void) +{ + OSStatus err; + CFStringRef ref; + HIViewRef ctl, root; + HIViewID cid; + + root = HIViewGetRoot(sRef); + cid.signature = 'PLNM'; + + for (int i = 0; i < NP_MAX_PLAYERS; i++) + { + if (npcinfo[i].ready) + { + cid.id = npcinfo[i].player; + HIViewFindByID(root, cid, &ctl); + ref = CFStringCreateWithCString(kCFAllocatorDefault, npcinfo[i].name, MAC_PATH_ENCODING); + if (ref) + { + SetStaticTextCFString(ctl, ref, false); + CFRelease(ref); + } + else + SetStaticTextCFString(ctl, CFSTR("unknown"), false); + } + } + + err = ShowSheetWindow(sRef, mRef); +} + +static void NPClientEndPlayerListSheet (void) +{ + OSStatus err; + + err = HideSheetWindow(sRef); +} + +static pascal OSStatus NPClientSheetEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + if (!npclient.dialogsheet) + return (eventNotHandledErr); + + OSStatus err, result = eventNotHandledErr; + + switch (GetEventClass(inEvent)) + { + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(false); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + switch (tHICommand.commandID) + { + case 'ok ': + npclient.dialogprocess = kNPCDialogDone; + result = noErr; + break; + } + } + + break; + } + + break; + } + + return (result); +} + +void NPClientDetachNetPlayThread (void) +{ + NPNotification("Client: Detaching pad thread...", -1); + + npclient.padloop = true; + npclient.exitsgn = false; + + csememu = sem_open(n_csememu, O_CREAT, 0600, 0); + csempad = sem_open(n_csempad, O_CREAT, 0600, 0); + + pthread_create(&gamepadthread, NULL, NPClientNetPlayThread, NULL); + pthread_detach(gamepadthread); + + NPNotification("Client: Detached pad thread.", -1); +} + +void NPClientStopNetPlayThread (void) +{ + NPNotification("Client: Stopping pad thread...", -1); + + npclient.padloop = false; + sem_post(csempad); + sem_post(csememu); + + while (!npclient.exitsgn) + sleep(0); + + sem_unlink(n_csememu); + sem_unlink(n_csempad); + sem_close(csememu); + sem_close(csempad); + + NPNotification("Client: Stopped pad thread.", -1); +} + +bool8 NPClientNetPlayWaitStart (void) +{ + NPNotification("Client: Waiting start flag...", -1); + + if (NPClientSendMesToServer(kNPClientStartWait) == false) + { + NPError("Client: Failed to send messsage to server.", 5801); + return (false); + } + + if (NPClientGetMesFromServer() != kNPServerStart) + { + NPError("Client: Failed to send messsage to server.", 5802); + return (false); + } + + npclient.phasecount = 0; + npclient.header = 0; + + sem_post(csempad); + + NPNotification("Client: Netplay started.", -1); + return (true); +} + +static void * NPClientNetPlayThread (void *) +{ + uint8 mes[NP_MAX_PLAYERS * 64 * 4 + 1]; + uint8 count = 0; + int l; + + NPNotification("Client: Entered pad thread.", -1); + + while (npclient.padloop) + { + sem_wait(csempad); + + l = npclient.numplayers * npclient.phasespan * 4 + 1; + if (socket_read(npclient.socket, mes, l) != l) + { + npclient.exitsgn = true; + sem_post(csememu); + pthread_exit(NULL); + } + + if ((mes[0] & 0xF) != count) + NPNotification("Client: Warning: Failed to synchronize server.", -1); + + npclient.header = mes[0] & 0xF0; + + for (int i = 0; i < npclient.numplayers; i++) + for (uint32 j = 0; j < npclient.phasespan; j++) + npcrecvpad[i][j] = READ_LONG(mes + (i * npclient.phasespan + j) * 4 + 1); + + WRITE_BYTE(mes + 0, count); + + for (uint32 j = 0; j < npclient.phasespan; j++) + WRITE_LONG(mes + j * 4 + 1, npcsendpad[j]); + + l = npclient.phasespan * 4 + 1; + if (socket_write(npclient.socket, mes, l) != l) + { + npclient.exitsgn = true; + sem_post(csememu); + pthread_exit(NULL); + } + + count = (count + 1) & 0xF; + + sem_post(csememu); + } + + npclient.exitsgn = true; + + NPNotification("Client: Exited pad thread.", -1); + return (NULL); +} + +void NPClientProcessInput (void) +{ + static uint32 pos = 0; + KeyMap myKeys; + + if (npclient.exitsgn) + { + if (s9xthreadrunning) + { + if (!eventQueued) + { + PostQueueToSubEventLoop(); + eventQueued = true; + } + } + else + running = false; + + return; + } + + if (npclient.phasecount == 0) + { + sem_wait(csememu); + + for (int i = 0; i < npclient.numplayers; i++) + for (uint32 j = 0; j < npclient.phasespan; j++) + npcactvpad[i][j] = npcrecvpad[i][j]; + + for (uint32 j = 0; j < npclient.phasespan; j++) + npcsendpad[j] = npccachpad[j]; + + if (npclient.header & 0x80) + { + npcsendpad[npclient.phasespan] = 0; + for (int i = 0; i < npclient.numplayers; i++) + npcactvpad[i][npclient.phasespan] = 0; + + npclient.phasespan++; + if (npclient.phasespan > (uint32) Memory.ROMFramesPerSecond) + npclient.phasespan = (uint32) Memory.ROMFramesPerSecond; + + char str[256]; + sprintf(str, "delay: %d", npclient.phasespan); + S9xMessage(0, 0, str); + } + else + if (npclient.header & 0x40) + { + npclient.phasespan--; + if (npclient.phasespan == 0) + npclient.phasespan = 1; + + char str[256]; + sprintf(str, "delay: %d", npclient.phasespan); + S9xMessage(0, 0, str); + } + + npclient.header = 0; + pos = 0; + } + + for (int i = 0; i < npclient.numplayers; i++) + { + controlPad[i] = npcactvpad[i][pos]; + ControlPadFlagsToS9xReportButtons(i, controlPad[i]); + } + + GetKeys(myKeys); + + uint32 pad = 0; + + JoypadScanDirection(0, &pad); + if (ISpKeyIsPressed(kISp1PR )) pad |= 0x0010; + if (ISpKeyIsPressed(kISp1PL )) pad |= 0x0020; + if (ISpKeyIsPressed(kISp1PX )) pad |= 0x0040; + if (ISpKeyIsPressed(kISp1PA )) pad |= 0x0080; + if (ISpKeyIsPressed(kISp1PStart )) pad |= 0x1000; + if (ISpKeyIsPressed(kISp1PSelect)) pad |= 0x2000; + if (ISpKeyIsPressed(kISp1PY )) pad |= 0x4000; + if (ISpKeyIsPressed(kISp1PB )) pad |= 0x8000; + + if (KeyIsPressed(myKeys, keyCode[k1PR] )) pad |= 0x0010; + if (KeyIsPressed(myKeys, keyCode[k1PL] )) pad |= 0x0020; + if (KeyIsPressed(myKeys, keyCode[k1PX] )) pad |= 0x0040; + if (KeyIsPressed(myKeys, keyCode[k1PA] )) pad |= 0x0080; + if (KeyIsPressed(myKeys, keyCode[k1PRight] )) pad |= 0x0100; + if (KeyIsPressed(myKeys, keyCode[k1PLeft] )) pad |= 0x0200; + if (KeyIsPressed(myKeys, keyCode[k1PDown] )) pad |= 0x0400; + if (KeyIsPressed(myKeys, keyCode[k1PUp] )) pad |= 0x0800; + if (KeyIsPressed(myKeys, keyCode[k1PStart] )) pad |= 0x1000; + if (KeyIsPressed(myKeys, keyCode[k1PSelect])) pad |= 0x2000; + if (KeyIsPressed(myKeys, keyCode[k1PY] )) pad |= 0x4000; + if (KeyIsPressed(myKeys, keyCode[k1PB] )) pad |= 0x8000; + + npccachpad[pos] = pad; + + if (npclient.phasecount == 0) + { + npclient.phasecount = npclient.phasespan; + sem_post(csempad); + } + + npclient.phasecount--; + pos++; +} diff --git a/macosx/mac-client.h b/macosx/mac-client.h new file mode 100644 index 00000000..20d2fae0 --- /dev/null +++ b/macosx/mac-client.h @@ -0,0 +1,204 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_client_h_ +#define _mac_client_h_ + +void NPClientInit (void); +void NPClientDisconnect (void); +void NPClientStoreConfig (void); +void NPClientRestoreConfig (void); +void NPClientDetachNetPlayThread (void); +void NPClientStopNetPlayThread (void); +void NPClientProcessInput (void); +bool8 NPClientNetPlayWaitStart (void); +bool8 NPClientDialog (void); + +#endif diff --git a/macosx/mac-cocoatools.h b/macosx/mac-cocoatools.h new file mode 100644 index 00000000..59a4531a --- /dev/null +++ b/macosx/mac-cocoatools.h @@ -0,0 +1,196 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_cocoatools_h_ +#define _mac_cocoatools_h_ + +void CocoaPlayFreezeDefrostSound (void); + +#endif diff --git a/macosx/mac-cocoatools.mm b/macosx/mac-cocoatools.mm new file mode 100644 index 00000000..ee045bb1 --- /dev/null +++ b/macosx/mac-cocoatools.mm @@ -0,0 +1,219 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#import + +#import "mac-cocoatools.h" + + +void CocoaPlayFreezeDefrostSound (void) +{ + NSAutoreleasePool *pool; + NSBundle *bundle; + NSString *path; + NSSound *sound; + BOOL r; + + pool = [[NSAutoreleasePool alloc] init]; + + bundle = [NSBundle mainBundle]; + path = [bundle pathForSoundResource: @"freeze_defrost"]; + if (path) + { + sound = [[NSSound alloc] initWithContentsOfFile: path byReference: YES]; + if (sound) + { + r = [sound play]; + [sound release]; + } + } + + [pool release]; +} diff --git a/macosx/mac-controls.cpp b/macosx/mac-controls.cpp new file mode 100644 index 00000000..919fb7c9 --- /dev/null +++ b/macosx/mac-controls.cpp @@ -0,0 +1,482 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "port.h" +#include "controls.h" + +#include "mac-prefix.h" +#include "mac-joypad.h" +#include "mac-keyboard.h" +#include "mac-os.h" +#include "mac-controls.h" + +#define ASSIGN_BUTTONf(n, s) S9xMapButton (n, cmd = S9xGetCommandT(s), false) +#define ASSIGN_BUTTONt(n, s) S9xMapButton (n, cmd = S9xGetCommandT(s), true) +#define ASSIGN_POINTRf(n, s) S9xMapPointer(n, cmd = S9xGetCommandT(s), false) +#define ASSIGN_POINTRt(n, s) S9xMapPointer(n, cmd = S9xGetCommandT(s), true) + +#define KeyIsPressed(km, k) (1 & (((unsigned char *) km) [(k) >> 3] >> ((k) & 7))) + + +void S9xSetupDefaultKeymap (void) +{ + s9xcommand_t cmd; + + ASSIGN_BUTTONf(kMacCMapPad1PX, "Joypad1 X"); + ASSIGN_BUTTONf(kMacCMapPad1PA, "Joypad1 A"); + ASSIGN_BUTTONf(kMacCMapPad1PB, "Joypad1 B"); + ASSIGN_BUTTONf(kMacCMapPad1PY, "Joypad1 Y"); + ASSIGN_BUTTONf(kMacCMapPad1PL, "Joypad1 L"); + ASSIGN_BUTTONf(kMacCMapPad1PR, "Joypad1 R"); + ASSIGN_BUTTONf(kMacCMapPad1PSelect, "Joypad1 Select"); + ASSIGN_BUTTONf(kMacCMapPad1PStart, "Joypad1 Start"); + ASSIGN_BUTTONf(kMacCMapPad1PUp, "Joypad1 Up"); + ASSIGN_BUTTONf(kMacCMapPad1PDown, "Joypad1 Down"); + ASSIGN_BUTTONf(kMacCMapPad1PLeft, "Joypad1 Left"); + ASSIGN_BUTTONf(kMacCMapPad1PRight, "Joypad1 Right"); + + ASSIGN_BUTTONf(kMacCMapPad2PX, "Joypad2 X"); + ASSIGN_BUTTONf(kMacCMapPad2PA, "Joypad2 A"); + ASSIGN_BUTTONf(kMacCMapPad2PB, "Joypad2 B"); + ASSIGN_BUTTONf(kMacCMapPad2PY, "Joypad2 Y"); + ASSIGN_BUTTONf(kMacCMapPad2PL, "Joypad2 L"); + ASSIGN_BUTTONf(kMacCMapPad2PR, "Joypad2 R"); + ASSIGN_BUTTONf(kMacCMapPad2PSelect, "Joypad2 Select"); + ASSIGN_BUTTONf(kMacCMapPad2PStart, "Joypad2 Start"); + ASSIGN_BUTTONf(kMacCMapPad2PUp, "Joypad2 Up"); + ASSIGN_BUTTONf(kMacCMapPad2PDown, "Joypad2 Down"); + ASSIGN_BUTTONf(kMacCMapPad2PLeft, "Joypad2 Left"); + ASSIGN_BUTTONf(kMacCMapPad2PRight, "Joypad2 Right"); + + ASSIGN_BUTTONf(kMacCMapPad3PX, "Joypad3 X"); + ASSIGN_BUTTONf(kMacCMapPad3PA, "Joypad3 A"); + ASSIGN_BUTTONf(kMacCMapPad3PB, "Joypad3 B"); + ASSIGN_BUTTONf(kMacCMapPad3PY, "Joypad3 Y"); + ASSIGN_BUTTONf(kMacCMapPad3PL, "Joypad3 L"); + ASSIGN_BUTTONf(kMacCMapPad3PR, "Joypad3 R"); + ASSIGN_BUTTONf(kMacCMapPad3PSelect, "Joypad3 Select"); + ASSIGN_BUTTONf(kMacCMapPad3PStart, "Joypad3 Start"); + ASSIGN_BUTTONf(kMacCMapPad3PUp, "Joypad3 Up"); + ASSIGN_BUTTONf(kMacCMapPad3PDown, "Joypad3 Down"); + ASSIGN_BUTTONf(kMacCMapPad3PLeft, "Joypad3 Left"); + ASSIGN_BUTTONf(kMacCMapPad3PRight, "Joypad3 Right"); + + ASSIGN_BUTTONf(kMacCMapPad4PX, "Joypad4 X"); + ASSIGN_BUTTONf(kMacCMapPad4PA, "Joypad4 A"); + ASSIGN_BUTTONf(kMacCMapPad4PB, "Joypad4 B"); + ASSIGN_BUTTONf(kMacCMapPad4PY, "Joypad4 Y"); + ASSIGN_BUTTONf(kMacCMapPad4PL, "Joypad4 L"); + ASSIGN_BUTTONf(kMacCMapPad4PR, "Joypad4 R"); + ASSIGN_BUTTONf(kMacCMapPad4PSelect, "Joypad4 Select"); + ASSIGN_BUTTONf(kMacCMapPad4PStart, "Joypad4 Start"); + ASSIGN_BUTTONf(kMacCMapPad4PUp, "Joypad4 Up"); + ASSIGN_BUTTONf(kMacCMapPad4PDown, "Joypad4 Down"); + ASSIGN_BUTTONf(kMacCMapPad4PLeft, "Joypad4 Left"); + ASSIGN_BUTTONf(kMacCMapPad4PRight, "Joypad4 Right"); + + ASSIGN_BUTTONf(kMacCMapPad5PX, "Joypad5 X"); + ASSIGN_BUTTONf(kMacCMapPad5PA, "Joypad5 A"); + ASSIGN_BUTTONf(kMacCMapPad5PB, "Joypad5 B"); + ASSIGN_BUTTONf(kMacCMapPad5PY, "Joypad5 Y"); + ASSIGN_BUTTONf(kMacCMapPad5PL, "Joypad5 L"); + ASSIGN_BUTTONf(kMacCMapPad5PR, "Joypad5 R"); + ASSIGN_BUTTONf(kMacCMapPad5PSelect, "Joypad5 Select"); + ASSIGN_BUTTONf(kMacCMapPad5PStart, "Joypad5 Start"); + ASSIGN_BUTTONf(kMacCMapPad5PUp, "Joypad5 Up"); + ASSIGN_BUTTONf(kMacCMapPad5PDown, "Joypad5 Down"); + ASSIGN_BUTTONf(kMacCMapPad5PLeft, "Joypad5 Left"); + ASSIGN_BUTTONf(kMacCMapPad5PRight, "Joypad5 Right"); + + ASSIGN_BUTTONf(kMacCMapPad6PX, "Joypad6 X"); + ASSIGN_BUTTONf(kMacCMapPad6PA, "Joypad6 A"); + ASSIGN_BUTTONf(kMacCMapPad6PB, "Joypad6 B"); + ASSIGN_BUTTONf(kMacCMapPad6PY, "Joypad6 Y"); + ASSIGN_BUTTONf(kMacCMapPad6PL, "Joypad6 L"); + ASSIGN_BUTTONf(kMacCMapPad6PR, "Joypad6 R"); + ASSIGN_BUTTONf(kMacCMapPad6PSelect, "Joypad6 Select"); + ASSIGN_BUTTONf(kMacCMapPad6PStart, "Joypad6 Start"); + ASSIGN_BUTTONf(kMacCMapPad6PUp, "Joypad6 Up"); + ASSIGN_BUTTONf(kMacCMapPad6PDown, "Joypad6 Down"); + ASSIGN_BUTTONf(kMacCMapPad6PLeft, "Joypad6 Left"); + ASSIGN_BUTTONf(kMacCMapPad6PRight, "Joypad6 Right"); + + ASSIGN_BUTTONf(kMacCMapPad7PX, "Joypad7 X"); + ASSIGN_BUTTONf(kMacCMapPad7PA, "Joypad7 A"); + ASSIGN_BUTTONf(kMacCMapPad7PB, "Joypad7 B"); + ASSIGN_BUTTONf(kMacCMapPad7PY, "Joypad7 Y"); + ASSIGN_BUTTONf(kMacCMapPad7PL, "Joypad7 L"); + ASSIGN_BUTTONf(kMacCMapPad7PR, "Joypad7 R"); + ASSIGN_BUTTONf(kMacCMapPad7PSelect, "Joypad7 Select"); + ASSIGN_BUTTONf(kMacCMapPad7PStart, "Joypad7 Start"); + ASSIGN_BUTTONf(kMacCMapPad7PUp, "Joypad7 Up"); + ASSIGN_BUTTONf(kMacCMapPad7PDown, "Joypad7 Down"); + ASSIGN_BUTTONf(kMacCMapPad7PLeft, "Joypad7 Left"); + ASSIGN_BUTTONf(kMacCMapPad7PRight, "Joypad7 Right"); + + ASSIGN_BUTTONf(kMacCMapPad8PX, "Joypad8 X"); + ASSIGN_BUTTONf(kMacCMapPad8PA, "Joypad8 A"); + ASSIGN_BUTTONf(kMacCMapPad8PB, "Joypad8 B"); + ASSIGN_BUTTONf(kMacCMapPad8PY, "Joypad8 Y"); + ASSIGN_BUTTONf(kMacCMapPad8PL, "Joypad8 L"); + ASSIGN_BUTTONf(kMacCMapPad8PR, "Joypad8 R"); + ASSIGN_BUTTONf(kMacCMapPad8PSelect, "Joypad8 Select"); + ASSIGN_BUTTONf(kMacCMapPad8PStart, "Joypad8 Start"); + ASSIGN_BUTTONf(kMacCMapPad8PUp, "Joypad8 Up"); + ASSIGN_BUTTONf(kMacCMapPad8PDown, "Joypad8 Down"); + ASSIGN_BUTTONf(kMacCMapPad8PLeft, "Joypad8 Left"); + ASSIGN_BUTTONf(kMacCMapPad8PRight, "Joypad8 Right"); + + ASSIGN_BUTTONt(kMacCMapMouse1PL, "Mouse1 L"); + ASSIGN_BUTTONt(kMacCMapMouse1PR, "Mouse1 R"); + ASSIGN_BUTTONt(kMacCMapMouse2PL, "Mouse2 L"); + ASSIGN_BUTTONt(kMacCMapMouse2PR, "Mouse2 R"); + + ASSIGN_BUTTONt(kMacCMapScopeOffscreen, "Superscope AimOffscreen"); + ASSIGN_BUTTONt(kMacCMapScopeFire, "Superscope Fire"); + ASSIGN_BUTTONt(kMacCMapScopeCursor, "Superscope Cursor"); + ASSIGN_BUTTONt(kMacCMapScopeTurbo, "Superscope ToggleTurbo"); + ASSIGN_BUTTONt(kMacCMapScopePause, "Superscope Pause"); + + ASSIGN_BUTTONt(kMacCMapLGun1Offscreen, "Justifier1 AimOffscreen"); + ASSIGN_BUTTONt(kMacCMapLGun1Trigger, "Justifier1 Trigger"); + ASSIGN_BUTTONt(kMacCMapLGun1Start, "Justifier1 Start"); + ASSIGN_BUTTONt(kMacCMapLGun2Offscreen, "Justifier2 AimOffscreen"); + ASSIGN_BUTTONt(kMacCMapLGun2Trigger, "Justifier2 Trigger"); + ASSIGN_BUTTONt(kMacCMapLGun2Start, "Justifier2 Start"); + + ASSIGN_POINTRt(kMacCMapMouse1Pointer, "Pointer Mouse1"); + ASSIGN_POINTRt(kMacCMapMouse2Pointer, "Pointer Mouse2"); + ASSIGN_POINTRt(kMacCMapSuperscopePointer, "Pointer Superscope"); + ASSIGN_POINTRt(kMacCMapJustifier1Pointer, "Pointer Justifier1"); + + ASSIGN_POINTRf(PseudoPointerBase, "Pointer Justifier2"); + ASSIGN_BUTTONf(kMacCMapPseudoPtrBase + 0, "ButtonToPointer 1u Med"); + ASSIGN_BUTTONf(kMacCMapPseudoPtrBase + 1, "ButtonToPointer 1d Med"); + ASSIGN_BUTTONf(kMacCMapPseudoPtrBase + 2, "ButtonToPointer 1l Med"); + ASSIGN_BUTTONf(kMacCMapPseudoPtrBase + 3, "ButtonToPointer 1r Med"); +} + +bool S9xPollButton (uint32 id, bool *pressed) +{ + #define kmControlKey 0x3B + + KeyMap keys; + + GetKeys(keys); + + *pressed = false; + + if (id & k_MO) // mouse + { + switch (id & 0xFF) + { + case 0: *pressed = ISpKeyIsPressed(kISpMouseL); break; + case 1: *pressed = ISpKeyIsPressed(kISpMouseR); + } + } + else + if (id & k_SS) // superscope + { + switch (id & 0xFF) + { + case 0: *pressed = ISpKeyIsPressed(kISpOffScreen) | KeyIsPressed(keys, keyCode[kKeyOffScreen]); break; + case 2: *pressed = ISpKeyIsPressed(kISpScopeC) | KeyIsPressed(keys, keyCode[kKeyScopeCursor]); break; + case 3: *pressed = ISpKeyIsPressed(kISpScopeT) | KeyIsPressed(keys, keyCode[kKeyScopeTurbo]); break; + case 4: *pressed = ISpKeyIsPressed(kISpScopeP) | KeyIsPressed(keys, keyCode[kKeyScopePause]); break; + case 1: *pressed = ISpKeyIsPressed(kISpMouseL); + } + } + else + if (id & k_LG) // justifier + { + if (id & k_C1) + { + switch (id & 0xFF) + { + case 0: *pressed = ISpKeyIsPressed(kISpOffScreen) | KeyIsPressed(keys, keyCode[kKeyOffScreen]); break; + case 1: *pressed = ISpKeyIsPressed(kISpMouseL); break; + case 2: *pressed = ISpKeyIsPressed(kISpMouseR); + } + } + else + { + switch (id & 0xFF) + { + case 0: *pressed = ISpKeyIsPressed(kISp2PStart) | KeyIsPressed(keys, keyCode[k2PStart]); break; + case 1: *pressed = ISpKeyIsPressed(kISp2PB) | KeyIsPressed(keys, keyCode[k2PB]); break; + case 2: *pressed = ISpKeyIsPressed(kISp2PA) | KeyIsPressed(keys, keyCode[k2PA]); + } + } + } + + return (true); +} + +bool S9xPollPointer (uint32 id, int16 *x, int16 *y) +{ + if (id & k_PT) + { + if ((id & k_MO) && fullscreen) + GetGameScreenPointer(x, y, true); + else + GetGameScreenPointer(x, y, false); + } + else + *x = *y = 0; + + return (true); +} + +bool S9xPollAxis (uint32 id, int16 *value) +{ + return (false); +} + +s9xcommand_t S9xGetPortCommandT (const char *name) +{ + s9xcommand_t cmd; + + ZeroMemory(&cmd, sizeof(cmd)); + cmd.type = S9xBadMapping; + + return (cmd); +} + +char * S9xGetPortCommandName (s9xcommand_t command) +{ + static char str[] = "PortCommand"; + + return (str); +} + +void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2) +{ + return; +} + +bool8 S9xMapInput (const char *name, s9xcommand_t *cmd) +{ + return (true); +} + +void ControlPadFlagsToS9xReportButtons (int n, uint32 p) +{ + uint32 base = k_HD | k_BT | k_JP | (0x100 << n); + + S9xReportButton(base + 0, (p & 0x0040)); + S9xReportButton(base + 1, (p & 0x0080)); + S9xReportButton(base + 2, (p & 0x8000)); + S9xReportButton(base + 3, (p & 0x4000)); + S9xReportButton(base + 4, (p & 0x0020)); + S9xReportButton(base + 5, (p & 0x0010)); + S9xReportButton(base + 6, (p & 0x2000)); + S9xReportButton(base + 7, (p & 0x1000)); + S9xReportButton(base + 8, (p & 0x0800)); + S9xReportButton(base + 9, (p & 0x0400)); + S9xReportButton(base + 10, (p & 0x0200)); + S9xReportButton(base + 11, (p & 0x0100)); +} + +void ControlPadFlagsToS9xPseudoPointer (uint32 p) +{ + // prevent screwiness caused by trying to move the pointer left+right or up+down + if ((p & 0x0c00) == 0x0c00) p &= ~0x0c00; + if ((p & 0x0300) == 0x0300) p &= ~0x0300; + + // checks added to prevent a lack of right/down movement from breaking left/up movement + if (!(p & 0x0400)) + S9xReportButton(kMacCMapPseudoPtrBase + 0, (p & 0x0800)); + if (!(p & 0x0800)) + S9xReportButton(kMacCMapPseudoPtrBase + 1, (p & 0x0400)); + if (!(p & 0x0100)) + S9xReportButton(kMacCMapPseudoPtrBase + 2, (p & 0x0200)); + if (!(p & 0x0200)) + S9xReportButton(kMacCMapPseudoPtrBase + 3, (p & 0x0100)); +} diff --git a/macosx/mac-controls.h b/macosx/mac-controls.h new file mode 100644 index 00000000..10daba6a --- /dev/null +++ b/macosx/mac-controls.h @@ -0,0 +1,352 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_controls_h_ +#define _mac_controls_h_ + +enum +{ + k_HD = 0x80000000, + + k_JP = 0x01000000, + k_MO = 0x02000000, + k_SS = 0x04000000, + k_LG = 0x08000000, + + k_BT = 0x00100000, + k_PT = 0x00200000, + k_PS = 0x00400000, + + k_C1 = 0x00000100, + k_C2 = 0x00000200, + k_C3 = 0x00000400, + k_C4 = 0x00000800, + k_C5 = 0x00001000, + k_C6 = 0x00002000, + k_C7 = 0x00004000, + k_C8 = 0x00008000 +}; + +enum +{ + kMacCMapPad1PX = k_HD | k_BT | k_JP | k_C1, + kMacCMapPad1PA, + kMacCMapPad1PB, + kMacCMapPad1PY, + kMacCMapPad1PL, + kMacCMapPad1PR, + kMacCMapPad1PSelect, + kMacCMapPad1PStart, + kMacCMapPad1PUp, + kMacCMapPad1PDown, + kMacCMapPad1PLeft, + kMacCMapPad1PRight, + + kMacCMapPad2PX = k_HD | k_BT | k_JP | k_C2, + kMacCMapPad2PA, + kMacCMapPad2PB, + kMacCMapPad2PY, + kMacCMapPad2PL, + kMacCMapPad2PR, + kMacCMapPad2PSelect, + kMacCMapPad2PStart, + kMacCMapPad2PUp, + kMacCMapPad2PDown, + kMacCMapPad2PLeft, + kMacCMapPad2PRight, + + kMacCMapPad3PX = k_HD | k_BT | k_JP | k_C3, + kMacCMapPad3PA, + kMacCMapPad3PB, + kMacCMapPad3PY, + kMacCMapPad3PL, + kMacCMapPad3PR, + kMacCMapPad3PSelect, + kMacCMapPad3PStart, + kMacCMapPad3PUp, + kMacCMapPad3PDown, + kMacCMapPad3PLeft, + kMacCMapPad3PRight, + + kMacCMapPad4PX = k_HD | k_BT | k_JP | k_C4, + kMacCMapPad4PA, + kMacCMapPad4PB, + kMacCMapPad4PY, + kMacCMapPad4PL, + kMacCMapPad4PR, + kMacCMapPad4PSelect, + kMacCMapPad4PStart, + kMacCMapPad4PUp, + kMacCMapPad4PDown, + kMacCMapPad4PLeft, + kMacCMapPad4PRight, + + kMacCMapPad5PX = k_HD | k_BT | k_JP | k_C5, + kMacCMapPad5PA, + kMacCMapPad5PB, + kMacCMapPad5PY, + kMacCMapPad5PL, + kMacCMapPad5PR, + kMacCMapPad5PSelect, + kMacCMapPad5PStart, + kMacCMapPad5PUp, + kMacCMapPad5PDown, + kMacCMapPad5PLeft, + kMacCMapPad5PRight, + + kMacCMapPad6PX = k_HD | k_BT | k_JP | k_C6, + kMacCMapPad6PA, + kMacCMapPad6PB, + kMacCMapPad6PY, + kMacCMapPad6PL, + kMacCMapPad6PR, + kMacCMapPad6PSelect, + kMacCMapPad6PStart, + kMacCMapPad6PUp, + kMacCMapPad6PDown, + kMacCMapPad6PLeft, + kMacCMapPad6PRight, + + kMacCMapPad7PX = k_HD | k_BT | k_JP | k_C7, + kMacCMapPad7PA, + kMacCMapPad7PB, + kMacCMapPad7PY, + kMacCMapPad7PL, + kMacCMapPad7PR, + kMacCMapPad7PSelect, + kMacCMapPad7PStart, + kMacCMapPad7PUp, + kMacCMapPad7PDown, + kMacCMapPad7PLeft, + kMacCMapPad7PRight, + + kMacCMapPad8PX = k_HD | k_BT | k_JP | k_C8, + kMacCMapPad8PA, + kMacCMapPad8PB, + kMacCMapPad8PY, + kMacCMapPad8PL, + kMacCMapPad8PR, + kMacCMapPad8PSelect, + kMacCMapPad8PStart, + kMacCMapPad8PUp, + kMacCMapPad8PDown, + kMacCMapPad8PLeft, + kMacCMapPad8PRight, + + kMacCMapMouse1PL = k_HD | k_BT | k_MO | k_C1, + kMacCMapMouse1PR, + kMacCMapMouse2PL = k_HD | k_BT | k_MO | k_C2, + kMacCMapMouse2PR, + + kMacCMapScopeOffscreen = k_HD | k_BT | k_SS | k_C1, + kMacCMapScopeFire, + kMacCMapScopeCursor, + kMacCMapScopeTurbo, + kMacCMapScopePause, + + kMacCMapLGun1Offscreen = k_HD | k_BT | k_LG | k_C1, + kMacCMapLGun1Trigger, + kMacCMapLGun1Start, + kMacCMapLGun2Offscreen = k_HD | k_BT | k_LG | k_C2, + kMacCMapLGun2Trigger, + kMacCMapLGun2Start, + + kMacCMapMouse1Pointer = k_HD | k_PT | k_MO | k_C1, + kMacCMapMouse2Pointer = k_HD | k_PT | k_MO | k_C2, + kMacCMapSuperscopePointer = k_HD | k_PT | k_SS | k_C1, + kMacCMapJustifier1Pointer = k_HD | k_PT | k_LG | k_C1, + + kMacCMapPseudoPtrBase = k_HD | k_PS | k_LG | k_C2 // for Justifier 2P +}; + +void ControlPadFlagsToS9xReportButtons (int, uint32); +void ControlPadFlagsToS9xPseudoPointer (uint32); + +#endif diff --git a/macosx/mac-coreimage.h b/macosx/mac-coreimage.h new file mode 100644 index 00000000..fd4b436f --- /dev/null +++ b/macosx/mac-coreimage.h @@ -0,0 +1,203 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_coreimage_h_ +#define _mac_coreimage_h_ + +void InitCoreImage (void); +void DeinitCoreImage (void); +void InitCoreImageFilter (void); +void DeinitCoreImageFilter (void); +void ConfigureCoreImageFilter (void); +void InitCoreImageContext (CGLContextObj, CGLPixelFormatObj); +void DeinitCoreImageContext (void); +void DrawWithCoreImageFilter (CGRect, CGImageRef); + +#endif diff --git a/macosx/mac-coreimage.mm b/macosx/mac-coreimage.mm new file mode 100644 index 00000000..892522ff --- /dev/null +++ b/macosx/mac-coreimage.mm @@ -0,0 +1,1015 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#import "port.h" + +#import +#import +#import + +#import "mac-prefix.h" +#import "mac-dialog.h" +#import "mac-os.h" +#import "mac-coreimage.h" + +enum +{ + kCITypeNone = 0, + kCITypeBoolean = 1000, + kCITypeScalar, + kCITypeColor +}; + +#define mCoreImageFilter 501 +#define FIXEDRANGE 0x10000 +#define kCommandFilterMenuBase 0x41000000 +#define kCommandCheckBoxBase 0x49000000 +#define kCommandSliderBase 0x51000000 +#define kCommandColorButtonBase 0x59000000 +#define kCIFilterNamePrefKey CFSTR("CoreImageFilterName") + +typedef struct { + char name[256]; + char displayName[256]; + int type; + union { + struct { + bool8 cur; + } b; + + struct { + float max, min, cur; + } s; + + struct { + float r, g, b, a; + } c; + } u; +} FilterParam; + +static NSMutableArray *ciFilterNameList = NULL; +static NSMutableArray *ciFilterLocalizedNameList = NULL; +static NSArray *ciFilterInputKeys = NULL; +static CIFilter *ciFilter = NULL; +static CIContext *ciContext = NULL; +static FilterParam *ciFilterParam = NULL; +static CFStringRef ciFilterName = NULL; +static HIViewRef ciFilterUIPane = NULL; +static MenuRef ciFilterMenu = NULL; +static CGColorSpaceRef cgColor = NULL; +static MPSemaphoreID cisem = NULL; +static bool8 ciFilterHasInputCenter = false; +static bool8 ciFilterHasInputImage = false; +static int ciFilterInputKeysCount = 0; + +static void LoadFilterPrefs (void); +static void SaveFilterPrefs (void); +static void FilterParamToFilter (void); +static void FilterToFilterParam (void); +static void BuildCoreImageFilterListAndMenu (void); +static void ReleaseCoreImageFilterListAndMenu (void); +static void ReplaceFilterUI (WindowRef); +static void FilterUIAddSubviews (WindowRef, HIViewRef); +static void FilterUISetValues (HIViewRef); +static bool8 IsCoreImageFilterSupported (CIFilter *); +static pascal OSStatus CoreImageFilterEventHandler (EventHandlerCallRef, EventRef, void *); + + +void InitCoreImage (void) +{ + OSStatus err; + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + ciFilterName = (CFStringRef) CFPreferencesCopyAppValue(kCIFilterNamePrefKey, kCFPreferencesCurrentApplication); + if (!ciFilterName) + ciFilterName = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("CIGammaAdjust")); + + BuildCoreImageFilterListAndMenu(); + + err = MPCreateBinarySemaphore(&cisem); + + [pool release]; +} + +void DeinitCoreImage (void) +{ + OSStatus err; + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + err = MPDeleteSemaphore(cisem); + + ReleaseCoreImageFilterListAndMenu(); + + CFPreferencesSetAppValue(kCIFilterNamePrefKey, ciFilterName, kCFPreferencesCurrentApplication); + + CFRelease(ciFilterName); + + [pool release]; +} + +void InitCoreImageFilter (void) +{ + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + ciFilter = [[CIFilter filterWithName: (NSString *) ciFilterName] retain]; + [ciFilter setDefaults]; + + ciFilterInputKeys = [[ciFilter inputKeys] retain]; + ciFilterInputKeysCount = [ciFilterInputKeys count]; + + ciFilterParam = new FilterParam [ciFilterInputKeysCount]; + memset(ciFilterParam, 0, sizeof(FilterParam) * ciFilterInputKeysCount); + + ciFilterHasInputCenter = false; + ciFilterHasInputImage = false; + + LoadFilterPrefs(); + + [pool release]; +} + +void DeinitCoreImageFilter (void) +{ + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + SaveFilterPrefs(); + + ciFilterHasInputCenter = false; + ciFilterHasInputImage = false; + + delete [] ciFilterParam; + + [ciFilterInputKeys release]; + ciFilterInputKeysCount = 0; + + [ciFilter release]; + + [pool release]; +} + +static void LoadFilterPrefs (void) +{ + CFDataRef data; + int n = sizeof(FilterParam) * ciFilterInputKeysCount; + + data = (CFDataRef) CFPreferencesCopyAppValue(ciFilterName, kCFPreferencesCurrentApplication); + if (data) + { + if (CFDataGetLength(data) == n) + { + CFDataGetBytes(data, CFRangeMake(0, n), (UInt8 *) ciFilterParam); + FilterParamToFilter(); + } + + CFRelease(data); + } + + FilterToFilterParam(); +} + +static void SaveFilterPrefs (void) +{ + CFDataRef data; + int n = sizeof(FilterParam) * ciFilterInputKeysCount; + + data = CFDataCreate(kCFAllocatorDefault, (UInt8 *) ciFilterParam, n); + if (data) + { + CFPreferencesSetAppValue(ciFilterName, data, kCFPreferencesCurrentApplication); + CFRelease(data); + } +} + +static void FilterParamToFilter (void) +{ + NSString *key; + NSNumber *num; + CIColor *color; + + for (int i = 0; i < ciFilterInputKeysCount; i++) + { + key = [NSString stringWithUTF8String: ciFilterParam[i].name]; + if (key) + { + switch (ciFilterParam[i].type) + { + case kCITypeBoolean: + num = [NSNumber numberWithBool: ciFilterParam[i].u.b.cur]; + [ciFilter setValue: num forKey: key]; + break; + + case kCITypeScalar: + num = [NSNumber numberWithFloat: ciFilterParam[i].u.s.cur]; + [ciFilter setValue: num forKey: key]; + break; + + case kCITypeColor: + color = [CIColor colorWithRed: ciFilterParam[i].u.c.r green: ciFilterParam[i].u.c.g + blue: ciFilterParam[i].u.c.b alpha: ciFilterParam[i].u.c.a]; + [ciFilter setValue: color forKey: key]; + break; + + default: + break; + } + } + } +} + +static void FilterToFilterParam (void) +{ + NSDictionary *attr; + NSString *key, *label, *className, *typeName; + NSNumber *num; + CIColor *color; + id param; + + attr = [ciFilter attributes]; + ciFilterHasInputCenter = false; + ciFilterHasInputImage = false; + + for (int i = 0; i < ciFilterInputKeysCount; i++) + { + key = [ciFilterInputKeys objectAtIndex: i]; + param = [attr objectForKey: key]; + + strncpy(ciFilterParam[i].name, [key UTF8String], sizeof(ciFilterParam[i].name)); + ciFilterParam[i].displayName[0] = 0; + + if ([param isKindOfClass: [NSDictionary class]]) + { + label = [(NSDictionary *) param objectForKey: kCIAttributeDisplayName]; + if (!label) + label = [NSString stringWithString: key]; + strncpy(ciFilterParam[i].displayName, [label UTF8String], sizeof(ciFilterParam[i].displayName)); + + className = [(NSDictionary *) param objectForKey: kCIAttributeClass]; + + if ([className isEqualToString: @"NSNumber"]) + { + typeName = [(NSDictionary *) param objectForKey: kCIAttributeType]; + + if ([typeName isEqualToString: kCIAttributeTypeBoolean]) + { + ciFilterParam[i].type = kCITypeBoolean; + + num = [ciFilter valueForKey: key]; + ciFilterParam[i].u.b.cur = [num boolValue]; + } + else + { + ciFilterParam[i].type = kCITypeScalar; + + num = [ciFilter valueForKey: key]; + ciFilterParam[i].u.s.cur = [num floatValue]; + + num = [(NSDictionary *) param objectForKey: kCIAttributeSliderMax]; + if (!num) + num = [(NSDictionary *) param objectForKey: kCIAttributeMax]; + ciFilterParam[i].u.s.max = [num floatValue]; + + num = [(NSDictionary *) param objectForKey: kCIAttributeSliderMin]; + if (!num) + num = [(NSDictionary *) param objectForKey: kCIAttributeMin]; + ciFilterParam[i].u.s.min = [num floatValue]; + } + } + else + if ([className isEqualToString: @"CIColor"]) + { + ciFilterParam[i].type = kCITypeColor; + + color = [ciFilter valueForKey: key]; + ciFilterParam[i].u.c.r = [color red]; + ciFilterParam[i].u.c.g = [color green]; + ciFilterParam[i].u.c.b = [color blue]; + ciFilterParam[i].u.c.a = [color alpha]; + } + else + { + ciFilterParam[i].type = kCITypeNone; + + if ([className isEqualToString: @"CIVector"] && [key isEqualToString: @"inputCenter"]) + ciFilterHasInputCenter = true; + + if ([className isEqualToString: @"CIImage" ] && [key isEqualToString: @"inputImage" ]) + ciFilterHasInputImage = true; + } + } + } +} + +static void BuildCoreImageFilterListAndMenu (void) +{ + NSArray *categories, *filterNames; + OSStatus err; + + categories = [NSArray arrayWithObject: kCICategoryStillImage]; + filterNames = [CIFilter filterNamesInCategories: categories]; + + ciFilterNameList = [[NSMutableArray alloc] initWithCapacity: 1]; + ciFilterLocalizedNameList = [[NSMutableArray alloc] initWithCapacity: 1]; + err = CreateNewMenu(mCoreImageFilter, 0, &ciFilterMenu); + + int n = [filterNames count], m = 0; + for (int i = 0; i < n; i++) + { + CIFilter *filter; + NSString *name, *localName; + + name = [filterNames objectAtIndex: i]; + filter = [CIFilter filterWithName: name]; + + if (IsCoreImageFilterSupported(filter)) + { + [ciFilterNameList addObject: name]; + + localName = [CIFilter localizedNameForFilterName: name]; + if (!localName) + localName = [NSString stringWithString: name]; + + [ciFilterLocalizedNameList addObject: localName]; + + err = AppendMenuItemTextWithCFString(ciFilterMenu, (CFStringRef) localName, 0, kCommandFilterMenuBase + m, NULL); + m++; + } + } +} + +static void ReleaseCoreImageFilterListAndMenu (void) +{ + CFRelease(ciFilterMenu); + [ciFilterLocalizedNameList release]; + [ciFilterNameList release]; +} + +static bool8 IsCoreImageFilterSupported (CIFilter *filter) +{ + NSDictionary *attr; + NSArray *inputKeys; + NSString *key, *className; + id param; + bool8 result = true, hasInputImage = false; + + attr = [filter attributes]; + inputKeys = [filter inputKeys]; + + int n = [inputKeys count]; + for (int i = 0; i < n; i++) + { + key = [inputKeys objectAtIndex: i]; + param = [attr objectForKey: key]; + + if ([param isKindOfClass: [NSDictionary class]]) + { + className = [(NSDictionary *) param objectForKey: kCIAttributeClass]; + + if ([className isEqualToString: @"CIImage"]) + { + if (![key isEqualToString: @"inputImage"]) + result = false; + else + hasInputImage = true; + } + else + if ([className isEqualToString: @"CIVector"]) + { + if (![key isEqualToString: @"inputCenter"]) + result = false; + } + else + if (![className isEqualToString: @"NSNumber"] && ![className isEqualToString: @"CIColor"]) + result = false; + } + } + + if (hasInputImage == false) + result = false; + + return (result); +} + +void ConfigureCoreImageFilter (void) +{ + NSAutoreleasePool *pool; + OSStatus err; + IBNibRef nibRef; + + pool = [[NSAutoreleasePool alloc] init]; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef window; + + err = CreateWindowFromNib(nibRef, CFSTR("CIFilter"), &window); + if (err == noErr) + { + EventHandlerRef eref; + EventHandlerUPP eUPP; + EventTypeSpec event[] = { { kEventClassWindow, kEventWindowClose }, + { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }; + HIViewRef ctl, root; + HIViewID cid; + Rect rct; + int value; + + ciFilterUIPane = NULL; + + FilterToFilterParam(); + + root = HIViewGetRoot(window); + + SetHIViewID(&cid, 'FILT', 0); + rct.left = 74; + rct.top = 20; + rct.right = 74 + 279; + rct.bottom = 20 + 20; + err = CreatePopupButtonControl(window, &rct, NULL, -12345, false, 0, 0, 0, &ctl); + HIViewSetID(ctl, cid); + int n = CountMenuItems(ciFilterMenu); + SetControlPopupMenuHandle(ctl, ciFilterMenu); + HIViewSetMaximum(ctl, n); + for (int i = 1; i <= n; i++) + CheckMenuItem(ciFilterMenu, i, false); + value = [ciFilterNameList indexOfObject: (NSString *) ciFilterName]; + CheckMenuItem(ciFilterMenu, value + 1, true); + HIViewSetValue(ctl, value + 1); + + ReplaceFilterUI(window); + + eUPP = NewEventHandlerUPP(CoreImageFilterEventHandler); + err = InstallWindowEventHandler(window, eUPP, GetEventTypeCount(event), event, (void *) window, &eref); + + MoveWindowPosition(window, kWindowCoreImageFilter, false); + ShowWindow(window); + err = RunAppModalLoopForWindow(window); + HideWindow(window); + SaveWindowPosition(window, kWindowCoreImageFilter); + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eUPP); + + FilterParamToFilter(); + + CFRelease(window); + } + + DisposeNibReference(nibRef); + } + + [pool release]; +} + +static void ReplaceFilterUI (WindowRef window) +{ + OSStatus err; + HIRect frame; + Rect bounds, rct; + + if (ciFilterUIPane) + { + HIViewSetVisible(ciFilterUIPane, false); + DisposeControl(ciFilterUIPane); + ciFilterUIPane = NULL; + } + + GetWindowBounds(window, kWindowStructureRgn, &bounds); + + rct.left = 15; + rct.right = bounds.right - bounds.left - 15; + rct.top = 81; + rct.bottom = rct.top + 40; + err = CreateUserPaneControl(window, &rct, kControlSupportsEmbedding, &ciFilterUIPane); + HIViewSetVisible(ciFilterUIPane, false); + FilterUIAddSubviews(window, ciFilterUIPane); + + HIViewGetFrame(ciFilterUIPane, &frame); + bounds.bottom = bounds.top + (short) (frame.origin.y + frame.size.height + 30); + + err = TransitionWindow(window, kWindowSlideTransitionEffect, kWindowResizeTransitionAction, &bounds); + HIViewSetVisible(ciFilterUIPane, true); +} + +static void FilterUIAddSubviews (WindowRef window, HIViewRef parent) +{ + OSStatus err; + CFMutableStringRef label; + CFStringRef str; + HIViewRef ctl; + HIViewID cid; + HIRect bounds, frame; + Rect rct; + SInt32 value; + + HIViewGetFrame(parent, &bounds); + rct.left = 0; + rct.top = 0; + rct.right = 200; + rct.bottom = 20; + + int m = 0; + for (int i = 0; i < ciFilterInputKeysCount; i++) + { + str = CFStringCreateWithCString(kCFAllocatorDefault, ciFilterParam[i].displayName, kCFStringEncodingUTF8); + if (!str) + str = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("Parameter")); + label = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, str); + CFRelease(str); + + switch (ciFilterParam[i].type) + { + case kCITypeBoolean: + { + err = CreateCheckBoxControl(window, &rct, label, ciFilterParam[i].u.b.cur, true, &ctl); + SetHIViewID(&cid, kCommandCheckBoxBase + i, i); + HIViewSetID(ctl, cid); + HIViewSetCommandID(ctl, cid.signature); + err = HIViewAddSubview(parent, ctl); + frame.origin.x = 5.0f; + frame.origin.y = (float) (m * 28); + frame.size.width = bounds.size.width - 10.0f; + frame.size.height = 20.0f; + err = HIViewSetFrame(ctl, &frame); + m++; + + break; + } + + case kCITypeScalar: + { + CFStringAppend(label, CFSTR(" :")); + err = CreateStaticTextControl(window, &rct, label, NULL, &ctl); + SetStaticTextTrunc(ctl, truncEnd, true); + err = HIViewAddSubview(parent, ctl); + frame.origin.x = 5.0f; + frame.origin.y = (float) (m * 28); + frame.size.width = 120.0f; + frame.size.height = 20.0f; + err = HIViewSetFrame(ctl, &frame); + + value = (SInt32) ((ciFilterParam[i].u.s.cur - ciFilterParam[i].u.s.min) / (ciFilterParam[i].u.s.max - ciFilterParam[i].u.s.min) * (float) FIXEDRANGE); + err = CreateSliderControl(window, &rct, value, 0, FIXEDRANGE, kControlSliderDoesNotPoint, 0, false, NULL, &ctl); + SetHIViewID(&cid, kCommandSliderBase + i, i); + HIViewSetID(ctl, cid); + HIViewSetCommandID(ctl, cid.signature); + err = HIViewAddSubview(parent, ctl); + frame.origin.x = 135.0f; + frame.origin.y = (float) (m * 28) - 1.0f; + frame.size.width = bounds.size.width - 140.0f; + frame.size.height = 20.0f; + err = HIViewSetFrame(ctl, &frame); + m++; + + break; + } + + case kCITypeColor: + { + CFStringAppend(label, CFSTR("...")); + err = CreatePushButtonControl(window, &rct, label, &ctl); + SetHIViewID(&cid, kCommandColorButtonBase + i, i); + HIViewSetID(ctl, cid); + HIViewSetCommandID(ctl, cid.signature); + err = HIViewAddSubview(parent, ctl); + frame.origin.x = bounds.size.width - 180.0f; + frame.origin.y = (float) (m * 28); + frame.size.width = 175.0f; + frame.size.height = 20.0f; + err = HIViewSetFrame(ctl, &frame); + m++; + + break; + } + + default: + break; + } + + CFRelease(label); + } + + if (m) + { + str = CFCopyLocalizedString(CFSTR("ResetCIFilter"), "Reset"); + err = CreatePushButtonControl(window, &rct, str, &ctl); + SetHIViewID(&cid, 'rSET', 0); + HIViewSetID(ctl, cid); + HIViewSetCommandID(ctl, cid.signature); + err = HIViewAddSubview(parent, ctl); + frame.origin.x = bounds.size.width - 180.0f; + frame.origin.y = (float) (m * 28 + 12); + frame.size.width = 175.0f; + frame.size.height = 20.0f; + err = HIViewSetFrame(ctl, &frame); + CFRelease(str); + bounds.size.height = frame.origin.y + 32.0f; + } + else + bounds.size.height = 4.0f; + + err = HIViewSetFrame(parent, &bounds); +} + +static void FilterUISetValues (HIViewRef parent) +{ + HIViewRef ctl; + HIViewID cid; + SInt32 value; + + for (int i = 0; i < ciFilterInputKeysCount; i++) + { + switch (ciFilterParam[i].type) + { + case kCITypeBoolean: + SetHIViewID(&cid, kCommandCheckBoxBase + i, i); + HIViewFindByID(parent, cid, &ctl); + HIViewSetValue(ctl, ciFilterParam[i].u.b.cur); + break; + + case kCITypeScalar: + value = (SInt32) ((ciFilterParam[i].u.s.cur - ciFilterParam[i].u.s.min) / (ciFilterParam[i].u.s.max - ciFilterParam[i].u.s.min) * (float) FIXEDRANGE); + SetHIViewID(&cid, kCommandSliderBase + i, i); + HIViewFindByID(parent, cid, &ctl); + HIViewSetValue(ctl, value); + break; + + default: + break; + } + } +} + +static pascal OSStatus CoreImageFilterEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef window = (WindowRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + switch (GetEventKind(inEvent)) + { + case kEventWindowClose: + QuitAppModalLoopForWindow(window); + result = noErr; + } + + break; + + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommandExtended tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommandExtended), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(true); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommandExtended), NULL, &tHICommand); + if (err == noErr) + { + err = MPWaitOnSemaphore(cisem, kDurationForever); + + if (tHICommand.commandID == 'rSET') + { + [ciFilter setDefaults]; + FilterToFilterParam(); + FilterUISetValues(ciFilterUIPane); + + result = noErr; + } + else + { + unsigned long i = tHICommand.commandID & 0x00FFFFFF; + + switch (tHICommand.commandID & 0xFF000000) + { + case kCommandFilterMenuBase: + DeinitCoreImageFilter(); + + CFRelease(ciFilterName); + ciFilterName = CFStringCreateCopy(kCFAllocatorDefault, (CFStringRef) [ciFilterNameList objectAtIndex: i]); + + InitCoreImageFilter(); + + ReplaceFilterUI(window); + + break; + + case kCommandCheckBoxBase: + ciFilterParam[i].u.b.cur = !(ciFilterParam[i].u.b.cur); + FilterParamToFilter(); + result = noErr; + + break; + + case kCommandSliderBase: + SInt32 value; + + value = HIViewGetValue(tHICommand.source.control); + ciFilterParam[i].u.s.cur = ciFilterParam[i].u.s.min + (ciFilterParam[i].u.s.max - ciFilterParam[i].u.s.min) * (float) value / (float) FIXEDRANGE; + FilterParamToFilter(); + result = noErr; + + break; + + case kCommandColorButtonBase: + NColorPickerInfo info; + + memset(&info, 0, sizeof(NColorPickerInfo)); + info.placeWhere = kCenterOnMainScreen; + info.flags = kColorPickerDialogIsMoveable | kColorPickerDialogIsModal; + info.theColor.color.rgb.red = (int) (65535.0 * ciFilterParam[i].u.c.r); + info.theColor.color.rgb.green = (int) (65535.0 * ciFilterParam[i].u.c.g); + info.theColor.color.rgb.blue = (int) (65535.0 * ciFilterParam[i].u.c.b); + + err = NPickColor(&info); + + if ((err == noErr) && info.newColorChosen) + { + ciFilterParam[i].u.c.r = (float) info.theColor.color.rgb.red / 65535.0f; + ciFilterParam[i].u.c.g = (float) info.theColor.color.rgb.green / 65535.0f; + ciFilterParam[i].u.c.b = (float) info.theColor.color.rgb.blue / 65535.0f; + } + + FilterParamToFilter(); + result = noErr; + + break; + } + } + + err = MPSignalSemaphore(cisem); + } + } + } + + return (result); +} + +void InitCoreImageContext (CGLContextObj cglctx, CGLPixelFormatObj cglpix) +{ + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + FilterToFilterParam(); + + cgColor = CGColorSpaceCreateDeviceRGB(); + +#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT + ciContext = [[CIContext contextWithCGLContext: cglctx pixelFormat: cglpix options: NULL] retain]; +#else + ciContext = [[CIContext contextWithCGLContext: cglctx pixelFormat: cglpix colorSpace: cgColor options: NULL] retain]; +#endif + + [pool release]; +} + +void DeinitCoreImageContext (void) +{ + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + [ciContext release]; + CGColorSpaceRelease(cgColor); + + [pool release]; +} + +void DrawWithCoreImageFilter (CGRect src, CGImageRef img) +{ + OSStatus err; + NSAutoreleasePool *pool; + + pool = [[NSAutoreleasePool alloc] init]; + + err = MPWaitOnSemaphore(cisem, kDurationForever); + + if (ciFilterHasInputImage) + { + CIImage *image; + + image = [CIImage imageWithCGImage: img]; + [ciFilter setValue: image forKey: @"inputImage" ]; + } + + if (ciFilterHasInputCenter) + { + CIVector *vector; + + vector = [CIVector vectorWithX: (src.origin.x + src.size.width / 2) Y: (src.origin.y + src.size.height / 2)]; + [ciFilter setValue: vector forKey: @"inputCenter"]; + } + + [ciContext drawImage: [ciFilter valueForKey: @"outputImage"] atPoint: CGPointZero fromRect: src]; + + err = MPSignalSemaphore(cisem); + + [pool release]; +} diff --git a/macosx/mac-dialog.cpp b/macosx/mac-dialog.cpp new file mode 100644 index 00000000..8fa3c8e7 --- /dev/null +++ b/macosx/mac-dialog.cpp @@ -0,0 +1,1326 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" + +#include "mac-prefix.h" +#include "mac-audio.h" +#include "mac-joypad.h" +#include "mac-keyboard.h" +#include "mac-os.h" +#include "mac-render.h" +#include "mac-stringtools.h" +#include "mac-dialog.h" + +int autofireLastTabIndex = 1; + +static int tabList[] = { 2, 257, 258 }; + +static void RomInfoCopyToClipboard (void); +static void RomInfoBuildInfoText (char *); +static void AutofireSetAllIconImages (int, HIViewRef); +static void AutofireSetIconImages (int, HIViewRef); +static void AutofireReadAllSettings (int, HIViewRef); +static void AutofireReadSetting (int, uint16, HIViewRef); +static void AutofireWriteAllSettings (int, HIViewRef); +static void AutofireWriteSetting (int, uint16 *, HIViewRef); +static void AutofireSelectTabPane (HIViewRef, SInt16); +static OSStatus UpdateTextControlView (HIViewRef); +static pascal void AutofireSliderActionProc (HIViewRef, HIViewPartCode); +static pascal OSStatus RomInfoEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus AutofireTabEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus AutofireWindowEventHandler (EventHandlerCallRef, EventRef, void *); + + +static OSStatus UpdateTextControlView (HIViewRef control) +{ + OSStatus err; + WindowAttributes attr; + + err = GetWindowAttributes(GetControlOwner(control), &attr); + if (err == noErr) + { + if (attr & kWindowCompositingAttribute) + err = HIViewSetNeedsDisplay(control, true); + else + Draw1Control(control); + } + + return (err); +} + +OSStatus SetStaticTextCStr (HIViewRef control, char *text, Boolean draw) +{ + OSStatus err; + + if (!control || !text) + return (paramErr); + + err = SetControlData(control, 0, kControlStaticTextTextTag, strlen(text), text); + if ((err == noErr) && draw) + err = UpdateTextControlView(control); + + return (err); +} + +OSStatus SetStaticTextCFString (HIViewRef control, CFStringRef text, Boolean draw) +{ + OSStatus err; + + if (!control || !text) + return (paramErr); + + err = SetControlData(control, 0, kControlStaticTextCFStringTag, sizeof(CFStringRef), &text); + if ((err == noErr) && draw) + err = UpdateTextControlView(control); + + return (err); +} + +OSStatus SetStaticTextTrunc (HIViewRef control, TruncCode mode, Boolean draw) +{ + OSStatus err; + TruncCode trunc; + Boolean multiline; + + if (!control) + return (paramErr); + + trunc = mode; + multiline = false; + + err = SetControlData(control, 0, kControlStaticTextIsMultilineTag, sizeof(Boolean), &multiline); + if (err == noErr) + { + err = SetControlData(control, 0, kControlStaticTextTruncTag, sizeof(TruncCode), &trunc); + if ((err == noErr) && draw) + err = UpdateTextControlView(control); + } + + return (err); +} + +OSStatus GetEditTextCStr (HIViewRef control, char *text) +{ + OSStatus err; + Size actualSize; + + if (!control || !text) + return (paramErr); + + err = GetControlData(control, 0, kControlEditTextTextTag, 255, text, &actualSize); + if (err == noErr) + text[actualSize] = 0; + + return (err); +} + +OSStatus SetEditTextCStr (HIViewRef control, char *text, Boolean draw) +{ + OSStatus err; + + if (!control || !text) + return (paramErr); + + err = SetControlData(control, 0, kControlEditTextTextTag, strlen(text), text); + if ((err == noErr) && draw) + err = UpdateTextControlView(control); + + return (err); +} + +OSStatus CopyEditTextCFString (HIViewRef control, CFStringRef *text) +{ + OSStatus err; + Size actualSize; + + if (!control || !text) + return (paramErr); + + err = GetControlData(control, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), text, &actualSize); + + return (err); +} + +OSStatus SetEditTextCFString (HIViewRef control, CFStringRef text, Boolean draw) +{ + OSStatus err; + + if (!control || !text) + return (paramErr); + + err = SetControlData(control, 0, kControlEditTextCFStringTag, sizeof(CFStringRef), &text); + if ((err == noErr) && draw) + err = UpdateTextControlView(control); + + return (err); +} + +OSStatus SetEditTextSelection (HIViewRef control, SInt16 selStart, SInt16 selEnd) +{ + OSStatus err; + ControlEditTextSelectionRec selection; + + if (!control) + return (paramErr); + + selection.selStart = selStart; + selection.selEnd = selEnd; + + err = SetControlData(control, 0, kControlEditTextSelectionTag, sizeof(selection), &selection); + if (err == noErr) + err = UpdateTextControlView(control); + + return (err); +} + +void StartCarbonModalDialog (void) +{ + HiliteMenu(0); + if (gWindow) + HideWindow(gWindow); +} + +void FinishCarbonModalDialog (void) +{ + if (gWindow) + ShowWindow(gWindow); +} + +void MoveWindowPosition (WindowRef window, int which, Boolean resize) +{ + if (savewindowpos) + { + MoveWindow(window, windowPos[which].h, windowPos[which].v, false); + + if (resize) + { + if ((windowSize[which].width > 0) && (windowSize[which].height > 0)) + SizeWindow(window, (short) windowSize[which].width, (short) windowSize[which].height, false); + } + } + else + RepositionWindow(window, NULL, kWindowAlertPositionOnMainScreen); +} + +void SaveWindowPosition (WindowRef window, int which) +{ + Rect rct; + + GetWindowBounds(window, kWindowContentRgn, &rct); + windowPos[which].h = rct.left; + windowPos[which].v = rct.top; + windowSize[which].width = (float) (rct.right - rct.left); + windowSize[which].height = (float) (rct.bottom - rct.top ); +} + +void AppearanceAlert (AlertType type, int stringID1, int stringID2) +{ + OSStatus err; + DialogRef dialog; + DialogItemIndex outItemHit; + CFStringRef key1, key2, mes1, mes2; + char label1[32], label2[32]; + + sprintf(label1, "AlertMes_%02d", stringID1); + sprintf(label2, "AlertMes_%02d", stringID2); + + key1 = CFStringCreateWithCString(kCFAllocatorDefault, label1, CFStringGetSystemEncoding()); + key2 = CFStringCreateWithCString(kCFAllocatorDefault, label2, CFStringGetSystemEncoding()); + + if (key1) mes1 = CFCopyLocalizedString(key1, "mes1"); else mes1 = NULL; + if (key2) mes2 = CFCopyLocalizedString(key2, "mes2"); else mes2 = NULL; + + PlayAlertSound(); + + err = CreateStandardAlert(type, mes1, mes2, NULL, &dialog); + err = RunStandardAlert(dialog, NULL, &outItemHit); + + if (key1) CFRelease(key1); + if (key2) CFRelease(key2); + if (mes1) CFRelease(mes1); + if (mes2) CFRelease(mes2); +} + +void AboutDialog (void) +{ + OSStatus err; + IBNibRef nibRef; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef tWindowRef; + + err = CreateWindowFromNib(nibRef, CFSTR("About"), &tWindowRef); + if (err == noErr) + { + EventHandlerRef eref; + EventHandlerUPP eventUPP; + EventTypeSpec windowEvents[] = { { kEventClassWindow, kEventWindowClose }, + { kEventClassCommand, kEventCommandUpdateStatus } }; + ControlFontStyleRec frec; + HIViewRef ctl, root; + HIViewID cid; + char text[32]; + + err = ChangeWindowAttributes(tWindowRef, kWindowNoAttributes, kWindowInWindowMenuAttribute); + + if (systemVersion >= 0x1040) + frec.font = FMGetFontFromATSFontRef(ATSFontFindFromName(CFSTR("Lucida Grande"), kATSOptionFlagsDefault)); + #ifdef MAC_PANTHER_SUPPORT + else + frec.font = kThemeSystemFont; + #endif + frec.just = teCenter; + + root = HIViewGetRoot(tWindowRef); + cid.id = 0; + + cid.signature = 'VERS'; + HIViewFindByID(root, cid, &ctl); + sprintf(text, "Version %s (%s)", VERSION, MAC_VERSION); + SetStaticTextCStr(ctl, text, false); + frec.flags = kControlUseFontMask | kControlUseSizeMask | kControlUseJustMask; + frec.size = 10; + err = SetControlFontStyle(ctl, &frec); + + cid.signature = 'NAME'; + HIViewFindByID(root, cid, &ctl); + frec.flags = kControlUseFontMask | kControlUseSizeMask | kControlUseFaceMask | kControlUseJustMask; + frec.size = 14; + frec.style = 1; + err = SetControlFontStyle(ctl, &frec); + + eventUPP = NewEventHandlerUPP(DefaultEventHandler); + err = InstallWindowEventHandler(tWindowRef, eventUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) tWindowRef, &eref); + + MoveWindowPosition(tWindowRef, kWindowAbout, false); + ShowWindow(tWindowRef); + err = RunAppModalLoopForWindow(tWindowRef); + HideWindow(tWindowRef); + SaveWindowPosition(tWindowRef, kWindowAbout); + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eventUPP); + + CFRelease(tWindowRef); + } + + DisposeNibReference(nibRef); + } +} + +pascal OSStatus DefaultEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef tWindowRef = (WindowRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + switch (GetEventKind(inEvent)) + { + case kEventWindowClose: + QuitAppModalLoopForWindow(tWindowRef); + result = noErr; + } + + break; + + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + case kEventCommandUpdateStatus: + HICommand tHICommand; + + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(true); + result = noErr; + } + } + + break; + } + + return (result); +} + +void ConfigureAutofire (void) +{ + OSStatus err; + IBNibRef nibRef; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef tWindowRef; + + err = CreateWindowFromNib(nibRef, CFSTR("AutoFire"), &tWindowRef); + if (err == noErr) + { + EventHandlerRef wRef, tRef; + EventHandlerUPP wUPP, tUPP; + EventTypeSpec wEvent[] = { { kEventClassWindow, kEventWindowClose }, + { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }, + tEvent[] = { { kEventClassControl, kEventControlHit } }; + ControlActionUPP actionUPP; + HIViewRef ctl, root; + HIViewID cid; + + root = HIViewGetRoot(tWindowRef); + + wUPP = NewEventHandlerUPP(AutofireWindowEventHandler); + err = InstallWindowEventHandler(tWindowRef, wUPP, GetEventTypeCount(wEvent), wEvent, (void *) tWindowRef, &wRef); + + cid.signature = 'Ftab'; + cid.id = 256; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, autofireLastTabIndex); + AutofireSelectTabPane(ctl, autofireLastTabIndex); + tUPP = NewEventHandlerUPP(AutofireTabEventHandler); + err = InstallControlEventHandler(ctl, tUPP, GetEventTypeCount(tEvent), tEvent, 0, &tRef); + + actionUPP = NewControlActionUPP(AutofireSliderActionProc); + + for (int player = 0; player < 2; player++) + { + AutofireSetAllIconImages(player + 1, root); + AutofireReadAllSettings(player + 1, root); + + cid.id = player + 1; + cid.signature = 'Slid'; + HIViewFindByID(root, cid, &ctl); + SetControlAction(ctl, actionUPP); + } + + MoveWindowPosition(tWindowRef, kWindowAutoFire, false); + ShowWindow(tWindowRef); + err = RunAppModalLoopForWindow(tWindowRef); + HideWindow(tWindowRef); + SaveWindowPosition(tWindowRef, kWindowAutoFire); + + for (int player = 0; player < 2; player++) + AutofireWriteAllSettings(player + 1, root); + + autofire = (autofireRec[0].buttonMask || autofireRec[1].buttonMask) ? true : false; + + err = RemoveEventHandler(tRef); + DisposeEventHandlerUPP(tUPP); + + err = RemoveEventHandler(wRef); + DisposeEventHandlerUPP(wUPP); + + DisposeControlActionUPP(actionUPP); + + CFRelease(tWindowRef); + } + + DisposeNibReference(nibRef); + } +} + +static void AutofireSetAllIconImages (int player, HIViewRef parent) +{ + AutofireSetIconImages(player * 1, parent); + AutofireSetIconImages(player * 11, parent); + AutofireSetIconImages(player * 111, parent); + AutofireSetIconImages(player * 1111, parent); +} + +static void AutofireSetIconImages (int sig, HIViewRef parent) +{ + OSStatus err; + ControlButtonContentInfo info; + HIViewRef ctl; + HIViewID cid; + int ofs; + + cid.id = sig; + ofs = macPadIconIndex + ((sig % 2) ? 0 : 12); + + if (systemVersion >= 0x1040) + { + info.contentType = kControlContentCGImageRef; + + cid.signature = 'AChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[7 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'BChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[5 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'XChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[6 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'YChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[4 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'LChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[8 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'RChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[9 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Up '; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[0 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Down'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[1 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Left'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[2 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Righ'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[3 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Star'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[10 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Sele'; + HIViewFindByID(parent, cid, &ctl); + info.u.imageRef = macIconImage[11 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + } +#ifdef MAC_PANTHER_SUPPORT + else + { + info.contentType = kControlContentIconRef; + + cid.signature = 'AChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[7 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'BChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[5 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'XChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[6 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'YChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[4 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'LChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[8 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'RChk'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[9 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Up '; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[0 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Down'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[1 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Left'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[2 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Righ'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[3 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Star'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[10 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + + cid.signature = 'Sele'; + HIViewFindByID(parent, cid, &ctl); + info.u.iconRef = macIconRef[11 + ofs]; + err = SetBevelButtonContentInfo(ctl, &info); + } +#endif +} + +static void AutofireReadAllSettings (int player, HIViewRef parent) +{ + HIViewRef ctl; + HIViewID cid; + char num[10]; + + AutofireReadSetting(player * 1, autofireRec[player - 1].buttonMask, parent); + AutofireReadSetting(player * 11, autofireRec[player - 1].toggleMask, parent); + AutofireReadSetting(player * 111, autofireRec[player - 1].tcMask, parent); + AutofireReadSetting(player * 1111, autofireRec[player - 1].invertMask, parent); + + cid.id = player; + + cid.signature = 'Num_'; + HIViewFindByID(parent, cid, &ctl); + sprintf(num, "%ld", autofireRec[player - 1].frequency); + SetStaticTextCStr(ctl, num, false); + + cid.signature = 'Slid'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, autofireRec[player - 1].frequency); +} + +static void AutofireReadSetting (int sig, uint16 target, HIViewRef parent) +{ + HIViewRef ctl; + HIViewID cid; + + cid.id = sig; + + cid.signature = 'AChk'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x0080) ? 1 : 0); + + cid.signature = 'BChk'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x8000) ? 1 : 0); + + cid.signature = 'XChk'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x0040) ? 1 : 0); + + cid.signature = 'YChk'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x4000) ? 1 : 0); + + cid.signature = 'LChk'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x0020) ? 1 : 0); + + cid.signature = 'RChk'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x0010) ? 1 : 0); + + cid.signature = 'Up '; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x0800) ? 1 : 0); + + cid.signature = 'Down'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x0400) ? 1 : 0); + + cid.signature = 'Left'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x0200) ? 1 : 0); + + cid.signature = 'Righ'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x0100) ? 1 : 0); + + cid.signature = 'Star'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x1000) ? 1 : 0); + + cid.signature = 'Sele'; + HIViewFindByID(parent, cid, &ctl); + SetControl32BitValue(ctl, (target & 0x2000) ? 1 : 0); +} + +static void AutofireWriteAllSettings (int player, HIViewRef parent) +{ + HIViewRef ctl; + HIViewID cid; + + AutofireWriteSetting(player * 1, &(autofireRec[player - 1].buttonMask), parent); + AutofireWriteSetting(player * 11, &(autofireRec[player - 1].toggleMask), parent); + AutofireWriteSetting(player * 111, &(autofireRec[player - 1].tcMask), parent); + AutofireWriteSetting(player * 1111, &(autofireRec[player - 1].invertMask), parent); + + cid.id = player; + cid.signature = 'Slid'; + HIViewFindByID(parent, cid, &ctl); + autofireRec[player - 1].frequency = GetControl32BitValue(ctl); +} + +static void AutofireWriteSetting (int sig, uint16 *target, HIViewRef parent) +{ + HIViewRef ctl; + HIViewID cid; + + cid.id = sig; + *target = 0x0000; + + cid.signature = 'AChk'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x0080; + + cid.signature = 'BChk'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x8000; + + cid.signature = 'XChk'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x0040; + + cid.signature = 'YChk'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x4000; + + cid.signature = 'LChk'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x0020; + + cid.signature = 'RChk'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x0010; + + cid.signature = 'Up '; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x0800; + + cid.signature = 'Down'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x0400; + + cid.signature = 'Left'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x0200; + + cid.signature = 'Righ'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x0100; + + cid.signature = 'Star'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x1000; + + cid.signature = 'Sele'; + HIViewFindByID(parent, cid, &ctl); + if (GetControl32BitValue(ctl)) + (*target) |= 0x2000; +} + +static void AutofireSelectTabPane (HIViewRef tabControl, SInt16 index) +{ + HIViewRef sup, userPane, selectedPane = NULL; + HIViewID cid; + + autofireLastTabIndex = index; + + sup = HIViewGetSuperview(tabControl); + cid.signature = 'Ftab'; + + for (int i = 1; i < tabList[0] + 1; i++) + { + cid.id = tabList[i]; + HIViewFindByID(sup, cid, &userPane); + + if (i == index) + selectedPane = userPane; + else + HIViewSetVisible(userPane, false); + } + + if (selectedPane != NULL) + HIViewSetVisible(selectedPane, true); + + HIViewSetNeedsDisplay(tabControl, true); +} + +static pascal OSStatus AutofireTabEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + HIViewRef ctl; + HIViewID cid; + SInt32 value; + + err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &ctl); + if (err == noErr) + { + GetControlID(ctl, &cid); + value = GetControl32BitValue(ctl); + + if ((cid.id == 256) && (value != autofireLastTabIndex)) + { + AutofireSelectTabPane(ctl, value); + result = noErr; + } + } + + return (result); +} + +static pascal OSStatus AutofireWindowEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef tWindowRef = (WindowRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + switch (GetEventKind(inEvent)) + { + case kEventWindowClose: + QuitAppModalLoopForWindow(tWindowRef); + result = noErr; + } + + break; + + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(true); + result = noErr; + } + + break; + + case kEventCommandProcess: + HIViewRef root; + int player = -1; + + root = HIViewGetRoot(tWindowRef); + + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + switch (tHICommand.commandID) + { + case 'DEF1': + player = 0; + break; + + case 'DEF2': + player = 1; + break; + } + + if (player != -1) + { + autofireRec[player].buttonMask = 0x0000; + autofireRec[player].toggleMask = 0xFFF0; + autofireRec[player].tcMask = 0x0000; + autofireRec[player].invertMask = 0x0000; + autofireRec[player].frequency = 10; + AutofireReadAllSettings(player + 1, root); + + result = noErr; + } + } + } + } + + return (result); +} + +static pascal void AutofireSliderActionProc (HIViewRef slider, HIViewPartCode partCode) +{ + HIViewRef ctl; + HIViewID cid; + char num[10]; + + GetControlID(slider, &cid); + cid.signature = 'Num_'; + HIViewFindByID(HIViewGetSuperview(slider), cid, &ctl); + + sprintf(num, "%ld", GetControl32BitValue(slider)); + SetStaticTextCStr(ctl, num, true); +} + +void RomInfoDialog (void) +{ + OSStatus err; + IBNibRef nibRef; + + if (!cartOpen) + return; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef tWindowRef; + + err = CreateWindowFromNib(nibRef, CFSTR("RomInfo"), &tWindowRef); + if (err == noErr) + { + EventHandlerRef eref; + EventHandlerUPP eventUPP; + EventTypeSpec windowEvents[] = { { kEventClassWindow, kEventWindowClose }, + { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }; + CFStringRef sref; + HIViewRef ctl, root; + HIViewID cid; + char text[256]; + + eventUPP = NewEventHandlerUPP(RomInfoEventHandler); + err = InstallWindowEventHandler(tWindowRef, eventUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) tWindowRef, &eref); + + root = HIViewGetRoot(tWindowRef); + cid.id = 0; + + cid.signature = 'Name'; // Cart Name + HIViewFindByID(root, cid, &ctl); + + strcpy(text, Memory.RawROMName); + sref = CopyFixNameStrings(text, Memory.ROMRegion); + if (!sref) + SetStaticTextCFString(ctl, CFSTR("unknown"), false); + else + { + SetStaticTextCFString(ctl, sref, false); + CFRelease(sref); + } + + cid.signature = 'Code'; // Game Code + HIViewFindByID(root, cid, &ctl); + sprintf(text, "%s", Memory.ROMId); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'Cont'; // Contents + HIViewFindByID(root, cid, &ctl); + sprintf(text, "%s", Memory.KartContents()); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'Map '; // ROM Map + HIViewFindByID(root, cid, &ctl); + sprintf(text, "%s", Memory.MapType()); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'Spee'; // ROM Speed + HIViewFindByID(root, cid, &ctl); + sprintf(text, "0x%02X (%s)", Memory.ROMSpeed, ((Memory.ROMSpeed & 0x10) != 0) ? "FastROM" : "SlowROM"); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'Type'; // ROM Type + HIViewFindByID(root, cid, &ctl); + sprintf(text, "0x%02X", Memory.ROMType); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'SizC'; // Actual ROM Size + HIViewFindByID(root, cid, &ctl); + sprintf(text, "%dMbits", Memory.CalculatedSize / 0x20000); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'SizH'; // ROM Size written in info block + HIViewFindByID(root, cid, &ctl); + sprintf(text, "%s", Memory.Size()); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'SRAM'; // SRAM Size + HIViewFindByID(root, cid, &ctl); + sprintf(text, "%s", Memory.StaticRAMSize()); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'SumC'; // Actual checksum + HIViewFindByID(root, cid, &ctl); + sprintf(text, "0x%04X", Memory.CalculatedChecksum); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'SumH'; // Checksum written in info block + HIViewFindByID(root, cid, &ctl); + sprintf(text, "0x%04X", Memory.ROMChecksum); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'ComH'; // Checksum complement written in info block : SumH + ComH = 0xFFFF + HIViewFindByID(root, cid, &ctl); + sprintf(text, "0x%04X", Memory.ROMComplementChecksum); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'Outp'; // Video output (NTSC or PAL) + HIViewFindByID(root, cid, &ctl); + sprintf(text, "%s", (Memory.ROMRegion > 12 || Memory.ROMRegion < 2) ? "NTSC 60Hz" : "PAL 50Hz"); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'Vers'; // Revision + HIViewFindByID(root, cid, &ctl); + sprintf(text, "%s", Memory.Revision()); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'Lice'; // Licensee + HIViewFindByID(root, cid, &ctl); + sprintf(text, "%s", Memory.PublishingCompany()); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'Regi'; // Region + HIViewFindByID(root, cid, &ctl); + sprintf(text, "%s", Memory.Country()); + SetStaticTextCStr(ctl, text, false); + + cid.signature = 'CRC '; // CRC32 + HIViewFindByID(root, cid, &ctl); + sprintf(text, "0x%08X", Memory.ROMCRC32); + SetStaticTextCStr(ctl, text, false); + + MoveWindowPosition(tWindowRef, kWindowRomInfo, false); + ShowWindow(tWindowRef); + err = RunAppModalLoopForWindow(tWindowRef); + HideWindow(tWindowRef); + SaveWindowPosition(tWindowRef, kWindowRomInfo); + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eventUPP); + + CFRelease(tWindowRef); + } + + DisposeNibReference(nibRef); + } +} + +static void RomInfoCopyToClipboard (void) +{ + OSStatus err; + PasteboardRef clipboard; + PasteboardSyncFlags sync; + CFDataRef cfdata; + char text[1024]; + + RomInfoBuildInfoText(text); + + err = PasteboardCreate(kPasteboardClipboard, &clipboard); + if (err == noErr) + { + err = PasteboardClear(clipboard); + if (err == noErr) + { + sync = PasteboardSynchronize(clipboard); + if (!(sync & kPasteboardModified) && (sync & kPasteboardClientIsOwner)) + { + cfdata = CFDataCreate(kCFAllocatorDefault, (UInt8 *) text, (CFIndex) strlen(text)); + if (cfdata) + { + err = PasteboardPutItemFlavor(clipboard, (PasteboardItemID) 1, CFSTR("com.apple.traditional-mac-plain-text"), cfdata, 0); + CFRelease(cfdata); + } + } + } + + CFRelease(clipboard); + } +} + +static void RomInfoBuildInfoText (char *romtext) +{ + char s1[256], s2[1024]; + + sprintf(s1, "Snes9x version: %s\nMac port version: %s, ", VERSION, MAC_VERSION); +#ifdef __BIG_ENDIAN__ + strcat(s1, "PowerPC\n\n"); +#else + strcat(s1, "Intel\n\n"); +#endif + Memory.MakeRomInfoText(s2); + sprintf(romtext, "%s%s", s1, s2); +} + +static pascal OSStatus RomInfoEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef tWindowRef = (WindowRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + switch (GetEventKind(inEvent)) + { + case kEventWindowClose: + QuitAppModalLoopForWindow(tWindowRef); + result = noErr; + } + + break; + + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(true); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + switch (tHICommand.commandID) + { + case 'Clip': + RomInfoCopyToClipboard(); + result = noErr; + } + } + } + } + + return (result); +} + +void RegisterHelpBook (void) +{ + OSStatus err; + CFBundleRef bundleRef; + CFURLRef bundleURL; + FSRef fref; + + bundleRef = CFBundleGetMainBundle(); + if (bundleRef) + { + bundleURL = CFBundleCopyBundleURL(bundleRef); + if (bundleURL) + { + if (CFURLGetFSRef(bundleURL, &fref)) + err = AHRegisterHelpBook(&fref); + + CFRelease(bundleURL); + } + } +} + +void SetHIViewID (HIViewID *cid, OSType signature, SInt32 value) +{ + // Since HIViewID.id conflicts Objective-C 'id'... + + cid->signature = signature; + cid->id = value; +} diff --git a/macosx/mac-dialog.h b/macosx/mac-dialog.h new file mode 100644 index 00000000..b5942e62 --- /dev/null +++ b/macosx/mac-dialog.h @@ -0,0 +1,228 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_dialog_h_ +#define _mac_dialog_h_ + +enum +{ + kFolderFail = 3, + kFolderHint, + kBadRomWarning, + kBadRomHint, + kCFCantAddWarning, + kCFCantAddHint, + kRequiredSystemWarning, + kRequiredSystemHint +}; + +extern int autofireLastTabIndex; + +void AboutDialog (void); +void RomInfoDialog (void); +void ConfigureAutofire (void); +void StartCarbonModalDialog (void); +void FinishCarbonModalDialog (void); +void RegisterHelpBook (void); +void MoveWindowPosition (WindowRef, int, Boolean); +void SaveWindowPosition (WindowRef, int); +void AppearanceAlert (AlertType, int, int); +void SetHIViewID (HIViewID *, OSType, SInt32); +OSStatus SetStaticTextCStr (HIViewRef, char *, Boolean); +OSStatus SetStaticTextCFString (HIViewRef, CFStringRef, Boolean); +OSStatus SetStaticTextTrunc (HIViewRef, TruncCode, Boolean); +OSStatus GetEditTextCStr (HIViewRef, char *); +OSStatus SetEditTextCStr (HIViewRef, char *, Boolean); +OSStatus CopyEditTextCFString (HIViewRef, CFStringRef *); +OSStatus SetEditTextCFString (HIViewRef, CFStringRef, Boolean); +OSStatus SetEditTextSelection (HIViewRef, SInt16, SInt16); +pascal OSStatus DefaultEventHandler (EventHandlerCallRef, EventRef, void *); + +#endif diff --git a/macosx/mac-file.cpp b/macosx/mac-file.cpp new file mode 100644 index 00000000..8b62aa10 --- /dev/null +++ b/macosx/mac-file.cpp @@ -0,0 +1,687 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "movie.h" +#include "display.h" + +#include + +#include "mac-prefix.h" +#include "mac-dialog.h" +#include "mac-os.h" +#include "mac-stringtools.h" +#include "mac-file.h" + +static void AddFolderIcon (FSRef *, const char *); +static OSStatus FindSNESFolder (FSRef *, char *, const char *); +static OSStatus FindApplicationSupportFolder (FSRef *, char *, const char *); + + +static OSStatus FindSNESFolder (FSRef *folderRef, char *folderPath, const char *folderName) +{ + OSStatus err; + CFURLRef burl, purl; + CFStringRef fstr; + FSRef pref; + UniChar buffer[PATH_MAX + 1]; + Boolean r; + + fstr = CFStringCreateWithCString(kCFAllocatorDefault, folderName, CFStringGetSystemEncoding()); + CFStringGetCharacters(fstr, CFRangeMake(0, CFStringGetLength(fstr)), buffer); + + burl = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + purl = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, burl); + r = CFURLGetFSRef(purl, &pref); + + err = FSMakeFSRefUnicode(&pref, CFStringGetLength(fstr), buffer, kTextEncodingUnicodeDefault, folderRef); + if (err == dirNFErr || err == fnfErr) + { + err = FSCreateDirectoryUnicode(&pref, CFStringGetLength(fstr), buffer, kFSCatInfoNone, NULL, folderRef, NULL, NULL); + if (err == noErr) + AddFolderIcon(folderRef, folderName); + } + + if (err != noErr && !folderWarning) + { + AppearanceAlert(kAlertCautionAlert, kFolderFail, kFolderHint); + folderWarning = true; + } + else + err = FSRefMakePath(folderRef, (unsigned char *) folderPath, PATH_MAX); + + CFRelease(purl); + CFRelease(burl); + CFRelease(fstr); + + return (err); +} + +static OSStatus FindApplicationSupportFolder (FSRef *folderRef, char *folderPath, const char *folderName) +{ + OSStatus err; + FSRef p2ref, p1ref; + CFStringRef fstr; + UniChar buffer[PATH_MAX + 1]; + UniChar s9xfolder[6] = { 'S', 'n', 'e', 's', '9', 'x' }, + oldfolder[6] = { 'S', 'N', 'E', 'S', '9', 'X' }; + + err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &p2ref); + if (err) + return (err); + + err = FSMakeFSRefUnicode(&p2ref, 6, s9xfolder, kTextEncodingUnicodeDefault, &p1ref); + if (err == dirNFErr || err == fnfErr) + { + err = FSMakeFSRefUnicode(&p2ref, 6, oldfolder, kTextEncodingUnicodeDefault, &p1ref); + if (err == dirNFErr || err == fnfErr) + err = FSCreateDirectoryUnicode(&p2ref, 6, s9xfolder, kFSCatInfoNone, NULL, &p1ref, NULL, NULL); + } + if (err) + return (err); + + fstr = CFStringCreateWithCString(kCFAllocatorDefault, folderName, CFStringGetSystemEncoding()); + CFStringGetCharacters(fstr, CFRangeMake(0, CFStringGetLength(fstr)), buffer); + + err = FSMakeFSRefUnicode(&p1ref, CFStringGetLength(fstr), buffer, kTextEncodingUnicodeDefault, folderRef); + if (err == dirNFErr || err == fnfErr) + { + err = FSCreateDirectoryUnicode(&p1ref, CFStringGetLength(fstr), buffer, kFSCatInfoNone, NULL, folderRef, NULL, NULL); + if (err == noErr) + AddFolderIcon(folderRef, folderName); + } + + if (err != noErr && !folderWarning) + { + AppearanceAlert(kAlertCautionAlert, kFolderFail, kFolderHint); + folderWarning = true; + } + else + err = FSRefMakePath(folderRef, (unsigned char *) folderPath, PATH_MAX); + + CFRelease(fstr); + + return (err); +} + +void ChangeTypeAndCreator (const char *path, OSType type, OSType creator) +{ + OSStatus err; + FSRef ref; + + err = FSPathMakeRef((unsigned char *) path, &ref, NULL); + if (err == noErr) + { + FSCatalogInfo catinfo; + + err = FSGetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catinfo, NULL, NULL, NULL); + if (err == noErr) + { + ((FileInfo *) &catinfo.finderInfo)->fileCreator = creator; + ((FileInfo *) &catinfo.finderInfo)->fileType = type; + + err = FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &catinfo); + } + } +} + +static void AddFolderIcon (FSRef *fref, const char *folderName) +{ + OSStatus err; + FSCatalogInfo fcat, icat; + FSRef bref, iref; + CFStringRef str; + CFURLRef url; + IconFamilyHandle family; + IconRef icon; + HFSUniStr255 fork; + Boolean r; + SInt16 resf; + char name[64]; + UniChar iconName[5] = { 'I', 'c', 'o', 'n', '\r' }; + + strcpy(name, "folder_"); + strcat(name, folderName); + + str = CFStringCreateWithCString(kCFAllocatorDefault, name, CFStringGetSystemEncoding()); + if (str) + { + url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), str, CFSTR("icns"), NULL); + if (url) + { + r = CFURLGetFSRef(url, &bref); + if (r) + { + err = RegisterIconRefFromFSRef('~9X~', 'TEMP', &bref, &icon); + if (err == noErr) + { + err = FSGetResourceForkName(&fork); + if (err == noErr) + { + err = FSCreateResourceFile(fref, 5, iconName, kFSCatInfoNone, NULL, fork.length, fork.unicode, &iref, NULL); + if (err == noErr) + { + err = FSOpenResourceFile(&iref, fork.length, fork.unicode, fsWrPerm, &resf); + if (err == noErr) + { + err = IconRefToIconFamily(icon, kSelectorAllAvailableData, &family); + if (err == noErr) + { + AddResource((Handle) family, 'icns', -16455, "\p"); + WriteResource((Handle) family); + ReleaseResource((Handle) family); + + err = FSGetCatalogInfo(&iref, kFSCatInfoFinderInfo, &icat, NULL, NULL, NULL); + ((FileInfo *) &icat.finderInfo)->finderFlags |= kIsInvisible; + ((FileInfo *) &icat.finderInfo)->fileCreator = 'MACS'; + ((FileInfo *) &icat.finderInfo)->fileType = 'icon'; + err = FSSetCatalogInfo(&iref, kFSCatInfoFinderInfo, &icat); + + err = FSGetCatalogInfo(fref, kFSCatInfoFinderInfo, &fcat, NULL, NULL, NULL); + ((FolderInfo *) &fcat.finderInfo)->finderFlags |= kHasCustomIcon; + ((FolderInfo *) &fcat.finderInfo)->finderFlags &= ~kHasBeenInited; + err = FSSetCatalogInfo(fref, kFSCatInfoFinderInfo, &fcat); + } + + CloseResFile(resf); + } + } + } + + err = UnregisterIconRef('~9X~', 'TEMP'); + } + } + + CFRelease(url); + } + + CFRelease(str); + } +} + +Boolean IsLockedMedia (FSVolumeRefNum volume) +{ + OSStatus err; + FSVolumeInfo info; + + err = FSGetVolumeInfo(volume, 0, NULL, kFSVolInfoFlags, &info, NULL, NULL); + if (err == noErr) + { + if ((info.flags & kFSVolFlagHardwareLockedMask) || (info.flags & kFSVolFlagSoftwareLockedMask)) + return (true); + } + + return (false); +} + +const char * S9xGetFilename (const char *inExt, enum s9x_getdirtype dirtype) +{ + static int index = 0; + static char filePath[4][PATH_MAX + 1]; + + OSStatus err; + FSRef ref; + uint32 type; + char folderName[16]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + const char *p; + + index++; + if (index > 3) + index = 0; + + folderName[0] = filePath[index][0] = 0; + + if (strlen(inExt) < 4) + return (filePath[index]); + + p = inExt + strlen(inExt) - 4; + type = ((uint32) p[0] << 24) + ((uint32) p[1] << 16) + ((uint32) p[2] << 8) + (uint32) p[3]; + + switch (type) + { + case '.srm': + case '.rtc': + strcpy(folderName, "SRAMs"); + break; + + case '.frz': + strcpy(folderName, "Freezes"); + break; + + case '.spc': + strcpy(folderName, "SPCs"); + break; + + case '.cht': + strcpy(folderName, "Cheats"); + break; + + case '.ups': + case '.ips': + strcpy(folderName, "Patches"); + break; + + case '.png': + strcpy(folderName, "Screenshots"); + break; + + case '.dat': + case '.out': + strcpy(folderName, "Logs"); + break; + + case '.bio': // dummy + strcpy(folderName, "BIOSes"); + break; + } + + if (folderName[0] && ((saveInROMFolder != 1) || lockedROMMedia)) + { + char s[PATH_MAX + 1]; + + s[0] = 0; + + if (saveInROMFolder == 0) + err = FindSNESFolder(&ref, s, folderName); + else + err = FindApplicationSupportFolder(&ref, s, folderName); + + if (err == noErr) + { + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + snprintf(filePath[index], PATH_MAX + 1, "%s%s%s%s", s, MAC_PATH_SEPARATOR, fname, inExt); + } + else + { + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + _makepath(filePath[index], drive, dir, fname, inExt); + } + } + else + { + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + _makepath(filePath[index], drive, dir, fname, inExt); + } + + return (filePath[index]); +} + +const char * S9xGetSPCFilename (void) +{ + char spcExt[16]; + + sprintf(spcExt, ".%03d.spc", (int) spcFileCount); + + spcFileCount++; + if (spcFileCount == 1000) + spcFileCount = 0; + + return (S9xGetFilename(spcExt, SPC_DIR)); +} + +const char * S9xGetPNGFilename (void) +{ + char pngExt[16]; + + sprintf(pngExt, ".%03d.png", (int) pngFileCount); + + pngFileCount++; + if (pngFileCount == 1000) + pngFileCount = 0; + + return (S9xGetFilename(pngExt, SCREENSHOT_DIR)); +} + +const char * S9xGetFreezeFilename (int which) +{ + char frzExt[16]; + + sprintf(frzExt, ".%03d.frz", which); + + return (S9xGetFilename(frzExt, SNAPSHOT_DIR)); +} + +const char * S9xGetFilenameInc (const char *inExt, enum s9x_getdirtype dirtype) +{ + uint32 type; + const char *p; + + if (strlen(inExt) < 4) + return (NULL); + + p = inExt + strlen(inExt) - 4; + type = ((uint32) p[0] << 24) + ((uint32) p[1] << 16) + ((uint32) p[2] << 8) + (uint32) p[3]; + + switch (type) + { + case '.spc': + return (S9xGetSPCFilename()); + + case '.png': + return (S9xGetPNGFilename()); + } + + return (NULL); +} + +const char * S9xChooseFilename (bool8 read_only) +{ + return (NULL); +} + +const char * S9xChooseMovieFilename (bool8 read_only) +{ + return (NULL); +} + +bool8 S9xOpenSnapshotFile (const char *fname, bool8 read_only, STREAM *file) +{ + if (read_only) + { + if (0 != (*file = OPEN_STREAM(fname, "rb"))) + return (true); + } + else + { + if (0 != (*file = OPEN_STREAM(fname, "wb"))) + return (true); + } + + return (false); +} + +void S9xCloseSnapshotFile (STREAM file) +{ + CLOSE_STREAM(file); +} + +const char * S9xBasename (const char *in) +{ + static char s[PATH_MAX + 1]; + + strncpy(s, in, PATH_MAX + 1); + s[PATH_MAX] = 0; + + size_t l = strlen(s); + + for (unsigned int i = 0; i < l; i++) + { + if (s[i] < 32 || s[i] >= 127) + s[i] = '_'; + } + + return (basename(s)); +} + +const char * S9xGetDirectory (enum s9x_getdirtype dirtype) +{ + static int index = 0; + static char path[4][PATH_MAX + 1]; + + char inExt[16]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + index++; + if (index > 3) + index = 0; + + switch (dirtype) + { + case SNAPSHOT_DIR: strcpy(inExt, ".frz"); break; + case SRAM_DIR: strcpy(inExt, ".srm"); break; + case SCREENSHOT_DIR: strcpy(inExt, ".png"); break; + case SPC_DIR: strcpy(inExt, ".spc"); break; + case CHEAT_DIR: strcpy(inExt, ".cht"); break; + case BIOS_DIR: strcpy(inExt, ".bio"); break; + default: strcpy(inExt, ".xxx"); break; + } + + _splitpath(S9xGetFilename(inExt, dirtype), drive, dir, fname, ext); + _makepath(path[index], drive, dir, "", ""); + + int l = strlen(path[index]); + if (l > 1) + path[index][l - 1] = 0; + + return (path[index]); +} + +void _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext) +{ + drive[0] = 0; + fname[0] = 0; + ext[0] = 0; + dir[0] = 0; + + int x; + + x = strlen(path) - 1; + if (x < 0) + return; + + while (x && (path[x] != MAC_PATH_SEP_CHAR)) + x--; + + if (x) + { + strcpy(dir, path); + dir[x + 1] = 0; + + strcpy(fname, path + x + 1); + } + else + strcpy(fname, path); + + x = strlen(fname); + while (x && (fname[x] != '.')) + x--; + + if (x) + { + strcpy(ext, fname + x); + fname[x] = 0; + } +} + +void _makepath (char *path, const char *drive, const char *dir, const char *fname, const char *ext) +{ + static const char emp[] = "", dot[] = "."; + + const char *d, *f, *e, *p; + + d = dir ? dir : emp; + f = fname ? fname : emp; + e = ext ? ext : emp; + p = (e[0] && e[0] != '.') ? dot : emp; + + snprintf(path, PATH_MAX + 1, "%s%s%s%s", d, f, p, e); +} diff --git a/macosx/mac-file.h b/macosx/mac-file.h new file mode 100644 index 00000000..711ee7a2 --- /dev/null +++ b/macosx/mac-file.h @@ -0,0 +1,200 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_file_h_ +#define _mac_file_h_ + +void ChangeTypeAndCreator (const char *, OSType, OSType); +Boolean IsLockedMedia (FSVolumeRefNum); +const char * S9xGetSPCFilename (void); +const char * S9xGetPNGFilename (void); +const char * S9xGetFreezeFilename (int); + +#endif diff --git a/macosx/mac-global_prefix.h b/macosx/mac-global_prefix.h new file mode 100644 index 00000000..5d8041dd --- /dev/null +++ b/macosx/mac-global_prefix.h @@ -0,0 +1,208 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#undef READ_WORD(s) +#undef READ_3WORD(s) +#undef READ_DWORD(s) +#undef WRITE_WORD(s, d) +#undef WRITE_3WORD(s, d) +#undef WRITE_DWORD(s, d) + +#define ZLIB +#define UNZIP_SUPPORT +#define JMA_SUPPORT +#define CPU_SHUTDOWN +#define USE_OPENGL +#define RIGHTSHIFT_IS_SAR +#define CORRECT_VRAM_READS +#define HAVE_STDINT_H +//#define DEBUGGER + +#define __MACOSX__ diff --git a/macosx/mac-gworld.cpp b/macosx/mac-gworld.cpp new file mode 100644 index 00000000..cddcfb9c --- /dev/null +++ b/macosx/mac-gworld.cpp @@ -0,0 +1,431 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "port.h" + +#include "mac-prefix.h" +#include "mac-os.h" +#include "mac-gworld.h" + +#define kIconSize 16 + +static void SetIconImage (CGImageRef, CGRect, int); +#ifdef MAC_PANTHER_SUPPORT +static IconRef CreateIconRefFromImage (CGImageRef, CGRect); +#endif + + +void DrawSubCGImage (CGContextRef ctx, CGImageRef image, CGRect src, CGRect dst) +{ + float w = (float) CGImageGetWidth(image); + float h = (float) CGImageGetHeight(image); + + CGRect drawRect = CGRectMake(0.0f, 0.0f, w, h); + + if (!CGRectEqualToRect(src, dst)) + { + float sx = CGRectGetWidth(dst) / CGRectGetWidth(src); + float sy = CGRectGetHeight(dst) / CGRectGetHeight(src); + float dx = CGRectGetMinX(dst) - (CGRectGetMinX(src) * sx); + float dy = CGRectGetMinY(dst) - (CGRectGetMinY(src) * sy); + + drawRect = CGRectMake(dx, dy, w * sx, h * sy); + } + + CGContextSaveGState(ctx); + CGContextClipToRect(ctx, dst); + CGContextDrawImage(ctx, drawRect, image); + CGContextRestoreGState(ctx); +} + +static void SetIconImage (CGImageRef image, CGRect rct, int n) +{ + if (systemVersion >= 0x1040) + macIconImage[n] = CGImageCreateWithImageInRect(image, rct); +#ifdef MAC_PANTHER_SUPPORT + else + macIconRef[n] = CreateIconRefFromImage(image, rct); +#endif +} + +void CreateIconImages (void) +{ + CGDataProviderRef prov; + CGImageRef image; + CFURLRef url; + + image = NULL; + memset(macIconImage, 0, sizeof(macIconImage)); +#ifdef MAC_PANTHER_SUPPORT + if (systemVersion < 0x1040) + memset(macIconRef, 0, sizeof(macIconRef)); +#endif + + url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("icons"), CFSTR("png"), NULL); + if (url) + { + prov = CGDataProviderCreateWithURL(url); + if (prov) + { + image = CGImageCreateWithPNGDataProvider(prov, NULL, true, kCGRenderingIntentDefault); + CGDataProviderRelease(prov); + } + + CFRelease(url); + } + + if (image) + { + int x, y, v = 0, n = 0; + + macPadIconIndex = n; + for (y = 0; y < 8; y++) + { + for (x = 0; x < 12; x++) + SetIconImage(image, CGRectMake(x * kIconSize, v, kIconSize, kIconSize), n++); + v += kIconSize; + } + + macLegendIconIndex = n; + for (x = 0; x < 2; x++) + SetIconImage(image, CGRectMake(x * kIconSize, v, kIconSize, kIconSize), n++); + v += kIconSize; + + macMusicBoxIconIndex = n; + for (x = 0; x < 3; x++) + SetIconImage(image, CGRectMake(x * kIconSize, v, kIconSize, kIconSize), n++); + v += kIconSize; + + macFunctionIconIndex = n; + for (x = 0; x < 17; x++) + SetIconImage(image, CGRectMake(x * kIconSize, v, kIconSize, kIconSize), n++); + + CGImageRelease(image); + + #ifdef MAC_PANTHER_SUPPORT + if (systemVersion < 0x1040) + { + CGColorSpaceRef color; + CGContextRef ctx; + CGRect rct; + static UInt32 data[2][kIconSize * kIconSize]; + + rct = CGRectMake(0, 0, kIconSize, kIconSize); + + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + for (int i = 0; i < 2; i++) + { + ctx = CGBitmapContextCreate(data[i], kIconSize, kIconSize, 8, kIconSize * 4, color, kCGImageAlphaNoneSkipFirst); + if (ctx) + { + PlotIconRefInContext(ctx, &rct, kAlignNone, kTransformNone, NULL, kPlotIconRefNormalFlags, macIconRef[macLegendIconIndex + i]); + CGContextRelease(ctx); + + prov = CGDataProviderCreateWithData(NULL, data[i], kIconSize * kIconSize * 4, NULL); + if (prov) + { + macIconImage[macLegendIconIndex + i] = CGImageCreate(kIconSize, kIconSize, 8, 32, kIconSize * 4, color, kCGImageAlphaNoneSkipFirst, prov, NULL, 1, kCGRenderingIntentDefault); + CGDataProviderRelease(prov); + } + } + } + + CGColorSpaceRelease(color); + } + } + #endif + } +} + +void ReleaseIconImages (void) +{ + for (int i = 0; i < 118; i++) + { + if (systemVersion >= 0x1040) + { + if (macIconImage[i]) + CGImageRelease(macIconImage[i]); + } + #ifdef MAC_PANTHER_SUPPORT + else + { + if (macIconRef[i]) + ReleaseIconRef(macIconRef[i]); + } + #endif + } + +#ifdef MAC_PANTHER_SUPPORT + if (systemVersion < 0x1040) + { + if (macIconImage[macLegendIconIndex]) + CGImageRelease(macIconImage[macLegendIconIndex]); + if (macIconImage[macLegendIconIndex + 1]) + CGImageRelease(macIconImage[macLegendIconIndex + 1]); + } +#endif +} + +#ifdef MAC_PANTHER_SUPPORT +static IconRef CreateIconRefFromImage (CGImageRef srcImage, CGRect srcRect) +{ + OSStatus err; + CGContextRef cctx, actx; + CGColorSpaceRef color; + CGRect dstRect; + IconRef iconRef; + IconFamilyHandle icns; + Handle hdl; + SInt32 size; + UInt32 rgb[kIconSize * kIconSize]; + UInt8 alp[kIconSize * kIconSize]; + + srcRect.origin.y = CGImageGetHeight(srcImage) - srcRect.origin.y - kIconSize; + + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + cctx = CGBitmapContextCreate(rgb, kIconSize, kIconSize, 8, kIconSize * 4, color, kCGImageAlphaNoneSkipFirst); + if (cctx) + { + dstRect = CGRectMake(0, 0, kIconSize, kIconSize); + DrawSubCGImage(cctx, srcImage, srcRect, dstRect); + + actx = CGBitmapContextCreate(alp, kIconSize, kIconSize, 8, kIconSize, NULL, kCGImageAlphaOnly); + if (actx) + { + DrawSubCGImage(actx, srcImage, srcRect, dstRect); + CGContextRelease(actx); + } + + CGContextRelease(cctx); + } + + CGColorSpaceRelease(color); + } + + iconRef = NULL; + + size = sizeof(OSType) + sizeof(SInt32); + icns = (IconFamilyHandle) NewHandle(size); + if (icns) + { + // Big-endian: Panther is for PowerPC only + (*icns)->resourceType = kIconFamilyType; + (*icns)->resourceSize = size; + + err = PtrToHand(rgb, &hdl, sizeof(rgb)); + if (err == noErr) + { + err = SetIconFamilyData(icns, kSmall32BitData, hdl); + DisposeHandle(hdl); + + if (err == noErr) + { + err = PtrToHand(alp, &hdl, sizeof(alp)); + if (err == noErr) + { + err = SetIconFamilyData(icns, kSmall8BitMask, hdl); + DisposeHandle(hdl); + } + } + } + + if (err == noErr) + err = GetIconRefFromIconFamilyPtr(*icns, GetHandleSize((Handle) icns), &iconRef); + + DisposeHandle((Handle) icns); + } + + return (iconRef); +} +#endif diff --git a/macosx/mac-gworld.h b/macosx/mac-gworld.h new file mode 100644 index 00000000..87b1e100 --- /dev/null +++ b/macosx/mac-gworld.h @@ -0,0 +1,198 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_gworld_h_ +#define _mac_gworld_h_ + +void DrawSubCGImage (CGContextRef, CGImageRef, CGRect, CGRect); +void CreateIconImages (void); +void ReleaseIconImages (void); + +#endif diff --git a/macosx/mac-joypad.cpp b/macosx/mac-joypad.cpp new file mode 100644 index 00000000..c2b8f5b2 --- /dev/null +++ b/macosx/mac-joypad.cpp @@ -0,0 +1,1318 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "port.h" + +#include +#include "HID_Utilities_External.h" + +#include "mac-prefix.h" +#include "mac-dialog.h" +#include "mac-os.h" +#include "mac-joypad.h" + +#define kUp(i) (i * 4) +#define kDn(i) (i * 4 + 1) +#define kLf(i) (i * 4 + 2) +#define kRt(i) (i * 4 + 3) + +#define kPadElemTypeNone 0 +#define kPadElemTypeHat4 1 +#define kPadElemTypeHat8 2 +#define kPadElemTypeAxis 3 +#define kPadElemTypeButton 4 +#define kPadElemTypeOtherHat4 5 +#define kPadElemTypeOtherHat8 6 + +#define kPadXAxis 1 +#define kPadYAxis 0 +#define kPadHat 0 + +#define kMaskUp 0x0800 +#define kMaskDn 0x0400 +#define kMaskLf 0x0200 +#define kMaskRt 0x0100 + +typedef hu_device_t *pRecDevice; +typedef hu_element_t *pRecElement; + +typedef struct actionStruct +{ + pRecDevice fDevice; + pRecElement fElement; + long fValue; + long fOldValue; +} actionRec, *actionPtr; + +typedef struct padDirectionInfo +{ + int type; + pRecDevice device [2]; + pRecElement element[2]; + long max [2]; + long maxmid [2]; + long mid [2]; + long midmin [2]; + long min [2]; +} directionInfo; + +static actionRec gActionRecs[kNeedCount]; +static directionInfo gDirectionInfo[MAC_MAX_PLAYERS]; +static int gDirectionHint[MAC_MAX_PLAYERS]; + +static const HIViewID gControlIDs[kNeedCount] = +{ + { '1_Up', 0 }, + { '1_Dn', 0 }, + { '1_Lf', 0 }, + { '1_Rt', 0 }, + + { '2_Up', 0 }, + { '2_Dn', 0 }, + { '2_Lf', 0 }, + { '2_Rt', 0 }, + + { '3_Up', 0 }, + { '3_Dn', 0 }, + { '3_Lf', 0 }, + { '3_Rt', 0 }, + + { '4_Up', 0 }, + { '4_Dn', 0 }, + { '4_Lf', 0 }, + { '4_Rt', 0 }, + + { '5_Up', 0 }, + { '5_Dn', 0 }, + { '5_Lf', 0 }, + { '5_Rt', 0 }, + + { '6_Up', 0 }, + { '6_Dn', 0 }, + { '6_Lf', 0 }, + { '6_Rt', 0 }, + + { '7_Up', 0 }, + { '7_Dn', 0 }, + { '7_Lf', 0 }, + { '7_Rt', 0 }, + + { '8_Up', 0 }, + { '8_Dn', 0 }, + { '8_Lf', 0 }, + { '8_Rt', 0 }, + + { '1__B', 0 }, + { '1__A', 0 }, + { '1__X', 0 }, + { '1__Y', 0 }, + { '1__L', 0 }, + { '1__R', 0 }, + { '1Sel', 0 }, + { '1Srt', 0 }, + + { '2__B', 0 }, + { '2__A', 0 }, + { '2__X', 0 }, + { '2__Y', 0 }, + { '2__L', 0 }, + { '2__R', 0 }, + { '2Sel', 0 }, + { '2Srt', 0 }, + + { '3__B', 0 }, + { '3__A', 0 }, + { '3__X', 0 }, + { '3__Y', 0 }, + { '3__L', 0 }, + { '3__R', 0 }, + { '3Sel', 0 }, + { '3Srt', 0 }, + + { '4__B', 0 }, + { '4__A', 0 }, + { '4__X', 0 }, + { '4__Y', 0 }, + { '4__L', 0 }, + { '4__R', 0 }, + { '4Sel', 0 }, + { '4Srt', 0 }, + + { '5__B', 0 }, + { '5__A', 0 }, + { '5__X', 0 }, + { '5__Y', 0 }, + { '5__L', 0 }, + { '5__R', 0 }, + { '5Sel', 0 }, + { '5Srt', 0 }, + + { '6__B', 0 }, + { '6__A', 0 }, + { '6__X', 0 }, + { '6__Y', 0 }, + { '6__L', 0 }, + { '6__R', 0 }, + { '6Sel', 0 }, + { '6Srt', 0 }, + + { '7__B', 0 }, + { '7__A', 0 }, + { '7__X', 0 }, + { '7__Y', 0 }, + { '7__L', 0 }, + { '7__R', 0 }, + { '7Sel', 0 }, + { '7Srt', 0 }, + + { '8__B', 0 }, + { '8__A', 0 }, + { '8__X', 0 }, + { '8__Y', 0 }, + { '8__L', 0 }, + { '8__R', 0 }, + { '8Sel', 0 }, + { '8Srt', 0 }, + + { '__FF', 0 }, + { '_Frz', 0 }, + { '_DeF', 0 }, + { '_Snp', 0 }, + { '_Esc', 0 }, + { '_SPC', 0 }, + { 'MouL', 0 }, + { 'MouR', 0 }, + { 'ScoT', 0 }, + { 'ScoP', 0 }, + { 'ScoC', 0 }, + { 'Ofsc', 0 }, + { '__Fn', 0 }, + { '_Alt', 0 }, + { 'FFUp', 0 }, + { 'FFDn', 0 }, + { '__TC', 0 } +}; + +static char gNeeds[kNeedCount][64] = +{ + "1P Up", + "1P Down", + "1P Left", + "1P Right", + + "2P Up", + "2P Down", + "2P Left", + "2P Right", + + "3P Up", + "3P Down", + "3P Left", + "3P Right", + + "4P Up", + "4P Down", + "4P Left", + "4P Right", + + "5P Up", + "5P Down", + "5P Left", + "5P Right", + + "6P Up", + "6P Down", + "6P Left", + "6P Right", + + "7P Up", + "7P Down", + "7P Left", + "7P Right", + + "8P Up", + "8P Down", + "8P Left", + "8P Right", + + "1P B Button", + "1P A Button", + "1P X Button", + "1P Y Button", + "1P L Button", + "1P R Button", + "1P Select", + "1P Start", + + "2P B Button", + "2P A Button", + "2P X Button", + "2P Y Button", + "2P L Button", + "2P R Button", + "2P Select", + "2P Start", + + "3P B Button", + "3P A Button", + "3P X Button", + "3P Y Button", + "3P L Button", + "3P R Button", + "3P Select", + "3P Start", + + "4P B Button", + "4P A Button", + "4P X Button", + "4P Y Button", + "4P L Button", + "4P R Button", + "4P Select", + "4P Start", + + "5P B Button", + "5P A Button", + "5P X Button", + "5P Y Button", + "5P L Button", + "5P R Button", + "5P Select", + "5P Start", + + "6P B Button", + "6P A Button", + "6P X Button", + "6P Y Button", + "6P L Button", + "6P R Button", + "6P Select", + "6P Start", + + "7P B Button", + "7P A Button", + "7P X Button", + "7P Y Button", + "7P L Button", + "7P R Button", + "7P Select", + "7P Start", + + "8P B Button", + "8P A Button", + "8P X Button", + "8P Y Button", + "8P L Button", + "8P R Button", + "8P Select", + "8P Start", + + "Fast Forward", + "Freeze Game", + "Defrost Game", + "Screenshot", + "Break", + "Save SPC", + "Mouse Left", + "Mouse Right", + "Scope Turbo", + "Scope Pause", + "Scope Cursor", + "Offscreen", + "Fn Modifier", + "Alt Modifier", + "Turbo Speed Up", + "Turbo Speed Down", + "Turbo Control Modifier" +}; + +static int gIconNumber[kNeedCount] = +{ + 0, + 1, + 2, + 3, + + 12, + 13, + 14, + 15, + + 24, + 25, + 26, + 27, + + 36, + 37, + 38, + 39, + + 48, + 49, + 50, + 51, + + 60, + 61, + 62, + 63, + + 72, + 73, + 74, + 75, + + 84, + 85, + 86, + 87, + + 5, + 7, + 6, + 4, + 8, + 9, + 11, + 10, + + 17, + 19, + 18, + 16, + 20, + 21, + 23, + 22, + + 29, + 31, + 30, + 28, + 32, + 33, + 35, + 34, + + 41, + 43, + 42, + 40, + 44, + 45, + 47, + 46, + + 53, + 55, + 54, + 52, + 56, + 57, + 59, + 58, + + 65, + 67, + 66, + 64, + 68, + 69, + 71, + 70, + + 77, + 79, + 78, + 76, + 80, + 81, + 83, + 82, + + 89, + 91, + 90, + 88, + 92, + 93, + 95, + 94, + + 101, + 102, + 103, + 104, + 114, + 105, + 116, + 117, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 115 +}; + +static void JoypadSetDirectionInfo (void); +static pascal void IdleTimer (EventLoopTimerRef, void *); +static pascal OSStatus ControllerEventHandler (EventHandlerCallRef, EventRef, void *); + + +void SaveControllerSettings (void) +{ + CFStringRef keyCFStringRef; + Boolean syncFlag; + + JoypadSetDirectionInfo(); + + for (int a = 0; a < kNeedCount; a++) + { + char needCStr[64], num[10]; + + strcpy(needCStr, gNeeds[a]); + if (padSetting > 1) + { + sprintf(num, "_%d", padSetting); + strcat(needCStr, num); + } + + keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s"), needCStr); + if (keyCFStringRef) + { + if (gActionRecs[a].fDevice && gActionRecs[a].fElement) + syncFlag = HIDSaveElementPref(keyCFStringRef, kCFPreferencesCurrentApplication, gActionRecs[a].fDevice, gActionRecs[a].fElement); + else + CFPreferencesSetAppValue(keyCFStringRef, NULL, kCFPreferencesCurrentApplication); + + CFRelease(keyCFStringRef); + } + } + + for (int a = 0; a < MAC_MAX_PLAYERS; a++) + { + keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DirectionHint_%d_%d"), a, padSetting); + if (keyCFStringRef) + { + CFNumberRef numRef; + CFIndex v; + + v = (CFIndex) gDirectionHint[a]; + numRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberCFIndexType, &v); + if (numRef) + { + CFPreferencesSetAppValue(keyCFStringRef, numRef, kCFPreferencesCurrentApplication); + CFRelease(numRef); + } + + CFRelease(keyCFStringRef); + } + } + + CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); +} + +void LoadControllerSettings (void) +{ + CFStringRef keyCFStringRef; + + for (int a = 0; a < kNeedCount; a++) + { + pRecDevice pDevice = NULL; + pRecElement pElement = NULL; + Boolean r = false; + char needCStr[64], num[10]; + + strcpy(needCStr, gNeeds[a]); + if (padSetting > 1) + { + sprintf(num, "_%d", padSetting); + strcat(needCStr, num); + } + + keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s"), needCStr); + if (keyCFStringRef) + { + r = HIDRestoreElementPref(keyCFStringRef, kCFPreferencesCurrentApplication, &pDevice, &pElement); + if (r && pDevice && pElement) + { + gActionRecs[a].fDevice = pDevice; + gActionRecs[a].fElement = pElement; + } + else + { + gActionRecs[a].fDevice = NULL; + gActionRecs[a].fElement = NULL; + } + + CFRelease(keyCFStringRef); + } + } + + for (int a = 0; a < MAC_MAX_PLAYERS; a++) + { + keyCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("DirectionHint_%d_%d"), a, padSetting); + if (keyCFStringRef) + { + Boolean r; + + gDirectionHint[a] = (int) CFPreferencesGetAppIntegerValue(keyCFStringRef, kCFPreferencesCurrentApplication, &r); + if (!r) + gDirectionHint[a] = kPadElemTypeNone; + + CFRelease(keyCFStringRef); + } + else + gDirectionHint[a] = kPadElemTypeNone; + } + + JoypadSetDirectionInfo(); +} + +static pascal OSStatus ControllerEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef tWindowRef; + + tWindowRef = (WindowRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + switch (GetEventKind(inEvent)) + { + case kEventWindowClose: + QuitAppModalLoopForWindow(tWindowRef); + result = noErr; + break; + } + + break; + + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(true); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + if (tHICommand.commandID == 'CLRa') + { + ClearPadSetting(); + result = noErr; + } + else + { + SInt32 command = -1, count; + + for (count = 0; count < kNeedCount; count++) + if (tHICommand.commandID == gControlIDs[count].signature) + command = count; + + if (command >= 0) + { + pRecDevice pDevice; + pRecElement pElement; + + FlushEventQueue(GetCurrentEventQueue()); + + if (HIDConfigureAction(&pDevice, &pElement, 2.5f)) + { + if (command < MAC_MAX_PLAYERS * 4) // Direction + { + int i = command >> 2; // Player + long curv = HIDGetElementValue(pDevice, pElement); + + if (pElement->usage == kHIDUsage_GD_Hatswitch) // Hat Switch + { + gActionRecs[kUp(i)].fDevice = gActionRecs[kDn(i)].fDevice = gActionRecs[kLf(i)].fDevice = gActionRecs[kRt(i)].fDevice = pDevice; + gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = pElement; + + if (pDevice->vendorID == 1103) // Thrustmaster + gDirectionInfo[i].type = (pElement->max > 4) ? kPadElemTypeOtherHat8 : kPadElemTypeOtherHat4; + else + { + if (pElement->max > 4) + { + if (((command % 4 == 0) && (curv == 0)) || // Up : 0 + ((command % 4 == 1) && (curv == 4)) || // Down : 4 + ((command % 4 == 2) && (curv == 6)) || // Left : 6 + ((command % 4 == 3) && (curv == 2))) // Right : 2 + gDirectionInfo[i].type = kPadElemTypeOtherHat8; + else + gDirectionInfo[i].type = kPadElemTypeHat8; + } + else + { + if (((command % 4 == 0) && (curv == 0)) || // Up : 0 + ((command % 4 == 1) && (curv == 2)) || // Down : 2 + ((command % 4 == 2) && (curv == 3)) || // Left : 3 + ((command % 4 == 3) && (curv == 1))) // Right : 1 + gDirectionInfo[i].type = kPadElemTypeOtherHat4; + else + gDirectionInfo[i].type = kPadElemTypeHat4; + } + } + + gDirectionInfo[i].device [kPadHat] = pDevice; + gDirectionInfo[i].element[kPadHat] = pElement; + gDirectionInfo[i].max [kPadHat] = pElement->max; + gDirectionInfo[i].min [kPadHat] = pElement->min; + } + else + if (pElement->max - pElement->min > 1) // Axis (maybe) + { + if ((command % 4 == 0) || (command % 4 == 1)) // Up or Dn + { + gActionRecs[kUp(i)].fDevice = gActionRecs[kDn(i)].fDevice = pDevice; + gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = pElement; + + gDirectionInfo[i].type = kPadElemTypeAxis; + gDirectionInfo[i].device [kPadYAxis] = pDevice; + gDirectionInfo[i].element[kPadYAxis] = pElement; + gDirectionInfo[i].max [kPadYAxis] = pElement->max; + gDirectionInfo[i].min [kPadYAxis] = pElement->min; + gDirectionInfo[i].mid [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1; + gDirectionInfo[i].maxmid [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].mid[kPadYAxis]) >> 1; + gDirectionInfo[i].midmin [kPadYAxis] = (gDirectionInfo[i].mid[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1; + } + else // Lf or Rt + { + gActionRecs[kLf(i)].fDevice = gActionRecs[kRt(i)].fDevice = pDevice; + gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = pElement; + + gDirectionInfo[i].type = kPadElemTypeAxis; + gDirectionInfo[i].device [kPadXAxis] = pDevice; + gDirectionInfo[i].element[kPadXAxis] = pElement; + gDirectionInfo[i].max [kPadXAxis] = pElement->max; + gDirectionInfo[i].min [kPadXAxis] = pElement->min; + gDirectionInfo[i].mid [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1; + gDirectionInfo[i].maxmid [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].mid[kPadXAxis]) >> 1; + gDirectionInfo[i].midmin [kPadXAxis] = (gDirectionInfo[i].mid[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1; + } + } + else // Button (maybe) + { + gActionRecs[command].fDevice = pDevice; + gActionRecs[command].fElement = pElement; + gDirectionInfo[i].type = kPadElemTypeButton; + } + + gDirectionHint[i] = gDirectionInfo[i].type; + } + else + { + gActionRecs[command].fDevice = pDevice; + gActionRecs[command].fElement = pElement; + } + } + else + { + if (command < MAC_MAX_PLAYERS * 4) // Direction + { + int i = command >> 2; // Player + + gActionRecs[kUp(i)].fDevice = gActionRecs[kDn(i)].fDevice = gActionRecs[kLf(i)].fDevice = gActionRecs[kRt(i)].fDevice = NULL; + gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = NULL; + + gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeNone; + gDirectionInfo[i].device [0] = gDirectionInfo[i].device [1] = NULL; + gDirectionInfo[i].element[0] = gDirectionInfo[i].element[1] = NULL; + } + else + { + gActionRecs[command].fDevice = NULL; + gActionRecs[command].fElement = NULL; + } + } + + gActionRecs[command].fValue = 0; + gActionRecs[command].fOldValue = -2; + + FlushEventQueue(GetCurrentEventQueue()); + + result = noErr; + } + } + } + + break; + } + + break; + } + + return (result); +} + +static pascal void IdleTimer (EventLoopTimerRef inTimer, void *userData) +{ + static uint32 old[MAC_MAX_PLAYERS] = { ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 }; + + HIViewRef ctl, root; + uint32 pad[MAC_MAX_PLAYERS]; + + root = HIViewGetRoot((WindowRef) userData); + + for (int i = 0; i < MAC_MAX_PLAYERS; i++) + { + pad[i] = 0; + JoypadScanDirection(i, &(pad[i])); + + if (old[i] != pad[i]) + { + old[i] = pad[i]; + + HIViewFindByID(root, gControlIDs[kUp(i)], &ctl); + SetControl32BitValue(ctl, (pad[i] & kMaskUp) ? 1 : 0); + HIViewFindByID(root, gControlIDs[kDn(i)], &ctl); + SetControl32BitValue(ctl, (pad[i] & kMaskDn) ? 1 : 0); + HIViewFindByID(root, gControlIDs[kLf(i)], &ctl); + SetControl32BitValue(ctl, (pad[i] & kMaskLf) ? 1 : 0); + HIViewFindByID(root, gControlIDs[kRt(i)], &ctl); + SetControl32BitValue(ctl, (pad[i] & kMaskRt) ? 1 : 0); + } + } + + for (int i = MAC_MAX_PLAYERS * 4; i < kNeedCount; i++) + { + gActionRecs[i].fValue = ISpKeyIsPressed(i); + + if (gActionRecs[i].fOldValue != gActionRecs[i].fValue) + { + gActionRecs[i].fOldValue = gActionRecs[i].fValue; + + HIViewFindByID(root, gControlIDs[i], &ctl); + SetControl32BitValue(ctl, (gActionRecs[i].fValue ? 1 : 0)); + } + } +} + +void SetUpHID (void) +{ + pRecDevice device; + + HIDBuildDeviceList(NULL, NULL); + device = HIDGetFirstDevice(); + if (!device) + { + hidExist = false; + return; + } + + hidExist = true; + + ClearPadSetting(); + + LoadControllerSettings(); +} + +void ClearPadSetting (void) +{ + for (int i = 0; i < MAC_MAX_PLAYERS; i++) + { + gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeNone; + gDirectionInfo[i].device [0] = gDirectionInfo[i].device [1] = NULL; + gDirectionInfo[i].element[0] = gDirectionInfo[i].element[1] = NULL; + } + + for (int i = 0; i < kNeedCount; i++) + { + gActionRecs[i].fDevice = NULL; + gActionRecs[i].fElement = NULL; + gActionRecs[i].fValue = 0; + gActionRecs[i].fOldValue = -2; + } +} + +void ReleaseHID (void) +{ + if (hidExist) + HIDReleaseDeviceList(); +} + +void ConfigureHID (void) +{ + OSStatus err; + IBNibRef nibRef; + + if (!hidExist) + return; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef tWindowRef; + + err = CreateWindowFromNib(nibRef, CFSTR("Controllers"), &tWindowRef); + if (err == noErr) + { + EventHandlerRef eref; + EventLoopTimerRef tref; + EventHandlerUPP eventUPP; + EventLoopTimerUPP timerUPP; + EventTypeSpec windowEvents[] = { { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus }, + { kEventClassWindow, kEventWindowClose } }; + HIViewRef ctl, root; + HIViewID cid; + CFStringRef str1, str2; + ControlButtonContentInfo info; + + LoadControllerSettings(); + + root = HIViewGetRoot(tWindowRef); + cid.id = 0; + cid.signature = 'PRES'; + HIViewFindByID(root, cid, &ctl); + str1 = CFCopyLocalizedString(CFSTR("PresetNum"), "PresetNum"); + str2 = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, str1, padSetting); + SetStaticTextCFString(ctl, str2, false); + CFRelease(str2); + CFRelease(str1); + + if (systemVersion >= 0x1040) + { + info.contentType = kControlContentCGImageRef; + for (int i = 0; i < kNeedCount; i++) + { + HIViewFindByID(root, gControlIDs[i], &ctl); + info.u.imageRef = macIconImage[gIconNumber[i]]; + err = SetBevelButtonContentInfo(ctl, &info); + } + } + #ifdef MAC_PANTHER_SUPPORT + else + { + info.contentType = kControlContentIconRef; + for (int i = 0; i < kNeedCount; i++) + { + HIViewFindByID(root, gControlIDs[i], &ctl); + info.u.iconRef = macIconRef[gIconNumber[i]]; + err = SetBevelButtonContentInfo(ctl, &info); + } + } + #endif + + eventUPP = NewEventHandlerUPP(ControllerEventHandler); + err = InstallWindowEventHandler(tWindowRef, eventUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) tWindowRef, &eref); + + timerUPP = NewEventLoopTimerUPP(IdleTimer); + err = InstallEventLoopTimer(GetCurrentEventLoop(), 0.0f, 0.1f, timerUPP, (void *) tWindowRef, &tref); + + MoveWindowPosition(tWindowRef, kWindowControllers, false); + ShowWindow(tWindowRef); + err = RunAppModalLoopForWindow(tWindowRef); + HideWindow(tWindowRef); + SaveWindowPosition(tWindowRef, kWindowControllers); + + err = RemoveEventLoopTimer(tref); + DisposeEventLoopTimerUPP(timerUPP); + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eventUPP); + + CFRelease(tWindowRef); + + SaveControllerSettings(); + } + + DisposeNibReference(nibRef); + } +} + +long ISpKeyIsPressed (int needID) +{ + return (gActionRecs[needID].fDevice ? HIDGetElementValue(gActionRecs[needID].fDevice, gActionRecs[needID].fElement) : 0); +} + +void JoypadScanDirection (int i, uint32 *pad) +{ + long state; + + switch (gDirectionInfo[i].type) + { + case kPadElemTypeAxis: // Axis (maybe) + if (gDirectionInfo[i].device[kPadYAxis]) // Y-Axis + { + state = HIDGetElementValue(gDirectionInfo[i].device[kPadYAxis], gDirectionInfo[i].element[kPadYAxis]); + if (state >= gDirectionInfo[i].maxmid[kPadYAxis]) + *pad |= kMaskDn; + else + if (state <= gDirectionInfo[i].midmin[kPadYAxis]) + *pad |= kMaskUp; + } + + if (gDirectionInfo[i].device[kPadXAxis]) // X-Axis + { + state = HIDGetElementValue(gDirectionInfo[i].device[kPadXAxis], gDirectionInfo[i].element[kPadXAxis]); + if (state >= gDirectionInfo[i].maxmid[kPadXAxis]) + *pad |= kMaskRt; + else + if (state <= gDirectionInfo[i].midmin[kPadXAxis]) + *pad |= kMaskLf; + } + + break; + + case kPadElemTypeHat8: // Hat Switch (8 Directions) + if (gDirectionInfo[i].device[kPadHat]) + { + state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]); + switch (state) + { + case 1: *pad |= kMaskUp ; break; + case 2: *pad |= (kMaskUp | kMaskRt); break; + case 3: *pad |= kMaskRt ; break; + case 4: *pad |= (kMaskRt | kMaskDn); break; + case 5: *pad |= kMaskDn ; break; + case 6: *pad |= (kMaskDn | kMaskLf); break; + case 7: *pad |= kMaskLf ; break; + case 8: *pad |= (kMaskLf | kMaskUp); break; + } + } + + break; + + case kPadElemTypeHat4: // Hat Switch (4 Directions) + if (gDirectionInfo[i].device[kPadHat]) + { + state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]); + switch (state) + { + case 1: *pad |= kMaskUp; break; + case 2: *pad |= kMaskRt; break; + case 3: *pad |= kMaskDn; break; + case 4: *pad |= kMaskLf; break; + } + } + + break; + + case kPadElemTypeOtherHat8: // Hat Switch (8 Directions, Start at 0) + if (gDirectionInfo[i].device[kPadHat]) + { + state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]); + switch (state) + { + case 0: *pad |= kMaskUp ; break; + case 1: *pad |= (kMaskUp | kMaskRt); break; + case 2: *pad |= kMaskRt ; break; + case 3: *pad |= (kMaskRt | kMaskDn); break; + case 4: *pad |= kMaskDn ; break; + case 5: *pad |= (kMaskDn | kMaskLf); break; + case 6: *pad |= kMaskLf ; break; + case 7: *pad |= (kMaskLf | kMaskUp); break; + } + } + + break; + + case kPadElemTypeOtherHat4: // Hat Switch (4 Directions, Start at 0) + if (gDirectionInfo[i].device[kPadHat]) + { + state = HIDGetElementValue(gDirectionInfo[i].device[kPadHat], gDirectionInfo[i].element[kPadHat]); + switch (state) + { + case 0: *pad |= kMaskUp; break; + case 1: *pad |= kMaskRt; break; + case 2: *pad |= kMaskDn; break; + case 3: *pad |= kMaskLf; break; + } + } + + break; + + case kPadElemTypeButton: // Button (maybe) + if (gActionRecs[kUp(i)].fDevice && HIDGetElementValue(gActionRecs[kUp(i)].fDevice, gActionRecs[kUp(i)].fElement)) + *pad |= kMaskUp; + if (gActionRecs[kDn(i)].fDevice && HIDGetElementValue(gActionRecs[kDn(i)].fDevice, gActionRecs[kDn(i)].fElement)) + *pad |= kMaskDn; + if (gActionRecs[kLf(i)].fDevice && HIDGetElementValue(gActionRecs[kLf(i)].fDevice, gActionRecs[kLf(i)].fElement)) + *pad |= kMaskLf; + if (gActionRecs[kRt(i)].fDevice && HIDGetElementValue(gActionRecs[kRt(i)].fDevice, gActionRecs[kRt(i)].fElement)) + *pad |= kMaskRt; + + break; + } +} + +static void JoypadSetDirectionInfo (void) +{ + for (int i = 0; i < MAC_MAX_PLAYERS; i++) + { + if (((gActionRecs[kUp(i)].fDevice) && (gActionRecs[kUp(i)].fElement)) && + ((gActionRecs[kDn(i)].fDevice) && (gActionRecs[kDn(i)].fElement)) && + ((gActionRecs[kLf(i)].fDevice) && (gActionRecs[kLf(i)].fElement)) && + ((gActionRecs[kRt(i)].fDevice) && (gActionRecs[kRt(i)].fElement))) + { + if ((gActionRecs[kUp(i)].fDevice == gActionRecs[kDn(i)].fDevice) && + (gActionRecs[kDn(i)].fDevice == gActionRecs[kLf(i)].fDevice) && + (gActionRecs[kLf(i)].fDevice == gActionRecs[kRt(i)].fDevice) && + (gActionRecs[kUp(i)].fElement == gActionRecs[kDn(i)].fElement) && + (gActionRecs[kDn(i)].fElement == gActionRecs[kLf(i)].fElement) && + (gActionRecs[kLf(i)].fElement == gActionRecs[kRt(i)].fElement) && + (gActionRecs[kUp(i)].fElement->usage == kHIDUsage_GD_Hatswitch)) // Hat Switch + { + if ((gDirectionHint[i] == kPadElemTypeHat8) || (gDirectionHint[i] == kPadElemTypeOtherHat8) || + (gDirectionHint[i] == kPadElemTypeHat4) || (gDirectionHint[i] == kPadElemTypeOtherHat4)) + gDirectionInfo[i].type = gDirectionHint[i]; + else // Assuming... + { + if ((gActionRecs[kUp(i)].fDevice->vendorID == 1103) || (gActionRecs[kUp(i)].fElement->min == 0)) + gDirectionInfo[i].type = (gActionRecs[kUp(i)].fElement->max > 4) ? kPadElemTypeOtherHat8 : kPadElemTypeOtherHat4; + else + gDirectionInfo[i].type = (gActionRecs[kUp(i)].fElement->max > 4) ? kPadElemTypeHat8 : kPadElemTypeHat4; + + gDirectionHint[i] = gDirectionInfo[i].type; + } + + gDirectionInfo[i].device [kPadHat] = gActionRecs[kUp(i)].fDevice; + gDirectionInfo[i].element[kPadHat] = gActionRecs[kUp(i)].fElement; + gDirectionInfo[i].max [kPadHat] = gActionRecs[kUp(i)].fElement->max; + gDirectionInfo[i].min [kPadHat] = gActionRecs[kUp(i)].fElement->min; + } + else + if ((gActionRecs[kUp(i)].fDevice == gActionRecs[kDn(i)].fDevice) && + (gActionRecs[kLf(i)].fDevice == gActionRecs[kRt(i)].fDevice) && + (gActionRecs[kUp(i)].fElement == gActionRecs[kDn(i)].fElement) && + (gActionRecs[kLf(i)].fElement == gActionRecs[kRt(i)].fElement) && + (gActionRecs[kUp(i)].fElement->max - gActionRecs[kUp(i)].fElement->min > 1) && + (gActionRecs[kLf(i)].fElement->max - gActionRecs[kLf(i)].fElement->min > 1)) // Axis (maybe) + { + gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeAxis; + + gDirectionInfo[i].device [kPadYAxis] = gActionRecs[kUp(i)].fDevice; + gDirectionInfo[i].element[kPadYAxis] = gActionRecs[kUp(i)].fElement; + gDirectionInfo[i].max [kPadYAxis] = gActionRecs[kUp(i)].fElement->max; + gDirectionInfo[i].min [kPadYAxis] = gActionRecs[kUp(i)].fElement->min; + gDirectionInfo[i].mid [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1; + gDirectionInfo[i].maxmid [kPadYAxis] = (gDirectionInfo[i].max[kPadYAxis] + gDirectionInfo[i].mid[kPadYAxis]) >> 1; + gDirectionInfo[i].midmin [kPadYAxis] = (gDirectionInfo[i].mid[kPadYAxis] + gDirectionInfo[i].min[kPadYAxis]) >> 1; + + gDirectionInfo[i].device [kPadXAxis] = gActionRecs[kLf(i)].fDevice; + gDirectionInfo[i].element[kPadXAxis] = gActionRecs[kLf(i)].fElement; + gDirectionInfo[i].max [kPadXAxis] = gActionRecs[kLf(i)].fElement->max; + gDirectionInfo[i].min [kPadXAxis] = gActionRecs[kLf(i)].fElement->min; + gDirectionInfo[i].mid [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1; + gDirectionInfo[i].maxmid [kPadXAxis] = (gDirectionInfo[i].max[kPadXAxis] + gDirectionInfo[i].mid[kPadXAxis]) >> 1; + gDirectionInfo[i].midmin [kPadXAxis] = (gDirectionInfo[i].mid[kPadXAxis] + gDirectionInfo[i].min[kPadXAxis]) >> 1; + } + else // Button (maybe) + gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeButton; + } + else + { + gActionRecs[kUp(i)].fDevice = gActionRecs[kDn(i)].fDevice = gActionRecs[kLf(i)].fDevice = gActionRecs[kRt(i)].fDevice = NULL; + gActionRecs[kUp(i)].fElement = gActionRecs[kDn(i)].fElement = gActionRecs[kLf(i)].fElement = gActionRecs[kRt(i)].fElement = NULL; + + gDirectionInfo[i].type = gDirectionHint[i] = kPadElemTypeNone; + gDirectionInfo[i].device [0] = gDirectionInfo[i].device [1] = NULL; + gDirectionInfo[i].element[0] = gDirectionInfo[i].element[1] = NULL; + } + } +} diff --git a/macosx/mac-joypad.h b/macosx/mac-joypad.h new file mode 100644 index 00000000..4cdf19cb --- /dev/null +++ b/macosx/mac-joypad.h @@ -0,0 +1,338 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_joypad_h_ +#define _mac_joypad_h_ + +enum +{ + kISp1PUp = 0, + kISp1PDn, + kISp1PLf, + kISp1PRt, + + kISp2PUp, + kISp2PDn, + kISp2PLf, + kISp2PRt, + + kISp3PUp, + kISp3PDn, + kISp3PLf, + kISp3PRt, + + kISp4PUp, + kISp4PDn, + kISp4PLf, + kISp4PRt, + + kISp5PUp, + kISp5PDn, + kISp5PLf, + kISp5PRt, + + kISp6PUp, + kISp6PDn, + kISp6PLf, + kISp6PRt, + + kISp7PUp, + kISp7PDn, + kISp7PLf, + kISp7PRt, + + kISp8PUp, + kISp8PDn, + kISp8PLf, + kISp8PRt, + + kISp1PB, + kISp1PA, + kISp1PX, + kISp1PY, + kISp1PL, + kISp1PR, + kISp1PSelect, + kISp1PStart, + + kISp2PB, + kISp2PA, + kISp2PX, + kISp2PY, + kISp2PL, + kISp2PR, + kISp2PSelect, + kISp2PStart, + + kISp3PB, + kISp3PA, + kISp3PX, + kISp3PY, + kISp3PL, + kISp3PR, + kISp3PSelect, + kISp3PStart, + + kISp4PB, + kISp4PA, + kISp4PX, + kISp4PY, + kISp4PL, + kISp4PR, + kISp4PSelect, + kISp4PStart, + + kISp5PB, + kISp5PA, + kISp5PX, + kISp5PY, + kISp5PL, + kISp5PR, + kISp5PSelect, + kISp5PStart, + + kISp6PB, + kISp6PA, + kISp6PX, + kISp6PY, + kISp6PL, + kISp6PR, + kISp6PSelect, + kISp6PStart, + + kISp7PB, + kISp7PA, + kISp7PX, + kISp7PY, + kISp7PL, + kISp7PR, + kISp7PSelect, + kISp7PStart, + + kISp8PB, + kISp8PA, + kISp8PX, + kISp8PY, + kISp8PL, + kISp8PR, + kISp8PSelect, + kISp8PStart, + + kISpFastForward, + kISpFreeze, + kISpDefrost, + kISpScreenshot, + kISpEsc, + kISpSPC, + kISpMouseL, + kISpMouseR, + kISpScopeT, + kISpScopeP, + kISpScopeC, + kISpOffScreen, + kISpFunction, + kISpAlt, + kISpFFUp, + kISpFFDown, + kISpTC, + + kNeedCount +}; + +void SetUpHID (void); +void ReleaseHID (void); +void ConfigureHID (void); +void ClearPadSetting (void); +void SaveControllerSettings (void); +void LoadControllerSettings (void); +long ISpKeyIsPressed (int); +void JoypadScanDirection (int, uint32 *); + +#endif diff --git a/macosx/mac-keyboard.cpp b/macosx/mac-keyboard.cpp new file mode 100644 index 00000000..b8377e07 --- /dev/null +++ b/macosx/mac-keyboard.cpp @@ -0,0 +1,1204 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "port.h" + +#include "mac-prefix.h" +#include "mac-dialog.h" +#include "mac-gworld.h" +#include "mac-os.h" +#include "mac-keyboard.h" + +#define kmUpArrowKey 0x7E +#define kmDownArrowKey 0x7D +#define kmRightArrowKey 0x7C +#define kmLeftArrowKey 0x7B +#define kmReturnKey 0x24 +#define kmTabKey 0x30 +#define kmShiftKey 0x38 +#define kmControlKey 0x3B +#define kmOptionKey 0x3A +#define kmCommandKey 0x37 +#define kmXKey 0x07 +#define kmZKey 0x06 +#define kmKP2Key 0x54 +#define kmKP4Key 0x56 +#define kmKP5Key 0x57 +#define kmKP6Key 0x58 +#define kmKP8Key 0x5B +#define kmKPEnterKey 0x4C +#define kmKPPlusKey 0x45 +#define kmKP0Key 0x52 +#define kmKPPeriodKey 0x41 +#define kmHomeKey 0x73 +#define kmPageUpKey 0x74 +#define kmEndKey 0x77 +#define kmPageDownKey 0x79 +#define kmBackslashKey 0x2A +#define km1Key 0x12 +#define km0Key 0x1D +#define kmIKey 0x22 +#define kmJKey 0x26 +#define kmKKey 0x28 +#define kmLKey 0x25 +#define kmTildeKey 0x32 +#define kmRKey 0x0F +#define kmBKey 0x0B +#define kmNKey 0x2D +#define kmMKey 0x2E +#define kmSpaceKey 0x31 +#define kmSlashKey 0x2C +#define kmPeriodKey 0x2F +#define kmQKey 0x0C +#define kmWKey 0x0D +#define kmEscKey 0x35 +#define kmCommaKey 0x2B + +#define kIconSize 16 +#define kKeySize 24 +#define KS kKeySize + +uint8 keyCode[kKeys] = +{ + kmUpArrowKey, + kmDownArrowKey, + kmLeftArrowKey, + kmRightArrowKey, + kmShiftKey, + kmOptionKey, + kmControlKey, + kmCommandKey, + kmZKey, + kmXKey, + kmReturnKey, + kmTabKey, + + kmKP8Key, + kmKP2Key, + kmKP4Key, + kmKP6Key, + kmPageDownKey, + kmPageUpKey, + kmEndKey, + kmHomeKey, + kmKP0Key, + kmKPPeriodKey, + kmKPEnterKey, + kmKPPlusKey, + + kmBackslashKey, + km1Key, + km0Key, + kmTildeKey, + kmRKey, + kmBKey, + kmNKey, + kmMKey, + kmSpaceKey, + kmSlashKey, + kmPeriodKey, + kmQKey, + kmWKey, + kmEscKey, + kmCommaKey +}; + +typedef struct +{ + int keyWidth, keyHeight; + uint8 scancode; + const char *keyLabel; +} KeyboardLayout; + +typedef struct +{ + HIViewRef view; +} CustomViewData; + +static CGImageRef iconTableImage; +static CGImageRef keyLayoutImage; +static CGImageRef iconPlaceImage; +static Ptr iconTableCGWld; +static Ptr keyLayoutWorld; +static Ptr iconPlaceWorld; + +static CGRect keyRect[0x80][2]; +static uint8 defaultKeys[kKeys]; + +static HIObjectClassRef theClass; +static HIViewRef customView; +static HIPoint mousePos; +static float ofsx, ofsy; +static int dragKey; +static CGPoint dragKeyOfs; +static CGRect dragKeyRect; +static volatile Boolean keyInDrag; + +static const int kKeyLayoutWidth = kKeySize * 23 + 1, + kKeyLayoutHeight = kKeySize * 7 + 1; + +static KeyboardLayout keys[] = +{ + { KS, KS, 0x35, "esc" }, + { KS, KS, 0x00, NULL }, + { KS, KS, 0x7a, "F1" }, + { KS, KS, 0x78, "F2" }, + { KS, KS, 0x63, "F3" }, + { KS, KS, 0x76, "F4" }, + { KS / 2, KS, 0x00, NULL }, + { KS, KS, 0x60, "F5" }, + { KS, KS, 0x61, "F6" }, + { KS, KS, 0x62, "F7" }, + { KS, KS, 0x64, "F8" }, + { KS / 2, KS, 0x00, NULL }, + { KS, KS, 0x65, "F9" }, + { KS, KS, 0x6d, "F10" }, + { KS, KS, 0x67, "F11" }, + { KS, KS, 0x6f, "F12" }, + { KS / 2, KS, 0x00, NULL }, + { KS, KS, 0x69, "F13" }, + { KS, KS, 0x6b, "F14" }, + { KS, KS, 0x71, "F15" }, + { 0, 0, 0x00, NULL }, + + { 0, 0, 0x00, NULL }, + + { KS, KS, 0x32, "`" }, + { KS, KS, 0x12, "1" }, + { KS, KS, 0x13, "2" }, + { KS, KS, 0x14, "3" }, + { KS, KS, 0x15, "4" }, + { KS, KS, 0x17, "5" }, + { KS, KS, 0x16, "6" }, + { KS, KS, 0x1a, "7" }, + { KS, KS, 0x1c, "8" }, + { KS, KS, 0x19, "9" }, + { KS, KS, 0x1d, "0" }, + { KS, KS, 0x1b, "-" }, + { KS, KS, 0x18, "=" }, + { KS * 2, KS, 0x33, "delete" }, + { KS / 2, KS, 0x00, NULL }, + { KS, KS, 0x72, "ins" }, + { KS, KS, 0x73, "hom" }, + { KS, KS, 0x74, "pgu" }, + { KS / 2, KS, 0x00, NULL }, + { KS, KS, 0x47, "clr" }, + { KS, KS, 0x51, "=" }, + { KS, KS, 0x4b, "/" }, + { KS, KS, 0x43, "*" }, + { 0, 0, 0x00, NULL }, + + { KS * 3 / 2, KS, 0x30, "tab" }, + { KS, KS, 0x0c, "Q" }, + { KS, KS, 0x0d, "W" }, + { KS, KS, 0x0e, "E" }, + { KS, KS, 0x0f, "R" }, + { KS, KS, 0x11, "T" }, + { KS, KS, 0x10, "Y" }, + { KS, KS, 0x20, "U" }, + { KS, KS, 0x22, "I" }, + { KS, KS, 0x1f, "O" }, + { KS, KS, 0x23, "P" }, + { KS, KS, 0x21, "[" }, + { KS, KS, 0x1e, "]" }, + { KS * 3 / 2, KS, 0x2a, "\\" }, + { KS / 2, KS, 0x00, NULL }, + { KS, KS, 0x75, "del" }, + { KS, KS, 0x77, "end" }, + { KS, KS, 0x79, "pgd" }, + { KS / 2, KS, 0x00, NULL }, + { KS, KS, 0x59, "7" }, + { KS, KS, 0x5b, "8" }, + { KS, KS, 0x5c, "9" }, + { KS, KS, 0x4e, "-" }, + { 0, 0, 0x00, NULL }, + + { KS * 2, KS, 0x39, "caps" }, + { KS, KS, 0x00, "A" }, + { KS, KS, 0x01, "S" }, + { KS, KS, 0x02, "D" }, + { KS, KS, 0x03, "F" }, + { KS, KS, 0x05, "G" }, + { KS, KS, 0x04, "H" }, + { KS, KS, 0x26, "J" }, + { KS, KS, 0x28, "K" }, + { KS, KS, 0x25, "L" }, + { KS, KS, 0x29, ";" }, + { KS, KS, 0x27, "\xd3" }, + { KS * 2, KS, 0x24, "return" }, + { KS * 4, KS, 0x00, NULL }, + { KS, KS, 0x56, "4" }, + { KS, KS, 0x57, "5" }, + { KS, KS, 0x58, "6" }, + { KS, KS, 0x45, "+" }, + { 0, 0, 0x00, NULL }, + + { KS * 5 / 2, KS, 0x38, "shift" }, + { KS, KS, 0x06, "Z" }, + { KS, KS, 0x07, "X" }, + { KS, KS, 0x08, "C" }, + { KS, KS, 0x09, "V" }, + { KS, KS, 0x0b, "B" }, + { KS, KS, 0x2d, "N" }, + { KS, KS, 0x2e, "M" }, + { KS, KS, 0x2b, "," }, + { KS, KS, 0x2f, "." }, + { KS, KS, 0x2c, "/" }, + { KS * 5 / 2, KS, 0x38, "shift" }, + { KS * 3 / 2, KS, 0x00, NULL }, + { KS, KS, 0x7e, "up" }, + { KS * 3 / 2, KS, 0x00, NULL }, + { KS, KS, 0x53, "1" }, + { KS, KS, 0x54, "2" }, + { KS, KS, 0x55, "3" }, + { KS, KS * 2, 0x4c, "ent" }, + { 0, 0, 0x00, NULL }, + + { KS * 3 / 2, KS, 0x3b, "ctrl" }, + { KS * 3 / 2, KS, 0x3a, "opt" }, + { KS * 3 / 2, KS, 0x37, "cmd" }, + { KS * 6, KS, 0x31, " " }, + { KS * 3 / 2, KS, 0x37, "cmd" }, + { KS * 3 / 2, KS, 0x3a, "opt" }, + { KS * 3 / 2, KS, 0x3b, "ctrl" }, + { KS / 2, KS, 0x00, NULL }, + { KS, KS, 0x7b, "lt" }, + { KS, KS, 0x7d, "dn" }, + { KS, KS, 0x7c, "rt" }, + { KS / 2, KS, 0x00, NULL }, + { KS * 2, KS, 0x52, "0" }, + { KS, KS, 0x41, "." }, + { 0, 0, 0x00, NULL } +}; + +static void CreateIconTableImage (void); +static void ReleaseIconTableImage (void); +static void CreateKeyLayoutImage (void); +static void ReleaseKeyLayoutImage (void); +static void CreateIconPlaceImage (void); +static void UpdateIconPlaceImage (void); +static void ReleaseIconPlaceImage (void); +static void DrawPlacedIcon (CGContextRef, int); +static void DrawDraggedIcon (CGContextRef, int, CGPoint *); +static Boolean KeyCodeInUse (int); +static int FindHitKey (HIPoint, CGRect *, CGPoint *); +static pascal OSStatus KeyWindowEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus KeyLegendEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus KeyLayoutEventHandler (EventHandlerCallRef, EventRef, void *); + +#define kCustomLayoutViewClassID CFSTR("com.snes9x.macos.snes9x.keylayout") + + +void ConfigureKeyboard (void) +{ + OSStatus err; + IBNibRef nibRef; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef tWindowRef; + + err = CreateWindowFromNib(nibRef, CFSTR("Keyboard"), &tWindowRef); + if (err == noErr) + { + EventHandlerRef wref, iref1, iref2; + EventHandlerUPP wUPP, iUPP; + EventTypeSpec wEvents[] = { { kEventClassWindow, kEventWindowClose }, + { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }, + cEvents[] = { { kEventClassHIObject, kEventHIObjectConstruct }, + { kEventClassHIObject, kEventHIObjectDestruct }, + { kEventClassHIObject, kEventHIObjectInitialize }, + { kEventClassControl, kEventControlDraw }, + { kEventClassControl, kEventControlHitTest }, + { kEventClassControl, kEventControlTrack } }, + iEvents[] = { { kEventClassControl, kEventControlDraw } }; + HIObjectRef hiObject; + HIViewRef contentView, image1, image2; + HIViewID cid; + HIRect frame; + Rect winBounds; + + UpdateIconPlaceImage(); + + keyInDrag = false; + dragKey = -1; + dragKeyOfs = CGPointMake(0.0f, 0.0f); + dragKeyRect = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f); + mousePos = CGPointMake(0.0f, 0.0f); + + err = noErr; + if (theClass == NULL) + err = HIObjectRegisterSubclass(kCustomLayoutViewClassID, kHIViewClassID, 0, KeyLayoutEventHandler, GetEventTypeCount(cEvents), cEvents, NULL, &theClass); + + if (err == noErr) + { + err = HIObjectCreate(kCustomLayoutViewClassID, NULL, &hiObject); + if (err == noErr) + { + GetWindowBounds(tWindowRef, kWindowContentRgn, &winBounds); + + frame.origin.x = 2.0f; + frame.origin.y = 2.0f; + frame.size.width = (float) (winBounds.right - winBounds.left) - 4.0f; + frame.size.height = (float) kKeyLayoutHeight + 36.0f; + + ofsx = (float) (((int) frame.size.width - kKeyLayoutWidth ) >> 1) + 1.0f; + ofsy = (float) (((int) frame.size.height - kKeyLayoutHeight) >> 1) + 1.0f; + + customView = (HIViewRef) hiObject; + + HIViewFindByID(HIViewGetRoot(tWindowRef), kHIViewWindowContentID, &contentView); + HIViewAddSubview(contentView, customView); + HIViewSetFrame(customView, &frame); + HIViewSetVisible(customView, true); + + cid.signature = 'Lgnd'; + cid.id = 0; + HIViewFindByID(contentView, cid, &image1); + cid.id = 1; + HIViewFindByID(contentView, cid, &image2); + iUPP = NewEventHandlerUPP(KeyLegendEventHandler); + err = InstallControlEventHandler(image1, iUPP, GetEventTypeCount(iEvents), iEvents, (void *) image1, &iref1); + err = InstallControlEventHandler(image2, iUPP, GetEventTypeCount(iEvents), iEvents, (void *) image2, &iref2); + + wUPP = NewEventHandlerUPP(KeyWindowEventHandler); + err = InstallWindowEventHandler(tWindowRef, wUPP, GetEventTypeCount(wEvents), wEvents, (void *) tWindowRef, &wref); + + MoveWindowPosition(tWindowRef, kWindowKeyConfig, false); + ShowWindow(tWindowRef); + err = RunAppModalLoopForWindow(tWindowRef); + HideWindow(tWindowRef); + SaveWindowPosition(tWindowRef, kWindowKeyConfig); + + err = RemoveEventHandler(iref2); + err = RemoveEventHandler(iref1); + DisposeEventHandlerUPP(iUPP); + + err = RemoveEventHandler(wref); + DisposeEventHandlerUPP(wUPP); + } + } + + CFRelease(tWindowRef); + } + + DisposeNibReference(nibRef); + } +} + +static void CreateIconTableImage (void) +{ + CGContextRef ctx; + CGDataProviderRef prov; + CGColorSpaceRef color; + CGRect rct; + + rct = CGRectMake(0.0f, 0.0f, (float) kIconSize, (float) kIconSize); + + iconTableCGWld = (Ptr) malloc(kIconSize * kKeys * (kIconSize + 1) * 4); + if (!iconTableCGWld) + QuitWithFatalError(0, "keyboard 08"); + + ctx = NULL; + + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + ctx = CGBitmapContextCreate(iconTableCGWld, kIconSize * kKeys, kIconSize, 8, kIconSize * kKeys * 4, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0)); + CGColorSpaceRelease(color); + } + + if (!ctx) + QuitWithFatalError(0, "keyboard 09"); + + CGContextTranslateCTM(ctx, 0.0f, (float) kIconSize); + CGContextScaleCTM(ctx, 1.0f, -1.0f); + + // SNES pads + for (int i = macPadIconIndex; i < macPadIconIndex + 12 * 2; i++) + { + if (systemVersion >= 0x1040) + CGContextDrawImage(ctx, rct, macIconImage[i]); + #ifdef MAC_PANTHER_SUPPORT + else + PlotIconRefInContext(ctx, &rct, kAlignNone, kTransformNone, NULL, kPlotIconRefNormalFlags, macIconRef[i]); + #endif + rct = CGRectOffset(rct, kIconSize, 0); + } + + // Function buttons + for (int i = macFunctionIconIndex; i < macFunctionIconIndex + 17; i++) + { + if (systemVersion >= 0x1040) + CGContextDrawImage(ctx, rct, macIconImage[i]); + #ifdef MAC_PANTHER_SUPPORT + else + PlotIconRefInContext(ctx, &rct, kAlignNone, kTransformNone, NULL, kPlotIconRefNormalFlags, macIconRef[i]); + #endif + rct = CGRectOffset(rct, kIconSize, 0); + } + + CGContextRelease(ctx); + + iconTableImage = NULL; + + prov = CGDataProviderCreateWithData(NULL, iconTableCGWld, kIconSize * kKeys * kIconSize * 4, NULL); + if (prov) + { + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + iconTableImage = CGImageCreate(kIconSize * kKeys, kIconSize, 8, 32, kIconSize * kKeys * 4, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0), prov, NULL, 0, kCGRenderingIntentDefault); + CGColorSpaceRelease(color); + } + + CGDataProviderRelease(prov); + } + + if (!iconTableImage) + QuitWithFatalError(0, "keyboard 10"); +} + +static void ReleaseIconTableImage (void) +{ + CGImageRelease(iconTableImage); + free(iconTableCGWld); +} + +static void CreateKeyLayoutImage (void) +{ + CGContextRef ctx; + CGDataProviderRef prov; + CGColorSpaceRef color; + CGAffineTransform flipMatrix; + CGRect rct, r; + int index, scancode; + + rct = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f); + for (int i = 0; i < 0x80; i++) + keyRect[i][0] = keyRect[i][1] = rct; + + keyLayoutWorld = (Ptr) malloc(kKeyLayoutWidth * (kKeyLayoutHeight + 1) * 4); + if (!keyLayoutWorld) + QuitWithFatalError(0, "keyboard 02"); + + ctx = NULL; + + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + ctx = CGBitmapContextCreate(keyLayoutWorld, kKeyLayoutWidth, kKeyLayoutHeight, 8, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0)); + CGColorSpaceRelease(color); + } + + if (!ctx) + QuitWithFatalError(0, "keyboard 04"); + + CGContextSetLineJoin(ctx, kCGLineJoinMiter); + + flipMatrix = CGAffineTransformMake(1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f); + CGContextSelectFont(ctx, "Helvetica", 10.0f, kCGEncodingMacRoman); + CGContextSetTextDrawingMode(ctx, kCGTextFill); + CGContextSetTextMatrix(ctx, flipMatrix); + + rct = CGRectMake(0.0f, 0.0f, (float) kKeyLayoutWidth, (float) kKeyLayoutHeight); + CGContextClearRect(ctx, rct); + + index = 0; + rct = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f); + + for (int i = 0; i < 7; i++) + { + while (keys[index].keyWidth) + { + rct.size.width = (float) keys[index].keyWidth; + + if (keys[index].keyLabel) + { + rct.size.height = (float) keys[index].keyHeight; + scancode = keys[index].scancode; + + if (keyRect[scancode][0].size.height < 1.0) + keyRect[scancode][0] = rct; + else + keyRect[scancode][1] = rct; + + r = rct; + + r.origin.x += 1.0f; + r.origin.y += 1.0f; + r.size.width -= 1.0f; + r.size.height -= 1.0f; + + CGContextSetRGBStrokeColor(ctx, 0.1f, 0.1f, 0.1f, 1.0f); + CGContextStrokeRect(ctx, r); + + float h, p; + + CGRectInset(r, 2.0f, 2.0f); + h = r.size.height; + for (float f = h; f >= 1.0f; f -= 1.0f) + { + p = (155.0f + (h - f)) / 180.0f; + CGContextSetRGBFillColor(ctx, p, p, p, 1.0f); + CGContextFillRect(ctx, r); + r.size.height -= 1.0f; + } + + CGContextSetRGBFillColor(ctx, 0.1f, 0.1f, 0.1f, 1.0f); + CGContextShowTextAtPoint(ctx, rct.origin.x + 3.0f, rct.origin.y + rct.size.height - 3.0f, keys[index].keyLabel, strlen(keys[index].keyLabel)); + } + + rct.origin.x += rct.size.width; + index++; + } + + rct.origin.y += kKeySize; + rct.origin.x = rct.size.width = 0; + index++; + } + + CGContextRelease(ctx); + + keyLayoutImage = NULL; + + prov = CGDataProviderCreateWithData(NULL, keyLayoutWorld, kKeyLayoutWidth * kKeyLayoutHeight * 4, NULL); + if (prov) + { + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + keyLayoutImage = CGImageCreate(kKeyLayoutWidth, kKeyLayoutHeight, 8, 32, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0), prov, NULL, 0, kCGRenderingIntentDefault); + CGColorSpaceRelease(color); + } + + CGDataProviderRelease(prov); + } + + if (!keyLayoutImage) + QuitWithFatalError(0, "keyboard 05"); +} + +static void ReleaseKeyLayoutImage (void) +{ + CGImageRelease(keyLayoutImage); + free(keyLayoutWorld); +} + +static void CreateIconPlaceImage (void) +{ + iconPlaceWorld = (Ptr) malloc(kKeyLayoutWidth * (kKeyLayoutHeight + 1) * 4); + if (!iconPlaceWorld) + QuitWithFatalError(0, "keyboard 06"); + + iconPlaceImage = NULL; + + UpdateIconPlaceImage(); +} + +static void UpdateIconPlaceImage (void) +{ + CGContextRef ctx; + CGDataProviderRef prov; + CGColorSpaceRef color; + CGRect rct; + + if (iconPlaceImage) + CGImageRelease(iconPlaceImage); + + iconPlaceImage = NULL; + + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + ctx = CGBitmapContextCreate(iconPlaceWorld, kKeyLayoutWidth, kKeyLayoutHeight, 8, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0)); + if (ctx) + { + rct = CGRectMake(0.0f, 0.0f, (float) kKeyLayoutWidth, (float) kKeyLayoutHeight); + CGContextDrawImage(ctx, rct, keyLayoutImage); + + for (int i = 0; i < kKeys; i++) + DrawPlacedIcon(ctx, i); + + CGContextRelease(ctx); + } + + prov = CGDataProviderCreateWithData(NULL, iconPlaceWorld, kKeyLayoutWidth * kKeyLayoutHeight * 4, NULL); + if (prov) + { + iconPlaceImage = CGImageCreate(kKeyLayoutWidth, kKeyLayoutHeight, 8, 32, kKeyLayoutWidth * 4, color, kCGImageAlphaPremultipliedFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrderDefault : 0), prov, NULL, 0, kCGRenderingIntentDefault); + CGDataProviderRelease(prov); + } + + CGColorSpaceRelease(color); + } + + if (!iconPlaceImage) + QuitWithFatalError(0, "keyboard 07"); +} + +static void ReleaseIconPlaceImage (void) +{ + CGImageRelease(iconPlaceImage); + free(iconPlaceWorld); +} + +void InitKeyboard (void) +{ + theClass = NULL; + + memcpy(defaultKeys, keyCode, sizeof(keyCode)); + + CreateIconTableImage(); + CreateKeyLayoutImage(); + CreateIconPlaceImage(); +} + +void DeinitKeyboard (void) +{ + ReleaseIconPlaceImage(); + ReleaseKeyLayoutImage(); + ReleaseIconTableImage(); +} + +static void DrawPlacedIcon (CGContextRef ctx, int which) +{ + CGRect keyBounds, srcRect, dstRect; + + CGContextSaveGState(ctx); + + CGContextSetRGBFillColor(ctx, 0.40f, 0.40f, 0.65f, 0.5f); + + for (int each = 0; each <= 1; each++) + { + keyBounds = keyRect[keyCode[which]][each]; + + if (keyBounds.size.height > 1.0f) + { + keyBounds.origin.x += 1.0f; + keyBounds.origin.y += 1.0f; + keyBounds.size.width -= 1.0f; + keyBounds.size.height -= 1.0f; + + CGContextFillRect(ctx, keyBounds); + + keyBounds.origin.x -= 1.0f; + keyBounds.origin.y -= 1.0f; + keyBounds.size.width += 1.0f; + keyBounds.size.height += 1.0f; + + srcRect.origin.x = (float) (which * kIconSize); + srcRect.origin.y = 0.0f; + srcRect.size.width = (float) kIconSize; + srcRect.size.height = (float) kIconSize; + + dstRect.origin.x = keyBounds.origin.x + (keyBounds.size.width - kIconSize) / 2.0f; + dstRect.origin.y = keyBounds.origin.y + (keyBounds.size.height - kIconSize) / 2.0f; + dstRect.size.width = (float) kIconSize; + dstRect.size.height = (float) kIconSize; + + DrawSubCGImage(ctx, iconTableImage, srcRect, dstRect); + } + } + + CGContextRestoreGState(ctx); +} + +static void DrawDraggedIcon (CGContextRef ctx, int which, CGPoint *offset) +{ + CGRect srcRect, dstRect; + + CGContextSaveGState(ctx); + + srcRect.origin.x = (float) (which * kIconSize); + srcRect.origin.y = 0.0f; + srcRect.size.width = (float) kIconSize; + srcRect.size.height = (float) kIconSize; + + dstRect.origin.x = mousePos.x + offset->x; + dstRect.origin.y = mousePos.y + offset->y; + dstRect.size.width = (float) kIconSize; + dstRect.size.height = (float) kIconSize; + + CGContextSetAlpha(ctx, 0.5f); + DrawSubCGImage(ctx, iconTableImage, srcRect, dstRect); + + CGContextRestoreGState(ctx); +} + +static Boolean KeyCodeInUse (int code) +{ + for (int i = 0; i < kKeys; i++) + if (keyCode[i] == code) + return (true); + + return (false); +} + +static int FindHitKey (HIPoint where, CGRect *keybounds, CGPoint *offset) +{ + int hit; + + hit = -1; + *offset = CGPointMake(0.0f, 0.0f); + *keybounds = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f); + + for (int which = 0; which < kKeys; which++) + { + for (int each = 0; each <= 1; each++) + { + if (CGRectContainsPoint(keyRect[keyCode[which]][each], where)) + { + hit = which; + + *keybounds = keyRect[keyCode[which]][each]; + offset->x = keybounds->origin.x + (keybounds->size.width - kIconSize) / 2.0f - where.x + 18.0f; + offset->y = keybounds->origin.y + (keybounds->size.height - kIconSize) / 2.0f - where.y + 18.0f; + } + } + } + + return (hit); +} + +static pascal OSStatus KeyWindowEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef tWindowRef = (WindowRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + switch (GetEventKind(inEvent)) + { + case kEventWindowClose: + QuitAppModalLoopForWindow(tWindowRef); + result = noErr; + } + + break; + + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(true); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + if (tHICommand.commandID == 'DFLT') + { + memcpy(keyCode, defaultKeys, sizeof(keyCode)); + UpdateIconPlaceImage(); + HIViewSetNeedsDisplay(customView, true); + result = noErr; + } + } + } + } + + return (result); +} + +static pascal OSStatus KeyLegendEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + HIViewRef view = (HIViewRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassControl: + switch (GetEventKind(inEvent)) + { + case kEventControlDraw: + CGContextRef ctx; + + err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &ctx); + if (err == noErr) + { + HIViewID cid; + HIRect bounds; + + GetControlID(view, &cid); + HIViewGetBounds(view, &bounds); + CGContextTranslateCTM(ctx, 0, bounds.size.height); + CGContextScaleCTM(ctx, 1.0f, -1.0f); + CGContextDrawImage(ctx, CGRectMake(0, 0, kIconSize, kIconSize), macIconImage[macLegendIconIndex + cid.id]); + + result = noErr; + } + } + } + + return (result); +} + +static pascal OSStatus KeyLayoutEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + CustomViewData *data = (CustomViewData *) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassHIObject: + switch (GetEventKind(inEvent)) + { + case kEventHIObjectConstruct: + data = (CustomViewData *) calloc(1, sizeof(CustomViewData)); + if (data) + { + HIViewRef epView; + + err = GetEventParameter(inEvent, kEventParamHIObjectInstance, typeHIObjectRef, NULL, sizeof(epView), NULL, &epView); + if (err == noErr) + { + data->view = epView; + result = SetEventParameter(inEvent, kEventParamHIObjectInstance, typeVoidPtr, sizeof(data), &data); + } + } + + break; + + case kEventHIObjectDestruct: + if (data) + free(data); + + result = noErr; + break; + + case kEventHIObjectInitialize: + result = CallNextEventHandler(inHandlerRef, inEvent); + } + + break; + + case kEventClassControl: + switch (GetEventKind(inEvent)) + { + case kEventControlDraw: + CGContextRef ctx; + + err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(ctx), NULL, &ctx); + if (err == noErr) + { + HIRect bounds, srcRect, dstRect; + + HIViewGetBounds(customView, &bounds); + srcRect = CGRectMake(0, 0, kKeyLayoutWidth, kKeyLayoutHeight); + + dstRect.origin.x = (float) (((int) bounds.size.width - kKeyLayoutWidth ) >> 1); + dstRect.origin.y = (float) (((int) bounds.size.height - kKeyLayoutHeight) >> 1); + dstRect.size.width = (float) kKeyLayoutWidth; + dstRect.size.height = (float) kKeyLayoutHeight; + + DrawSubCGImage(ctx, iconPlaceImage, srcRect, dstRect); + if (keyInDrag && (dragKey != -1)) + DrawDraggedIcon(ctx, dragKey, &dragKeyOfs); + } + + result = noErr; + break; + + case kEventControlHitTest: + ControlPartCode part; + + part = kControlButtonPart; + result = SetEventParameter(inEvent, kEventParamControlPart, typeControlPartCode, sizeof(part), &part); + + break; + + case kEventControlTrack: + MouseTrackingResult trackResult; + WindowRef window; + HIViewRef contentView; + HIPoint hipt; + + dragKey = -1; + dragKeyOfs = CGPointMake(0.0f, 0.0f); + dragKeyRect = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f); + mousePos = CGPointMake(0.0f, 0.0f); + trackResult = kMouseTrackingMouseDown; + + window = GetControlOwner(customView); + HIViewFindByID(HIViewGetRoot(window), kHIViewWindowContentID, &contentView); + + #ifdef MAC_TIGER_PANTHER_SUPPORT + CGrafPtr oldPort; + Point qdpt; + Boolean portChanged = false; + + if (systemVersion < 0x1050) + portChanged = QDSwapPort(GetWindowPort(window), &oldPort); + #endif + + err = GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(hipt), NULL, &hipt); + if (err == noErr) + { + hipt.x -= ofsx; + hipt.y -= ofsy; + + dragKey = FindHitKey(hipt, &dragKeyRect, &dragKeyOfs); + if (dragKey != -1) + { + keyInDrag = true; + + while (trackResult != kMouseTrackingMouseUp) + { + if (CGPointEqualToPoint(mousePos, hipt) == 0) + { + mousePos = hipt; + HIViewSetNeedsDisplay(customView, true); + } + + if (systemVersion >= 0x1050) + { + err = HIViewTrackMouseLocation(customView, 0, kEventDurationForever, 0, NULL, &hipt, NULL, NULL, &trackResult); + hipt.x -= ofsx; + hipt.y -= ofsy; + } + #ifdef MAC_TIGER_PANTHER_SUPPORT + else + { + TrackMouseLocation(NULL, &qdpt, &trackResult); + hipt.x = qdpt.h - ofsx; + hipt.y = qdpt.v - ofsy; + HIViewConvertPoint(&hipt, contentView, customView); + } + #endif + } + + keyInDrag = false; + + for (int code = 0; code < 0x80; code++) + { + for (int each = 0; each <= 1; each++) + { + if (CGRectContainsPoint(keyRect[code][each], mousePos)) + { + if (!KeyCodeInUse(code)) + { + keyCode[dragKey] = code; + UpdateIconPlaceImage(); + } + } + } + } + + HIViewSetNeedsDisplay(customView, true); + } + } + + #ifdef MAC_TIGER_PANTHER_SUPPORT + if (systemVersion < 0x1050) + { + if (portChanged) + QDSwapPort(oldPort, NULL); + } + #endif + + result = noErr; + } + } + + return (result); +} diff --git a/macosx/mac-keyboard.h b/macosx/mac-keyboard.h new file mode 100644 index 00000000..c10e76dd --- /dev/null +++ b/macosx/mac-keyboard.h @@ -0,0 +1,247 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_keyboard_h_ +#define _mac_keyboard_h_ + +#define kKeys 39 + +extern uint8 keyCode[kKeys]; + +enum +{ + k1PUp, + k1PDown, + k1PLeft, + k1PRight, + k1PY, + k1PB, + k1PX, + k1PA, + k1PL, + k1PR, + k1PStart, + k1PSelect, + + k2PUp, + k2PDown, + k2PLeft, + k2PRight, + k2PY, + k2PB, + k2PX, + k2PA, + k2PL, + k2PR, + k2PStart, + k2PSelect, + + kKeyFastForward, + kKeyFreeze, + kKeyDefrost, + kKeyScreenshot, + kKeySPC, + kKeyScopeTurbo, + kKeyScopePause, + kKeyScopeCursor, + kKeyOffScreen, + kKeyFunction, + kKeyAlt, + kKeyFFDown, + kKeyFFUp, + kKeyEsc, + kKeyTC +}; + +void InitKeyboard (void); +void DeinitKeyboard (void); +void ConfigureKeyboard (void); + +#endif diff --git a/macosx/mac-multicart.cpp b/macosx/mac-multicart.cpp new file mode 100644 index 00000000..a9ab1199 --- /dev/null +++ b/macosx/mac-multicart.cpp @@ -0,0 +1,701 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "port.h" + +#include "mac-prefix.h" +#include "mac-cart.h" +#include "mac-dialog.h" +#include "mac-os.h" +#include "mac-multicart.h" + +static pascal OSStatus MultiCartEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus MultiCartPaneEventHandler (EventHandlerCallRef, EventRef, void *); + +static int multiCartDragHilite; +static Boolean multiCartDialogResult; + + +void InitMultiCart (void) +{ + CFStringRef keyRef, pathRef; + char key[32]; + + multiCartPath[0] = multiCartPath[1] = NULL; + + for (int i = 0; i < 2; i++) + { + sprintf(key, "MultiCartPath_%02d", i); + keyRef = CFStringCreateWithCString(kCFAllocatorDefault, key, CFStringGetSystemEncoding()); + if (keyRef) + { + pathRef = (CFStringRef) CFPreferencesCopyAppValue(keyRef, kCFPreferencesCurrentApplication); + if (pathRef) + multiCartPath[i] = pathRef; + + CFRelease(keyRef); + } + } +} + +void DeinitMultiCart (void) +{ + CFStringRef keyRef; + char key[32]; + + for (int i = 0; i < 2; i++) + { + sprintf(key, "MultiCartPath_%02d", i); + keyRef = CFStringCreateWithCString(kCFAllocatorDefault, key, CFStringGetSystemEncoding()); + if (keyRef) + { + if (multiCartPath[i]) + { + CFPreferencesSetAppValue(keyRef, multiCartPath[i], kCFPreferencesCurrentApplication); + CFRelease(multiCartPath[i]); + } + else + CFPreferencesSetAppValue(keyRef, NULL, kCFPreferencesCurrentApplication); + + CFRelease(keyRef); + } + } + + CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); +} + +Boolean MultiCartDialog (void) +{ + OSStatus err; + IBNibRef nibRef; + + multiCartDragHilite = -1; + multiCartDialogResult = false; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef window; + + err = CreateWindowFromNib(nibRef, CFSTR("MultiCart"), &window); + if (err == noErr) + { + static int index[2] = { 0, 1 }; + + EventHandlerRef wRef, cRef[2]; + EventHandlerUPP wUPP, cUPP[2]; + EventTypeSpec wEvent[] = { { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }, + cEvent[] = { { kEventClassControl, kEventControlDraw }, + { kEventClassControl, kEventControlDragEnter }, + { kEventClassControl, kEventControlDragWithin }, + { kEventClassControl, kEventControlDragLeave }, + { kEventClassControl, kEventControlDragReceive } }; + HIViewRef ctl, root, pane[2]; + HIViewID cid; + + root = HIViewGetRoot(window); + + wUPP = NewEventHandlerUPP(MultiCartEventHandler); + err = InstallWindowEventHandler(window, wUPP, GetEventTypeCount(wEvent), wEvent, (void *) window, &wRef); + err = SetAutomaticControlDragTrackingEnabledForWindow(window, true); + + for (int i = 0; i < 2; i++) + { + cid.id = i; + + cid.signature = 'MPan'; + HIViewFindByID(root, cid, &pane[i]); + cUPP[i] = NewEventHandlerUPP(MultiCartPaneEventHandler); + err = InstallControlEventHandler(pane[i], cUPP[i], GetEventTypeCount(cEvent), cEvent, (void *) &index[i], &cRef[i]); + err = SetControlDragTrackingEnabled(pane[i], true); + + cid.signature = 'MNAM'; + HIViewFindByID(root, cid, &ctl); + SetStaticTextTrunc(ctl, truncEnd, false); + if (multiCartPath[i]) + { + CFStringRef str; + CFURLRef url; + + url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, multiCartPath[i], kCFURLPOSIXPathStyle, false); + str = CFURLCopyLastPathComponent(url); + SetStaticTextCFString(ctl, str, false); + CFRelease(str); + CFRelease(url); + } + else + SetStaticTextCFString(ctl, CFSTR(""), false); + } + + MoveWindowPosition(window, kWindowMultiCart, false); + ShowWindow(window); + err = RunAppModalLoopForWindow(window); + HideWindow(window); + SaveWindowPosition(window, kWindowMultiCart); + + for (int i = 0; i < 2; i++) + { + err = RemoveEventHandler(cRef[i]); + DisposeEventHandlerUPP(cUPP[i]); + } + + err = RemoveEventHandler(wRef); + DisposeEventHandlerUPP(wUPP); + + CFRelease(window); + } + + DisposeNibReference(nibRef); + } + + return (multiCartDialogResult); +} + +static pascal OSStatus MultiCartEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef window = (WindowRef) inUserData; + static int index = -1; + + switch (GetEventClass(inEvent)) + { + case kEventClassCommand: + { + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(false); + result = noErr; + } + + break; + } + + case kEventCommandProcess: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + HIViewRef ctl, root; + HIViewID cid; + FSRef ref; + bool8 r; + + root = HIViewGetRoot(window); + + switch (tHICommand.commandID) + { + case 'Cho0': + case 'Cho1': + { + index = (tHICommand.commandID & 0xFF) - '0'; + r = NavBeginOpenROMImageSheet(window, NULL); + result = noErr; + break; + } + + case 'NvDn': + { + r = NavEndOpenROMImageSheet(&ref); + if (r) + { + CFStringRef str; + CFURLRef url; + + url = CFURLCreateFromFSRef(kCFAllocatorDefault, &ref); + str = CFURLCopyLastPathComponent(url); + cid.signature = 'MNAM'; + cid.id = index; + HIViewFindByID(root, cid, &ctl); + SetStaticTextCFString(ctl, str, true); + CFRelease(str); + str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); + if (multiCartPath[index]) + CFRelease(multiCartPath[index]); + multiCartPath[index] = str; + CFRelease(url); + } + + index = -1; + result = noErr; + break; + } + + case 'Cle0': + case 'Cle1': + { + index = (tHICommand.commandID & 0xFF) - '0'; + cid.signature = 'MNAM'; + cid.id = index; + HIViewFindByID(root, cid, &ctl); + SetStaticTextCFString(ctl, CFSTR(""), true); + if (multiCartPath[index]) + { + CFRelease(multiCartPath[index]); + multiCartPath[index] = NULL; + } + + index = -1; + result = noErr; + break; + } + + case 'SWAP': + { + CFStringRef str; + CFURLRef url; + + str = multiCartPath[0]; + multiCartPath[0] = multiCartPath[1]; + multiCartPath[1] = str; + + cid.signature = 'MNAM'; + + for (int i = 0; i < 2; i++) + { + cid.id = i; + HIViewFindByID(root, cid, &ctl); + + if (multiCartPath[i]) + { + url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, multiCartPath[i], kCFURLPOSIXPathStyle, false); + str = CFURLCopyLastPathComponent(url); + SetStaticTextCFString(ctl, str, true); + CFRelease(str); + CFRelease(url); + } + else + SetStaticTextCFString(ctl, CFSTR(""), true); + } + + result = noErr; + break; + } + + case 'ok ': + { + QuitAppModalLoopForWindow(window); + multiCartDialogResult = true; + result = noErr; + break; + } + + case 'not!': + { + QuitAppModalLoopForWindow(window); + multiCartDialogResult = false; + result = noErr; + break; + } + } + } + } + } + } + } + + return (result); +} + +static pascal OSStatus MultiCartPaneEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + HIViewRef view; + DragRef drag; + PasteboardRef pasteboard; + PasteboardItemID itemID; + CFArrayRef array; + CFStringRef flavorType; + CFIndex numFlavors; + ItemCount numItems; + int index = *((int *) inUserData); + + switch (GetEventClass(inEvent)) + { + case kEventClassControl: + { + switch (GetEventKind(inEvent)) + { + case kEventControlDraw: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view); + if (err == noErr) + { + CGContextRef ctx; + + err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &ctx); + if (err == noErr) + { + HIThemeFrameDrawInfo info; + HIRect bounds, frame; + + HIViewGetBounds(view, &bounds); + + CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f); + CGContextFillRect(ctx, bounds); + + info.version = 0; + info.kind = kHIThemeFrameTextFieldSquare; + info.state = kThemeStateInactive; + info.isFocused = false; + err = HIThemeDrawFrame(&bounds, &info, ctx, kHIThemeOrientationNormal); + + if (multiCartDragHilite == index && systemVersion >= 0x1040) + { + err = HIThemeSetStroke(kThemeBrushDragHilite, NULL, ctx, kHIThemeOrientationNormal); + frame = CGRectInset(bounds, 1, 1); + CGContextBeginPath(ctx); + CGContextAddRect(ctx, frame); + CGContextStrokePath(ctx); + } + } + } + + result = noErr; + break; + } + + case kEventControlDragEnter: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view); + if (err == noErr) + { + err = GetEventParameter(inEvent, kEventParamDragRef, typeDragRef, NULL, sizeof(DragRef), NULL, &drag); + if (err == noErr) + { + err = GetDragPasteboard(drag, &pasteboard); + if (err == noErr) + { + err = PasteboardGetItemCount(pasteboard, &numItems); + if (err == noErr && numItems == 1) + { + err = PasteboardGetItemIdentifier(pasteboard, 1, &itemID); + if (err == noErr) + { + err = PasteboardCopyItemFlavors(pasteboard, itemID, &array); + if (err == noErr) + { + numFlavors = CFArrayGetCount(array); + for (CFIndex i = 0; i < numFlavors; i++) + { + flavorType = (CFStringRef) CFArrayGetValueAtIndex(array, i); + if (UTTypeConformsTo(flavorType, CFSTR("public.file-url"))) + { + Boolean accept = true; + + err = SetEventParameter(inEvent, kEventParamControlWouldAcceptDrop, typeBoolean, sizeof(Boolean), &accept); + if (err == noErr) + { + multiCartDragHilite = index; + HIViewSetNeedsDisplay(view, true); + result = noErr; + } + } + } + + CFRelease(array); + } + } + } + } + } + } + + break; + } + + case kEventControlDragWithin: + { + result = noErr; + break; + } + + case kEventControlDragLeave: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view); + if (err == noErr) + { + multiCartDragHilite = -1; + HIViewSetNeedsDisplay(view, true); + } + + result = noErr; + break; + } + + case kEventControlDragReceive: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view); + if (err == noErr) + { + err = GetEventParameter(inEvent, kEventParamDragRef, typeDragRef, NULL, sizeof(DragRef), NULL, &drag); + if (err == noErr) + { + multiCartDragHilite = -1; + HIViewSetNeedsDisplay(view, true); + + err = GetDragPasteboard(drag, &pasteboard); + if (err == noErr) + { + err = PasteboardGetItemIdentifier(pasteboard, 1, &itemID); + if (err == noErr) + { + err = PasteboardCopyItemFlavors(pasteboard, itemID, &array); + if (err == noErr) + { + numFlavors = CFArrayGetCount(array); + for (CFIndex i = 0; i < numFlavors; i++) + { + flavorType = (CFStringRef) CFArrayGetValueAtIndex(array, i); + if (UTTypeConformsTo(flavorType, CFSTR("public.file-url"))) + { + CFDataRef flavorData; + + err = PasteboardCopyItemFlavorData(pasteboard, itemID, flavorType, &flavorData); + if (err == noErr) + { + CFIndex dataSize; + UInt8 *data; + + dataSize = CFDataGetLength(flavorData); + data = (UInt8 *) malloc(dataSize); + if (data) + { + CFDataGetBytes(flavorData, CFRangeMake(0, dataSize), data); + + HIViewRef ctl; + HIViewID cid; + CFStringRef str; + CFURLRef url; + + GetControlID(view, &cid); + cid.signature = 'MNAM'; + HIViewFindByID(view, cid, &ctl); + + url = CFURLCreateWithBytes(kCFAllocatorDefault, data, dataSize, MAC_PATH_ENCODING, NULL); + str = CFURLCopyLastPathComponent(url); + SetStaticTextCFString(ctl, str, true); + CFRelease(str); + str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); + if (multiCartPath[cid.id]) + CFRelease(multiCartPath[cid.id]); + multiCartPath[cid.id] = str; + CFRelease(url); + + result = noErr; + + free(data); + } + + CFRelease(flavorData); + } + } + } + + CFRelease(array); + } + } + } + } + } + } + } + } + } + + return (result); +} diff --git a/macosx/mac-multicart.h b/macosx/mac-multicart.h new file mode 100644 index 00000000..a7ed7018 --- /dev/null +++ b/macosx/mac-multicart.h @@ -0,0 +1,198 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_multicart_h_ +#define _mac_multicart_h_ + +void InitMultiCart (void); +void DeinitMultiCart (void); +Boolean MultiCartDialog (void); + +#endif diff --git a/macosx/mac-musicbox.cpp b/macosx/mac-musicbox.cpp new file mode 100644 index 00000000..f5a0bef7 --- /dev/null +++ b/macosx/mac-musicbox.cpp @@ -0,0 +1,860 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "apu.h" +#include "snapshot.h" + +#include + +#include "mac-prefix.h" +#include "mac-audio.h" +#include "mac-dialog.h" +#include "mac-file.h" +#include "mac-os.h" +#include "mac-stringtools.h" +#include "mac-musicbox.h" + +const float mbxOffsetX = 0.0f, + mbxOffsetY = 0.0f, + mbxBarWidth = 12.0f, + mbxBarHeight = 128.0f, + mbxBarSpace = 2.0f, + mbxLRSpace = 20.0f, + mbxRightBarX = (mbxLRSpace + (mbxBarWidth * 8.0f + mbxBarSpace * 7.0f)), + yyscale = (float) (128.0 / sqrt(64.0)); + +extern char gMacRomName[ROM_NAME_LEN]; + +volatile Boolean mboxPause = false; + +static uint8 storedSoundSnapshot[SPC_SAVE_STATE_BLOCK_SIZE]; +static int32 oldCPUCycles; + +static short mbxOpenedHeight, mbxClosedHeight; +static float mbxMarginX, mbxMarginY, mbxViewWidth, mbxViewHeight; + +static short prevLMax[8], prevRMax[8]; +static short prevLVol[8], prevRVol[8]; +static long long barTimeL[8], barTimeR[8]; + +static pthread_t mbxThread; + +static uint16 stereo_switch; + +static volatile Boolean stopNow, showIndicator, mbxFinished; + +static void SPCPlayExec (void); +static void SPCPlayFreeze (void); +static void SPCPlayDefrost (void); +static void MusicBoxForceFreeze (void); +static void MusicBoxForceDefrost (void); +static void MusicBoxInitIndicator (void); +static void MusicBoxDrawIndicator (HIViewRef, CGContextRef); +static void * SoundTask (void *); +static pascal void MusicBoxTimerHandler (EventLoopTimerRef, void *); +static pascal OSStatus MusicBoxEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus IndicatorEventHandler (EventHandlerCallRef, EventRef, void *); + + +void MusicBoxDialog (void) +{ + OSStatus err; + IBNibRef nibRef; + + if (!cartOpen) + return; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + CFURLRef iconURL; + FSRef iconFSRef; + IconRef actIcon; + WindowRef tWindowRef; + + actIcon = NULL; + + if (musicboxmode == kMBXSoundEmulation) + iconURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("musicbox_ledoff"), CFSTR("icns"), NULL); + else + iconURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("musicbox_ledon" ), CFSTR("icns"), NULL); + + if (iconURL) + { + if (CFURLGetFSRef(iconURL, &iconFSRef)) + err = RegisterIconRefFromFSRef('~9X~', 'micn', &iconFSRef, &actIcon); + + CFRelease(iconURL); + } + + err = CreateWindowFromNib(nibRef, CFSTR("MusicBox"), &tWindowRef); + if (err == noErr) + { + EventHandlerRef mboxRef, paneRef; + EventHandlerUPP mboxUPP, paneUPP; + EventLoopTimerRef timeRef; + EventLoopTimerUPP timeUPP; + EventTypeSpec mboxEvents[] = { { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }, + paneEvents[] = { { kEventClassControl, kEventControlDraw } }; + CFStringRef sref; + CGDataProviderRef prov; + CGImageRef ipng; + CFURLRef iurl; + ControlButtonContentInfo info; + HIViewRef ctl, root, paneView, imageView, contentView; + HIViewID cid; + HIRect bounds; + Rect windowRect, barRect; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + mboxPause = false; + mbxFinished = false; + showIndicator = false; + + stereo_switch = ~0; + spc_core->dsp_set_stereo_switch(stereo_switch); + + for (int i = 0; i < MAC_MAX_PLAYERS; i++) + controlPad[i] = 0; + + // 107's enhanced SPC player + + root = HIViewGetRoot(tWindowRef); + cid.id = 0; + + if (musicboxmode == kMBXSoundEmulation) + { + cid.signature = 'HEAD'; + HIViewFindByID(root, cid, &ctl); + EnableControl(ctl); + + SPCPlayFreeze(); + } + else + MusicBoxForceFreeze(); + + cid.signature = 'Kart'; + HIViewFindByID(root, cid, &ctl); + SetStaticTextTrunc(ctl, truncEnd, false); + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + sref = CFStringCreateWithCString(kCFAllocatorDefault, fname, MAC_PATH_ENCODING); + if (sref) + { + SetStaticTextCFString(ctl, sref, false); + CFRelease(sref); + } + + ipng = NULL; + + iurl = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("musicbox_indicator"), CFSTR("png"), NULL); + if (iurl) + { + prov = CGDataProviderCreateWithURL(iurl); + if (prov) + { + ipng = CGImageCreateWithPNGDataProvider(prov, NULL, false, kCGRenderingIntentDefault); + CGDataProviderRelease(prov); + } + + CFRelease(iurl); + } + + imageView = NULL; + + if (ipng) + { + HIViewFindByID(root, kHIViewWindowContentID, &contentView); + + err = HIImageViewCreate(ipng, &imageView); + if (err == noErr) + { + bounds = CGRectMake(30, 64, CGImageGetWidth(ipng), CGImageGetHeight(ipng)); + HIViewSetFrame(imageView, &bounds); + HIImageViewSetOpaque(imageView, false); + HIViewSetVisible(imageView, true); + HIViewAddSubview(contentView, imageView); + cid.signature = 'iMaG'; + SetControlID(imageView, &cid); + } + + CGImageRelease(ipng); + } + + cid.signature = 'Pane'; + HIViewFindByID(root, cid, &paneView); + HIViewGetBounds(paneView, &bounds); + mbxViewWidth = bounds.size.width; + mbxViewHeight = bounds.size.height; + mbxMarginY = (mbxViewHeight - mbxBarHeight) / 2.0f; + mbxMarginX = (mbxViewWidth - ((mbxBarWidth * 8.0f + mbxBarSpace * 7.0f) * 2.0f + mbxLRSpace)) / 2.0f; + + if (imageView) + { + HIViewSetZOrder(imageView, kHIViewZOrderBelow, paneView); + HIViewAddSubview(imageView, paneView); + } + + if (systemVersion >= 0x1040) + { + info.contentType = kControlContentCGImageRef; + cid.signature = 'Paus'; + HIViewFindByID(root, cid, &ctl); + info.u.imageRef = macIconImage[98]; + err = SetBevelButtonContentInfo(ctl, &info); + cid.signature = 'HEAD'; + HIViewFindByID(root, cid, &ctl); + info.u.imageRef = macIconImage[99]; + err = SetBevelButtonContentInfo(ctl, &info); + cid.signature = 'S_EF'; + HIViewFindByID(root, cid, &ctl); + info.u.imageRef = macIconImage[100]; + err = SetBevelButtonContentInfo(ctl, &info); + } + #ifdef MAC_PANTHER_SUPPORT + else + { + info.contentType = kControlContentIconRef; + cid.signature = 'Paus'; + HIViewFindByID(root, cid, &ctl); + info.u.iconRef = macIconRef[98]; + err = SetBevelButtonContentInfo(ctl, &info); + cid.signature = 'HEAD'; + HIViewFindByID(root, cid, &ctl); + info.u.iconRef = macIconRef[99]; + err = SetBevelButtonContentInfo(ctl, &info); + cid.signature = 'S_EF'; + HIViewFindByID(root, cid, &ctl); + info.u.iconRef = macIconRef[100]; + err = SetBevelButtonContentInfo(ctl, &info); + } + #endif + + cid.signature = 'Tr_i'; + HIViewFindByID(root, cid, &ctl); + HIViewGetFrame(ctl, &bounds); + GetWindowBounds(tWindowRef, kWindowTitleBarRgn, &barRect); + mbxClosedHeight = (short) (bounds.origin.y + bounds.size.height + 7.0) + (barRect.bottom - barRect.top); + + GetWindowBounds(tWindowRef, kWindowStructureRgn, &windowRect); + mbxOpenedHeight = windowRect.bottom - windowRect.top; + + windowRect.bottom = windowRect.top + mbxClosedHeight; + SetWindowBounds(tWindowRef, kWindowStructureRgn, &windowRect); + + paneUPP = NewEventHandlerUPP(IndicatorEventHandler); + err = InstallControlEventHandler(paneView, paneUPP, GetEventTypeCount(paneEvents), paneEvents, (void *) paneView, &paneRef); + + mboxUPP = NewEventHandlerUPP(MusicBoxEventHandler); + err = InstallWindowEventHandler(tWindowRef, mboxUPP, GetEventTypeCount(mboxEvents), mboxEvents, (void *) tWindowRef, &mboxRef); + + timeUPP = NewEventLoopTimerUPP(MusicBoxTimerHandler); + err = InstallEventLoopTimer(GetCurrentEventLoop(), kEventDurationNoWait, kEventDurationSecond * 2.0 / (double) Memory.ROMFramesPerSecond, timeUPP, (void *) paneView, &timeRef); + + MusicBoxInitIndicator(); + + stopNow = false; + MacStartSound(); + pthread_create(&mbxThread, NULL, SoundTask, NULL); + + MoveWindowPosition(tWindowRef, kWindowMusicBox, true); + GetWindowBounds(tWindowRef, kWindowStructureRgn, &windowRect); + if (windowRect.bottom - windowRect.top > mbxClosedHeight) + { + showIndicator = true; + SetControl32BitValue(ctl, 1); // Tr_i + } + + ShowWindow(tWindowRef); + err = RunAppModalLoopForWindow(tWindowRef); + HideWindow(tWindowRef); + SaveWindowPosition(tWindowRef, kWindowMusicBox); + + stopNow = true; + pthread_join(mbxThread, NULL); + MacStopSound(); + + err = RemoveEventLoopTimer(timeRef); + DisposeEventLoopTimerUPP(timeUPP); + + err = RemoveEventHandler(mboxRef); + DisposeEventHandlerUPP(mboxUPP); + + err = RemoveEventHandler(paneRef); + DisposeEventHandlerUPP(paneUPP); + + CFRelease(tWindowRef); + + stereo_switch = ~0; + spc_core->dsp_set_stereo_switch(stereo_switch); + + mbxFinished = true; + + if (musicboxmode == kMBXSoundEmulation) + SPCPlayDefrost(); + else + MusicBoxForceDefrost(); + } + + if (actIcon) + err = UnregisterIconRef('~9X~', 'micn'); + + DisposeNibReference(nibRef); + } +} + +static pascal OSStatus MusicBoxEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *userData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef tWindowRef = (WindowRef) userData; + + switch (GetEventClass(inEvent)) + { + case kEventClassCommand: + { + switch (GetEventKind(inEvent)) + { + HICommand cmd; + + case kEventCommandUpdateStatus: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd); + if (err == noErr && cmd.commandID == 'clos') + { + UpdateMenuCommandStatus(false); + result = noErr; + } + + break; + } + + case kEventCommandProcess: + { + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd); + if (err == noErr) + { + HIViewRef root, c1, c2, c3, c4; + HIViewID cid; + Rect rct; + + switch (cmd.commandID) + { + case 'bar1': stereo_switch ^= (1 << 0); result = noErr; break; + case 'bar2': stereo_switch ^= (1 << 1); result = noErr; break; + case 'bar3': stereo_switch ^= (1 << 2); result = noErr; break; + case 'bar4': stereo_switch ^= (1 << 3); result = noErr; break; + case 'bar5': stereo_switch ^= (1 << 4); result = noErr; break; + case 'bar6': stereo_switch ^= (1 << 5); result = noErr; break; + case 'bar7': stereo_switch ^= (1 << 6); result = noErr; break; + case 'bar8': stereo_switch ^= (1 << 7); result = noErr; break; + case 'bar9': stereo_switch ^= (1 << 8); result = noErr; break; + case 'bara': stereo_switch ^= (1 << 9); result = noErr; break; + case 'barb': stereo_switch ^= (1 << 10); result = noErr; break; + case 'barc': stereo_switch ^= (1 << 11); result = noErr; break; + case 'bard': stereo_switch ^= (1 << 12); result = noErr; break; + case 'bare': stereo_switch ^= (1 << 13); result = noErr; break; + case 'barf': stereo_switch ^= (1 << 14); result = noErr; break; + case 'bar0': stereo_switch ^= (1 << 15); result = noErr; break; + + case 'Paus': + { + mboxPause = !mboxPause; + S9xSetSoundMute(mboxPause); + result = noErr; + break; + } + + case 'Tr_i': + { + showIndicator = !showIndicator; + + root = HIViewGetRoot(tWindowRef); + cid.id = 0; + + cid.signature = 'Pane'; + HIViewFindByID(root, cid, &c1); + HIViewSetVisible(c1, false); + cid.signature = 'iMaG'; + HIViewFindByID(root, cid, &c2); + HIViewSetVisible(c2, false); + cid.signature = 'rCTL'; + HIViewFindByID(root, cid, &c3); + HIViewSetVisible(c3, false); + cid.signature = 'bCTL'; + HIViewFindByID(root, cid, &c4); + HIViewSetVisible(c4, false); + + GetWindowBounds(tWindowRef, kWindowStructureRgn, &rct); + rct.bottom = rct.top + (showIndicator ? mbxOpenedHeight : mbxClosedHeight); + + err = TransitionWindow(tWindowRef, kWindowSlideTransitionEffect, kWindowResizeTransitionAction, &rct); + + HIViewSetVisible(c1, true); + HIViewSetVisible(c2, true); + HIViewSetVisible(c3, true); + HIViewSetVisible(c4, true); + + result = noErr; + break; + } + + case 'DONE': + { + QuitAppModalLoopForWindow(tWindowRef); + result = noErr; + break; + } + + case 'HEAD': + { + showIndicator = !showIndicator; + SPCPlayDefrost(); + showIndicator = !showIndicator; + result = noErr; + break; + } + + case 'S_EF': + { + HideWindow(tWindowRef); + showIndicator = !showIndicator; + ConfigureSoundEffects(); + showIndicator = !showIndicator; + ShowWindow(tWindowRef); + result = noErr; + } + } + + spc_core->dsp_set_stereo_switch(stereo_switch); + } + } + } + } + } + + return (result); +} + +static void * SoundTask (void *) +{ + static long long last; + long long curt; + + Microseconds((UnsignedWide *) &last); + + while (!stopNow) + { + if (!mboxPause) + { + if (musicboxmode == kMBXSoundEmulation) + SPCPlayExec(); + else + S9xMainLoop(); + } + + last += (1000000 / Memory.ROMFramesPerSecond); + Microseconds((UnsignedWide *) &curt); + + if (last > curt) + usleep((useconds_t) (last - curt)); + } + + return (NULL); +} + +static void SPCPlayExec (void) +{ + for (int v = 0; v < Timings.V_Max; v++) + { + CPU.Cycles = Timings.H_Max; + S9xAPUEndScanline(); + CPU.Cycles = 0; + S9xAPUSetReferenceTime(0); + } +} + +static void MusicBoxForceFreeze (void) +{ + char filename[PATH_MAX + 1]; + + strcpy(filename, S9xGetFreezeFilename(999)); + strcat(filename, ".tmp"); + + S9xFreezeGame(filename); +} + +static void MusicBoxForceDefrost (void) +{ + char filename[PATH_MAX + 1]; + + strcpy(filename, S9xGetFreezeFilename(999)); + strcat(filename, ".tmp"); + + S9xUnfreezeGame(filename); + remove(filename); +} + +static void SPCPlayFreeze (void) +{ + oldCPUCycles = CPU.Cycles; + CPU.Cycles = Timings.H_Max; + + S9xSetSoundMute(true); + S9xAPUSaveState(storedSoundSnapshot); + S9xSetSoundMute(false); +} + +static void SPCPlayDefrost (void) +{ + CPU.Cycles = oldCPUCycles; + + S9xSetSoundMute(true); + S9xAPULoadState(storedSoundSnapshot); + S9xSetSoundMute(false); +} + +static void MusicBoxInitIndicator (void) +{ + long long currentTime; + + Microseconds((UnsignedWide *) ¤tTime); + + for (int i = 0; i < 8; i++) + { + prevLMax[i] = prevRMax[i] = 0; + prevLVol[i] = prevRVol[i] = 0; + barTimeL[i] = barTimeR[i] = currentTime; + } +} + +static pascal void MusicBoxTimerHandler (EventLoopTimerRef inHandlerCallRef, void *userData) +{ + OSStatus err; + + if (showIndicator) + err = HIViewSetNeedsDisplay((HIViewRef) userData, true); +} + +static pascal OSStatus IndicatorEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *userData) +{ + OSStatus err, result = eventNotHandledErr; + HIViewRef view = (HIViewRef) userData; + + switch (GetEventClass(inEvent)) + { + case kEventClassControl: + switch (GetEventKind(inEvent)) + { + case kEventControlDraw: + CGContextRef ctx; + + err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &ctx); + if (err == noErr) + { + HIRect bounds; + + HIViewGetBounds(view, &bounds); + CGContextTranslateCTM(ctx, 0, bounds.size.height); + CGContextScaleCTM(ctx, 1.0f, -1.0f); + MusicBoxDrawIndicator(view, ctx); + + result = noErr; + } + } + } + + return (result); +} + +static void MusicBoxDrawIndicator (HIViewRef view, CGContextRef mboxctx) +{ + if (!showIndicator) + return; + + // Bar + + const float length[] = { 1.0f, 1.0f }; + + CGContextSetLineWidth(mboxctx, mbxBarWidth); + CGContextSetLineDash(mboxctx, 0, length, 2); + CGContextSetLineJoin(mboxctx, kCGLineJoinMiter); + + CGContextBeginPath(mboxctx); + + float x = mbxOffsetX + mbxMarginX + mbxBarWidth / 2.0f; + + for (int h = 0; h < 8; h++) + { + // Inactive + + CGContextSetRGBStrokeColor(mboxctx, (196.0f / 256.0f), (200.0f / 256.0f), (176.0f / 256.0f), 1.0f); + + CGContextMoveToPoint (mboxctx, x, mbxOffsetY + mbxMarginY); + CGContextAddLineToPoint(mboxctx, x, mbxOffsetY + mbxMarginY + mbxBarHeight); + + CGContextMoveToPoint (mboxctx, x + mbxRightBarX, mbxOffsetY + mbxMarginY); + CGContextAddLineToPoint(mboxctx, x + mbxRightBarX, mbxOffsetY + mbxMarginY + mbxBarHeight); + + CGContextStrokePath(mboxctx); + + // Max + + short vl = (spc_core->dsp_reg_value(h, 0x00) * spc_core->dsp_envx_value(h)) >> 11; + short vr = (spc_core->dsp_reg_value(h, 0x01) * spc_core->dsp_envx_value(h)) >> 11; + long long currentTime; + + if (vl <= 0) vl = 0; else if (vl > 64) vl = 64; else vl = (short) (yyscale * sqrt((double) vl)) & (~0 << 1); + if (vr <= 0) vr = 0; else if (vr > 64) vr = 64; else vr = (short) (yyscale * sqrt((double) vr)) & (~0 << 1); + + if (vl < prevLVol[h]) vl = ((prevLVol[h] + vl) >> 1); + if (vr < prevRVol[h]) vr = ((prevRVol[h] + vr) >> 1); + + Microseconds((UnsignedWide *) ¤tTime); + + // left + + if ((vl >= prevLMax[h]) && (vl > prevLVol[h])) + { + barTimeL[h] = currentTime; + prevLMax[h] = vl; + } + else + if ((prevLMax[h] > 0) && (barTimeL[h] + 1000000 > currentTime)) + { + CGContextSetRGBStrokeColor(mboxctx, (22.0f / 256.0f), (156.0f / 256.0f), (20.0f / 256.0f), (float) (barTimeL[h] + 1000000 - currentTime) / 1000000.0f); + + CGContextMoveToPoint (mboxctx, x, mbxOffsetY + mbxMarginY + (float) (prevLMax[h] - 2)); + CGContextAddLineToPoint(mboxctx, x, mbxOffsetY + mbxMarginY + (float) (prevLMax[h] )); + + CGContextStrokePath(mboxctx); + } + else + prevLMax[h] = 0; + + prevLVol[h] = vl; + + // right + + if ((vr >= prevRMax[h]) && (vr > prevRVol[h])) + { + barTimeR[h] = currentTime; + prevRMax[h] = vr; + } + else + if ((prevRMax[h] > 0) && (barTimeR[h] + 1000000 > currentTime)) + { + CGContextSetRGBStrokeColor(mboxctx, (22.0f / 256.0f), (156.0f / 256.0f), (20.0f / 256.0f), (float) (barTimeR[h] + 1000000 - currentTime) / 1000000.0f); + + CGContextMoveToPoint (mboxctx, x + mbxRightBarX, mbxOffsetY + mbxMarginY + (float) (prevRMax[h] - 2)); + CGContextAddLineToPoint(mboxctx, x + mbxRightBarX, mbxOffsetY + mbxMarginY + (float) (prevRMax[h] )); + + CGContextStrokePath(mboxctx); + } + else + prevRMax[h] = 0; + + prevRVol[h] = vr; + + // Active + + CGContextSetRGBStrokeColor(mboxctx, (22.0f / 256.0f), (22.0f / 256.0f), (20.0f / 256.0f), 1.0f); + + CGContextMoveToPoint (mboxctx, x, mbxOffsetY + mbxMarginY); + CGContextAddLineToPoint(mboxctx, x, mbxOffsetY + mbxMarginY + (float) vl); + CGContextStrokePath(mboxctx); + CGContextMoveToPoint (mboxctx, x + mbxRightBarX, mbxOffsetY + mbxMarginY); + CGContextAddLineToPoint(mboxctx, x + mbxRightBarX, mbxOffsetY + mbxMarginY + (float) vr); + CGContextStrokePath(mboxctx); + + x += (mbxBarWidth + mbxBarSpace); + } +} diff --git a/macosx/mac-musicbox.h b/macosx/mac-musicbox.h new file mode 100644 index 00000000..c50879f7 --- /dev/null +++ b/macosx/mac-musicbox.h @@ -0,0 +1,201 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_musicbox_h_ +#define _mac_musicbox_h_ + +#define kMBXSoundEmulation 1 +#define kMBXWholeEmulation 2 + +extern volatile Boolean mboxPause; + +void MusicBoxDialog (void); + +#endif diff --git a/macosx/mac-netplay.cpp b/macosx/mac-netplay.cpp new file mode 100644 index 00000000..0207c9f6 --- /dev/null +++ b/macosx/mac-netplay.cpp @@ -0,0 +1,238 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "mac-prefix.h" +#include "mac-netplay.h" + + +int socket_read (int fd, unsigned char *buf, int size) +{ + int l, n = 0; + + do + { + if ((l = read(fd, &buf[n], size - n)) <= 0) + return (-1); + else + n += l; + } while (n < size); + + return (n); +} + +int socket_write (int fd, unsigned char *buf, int size) +{ + int l, n = 0; + + do + { + if ((l = write(fd, &buf[n], size - n)) <= 0) + return (-1); + else + n += l; + } while (n < size); + + return (n); +} + +void NPError (const char *s, int err) +{ + printf("ERROR! %d: %s\n", err, s); +} + +void NPNotification (const char *s, int c) +{ + if (c != -1) + printf(s, c); + else + printf("%s", s); + + printf("\n"); +} diff --git a/macosx/mac-netplay.h b/macosx/mac-netplay.h new file mode 100644 index 00000000..9b788fb8 --- /dev/null +++ b/macosx/mac-netplay.h @@ -0,0 +1,259 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_netplay_h_ +#define _mac_netplay_h_ + +#define WRITE_LONG(p, v) \ +{ \ + *((p) + 0) = (uint8) ((v) >> 24); \ + *((p) + 1) = (uint8) ((v) >> 16); \ + *((p) + 2) = (uint8) ((v) >> 8); \ + *((p) + 3) = (uint8) ((v) >> 0); \ +} + +#define WRITE_BYTE(p, v) \ +{ \ + *(p) = (uint8) (v); \ +} + +#define READ_LONG(p) \ +( \ + (((uint8) *((p) + 0)) << 24) | \ + (((uint8) *((p) + 1)) << 16) | \ + (((uint8) *((p) + 2)) << 8) | \ + (((uint8) *((p) + 3)) << 0) \ +) + +#define READ_BYTE(p) \ +( \ + (uint8) *(p) \ +) + +//#define SELF_TEST + +#define NP_SERVER_MAGIC 'S' +#define NP_CLIENT_MAGIC 'C' +#define NP_MAX_PLAYERS 5 +#define NP_MAX_CLIENTS (NP_MAX_PLAYERS - 1) +#define NP_PORT 6096 + +#ifdef SELF_TEST +#define SOCK_NAME "/tmp/s9xsocket" +#endif + +enum +{ + kNPClientNameSent = 101, + kNPClientROMInfoWaiting, + kNPClientROMOpened, + kNPClientSRAMWaiting, + kNPClientSRAMLoaded, + kNPClientPlayerWaiting, + kNPClientPlayWaiting, + kNPClientStartWait +}; + +enum +{ + kNPServerNameRequest = 201, + kNPServerNameReceived, + kNPServerROMInfoWillSend, + kNPServerSRAMWillSend, + kNPServerPlayerWillSend, + kNPServerStart +}; + +int socket_read (int, unsigned char *, int); +int socket_write (int, unsigned char *, int); +void NPError (const char *, int); +void NPNotification (const char *, int); + +#endif diff --git a/macosx/mac-os.cpp b/macosx/mac-os.cpp new file mode 100644 index 00000000..ccaf02f7 --- /dev/null +++ b/macosx/mac-os.cpp @@ -0,0 +1,3464 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "apu.h" +#include "controls.h" +#include "crosshairs.h" +#include "cheats.h" +#include "movie.h" +#include "display.h" +#include "blit.h" + +#ifdef DEBUGGER +#include "debug.h" +#endif + +#include +#include + +#include "mac-prefix.h" +#include "mac-appleevent.h" +#include "mac-audio.h" +#include "mac-cheat.h" +#include "mac-cheatfinder.h" +#include "mac-client.h" +#include "mac-cocoatools.h" +#include "mac-controls.h" +#include "mac-coreimage.h" +#include "mac-dialog.h" +#include "mac-file.h" +#include "mac-gworld.h" +#include "mac-joypad.h" +#include "mac-keyboard.h" +#include "mac-multicart.h" +#include "mac-musicbox.h" +#include "mac-netplay.h" +#include "mac-prefs.h" +#include "mac-quicktime.h" +#include "mac-render.h" +#include "mac-screenshot.h" +#include "mac-server.h" +#include "mac-snes9x.h" +#include "mac-stringtools.h" +#include "mac-os.h" + +#define kRecentMenu_MAX 20 +#define KeyIsPressed(km, k) (1 & (((unsigned char *) km) [(k) >> 3] >> ((k) & 7))) + +volatile bool8 running = false; +volatile bool8 s9xthreadrunning = false; + +volatile bool8 eventQueued = false; + +volatile int windowResizeCount = 1; +volatile bool8 windowExtend = true; + +SInt32 systemVersion; + +uint32 controlPad[MAC_MAX_PLAYERS]; + +uint8 romDetect = kAutoROMType, + interleaveDetect = kAutoInterleave, + videoDetect = kAutoVideo, + headerDetect = kAutoHeader; + +WindowRef gWindow = NULL; +HIRect gWindowRect; +int glScreenW, + glScreenH; +CGRect glScreenBounds; +Point windowPos[kWindowCount]; +CGSize windowSize[kWindowCount]; + +CGImageRef macIconImage[118]; +int macPadIconIndex, + macLegendIconIndex, + macMusicBoxIconIndex, + macFunctionIconIndex; + +int macFrameSkip = -1; +int32 skipFrames = 3; +int64 lastFrame = 0; + +int macFastForwardRate = 5, + macFrameAdvanceRate = 1000000; + +unsigned long spcFileCount = 0, + pngFileCount = 0; + +bool8 finished = false, + cartOpen = false, + autofire = false, + hidExist = true, + folderWarning = false, + lockedROMMedia = false, + directDisplay = false; + +bool8 fullscreen = false, + autoRes = false, + glstretch = true, + gl32bit = true, + vsync = true, + drawoverscan = false, + screencurvature = false, + multiprocessor = false, + ciFilterEnable = false; +long drawingMethod = kDrawingOpenGL; +int videoMode = VIDEOMODE_SMOOTH; + +SInt32 macSoundVolume = 80; // % +uint32 macSoundBuffer_ms = 100; // ms +uint32 macSoundInterval_ms = 16; // ms +bool8 macSoundLagEnable = false; +uint16 aueffect = 0; + +uint8 saveInROMFolder = 2; // 0 : Snes9x 1 : ROM 2 : Application Support + +int macCurvatureWarp = 15, + macAspectRatio = 0; + +bool8 startopendlog = false, + showtimeinfrz = true, + enabletoggle = true, + savewindowpos = false, + onscreeninfo = true; +int inactiveMode = 2; +int musicboxmode = kMBXSoundEmulation; + +bool8 applycheat = false; +int padSetting = 1, + deviceSetting = 1, + deviceSettingMaster = 1; +int macControllerOption = SNES_JOYPAD; +AutoFireState autofireRec[MAC_MAX_PLAYERS]; + +bool8 macQTRecord = false; +uint16 macQTMovFlag = 0; + +uint16 macRecordFlag = 0x3, + macPlayFlag = 0x1; +wchar_t macRecordWChar[MOVIE_MAX_METADATA]; + +char npServerIP[256], + npName[256]; + +bool8 lastoverscan = false; + +CGPoint unlimitedCursor; + +ExtraOption extraOptions; + +CFStringRef multiCartPath[2]; + +#ifdef MAC_PANTHER_SUPPORT +IconRef macIconRef[118]; +#endif + +enum +{ + mApple = 128, + iAbout = 1, + + mFile = 129, + iOpen = 1, + iOpenMulti = 2, + iOpenRecent = 3, + iClose = 5, + iRomInfo = 7, + + mControl = 134, + iKeyboardLayout = 1, + iISpLayout = 2, + iAutoFire = 4, + iISpPreset = 6, + + mEdit = 130, + + mEmulation = 131, + iResume = 1, + iSoftReset = 3, + iReset = 4, + iDevice = 6, + + mCheat = 132, + iApplyCheats = 1, + iGameGenie = 3, + iCheatFinder = 4, + + mOption = 133, + iFreeze = 1, + iDefrost = 2, + iFreezeTo = 4, + iDefrostFrom = 5, + iRecordMovie = 7, + iPlayMovie = 8, + iQTMovie = 10, + iSaveSPC = 12, + iSaveSRAM = 13, + iCIFilter = 15, + iMusicBox = 17, + + mNetplay = 135, + iServer = 1, + iClient = 2, + + mPresets = 201, + + mDevice = 202, + iPad = 1, + iMouse = 2, + iMouse2 = 3, + iSuperScope = 4, + iMultiPlayer5 = 5, + iMultiPlayer5_2 = 6, + iJustifier1 = 7, + iJustifier2 = 8, + + mRecentItem = 203 +}; + +enum +{ + kmF1Key = 0x7A, + kmF2Key = 0x78, + kmF3Key = 0x63, + kmF4Key = 0x76, + kmF5Key = 0x60, + kmF6Key = 0x61, + km0Key = 0x1D, + km1Key = 0x12, + km2Key = 0x13, + km3Key = 0x14, + km4Key = 0x15, + km5Key = 0x17, + km6Key = 0x16, + km7Key = 0x1A, + km8Key = 0x1C, + km9Key = 0x19, + kmAKey = 0x00, + kmBKey = 0x0B, + kmCKey = 0x08, + kmEscKey = 0x35, + kmCtrKey = 0x3B, + kmMinusKey = 0x1B, + kmQKey = 0x0C, + kmWKey = 0x0D +}; + +struct ButtonCommand +{ + char command[16]; + uint8 keycode; + bool8 held; +}; + +struct GameViewInfo +{ + int globalLeft; + int globalTop; + int width; + int height; +}; + +static volatile bool8 rejectinput = false; + +static pthread_t s9xthread; + +static MenuRef recentMenu; +static CFStringRef recentItem[kRecentMenu_MAX + 1]; + +static EventHandlerUPP gameWindowUPP, + gameWUPaneUPP; +static EventHandlerRef gameWindowEventRef, + gameWUPaneEventRef; + +static int windowZoomCount = 0; + +static int frameCount = 0; + +static bool8 frzselecting = false; + +static uint16 changeAuto[2] = { 0x0000, 0x0000 }; + +static GameViewInfo scopeViewInfo; + +static ButtonCommand btncmd[] = +{ + { "ToggleBG0", kmF1Key, false }, + { "ToggleBG1", kmF2Key, false }, + { "ToggleBG2", kmF3Key, false }, + { "ToggleBG3", kmF4Key, false }, + { "ToggleSprites", kmF5Key, false }, + { "SwapJoypads", kmF6Key, false }, + { "SoundChannel0", km1Key, false }, + { "SoundChannel1", km2Key, false }, + { "SoundChannel2", km3Key, false }, + { "SoundChannel3", km4Key, false }, + { "SoundChannel4", km5Key, false }, + { "SoundChannel5", km6Key, false }, + { "SoundChannel6", km7Key, false }, + { "SoundChannel7", km8Key, false }, + { "SoundChannelsOn", km9Key, false }, + { "_mac1", km0Key, false }, + { "_mac2", kmMinusKey, false }, + { "_mac3", kmQKey, false }, + { "_mac4", kmWKey, false } +}; + +#define kCommandListSize (sizeof(btncmd) / sizeof(btncmd[0])) + +static void Initialize (void); +static void Deinitialize (void); +static void InitAutofire (void); +static void InitRecentItems (void); +static void DeinitRecentItems (void); +static void ClearRecentItems (void); +static void InitRecentMenu (void); +static void DeinitRecentMenu (void); +static void ProcessInput (void); +static void ResizeGameWindow (void); +static void ChangeAutofireSettings (int, int); +static void ChangeTurboRate (int); +static void ForceChangingKeyScript (void); +static void CFTimerCallback (CFRunLoopTimerRef, void *); +static void UpdateFreezeDefrostScreen (int, CGImageRef, uint8 *, CGContextRef); +static void * MacSnes9xThread (void *); +static OSStatus HandleMenuChoice (UInt32, Boolean *); +static inline void EmulationLoop (void); +static pascal OSStatus MainEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus SubEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus GameWindowEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus GameWindowUserPaneEventHandler (EventHandlerCallRef, EventRef, void *); + + +int main (int argc, char **argv) +{ + OSStatus err; + EventHandlerRef eref; + EventHandlerUPP eUPP; + EventTypeSpec mEvents[] = { { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }, + sEvents[] = { { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus }, + { kEventClassMouse, kEventMouseUp }, + { kEventClassMouse, kEventMouseMoved }, + { kEventClassMouse, kEventMouseDragged } }; + + eUPP = NewEventHandlerUPP(MainEventHandler); + err = InstallApplicationEventHandler(eUPP, GetEventTypeCount(mEvents), mEvents, NULL, &eref); + + Initialize(); + + while (!finished) + { + if (cartOpen && running) + { + #ifdef DEBUGGER + CPU.Flags |= DEBUG_MODE_FLAG; + S9xDoDebug(); + #endif + + eventQueued = false; + + Microseconds((UnsignedWide *) &lastFrame); + frameCount = 0; + if (macFrameSkip < 0) + skipFrames = 3; + else + skipFrames = macFrameSkip; + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eUPP); + + eUPP = NewEventHandlerUPP(SubEventHandler); + err = InstallApplicationEventHandler(eUPP, GetEventTypeCount(sEvents), sEvents, NULL, &eref); + + S9xInitDisplay(NULL, NULL); + ClearGFXScreen(); + + if (!fullscreen) + ForceChangingKeyScript(); + + pthread_create(&s9xthread, NULL, MacSnes9xThread, NULL); + + CFRunLoopTimerRef cftimer = NULL; + CFRunLoopTimerContext cftimerctx = { 0, NULL, NULL, NULL, NULL }; + + if (!fullscreen) + { + cftimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), 30, 0, 0, CFTimerCallback, &cftimerctx); + if (cftimer) + CFRunLoopAddTimer(CFRunLoopGetCurrent(), cftimer, kCFRunLoopCommonModes); + } + + AdjustMenus(); + + RunApplicationEventLoop(); + + if (!fullscreen) + { + if (cftimer) + { + CFRunLoopTimerInvalidate(cftimer); + CFRelease(cftimer); + cftimer = NULL; + } + } + + pthread_join(s9xthread, NULL); + + S9xDeinitDisplay(); + + if (Settings.NetPlay) + { + if (!Settings.NetPlayServer) + { + DeinitGameWindow(); + cartOpen = false; + } + + Settings.NetPlay = false; + Settings.NetPlayServer = false; + } + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eUPP); + + eUPP = NewEventHandlerUPP(MainEventHandler); + err = InstallApplicationEventHandler(eUPP, GetEventTypeCount(mEvents), mEvents, NULL, &eref); + } + + if (!finished) + { + AdjustMenus(); + RunApplicationEventLoop(); + } + } + + Deinitialize(); + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eUPP); + + return (0); +} + +static void CFTimerCallback (CFRunLoopTimerRef timer, void *info) +{ + OSStatus err; + + err = UpdateSystemActivity(OverallAct); +} + +static void * MacSnes9xThread (void *) +{ + Settings.StopEmulation = false; + s9xthreadrunning = true; + + EmulationLoop(); + + s9xthreadrunning = false; + Settings.StopEmulation = true; + + return (NULL); +} + +static inline void EmulationLoop (void) +{ + bool8 olddisplayframerate = false; + + if (macQTRecord) + { + olddisplayframerate = Settings.DisplayFrameRate; + Settings.DisplayFrameRate = false; + } + + MacStartSound(); + + if (Settings.NetPlay) + { + if (Settings.NetPlayServer) + { + NPServerDetachNetPlayThread(); + NPServerStartClients(); + + while (running) + { + NPServerProcessInput(); + S9xMainLoop(); + } + + NPServerStopNetPlayThread(); + NPServerStopServer(); + } + else + { + NPClientDetachNetPlayThread(); + NPClientNetPlayWaitStart(); + + while (running) + { + NPClientProcessInput(); + S9xMainLoop(); + } + + NPClientStopNetPlayThread(); + NPClientDisconnect(); + + NPClientRestoreConfig(); + } + } + else + { + while (running) + { + ProcessInput(); + S9xMainLoop(); + } + } + + MacStopSound(); + + if (macQTRecord) + { + MacQTStopRecording(); + macQTRecord = false; + + Settings.DisplayFrameRate = olddisplayframerate; + } + + S9xMovieShutdown(); +} + +static pascal OSStatus MainEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + Boolean done = false; + + if (frzselecting) + return (result); + + switch (GetEventClass(inEvent)) + { + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand cmd; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd); + if (err == noErr && cmd.commandID == 'clos') + { + UpdateMenuCommandStatus(false); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd); + if (err == noErr) + { + UInt32 modifierkey; + + err = GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifierkey); + if (err == noErr) + { + if ((cmd.commandID == 'pref') && (modifierkey & optionKey)) + cmd.commandID = 'EXTR'; + + result = HandleMenuChoice(cmd.commandID, &done); + + if (done) + QuitApplicationEventLoop(); + } + } + + break; + } + + break; + } + + return (result); +} + +static pascal OSStatus SubEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + + if (frzselecting) + return (result); + + switch (GetEventClass(inEvent)) + { + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand cmd; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd); + if (err == noErr && cmd.commandID == 'clos') + { + UpdateMenuCommandStatus(false); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd); + if (err == noErr) + { + switch (cmd.commandID) + { + case 'Erun': // Pause + case 'SubQ': // Queue from emulation thread + running = false; + while (s9xthreadrunning) + sleep(0); + QuitApplicationEventLoop(); + result = noErr; + break; + + case 'Ocif': // Core Image Filter + HiliteMenu(0); + ConfigureCoreImageFilter(); + result = noErr; + break; + } + } + + break; + } + + break; + + case kEventClassMouse: + if (fullscreen) + { + if ((macControllerOption == SNES_JOYPAD) || (macControllerOption == SNES_MULTIPLAYER5) || (macControllerOption == SNES_MULTIPLAYER5_2)) + { + if (!(Settings.NetPlay && !Settings.NetPlayServer)) + { + switch (GetEventKind(inEvent)) + { + case kEventMouseUp: + HIPoint hipt; + + err = GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(HIPoint), NULL, &hipt); + if (err == noErr) + { + if (CGRectContainsPoint(glScreenBounds, hipt)) + { + running = false; + while (s9xthreadrunning) + sleep(0); + QuitApplicationEventLoop(); + result = noErr; + } + } + + break; + } + } + } + else + if ((macControllerOption == SNES_MOUSE) || (macControllerOption == SNES_MOUSE_SWAPPED)) + { + switch (GetEventKind(inEvent)) + { + case kEventMouseMoved: + case kEventMouseDragged: + HIPoint hipt; + + err = GetEventParameter(inEvent, kEventParamMouseDelta, typeHIPoint, NULL, sizeof(HIPoint), NULL, &hipt); + if (err == noErr) + { + unlimitedCursor.x += hipt.x; + unlimitedCursor.y += hipt.y; + } + + break; + } + } + } + + break; + } + + return (result); +} + +void PostQueueToSubEventLoop (void) +{ + OSStatus err; + EventRef event; + + err = CreateEvent(kCFAllocatorDefault, kEventClassCommand, kEventCommandProcess, 0, kEventAttributeUserEvent, &event); + if (err == noErr) + { + HICommand cmd; + + cmd.commandID = 'SubQ'; + cmd.attributes = kEventAttributeUserEvent; + cmd.menu.menuRef = NULL; + cmd.menu.menuItemIndex = 0; + + err = SetEventParameter(event, kEventParamDirectObject, typeHICommand, sizeof(HICommand), &cmd); + if (err == noErr) + err = PostEventToQueue(GetMainEventQueue(), event, kEventPriorityStandard); + + ReleaseEvent(event); + } +} + +void InitGameWindow (void) +{ + OSStatus err; + IBNibRef nibRef; + WindowAttributes attr; + CFStringRef ref; + HIViewRef ctl; + HIViewID cid = { 'Pict', 0 }; + Rect rct; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + EventTypeSpec wupaneEvents[] = { { kEventClassControl, kEventControlClick }, + { kEventClassControl, kEventControlDraw } }, + windowEvents[] = { { kEventClassWindow, kEventWindowDeactivated }, + { kEventClassWindow, kEventWindowActivated }, + { kEventClassWindow, kEventWindowBoundsChanging }, + { kEventClassWindow, kEventWindowBoundsChanged }, + { kEventClassWindow, kEventWindowZoom }, + { kEventClassWindow, kEventWindowToolbarSwitchMode } }; + + if (gWindow) + return; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err) + QuitWithFatalError(err, "os 02"); + + err = CreateWindowFromNib(nibRef, CFSTR("GameWindow"), &gWindow); + if (err) + QuitWithFatalError(err, "os 03"); + + DisposeNibReference(nibRef); + + HIViewFindByID(HIViewGetRoot(gWindow), cid, &ctl); + + gameWindowUPP = NewEventHandlerUPP(GameWindowEventHandler); + err = InstallWindowEventHandler(gWindow, gameWindowUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) gWindow, &gameWindowEventRef); + + gameWUPaneUPP = NewEventHandlerUPP(GameWindowUserPaneEventHandler); + err = InstallControlEventHandler(ctl, gameWUPaneUPP, GetEventTypeCount(wupaneEvents), wupaneEvents, (void *) gWindow, &gameWUPaneEventRef); + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + ref = CFStringCreateWithCString(kCFAllocatorDefault, fname, MAC_PATH_ENCODING); + if (ref) + { + SetWindowTitleWithCFString(gWindow, ref); + CFRelease(ref); + } + + attr = kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute; + err = ChangeWindowAttributes(gWindow, attr, kWindowNoAttributes); + + attr = kWindowToolbarButtonAttribute; + if (!drawoverscan) + err = ChangeWindowAttributes(gWindow, attr, kWindowNoAttributes); + else + err = ChangeWindowAttributes(gWindow, kWindowNoAttributes, attr); + + if (savewindowpos) + { + MoveWindow(gWindow, windowPos[kWindowScreen].h, windowPos[kWindowScreen].v, false); + + if ((windowSize[kWindowScreen].width <= 0) || (windowSize[kWindowScreen].height <= 0)) + { + windowExtend = true; + windowSize[kWindowScreen].width = 512; + windowSize[kWindowScreen].height = kMacWindowHeight; + } + + if (!lastoverscan && !windowExtend && drawoverscan) + { + windowExtend = true; + windowSize[kWindowScreen].height = (int) ((float) (windowSize[kWindowScreen].height + 0.5) * SNES_HEIGHT_EXTENDED / SNES_HEIGHT); + } + + SizeWindow(gWindow, (short) windowSize[kWindowScreen].width, (short) windowSize[kWindowScreen].height, false); + } + else + { + if (drawoverscan) + windowExtend = true; + + SizeWindow(gWindow, 512, (windowExtend ? kMacWindowHeight : (SNES_HEIGHT << 1)), false); + RepositionWindow(gWindow, NULL, kWindowCenterOnMainScreen); + } + + windowZoomCount = 0; + + GetWindowBounds(gWindow, kWindowContentRgn, &rct); + gWindowRect = CGRectMake((float) rct.left, (float) rct.top, (float) (rct.right - rct.left), (float) (rct.bottom - rct.top)); + + ActivateWindow(gWindow, true); +} + +void UpdateGameWindow (void) +{ + OSStatus err; + HIViewRef ctl; + HIViewID cid = { 'Pict', 0 }; + + if (!gWindow) + return; + + HIViewFindByID(HIViewGetRoot(gWindow), cid, &ctl); + err = HIViewSetNeedsDisplay(ctl, true); +} + +static void ResizeGameWindow (void) +{ + Rect rct; + int ww, wh; + + if (!gWindow) + return; + + GetWindowBounds(gWindow, kWindowContentRgn, &rct); + + wh = (windowExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) * ((windowZoomCount >> 1) + 1); + + if (windowZoomCount % 2) + ww = SNES_NTSC_OUT_WIDTH(SNES_WIDTH) * ((windowZoomCount >> 1) + 1) / 2; + else + ww = SNES_WIDTH * ((windowZoomCount >> 1) + 1); + + rct.right = rct.left + ww; + rct.bottom = rct.top + wh; + + SetWindowBounds(gWindow, kWindowContentRgn, &rct); + + printf("Window Size: %d, %d\n", ww, wh); + + windowZoomCount++; + if (windowZoomCount == 8) + windowZoomCount = 0; +} + +void DeinitGameWindow (void) +{ + OSStatus err; + + if (!gWindow) + return; + + SaveWindowPosition(gWindow, kWindowScreen); + lastoverscan = drawoverscan; + + err = RemoveEventHandler(gameWUPaneEventRef); + DisposeEventHandlerUPP(gameWUPaneUPP); + + err = RemoveEventHandler(gameWindowEventRef); + DisposeEventHandlerUPP(gameWindowUPP); + + CFRelease(gWindow); + gWindow = NULL; +} + +static pascal OSStatus GameWindowEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + HIRect rct; + Rect r; + UInt32 attr; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + switch (GetEventKind(inEvent)) + { + case kEventWindowDeactivated: + if (running) + { + if (!(Settings.NetPlay && !Settings.NetPlayServer)) + { + if (inactiveMode == 3) + { + running = false; + while (s9xthreadrunning) + sleep(0); + QuitApplicationEventLoop(); + result = noErr; + } + else + if (inactiveMode == 2) + { + rejectinput = true; + result = noErr; + } + } + } + + break; + + case kEventWindowActivated: + if (running) + { + if (!(Settings.NetPlay && !Settings.NetPlayServer)) + { + ForceChangingKeyScript(); + + if (inactiveMode == 2) + { + rejectinput = false; + result = noErr; + } + } + } + + break; + + case kEventWindowBoundsChanging: + windowResizeCount = 0x7FFFFFFF; + + err = GetEventParameter(inEvent, kEventParamAttributes, typeUInt32, NULL, sizeof(UInt32), NULL, &attr); + if ((err == noErr) && (attr & kWindowBoundsChangeSizeChanged)) + { + err = GetEventParameter(inEvent, kEventParamCurrentBounds, typeHIRect, NULL, sizeof(HIRect), NULL, &rct); + if (err == noErr) + { + if (GetCurrentEventKeyModifiers() & shiftKey) + { + HIRect origRct; + + err = GetEventParameter(inEvent, kEventParamOriginalBounds, typeHIRect, NULL, sizeof(HIRect), NULL, &origRct); + if (err == noErr) + { + rct.size.width = (float) (int) (origRct.size.width * rct.size.height / origRct.size.height); + err = SetEventParameter(inEvent, kEventParamCurrentBounds, typeHIRect, sizeof(HIRect), &rct); + } + } + + gWindowRect = rct; + } + } + + result = noErr; + break; + + case kEventWindowBoundsChanged: + windowResizeCount = 3; + result = noErr; + break; + + case kEventWindowZoom: + ResizeGameWindow(); + result = noErr; + break; + + case kEventWindowToolbarSwitchMode: + windowExtend = !windowExtend; + + GetWindowBounds(gWindow, kWindowContentRgn, &r); + + if (windowExtend) + r.bottom = r.top + (int) (((float) (r.bottom - r.top) + 0.5) * SNES_HEIGHT_EXTENDED / SNES_HEIGHT); + else + r.bottom = r.top + (int) (((float) (r.bottom - r.top) + 0.5) * SNES_HEIGHT / SNES_HEIGHT_EXTENDED); + + SetWindowBounds(gWindow, kWindowContentRgn, &r); + + result = noErr; + break; + } + + break; + } + + return (result); +} + +static pascal OSStatus GameWindowUserPaneEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + + switch (GetEventClass(inEvent)) + { + case kEventClassControl: + switch (GetEventKind(inEvent)) + { + case kEventControlClick: + if (running) + { + if ((macControllerOption == SNES_JOYPAD) || (macControllerOption == SNES_MULTIPLAYER5) || (macControllerOption == SNES_MULTIPLAYER5_2)) + { + if (!(Settings.NetPlay && !Settings.NetPlayServer)) + { + if (!frzselecting) + { + running = false; + while (s9xthreadrunning) + sleep(0); + QuitApplicationEventLoop(); + result = noErr; + } + } + } + } + else + { + UInt32 count; + + err = GetEventParameter(inEvent, kEventParamClickCount, typeUInt32, NULL, sizeof(UInt32), NULL, &count); + if ((err == noErr) && (count == 2)) + { + SNES9X_Go(); + QuitApplicationEventLoop(); + result = noErr; + } + } + + break; + + case kEventControlDraw: + CGContextRef ctx; + HIViewRef view; + HIRect bounds; + + err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view); + if (err == noErr) + { + err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &ctx); + if (err == noErr) + { + if (!running) + { + HIViewGetBounds(view, &bounds); + CGContextTranslateCTM(ctx, 0, bounds.size.height); + CGContextScaleCTM(ctx, 1.0f, -1.0f); + DrawPauseScreen(ctx, bounds); + } + } + } + + result = noErr; + break; + } + + break; + } + + return (result); +} + +static void InitRecentItems (void) +{ + CFStringRef keyRef, pathRef; + int count; + char key[32]; + + count = 0; + + for (int i = 0; i <= kRecentMenu_MAX; i++) + recentItem[i] = NULL; + + for (int i = 0; i < kRecentMenu_MAX; i++) + { + sprintf(key, "RecentItem_%02d", i); + keyRef = CFStringCreateWithCString(kCFAllocatorDefault, key, CFStringGetSystemEncoding()); + if (keyRef) + { + pathRef = (CFStringRef) CFPreferencesCopyAppValue(keyRef, kCFPreferencesCurrentApplication); + if (pathRef) + { + recentItem[count] = pathRef; + count++; + } + + CFRelease(keyRef); + } + } +} + +static void DeinitRecentItems (void) +{ + CFStringRef keyRef; + char key[32]; + + for (int i = 0; i < kRecentMenu_MAX; i++) + { + sprintf(key, "RecentItem_%02d", i); + keyRef = CFStringCreateWithCString(kCFAllocatorDefault, key, CFStringGetSystemEncoding()); + if (keyRef) + { + if (recentItem[i]) + { + CFPreferencesSetAppValue(keyRef, recentItem[i], kCFPreferencesCurrentApplication); + CFRelease(recentItem[i]); + recentItem[i] = NULL; + } + else + CFPreferencesSetAppValue(keyRef, NULL, kCFPreferencesCurrentApplication); + + CFRelease(keyRef); + } + } + + CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); +} + +static void ClearRecentItems (void) +{ + for (int i = 0; i < kRecentMenu_MAX; i++) + { + if (recentItem[i]) + { + CFRelease(recentItem[i]); + recentItem[i] = NULL; + } + } +} + +void AddRecentItem (FSRef *ref) +{ + OSStatus err; + char path[PATH_MAX + 1]; + + err = FSRefMakePath(ref, (unsigned char *) path, PATH_MAX); + if (err == noErr) + { + CFStringRef pathRef; + + pathRef = CFStringCreateWithCString(kCFAllocatorDefault, path, MAC_PATH_ENCODING); + if (pathRef) + { + int i, j; + + for (i = 0; i < kRecentMenu_MAX; i++) + if (recentItem[i] && (CFStringCompare(pathRef, recentItem[i], 0) == 0)) + break; + + if (i == kRecentMenu_MAX) + { + for (j = kRecentMenu_MAX - 1; j >= 0; j--) + recentItem[j + 1] = recentItem[j]; + + if (recentItem[kRecentMenu_MAX]) + { + CFRelease(recentItem[kRecentMenu_MAX]); + recentItem[kRecentMenu_MAX] = NULL; + } + + recentItem[0] = pathRef; + } + else + { + CFRelease(pathRef); + + if (i > 0) + { + CFStringRef temp; + + temp = recentItem[i]; + + for (j = i - 1; j >= 0; j--) + recentItem[j + 1] = recentItem[j]; + + recentItem[0] = temp; + } + } + } + } +} + +static void InitRecentMenu (void) +{ + OSStatus err; + + err = CreateNewMenu(mRecentItem, 0, &recentMenu); + err = SetMenuItemHierarchicalMenu(GetMenuRef(mFile), iOpenRecent, recentMenu); +} + +static void DeinitRecentMenu (void) +{ + CFRelease(recentMenu); +} + +void BuildRecentMenu (void) +{ + OSStatus err; + CFStringRef str; + + err = DeleteMenuItems(recentMenu, 1, CountMenuItems(recentMenu)); + + for (int i = 0; i < kRecentMenu_MAX; i++) + { + if (!recentItem[i]) + break; + + Boolean r; + char path[PATH_MAX + 1]; + + r = CFStringGetCString(recentItem[i], path, PATH_MAX, MAC_PATH_ENCODING); + if (r) + { + CFStringRef nameRef; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(path, drive, dir, fname, ext); + snprintf(path, PATH_MAX + 1, "%s%s", fname, ext); + nameRef = CFStringCreateWithCString(kCFAllocatorDefault, path, MAC_PATH_ENCODING); + if (nameRef) + { + err = AppendMenuItemTextWithCFString(recentMenu, nameRef, 0, 'FRe0' + i, NULL); + CFRelease(nameRef); + } + } + } + + err = AppendMenuItemTextWithCFString(recentMenu, NULL, kMenuItemAttrSeparator, 'FR__', NULL); + + str = CFCopyLocalizedString(CFSTR("ClearMenu"), "ClearMenu"); + if (str) + { + err = AppendMenuItemTextWithCFString(recentMenu, str, 0, 'FRcr', NULL); + CFRelease(str); + } +} + +void AdjustMenus (void) +{ + OSStatus err; + MenuRef menu; + CFStringRef str; + + if (running) + { + menu = GetMenuRef(mApple); + DisableMenuItem(menu, iAbout); + DisableMenuCommand(NULL, kHICommandPreferences); + DisableMenuCommand(NULL, kHICommandQuit); + + menu = GetMenuRef(mFile); + DisableMenuItem(menu, iOpen); + DisableMenuItem(menu, iOpenMulti); + DisableMenuItem(menu, iOpenRecent); + DisableMenuItem(menu, iRomInfo); + + menu = GetMenuRef(mControl); + DisableMenuItem(menu, iKeyboardLayout); + DisableMenuItem(menu, iISpLayout); + DisableMenuItem(menu, iAutoFire); + DisableMenuItem(menu, iISpPreset); + + menu = GetMenuRef(mEmulation); + str = CFCopyLocalizedString(CFSTR("PauseMenu"), "pause"); + err = SetMenuItemTextWithCFString(menu, iResume, str); + CFRelease(str); + DisableMenuItem(menu, iSoftReset); + DisableMenuItem(menu, iReset); + DisableMenuItem(menu, iDevice); + + if (Settings.NetPlay) + { + if (Settings.NetPlayServer) + EnableMenuItem(menu, iResume); + else + DisableMenuItem(menu, iResume); + } + else + EnableMenuItem(menu, iResume); + + menu = GetMenuRef(mCheat); + DisableMenuItem(menu, iApplyCheats); + DisableMenuItem(menu, iGameGenie); + DisableMenuItem(menu, iCheatFinder); + + menu = GetMenuRef(mOption); + DisableMenuItem(menu, iFreeze); + DisableMenuItem(menu, iDefrost); + DisableMenuItem(menu, iFreezeTo); + DisableMenuItem(menu, iDefrostFrom); + DisableMenuItem(menu, iRecordMovie); + DisableMenuItem(menu, iPlayMovie); + DisableMenuItem(menu, iQTMovie); + DisableMenuItem(menu, iSaveSPC); + DisableMenuItem(menu, iSaveSRAM); + DisableMenuItem(menu, iMusicBox); + if (ciFilterEnable) + EnableMenuItem(menu, iCIFilter); + else + DisableMenuItem(menu, iCIFilter); + + menu = GetMenuRef(mNetplay); + DisableMenuItem(menu, iServer); + DisableMenuItem(menu, iClient); + } + else + { + menu = GetMenuRef(mApple); + EnableMenuItem(menu, iAbout); + EnableMenuCommand(NULL, kHICommandPreferences); + EnableMenuCommand(NULL, kHICommandQuit); + + menu = GetMenuRef(mFile); + EnableMenuItem(menu, iOpen); + EnableMenuItem(menu, iOpenMulti); + EnableMenuItem(menu, iOpenRecent); + if (cartOpen) + EnableMenuItem(menu, iRomInfo); + else + DisableMenuItem(menu, iRomInfo); + + menu = GetMenuRef(mControl); + EnableMenuItem(menu, iKeyboardLayout); + EnableMenuItem(menu, iAutoFire); + if (hidExist) + { + EnableMenuItem(menu, iISpLayout); + EnableMenuItem(menu, iISpPreset); + } + else + { + DisableMenuItem(menu, iISpLayout); + DisableMenuItem(menu, iISpPreset); + } + + menu = GetMenuRef(mEmulation); + str = CFCopyLocalizedString(CFSTR("RunMenu"), "run"); + err = SetMenuItemTextWithCFString(menu, iResume, str); + CFRelease(str); + EnableMenuItem(menu, iDevice); + if (cartOpen) + { + EnableMenuItem(menu, iResume); + EnableMenuItem(menu, iSoftReset); + EnableMenuItem(menu, iReset); + } + else + { + DisableMenuItem(menu, iResume); + DisableMenuItem(menu, iSoftReset); + DisableMenuItem(menu, iReset); + } + + menu = GetMenuRef(mCheat); + if (cartOpen) + { + EnableMenuItem(menu, iApplyCheats); + EnableMenuItem(menu, iGameGenie); + EnableMenuItem(menu, iCheatFinder); + } + else + { + DisableMenuItem(menu, iApplyCheats); + DisableMenuItem(menu, iGameGenie); + DisableMenuItem(menu, iCheatFinder); + } + + menu = GetMenuRef(mOption); + DisableMenuItem(menu, iCIFilter); + if (cartOpen) + { + EnableMenuItem(menu, iFreeze); + EnableMenuItem(menu, iDefrost); + EnableMenuItem(menu, iFreezeTo); + EnableMenuItem(menu, iDefrostFrom); + EnableMenuItem(menu, iRecordMovie); + EnableMenuItem(menu, iPlayMovie); + EnableMenuItem(menu, iQTMovie); + EnableMenuItem(menu, iSaveSPC); + EnableMenuItem(menu, iSaveSRAM); + EnableMenuItem(menu, iMusicBox); + } + else + { + DisableMenuItem(menu, iFreeze); + DisableMenuItem(menu, iDefrost); + DisableMenuItem(menu, iFreezeTo); + DisableMenuItem(menu, iDefrostFrom); + DisableMenuItem(menu, iRecordMovie); + DisableMenuItem(menu, iPlayMovie); + DisableMenuItem(menu, iQTMovie); + DisableMenuItem(menu, iSaveSPC); + DisableMenuItem(menu, iSaveSRAM); + DisableMenuItem(menu, iMusicBox); + } + + menu = GetMenuRef(mNetplay); + EnableMenuItem(menu, iClient); + if (cartOpen) + EnableMenuItem(menu, iServer); + else + DisableMenuItem(menu, iServer); + } + + DrawMenuBar(); +} + +void UpdateMenuCommandStatus (Boolean closeMenu) +{ + if (closeMenu) + EnableMenuItem(GetMenuRef(mFile), iClose); + else + DisableMenuItem(GetMenuRef(mFile), iClose); +} + +static OSStatus HandleMenuChoice (UInt32 command, Boolean *done) +{ + OSStatus err, result = noErr; + MenuRef mh; + int item; + bool8 isok = true; + + if ((command & 0xFFFFFF00) == 'FRe\0') + { + Boolean r; + int index; + char path[PATH_MAX + 1]; + + index = (int) (command & 0x000000FF) - (int) '0'; + r = CFStringGetCString(recentItem[index], path, PATH_MAX, MAC_PATH_ENCODING); + if (r) + { + FSRef ref; + + err = FSPathMakeRef((unsigned char *) path, &ref, NULL); + if (err == noErr) + { + if (SNES9X_OpenCart(&ref)) + { + SNES9X_Go(); + *done = true; + } + else + AdjustMenus(); + } + } + } + else + { + switch (command) + { + case 'abou': // About SNES9X + StartCarbonModalDialog(); + AboutDialog(); + FinishCarbonModalDialog(); + + break; + + case 'pref': // Preferences... + StartCarbonModalDialog(); + ConfigurePreferences(); + FinishCarbonModalDialog(); + + break; + + case 'EXTR': // Extra Options... + StartCarbonModalDialog(); + ConfigureExtraOptions(); + FinishCarbonModalDialog(); + + break; + + case 'quit': // Quit SNES9X + SNES9X_Quit(); + *done = true; + + break; + + case 'open': // Open ROM Image... + if (SNES9X_OpenCart(NULL)) + { + SNES9X_Go(); + *done = true; + } + else + AdjustMenus(); + + break; + + case 'Mult': // Open Multiple ROM Images... + if (SNES9X_OpenMultiCart()) + { + SNES9X_Go(); + *done = true; + } + else + AdjustMenus(); + + break; + + case 'FRcr': // Clear Menu + ClearRecentItems(); + BuildRecentMenu(); + + break; + + case 'Finf': // ROM Information + StartCarbonModalDialog(); + RomInfoDialog(); + FinishCarbonModalDialog(); + + break; + + case 'Ckey': // Configure Keyboard... + StartCarbonModalDialog(); + ConfigureKeyboard(); + FinishCarbonModalDialog(); + + break; + + case 'Cpad': // Configure Controllers... + StartCarbonModalDialog(); + ConfigureHID(); + FinishCarbonModalDialog(); + + break; + + case 'Caut': // Automatic Fire... + StartCarbonModalDialog(); + ConfigureAutofire(); + FinishCarbonModalDialog(); + + break; + + case 'Hapl': // Apply Cheat Entries + mh = GetMenuRef(mCheat); + applycheat = !applycheat; + CheckMenuItem(mh, iApplyCheats, applycheat); + Settings.ApplyCheats = applycheat; + + if (!Settings.ApplyCheats) + S9xRemoveCheats(); + else + S9xApplyCheats(); + + break; + + case 'Hent': // Cheat Entry... + StartCarbonModalDialog(); + ConfigureCheat(); + FinishCarbonModalDialog(); + + break; + + case 'Hfnd': // Cheat Finder... + StartCarbonModalDialog(); + CheatFinder(); + FinishCarbonModalDialog(); + + break; + + case 'Erun': // Run + SNES9X_Go(); + *done = true; + + break; + + case 'Esrs': // Software Reset + SNES9X_SoftReset(); + SNES9X_Go(); + *done = true; + + break; + + case 'Erst': // Hardware Reset + SNES9X_Reset(); + SNES9X_Go(); + *done = true; + + break; + + case 'Ofrz': // Freeze State + isok = SNES9X_Freeze(); + *done = true; + + break; + + case 'Odfr': // Defrost state + isok = SNES9X_Defrost(); + *done = true; + + break; + + case 'Ofrd': // Freeze State to... + StartCarbonModalDialog(); + isok = SNES9X_FreezeTo(); + FinishCarbonModalDialog(); + + break; + + case 'Odfd': // Defrost State From... + StartCarbonModalDialog(); + isok = SNES9X_DefrostFrom(); + if (gWindow) + ActivateWindow(gWindow, true); + FinishCarbonModalDialog(); + *done = true; + + break; + + case 'MVrc': // Record Movie... + StartCarbonModalDialog(); + isok = SNES9X_RecordMovie(); + if (gWindow) + ActivateWindow(gWindow, true); + FinishCarbonModalDialog(); + *done = true; + + break; + + case 'MVpl': // Play Movie... + StartCarbonModalDialog(); + isok = SNES9X_PlayMovie(); + if (isok && (macPlayFlag & 0x2)) + { + running = false; + isok = SNES9X_QTMovieRecord(); + running = true; + } + + if (gWindow) + ActivateWindow(gWindow, true); + FinishCarbonModalDialog(); + *done = true; + + break; + + case 'QTmv': // Record QuickTime Movie... + StartCarbonModalDialog(); + isok = SNES9X_QTMovieRecord(); + if (gWindow) + ActivateWindow(gWindow, true); + FinishCarbonModalDialog(); + *done = true; + + break; + + case 'Ospc': // Save SPC File at Next Note-on + S9xDumpSPCSnapshot(); + + break; + + case 'Osrm': // Save SRAM Now + SNES9X_SaveSRAM(); + + break; + + case 'Ombx': // Music Box + StartCarbonModalDialog(); + MusicBoxDialog(); + FinishCarbonModalDialog(); + + break; + + case 'Nser': // Server... + bool8 sr; + + Settings.NetPlay = false; + Settings.NetPlayServer = false; + + NPServerInit(); + + if (!NPServerStartServer(NP_PORT)) + { + NPServerStopServer(); + break; + } + + StartCarbonModalDialog(); + sr = NPServerDialog(); + FinishCarbonModalDialog(); + + if (sr) + { + SNES9X_Reset(); + SNES9X_Go(); + Settings.NetPlay = true; + Settings.NetPlayServer = true; + + *done = true; + } + else + NPServerStopServer(); + + break; + + case 'Ncli': // Client... + bool8 cr; + + Settings.NetPlay = false; + Settings.NetPlayServer = false; + + NPClientInit(); + + StartCarbonModalDialog(); + cr = NPClientDialog(); + FinishCarbonModalDialog(); + + if (cr) + { + SNES9X_Go(); + Settings.NetPlay = true; + Settings.NetPlayServer = false; + + *done = true; + } + else + AdjustMenus(); + + break; + + case 'CPr1': // Controller Preset + case 'CPr2': + case 'CPr3': + case 'CPr4': + case 'CPr5': + item = (int) (command & 0x000000FF) - (int) '0'; + err = GetMenuItemHierarchicalMenu(GetMenuRef(mControl), iISpPreset, &mh); + CheckMenuItem(mh, padSetting, false); + padSetting = item; + CheckMenuItem(mh, padSetting, true); + ClearPadSetting(); + LoadControllerSettings(); + + break; + + case 'EIp1': // Input Device + case 'EIp2': + case 'EIp3': + case 'EIp4': + case 'EIp5': + case 'EIp6': + case 'EIp7': + case 'EIp8': + item = (int) (command & 0x000000FF) - (int) '0'; + err = GetMenuItemHierarchicalMenu(GetMenuRef(mEmulation), iDevice, &mh); + CheckMenuItem(mh, deviceSetting, false); + deviceSetting = item; + deviceSettingMaster = deviceSetting; + CheckMenuItem(mh, deviceSetting, true); + ChangeInputDevice(); + + break; + + default: + result = eventNotHandledErr; + break; + } + } + + return (result); +} + +void ChangeInputDevice (void) +{ + switch (deviceSetting) + { + case iPad: + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); + macControllerOption = SNES_JOYPAD; + break; + + case iMouse: + S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0); + S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); + macControllerOption = SNES_MOUSE; + break; + + case iMouse2: + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0); + macControllerOption = SNES_MOUSE_SWAPPED; + break; + + case iSuperScope: + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0); + macControllerOption = SNES_SUPERSCOPE; + break; + + case iMultiPlayer5: + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_MP5, 1, 2, 3, 4); + macControllerOption = SNES_MULTIPLAYER5; + break; + + case iMultiPlayer5_2: + S9xSetController(0, CTL_MP5, 0, 1, 2, 3); + S9xSetController(1, CTL_MP5, 4, 5, 6, 7); + macControllerOption = SNES_MULTIPLAYER5_2; + break; + + case iJustifier1: + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_JUSTIFIER, 0, 0, 0, 0); + macControllerOption = SNES_JUSTIFIER; + break; + + case iJustifier2: + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0); + macControllerOption = SNES_JUSTIFIER_2; + break; + } +} + +void ApplyNSRTHeaderControllers (void) +{ + OSStatus err; + MenuRef menu; + + err = GetMenuItemHierarchicalMenu(GetMenuRef(mEmulation), iDevice, &menu); + if (err) + return; + + for (int i = 1; i <= CountMenuItems(menu); i++) + { + CheckMenuItem(menu, i, false); + SetItemStyle(menu, i, normal); + } + + deviceSetting = deviceSettingMaster; + + uint32 valid = 0; + + if (!strncmp((const char *) Memory.NSRTHeader + 24, "NSRT", 4)) + { + switch (Memory.NSRTHeader[29]) + { + case 0x00: // Everything goes + deviceSetting = iPad; + valid = (1 << iPad); + break; + + case 0x10: // Mouse in Port 0 + deviceSetting = iMouse; + valid = (1 << iMouse); + break; + + case 0x01: // Mouse in Port 1 + deviceSetting = iMouse2; + valid = (1 << iMouse2); + break; + + case 0x03: // Super Scope in Port 1 + deviceSetting = iSuperScope; + valid = (1 << iSuperScope); + break; + + case 0x06: // Multitap in Port 1 + deviceSetting = iMultiPlayer5; + valid = (1 << iPad) | (1 << iMultiPlayer5); + break; + + case 0x66: // Multitap in Ports 0 and 1 + deviceSetting = iMultiPlayer5_2; + valid = (1 << iPad) | (1 << iMultiPlayer5) | (1 << iMultiPlayer5_2); + break; + + case 0x08: // Multitap in Port 1, Mouse in new Port 1 + deviceSetting = iMouse2; + valid = (1 << iPad) | (1 << iMouse2) | (1 << iMultiPlayer5); + break; + + case 0x04: // Pad or Super Scope in Port 1 + deviceSetting = iSuperScope; + valid = (1 << iPad) | (1 << iSuperScope); + break; + + case 0x05: // Justifier - Must ask user... + deviceSetting = iJustifier1; + valid = (1 << iJustifier1) | (1 << iJustifier2); + break; + + case 0x20: // Pad or Mouse in Port 0 + deviceSetting = iMouse; + valid = (1 << iPad) | (1 << iMouse); + break; + + case 0x22: // Pad or Mouse in Port 0 & 1 + deviceSetting = iMouse; + valid = (1 << iPad) | (1 << iMouse) | (1 << iMouse2); + break; + + case 0x24: // Pad or Mouse in Port 0, Pad or Super Scope in Port 1 + deviceSetting = iSuperScope; + valid = (1 << iPad) | (1 << iMouse) | (1 << iSuperScope); + break; + + case 0x27: // Pad or Mouse in Port 0, Pad or Mouse or Super Scope in Port 1 + deviceSetting = iSuperScope; + valid = (1 << iPad) | (1 << iMouse) | (1 << iMouse2) | (1 << iSuperScope); + break; + + case 0x99: // Lasabirdie + break; + + case 0x0A: // Barcode Battler + break; + + default: + break; + } + } + + CheckMenuItem(menu, deviceSetting, true); + + for (int i = 1; i <= CountMenuItems(menu); i++) + { + if (valid & (1 << i)) + SetItemStyle(menu, i, underline); + } + + ChangeInputDevice(); +} + +int PromptFreezeDefrost (Boolean freezing) +{ + OSStatus err; + CGContextRef ctx; + CGColorSpaceRef color; + CGDataProviderRef prov; + CGImageRef image; + CGRect rct; + CGPoint pt; + CFURLRef url; + FSCatalogInfo info; + FSRef ref; + KeyMap keys; + UInt64 newestDate, currentDate; + UInt32 startTime; + float x, y, textw; + int result, newestIndex, current_selection, oldInactiveMode; + char dateC[256]; + uint8 *back, *draw; + + const UInt32 repeatDelay = 10; + const int w = SNES_WIDTH << 1, h = kMacWindowHeight; + const char letters[] = "123456789ABC", *filename; + const uint8 keyCheck[] = { kmEscKey, km1Key, km2Key, km3Key, km4Key, km5Key, km6Key, km7Key, km8Key, km9Key, kmAKey, kmBKey, kmCKey }; + + if (!directDisplay) + { + S9xInitDisplay(NULL, NULL); + SNES9X_Go(); + } + + frzselecting = true; + oldInactiveMode = inactiveMode; + if (inactiveMode == 3) + inactiveMode = 2; + + S9xSetSoundMute(true); + + back = (uint8 *) malloc(w * h * 2); + draw = (uint8 *) malloc(w * h * 2); + if (!back || !draw) + QuitWithFatalError(0, "os 04"); + + color = CGColorSpaceCreateDeviceRGB(); + if (!color) + QuitWithFatalError(0, "os 05"); + + ctx = CGBitmapContextCreate(back, w, h, 5, w * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0)); + if (!ctx) + QuitWithFatalError(0, "os 06"); + + rct = CGRectMake(0.0f, 0.0f, (float) w, (float) h); + CGContextClearRect(ctx, rct); + + image = NULL; + + if (freezing) + url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("logo_freeze"), CFSTR("png"), NULL); + else + url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("logo_defrost"), CFSTR("png"), NULL); + if (url) + { + prov = CGDataProviderCreateWithURL(url); + if (prov) + { + image = CGImageCreateWithPNGDataProvider(prov, NULL, true, kCGRenderingIntentDefault); + CGDataProviderRelease(prov); + } + + CFRelease(url); + } + + if (image) + { + rct = CGRectMake(0.0f, (float) h - 118.0f, 512.0f, 118.0f); + CGContextDrawImage(ctx, rct, image); + CGImageRelease(image); + } + + newestDate = 0; + newestIndex = -1; + + CGContextSetLineJoin(ctx, kCGLineJoinRound); + + rct = CGRectMake(0.0f, (float) h - 238.0f, 128.0f, 120.0f); + + for (int count = 0; count < 12; count++) + { + filename = S9xGetFreezeFilename(count); + err = FSPathMakeRef((unsigned char *) filename, &ref, NULL); + if (err == noErr) + { + err = FSGetCatalogInfo(&ref, kFSCatInfoContentMod, &info, NULL, NULL, NULL); + currentDate = (((UInt64) info.contentModDate.highSeconds << 48) | ((UInt64) info.contentModDate.lowSeconds << 16) | (UInt64) info.contentModDate.fraction); + + if (currentDate > newestDate) + { + newestIndex = count; + newestDate = currentDate; + } + + DrawThumbnailResource(&ref, ctx, rct); + + CGContextSetShouldAntialias(ctx, false); + CGContextSetLineWidth(ctx, 1.0f); + + CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); + x = rct.origin.x + 127.0f; + y = rct.origin.y + 119.0f; + CGContextBeginPath(ctx); + CGContextMoveToPoint(ctx, x, y); + CGContextAddLineToPoint(ctx, x, y - 119.0f); + CGContextAddLineToPoint(ctx, x - 127.0f, y - 119.0f); + CGContextStrokePath(ctx); + + CGContextSetShouldAntialias(ctx, true); + CGContextSetLineWidth(ctx, 3.0f); + + CGContextSelectFont(ctx, "Helvetica", 12.0f, kCGEncodingMacRoman); + x = rct.origin.x + 5.0f; + y = rct.origin.y + 107.0f; + CGContextSetTextDrawingMode(ctx, kCGTextStroke); + CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 0.8f); + CGContextShowTextAtPoint(ctx, x, y, &letters[count], 1); + CGContextSetTextDrawingMode(ctx, kCGTextFill); + CGContextSetRGBFillColor(ctx, 1.0f, 0.7f, 0.7f, 1.0f); + CGContextShowTextAtPoint(ctx, x, y, &letters[count], 1); + + if (showtimeinfrz) + { + CFAbsoluteTime at; + CFDateFormatterRef format; + CFLocaleRef locale; + CFStringRef datstr; + Boolean r; + + err = UCConvertUTCDateTimeToCFAbsoluteTime(&(info.contentModDate), &at); + locale = CFLocaleCopyCurrent(); + format = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle); + datstr = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, format, at); + r = CFStringGetCString(datstr, dateC, sizeof(dateC), CFStringGetSystemEncoding()); + CFRelease(datstr); + CFRelease(format); + CFRelease(locale); + + CGContextSelectFont(ctx, "Helvetica", 10.0f, kCGEncodingMacRoman); + x = rct.origin.x + 20.0f; + y = rct.origin.y + 107.0f; + CGContextSetTextDrawingMode(ctx, kCGTextInvisible); + CGContextShowTextAtPoint(ctx, x, y, dateC, strlen(dateC)); + pt = CGContextGetTextPosition(ctx); + textw = pt.x - x; + x = rct.origin.x + 122.0f - textw; + CGContextSetTextDrawingMode(ctx, kCGTextStroke); + CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 0.8f); + CGContextShowTextAtPoint(ctx, x, y, dateC, strlen(dateC)); + CGContextSetTextDrawingMode(ctx, kCGTextFill); + CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f); + CGContextShowTextAtPoint(ctx, x, y, dateC, strlen(dateC)); + } + } + else + { + CGContextSelectFont(ctx, "Helvetica", 12.0f, kCGEncodingMacRoman); + x = rct.origin.x + 5.0f; + y = rct.origin.y + 107.0f; + CGContextSetTextDrawingMode(ctx, kCGTextFill); + CGContextSetRGBFillColor(ctx, 0.7f, 0.7f, 0.7f, 1.0f); + CGContextShowTextAtPoint(ctx, x, y, &letters[count], 1); + } + + if ((count % 4) == 3) + rct = CGRectOffset(rct, -128.0f * 3.0f, -120.0f); + else + rct = CGRectOffset(rct, 128.0f, 0.0f); + } + + if (newestIndex < 0) + newestIndex = 0; + + CGContextRelease(ctx); + + image = NULL; + + prov = CGDataProviderCreateWithData(NULL, back, w * h * 2, NULL); + if (prov) + { + image = CGImageCreate(w, h, 5, 16, w * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0), prov, NULL, 0, kCGRenderingIntentDefault); + CGDataProviderRelease(prov); + } + + if (!image) + QuitWithFatalError(0, "os 07"); + + ctx = CGBitmapContextCreate(draw, w, h, 5, w * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0)); + if (!ctx) + QuitWithFatalError(0, "os 08"); + + CGContextSetShouldAntialias(ctx, false); + + UpdateFreezeDefrostScreen(newestIndex, image, draw, ctx); + + CocoaPlayFreezeDefrostSound(); + + result = -2; + current_selection = newestIndex; + + do + { + if (!rejectinput) + { + GetKeys(keys); + + for (int count = 0; count <= 12; count++) + { + while (KeyIsPressed(keys, keyCheck[count])) + { + result = count - 1; + GetKeys(keys); + } + } + + while (KeyIsPressed(keys, keyCode[k1PRight])) + { + startTime = TickCount(); + current_selection += 1; + if (current_selection > 11) + current_selection -= 12; + UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); + while (KeyIsPressed(keys, keyCode[k1PRight]) && (TickCount() < (startTime + repeatDelay))) + GetKeys(keys); + } + + while (KeyIsPressed(keys, keyCode[k1PLeft])) + { + startTime = TickCount(); + current_selection -= 1; + if (current_selection < 0) + current_selection += 12; + UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); + while (KeyIsPressed(keys, keyCode[k1PLeft]) && (TickCount() < (startTime + repeatDelay))) + GetKeys(keys); + } + + while (KeyIsPressed(keys, keyCode[k1PDown])) + { + startTime = TickCount(); + current_selection += 4; + if (current_selection > 11) + current_selection -= 12; + UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); + while (KeyIsPressed(keys, keyCode[k1PDown]) && (TickCount() < (startTime + repeatDelay))) + GetKeys(keys); + } + + while (KeyIsPressed(keys, keyCode[k1PUp])) + { + startTime = TickCount(); + current_selection -= 4; + if (current_selection < 0) + current_selection += 12; + UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); + while (KeyIsPressed(keys, keyCode[k1PUp]) && (TickCount() < (startTime + repeatDelay))) + GetKeys(keys); + } + + while (KeyIsPressed(keys, keyCode[k1PA] ) || + KeyIsPressed(keys, keyCode[k2PA] ) || + KeyIsPressed(keys, keyCode[k1PB] ) || + KeyIsPressed(keys, keyCode[k2PB] ) || + KeyIsPressed(keys, keyCode[k1PX] ) || + KeyIsPressed(keys, keyCode[k2PX] ) || + KeyIsPressed(keys, keyCode[k1PY] ) || + KeyIsPressed(keys, keyCode[k2PY] ) || + KeyIsPressed(keys, keyCode[k1PStart] ) || + KeyIsPressed(keys, keyCode[k2PStart] ) || + KeyIsPressed(keys, keyCode[k1PSelect]) || + KeyIsPressed(keys, keyCode[k2PSelect])) + { + GetKeys(keys); + result = current_selection; + } + + uint32 pad1, pad2; + + while (ISpKeyIsPressed(kISpEsc ) || + ISpKeyIsPressed(kISp1PStart) || + ISpKeyIsPressed(kISp2PStart)) + result = -1; + + pad1 = pad2 = 0; + JoypadScanDirection(0, &pad1); + JoypadScanDirection(1, &pad2); + while ((pad1 & 0x0100) || (pad2 & 0x0100)) // Rt + { + startTime = TickCount(); + current_selection += 1; + if (current_selection > 11) + current_selection -= 12; + UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); + do + { + pad1 = pad2 = 0; + JoypadScanDirection(0, &pad1); + JoypadScanDirection(1, &pad2); + } while (((pad1 & 0x0100) || (pad2 & 0x0100)) && (TickCount() < (startTime + repeatDelay))); + } + + pad1 = pad2 = 0; + JoypadScanDirection(0, &pad1); + JoypadScanDirection(1, &pad2); + while ((pad1 & 0x0200) || (pad2 & 0x0200)) // Lf + { + startTime = TickCount(); + current_selection -= 1; + if (current_selection < 0) + current_selection += 12; + UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); + do + { + pad1 = pad2 = 0; + JoypadScanDirection(0, &pad1); + JoypadScanDirection(1, &pad2); + } while (((pad1 & 0x0200) || (pad2 & 0x0200)) && (TickCount() < (startTime + repeatDelay))); + } + + pad1 = pad2 = 0; + JoypadScanDirection(0, &pad1); + JoypadScanDirection(1, &pad2); + while ((pad1 & 0x0800) || (pad2 & 0x0800)) // Up + { + startTime = TickCount(); + current_selection -= 4; + if (current_selection < 0) + current_selection += 12; + UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); + do + { + pad1 = pad2 = 0; + JoypadScanDirection(0, &pad1); + JoypadScanDirection(1, &pad2); + } while (((pad1 & 0x0800) || (pad2 & 0x0800)) && (TickCount() < (startTime + repeatDelay))); + } + + pad1 = pad2 = 0; + JoypadScanDirection(0, &pad1); + JoypadScanDirection(1, &pad2); + while ((pad1 & 0x0400) || (pad2 & 0x0400)) // Dn + { + startTime = TickCount(); + current_selection += 4; + if (current_selection > 11) + current_selection -= 12; + UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); + do + { + pad1 = pad2 = 0; + JoypadScanDirection(0, &pad1); + JoypadScanDirection(1, &pad2); + } while (((pad1 & 0x0400) || (pad2 & 0x0400)) && (TickCount() < (startTime + repeatDelay))); + } + + while (ISpKeyIsPressed(kISp1PA) || + ISpKeyIsPressed(kISp2PA) || + ISpKeyIsPressed(kISp1PB) || + ISpKeyIsPressed(kISp2PB) || + ISpKeyIsPressed(kISp1PX) || + ISpKeyIsPressed(kISp2PX) || + ISpKeyIsPressed(kISp1PY) || + ISpKeyIsPressed(kISp2PY)) + result = current_selection; + } + + usleep(30000); + + windowResizeCount = 2; + UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); + } while (result == -2); + + CocoaPlayFreezeDefrostSound(); + + CGContextRelease(ctx); + CGImageRelease(image); + CGColorSpaceRelease(color); + free(draw); + free(back); + + S9xSetSoundMute(false); + + inactiveMode = oldInactiveMode; + frzselecting = false; + + windowResizeCount = 2; + + return (result); +} + +static void UpdateFreezeDefrostScreen (int newIndex, CGImageRef image, uint8 *draw, CGContextRef ctx) +{ + if (newIndex >= 0 && newIndex < 12) + { + CGRect rct; + const int w = SNES_WIDTH << 1, h = kMacWindowHeight; + + CGContextSetLineWidth(ctx, 1.0f); + + rct = CGRectMake(0.0f, 0.0f, (float) w, (float) h); + CGContextDrawImage(ctx, rct, image); + + rct = CGRectMake(0.0f, (float) h - 238.0f, 128.0f, 120.0f); + rct = CGRectOffset(rct, (float) (128 * (newIndex % 4)), (float) (-120 * (newIndex / 4))); + rct.size.width -= 1.0f; + rct.size.height -= 1.0f; + + CGContextSetRGBStrokeColor(ctx, 1.0f, 1.0f, 0.0f, 1.0f); + CGContextStrokeRect(ctx, rct); + rct = CGRectInset(rct, 1.0f, 1.0f); + CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); + CGContextStrokeRect(ctx, rct); + } + + DrawFreezeDefrostScreen(draw); +} + +static void ProcessInput (void) +{ + KeyMap myKeys; + bool8 isok, fnbtn, altbtn, tcbtn; + static bool8 toggleff = false, lastTimeTT = false, lastTimeFn = false, ffUp = false, ffDown = false, ffUpSp = false, ffDownSp = false; + + if (rejectinput) + return; + + if (ISpKeyIsPressed(kISpEsc)) + { + if (s9xthreadrunning) + { + if (!eventQueued) + { + PostQueueToSubEventLoop(); + eventQueued = true; + } + } + else + running = false; + + return; + } + + if (ISpKeyIsPressed(kISpFreeze)) + { + MacStopSound(); + while (ISpKeyIsPressed(kISpFreeze)); + + isok = SNES9X_Freeze(); + ClearGFXScreen(); + return; + } + + if (ISpKeyIsPressed(kISpDefrost)) + { + MacStopSound(); + while (ISpKeyIsPressed(kISpDefrost)); + + isok = SNES9X_Defrost(); + ClearGFXScreen(); + return; + } + + if (ISpKeyIsPressed(kISpScreenshot)) + { + Settings.TakeScreenshot = true; + while (ISpKeyIsPressed(kISpScreenshot)); + } + + if (ISpKeyIsPressed(kISpSPC)) + { + S9xDumpSPCSnapshot(); + while (ISpKeyIsPressed(kISpSPC)); + } + + if (ISpKeyIsPressed(kISpFFUp)) + { + if (!ffUpSp) + { + ChangeTurboRate(+1); + ffUpSp = true; + } + } + else + ffUpSp = false; + + if (ISpKeyIsPressed(kISpFFDown)) + { + if (!ffDownSp) + { + ChangeTurboRate(-1); + ffDownSp = true; + } + } + else + ffDownSp = false; + + controlPad[0] = controlPad[1] = 0; + + JoypadScanDirection(0, &(controlPad[0])); + if (ISpKeyIsPressed(kISp1PR )) controlPad[0] |= 0x0010; + if (ISpKeyIsPressed(kISp1PL )) controlPad[0] |= 0x0020; + if (ISpKeyIsPressed(kISp1PX )) controlPad[0] |= 0x0040; + if (ISpKeyIsPressed(kISp1PA )) controlPad[0] |= 0x0080; + if (ISpKeyIsPressed(kISp1PStart )) controlPad[0] |= 0x1000; + if (ISpKeyIsPressed(kISp1PSelect)) controlPad[0] |= 0x2000; + if (ISpKeyIsPressed(kISp1PY )) controlPad[0] |= 0x4000; + if (ISpKeyIsPressed(kISp1PB )) controlPad[0] |= 0x8000; + + JoypadScanDirection(1, &(controlPad[1])); + if (ISpKeyIsPressed(kISp2PR )) controlPad[1] |= 0x0010; + if (ISpKeyIsPressed(kISp2PL )) controlPad[1] |= 0x0020; + if (ISpKeyIsPressed(kISp2PX )) controlPad[1] |= 0x0040; + if (ISpKeyIsPressed(kISp2PA )) controlPad[1] |= 0x0080; + if (ISpKeyIsPressed(kISp2PStart )) controlPad[1] |= 0x1000; + if (ISpKeyIsPressed(kISp2PSelect)) controlPad[1] |= 0x2000; + if (ISpKeyIsPressed(kISp2PY )) controlPad[1] |= 0x4000; + if (ISpKeyIsPressed(kISp2PB )) controlPad[1] |= 0x8000; + + if (((macControllerOption == SNES_MULTIPLAYER5) || (macControllerOption == SNES_MULTIPLAYER5_2)) && Settings.MultiPlayer5Master) + { + controlPad[2] = controlPad[3] = controlPad[4] = 0; + + JoypadScanDirection(2, &(controlPad[2])); + if (ISpKeyIsPressed(kISp3PR )) controlPad[2] |= 0x0010; + if (ISpKeyIsPressed(kISp3PL )) controlPad[2] |= 0x0020; + if (ISpKeyIsPressed(kISp3PX )) controlPad[2] |= 0x0040; + if (ISpKeyIsPressed(kISp3PA )) controlPad[2] |= 0x0080; + if (ISpKeyIsPressed(kISp3PStart )) controlPad[2] |= 0x1000; + if (ISpKeyIsPressed(kISp3PSelect)) controlPad[2] |= 0x2000; + if (ISpKeyIsPressed(kISp3PY )) controlPad[2] |= 0x4000; + if (ISpKeyIsPressed(kISp3PB )) controlPad[2] |= 0x8000; + + JoypadScanDirection(3, &(controlPad[3])); + if (ISpKeyIsPressed(kISp4PR )) controlPad[3] |= 0x0010; + if (ISpKeyIsPressed(kISp4PL )) controlPad[3] |= 0x0020; + if (ISpKeyIsPressed(kISp4PX )) controlPad[3] |= 0x0040; + if (ISpKeyIsPressed(kISp4PA )) controlPad[3] |= 0x0080; + if (ISpKeyIsPressed(kISp4PStart )) controlPad[3] |= 0x1000; + if (ISpKeyIsPressed(kISp4PSelect)) controlPad[3] |= 0x2000; + if (ISpKeyIsPressed(kISp4PY )) controlPad[3] |= 0x4000; + if (ISpKeyIsPressed(kISp4PB )) controlPad[3] |= 0x8000; + + JoypadScanDirection(4, &(controlPad[4])); + if (ISpKeyIsPressed(kISp5PR )) controlPad[4] |= 0x0010; + if (ISpKeyIsPressed(kISp5PL )) controlPad[4] |= 0x0020; + if (ISpKeyIsPressed(kISp5PX )) controlPad[4] |= 0x0040; + if (ISpKeyIsPressed(kISp5PA )) controlPad[4] |= 0x0080; + if (ISpKeyIsPressed(kISp5PStart )) controlPad[4] |= 0x1000; + if (ISpKeyIsPressed(kISp5PSelect)) controlPad[4] |= 0x2000; + if (ISpKeyIsPressed(kISp5PY )) controlPad[4] |= 0x4000; + if (ISpKeyIsPressed(kISp5PB )) controlPad[4] |= 0x8000; + + ControlPadFlagsToS9xReportButtons(2, controlPad[2]); + ControlPadFlagsToS9xReportButtons(3, controlPad[3]); + ControlPadFlagsToS9xReportButtons(4, controlPad[4]); + + if (macControllerOption == SNES_MULTIPLAYER5_2) + { + controlPad[5] = controlPad[6] = controlPad[7] = 0; + + JoypadScanDirection(5, &(controlPad[5])); + if (ISpKeyIsPressed(kISp6PR )) controlPad[5] |= 0x0010; + if (ISpKeyIsPressed(kISp6PL )) controlPad[5] |= 0x0020; + if (ISpKeyIsPressed(kISp6PX )) controlPad[5] |= 0x0040; + if (ISpKeyIsPressed(kISp6PA )) controlPad[5] |= 0x0080; + if (ISpKeyIsPressed(kISp6PStart )) controlPad[5] |= 0x1000; + if (ISpKeyIsPressed(kISp6PSelect)) controlPad[5] |= 0x2000; + if (ISpKeyIsPressed(kISp6PY )) controlPad[5] |= 0x4000; + if (ISpKeyIsPressed(kISp6PB )) controlPad[5] |= 0x8000; + + JoypadScanDirection(6, &(controlPad[6])); + if (ISpKeyIsPressed(kISp7PR )) controlPad[6] |= 0x0010; + if (ISpKeyIsPressed(kISp7PL )) controlPad[6] |= 0x0020; + if (ISpKeyIsPressed(kISp7PX )) controlPad[6] |= 0x0040; + if (ISpKeyIsPressed(kISp7PA )) controlPad[6] |= 0x0080; + if (ISpKeyIsPressed(kISp7PStart )) controlPad[6] |= 0x1000; + if (ISpKeyIsPressed(kISp7PSelect)) controlPad[6] |= 0x2000; + if (ISpKeyIsPressed(kISp7PY )) controlPad[6] |= 0x4000; + if (ISpKeyIsPressed(kISp7PB )) controlPad[6] |= 0x8000; + + JoypadScanDirection(7, &(controlPad[7])); + if (ISpKeyIsPressed(kISp8PR )) controlPad[7] |= 0x0010; + if (ISpKeyIsPressed(kISp8PL )) controlPad[7] |= 0x0020; + if (ISpKeyIsPressed(kISp8PX )) controlPad[7] |= 0x0040; + if (ISpKeyIsPressed(kISp8PA )) controlPad[7] |= 0x0080; + if (ISpKeyIsPressed(kISp8PStart )) controlPad[7] |= 0x1000; + if (ISpKeyIsPressed(kISp8PSelect)) controlPad[7] |= 0x2000; + if (ISpKeyIsPressed(kISp8PY )) controlPad[7] |= 0x4000; + if (ISpKeyIsPressed(kISp8PB )) controlPad[7] |= 0x8000; + + ControlPadFlagsToS9xReportButtons(5, controlPad[5]); + ControlPadFlagsToS9xReportButtons(6, controlPad[6]); + ControlPadFlagsToS9xReportButtons(7, controlPad[7]); + } + } + + GetKeys(myKeys); + + fnbtn = (KeyIsPressed(myKeys, keyCode[kKeyFunction]) || ISpKeyIsPressed(kISpFunction)); + altbtn = (KeyIsPressed(myKeys, keyCode[kKeyAlt] ) || ISpKeyIsPressed(kISpAlt) ); + + if (fnbtn) + { + if (!lastTimeFn) + { + for (unsigned int i = 0; i < kCommandListSize; i++) + btncmd[i].held = false; + } + + lastTimeFn = true; + lastTimeTT = false; + ffUp = ffDown = false; + + for (unsigned int i = 0; i < kCommandListSize; i++) + { + if (KeyIsPressed(myKeys, btncmd[i].keycode)) + { + if (!(btncmd[i].held)) + { + btncmd[i].held = true; + + if (strncmp(btncmd[i].command, "_mac", 4) == 0) + { + static char msg[64]; + + switch (btncmd[i].command[4] - '0') + { + case 1: + Settings.DisplayPressedKeys = !Settings.DisplayPressedKeys; + break; + + case 2: + if (S9xMovieActive()) + Settings.DisplayMovieFrame = !Settings.DisplayMovieFrame; + break; + + case 3: + if (macFrameAdvanceRate < 5000000) + macFrameAdvanceRate += 100000; + sprintf(msg, "Emulation Speed: 100/%d", macFrameAdvanceRate / 10000); + S9xSetInfoString(msg); + break; + + case 4: + if (macFrameAdvanceRate > 500000) + macFrameAdvanceRate -= 100000; + sprintf(msg, "Emulation Speed: 100/%d", macFrameAdvanceRate / 10000); + S9xSetInfoString(msg); + break; + } + } + else + { + s9xcommand_t s9xcmd; + + s9xcmd = S9xGetCommandT(btncmd[i].command); + S9xApplyCommand(s9xcmd, 1, 0); + } + } + } + else + btncmd[i].held = false; + } + } + else + { + lastTimeFn = false; + + if (KeyIsPressed(myKeys, keyCode[kKeyEsc])) + { + if (s9xthreadrunning) + { + if (!eventQueued) + { + PostQueueToSubEventLoop(); + eventQueued = true; + } + } + else + running = false; + + return; + } + + if (KeyIsPressed(myKeys, keyCode[kKeyFreeze])) + { + MacStopSound(); + while (KeyIsPressed(myKeys, keyCode[kKeyFreeze])) + GetKeys(myKeys); + + isok = SNES9X_Freeze(); + ClearGFXScreen(); + return; + } + + if (KeyIsPressed(myKeys, keyCode[kKeyDefrost])) + { + MacStopSound(); + while (KeyIsPressed(myKeys, keyCode[kKeyDefrost])) + GetKeys(myKeys); + + isok = SNES9X_Defrost(); + ClearGFXScreen(); + return; + } + + if (KeyIsPressed(myKeys, keyCode[kKeyScreenshot])) + { + Settings.TakeScreenshot = true; + while (KeyIsPressed(myKeys, keyCode[kKeyScreenshot])) + GetKeys(myKeys); + } + + if (KeyIsPressed(myKeys, keyCode[kKeySPC])) + { + S9xDumpSPCSnapshot(); + while (KeyIsPressed(myKeys, keyCode[kKeySPC])) + GetKeys(myKeys); + } + + if (KeyIsPressed(myKeys, keyCode[kKeyFFUp])) + { + if (!ffUp) + { + ChangeTurboRate(+1); + ffUp = true; + } + } + else + ffUp = false; + + if (KeyIsPressed(myKeys, keyCode[kKeyFFDown])) + { + if (!ffDown) + { + ChangeTurboRate(-1); + ffDown = true; + } + } + else + ffDown = false; + + if (KeyIsPressed(myKeys, keyCode[k1PR] )) controlPad[0] |= 0x0010; + if (KeyIsPressed(myKeys, keyCode[k1PL] )) controlPad[0] |= 0x0020; + if (KeyIsPressed(myKeys, keyCode[k1PX] )) controlPad[0] |= 0x0040; + if (KeyIsPressed(myKeys, keyCode[k1PA] )) controlPad[0] |= 0x0080; + if (KeyIsPressed(myKeys, keyCode[k1PRight] )) controlPad[0] |= 0x0100; + if (KeyIsPressed(myKeys, keyCode[k1PLeft] )) controlPad[0] |= 0x0200; + if (KeyIsPressed(myKeys, keyCode[k1PDown] )) controlPad[0] |= 0x0400; + if (KeyIsPressed(myKeys, keyCode[k1PUp] )) controlPad[0] |= 0x0800; + if (KeyIsPressed(myKeys, keyCode[k1PStart] )) controlPad[0] |= 0x1000; + if (KeyIsPressed(myKeys, keyCode[k1PSelect])) controlPad[0] |= 0x2000; + if (KeyIsPressed(myKeys, keyCode[k1PY] )) controlPad[0] |= 0x4000; + if (KeyIsPressed(myKeys, keyCode[k1PB] )) controlPad[0] |= 0x8000; + + if (KeyIsPressed(myKeys, keyCode[k2PR] )) controlPad[1] |= 0x0010; + if (KeyIsPressed(myKeys, keyCode[k2PL] )) controlPad[1] |= 0x0020; + if (KeyIsPressed(myKeys, keyCode[k2PX] )) controlPad[1] |= 0x0040; + if (KeyIsPressed(myKeys, keyCode[k2PA] )) controlPad[1] |= 0x0080; + if (KeyIsPressed(myKeys, keyCode[k2PRight] )) controlPad[1] |= 0x0100; + if (KeyIsPressed(myKeys, keyCode[k2PLeft] )) controlPad[1] |= 0x0200; + if (KeyIsPressed(myKeys, keyCode[k2PDown] )) controlPad[1] |= 0x0400; + if (KeyIsPressed(myKeys, keyCode[k2PUp] )) controlPad[1] |= 0x0800; + if (KeyIsPressed(myKeys, keyCode[k2PStart] )) controlPad[1] |= 0x1000; + if (KeyIsPressed(myKeys, keyCode[k2PSelect])) controlPad[1] |= 0x2000; + if (KeyIsPressed(myKeys, keyCode[k2PY] )) controlPad[1] |= 0x4000; + if (KeyIsPressed(myKeys, keyCode[k2PB] )) controlPad[1] |= 0x8000; + + if (altbtn) + { + if (!lastTimeTT) + changeAuto[0] = changeAuto[1] = 0; + + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 12; j++) + { + uint16 mask = 0x0010 << j; + + if (controlPad[i] & mask & autofireRec[i].toggleMask) + { + controlPad[i] &= ~mask; + + if (!(changeAuto[i] & mask)) + { + changeAuto[i] |= mask; + ChangeAutofireSettings(i, j); + } + } + else + changeAuto[i] &= ~mask; + } + } + + lastTimeTT = true; + } + else + lastTimeTT = false; + } + + if (enabletoggle) + { + if ((ISpKeyIsPressed(kISpFastForward) || KeyIsPressed(myKeys, keyCode[kKeyFastForward])) && !fnbtn) + { + if (!toggleff) + { + toggleff = true; + Settings.TurboMode = !Settings.TurboMode; + S9xSetInfoString(Settings.TurboMode ? "Turbo mode on" : "Turbo mode off"); + if (!Settings.TurboMode) + S9xClearSamples(); + } + } + else + toggleff = false; + } + else + { + bool8 old = Settings.TurboMode; + Settings.TurboMode = ((ISpKeyIsPressed(kISpFastForward) || KeyIsPressed(myKeys, keyCode[kKeyFastForward])) && !fnbtn) ? true : false; + if (!Settings.TurboMode && old) + S9xClearSamples(); + } + + for (int i = 0; i < 2; i++) + controlPad[i] ^= autofireRec[i].invertMask; + + if (autofire) + { + long long currentTime; + uint16 changeMask; + + Microseconds((UnsignedWide *) ¤tTime); + tcbtn = (KeyIsPressed(myKeys, keyCode[kKeyTC]) || ISpKeyIsPressed(kISpTC)); + + for (int i = 0; i < 2; i++) + { + changeMask = (lastTimeTT ? (~changeAuto[i]) : 0xFFFF); + + for (int j = 0; j < 12; j++) + { + uint16 mask = (0x0010 << j) & changeMask; + + if (autofireRec[i].tcMask & mask) + { + if (!tcbtn) + continue; + } + + if (autofireRec[i].buttonMask & mask) + { + if (controlPad[i] & mask) + { + if (currentTime > autofireRec[i].nextTime[j]) + { + if (Settings.TurboMode) + autofireRec[i].nextTime[j] = currentTime + (long long) ((1.0 / (float) autofireRec[i].frequency) * 1000000.0 / macFastForwardRate); + else + autofireRec[i].nextTime[j] = currentTime + (long long) ((1.0 / (float) autofireRec[i].frequency) * 1000000.0); + } + else + controlPad[i] &= ~mask; + } + } + } + } + } + + ControlPadFlagsToS9xReportButtons(0, controlPad[0]); + ControlPadFlagsToS9xReportButtons(1, controlPad[1]); + + if (macControllerOption == SNES_JUSTIFIER_2) + ControlPadFlagsToS9xPseudoPointer(controlPad[1]); +} + +static void ChangeAutofireSettings (int player, int btn) +{ + static char msg[64]; + uint16 mask, m; + + mask = 0x0010 << btn; + autofireRec[player].buttonMask ^= mask; + autofire = (autofireRec[0].buttonMask || autofireRec[1].buttonMask); + + m = autofireRec[player].buttonMask; + if (m) + snprintf(msg, sizeof(msg), "Autofire %d:%s%s%s%s%s%s%s%s%s%s%s%s%s", player + 1, + (m & 0xC0F0 ? " " : ""), + (m & 0x0080 ? "A" : ""), + (m & 0x8000 ? "B" : ""), + (m & 0x0040 ? "X" : ""), + (m & 0x4000 ? "Y" : ""), + (m & 0x0020 ? "L" : ""), + (m & 0x0010 ? "R" : ""), + (m & 0x0800 ? " Up" : ""), + (m & 0x0400 ? " Dn" : ""), + (m & 0x0200 ? " Lf" : ""), + (m & 0x0100 ? " Rt" : ""), + (m & 0x1000 ? " St" : ""), + (m & 0x2000 ? " Se" : "")); + else + snprintf(msg, sizeof(msg), "Autofire %d: Off", player + 1); + + S9xSetInfoString(msg); +} + +static void ChangeTurboRate (int d) +{ + static char msg[64]; + + macFastForwardRate += d; + if (macFastForwardRate < 1) + macFastForwardRate = 1; + else + if (macFastForwardRate > 15) + macFastForwardRate = 15; + + snprintf(msg, sizeof(msg), "Turbo Rate: %d", macFastForwardRate); + S9xSetInfoString(msg); +} + +void GetGameScreenPointer (int16 *x, int16 *y, bool fullmouse) +{ + int ph; + + ph = !drawoverscan ? ((IPPU.RenderedScreenHeight > 256) ? IPPU.RenderedScreenHeight : (IPPU.RenderedScreenHeight << 1)) : (SNES_HEIGHT_EXTENDED << 1); + + if (fullscreen) + { + if (glstretch) + { + float fpw = (float) glScreenH / (float) ph * 512.0f; + + scopeViewInfo.width = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 100.0); + scopeViewInfo.height = glScreenH; + scopeViewInfo.globalLeft = (int) glScreenBounds.origin.x + ((glScreenW - scopeViewInfo.width) >> 1); + scopeViewInfo.globalTop = (int) glScreenBounds.origin.y; + } + else + { + scopeViewInfo.width = 512; + scopeViewInfo.height = ph; + scopeViewInfo.globalLeft = (int) glScreenBounds.origin.x + ((glScreenW - 512) >> 1); + scopeViewInfo.globalTop = (int) glScreenBounds.origin.y + ((glScreenH - ph ) >> 1); + } + } + else + { + Rect rct; + + GetWindowBounds(gWindow, kWindowContentRgn, &rct); + + int ww = rct.right - rct.left, + wh = rct.bottom - rct.top; + + scopeViewInfo.width = ww; + scopeViewInfo.globalLeft = rct.left; + + if (windowExtend) + { + scopeViewInfo.height = ph * wh / kMacWindowHeight; + scopeViewInfo.globalTop = rct.top + ((kMacWindowHeight - ph) >> 1) * wh / kMacWindowHeight; + } + else + { + scopeViewInfo.height = wh; + scopeViewInfo.globalTop = rct.top; + } + } + + if (!fullmouse) + { + Point pos; + + GetGlobalMouse(&pos); + + *x = (int16) (((float) (pos.h - scopeViewInfo.globalLeft)) / ((float) scopeViewInfo.width ) * (float) IPPU.RenderedScreenWidth); + *y = (int16) (((float) (pos.v - scopeViewInfo.globalTop )) / ((float) scopeViewInfo.height) * (float) (!drawoverscan ? IPPU.RenderedScreenHeight : SNES_HEIGHT_EXTENDED)); + } + else + { + *x = (int16) (unlimitedCursor.x / (float) scopeViewInfo.width * (float) IPPU.RenderedScreenWidth); + *y = (int16) (unlimitedCursor.y / (float) scopeViewInfo.height * (float) (!drawoverscan ? IPPU.RenderedScreenHeight : SNES_HEIGHT_EXTENDED)); + } +} + +static void Initialize (void) +{ + OSStatus err; + IBNibRef menuNibRef; + MenuRef menu; + SInt32 qtVersion; + + printf("\nSnes9x for Mac OS X %s (%s), ", VERSION, MAC_VERSION); +#ifdef __BIG_ENDIAN__ + printf("PowerPC\n\n"); +#else + printf("Intel\n\n"); +#endif + + err = Gestalt(gestaltSystemVersion, &systemVersion); + err = Gestalt(gestaltQuickTimeVersion, &qtVersion); + + if ((systemVersion < 0x1039) || (qtVersion < 0x07008000)) + { + AppearanceAlert(kAlertStopAlert, kRequiredSystemWarning, kRequiredSystemHint); + QuitWithFatalError(0, "os 09"); + } + + printf("OS: %x QuickTime: %x\n\n", (unsigned) systemVersion, (unsigned) qtVersion); + + ZeroMemory(&Settings, sizeof(Settings)); + Settings.MouseMaster = true; + Settings.SuperScopeMaster = true; + Settings.JustifierMaster = true; + Settings.MultiPlayer5Master = true; + Settings.FrameTimePAL = 20000; + Settings.FrameTimeNTSC = 16667; + Settings.SixteenBitSound = true; + Settings.Stereo = true; + Settings.SoundPlaybackRate = 32000; + Settings.SoundInputRate = 32000; + Settings.SupportHiRes = true; + Settings.Transparency = true; + Settings.AutoDisplayMessages = true; + Settings.InitialInfoStringTimeout = 120; + Settings.HDMATimingHack = 100; + Settings.BlockInvalidVRAMAccessMaster = true; + Settings.StopEmulation = true; + Settings.WrongMovieStateProtection = true; + Settings.DumpStreamsMaxFrames = -1; + Settings.StretchScreenshots = 1; + Settings.SnapshotScreenshots = true; + Settings.OpenGLEnable = true; + + for (int a = 0; a < kWindowCount; a++) + { + windowPos[a].h = 40; + windowPos[a].v = 80; + windowSize[a].width = -1.0f; + windowSize[a].height = -1.0f; + } + + extraOptions.benchmark = false; + extraOptions.glForceNoTextureRectangle = false; + extraOptions.glUseClientStrageApple = true; + extraOptions.glUseTexturePriority = false; + extraOptions.glStorageHint = 2; + + npServerIP[0] = 0; + npName[0] = 0; + + CreateIconImages(); + + InitAppleEvents(); + InitKeyboard(); + InitAutofire(); + InitCheatFinder(); + + LoadPrefs(); + + InitGraphics(); + InitMacSound(); + SetUpHID(); + + RegisterHelpBook(); + + if (systemVersion < 0x1040) + ciFilterEnable = false; + + err = CreateNibReference(kMacS9XCFString, &menuNibRef); + err = SetMenuBarFromNib(menuNibRef, CFSTR("MenuBar")); + DisposeNibReference(menuNibRef); + + EnableMenuCommand(NULL, kHICommandPreferences); + + DisableMenuItem(GetMenuRef(mEdit), 0); + + CheckMenuItem(GetMenuRef(mCheat), iApplyCheats, applycheat); + Settings.ApplyCheats = applycheat; + + err = GetMenuItemHierarchicalMenu(GetMenuRef(mControl), iISpPreset, &menu); + CheckMenuItem(menu, padSetting, true); + + err = GetMenuItemHierarchicalMenu(GetMenuRef(mEmulation), iDevice, &menu); + CheckMenuItem(menu, deviceSetting, true); + deviceSettingMaster = deviceSetting; + + DisableMenuItem(GetMenuRef(mOption), iCIFilter); + + InitRecentItems(); + InitRecentMenu(); + BuildRecentMenu(); + + InitMultiCart(); + + DrawMenuBar(); + + autofire = (autofireRec[0].buttonMask || autofireRec[1].buttonMask) ? true : false; + for (int a = 0; a < MAC_MAX_PLAYERS; a++) + for (int b = 0; b < 12; b++) + autofireRec[a].nextTime[b] = 0; + + S9xMovieInit(); + + S9xUnmapAllControls(); + S9xSetupDefaultKeymap(); + ChangeInputDevice(); + + err = EnterMovies(); + + if (!Memory.Init() || !S9xInitAPU() || !S9xGraphicsInit()) + QuitWithFatalError(err, "os 01"); + + frzselecting = false; + + S9xSetControllerCrosshair(X_MOUSE1, 0, NULL, NULL); + S9xSetControllerCrosshair(X_MOUSE2, 0, NULL, NULL); + + if (systemVersion >= 0x1040) + { + InitCoreImage(); + InitCoreImageFilter(); + } +} + +static void Deinitialize (void) +{ + if (systemVersion >= 0x1040) + { + DeinitCoreImageFilter(); + DeinitCoreImage(); + } + + deviceSetting = deviceSettingMaster; + + ExitMovies(); + + DeinitMultiCart(); + DeinitRecentMenu(); + DeinitRecentItems(); + SavePrefs(); + ReleaseHID(); + DeinitCheatFinder(); + DeinitGraphics(); + DeinitKeyboard(); + DeinitMacSound(); + DeinitAppleEvents(); + ReleaseIconImages(); + + S9xGraphicsDeinit(); + S9xDeinitAPU(); + Memory.Deinit(); +} + +static void InitAutofire (void) +{ + autofire = false; + + for (int i = 0; i < 2; i++) + { + for (int j = 0; j < 12; j++) + autofireRec[i].nextTime[j] = 0; + + autofireRec[i].buttonMask = 0x0000; + autofireRec[i].toggleMask = 0xFFF0; + autofireRec[i].tcMask = 0x0000; + autofireRec[i].invertMask = 0x0000; + autofireRec[i].frequency = 10; + } +} + +static void ForceChangingKeyScript (void) +{ + if (systemVersion >= 0x1050) + { + OSStatus err; + TISInputSourceRef tis; + + tis = TISCopyCurrentASCIICapableKeyboardInputSource(); + err = TISSelectInputSource(tis); + CFRelease(tis); + } +#ifdef MAC_TIGER_PANTHER_SUPPORT + else + { + long script; + + script = GetScriptManagerVariable(smKeyScript); + if (script == smJapanese) + KeyScript(smRoman | smKeyForceKeyScriptMask); + } +#endif +} + +void S9xSyncSpeed (void) +{ + long long currentFrame, adjustment; + + if (directDisplay) + { + if (extraOptions.benchmark) + IPPU.RenderThisFrame = true; + else + { + if (Settings.SoundSync) + { + while (!S9xSyncSound()) + usleep(0); + } + + if (!macQTRecord) + { + if (macFrameSkip < 0) // auto skip + { + skipFrames--; + + if (skipFrames <= 0) + { + adjustment = (Settings.TurboMode ? (macFrameAdvanceRate / macFastForwardRate) : macFrameAdvanceRate) / Memory.ROMFramesPerSecond; + Microseconds((UnsignedWide *) ¤tFrame); + + skipFrames = (int32) ((currentFrame - lastFrame) / adjustment); + lastFrame += frameCount * adjustment; + + if (skipFrames < 1) + skipFrames = 1; + else + if (skipFrames > 7) + { + skipFrames = 7; + Microseconds((UnsignedWide *) &lastFrame); + } + + frameCount = skipFrames; + + if (lastFrame > currentFrame) + usleep((useconds_t) (lastFrame - currentFrame)); + + IPPU.RenderThisFrame = true; + } + else + IPPU.RenderThisFrame = false; + } + else // constant + { + skipFrames--; + + if (skipFrames <= 0) + { + adjustment = macFrameAdvanceRate * macFrameSkip / Memory.ROMFramesPerSecond; + Microseconds((UnsignedWide *) ¤tFrame); + + if (currentFrame - lastFrame < adjustment) + { + usleep((useconds_t) (adjustment + lastFrame - currentFrame)); + Microseconds((UnsignedWide *) ¤tFrame); + } + + lastFrame = currentFrame; + skipFrames = macFrameSkip; + if (Settings.TurboMode) + skipFrames *= macFastForwardRate; + + IPPU.RenderThisFrame = true; + } + else + IPPU.RenderThisFrame = false; + } + } + else + { + MacQTRecordFrame(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); + + adjustment = macFrameAdvanceRate / Memory.ROMFramesPerSecond; + Microseconds((UnsignedWide *) ¤tFrame); + + if (currentFrame - lastFrame < adjustment) + usleep((useconds_t) (adjustment + lastFrame - currentFrame)); + + lastFrame = currentFrame; + + IPPU.RenderThisFrame = true; + } + } + } + else + IPPU.RenderThisFrame = false; +} + +void S9xAutoSaveSRAM (void) +{ + SNES9X_SaveSRAM(); +} + +void S9xMessage (int type, int number, const char *message) +{ + static char mes[256]; + + if (!onscreeninfo) + { + printf("%s\n", message); + + if ((type == S9X_INFO) && (number == S9X_ROM_INFO)) + if (strstr(message, "checksum ok") == NULL) + AppearanceAlert(kAlertCautionAlert, kBadRomWarning, kBadRomHint); + } + else + { + strncpy(mes, message, 255); + S9xSetInfoString(mes); + } +} + +const char * S9xStringInput (const char *s) +{ + return (NULL); +} + +void S9xToggleSoundChannel (int c) +{ + static int channel_enable = 255; + + if (c == 8) + channel_enable = 255; + else + channel_enable ^= 1 << c; + + S9xSetSoundControl(channel_enable); +} + +void S9xExit (void) +{ + PlayAlertSound(); + + running = false; + cartOpen = false; + + QuitApplicationEventLoop(); +} + +void QuitWithFatalError (OSStatus err, const char *msg) +{ + printf("Quit. %s err: %ld\n", msg, err); + ExitToShell(); +} diff --git a/macosx/mac-os.h b/macosx/mac-os.h new file mode 100644 index 00000000..af8bb2cd --- /dev/null +++ b/macosx/mac-os.h @@ -0,0 +1,344 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_os_h_ +#define _mac_os_h_ + +enum +{ + kDrawingReserved1 = 1, // unused + kDrawingOpenGL, + kDrawingBlitGL +}; + +enum +{ + kWindowControllers = 0, + kWindowPreferences, + kWindowAbout, + kWindowAutoFire, + kWindowMusicBox, + kWindowRomInfo, + kWindowCheatFinder, + kWindowKeyConfig, + kWindowCheatEntry, + kWindowScreen, + kWindowServer, + kWindowClient, + kWindowExtra, + kWindowSoundEffect, + kWindowCoreImageFilter, + kWindowMultiCart, + + kWindowCount +}; + +enum +{ + SNES_MULTIPLAYER5, + SNES_MULTIPLAYER5_2, + SNES_JOYPAD, + SNES_MOUSE_SWAPPED, + SNES_MOUSE, + SNES_SUPERSCOPE, + SNES_JUSTIFIER, + SNES_JUSTIFIER_2, + SNES_MAX_CONTROLLER_OPTIONS +}; + +enum +{ + VIDEOMODE_BLOCKY, + VIDEOMODE_TV, + VIDEOMODE_SMOOTH, + VIDEOMODE_SUPEREAGLE, + VIDEOMODE_2XSAI, + VIDEOMODE_SUPER2XSAI, + VIDEOMODE_EPX, + VIDEOMODE_HQ2X, + VIDEOMODE_HQ3X, + VIDEOMODE_HQ4X, + VIDEOMODE_NTSC_C, + VIDEOMODE_NTSC_S, + VIDEOMODE_NTSC_R, + VIDEOMODE_NTSC_M, + VIDEOMODE_NTSC_TV_C, + VIDEOMODE_NTSC_TV_S, + VIDEOMODE_NTSC_TV_R, + VIDEOMODE_NTSC_TV_M +}; + +typedef struct +{ + long long nextTime[12]; + uint16 buttonMask; + uint16 toggleMask; + uint16 tcMask; + uint16 invertMask; + SInt32 frequency; +} AutoFireState; + +typedef struct +{ + bool8 benchmark; + bool8 glForceNoTextureRectangle; + bool8 glUseClientStrageApple; + bool8 glUseTexturePriority; + int glStorageHint; +} ExtraOption; + +#define kMacWindowHeight (SNES_HEIGHT_EXTENDED << 1) +#define MAC_MAX_PLAYERS 8 + +extern volatile bool8 running, s9xthreadrunning; +extern volatile bool8 eventQueued, windowExtend; +extern volatile int windowResizeCount; +extern uint32 controlPad[MAC_MAX_PLAYERS]; +extern uint8 romDetect, interleaveDetect, videoDetect, headerDetect; +extern WindowRef gWindow; +extern HIRect gWindowRect; +extern int glScreenW, glScreenH; +extern CGRect glScreenBounds; +extern Point windowPos[kWindowCount]; +extern CGSize windowSize[kWindowCount]; +extern CGImageRef macIconImage[118]; +extern int macPadIconIndex, macLegendIconIndex, macMusicBoxIconIndex, macFunctionIconIndex; +extern int macFrameSkip; +extern int32 skipFrames; +extern int64 lastFrame; +extern unsigned long spcFileCount, pngFileCount; +extern SInt32 systemVersion; +extern bool8 finished, cartOpen, + autofire, hidExist, folderWarning, lockedROMMedia, directDisplay; +extern bool8 fullscreen, autoRes, + glstretch, gl32bit, vsync, drawoverscan, lastoverscan, screencurvature, + multiprocessor, ciFilterEnable; +extern long drawingMethod; +extern int videoMode; +extern SInt32 macSoundVolume; +extern uint32 macSoundBuffer_ms, macSoundInterval_ms; +extern bool8 macSoundLagEnable; +extern uint16 aueffect; +extern uint8 saveInROMFolder; +extern int macCurvatureWarp, macAspectRatio; +extern int macFastForwardRate, macFrameAdvanceRate; +extern int inactiveMode; +extern bool8 macQTRecord; +extern uint16 macRecordFlag, macPlayFlag, macQTMovFlag; +extern bool8 startopendlog, showtimeinfrz, enabletoggle, savewindowpos, onscreeninfo; +extern int musicboxmode; +extern bool8 applycheat; +extern int padSetting, deviceSetting, deviceSettingMaster; +extern int macControllerOption; +extern CGPoint unlimitedCursor; +extern char npServerIP[256], npName[256]; +extern AutoFireState autofireRec[MAC_MAX_PLAYERS]; +extern ExtraOption extraOptions; +extern CFStringRef multiCartPath[2]; + +#ifdef MAC_PANTHER_SUPPORT +extern IconRef macIconRef[118]; +#endif + +void InitGameWindow (void); +void DeinitGameWindow (void); +void UpdateGameWindow (void); +void AddRecentItem (FSRef *); +void BuildRecentMenu (void); +void AdjustMenus (void); +void UpdateMenuCommandStatus (Boolean); +void ApplyNSRTHeaderControllers (void); +void QuitWithFatalError (OSStatus, const char *); +void ChangeInputDevice (void); +void GetGameScreenPointer (int16 *, int16 *, bool); +void PostQueueToSubEventLoop (void); +int PromptFreezeDefrost (Boolean); + +#endif diff --git a/macosx/mac-prefix.h b/macosx/mac-prefix.h new file mode 100644 index 00000000..7aeb2cb0 --- /dev/null +++ b/macosx/mac-prefix.h @@ -0,0 +1,204 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_prefix_h_ +#define _mac_prefix_h_ + +#define MAC_PATH_ENCODING kCFStringEncodingUTF8 +#define MAC_PATH_SEPARATOR "/" +#define MAC_PATH_SEP_CHAR '/' + +#define kMacS9XCFString CFSTR("Snes9x") + +#define MAC_VERSION "100" + +#include + +#endif diff --git a/macosx/mac-prefs.cpp b/macosx/mac-prefs.cpp new file mode 100644 index 00000000..f7c19a8a --- /dev/null +++ b/macosx/mac-prefs.cpp @@ -0,0 +1,1626 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "apu.h" +#include "gfx.h" +#include "blit.h" + +#include +#define __STDC_FORMAT_MACROS +#include + +#include "mac-prefix.h" +#include "mac-audio.h" +#include "mac-coreimage.h" +#include "mac-dialog.h" +#include "mac-keyboard.h" +#include "mac-os.h" +#include "mac-snes9x.h" +#include "mac-stringtools.h" +#include "mac-prefs.h" + +enum +{ + iNibGFullScreen = 1, + iNibGSwitchResolution, + iNibGShowFrameRate, + iNibGCIFilterEnable, + iNibGTransparency, + iNibGGL32bit, + iNibGGLStretch, + iNibGCoreImageFilter, + iNibGVideoMode, + iNibGDirectMP, + iNibGGLVSync, + iNibGDrawOverscan, + iNibGScreenCurvature, + iNibGCurvatureWarp, + iNibGAspectRatio, + + iNibSSynchronize = 201, + iNibS16BitPlayback, + iNibSStereo, + iNibSReverseStereo, + iNibSPlaybackRate, + iNibSBufferSize, + iNibSVolume, + iNibSInputRate, + iNibSInputRateText, + iNibSAllowLag, + iNibSInterval, + + iNibOSaveFolder = 401, + iNibOAutoSaveInterval, + + iNibMCPUCycles = 601, + iNibMShutdownMaster, + iNibMTurboSkipArrows, + iNibMTurboSkipText, + iNibMFrameSkip, + iNibMAllowInvalidVRAMAccess, + iNibMAllowSpecificGameHacks, + + iNibXStartOpenDialog = 801, + iNibXShowTimeInFrz, + iNibXMusicBoxMode, + iNibXEnableToggle, + iNibXBSXBootup, + iNibXSaveWindowPos, + iNibXUseIPSPatch, + iNibXOnScreenInfo, + iNibXInactiveMode +}; + +enum +{ + iOpenGLBlocky = 1, + iOpenGLTVMode, + iOpenGLSmoothMode, + iOpenGLEagleMode, + iOpenGL2xSAIMode, + iOpenGLSuper2xSAIMode, + iOpenGLEPXMode, + iOpenGLHQ2xMode, + iOpenGLHQ3xMode, + iOpenGLHQ4xMode, + iOpenGLNTSC_CMode, + iOpenGLNTSC_SMode, + iOpenGLNTSC_RMode, + iOpenGLNTSC_MMode, + iOpenGLNTSC_TV_CMode, + iOpenGLNTSC_TV_SMode, + iOpenGLNTSC_TV_RMode, + iOpenGLNTSC_TV_MMode +}; + +static int lastTabIndex = 1; +static int tabList[] = { 5, 129, 130, 131, 132, 133 }; + +struct PrefList +{ + OSType itemName; + void *itemPointer; + int size; +}; + +static PrefList prefList[] = +{ + { 'flsc', &fullscreen, sizeof(bool8 ) }, + { 'reso', &autoRes, sizeof(bool8 ) }, + { 'dfps', &Settings.DisplayFrameRate, sizeof(bool8 ) }, + { 'tran', &Settings.Transparency, sizeof(bool8 ) }, + { 'gl32', &gl32bit, sizeof(bool8 ) }, + { 'glst', &glstretch, sizeof(bool8 ) }, + { 'draw', &drawingMethod, sizeof(long ) }, + { 'vmod', &videoMode, sizeof(int ) }, + { 'MPmt', &multiprocessor, sizeof(bool8 ) }, + { 'VSNC', &vsync, sizeof(bool8 ) }, + { 'H239', &drawoverscan, sizeof(bool8 ) }, + { 'SCur', &screencurvature, sizeof(bool8 ) }, + { 'SCuW', &macCurvatureWarp, sizeof(int ) }, + { 'ASPe', &macAspectRatio, sizeof(int ) }, + { 'CIFl', &ciFilterEnable, sizeof(bool8 ) }, + + { 'sSyn', &Settings.SoundSync, sizeof(bool8 ) }, + { 'so16', &Settings.SixteenBitSound, sizeof(bool8 ) }, + { 'ster', &Settings.Stereo, sizeof(bool8 ) }, + { 'rbst', &Settings.ReverseStereo, sizeof(bool8 ) }, + { 'srat', &Settings.SoundPlaybackRate, sizeof(uint32 ) }, + { 'InRt', &Settings.SoundInputRate, sizeof(uint32 ) }, + { 'MxIv', &macSoundInterval_ms, sizeof(uint32 ) }, + { 'SBuf', &macSoundBuffer_ms, sizeof(uint32 ) }, + { 'SLag', &macSoundLagEnable, sizeof(bool8 ) }, + { 'Volm', &macSoundVolume, sizeof(SInt32 ) }, + { 'AUef', &aueffect, sizeof(uint16 ) }, + { 'AUce', &cureffect, sizeof(int ) }, + + { 'romf', &saveInROMFolder, sizeof(uint8 ) }, + { 'atsv', &Settings.AutoSaveDelay, sizeof(int32 ) }, + { 'RFlg', &macRecordFlag, sizeof(uint16 ) }, + { 'PFlg', &macPlayFlag, sizeof(uint16 ) }, + { 'QTfg', &macQTMovFlag, sizeof(uint16 ) }, + + { 'HHck', &Settings.HDMATimingHack, sizeof(int32 ) }, + { 'stdm', &Settings.ShutdownMaster, sizeof(bool8 ) }, + { 'TbRt', &macFastForwardRate, sizeof(int ) }, + { 'FSkp', &macFrameSkip, sizeof(int ) }, + { 'IvVR', &Settings.BlockInvalidVRAMAccessMaster, sizeof(bool8 ) }, + { 'GSHk', &Settings.DisableGameSpecificHacks, sizeof(bool8 ) }, + + { 'StOp', &startopendlog, sizeof(bool8 ) }, + { 'STiF', &showtimeinfrz, sizeof(bool8 ) }, + { 'Togl', &enabletoggle, sizeof(bool8 ) }, + { 'SvWp', &savewindowpos, sizeof(bool8 ) }, + { 'OnSc', &onscreeninfo, sizeof(bool8 ) }, + { 'NIPS', &Settings.NoPatch, sizeof(bool8 ) }, + { 'BSX_', &Settings.BSXBootup, sizeof(bool8 ) }, + { 'MbxM', &musicboxmode, sizeof(int ) }, + { 'InAc', &inactiveMode, sizeof(int ) }, + + { 'tab ', &lastTabIndex, sizeof(int ) }, + { 'Ftab', &autofireLastTabIndex, sizeof(int ) }, + { 'keyb', keyCode, sizeof(keyCode ) }, + { 'pset', &padSetting, sizeof(int ) }, + { 'dset', &deviceSetting, sizeof(int ) }, + { 'chea', &applycheat, sizeof(bool8 ) }, + + { 'ARec', autofireRec, sizeof(autofireRec) }, + { 'WPos', windowPos, sizeof(windowPos ) }, + { 'WSiz', windowSize, sizeof(windowSize ) }, + { 'WExt', (void *) &windowExtend, sizeof(bool8 ) }, + + { 'NPIP', npServerIP, sizeof(npServerIP ) }, + { 'NPNM', npName, sizeof(npName ) }, + + { 'L239', &lastoverscan, sizeof(bool8 ) }, + + { 'ExT1', &(extraOptions.benchmark), sizeof(bool8 ) }, + { 'ExT2', &(extraOptions.glForceNoTextureRectangle), sizeof(bool8 ) }, + { 'ExT3', &(extraOptions.glUseClientStrageApple), sizeof(bool8 ) }, + { 'ExT4', &(extraOptions.glUseTexturePriority), sizeof(bool8 ) }, + { 'ExT5', &(extraOptions.glStorageHint), sizeof(int ) } +}; + +#define kPrefListSize (sizeof(prefList) / sizeof(prefList[0])) + +static void SelectTabPane (HIViewRef, SInt16); +static pascal void InputRateSliderActionProc (HIViewRef, HIViewPartCode); +static pascal void LittleArrowsActionProc (HIViewRef, HIViewPartCode); +static pascal OSStatus InputRateTextEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus TabEventHandler (EventHandlerCallRef, EventRef, void *); +static pascal OSStatus PreferencesEventHandler (EventHandlerCallRef, EventRef, void *); + + +void SavePrefs (void) +{ + CFMutableStringRef mref; + CFStringRef sref; + CFDataRef data; + + for (unsigned int i = 0; i < kPrefListSize; i++) + { + mref = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("Preferences_")); + if (mref) + { + sref = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *) &(prefList[i].itemName), sizeof(OSType), kCFStringEncodingMacRoman, false); + if (sref) + { + CFStringAppend(mref, sref); + + data = CFDataCreate(kCFAllocatorDefault, (UInt8 *) prefList[i].itemPointer, prefList[i].size); + if (data) + { + CFPreferencesSetAppValue(mref, data, kCFPreferencesCurrentApplication); + CFRelease(data); + } + + CFRelease(sref); + } + + CFRelease(mref); + } + } + + CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); +} + +void LoadPrefs (void) +{ + CFMutableStringRef mref; + CFStringRef sref; + CFDataRef data; + + for (unsigned int i = 0; i < kPrefListSize; i++) + { + mref = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("Preferences_")); + if (mref) + { + sref = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8 *) &(prefList[i].itemName), sizeof(OSType), kCFStringEncodingMacRoman, false); + if (sref) + { + CFStringAppend(mref, sref); + + data = (CFDataRef) CFPreferencesCopyAppValue(mref, kCFPreferencesCurrentApplication); + if (data) + { + if (CFDataGetLength(data) == prefList[i].size) + CFDataGetBytes(data, CFRangeMake(0, prefList[i].size), (UInt8 *) prefList[i].itemPointer); + CFRelease(data); + } + + CFRelease(sref); + } + + CFRelease(mref); + } + } +} + +void ConfigurePreferences (void) +{ + OSStatus err; + IBNibRef nibRef; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef tWindowRef; + SInt32 oldVolume; + uint32 oldPlaybackRate, oldInputRate, oldInterval, oldBufferSize; + bool8 oldSynchronize, old16BitPlayback, oldStereo, oldReverseStereo, oldLagEnable; + + oldSynchronize = Settings.SoundSync; + old16BitPlayback = Settings.SixteenBitSound; + oldStereo = Settings.Stereo; + oldReverseStereo = Settings.ReverseStereo; + oldPlaybackRate = Settings.SoundPlaybackRate; + oldInputRate = Settings.SoundInputRate; + oldInterval = macSoundInterval_ms; + oldBufferSize = macSoundBuffer_ms; + oldLagEnable = macSoundLagEnable; + oldVolume = macSoundVolume; + + if (cartOpen) + DeinitGameWindow(); + + S9xGraphicsDeinit(); + + err = CreateWindowFromNib(nibRef, CFSTR("Preferences"), &tWindowRef); + if (err == noErr) + { + EventHandlerUPP tUPP, iUPP, pUPP; + EventHandlerRef tRef, iRef, pRef; + EventTypeSpec tEvents[] = { { kEventClassControl, kEventControlHit } }, + iEvents[] = { { kEventClassControl, kEventControlClick } }, + pEvents[] = { { kEventClassWindow, kEventWindowClose }, + { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }; + ControlActionUPP arrowsUPP, sliderUPP; + HIViewRef ctl, root; + HIViewID cid; + MenuRef menu; + char num[16]; + + root = HIViewGetRoot(tWindowRef); + + cid.signature = 'tabs'; + cid.id = 128; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, lastTabIndex); + SelectTabPane(ctl, lastTabIndex); + tUPP = NewEventHandlerUPP(TabEventHandler); + err = InstallControlEventHandler(ctl, tUPP, GetEventTypeCount(tEvents), tEvents, 0, &tRef); + + cid.signature = 'snd_'; + cid.id = iNibSInputRateText; + HIViewFindByID(root, cid, &ctl); + iUPP = NewEventHandlerUPP(InputRateTextEventHandler); + err = InstallControlEventHandler(ctl, iUPP, GetEventTypeCount(iEvents), iEvents, 0, &iRef); + + pUPP = NewEventHandlerUPP(PreferencesEventHandler); + err = InstallWindowEventHandler(tWindowRef, pUPP, GetEventTypeCount(pEvents), pEvents, (void *) tWindowRef, &pRef); + + sliderUPP = NewControlActionUPP(InputRateSliderActionProc); + arrowsUPP = NewControlActionUPP(LittleArrowsActionProc); + + cid.signature = 'grap'; + + cid.id = iNibGFullScreen; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, fullscreen); + + cid.id = iNibGSwitchResolution; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, autoRes); + + cid.id = iNibGShowFrameRate; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, Settings.DisplayFrameRate); + + cid.id = iNibGTransparency; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, Settings.Transparency); + + cid.id = iNibGGL32bit; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, gl32bit); + + cid.id = iNibGGLStretch; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, glstretch); + + cid.id = iNibGVideoMode; + HIViewFindByID(root, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + switch (videoMode) + { + case VIDEOMODE_BLOCKY: + CheckMenuItem(menu, iOpenGLBlocky, true); + SetControl32BitValue(ctl, iOpenGLBlocky); + break; + + case VIDEOMODE_TV: + CheckMenuItem(menu, iOpenGLTVMode, true); + SetControl32BitValue(ctl, iOpenGLTVMode); + break; + + case VIDEOMODE_SMOOTH: + CheckMenuItem(menu, iOpenGLSmoothMode, true); + SetControl32BitValue(ctl, iOpenGLSmoothMode); + break; + + case VIDEOMODE_SUPEREAGLE: + CheckMenuItem(menu, iOpenGLEagleMode, true); + SetControl32BitValue(ctl, iOpenGLEagleMode); + break; + + case VIDEOMODE_2XSAI: + CheckMenuItem(menu, iOpenGL2xSAIMode, true); + SetControl32BitValue(ctl, iOpenGL2xSAIMode); + break; + + case VIDEOMODE_SUPER2XSAI: + CheckMenuItem(menu, iOpenGLSuper2xSAIMode, true); + SetControl32BitValue(ctl, iOpenGLSuper2xSAIMode); + break; + + case VIDEOMODE_EPX: + CheckMenuItem(menu, iOpenGLEPXMode, true); + SetControl32BitValue(ctl, iOpenGLEPXMode); + break; + + case VIDEOMODE_HQ2X: + CheckMenuItem(menu, iOpenGLHQ2xMode, true); + SetControl32BitValue(ctl, iOpenGLHQ2xMode); + break; + + case VIDEOMODE_HQ3X: + CheckMenuItem(menu, iOpenGLHQ3xMode, true); + SetControl32BitValue(ctl, iOpenGLHQ3xMode); + break; + + case VIDEOMODE_HQ4X: + CheckMenuItem(menu, iOpenGLHQ4xMode, true); + SetControl32BitValue(ctl, iOpenGLHQ4xMode); + break; + + case VIDEOMODE_NTSC_C: + CheckMenuItem(menu, iOpenGLNTSC_CMode, true); + SetControl32BitValue(ctl, iOpenGLNTSC_CMode); + break; + + case VIDEOMODE_NTSC_S: + CheckMenuItem(menu, iOpenGLNTSC_SMode, true); + SetControl32BitValue(ctl, iOpenGLNTSC_SMode); + break; + + case VIDEOMODE_NTSC_R: + CheckMenuItem(menu, iOpenGLNTSC_RMode, true); + SetControl32BitValue(ctl, iOpenGLNTSC_RMode); + break; + + case VIDEOMODE_NTSC_M: + CheckMenuItem(menu, iOpenGLNTSC_MMode, true); + SetControl32BitValue(ctl, iOpenGLNTSC_MMode); + break; + + case VIDEOMODE_NTSC_TV_C: + CheckMenuItem(menu, iOpenGLNTSC_TV_CMode, true); + SetControl32BitValue(ctl, iOpenGLNTSC_TV_CMode); + break; + + case VIDEOMODE_NTSC_TV_S: + CheckMenuItem(menu, iOpenGLNTSC_TV_SMode, true); + SetControl32BitValue(ctl, iOpenGLNTSC_TV_SMode); + break; + + case VIDEOMODE_NTSC_TV_R: + CheckMenuItem(menu, iOpenGLNTSC_TV_RMode, true); + SetControl32BitValue(ctl, iOpenGLNTSC_TV_RMode); + break; + + case VIDEOMODE_NTSC_TV_M: + CheckMenuItem(menu, iOpenGLNTSC_TV_MMode, true); + SetControl32BitValue(ctl, iOpenGLNTSC_TV_MMode); + break; + } + + cid.id = iNibGDirectMP; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, multiprocessor); + + cid.id = iNibGGLVSync; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, vsync); + + cid.id = iNibGDrawOverscan; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, drawoverscan); + + cid.id = iNibGScreenCurvature; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, screencurvature); + + cid.id = iNibGCurvatureWarp; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, macCurvatureWarp); + if (!screencurvature) + DeactivateControl(ctl); + + cid.id = iNibGAspectRatio; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, macAspectRatio); + if (!glstretch) + DeactivateControl(ctl); + + cid.id = iNibGCIFilterEnable; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, ciFilterEnable); + if (systemVersion < 0x1040) + DisableControl(ctl); + + if (systemVersion < 0x1040) + { + cid.id = iNibGCoreImageFilter; + HIViewFindByID(root, cid, &ctl); + DisableControl(ctl); + } + + cid.signature = 'snd_'; + + cid.id = iNibSSynchronize; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, Settings.SoundSync); + + cid.id = iNibS16BitPlayback; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, Settings.SixteenBitSound); + + cid.id = iNibSStereo; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, Settings.Stereo); + + cid.id = iNibSReverseStereo; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, Settings.ReverseStereo); + if (!Settings.Stereo) + DeactivateControl(ctl); + + cid.id = iNibSPlaybackRate; + HIViewFindByID(root, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + switch (Settings.SoundPlaybackRate) + { + case 48000: + CheckMenuItem(menu, 1, true); + SetControl32BitValue(ctl, 1); + break; + + case 44100: + CheckMenuItem(menu, 2, true); + SetControl32BitValue(ctl, 2); + break; + + case 35000: + CheckMenuItem(menu, 3, true); + SetControl32BitValue(ctl, 3); + break; + + case 32000: + CheckMenuItem(menu, 4, true); + SetControl32BitValue(ctl, 4); + break; + + case 30000: + CheckMenuItem(menu, 5, true); + SetControl32BitValue(ctl, 5); + break; + + case 22050: + CheckMenuItem(menu, 6, true); + SetControl32BitValue(ctl, 6); + break; + + case 16000: + CheckMenuItem(menu, 7, true); + SetControl32BitValue(ctl, 7); + break; + + case 11025: + CheckMenuItem(menu, 8, true); + SetControl32BitValue(ctl, 8); + break; + + case 8000: + CheckMenuItem(menu, 9, true); + SetControl32BitValue(ctl, 9); + break; + } + + cid.id = iNibSInputRate; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, Settings.SoundInputRate); + SetControlAction(ctl, sliderUPP); + + cid.id = iNibSInputRateText; + HIViewFindByID(root, cid, &ctl); + sprintf(num, "%d", Settings.SoundInputRate); + SetStaticTextCStr(ctl, num, false); + + cid.id = iNibSInterval; + HIViewFindByID(root, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + switch (macSoundInterval_ms) + { + case 8: + CheckMenuItem(menu, 1, true); + SetControl32BitValue(ctl, 1); + break; + + case 16: + CheckMenuItem(menu, 2, true); + SetControl32BitValue(ctl, 2); + break; + + case 32: + CheckMenuItem(menu, 3, true); + SetControl32BitValue(ctl, 3); + break; + + case 64: + CheckMenuItem(menu, 4, true); + SetControl32BitValue(ctl, 4); + break; + + case 0: + default: + CheckMenuItem(menu, 6, true); + SetControl32BitValue(ctl, 6); + break; + } + + cid.id = iNibSBufferSize; + HIViewFindByID(root, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + CheckMenuItem(menu, macSoundBuffer_ms / 20, true); + SetControl32BitValue(ctl, macSoundBuffer_ms / 20); + + cid.id = iNibSAllowLag; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, macSoundLagEnable); + + cid.id = iNibSVolume; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, macSoundVolume); + + cid.signature = 'othe'; + + cid.id = iNibOSaveFolder; + HIViewFindByID(root, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + if (saveInROMFolder == 1) + { + CheckMenuItem(menu, 2, true); + SetControl32BitValue(ctl, 2); + } + else + if (saveInROMFolder == 0) + { + CheckMenuItem(menu, 1, true); + SetControl32BitValue(ctl, 1); + } + else + { + CheckMenuItem(menu, 3, true); + SetControl32BitValue(ctl, 3); + } + + cid.id = iNibOAutoSaveInterval; + HIViewFindByID(root, cid, &ctl); + sprintf(num, "%d", Settings.AutoSaveDelay); + SetEditTextCStr(ctl, num, false); + + cid.signature = 'msc2'; + + cid.id = iNibMCPUCycles; + HIViewFindByID(root, cid, &ctl); + sprintf(num, "%" PRIi32, Settings.HDMATimingHack); + SetEditTextCStr(ctl, num, false); + + cid.id = iNibMShutdownMaster; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, Settings.ShutdownMaster); + + cid.id = iNibMTurboSkipArrows; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, macFastForwardRate); + SetControlAction(ctl, arrowsUPP); + + cid.id = iNibMTurboSkipText; + HIViewFindByID(root, cid, &ctl); + sprintf(num, "%d", macFastForwardRate); + SetStaticTextCStr(ctl, num, false); + + cid.id = iNibMFrameSkip; + HIViewFindByID(root, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + CheckMenuItem(menu, macFrameSkip + 2, true); + SetControl32BitValue(ctl, macFrameSkip + 2); + + cid.id = iNibMAllowInvalidVRAMAccess; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, !Settings.BlockInvalidVRAMAccessMaster); + + cid.id = iNibMAllowSpecificGameHacks; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, !Settings.DisableGameSpecificHacks); + + cid.signature = 'osx_'; + + cid.id = iNibXStartOpenDialog; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, startopendlog); + + cid.id = iNibXShowTimeInFrz; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, showtimeinfrz); + + cid.id = iNibXMusicBoxMode; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, musicboxmode); + + cid.id = iNibXEnableToggle; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, enabletoggle); + + cid.id = iNibXSaveWindowPos; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, savewindowpos); + + cid.id = iNibXUseIPSPatch; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, !Settings.NoPatch); + + cid.id = iNibXOnScreenInfo; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, onscreeninfo); + + cid.id = iNibXInactiveMode; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, inactiveMode); + + cid.id = iNibXBSXBootup; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, Settings.BSXBootup); + + MoveWindowPosition(tWindowRef, kWindowPreferences, false); + ShowWindow(tWindowRef); + err = RunAppModalLoopForWindow(tWindowRef); + HideWindow(tWindowRef); + SaveWindowPosition(tWindowRef, kWindowPreferences); + + cid.signature = 'grap'; + + cid.id = iNibGFullScreen; + HIViewFindByID(root, cid, &ctl); + fullscreen = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibGSwitchResolution; + HIViewFindByID(root, cid, &ctl); + autoRes = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibGShowFrameRate; + HIViewFindByID(root, cid, &ctl); + Settings.DisplayFrameRate = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibGTransparency; + HIViewFindByID(root, cid, &ctl); + Settings.Transparency = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibGGL32bit; + HIViewFindByID(root, cid, &ctl); + gl32bit = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibGGLStretch; + HIViewFindByID(root, cid, &ctl); + glstretch = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibGVideoMode; + HIViewFindByID(root, cid, &ctl); + switch (GetControl32BitValue(ctl)) + { + case iOpenGLBlocky: + drawingMethod = kDrawingOpenGL; + videoMode = VIDEOMODE_BLOCKY; + break; + + case iOpenGLTVMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_TV; + break; + + case iOpenGLSmoothMode: + drawingMethod = kDrawingOpenGL; + videoMode = VIDEOMODE_SMOOTH; + break; + + case iOpenGLEagleMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_SUPEREAGLE; + break; + + case iOpenGL2xSAIMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_2XSAI; + break; + + case iOpenGLSuper2xSAIMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_SUPER2XSAI; + break; + + case iOpenGLEPXMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_EPX; + break; + + case iOpenGLHQ2xMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_HQ2X; + break; + + case iOpenGLHQ3xMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_HQ3X; + break; + + case iOpenGLHQ4xMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_HQ4X; + break; + + case iOpenGLNTSC_CMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_NTSC_C; + S9xBlitNTSCFilterSet(&snes_ntsc_composite); + break; + + case iOpenGLNTSC_SMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_NTSC_S; + S9xBlitNTSCFilterSet(&snes_ntsc_svideo); + break; + + case iOpenGLNTSC_RMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_NTSC_R; + S9xBlitNTSCFilterSet(&snes_ntsc_rgb); + break; + + case iOpenGLNTSC_MMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_NTSC_M; + S9xBlitNTSCFilterSet(&snes_ntsc_monochrome); + break; + + case iOpenGLNTSC_TV_CMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_NTSC_TV_C; + S9xBlitNTSCFilterSet(&snes_ntsc_composite); + break; + + case iOpenGLNTSC_TV_SMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_NTSC_TV_S; + S9xBlitNTSCFilterSet(&snes_ntsc_svideo); + break; + + case iOpenGLNTSC_TV_RMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_NTSC_TV_R; + S9xBlitNTSCFilterSet(&snes_ntsc_rgb); + break; + + case iOpenGLNTSC_TV_MMode: + drawingMethod = kDrawingBlitGL; + videoMode = VIDEOMODE_NTSC_TV_M; + S9xBlitNTSCFilterSet(&snes_ntsc_monochrome); + break; + } + + cid.id = iNibGDirectMP; + HIViewFindByID(root, cid, &ctl); + multiprocessor = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibGGLVSync; + HIViewFindByID(root, cid, &ctl); + vsync = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibGDrawOverscan; + HIViewFindByID(root, cid, &ctl); + drawoverscan = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibGScreenCurvature; + HIViewFindByID(root, cid, &ctl); + screencurvature = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibGCurvatureWarp; + HIViewFindByID(root, cid, &ctl); + macCurvatureWarp = GetControl32BitValue(ctl); + + cid.id = iNibGAspectRatio; + HIViewFindByID(root, cid, &ctl); + macAspectRatio = GetControl32BitValue(ctl); + + cid.id = iNibGCIFilterEnable; + HIViewFindByID(root, cid, &ctl); + ciFilterEnable = GetControl32BitValue(ctl) ? true : false; + + cid.signature = 'snd_'; + + cid.id = iNibSSynchronize; + HIViewFindByID(root, cid, &ctl); + Settings.SoundSync = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibS16BitPlayback; + HIViewFindByID(root, cid, &ctl); + Settings.SixteenBitSound = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibSStereo; + HIViewFindByID(root, cid, &ctl); + Settings.Stereo = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibSReverseStereo; + HIViewFindByID(root, cid, &ctl); + Settings.ReverseStereo = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibSPlaybackRate; + HIViewFindByID(root, cid, &ctl); + switch (GetControl32BitValue(ctl)) + { + case 1: + Settings.SoundPlaybackRate = 48000; + break; + + case 2: + Settings.SoundPlaybackRate = 44100; + break; + + case 3: + Settings.SoundPlaybackRate = 35000; + break; + + case 4: + Settings.SoundPlaybackRate = 32000; + break; + + case 5: + Settings.SoundPlaybackRate = 30000; + break; + + case 6: + Settings.SoundPlaybackRate = 22050; + break; + + case 7: + Settings.SoundPlaybackRate = 16000; + break; + + case 8: + Settings.SoundPlaybackRate = 11025; + break; + + case 9: + Settings.SoundPlaybackRate = 8000; + break; + } + + cid.id = iNibSInputRate; + HIViewFindByID(root, cid, &ctl); + Settings.SoundInputRate = GetControl32BitValue(ctl); + + cid.id = iNibSInterval; + HIViewFindByID(root, cid, &ctl); + switch (GetControl32BitValue(ctl)) + { + case 1: + macSoundInterval_ms = 8; + break; + + case 2: + macSoundInterval_ms = 16; + break; + + case 3: + macSoundInterval_ms = 32; + break; + + case 4: + macSoundInterval_ms = 64; + break; + + case 6: + default: + macSoundInterval_ms = 0; + break; + } + + cid.id = iNibSBufferSize; + HIViewFindByID(root, cid, &ctl); + macSoundBuffer_ms = GetControl32BitValue(ctl) * 20; + + cid.id = iNibSAllowLag; + HIViewFindByID(root, cid, &ctl); + macSoundLagEnable = GetControl32BitValue(ctl); + + cid.id = iNibSVolume; + HIViewFindByID(root, cid, &ctl); + macSoundVolume = GetControl32BitValue(ctl); + + cid.signature = 'othe'; + + cid.id = iNibOSaveFolder; + HIViewFindByID(root, cid, &ctl); + int saveto = GetControl32BitValue(ctl); + if (saveto == 2) + saveInROMFolder = 1; + else + if (saveto == 1) + saveInROMFolder = 0; + else + saveInROMFolder = 3; + + cid.id = iNibOAutoSaveInterval; + HIViewFindByID(root, cid, &ctl); + GetEditTextCStr(ctl, num); + Settings.AutoSaveDelay = atoi(num); + + cid.signature = 'msc2'; + + cid.id = iNibMCPUCycles; + HIViewFindByID(root, cid, &ctl); + GetEditTextCStr(ctl, num); + Settings.HDMATimingHack = atoi(num); + if ((Settings.HDMATimingHack <= 0) || (Settings.HDMATimingHack >= 200)) + Settings.HDMATimingHack = 100; + + cid.id = iNibMShutdownMaster; + HIViewFindByID(root, cid, &ctl); + Settings.ShutdownMaster = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibMTurboSkipArrows; + HIViewFindByID(root, cid, &ctl); + macFastForwardRate = GetControl32BitValue(ctl); + + cid.id = iNibMFrameSkip; + HIViewFindByID(root, cid, &ctl); + macFrameSkip = GetControl32BitValue(ctl) - 2; + + cid.id = iNibMAllowInvalidVRAMAccess; + HIViewFindByID(root, cid, &ctl); + Settings.BlockInvalidVRAMAccessMaster = GetControl32BitValue(ctl) ? false : true; + + cid.id = iNibMAllowSpecificGameHacks; + HIViewFindByID(root, cid, &ctl); + Settings.DisableGameSpecificHacks = GetControl32BitValue(ctl) ? false : true; + + cid.signature = 'osx_'; + + cid.id = iNibXStartOpenDialog; + HIViewFindByID(root, cid, &ctl); + startopendlog = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibXShowTimeInFrz; + HIViewFindByID(root, cid, &ctl); + showtimeinfrz = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibXMusicBoxMode; + HIViewFindByID(root, cid, &ctl); + musicboxmode = GetControl32BitValue(ctl); + + cid.id = iNibXEnableToggle; + HIViewFindByID(root, cid, &ctl); + enabletoggle = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibXSaveWindowPos; + HIViewFindByID(root, cid, &ctl); + savewindowpos = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibXUseIPSPatch; + HIViewFindByID(root, cid, &ctl); + Settings.NoPatch = GetControl32BitValue(ctl) ? false : true; + + cid.id = iNibXOnScreenInfo; + HIViewFindByID(root, cid, &ctl); + onscreeninfo = GetControl32BitValue(ctl) ? true : false; + + cid.id = iNibXInactiveMode; + HIViewFindByID(root, cid, &ctl); + inactiveMode = GetControl32BitValue(ctl); + + cid.id = iNibXBSXBootup; + HIViewFindByID(root, cid, &ctl); + Settings.BSXBootup = GetControl32BitValue(ctl) ? true : false; + + DisposeControlActionUPP(arrowsUPP); + DisposeControlActionUPP(sliderUPP); + + err = RemoveEventHandler(pRef); + DisposeEventHandlerUPP(pUPP); + + err = RemoveEventHandler(iRef); + DisposeEventHandlerUPP(iUPP); + + err = RemoveEventHandler(tRef); + DisposeEventHandlerUPP(tUPP); + + CFRelease(tWindowRef); + } + + DisposeNibReference(nibRef); + + S9xGraphicsInit(); + + if (((oldSynchronize != Settings.SoundSync ) || + (old16BitPlayback != Settings.SixteenBitSound ) || + (oldStereo != Settings.Stereo ) || + (oldReverseStereo != Settings.ReverseStereo ) || + (oldPlaybackRate != Settings.SoundPlaybackRate) || + (oldInputRate != Settings.SoundInputRate ) || + (oldInterval != macSoundInterval_ms ) || + (oldBufferSize != macSoundBuffer_ms ) || + (oldLagEnable != macSoundLagEnable ) || + (oldVolume != macSoundVolume )) && cartOpen) + SNES9X_InitSound(); + + if (!fullscreen && cartOpen) + { + InitGameWindow(); + ShowWindow(gWindow); + } + } +} + +static void SelectTabPane (HIViewRef tabControl, SInt16 index) +{ + HIViewRef sup, userPane, selectedPane = NULL; + HIViewID cid; + + lastTabIndex = index; + + sup = HIViewGetSuperview(tabControl); + cid.signature = 'tabs'; + + for (int i = 1; i < tabList[0] + 1; i++) + { + cid.id = tabList[i]; + HIViewFindByID(sup, cid, &userPane); + + if (i == index) + selectedPane = userPane; + else + HIViewSetVisible(userPane, false); + } + + if (selectedPane != NULL) + HIViewSetVisible(selectedPane, true); + + HIViewSetNeedsDisplay(tabControl, true); +} + +static pascal void InputRateSliderActionProc (HIViewRef slider, HIViewPartCode partCode) +{ + HIViewRef ctl; + HIViewID cid; + char num[10]; + + cid.signature = 'snd_'; + cid.id = iNibSInputRateText; + HIViewFindByID(HIViewGetSuperview(slider), cid, &ctl); + + sprintf(num, "%ld", GetControl32BitValue(slider)); + SetStaticTextCStr(ctl, num, true); +} + +static pascal void LittleArrowsActionProc (HIViewRef arrows, HIViewPartCode partCode) +{ + HIViewRef ctl; + HIViewID cid = { 'msc2', iNibMTurboSkipText }; + char num[8]; + + if (partCode == kControlUpButtonPart) + SetControl32BitValue(arrows, GetControl32BitValue(arrows) + 1); + else + if (partCode == kControlDownButtonPart) + SetControl32BitValue(arrows, GetControl32BitValue(arrows) - 1); + + HIViewFindByID(HIViewGetSuperview(arrows), cid, &ctl); + sprintf(num, "%ld", GetControl32BitValue(arrows)); + SetStaticTextCStr(ctl, num, true); +} + +static pascal OSStatus InputRateTextEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + HIViewRef ctl, slider; + HIViewID cid; + SInt32 value; + char num[10]; + + err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &ctl); + if (err == noErr) + { + cid.signature = 'snd_'; + cid.id = iNibSInputRate; + HIViewFindByID(HIViewGetSuperview(ctl), cid, &slider); + value = GetControl32BitValue(slider); + + value /= 50; + value *= 50; + if (value > 33000) + value = 33000; + if (value < 31000) + value = 31000; + + SetControl32BitValue(slider, value); + sprintf(num, "%ld", value); + SetEditTextCStr(ctl, num, true); + + result = noErr; + } + + return (result); +} + +static pascal OSStatus TabEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + HIViewRef ctl; + HIViewID cid; + SInt32 value; + + err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &ctl); + if (err == noErr) + { + GetControlID(ctl, &cid); + value = GetControl32BitValue(ctl); + + if ((cid.id == 128) && (value != lastTabIndex)) + { + SelectTabPane(ctl, value); + result = noErr; + } + } + + return (result); +} + +static pascal OSStatus PreferencesEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef tWindowRef = (WindowRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassWindow: + switch (GetEventKind(inEvent)) + { + case kEventWindowClose: + QuitAppModalLoopForWindow(tWindowRef); + result = noErr; + break; + } + + break; + + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(true); + result = noErr; + } + + break; + + case kEventCommandProcess: + HIViewRef ctl, root; + HIViewID cid; + SInt32 value; + + root = HIViewGetRoot(tWindowRef); + + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + switch (tHICommand.commandID) + { + case 'S_EF': + HideWindow(tWindowRef); + ConfigureSoundEffects(); + ShowWindow(tWindowRef); + + result = noErr; + break; + + case 'G_FL': + if (systemVersion >= 0x1040) + { + HideWindow(tWindowRef); + ConfigureCoreImageFilter(); + ShowWindow(tWindowRef); + } + + result = noErr; + break; + + case 'G__7': + cid.signature = 'grap'; + cid.id = iNibGGLStretch; + HIViewFindByID(root, cid, &ctl); + value = GetControl32BitValue(ctl); + + cid.id = iNibGAspectRatio; + HIViewFindByID(root, cid, &ctl); + if (value) + ActivateControl(ctl); + else + DeactivateControl(ctl); + + result = noErr; + break; + + case 'G_13': + cid.signature = 'grap'; + cid.id = iNibGScreenCurvature; + HIViewFindByID(root, cid, &ctl); + value = GetControl32BitValue(ctl); + + cid.id = iNibGCurvatureWarp; + HIViewFindByID(root, cid, &ctl); + if (value) + ActivateControl(ctl); + else + DeactivateControl(ctl); + + result = noErr; + break; + + case 'S__3': + cid.signature = 'snd_'; + cid.id = iNibSStereo; + HIViewFindByID(root, cid, &ctl); + value = GetControl32BitValue(ctl); + + cid.id = iNibSReverseStereo; + HIViewFindByID(root, cid, &ctl); + if (value) + ActivateControl(ctl); + else + DeactivateControl(ctl); + + result = noErr; + break; + } + } + + break; + } + + break; + } + + return (result); +} + +void ConfigureExtraOptions (void) +{ + OSStatus err; + IBNibRef nibRef; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef tWindowRef; + + err = CreateWindowFromNib(nibRef, CFSTR("ExtraOptions"), &tWindowRef); + if (err == noErr) + { + EventHandlerRef eref; + EventHandlerUPP eventUPP; + EventTypeSpec windowEvents[] = { { kEventClassWindow, kEventWindowClose }, + { kEventClassCommand, kEventCommandUpdateStatus } }; + HIViewRef ctl, root; + HIViewID cid; + MenuRef menu; + + root = HIViewGetRoot(tWindowRef); + cid.id = 0; + + cid.signature = 'BMrk'; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, extraOptions.benchmark); + + cid.signature = 'NoTR'; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, extraOptions.glForceNoTextureRectangle); + + cid.signature = 'CSAp'; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, extraOptions.glUseClientStrageApple); + + cid.signature = 'AGPT'; + HIViewFindByID(root, cid, &ctl); + SetControl32BitValue(ctl, extraOptions.glUseTexturePriority); + + cid.signature = 'Hint'; + HIViewFindByID(root, cid, &ctl); + menu = HIMenuViewGetMenu(ctl); + for (int i = 1; i <= CountMenuItems(menu); i++) + CheckMenuItem(menu, i, false); + CheckMenuItem(menu, extraOptions.glStorageHint, true); + SetControl32BitValue(ctl, extraOptions.glStorageHint); + + eventUPP = NewEventHandlerUPP(DefaultEventHandler); + err = InstallWindowEventHandler(tWindowRef, eventUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) tWindowRef, &eref); + + MoveWindowPosition(tWindowRef, kWindowExtra, false); + ShowWindow(tWindowRef); + err = RunAppModalLoopForWindow(tWindowRef); + HideWindow(tWindowRef); + SaveWindowPosition(tWindowRef, kWindowExtra); + + cid.signature = 'BMrk'; + HIViewFindByID(root, cid, &ctl); + extraOptions.benchmark = GetControl32BitValue(ctl) ? true : false; + + cid.signature = 'NoTR'; + HIViewFindByID(root, cid, &ctl); + extraOptions.glForceNoTextureRectangle = GetControl32BitValue(ctl) ? true : false; + + cid.signature = 'CSAp'; + HIViewFindByID(root, cid, &ctl); + extraOptions.glUseClientStrageApple = GetControl32BitValue(ctl) ? true : false; + + cid.signature = 'AGPT'; + HIViewFindByID(root, cid, &ctl); + extraOptions.glUseTexturePriority = GetControl32BitValue(ctl) ? true : false; + + cid.signature = 'Hint'; + HIViewFindByID(root, cid, &ctl); + extraOptions.glStorageHint = GetControl32BitValue(ctl); + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eventUPP); + + CFRelease(tWindowRef); + } + + DisposeNibReference(nibRef); + } +} diff --git a/macosx/mac-prefs.h b/macosx/mac-prefs.h new file mode 100644 index 00000000..d3ff8d07 --- /dev/null +++ b/macosx/mac-prefs.h @@ -0,0 +1,199 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_prefs_h_ +#define _mac_prefs_h_ + +void LoadPrefs (void); +void SavePrefs (void); +void ConfigurePreferences (void); +void ConfigureExtraOptions (void); + +#endif diff --git a/macosx/mac-quicktime.cpp b/macosx/mac-quicktime.cpp new file mode 100644 index 00000000..00f16cc6 --- /dev/null +++ b/macosx/mac-quicktime.cpp @@ -0,0 +1,624 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "apu.h" + +#include + +#include "mac-prefix.h" +#include "mac-gworld.h" +#include "mac-os.h" +#include "mac-screenshot.h" +#include "mac-quicktime.h" + +#define kMovDoubleSize (1 << 0) +#define kMovExtendedHeight (1 << 1) + +static void CheckError (OSStatus, int); +static void MacQTOpenVideoComponent (ComponentInstance *); +static void MacQTCloseVideoComponent (ComponentInstance); +static OSStatus WriteFrameCallBack (void *, ICMCompressionSessionRef, OSStatus, ICMEncodedFrameRef, void *); + +typedef struct +{ + Movie movie; + Track vTrack, sTrack; + Media vMedia, sMedia; + ComponentInstance vci; + SoundDescriptionHandle soundDesc; + DataHandler dataHandler; + Handle soundBuffer; + Handle dataRef; + OSType dataRefType; + CVPixelBufferPoolRef pool; + ICMCompressionSessionRef session; + ICMCompressionSessionOptionsRef option; + CGImageRef srcImage; + TimeValue64 timeStamp; + long keyFrame, keyFrameCount; + long frameSkip, frameSkipCount; + int width, height; + int soundBufferSize; + int samplesPerSec; +} MacQTState; + +static MacQTState sqt; + + +static void CheckError (OSStatus err, int n) +{ + if (err != noErr) + { + char mes[32]; + + sprintf(mes, "quicktime %02d", n); + QuitWithFatalError(err, mes); + } +} + +static void MacQTOpenVideoComponent (ComponentInstance *rci) +{ + OSStatus err; + ComponentInstance ci; + CFDataRef data; + + ci = OpenDefaultComponent(StandardCompressionType, StandardCompressionSubType); + + data = (CFDataRef) CFPreferencesCopyAppValue(CFSTR("QTVideoSetting"), kCFPreferencesCurrentApplication); + if (data) + { + CFIndex len; + Handle hdl; + + len = CFDataGetLength(data); + hdl = NewHandleClear((Size) len); + if (MemError() == noErr) + { + HLock(hdl); + CFDataGetBytes(data, CFRangeMake(0, len), (unsigned char *) *hdl); + err = SCSetInfo(ci, scSettingsStateType, &hdl); + + DisposeHandle(hdl); + } + + CFRelease(data); + } + else + { + SCSpatialSettings ss; + SCTemporalSettings ts; + + ss.codecType = kAnimationCodecType; + ss.codec = 0; + ss.depth = 16; + ss.spatialQuality = codecMaxQuality; + err = SCSetInfo(ci, scSpatialSettingsType, &ss); + + ts.frameRate = FixRatio(Memory.ROMFramesPerSecond, 1); + ts.keyFrameRate = Memory.ROMFramesPerSecond; + ts.temporalQuality = codecMaxQuality; + err = SCSetInfo(ci, scTemporalSettingsType, &ts); + } + + *rci = ci; +} + +static void MacQTCloseVideoComponent (ComponentInstance ci) +{ + OSStatus err; + + err = CloseComponent(ci); +} + +void MacQTVideoConfig (WindowRef parent) +{ + OSStatus err; + ComponentInstance ci; + + if (running) + return; + + MacQTOpenVideoComponent(&ci); + + long flag; + flag = scListEveryCodec | scAllowZeroKeyFrameRate | scDisableFrameRateItem | scAllowEncodingWithCompressionSession; + err = SCSetInfo(ci, scPreferenceFlagsType, &flag); + + SCWindowSettings ws; + ws.size = sizeof(SCWindowSettings); + ws.windowRefKind = scWindowRefKindCarbon; + ws.parentWindow = parent; + err = SCSetInfo(ci, scWindowOptionsType, &ws); + + err = SCRequestSequenceSettings(ci); + if (err == noErr) + { + CFDataRef data; + Handle hdl; + + err = SCGetInfo(ci, scSettingsStateType, &hdl); + if (err == noErr) + { + HLock(hdl); + data = CFDataCreate(kCFAllocatorDefault, (unsigned char *) *hdl, GetHandleSize(hdl)); + if (data) + { + CFPreferencesSetAppValue(CFSTR("QTVideoSetting"), data, kCFPreferencesCurrentApplication); + CFRelease(data); + } + + DisposeHandle(hdl); + } + } + + MacQTCloseVideoComponent(ci); +} + +void MacQTStartRecording (char *path) +{ + OSStatus err; + CFStringRef str; + CFURLRef url; + + memset(&sqt, 0, sizeof(sqt)); + + // storage + + str = CFStringCreateWithCString(kCFAllocatorDefault, path, MAC_PATH_ENCODING); + url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, str, kCFURLPOSIXPathStyle, false); + err = QTNewDataReferenceFromCFURL(url, 0, &(sqt.dataRef), &(sqt.dataRefType)); + CheckError(err, 21); + CFRelease(url); + CFRelease(str); + + err = CreateMovieStorage(sqt.dataRef, sqt.dataRefType, 'TVOD', smSystemScript, createMovieFileDeleteCurFile | newMovieActive, &(sqt.dataHandler), &(sqt.movie)); + CheckError(err, 22); + + // video + + MacQTOpenVideoComponent(&(sqt.vci)); + + long flag; + SCTemporalSettings ts; + + flag = scAllowEncodingWithCompressionSession; + err = SCSetInfo(sqt.vci, scPreferenceFlagsType, &flag); + + err = SCGetInfo(sqt.vci, scTemporalSettingsType, &ts); + ts.frameRate = FixRatio(Memory.ROMFramesPerSecond, 1); + if (ts.keyFrameRate < 1) + ts.keyFrameRate = Memory.ROMFramesPerSecond; + sqt.keyFrame = sqt.keyFrameCount = ts.keyFrameRate; + sqt.frameSkip = sqt.frameSkipCount = (macQTMovFlag & 0xFF00) >> 8; + err = SCSetInfo(sqt.vci, scTemporalSettingsType, &ts); + + sqt.width = ((macQTMovFlag & kMovDoubleSize) ? 2 : 1) * SNES_WIDTH; + sqt.height = ((macQTMovFlag & kMovDoubleSize) ? 2 : 1) * ((macQTMovFlag & kMovExtendedHeight) ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT); + + sqt.srcImage = NULL; + sqt.timeStamp = 0; + + SCSpatialSettings ss; + ICMEncodedFrameOutputRecord record; + ICMMultiPassStorageRef nullStorage = NULL; + + err = SCCopyCompressionSessionOptions(sqt.vci, &(sqt.option)); + CheckError(err, 61); + err = ICMCompressionSessionOptionsSetProperty(sqt.option, kQTPropertyClass_ICMCompressionSessionOptions, kICMCompressionSessionOptionsPropertyID_MultiPassStorage, sizeof(ICMMultiPassStorageRef), &nullStorage); + + record.encodedFrameOutputCallback = WriteFrameCallBack; + record.encodedFrameOutputRefCon = NULL; + record.frameDataAllocator = NULL; + err = SCGetInfo(sqt.vci, scSpatialSettingsType, &ss); + err = ICMCompressionSessionCreate(kCFAllocatorDefault, sqt.width, sqt.height, ss.codecType, Memory.ROMFramesPerSecond, sqt.option, NULL, &record, &(sqt.session)); + CheckError(err, 62); + + CFMutableDictionaryRef dic; + CFNumberRef val; + OSType pix = k16BE555PixelFormat; + int row = sqt.width * 2; + + dic = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + val = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix); + CFDictionaryAddValue(dic, kCVPixelBufferPixelFormatTypeKey, val); + CFRelease(val); + + val = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &(sqt.width)); + CFDictionaryAddValue(dic, kCVPixelBufferWidthKey, val); + CFRelease(val); + + val = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &(sqt.height)); + CFDictionaryAddValue(dic, kCVPixelBufferHeightKey, val); + CFRelease(val); + + val = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &row); + CFDictionaryAddValue(dic, kCVPixelBufferBytesPerRowAlignmentKey, val); + CFRelease(val); + + CFDictionaryAddValue(dic, kCVPixelBufferCGImageCompatibilityKey, kCFBooleanTrue); + CFDictionaryAddValue(dic, kCVPixelBufferCGBitmapContextCompatibilityKey, kCFBooleanTrue); + + err = CVPixelBufferPoolCreate(kCFAllocatorDefault, NULL, dic, &(sqt.pool)); + CheckError(err, 63); + + CFRelease(dic); + + sqt.vTrack = NewMovieTrack(sqt.movie, FixRatio(sqt.width, 1), FixRatio(sqt.height, 1), kNoVolume); + CheckError(GetMoviesError(), 23); + + sqt.vMedia = NewTrackMedia(sqt.vTrack, VideoMediaType, Memory.ROMFramesPerSecond, NULL, 0); + CheckError(GetMoviesError(), 24); + + err = BeginMediaEdits(sqt.vMedia); + CheckError(err, 25); + + // sound + + sqt.soundDesc = (SoundDescriptionHandle) NewHandleClear(sizeof(SoundDescription)); + CheckError(MemError(), 26); + + (**sqt.soundDesc).descSize = sizeof(SoundDescription); +#ifdef __BIG_ENDIAN__ + (**sqt.soundDesc).dataFormat = Settings.SixteenBitSound ? k16BitBigEndianFormat : k8BitOffsetBinaryFormat; +#else + (**sqt.soundDesc).dataFormat = Settings.SixteenBitSound ? k16BitLittleEndianFormat : k8BitOffsetBinaryFormat; +#endif + (**sqt.soundDesc).numChannels = Settings.Stereo ? 2 : 1; + (**sqt.soundDesc).sampleSize = Settings.SixteenBitSound ? 16 : 8; + (**sqt.soundDesc).sampleRate = (UnsignedFixed) FixRatio(Settings.SoundPlaybackRate, 1); + + sqt.samplesPerSec = Settings.SoundPlaybackRate / Memory.ROMFramesPerSecond; + + sqt.soundBufferSize = sqt.samplesPerSec; + if (Settings.SixteenBitSound) + sqt.soundBufferSize <<= 1; + if (Settings.Stereo) + sqt.soundBufferSize <<= 1; + + sqt.soundBuffer = NewHandleClear(sqt.soundBufferSize); + CheckError(MemError(), 27); + HLock(sqt.soundBuffer); + + sqt.sTrack = NewMovieTrack(sqt.movie, 0, 0, kFullVolume); + CheckError(GetMoviesError(), 28); + + sqt.sMedia = NewTrackMedia(sqt.sTrack, SoundMediaType, Settings.SoundPlaybackRate, NULL, 0); + CheckError(GetMoviesError(), 29); + + err = BeginMediaEdits(sqt.sMedia); + CheckError(err, 30); +} + +void MacQTRecordFrame (int width, int height) +{ + OSStatus err; + + // video + + if (sqt.frameSkipCount == sqt.frameSkip) + { + CVPixelBufferRef buf; + + err = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, sqt.pool, &buf); + if (err == noErr) + { + CGColorSpaceRef color; + CGContextRef ctx; + uint16 *p; + + err = CVPixelBufferLockBaseAddress(buf, 0); + p = (uint16 *) CVPixelBufferGetBaseAddress(buf); + + color = CGColorSpaceCreateDeviceRGB(); + ctx = CGBitmapContextCreate((void *) p, sqt.width, sqt.height, 5, sqt.width * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0)); + CGContextSetShouldAntialias(ctx, false); + + if (sqt.srcImage) + CGImageRelease(sqt.srcImage); + sqt.srcImage = CreateGameScreenCGImage(); + + CGRect dst = CGRectMake(0.0f, 0.0f, (float) sqt.width, (float) sqt.height); + + if ((!(height % SNES_HEIGHT_EXTENDED)) && (!(macQTMovFlag & kMovExtendedHeight))) + { + CGRect src; + + src.size.width = (float) width; + src.size.height = (float) ((height > 256) ? (SNES_HEIGHT << 1) : SNES_HEIGHT); + src.origin.x = (float) 0; + src.origin.y = (float) height - src.size.height; + DrawSubCGImage(ctx, sqt.srcImage, src, dst); + } + else + if ((sqt.height << 1) % height) + { + CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); + CGContextFillRect(ctx, dst); + + float dh = (float) ((sqt.height > 256) ? (SNES_HEIGHT << 1) : SNES_HEIGHT); + float ofs = (float) ((int) ((drawoverscan ? 1.0 : 0.5) * ((float) sqt.height - dh) + 0.5)); + dst = CGRectMake(0.0f, ofs, (float) sqt.width, dh); + CGContextDrawImage(ctx, dst, sqt.srcImage); + } + else + CGContextDrawImage(ctx, dst, sqt.srcImage); + + CGContextRelease(ctx); + CGColorSpaceRelease(color); + + #ifndef __BIG_ENDIAN__ + for (int i = 0; i < sqt.width * sqt.height; i++) + SWAP_WORD(p[i]); + #endif + + err = CVPixelBufferUnlockBaseAddress(buf, 0); + + err = ICMCompressionSessionEncodeFrame(sqt.session, buf, sqt.timeStamp, 0, kICMValidTime_DisplayTimeStampIsValid, NULL, NULL, NULL); + + CVPixelBufferRelease(buf); + } + + sqt.keyFrameCount--; + if (sqt.keyFrameCount <= 0) + sqt.keyFrameCount = sqt.keyFrame; + } + + sqt.frameSkipCount--; + if (sqt.frameSkipCount < 0) + sqt.frameSkipCount = sqt.frameSkip; + + sqt.timeStamp++; + + // sound + + int sample_count = sqt.soundBufferSize; + if (Settings.SixteenBitSound) + sample_count >>= 1; + + S9xMixSamples((uint8 *) *(sqt.soundBuffer), sample_count); + + err = AddMediaSample(sqt.sMedia, sqt.soundBuffer, 0, sqt.soundBufferSize, 1, (SampleDescriptionHandle) sqt.soundDesc, sqt.samplesPerSec, mediaSampleNotSync, NULL); +} + +static OSStatus WriteFrameCallBack (void *refCon, ICMCompressionSessionRef session, OSStatus r, ICMEncodedFrameRef frame, void *reserved) +{ + OSStatus err; + + err = AddMediaSampleFromEncodedFrame(sqt.vMedia, frame, NULL); + return (err); +} + +void MacQTStopRecording (void) +{ + OSStatus err; + + // video + + err = ICMCompressionSessionCompleteFrames(sqt.session, true, 0, sqt.timeStamp); + err = ExtendMediaDecodeDurationToDisplayEndTime(sqt.vMedia, NULL); + + err = EndMediaEdits(sqt.vMedia); + CheckError(err, 52); + + err = InsertMediaIntoTrack(sqt.vTrack, 0, 0, (TimeValue) GetMediaDisplayDuration(sqt.vMedia), fixed1); + CheckError(err, 58); + + CGImageRelease(sqt.srcImage); + CVPixelBufferPoolRelease(sqt.pool); + ICMCompressionSessionRelease(sqt.session); + ICMCompressionSessionOptionsRelease(sqt.option); + + // sound + + err = EndMediaEdits(sqt.sMedia); + CheckError(err, 54); + + err = InsertMediaIntoTrack(sqt.sTrack, 0, 0, GetMediaDuration(sqt.sMedia), fixed1); + CheckError(err, 55); + + DisposeHandle(sqt.soundBuffer); + DisposeHandle((Handle) sqt.soundDesc); + + // storage + + err = AddMovieToStorage(sqt.movie, sqt.dataHandler); + CheckError(err, 56); + + MacQTCloseVideoComponent(sqt.vci); + + err = CloseMovieStorage(sqt.dataHandler); + CheckError(err, 57); + + DisposeHandle(sqt.dataRef); + DisposeMovie(sqt.movie); +} diff --git a/macosx/mac-quicktime.h b/macosx/mac-quicktime.h new file mode 100644 index 00000000..e1c14d50 --- /dev/null +++ b/macosx/mac-quicktime.h @@ -0,0 +1,199 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_quicktime_h_ +#define _mac_quicktime_h_ + +void MacQTStartRecording (char *); +void MacQTStopRecording (void); +void MacQTRecordFrame (int, int); +void MacQTVideoConfig (WindowRef); + +#endif diff --git a/macosx/mac-render.cpp b/macosx/mac-render.cpp new file mode 100644 index 00000000..5f3b5125 --- /dev/null +++ b/macosx/mac-render.cpp @@ -0,0 +1,2681 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "apu.h" +#include "display.h" +#include "blit.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "mac-prefix.h" +#include "mac-cheatfinder.h" +#include "mac-coreimage.h" +#include "mac-os.h" +#include "mac-quicktime.h" +#include "mac-screenshot.h" +#include "mac-render.h" + +static OSStatus BlitMPGLTask (void *); +static OSStatus PrepareMPBlitGL (void); +static void S9xInitFullScreen (void); +static void S9xDeinitFullScreen (void); +static void S9xInitWindowMode (void); +static void S9xDeinitWindowMode (void); +static void S9xInitOpenGLFullScreen (void); +static void S9xDeinitOpenGLFullScreen (void); +static void S9xInitOpenGLWindowMode (void); +static void S9xDeinitOpenGLWindowMode (void); +static void S9xInitBlitGL (void); +static void S9xDeinitBlitGL (void); +static void S9xInitOpenGLContext (void); +static void S9xDeinitOpenGLContext (void); +static void S9xInitCoreImage (void); +static void S9xDeinitCoreImage (void); +static void S9xPutImageOpenGL (int, int); +static void S9xPutImageBlitGL (int, int); +static void S9xPutImageCoreImage (int, int); +static void S9xPutImageOverscanOpenGL (int, int); +static void S9xPutImageOverscanBlitGL (int, int); +static void S9xPutImageOverscanCoreImage (int, int); +static void S9xPutImageBlitGL2 (int, int); +static void S9xPutImageBlitGL2CoreImage (int, int); +static void GLMakeScreenMesh (GLfloat *, int, int); +static void GLMakeTextureMesh (GLfloat *, int, int, float, float); + +#define BYTES_PER_PIXEL 2 + +#define kMarginDouble ((kMacWindowHeight - (SNES_HEIGHT << 1)) >> 1) +#define kMarginDoubleExt ((kMacWindowHeight - (SNES_HEIGHT_EXTENDED << 1)) >> 1) + +enum +{ + kMPBlitFrame = 1, + kMPBlitDone, + kMPBlitNone +}; + +enum +{ + kGL256256 = 0, + kGL512256, + kGL512512, + kGLBlit2x, + kGLBlit3x, + kGLBlit4x, + kGLNTS256, + kGLNTS512, + kGLNumTextures +}; + +enum +{ + kSC2xNormal = 0, + kSC2xExtend, + kSC2xNHiRes, + kSC2xEHiRes, + kSC3xNormal, + kSC3xExtend, + kSC3xNHiRes, + kSC3xEHiRes, + kSCNTNormal, + kSCNTExtend, + kSCNumTextures +}; + +enum +{ + kSCMeshX = 10, + kSCMeshY = 9 +}; + +typedef void (* Blitter) (uint8 *, int, uint8 *, int, int, int); + +typedef struct +{ + Blitter blitFn; + int nx; + int srcWidth; + int srcHeight; + int srcRowBytes; + int copyWidth; + int copyHeight; + uint16 *gfxBuffer; +} MPData; + +typedef struct +{ + GLint internal_format; + GLint format; + GLint type; + GLenum target; + GLuint textures[kGLNumTextures]; + GLfloat vertex[kGLNumTextures][8]; + GLint texW[kGLNumTextures]; + GLint texH[kGLNumTextures]; + GLboolean rangeExt; +} OpenGLData; + +static uint16 *gfxScreen[2], + *snesScreenA, + *snesScreenB; +static uint8 *blitGLBuffer; + +static CGDirectDisplayID gGameDisplayID; + +static MPTaskID taskID = NULL; +static MPQueueID notificationQueue = NULL, + taskQueue = NULL; +static MPSemaphoreID readySemaphore = NULL; +static MPData *mpDataBuffer = NULL; + +static OpenGLData OpenGL; +static CGLContextObj glContext; +static AGLContext agContext; +static CGLPixelFormatObj cglpix; +static AGLPixelFormat aglpix; +static GLint glSwapInterval = 0; +static GLint agSwapInterval = 0; +#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT +static CFDictionaryRef oldDisplayMode; +#else +static CGDisplayModeRef oldDisplayModeRef; +#endif +static CGImageRef cgGameImage = NULL, + cgBlitImage = NULL; + +static int whichBuf = 0; +static int textureNum = 0; +static int prevBlitWidth, prevBlitHeight; +static int imageWidth[2], imageHeight[2]; +static int nx = 2; + +static GLfloat *scTexArray[kSCNumTextures]; +static GLfloat *scScnArray; + +static struct timeval bencht1, bencht2; + +static const int ntsc_width = SNES_NTSC_OUT_WIDTH(SNES_WIDTH); // 602 + + +void InitGraphics (void) +{ + int safebuffersize = 520 * 520 * BYTES_PER_PIXEL - 512 * 512 * BYTES_PER_PIXEL; + + GFX.Pitch = 512 * BYTES_PER_PIXEL; + + snesScreenA = (uint16 *) calloc( 520 * 520 * BYTES_PER_PIXEL, 1); + snesScreenB = (uint16 *) calloc( 520 * 520 * BYTES_PER_PIXEL, 1); + blitGLBuffer = (uint8 *) calloc(1024 * 1024 * BYTES_PER_PIXEL, 1); + + gfxScreen[0] = snesScreenA + (safebuffersize >> 2); + gfxScreen[1] = snesScreenB + (safebuffersize >> 2); + + GFX.Screen = gfxScreen[0]; + + if (!snesScreenA || !snesScreenB || !blitGLBuffer) + QuitWithFatalError(0, "render 01"); + +#ifdef GFX_MULTI_FORMAT + S9xSetRenderPixelFormat(RGB555); + printf("GFX_MULTI_FORMAT is #defined.\n"); +#endif + + if (!S9xBlitFilterInit() | + !S9xBlit2xSaIFilterInit() | + !S9xBlitHQ2xFilterInit() | + !S9xBlitNTSCFilterInit()) + QuitWithFatalError(0, "render 02"); + + switch (videoMode) + { + default: + case VIDEOMODE_NTSC_C: + case VIDEOMODE_NTSC_TV_C: + S9xBlitNTSCFilterSet(&snes_ntsc_composite); + break; + + case VIDEOMODE_NTSC_S: + case VIDEOMODE_NTSC_TV_S: + S9xBlitNTSCFilterSet(&snes_ntsc_svideo); + break; + + case VIDEOMODE_NTSC_R: + case VIDEOMODE_NTSC_TV_R: + S9xBlitNTSCFilterSet(&snes_ntsc_rgb); + break; + + case VIDEOMODE_NTSC_M: + case VIDEOMODE_NTSC_TV_M: + S9xBlitNTSCFilterSet(&snes_ntsc_monochrome); + break; + } +} + +void DeinitGraphics (void) +{ + S9xBlitNTSCFilterDeinit(); + S9xBlitHQ2xFilterDeinit(); + S9xBlit2xSaIFilterDeinit(); + S9xBlitFilterDeinit(); + + if (snesScreenA) + { + free(snesScreenA); + snesScreenA = NULL; + } + + if (snesScreenB) + { + free(snesScreenB); + snesScreenB = NULL; + } + + if (blitGLBuffer) + { + free(blitGLBuffer); + blitGLBuffer = NULL; + } +} + +static OSStatus BlitMPGLTask (void *parameter) +{ + OSStatus err = noErr; + int32 theCommand, param1, param2; + + printf("MP: Entered BlitGL thread.\n"); + + for (;;) + { + err = MPWaitOnQueue(taskQueue, (void **) &theCommand, (void **) ¶m1, (void **) ¶m2, kDurationForever); + if (err) + break; + + if (theCommand == kMPBlitFrame) + { + switch (mpDataBuffer->nx) + { + case -1: + (mpDataBuffer->blitFn) ((uint8 *) mpDataBuffer->gfxBuffer, mpDataBuffer->srcRowBytes, blitGLBuffer, 1024 * 2, mpDataBuffer->srcWidth, mpDataBuffer->srcHeight); + break; + + case -2: + if (mpDataBuffer->srcHeight > SNES_HEIGHT_EXTENDED) + (mpDataBuffer->blitFn) ((uint8 *) mpDataBuffer->gfxBuffer, mpDataBuffer->srcRowBytes, blitGLBuffer, 1024 * 2, mpDataBuffer->srcWidth, mpDataBuffer->srcHeight); + else + { + uint8 *tmpBuffer = blitGLBuffer + (1024 * 512 * BYTES_PER_PIXEL); + int aligned = ((ntsc_width + 2) >> 1) << 1; + (mpDataBuffer->blitFn) ((uint8 *) mpDataBuffer->gfxBuffer, mpDataBuffer->srcRowBytes, tmpBuffer, 1024 * 2, mpDataBuffer->srcWidth, mpDataBuffer->srcHeight); + S9xBlitPixHiResMixedTV16(tmpBuffer, 1024 * 2, blitGLBuffer, 1024 * 2, aligned, mpDataBuffer->copyHeight); + mpDataBuffer->copyHeight *= 2; + } + + break; + + default: + int dstbytes = (OpenGL.rangeExt ? mpDataBuffer->copyWidth : ((mpDataBuffer->copyWidth > 512) ? 1024 : 512)) * 2; + (mpDataBuffer->blitFn) ((uint8 *) mpDataBuffer->gfxBuffer, mpDataBuffer->srcRowBytes, blitGLBuffer, dstbytes, mpDataBuffer->srcWidth, mpDataBuffer->srcHeight); + break; + } + + if (!ciFilterEnable) + S9xPutImageBlitGL2(mpDataBuffer->copyWidth, mpDataBuffer->copyHeight); + else + S9xPutImageBlitGL2CoreImage(mpDataBuffer->copyWidth, mpDataBuffer->copyHeight); + MPSignalSemaphore(readySemaphore); + } + else + if (theCommand == kMPBlitNone) + MPSignalSemaphore(readySemaphore); + else + if (theCommand == kMPBlitDone) + break; + else + { + err = userCanceledErr; + break; + } + } + + MPFree(mpDataBuffer); + MPDeleteSemaphore(readySemaphore); + MPDeleteQueue(taskQueue); + mpDataBuffer = NULL; + readySemaphore = NULL; + taskQueue = NULL; + + printf("MP: Exited BlitGL thread.\n"); + + return (err); +} + +static OSStatus PrepareMPBlitGL (void) +{ + OSStatus err; + + mpDataBuffer = (MPData *) MPAllocateAligned(sizeof(MPData), kMPAllocateDefaultAligned, kMPAllocateClearMask); + if (!mpDataBuffer) + return (memFullErr); + + err = MPCreateQueue(¬ificationQueue); + if (err == noErr) + { + err = MPCreateQueue(&taskQueue); + if (err == noErr) + { + err = MPCreateBinarySemaphore(&readySemaphore); + if (err == noErr) + { + MPSignalSemaphore(readySemaphore); + err = MPCreateTask(BlitMPGLTask, NULL, 0, notificationQueue, NULL, NULL, 0, &taskID); + } + } + } + + return (err); +} + +void DrawPauseScreen (CGContextRef ctx, HIRect bounds) +{ + CGImageRef image; + CGRect crt; + int top, bottom, left, right, width, height; + + width = IPPU.RenderedScreenWidth; + height = IPPU.RenderedScreenHeight; + + if ((width == 0) || (height == 0)) + return; + + top = left = 0; + + if (width > 256) + { + right = width; + + if (height > 256) + { + bottom = height; + + if (!drawoverscan) + { + if (height < (SNES_HEIGHT_EXTENDED << 1)) + { + top = kMarginDouble; + bottom += kMarginDouble; + } + else + { + top = kMarginDoubleExt; + bottom += kMarginDoubleExt; + } + } + } + else + { + bottom = height << 1; + + if (!drawoverscan) + { + if (height < SNES_HEIGHT_EXTENDED) + { + top = kMarginDouble; + bottom += kMarginDouble; + } + else + { + top = kMarginDoubleExt; + bottom += kMarginDoubleExt; + } + } + } + } + else + { + right = width << 1; + bottom = height << 1; + + if (!drawoverscan) + { + if (height < SNES_HEIGHT_EXTENDED) + { + top = kMarginDouble; + bottom += kMarginDouble; + } + else + { + top = kMarginDoubleExt; + bottom += kMarginDoubleExt; + } + } + } + + image = CreateGameScreenCGImage(); + if (image) + { + float rx, ry; + int ofs; + + rx = bounds.size.width / 512.0f; + + if (!drawoverscan) + { + if (windowExtend) + { + ofs = top; + ry = bounds.size.height / (float) kMacWindowHeight; + } + else + { + ofs = 0; + ry = bounds.size.height / (float) ((height <= 256) ? (height << 1) : height); + } + } + else + { + ofs = kMacWindowHeight - ((height <= 256) ? (height << 1) : height); + ry = bounds.size.height / (float) kMacWindowHeight; + } + + CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); + CGContextFillRect(ctx, bounds); + + crt = CGRectMake(0, 0, right - left, bottom - top); + crt.size.width *= rx; + crt.size.height *= ry; + crt.origin.x = (float) (int) (rx * (float) left); + crt.origin.y = (float) (int) (ry * (float) ofs); + CGContextDrawImage(ctx, crt, image); + + CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 0.5f); + CGContextFillRect(ctx, bounds); + + CGImageRelease(image); + } +} + +void DrawFreezeDefrostScreen (uint8 *draw) +{ + const int w = SNES_WIDTH << 1, h = kMacWindowHeight; + + imageWidth[0] = imageHeight[0] = 0; + imageWidth[1] = imageHeight[1] = 0; + prevBlitWidth = prevBlitHeight = 0; + + if ((drawingMethod == kDrawingBlitGL) && multiprocessor) + { + MPWaitOnSemaphore(readySemaphore, kDurationForever); + printf("MP: Send dummy signal.\n"); + MPNotifyQueue(taskQueue, (void *) kMPBlitNone, 0, 0); + } + + if (nx < 0 && !ciFilterEnable) + { + for (int y = 0; y < h; y++) + memcpy(blitGLBuffer + y * 1024 * 2, draw + y * w * 2, w * 2); + } + else + memcpy(blitGLBuffer, draw, w * h * 2); + + if (!ciFilterEnable) + S9xPutImageBlitGL2(512, kMacWindowHeight); + else + S9xPutImageBlitGL2CoreImage(512, kMacWindowHeight); +} + +void ClearGFXScreen (void) +{ + uint16 *p, *q; + + p = gfxScreen[0]; + q = gfxScreen[1]; + + for (int x = 0; x < 512; x++) + for (int y = 0; y < 512; y++) + *p++ = *q++ = 0; + + S9xBlitClearDelta(); + memset(blitGLBuffer, 0, 1024 * 1024 * BYTES_PER_PIXEL); + + imageWidth[0] = imageHeight[0] = 0; + imageWidth[1] = imageHeight[1] = 0; + prevBlitWidth = prevBlitHeight = 0; + + if (fullscreen) + { + CGLSetCurrentContext(glContext); + glViewport(0, 0, glScreenW, glScreenH); + } + else + { + aglSetCurrentContext(agContext); + aglUpdateContext(agContext); + glViewport(0, 0, (GLsizei) gWindowRect.size.width, (GLsizei) gWindowRect.size.height); + } + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + for (int i = 0; i < 2; i++) + { + glClear(GL_COLOR_BUFFER_BIT); + + if (fullscreen) + CGLFlushDrawable(glContext); + else + aglSwapBuffers(agContext); + } +} + +static void S9xInitFullScreen (void) +{ + DeinitGameWindow(); + + size_t width, height; + + width = autoRes ? 640 : CGDisplayPixelsWide(gGameDisplayID); + height = autoRes ? 480 : CGDisplayPixelsHigh(gGameDisplayID); + +#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT + CFDictionaryRef mode; + boolean_t exactMatch; + size_t depth = gl32bit ? 32 : 16; + + oldDisplayMode = CGDisplayCurrentMode(gGameDisplayID); + + mode = CGDisplayBestModeForParameters(gGameDisplayID, depth, width, height, &exactMatch); + + CGDisplayCapture(gGameDisplayID); + CGDisplaySwitchToMode(gGameDisplayID, mode); +#else + oldDisplayModeRef = CGDisplayCopyDisplayMode(gGameDisplayID); + + CGDisplayCapture(gGameDisplayID); + + if (autoRes || !gl32bit) + { + CGError err; + CGDisplayModeRef mode; + CFArrayRef array; + CFStringRef pixenc, pix; + CFIndex n, i; + size_t w, h; + bool r; + + pixenc = gl32bit ? CFSTR(IO32BitDirectPixels) : CFSTR(IO16BitDirectPixels); + + array = CGDisplayCopyAllDisplayModes(gGameDisplayID, NULL); + n = CFArrayGetCount(array); + + for (i = 0; i < n; i++) + { + mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(array, i); + + w = CGDisplayModeGetWidth(mode); + h = CGDisplayModeGetHeight(mode); + pix = CGDisplayModeCopyPixelEncoding(mode); + r = CFStringCompare(pix, pixenc, 0) == kCFCompareEqualTo; + CFRelease(pix); + + if (w == width && h == height && r) + break; + } + + if (i < n) + err = CGDisplaySetDisplayMode(gGameDisplayID, mode, NULL); + + CFRelease(array); + } +#endif + + CGDisplayErr cgErr; + CGDisplayCount numDisplays, maxDisplays = 32; + CGDirectDisplayID activeDisplays[32]; + + cgErr = CGGetActiveDisplayList(maxDisplays, activeDisplays, &numDisplays); + if (cgErr == noErr) + { + if ((macControllerOption == SNES_MOUSE) || (macControllerOption == SNES_MOUSE_SWAPPED) || (numDisplays == 1)) + CGDisplayHideCursor(gGameDisplayID); + + if ((macControllerOption == SNES_MOUSE) || (macControllerOption == SNES_MOUSE_SWAPPED)) + { + CGDisplayMoveCursorToPoint(gGameDisplayID, CGPointMake((float) (width >> 1), (float) (height >> 1))); + CGAssociateMouseAndMouseCursorPosition(false); + } + } +} + +static void S9xDeinitFullScreen (void) +{ + CGAssociateMouseAndMouseCursorPosition(true); + CGDisplayShowCursor(gGameDisplayID); + +#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT + CGDisplaySwitchToMode(gGameDisplayID, oldDisplayMode); +#else + CGError err; + + err = CGDisplaySetDisplayMode(gGameDisplayID, oldDisplayModeRef, NULL); + CGDisplayModeRelease(oldDisplayModeRef); +#endif + + CGDisplayRelease(gGameDisplayID); +} + +static void S9xInitWindowMode (void) +{ + Rect rct; + size_t width, height; + + width = CGDisplayPixelsWide(gGameDisplayID); + height = CGDisplayPixelsHigh(gGameDisplayID); + +#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT + CFDictionaryRef mode; + boolean_t exactMatch; + size_t depth = gl32bit ? 32 : 16; + + oldDisplayMode = CGDisplayCurrentMode(gGameDisplayID); + + mode = CGDisplayBestModeForParameters(gGameDisplayID, depth, width, height, &exactMatch); + + CGDisplaySwitchToMode(gGameDisplayID, mode); +#else + oldDisplayModeRef = CGDisplayCopyDisplayMode(gGameDisplayID); + + if (autoRes || !gl32bit) + { + CGError err; + CGDisplayModeRef mode; + CFArrayRef array; + CFStringRef pixenc, pix; + CFIndex n, i; + size_t w, h; + bool r; + + pixenc = gl32bit ? CFSTR(IO32BitDirectPixels) : CFSTR(IO16BitDirectPixels); + + array = CGDisplayCopyAllDisplayModes(gGameDisplayID, NULL); + n = CFArrayGetCount(array); + + for (i = 0; i < n; i++) + { + mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(array, i); + + w = CGDisplayModeGetWidth(mode); + h = CGDisplayModeGetHeight(mode); + pix = CGDisplayModeCopyPixelEncoding(mode); + r = CFStringCompare(pix, pixenc, 0) == kCFCompareEqualTo; + CFRelease(pix); + + if (w == width && h == height && r) + break; + } + + if (i < n) + err = CGDisplaySetDisplayMode(gGameDisplayID, mode, NULL); + + CFRelease(array); + } +#endif + + InitGameWindow(); + ShowWindow(gWindow); + + GetWindowBounds(gWindow, kWindowContentRgn, &rct); + gWindowRect = CGRectMake((float) rct.left, (float) rct.top, (float) (rct.right - rct.left), (float) (rct.bottom - rct.top)); + + UpdateGameWindow(); +} + +static void S9xDeinitWindowMode (void) +{ +#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT + CGDisplaySwitchToMode(gGameDisplayID, oldDisplayMode); +#else + CGError err; + + err = CGDisplaySetDisplayMode(gGameDisplayID, oldDisplayModeRef, NULL); + CGDisplayModeRelease(oldDisplayModeRef); +#endif + + UpdateGameWindow(); +} + +static void S9xInitOpenGLFullScreen (void) +{ + CGOpenGLDisplayMask displayMask; + GLint numPixelFormats; + + displayMask = CGDisplayIDToOpenGLDisplayMask(gGameDisplayID); + CGLPixelFormatAttribute attribs[] = { (CGLPixelFormatAttribute) kCGLPFAFullScreen, + (CGLPixelFormatAttribute) kCGLPFADoubleBuffer, + (CGLPixelFormatAttribute) kCGLPFAAccelerated, + (CGLPixelFormatAttribute) kCGLPFANoRecovery, + (CGLPixelFormatAttribute) kCGLPFAColorSize, + (CGLPixelFormatAttribute) (gl32bit ? 32 : 16), + (CGLPixelFormatAttribute) kCGLPFADisplayMask, + (CGLPixelFormatAttribute) displayMask, + (CGLPixelFormatAttribute) 0 }; + + CGLChoosePixelFormat(attribs, &cglpix, &numPixelFormats); + CGLCreateContext(cglpix, NULL, &glContext); + glSwapInterval = vsync ? 1 : 0; + if (extraOptions.benchmark) + glSwapInterval = 0; + CGLSetParameter(glContext, kCGLCPSwapInterval, &glSwapInterval); + CGLSetCurrentContext(glContext); + +#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT + CGLSetFullScreen(glContext); +#else + CGLSetFullScreenOnDisplay(glContext, CGDisplayIDToOpenGLDisplayMask(gGameDisplayID)); +#endif + + glScreenW = CGDisplayPixelsWide(gGameDisplayID); + glScreenH = CGDisplayPixelsHigh(gGameDisplayID); +} + +static void S9xDeinitOpenGLFullScreen (void) +{ + if (glContext) + { + CGLSetCurrentContext(NULL); + CGLClearDrawable(glContext); + CGLDestroyContext(glContext); + CGLDestroyPixelFormat(cglpix); + } +} + +static void S9xInitOpenGLWindowMode (void) +{ + GLint attribs[] = { AGL_RGBA, + AGL_DOUBLEBUFFER, + AGL_ACCELERATED, + AGL_NO_RECOVERY, + AGL_PIXEL_SIZE, gl32bit ? 32 : 16, + AGL_NONE }; + + aglpix = aglChoosePixelFormat(NULL, 0, attribs); + agContext = aglCreateContext(aglpix, NULL); + + if (systemVersion >= 0x1050) + aglSetWindowRef(agContext, gWindow); +#ifdef MAC_TIGER_PANTHER_SUPPORT + else + aglSetDrawable(agContext, GetWindowPort(gWindow)); +#endif + + agSwapInterval = vsync ? 1 : 0; + if (extraOptions.benchmark) + agSwapInterval = 0; + aglSetInteger(agContext, AGL_SWAP_INTERVAL, &agSwapInterval); + aglSetCurrentContext(agContext); + + if (systemVersion >= 0x1040) + { + aglGetCGLPixelFormat(aglpix, (void **) &cglpix); + aglGetCGLContext(agContext, (void **) &glContext); + } +} + +static void S9xDeinitOpenGLWindowMode (void) +{ + if (agContext) + { + if (systemVersion >= 0x1050) + aglSetWindowRef(agContext, NULL); + #ifdef MAC_TIGER_PANTHER_SUPPORT + else + aglSetDrawable(agContext, NULL); + #endif + + aglSetCurrentContext(NULL); + aglDestroyContext(agContext); + aglDestroyPixelFormat(aglpix); + } +} + +static void S9xInitBlitGL (void) +{ + if (multiprocessor) + { + printf("MP: Creating BlitGL thread.\n"); + + if (noErr != PrepareMPBlitGL()) + multiprocessor = false; + } +} + +static void S9xDeinitBlitGL (void) +{ + if (multiprocessor) + { + MPNotifyQueue(taskQueue, (void *) kMPBlitDone, 0, 0); + MPWaitOnQueue(notificationQueue, NULL, NULL, NULL, kDurationForever); + MPDeleteQueue(notificationQueue); + notificationQueue = NULL; + + printf("MP: Successfully received terminate signal from BlitGL thread.\n"); + } +} + +static void S9xInitOpenGLContext (void) +{ + OpenGL.internal_format = GL_RGB5_A1; + OpenGL.format = GL_BGRA; + OpenGL.type = GL_UNSIGNED_SHORT_1_5_5_5_REV; + OpenGL.rangeExt = gluCheckExtension((const GLubyte *) "GL_APPLE_texture_range", glGetString(GL_EXTENSIONS)); + OpenGL.target = OpenGL.rangeExt ? GL_TEXTURE_RECTANGLE_EXT : GL_TEXTURE_2D; + + GLint storage_hint = GL_STORAGE_SHARED_APPLE; + GLint storage_apple = 1; + GLfloat agp_texturing = 0.0f; + + storage_apple = extraOptions.glUseClientStrageApple ? 1 : 0; + + agp_texturing = extraOptions.glUseTexturePriority ? 0.0f : 1.0f; + + switch (extraOptions.glStorageHint) + { + case 1: storage_hint = GL_STORAGE_PRIVATE_APPLE; break; + case 2: storage_hint = GL_STORAGE_CACHED_APPLE; break; + case 3: storage_hint = GL_STORAGE_SHARED_APPLE; break; + } + + if (screencurvature || videoMode >= VIDEOMODE_NTSC_C || extraOptions.glForceNoTextureRectangle) + { + OpenGL.rangeExt = false; + OpenGL.target = GL_TEXTURE_2D; + } + + printf("TextureRange: %s\n", OpenGL.rangeExt ? "enable" : "disable"); + + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glEnable(GL_CULL_FACE); + glPolygonMode(GL_FRONT, GL_FILL); + glCullFace(GL_BACK); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_RECTANGLE_EXT); + glEnable(OpenGL.target); + + glGenTextures(kGLNumTextures, OpenGL.textures); + + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, storage_apple); + glPixelStorei(GL_UNPACK_ALIGNMENT, 8); + + // 256 * 224/239 + + OpenGL.texW[kGL256256] = 256; + OpenGL.texH[kGL256256] = OpenGL.rangeExt ? SNES_HEIGHT_EXTENDED : 256; + + if (OpenGL.rangeExt) + { + OpenGL.vertex[kGL256256][0] = 0; OpenGL.vertex[kGL256256][1] = 0; + OpenGL.vertex[kGL256256][2] = OpenGL.texW[kGL256256]; OpenGL.vertex[kGL256256][3] = 0; + OpenGL.vertex[kGL256256][4] = OpenGL.texW[kGL256256]; OpenGL.vertex[kGL256256][5] = OpenGL.texH[kGL256256]; + OpenGL.vertex[kGL256256][6] = 0; OpenGL.vertex[kGL256256][7] = OpenGL.texH[kGL256256]; + } + else + { + OpenGL.vertex[kGL256256][0] = 0.0f; OpenGL.vertex[kGL256256][1] = 0.0f; + OpenGL.vertex[kGL256256][2] = 1.0f; OpenGL.vertex[kGL256256][3] = 0.0f; + OpenGL.vertex[kGL256256][4] = 1.0f; OpenGL.vertex[kGL256256][5] = 1.0f; + OpenGL.vertex[kGL256256][6] = 0.0f; OpenGL.vertex[kGL256256][7] = 1.0f; + } + + glBindTexture(OpenGL.target, OpenGL.textures[kGL256256]); + + if (OpenGL.rangeExt) + { + glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGL256256] * OpenGL.texH[kGL256256] * BYTES_PER_PIXEL, GFX.Screen); + glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); + } + + glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); + glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGL256256], OpenGL.texH[kGL256256], 0, OpenGL.format, OpenGL.type, GFX.Screen); + + // 512 * 224/239 + + OpenGL.texW[kGL512256] = 512; + OpenGL.texH[kGL512256] = OpenGL.rangeExt ? SNES_HEIGHT_EXTENDED : 256; + + if (OpenGL.rangeExt) + { + OpenGL.vertex[kGL512256][0] = 0; OpenGL.vertex[kGL512256][1] = 0; + OpenGL.vertex[kGL512256][2] = OpenGL.texW[kGL512256]; OpenGL.vertex[kGL512256][3] = 0; + OpenGL.vertex[kGL512256][4] = OpenGL.texW[kGL512256]; OpenGL.vertex[kGL512256][5] = OpenGL.texH[kGL512256]; + OpenGL.vertex[kGL512256][6] = 0; OpenGL.vertex[kGL512256][7] = OpenGL.texH[kGL512256]; + } + else + { + OpenGL.vertex[kGL512256][0] = 0.0f; OpenGL.vertex[kGL512256][1] = 0.0f; + OpenGL.vertex[kGL512256][2] = 1.0f; OpenGL.vertex[kGL512256][3] = 0.0f; + OpenGL.vertex[kGL512256][4] = 1.0f; OpenGL.vertex[kGL512256][5] = 1.0f; + OpenGL.vertex[kGL512256][6] = 0.0f; OpenGL.vertex[kGL512256][7] = 1.0f; + } + + glBindTexture(OpenGL.target, OpenGL.textures[kGL512256]); + + if (OpenGL.rangeExt) + { + glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGL512256] * OpenGL.texH[kGL512256] * BYTES_PER_PIXEL, GFX.Screen); + glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); + } + + glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); + glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGL512256], OpenGL.texH[kGL512256], 0, OpenGL.format, OpenGL.type, GFX.Screen); + + // 512 * 448/478 + + OpenGL.texW[kGL512512] = 512; + OpenGL.texH[kGL512512] = OpenGL.rangeExt ? (SNES_HEIGHT_EXTENDED << 1) : 512; + + if (OpenGL.rangeExt) + { + OpenGL.vertex[kGL512512][0] = 0; OpenGL.vertex[kGL512512][1] = 0; + OpenGL.vertex[kGL512512][2] = OpenGL.texW[kGL512512]; OpenGL.vertex[kGL512512][3] = 0; + OpenGL.vertex[kGL512512][4] = OpenGL.texW[kGL512512]; OpenGL.vertex[kGL512512][5] = OpenGL.texH[kGL512512]; + OpenGL.vertex[kGL512512][6] = 0; OpenGL.vertex[kGL512512][7] = OpenGL.texH[kGL512512]; + } + else + { + OpenGL.vertex[kGL512512][0] = 0.0f; OpenGL.vertex[kGL512512][1] = 0.0f; + OpenGL.vertex[kGL512512][2] = 1.0f; OpenGL.vertex[kGL512512][3] = 0.0f; + OpenGL.vertex[kGL512512][4] = 1.0f; OpenGL.vertex[kGL512512][5] = 1.0f; + OpenGL.vertex[kGL512512][6] = 0.0f; OpenGL.vertex[kGL512512][7] = 1.0f; + } + + glBindTexture(OpenGL.target, OpenGL.textures[kGL512512]); + + if (OpenGL.rangeExt) + { + glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGL512512] * OpenGL.texH[kGL512512] * BYTES_PER_PIXEL, GFX.Screen); + glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); + } + + glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); + glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, videoMode == VIDEOMODE_SMOOTH ? GL_LINEAR : GL_NEAREST); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGL512512], OpenGL.texH[kGL512512], 0, OpenGL.format, OpenGL.type, GFX.Screen); + + // Blit 2x + + OpenGL.texW[kGLBlit2x] = 512; + OpenGL.texH[kGLBlit2x] = OpenGL.rangeExt ? (SNES_HEIGHT_EXTENDED * 2) : 512; + + if (OpenGL.rangeExt) + { + OpenGL.vertex[kGLBlit2x][0] = 0; OpenGL.vertex[kGLBlit2x][1] = 0; + OpenGL.vertex[kGLBlit2x][2] = OpenGL.texW[kGLBlit2x]; OpenGL.vertex[kGLBlit2x][3] = 0; + OpenGL.vertex[kGLBlit2x][4] = OpenGL.texW[kGLBlit2x]; OpenGL.vertex[kGLBlit2x][5] = OpenGL.texH[kGLBlit2x]; + OpenGL.vertex[kGLBlit2x][6] = 0; OpenGL.vertex[kGLBlit2x][7] = OpenGL.texH[kGLBlit2x]; + } + else + { + OpenGL.vertex[kGLBlit2x][0] = 0.0f; OpenGL.vertex[kGLBlit2x][1] = 0.0f; + OpenGL.vertex[kGLBlit2x][2] = 1.0f; OpenGL.vertex[kGLBlit2x][3] = 0.0f; + OpenGL.vertex[kGLBlit2x][4] = 1.0f; OpenGL.vertex[kGLBlit2x][5] = 1.0f; + OpenGL.vertex[kGLBlit2x][6] = 0.0f; OpenGL.vertex[kGLBlit2x][7] = 1.0f; + } + + glBindTexture(OpenGL.target, OpenGL.textures[kGLBlit2x]); + + if (OpenGL.rangeExt) + { + glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGLBlit2x] * OpenGL.texH[kGLBlit2x] * BYTES_PER_PIXEL, blitGLBuffer); + glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); + } + + glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGLBlit2x], OpenGL.texH[kGLBlit2x], 0, OpenGL.format, OpenGL.type, blitGLBuffer); + + // Blit 3x + + OpenGL.texW[kGLBlit3x] = OpenGL.rangeExt ? (SNES_WIDTH * 3) : 1024; + OpenGL.texH[kGLBlit3x] = OpenGL.rangeExt ? (SNES_HEIGHT_EXTENDED * 3) : 1024; + + if (OpenGL.rangeExt) + { + OpenGL.vertex[kGLBlit3x][0] = 0; OpenGL.vertex[kGLBlit3x][1] = 0; + OpenGL.vertex[kGLBlit3x][2] = OpenGL.texW[kGLBlit3x]; OpenGL.vertex[kGLBlit3x][3] = 0; + OpenGL.vertex[kGLBlit3x][4] = OpenGL.texW[kGLBlit3x]; OpenGL.vertex[kGLBlit3x][5] = OpenGL.texH[kGLBlit3x]; + OpenGL.vertex[kGLBlit3x][6] = 0; OpenGL.vertex[kGLBlit3x][7] = OpenGL.texH[kGLBlit3x]; + } + else + { + OpenGL.vertex[kGLBlit3x][0] = 0.0f; OpenGL.vertex[kGLBlit3x][1] = 0.0f; + OpenGL.vertex[kGLBlit3x][2] = SNES_WIDTH * 3 / 1024.0f; OpenGL.vertex[kGLBlit3x][3] = 0.0f; + OpenGL.vertex[kGLBlit3x][4] = SNES_WIDTH * 3 / 1024.0f; OpenGL.vertex[kGLBlit3x][5] = SNES_HEIGHT_EXTENDED * 3 / 1024.0f; + OpenGL.vertex[kGLBlit3x][6] = 0.0f; OpenGL.vertex[kGLBlit3x][7] = SNES_HEIGHT_EXTENDED * 3 / 1024.0f; + } + + glBindTexture(OpenGL.target, OpenGL.textures[kGLBlit3x]); + + if (OpenGL.rangeExt) + { + glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGLBlit3x] * OpenGL.texH[kGLBlit3x] * BYTES_PER_PIXEL, blitGLBuffer); + glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); + } + + glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGLBlit3x], OpenGL.texH[kGLBlit3x], 0, OpenGL.format, OpenGL.type, blitGLBuffer); + + // Blit 4x + + OpenGL.texW[kGLBlit4x] = 1024; + OpenGL.texH[kGLBlit4x] = OpenGL.rangeExt ? (SNES_HEIGHT_EXTENDED * 4) : 1024; + + if (OpenGL.rangeExt) + { + OpenGL.vertex[kGLBlit4x][0] = 0; OpenGL.vertex[kGLBlit4x][1] = 0; + OpenGL.vertex[kGLBlit4x][2] = OpenGL.texW[kGLBlit4x]; OpenGL.vertex[kGLBlit4x][3] = 0; + OpenGL.vertex[kGLBlit4x][4] = OpenGL.texW[kGLBlit4x]; OpenGL.vertex[kGLBlit4x][5] = OpenGL.texH[kGLBlit4x]; + OpenGL.vertex[kGLBlit4x][6] = 0; OpenGL.vertex[kGLBlit4x][7] = OpenGL.texH[kGLBlit4x]; + } + else + { + OpenGL.vertex[kGLBlit4x][0] = 0.0f; OpenGL.vertex[kGLBlit4x][1] = 0.0f; + OpenGL.vertex[kGLBlit4x][2] = 1.0f; OpenGL.vertex[kGLBlit4x][3] = 0.0f; + OpenGL.vertex[kGLBlit4x][4] = 1.0f; OpenGL.vertex[kGLBlit4x][5] = 1.0f; + OpenGL.vertex[kGLBlit4x][6] = 0.0f; OpenGL.vertex[kGLBlit4x][7] = 1.0f; + } + + glBindTexture(OpenGL.target, OpenGL.textures[kGLBlit4x]); + + if (OpenGL.rangeExt) + { + glTextureRangeAPPLE(OpenGL.target, OpenGL.texW[kGLBlit4x] * OpenGL.texH[kGLBlit4x] * BYTES_PER_PIXEL, blitGLBuffer); + glTexParameteri(OpenGL.target, GL_TEXTURE_STORAGE_HINT_APPLE, storage_hint); + } + + glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGLBlit4x], OpenGL.texH[kGLBlit4x], 0, OpenGL.format, OpenGL.type, blitGLBuffer); + + // Blit NTSC 602 * 224/239 + + OpenGL.texW[kGLNTS256] = 1024; + OpenGL.texH[kGLNTS256] = 256; + + OpenGL.vertex[kGLNTS256][0] = 0.0f; OpenGL.vertex[kGLNTS256][1] = 0.0f; + OpenGL.vertex[kGLNTS256][2] = 1.0f; OpenGL.vertex[kGLNTS256][3] = 0.0f; + OpenGL.vertex[kGLNTS256][4] = 1.0f; OpenGL.vertex[kGLNTS256][5] = 1.0f; + OpenGL.vertex[kGLNTS256][6] = 0.0f; OpenGL.vertex[kGLNTS256][7] = 1.0f; + + glBindTexture(OpenGL.target, OpenGL.textures[kGLNTS256]); + glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGLNTS256], OpenGL.texH[kGLNTS256], 0, OpenGL.format, OpenGL.type, blitGLBuffer); + + // Blit NTSC 602 * 448/478 + + OpenGL.texW[kGLNTS512] = 1024; + OpenGL.texH[kGLNTS512] = 512; + + OpenGL.vertex[kGLNTS512][0] = 0.0f; OpenGL.vertex[kGLNTS512][1] = 0.0f; + OpenGL.vertex[kGLNTS512][2] = 1.0f; OpenGL.vertex[kGLNTS512][3] = 0.0f; + OpenGL.vertex[kGLNTS512][4] = 1.0f; OpenGL.vertex[kGLNTS512][5] = 1.0f; + OpenGL.vertex[kGLNTS512][6] = 0.0f; OpenGL.vertex[kGLNTS512][7] = 1.0f; + + glBindTexture(OpenGL.target, OpenGL.textures[kGLNTS512]); + glTexParameterf(OpenGL.target, GL_TEXTURE_PRIORITY, agp_texturing); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(OpenGL.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(OpenGL.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glTexImage2D(OpenGL.target, 0, OpenGL.internal_format, OpenGL.texW[kGLNTS512], OpenGL.texH[kGLNTS512], 0, OpenGL.format, OpenGL.type, blitGLBuffer); + + // + + if (!screencurvature) + { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + else + { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -1.0, 1.0, 0.95, 5.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + scTexArray[kSC2xNormal] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; + GLMakeTextureMesh(scTexArray[kSC2xNormal], kSCMeshX, kSCMeshY, 1.0f, 224.0f / 256.0f); + + scTexArray[kSC2xExtend] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; + GLMakeTextureMesh(scTexArray[kSC2xExtend], kSCMeshX, kSCMeshY, 1.0f, 239.0f / 256.0f); + + scTexArray[kSC2xNHiRes] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; + GLMakeTextureMesh(scTexArray[kSC2xNHiRes], kSCMeshX, kSCMeshY, 1.0f, 224.0f / 512.0f); + + scTexArray[kSC2xEHiRes] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; + GLMakeTextureMesh(scTexArray[kSC2xEHiRes], kSCMeshX, kSCMeshY, 1.0f, 239.0f / 512.0f); + + scTexArray[kSC3xNormal] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; + GLMakeTextureMesh(scTexArray[kSC3xNormal], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 672.0f / 1024.0f); + + scTexArray[kSC3xExtend] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; + GLMakeTextureMesh(scTexArray[kSC3xExtend], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 717.0f / 1024.0f); + + scTexArray[kSC3xNHiRes] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; + GLMakeTextureMesh(scTexArray[kSC3xNHiRes], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 672.0f / 2048.0f); + + scTexArray[kSC3xEHiRes] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; + GLMakeTextureMesh(scTexArray[kSC3xEHiRes], kSCMeshX, kSCMeshY, 768.0f / 1024.0f, 717.0f / 2048.0f); + + scTexArray[kSCNTNormal] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; + GLMakeTextureMesh(scTexArray[kSCNTNormal], kSCMeshX, kSCMeshY, (float) ntsc_width / 1024.0f, 224.0f / 256.0f); + + scTexArray[kSCNTExtend] = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 2]; + GLMakeTextureMesh(scTexArray[kSCNTExtend], kSCMeshX, kSCMeshY, (float) ntsc_width / 1024.0f, 239.0f / 256.0f); + + scScnArray = new GLfloat [(kSCMeshX + 1) * 2 * kSCMeshY * 3]; + GLMakeScreenMesh(scScnArray, kSCMeshX, kSCMeshY); + } + + if (fullscreen) + { + CGLSetCurrentContext(glContext); + glViewport(0, 0, glScreenW, glScreenH); + } + else + { + aglSetCurrentContext(agContext); + aglUpdateContext(agContext); + glViewport(0, 0, (GLsizei) gWindowRect.size.width, (GLsizei) gWindowRect.size.height); + } + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + for (int i = 0; i < 2; i++) + { + glClear(GL_COLOR_BUFFER_BIT); + + if (fullscreen) + CGLFlushDrawable(glContext); + else + aglSwapBuffers(agContext); + } +} + +static void S9xDeinitOpenGLContext (void) +{ + if (screencurvature) + { + delete [] scTexArray[kSC2xNormal]; + delete [] scTexArray[kSC2xExtend]; + delete [] scTexArray[kSC2xNHiRes]; + delete [] scTexArray[kSC2xEHiRes]; + delete [] scTexArray[kSC3xNormal]; + delete [] scTexArray[kSC3xExtend]; + delete [] scTexArray[kSC3xNHiRes]; + delete [] scTexArray[kSC3xEHiRes]; + delete [] scTexArray[kSCNTNormal]; + delete [] scTexArray[kSCNTExtend]; + delete [] scScnArray; + + scTexArray[kSC2xNormal] = NULL; + scTexArray[kSC2xExtend] = NULL; + scTexArray[kSC2xNHiRes] = NULL; + scTexArray[kSC2xEHiRes] = NULL; + scTexArray[kSC3xNormal] = NULL; + scTexArray[kSC3xExtend] = NULL; + scTexArray[kSC3xNHiRes] = NULL; + scTexArray[kSC3xEHiRes] = NULL; + scTexArray[kSCNTNormal] = NULL; + scTexArray[kSCNTExtend] = NULL; + scScnArray = NULL; + } + + glDeleteTextures(kGLNumTextures, OpenGL.textures); +} + +static void S9xInitCoreImage (void) +{ + cgGameImage = NULL; + cgBlitImage = NULL; + + InitCoreImageContext(glContext, cglpix); +} + +static void S9xDeinitCoreImage (void) +{ + DeinitCoreImageContext(); + + if (cgGameImage) + { + CGImageRelease(cgGameImage); + cgGameImage = NULL; + } + + if (cgBlitImage) + { + CGImageRelease(cgBlitImage); + cgBlitImage = NULL; + } +} + +void S9xInitDisplay (int argc, char **argv) +{ + if (directDisplay) + return; + + gGameDisplayID = CGMainDisplayID(); + + CGDisplayErr cgErr; + CGDisplayCount numDisplays, maxDisplays = 32; + CGDirectDisplayID activeDisplays[32]; + CGPoint windowAt; + + windowAt = CGPointMake((float) windowPos[kWindowScreen].h, (float) windowPos[kWindowScreen].v); + + cgErr = CGGetDisplaysWithPoint(windowAt, maxDisplays, activeDisplays, &numDisplays); + if ((cgErr == noErr) && (numDisplays > 0)) + { + for (unsigned int i = 0; i < numDisplays; i++) + { + if (activeDisplays[i] != CGMainDisplayID()) + gGameDisplayID = activeDisplays[i]; + } + } + + glScreenBounds = CGDisplayBounds(gGameDisplayID); + + unlimitedCursor = CGPointMake(0.0f, 0.0f); + + imageWidth[0] = imageHeight[0] = 0; + imageWidth[1] = imageHeight[1] = 0; + prevBlitWidth = prevBlitHeight = 0; + GFX.Screen = gfxScreen[0]; + whichBuf = 0; + textureNum = 0; + + switch (videoMode) + { + case VIDEOMODE_HQ4X: + nx = 4; + break; + + case VIDEOMODE_HQ3X: + nx = 3; + break; + + case VIDEOMODE_NTSC_C: + case VIDEOMODE_NTSC_S: + case VIDEOMODE_NTSC_R: + case VIDEOMODE_NTSC_M: + nx = -1; + break; + + case VIDEOMODE_NTSC_TV_C: + case VIDEOMODE_NTSC_TV_S: + case VIDEOMODE_NTSC_TV_R: + case VIDEOMODE_NTSC_TV_M: + nx = -2; + break; + + default: + nx = 2; + break; + } + + if (fullscreen) + { + S9xInitFullScreen(); + S9xInitOpenGLFullScreen(); + } + else + { + S9xInitWindowMode(); + S9xInitOpenGLWindowMode(); + } + + S9xInitOpenGLContext(); + if (ciFilterEnable) + S9xInitCoreImage(); + if (drawingMethod == kDrawingBlitGL) + S9xInitBlitGL(); + + S9xSetSoundMute(false); + Microseconds((UnsignedWide *) &lastFrame); + + windowResizeCount = 1; + + gettimeofday(&bencht1, NULL); + + directDisplay = true; +} + +void S9xDeinitDisplay (void) +{ + if (!directDisplay) + return; + + S9xSetSoundMute(true); + + if (drawingMethod == kDrawingBlitGL) + S9xDeinitBlitGL(); + if (ciFilterEnable) + S9xDeinitCoreImage(); + S9xDeinitOpenGLContext(); + + if (fullscreen) + { + S9xDeinitOpenGLFullScreen(); + S9xDeinitFullScreen(); + } + else + { + S9xDeinitOpenGLWindowMode(); + S9xDeinitWindowMode(); + } + + directDisplay = false; +} + +bool8 S9xInitUpdate (void) +{ + return (true); +} + +bool8 S9xDeinitUpdate (int width, int height) +{ + if (directDisplay) + S9xPutImage(width, height); + + return (true); +} + +bool8 S9xContinueUpdate (int width, int height) +{ + return (true); +} + +void S9xPutImage (int width, int height) +{ + static float fps = 0.0f; + static long count = 0; + static char text[32]; + + if (extraOptions.benchmark) + { + uint16 *basePtr; + long delta; + size_t len; + + count++; + + gettimeofday(&bencht2, NULL); + + delta = 1000000 * (bencht2.tv_sec - bencht1.tv_sec) + (bencht2.tv_usec - bencht1.tv_usec); + if (delta > 1000000) + { + fps = (1000000.0f * (float) count) / (float) delta; + count = 0; + + gettimeofday(&bencht1, NULL); + } + + sprintf(text, "%.1f", fps); + + basePtr = GFX.Screen + 1; + len = strlen(text); + + for (unsigned int i = 0; i < len; i++) + { + S9xDisplayChar(basePtr, text[i]); + basePtr += (8 - 1); + } + } + else + { + if (cfIsWatching) + CheatFinderDrawWatchAddr(); + + if (Settings.DisplayFrameRate) + { + static int drawnFrames[60] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + static int tableIndex = 0; + int frameCalc = 0; + + drawnFrames[tableIndex] = skipFrames; + + if (Settings.TurboMode) + { + drawnFrames[tableIndex] = (drawnFrames[tableIndex] + (macFastForwardRate / 2)) / macFastForwardRate; + if (drawnFrames[tableIndex] == 0) + drawnFrames[tableIndex] = 1; + } + + tableIndex = (tableIndex + 1) % 60; + + for (int i = 0; i < 60; i++) + frameCalc += drawnFrames[i]; + + IPPU.DisplayedRenderedFrameCount = (Memory.ROMFramesPerSecond * 60) / frameCalc; + } + } + + if (!drawoverscan) + { + switch (drawingMethod) + { + case kDrawingOpenGL: + if (!ciFilterEnable) + S9xPutImageOpenGL(width, height); + else + S9xPutImageCoreImage(width, height); + break; + + case kDrawingBlitGL: + S9xPutImageBlitGL(width, height); + } + } + else + { + switch (drawingMethod) + { + case kDrawingOpenGL: + if (!ciFilterEnable) + S9xPutImageOverscanOpenGL(width, height); + else + S9xPutImageOverscanCoreImage(width, height); + break; + + case kDrawingBlitGL: + S9xPutImageOverscanBlitGL(width, height); + } + } +} + +static void S9xPutImageOpenGL (int width, int height) +{ + if ((imageWidth[0] != width) || (imageHeight[0] != height) || (windowResizeCount > 0)) + { + if ((imageWidth[0] != width) || (imageHeight[0] != height)) + windowResizeCount += 2; + + int vh = (height > 256) ? height : (height << 1); + + if (fullscreen) + { + CGLSetCurrentContext(glContext); + + glViewport(0, 0, glScreenW, glScreenH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (glstretch) + { + float fpw = (float) glScreenH / vh * 512.0f; + int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 100.0); + + glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); + } + else + glViewport((glScreenW - 512) >> 1, (glScreenH - vh) >> 1, 512, vh); + } + else + { + int ww = (int) gWindowRect.size.width, + wh = (int) gWindowRect.size.height; + + aglSetCurrentContext(agContext); + aglUpdateContext(agContext); + + glViewport(0, 0, ww, wh); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (windowExtend) + glViewport(0, ((kMacWindowHeight - vh) >> 1) * wh / kMacWindowHeight, ww, vh * wh / kMacWindowHeight); + } + + windowResizeCount--; + + textureNum = (width <= 256) ? kGL256256 : ((height <= 256) ? kGL512256 : kGL512512); + OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = OpenGL.rangeExt ? height : (vh / 512.0f); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, width); + glBindTexture(OpenGL.target, OpenGL.textures[textureNum]); + + imageWidth[0] = width; + imageHeight[0] = height; + } + + glTexSubImage2D(OpenGL.target, 0, 0, 0, OpenGL.texW[textureNum], OpenGL.texH[textureNum], OpenGL.format, OpenGL.type, GFX.Screen); + + if (!screencurvature) + { + glBegin(GL_QUADS); + + glTexCoord2fv(&OpenGL.vertex[textureNum][6]); + glVertex2f(-1.0f, -1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][4]); + glVertex2f( 1.0f, -1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][2]); + glVertex2f( 1.0f, 1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][0]); + glVertex2f(-1.0f, 1.0f); + + glEnd(); + } + else + { + GLfloat *t, *s; + int tex; + + if ((height == SNES_HEIGHT) || (height == (SNES_HEIGHT << 1))) + tex = kSC2xNormal; + else + tex = kSC2xExtend; + + t = scTexArray[tex]; + s = scScnArray; + + for (int i = 0; i < kSCMeshY; i++) + { + glTexCoordPointer(2, GL_FLOAT, 0, t); + glVertexPointer(3, GL_FLOAT, 0, s); + glDrawArrays(GL_TRIANGLE_STRIP, 0, (kSCMeshX + 1) * 2); + + t += (kSCMeshX + 1) * 2 * 2; + s += (kSCMeshX + 1) * 2 * 3; + } + } + + glFinishObjectAPPLE(GL_TEXTURE, OpenGL.textures[textureNum]); + + if (fullscreen) + CGLFlushDrawable(glContext); + else + aglSwapBuffers(agContext); +} + +static void S9xPutImageBlitGL (int width, int height) +{ + Blitter blitFn; + int copyWidth, copyHeight; + + if (videoMode == VIDEOMODE_TV) + if ((width <= 256) && ((imageWidth[whichBuf] != width) || (imageHeight[whichBuf] != height))) + S9xBlitClearDelta(); + + switch (nx) + { + default: + case 2: + if (width <= 256) + { + copyWidth = width * 2; + copyHeight = height * 2; + + switch (videoMode) + { + default: + case VIDEOMODE_TV: blitFn = S9xBlitPixScaledTV16; break; + case VIDEOMODE_SUPEREAGLE: blitFn = S9xBlitPixSuperEagle16; break; + case VIDEOMODE_2XSAI: blitFn = S9xBlitPix2xSaI16; break; + case VIDEOMODE_SUPER2XSAI: blitFn = S9xBlitPixSuper2xSaI16; break; + case VIDEOMODE_EPX: blitFn = S9xBlitPixEPX16; break; + case VIDEOMODE_HQ2X: blitFn = S9xBlitPixHQ2x16; break; + } + } + else + if ((videoMode == VIDEOMODE_TV) && (height <= 256)) + { + copyWidth = width; + copyHeight = height * 2; + blitFn = S9xBlitPixHiResTV16; + } + else + { + copyWidth = width; + copyHeight = height; + blitFn = S9xBlitPixSmall16; + } + + break; + + case 3: + if (width <= 256) + { + copyWidth = width * 3; + copyHeight = height * 3; + blitFn = S9xBlitPixHQ3x16; + } + else + { + copyWidth = width; + copyHeight = height; + blitFn = S9xBlitPixSmall16; + } + + break; + + case 4: + if (width <= 256) + { + copyWidth = width * 4; + copyHeight = height * 4; + blitFn = S9xBlitPixHQ4x16; + } + else + { + copyWidth = width * 2; + copyHeight = height * 2; + blitFn = S9xBlitPixHQ2x16; + } + + break; + + case -1: + case -2: + copyWidth = ntsc_width; + copyHeight = height; + + if (width <= 256) + blitFn = S9xBlitPixNTSC16; + else + blitFn = S9xBlitPixHiResNTSC16; + + break; + } + + imageWidth[whichBuf] = width; + imageHeight[whichBuf] = height; + + if (multiprocessor) + { + MPWaitOnSemaphore(readySemaphore, kDurationForever); + + mpDataBuffer->nx = nx; + mpDataBuffer->blitFn = blitFn; + mpDataBuffer->srcWidth = width; + mpDataBuffer->srcHeight = height; + mpDataBuffer->srcRowBytes = width * 2; + mpDataBuffer->copyWidth = copyWidth; + mpDataBuffer->copyHeight = copyHeight; + mpDataBuffer->gfxBuffer = GFX.Screen; + + MPNotifyQueue(taskQueue, (void *) kMPBlitFrame, 0, 0); + + whichBuf = 1 - whichBuf; + GFX.Screen = gfxScreen[whichBuf]; + } + else + { + switch (nx) + { + case -1: + blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, 1024 * 2, width, height); + break; + + case -2: + if (height > SNES_HEIGHT_EXTENDED) + blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, 1024 * 2, width, height); + else + { + uint8 *tmpBuffer = blitGLBuffer + (1024 * 512 * BYTES_PER_PIXEL); + int aligned = ((ntsc_width + 2) >> 1) << 1; + blitFn((uint8 *) GFX.Screen, width * 2, tmpBuffer, 1024 * 2, width, height); + S9xBlitPixHiResMixedTV16(tmpBuffer, 1024 * 2, blitGLBuffer, 1024 * 2, aligned, copyHeight); + copyHeight *= 2; + } + + break; + + default: + int dstbytes = (OpenGL.rangeExt ? copyWidth : ((copyWidth > 512) ? 1024 : 512)) * 2; + blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, dstbytes, width, height); + break; + } + + if (!ciFilterEnable) + S9xPutImageBlitGL2(copyWidth, copyHeight); + else + S9xPutImageBlitGL2CoreImage(copyWidth, copyHeight); + } +} + +static void S9xPutImageCoreImage (int width, int height) +{ + if ((imageWidth[0] != width) || (imageHeight[0] != height) || (windowResizeCount > 0)) + { + if ((imageWidth[0] != width) || (imageHeight[0] != height)) + windowResizeCount += 2; + + int vh = (height > 256) ? height : (height << 1); + + if (fullscreen) + { + CGLSetCurrentContext(glContext); + + glViewport(0, 0, glScreenW, glScreenH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (glstretch) + { + float fpw = (float) glScreenH / vh * 512.0f; + int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 100.0); + + glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); + } + else + glViewport((glScreenW - 512) >> 1, (glScreenH - vh) >> 1, 512, vh); + } + else + { + int ww = (int) gWindowRect.size.width, + wh = (int) gWindowRect.size.height; + + aglSetCurrentContext(agContext); + aglUpdateContext(agContext); + + glViewport(0, 0, ww, wh); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (windowExtend) + glViewport(0, ((kMacWindowHeight - vh) >> 1) * wh / kMacWindowHeight, ww, vh * wh / kMacWindowHeight); + } + + windowResizeCount--; + + glPixelStorei(GL_UNPACK_ROW_LENGTH, width); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, 0, height, -1, 1); + + if (cgGameImage) + CGImageRelease(cgGameImage); + cgGameImage = CreateGameScreenCGImage(); + + imageWidth[0] = width; + imageHeight[0] = height; + } + + CGRect src; + + src = CGRectMake(0, 0, width, height); + DrawWithCoreImageFilter(src, cgGameImage); + + if (fullscreen) + CGLFlushDrawable(glContext); + else + aglSwapBuffers(agContext); +} + +static void S9xPutImageOverscanOpenGL (int width, int height) +{ + if ((imageWidth[0] != width) || (imageHeight[0] != height) || (windowResizeCount > 0)) + { + if ((imageWidth[0] != width) || (imageHeight[0] != height)) + windowResizeCount += 2; + + if ((height == SNES_HEIGHT) || (height == (SNES_HEIGHT << 1))) + { + int pitch = width << 1; + int extbtm = (height > 256) ? (SNES_HEIGHT_EXTENDED << 1) : SNES_HEIGHT_EXTENDED; + uint32 *extarea = (uint32 *) ((uint8 *) GFX.Screen + height * pitch); + + for (int i = 0; i < (((extbtm - height) * pitch) >> 2); i++) + extarea[i] = 0; + } + + const int vh = SNES_HEIGHT_EXTENDED << 1; + + if (fullscreen) + { + CGLSetCurrentContext(glContext); + + glViewport(0, 0, glScreenW, glScreenH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (glstretch) + { + float fpw = (float) glScreenH / vh * 512.0f; + int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 100.0); + + glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); + } + else + glViewport((glScreenW - 512) >> 1, (glScreenH - vh) >> 1, 512, vh); + } + else + { + int ww = (int) gWindowRect.size.width, + wh = (int) gWindowRect.size.height; + + aglSetCurrentContext(agContext); + aglUpdateContext(agContext); + + glViewport(0, 0, ww, wh); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + + windowResizeCount--; + + textureNum = (width <= 256) ? kGL256256 : ((height <= 256) ? kGL512256 : kGL512512); + OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = OpenGL.rangeExt ? ((height > 256) ? vh : SNES_HEIGHT_EXTENDED) : (vh / 512.0f); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, width); + glBindTexture(OpenGL.target, OpenGL.textures[textureNum]); + + imageWidth[0] = width; + imageHeight[0] = height; + } + + glTexSubImage2D(OpenGL.target, 0, 0, 0, OpenGL.texW[textureNum], OpenGL.texH[textureNum], OpenGL.format, OpenGL.type, GFX.Screen); + + if (!screencurvature) + { + glBegin(GL_QUADS); + + glTexCoord2fv(&OpenGL.vertex[textureNum][6]); + glVertex2f(-1.0f, -1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][4]); + glVertex2f( 1.0f, -1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][2]); + glVertex2f( 1.0f, 1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][0]); + glVertex2f(-1.0f, 1.0f); + + glEnd(); + } + else + { + GLfloat *t, *s; + + t = scTexArray[kSC2xExtend]; + s = scScnArray; + + for (int i = 0; i < kSCMeshY; i++) + { + glTexCoordPointer(2, GL_FLOAT, 0, t); + glVertexPointer(3, GL_FLOAT, 0, s); + glDrawArrays(GL_TRIANGLE_STRIP, 0, (kSCMeshX + 1) * 2); + + t += (kSCMeshX + 1) * 2 * 2; + s += (kSCMeshX + 1) * 2 * 3; + } + } + + glFinishObjectAPPLE(GL_TEXTURE, OpenGL.textures[textureNum]); + + if (fullscreen) + CGLFlushDrawable(glContext); + else + aglSwapBuffers(agContext); +} + +static void S9xPutImageOverscanBlitGL (int width, int height) +{ + Blitter blitFn; + int copyWidth, copyHeight, extbtm; + + extbtm = (height > 256) ? (SNES_HEIGHT_EXTENDED << 1) : SNES_HEIGHT_EXTENDED; + + if ((imageWidth[whichBuf] != width) || (imageHeight[whichBuf] != height)) + { + if ((height == SNES_HEIGHT) || (height == (SNES_HEIGHT << 1))) + { + const unsigned int pitch = 1024; + unsigned int i; + uint32 *extarea; + + extarea = (uint32 *) ((uint8 *) GFX.Screen + height * pitch); + for (i = 0; i < (((extbtm - height) * pitch) >> 2); i++) + extarea[i] = 0; + + memset(blitGLBuffer, 0, 1024 * 1024 * BYTES_PER_PIXEL); + } + + if (videoMode == VIDEOMODE_TV) + if (width <= 256) + S9xBlitClearDelta(); + } + + switch (nx) + { + default: + case 2: + if (width <= 256) + { + copyWidth = width * 2; + copyHeight = SNES_HEIGHT_EXTENDED * 2; + + switch (videoMode) + { + default: + case VIDEOMODE_TV: blitFn = S9xBlitPixScaledTV16; break; + case VIDEOMODE_SUPEREAGLE: blitFn = S9xBlitPixSuperEagle16; break; + case VIDEOMODE_2XSAI: blitFn = S9xBlitPix2xSaI16; break; + case VIDEOMODE_SUPER2XSAI: blitFn = S9xBlitPixSuper2xSaI16; break; + case VIDEOMODE_EPX: blitFn = S9xBlitPixEPX16; break; + case VIDEOMODE_HQ2X: blitFn = S9xBlitPixHQ2x16; break; + } + } + else + if ((videoMode == VIDEOMODE_TV) && (height <= 256)) + { + copyWidth = width; + copyHeight = SNES_HEIGHT_EXTENDED * 2; + blitFn = S9xBlitPixHiResTV16; + } + else + { + copyWidth = width; + copyHeight = extbtm; + blitFn = S9xBlitPixSmall16; + } + + break; + + case 3: + if (width <= 256) + { + copyWidth = width * 3; + copyHeight = SNES_HEIGHT_EXTENDED * 3; + blitFn = S9xBlitPixHQ3x16; + } + else + { + copyWidth = width; + copyHeight = extbtm; + blitFn = S9xBlitPixSmall16; + } + + break; + + case 4: + if (width <= 256) + { + copyWidth = width * 4; + copyHeight = SNES_HEIGHT_EXTENDED * 4; + blitFn = S9xBlitPixHQ4x16; + } + else + { + copyWidth = width * 2; + copyHeight = extbtm * 2; + blitFn = S9xBlitPixHQ2x16; + } + + break; + + case -1: + case -2: + copyWidth = ntsc_width; + copyHeight = extbtm; + + if (width <= 256) + blitFn = S9xBlitPixNTSC16; + else + blitFn = S9xBlitPixHiResNTSC16; + + break; + } + + imageWidth[whichBuf] = width; + imageHeight[whichBuf] = height; + + if (multiprocessor) + { + MPWaitOnSemaphore(readySemaphore, kDurationForever); + + mpDataBuffer->nx = nx; + mpDataBuffer->blitFn = blitFn; + mpDataBuffer->srcWidth = width; + mpDataBuffer->srcHeight = height; + mpDataBuffer->srcRowBytes = width * 2; + mpDataBuffer->copyWidth = copyWidth; + mpDataBuffer->copyHeight = copyHeight; + mpDataBuffer->gfxBuffer = GFX.Screen; + + MPNotifyQueue(taskQueue, (void *) kMPBlitFrame, 0, 0); + + whichBuf = 1 - whichBuf; + GFX.Screen = gfxScreen[whichBuf]; + } + else + { + switch (nx) + { + case -1: + blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, 1024 * 2, width, height); + break; + + case -2: + if (height > SNES_HEIGHT_EXTENDED) + blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, 1024 * 2, width, height); + else + { + uint8 *tmpBuffer = blitGLBuffer + (1024 * 512 * BYTES_PER_PIXEL); + int aligned = ((ntsc_width + 2) >> 1) << 1; + blitFn((uint8 *) GFX.Screen, width * 2, tmpBuffer, 1024 * 2, width, height); + S9xBlitPixHiResMixedTV16(tmpBuffer, 1024 * 2, blitGLBuffer, 1024 * 2, aligned, copyHeight); + copyHeight *= 2; + } + + break; + + default: + int dstbytes = (OpenGL.rangeExt ? copyWidth : ((copyWidth > 512) ? 1024 : 512)) * 2; + blitFn((uint8 *) GFX.Screen, width * 2, blitGLBuffer, dstbytes, width, height); + break; + } + + if (!ciFilterEnable) + S9xPutImageBlitGL2(copyWidth, copyHeight); + else + S9xPutImageBlitGL2CoreImage(copyWidth, copyHeight); + } +} + +static void S9xPutImageOverscanCoreImage (int width, int height) +{ + int extbtm = (height > 256) ? (SNES_HEIGHT_EXTENDED << 1) : SNES_HEIGHT_EXTENDED; + + if ((imageWidth[0] != width) || (imageHeight[0] != height) || (windowResizeCount > 0)) + { + if ((imageWidth[0] != width) || (imageHeight[0] != height)) + windowResizeCount += 2; + + if ((height == SNES_HEIGHT) || (height == (SNES_HEIGHT << 1))) + { + int pitch = width << 1; + uint32 *extarea = (uint32 *) ((uint8 *) GFX.Screen + height * pitch); + + for (int i = 0; i < (((extbtm - height) * pitch) >> 2); i++) + extarea[i] = 0; + } + + const int vh = SNES_HEIGHT_EXTENDED << 1; + + if (fullscreen) + { + CGLSetCurrentContext(glContext); + + glViewport(0, 0, glScreenW, glScreenH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (glstretch) + { + float fpw = (float) glScreenH / vh * 512.0f; + int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 100.0); + + glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); + } + else + glViewport((glScreenW - 512) >> 1, (glScreenH - vh) >> 1, 512, vh); + } + else + { + int ww = (int) gWindowRect.size.width, + wh = (int) gWindowRect.size.height; + + aglSetCurrentContext(agContext); + aglUpdateContext(agContext); + + glViewport(0, 0, ww, wh); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + + windowResizeCount--; + + glPixelStorei(GL_UNPACK_ROW_LENGTH, width); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, height - extbtm, height, -1, 1); + + if (cgGameImage) + CGImageRelease(cgGameImage); + cgGameImage = CreateGameScreenCGImage(); + + imageWidth[0] = width; + imageHeight[0] = height; + } + + CGRect src; + + src = CGRectMake(0, 0, width, height); + DrawWithCoreImageFilter(src, cgGameImage); + + if (fullscreen) + CGLFlushDrawable(glContext); + else + aglSwapBuffers(agContext); +} + +static void S9xPutImageBlitGL2 (int blit_width, int blit_height) +{ + if ((prevBlitWidth != blit_width) || (prevBlitHeight != blit_height) || (windowResizeCount > 0)) + { + if ((prevBlitWidth != blit_width) || (prevBlitHeight != blit_height)) + windowResizeCount += 2; + + if (fullscreen) + { + CGLSetCurrentContext(glContext); + + glViewport(0, 0, glScreenW, glScreenH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (glstretch) + { + int sh = (blit_width > blit_height * 2) ? (blit_height * 2) : blit_height; + float fpw = (float) glScreenH / (float) sh * (float) blit_width; + int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 100.0); + glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); + } + else + { + int sw, sh; + + if (nx < 0) + { + sw = ntsc_width; + sh = ((blit_height % SNES_HEIGHT) ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) * 2; + } + else + { + sw = SNES_WIDTH * nx; + sh = ((blit_height % SNES_HEIGHT) ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) * nx; + } + + glViewport((glScreenW - sw) >> 1, (glScreenH - sh) >> 1, sw, sh); + } + } + else + { + int ww = (int) gWindowRect.size.width, + wh = (int) gWindowRect.size.height; + + aglSetCurrentContext(agContext); + aglUpdateContext(agContext); + + glViewport(0, 0, ww, wh); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (windowExtend) + { + int bh = (blit_height % SNES_HEIGHT) ? (SNES_HEIGHT_EXTENDED << 1) : (SNES_HEIGHT << 1); + glViewport(0, ((kMacWindowHeight - bh) >> 1) * wh / kMacWindowHeight, ww, bh * wh / kMacWindowHeight); + } + } + + windowResizeCount--; + + if (nx < 0) + textureNum = (blit_height > SNES_HEIGHT_EXTENDED) ? kGLNTS512 : kGLNTS256; + else + { + switch (blit_width / SNES_WIDTH) + { + default: + case 2: textureNum = kGLBlit2x; break; + case 3: textureNum = kGLBlit3x; break; + case 4: textureNum = kGLBlit4x; break; + } + } + + if (nx < 0) + { + int sh = (blit_height > 256) ? 512 : 256; + OpenGL.vertex[textureNum][2] = OpenGL.vertex[textureNum][4] = blit_width / 1024.0f; + OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = blit_height / (float) sh; + glPixelStorei(GL_UNPACK_ROW_LENGTH, 1024); + } + else + { + if (OpenGL.rangeExt) + { + OpenGL.vertex[textureNum][2] = OpenGL.vertex[textureNum][4] = blit_width; + OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = blit_height; + glPixelStorei(GL_UNPACK_ROW_LENGTH, blit_width); + } + else + { + int sl = (blit_width > 512) ? 1024 : 512; + OpenGL.vertex[textureNum][2] = OpenGL.vertex[textureNum][4] = blit_width / (float) sl; + OpenGL.vertex[textureNum][5] = OpenGL.vertex[textureNum][7] = blit_height / (float) sl; + glPixelStorei(GL_UNPACK_ROW_LENGTH, sl); + } + } + + glBindTexture(OpenGL.target, OpenGL.textures[textureNum]); + + prevBlitWidth = blit_width; + prevBlitHeight = blit_height; + } + + glTexSubImage2D(OpenGL.target, 0, 0, 0, OpenGL.texW[textureNum], OpenGL.texH[textureNum], OpenGL.format, OpenGL.type, blitGLBuffer); + + if (!screencurvature) + { + glBegin(GL_QUADS); + + glTexCoord2fv(&OpenGL.vertex[textureNum][6]); + glVertex2f(-1.0f, -1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][4]); + glVertex2f( 1.0f, -1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][2]); + glVertex2f( 1.0f, 1.0f); + glTexCoord2fv(&OpenGL.vertex[textureNum][0]); + glVertex2f(-1.0f, 1.0f); + + glEnd(); + } + else + { + GLfloat *t, *s; + int tex; + + if (nx < 0) + tex = (blit_height % SNES_HEIGHT) ? kSCNTExtend : kSCNTNormal; + else + if (blit_width > blit_height * 2) + { + if (blit_width / SNES_WIDTH != 3) + tex = (blit_height % SNES_HEIGHT) ? kSC2xEHiRes : kSC2xNHiRes; + else + tex = (blit_height % SNES_HEIGHT) ? kSC3xEHiRes : kSC3xNHiRes; + } + else + { + if (blit_width / SNES_WIDTH != 3) + tex = (blit_height % SNES_HEIGHT) ? kSC2xExtend : kSC2xNormal; + else + tex = (blit_height % SNES_HEIGHT) ? kSC3xExtend : kSC3xNormal; + } + + t = scTexArray[tex]; + s = scScnArray; + + for (int i = 0; i < kSCMeshY; i++) + { + glTexCoordPointer(2, GL_FLOAT, 0, t); + glVertexPointer(3, GL_FLOAT, 0, s); + glDrawArrays(GL_TRIANGLE_STRIP, 0, (kSCMeshX + 1) * 2); + + t += (kSCMeshX + 1) * 2 * 2; + s += (kSCMeshX + 1) * 2 * 3; + } + } + + glFinishObjectAPPLE(GL_TEXTURE, OpenGL.textures[textureNum]); + + if (fullscreen) + CGLFlushDrawable(glContext); + else + aglSwapBuffers(agContext); +} + +static void S9xPutImageBlitGL2CoreImage (int blit_width, int blit_height) +{ + if ((prevBlitWidth != blit_width) || (prevBlitHeight != blit_height) || (windowResizeCount > 0)) + { + if ((prevBlitWidth != blit_width) || (prevBlitHeight != blit_height)) + windowResizeCount += 2; + + if (fullscreen) + { + CGLSetCurrentContext(glContext); + + glViewport(0, 0, glScreenW, glScreenH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (glstretch) + { + int sh = (blit_width > blit_height * 2) ? (blit_height * 2) : blit_height; + float fpw = (float) glScreenH / (float) sh * (float) blit_width; + int pw = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 100.0); + glViewport((glScreenW - pw) >> 1, 0, pw, glScreenH); + } + else + { + int sw, sh; + + if (nx < 0) + { + sw = ntsc_width; + sh = ((blit_height % SNES_HEIGHT) ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) * 2; + } + else + { + sw = SNES_WIDTH * nx; + sh = ((blit_height % SNES_HEIGHT) ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) * nx; + } + + glViewport((glScreenW - sw) >> 1, (glScreenH - sh) >> 1, sw, sh); + } + } + else + { + int ww = (int) gWindowRect.size.width, + wh = (int) gWindowRect.size.height; + + aglSetCurrentContext(agContext); + aglUpdateContext(agContext); + + glViewport(0, 0, ww, wh); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + if (windowExtend) + { + int bh = (blit_height % SNES_HEIGHT) ? (SNES_HEIGHT_EXTENDED << 1) : (SNES_HEIGHT << 1); + glViewport(0, ((kMacWindowHeight - bh) >> 1) * wh / kMacWindowHeight, ww, bh * wh / kMacWindowHeight); + } + } + + windowResizeCount--; + + int sl = OpenGL.rangeExt ? blit_width : ((blit_width > 512) ? 1024 : 512); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, sl); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, blit_width, 0, blit_height, -1, 1); + + if (cgBlitImage) + CGImageRelease(cgBlitImage); + cgBlitImage = CreateBlitScreenCGImage(blit_width, blit_height, sl << 1, blitGLBuffer); + + prevBlitWidth = blit_width; + prevBlitHeight = blit_height; + } + + CGRect src; + + src = CGRectMake(0, 0, blit_width, blit_height); + DrawWithCoreImageFilter(src, cgBlitImage); + + if (fullscreen) + CGLFlushDrawable(glContext); + else + aglSwapBuffers(agContext); +} + +static void GLMakeScreenMesh (GLfloat *vertex3D, int meshx, int meshy) +{ + GLfloat *v; + float warp; + + v = vertex3D; + warp = macCurvatureWarp * 0.001f; + + for (int y = 0; y < meshy; y++) + { + for (int x = 0; x <= meshx; x++) + { + float u1, v1, v2; + + u1 = -1.0f + 2.0f / (float) meshx * (float) x; + v1 = -1.0f + 2.0f / (float) meshy * (float) y; + v2 = -1.0f + 2.0f / (float) meshy * (float) (y + 1); + + *v++ = u1; + *v++ = v2; + *v++ = -1.0f - (u1 * u1 + v2 * v2) * warp; + + *v++ = u1; + *v++ = v1; + *v++ = -1.0f - (u1 * u1 + v1 * v1) * warp; + } + } +} + +static void GLMakeTextureMesh (GLfloat *vertex2D, int meshx, int meshy, float lx, float ly) +{ + GLfloat *v; + + v = vertex2D; + + for (int y = meshy; y > 0; y--) + { + for (int x = 0; x <= meshx; x++) + { + float u1, v1, v2; + + u1 = lx / (float) meshx * (float) x; + v1 = ly / (float) meshy * (float) y; + v2 = ly / (float) meshy * (float) (y - 1); + + *v++ = u1; + *v++ = v2; + + *v++ = u1; + *v++ = v1; + } + } +} + +void S9xTextMode (void) +{ + return; +} + +void S9xGraphicsMode (void) +{ + return; +} + +void S9xSetPalette (void) +{ + return; +} diff --git a/macosx/mac-render.h b/macosx/mac-render.h new file mode 100644 index 00000000..3755db9b --- /dev/null +++ b/macosx/mac-render.h @@ -0,0 +1,200 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_render_h_ +#define _mac_render_h_ + +void InitGraphics (void); +void DeinitGraphics (void); +void DrawPauseScreen (CGContextRef, HIRect); +void ClearGFXScreen (void); +void DrawFreezeDefrostScreen (uint8 *); + +#endif diff --git a/macosx/mac-screenshot.cpp b/macosx/mac-screenshot.cpp new file mode 100644 index 00000000..403a622b --- /dev/null +++ b/macosx/mac-screenshot.cpp @@ -0,0 +1,514 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "screenshot.h" + +#include + +#include "mac-prefix.h" +#include "mac-file.h" +#include "mac-gworld.h" +#include "mac-os.h" +#include "mac-render.h" +#include "mac-screenshot.h" + +static Handle GetScreenAsRawHandle (int, int); +static void ExportCGImageToPNGFile (CGImageRef, const char *); + + +static Handle GetScreenAsRawHandle (int destWidth, int destHeight) +{ + CGContextRef ctx; + CGColorSpaceRef color; + CGImageRef image; + Handle data = NULL; + + image = CreateGameScreenCGImage(); + if (image) + { + data = NewHandleClear(destWidth * destHeight * 2); + if (data) + { + HLock(data); + + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + ctx = CGBitmapContextCreate(*data, destWidth, destHeight, 5, destWidth * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Big : 0)); + if (ctx) + { + CGContextDrawImage(ctx, CGRectMake(0.0f, 0.0f, (float) destWidth, (float) destHeight), image); + CGContextRelease(ctx); + } + + CGColorSpaceRelease(color); + } + + HUnlock(data); + } + + CGImageRelease(image); + } + + return (data); +} + +void WriteThumbnailToResourceFork (FSRef *ref, int destWidth, int destHeight) +{ + OSStatus err; + HFSUniStr255 fork; + SInt16 resf; + + err = FSGetResourceForkName(&fork); + if (err == noErr) + { + err = FSCreateResourceFork(ref, fork.length, fork.unicode, 0); + if ((err == noErr) || (err == errFSForkExists)) + { + err = FSOpenResourceFile(ref, fork.length, fork.unicode, fsWrPerm, &resf); + if (err == noErr) + { + Handle pict; + + pict = GetScreenAsRawHandle(destWidth, destHeight); + if (pict) + { + AddResource(pict, 'Thum', 128, "\p"); + WriteResource(pict); + ReleaseResource(pict); + } + + CloseResFile(resf); + } + } + } +} + +static void ExportCGImageToPNGFile (CGImageRef image, const char *path) +{ + OSStatus err; + GraphicsExportComponent exporter; + CFStringRef str; + CFURLRef url; + Handle dataRef; + OSType dataRefType; + + str = CFStringCreateWithCString(kCFAllocatorDefault, path, MAC_PATH_ENCODING); + if (str) + { + url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, str, kCFURLPOSIXPathStyle, false); + if (url) + { + err = QTNewDataReferenceFromCFURL(url, 0, &dataRef, &dataRefType); + if (err == noErr) + { + err = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG, &exporter); + if (err == noErr) + { + err = GraphicsExportSetInputCGImage(exporter, image); + if (err == noErr) + { + err = GraphicsExportSetOutputDataReference(exporter, dataRef, dataRefType); + if (err == noErr) + err = GraphicsExportDoExport(exporter, NULL); + } + + CloseComponent(exporter); + } + + DisposeHandle(dataRef); + } + + CFRelease(url); + } + + CFRelease(str); + } +} + +CGImageRef CreateGameScreenCGImage (void) +{ + CGDataProviderRef prov; + CGColorSpaceRef color; + CGImageRef image = NULL; + int rowbytes; + + rowbytes = IPPU.RenderedScreenWidth * 2; + + prov = CGDataProviderCreateWithData(NULL, GFX.Screen, 512 * 2 * 478, NULL); + if (prov) + { + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + image = CGImageCreate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, 5, 16, rowbytes, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0), prov, NULL, 1, kCGRenderingIntentDefault); + CGColorSpaceRelease(color); + } + + CGDataProviderRelease(prov); + } + + return (image); +} + +CGImageRef CreateBlitScreenCGImage (int width, int height, int rowbytes, uint8 *buffer) +{ + CGDataProviderRef prov; + CGColorSpaceRef color; + CGImageRef image = NULL; + + prov = CGDataProviderCreateWithData(NULL, buffer, rowbytes * height, NULL); + if (prov) + { + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + image = CGImageCreate(width, height, 5, 16, rowbytes, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0), prov, NULL, 1, kCGRenderingIntentDefault); + CGColorSpaceRelease(color); + } + + CGDataProviderRelease(prov); + } + + return (image); +} + +void DrawThumbnailResource (FSRef *ref, CGContextRef ctx, CGRect bounds) +{ + OSStatus err; + CGDataProviderRef prov; + CGColorSpaceRef color; + CGImageRef image; + QDPictRef qdpr; + Handle pict; + HFSUniStr255 fork; + SInt16 resf; + Size size; + + CGContextSaveGState(ctx); + + CGContextSetRGBFillColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); + CGContextFillRect(ctx, bounds); + + err = FSGetResourceForkName(&fork); + if (err == noErr) + { + err = FSOpenResourceFile(ref, fork.length, fork.unicode, fsRdPerm, &resf); + if (err == noErr) + { + pict = Get1Resource('PICT', 128); + if (pict) + { + HLock(pict); + + size = GetHandleSize(pict); + prov = CGDataProviderCreateWithData(NULL, (void *) *pict, size, NULL); + if (prov) + { + qdpr = QDPictCreateWithProvider(prov); + if (qdpr) + { + QDPictDrawToCGContext(ctx, bounds, qdpr); + QDPictRelease(qdpr); + } + + CGDataProviderRelease(prov); + } + + HUnlock(pict); + ReleaseResource(pict); + } + else + { + pict = Get1Resource('Thum', 128); + if (pict) + { + HLock(pict); + + size = GetHandleSize(pict); + prov = CGDataProviderCreateWithData(NULL, (void *) *pict, size, NULL); + if (prov) + { + color = CGColorSpaceCreateDeviceRGB(); + if (color) + { + image = CGImageCreate(128, 120, 5, 16, 256, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Big : 0), prov, NULL, 0, kCGRenderingIntentDefault); + if (image) + { + CGContextDrawImage(ctx, bounds, image); + CGImageRelease(image); + } + + CGColorSpaceRelease(color); + } + + CGDataProviderRelease(prov); + } + + HUnlock(pict); + ReleaseResource(pict); + } + } + + CloseResFile(resf); + } + } + + CGContextRestoreGState(ctx); +} + +bool8 S9xDoScreenshot (int width, int height) +{ + Settings.TakeScreenshot = false; + + uint16 *data; + + data = (uint16 *) malloc(512 * 478 * 2); + if (data) + { + uint16 *sp, *dp; + + if (width > 256 && height > 239) + { + for (int y = 0; y < height; y++) + { + sp = GFX.Screen + y * GFX.RealPPL; + dp = data + y * 512; + + for (int x = 0; x < width; x++) + *dp++ = *sp++; + } + } + else + if (width > 256) + { + for (int y = 0; y < height; y++) + { + sp = GFX.Screen + y * GFX.RealPPL; + dp = data + y * 2 * 512; + + for (int x = 0; x < width; x++) + { + *dp = *(dp + 512) = *sp++; + dp++; + } + } + } + else + { + for (int y = 0; y < height; y++) + { + sp = GFX.Screen + y * GFX.RealPPL; + dp = data + y * 2 * 512; + + for (int x = 0; x < width; x++) + { + *dp = *(dp + 1) = *(dp + 512) = *(dp + 512 + 1) = *sp++; + dp += 2; + } + } + } + + CGImageRef image; + + image = CreateBlitScreenCGImage(512, (height > 239) ? height : (height * 2), 1024, (uint8 *) data); + if (image) + { + ExportCGImageToPNGFile(image, S9xGetPNGFilename()); + CGImageRelease(image); + } + + free(data); + } + + return (true); +} diff --git a/macosx/mac-screenshot.h b/macosx/mac-screenshot.h new file mode 100644 index 00000000..6cba7cf8 --- /dev/null +++ b/macosx/mac-screenshot.h @@ -0,0 +1,200 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_scheenshot_h_ +#define _mac_scheenshot_h_ + +void WriteThumbnailToResourceFork (FSRef *, int, int); +void DrawThumbnailResource (FSRef *, CGContextRef, CGRect); +PicHandle GetScreenAsPicHandle (int, int, int, int); +CGImageRef CreateGameScreenCGImage (void); +CGImageRef CreateBlitScreenCGImage (int, int, int, uint8 *); + +#endif diff --git a/macosx/mac-server.cpp b/macosx/mac-server.cpp new file mode 100644 index 00000000..a5a50b6a --- /dev/null +++ b/macosx/mac-server.cpp @@ -0,0 +1,1503 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" + +#include +#include +#include +#include +#include + +#include "mac-prefix.h" +#include "mac-controls.h" +#include "mac-dialog.h" +#include "mac-joypad.h" +#include "mac-keyboard.h" +#include "mac-os.h" +#include "mac-stringtools.h" +#include "mac-netplay.h" +#include "mac-server.h" + +#ifdef SELF_TEST +#include +#endif + +#define KeyIsPressed(km, k) (1 & (((unsigned char *) km) [(k) >> 3] >> ((k) & 7))) + +enum +{ + kNPSDialogNone, + kNPSDialogInit, + kNPSDialogProcess, + kNPSDialogDone, + kNPSDialogCancel +}; + +typedef struct +{ + volatile bool8 listenloop; + volatile uint32 phasecount; + volatile uint32 phasespan; + volatile uint8 header; + int socket; + int numplayers; + + bool8 dialogcancel; + int dialogprocess; +} serverState; + +typedef struct +{ + volatile bool8 padloop; + volatile bool8 exitsgn; + bool8 online; + bool8 ready; + int socket; + int client; + int player; + char ip[256]; + char name[256]; +} clientsState; + +static char n_sememu[NP_MAX_PLAYERS][30] = +{ + "/tmp/s9x_s_emu_semaphore1", + "/tmp/s9x_s_emu_semaphore2", + "/tmp/s9x_s_emu_semaphore3", + "/tmp/s9x_s_emu_semaphore4", + "/tmp/s9x_s_emu_semaphore5" +}; + +static char n_sempad[NP_MAX_PLAYERS][30] = +{ + "/tmp/s9x_s_pad_semaphore1", + "/tmp/s9x_s_pad_semaphore2", + "/tmp/s9x_s_pad_semaphore3", + "/tmp/s9x_s_pad_semaphore4", + "/tmp/s9x_s_pad_semaphore5" +}; + +static serverState npserver; +static clientsState npplayer[NP_MAX_PLAYERS]; + +static uint32 npactvpad[NP_MAX_PLAYERS][64], // [player number][] + nprecvpad[NP_MAX_PLAYERS][64], // [player number][] + npsendpad[NP_MAX_PLAYERS][64], // [player number][] + npcachpad[64]; + +static sem_t *sememu[NP_MAX_PLAYERS], + *sempad[NP_MAX_PLAYERS]; + +static pthread_t listenthread, + processthread, + padthread[NP_MAX_PLAYERS]; + +static int NPServerAcceptClient (int); +static int NPServerGetMesFromClient (int); +static void NPServerBeginListenLoop (void); +static void NPServerEndListenLoop (void); +static void NPServerDetachProcessThread (void); +static void NPServerShutdownClient (int); +static void NPServerAllotPlayers (void); +static void NPServerSendPlayerList (void); +static void NPServerWaitStartReply (void); +static void NPServerSetPhaseSpan (void); +static bool8 NPServerSendMesToClient (int, int); +static bool8 NPServerGetNameFromClient (int); +static bool8 NPServerSendROMInfoToClient (int); +static bool8 NPServerSendSRAMToClient (int); +static bool8 NPServerSendPlayerListToClient (int); +static void * NPServerListenLoop (void *); +static void * NPServerProcessThread (void *); +static void * NPServerNetPlayThread (void *); +static pascal void NPServerDialogTimerHandler (EventLoopTimerRef, void *); +static pascal OSStatus NPServerDialogEventHandler (EventHandlerCallRef, EventRef, void *); + + +bool8 NPServerDialog (void) +{ + OSStatus err; + IBNibRef nibRef; + + npserver.dialogcancel = true; + + err = CreateNibReference(kMacS9XCFString, &nibRef); + if (err == noErr) + { + WindowRef tWindowRef; + + err = CreateWindowFromNib(nibRef, CFSTR("ClientList"), &tWindowRef); + if (err == noErr) + { + EventHandlerRef eref; + EventLoopTimerRef tref; + EventHandlerUPP eventUPP; + EventLoopTimerUPP timerUPP; + EventTypeSpec windowEvents[] = { { kEventClassCommand, kEventCommandProcess }, + { kEventClassCommand, kEventCommandUpdateStatus } }; + HIViewRef ctl; + HIViewID cid = { 'Chse', 0 }; + + npserver.dialogprocess = kNPSDialogInit; + + eventUPP = NewEventHandlerUPP(NPServerDialogEventHandler); + err = InstallWindowEventHandler(tWindowRef, eventUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) tWindowRef, &eref); + + timerUPP = NewEventLoopTimerUPP(NPServerDialogTimerHandler); + err = InstallEventLoopTimer(GetCurrentEventLoop(), 0.0f, 0.1f, timerUPP, (void *) tWindowRef, &tref); + + HIViewFindByID(HIViewGetRoot(tWindowRef), cid, &ctl); + HIViewSetVisible(ctl, false); + + MoveWindowPosition(tWindowRef, kWindowServer, false); + ShowWindow(tWindowRef); + err = RunAppModalLoopForWindow(tWindowRef); + HideWindow(tWindowRef); + SaveWindowPosition(tWindowRef, kWindowServer); + + err = RemoveEventLoopTimer(tref); + DisposeEventLoopTimerUPP(timerUPP); + + err = RemoveEventHandler(eref); + DisposeEventHandlerUPP(eventUPP); + + CFRelease(tWindowRef); + } + + DisposeNibReference(nibRef); + } + + return (!npserver.dialogcancel); +} + +static pascal void NPServerDialogTimerHandler (EventLoopTimerRef inTimer, void *userData) +{ + WindowRef window = (WindowRef) userData; + CFStringRef ref; + HIViewRef ctl, root; + HIViewID cid; + int n = 0; + + root = HIViewGetRoot(window); + + for (int c = 0; c < NP_MAX_PLAYERS; c++) + { + cid.id = c; + + cid.signature = 'Pnum'; + HIViewFindByID(root, cid, &ctl); + if (npplayer[c].ready) + { + char num[4]; + + num[0] = '1' + n; + num[1] = 'P'; + num[2] = 0; + SetStaticTextCStr(ctl, num, true); + n++; + } + + cid.signature = 'IP__'; + HIViewFindByID(root, cid, &ctl); + if (npplayer[c].online) + { + ref = CFStringCreateWithCString(kCFAllocatorDefault, npplayer[c].ip, MAC_PATH_ENCODING); + if (ref) + { + SetStaticTextCFString(ctl, ref, true); + CFRelease(ref); + } + else + SetStaticTextCFString(ctl, CFSTR("unknown"), true); + } + else + SetStaticTextCFString(ctl, CFSTR(""), true); + + cid.signature = 'Name'; + HIViewFindByID(root, cid, &ctl); + if (npplayer[c].online) + { + ref = CFStringCreateWithCString(kCFAllocatorDefault, npplayer[c].name, MAC_PATH_ENCODING); + if (ref) + { + SetStaticTextCFString(ctl, ref, true); + CFRelease(ref); + } + else + SetStaticTextCFString(ctl, CFSTR("unknown"), true); + } + else + SetStaticTextCFString(ctl, CFSTR(""), true); + + cid.signature = 'Stat'; + HIViewFindByID(root, cid, &ctl); + if (npplayer[c].online) + { + if (npplayer[c].ready) + ref = CFCopyLocalizedString(CFSTR("NPReady"), "NPReady"); + else + ref = CFCopyLocalizedString(CFSTR("NPConnecting"), "NPConnecting"); + + if (ref) + { + SetStaticTextCFString(ctl, ref, true); + CFRelease(ref); + } + else + SetStaticTextCFString(ctl, CFSTR("error"), true); + } + else + SetStaticTextCFString(ctl, CFSTR(""), true); + } + + switch (npserver.dialogprocess) + { + case kNPSDialogNone: + break; + + case kNPSDialogInit: + NPNotification(" kNPSDialogInit", -1); + npserver.dialogprocess = kNPSDialogNone; + NPServerBeginListenLoop(); + break; + + case kNPSDialogProcess: + NPNotification(" kNPSDialogProcess", -1); + npserver.dialogprocess = kNPSDialogNone; + NPServerEndListenLoop(); + cid.id = 0; + cid.signature = 'Chse'; + HIViewFindByID(root, cid, &ctl); + HIViewSetVisible(ctl, true); + NPServerDetachProcessThread(); + break; + + case kNPSDialogDone: + NPNotification(" kNPSDialogDone", -1); + npserver.dialogprocess = kNPSDialogNone; + npserver.dialogcancel = false; + QuitAppModalLoopForWindow(window); + break; + + case kNPSDialogCancel: + NPNotification(" kNPSDialogCancel", -1); + npserver.dialogprocess = kNPSDialogNone; + NPServerEndListenLoop(); + npserver.dialogcancel = true; + QuitAppModalLoopForWindow(window); + break; + } +} + +static pascal OSStatus NPServerDialogEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) +{ + OSStatus err, result = eventNotHandledErr; + WindowRef tWindowRef = (WindowRef) inUserData; + + switch (GetEventClass(inEvent)) + { + case kEventClassCommand: + switch (GetEventKind(inEvent)) + { + HICommand tHICommand; + + case kEventCommandUpdateStatus: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr && tHICommand.commandID == 'clos') + { + UpdateMenuCommandStatus(false); + result = noErr; + } + + break; + + case kEventCommandProcess: + err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); + if (err == noErr) + { + switch (tHICommand.commandID) + { + case 'OKAY': + HIViewRef ctl, root; + HIViewID cid; + + root = HIViewGetRoot(tWindowRef); + cid.id = 0; + cid.signature = 'OKAY'; + HIViewFindByID(root, cid, &ctl); + DeactivateControl(ctl); + cid.signature = 'CNSL'; + HIViewFindByID(root, cid, &ctl); + DeactivateControl(ctl); + + npserver.dialogprocess = kNPSDialogProcess; + result = noErr; + break; + + case 'CNSL': + npserver.dialogprocess = kNPSDialogCancel; + result = noErr; + break; + } + } + + break; + } + + break; + } + + return (result); +} + +void NPServerInit (void) +{ + npserver.listenloop = false; + npserver.phasecount = 0; + npserver.phasespan = 0; + npserver.header = 0; + npserver.socket = -1; + npserver.numplayers = 0; + + for (int i = 0; i < NP_MAX_PLAYERS; i++) + { + for (int j = 0; j < 64; j++) + { + npactvpad[i][j] = 0; + nprecvpad[i][j] = 0; + npsendpad[i][j] = 0; + } + } + + for (int j = 0; j < 64; j++) + npcachpad[j] = 0; + + for (int c = 0; c < NP_MAX_PLAYERS; c++) + { + npplayer[c].padloop = false; + npplayer[c].exitsgn = false; + npplayer[c].online = false; + npplayer[c].ready = false; + npplayer[c].socket = -1; + npplayer[c].client = 0; + npplayer[c].player = 0; + npplayer[c].ip[0] = 0; + npplayer[c].name[0] = 0; + } + + npplayer[0].online = true; + npplayer[0].ready = true; + + char name[256]; + if (gethostname(name, 256) == 0) + { + struct hostent *hn; + if ((hn = gethostbyname(name)) != NULL) + { + struct in_addr addr; + memcpy(&addr, hn->h_addr_list[0], sizeof(struct in_addr)); + strcpy(npplayer[0].ip, inet_ntoa(addr)); + } + else + strcpy(npplayer[0].ip, "unknown"); + } + else + strcpy(npplayer[0].ip, "unknown"); + + CFStringRef ref; + ref = CFCopyLocalizedString(CFSTR("NPServerName"), "NPServer"); + if (ref) + { + Boolean r; + r = CFStringGetCString(ref, npplayer[0].name, 256, MAC_PATH_ENCODING); + if (!r) + strcpy(npplayer[0].name, "unknown"); + + CFRelease(ref); + } + else + strcpy(npplayer[0].name, "unknown"); +} + +bool8 NPServerStartServer (int port) +{ +#ifndef SELF_TEST + struct sockaddr_in address; +#else + struct sockaddr_un address; +#endif + int v = 1; + + NPNotification("Server: Starting server...", -1); + +#ifndef SELF_TEST + if ((npserver.socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) +#else + if ((npserver.socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) +#endif + { + NPError("Server: Failed to create listening socket.", 1001); + return (false); + } + + if ((setsockopt(npserver.socket, SOL_SOCKET, SO_REUSEADDR, (char *) &v, sizeof(v))) < 0) + { + NPError("Server: Failed to set socket option.", 1002); + return (false); + } + + memset(&address, 0, sizeof(address)); +#ifndef SELF_TEST + address.sin_family = AF_INET; + address.sin_addr.s_addr = htonl(INADDR_ANY); + address.sin_port = htons(port); +#else + address.sun_family = AF_UNIX; + strcpy(address.sun_path, SOCK_NAME); +#endif + +#ifndef SELF_TEST + if ((bind(npserver.socket, (struct sockaddr *) &address, sizeof(address))) < 0) +#else + unlink(SOCK_NAME); + if ((bind(npserver.socket, (struct sockaddr *) &address, sizeof(address))) < 0) +#endif + { + NPError("Server: Failed to bind socket to port number.", 1003); + return (false); + } + + if ((listen(npserver.socket, NP_MAX_CLIENTS)) < 0) + { + NPError("Server: Failed to get new socket to listen.", 1004); + return (false); + } + + npplayer[0].socket = npserver.socket; + + NPNotification("Server: Started server.", -1); + return (true); +} + +void NPServerStopServer (void) +{ + NPNotification("Server: Stopping server...", -1); + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + NPServerShutdownClient(c); + + npplayer[0].online = false; + npplayer[0].ready = false; + npplayer[0].socket = -1; + npplayer[0].client = 0; + npplayer[0].player = 0; + npplayer[0].ip[0] = 0; + npplayer[0].name[0] = 0; + + if (npserver.socket != -1) + { + close(npserver.socket); + npserver.socket = -1; + } + + NPNotification("Server: Stopped server.", -1); +} + +static void NPServerShutdownClient (int c) +{ + if (npplayer[c].online) + { + NPNotification("Server: Closing client %d connection...", c); + + if (npplayer[c].socket != -1) + { + close(npplayer[c].socket); + npplayer[c].socket = -1; + } + + npplayer[c].online = false; + npplayer[c].ready = false; + npplayer[c].client = 0; + npplayer[c].player = 0; + npplayer[c].ip[0] = 0; + npplayer[c].name[0] = 0; + + NPNotification("Server: Client %d has disconnected.", c); + } +} + +static int NPServerAcceptClient (int port) +{ +#ifndef SELF_TEST + struct sockaddr_in address; +#else + struct sockaddr_un address; +#endif + int newfd; + int c; + socklen_t l; + + NPNotification("Server: Accepting new client connection...", -1); + + for (c = 1; c <= NP_MAX_CLIENTS; c++) + if (!npplayer[c].online) + break; + + if (c > NP_MAX_CLIENTS) + { + NPError("Server: Maximum number of clients have already connected.", 1101); + return (-1); + } + + l = sizeof(address); + memset(&address, 0, l); + + if ((newfd = accept(port, (struct sockaddr *) &address, &l)) < 0) + { + NPError("Server: Can't accept client connection.", 1102); + return (-1); + } + + npplayer[c].online = true; + npplayer[c].socket = newfd; + +#ifndef SELF_TEST + if (address.sin_family == AF_INET) + strcpy(npplayer[c].ip, inet_ntoa(address.sin_addr)); + else + strcpy(npplayer[c].ip, "unknown"); +#else + strcpy(npplayer[c].ip, "Unix"); +#endif + + NPNotification("Server: new client %d has connected.", c); + + return (c); +} + +static void NPServerBeginListenLoop (void) +{ + npserver.listenloop = true; + pthread_create(&listenthread, NULL, NPServerListenLoop, NULL); +} + +static void NPServerEndListenLoop (void) +{ + npserver.listenloop = false; + pthread_join(listenthread, NULL); +} + +static void * NPServerListenLoop (void *) +{ + struct timeval timeout; + fd_set readfds; + int maxfd; + + NPNotification("Server: Entered listening loop.", -1); + + while (npserver.listenloop) + { + FD_ZERO(&readfds); + maxfd = 0; + + if (npserver.socket != -1) + { + FD_SET(npserver.socket, &readfds); + maxfd = npserver.socket; + } + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].online) + { + FD_SET(npplayer[c].socket, &readfds); + if (maxfd < npplayer[c].socket) + maxfd = npplayer[c].socket; + } + } + + timeout.tv_sec = 0; + timeout.tv_usec = 50000; + + if (select(maxfd + 1, &readfds, NULL, NULL, &timeout) > 0) + { + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].online) + { + if (FD_ISSET(npplayer[c].socket, &readfds)) + { + switch (NPServerGetMesFromClient(c)) + { + case kNPClientNameSent: + if (!NPServerSendROMInfoToClient(c)) + NPServerShutdownClient(c); + break; + + case kNPClientROMOpened: + if (!NPServerSendSRAMToClient(c)) + NPServerShutdownClient(c); + break; + + case kNPClientSRAMLoaded: + npplayer[c].ready = true; + break; + + default: + NPServerShutdownClient(c); + break; + } + } + } + } + + if (FD_ISSET(npserver.socket, &readfds)) + { + int client; + + if ((client = NPServerAcceptClient(npserver.socket)) != -1) + { + if (!NPServerGetNameFromClient(client)) + NPServerShutdownClient(client); + } + } + } + } + + NPNotification("Server: Exited listening loop.", -1); + + return (NULL); +} + +static bool8 NPServerSendMesToClient (int c, int num) +{ + uint8 mes[2]; + + mes[0] = NP_SERVER_MAGIC; + mes[1] = num; + + if (socket_write(npplayer[c].socket, mes, 2) != 2) + return (false); + + return (true); +} + +static int NPServerGetMesFromClient (int c) +{ + uint8 mes[2]; + + if (socket_read(npplayer[c].socket, mes, 2) != 2) + return (-1); + + if (mes[0] != NP_CLIENT_MAGIC) + return (-1); + + return ((int) mes[1]); +} + +static bool8 NPServerGetNameFromClient (int c) +{ + if (!npplayer[c].online) + return (false); + + NPNotification("Server: Receiving player name from client %d...", c); + + if (NPServerSendMesToClient(c, kNPServerNameRequest) == false) + { + NPError("Server: Failed to send messsage to client.", 1201); + return (false); + } + + uint8 mes[4]; + uint32 l; + + if (socket_read(npplayer[c].socket, mes, 4) != 4) + { + NPError("Server: Failed to receive name size from client.", 1202); + return (false); + } + + l = READ_LONG(mes + 0); + + if (socket_read(npplayer[c].socket, (uint8 *) npplayer[c].name, l) != (int) l) + { + NPError("Server: Failed to receive name from client.", 1203); + return (false); + } + + npplayer[c].name[l] = 0; + + if (NPServerSendMesToClient(c, kNPServerNameReceived) == false) + { + NPError("Server: Failed to send messsage to client.", 1204); + return (false); + } + + NPNotification("Server: Received player name from client %d.", c); + return (true); + + // next: kNPClientNameSent +} + +static bool8 NPServerSendROMInfoToClient (int c) +{ + if (!npplayer[c].online) + return (false); + + NPNotification("Server: Sending ROM information to client %d...", c); + + if (NPServerSendMesToClient(c, kNPServerROMInfoWillSend) == false) + { + NPError("Server: Failed to send messsage to client.", 1301); + return (false); + } + + if (NPServerGetMesFromClient(c) != kNPClientROMInfoWaiting) + { + NPError("Server: Failed to receive messsage from client.", 1302); + return (false); + } + + uint8 mes[16]; + uint32 l; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + l = strlen(fname); + + WRITE_LONG(mes + 0, Memory.ROMCRC32); + WRITE_LONG(mes + 4, deviceSetting); + WRITE_BYTE(mes + 8, 0); // reserved + WRITE_BYTE(mes + 9, 0); // reserved + WRITE_BYTE(mes + 10, 0); // reserved + WRITE_BYTE(mes + 11, 0); // reserved + WRITE_LONG(mes + 12, l); + + if (socket_write(npplayer[c].socket, mes, 16) != 16) + { + NPError("Server: Failed to send ROM information to client.", 1303); + return (false); + } + + if (socket_write(npplayer[c].socket, (uint8 *) fname, l) != (int) l) + { + NPError("Server: Failed to send ROM name to client.", 1304); + return (false); + } + + NPNotification("Server: Sent ROM information to client %d.", c); + return (true); + + // next: kNPClientROMOpened +} + +static bool8 NPServerSendSRAMToClient (int c) +{ + if (!npplayer[c].online) + return (false); + + NPNotification("Server: Sending SRAM to client %d...", c); + + if (NPServerSendMesToClient(c, kNPServerSRAMWillSend) == false) + { + NPError("Server: Failed to send messsage to client.", 1401); + return (false); + } + + if (NPServerGetMesFromClient(c) != kNPClientSRAMWaiting) + { + NPError("Server: Failed to receive messsage from client.", 1402); + return (false); + } + + uint8 mes[4]; + uint32 sramsize; + + sramsize = Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0; + + WRITE_LONG(mes + 0, sramsize); + + if (socket_write(npplayer[c].socket, mes, 4) != 4) + { + NPError("Server: Failed to send SRAM size to client.", 1403); + return (false); + } + + if (sramsize && (socket_write(npplayer[c].socket, Memory.SRAM, sramsize) != (int) sramsize)) + { + NPError("Server: Failed to send SRAM to client.", 1404); + return (false); + } + + NPNotification("Server: Sent SRAM to client %d.", c); + return (true); + + // next: kNPClientSRAMLoaded +} + +static void NPServerDetachProcessThread (void) +{ + pthread_create(&processthread, NULL, NPServerProcessThread, NULL); + pthread_detach(processthread); +} + +static void * NPServerProcessThread (void *) +{ + NPNotification("Server: Entered process thread.", -1); + + NPServerAllotPlayers(); + NPServerSendPlayerList(); + NPServerSetPhaseSpan(); + NPServerWaitStartReply(); + + npserver.dialogprocess = kNPSDialogDone; + + NPNotification("Server: Exited process thread.", -1); + return (NULL); +} + +static void NPServerAllotPlayers (void) +{ + int n = 1; + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].ready) + { + npplayer[c].client = c; + npplayer[c].player = n++; + } + else + NPServerShutdownClient(c); + } + + npplayer[0].client = 0; + npplayer[0].player = 0; + + npserver.numplayers = n; + + NPNotification("Server: Number of players: %d", n); +} + +static bool8 NPServerSendPlayerListToClient (int c) +{ + if (!npplayer[c].online || !npplayer[c].ready) + return (false); + + NPNotification("Server: Sending player list to client %d...", c); + + if (NPServerSendMesToClient(c, kNPServerPlayerWillSend) == false) + { + NPError("Server: Failed to send messsage to client.", 1601); + return (false); + } + + if (NPServerGetMesFromClient(c) != kNPClientPlayerWaiting) + { + NPError("Server: Failed to receive messsage from client.", 1602); + return (false); + } + + for (int i = 0; i < NP_MAX_PLAYERS; i++) + { + uint8 mes[10]; + uint32 l; + + l = npplayer[i].ready ? strlen(npplayer[i].name) : 0; + + WRITE_BYTE(mes + 0, (i == c)); + WRITE_BYTE(mes + 1, npplayer[i].ready); + WRITE_LONG(mes + 2, npplayer[i].player); + WRITE_LONG(mes + 6, l); + + if (socket_write(npplayer[c].socket, mes, 10) != 10) + { + NPError("Server: Failed to send name size to client.", 1603); + return (false); + } + + if (l && (socket_write(npplayer[c].socket, (uint8 *) npplayer[i].name, l) != (int) l)) + { + NPError("Server: Failed to send name to client.", 1604); + return (false); + } + } + + NPNotification("Server: Sent player list to client %d.", c); + return (true); +} + +static void NPServerSendPlayerList (void) +{ + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].ready) + { + if (NPServerSendPlayerListToClient(c) == false) + NPServerShutdownClient(c); + } + } +} + +static void NPServerSetPhaseSpan (void) +{ + struct timeval tv1, tv2; + uint8 mes[21]; + uint32 dus, dusmax; + int l = npserver.numplayers * 4 + 1; + + NPNotification("Server: Testing sending / receiving pad states...", -1); + + dusmax = 0; + + for (int n = 0; n < 5; n++) + { + gettimeofday(&tv1, NULL); + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].ready) + { + if (socket_write(npplayer[c].socket, mes, l) != l) + NPServerShutdownClient(c); + } + } + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].ready) + { + if (socket_read(npplayer[c].socket, mes, 5) != 5) + NPServerShutdownClient(c); + } + } + + gettimeofday(&tv2, NULL); + + dus = (tv2.tv_sec * 1000000 + tv2.tv_usec) - (tv1.tv_sec * 1000000 + tv1.tv_usec); + + NPNotification(" %d [usec]", dus); + + if (dusmax < dus) + dusmax = dus; + + usleep(50000); + } + + NPNotification("Server: Tested sending / receiving pad states.", -1); + + npserver.phasespan = (uint32) Memory.ROMFramesPerSecond * dusmax / 1000000 + 1; + if (npserver.phasespan > (uint32) Memory.ROMFramesPerSecond) + npserver.phasespan = (uint32) Memory.ROMFramesPerSecond; + + NPNotification(" phase span: %d (frames)", npserver.phasespan); + + NPNotification("Server: Sending phase span value to clients...", -1); + + WRITE_LONG(mes + 0, npserver.phasespan); + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].ready) + { + if (socket_write(npplayer[c].socket, mes, 4) != 4) + NPServerShutdownClient(c); + } + } + + NPNotification("Server: Sent phase span value to clients.", -1); +} + +static void NPServerWaitStartReply (void) +{ + struct timeval timeout; + fd_set readfds; + int maxfd; + bool8 allok, flag[NP_MAX_PLAYERS]; + + NPNotification("Server: Waiting clients reply to start...", -1); + + allok = false; + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + flag[c] = false; + + while (!allok) + { + FD_ZERO(&readfds); + maxfd = 0; + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].ready) + { + FD_SET(npplayer[c].socket, &readfds); + if (maxfd < npplayer[c].socket) + maxfd = npplayer[c].socket; + } + } + + timeout.tv_sec = 0; + timeout.tv_usec = 50000; + + if (select(maxfd + 1, &readfds, NULL, NULL, &timeout) > 0) + { + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].ready) + { + if (FD_ISSET(npplayer[c].socket, &readfds)) + { + if (NPServerGetMesFromClient(c) == kNPClientStartWait) + flag[c] = true; + else + NPServerShutdownClient(c); + } + } + } + } + + allok = true; + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + if (npplayer[c].ready && !flag[c]) + allok = false; + } + + NPNotification("Server: All clients are ready to start netplay.", -1); +} + +void NPServerDetachNetPlayThread (void) +{ + NPNotification("Server: Detaching pad threads...", -1); + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].ready) + { + npplayer[c].padloop = true; + npplayer[c].exitsgn = false; + + sememu[c] = sem_open(n_sememu[c], O_CREAT, 0600, 0); + sempad[c] = sem_open(n_sempad[c], O_CREAT, 0600, 0); + + pthread_create(&padthread[c], NULL, NPServerNetPlayThread, &(npplayer[c].client)); + pthread_detach(padthread[c]); + } + } + + NPNotification("Server: Detached pad threads.", -1); +} + +void NPServerStopNetPlayThread (void) +{ + NPNotification("Server: Stopping pad threads...", -1); + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].ready) + { + npplayer[c].padloop = false; + sem_post(sempad[c]); + + while (!npplayer[c].exitsgn) + sleep(0); + + sem_unlink(n_sememu[c]); + sem_unlink(n_sempad[c]); + sem_close(sememu[c]); + sem_close(sempad[c]); + } + } + + NPNotification("Server: Stopped pad threads.", -1); +} + +void NPServerStartClients (void) +{ + NPNotification("Server: Sending start flag to clients...", -1); + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + { + if (npplayer[c].ready) + { + if (NPServerSendMesToClient(c, kNPServerStart) == false) + NPServerShutdownClient(c); + } + } + + NPNotification("Server: Sent start flag to clients.", -1); + + npserver.phasecount = 0; + npserver.header = 0; + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + if (npplayer[c].ready) + sem_post(sempad[c]); + + NPNotification("Server: Netplay started.", -1); +} + +static void * NPServerNetPlayThread (void *p) +{ + uint8 mes[NP_MAX_PLAYERS * 64 * 4 + 1]; + uint8 count = 0; + int c = *((int *) p), l; + + NPNotification("Server: Entered pad thread for client %d.", c); + + while (npplayer[c].padloop) + { + sem_wait(sempad[c]); + + WRITE_BYTE(mes + 0, count | npserver.header); + + for (int i = 0; i < npserver.numplayers; i++) + for (uint32 j = 0; j < npserver.phasespan; j++) + WRITE_LONG(mes + (i * npserver.phasespan + j) * 4 + 1, npsendpad[i][j]); + + l = npserver.numplayers * npserver.phasespan * 4 + 1; + if (socket_write(npplayer[c].socket, mes, l) != l) + { + NPServerShutdownClient(c); + npplayer[c].exitsgn = true; + sem_post(sememu[c]); + pthread_exit(NULL); + } + + l = npserver.phasespan * 4 + 1; + if (socket_read(npplayer[c].socket, mes, l) != l) + { + NPServerShutdownClient(c); + npplayer[c].exitsgn = true; + sem_post(sememu[c]); + pthread_exit(NULL); + } + + for (uint32 j = 0; j < npserver.phasespan; j++) + nprecvpad[npplayer[c].player][j] = READ_LONG(mes + j * 4 + 1); + + if ((mes[0] & 0xF) != count) + NPNotification("Server: Warning: Failed to synchronize client %d.", c); + + count = (count + 1) & 0xF; + + sem_post(sememu[c]); + } + + npplayer[c].exitsgn = true; + + NPNotification("Server: Exited pad thread for client %d.", c); + return (NULL); +} + +void NPServerProcessInput (void) +{ + static uint8 header = 0; + static uint32 pos = 0; + KeyMap myKeys; + + if (npserver.phasecount == 0) + { + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + if (npplayer[c].ready) + sem_wait(sememu[c]); + + for (uint32 j = 0; j < npserver.phasespan; j++) + nprecvpad[0][j] = npcachpad[j]; + + for (int i = 0; i < npserver.numplayers; i++) + { + for (uint32 j = 0; j < npserver.phasespan; j++) + { + npactvpad[i][j] = npsendpad[i][j]; + npsendpad[i][j] = nprecvpad[i][j]; + } + } + + if (npserver.header & 0x80) + { + for (int i = 0; i < npserver.numplayers; i++) + { + npactvpad[i][npserver.phasespan] = 0; + npsendpad[i][npserver.phasespan] = 0; + } + + npserver.phasespan++; + if (npserver.phasespan > (uint32) Memory.ROMFramesPerSecond) + npserver.phasespan = (uint32) Memory.ROMFramesPerSecond; + + char str[256]; + sprintf(str, "delay: %d", npserver.phasespan); + S9xMessage(0, 0, str); + } + else + if (npserver.header & 0x40) + { + npserver.phasespan--; + if (npserver.phasespan == 0) + npserver.phasespan = 1; + + char str[256]; + sprintf(str, "delay: %d", npserver.phasespan); + S9xMessage(0, 0, str); + } + + npserver.header = header; + header = 0; + pos = 0; + } + + for (int i = 0; i < npserver.numplayers; i++) + { + controlPad[i] = npactvpad[i][pos]; + ControlPadFlagsToS9xReportButtons(i, controlPad[i]); + } + + GetKeys(myKeys); + + if (ISpKeyIsPressed(kISpEsc) || KeyIsPressed(myKeys, keyCode[kKeyEsc])) + { + if (s9xthreadrunning) + { + if (!eventQueued) + { + PostQueueToSubEventLoop(); + eventQueued = true; + } + } + else + running = false; + + return; + } + + uint32 pad = 0; + + JoypadScanDirection(0, &pad); + if (ISpKeyIsPressed(kISp1PR )) pad |= 0x0010; + if (ISpKeyIsPressed(kISp1PL )) pad |= 0x0020; + if (ISpKeyIsPressed(kISp1PX )) pad |= 0x0040; + if (ISpKeyIsPressed(kISp1PA )) pad |= 0x0080; + if (ISpKeyIsPressed(kISp1PStart )) pad |= 0x1000; + if (ISpKeyIsPressed(kISp1PSelect)) pad |= 0x2000; + if (ISpKeyIsPressed(kISp1PY )) pad |= 0x4000; + if (ISpKeyIsPressed(kISp1PB )) pad |= 0x8000; + + if (KeyIsPressed(myKeys, keyCode[k1PR] )) pad |= 0x0010; + if (KeyIsPressed(myKeys, keyCode[k1PL] )) pad |= 0x0020; + if (KeyIsPressed(myKeys, keyCode[k1PX] )) pad |= 0x0040; + if (KeyIsPressed(myKeys, keyCode[k1PA] )) pad |= 0x0080; + if (KeyIsPressed(myKeys, keyCode[k1PRight] )) pad |= 0x0100; + if (KeyIsPressed(myKeys, keyCode[k1PLeft] )) pad |= 0x0200; + if (KeyIsPressed(myKeys, keyCode[k1PDown] )) pad |= 0x0400; + if (KeyIsPressed(myKeys, keyCode[k1PUp] )) pad |= 0x0800; + if (KeyIsPressed(myKeys, keyCode[k1PStart] )) pad |= 0x1000; + if (KeyIsPressed(myKeys, keyCode[k1PSelect])) pad |= 0x2000; + if (KeyIsPressed(myKeys, keyCode[k1PY] )) pad |= 0x4000; + if (KeyIsPressed(myKeys, keyCode[k1PB] )) pad |= 0x8000; + + npcachpad[pos] = pad; + + if (KeyIsPressed(myKeys, keyCode[k2PR])) header |= 0x80; + if (KeyIsPressed(myKeys, keyCode[k2PL])) header |= 0x40; + + if (npserver.phasecount == 0) + { + npserver.phasecount = npserver.phasespan; + + for (int c = 1; c <= NP_MAX_CLIENTS; c++) + if (npplayer[c].ready) + sem_post(sempad[c]); + } + + npserver.phasecount--; + pos++; +} diff --git a/macosx/mac-server.h b/macosx/mac-server.h new file mode 100644 index 00000000..d94bc10b --- /dev/null +++ b/macosx/mac-server.h @@ -0,0 +1,203 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_server_h_ +#define _mac_server_h_ + +void NPServerInit (void); +void NPServerStopServer (void); +void NPServerDetachNetPlayThread (void); +void NPServerStopNetPlayThread (void); +void NPServerStartClients (void); +void NPServerProcessInput (void); +bool8 NPServerStartServer (int); +bool8 NPServerDialog (void); + +#endif diff --git a/macosx/mac-snes9x.cpp b/macosx/mac-snes9x.cpp new file mode 100644 index 00000000..99e62f84 --- /dev/null +++ b/macosx/mac-snes9x.cpp @@ -0,0 +1,635 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "snes9x.h" +#include "memmap.h" +#include "apu.h" +#include "snapshot.h" +#include "cheats.h" +#include "movie.h" +#include "display.h" + +#include + +#include "mac-prefix.h" +#include "mac-audio.h" +#include "mac-cart.h" +#include "mac-cheatfinder.h" +#include "mac-dialog.h" +#include "mac-file.h" +#include "mac-multicart.h" +#include "mac-os.h" +#include "mac-quicktime.h" +#include "mac-screenshot.h" +#include "mac-stringtools.h" +#include "mac-snes9x.h" + +extern wchar_t macRecordWChar[MOVIE_MAX_METADATA]; + + +void SNES9X_Go (void) +{ + if (cartOpen) + running = true; +} + +bool8 SNES9X_OpenCart (FSRef *inRef) +{ + OSStatus err; + FSCatalogInfo info; + FSRef cartRef; + char filename[PATH_MAX + 1]; + + DeinitGameWindow(); + + if (cartOpen) + { + SNES9X_SaveSRAM(); + S9xResetSaveTimer(false); + S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); + } + + ResetCheatFinder(); + + if (!inRef) + { + if (!NavOpenROMImage(&cartRef)) + { + cartOpen = false; + return (false); + } + } + else + cartRef = *inRef; + + spcFileCount = pngFileCount = 0; + + err = FSGetCatalogInfo(&cartRef, kFSCatInfoVolume, &info, NULL, NULL, NULL); + lockedROMMedia = IsLockedMedia(info.volume); + + Settings.ForceLoROM = (romDetect == kLoROMForce ); + Settings.ForceHiROM = (romDetect == kHiROMForce ); + Settings.ForceHeader = (headerDetect == kHeaderForce ); + Settings.ForceNoHeader = (headerDetect == kNoHeaderForce ); + Settings.ForceInterleaved = (interleaveDetect == kInterleaveForce ); + Settings.ForceInterleaved2 = (interleaveDetect == kInterleave2Force ); + Settings.ForceInterleaveGD24 = (interleaveDetect == kInterleaveGD24 ); + Settings.ForceNotInterleaved = (interleaveDetect == kNoInterleaveForce); + Settings.ForcePAL = (videoDetect == kPALForce ); + Settings.ForceNTSC = (videoDetect == kNTSCForce ); + + GFX.InfoString = NULL; + GFX.InfoStringTimeout = 0; + + S9xResetSaveTimer(true); + + err = FSRefMakePath(&cartRef, (unsigned char *) filename, PATH_MAX); + + SNES9X_InitSound(); + + if (Memory.LoadROM(filename)) + { + cartOpen = true; + + SNES9X_LoadSRAM(); + + ChangeTypeAndCreator(filename, 'CART', '~9X~'); + + AddRecentItem(&cartRef); + BuildRecentMenu(); + + ApplyNSRTHeaderControllers(); + + for (int a = 0; a < MAC_MAX_PLAYERS; a++) + for (int b = 0; b < 12; b++) + autofireRec[a].nextTime[b] = 0; + + return (true); + } + else + { + cartOpen = false; + return (false); + } +} + +bool8 SNES9X_OpenMultiCart (void) +{ + Boolean r; + char cart[2][PATH_MAX + 1]; + + DeinitGameWindow(); + + if (cartOpen) + { + SNES9X_SaveSRAM(); + S9xResetSaveTimer(false); + S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); + } + + ResetCheatFinder(); + + if (!MultiCartDialog()) + { + cartOpen = false; + return (false); + } + + spcFileCount = pngFileCount = 0; + + Settings.ForceHeader = (headerDetect == kHeaderForce ); + Settings.ForceNoHeader = (headerDetect == kNoHeaderForce); + Settings.ForcePAL = (videoDetect == kPALForce ); + Settings.ForceNTSC = (videoDetect == kNTSCForce ); + + GFX.InfoString = NULL; + GFX.InfoStringTimeout = 0; + + S9xResetSaveTimer(true); + + for (int i = 0; i < 2; i++) + { + cart[i][0] = 0; + if (multiCartPath[i]) + r = CFStringGetCString(multiCartPath[i], cart[i], PATH_MAX, MAC_PATH_ENCODING); + } + + SNES9X_InitSound(); + + if (Memory.LoadMultiCart(cart[0], cart[1])) + { + cartOpen = true; + + SNES9X_LoadSRAM(); + + for (int i = 0; i < 2; i++) + { + if (cart[i][0]) + ChangeTypeAndCreator(cart[i], 'CART', '~9X~'); + } + + ApplyNSRTHeaderControllers(); + + for (int a = 0; a < MAC_MAX_PLAYERS; a++) + for (int b = 0; b < 12; b++) + autofireRec[a].nextTime[b] = 0; + + return (true); + } + else + { + cartOpen = false; + return (false); + } +} + +void SNES9X_LoadSRAM (void) +{ + if (cartOpen) + Memory.LoadSRAM(S9xGetFilename(".srm", SRAM_DIR)); +} + +void SNES9X_SaveSRAM (void) +{ + const char *sramFilename; + + if (cartOpen) + { + sramFilename = S9xGetFilename(".srm", SRAM_DIR); + Memory.SaveSRAM(sramFilename); + ChangeTypeAndCreator(sramFilename, 'SRAM', '~9X~'); + } +} + +void SNES9X_Reset (void) +{ + if (cartOpen) + { + SNES9X_SaveSRAM(); + S9xReset(); + SNES9X_LoadSRAM(); + } +} + +void SNES9X_SoftReset (void) +{ + if (cartOpen) + { + SNES9X_SaveSRAM(); + S9xSoftReset(); + SNES9X_LoadSRAM(); + } +} + +bool8 SNES9X_Freeze (void) +{ + OSStatus err; + FSRef ref; + int which; + const char *filename; + + if (cartOpen) + { + MacStopSound(); + + which = PromptFreezeDefrost(true); + + if (which >= 0) + { + filename = S9xGetFreezeFilename(which); + + err = FSPathMakeRef((unsigned char *) filename, &ref, NULL); + if (!err) + FSDeleteObject(&ref); + + S9xFreezeGame(filename); + ChangeTypeAndCreator(filename, 'SAVE', '~9X~'); + err = FSPathMakeRef((unsigned char *) filename, &ref, NULL); + WriteThumbnailToResourceFork(&ref, 128, 120); + + SNES9X_Go(); + + MacStartSound(); + return (true); + } + else + { + MacStartSound(); + return (false); + } + } + else + return (false); +} + +bool8 SNES9X_Defrost (void) +{ + int which; + const char *filename; + + if (cartOpen) + { + MacStopSound(); + + which = PromptFreezeDefrost(false); + + if (which >= 0) + { + filename = S9xGetFreezeFilename(which); + S9xUnfreezeGame(filename); + + SNES9X_Go(); + + MacStartSound(); + return (true); + } + else + { + MacStartSound(); + return (false); + } + } + else + return (false); +} + +bool8 SNES9X_FreezeTo (void) +{ + OSStatus err; + FSRef ref; + char filename[PATH_MAX + 1]; + + if (cartOpen) + { + if (NavFreezeTo(filename)) + { + err = FSPathMakeRef((unsigned char *) filename, &ref, NULL); + if (!err) + FSDeleteObject(&ref); + + S9xFreezeGame(filename); + ChangeTypeAndCreator(filename, 'SAVE', '~9X~'); + err = FSPathMakeRef((unsigned char *) filename, &ref, NULL); + WriteThumbnailToResourceFork(&ref, 128, 120); + + return (true); + } + } + + return (false); +} + +bool8 SNES9X_DefrostFrom (void) +{ + char filename[PATH_MAX + 1]; + + if (cartOpen) + { + if (NavDefrostFrom(filename)) + { + S9xUnfreezeGame(filename); + + SNES9X_Go(); + + return (true); + } + } + + return (false); +} + +bool8 SNES9X_RecordMovie (void) +{ + OSStatus err; + FSRef ref; + char filename[PATH_MAX + 1]; + + if (cartOpen) + { + if (NavRecordMovieTo(filename)) + { + err = FSPathMakeRef((unsigned char *) filename, &ref, NULL); + if (!err) + FSDeleteObject(&ref); + + int r; + uint8 opt = 0, mask = 0; + + for (int i = 0; i <= 4; i++) + if (macRecordFlag & (1 << i)) + mask |= (1 << i); + + if (macRecordFlag & (1 << 5)) + opt |= MOVIE_OPT_FROM_RESET; + else + opt |= MOVIE_OPT_FROM_SNAPSHOT; + + r = S9xMovieCreate(filename, mask, opt, macRecordWChar, wcslen(macRecordWChar)); + if (r == SUCCESS) + { + ChangeTypeAndCreator(filename, 'SMOV', '~9X~'); + + if ((macRecordFlag & (1 << 5)) == 0) + { + err = FSPathMakeRef((unsigned char *) filename, &ref, NULL); + WriteThumbnailToResourceFork(&ref, 128, 120); + } + + SNES9X_Go(); + + return (true); + } + } + } + + return (false); +} + +bool8 SNES9X_PlayMovie (void) +{ + char filename[PATH_MAX + 1]; + + if (cartOpen) + { + if (NavPlayMovieFrom(filename)) + { + int r; + + r = S9xMovieOpen(filename, macPlayFlag & 1); + if (r == SUCCESS) + { + SNES9X_Go(); + + return (true); + } + } + } + + return (false); +} + +bool8 SNES9X_QTMovieRecord (void) +{ + char filename[PATH_MAX + 1]; + + if (cartOpen) + { + if (NavQTMovieRecordTo(filename)) + { + MacQTStartRecording(filename); + macQTRecord = true; + SNES9X_Go(); + + return (true); + } + } + + macQTRecord = false; + + return (false); +} + +void SNES9X_Quit (void) +{ + DeinitGameWindow(); + + if (cartOpen) + { + SNES9X_SaveSRAM(); + S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); + } + + finished = true; +} + +void SNES9X_InitSound (void) +{ + S9xInitSound(macSoundBuffer_ms, macSoundLagEnable ? macSoundBuffer_ms / 2 : 0); +} diff --git a/macosx/mac-snes9x.h b/macosx/mac-snes9x.h new file mode 100644 index 00000000..ae0cf2b7 --- /dev/null +++ b/macosx/mac-snes9x.h @@ -0,0 +1,241 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_snes9x_h_ +#define _mac_snes9x_h_ + +enum +{ + kAutoROMType = 0, + kLoROMForce, + kHiROMForce +}; + +enum +{ + kAutoInterleave = 0, + kNoInterleaveForce, + kInterleaveForce, + kInterleave2Force, + kInterleaveGD24 +}; + +enum +{ + kAutoVideo = 0, + kPALForce, + kNTSCForce +}; + +enum +{ + kAutoHeader = 0, + kNoHeaderForce, + kHeaderForce +}; + +void SNES9X_Go (void); +void SNES9X_LoadSRAM (void); +void SNES9X_SaveSRAM (void); +void SNES9X_Reset (void); +void SNES9X_SoftReset (void); +void SNES9X_Quit (void); +void SNES9X_InitSound (void); +bool8 SNES9X_OpenCart (FSRef *); +bool8 SNES9X_OpenMultiCart (void); +bool8 SNES9X_Freeze (void); +bool8 SNES9X_FreezeTo (void); +bool8 SNES9X_Defrost (void); +bool8 SNES9X_DefrostFrom (void); +bool8 SNES9X_RecordMovie (void); +bool8 SNES9X_PlayMovie (void); +bool8 SNES9X_QTMovieRecord (void); + +#endif diff --git a/macosx/mac-stringtools.cpp b/macosx/mac-stringtools.cpp new file mode 100644 index 00000000..7de4c273 --- /dev/null +++ b/macosx/mac-stringtools.cpp @@ -0,0 +1,280 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#include "mac-prefix.h" +#include "mac-stringtools.h" + + +CFStringRef CopyFixNameStrings (const char *itext, uint8 region) +{ + CFStringRef str = NULL; + + if (region != 0) // non-Japanese + { + char btext[256]; + size_t len = strlen(itext); + + btext[len] = 0; + for (unsigned int i = 0; i < len ; i++) + btext[i] = isgraph(itext[i]) ? itext[i] : ' '; + + str = CFStringCreateWithCString(kCFAllocatorDefault, btext, kCFStringEncodingNonLossyASCII); + } + else + str = CFStringCreateWithCString(kCFAllocatorDefault, itext, kCFStringEncodingMacJapanese); // assuming Shift-JIS + + return (str); +} + +#ifdef MAC_TIGER_PANTHER_SUPPORT +OSStatus CreateATSUIStyleFromFontFullNameAndSize (const char *fontName, int fontSize, ATSUStyle *theStyle) +{ + OSStatus err; + ATSUStyle localStyle; + ATSUFontID atsuFont; + Fixed atsuSize; + + ATSUAttributeTag theTags[] = { kATSUFontTag, kATSUSizeTag }; + ByteCount theSizes[] = { sizeof(ATSUFontID), sizeof(Fixed) }; + ATSUAttributeValuePtr theValues[] = { NULL, NULL }; + + atsuFont = 0; + atsuSize = FixRatio(fontSize, 1); + localStyle = NULL; + + theValues[0] = &atsuFont; + theValues[1] = &atsuSize; + + err = ATSUFindFontFromName(fontName, strlen(fontName), kFontFullName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &atsuFont); + if (err == noErr) + { + err = ATSUCreateStyle(&localStyle); + if (err == noErr) + { + err = ATSUSetAttributes(localStyle, sizeof(theTags) / sizeof(theTags[0]), theTags, theSizes, theValues); + if (err == noErr) + { + *theStyle = localStyle; + return (noErr); + } + } + } + + if (localStyle != NULL) + err = ATSUDisposeStyle(localStyle); + + return (err); +} +#endif + +const char * GetMultiByteCharacters (CFStringRef inText, int cutAt) +{ + static char buf[256]; + + CFStringRef str; + + buf[0] = 0; + + if (!inText || (cutAt < 1)) + return (buf); + + if (CFStringGetCString(inText, buf, sizeof(buf), CFStringGetSystemEncoding())) + { + buf[cutAt] = 0; + + str = CFStringCreateWithCString(kCFAllocatorDefault, buf, CFStringGetSystemEncoding()); + if (str) + CFRelease(str); + else + buf[cutAt - 1] = 0; + } + + return (buf); +} diff --git a/macosx/mac-stringtools.h b/macosx/mac-stringtools.h new file mode 100644 index 00000000..ec89d955 --- /dev/null +++ b/macosx/mac-stringtools.h @@ -0,0 +1,200 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/*********************************************************************************** + SNES9X for Mac OS (c) Copyright John Stiles + + Snes9x for Mac OS X + + (c) Copyright 2001 - 2010 zones + (c) Copyright 2002 - 2005 107 + (c) Copyright 2002 PB1400c + (c) Copyright 2004 Alexander and Sander + (c) Copyright 2004 - 2005 Steven Seeger + (c) Copyright 2005 Ryan Vogt + ***********************************************************************************/ + + +#ifndef _mac_stringtools_h_ +#define _mac_stringtools_h_ + +CFStringRef CopyFixNameStrings (const char *, uint8); +const char * GetMultiByteCharacters (CFStringRef, int); +#ifdef MAC_TIGER_PANTHER_SUPPORT +OSStatus CreateATSUIStyleFromFontFullNameAndSize (const char *, int, ATSUStyle *); +#endif + +#endif diff --git a/macosx/musicbox_indicator.png b/macosx/musicbox_indicator.png new file mode 100644 index 00000000..58c232d2 Binary files /dev/null and b/macosx/musicbox_indicator.png differ diff --git a/macosx/musicbox_ledoff.icns b/macosx/musicbox_ledoff.icns new file mode 100644 index 00000000..3d3f53ad Binary files /dev/null and b/macosx/musicbox_ledoff.icns differ diff --git a/macosx/musicbox_ledon.icns b/macosx/musicbox_ledon.icns new file mode 100644 index 00000000..de699f95 Binary files /dev/null and b/macosx/musicbox_ledon.icns differ diff --git a/macosx/snes9x.xcodeproj/project.pbxproj b/macosx/snes9x.xcodeproj/project.pbxproj new file mode 100644 index 00000000..af2a5788 --- /dev/null +++ b/macosx/snes9x.xcodeproj/project.pbxproj @@ -0,0 +1,2490 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + CF047D38109D0E0600FD0754 /* 65c816.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0615A0526CCB900A80003 /* 65c816.h */; }; + CF047D3B109D0E0600FD0754 /* bsx.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2F381A09B17E9E0078DCA7 /* bsx.h */; }; + CF047D3C109D0E0600FD0754 /* c4.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061600526CCB900A80003 /* c4.h */; }; + CF047D3D109D0E0600FD0754 /* cheats.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061640526CCB900A80003 /* cheats.h */; }; + CF047D3E109D0E0600FD0754 /* controls.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9308F8D6C40072CDFB /* controls.h */; }; + CF047D3F109D0E0600FD0754 /* cpuaddr.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616A0526CCB900A80003 /* cpuaddr.h */; }; + CF047D40109D0E0600FD0754 /* cpuexec.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616C0526CCB900A80003 /* cpuexec.h */; }; + CF047D41109D0E0600FD0754 /* cpumacro.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616D0526CCB900A80003 /* cpumacro.h */; }; + CF047D42109D0E0600FD0754 /* cpuops.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616F0526CCB900A80003 /* cpuops.h */; }; + CF047D43109D0E0600FD0754 /* crosshairs.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9D08F8D73A0072CDFB /* crosshairs.h */; }; + CF047D44109D0E0600FD0754 /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = EA6E6C0E08F9734500CB3555 /* debug.h */; }; + CF047D45109D0E0600FD0754 /* display.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061730526CCB900A80003 /* display.h */; }; + CF047D46109D0E0600FD0754 /* dma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061750526CCB900A80003 /* dma.h */; }; + CF047D47109D0E0600FD0754 /* dsp.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5D3E100FAFD34200340007 /* dsp.h */; }; + CF047D48109D0E0600FD0754 /* font.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0617A0526CCB900A80003 /* font.h */; }; + CF047D49109D0E0600FD0754 /* fxemu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0617D0526CCB900A80003 /* fxemu.h */; }; + CF047D4A109D0E0600FD0754 /* fxinst.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0617F0526CCB900A80003 /* fxinst.h */; }; + CF047D4B109D0E0600FD0754 /* getset.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061800526CCB900A80003 /* getset.h */; }; + CF047D4C109D0E0600FD0754 /* gfx.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061820526CCB900A80003 /* gfx.h */; }; + CF047D4D109D0E0600FD0754 /* language.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9508F8D6E00072CDFB /* language.h */; }; + CF047D4E109D0E0600FD0754 /* logger.h in Headers */ = {isa = PBXBuildFile; fileRef = EA00D01F0A5A998F000C58E0 /* logger.h */; }; + CF047D4F109D0E0600FD0754 /* memmap.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061B10526CCB900A80003 /* memmap.h */; }; + CF047D50109D0E0600FD0754 /* messages.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061B20526CCB900A80003 /* messages.h */; }; + CF047D51109D0E0600FD0754 /* missing.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061B30526CCB900A80003 /* missing.h */; }; + CF047D52109D0E0600FD0754 /* movie.h in Headers */ = {isa = PBXBuildFile; fileRef = EA813E86066F5076004F99B5 /* movie.h */; }; + CF047D53109D0E0600FD0754 /* obc1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C40526CCB900A80003 /* obc1.h */; }; + CF047D54109D0E0600FD0754 /* pixform.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C60526CCB900A80003 /* pixform.h */; }; + CF047D55109D0E0600FD0754 /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C70526CCB900A80003 /* port.h */; }; + CF047D56109D0E0600FD0754 /* ppu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C90526CCB900A80003 /* ppu.h */; }; + CF047D57109D0E0600FD0754 /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* reader.h */; }; + CF047D58109D0E0600FD0754 /* sa1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CC0526CCB900A80003 /* sa1.h */; }; + CF047D59109D0E0600FD0754 /* sar.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CE0526CCB900A80003 /* sar.h */; }; + CF047D5A109D0E0600FD0754 /* screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D00526CCB900A80003 /* screenshot.h */; }; + CF047D5B109D0E0600FD0754 /* sdd1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D20526CCB900A80003 /* sdd1.h */; }; + CF047D5C109D0E0600FD0754 /* sdd1emu.h in Headers */ = {isa = PBXBuildFile; fileRef = EA22EFA2053EEDE500A80003 /* sdd1emu.h */; }; + CF047D5D109D0E0600FD0754 /* seta.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D50526CCB900A80003 /* seta.h */; }; + CF047D5E109D0E0600FD0754 /* snapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061DC0526CCB900A80003 /* snapshot.h */; }; + CF047D5F109D0E0600FD0754 /* snes9x.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061DE0526CCB900A80003 /* snes9x.h */; }; + CF047D62109D0E0600FD0754 /* spc7110.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061E60526CCB900A80003 /* spc7110.h */; }; + CF047D63109D0E0600FD0754 /* srtc.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061EA0526CCB900A80003 /* srtc.h */; }; + CF047D64109D0E0600FD0754 /* tile.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061EC0526CCB900A80003 /* tile.h */; }; + CF047D65109D0E0600FD0754 /* 2xsai.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B20EA24C36005957E4 /* 2xsai.h */; }; + CF047D66109D0E0600FD0754 /* blit.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B40EA24C36005957E4 /* blit.h */; }; + CF047D67109D0E0600FD0754 /* epx.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B60EA24C36005957E4 /* epx.h */; }; + CF047D68109D0E0600FD0754 /* hq2x.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B80EA24C36005957E4 /* hq2x.h */; }; + CF047D69109D0E0600FD0754 /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518E50EBCB5B1008379F6 /* crypt.h */; }; + CF047D6A109D0E0600FD0754 /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518D60EBCB4CA008379F6 /* ioapi.h */; }; + CF047D6B109D0E0600FD0754 /* unzip.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518DA0EBCB4D2008379F6 /* unzip.h */; }; + CF047D6C109D0E0600FD0754 /* 7z.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5D907609F76001BAB8B /* 7z.h */; }; + CF047D6D109D0E0600FD0754 /* aribitcd.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DB07609F76001BAB8B /* aribitcd.h */; }; + CF047D6E109D0E0600FD0754 /* ariconst.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DC07609F76001BAB8B /* ariconst.h */; }; + CF047D6F109D0E0600FD0754 /* ariprice.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DD07609F76001BAB8B /* ariprice.h */; }; + CF047D70109D0E0600FD0754 /* btreecd.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DE07609F76001BAB8B /* btreecd.h */; }; + CF047D71109D0E0600FD0754 /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E007609F76001BAB8B /* crc32.h */; }; + CF047D72109D0E0600FD0754 /* iiostrm.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E207609F76001BAB8B /* iiostrm.h */; }; + CF047D73109D0E0600FD0754 /* inbyte.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E407609F76001BAB8B /* inbyte.h */; }; + CF047D74109D0E0600FD0754 /* jma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E607609F76001BAB8B /* jma.h */; }; + CF047D75109D0E0600FD0754 /* lencoder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E707609F76001BAB8B /* lencoder.h */; }; + CF047D76109D0E0600FD0754 /* litcoder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E807609F76001BAB8B /* litcoder.h */; }; + CF047D77109D0E0600FD0754 /* lzma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EA07609F76001BAB8B /* lzma.h */; }; + CF047D78109D0E0600FD0754 /* lzmadec.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EC07609F76001BAB8B /* lzmadec.h */; }; + CF047D79109D0E0600FD0754 /* portable.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5ED07609F76001BAB8B /* portable.h */; }; + CF047D7A109D0E0600FD0754 /* rcdefs.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EE07609F76001BAB8B /* rcdefs.h */; }; + CF047D7B109D0E0600FD0754 /* rngcoder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EF07609F76001BAB8B /* rngcoder.h */; }; + CF047D7C109D0E0600FD0754 /* s9x-jma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5F107609F76001BAB8B /* s9x-jma.h */; }; + CF047D7D109D0E0600FD0754 /* winout.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5F307609F76001BAB8B /* winout.h */; }; + CF047D7E109D0E0600FD0754 /* mac-appleevent.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB66D04AC7FCD00A80003 /* mac-appleevent.h */; }; + CF047D7F109D0E0600FD0754 /* mac-audio.h in Headers */ = {isa = PBXBuildFile; fileRef = EADE6349052E5C5300A80003 /* mac-audio.h */; }; + CF047D80109D0E0600FD0754 /* mac-cart.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67104AC7FCE00A80003 /* mac-cart.h */; }; + CF047D81109D0E0600FD0754 /* mac-cheat.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67304AC7FCE00A80003 /* mac-cheat.h */; }; + CF047D82109D0E0600FD0754 /* mac-cheatfinder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67504AC7FCE00A80003 /* mac-cheatfinder.h */; }; + CF047D83109D0E0600FD0754 /* mac-client.h in Headers */ = {isa = PBXBuildFile; fileRef = EA1605540639E937004412AB /* mac-client.h */; }; + CF047D84109D0E0600FD0754 /* mac-cocoatools.h in Headers */ = {isa = PBXBuildFile; fileRef = EA85C24D0B4EC13300F5F9C9 /* mac-cocoatools.h */; }; + CF047D85109D0E0600FD0754 /* mac-controls.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809F9D08F8F2190072CDFB /* mac-controls.h */; }; + CF047D86109D0E0600FD0754 /* mac-coreimage.h in Headers */ = {isa = PBXBuildFile; fileRef = EA0C952D08364A4A009307B4 /* mac-coreimage.h */; }; + CF047D87109D0E0600FD0754 /* mac-dialog.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67804AC7FCE00A80003 /* mac-dialog.h */; }; + CF047D88109D0E0600FD0754 /* mac-file.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2DBC0A0510ABE700A80003 /* mac-file.h */; }; + CF047D89109D0E0600FD0754 /* mac-gworld.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67A04AC7FCE00A80003 /* mac-gworld.h */; }; + CF047D8A109D0E0600FD0754 /* mac-joypad.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67C04AC7FCE00A80003 /* mac-joypad.h */; }; + CF047D8B109D0E0600FD0754 /* mac-keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67E04AC7FCE00A80003 /* mac-keyboard.h */; }; + CF047D8C109D0E0600FD0754 /* mac-multicart.h in Headers */ = {isa = PBXBuildFile; fileRef = EA26BBD90B36771500A570B5 /* mac-multicart.h */; }; + CF047D8D109D0E0600FD0754 /* mac-musicbox.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68004AC7FCE00A80003 /* mac-musicbox.h */; }; + CF047D8E109D0E0600FD0754 /* mac-netplay.h in Headers */ = {isa = PBXBuildFile; fileRef = EA16053E0639E655004412AB /* mac-netplay.h */; }; + CF047D8F109D0E0600FD0754 /* mac-os.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68204AC7FCE00A80003 /* mac-os.h */; }; + CF047D90109D0E0600FD0754 /* mac-prefs.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68504AC7FCE00A80003 /* mac-prefs.h */; }; + CF047D91109D0E0600FD0754 /* mac-quicktime.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7F17F06CB3D4A00C2D767 /* mac-quicktime.h */; }; + CF047D92109D0E0600FD0754 /* mac-render.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2DBC090510ABE700A80003 /* mac-render.h */; }; + CF047D93109D0E0600FD0754 /* mac-screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2DBC070510ABE700A80003 /* mac-screenshot.h */; }; + CF047D94109D0E0600FD0754 /* mac-server.h in Headers */ = {isa = PBXBuildFile; fileRef = EA16054C0639E6C7004412AB /* mac-server.h */; }; + CF047D95109D0E0600FD0754 /* mac-snes9x.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68704AC7FCE00A80003 /* mac-snes9x.h */; }; + CF047D96109D0E0600FD0754 /* mac-stringtools.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68904AC7FCE00A80003 /* mac-stringtools.h */; }; + CF047D97109D0E0600FD0754 /* mac-prefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68304AC7FCE00A80003 /* mac-prefix.h */; }; + CF047D98109D0E0600FD0754 /* mac-global_prefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EAD978980555059300E8BBFD /* mac-global_prefix.h */; }; + CF047D99109D0E0600FD0754 /* HID_Utilities_External.h in Headers */ = {isa = PBXBuildFile; fileRef = EA362C3E086119D100FBE476 /* HID_Utilities_External.h */; }; + CF047D9B109D0E0600FD0754 /* APPL.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3D0A26083B00BDACCC /* APPL.icns */; }; + CF047D9C109D0E0600FD0754 /* CART.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3C0A26083B00BDACCC /* CART.icns */; }; + CF047D9D109D0E0600FD0754 /* SRAM.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F360A26083B00BDACCC /* SRAM.icns */; }; + CF047D9E109D0E0600FD0754 /* SAVE.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F370A26083B00BDACCC /* SAVE.icns */; }; + CF047D9F109D0E0600FD0754 /* folder_SRAMs.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3A0A26083B00BDACCC /* folder_SRAMs.icns */; }; + CF047DA0109D0E0600FD0754 /* folder_Freezes.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3B0A26083B00BDACCC /* folder_Freezes.icns */; }; + CF047DA1109D0E0600FD0754 /* icons.png in Resources */ = {isa = PBXBuildFile; fileRef = CF4B7C420CF841580080E643 /* icons.png */; }; + CF047DA2109D0E0600FD0754 /* logo_freeze.png in Resources */ = {isa = PBXBuildFile; fileRef = EA3D300B0A260A3200BDACCC /* logo_freeze.png */; }; + CF047DA3109D0E0600FD0754 /* logo_defrost.png in Resources */ = {isa = PBXBuildFile; fileRef = EA3D300C0A260A3200BDACCC /* logo_defrost.png */; }; + CF047DA4109D0E0600FD0754 /* musicbox_ledon.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F380A26083B00BDACCC /* musicbox_ledon.icns */; }; + CF047DA5109D0E0600FD0754 /* musicbox_ledoff.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F390A26083B00BDACCC /* musicbox_ledoff.icns */; }; + CF047DA6109D0E0600FD0754 /* musicbox_indicator.png in Resources */ = {isa = PBXBuildFile; fileRef = EA3D300A0A260A3200BDACCC /* musicbox_indicator.png */; }; + CF047DA7109D0E0600FD0754 /* freeze_defrost.aiff in Resources */ = {isa = PBXBuildFile; fileRef = EA85C3560B4ECBD900F5F9C9 /* freeze_defrost.aiff */; }; + CF047DA8109D0E0600FD0754 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEA9E0A28384E00A8FAE5 /* InfoPlist.strings */; }; + CF047DA9109D0E0600FD0754 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEA980A28384E00A8FAE5 /* Localizable.strings */; }; + CF047DAA109D0E0600FD0754 /* Snes9x.nib in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEA9C0A28384E00A8FAE5 /* Snes9x.nib */; }; + CF047DAB109D0E0600FD0754 /* Snes9x Help in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEAA80A28386500A8FAE5 /* Snes9x Help */; }; + CF047DAF109D0E0600FD0754 /* bsx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA2F380F09B17E070078DCA7 /* bsx.cpp */; }; + CF047DB0109D0E0600FD0754 /* c4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0615F0526CCB900A80003 /* c4.cpp */; }; + CF047DB1109D0E0600FD0754 /* c4emu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061610526CCB900A80003 /* c4emu.cpp */; }; + CF047DB2109D0E0600FD0754 /* cheats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061630526CCB900A80003 /* cheats.cpp */; }; + CF047DB3109D0E0600FD0754 /* cheats2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061650526CCB900A80003 /* cheats2.cpp */; }; + CF047DB4109D0E0600FD0754 /* clip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061660526CCB900A80003 /* clip.cpp */; }; + CF047DB5109D0E0600FD0754 /* controls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9908F8D7240072CDFB /* controls.cpp */; }; + CF047DB6109D0E0600FD0754 /* cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061690526CCB900A80003 /* cpu.cpp */; }; + CF047DB7109D0E0600FD0754 /* cpuexec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0616B0526CCB900A80003 /* cpuexec.cpp */; }; + CF047DB8109D0E0600FD0754 /* cpuops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0616E0526CCB900A80003 /* cpuops.cpp */; }; + CF047DB9109D0E0600FD0754 /* crosshairs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9B08F8D72C0072CDFB /* crosshairs.cpp */; }; + CF047DBA109D0E0600FD0754 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061710526CCB900A80003 /* debug.cpp */; }; + CF047DBB109D0E0600FD0754 /* dma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061740526CCB900A80003 /* dma.cpp */; }; + CF047DBC109D0E0600FD0754 /* dsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E270FAFD35A00340007 /* dsp.cpp */; }; + CF047DBD109D0E0600FD0754 /* dsp1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061760526CCB900A80003 /* dsp1.cpp */; }; + CF047DBE109D0E0600FD0754 /* dsp2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E1B0FAFD35400340007 /* dsp2.cpp */; }; + CF047DBF109D0E0600FD0754 /* dsp3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E1D0FAFD35400340007 /* dsp3.cpp */; }; + CF047DC0109D0E0600FD0754 /* dsp4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E1C0FAFD35400340007 /* dsp4.cpp */; }; + CF047DC2109D0E0600FD0754 /* fxemu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0617C0526CCB900A80003 /* fxemu.cpp */; }; + CF047DC3109D0E0600FD0754 /* fxinst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0617E0526CCB900A80003 /* fxinst.cpp */; }; + CF047DC4109D0E0600FD0754 /* gfx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA31FE2D05F7743E00E13748 /* gfx.cpp */; }; + CF047DC5109D0E0600FD0754 /* globals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061830526CCB900A80003 /* globals.cpp */; }; + CF047DC6109D0E0600FD0754 /* loadzip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061A90526CCB900A80003 /* loadzip.cpp */; }; + CF047DC7109D0E0600FD0754 /* logger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA00D01D0A5A9956000C58E0 /* logger.cpp */; }; + CF047DC8109D0E0600FD0754 /* memmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAB7319C0527033000A80003 /* memmap.cpp */; }; + CF047DC9109D0E0600FD0754 /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA813E9A066F50A5004F99B5 /* movie.cpp */; }; + CF047DCA109D0E0600FD0754 /* obc1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C30526CCB900A80003 /* obc1.cpp */; }; + CF047DCB109D0E0600FD0754 /* ppu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C80526CCB900A80003 /* ppu.cpp */; }; + CF047DCC109D0E0600FD0754 /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* reader.cpp */; }; + CF047DCD109D0E0600FD0754 /* sa1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CB0526CCB900A80003 /* sa1.cpp */; }; + CF047DCE109D0E0600FD0754 /* sa1cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CD0526CCB900A80003 /* sa1cpu.cpp */; }; + CF047DCF109D0E0600FD0754 /* sdd1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D10526CCB900A80003 /* sdd1.cpp */; }; + CF047DD0109D0E0600FD0754 /* sdd1emu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA22EFA4053EEE0700A80003 /* sdd1emu.cpp */; }; + CF047DD1109D0E0600FD0754 /* seta.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D40526CCB900A80003 /* seta.cpp */; }; + CF047DD2109D0E0600FD0754 /* seta010.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D60526CCB900A80003 /* seta010.cpp */; }; + CF047DD3109D0E0600FD0754 /* seta011.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D70526CCB900A80003 /* seta011.cpp */; }; + CF047DD4109D0E0600FD0754 /* seta018.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D80526CCB900A80003 /* seta018.cpp */; }; + CF047DD5109D0E0600FD0754 /* snapshot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061DB0526CCB900A80003 /* snapshot.cpp */; }; + CF047DD8109D0E0600FD0754 /* spc7110.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061E50526CCB900A80003 /* spc7110.cpp */; }; + CF047DD9109D0E0600FD0754 /* srtc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061E90526CCB900A80003 /* srtc.cpp */; }; + CF047DDA109D0E0600FD0754 /* tile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061EB0526CCB900A80003 /* tile.cpp */; }; + CF047DDB109D0E0600FD0754 /* 2xsai.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B10EA24C36005957E4 /* 2xsai.cpp */; }; + CF047DDC109D0E0600FD0754 /* blit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B30EA24C36005957E4 /* blit.cpp */; }; + CF047DDD109D0E0600FD0754 /* epx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B50EA24C36005957E4 /* epx.cpp */; }; + CF047DDE109D0E0600FD0754 /* hq2x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B70EA24C36005957E4 /* hq2x.cpp */; }; + CF047DDF109D0E0600FD0754 /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = CFA518D10EBCB4AD008379F6 /* ioapi.c */; }; + CF047DE0109D0E0600FD0754 /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = CFA518BC0EBCB3ED008379F6 /* unzip.c */; }; + CF047DE1109D0E0600FD0754 /* 7zlzma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5DA07609F76001BAB8B /* 7zlzma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF047DE2109D0E0600FD0754 /* crc32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5DF07609F76001BAB8B /* crc32.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF047DE3109D0E0600FD0754 /* iiostrm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E107609F76001BAB8B /* iiostrm.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF047DE4109D0E0600FD0754 /* inbyte.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E307609F76001BAB8B /* inbyte.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF047DE5109D0E0600FD0754 /* jma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E507609F76001BAB8B /* jma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF047DE6109D0E0600FD0754 /* lzma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E907609F76001BAB8B /* lzma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF047DE7109D0E0600FD0754 /* lzmadec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5EB07609F76001BAB8B /* lzmadec.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF047DE8109D0E0600FD0754 /* s9x-jma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5F007609F76001BAB8B /* s9x-jma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF047DE9109D0E0600FD0754 /* winout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5F207609F76001BAB8B /* winout.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF047DEA109D0E0600FD0754 /* mac-appleevent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EACDDBB004D6A89700A80003 /* mac-appleevent.cpp */; }; + CF047DEB109D0E0600FD0754 /* mac-audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EADE6347052E5C4300A80003 /* mac-audio.cpp */; }; + CF047DEC109D0E0600FD0754 /* mac-cart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67004AC7FCE00A80003 /* mac-cart.cpp */; }; + CF047DED109D0E0600FD0754 /* mac-cheat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67204AC7FCE00A80003 /* mac-cheat.cpp */; }; + CF047DEE109D0E0600FD0754 /* mac-cheatfinder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67404AC7FCE00A80003 /* mac-cheatfinder.cpp */; }; + CF047DEF109D0E0600FD0754 /* mac-client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA16051C0639E4C0004412AB /* mac-client.cpp */; }; + CF047DF0109D0E0600FD0754 /* mac-cocoatools.mm in Sources */ = {isa = PBXBuildFile; fileRef = EA85C24E0B4EC13300F5F9C9 /* mac-cocoatools.mm */; }; + CF047DF1109D0E0600FD0754 /* mac-controls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809FA108F8F2420072CDFB /* mac-controls.cpp */; }; + CF047DF2109D0E0600FD0754 /* mac-coreimage.mm in Sources */ = {isa = PBXBuildFile; fileRef = EA0C952E08364A4A009307B4 /* mac-coreimage.mm */; }; + CF047DF3109D0E0600FD0754 /* mac-dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67704AC7FCE00A80003 /* mac-dialog.cpp */; }; + CF047DF4109D0E0600FD0754 /* mac-file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA2DBC0C0510ABE700A80003 /* mac-file.cpp */; }; + CF047DF5109D0E0600FD0754 /* mac-gworld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67904AC7FCE00A80003 /* mac-gworld.cpp */; }; + CF047DF6109D0E0600FD0754 /* mac-joypad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67B04AC7FCE00A80003 /* mac-joypad.cpp */; }; + CF047DF7109D0E0600FD0754 /* mac-keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67D04AC7FCE00A80003 /* mac-keyboard.cpp */; }; + CF047DF8109D0E0600FD0754 /* mac-multicart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA26BBD50B3676E800A570B5 /* mac-multicart.cpp */; }; + CF047DF9109D0E0600FD0754 /* mac-musicbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67F04AC7FCE00A80003 /* mac-musicbox.cpp */; }; + CF047DFA109D0E0600FD0754 /* mac-netplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA1605500639E735004412AB /* mac-netplay.cpp */; }; + CF047DFB109D0E0600FD0754 /* mac-os.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0E96604D582B700A80003 /* mac-os.cpp */; }; + CF047DFC109D0E0600FD0754 /* mac-prefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0E96B04D584B700A80003 /* mac-prefs.cpp */; }; + CF047DFD109D0E0600FD0754 /* mac-quicktime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7F18506CB3D6F00C2D767 /* mac-quicktime.cpp */; }; + CF047DFE109D0E0600FD0754 /* mac-render.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA942A50059B0F9000D7D022 /* mac-render.cpp */; }; + CF047DFF109D0E0600FD0754 /* mac-screenshot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA2DBC0D0510ABE700A80003 /* mac-screenshot.cpp */; }; + CF047E00109D0E0600FD0754 /* mac-server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA16051D0639E4C0004412AB /* mac-server.cpp */; }; + CF047E01109D0E0600FD0754 /* mac-snes9x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB68604AC7FCE00A80003 /* mac-snes9x.cpp */; }; + CF047E02109D0E0600FD0754 /* mac-stringtools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB68804AC7FCE00A80003 /* mac-stringtools.cpp */; }; + CF047E04109D0E0600FD0754 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAC5E47003D2D9C800A80004 /* AGL.framework */; }; + CF047E05109D0E0600FD0754 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA85C2AC0B4ECA8300F5F9C9 /* AppKit.framework */; }; + CF047E06109D0E0600FD0754 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EADE634B052E5D3600A80003 /* AudioToolbox.framework */; }; + CF047E07109D0E0600FD0754 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EADE634C052E5D3600A80003 /* AudioUnit.framework */; }; + CF047E08109D0E0600FD0754 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; + CF047E09109D0E0600FD0754 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EADE634D052E5D3600A80003 /* CoreAudio.framework */; }; + CF047E0A109D0E0600FD0754 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA0C95D808364AAE009307B4 /* Foundation.framework */; }; + CF047E0B109D0E0600FD0754 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5FC76BD03873BBF01A80002 /* IOKit.framework */; }; + CF047E0C109D0E0600FD0754 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA8FA89603D294C000A80004 /* OpenGL.framework */; }; + CF047E0D109D0E0600FD0754 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CF05677E0CF9971000C7877C /* QuartzCore.framework */; }; + CF047E0E109D0E0600FD0754 /* QuickTime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5C108DD0386806001A80002 /* QuickTime.framework */; }; + CF047E0F109D0E0600FD0754 /* libHIDUtilities_u.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EA3D2F580A26085800BDACCC /* libHIDUtilities_u.a */; }; + CF047E10109D0E0600FD0754 /* libz_u.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CF10B8EF0F63BF8A009C81CD /* libz_u.a */; }; + CF05668E0CF98E7E00C7877C /* 65c816.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0615A0526CCB900A80003 /* 65c816.h */; }; + CF0566910CF98E7E00C7877C /* bsx.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2F381A09B17E9E0078DCA7 /* bsx.h */; }; + CF0566920CF98E7E00C7877C /* c4.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061600526CCB900A80003 /* c4.h */; }; + CF0566930CF98E7E00C7877C /* cheats.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061640526CCB900A80003 /* cheats.h */; }; + CF0566940CF98E7E00C7877C /* controls.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9308F8D6C40072CDFB /* controls.h */; }; + CF0566950CF98E7E00C7877C /* cpuaddr.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616A0526CCB900A80003 /* cpuaddr.h */; }; + CF0566960CF98E7E00C7877C /* cpuexec.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616C0526CCB900A80003 /* cpuexec.h */; }; + CF0566970CF98E7E00C7877C /* cpumacro.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616D0526CCB900A80003 /* cpumacro.h */; }; + CF0566980CF98E7E00C7877C /* cpuops.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616F0526CCB900A80003 /* cpuops.h */; }; + CF0566990CF98E7E00C7877C /* crosshairs.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9D08F8D73A0072CDFB /* crosshairs.h */; }; + CF05669A0CF98E7E00C7877C /* display.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061730526CCB900A80003 /* display.h */; }; + CF05669B0CF98E7E00C7877C /* dma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061750526CCB900A80003 /* dma.h */; }; + CF05669D0CF98E7E00C7877C /* font.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0617A0526CCB900A80003 /* font.h */; }; + CF05669E0CF98E7E00C7877C /* fxemu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0617D0526CCB900A80003 /* fxemu.h */; }; + CF05669F0CF98E7E00C7877C /* fxinst.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0617F0526CCB900A80003 /* fxinst.h */; }; + CF0566A00CF98E7E00C7877C /* getset.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061800526CCB900A80003 /* getset.h */; }; + CF0566A10CF98E7E00C7877C /* gfx.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061820526CCB900A80003 /* gfx.h */; }; + CF0566A20CF98E7E00C7877C /* language.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9508F8D6E00072CDFB /* language.h */; }; + CF0566A30CF98E7E00C7877C /* logger.h in Headers */ = {isa = PBXBuildFile; fileRef = EA00D01F0A5A998F000C58E0 /* logger.h */; }; + CF0566A40CF98E7E00C7877C /* memmap.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061B10526CCB900A80003 /* memmap.h */; }; + CF0566A50CF98E7E00C7877C /* messages.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061B20526CCB900A80003 /* messages.h */; }; + CF0566A60CF98E7E00C7877C /* missing.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061B30526CCB900A80003 /* missing.h */; }; + CF0566A70CF98E7E00C7877C /* movie.h in Headers */ = {isa = PBXBuildFile; fileRef = EA813E86066F5076004F99B5 /* movie.h */; }; + CF0566A80CF98E7E00C7877C /* obc1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C40526CCB900A80003 /* obc1.h */; }; + CF0566A90CF98E7E00C7877C /* pixform.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C60526CCB900A80003 /* pixform.h */; }; + CF0566AA0CF98E7E00C7877C /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C70526CCB900A80003 /* port.h */; }; + CF0566AB0CF98E7E00C7877C /* ppu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C90526CCB900A80003 /* ppu.h */; }; + CF0566AC0CF98E7E00C7877C /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* reader.h */; }; + CF0566AD0CF98E7E00C7877C /* sa1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CC0526CCB900A80003 /* sa1.h */; }; + CF0566AE0CF98E7E00C7877C /* sar.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CE0526CCB900A80003 /* sar.h */; }; + CF0566AF0CF98E7E00C7877C /* screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D00526CCB900A80003 /* screenshot.h */; }; + CF0566B00CF98E7E00C7877C /* sdd1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D20526CCB900A80003 /* sdd1.h */; }; + CF0566B10CF98E7E00C7877C /* sdd1emu.h in Headers */ = {isa = PBXBuildFile; fileRef = EA22EFA2053EEDE500A80003 /* sdd1emu.h */; }; + CF0566B20CF98E7E00C7877C /* seta.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D50526CCB900A80003 /* seta.h */; }; + CF0566B30CF98E7E00C7877C /* snapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061DC0526CCB900A80003 /* snapshot.h */; }; + CF0566B40CF98E7E00C7877C /* snes9x.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061DE0526CCB900A80003 /* snes9x.h */; }; + CF0566B70CF98E7E00C7877C /* spc7110.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061E60526CCB900A80003 /* spc7110.h */; }; + CF0566B80CF98E7E00C7877C /* srtc.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061EA0526CCB900A80003 /* srtc.h */; }; + CF0566B90CF98E7E00C7877C /* tile.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061EC0526CCB900A80003 /* tile.h */; }; + CF0566BD0CF98E7E00C7877C /* 7z.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5D907609F76001BAB8B /* 7z.h */; }; + CF0566BE0CF98E7E00C7877C /* aribitcd.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DB07609F76001BAB8B /* aribitcd.h */; }; + CF0566BF0CF98E7E00C7877C /* ariconst.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DC07609F76001BAB8B /* ariconst.h */; }; + CF0566C00CF98E7E00C7877C /* ariprice.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DD07609F76001BAB8B /* ariprice.h */; }; + CF0566C10CF98E7E00C7877C /* btreecd.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DE07609F76001BAB8B /* btreecd.h */; }; + CF0566C20CF98E7E00C7877C /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E007609F76001BAB8B /* crc32.h */; }; + CF0566C30CF98E7E00C7877C /* iiostrm.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E207609F76001BAB8B /* iiostrm.h */; }; + CF0566C40CF98E7E00C7877C /* inbyte.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E407609F76001BAB8B /* inbyte.h */; }; + CF0566C50CF98E7E00C7877C /* jma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E607609F76001BAB8B /* jma.h */; }; + CF0566C60CF98E7E00C7877C /* lencoder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E707609F76001BAB8B /* lencoder.h */; }; + CF0566C70CF98E7E00C7877C /* litcoder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E807609F76001BAB8B /* litcoder.h */; }; + CF0566C80CF98E7E00C7877C /* lzma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EA07609F76001BAB8B /* lzma.h */; }; + CF0566C90CF98E7E00C7877C /* lzmadec.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EC07609F76001BAB8B /* lzmadec.h */; }; + CF0566CA0CF98E7E00C7877C /* portable.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5ED07609F76001BAB8B /* portable.h */; }; + CF0566CB0CF98E7E00C7877C /* rcdefs.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EE07609F76001BAB8B /* rcdefs.h */; }; + CF0566CC0CF98E7E00C7877C /* rngcoder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EF07609F76001BAB8B /* rngcoder.h */; }; + CF0566CD0CF98E7E00C7877C /* s9x-jma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5F107609F76001BAB8B /* s9x-jma.h */; }; + CF0566CE0CF98E7E00C7877C /* winout.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5F307609F76001BAB8B /* winout.h */; }; + CF0566D00CF98E7E00C7877C /* mac-appleevent.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB66D04AC7FCD00A80003 /* mac-appleevent.h */; }; + CF0566D10CF98E7E00C7877C /* mac-audio.h in Headers */ = {isa = PBXBuildFile; fileRef = EADE6349052E5C5300A80003 /* mac-audio.h */; }; + CF0566D30CF98E7E00C7877C /* mac-cart.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67104AC7FCE00A80003 /* mac-cart.h */; }; + CF0566D40CF98E7E00C7877C /* mac-cheat.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67304AC7FCE00A80003 /* mac-cheat.h */; }; + CF0566D50CF98E7E00C7877C /* mac-cheatfinder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67504AC7FCE00A80003 /* mac-cheatfinder.h */; }; + CF0566D60CF98E7E00C7877C /* mac-client.h in Headers */ = {isa = PBXBuildFile; fileRef = EA1605540639E937004412AB /* mac-client.h */; }; + CF0566D70CF98E7E00C7877C /* mac-cocoatools.h in Headers */ = {isa = PBXBuildFile; fileRef = EA85C24D0B4EC13300F5F9C9 /* mac-cocoatools.h */; }; + CF0566D80CF98E7E00C7877C /* mac-controls.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809F9D08F8F2190072CDFB /* mac-controls.h */; }; + CF0566D90CF98E7E00C7877C /* mac-coreimage.h in Headers */ = {isa = PBXBuildFile; fileRef = EA0C952D08364A4A009307B4 /* mac-coreimage.h */; }; + CF0566DA0CF98E7E00C7877C /* mac-dialog.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67804AC7FCE00A80003 /* mac-dialog.h */; }; + CF0566DC0CF98E7E00C7877C /* mac-file.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2DBC0A0510ABE700A80003 /* mac-file.h */; }; + CF0566DD0CF98E7E00C7877C /* mac-gworld.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67A04AC7FCE00A80003 /* mac-gworld.h */; }; + CF0566DF0CF98E7E00C7877C /* mac-joypad.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67C04AC7FCE00A80003 /* mac-joypad.h */; }; + CF0566E00CF98E7E00C7877C /* mac-keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67E04AC7FCE00A80003 /* mac-keyboard.h */; }; + CF0566E10CF98E7E00C7877C /* mac-multicart.h in Headers */ = {isa = PBXBuildFile; fileRef = EA26BBD90B36771500A570B5 /* mac-multicart.h */; }; + CF0566E20CF98E7E00C7877C /* mac-musicbox.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68004AC7FCE00A80003 /* mac-musicbox.h */; }; + CF0566E30CF98E7E00C7877C /* mac-netplay.h in Headers */ = {isa = PBXBuildFile; fileRef = EA16053E0639E655004412AB /* mac-netplay.h */; }; + CF0566E40CF98E7E00C7877C /* mac-os.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68204AC7FCE00A80003 /* mac-os.h */; }; + CF0566E50CF98E7E00C7877C /* mac-prefs.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68504AC7FCE00A80003 /* mac-prefs.h */; }; + CF0566E60CF98E7E00C7877C /* mac-quicktime.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7F17F06CB3D4A00C2D767 /* mac-quicktime.h */; }; + CF0566E70CF98E7E00C7877C /* mac-render.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2DBC090510ABE700A80003 /* mac-render.h */; }; + CF0566E80CF98E7E00C7877C /* mac-screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2DBC070510ABE700A80003 /* mac-screenshot.h */; }; + CF0566E90CF98E7E00C7877C /* mac-server.h in Headers */ = {isa = PBXBuildFile; fileRef = EA16054C0639E6C7004412AB /* mac-server.h */; }; + CF0566EA0CF98E7E00C7877C /* mac-snes9x.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68704AC7FCE00A80003 /* mac-snes9x.h */; }; + CF0566EB0CF98E7E00C7877C /* mac-stringtools.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68904AC7FCE00A80003 /* mac-stringtools.h */; }; + CF0566EC0CF98E7E00C7877C /* mac-prefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68304AC7FCE00A80003 /* mac-prefix.h */; }; + CF0566ED0CF98E7E00C7877C /* mac-global_prefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EAD978980555059300E8BBFD /* mac-global_prefix.h */; }; + CF0566EE0CF98E7E00C7877C /* HID_Utilities_External.h in Headers */ = {isa = PBXBuildFile; fileRef = EA362C3E086119D100FBE476 /* HID_Utilities_External.h */; }; + CF0566F00CF98E7E00C7877C /* APPL.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3D0A26083B00BDACCC /* APPL.icns */; }; + CF0566F10CF98E7E00C7877C /* CART.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3C0A26083B00BDACCC /* CART.icns */; }; + CF0566F20CF98E7E00C7877C /* SRAM.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F360A26083B00BDACCC /* SRAM.icns */; }; + CF0566F30CF98E7E00C7877C /* SAVE.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F370A26083B00BDACCC /* SAVE.icns */; }; + CF0566F40CF98E7E00C7877C /* folder_SRAMs.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3A0A26083B00BDACCC /* folder_SRAMs.icns */; }; + CF0566F50CF98E7E00C7877C /* folder_Freezes.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3B0A26083B00BDACCC /* folder_Freezes.icns */; }; + CF0566F60CF98E7E00C7877C /* icons.png in Resources */ = {isa = PBXBuildFile; fileRef = CF4B7C420CF841580080E643 /* icons.png */; }; + CF0566F70CF98E7E00C7877C /* logo_freeze.png in Resources */ = {isa = PBXBuildFile; fileRef = EA3D300B0A260A3200BDACCC /* logo_freeze.png */; }; + CF0566F80CF98E7E00C7877C /* logo_defrost.png in Resources */ = {isa = PBXBuildFile; fileRef = EA3D300C0A260A3200BDACCC /* logo_defrost.png */; }; + CF0566F90CF98E7E00C7877C /* musicbox_ledon.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F380A26083B00BDACCC /* musicbox_ledon.icns */; }; + CF0566FA0CF98E7E00C7877C /* musicbox_ledoff.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F390A26083B00BDACCC /* musicbox_ledoff.icns */; }; + CF0566FB0CF98E7E00C7877C /* musicbox_indicator.png in Resources */ = {isa = PBXBuildFile; fileRef = EA3D300A0A260A3200BDACCC /* musicbox_indicator.png */; }; + CF0566FC0CF98E7E00C7877C /* freeze_defrost.aiff in Resources */ = {isa = PBXBuildFile; fileRef = EA85C3560B4ECBD900F5F9C9 /* freeze_defrost.aiff */; }; + CF0566FD0CF98E7E00C7877C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEA9E0A28384E00A8FAE5 /* InfoPlist.strings */; }; + CF0566FE0CF98E7E00C7877C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEA980A28384E00A8FAE5 /* Localizable.strings */; }; + CF0566FF0CF98E7E00C7877C /* Snes9x.nib in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEA9C0A28384E00A8FAE5 /* Snes9x.nib */; }; + CF0567000CF98E7E00C7877C /* Snes9x Help in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEAA80A28386500A8FAE5 /* Snes9x Help */; }; + CF0567030CF98E7E00C7877C /* bsx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA2F380F09B17E070078DCA7 /* bsx.cpp */; }; + CF0567040CF98E7E00C7877C /* c4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0615F0526CCB900A80003 /* c4.cpp */; }; + CF0567050CF98E7E00C7877C /* c4emu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061610526CCB900A80003 /* c4emu.cpp */; }; + CF0567060CF98E7E00C7877C /* cheats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061630526CCB900A80003 /* cheats.cpp */; }; + CF0567070CF98E7E00C7877C /* cheats2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061650526CCB900A80003 /* cheats2.cpp */; }; + CF0567080CF98E7E00C7877C /* clip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061660526CCB900A80003 /* clip.cpp */; }; + CF0567090CF98E7E00C7877C /* controls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9908F8D7240072CDFB /* controls.cpp */; }; + CF05670A0CF98E7E00C7877C /* cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061690526CCB900A80003 /* cpu.cpp */; }; + CF05670B0CF98E7E00C7877C /* cpuexec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0616B0526CCB900A80003 /* cpuexec.cpp */; }; + CF05670C0CF98E7E00C7877C /* cpuops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0616E0526CCB900A80003 /* cpuops.cpp */; }; + CF05670D0CF98E7E00C7877C /* crosshairs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9B08F8D72C0072CDFB /* crosshairs.cpp */; }; + CF05670F0CF98E7E00C7877C /* dma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061740526CCB900A80003 /* dma.cpp */; }; + CF0567100CF98E7E00C7877C /* dsp1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061760526CCB900A80003 /* dsp1.cpp */; }; + CF0567120CF98E7E00C7877C /* fxinst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0617E0526CCB900A80003 /* fxinst.cpp */; }; + CF0567130CF98E7E00C7877C /* gfx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA31FE2D05F7743E00E13748 /* gfx.cpp */; }; + CF0567140CF98E7E00C7877C /* globals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061830526CCB900A80003 /* globals.cpp */; }; + CF0567150CF98E7E00C7877C /* loadzip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061A90526CCB900A80003 /* loadzip.cpp */; }; + CF0567160CF98E7E00C7877C /* logger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA00D01D0A5A9956000C58E0 /* logger.cpp */; }; + CF0567170CF98E7E00C7877C /* memmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAB7319C0527033000A80003 /* memmap.cpp */; }; + CF0567180CF98E7E00C7877C /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA813E9A066F50A5004F99B5 /* movie.cpp */; }; + CF0567190CF98E7E00C7877C /* obc1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C30526CCB900A80003 /* obc1.cpp */; }; + CF05671A0CF98E7E00C7877C /* ppu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C80526CCB900A80003 /* ppu.cpp */; }; + CF05671B0CF98E7E00C7877C /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* reader.cpp */; }; + CF05671C0CF98E7E00C7877C /* sa1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CB0526CCB900A80003 /* sa1.cpp */; }; + CF05671D0CF98E7E00C7877C /* sa1cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CD0526CCB900A80003 /* sa1cpu.cpp */; }; + CF05671E0CF98E7E00C7877C /* sdd1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D10526CCB900A80003 /* sdd1.cpp */; }; + CF05671F0CF98E7E00C7877C /* sdd1emu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA22EFA4053EEE0700A80003 /* sdd1emu.cpp */; }; + CF0567200CF98E7E00C7877C /* seta.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D40526CCB900A80003 /* seta.cpp */; }; + CF0567210CF98E7E00C7877C /* seta010.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D60526CCB900A80003 /* seta010.cpp */; }; + CF0567220CF98E7E00C7877C /* seta011.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D70526CCB900A80003 /* seta011.cpp */; }; + CF0567230CF98E7E00C7877C /* seta018.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D80526CCB900A80003 /* seta018.cpp */; }; + CF0567240CF98E7E00C7877C /* snapshot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061DB0526CCB900A80003 /* snapshot.cpp */; }; + CF0567270CF98E7E00C7877C /* spc7110.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061E50526CCB900A80003 /* spc7110.cpp */; }; + CF0567280CF98E7E00C7877C /* srtc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061E90526CCB900A80003 /* srtc.cpp */; }; + CF0567290CF98E7E00C7877C /* tile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061EB0526CCB900A80003 /* tile.cpp */; }; + CF05672E0CF98E7E00C7877C /* 7zlzma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5DA07609F76001BAB8B /* 7zlzma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF05672F0CF98E7E00C7877C /* crc32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5DF07609F76001BAB8B /* crc32.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF0567300CF98E7E00C7877C /* iiostrm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E107609F76001BAB8B /* iiostrm.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF0567310CF98E7E00C7877C /* inbyte.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E307609F76001BAB8B /* inbyte.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF0567320CF98E7E00C7877C /* jma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E507609F76001BAB8B /* jma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF0567330CF98E7E00C7877C /* lzma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E907609F76001BAB8B /* lzma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF0567340CF98E7E00C7877C /* lzmadec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5EB07609F76001BAB8B /* lzmadec.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF0567350CF98E7E00C7877C /* s9x-jma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5F007609F76001BAB8B /* s9x-jma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF0567360CF98E7E00C7877C /* winout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5F207609F76001BAB8B /* winout.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF0567380CF98E7E00C7877C /* mac-appleevent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EACDDBB004D6A89700A80003 /* mac-appleevent.cpp */; }; + CF0567390CF98E7E00C7877C /* mac-audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EADE6347052E5C4300A80003 /* mac-audio.cpp */; }; + CF05673B0CF98E7E00C7877C /* mac-cart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67004AC7FCE00A80003 /* mac-cart.cpp */; }; + CF05673C0CF98E7E00C7877C /* mac-cheat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67204AC7FCE00A80003 /* mac-cheat.cpp */; }; + CF05673D0CF98E7E00C7877C /* mac-cheatfinder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67404AC7FCE00A80003 /* mac-cheatfinder.cpp */; }; + CF05673E0CF98E7E00C7877C /* mac-client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA16051C0639E4C0004412AB /* mac-client.cpp */; }; + CF05673F0CF98E7E00C7877C /* mac-cocoatools.mm in Sources */ = {isa = PBXBuildFile; fileRef = EA85C24E0B4EC13300F5F9C9 /* mac-cocoatools.mm */; }; + CF0567400CF98E7E00C7877C /* mac-controls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809FA108F8F2420072CDFB /* mac-controls.cpp */; }; + CF0567410CF98E7E00C7877C /* mac-coreimage.mm in Sources */ = {isa = PBXBuildFile; fileRef = EA0C952E08364A4A009307B4 /* mac-coreimage.mm */; }; + CF0567420CF98E7E00C7877C /* mac-dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67704AC7FCE00A80003 /* mac-dialog.cpp */; }; + CF0567440CF98E7E00C7877C /* mac-file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA2DBC0C0510ABE700A80003 /* mac-file.cpp */; }; + CF0567450CF98E7E00C7877C /* mac-gworld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67904AC7FCE00A80003 /* mac-gworld.cpp */; }; + CF0567470CF98E7E00C7877C /* mac-joypad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67B04AC7FCE00A80003 /* mac-joypad.cpp */; }; + CF0567480CF98E7E00C7877C /* mac-keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67D04AC7FCE00A80003 /* mac-keyboard.cpp */; }; + CF0567490CF98E7E00C7877C /* mac-multicart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA26BBD50B3676E800A570B5 /* mac-multicart.cpp */; }; + CF05674A0CF98E7E00C7877C /* mac-musicbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67F04AC7FCE00A80003 /* mac-musicbox.cpp */; }; + CF05674B0CF98E7E00C7877C /* mac-netplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA1605500639E735004412AB /* mac-netplay.cpp */; }; + CF05674C0CF98E7E00C7877C /* mac-os.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0E96604D582B700A80003 /* mac-os.cpp */; }; + CF05674D0CF98E7E00C7877C /* mac-prefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0E96B04D584B700A80003 /* mac-prefs.cpp */; }; + CF05674E0CF98E7E00C7877C /* mac-quicktime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7F18506CB3D6F00C2D767 /* mac-quicktime.cpp */; }; + CF05674F0CF98E7E00C7877C /* mac-render.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA942A50059B0F9000D7D022 /* mac-render.cpp */; }; + CF0567500CF98E7E00C7877C /* mac-screenshot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA2DBC0D0510ABE700A80003 /* mac-screenshot.cpp */; }; + CF0567510CF98E7E00C7877C /* mac-server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA16051D0639E4C0004412AB /* mac-server.cpp */; }; + CF0567520CF98E7E00C7877C /* mac-snes9x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB68604AC7FCE00A80003 /* mac-snes9x.cpp */; }; + CF0567530CF98E7E00C7877C /* mac-stringtools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB68804AC7FCE00A80003 /* mac-stringtools.cpp */; }; + CF0567550CF98E7E00C7877C /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; + CF0567560CF98E7E00C7877C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA0C95D808364AAE009307B4 /* Foundation.framework */; }; + CF0567570CF98E7E00C7877C /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA85C2AC0B4ECA8300F5F9C9 /* AppKit.framework */; }; + CF0567580CF98E7E00C7877C /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EADE634D052E5D3600A80003 /* CoreAudio.framework */; }; + CF0567590CF98E7E00C7877C /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EADE634C052E5D3600A80003 /* AudioUnit.framework */; }; + CF05675A0CF98E7E00C7877C /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EADE634B052E5D3600A80003 /* AudioToolbox.framework */; }; + CF05675B0CF98E7E00C7877C /* QuickTime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5C108DD0386806001A80002 /* QuickTime.framework */; }; + CF05675C0CF98E7E00C7877C /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA8FA89603D294C000A80004 /* OpenGL.framework */; }; + CF05675D0CF98E7E00C7877C /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAC5E47003D2D9C800A80004 /* AGL.framework */; }; + CF05675E0CF98E7E00C7877C /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5FC76BD03873BBF01A80002 /* IOKit.framework */; }; + CF0567600CF98E7E00C7877C /* libHIDUtilities_u.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EA3D2F580A26085800BDACCC /* libHIDUtilities_u.a */; }; + CF0567810CF9971000C7877C /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CF05677E0CF9971000C7877C /* QuartzCore.framework */; }; + CF10B8F20F63BF8A009C81CD /* libz_u.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CF10B8EF0F63BF8A009C81CD /* libz_u.a */; }; + CF2F46121095EE72007D33FA /* 65c816.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0615A0526CCB900A80003 /* 65c816.h */; }; + CF2F46151095EE72007D33FA /* bsx.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2F381A09B17E9E0078DCA7 /* bsx.h */; }; + CF2F46161095EE72007D33FA /* c4.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061600526CCB900A80003 /* c4.h */; }; + CF2F46171095EE72007D33FA /* cheats.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061640526CCB900A80003 /* cheats.h */; }; + CF2F46181095EE72007D33FA /* controls.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9308F8D6C40072CDFB /* controls.h */; }; + CF2F46191095EE72007D33FA /* cpuaddr.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616A0526CCB900A80003 /* cpuaddr.h */; }; + CF2F461A1095EE72007D33FA /* cpuexec.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616C0526CCB900A80003 /* cpuexec.h */; }; + CF2F461B1095EE72007D33FA /* cpumacro.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616D0526CCB900A80003 /* cpumacro.h */; }; + CF2F461C1095EE72007D33FA /* cpuops.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0616F0526CCB900A80003 /* cpuops.h */; }; + CF2F461D1095EE72007D33FA /* crosshairs.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9D08F8D73A0072CDFB /* crosshairs.h */; }; + CF2F461E1095EE72007D33FA /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = EA6E6C0E08F9734500CB3555 /* debug.h */; }; + CF2F461F1095EE72007D33FA /* display.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061730526CCB900A80003 /* display.h */; }; + CF2F46201095EE72007D33FA /* dma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061750526CCB900A80003 /* dma.h */; }; + CF2F46211095EE72007D33FA /* dsp.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5D3E100FAFD34200340007 /* dsp.h */; }; + CF2F46221095EE72007D33FA /* font.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0617A0526CCB900A80003 /* font.h */; }; + CF2F46231095EE72007D33FA /* fxemu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0617D0526CCB900A80003 /* fxemu.h */; }; + CF2F46241095EE72007D33FA /* fxinst.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE0617F0526CCB900A80003 /* fxinst.h */; }; + CF2F46251095EE72007D33FA /* getset.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061800526CCB900A80003 /* getset.h */; }; + CF2F46261095EE72007D33FA /* gfx.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061820526CCB900A80003 /* gfx.h */; }; + CF2F46271095EE72007D33FA /* language.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9508F8D6E00072CDFB /* language.h */; }; + CF2F46281095EE72007D33FA /* logger.h in Headers */ = {isa = PBXBuildFile; fileRef = EA00D01F0A5A998F000C58E0 /* logger.h */; }; + CF2F46291095EE72007D33FA /* memmap.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061B10526CCB900A80003 /* memmap.h */; }; + CF2F462A1095EE72007D33FA /* messages.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061B20526CCB900A80003 /* messages.h */; }; + CF2F462B1095EE72007D33FA /* missing.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061B30526CCB900A80003 /* missing.h */; }; + CF2F462C1095EE72007D33FA /* movie.h in Headers */ = {isa = PBXBuildFile; fileRef = EA813E86066F5076004F99B5 /* movie.h */; }; + CF2F462D1095EE72007D33FA /* obc1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C40526CCB900A80003 /* obc1.h */; }; + CF2F462E1095EE72007D33FA /* pixform.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C60526CCB900A80003 /* pixform.h */; }; + CF2F462F1095EE72007D33FA /* port.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C70526CCB900A80003 /* port.h */; }; + CF2F46301095EE72007D33FA /* ppu.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061C90526CCB900A80003 /* ppu.h */; }; + CF2F46311095EE72007D33FA /* reader.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809E9708F8D70D0072CDFB /* reader.h */; }; + CF2F46321095EE72007D33FA /* sa1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CC0526CCB900A80003 /* sa1.h */; }; + CF2F46331095EE72007D33FA /* sar.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061CE0526CCB900A80003 /* sar.h */; }; + CF2F46341095EE72007D33FA /* screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D00526CCB900A80003 /* screenshot.h */; }; + CF2F46351095EE72007D33FA /* sdd1.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D20526CCB900A80003 /* sdd1.h */; }; + CF2F46361095EE72007D33FA /* sdd1emu.h in Headers */ = {isa = PBXBuildFile; fileRef = EA22EFA2053EEDE500A80003 /* sdd1emu.h */; }; + CF2F46371095EE72007D33FA /* seta.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061D50526CCB900A80003 /* seta.h */; }; + CF2F46381095EE72007D33FA /* snapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061DC0526CCB900A80003 /* snapshot.h */; }; + CF2F46391095EE72007D33FA /* snes9x.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061DE0526CCB900A80003 /* snes9x.h */; }; + CF2F463C1095EE72007D33FA /* spc7110.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061E60526CCB900A80003 /* spc7110.h */; }; + CF2F463D1095EE72007D33FA /* srtc.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061EA0526CCB900A80003 /* srtc.h */; }; + CF2F463E1095EE72007D33FA /* tile.h in Headers */ = {isa = PBXBuildFile; fileRef = EAE061EC0526CCB900A80003 /* tile.h */; }; + CF2F463F1095EE72007D33FA /* 2xsai.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B20EA24C36005957E4 /* 2xsai.h */; }; + CF2F46401095EE72007D33FA /* blit.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B40EA24C36005957E4 /* blit.h */; }; + CF2F46411095EE72007D33FA /* epx.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B60EA24C36005957E4 /* epx.h */; }; + CF2F46421095EE72007D33FA /* hq2x.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B80EA24C36005957E4 /* hq2x.h */; }; + CF2F46431095EE72007D33FA /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518E50EBCB5B1008379F6 /* crypt.h */; }; + CF2F46441095EE72007D33FA /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518D60EBCB4CA008379F6 /* ioapi.h */; }; + CF2F46451095EE72007D33FA /* unzip.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518DA0EBCB4D2008379F6 /* unzip.h */; }; + CF2F46461095EE72007D33FA /* 7z.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5D907609F76001BAB8B /* 7z.h */; }; + CF2F46471095EE72007D33FA /* aribitcd.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DB07609F76001BAB8B /* aribitcd.h */; }; + CF2F46481095EE72007D33FA /* ariconst.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DC07609F76001BAB8B /* ariconst.h */; }; + CF2F46491095EE72007D33FA /* ariprice.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DD07609F76001BAB8B /* ariprice.h */; }; + CF2F464A1095EE72007D33FA /* btreecd.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5DE07609F76001BAB8B /* btreecd.h */; }; + CF2F464B1095EE72007D33FA /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E007609F76001BAB8B /* crc32.h */; }; + CF2F464C1095EE72007D33FA /* iiostrm.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E207609F76001BAB8B /* iiostrm.h */; }; + CF2F464D1095EE72007D33FA /* inbyte.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E407609F76001BAB8B /* inbyte.h */; }; + CF2F464E1095EE72007D33FA /* jma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E607609F76001BAB8B /* jma.h */; }; + CF2F464F1095EE72007D33FA /* lencoder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E707609F76001BAB8B /* lencoder.h */; }; + CF2F46501095EE72007D33FA /* litcoder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5E807609F76001BAB8B /* litcoder.h */; }; + CF2F46511095EE72007D33FA /* lzma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EA07609F76001BAB8B /* lzma.h */; }; + CF2F46521095EE72007D33FA /* lzmadec.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EC07609F76001BAB8B /* lzmadec.h */; }; + CF2F46531095EE72007D33FA /* portable.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5ED07609F76001BAB8B /* portable.h */; }; + CF2F46541095EE72007D33FA /* rcdefs.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EE07609F76001BAB8B /* rcdefs.h */; }; + CF2F46551095EE72007D33FA /* rngcoder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5EF07609F76001BAB8B /* rngcoder.h */; }; + CF2F46561095EE72007D33FA /* s9x-jma.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5F107609F76001BAB8B /* s9x-jma.h */; }; + CF2F46571095EE72007D33FA /* winout.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7B5F307609F76001BAB8B /* winout.h */; }; + CF2F46581095EE72007D33FA /* mac-appleevent.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB66D04AC7FCD00A80003 /* mac-appleevent.h */; }; + CF2F46591095EE72007D33FA /* mac-audio.h in Headers */ = {isa = PBXBuildFile; fileRef = EADE6349052E5C5300A80003 /* mac-audio.h */; }; + CF2F465A1095EE72007D33FA /* mac-cart.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67104AC7FCE00A80003 /* mac-cart.h */; }; + CF2F465B1095EE72007D33FA /* mac-cheat.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67304AC7FCE00A80003 /* mac-cheat.h */; }; + CF2F465C1095EE72007D33FA /* mac-cheatfinder.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67504AC7FCE00A80003 /* mac-cheatfinder.h */; }; + CF2F465D1095EE72007D33FA /* mac-client.h in Headers */ = {isa = PBXBuildFile; fileRef = EA1605540639E937004412AB /* mac-client.h */; }; + CF2F465E1095EE72007D33FA /* mac-cocoatools.h in Headers */ = {isa = PBXBuildFile; fileRef = EA85C24D0B4EC13300F5F9C9 /* mac-cocoatools.h */; }; + CF2F465F1095EE72007D33FA /* mac-controls.h in Headers */ = {isa = PBXBuildFile; fileRef = EA809F9D08F8F2190072CDFB /* mac-controls.h */; }; + CF2F46601095EE72007D33FA /* mac-coreimage.h in Headers */ = {isa = PBXBuildFile; fileRef = EA0C952D08364A4A009307B4 /* mac-coreimage.h */; }; + CF2F46611095EE72007D33FA /* mac-dialog.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67804AC7FCE00A80003 /* mac-dialog.h */; }; + CF2F46621095EE72007D33FA /* mac-file.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2DBC0A0510ABE700A80003 /* mac-file.h */; }; + CF2F46631095EE72007D33FA /* mac-gworld.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67A04AC7FCE00A80003 /* mac-gworld.h */; }; + CF2F46641095EE72007D33FA /* mac-joypad.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67C04AC7FCE00A80003 /* mac-joypad.h */; }; + CF2F46651095EE72007D33FA /* mac-keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB67E04AC7FCE00A80003 /* mac-keyboard.h */; }; + CF2F46661095EE72007D33FA /* mac-multicart.h in Headers */ = {isa = PBXBuildFile; fileRef = EA26BBD90B36771500A570B5 /* mac-multicart.h */; }; + CF2F46671095EE72007D33FA /* mac-musicbox.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68004AC7FCE00A80003 /* mac-musicbox.h */; }; + CF2F46681095EE72007D33FA /* mac-netplay.h in Headers */ = {isa = PBXBuildFile; fileRef = EA16053E0639E655004412AB /* mac-netplay.h */; }; + CF2F46691095EE72007D33FA /* mac-os.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68204AC7FCE00A80003 /* mac-os.h */; }; + CF2F466A1095EE72007D33FA /* mac-prefs.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68504AC7FCE00A80003 /* mac-prefs.h */; }; + CF2F466B1095EE72007D33FA /* mac-quicktime.h in Headers */ = {isa = PBXBuildFile; fileRef = EAA7F17F06CB3D4A00C2D767 /* mac-quicktime.h */; }; + CF2F466C1095EE72007D33FA /* mac-render.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2DBC090510ABE700A80003 /* mac-render.h */; }; + CF2F466D1095EE72007D33FA /* mac-screenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = EA2DBC070510ABE700A80003 /* mac-screenshot.h */; }; + CF2F466E1095EE72007D33FA /* mac-server.h in Headers */ = {isa = PBXBuildFile; fileRef = EA16054C0639E6C7004412AB /* mac-server.h */; }; + CF2F466F1095EE72007D33FA /* mac-snes9x.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68704AC7FCE00A80003 /* mac-snes9x.h */; }; + CF2F46701095EE72007D33FA /* mac-stringtools.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68904AC7FCE00A80003 /* mac-stringtools.h */; }; + CF2F46711095EE72007D33FA /* mac-prefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EAECB68304AC7FCE00A80003 /* mac-prefix.h */; }; + CF2F46721095EE72007D33FA /* mac-global_prefix.h in Headers */ = {isa = PBXBuildFile; fileRef = EAD978980555059300E8BBFD /* mac-global_prefix.h */; }; + CF2F46731095EE72007D33FA /* HID_Utilities_External.h in Headers */ = {isa = PBXBuildFile; fileRef = EA362C3E086119D100FBE476 /* HID_Utilities_External.h */; }; + CF2F46751095EE72007D33FA /* APPL.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3D0A26083B00BDACCC /* APPL.icns */; }; + CF2F46761095EE72007D33FA /* CART.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3C0A26083B00BDACCC /* CART.icns */; }; + CF2F46771095EE72007D33FA /* SRAM.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F360A26083B00BDACCC /* SRAM.icns */; }; + CF2F46781095EE72007D33FA /* SAVE.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F370A26083B00BDACCC /* SAVE.icns */; }; + CF2F46791095EE72007D33FA /* folder_SRAMs.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3A0A26083B00BDACCC /* folder_SRAMs.icns */; }; + CF2F467A1095EE72007D33FA /* folder_Freezes.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3B0A26083B00BDACCC /* folder_Freezes.icns */; }; + CF2F467B1095EE72007D33FA /* icons.png in Resources */ = {isa = PBXBuildFile; fileRef = CF4B7C420CF841580080E643 /* icons.png */; }; + CF2F467C1095EE72007D33FA /* logo_freeze.png in Resources */ = {isa = PBXBuildFile; fileRef = EA3D300B0A260A3200BDACCC /* logo_freeze.png */; }; + CF2F467D1095EE72007D33FA /* logo_defrost.png in Resources */ = {isa = PBXBuildFile; fileRef = EA3D300C0A260A3200BDACCC /* logo_defrost.png */; }; + CF2F467E1095EE72007D33FA /* musicbox_ledon.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F380A26083B00BDACCC /* musicbox_ledon.icns */; }; + CF2F467F1095EE72007D33FA /* musicbox_ledoff.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F390A26083B00BDACCC /* musicbox_ledoff.icns */; }; + CF2F46801095EE72007D33FA /* musicbox_indicator.png in Resources */ = {isa = PBXBuildFile; fileRef = EA3D300A0A260A3200BDACCC /* musicbox_indicator.png */; }; + CF2F46811095EE72007D33FA /* freeze_defrost.aiff in Resources */ = {isa = PBXBuildFile; fileRef = EA85C3560B4ECBD900F5F9C9 /* freeze_defrost.aiff */; }; + CF2F46821095EE72007D33FA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEA9E0A28384E00A8FAE5 /* InfoPlist.strings */; }; + CF2F46831095EE72007D33FA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEA980A28384E00A8FAE5 /* Localizable.strings */; }; + CF2F46841095EE72007D33FA /* Snes9x.nib in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEA9C0A28384E00A8FAE5 /* Snes9x.nib */; }; + CF2F46851095EE72007D33FA /* Snes9x Help in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEAA80A28386500A8FAE5 /* Snes9x Help */; }; + CF2F46891095EE72007D33FA /* bsx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA2F380F09B17E070078DCA7 /* bsx.cpp */; }; + CF2F468A1095EE72007D33FA /* c4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0615F0526CCB900A80003 /* c4.cpp */; }; + CF2F468B1095EE72007D33FA /* c4emu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061610526CCB900A80003 /* c4emu.cpp */; }; + CF2F468C1095EE72007D33FA /* cheats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061630526CCB900A80003 /* cheats.cpp */; }; + CF2F468D1095EE72007D33FA /* cheats2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061650526CCB900A80003 /* cheats2.cpp */; }; + CF2F468E1095EE72007D33FA /* clip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061660526CCB900A80003 /* clip.cpp */; }; + CF2F468F1095EE72007D33FA /* controls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9908F8D7240072CDFB /* controls.cpp */; }; + CF2F46901095EE72007D33FA /* cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061690526CCB900A80003 /* cpu.cpp */; }; + CF2F46911095EE72007D33FA /* cpuexec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0616B0526CCB900A80003 /* cpuexec.cpp */; }; + CF2F46921095EE72007D33FA /* cpuops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0616E0526CCB900A80003 /* cpuops.cpp */; }; + CF2F46931095EE72007D33FA /* crosshairs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9B08F8D72C0072CDFB /* crosshairs.cpp */; }; + CF2F46941095EE72007D33FA /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061710526CCB900A80003 /* debug.cpp */; }; + CF2F46951095EE72007D33FA /* dma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061740526CCB900A80003 /* dma.cpp */; }; + CF2F46961095EE72007D33FA /* dsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E270FAFD35A00340007 /* dsp.cpp */; }; + CF2F46971095EE72007D33FA /* dsp1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061760526CCB900A80003 /* dsp1.cpp */; }; + CF2F46981095EE72007D33FA /* dsp2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E1B0FAFD35400340007 /* dsp2.cpp */; }; + CF2F46991095EE72007D33FA /* dsp3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E1D0FAFD35400340007 /* dsp3.cpp */; }; + CF2F469A1095EE72007D33FA /* dsp4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E1C0FAFD35400340007 /* dsp4.cpp */; }; + CF2F469C1095EE72007D33FA /* fxemu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0617C0526CCB900A80003 /* fxemu.cpp */; }; + CF2F469D1095EE72007D33FA /* fxinst.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0617E0526CCB900A80003 /* fxinst.cpp */; }; + CF2F469E1095EE72007D33FA /* gfx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA31FE2D05F7743E00E13748 /* gfx.cpp */; }; + CF2F469F1095EE72007D33FA /* globals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061830526CCB900A80003 /* globals.cpp */; }; + CF2F46A01095EE72007D33FA /* loadzip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061A90526CCB900A80003 /* loadzip.cpp */; }; + CF2F46A11095EE72007D33FA /* logger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA00D01D0A5A9956000C58E0 /* logger.cpp */; }; + CF2F46A21095EE72007D33FA /* memmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAB7319C0527033000A80003 /* memmap.cpp */; }; + CF2F46A31095EE72007D33FA /* movie.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA813E9A066F50A5004F99B5 /* movie.cpp */; }; + CF2F46A41095EE72007D33FA /* obc1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C30526CCB900A80003 /* obc1.cpp */; }; + CF2F46A51095EE72007D33FA /* ppu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061C80526CCB900A80003 /* ppu.cpp */; }; + CF2F46A61095EE72007D33FA /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809E9F08F8D7530072CDFB /* reader.cpp */; }; + CF2F46A71095EE72007D33FA /* sa1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CB0526CCB900A80003 /* sa1.cpp */; }; + CF2F46A81095EE72007D33FA /* sa1cpu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061CD0526CCB900A80003 /* sa1cpu.cpp */; }; + CF2F46A91095EE72007D33FA /* sdd1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D10526CCB900A80003 /* sdd1.cpp */; }; + CF2F46AA1095EE72007D33FA /* sdd1emu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA22EFA4053EEE0700A80003 /* sdd1emu.cpp */; }; + CF2F46AB1095EE72007D33FA /* seta.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D40526CCB900A80003 /* seta.cpp */; }; + CF2F46AC1095EE72007D33FA /* seta010.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D60526CCB900A80003 /* seta010.cpp */; }; + CF2F46AD1095EE72007D33FA /* seta011.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D70526CCB900A80003 /* seta011.cpp */; }; + CF2F46AE1095EE72007D33FA /* seta018.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061D80526CCB900A80003 /* seta018.cpp */; }; + CF2F46AF1095EE72007D33FA /* snapshot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061DB0526CCB900A80003 /* snapshot.cpp */; }; + CF2F46B21095EE72007D33FA /* spc7110.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061E50526CCB900A80003 /* spc7110.cpp */; }; + CF2F46B31095EE72007D33FA /* srtc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061E90526CCB900A80003 /* srtc.cpp */; }; + CF2F46B41095EE72007D33FA /* tile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061EB0526CCB900A80003 /* tile.cpp */; }; + CF2F46B51095EE72007D33FA /* 2xsai.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B10EA24C36005957E4 /* 2xsai.cpp */; }; + CF2F46B61095EE72007D33FA /* blit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B30EA24C36005957E4 /* blit.cpp */; }; + CF2F46B71095EE72007D33FA /* epx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B50EA24C36005957E4 /* epx.cpp */; }; + CF2F46B81095EE72007D33FA /* hq2x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B70EA24C36005957E4 /* hq2x.cpp */; }; + CF2F46B91095EE72007D33FA /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = CFA518D10EBCB4AD008379F6 /* ioapi.c */; }; + CF2F46BA1095EE72007D33FA /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = CFA518BC0EBCB3ED008379F6 /* unzip.c */; }; + CF2F46BB1095EE72007D33FA /* 7zlzma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5DA07609F76001BAB8B /* 7zlzma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF2F46BC1095EE72007D33FA /* crc32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5DF07609F76001BAB8B /* crc32.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF2F46BD1095EE72007D33FA /* iiostrm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E107609F76001BAB8B /* iiostrm.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF2F46BE1095EE72007D33FA /* inbyte.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E307609F76001BAB8B /* inbyte.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF2F46BF1095EE72007D33FA /* jma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E507609F76001BAB8B /* jma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF2F46C01095EE72007D33FA /* lzma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5E907609F76001BAB8B /* lzma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF2F46C11095EE72007D33FA /* lzmadec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5EB07609F76001BAB8B /* lzmadec.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF2F46C21095EE72007D33FA /* s9x-jma.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5F007609F76001BAB8B /* s9x-jma.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF2F46C31095EE72007D33FA /* winout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7B5F207609F76001BAB8B /* winout.cpp */; settings = {COMPILER_FLAGS = "-fexceptions"; }; }; + CF2F46C41095EE72007D33FA /* mac-appleevent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EACDDBB004D6A89700A80003 /* mac-appleevent.cpp */; }; + CF2F46C51095EE72007D33FA /* mac-audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EADE6347052E5C4300A80003 /* mac-audio.cpp */; }; + CF2F46C61095EE72007D33FA /* mac-cart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67004AC7FCE00A80003 /* mac-cart.cpp */; }; + CF2F46C71095EE72007D33FA /* mac-cheat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67204AC7FCE00A80003 /* mac-cheat.cpp */; }; + CF2F46C81095EE72007D33FA /* mac-cheatfinder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67404AC7FCE00A80003 /* mac-cheatfinder.cpp */; }; + CF2F46C91095EE72007D33FA /* mac-client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA16051C0639E4C0004412AB /* mac-client.cpp */; }; + CF2F46CA1095EE72007D33FA /* mac-cocoatools.mm in Sources */ = {isa = PBXBuildFile; fileRef = EA85C24E0B4EC13300F5F9C9 /* mac-cocoatools.mm */; }; + CF2F46CB1095EE72007D33FA /* mac-controls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA809FA108F8F2420072CDFB /* mac-controls.cpp */; }; + CF2F46CC1095EE72007D33FA /* mac-coreimage.mm in Sources */ = {isa = PBXBuildFile; fileRef = EA0C952E08364A4A009307B4 /* mac-coreimage.mm */; }; + CF2F46CD1095EE72007D33FA /* mac-dialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67704AC7FCE00A80003 /* mac-dialog.cpp */; }; + CF2F46CE1095EE72007D33FA /* mac-file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA2DBC0C0510ABE700A80003 /* mac-file.cpp */; }; + CF2F46CF1095EE72007D33FA /* mac-gworld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67904AC7FCE00A80003 /* mac-gworld.cpp */; }; + CF2F46D01095EE72007D33FA /* mac-joypad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67B04AC7FCE00A80003 /* mac-joypad.cpp */; }; + CF2F46D11095EE72007D33FA /* mac-keyboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67D04AC7FCE00A80003 /* mac-keyboard.cpp */; }; + CF2F46D21095EE72007D33FA /* mac-multicart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA26BBD50B3676E800A570B5 /* mac-multicart.cpp */; }; + CF2F46D31095EE72007D33FA /* mac-musicbox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67F04AC7FCE00A80003 /* mac-musicbox.cpp */; }; + CF2F46D41095EE72007D33FA /* mac-netplay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA1605500639E735004412AB /* mac-netplay.cpp */; }; + CF2F46D51095EE72007D33FA /* mac-os.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0E96604D582B700A80003 /* mac-os.cpp */; }; + CF2F46D61095EE72007D33FA /* mac-prefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0E96B04D584B700A80003 /* mac-prefs.cpp */; }; + CF2F46D71095EE72007D33FA /* mac-quicktime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAA7F18506CB3D6F00C2D767 /* mac-quicktime.cpp */; }; + CF2F46D81095EE72007D33FA /* mac-render.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA942A50059B0F9000D7D022 /* mac-render.cpp */; }; + CF2F46D91095EE72007D33FA /* mac-screenshot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA2DBC0D0510ABE700A80003 /* mac-screenshot.cpp */; }; + CF2F46DA1095EE72007D33FA /* mac-server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EA16051D0639E4C0004412AB /* mac-server.cpp */; }; + CF2F46DB1095EE72007D33FA /* mac-snes9x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB68604AC7FCE00A80003 /* mac-snes9x.cpp */; }; + CF2F46DC1095EE72007D33FA /* mac-stringtools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAECB68804AC7FCE00A80003 /* mac-stringtools.cpp */; }; + CF2F46DE1095EE72007D33FA /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAC5E47003D2D9C800A80004 /* AGL.framework */; }; + CF2F46DF1095EE72007D33FA /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA85C2AC0B4ECA8300F5F9C9 /* AppKit.framework */; }; + CF2F46E01095EE72007D33FA /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EADE634B052E5D3600A80003 /* AudioToolbox.framework */; }; + CF2F46E11095EE72007D33FA /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EADE634C052E5D3600A80003 /* AudioUnit.framework */; }; + CF2F46E21095EE72007D33FA /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; + CF2F46E31095EE72007D33FA /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EADE634D052E5D3600A80003 /* CoreAudio.framework */; }; + CF2F46E41095EE72007D33FA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA0C95D808364AAE009307B4 /* Foundation.framework */; }; + CF2F46E51095EE72007D33FA /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5FC76BD03873BBF01A80002 /* IOKit.framework */; }; + CF2F46E61095EE72007D33FA /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA8FA89603D294C000A80004 /* OpenGL.framework */; }; + CF2F46E81095EE72007D33FA /* QuickTime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5C108DD0386806001A80002 /* QuickTime.framework */; }; + CF2F46E91095EE72007D33FA /* libHIDUtilities_u.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EA3D2F580A26085800BDACCC /* libHIDUtilities_u.a */; }; + CF2F46EA1095EE72007D33FA /* libz_u.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CF10B8EF0F63BF8A009C81CD /* libz_u.a */; }; + CF37575E10A6AEA1001BF7C5 /* apu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37574C10A6AEA1001BF7C5 /* apu.cpp */; }; + CF37575F10A6AEA1001BF7C5 /* apu.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37574D10A6AEA1001BF7C5 /* apu.h */; }; + CF37576010A6AEA1001BF7C5 /* blargg_common.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37574E10A6AEA1001BF7C5 /* blargg_common.h */; }; + CF37576110A6AEA1001BF7C5 /* blargg_config.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37574F10A6AEA1001BF7C5 /* blargg_config.h */; }; + CF37576210A6AEA1001BF7C5 /* blargg_endian.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575010A6AEA1001BF7C5 /* blargg_endian.h */; }; + CF37576310A6AEA1001BF7C5 /* blargg_source.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575110A6AEA1001BF7C5 /* blargg_source.h */; }; + CF37576510A6AEA1001BF7C5 /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575310A6AEA1001BF7C5 /* resampler.h */; }; + CF37576610A6AEA1001BF7C5 /* ring_buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575410A6AEA1001BF7C5 /* ring_buffer.h */; }; + CF37576710A6AEA1001BF7C5 /* SNES_SPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575510A6AEA1001BF7C5 /* SNES_SPC.cpp */; }; + CF37576810A6AEA1001BF7C5 /* SNES_SPC.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575610A6AEA1001BF7C5 /* SNES_SPC.h */; }; + CF37576910A6AEA1001BF7C5 /* SNES_SPC_misc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575710A6AEA1001BF7C5 /* SNES_SPC_misc.cpp */; }; + CF37576A10A6AEA1001BF7C5 /* SNES_SPC_state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575810A6AEA1001BF7C5 /* SNES_SPC_state.cpp */; }; + CF37576B10A6AEA1001BF7C5 /* SPC_CPU.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575910A6AEA1001BF7C5 /* SPC_CPU.h */; }; + CF37576C10A6AEA1001BF7C5 /* SPC_DSP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575A10A6AEA1001BF7C5 /* SPC_DSP.cpp */; }; + CF37576D10A6AEA1001BF7C5 /* SPC_DSP.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575B10A6AEA1001BF7C5 /* SPC_DSP.h */; }; + CF37576E10A6AEA1001BF7C5 /* SPC_Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575C10A6AEA1001BF7C5 /* SPC_Filter.cpp */; }; + CF37576F10A6AEA1001BF7C5 /* SPC_Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575D10A6AEA1001BF7C5 /* SPC_Filter.h */; }; + CF37577010A6AEA1001BF7C5 /* apu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37574C10A6AEA1001BF7C5 /* apu.cpp */; }; + CF37577110A6AEA1001BF7C5 /* apu.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37574D10A6AEA1001BF7C5 /* apu.h */; }; + CF37577210A6AEA1001BF7C5 /* blargg_common.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37574E10A6AEA1001BF7C5 /* blargg_common.h */; }; + CF37577310A6AEA1001BF7C5 /* blargg_config.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37574F10A6AEA1001BF7C5 /* blargg_config.h */; }; + CF37577410A6AEA1001BF7C5 /* blargg_endian.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575010A6AEA1001BF7C5 /* blargg_endian.h */; }; + CF37577510A6AEA1001BF7C5 /* blargg_source.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575110A6AEA1001BF7C5 /* blargg_source.h */; }; + CF37577710A6AEA1001BF7C5 /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575310A6AEA1001BF7C5 /* resampler.h */; }; + CF37577810A6AEA1001BF7C5 /* ring_buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575410A6AEA1001BF7C5 /* ring_buffer.h */; }; + CF37577910A6AEA1001BF7C5 /* SNES_SPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575510A6AEA1001BF7C5 /* SNES_SPC.cpp */; }; + CF37577A10A6AEA1001BF7C5 /* SNES_SPC.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575610A6AEA1001BF7C5 /* SNES_SPC.h */; }; + CF37577B10A6AEA1001BF7C5 /* SNES_SPC_misc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575710A6AEA1001BF7C5 /* SNES_SPC_misc.cpp */; }; + CF37577C10A6AEA1001BF7C5 /* SNES_SPC_state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575810A6AEA1001BF7C5 /* SNES_SPC_state.cpp */; }; + CF37577D10A6AEA1001BF7C5 /* SPC_CPU.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575910A6AEA1001BF7C5 /* SPC_CPU.h */; }; + CF37577E10A6AEA1001BF7C5 /* SPC_DSP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575A10A6AEA1001BF7C5 /* SPC_DSP.cpp */; }; + CF37577F10A6AEA1001BF7C5 /* SPC_DSP.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575B10A6AEA1001BF7C5 /* SPC_DSP.h */; }; + CF37578010A6AEA1001BF7C5 /* SPC_Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575C10A6AEA1001BF7C5 /* SPC_Filter.cpp */; }; + CF37578110A6AEA1001BF7C5 /* SPC_Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575D10A6AEA1001BF7C5 /* SPC_Filter.h */; }; + CF37578210A6AEA1001BF7C5 /* apu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37574C10A6AEA1001BF7C5 /* apu.cpp */; }; + CF37578310A6AEA1001BF7C5 /* apu.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37574D10A6AEA1001BF7C5 /* apu.h */; }; + CF37578410A6AEA1001BF7C5 /* blargg_common.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37574E10A6AEA1001BF7C5 /* blargg_common.h */; }; + CF37578510A6AEA1001BF7C5 /* blargg_config.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37574F10A6AEA1001BF7C5 /* blargg_config.h */; }; + CF37578610A6AEA1001BF7C5 /* blargg_endian.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575010A6AEA1001BF7C5 /* blargg_endian.h */; }; + CF37578710A6AEA1001BF7C5 /* blargg_source.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575110A6AEA1001BF7C5 /* blargg_source.h */; }; + CF37578910A6AEA1001BF7C5 /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575310A6AEA1001BF7C5 /* resampler.h */; }; + CF37578A10A6AEA1001BF7C5 /* ring_buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575410A6AEA1001BF7C5 /* ring_buffer.h */; }; + CF37578B10A6AEA1001BF7C5 /* SNES_SPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575510A6AEA1001BF7C5 /* SNES_SPC.cpp */; }; + CF37578C10A6AEA1001BF7C5 /* SNES_SPC.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575610A6AEA1001BF7C5 /* SNES_SPC.h */; }; + CF37578D10A6AEA1001BF7C5 /* SNES_SPC_misc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575710A6AEA1001BF7C5 /* SNES_SPC_misc.cpp */; }; + CF37578E10A6AEA1001BF7C5 /* SNES_SPC_state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575810A6AEA1001BF7C5 /* SNES_SPC_state.cpp */; }; + CF37578F10A6AEA1001BF7C5 /* SPC_CPU.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575910A6AEA1001BF7C5 /* SPC_CPU.h */; }; + CF37579010A6AEA1001BF7C5 /* SPC_DSP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575A10A6AEA1001BF7C5 /* SPC_DSP.cpp */; }; + CF37579110A6AEA1001BF7C5 /* SPC_DSP.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575B10A6AEA1001BF7C5 /* SPC_DSP.h */; }; + CF37579210A6AEA1001BF7C5 /* SPC_Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF37575C10A6AEA1001BF7C5 /* SPC_Filter.cpp */; }; + CF37579310A6AEA1001BF7C5 /* SPC_Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = CF37575D10A6AEA1001BF7C5 /* SPC_Filter.h */; }; + CF5553C90EA24C36005957E4 /* 2xsai.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B10EA24C36005957E4 /* 2xsai.cpp */; }; + CF5553CA0EA24C36005957E4 /* 2xsai.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B20EA24C36005957E4 /* 2xsai.h */; }; + CF5553CB0EA24C36005957E4 /* blit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B30EA24C36005957E4 /* blit.cpp */; }; + CF5553CC0EA24C36005957E4 /* blit.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B40EA24C36005957E4 /* blit.h */; }; + CF5553CD0EA24C36005957E4 /* epx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B50EA24C36005957E4 /* epx.cpp */; }; + CF5553CE0EA24C36005957E4 /* epx.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B60EA24C36005957E4 /* epx.h */; }; + CF5553CF0EA24C36005957E4 /* hq2x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5553B70EA24C36005957E4 /* hq2x.cpp */; }; + CF5553D00EA24C36005957E4 /* hq2x.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5553B80EA24C36005957E4 /* hq2x.h */; }; + CF5D3E130FAFD34200340007 /* dsp.h in Headers */ = {isa = PBXBuildFile; fileRef = CF5D3E100FAFD34200340007 /* dsp.h */; }; + CF5D3E240FAFD35400340007 /* dsp2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E1B0FAFD35400340007 /* dsp2.cpp */; }; + CF5D3E250FAFD35400340007 /* dsp4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E1C0FAFD35400340007 /* dsp4.cpp */; }; + CF5D3E260FAFD35400340007 /* dsp3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E1D0FAFD35400340007 /* dsp3.cpp */; }; + CF5D3E2A0FAFD35A00340007 /* dsp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF5D3E270FAFD35A00340007 /* dsp.cpp */; }; + CFA518C80EBCB3ED008379F6 /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = CFA518BC0EBCB3ED008379F6 /* unzip.c */; }; + CFA518D40EBCB4AD008379F6 /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = CFA518D10EBCB4AD008379F6 /* ioapi.c */; }; + CFA518D90EBCB4CA008379F6 /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518D60EBCB4CA008379F6 /* ioapi.h */; }; + CFA518DD0EBCB4D2008379F6 /* unzip.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518DA0EBCB4D2008379F6 /* unzip.h */; }; + CFA518E80EBCB5B1008379F6 /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518E50EBCB5B1008379F6 /* crypt.h */; }; + CFE7FBB10D2F6755002F3102 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE061710526CCB900A80003 /* debug.cpp */; }; + CFE7FBB40D2F67BA002F3102 /* fxemu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAE0617C0526CCB900A80003 /* fxemu.cpp */; }; + CFE7FBB80D2F683C002F3102 /* debug.h in Headers */ = {isa = PBXBuildFile; fileRef = EA6E6C0E08F9734500CB3555 /* debug.h */; }; + CFEFAE8B10EAC92300FB081A /* snes_ntsc.c in Sources */ = {isa = PBXBuildFile; fileRef = CFEFAE8A10EAC92300FB081A /* snes_ntsc.c */; }; + CFEFAE8C10EAC92300FB081A /* snes_ntsc.c in Sources */ = {isa = PBXBuildFile; fileRef = CFEFAE8A10EAC92300FB081A /* snes_ntsc.c */; }; + CFEFAE8D10EAC92300FB081A /* snes_ntsc.c in Sources */ = {isa = PBXBuildFile; fileRef = CFEFAE8A10EAC92300FB081A /* snes_ntsc.c */; }; + CFEFAE9110EAC92B00FB081A /* snes_ntsc_config.h in Headers */ = {isa = PBXBuildFile; fileRef = CFEFAE8E10EAC92B00FB081A /* snes_ntsc_config.h */; }; + CFEFAE9210EAC92B00FB081A /* snes_ntsc_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = CFEFAE8F10EAC92B00FB081A /* snes_ntsc_impl.h */; }; + CFEFAE9310EAC92B00FB081A /* snes_ntsc.h in Headers */ = {isa = PBXBuildFile; fileRef = CFEFAE9010EAC92B00FB081A /* snes_ntsc.h */; }; + CFEFAE9410EAC92B00FB081A /* snes_ntsc_config.h in Headers */ = {isa = PBXBuildFile; fileRef = CFEFAE8E10EAC92B00FB081A /* snes_ntsc_config.h */; }; + CFEFAE9510EAC92B00FB081A /* snes_ntsc_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = CFEFAE8F10EAC92B00FB081A /* snes_ntsc_impl.h */; }; + CFEFAE9610EAC92B00FB081A /* snes_ntsc.h in Headers */ = {isa = PBXBuildFile; fileRef = CFEFAE9010EAC92B00FB081A /* snes_ntsc.h */; }; + CFEFAE9710EAC92B00FB081A /* snes_ntsc_config.h in Headers */ = {isa = PBXBuildFile; fileRef = CFEFAE8E10EAC92B00FB081A /* snes_ntsc_config.h */; }; + CFEFAE9810EAC92B00FB081A /* snes_ntsc_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = CFEFAE8F10EAC92B00FB081A /* snes_ntsc_impl.h */; }; + CFEFAE9910EAC92B00FB081A /* snes_ntsc.h in Headers */ = {isa = PBXBuildFile; fileRef = CFEFAE9010EAC92B00FB081A /* snes_ntsc.h */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 20286C33FDCF999611CA2CEA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; + CF047E15109D0E0600FD0754 /* Snes9x (i386).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Snes9x (i386).app"; sourceTree = BUILT_PRODUCTS_DIR; }; + CF047E17109D0E0600FD0754 /* Info_i386.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info_i386.plist; sourceTree = ""; }; + CF0567660CF98E7E00C7877C /* Snes9x.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Snes9x.app; sourceTree = BUILT_PRODUCTS_DIR; }; + CF05677E0CF9971000C7877C /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = /System/Library/Frameworks/QuartzCore.framework; sourceTree = ""; }; + CF10B8EF0F63BF8A009C81CD /* libz_u.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libz_u.a; sourceTree = ""; }; + CF2CFFD30F10F2C000B8B35E /* spc7110emu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spc7110emu.cpp; sourceTree = ""; }; + CF2CFFD40F10F2C000B8B35E /* spc7110dec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = spc7110dec.cpp; sourceTree = ""; }; + CF2CFFDB0F10F2DD00B8B35E /* spc7110emu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spc7110emu.h; sourceTree = ""; }; + CF2CFFDC0F10F2DD00B8B35E /* spc7110dec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spc7110dec.h; sourceTree = ""; }; + CF2F46F11095EE72007D33FA /* Snes9x (ppc).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Snes9x (ppc).app"; sourceTree = BUILT_PRODUCTS_DIR; }; + CF2F47C41095F093007D33FA /* Info_ppc.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info_ppc.plist; sourceTree = ""; }; + CF37574C10A6AEA1001BF7C5 /* apu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = apu.cpp; sourceTree = ""; }; + CF37574D10A6AEA1001BF7C5 /* apu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = apu.h; sourceTree = ""; }; + CF37574E10A6AEA1001BF7C5 /* blargg_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blargg_common.h; sourceTree = ""; }; + CF37574F10A6AEA1001BF7C5 /* blargg_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blargg_config.h; sourceTree = ""; }; + CF37575010A6AEA1001BF7C5 /* blargg_endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blargg_endian.h; sourceTree = ""; }; + CF37575110A6AEA1001BF7C5 /* blargg_source.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blargg_source.h; sourceTree = ""; }; + CF37575310A6AEA1001BF7C5 /* resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resampler.h; sourceTree = ""; }; + CF37575410A6AEA1001BF7C5 /* ring_buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ring_buffer.h; sourceTree = ""; }; + CF37575510A6AEA1001BF7C5 /* SNES_SPC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SNES_SPC.cpp; sourceTree = ""; }; + CF37575610A6AEA1001BF7C5 /* SNES_SPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SNES_SPC.h; sourceTree = ""; }; + CF37575710A6AEA1001BF7C5 /* SNES_SPC_misc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SNES_SPC_misc.cpp; sourceTree = ""; }; + CF37575810A6AEA1001BF7C5 /* SNES_SPC_state.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SNES_SPC_state.cpp; sourceTree = ""; }; + CF37575910A6AEA1001BF7C5 /* SPC_CPU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPC_CPU.h; sourceTree = ""; }; + CF37575A10A6AEA1001BF7C5 /* SPC_DSP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SPC_DSP.cpp; sourceTree = ""; }; + CF37575B10A6AEA1001BF7C5 /* SPC_DSP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPC_DSP.h; sourceTree = ""; }; + CF37575C10A6AEA1001BF7C5 /* SPC_Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SPC_Filter.cpp; sourceTree = ""; }; + CF37575D10A6AEA1001BF7C5 /* SPC_Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPC_Filter.h; sourceTree = ""; }; + CF4B7C420CF841580080E643 /* icons.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icons.png; sourceTree = ""; }; + CF5553B10EA24C36005957E4 /* 2xsai.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = 2xsai.cpp; sourceTree = ""; }; + CF5553B20EA24C36005957E4 /* 2xsai.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = 2xsai.h; sourceTree = ""; }; + CF5553B30EA24C36005957E4 /* blit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = blit.cpp; sourceTree = ""; }; + CF5553B40EA24C36005957E4 /* blit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = blit.h; sourceTree = ""; }; + CF5553B50EA24C36005957E4 /* epx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = epx.cpp; sourceTree = ""; }; + CF5553B60EA24C36005957E4 /* epx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = epx.h; sourceTree = ""; }; + CF5553B70EA24C36005957E4 /* hq2x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = hq2x.cpp; sourceTree = ""; }; + CF5553B80EA24C36005957E4 /* hq2x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = hq2x.h; sourceTree = ""; }; + CF5D3E100FAFD34200340007 /* dsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dsp.h; sourceTree = ""; }; + CF5D3E1B0FAFD35400340007 /* dsp2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsp2.cpp; sourceTree = ""; }; + CF5D3E1C0FAFD35400340007 /* dsp4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsp4.cpp; sourceTree = ""; }; + CF5D3E1D0FAFD35400340007 /* dsp3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsp3.cpp; sourceTree = ""; }; + CF5D3E270FAFD35A00340007 /* dsp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dsp.cpp; sourceTree = ""; }; + CFA518BC0EBCB3ED008379F6 /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = ""; }; + CFA518D10EBCB4AD008379F6 /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = ""; }; + CFA518D60EBCB4CA008379F6 /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = ""; }; + CFA518DA0EBCB4D2008379F6 /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = ""; }; + CFA518E50EBCB5B1008379F6 /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = ""; }; + CFA82C3D0F1B43A60089C17F /* srtcemu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = srtcemu.h; sourceTree = ""; }; + CFA82C3E0F1B43A60089C17F /* srtcemu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = srtcemu.cpp; sourceTree = ""; }; + CFEFAE8A10EAC92300FB081A /* snes_ntsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = snes_ntsc.c; sourceTree = ""; }; + CFEFAE8E10EAC92B00FB081A /* snes_ntsc_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snes_ntsc_config.h; sourceTree = ""; }; + CFEFAE8F10EAC92B00FB081A /* snes_ntsc_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snes_ntsc_impl.h; sourceTree = ""; }; + CFEFAE9010EAC92B00FB081A /* snes_ntsc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = snes_ntsc.h; sourceTree = ""; }; + EA00D01D0A5A9956000C58E0 /* logger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = logger.cpp; sourceTree = ""; }; + EA00D01F0A5A998F000C58E0 /* logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logger.h; sourceTree = ""; }; + EA0C952D08364A4A009307B4 /* mac-coreimage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-coreimage.h"; sourceTree = ""; }; + EA0C952E08364A4A009307B4 /* mac-coreimage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = "mac-coreimage.mm"; sourceTree = ""; }; + EA0C95D808364AAE009307B4 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; + EA16051C0639E4C0004412AB /* mac-client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-client.cpp"; sourceTree = ""; }; + EA16051D0639E4C0004412AB /* mac-server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-server.cpp"; sourceTree = ""; }; + EA16053E0639E655004412AB /* mac-netplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-netplay.h"; sourceTree = ""; }; + EA16054C0639E6C7004412AB /* mac-server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-server.h"; sourceTree = ""; }; + EA1605500639E735004412AB /* mac-netplay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-netplay.cpp"; sourceTree = ""; }; + EA1605540639E937004412AB /* mac-client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-client.h"; sourceTree = ""; }; + EA22EFA2053EEDE500A80003 /* sdd1emu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = sdd1emu.h; sourceTree = ""; }; + EA22EFA4053EEE0700A80003 /* sdd1emu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = sdd1emu.cpp; sourceTree = ""; }; + EA26BBD50B3676E800A570B5 /* mac-multicart.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-multicart.cpp"; sourceTree = ""; }; + EA26BBD90B36771500A570B5 /* mac-multicart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-multicart.h"; sourceTree = ""; }; + EA2DBC070510ABE700A80003 /* mac-screenshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-screenshot.h"; sourceTree = ""; }; + EA2DBC090510ABE700A80003 /* mac-render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-render.h"; sourceTree = ""; }; + EA2DBC0A0510ABE700A80003 /* mac-file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-file.h"; sourceTree = ""; }; + EA2DBC0C0510ABE700A80003 /* mac-file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-file.cpp"; sourceTree = ""; }; + EA2DBC0D0510ABE700A80003 /* mac-screenshot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-screenshot.cpp"; sourceTree = ""; }; + EA2F380F09B17E070078DCA7 /* bsx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bsx.cpp; sourceTree = ""; }; + EA2F381A09B17E9E0078DCA7 /* bsx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bsx.h; sourceTree = ""; }; + EA31FE2D05F7743E00E13748 /* gfx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = gfx.cpp; sourceTree = ""; }; + EA362C3E086119D100FBE476 /* HID_Utilities_External.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = HID_Utilities_External.h; sourceTree = ""; }; + EA3BEA990A28384E00A8FAE5 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Localizable.strings; sourceTree = ""; }; + EA3BEA9D0A28384E00A8FAE5 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/Snes9x.nib; sourceTree = ""; }; + EA3BEA9F0A28384E00A8FAE5 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; + EA3BEAA90A28386500A8FAE5 /* English */ = {isa = PBXFileReference; lastKnownFileType = folder; name = English; path = "English.lproj/Snes9x Help"; sourceTree = ""; }; + EA3D2F360A26083B00BDACCC /* SRAM.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = SRAM.icns; sourceTree = ""; }; + EA3D2F370A26083B00BDACCC /* SAVE.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = SAVE.icns; sourceTree = ""; }; + EA3D2F380A26083B00BDACCC /* musicbox_ledon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = musicbox_ledon.icns; sourceTree = ""; }; + EA3D2F390A26083B00BDACCC /* musicbox_ledoff.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = musicbox_ledoff.icns; sourceTree = ""; }; + EA3D2F3A0A26083B00BDACCC /* folder_SRAMs.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = folder_SRAMs.icns; sourceTree = ""; }; + EA3D2F3B0A26083B00BDACCC /* folder_Freezes.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = folder_Freezes.icns; sourceTree = ""; }; + EA3D2F3C0A26083B00BDACCC /* CART.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = CART.icns; sourceTree = ""; }; + EA3D2F3D0A26083B00BDACCC /* APPL.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = APPL.icns; sourceTree = ""; }; + EA3D2F580A26085800BDACCC /* libHIDUtilities_u.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libHIDUtilities_u.a; sourceTree = ""; }; + EA3D300A0A260A3200BDACCC /* musicbox_indicator.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = musicbox_indicator.png; sourceTree = ""; }; + EA3D300B0A260A3200BDACCC /* logo_freeze.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo_freeze.png; sourceTree = ""; }; + EA3D300C0A260A3200BDACCC /* logo_defrost.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo_defrost.png; sourceTree = ""; }; + EA3D301C0A260A4D00BDACCC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + EA6E6C0E08F9734500CB3555 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; }; + EA809E9308F8D6C40072CDFB /* controls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controls.h; sourceTree = ""; }; + EA809E9508F8D6E00072CDFB /* language.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = language.h; sourceTree = ""; }; + EA809E9708F8D70D0072CDFB /* reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reader.h; sourceTree = ""; }; + EA809E9908F8D7240072CDFB /* controls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = controls.cpp; sourceTree = ""; }; + EA809E9B08F8D72C0072CDFB /* crosshairs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = crosshairs.cpp; sourceTree = ""; }; + EA809E9D08F8D73A0072CDFB /* crosshairs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crosshairs.h; sourceTree = ""; }; + EA809E9F08F8D7530072CDFB /* reader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reader.cpp; sourceTree = ""; }; + EA809F9D08F8F2190072CDFB /* mac-controls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-controls.h"; sourceTree = ""; }; + EA809FA108F8F2420072CDFB /* mac-controls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-controls.cpp"; sourceTree = ""; }; + EA813E86066F5076004F99B5 /* movie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = movie.h; sourceTree = ""; }; + EA813E9A066F50A5004F99B5 /* movie.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = movie.cpp; sourceTree = ""; }; + EA85C24D0B4EC13300F5F9C9 /* mac-cocoatools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-cocoatools.h"; sourceTree = ""; }; + EA85C24E0B4EC13300F5F9C9 /* mac-cocoatools.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = "mac-cocoatools.mm"; sourceTree = ""; }; + EA85C2AC0B4ECA8300F5F9C9 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; + EA85C3560B4ECBD900F5F9C9 /* freeze_defrost.aiff */ = {isa = PBXFileReference; lastKnownFileType = audio.aiff; path = freeze_defrost.aiff; sourceTree = ""; }; + EA8FA89603D294C000A80004 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; + EA942A50059B0F9000D7D022 /* mac-render.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-render.cpp"; sourceTree = ""; }; + EAA7B5D907609F76001BAB8B /* 7z.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = 7z.h; sourceTree = ""; }; + EAA7B5DA07609F76001BAB8B /* 7zlzma.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = 7zlzma.cpp; sourceTree = ""; }; + EAA7B5DB07609F76001BAB8B /* aribitcd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = aribitcd.h; sourceTree = ""; }; + EAA7B5DC07609F76001BAB8B /* ariconst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ariconst.h; sourceTree = ""; }; + EAA7B5DD07609F76001BAB8B /* ariprice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ariprice.h; sourceTree = ""; }; + EAA7B5DE07609F76001BAB8B /* btreecd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = btreecd.h; sourceTree = ""; }; + EAA7B5DF07609F76001BAB8B /* crc32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = crc32.cpp; sourceTree = ""; }; + EAA7B5E007609F76001BAB8B /* crc32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = crc32.h; sourceTree = ""; }; + EAA7B5E107609F76001BAB8B /* iiostrm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = iiostrm.cpp; sourceTree = ""; }; + EAA7B5E207609F76001BAB8B /* iiostrm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = iiostrm.h; sourceTree = ""; }; + EAA7B5E307609F76001BAB8B /* inbyte.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = inbyte.cpp; sourceTree = ""; }; + EAA7B5E407609F76001BAB8B /* inbyte.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = inbyte.h; sourceTree = ""; }; + EAA7B5E507609F76001BAB8B /* jma.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = jma.cpp; sourceTree = ""; }; + EAA7B5E607609F76001BAB8B /* jma.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = jma.h; sourceTree = ""; }; + EAA7B5E707609F76001BAB8B /* lencoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = lencoder.h; sourceTree = ""; }; + EAA7B5E807609F76001BAB8B /* litcoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = litcoder.h; sourceTree = ""; }; + EAA7B5E907609F76001BAB8B /* lzma.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = lzma.cpp; sourceTree = ""; }; + EAA7B5EA07609F76001BAB8B /* lzma.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = lzma.h; sourceTree = ""; }; + EAA7B5EB07609F76001BAB8B /* lzmadec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = lzmadec.cpp; sourceTree = ""; }; + EAA7B5EC07609F76001BAB8B /* lzmadec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = lzmadec.h; sourceTree = ""; }; + EAA7B5ED07609F76001BAB8B /* portable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = portable.h; sourceTree = ""; }; + EAA7B5EE07609F76001BAB8B /* rcdefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = rcdefs.h; sourceTree = ""; }; + EAA7B5EF07609F76001BAB8B /* rngcoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = rngcoder.h; sourceTree = ""; }; + EAA7B5F007609F76001BAB8B /* s9x-jma.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "s9x-jma.cpp"; sourceTree = ""; }; + EAA7B5F107609F76001BAB8B /* s9x-jma.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "s9x-jma.h"; sourceTree = ""; }; + EAA7B5F207609F76001BAB8B /* winout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = winout.cpp; sourceTree = ""; }; + EAA7B5F307609F76001BAB8B /* winout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = winout.h; sourceTree = ""; }; + EAA7F17F06CB3D4A00C2D767 /* mac-quicktime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-quicktime.h"; sourceTree = ""; }; + EAA7F18506CB3D6F00C2D767 /* mac-quicktime.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; lineEnding = 0; path = "mac-quicktime.cpp"; sourceTree = ""; }; + EAB7319C0527033000A80003 /* memmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = memmap.cpp; sourceTree = ""; }; + EAC5E47003D2D9C800A80004 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = /System/Library/Frameworks/AGL.framework; sourceTree = ""; }; + EACDDBB004D6A89700A80003 /* mac-appleevent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-appleevent.cpp"; sourceTree = ""; }; + EAD978980555059300E8BBFD /* mac-global_prefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-global_prefix.h"; sourceTree = ""; }; + EADE6347052E5C4300A80003 /* mac-audio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-audio.cpp"; sourceTree = ""; }; + EADE6349052E5C5300A80003 /* mac-audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-audio.h"; sourceTree = ""; }; + EADE634B052E5D3600A80003 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; + EADE634C052E5D3600A80003 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = /System/Library/Frameworks/AudioUnit.framework; sourceTree = ""; }; + EADE634D052E5D3600A80003 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; }; + EAE0615A0526CCB900A80003 /* 65c816.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = 65c816.h; sourceTree = ""; }; + EAE0615F0526CCB900A80003 /* c4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = c4.cpp; sourceTree = ""; }; + EAE061600526CCB900A80003 /* c4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = c4.h; sourceTree = ""; }; + EAE061610526CCB900A80003 /* c4emu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = c4emu.cpp; sourceTree = ""; }; + EAE061630526CCB900A80003 /* cheats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = cheats.cpp; sourceTree = ""; }; + EAE061640526CCB900A80003 /* cheats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = cheats.h; sourceTree = ""; }; + EAE061650526CCB900A80003 /* cheats2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = cheats2.cpp; sourceTree = ""; }; + EAE061660526CCB900A80003 /* clip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = clip.cpp; sourceTree = ""; }; + EAE061690526CCB900A80003 /* cpu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = cpu.cpp; sourceTree = ""; }; + EAE0616A0526CCB900A80003 /* cpuaddr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = cpuaddr.h; sourceTree = ""; }; + EAE0616B0526CCB900A80003 /* cpuexec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = cpuexec.cpp; sourceTree = ""; }; + EAE0616C0526CCB900A80003 /* cpuexec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = cpuexec.h; sourceTree = ""; }; + EAE0616D0526CCB900A80003 /* cpumacro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = cpumacro.h; sourceTree = ""; }; + EAE0616E0526CCB900A80003 /* cpuops.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = cpuops.cpp; sourceTree = ""; }; + EAE0616F0526CCB900A80003 /* cpuops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = cpuops.h; sourceTree = ""; }; + EAE061710526CCB900A80003 /* debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = debug.cpp; sourceTree = ""; }; + EAE061730526CCB900A80003 /* display.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = display.h; sourceTree = ""; }; + EAE061740526CCB900A80003 /* dma.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = dma.cpp; sourceTree = ""; }; + EAE061750526CCB900A80003 /* dma.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = dma.h; sourceTree = ""; }; + EAE061760526CCB900A80003 /* dsp1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = dsp1.cpp; sourceTree = ""; }; + EAE0617A0526CCB900A80003 /* font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = font.h; sourceTree = ""; }; + EAE0617C0526CCB900A80003 /* fxemu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = fxemu.cpp; sourceTree = ""; }; + EAE0617D0526CCB900A80003 /* fxemu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = fxemu.h; sourceTree = ""; }; + EAE0617E0526CCB900A80003 /* fxinst.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = fxinst.cpp; sourceTree = ""; }; + EAE0617F0526CCB900A80003 /* fxinst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = fxinst.h; sourceTree = ""; }; + EAE061800526CCB900A80003 /* getset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = getset.h; sourceTree = ""; }; + EAE061820526CCB900A80003 /* gfx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = gfx.h; sourceTree = ""; }; + EAE061830526CCB900A80003 /* globals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = globals.cpp; sourceTree = ""; }; + EAE061A90526CCB900A80003 /* loadzip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = loadzip.cpp; sourceTree = ""; }; + EAE061B10526CCB900A80003 /* memmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = memmap.h; sourceTree = ""; }; + EAE061B20526CCB900A80003 /* messages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = messages.h; sourceTree = ""; }; + EAE061B30526CCB900A80003 /* missing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = missing.h; sourceTree = ""; }; + EAE061C30526CCB900A80003 /* obc1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = obc1.cpp; sourceTree = ""; }; + EAE061C40526CCB900A80003 /* obc1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = obc1.h; sourceTree = ""; }; + EAE061C60526CCB900A80003 /* pixform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = pixform.h; sourceTree = ""; }; + EAE061C70526CCB900A80003 /* port.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = port.h; sourceTree = ""; }; + EAE061C80526CCB900A80003 /* ppu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = ppu.cpp; sourceTree = ""; }; + EAE061C90526CCB900A80003 /* ppu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ppu.h; sourceTree = ""; }; + EAE061CB0526CCB900A80003 /* sa1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = sa1.cpp; sourceTree = ""; }; + EAE061CC0526CCB900A80003 /* sa1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = sa1.h; sourceTree = ""; }; + EAE061CD0526CCB900A80003 /* sa1cpu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = sa1cpu.cpp; sourceTree = ""; }; + EAE061CE0526CCB900A80003 /* sar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = sar.h; sourceTree = ""; }; + EAE061D00526CCB900A80003 /* screenshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = screenshot.h; sourceTree = ""; }; + EAE061D10526CCB900A80003 /* sdd1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = sdd1.cpp; sourceTree = ""; }; + EAE061D20526CCB900A80003 /* sdd1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = sdd1.h; sourceTree = ""; }; + EAE061D40526CCB900A80003 /* seta.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = seta.cpp; sourceTree = ""; }; + EAE061D50526CCB900A80003 /* seta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = seta.h; sourceTree = ""; }; + EAE061D60526CCB900A80003 /* seta010.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = seta010.cpp; sourceTree = ""; }; + EAE061D70526CCB900A80003 /* seta011.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = seta011.cpp; sourceTree = ""; }; + EAE061D80526CCB900A80003 /* seta018.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = seta018.cpp; sourceTree = ""; }; + EAE061DB0526CCB900A80003 /* snapshot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = snapshot.cpp; sourceTree = ""; }; + EAE061DC0526CCB900A80003 /* snapshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = snapshot.h; sourceTree = ""; }; + EAE061DE0526CCB900A80003 /* snes9x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = snes9x.h; sourceTree = ""; }; + EAE061E50526CCB900A80003 /* spc7110.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = spc7110.cpp; sourceTree = ""; }; + EAE061E60526CCB900A80003 /* spc7110.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = spc7110.h; sourceTree = ""; }; + EAE061E90526CCB900A80003 /* srtc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = srtc.cpp; sourceTree = ""; }; + EAE061EA0526CCB900A80003 /* srtc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = srtc.h; sourceTree = ""; }; + EAE061EB0526CCB900A80003 /* tile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = tile.cpp; sourceTree = ""; }; + EAE061EC0526CCB900A80003 /* tile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = tile.h; sourceTree = ""; }; + EAE0E96604D582B700A80003 /* mac-os.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-os.cpp"; sourceTree = ""; }; + EAE0E96B04D584B700A80003 /* mac-prefs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-prefs.cpp"; sourceTree = ""; }; + EAECB66D04AC7FCD00A80003 /* mac-appleevent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-appleevent.h"; sourceTree = ""; }; + EAECB67004AC7FCE00A80003 /* mac-cart.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-cart.cpp"; sourceTree = ""; }; + EAECB67104AC7FCE00A80003 /* mac-cart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-cart.h"; sourceTree = ""; }; + EAECB67204AC7FCE00A80003 /* mac-cheat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-cheat.cpp"; sourceTree = ""; }; + EAECB67304AC7FCE00A80003 /* mac-cheat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-cheat.h"; sourceTree = ""; }; + EAECB67404AC7FCE00A80003 /* mac-cheatfinder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-cheatfinder.cpp"; sourceTree = ""; }; + EAECB67504AC7FCE00A80003 /* mac-cheatfinder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-cheatfinder.h"; sourceTree = ""; }; + EAECB67704AC7FCE00A80003 /* mac-dialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-dialog.cpp"; sourceTree = ""; }; + EAECB67804AC7FCE00A80003 /* mac-dialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-dialog.h"; sourceTree = ""; }; + EAECB67904AC7FCE00A80003 /* mac-gworld.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-gworld.cpp"; sourceTree = ""; }; + EAECB67A04AC7FCE00A80003 /* mac-gworld.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-gworld.h"; sourceTree = ""; }; + EAECB67B04AC7FCE00A80003 /* mac-joypad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-joypad.cpp"; sourceTree = ""; }; + EAECB67C04AC7FCE00A80003 /* mac-joypad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-joypad.h"; sourceTree = ""; }; + EAECB67D04AC7FCE00A80003 /* mac-keyboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-keyboard.cpp"; sourceTree = ""; }; + EAECB67E04AC7FCE00A80003 /* mac-keyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-keyboard.h"; sourceTree = ""; }; + EAECB67F04AC7FCE00A80003 /* mac-musicbox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-musicbox.cpp"; sourceTree = ""; }; + EAECB68004AC7FCE00A80003 /* mac-musicbox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-musicbox.h"; sourceTree = ""; }; + EAECB68204AC7FCE00A80003 /* mac-os.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-os.h"; sourceTree = ""; }; + EAECB68304AC7FCE00A80003 /* mac-prefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-prefix.h"; sourceTree = ""; }; + EAECB68504AC7FCE00A80003 /* mac-prefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-prefs.h"; sourceTree = ""; }; + EAECB68604AC7FCE00A80003 /* mac-snes9x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-snes9x.cpp"; sourceTree = ""; }; + EAECB68704AC7FCE00A80003 /* mac-snes9x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-snes9x.h"; sourceTree = ""; }; + EAECB68804AC7FCE00A80003 /* mac-stringtools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = "mac-stringtools.cpp"; sourceTree = ""; }; + EAECB68904AC7FCE00A80003 /* mac-stringtools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-stringtools.h"; sourceTree = ""; }; + F5C108DD0386806001A80002 /* QuickTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = /System/Library/Frameworks/QuickTime.framework; sourceTree = ""; }; + F5FC76BD03873BBF01A80002 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + CF047E03109D0E0600FD0754 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CF047E04109D0E0600FD0754 /* AGL.framework in Frameworks */, + CF047E05109D0E0600FD0754 /* AppKit.framework in Frameworks */, + CF047E06109D0E0600FD0754 /* AudioToolbox.framework in Frameworks */, + CF047E07109D0E0600FD0754 /* AudioUnit.framework in Frameworks */, + CF047E08109D0E0600FD0754 /* Carbon.framework in Frameworks */, + CF047E09109D0E0600FD0754 /* CoreAudio.framework in Frameworks */, + CF047E0A109D0E0600FD0754 /* Foundation.framework in Frameworks */, + CF047E0B109D0E0600FD0754 /* IOKit.framework in Frameworks */, + CF047E0C109D0E0600FD0754 /* OpenGL.framework in Frameworks */, + CF047E0D109D0E0600FD0754 /* QuartzCore.framework in Frameworks */, + CF047E0E109D0E0600FD0754 /* QuickTime.framework in Frameworks */, + CF047E0F109D0E0600FD0754 /* libHIDUtilities_u.a in Frameworks */, + CF047E10109D0E0600FD0754 /* libz_u.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF0567540CF98E7E00C7877C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CF05675D0CF98E7E00C7877C /* AGL.framework in Frameworks */, + CF0567570CF98E7E00C7877C /* AppKit.framework in Frameworks */, + CF05675A0CF98E7E00C7877C /* AudioToolbox.framework in Frameworks */, + CF0567590CF98E7E00C7877C /* AudioUnit.framework in Frameworks */, + CF0567550CF98E7E00C7877C /* Carbon.framework in Frameworks */, + CF0567580CF98E7E00C7877C /* CoreAudio.framework in Frameworks */, + CF0567560CF98E7E00C7877C /* Foundation.framework in Frameworks */, + CF05675E0CF98E7E00C7877C /* IOKit.framework in Frameworks */, + CF05675C0CF98E7E00C7877C /* OpenGL.framework in Frameworks */, + CF0567810CF9971000C7877C /* QuartzCore.framework in Frameworks */, + CF05675B0CF98E7E00C7877C /* QuickTime.framework in Frameworks */, + CF0567600CF98E7E00C7877C /* libHIDUtilities_u.a in Frameworks */, + CF10B8F20F63BF8A009C81CD /* libz_u.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF2F46DD1095EE72007D33FA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CF2F46DE1095EE72007D33FA /* AGL.framework in Frameworks */, + CF2F46DF1095EE72007D33FA /* AppKit.framework in Frameworks */, + CF2F46E01095EE72007D33FA /* AudioToolbox.framework in Frameworks */, + CF2F46E11095EE72007D33FA /* AudioUnit.framework in Frameworks */, + CF2F46E21095EE72007D33FA /* Carbon.framework in Frameworks */, + CF2F46E31095EE72007D33FA /* CoreAudio.framework in Frameworks */, + CF2F46E41095EE72007D33FA /* Foundation.framework in Frameworks */, + CF2F46E51095EE72007D33FA /* IOKit.framework in Frameworks */, + CF2F46E61095EE72007D33FA /* OpenGL.framework in Frameworks */, + CF2F46E81095EE72007D33FA /* QuickTime.framework in Frameworks */, + CF2F46E91095EE72007D33FA /* libHIDUtilities_u.a in Frameworks */, + CF2F46EA1095EE72007D33FA /* libz_u.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 195DF8C9FE9D4F0611CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + CF0567660CF98E7E00C7877C /* Snes9x.app */, + CF047E15109D0E0600FD0754 /* Snes9x (i386).app */, + CF2F46F11095EE72007D33FA /* Snes9x (ppc).app */, + ); + name = Products; + sourceTree = ""; + }; + 20286C29FDCF999611CA2CEA /* Snes9x CVS */ = { + isa = PBXGroup; + children = ( + 20286C2AFDCF999611CA2CEA /* Sources */, + 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */, + 195DF8C9FE9D4F0611CA2CBB /* Products */, + ); + name = "Snes9x CVS"; + sourceTree = ""; + }; + 20286C2AFDCF999611CA2CEA /* Sources */ = { + isa = PBXGroup; + children = ( + EAE061540526CCB900A80003 /* snes9x */, + ); + name = Sources; + sourceTree = ""; + }; + 20286C32FDCF999611CA2CEA /* External Frameworks and Libraries */ = { + isa = PBXGroup; + children = ( + EAC5E47003D2D9C800A80004 /* AGL.framework */, + EA85C2AC0B4ECA8300F5F9C9 /* AppKit.framework */, + EADE634B052E5D3600A80003 /* AudioToolbox.framework */, + EADE634C052E5D3600A80003 /* AudioUnit.framework */, + 20286C33FDCF999611CA2CEA /* Carbon.framework */, + EADE634D052E5D3600A80003 /* CoreAudio.framework */, + EA0C95D808364AAE009307B4 /* Foundation.framework */, + F5FC76BD03873BBF01A80002 /* IOKit.framework */, + EA8FA89603D294C000A80004 /* OpenGL.framework */, + CF05677E0CF9971000C7877C /* QuartzCore.framework */, + F5C108DD0386806001A80002 /* QuickTime.framework */, + ); + name = "External Frameworks and Libraries"; + sourceTree = ""; + }; + CF37574B10A6AEA1001BF7C5 /* apu */ = { + isa = PBXGroup; + children = ( + CF37574D10A6AEA1001BF7C5 /* apu.h */, + CF37574E10A6AEA1001BF7C5 /* blargg_common.h */, + CF37574F10A6AEA1001BF7C5 /* blargg_config.h */, + CF37575010A6AEA1001BF7C5 /* blargg_endian.h */, + CF37575110A6AEA1001BF7C5 /* blargg_source.h */, + CF37575310A6AEA1001BF7C5 /* resampler.h */, + CF37575410A6AEA1001BF7C5 /* ring_buffer.h */, + CF37575610A6AEA1001BF7C5 /* SNES_SPC.h */, + CF37575910A6AEA1001BF7C5 /* SPC_CPU.h */, + CF37575B10A6AEA1001BF7C5 /* SPC_DSP.h */, + CF37575D10A6AEA1001BF7C5 /* SPC_Filter.h */, + CF37574C10A6AEA1001BF7C5 /* apu.cpp */, + CF37575510A6AEA1001BF7C5 /* SNES_SPC.cpp */, + CF37575710A6AEA1001BF7C5 /* SNES_SPC_misc.cpp */, + CF37575810A6AEA1001BF7C5 /* SNES_SPC_state.cpp */, + CF37575A10A6AEA1001BF7C5 /* SPC_DSP.cpp */, + CF37575C10A6AEA1001BF7C5 /* SPC_Filter.cpp */, + ); + path = apu; + sourceTree = ""; + }; + CF5553B00EA24C36005957E4 /* filter */ = { + isa = PBXGroup; + children = ( + CF5553B20EA24C36005957E4 /* 2xsai.h */, + CF5553B40EA24C36005957E4 /* blit.h */, + CF5553B60EA24C36005957E4 /* epx.h */, + CF5553B80EA24C36005957E4 /* hq2x.h */, + CFEFAE9010EAC92B00FB081A /* snes_ntsc.h */, + CFEFAE8E10EAC92B00FB081A /* snes_ntsc_config.h */, + CFEFAE8F10EAC92B00FB081A /* snes_ntsc_impl.h */, + CF5553B10EA24C36005957E4 /* 2xsai.cpp */, + CF5553B30EA24C36005957E4 /* blit.cpp */, + CF5553B50EA24C36005957E4 /* epx.cpp */, + CF5553B70EA24C36005957E4 /* hq2x.cpp */, + CFEFAE8A10EAC92300FB081A /* snes_ntsc.c */, + ); + path = filter; + sourceTree = ""; + }; + EAA7B5D807609F76001BAB8B /* jma */ = { + isa = PBXGroup; + children = ( + EAA7B5D907609F76001BAB8B /* 7z.h */, + EAA7B5DB07609F76001BAB8B /* aribitcd.h */, + EAA7B5DC07609F76001BAB8B /* ariconst.h */, + EAA7B5DD07609F76001BAB8B /* ariprice.h */, + EAA7B5DE07609F76001BAB8B /* btreecd.h */, + EAA7B5E007609F76001BAB8B /* crc32.h */, + EAA7B5E207609F76001BAB8B /* iiostrm.h */, + EAA7B5E407609F76001BAB8B /* inbyte.h */, + EAA7B5E607609F76001BAB8B /* jma.h */, + EAA7B5E707609F76001BAB8B /* lencoder.h */, + EAA7B5E807609F76001BAB8B /* litcoder.h */, + EAA7B5EA07609F76001BAB8B /* lzma.h */, + EAA7B5EC07609F76001BAB8B /* lzmadec.h */, + EAA7B5ED07609F76001BAB8B /* portable.h */, + EAA7B5EE07609F76001BAB8B /* rcdefs.h */, + EAA7B5EF07609F76001BAB8B /* rngcoder.h */, + EAA7B5F107609F76001BAB8B /* s9x-jma.h */, + EAA7B5F307609F76001BAB8B /* winout.h */, + EAA7B5DA07609F76001BAB8B /* 7zlzma.cpp */, + EAA7B5DF07609F76001BAB8B /* crc32.cpp */, + EAA7B5E107609F76001BAB8B /* iiostrm.cpp */, + EAA7B5E307609F76001BAB8B /* inbyte.cpp */, + EAA7B5E507609F76001BAB8B /* jma.cpp */, + EAA7B5E907609F76001BAB8B /* lzma.cpp */, + EAA7B5EB07609F76001BAB8B /* lzmadec.cpp */, + EAA7B5F007609F76001BAB8B /* s9x-jma.cpp */, + EAA7B5F207609F76001BAB8B /* winout.cpp */, + ); + path = jma; + sourceTree = ""; + }; + EAE061540526CCB900A80003 /* snes9x */ = { + isa = PBXGroup; + children = ( + EAE0615A0526CCB900A80003 /* 65c816.h */, + EA2F381A09B17E9E0078DCA7 /* bsx.h */, + EAE061600526CCB900A80003 /* c4.h */, + EAE061640526CCB900A80003 /* cheats.h */, + EA809E9308F8D6C40072CDFB /* controls.h */, + EAE0616A0526CCB900A80003 /* cpuaddr.h */, + EAE0616C0526CCB900A80003 /* cpuexec.h */, + EAE0616D0526CCB900A80003 /* cpumacro.h */, + EAE0616F0526CCB900A80003 /* cpuops.h */, + EA809E9D08F8D73A0072CDFB /* crosshairs.h */, + EA6E6C0E08F9734500CB3555 /* debug.h */, + EAE061730526CCB900A80003 /* display.h */, + EAE061750526CCB900A80003 /* dma.h */, + CF5D3E100FAFD34200340007 /* dsp.h */, + EAE0617A0526CCB900A80003 /* font.h */, + EAE0617D0526CCB900A80003 /* fxemu.h */, + EAE0617F0526CCB900A80003 /* fxinst.h */, + EAE061800526CCB900A80003 /* getset.h */, + EAE061820526CCB900A80003 /* gfx.h */, + EA809E9508F8D6E00072CDFB /* language.h */, + EA00D01F0A5A998F000C58E0 /* logger.h */, + EAE061B10526CCB900A80003 /* memmap.h */, + EAE061B20526CCB900A80003 /* messages.h */, + EAE061B30526CCB900A80003 /* missing.h */, + EA813E86066F5076004F99B5 /* movie.h */, + EAE061C40526CCB900A80003 /* obc1.h */, + EAE061C60526CCB900A80003 /* pixform.h */, + EAE061C70526CCB900A80003 /* port.h */, + EAE061C90526CCB900A80003 /* ppu.h */, + EA809E9708F8D70D0072CDFB /* reader.h */, + EAE061CC0526CCB900A80003 /* sa1.h */, + EAE061CE0526CCB900A80003 /* sar.h */, + EAE061D00526CCB900A80003 /* screenshot.h */, + EAE061D20526CCB900A80003 /* sdd1.h */, + EA22EFA2053EEDE500A80003 /* sdd1emu.h */, + EAE061D50526CCB900A80003 /* seta.h */, + EAE061DC0526CCB900A80003 /* snapshot.h */, + EAE061DE0526CCB900A80003 /* snes9x.h */, + EAE061E60526CCB900A80003 /* spc7110.h */, + CF2CFFDC0F10F2DD00B8B35E /* spc7110dec.h */, + CF2CFFDB0F10F2DD00B8B35E /* spc7110emu.h */, + EAE061EA0526CCB900A80003 /* srtc.h */, + CFA82C3D0F1B43A60089C17F /* srtcemu.h */, + EAE061EC0526CCB900A80003 /* tile.h */, + EA2F380F09B17E070078DCA7 /* bsx.cpp */, + EAE0615F0526CCB900A80003 /* c4.cpp */, + EAE061610526CCB900A80003 /* c4emu.cpp */, + EAE061630526CCB900A80003 /* cheats.cpp */, + EAE061650526CCB900A80003 /* cheats2.cpp */, + EAE061660526CCB900A80003 /* clip.cpp */, + EA809E9908F8D7240072CDFB /* controls.cpp */, + EAE061690526CCB900A80003 /* cpu.cpp */, + EAE0616B0526CCB900A80003 /* cpuexec.cpp */, + EAE0616E0526CCB900A80003 /* cpuops.cpp */, + EA809E9B08F8D72C0072CDFB /* crosshairs.cpp */, + EAE061710526CCB900A80003 /* debug.cpp */, + EAE061740526CCB900A80003 /* dma.cpp */, + CF5D3E270FAFD35A00340007 /* dsp.cpp */, + EAE061760526CCB900A80003 /* dsp1.cpp */, + CF5D3E1B0FAFD35400340007 /* dsp2.cpp */, + CF5D3E1D0FAFD35400340007 /* dsp3.cpp */, + CF5D3E1C0FAFD35400340007 /* dsp4.cpp */, + EAE0617C0526CCB900A80003 /* fxemu.cpp */, + EAE0617E0526CCB900A80003 /* fxinst.cpp */, + EA31FE2D05F7743E00E13748 /* gfx.cpp */, + EAE061830526CCB900A80003 /* globals.cpp */, + EAE061A90526CCB900A80003 /* loadzip.cpp */, + EA00D01D0A5A9956000C58E0 /* logger.cpp */, + EAB7319C0527033000A80003 /* memmap.cpp */, + EA813E9A066F50A5004F99B5 /* movie.cpp */, + EAE061C30526CCB900A80003 /* obc1.cpp */, + EAE061C80526CCB900A80003 /* ppu.cpp */, + EA809E9F08F8D7530072CDFB /* reader.cpp */, + EAE061CB0526CCB900A80003 /* sa1.cpp */, + EAE061CD0526CCB900A80003 /* sa1cpu.cpp */, + EAE061D10526CCB900A80003 /* sdd1.cpp */, + EA22EFA4053EEE0700A80003 /* sdd1emu.cpp */, + EAE061D40526CCB900A80003 /* seta.cpp */, + EAE061D60526CCB900A80003 /* seta010.cpp */, + EAE061D70526CCB900A80003 /* seta011.cpp */, + EAE061D80526CCB900A80003 /* seta018.cpp */, + EAE061DB0526CCB900A80003 /* snapshot.cpp */, + EAE061E50526CCB900A80003 /* spc7110.cpp */, + CF2CFFD40F10F2C000B8B35E /* spc7110dec.cpp */, + CF2CFFD30F10F2C000B8B35E /* spc7110emu.cpp */, + EAE061E90526CCB900A80003 /* srtc.cpp */, + CFA82C3E0F1B43A60089C17F /* srtcemu.cpp */, + EAE061EB0526CCB900A80003 /* tile.cpp */, + CF37574B10A6AEA1001BF7C5 /* apu */, + CF5553B00EA24C36005957E4 /* filter */, + EAA7B5D807609F76001BAB8B /* jma */, + EAE061FD0526CCB900A80003 /* unzip */, + EAECB65C04AC7FCD00A80003 /* macosx */, + ); + name = snes9x; + path = ..; + sourceTree = ""; + }; + EAE061FD0526CCB900A80003 /* unzip */ = { + isa = PBXGroup; + children = ( + CFA518E50EBCB5B1008379F6 /* crypt.h */, + CFA518D60EBCB4CA008379F6 /* ioapi.h */, + CFA518DA0EBCB4D2008379F6 /* unzip.h */, + CFA518D10EBCB4AD008379F6 /* ioapi.c */, + CFA518BC0EBCB3ED008379F6 /* unzip.c */, + ); + path = unzip; + sourceTree = ""; + }; + EAECB65C04AC7FCD00A80003 /* macosx */ = { + isa = PBXGroup; + children = ( + EAECB66D04AC7FCD00A80003 /* mac-appleevent.h */, + EADE6349052E5C5300A80003 /* mac-audio.h */, + EAECB67104AC7FCE00A80003 /* mac-cart.h */, + EAECB67304AC7FCE00A80003 /* mac-cheat.h */, + EAECB67504AC7FCE00A80003 /* mac-cheatfinder.h */, + EA1605540639E937004412AB /* mac-client.h */, + EA85C24D0B4EC13300F5F9C9 /* mac-cocoatools.h */, + EA809F9D08F8F2190072CDFB /* mac-controls.h */, + EA0C952D08364A4A009307B4 /* mac-coreimage.h */, + EAECB67804AC7FCE00A80003 /* mac-dialog.h */, + EA2DBC0A0510ABE700A80003 /* mac-file.h */, + EAECB67A04AC7FCE00A80003 /* mac-gworld.h */, + EAECB67C04AC7FCE00A80003 /* mac-joypad.h */, + EAECB67E04AC7FCE00A80003 /* mac-keyboard.h */, + EA26BBD90B36771500A570B5 /* mac-multicart.h */, + EAECB68004AC7FCE00A80003 /* mac-musicbox.h */, + EA16053E0639E655004412AB /* mac-netplay.h */, + EAECB68204AC7FCE00A80003 /* mac-os.h */, + EAECB68504AC7FCE00A80003 /* mac-prefs.h */, + EAA7F17F06CB3D4A00C2D767 /* mac-quicktime.h */, + EA2DBC090510ABE700A80003 /* mac-render.h */, + EA2DBC070510ABE700A80003 /* mac-screenshot.h */, + EA16054C0639E6C7004412AB /* mac-server.h */, + EAECB68704AC7FCE00A80003 /* mac-snes9x.h */, + EAECB68904AC7FCE00A80003 /* mac-stringtools.h */, + EAECB68304AC7FCE00A80003 /* mac-prefix.h */, + EAD978980555059300E8BBFD /* mac-global_prefix.h */, + EA362C3E086119D100FBE476 /* HID_Utilities_External.h */, + EACDDBB004D6A89700A80003 /* mac-appleevent.cpp */, + EADE6347052E5C4300A80003 /* mac-audio.cpp */, + EAECB67004AC7FCE00A80003 /* mac-cart.cpp */, + EAECB67204AC7FCE00A80003 /* mac-cheat.cpp */, + EAECB67404AC7FCE00A80003 /* mac-cheatfinder.cpp */, + EA16051C0639E4C0004412AB /* mac-client.cpp */, + EA85C24E0B4EC13300F5F9C9 /* mac-cocoatools.mm */, + EA809FA108F8F2420072CDFB /* mac-controls.cpp */, + EA0C952E08364A4A009307B4 /* mac-coreimage.mm */, + EAECB67704AC7FCE00A80003 /* mac-dialog.cpp */, + EA2DBC0C0510ABE700A80003 /* mac-file.cpp */, + EAECB67904AC7FCE00A80003 /* mac-gworld.cpp */, + EAECB67B04AC7FCE00A80003 /* mac-joypad.cpp */, + EAECB67D04AC7FCE00A80003 /* mac-keyboard.cpp */, + EA26BBD50B3676E800A570B5 /* mac-multicart.cpp */, + EAECB67F04AC7FCE00A80003 /* mac-musicbox.cpp */, + EA1605500639E735004412AB /* mac-netplay.cpp */, + EAE0E96604D582B700A80003 /* mac-os.cpp */, + EAE0E96B04D584B700A80003 /* mac-prefs.cpp */, + EAA7F18506CB3D6F00C2D767 /* mac-quicktime.cpp */, + EA942A50059B0F9000D7D022 /* mac-render.cpp */, + EA2DBC0D0510ABE700A80003 /* mac-screenshot.cpp */, + EA16051D0639E4C0004412AB /* mac-server.cpp */, + EAECB68604AC7FCE00A80003 /* mac-snes9x.cpp */, + EAECB68804AC7FCE00A80003 /* mac-stringtools.cpp */, + EA3D2F3D0A26083B00BDACCC /* APPL.icns */, + EA3D2F3C0A26083B00BDACCC /* CART.icns */, + EA3D2F360A26083B00BDACCC /* SRAM.icns */, + EA3D2F370A26083B00BDACCC /* SAVE.icns */, + EA3D2F3A0A26083B00BDACCC /* folder_SRAMs.icns */, + EA3D2F3B0A26083B00BDACCC /* folder_Freezes.icns */, + CF4B7C420CF841580080E643 /* icons.png */, + EA3D300B0A260A3200BDACCC /* logo_freeze.png */, + EA3D300C0A260A3200BDACCC /* logo_defrost.png */, + EA3D300A0A260A3200BDACCC /* musicbox_indicator.png */, + EA3D2F380A26083B00BDACCC /* musicbox_ledon.icns */, + EA3D2F390A26083B00BDACCC /* musicbox_ledoff.icns */, + EA85C3560B4ECBD900F5F9C9 /* freeze_defrost.aiff */, + EA3BEA9E0A28384E00A8FAE5 /* InfoPlist.strings */, + EA3BEA980A28384E00A8FAE5 /* Localizable.strings */, + EA3BEA9C0A28384E00A8FAE5 /* Snes9x.nib */, + EA3BEAA80A28386500A8FAE5 /* Snes9x Help */, + EA3D2F580A26085800BDACCC /* libHIDUtilities_u.a */, + CF10B8EF0F63BF8A009C81CD /* libz_u.a */, + EA3D301C0A260A4D00BDACCC /* Info.plist */, + CF047E17109D0E0600FD0754 /* Info_i386.plist */, + CF2F47C41095F093007D33FA /* Info_ppc.plist */, + ); + path = macosx; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + CF047D37109D0E0600FD0754 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CF047D38109D0E0600FD0754 /* 65c816.h in Headers */, + CF047D3B109D0E0600FD0754 /* bsx.h in Headers */, + CF047D3C109D0E0600FD0754 /* c4.h in Headers */, + CF047D3D109D0E0600FD0754 /* cheats.h in Headers */, + CF047D3E109D0E0600FD0754 /* controls.h in Headers */, + CF047D3F109D0E0600FD0754 /* cpuaddr.h in Headers */, + CF047D40109D0E0600FD0754 /* cpuexec.h in Headers */, + CF047D41109D0E0600FD0754 /* cpumacro.h in Headers */, + CF047D42109D0E0600FD0754 /* cpuops.h in Headers */, + CF047D43109D0E0600FD0754 /* crosshairs.h in Headers */, + CF047D44109D0E0600FD0754 /* debug.h in Headers */, + CF047D45109D0E0600FD0754 /* display.h in Headers */, + CF047D46109D0E0600FD0754 /* dma.h in Headers */, + CF047D47109D0E0600FD0754 /* dsp.h in Headers */, + CF047D48109D0E0600FD0754 /* font.h in Headers */, + CF047D49109D0E0600FD0754 /* fxemu.h in Headers */, + CF047D4A109D0E0600FD0754 /* fxinst.h in Headers */, + CF047D4B109D0E0600FD0754 /* getset.h in Headers */, + CF047D4C109D0E0600FD0754 /* gfx.h in Headers */, + CF047D4D109D0E0600FD0754 /* language.h in Headers */, + CF047D4E109D0E0600FD0754 /* logger.h in Headers */, + CF047D4F109D0E0600FD0754 /* memmap.h in Headers */, + CF047D50109D0E0600FD0754 /* messages.h in Headers */, + CF047D51109D0E0600FD0754 /* missing.h in Headers */, + CF047D52109D0E0600FD0754 /* movie.h in Headers */, + CF047D53109D0E0600FD0754 /* obc1.h in Headers */, + CF047D54109D0E0600FD0754 /* pixform.h in Headers */, + CF047D55109D0E0600FD0754 /* port.h in Headers */, + CF047D56109D0E0600FD0754 /* ppu.h in Headers */, + CF047D57109D0E0600FD0754 /* reader.h in Headers */, + CF047D58109D0E0600FD0754 /* sa1.h in Headers */, + CF047D59109D0E0600FD0754 /* sar.h in Headers */, + CF047D5A109D0E0600FD0754 /* screenshot.h in Headers */, + CF047D5B109D0E0600FD0754 /* sdd1.h in Headers */, + CF047D5C109D0E0600FD0754 /* sdd1emu.h in Headers */, + CF047D5D109D0E0600FD0754 /* seta.h in Headers */, + CF047D5E109D0E0600FD0754 /* snapshot.h in Headers */, + CF047D5F109D0E0600FD0754 /* snes9x.h in Headers */, + CF047D62109D0E0600FD0754 /* spc7110.h in Headers */, + CF047D63109D0E0600FD0754 /* srtc.h in Headers */, + CF047D64109D0E0600FD0754 /* tile.h in Headers */, + CF37577110A6AEA1001BF7C5 /* apu.h in Headers */, + CF37577210A6AEA1001BF7C5 /* blargg_common.h in Headers */, + CF37577310A6AEA1001BF7C5 /* blargg_config.h in Headers */, + CF37577410A6AEA1001BF7C5 /* blargg_endian.h in Headers */, + CF37577510A6AEA1001BF7C5 /* blargg_source.h in Headers */, + CF37577710A6AEA1001BF7C5 /* resampler.h in Headers */, + CF37577810A6AEA1001BF7C5 /* ring_buffer.h in Headers */, + CF37577A10A6AEA1001BF7C5 /* SNES_SPC.h in Headers */, + CF37577D10A6AEA1001BF7C5 /* SPC_CPU.h in Headers */, + CF37577F10A6AEA1001BF7C5 /* SPC_DSP.h in Headers */, + CF37578110A6AEA1001BF7C5 /* SPC_Filter.h in Headers */, + CF047D65109D0E0600FD0754 /* 2xsai.h in Headers */, + CF047D66109D0E0600FD0754 /* blit.h in Headers */, + CF047D67109D0E0600FD0754 /* epx.h in Headers */, + CF047D68109D0E0600FD0754 /* hq2x.h in Headers */, + CFEFAE9610EAC92B00FB081A /* snes_ntsc.h in Headers */, + CFEFAE9410EAC92B00FB081A /* snes_ntsc_config.h in Headers */, + CFEFAE9510EAC92B00FB081A /* snes_ntsc_impl.h in Headers */, + CF047D69109D0E0600FD0754 /* crypt.h in Headers */, + CF047D6A109D0E0600FD0754 /* ioapi.h in Headers */, + CF047D6B109D0E0600FD0754 /* unzip.h in Headers */, + CF047D6C109D0E0600FD0754 /* 7z.h in Headers */, + CF047D6D109D0E0600FD0754 /* aribitcd.h in Headers */, + CF047D6E109D0E0600FD0754 /* ariconst.h in Headers */, + CF047D6F109D0E0600FD0754 /* ariprice.h in Headers */, + CF047D70109D0E0600FD0754 /* btreecd.h in Headers */, + CF047D71109D0E0600FD0754 /* crc32.h in Headers */, + CF047D72109D0E0600FD0754 /* iiostrm.h in Headers */, + CF047D73109D0E0600FD0754 /* inbyte.h in Headers */, + CF047D74109D0E0600FD0754 /* jma.h in Headers */, + CF047D75109D0E0600FD0754 /* lencoder.h in Headers */, + CF047D76109D0E0600FD0754 /* litcoder.h in Headers */, + CF047D77109D0E0600FD0754 /* lzma.h in Headers */, + CF047D78109D0E0600FD0754 /* lzmadec.h in Headers */, + CF047D79109D0E0600FD0754 /* portable.h in Headers */, + CF047D7A109D0E0600FD0754 /* rcdefs.h in Headers */, + CF047D7B109D0E0600FD0754 /* rngcoder.h in Headers */, + CF047D7C109D0E0600FD0754 /* s9x-jma.h in Headers */, + CF047D7D109D0E0600FD0754 /* winout.h in Headers */, + CF047D7E109D0E0600FD0754 /* mac-appleevent.h in Headers */, + CF047D7F109D0E0600FD0754 /* mac-audio.h in Headers */, + CF047D80109D0E0600FD0754 /* mac-cart.h in Headers */, + CF047D81109D0E0600FD0754 /* mac-cheat.h in Headers */, + CF047D82109D0E0600FD0754 /* mac-cheatfinder.h in Headers */, + CF047D83109D0E0600FD0754 /* mac-client.h in Headers */, + CF047D84109D0E0600FD0754 /* mac-cocoatools.h in Headers */, + CF047D85109D0E0600FD0754 /* mac-controls.h in Headers */, + CF047D86109D0E0600FD0754 /* mac-coreimage.h in Headers */, + CF047D87109D0E0600FD0754 /* mac-dialog.h in Headers */, + CF047D88109D0E0600FD0754 /* mac-file.h in Headers */, + CF047D89109D0E0600FD0754 /* mac-gworld.h in Headers */, + CF047D8A109D0E0600FD0754 /* mac-joypad.h in Headers */, + CF047D8B109D0E0600FD0754 /* mac-keyboard.h in Headers */, + CF047D8C109D0E0600FD0754 /* mac-multicart.h in Headers */, + CF047D8D109D0E0600FD0754 /* mac-musicbox.h in Headers */, + CF047D8E109D0E0600FD0754 /* mac-netplay.h in Headers */, + CF047D8F109D0E0600FD0754 /* mac-os.h in Headers */, + CF047D90109D0E0600FD0754 /* mac-prefs.h in Headers */, + CF047D91109D0E0600FD0754 /* mac-quicktime.h in Headers */, + CF047D92109D0E0600FD0754 /* mac-render.h in Headers */, + CF047D93109D0E0600FD0754 /* mac-screenshot.h in Headers */, + CF047D94109D0E0600FD0754 /* mac-server.h in Headers */, + CF047D95109D0E0600FD0754 /* mac-snes9x.h in Headers */, + CF047D96109D0E0600FD0754 /* mac-stringtools.h in Headers */, + CF047D97109D0E0600FD0754 /* mac-prefix.h in Headers */, + CF047D98109D0E0600FD0754 /* mac-global_prefix.h in Headers */, + CF047D99109D0E0600FD0754 /* HID_Utilities_External.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF05668D0CF98E7E00C7877C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CF05668E0CF98E7E00C7877C /* 65c816.h in Headers */, + CF0566910CF98E7E00C7877C /* bsx.h in Headers */, + CF0566920CF98E7E00C7877C /* c4.h in Headers */, + CF0566930CF98E7E00C7877C /* cheats.h in Headers */, + CF0566940CF98E7E00C7877C /* controls.h in Headers */, + CF0566950CF98E7E00C7877C /* cpuaddr.h in Headers */, + CF0566960CF98E7E00C7877C /* cpuexec.h in Headers */, + CF0566970CF98E7E00C7877C /* cpumacro.h in Headers */, + CF0566980CF98E7E00C7877C /* cpuops.h in Headers */, + CF0566990CF98E7E00C7877C /* crosshairs.h in Headers */, + CFE7FBB80D2F683C002F3102 /* debug.h in Headers */, + CF05669A0CF98E7E00C7877C /* display.h in Headers */, + CF05669B0CF98E7E00C7877C /* dma.h in Headers */, + CF5D3E130FAFD34200340007 /* dsp.h in Headers */, + CF05669D0CF98E7E00C7877C /* font.h in Headers */, + CF05669E0CF98E7E00C7877C /* fxemu.h in Headers */, + CF05669F0CF98E7E00C7877C /* fxinst.h in Headers */, + CF0566A00CF98E7E00C7877C /* getset.h in Headers */, + CF0566A10CF98E7E00C7877C /* gfx.h in Headers */, + CF0566A20CF98E7E00C7877C /* language.h in Headers */, + CF0566A30CF98E7E00C7877C /* logger.h in Headers */, + CF0566A40CF98E7E00C7877C /* memmap.h in Headers */, + CF0566A50CF98E7E00C7877C /* messages.h in Headers */, + CF0566A60CF98E7E00C7877C /* missing.h in Headers */, + CF0566A70CF98E7E00C7877C /* movie.h in Headers */, + CF0566A80CF98E7E00C7877C /* obc1.h in Headers */, + CF0566A90CF98E7E00C7877C /* pixform.h in Headers */, + CF0566AA0CF98E7E00C7877C /* port.h in Headers */, + CF0566AB0CF98E7E00C7877C /* ppu.h in Headers */, + CF0566AC0CF98E7E00C7877C /* reader.h in Headers */, + CF0566AD0CF98E7E00C7877C /* sa1.h in Headers */, + CF0566AE0CF98E7E00C7877C /* sar.h in Headers */, + CF0566AF0CF98E7E00C7877C /* screenshot.h in Headers */, + CF0566B00CF98E7E00C7877C /* sdd1.h in Headers */, + CF0566B10CF98E7E00C7877C /* sdd1emu.h in Headers */, + CF0566B20CF98E7E00C7877C /* seta.h in Headers */, + CF0566B30CF98E7E00C7877C /* snapshot.h in Headers */, + CF0566B40CF98E7E00C7877C /* snes9x.h in Headers */, + CF0566B70CF98E7E00C7877C /* spc7110.h in Headers */, + CF0566B80CF98E7E00C7877C /* srtc.h in Headers */, + CF0566B90CF98E7E00C7877C /* tile.h in Headers */, + CF37578310A6AEA1001BF7C5 /* apu.h in Headers */, + CF37578410A6AEA1001BF7C5 /* blargg_common.h in Headers */, + CF37578510A6AEA1001BF7C5 /* blargg_config.h in Headers */, + CF37578610A6AEA1001BF7C5 /* blargg_endian.h in Headers */, + CF37578710A6AEA1001BF7C5 /* blargg_source.h in Headers */, + CF37578910A6AEA1001BF7C5 /* resampler.h in Headers */, + CF37578A10A6AEA1001BF7C5 /* ring_buffer.h in Headers */, + CF37578C10A6AEA1001BF7C5 /* SNES_SPC.h in Headers */, + CF37578F10A6AEA1001BF7C5 /* SPC_CPU.h in Headers */, + CF37579110A6AEA1001BF7C5 /* SPC_DSP.h in Headers */, + CF37579310A6AEA1001BF7C5 /* SPC_Filter.h in Headers */, + CF5553CA0EA24C36005957E4 /* 2xsai.h in Headers */, + CF5553CC0EA24C36005957E4 /* blit.h in Headers */, + CF5553CE0EA24C36005957E4 /* epx.h in Headers */, + CF5553D00EA24C36005957E4 /* hq2x.h in Headers */, + CFEFAE9910EAC92B00FB081A /* snes_ntsc.h in Headers */, + CFEFAE9710EAC92B00FB081A /* snes_ntsc_config.h in Headers */, + CFEFAE9810EAC92B00FB081A /* snes_ntsc_impl.h in Headers */, + CFA518E80EBCB5B1008379F6 /* crypt.h in Headers */, + CFA518D90EBCB4CA008379F6 /* ioapi.h in Headers */, + CFA518DD0EBCB4D2008379F6 /* unzip.h in Headers */, + CF0566BD0CF98E7E00C7877C /* 7z.h in Headers */, + CF0566BE0CF98E7E00C7877C /* aribitcd.h in Headers */, + CF0566BF0CF98E7E00C7877C /* ariconst.h in Headers */, + CF0566C00CF98E7E00C7877C /* ariprice.h in Headers */, + CF0566C10CF98E7E00C7877C /* btreecd.h in Headers */, + CF0566C20CF98E7E00C7877C /* crc32.h in Headers */, + CF0566C30CF98E7E00C7877C /* iiostrm.h in Headers */, + CF0566C40CF98E7E00C7877C /* inbyte.h in Headers */, + CF0566C50CF98E7E00C7877C /* jma.h in Headers */, + CF0566C60CF98E7E00C7877C /* lencoder.h in Headers */, + CF0566C70CF98E7E00C7877C /* litcoder.h in Headers */, + CF0566C80CF98E7E00C7877C /* lzma.h in Headers */, + CF0566C90CF98E7E00C7877C /* lzmadec.h in Headers */, + CF0566CA0CF98E7E00C7877C /* portable.h in Headers */, + CF0566CB0CF98E7E00C7877C /* rcdefs.h in Headers */, + CF0566CC0CF98E7E00C7877C /* rngcoder.h in Headers */, + CF0566CD0CF98E7E00C7877C /* s9x-jma.h in Headers */, + CF0566CE0CF98E7E00C7877C /* winout.h in Headers */, + CF0566D00CF98E7E00C7877C /* mac-appleevent.h in Headers */, + CF0566D10CF98E7E00C7877C /* mac-audio.h in Headers */, + CF0566D30CF98E7E00C7877C /* mac-cart.h in Headers */, + CF0566D40CF98E7E00C7877C /* mac-cheat.h in Headers */, + CF0566D50CF98E7E00C7877C /* mac-cheatfinder.h in Headers */, + CF0566D60CF98E7E00C7877C /* mac-client.h in Headers */, + CF0566D70CF98E7E00C7877C /* mac-cocoatools.h in Headers */, + CF0566D80CF98E7E00C7877C /* mac-controls.h in Headers */, + CF0566D90CF98E7E00C7877C /* mac-coreimage.h in Headers */, + CF0566DA0CF98E7E00C7877C /* mac-dialog.h in Headers */, + CF0566DC0CF98E7E00C7877C /* mac-file.h in Headers */, + CF0566DD0CF98E7E00C7877C /* mac-gworld.h in Headers */, + CF0566DF0CF98E7E00C7877C /* mac-joypad.h in Headers */, + CF0566E00CF98E7E00C7877C /* mac-keyboard.h in Headers */, + CF0566E10CF98E7E00C7877C /* mac-multicart.h in Headers */, + CF0566E20CF98E7E00C7877C /* mac-musicbox.h in Headers */, + CF0566E30CF98E7E00C7877C /* mac-netplay.h in Headers */, + CF0566E40CF98E7E00C7877C /* mac-os.h in Headers */, + CF0566E50CF98E7E00C7877C /* mac-prefs.h in Headers */, + CF0566E60CF98E7E00C7877C /* mac-quicktime.h in Headers */, + CF0566E70CF98E7E00C7877C /* mac-render.h in Headers */, + CF0566E80CF98E7E00C7877C /* mac-screenshot.h in Headers */, + CF0566E90CF98E7E00C7877C /* mac-server.h in Headers */, + CF0566EA0CF98E7E00C7877C /* mac-snes9x.h in Headers */, + CF0566EB0CF98E7E00C7877C /* mac-stringtools.h in Headers */, + CF0566EC0CF98E7E00C7877C /* mac-prefix.h in Headers */, + CF0566ED0CF98E7E00C7877C /* mac-global_prefix.h in Headers */, + CF0566EE0CF98E7E00C7877C /* HID_Utilities_External.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF2F46111095EE72007D33FA /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + CF2F46121095EE72007D33FA /* 65c816.h in Headers */, + CF2F46151095EE72007D33FA /* bsx.h in Headers */, + CF2F46161095EE72007D33FA /* c4.h in Headers */, + CF2F46171095EE72007D33FA /* cheats.h in Headers */, + CF2F46181095EE72007D33FA /* controls.h in Headers */, + CF2F46191095EE72007D33FA /* cpuaddr.h in Headers */, + CF2F461A1095EE72007D33FA /* cpuexec.h in Headers */, + CF2F461B1095EE72007D33FA /* cpumacro.h in Headers */, + CF2F461C1095EE72007D33FA /* cpuops.h in Headers */, + CF2F461D1095EE72007D33FA /* crosshairs.h in Headers */, + CF2F461E1095EE72007D33FA /* debug.h in Headers */, + CF2F461F1095EE72007D33FA /* display.h in Headers */, + CF2F46201095EE72007D33FA /* dma.h in Headers */, + CF2F46211095EE72007D33FA /* dsp.h in Headers */, + CF2F46221095EE72007D33FA /* font.h in Headers */, + CF2F46231095EE72007D33FA /* fxemu.h in Headers */, + CF2F46241095EE72007D33FA /* fxinst.h in Headers */, + CF2F46251095EE72007D33FA /* getset.h in Headers */, + CF2F46261095EE72007D33FA /* gfx.h in Headers */, + CF2F46271095EE72007D33FA /* language.h in Headers */, + CF2F46281095EE72007D33FA /* logger.h in Headers */, + CF2F46291095EE72007D33FA /* memmap.h in Headers */, + CF2F462A1095EE72007D33FA /* messages.h in Headers */, + CF2F462B1095EE72007D33FA /* missing.h in Headers */, + CF2F462C1095EE72007D33FA /* movie.h in Headers */, + CF2F462D1095EE72007D33FA /* obc1.h in Headers */, + CF2F462E1095EE72007D33FA /* pixform.h in Headers */, + CF2F462F1095EE72007D33FA /* port.h in Headers */, + CF2F46301095EE72007D33FA /* ppu.h in Headers */, + CF2F46311095EE72007D33FA /* reader.h in Headers */, + CF2F46321095EE72007D33FA /* sa1.h in Headers */, + CF2F46331095EE72007D33FA /* sar.h in Headers */, + CF2F46341095EE72007D33FA /* screenshot.h in Headers */, + CF2F46351095EE72007D33FA /* sdd1.h in Headers */, + CF2F46361095EE72007D33FA /* sdd1emu.h in Headers */, + CF2F46371095EE72007D33FA /* seta.h in Headers */, + CF2F46381095EE72007D33FA /* snapshot.h in Headers */, + CF2F46391095EE72007D33FA /* snes9x.h in Headers */, + CF2F463C1095EE72007D33FA /* spc7110.h in Headers */, + CF2F463D1095EE72007D33FA /* srtc.h in Headers */, + CF2F463E1095EE72007D33FA /* tile.h in Headers */, + CF37575F10A6AEA1001BF7C5 /* apu.h in Headers */, + CF37576010A6AEA1001BF7C5 /* blargg_common.h in Headers */, + CF37576110A6AEA1001BF7C5 /* blargg_config.h in Headers */, + CF37576210A6AEA1001BF7C5 /* blargg_endian.h in Headers */, + CF37576310A6AEA1001BF7C5 /* blargg_source.h in Headers */, + CF37576510A6AEA1001BF7C5 /* resampler.h in Headers */, + CF37576610A6AEA1001BF7C5 /* ring_buffer.h in Headers */, + CF37576810A6AEA1001BF7C5 /* SNES_SPC.h in Headers */, + CF37576B10A6AEA1001BF7C5 /* SPC_CPU.h in Headers */, + CF37576D10A6AEA1001BF7C5 /* SPC_DSP.h in Headers */, + CF37576F10A6AEA1001BF7C5 /* SPC_Filter.h in Headers */, + CF2F463F1095EE72007D33FA /* 2xsai.h in Headers */, + CF2F46401095EE72007D33FA /* blit.h in Headers */, + CF2F46411095EE72007D33FA /* epx.h in Headers */, + CF2F46421095EE72007D33FA /* hq2x.h in Headers */, + CFEFAE9310EAC92B00FB081A /* snes_ntsc.h in Headers */, + CFEFAE9110EAC92B00FB081A /* snes_ntsc_config.h in Headers */, + CFEFAE9210EAC92B00FB081A /* snes_ntsc_impl.h in Headers */, + CF2F46431095EE72007D33FA /* crypt.h in Headers */, + CF2F46441095EE72007D33FA /* ioapi.h in Headers */, + CF2F46451095EE72007D33FA /* unzip.h in Headers */, + CF2F46461095EE72007D33FA /* 7z.h in Headers */, + CF2F46471095EE72007D33FA /* aribitcd.h in Headers */, + CF2F46481095EE72007D33FA /* ariconst.h in Headers */, + CF2F46491095EE72007D33FA /* ariprice.h in Headers */, + CF2F464A1095EE72007D33FA /* btreecd.h in Headers */, + CF2F464B1095EE72007D33FA /* crc32.h in Headers */, + CF2F464C1095EE72007D33FA /* iiostrm.h in Headers */, + CF2F464D1095EE72007D33FA /* inbyte.h in Headers */, + CF2F464E1095EE72007D33FA /* jma.h in Headers */, + CF2F464F1095EE72007D33FA /* lencoder.h in Headers */, + CF2F46501095EE72007D33FA /* litcoder.h in Headers */, + CF2F46511095EE72007D33FA /* lzma.h in Headers */, + CF2F46521095EE72007D33FA /* lzmadec.h in Headers */, + CF2F46531095EE72007D33FA /* portable.h in Headers */, + CF2F46541095EE72007D33FA /* rcdefs.h in Headers */, + CF2F46551095EE72007D33FA /* rngcoder.h in Headers */, + CF2F46561095EE72007D33FA /* s9x-jma.h in Headers */, + CF2F46571095EE72007D33FA /* winout.h in Headers */, + CF2F46581095EE72007D33FA /* mac-appleevent.h in Headers */, + CF2F46591095EE72007D33FA /* mac-audio.h in Headers */, + CF2F465A1095EE72007D33FA /* mac-cart.h in Headers */, + CF2F465B1095EE72007D33FA /* mac-cheat.h in Headers */, + CF2F465C1095EE72007D33FA /* mac-cheatfinder.h in Headers */, + CF2F465D1095EE72007D33FA /* mac-client.h in Headers */, + CF2F465E1095EE72007D33FA /* mac-cocoatools.h in Headers */, + CF2F465F1095EE72007D33FA /* mac-controls.h in Headers */, + CF2F46601095EE72007D33FA /* mac-coreimage.h in Headers */, + CF2F46611095EE72007D33FA /* mac-dialog.h in Headers */, + CF2F46621095EE72007D33FA /* mac-file.h in Headers */, + CF2F46631095EE72007D33FA /* mac-gworld.h in Headers */, + CF2F46641095EE72007D33FA /* mac-joypad.h in Headers */, + CF2F46651095EE72007D33FA /* mac-keyboard.h in Headers */, + CF2F46661095EE72007D33FA /* mac-multicart.h in Headers */, + CF2F46671095EE72007D33FA /* mac-musicbox.h in Headers */, + CF2F46681095EE72007D33FA /* mac-netplay.h in Headers */, + CF2F46691095EE72007D33FA /* mac-os.h in Headers */, + CF2F466A1095EE72007D33FA /* mac-prefs.h in Headers */, + CF2F466B1095EE72007D33FA /* mac-quicktime.h in Headers */, + CF2F466C1095EE72007D33FA /* mac-render.h in Headers */, + CF2F466D1095EE72007D33FA /* mac-screenshot.h in Headers */, + CF2F466E1095EE72007D33FA /* mac-server.h in Headers */, + CF2F466F1095EE72007D33FA /* mac-snes9x.h in Headers */, + CF2F46701095EE72007D33FA /* mac-stringtools.h in Headers */, + CF2F46711095EE72007D33FA /* mac-prefix.h in Headers */, + CF2F46721095EE72007D33FA /* mac-global_prefix.h in Headers */, + CF2F46731095EE72007D33FA /* HID_Utilities_External.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + CF047D36109D0E0600FD0754 /* Intel */ = { + isa = PBXNativeTarget; + buildConfigurationList = CF047E12109D0E0600FD0754 /* Build configuration list for PBXNativeTarget "Intel" */; + buildPhases = ( + CF047D37109D0E0600FD0754 /* Headers */, + CF047D9A109D0E0600FD0754 /* Resources */, + CF047DAC109D0E0600FD0754 /* Sources */, + CF047E03109D0E0600FD0754 /* Frameworks */, + CF047E11109D0E0600FD0754 /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Intel; + productName = "«PROJECTNAME»"; + productReference = CF047E15109D0E0600FD0754 /* Snes9x (i386).app */; + productType = "com.apple.product-type.application"; + }; + CF05668C0CF98E7E00C7877C /* Snow Leopard */ = { + isa = PBXNativeTarget; + buildConfigurationList = CF0567640CF98E7E00C7877C /* Build configuration list for PBXNativeTarget "Snow Leopard" */; + buildPhases = ( + CF05668D0CF98E7E00C7877C /* Headers */, + CF0566EF0CF98E7E00C7877C /* Resources */, + CF0567010CF98E7E00C7877C /* Sources */, + CF0567540CF98E7E00C7877C /* Frameworks */, + CF0567610CF98E7E00C7877C /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Snow Leopard"; + productName = "«PROJECTNAME»"; + productReference = CF0567660CF98E7E00C7877C /* Snes9x.app */; + productType = "com.apple.product-type.application"; + }; + CF2F46101095EE72007D33FA /* PowerPC */ = { + isa = PBXNativeTarget; + buildConfigurationList = CF2F46EE1095EE72007D33FA /* Build configuration list for PBXNativeTarget "PowerPC" */; + buildPhases = ( + CF2F46111095EE72007D33FA /* Headers */, + CF2F46741095EE72007D33FA /* Resources */, + CF2F46861095EE72007D33FA /* Sources */, + CF2F46DD1095EE72007D33FA /* Frameworks */, + CF2F46EB1095EE72007D33FA /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PowerPC; + productName = "«PROJECTNAME»"; + productReference = CF2F46F11095EE72007D33FA /* Snes9x (ppc).app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 20286C28FDCF999611CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = EA6A1100085808D200A1CF18 /* Build configuration list for PBXProject "snes9x" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 20286C29FDCF999611CA2CEA /* Snes9x CVS */; + projectDirPath = ""; + projectRoot = ..; + targets = ( + CF05668C0CF98E7E00C7877C /* Snow Leopard */, + CF047D36109D0E0600FD0754 /* Intel */, + CF2F46101095EE72007D33FA /* PowerPC */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + CF047D9A109D0E0600FD0754 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CF047D9B109D0E0600FD0754 /* APPL.icns in Resources */, + CF047D9C109D0E0600FD0754 /* CART.icns in Resources */, + CF047D9D109D0E0600FD0754 /* SRAM.icns in Resources */, + CF047D9E109D0E0600FD0754 /* SAVE.icns in Resources */, + CF047D9F109D0E0600FD0754 /* folder_SRAMs.icns in Resources */, + CF047DA0109D0E0600FD0754 /* folder_Freezes.icns in Resources */, + CF047DA1109D0E0600FD0754 /* icons.png in Resources */, + CF047DA2109D0E0600FD0754 /* logo_freeze.png in Resources */, + CF047DA3109D0E0600FD0754 /* logo_defrost.png in Resources */, + CF047DA4109D0E0600FD0754 /* musicbox_ledon.icns in Resources */, + CF047DA5109D0E0600FD0754 /* musicbox_ledoff.icns in Resources */, + CF047DA6109D0E0600FD0754 /* musicbox_indicator.png in Resources */, + CF047DA7109D0E0600FD0754 /* freeze_defrost.aiff in Resources */, + CF047DA8109D0E0600FD0754 /* InfoPlist.strings in Resources */, + CF047DA9109D0E0600FD0754 /* Localizable.strings in Resources */, + CF047DAA109D0E0600FD0754 /* Snes9x.nib in Resources */, + CF047DAB109D0E0600FD0754 /* Snes9x Help in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF0566EF0CF98E7E00C7877C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CF0566F00CF98E7E00C7877C /* APPL.icns in Resources */, + CF0566F10CF98E7E00C7877C /* CART.icns in Resources */, + CF0566F20CF98E7E00C7877C /* SRAM.icns in Resources */, + CF0566F30CF98E7E00C7877C /* SAVE.icns in Resources */, + CF0566F40CF98E7E00C7877C /* folder_SRAMs.icns in Resources */, + CF0566F50CF98E7E00C7877C /* folder_Freezes.icns in Resources */, + CF0566F60CF98E7E00C7877C /* icons.png in Resources */, + CF0566F70CF98E7E00C7877C /* logo_freeze.png in Resources */, + CF0566F80CF98E7E00C7877C /* logo_defrost.png in Resources */, + CF0566F90CF98E7E00C7877C /* musicbox_ledon.icns in Resources */, + CF0566FA0CF98E7E00C7877C /* musicbox_ledoff.icns in Resources */, + CF0566FB0CF98E7E00C7877C /* musicbox_indicator.png in Resources */, + CF0566FC0CF98E7E00C7877C /* freeze_defrost.aiff in Resources */, + CF0566FD0CF98E7E00C7877C /* InfoPlist.strings in Resources */, + CF0566FE0CF98E7E00C7877C /* Localizable.strings in Resources */, + CF0566FF0CF98E7E00C7877C /* Snes9x.nib in Resources */, + CF0567000CF98E7E00C7877C /* Snes9x Help in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF2F46741095EE72007D33FA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CF2F46751095EE72007D33FA /* APPL.icns in Resources */, + CF2F46761095EE72007D33FA /* CART.icns in Resources */, + CF2F46771095EE72007D33FA /* SRAM.icns in Resources */, + CF2F46781095EE72007D33FA /* SAVE.icns in Resources */, + CF2F46791095EE72007D33FA /* folder_SRAMs.icns in Resources */, + CF2F467A1095EE72007D33FA /* folder_Freezes.icns in Resources */, + CF2F467B1095EE72007D33FA /* icons.png in Resources */, + CF2F467C1095EE72007D33FA /* logo_freeze.png in Resources */, + CF2F467D1095EE72007D33FA /* logo_defrost.png in Resources */, + CF2F467E1095EE72007D33FA /* musicbox_ledon.icns in Resources */, + CF2F467F1095EE72007D33FA /* musicbox_ledoff.icns in Resources */, + CF2F46801095EE72007D33FA /* musicbox_indicator.png in Resources */, + CF2F46811095EE72007D33FA /* freeze_defrost.aiff in Resources */, + CF2F46821095EE72007D33FA /* InfoPlist.strings in Resources */, + CF2F46831095EE72007D33FA /* Localizable.strings in Resources */, + CF2F46841095EE72007D33FA /* Snes9x.nib in Resources */, + CF2F46851095EE72007D33FA /* Snes9x Help in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXRezBuildPhase section */ + CF047E11109D0E0600FD0754 /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF0567610CF98E7E00C7877C /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF2F46EB1095EE72007D33FA /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXRezBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + CF047DAC109D0E0600FD0754 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CF047DAF109D0E0600FD0754 /* bsx.cpp in Sources */, + CF047DB0109D0E0600FD0754 /* c4.cpp in Sources */, + CF047DB1109D0E0600FD0754 /* c4emu.cpp in Sources */, + CF047DB2109D0E0600FD0754 /* cheats.cpp in Sources */, + CF047DB3109D0E0600FD0754 /* cheats2.cpp in Sources */, + CF047DB4109D0E0600FD0754 /* clip.cpp in Sources */, + CF047DB5109D0E0600FD0754 /* controls.cpp in Sources */, + CF047DB6109D0E0600FD0754 /* cpu.cpp in Sources */, + CF047DB7109D0E0600FD0754 /* cpuexec.cpp in Sources */, + CF047DB8109D0E0600FD0754 /* cpuops.cpp in Sources */, + CF047DB9109D0E0600FD0754 /* crosshairs.cpp in Sources */, + CF047DBA109D0E0600FD0754 /* debug.cpp in Sources */, + CF047DBB109D0E0600FD0754 /* dma.cpp in Sources */, + CF047DBC109D0E0600FD0754 /* dsp.cpp in Sources */, + CF047DBD109D0E0600FD0754 /* dsp1.cpp in Sources */, + CF047DBE109D0E0600FD0754 /* dsp2.cpp in Sources */, + CF047DBF109D0E0600FD0754 /* dsp3.cpp in Sources */, + CF047DC0109D0E0600FD0754 /* dsp4.cpp in Sources */, + CF047DC2109D0E0600FD0754 /* fxemu.cpp in Sources */, + CF047DC3109D0E0600FD0754 /* fxinst.cpp in Sources */, + CF047DC4109D0E0600FD0754 /* gfx.cpp in Sources */, + CF047DC5109D0E0600FD0754 /* globals.cpp in Sources */, + CF047DC6109D0E0600FD0754 /* loadzip.cpp in Sources */, + CF047DC7109D0E0600FD0754 /* logger.cpp in Sources */, + CF047DC8109D0E0600FD0754 /* memmap.cpp in Sources */, + CF047DC9109D0E0600FD0754 /* movie.cpp in Sources */, + CF047DCA109D0E0600FD0754 /* obc1.cpp in Sources */, + CF047DCB109D0E0600FD0754 /* ppu.cpp in Sources */, + CF047DCC109D0E0600FD0754 /* reader.cpp in Sources */, + CF047DCD109D0E0600FD0754 /* sa1.cpp in Sources */, + CF047DCE109D0E0600FD0754 /* sa1cpu.cpp in Sources */, + CF047DCF109D0E0600FD0754 /* sdd1.cpp in Sources */, + CF047DD0109D0E0600FD0754 /* sdd1emu.cpp in Sources */, + CF047DD1109D0E0600FD0754 /* seta.cpp in Sources */, + CF047DD2109D0E0600FD0754 /* seta010.cpp in Sources */, + CF047DD3109D0E0600FD0754 /* seta011.cpp in Sources */, + CF047DD4109D0E0600FD0754 /* seta018.cpp in Sources */, + CF047DD5109D0E0600FD0754 /* snapshot.cpp in Sources */, + CF047DD8109D0E0600FD0754 /* spc7110.cpp in Sources */, + CF047DD9109D0E0600FD0754 /* srtc.cpp in Sources */, + CF047DDA109D0E0600FD0754 /* tile.cpp in Sources */, + CF37577010A6AEA1001BF7C5 /* apu.cpp in Sources */, + CF37577910A6AEA1001BF7C5 /* SNES_SPC.cpp in Sources */, + CF37577B10A6AEA1001BF7C5 /* SNES_SPC_misc.cpp in Sources */, + CF37577C10A6AEA1001BF7C5 /* SNES_SPC_state.cpp in Sources */, + CF37577E10A6AEA1001BF7C5 /* SPC_DSP.cpp in Sources */, + CF37578010A6AEA1001BF7C5 /* SPC_Filter.cpp in Sources */, + CF047DDB109D0E0600FD0754 /* 2xsai.cpp in Sources */, + CF047DDC109D0E0600FD0754 /* blit.cpp in Sources */, + CF047DDD109D0E0600FD0754 /* epx.cpp in Sources */, + CF047DDE109D0E0600FD0754 /* hq2x.cpp in Sources */, + CFEFAE8C10EAC92300FB081A /* snes_ntsc.c in Sources */, + CF047DDF109D0E0600FD0754 /* ioapi.c in Sources */, + CF047DE0109D0E0600FD0754 /* unzip.c in Sources */, + CF047DE1109D0E0600FD0754 /* 7zlzma.cpp in Sources */, + CF047DE2109D0E0600FD0754 /* crc32.cpp in Sources */, + CF047DE3109D0E0600FD0754 /* iiostrm.cpp in Sources */, + CF047DE4109D0E0600FD0754 /* inbyte.cpp in Sources */, + CF047DE5109D0E0600FD0754 /* jma.cpp in Sources */, + CF047DE6109D0E0600FD0754 /* lzma.cpp in Sources */, + CF047DE7109D0E0600FD0754 /* lzmadec.cpp in Sources */, + CF047DE8109D0E0600FD0754 /* s9x-jma.cpp in Sources */, + CF047DE9109D0E0600FD0754 /* winout.cpp in Sources */, + CF047DEA109D0E0600FD0754 /* mac-appleevent.cpp in Sources */, + CF047DEB109D0E0600FD0754 /* mac-audio.cpp in Sources */, + CF047DEC109D0E0600FD0754 /* mac-cart.cpp in Sources */, + CF047DED109D0E0600FD0754 /* mac-cheat.cpp in Sources */, + CF047DEE109D0E0600FD0754 /* mac-cheatfinder.cpp in Sources */, + CF047DEF109D0E0600FD0754 /* mac-client.cpp in Sources */, + CF047DF0109D0E0600FD0754 /* mac-cocoatools.mm in Sources */, + CF047DF1109D0E0600FD0754 /* mac-controls.cpp in Sources */, + CF047DF2109D0E0600FD0754 /* mac-coreimage.mm in Sources */, + CF047DF3109D0E0600FD0754 /* mac-dialog.cpp in Sources */, + CF047DF4109D0E0600FD0754 /* mac-file.cpp in Sources */, + CF047DF5109D0E0600FD0754 /* mac-gworld.cpp in Sources */, + CF047DF6109D0E0600FD0754 /* mac-joypad.cpp in Sources */, + CF047DF7109D0E0600FD0754 /* mac-keyboard.cpp in Sources */, + CF047DF8109D0E0600FD0754 /* mac-multicart.cpp in Sources */, + CF047DF9109D0E0600FD0754 /* mac-musicbox.cpp in Sources */, + CF047DFA109D0E0600FD0754 /* mac-netplay.cpp in Sources */, + CF047DFB109D0E0600FD0754 /* mac-os.cpp in Sources */, + CF047DFC109D0E0600FD0754 /* mac-prefs.cpp in Sources */, + CF047DFD109D0E0600FD0754 /* mac-quicktime.cpp in Sources */, + CF047DFE109D0E0600FD0754 /* mac-render.cpp in Sources */, + CF047DFF109D0E0600FD0754 /* mac-screenshot.cpp in Sources */, + CF047E00109D0E0600FD0754 /* mac-server.cpp in Sources */, + CF047E01109D0E0600FD0754 /* mac-snes9x.cpp in Sources */, + CF047E02109D0E0600FD0754 /* mac-stringtools.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF0567010CF98E7E00C7877C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CF0567030CF98E7E00C7877C /* bsx.cpp in Sources */, + CF0567040CF98E7E00C7877C /* c4.cpp in Sources */, + CF0567050CF98E7E00C7877C /* c4emu.cpp in Sources */, + CF0567060CF98E7E00C7877C /* cheats.cpp in Sources */, + CF0567070CF98E7E00C7877C /* cheats2.cpp in Sources */, + CF0567080CF98E7E00C7877C /* clip.cpp in Sources */, + CF0567090CF98E7E00C7877C /* controls.cpp in Sources */, + CF05670A0CF98E7E00C7877C /* cpu.cpp in Sources */, + CF05670B0CF98E7E00C7877C /* cpuexec.cpp in Sources */, + CF05670C0CF98E7E00C7877C /* cpuops.cpp in Sources */, + CF05670D0CF98E7E00C7877C /* crosshairs.cpp in Sources */, + CFE7FBB10D2F6755002F3102 /* debug.cpp in Sources */, + CF05670F0CF98E7E00C7877C /* dma.cpp in Sources */, + CF5D3E2A0FAFD35A00340007 /* dsp.cpp in Sources */, + CF0567100CF98E7E00C7877C /* dsp1.cpp in Sources */, + CF5D3E240FAFD35400340007 /* dsp2.cpp in Sources */, + CF5D3E260FAFD35400340007 /* dsp3.cpp in Sources */, + CF5D3E250FAFD35400340007 /* dsp4.cpp in Sources */, + CFE7FBB40D2F67BA002F3102 /* fxemu.cpp in Sources */, + CF0567120CF98E7E00C7877C /* fxinst.cpp in Sources */, + CF0567130CF98E7E00C7877C /* gfx.cpp in Sources */, + CF0567140CF98E7E00C7877C /* globals.cpp in Sources */, + CF0567150CF98E7E00C7877C /* loadzip.cpp in Sources */, + CF0567160CF98E7E00C7877C /* logger.cpp in Sources */, + CF0567170CF98E7E00C7877C /* memmap.cpp in Sources */, + CF0567180CF98E7E00C7877C /* movie.cpp in Sources */, + CF0567190CF98E7E00C7877C /* obc1.cpp in Sources */, + CF05671A0CF98E7E00C7877C /* ppu.cpp in Sources */, + CF05671B0CF98E7E00C7877C /* reader.cpp in Sources */, + CF05671C0CF98E7E00C7877C /* sa1.cpp in Sources */, + CF05671D0CF98E7E00C7877C /* sa1cpu.cpp in Sources */, + CF05671E0CF98E7E00C7877C /* sdd1.cpp in Sources */, + CF05671F0CF98E7E00C7877C /* sdd1emu.cpp in Sources */, + CF0567200CF98E7E00C7877C /* seta.cpp in Sources */, + CF0567210CF98E7E00C7877C /* seta010.cpp in Sources */, + CF0567220CF98E7E00C7877C /* seta011.cpp in Sources */, + CF0567230CF98E7E00C7877C /* seta018.cpp in Sources */, + CF0567240CF98E7E00C7877C /* snapshot.cpp in Sources */, + CF0567270CF98E7E00C7877C /* spc7110.cpp in Sources */, + CF0567280CF98E7E00C7877C /* srtc.cpp in Sources */, + CF0567290CF98E7E00C7877C /* tile.cpp in Sources */, + CF37578210A6AEA1001BF7C5 /* apu.cpp in Sources */, + CF37578B10A6AEA1001BF7C5 /* SNES_SPC.cpp in Sources */, + CF37578D10A6AEA1001BF7C5 /* SNES_SPC_misc.cpp in Sources */, + CF37578E10A6AEA1001BF7C5 /* SNES_SPC_state.cpp in Sources */, + CF37579010A6AEA1001BF7C5 /* SPC_DSP.cpp in Sources */, + CF37579210A6AEA1001BF7C5 /* SPC_Filter.cpp in Sources */, + CF5553C90EA24C36005957E4 /* 2xsai.cpp in Sources */, + CF5553CB0EA24C36005957E4 /* blit.cpp in Sources */, + CF5553CD0EA24C36005957E4 /* epx.cpp in Sources */, + CF5553CF0EA24C36005957E4 /* hq2x.cpp in Sources */, + CFEFAE8D10EAC92300FB081A /* snes_ntsc.c in Sources */, + CFA518D40EBCB4AD008379F6 /* ioapi.c in Sources */, + CFA518C80EBCB3ED008379F6 /* unzip.c in Sources */, + CF05672E0CF98E7E00C7877C /* 7zlzma.cpp in Sources */, + CF05672F0CF98E7E00C7877C /* crc32.cpp in Sources */, + CF0567300CF98E7E00C7877C /* iiostrm.cpp in Sources */, + CF0567310CF98E7E00C7877C /* inbyte.cpp in Sources */, + CF0567320CF98E7E00C7877C /* jma.cpp in Sources */, + CF0567330CF98E7E00C7877C /* lzma.cpp in Sources */, + CF0567340CF98E7E00C7877C /* lzmadec.cpp in Sources */, + CF0567350CF98E7E00C7877C /* s9x-jma.cpp in Sources */, + CF0567360CF98E7E00C7877C /* winout.cpp in Sources */, + CF0567380CF98E7E00C7877C /* mac-appleevent.cpp in Sources */, + CF0567390CF98E7E00C7877C /* mac-audio.cpp in Sources */, + CF05673B0CF98E7E00C7877C /* mac-cart.cpp in Sources */, + CF05673C0CF98E7E00C7877C /* mac-cheat.cpp in Sources */, + CF05673D0CF98E7E00C7877C /* mac-cheatfinder.cpp in Sources */, + CF05673E0CF98E7E00C7877C /* mac-client.cpp in Sources */, + CF05673F0CF98E7E00C7877C /* mac-cocoatools.mm in Sources */, + CF0567400CF98E7E00C7877C /* mac-controls.cpp in Sources */, + CF0567410CF98E7E00C7877C /* mac-coreimage.mm in Sources */, + CF0567420CF98E7E00C7877C /* mac-dialog.cpp in Sources */, + CF0567440CF98E7E00C7877C /* mac-file.cpp in Sources */, + CF0567450CF98E7E00C7877C /* mac-gworld.cpp in Sources */, + CF0567470CF98E7E00C7877C /* mac-joypad.cpp in Sources */, + CF0567480CF98E7E00C7877C /* mac-keyboard.cpp in Sources */, + CF0567490CF98E7E00C7877C /* mac-multicart.cpp in Sources */, + CF05674A0CF98E7E00C7877C /* mac-musicbox.cpp in Sources */, + CF05674B0CF98E7E00C7877C /* mac-netplay.cpp in Sources */, + CF05674C0CF98E7E00C7877C /* mac-os.cpp in Sources */, + CF05674D0CF98E7E00C7877C /* mac-prefs.cpp in Sources */, + CF05674E0CF98E7E00C7877C /* mac-quicktime.cpp in Sources */, + CF05674F0CF98E7E00C7877C /* mac-render.cpp in Sources */, + CF0567500CF98E7E00C7877C /* mac-screenshot.cpp in Sources */, + CF0567510CF98E7E00C7877C /* mac-server.cpp in Sources */, + CF0567520CF98E7E00C7877C /* mac-snes9x.cpp in Sources */, + CF0567530CF98E7E00C7877C /* mac-stringtools.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CF2F46861095EE72007D33FA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CF2F46891095EE72007D33FA /* bsx.cpp in Sources */, + CF2F468A1095EE72007D33FA /* c4.cpp in Sources */, + CF2F468B1095EE72007D33FA /* c4emu.cpp in Sources */, + CF2F468C1095EE72007D33FA /* cheats.cpp in Sources */, + CF2F468D1095EE72007D33FA /* cheats2.cpp in Sources */, + CF2F468E1095EE72007D33FA /* clip.cpp in Sources */, + CF2F468F1095EE72007D33FA /* controls.cpp in Sources */, + CF2F46901095EE72007D33FA /* cpu.cpp in Sources */, + CF2F46911095EE72007D33FA /* cpuexec.cpp in Sources */, + CF2F46921095EE72007D33FA /* cpuops.cpp in Sources */, + CF2F46931095EE72007D33FA /* crosshairs.cpp in Sources */, + CF2F46941095EE72007D33FA /* debug.cpp in Sources */, + CF2F46951095EE72007D33FA /* dma.cpp in Sources */, + CF2F46961095EE72007D33FA /* dsp.cpp in Sources */, + CF2F46971095EE72007D33FA /* dsp1.cpp in Sources */, + CF2F46981095EE72007D33FA /* dsp2.cpp in Sources */, + CF2F46991095EE72007D33FA /* dsp3.cpp in Sources */, + CF2F469A1095EE72007D33FA /* dsp4.cpp in Sources */, + CF2F469C1095EE72007D33FA /* fxemu.cpp in Sources */, + CF2F469D1095EE72007D33FA /* fxinst.cpp in Sources */, + CF2F469E1095EE72007D33FA /* gfx.cpp in Sources */, + CF2F469F1095EE72007D33FA /* globals.cpp in Sources */, + CF2F46A01095EE72007D33FA /* loadzip.cpp in Sources */, + CF2F46A11095EE72007D33FA /* logger.cpp in Sources */, + CF2F46A21095EE72007D33FA /* memmap.cpp in Sources */, + CF2F46A31095EE72007D33FA /* movie.cpp in Sources */, + CF2F46A41095EE72007D33FA /* obc1.cpp in Sources */, + CF2F46A51095EE72007D33FA /* ppu.cpp in Sources */, + CF2F46A61095EE72007D33FA /* reader.cpp in Sources */, + CF2F46A71095EE72007D33FA /* sa1.cpp in Sources */, + CF2F46A81095EE72007D33FA /* sa1cpu.cpp in Sources */, + CF2F46A91095EE72007D33FA /* sdd1.cpp in Sources */, + CF2F46AA1095EE72007D33FA /* sdd1emu.cpp in Sources */, + CF2F46AB1095EE72007D33FA /* seta.cpp in Sources */, + CF2F46AC1095EE72007D33FA /* seta010.cpp in Sources */, + CF2F46AD1095EE72007D33FA /* seta011.cpp in Sources */, + CF2F46AE1095EE72007D33FA /* seta018.cpp in Sources */, + CF2F46AF1095EE72007D33FA /* snapshot.cpp in Sources */, + CF2F46B21095EE72007D33FA /* spc7110.cpp in Sources */, + CF2F46B31095EE72007D33FA /* srtc.cpp in Sources */, + CF2F46B41095EE72007D33FA /* tile.cpp in Sources */, + CF37575E10A6AEA1001BF7C5 /* apu.cpp in Sources */, + CF37576710A6AEA1001BF7C5 /* SNES_SPC.cpp in Sources */, + CF37576910A6AEA1001BF7C5 /* SNES_SPC_misc.cpp in Sources */, + CF37576A10A6AEA1001BF7C5 /* SNES_SPC_state.cpp in Sources */, + CF37576C10A6AEA1001BF7C5 /* SPC_DSP.cpp in Sources */, + CF37576E10A6AEA1001BF7C5 /* SPC_Filter.cpp in Sources */, + CF2F46B51095EE72007D33FA /* 2xsai.cpp in Sources */, + CF2F46B61095EE72007D33FA /* blit.cpp in Sources */, + CF2F46B71095EE72007D33FA /* epx.cpp in Sources */, + CF2F46B81095EE72007D33FA /* hq2x.cpp in Sources */, + CFEFAE8B10EAC92300FB081A /* snes_ntsc.c in Sources */, + CF2F46B91095EE72007D33FA /* ioapi.c in Sources */, + CF2F46BA1095EE72007D33FA /* unzip.c in Sources */, + CF2F46BB1095EE72007D33FA /* 7zlzma.cpp in Sources */, + CF2F46BC1095EE72007D33FA /* crc32.cpp in Sources */, + CF2F46BD1095EE72007D33FA /* iiostrm.cpp in Sources */, + CF2F46BE1095EE72007D33FA /* inbyte.cpp in Sources */, + CF2F46BF1095EE72007D33FA /* jma.cpp in Sources */, + CF2F46C01095EE72007D33FA /* lzma.cpp in Sources */, + CF2F46C11095EE72007D33FA /* lzmadec.cpp in Sources */, + CF2F46C21095EE72007D33FA /* s9x-jma.cpp in Sources */, + CF2F46C31095EE72007D33FA /* winout.cpp in Sources */, + CF2F46C41095EE72007D33FA /* mac-appleevent.cpp in Sources */, + CF2F46C51095EE72007D33FA /* mac-audio.cpp in Sources */, + CF2F46C61095EE72007D33FA /* mac-cart.cpp in Sources */, + CF2F46C71095EE72007D33FA /* mac-cheat.cpp in Sources */, + CF2F46C81095EE72007D33FA /* mac-cheatfinder.cpp in Sources */, + CF2F46C91095EE72007D33FA /* mac-client.cpp in Sources */, + CF2F46CA1095EE72007D33FA /* mac-cocoatools.mm in Sources */, + CF2F46CB1095EE72007D33FA /* mac-controls.cpp in Sources */, + CF2F46CC1095EE72007D33FA /* mac-coreimage.mm in Sources */, + CF2F46CD1095EE72007D33FA /* mac-dialog.cpp in Sources */, + CF2F46CE1095EE72007D33FA /* mac-file.cpp in Sources */, + CF2F46CF1095EE72007D33FA /* mac-gworld.cpp in Sources */, + CF2F46D01095EE72007D33FA /* mac-joypad.cpp in Sources */, + CF2F46D11095EE72007D33FA /* mac-keyboard.cpp in Sources */, + CF2F46D21095EE72007D33FA /* mac-multicart.cpp in Sources */, + CF2F46D31095EE72007D33FA /* mac-musicbox.cpp in Sources */, + CF2F46D41095EE72007D33FA /* mac-netplay.cpp in Sources */, + CF2F46D51095EE72007D33FA /* mac-os.cpp in Sources */, + CF2F46D61095EE72007D33FA /* mac-prefs.cpp in Sources */, + CF2F46D71095EE72007D33FA /* mac-quicktime.cpp in Sources */, + CF2F46D81095EE72007D33FA /* mac-render.cpp in Sources */, + CF2F46D91095EE72007D33FA /* mac-screenshot.cpp in Sources */, + CF2F46DA1095EE72007D33FA /* mac-server.cpp in Sources */, + CF2F46DB1095EE72007D33FA /* mac-snes9x.cpp in Sources */, + CF2F46DC1095EE72007D33FA /* mac-stringtools.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + EA3BEA980A28384E00A8FAE5 /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + EA3BEA990A28384E00A8FAE5 /* English */, + ); + name = Localizable.strings; + sourceTree = ""; + }; + EA3BEA9C0A28384E00A8FAE5 /* Snes9x.nib */ = { + isa = PBXVariantGroup; + children = ( + EA3BEA9D0A28384E00A8FAE5 /* English */, + ); + name = Snes9x.nib; + sourceTree = ""; + }; + EA3BEA9E0A28384E00A8FAE5 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + EA3BEA9F0A28384E00A8FAE5 /* English */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + EA3BEAA80A28386500A8FAE5 /* Snes9x Help */ = { + isa = PBXVariantGroup; + children = ( + EA3BEAA90A28386500A8FAE5 /* English */, + ); + name = "Snes9x Help"; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + CF047D02109C98F900FD0754 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + CF047D03109C98F900FD0754 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + GCC_ENABLE_CPP_EXCEPTIONS = NO; + GCC_ENABLE_CPP_RTTI = NO; + GCC_MODEL_TUNING = ""; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREFIX_HEADER = "mac-global_prefix.h"; + GCC_STRICT_ALIASING = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = .; + PRODUCT_NAME = Snes9x; + WARNING_CFLAGS = "-Wfloat-equal"; + }; + name = Debug; + }; + CF047D04109C98F900FD0754 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ppc; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + GCC_ENABLE_CPP_EXCEPTIONS = NO; + GCC_ENABLE_CPP_RTTI = NO; + GCC_MODEL_TUNING = G4; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREFIX_HEADER = "mac-global_prefix.h"; + GCC_PREPROCESSOR_DEFINITIONS = ( + MAC_LEOPARD_TIGER_PANTHER_SUPPORT, + MAC_TIGER_PANTHER_SUPPORT, + MAC_PANTHER_SUPPORT, + ); + GCC_STRICT_ALIASING = YES; + GCC_VERSION = 4.0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Info_ppc.plist; + LIBRARY_SEARCH_PATHS = .; + MACOSX_DEPLOYMENT_TARGET = 10.3; + OTHER_LDFLAGS = ( + "-weak_framework", + QuartzCore, + ); + PRODUCT_NAME = "Snes9x (ppc)"; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + WARNING_CFLAGS = "-Wfloat-equal"; + }; + name = Debug; + }; + CF047E13109D0E0600FD0754 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = i386; + DEAD_CODE_STRIPPING = YES; + GCC_ENABLE_CPP_EXCEPTIONS = NO; + GCC_ENABLE_CPP_RTTI = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = ""; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_PREFIX_HEADER = "mac-global_prefix.h"; + GCC_PREPROCESSOR_DEFINITIONS = ( + MAC_LEOPARD_TIGER_PANTHER_SUPPORT, + MAC_TIGER_PANTHER_SUPPORT, + ); + GCC_STRICT_ALIASING = YES; + GCC_UNROLL_LOOPS = YES; + GCC_VERSION = 4.0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Info_i386.plist; + LIBRARY_SEARCH_PATHS = .; + MACOSX_DEPLOYMENT_TARGET = 10.4; + OTHER_CFLAGS = ( + "-fomit-frame-pointer", + "-fast", + ); + PRODUCT_NAME = "Snes9x (i386)"; + WARNING_CFLAGS = "-Wfloat-equal"; + }; + name = Release; + }; + CF047E14109D0E0600FD0754 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = i386; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + GCC_ENABLE_CPP_EXCEPTIONS = NO; + GCC_ENABLE_CPP_RTTI = NO; + GCC_MODEL_TUNING = ""; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREFIX_HEADER = "mac-global_prefix.h"; + GCC_PREPROCESSOR_DEFINITIONS = ( + MAC_LEOPARD_TIGER_PANTHER_SUPPORT, + MAC_TIGER_PANTHER_SUPPORT, + ); + GCC_STRICT_ALIASING = YES; + GCC_VERSION = 4.0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Info_i386.plist; + LIBRARY_SEARCH_PATHS = .; + MACOSX_DEPLOYMENT_TARGET = 10.4; + PRODUCT_NAME = "Snes9x (i386)"; + WARNING_CFLAGS = "-Wfloat-equal"; + }; + name = Debug; + }; + CF0567650CF98E7E00C7877C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEAD_CODE_STRIPPING = YES; + GCC_ENABLE_CPP_EXCEPTIONS = NO; + GCC_ENABLE_CPP_RTTI = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = ""; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_PREFIX_HEADER = "mac-global_prefix.h"; + GCC_STRICT_ALIASING = YES; + GCC_UNROLL_LOOPS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Info.plist; + LIBRARY_SEARCH_PATHS = .; + OTHER_CFLAGS = ( + "-fomit-frame-pointer", + "-fast", + ); + PRODUCT_NAME = Snes9x; + WARNING_CFLAGS = "-Wfloat-equal"; + }; + name = Release; + }; + CF2F46EF1095EE72007D33FA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ppc; + DEAD_CODE_STRIPPING = YES; + GCC_ENABLE_CPP_EXCEPTIONS = NO; + GCC_ENABLE_CPP_RTTI = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G4; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_PREFIX_HEADER = "mac-global_prefix.h"; + GCC_PREPROCESSOR_DEFINITIONS = ( + MAC_LEOPARD_TIGER_PANTHER_SUPPORT, + MAC_TIGER_PANTHER_SUPPORT, + MAC_PANTHER_SUPPORT, + ); + GCC_STRICT_ALIASING = YES; + GCC_UNROLL_LOOPS = YES; + GCC_VERSION = 4.0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_VALUE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Info_ppc.plist; + LIBRARY_SEARCH_PATHS = .; + MACOSX_DEPLOYMENT_TARGET = 10.3; + OTHER_CFLAGS = ( + "-mcpu=G4", + "-fomit-frame-pointer", + "-fast", + ); + OTHER_LDFLAGS = ( + "-weak_framework", + QuartzCore, + ); + PRODUCT_NAME = "Snes9x (ppc)"; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + WARNING_CFLAGS = "-Wfloat-equal"; + }; + name = Release; + }; + EA6A1102085808D200A1CF18 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + CF047E12109D0E0600FD0754 /* Build configuration list for PBXNativeTarget "Intel" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CF047E13109D0E0600FD0754 /* Release */, + CF047E14109D0E0600FD0754 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CF0567640CF98E7E00C7877C /* Build configuration list for PBXNativeTarget "Snow Leopard" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CF0567650CF98E7E00C7877C /* Release */, + CF047D03109C98F900FD0754 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CF2F46EE1095EE72007D33FA /* Build configuration list for PBXNativeTarget "PowerPC" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CF2F46EF1095EE72007D33FA /* Release */, + CF047D04109C98F900FD0754 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + EA6A1100085808D200A1CF18 /* Build configuration list for PBXProject "snes9x" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + EA6A1102085808D200A1CF18 /* Release */, + CF047D02109C98F900FD0754 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 20286C28FDCF999611CA2CEA /* Project object */; +} diff --git a/memmap.cpp b/memmap.cpp new file mode 100644 index 00000000..3ecb9813 --- /dev/null +++ b/memmap.cpp @@ -0,0 +1,4630 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 + +#ifdef UNZIP_SUPPORT +#include "unzip/unzip.h" +#endif + +#ifdef JMA_SUPPORT +#include "jma/s9x-jma.h" +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "apu/apu.h" +#include "fxemu.h" +#include "sdd1.h" +#include "srtc.h" +#include "controls.h" +#include "cheats.h" +#include "movie.h" +#include "reader.h" +#include "display.h" + +#ifndef SET_UI_COLOR +#define SET_UI_COLOR(r, g, b) ; +#endif + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +static bool8 stopMovie = TRUE; +static char LastRomFilename[PATH_MAX + 1] = ""; + +// from NSRT +static const char *nintendo_licensees[] = +{ + "Unlicensed", + "Nintendo", + "Rocket Games/Ajinomoto", + "Imagineer-Zoom", + "Gray Matter", + "Zamuse", + "Falcom", + NULL, + "Capcom", + "Hot B Co.", + "Jaleco", + "Coconuts Japan", + "Coconuts Japan/G.X.Media", + "Micronet", + "Technos", + "Mebio Software", + "Shouei System", + "Starfish", + NULL, + "Mitsui Fudosan/Dentsu", + NULL, + "Warashi Inc.", + NULL, + "Nowpro", + NULL, + "Game Village", + "IE Institute", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Banarex", + "Starfish", + "Infocom", + "Electronic Arts Japan", + NULL, + "Cobra Team", + "Human/Field", + "KOEI", + "Hudson Soft", + "S.C.P./Game Village", + "Yanoman", + NULL, + "Tecmo Products", + "Japan Glary Business", + "Forum/OpenSystem", + "Virgin Games (Japan)", + "SMDE", + "Yojigen", + NULL, + "Daikokudenki", + NULL, + NULL, + NULL, + NULL, + NULL, + "Creatures Inc.", + "TDK Deep Impresion", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Destination Software/KSS", + "Sunsoft/Tokai Engineering", + "POW (Planning Office Wada)/VR 1 Japan", + "Micro World", + NULL, + "San-X", + "Enix", + "Loriciel/Electro Brain", + "Kemco Japan", + "Seta Co.,Ltd.", + "Culture Brain", + "Irem Corp.", + "Palsoft", + "Visit Co., Ltd.", + "Intec", + "System Sacom", + "Poppo", + "Ubisoft Japan", + NULL, + "Media Works", + "NEC InterChannel", + "Tam", + "Gajin/Jordan", + "Smilesoft", + NULL, + NULL, + "Mediakite", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Viacom", + "Carrozzeria", + "Dynamic", + NULL, + "Magifact", + "Hect", + "Codemasters", + "Taito/GAGA Communications", + "Laguna", + "Telstar Fun & Games/Event/Taito", + NULL, + "Arcade Zone Ltd.", + "Entertainment International/Empire Software", + "Loriciel", + "Gremlin Graphics", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Seika Corp.", + "UBI SOFT Entertainment Software", + "Sunsoft US", + NULL, + "Life Fitness", + NULL, + "System 3", + "Spectrum Holobyte", + NULL, + "Irem", + NULL, + "Raya Systems", + "Renovation Products", + "Malibu Games", + NULL, + "Eidos/U.S. Gold", + "Playmates Interactive", + NULL, + NULL, + "Fox Interactive", + "Time Warner Interactive", + NULL, + NULL, + NULL, + NULL, + NULL, + "Disney Interactive", + NULL, + "Black Pearl", + NULL, + "Advanced Productions", + NULL, + NULL, + "GT Interactive", + "RARE", + "Crave Entertainment", + "Absolute Entertainment", + "Acclaim", + "Activision", + "American Sammy", + "Take 2/GameTek", + "Hi Tech", + "LJN Ltd.", + NULL, + "Mattel", + NULL, + "Mindscape/Red Orb Entertainment", + "Romstar", + "Taxan", + "Midway/Tradewest", + NULL, + "American Softworks Corp.", + "Majesco Sales Inc.", + "3DO", + NULL, + NULL, + "Hasbro", + "NewKidCo", + "Telegames", + "Metro3D", + NULL, + "Vatical Entertainment", + "LEGO Media", + NULL, + "Xicat Interactive", + "Cryo Interactive", + NULL, + NULL, + "Red Storm Entertainment", + "Microids", + NULL, + "Conspiracy/Swing", + "Titus", + "Virgin Interactive", + "Maxis", + NULL, + "LucasArts Entertainment", + NULL, + NULL, + "Ocean", + NULL, + "Electronic Arts", + NULL, + "Laser Beam", + NULL, + NULL, + "Elite Systems", + "Electro Brain", + "The Learning Company", + "BBC", + NULL, + "Software 2000", + NULL, + "BAM! Entertainment", + "Studio 3", + NULL, + NULL, + NULL, + "Classified Games", + NULL, + "TDK Mediactive", + NULL, + "DreamCatcher", + "JoWood Produtions", + "SEGA", + "Wannado Edition", + "LSP (Light & Shadow Prod.)", + "ITE Media", + "Infogrames", + "Interplay", + "JVC (US)", + "Parker Brothers", + NULL, + "SCI (Sales Curve Interactive)/Storm", + NULL, + NULL, + "THQ Software", + "Accolade Inc.", + "Triffix Entertainment", + NULL, + "Microprose Software", + "Universal Interactive/Sierra/Simon & Schuster", + NULL, + "Kemco", + "Rage Software", + "Encore", + NULL, + "Zoo", + "Kiddinx", + "Simon & Schuster Interactive", + "Asmik Ace Entertainment Inc./AIA", + "Empire Interactive", + NULL, + NULL, + "Jester Interactive", + NULL, + "Rockstar Games", + "Scholastic", + "Ignition Entertainment", + "Summitsoft", + "Stadlbauer", + NULL, + NULL, + NULL, + "Misawa", + "Teichiku", + "Namco Ltd.", + "LOZC", + "KOEI", + NULL, + "Tokuma Shoten Intermedia", + "Tsukuda Original", + "DATAM-Polystar", + NULL, + NULL, + "Bullet-Proof Software", + "Vic Tokai Inc.", + NULL, + "Character Soft", + "I'Max", + "Saurus", + NULL, + NULL, + "General Entertainment", + NULL, + NULL, + "I'Max", + "Success", + NULL, + "SEGA Japan", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Takara", + "Chun Soft", + "Video System Co., Ltd./McO'River", + "BEC", + NULL, + "Varie", + "Yonezawa/S'pal", + "Kaneko", + NULL, + "Victor Interactive Software/Pack-in-Video", + "Nichibutsu/Nihon Bussan", + "Tecmo", + "Imagineer", + NULL, + NULL, + "Nova", + "Den'Z", + "Bottom Up", + NULL, + "TGL (Technical Group Laboratory)", + NULL, + "Hasbro Japan", + NULL, + "Marvelous Entertainment", + NULL, + "Keynet Inc.", + "Hands-On Entertainment", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Telenet", + "Hori", + NULL, + NULL, + "Konami", + "K.Amusement Leasing Co.", + "Kawada", + "Takara", + NULL, + "Technos Japan Corp.", + "JVC (Europe/Japan)/Victor Musical Industries", + NULL, + "Toei Animation", + "Toho", + NULL, + "Namco", + "Media Rings Corp.", + "J-Wing", + NULL, + "Pioneer LDC", + "KID", + "Mediafactory", + NULL, + NULL, + NULL, + "Infogrames Hudson", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Acclaim Japan", + "ASCII Co./Nexoft", + "Bandai", + NULL, + "Enix", + NULL, + "HAL Laboratory/Halken", + "SNK", + NULL, + "Pony Canyon Hanbai", + "Culture Brain", + "Sunsoft", + "Toshiba EMI", + "Sony Imagesoft", + NULL, + "Sammy", + "Magical", + "Visco", + NULL, + "Compile", + NULL, + "MTO Inc.", + NULL, + "Sunrise Interactive", + NULL, + "Global A Entertainment", + "Fuuki", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Taito", + NULL, + "Kemco", + "Square", + "Tokuma Shoten", + "Data East", + "Tonkin House", + NULL, + "KOEI", + NULL, + "Konami/Ultra/Palcom", + "NTVIC/VAP", + "Use Co., Ltd.", + "Meldac", + "Pony Canyon (Japan)/FCI (US)", + "Angel/Sotsu Agency/Sunrise", + "Yumedia/Aroma Co., Ltd.", + NULL, + NULL, + "Boss", + "Axela/Crea-Tech", + "Sekaibunka-Sha/Sumire kobo/Marigul Management Inc.", + "Konami Computer Entertainment Osaka", + NULL, + NULL, + "Enterbrain", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Taito/Disco", + "Sofel", + "Quest Corp.", + "Sigma", + "Ask Kodansha", + NULL, + "Naxat", + "Copya System", + "Capcom Co., Ltd.", + "Banpresto", + "TOMY", + "Acclaim/LJN Japan", + NULL, + "NCS", + "Human Entertainment", + "Altron", + "Jaleco", + "Gaps Inc.", + NULL, + NULL, + NULL, + NULL, + NULL, + "Elf", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Jaleco", + NULL, + "Yutaka", + "Varie", + "T&ESoft", + "Epoch Co., Ltd.", + NULL, + "Athena", + "Asmik", + "Natsume", + "King Records", + "Atlus", + "Epic/Sony Records (Japan)", + NULL, + "IGS (Information Global Service)", + NULL, + "Chatnoir", + "Right Stuff", + NULL, + "NTT COMWARE", + NULL, + "Spike", + "Konami Computer Entertainment Tokyo", + "Alphadream Corp.", + NULL, + "Sting", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "A Wave", + "Motown Software", + "Left Field Entertainment", + "Extreme Entertainment Group", + "TecMagik", + NULL, + NULL, + NULL, + NULL, + "Cybersoft", + NULL, + "Psygnosis", + NULL, + NULL, + "Davidson/Western Tech.", + "Unlicensed", + NULL, + NULL, + NULL, + NULL, + "The Game Factory Europe", + "Hip Games", + "Aspyr", + NULL, + NULL, + "Mastiff", + "iQue", + "Digital Tainment Pool", + "XS Games", + "Daiwon", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "PCCW Japan", + NULL, + NULL, + "KiKi Co. Ltd.", + "Open Sesame Inc.", + "Sims", + "Broccoli", + "Avex", + "D3 Publisher", + NULL, + "Konami Computer Entertainment Japan", + NULL, + "Square-Enix", + "KSG", + "Micott & Basara Inc.", + NULL, + "Orbital Media", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "The Game Factory USA", + NULL, + NULL, + "Treasure", + "Aruze", + "Ertain", + "SNK Playmore", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Yojigen" +}; + +static 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 +}; + +static void S9xDeinterleaveType1 (int, uint8 *); +static void S9xDeinterleaveType2 (int, uint8 *); +static void S9xDeinterleaveGD24 (int, uint8 *); +static bool8 allASCII (uint8 *, int); +static bool8 is_SufamiTurbo_BIOS (uint8 *, uint32); +static bool8 is_SufamiTurbo_Cart (uint8 *, uint32); +static bool8 is_SameGame_BIOS (uint8 *, uint32); +static bool8 is_SameGame_Add_On (uint8 *, uint32); +static uint32 caCRC32 (uint8 *, uint32, uint32 crc32 = 0xffffffff); +static uint32 ReadUPSPointer (const uint8 *, unsigned &, unsigned); +static bool8 ReadUPSPatch (Reader *, long, int32 &); +static long ReadInt (Reader *, unsigned); +static bool8 ReadIPSPatch (Reader *, long, int32 &); +#ifdef UNZIP_SUPPORT +static int unzFindExtension (unzFile &, const char *, bool restart = TRUE, bool print = TRUE); +#endif + +// deinterleave + +static void S9xDeinterleaveType1 (int size, uint8 *base) +{ + Settings.DisplayColor = BUILD_PIXEL(0, 31, 0); + SET_UI_COLOR(0, 255, 0); + + uint8 blocks[256]; + int nblocks = size >> 16; + + for (int i = 0; i < nblocks; i++) + { + blocks[i * 2] = i + nblocks; + blocks[i * 2 + 1] = i; + } + + uint8 *tmp = (uint8 *) malloc(0x8000); + if (tmp) + { + for (int i = 0; i < nblocks * 2; i++) + { + for (int j = i; j < nblocks * 2; j++) + { + if (blocks[j] == i) + { + memmove(tmp, &base[blocks[j] * 0x8000], 0x8000); + memmove(&base[blocks[j] * 0x8000], &base[blocks[i] * 0x8000], 0x8000); + memmove(&base[blocks[i] * 0x8000], tmp, 0x8000); + uint8 b = blocks[j]; + blocks[j] = blocks[i]; + blocks[i] = b; + break; + } + } + } + + free(tmp); + } +} + +static void S9xDeinterleaveType2 (int size, uint8 *base) +{ + // for odd Super FX images + Settings.DisplayColor = BUILD_PIXEL(31, 14, 6); + SET_UI_COLOR(255, 119, 25); + + uint8 blocks[256]; + int nblocks = size >> 16; + int step = 64; + + while (nblocks <= step) + step >>= 1; + nblocks = step; + + for (int i = 0; i < nblocks * 2; i++) + blocks[i] = (i & ~0xf) | ((i & 3) << 2) | ((i & 12) >> 2); + + uint8 *tmp = (uint8 *) malloc(0x10000); + if (tmp) + { + for (int i = 0; i < nblocks * 2; i++) + { + for (int j = i; j < nblocks * 2; j++) + { + if (blocks[j] == i) + { + memmove(tmp, &base[blocks[j] * 0x10000], 0x10000); + memmove(&base[blocks[j] * 0x10000], &base[blocks[i] * 0x10000], 0x10000); + memmove(&base[blocks[i] * 0x10000], tmp, 0x10000); + uint8 b = blocks[j]; + blocks[j] = blocks[i]; + blocks[i] = b; + break; + } + } + } + + free(tmp); + } +} + +static void S9xDeinterleaveGD24 (int size, uint8 *base) +{ + // for 24Mb images dumped with Game Doctor + if (size != 0x300000) + return; + + Settings.DisplayColor = BUILD_PIXEL(0, 31, 31); + SET_UI_COLOR(0, 255, 255); + + uint8 *tmp = (uint8 *) malloc(0x80000); + if (tmp) + { + memmove(tmp, &base[0x180000], 0x80000); + memmove(&base[0x180000], &base[0x200000], 0x80000); + memmove(&base[0x200000], &base[0x280000], 0x80000); + memmove(&base[0x280000], tmp, 0x80000); + + free(tmp); + + S9xDeinterleaveType1(size, base); + } +} + +// allocation and deallocation + +bool8 CMemory::Init (void) +{ + RAM = (uint8 *) malloc(0x20000); + SRAM = (uint8 *) malloc(0x20000); + VRAM = (uint8 *) malloc(0x10000); + ROM = (uint8 *) malloc(MAX_ROM_SIZE + 0x200 + 0x8000); + + IPPU.TileCache[TILE_2BIT] = (uint8 *) malloc(MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT] = (uint8 *) malloc(MAX_4BIT_TILES * 64); + IPPU.TileCache[TILE_8BIT] = (uint8 *) malloc(MAX_8BIT_TILES * 64); + IPPU.TileCache[TILE_2BIT_EVEN] = (uint8 *) malloc(MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_2BIT_ODD] = (uint8 *) malloc(MAX_2BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT_EVEN] = (uint8 *) malloc(MAX_4BIT_TILES * 64); + IPPU.TileCache[TILE_4BIT_ODD] = (uint8 *) malloc(MAX_4BIT_TILES * 64); + + 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); + IPPU.TileCached[TILE_2BIT_EVEN] = (uint8 *) malloc(MAX_2BIT_TILES); + IPPU.TileCached[TILE_2BIT_ODD] = (uint8 *) malloc(MAX_2BIT_TILES); + IPPU.TileCached[TILE_4BIT_EVEN] = (uint8 *) malloc(MAX_4BIT_TILES); + IPPU.TileCached[TILE_4BIT_ODD] = (uint8 *) malloc(MAX_4BIT_TILES); + + if (!RAM || !SRAM || !VRAM || !ROM || + !IPPU.TileCache[TILE_2BIT] || + !IPPU.TileCache[TILE_4BIT] || + !IPPU.TileCache[TILE_8BIT] || + !IPPU.TileCache[TILE_2BIT_EVEN] || + !IPPU.TileCache[TILE_2BIT_ODD] || + !IPPU.TileCache[TILE_4BIT_EVEN] || + !IPPU.TileCache[TILE_4BIT_ODD] || + !IPPU.TileCached[TILE_2BIT] || + !IPPU.TileCached[TILE_4BIT] || + !IPPU.TileCached[TILE_8BIT] || + !IPPU.TileCached[TILE_2BIT_EVEN] || + !IPPU.TileCached[TILE_2BIT_ODD] || + !IPPU.TileCached[TILE_4BIT_EVEN] || + !IPPU.TileCached[TILE_4BIT_ODD]) + { + Deinit(); + return (FALSE); + } + + ZeroMemory(RAM, 0x20000); + ZeroMemory(SRAM, 0x20000); + ZeroMemory(VRAM, 0x10000); + ZeroMemory(ROM, MAX_ROM_SIZE + 0x200 + 0x8000); + + ZeroMemory(IPPU.TileCache[TILE_2BIT], MAX_2BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_4BIT], MAX_4BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_8BIT], MAX_8BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_2BIT_EVEN], MAX_2BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_2BIT_ODD], MAX_2BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_4BIT_EVEN], MAX_4BIT_TILES * 64); + ZeroMemory(IPPU.TileCache[TILE_4BIT_ODD], MAX_4BIT_TILES * 64); + + ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD], MAX_4BIT_TILES); + + // 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; // C4 + OBC1RAM = ROM + 0x400000; // OBC1 + BIOSROM = ROM + 0x300000; // BS + BSRAM = ROM + 0x400000; // BS + +#if defined(ZSNES_FX) || defined(ZSNES_C4) + ::ROM = ROM; + ::SRAM = SRAM; + ::RegRAM = FillRAM; +#endif + +#ifdef ZSNES_FX + SFXPlotTable = ROM + 0x400000; +#else + SuperFX.pvRegisters = FillRAM + 0x3000; + SuperFX.nRamBanks = 2; // Most only use 1. 1=64KB=512Mb, 2=128KB=1024Mb + SuperFX.pvRam = SRAM; + SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024); + SuperFX.pvRom = (uint8 *) ROM; +#endif + + PostRomInitFunc = NULL; + + return (TRUE); +} + +void CMemory::Deinit (void) +{ + if (RAM) + { + free(RAM); + RAM = NULL; + } + + if (SRAM) + { + free(SRAM); + SRAM = NULL; + } + + if (VRAM) + { + free(VRAM); + VRAM = NULL; + } + + if (ROM) + { + ROM -= 0x8000; + free(ROM); + ROM = NULL; + } + + for (int t = 0; t < 7; t++) + { + if (IPPU.TileCache[t]) + { + free(IPPU.TileCache[t]); + IPPU.TileCache[t] = NULL; + } + + if (IPPU.TileCached[t]) + { + free(IPPU.TileCached[t]); + IPPU.TileCached[t] = NULL; + } + } + + Safe(NULL); + SafeANK(NULL); +} + +// file management and ROM detection + +static bool8 allASCII (uint8 *b, int size) +{ + for (int i = 0; i < size; i++) + { + if (b[i] < 32 || b[i] > 126) + return (FALSE); + } + + return (TRUE); +} + +static bool8 is_SufamiTurbo_BIOS (uint8 *data, uint32 size) +{ + if (size == 0x40000 && + strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) == 0) + return (TRUE); + else + return (FALSE); +} + +static bool8 is_SufamiTurbo_Cart (uint8 *data, uint32 size) +{ + if (size >= 0x80000 && size <= 0x100000 && + strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) != 0) + return (TRUE); + else + return (FALSE); +} + +static bool8 is_SameGame_BIOS (uint8 *data, uint32 size) +{ + if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0) + return (TRUE); + else + return (FALSE); +} + +static bool8 is_SameGame_Add_On (uint8 *data, uint32 size) +{ + if (size == 0x80000) + return (TRUE); + else + return (FALSE); +} + +int CMemory::ScoreHiROM (bool8 skip_header, int32 romoff) +{ + uint8 *buf = ROM + 0xff00 + romoff + (skip_header ? 0x200 : 0); + int score = 0; + + if (buf[0xd5] & 0x1) + score += 2; + + // Mode23 is SA-1 + if (buf[0xd5] == 0x23) + score -= 2; + + if (buf[0xd4] == 0x20) + score += 2; + + if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff) + { + score += 2; + if (0 != (buf[0xde] + (buf[0xdf] << 8))) + score++; + } + + if (buf[0xda] == 0x33) + score += 2; + + if ((buf[0xd5] & 0xf) < 4) + score += 2; + + if (!(buf[0xfd] & 0x80)) + score -= 6; + + if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0) + score -= 2; // reduced after looking at a scan by Cowering + + if (CalculatedSize > 1024 * 1024 * 3) + score += 4; + + if ((1 << (buf[0xd7] - 7)) > 48) + score -= 1; + + if (!allASCII(&buf[0xb0], 6)) + score -= 1; + + if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1)) + score -= 1; + + return (score); +} + +int CMemory::ScoreLoROM (bool8 skip_header, int32 romoff) +{ + uint8 *buf = ROM + 0x7f00 + romoff + (skip_header ? 0x200 : 0); + int score = 0; + + if (!(buf[0xd5] & 0x1)) + score += 3; + + // Mode23 is SA-1 + if (buf[0xd5] == 0x23) + score += 2; + + if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff) + { + score += 2; + if (0 != (buf[0xde] + (buf[0xdf] << 8))) + score++; + } + + if (buf[0xda] == 0x33) + score += 2; + + if ((buf[0xd5] & 0xf) < 4) + score += 2; + + if (!(buf[0xfd] & 0x80)) + score -= 6; + + if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0) + score -= 2; // reduced per Cowering suggestion + + if (CalculatedSize <= 1024 * 1024 * 16) + score += 2; + + if ((1 << (buf[0xd7] - 7)) > 48) + score -= 1; + + if (!allASCII(&buf[0xb0], 6)) + score -= 1; + + if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1)) + score -= 1; + + return (score); +} + +uint32 CMemory::HeaderRemove (uint32 size, int32 &headerCount, uint8 *buf) +{ + uint32 calc_size = (size / 0x2000) * 0x2000; + + if ((size - calc_size == 512 && !Settings.ForceNoHeader) || Settings.ForceHeader) + { + uint8 *NSRTHead = buf + 0x1D0; // NSRT Header Location + + // detect NSRT header + if (!strncmp("NSRT", (char *) &NSRTHead[24], 4)) + { + if (NSRTHead[28] == 22) + { + if (((std::accumulate(NSRTHead, NSRTHead + sizeof(NSRTHeader), 0) & 0xFF) == NSRTHead[30]) && + (NSRTHead[30] + NSRTHead[31] == 255) && ((NSRTHead[0] & 0x0F) <= 13) && + (((NSRTHead[0] & 0xF0) >> 4) <= 3) && ((NSRTHead[0] & 0xF0) >> 4)) + memcpy(NSRTHeader, NSRTHead, sizeof(NSRTHeader)); + } + } + + memmove(buf, buf + 512, calc_size); + headerCount++; + size -= 512; + } + + return (size); +} + +uint32 CMemory::FileLoader (uint8 *buffer, const char *filename, int32 maxsize) +{ + // <- ROM size without header + // ** Memory.HeaderCount + // ** Memory.ROMFilename + + int32 totalSize = 0; + char fname[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], name[_MAX_FNAME + 1], exts[_MAX_EXT + 1]; + char *ext; + +#if defined(__WIN32__) || defined(__MACOSX__) + ext = &exts[1]; +#else + ext = &exts[0]; +#endif + + memset(NSRTHeader, 0, sizeof(NSRTHeader)); + HeaderCount = 0; + + _splitpath(filename, drive, dir, name, exts); + _makepath(fname, drive, dir, name, exts); + + int nFormat = FILE_DEFAULT; + if (strcasecmp(ext, "zip") == 0) + nFormat = FILE_ZIP; + else + if (strcasecmp(ext, "jma") == 0) + nFormat = FILE_JMA; + + switch (nFormat) + { + case FILE_ZIP: + { + #ifdef UNZIP_SUPPORT + if (!LoadZip(fname, &totalSize, &HeaderCount, buffer)) + { + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid Zip archive."); + return (0); + } + + strcpy(ROMFilename, fname); + #else + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with Zip support."); + return (0); + #endif + break; + } + + case FILE_JMA: + { + #ifdef JMA_SUPPORT + size_t size = load_jma_file(fname, buffer); + if (!size) + { + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid JMA archive."); + return (0); + } + + totalSize = HeaderRemove(size, HeaderCount, buffer); + + strcpy(ROMFilename, fname); + #else + S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with JMA support."); + return (0); + #endif + break; + } + + case FILE_DEFAULT: + default: + { + STREAM fp = OPEN_STREAM(fname, "rb"); + if (!fp) + return (0); + + strcpy(ROMFilename, fname); + + int len = 0; + uint32 size = 0; + bool8 more = FALSE; + uint8 *ptr = buffer; + + do + { + size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp); + CLOSE_STREAM(fp); + + size = HeaderRemove(size, HeaderCount, ptr); + totalSize += size; + ptr += size; + + // check for multi file roms + if (ptr - buffer < maxsize + 0x200 && + (isdigit(ext[0]) && ext[1] == 0 && ext[0] < '9')) + { + more = TRUE; + ext[0]++; + _makepath(fname, drive, dir, name, exts); + } + else + if (ptr - buffer < maxsize + 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]++; + _makepath(fname, drive, dir, name, exts); + } + else + more = FALSE; + + } while (more && (fp = OPEN_STREAM(fname, "rb")) != NULL); + + break; + } + } + + 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)."); + + return ((uint32) totalSize); +} + +bool8 CMemory::LoadROM (const char *filename) +{ + int retry_count = 0; + + if (!filename || !*filename) + return (FALSE); + + ZeroMemory(ROM, MAX_ROM_SIZE); + ZeroMemory(&Multi, sizeof(Multi)); + +again: + Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); + SET_UI_COLOR(255, 255, 255); + + CalculatedSize = 0; + ExtendedFormat = NOPE; + + int32 totalFileSize; + + totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE); + if (!totalFileSize) + return (FALSE); + + if (!Settings.NoPatch) + CheckForAnyPatch(filename, HeaderCount != 0, totalFileSize); + + int hi_score, lo_score; + + hi_score = ScoreHiROM(FALSE); + 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(ROM, ROM + 512, totalFileSize - 512); + totalFileSize -= 512; + S9xMessage(S9X_INFO, S9X_HEADER_WARNING, "Try 'force no-header' option if the game doesn't work"); + // modifying ROM, so we need to rescore + hi_score = ScoreHiROM(FALSE); + lo_score = ScoreLoROM(FALSE); + } + + CalculatedSize = (totalFileSize / 0x2000) * 0x2000; + + if (CalculatedSize > 0x400000 && + (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4332 && // exclude S-DD1 + (ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4532 && + (ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF93a && // exclude SPC7110 + (ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF53a) + ExtendedFormat = YEAH; + + // if both vectors are invalid, it's type 1 interleaved LoROM + if (ExtendedFormat == NOPE && + ((ROM[0x7ffc] + (ROM[0x7ffd] << 8)) < 0x8000) && + ((ROM[0xfffc] + (ROM[0xfffd] << 8)) < 0x8000)) + { + if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved) + S9xDeinterleaveType1(totalFileSize, ROM); + } + + // CalculatedSize is now set, so rescore + hi_score = ScoreHiROM(FALSE); + lo_score = ScoreLoROM(FALSE); + + uint8 *RomHeader = ROM; + + if (ExtendedFormat != NOPE) + { + int swappedhirom, swappedlorom; + + swappedhirom = ScoreHiROM(FALSE, 0x400000); + swappedlorom = ScoreLoROM(FALSE, 0x400000); + + // set swapped here + if (max(swappedlorom, swappedhirom) >= max(lo_score, hi_score)) + { + ExtendedFormat = BIGFIRST; + hi_score = swappedhirom; + lo_score = swappedlorom; + RomHeader += 0x400000; + } + else + ExtendedFormat = SMALLFIRST; + } + + bool8 interleaved, tales = FALSE; + + interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2 || Settings.ForceInterleaveGD24; + + if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score)) + { + LoROM = TRUE; + HiROM = FALSE; + + // ignore map type byte if not 0x2x or 0x3x + if ((RomHeader[0x7fd5] & 0xf0) == 0x20 || (RomHeader[0x7fd5] & 0xf0) == 0x30) + { + switch (RomHeader[0x7fd5] & 0xf) + { + case 1: + interleaved = TRUE; + break; + + case 5: + interleaved = TRUE; + tales = TRUE; + break; + } + } + } + else + { + LoROM = FALSE; + HiROM = TRUE; + + if ((RomHeader[0xffd5] & 0xf0) == 0x20 || (RomHeader[0xffd5] & 0xf0) == 0x30) + { + switch (RomHeader[0xffd5] & 0xf) + { + case 0: + case 3: + interleaved = TRUE; + break; + } + } + } + + // this two games fail to be detected + if (!Settings.ForceHiROM && !Settings.ForceLoROM) + { + if (strncmp((char *) &ROM[0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 || + (strncmp((char *) &ROM[0xffc0], "BATMAN--REVENGE JOKER", 21) == 0)) + { + LoROM = TRUE; + HiROM = FALSE; + interleaved = FALSE; + tales = FALSE; + } + } + + if (!Settings.ForceNotInterleaved && interleaved) + { + S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "ROM image is in interleaved format - converting..."); + + if (tales) + { + if (ExtendedFormat == BIGFIRST) + { + S9xDeinterleaveType1(0x400000, ROM); + S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM + 0x400000); + } + else + { + S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM); + S9xDeinterleaveType1(0x400000, ROM + CalculatedSize - 0x400000); + } + + LoROM = FALSE; + HiROM = TRUE; + } + else + if (Settings.ForceInterleaveGD24 && CalculatedSize == 0x300000) + { + bool8 t = LoROM; + LoROM = HiROM; + HiROM = t; + S9xDeinterleaveGD24(CalculatedSize, ROM); + } + else + if (Settings.ForceInterleaved2) + S9xDeinterleaveType2(CalculatedSize, ROM); + else + { + bool8 t = LoROM; + LoROM = HiROM; + HiROM = t; + S9xDeinterleaveType1(CalculatedSize, ROM); + } + + 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; + } + } + } + + if (ExtendedFormat == SMALLFIRST) + tales = TRUE; + + if (tales) + { + uint8 *tmp = (uint8 *) malloc(CalculatedSize - 0x400000); + if (tmp) + { + S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "Fixing swapped ExHiROM..."); + memmove(tmp, ROM, CalculatedSize - 0x400000); + memmove(ROM, ROM + CalculatedSize - 0x400000, 0x400000); + memmove(ROM + 0x400000, tmp, CalculatedSize - 0x400000); + free(tmp); + } + } + + if (strncmp(LastRomFilename, filename, PATH_MAX + 1)) + { + strncpy(LastRomFilename, filename, PATH_MAX + 1); + LastRomFilename[PATH_MAX] = 0; + } + + ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); + SNESGameFixes.SRAMInitialValue = 0x60; + + S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); + + InitROM(); + + S9xInitCheatData(); + S9xApplyCheats(); + + S9xReset(); + + return (TRUE); +} + +bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) +{ + bool8 r = TRUE; + + ZeroMemory(ROM, MAX_ROM_SIZE); + ZeroMemory(&Multi, sizeof(Multi)); + + Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); + SET_UI_COLOR(255, 255, 255); + + CalculatedSize = 0; + ExtendedFormat = NOPE; + + if (cartA && cartA[0]) + Multi.cartSizeA = FileLoader(ROM, cartA, MAX_ROM_SIZE); + + if (Multi.cartSizeA == 0) + { + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); + } + + if (Multi.cartSizeA) + { + if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeA)) + Multi.cartType = 4; + else + if (is_SameGame_BIOS(ROM, Multi.cartSizeA)) + Multi.cartType = 3; + } + else + if (Multi.cartSizeB) + { + if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeB)) + Multi.cartType = 4; + } + else + Multi.cartType = 4; // assuming BIOS only + + switch (Multi.cartType) + { + case 4: + r = LoadSufamiTurbo(cartA, cartB); + break; + + case 3: + r = LoadSameGame(cartA, cartB); + break; + + default: + r = FALSE; + } + + if (!r) + { + ZeroMemory(&Multi, sizeof(Multi)); + return (FALSE); + } + + ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); + SNESGameFixes.SRAMInitialValue = 0x60; + + S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); + + InitROM(); + + S9xInitCheatData(); + S9xApplyCheats(); + + S9xReset(); + + return (TRUE); +} + +bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) +{ + Multi.cartOffsetA = 0x100000; + Multi.cartOffsetB = 0x200000; + Multi.sramA = SRAM; + Multi.sramB = SRAM + 0x10000; + + if (Multi.cartSizeA) + { + Multi.sramSizeA = 4; // ROM[0x37]? + Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; + + if (!Settings.NoPatch) + CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); + + strcpy(Multi.fileNameA, cartA); + memcpy(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA); + } + + if (Multi.cartSizeA && !Multi.cartSizeB) + { + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); + + if (Multi.cartSizeB) + { + if (!is_SufamiTurbo_Cart(ROM, Multi.cartSizeB)) + Multi.cartSizeB = 0; + } + } + + if (Multi.cartSizeB) + { + Multi.sramSizeB = 4; // ROM[0x37]? + Multi.sramMaskB = Multi.sramSizeB ? ((1 << (Multi.sramSizeB + 3)) * 128 - 1) : 0; + + if (!Settings.NoPatch) + CheckForAnyPatch(cartB, HeaderCount != 0, Multi.cartSizeB); + + strcpy(Multi.fileNameB, cartB); + memcpy(ROM + Multi.cartOffsetB, ROM, Multi.cartSizeB); + } + + FILE *fp; + size_t size; + char path[PATH_MAX + 1]; + + strcpy(path, S9xGetDirectory(BIOS_DIR)); + strcat(path, SLASH_STR); + strcat(path, "STBIOS.bin"); + + fp = fopen(path, "rb"); + if (fp) + { + size = fread((void *) ROM, 1, 0x40000, fp); + fclose(fp); + if (!is_SufamiTurbo_BIOS(ROM, size)) + return (FALSE); + } + else + return (FALSE); + + if (Multi.cartSizeA) + strcpy(ROMFilename, Multi.fileNameA); + else + if (Multi.cartSizeB) + strcpy(ROMFilename, Multi.fileNameB); + else + strcpy(ROMFilename, path); + + LoROM = TRUE; + HiROM = FALSE; + CalculatedSize = 0x40000; + + return (TRUE); +} + +bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) +{ + Multi.cartOffsetA = 0; + Multi.cartOffsetB = 0x200000; + Multi.sramA = SRAM; + Multi.sramB = NULL; + + Multi.sramSizeA = ROM[0xffd8]; + Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; + Multi.sramSizeB = 0; + Multi.sramMaskB = 0; + + if (!Settings.NoPatch) + CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); + + strcpy(Multi.fileNameA, cartA); + + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM + Multi.cartOffsetB, cartB, MAX_ROM_SIZE - Multi.cartOffsetB); + + if (Multi.cartSizeB) + { + if (!is_SameGame_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB)) + Multi.cartSizeB = 0; + else + strcpy(Multi.fileNameB, cartB); + } + + strcpy(ROMFilename, Multi.fileNameA); + + LoROM = FALSE; + HiROM = TRUE; + CalculatedSize = Multi.cartSizeA; + + return (TRUE); +} + +bool8 CMemory::LoadSRTC (void) +{ + FILE *fp; + size_t ignore; + + fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "rb"); + if (!fp) + return (FALSE); + + ignore = fread(RTCData.reg, 1, 20, fp); + fclose(fp); + + return (TRUE); +} + +bool8 CMemory::SaveSRTC (void) +{ + FILE *fp; + size_t ignore; + + fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "wb"); + if (!fp) + return (FALSE); + + ignore = fwrite(RTCData.reg, 1, 20, fp); + fclose(fp); + + return (TRUE); +} + +void CMemory::ClearSRAM (bool8 onlyNonSavedSRAM) +{ + if (onlyNonSavedSRAM) + if (!(Settings.SuperFX && ROMType < 0x15) && !(Settings.SA1 && ROMType == 0x34)) // can have SRAM + return; + + memset(SRAM, SNESGameFixes.SRAMInitialValue, 0x20000); +} + +bool8 CMemory::LoadSRAM (const char *filename) +{ + FILE *file; + int size, len; + char sramName[PATH_MAX + 1]; + + strcpy(sramName, filename); + + ClearSRAM(); + + if (Multi.cartType && Multi.sramSizeB) + { + char temp[PATH_MAX + 1]; + + strcpy(temp, ROMFilename); + strcpy(ROMFilename, Multi.fileNameB); + + size = (1 << (Multi.sramSizeB + 3)) * 128; + + file = fopen(S9xGetFilename(".srm", SRAM_DIR), "rb"); + if (file) + { + len = fread((char *) Multi.sramB, 1, 0x10000, file); + fclose(file); + if (len - size == 512) + memmove(Multi.sramB, Multi.sramB + 512, size); + } + + strcpy(ROMFilename, temp); + } + + size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0; + if (size > 0x20000) + size = 0x20000; + + if (size) + { + file = fopen(sramName, "rb"); + if (file) + { + len = fread((char *) SRAM, 1, 0x20000, file); + fclose(file); + if (len - size == 512) + memmove(SRAM, SRAM + 512, size); + + if (Settings.SRTC || Settings.SPC7110RTC) + LoadSRTC(); + + return (TRUE); + } + else + if (Settings.BS && !Settings.BSXItself) + { + // The BS game's SRAM was not found + // Try to read BS-X.srm instead + char path[PATH_MAX + 1]; + + strcpy(path, S9xGetDirectory(SRAM_DIR)); + strcat(path, SLASH_STR); + strcat(path, "BS-X.srm"); + + file = fopen(path, "rb"); + if (file) + { + len = fread((char *) SRAM, 1, 0x20000, file); + fclose(file); + if (len - size == 512) + memmove(SRAM, SRAM + 512, size); + + S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found: BS-X.srm was read instead."); + return (TRUE); + } + else + { + S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found, BS-X.srm wasn't found either."); + return (FALSE); + } + } + + return (FALSE); + } + + return (TRUE); +} + +bool8 CMemory::SaveSRAM (const char *filename) +{ + if (Settings.SuperFX && ROMType < 0x15) // doesn't have SRAM + return (TRUE); + + if (Settings.SA1 && ROMType == 0x34) // doesn't have SRAM + return (TRUE); + + FILE *file; + int size; + char sramName[PATH_MAX + 1]; + + strcpy(sramName, filename); + + if (Multi.cartType && Multi.sramSizeB) + { + char name[PATH_MAX + 1], temp[PATH_MAX + 1]; + + strcpy(temp, ROMFilename); + strcpy(ROMFilename, Multi.fileNameB); + strcpy(name, S9xGetFilename(".srm", SRAM_DIR)); + + size = (1 << (Multi.sramSizeB + 3)) * 128; + + file = fopen(name, "wb"); + if (file) + { + size_t ignore; + ignore = fwrite((char *) Multi.sramB, size, 1, file); + fclose(file); + #ifdef __linux + ignore = chown(name, getuid(), getgid()); + #endif + } + + strcpy(ROMFilename, temp); + } + + size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0; + if (size > 0x20000) + size = 0x20000; + + if (size) + { + file = fopen(sramName, "wb"); + if (file) + { + size_t ignore; + ignore = fwrite((char *) SRAM, size, 1, file); + fclose(file); + #ifdef __linux + ignore = chown(sramName, getuid(), getgid()); + #endif + + if (Settings.SRTC || Settings.SPC7110RTC) + SaveSRTC(); + + return (TRUE); + } + } + + return (FALSE); +} + +// initialization + +static uint32 caCRC32 (uint8 *array, uint32 size, uint32 crc32) +{ + for (uint32 i = 0; i < size; i++) + crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF]; + + return (~crc32); +} + +char * CMemory::Safe (const char *s) +{ + static char *safe = NULL; + static int safe_len = 0; + + if (s == NULL) + { + if (safe) + { + free(safe); + safe = NULL; + } + + return (NULL); + } + + int len = strlen(s); + if (!safe || len + 1 > safe_len) + { + if (safe) + free(safe); + + safe_len = len + 1; + safe = (char *) malloc(safe_len); + } + + 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); +} + +char * CMemory::SafeANK (const char *s) +{ + static char *safe = NULL; + static int safe_len = 0; + + if (s == NULL) + { + if (safe) + { + free(safe); + safe = NULL; + } + + return (NULL); + } + + int len = strlen(s); + if (!safe || len + 1 > safe_len) + { + if (safe) + free(safe); + + safe_len = len + 1; + safe = (char *) malloc(safe_len); + } + + for (int i = 0; i < len; i++) + { + if (s[i] >= 32 && s[i] < 127) // ASCII + safe [i] = s[i]; + else + if (ROMRegion == 0 && ((uint8) s[i] >= 0xa0 && (uint8) s[i] < 0xe0)) // JIS X 201 - Katakana + safe [i] = s[i]; + else + safe [i] = '_'; + } + + safe [len] = 0; + + return (safe); +} + +void CMemory::ParseSNESHeader (uint8 *RomHeader) +{ + bool8 bs = Settings.BS & !Settings.BSXItself; + + strncpy(ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1); + if (bs) + memset(ROMName + 16, 0x20, ROM_NAME_LEN - 17); + + if (bs) + { + if (!(((RomHeader[0x29] & 0x20) && CalculatedSize < 0x100000) || + (!(RomHeader[0x29] & 0x20) && CalculatedSize == 0x100000))) + printf("BS: Size mismatch\n"); + + // FIXME + int p = 0; + while ((1 << p) < (int) CalculatedSize) + p++; + ROMSize = p - 10; + } + else + ROMSize = RomHeader[0x27]; + + SRAMSize = bs ? 5 /* BS-X */ : RomHeader[0x28]; + ROMSpeed = bs ? RomHeader[0x28] : RomHeader[0x25]; + ROMType = bs ? 0xE5 /* BS-X */ : RomHeader[0x26]; + ROMRegion = bs ? 0 : RomHeader[0x29]; + + ROMChecksum = RomHeader[0x2E] + (RomHeader[0x2F] << 8); + ROMComplementChecksum = RomHeader[0x2C] + (RomHeader[0x2D] << 8); + + memmove(ROMId, &RomHeader[0x02], 4); + + if (RomHeader[0x2A] != 0x33) + CompanyId = ((RomHeader[0x2A] >> 4) & 0x0F) * 36 + (RomHeader[0x2A] & 0x0F); + else + if (isalnum(RomHeader[0x00]) && isalnum(RomHeader[0x01])) + { + int l, r, l2, r2; + l = toupper(RomHeader[0x00]); + r = toupper(RomHeader[0x01]); + l2 = (l > '9') ? l - '7' : l - '0'; + r2 = (r > '9') ? r - '7' : r - '0'; + CompanyId = l2 * 36 + r2; + } +} + +void CMemory::InitROM (void) +{ + Settings.SuperFX = FALSE; + Settings.DSP = 0; + Settings.SA1 = FALSE; + Settings.C4 = FALSE; + Settings.SDD1 = FALSE; + Settings.SPC7110 = FALSE; + Settings.SPC7110RTC = FALSE; + Settings.OBC1 = FALSE; + Settings.SETA = 0; + Settings.SRTC = FALSE; + Settings.BS = FALSE; +#ifndef ZSNES_FX + SuperFX.nRomBanks = CalculatedSize >> 15; +#endif + SA1.Executing = FALSE; + + //// Parse ROM header and read ROM informatoin + + CompanyId = -1; + memset(ROMId, 0, 5); + + uint8 *RomHeader = ROM + 0x7FB0; + if (ExtendedFormat == BIGFIRST) + RomHeader += 0x400000; + if (HiROM) + RomHeader += 0x8000; + + S9xInitBSX(); // Set BS header before parsing + + ParseSNESHeader(RomHeader); + + //// Detect and initialize chips + //// detection codes are compatible with NSRT + + // DSP1/2/3/4 + if (ROMType == 0x03) + { + if (ROMSpeed == 0x30) + Settings.DSP = 4; // DSP4 + else + Settings.DSP = 1; // DSP1 + } + else + if (ROMType == 0x05) + { + if (ROMSpeed == 0x20) + Settings.DSP = 2; // DSP2 + else + if (ROMSpeed == 0x30 && RomHeader[0x2a] == 0xb2) + Settings.DSP = 3; // DSP3 + else + Settings.DSP = 1; // DSP1 + } + + switch (Settings.DSP) + { + case 1: // DSP1 + if (HiROM) + { + DSP0.boundary = 0x7000; + DSP0.maptype = M_DSP1_HIROM; + } + else + if (CalculatedSize > 0x100000) + { + DSP0.boundary = 0x4000; + DSP0.maptype = M_DSP1_LOROM_L; + } + else + { + DSP0.boundary = 0xc000; + DSP0.maptype = M_DSP1_LOROM_S; + } + + SetDSP = &DSP1SetByte; + GetDSP = &DSP1GetByte; + break; + + case 2: // DSP2 + DSP0.boundary = 0x10000; + DSP0.maptype = M_DSP2_LOROM; + SetDSP = &DSP2SetByte; + GetDSP = &DSP2GetByte; + break; + + case 3: // DSP3 + DSP0.boundary = 0xc000; + DSP0.maptype = M_DSP3_LOROM; + SetDSP = &DSP3SetByte; + GetDSP = &DSP3GetByte; + break; + + case 4: // DSP4 + DSP0.boundary = 0xc000; + DSP0.maptype = M_DSP4_LOROM; + SetDSP = &DSP4SetByte; + GetDSP = &DSP4GetByte; + break; + + default: + SetDSP = NULL; + GetDSP = NULL; + break; + } + + uint32 identifier = ((ROMType & 0xff) << 8) + (ROMSpeed & 0xff); + + switch (identifier) + { + // SRTC + case 0x5535: + Settings.SRTC = TRUE; + S9xInitSRTC(); + break; + + // SPC7110 + case 0xF93A: + Settings.SPC7110RTC = TRUE; + case 0xF53A: + Settings.SPC7110 = TRUE; + S9xInitSPC7110(); + break; + + // OBC1 + case 0x2530: + Settings.OBC1 = TRUE; + break; + + // SA1 + case 0x3423: + case 0x3523: + Settings.SA1 = TRUE; + break; + + // SuperFX + case 0x1320: + case 0x1420: + case 0x1520: + case 0x1A20: + Settings.SuperFX = TRUE; + #ifndef ZSNES_FX + S9xInitSuperFX(); + #endif + if (ROM[0x7FDA] == 0x33) + SRAMSize = ROM[0x7FBD]; + else + SRAMSize = 5; + break; + + // SDD1 + case 0x4332: + case 0x4532: + Settings.SDD1 = TRUE; + break; + + // ST018 + case 0xF530: + Settings.SETA = ST_018; + SetSETA = NULL; + GetSETA = NULL; + SRAMSize = 2; + SNESGameFixes.SRAMInitialValue = 0x00; + break; + + // ST010/011 + case 0xF630: + if (ROM[0x7FD7] == 0x09) + { + Settings.SETA = ST_011; + SetSETA = &S9xSetST011; + GetSETA = &S9xGetST011; + } + else + { + Settings.SETA = ST_010; + SetSETA = &S9xSetST010; + GetSETA = &S9xGetST010; + } + + SRAMSize = 2; + SNESGameFixes.SRAMInitialValue = 0x00; + break; + + // C4 + case 0xF320: + Settings.C4 = TRUE; + break; + } + + //// Map memory and calculate checksum + + Map_Initialize(); + CalculatedChecksum = 0; + + if (HiROM) + { + if (Settings.BS) + /* Do nothing */; + else + if (Settings.SPC7110) + Map_SPC7110HiROMMap(); + else + if (ExtendedFormat != NOPE) + Map_ExtendedHiROMMap(); + else + if (Multi.cartType == 3) + Map_SameGameHiROMMap(); + else + Map_HiROMMap(); + } + else + { + if (Settings.BS) + /* Do nothing */; + else + if (Settings.SETA && Settings.SETA != ST_018) + Map_SetaDSPLoROMMap(); + else + if (Settings.SuperFX) + Map_SuperFXLoROMMap(); + else + if (Settings.SA1) + Map_SA1LoROMMap(); + else + if (Settings.SDD1) + Map_SDD1LoROMMap(); + else + if (ExtendedFormat != NOPE) + Map_JumboLoROMMap(); + else + if (strncmp(ROMName, "WANDERERS FROM YS", 17) == 0) + Map_NoMAD1LoROMMap(); + else + if (strncmp(ROMName, "SOUND NOVEL-TCOOL", 17) == 0 || + strncmp(ROMName, "DERBY STALLION 96", 17) == 0) + Map_ROM24MBSLoROMMap(); + else + if (strncmp(ROMName, "THOROUGHBRED BREEDER3", 21) == 0 || + strncmp(ROMName, "RPG-TCOOL 2", 11) == 0) + Map_SRAM512KLoROMMap(); + else + if (strncmp(ROMName, "ADD-ON BASE CASSETE", 19) == 0) + { + if (Multi.cartType == 4) + { + SRAMSize = Multi.sramSizeA; + Map_SufamiTurboLoROMMap(); + } + else + { + SRAMSize = 5; + Map_SufamiTurboPseudoLoROMMap(); + } + } + else + Map_LoROMMap(); + } + + Checksum_Calculate(); + + bool8 isChecksumOK = (ROMChecksum + ROMComplementChecksum == 0xffff) & + (ROMChecksum == CalculatedChecksum); + + //// Build more ROM information + + // CRC32 + if (!Settings.BS || Settings.BSXItself) // Not BS Dump + ROMCRC32 = caCRC32(ROM, CalculatedSize); + else // Convert to correct format before scan + { + int offset = HiROM ? 0xffc0 : 0x7fc0; + // Backup + uint8 BSMagic0 = ROM[offset + 22], + BSMagic1 = ROM[offset + 23]; + // uCONSRT standard + ROM[offset + 22] = 0x42; + ROM[offset + 23] = 0x00; + // Calc + ROMCRC32 = caCRC32(ROM, CalculatedSize); + // Convert back + ROM[offset + 22] = BSMagic0; + ROM[offset + 23] = BSMagic1; + } + + // NTSC/PAL + if (Settings.ForceNTSC) + Settings.PAL = FALSE; + else + if (Settings.ForcePAL) + Settings.PAL = TRUE; + else + if (!Settings.BS && (ROMRegion >= 2) && (ROMRegion <= 12)) + Settings.PAL = TRUE; + else + Settings.PAL = FALSE; + + if (Settings.PAL) + { + Settings.FrameTime = Settings.FrameTimePAL; + ROMFramesPerSecond = 50; + } + else + { + Settings.FrameTime = Settings.FrameTimeNTSC; + ROMFramesPerSecond = 60; + } + + // truncate cart name + ROMName[ROM_NAME_LEN - 1] = 0; + if (strlen(ROMName)) + { + char *p = ROMName + strlen(ROMName); + if (p > ROMName + 21 && ROMName[20] == ' ') + p = ROMName + 21; + while (p > ROMName && *(p - 1) == ' ') + p--; + *p = 0; + } + + // SRAM size + SRAMMask = SRAMSize ? ((1 << (SRAMSize + 3)) * 128) - 1 : 0; + + // checksum + if (!isChecksumOK || ((uint32) CalculatedSize > (uint32) (((1 << (ROMSize - 7)) * 128) * 1024))) + { + Settings.DisplayColor = BUILD_PIXEL(31, 31, 0); + SET_UI_COLOR(255, 255, 0); + } + + if (Multi.cartType == 4) + { + Settings.DisplayColor = BUILD_PIXEL(0, 16, 31); + SET_UI_COLOR(0, 128, 255); + } + + //// Initialize emulation + + Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE; + Timings.H_Max = Timings.H_Max_Master; + Timings.HBlankStart = SNES_HBLANK_START_HC; + Timings.HBlankEnd = SNES_HBLANK_END_HC; + Timings.HDMAInit = SNES_HDMA_INIT_HC; + Timings.HDMAStart = SNES_HDMA_START_HC; + Timings.RenderPos = SNES_RENDER_START_HC; + Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER; + Timings.V_Max = Timings.V_Max_Master; + /* From byuu: The total delay time for both the initial (H)DMA sync (to the DMA clock), + and the end (H)DMA sync (back to the last CPU cycle's mcycle rate (6, 8, or 12)) always takes between 12-24 mcycles. + Possible delays: { 12, 14, 16, 18, 20, 22, 24 } + XXX: Snes9x can't emulate this timing :( so let's use the average value... */ + Timings.DMACPUSync = 18; + /* If the CPU is halted (i.e. for DMA) while /NMI goes low, the NMI will trigger + after the DMA completes (even if /NMI goes high again before the DMA + completes). In this case, there is a 24-30 cycle delay between the end of DMA + and the NMI handler, time enough for an instruction or two. */ + // Wild Guns, Mighty Morphin Power Rangers - The Fighting Edition + Timings.NMIDMADelay = 24; + Timings.IRQPendCount = 0; + + CPU.FastROMSpeed = 0; + ResetSpeedMap(); + + IPPU.TotalEmulatedFrames = 0; + + //// Hack games + + ApplyROMFixes(); + + //// Show ROM information + char displayName[ROM_NAME_LEN]; + + strcpy(RawROMName, ROMName); + sprintf(displayName, "%s", SafeANK(ROMName)); + sprintf(ROMName, "%s", Safe(ROMName)); + sprintf(ROMId, "%s", Safe(ROMId)); + + sprintf(String, "\"%s\" [%s] %s, %s, %s, %s, SRAM:%s, ID:%s, CRC32:%08X", + displayName, isChecksumOK ? "checksum ok" : ((Multi.cartType == 4) ? "no checksum" : "bad checksum"), + MapType(), Size(), KartContents(), Settings.PAL ? "PAL" : "NTSC", StaticRAMSize(), ROMId, ROMCRC32); + S9xMessage(S9X_INFO, S9X_ROM_INFO, String); + + Settings.ForceLoROM = FALSE; + Settings.ForceHiROM = FALSE; + Settings.ForceHeader = FALSE; + Settings.ForceNoHeader = FALSE; + Settings.ForceInterleaved = FALSE; + Settings.ForceInterleaved2 = FALSE; + Settings.ForceInterleaveGD24 = FALSE; + Settings.ForceNotInterleaved = FALSE; + Settings.ForcePAL = FALSE; + Settings.ForceNTSC = FALSE; + + Settings.TakeScreenshot = FALSE; + + if (stopMovie) + S9xMovieStop(TRUE); + + if (PostRomInitFunc) + PostRomInitFunc(); + + S9xVerifyControllers(); +} + +void CMemory::FixROMSpeed (void) +{ + if (CPU.FastROMSpeed == 0) + CPU.FastROMSpeed = SLOW_ONE_CYCLE; + + // [80-bf]:[8000-ffff], [c0-ff]:[0000-ffff] + for (int c = 0x800; c < 0x1000; c++) + { + if (c & 0x8 || c & 0x400) + MemorySpeed[c] = (uint8) CPU.FastROMSpeed; + } +} + +void CMemory::ResetSpeedMap (void) +{ + memset(MemorySpeed, SLOW_ONE_CYCLE, 0x1000); + + // Fast - [00-3f|80-bf]:[2000-3fff|4200-5fff] + // XSlow - [00-3f|80-bf]:[4000-41ff] see also S9xGet/SetCPU() + for (int i = 0; i < 0x400; i += 0x10) + { + MemorySpeed[i + 2] = MemorySpeed[0x800 + i + 2] = ONE_CYCLE; + MemorySpeed[i + 3] = MemorySpeed[0x800 + i + 3] = ONE_CYCLE; + MemorySpeed[i + 4] = MemorySpeed[0x800 + i + 4] = ONE_CYCLE; + MemorySpeed[i + 5] = MemorySpeed[0x800 + i + 5] = ONE_CYCLE; + } + + FixROMSpeed(); +} + +// memory map + +uint32 CMemory::map_mirror (uint32 size, uint32 pos) +{ + // from bsnes + if (size == 0) + return (0); + if (pos < size) + return (pos); + + uint32 mask = 1 << 31; + while (!(pos & mask)) + mask >>= 1; + + if (size <= (pos & mask)) + return (map_mirror(size, pos - mask)); + else + return (mask + map_mirror(size - mask, pos - mask)); +} + +void CMemory::map_lorom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size) +{ + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = (c & 0x7f) * 0x8000; + Map[p] = ROM + map_mirror(size, addr) - (i & 0x8000); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} + +void CMemory::map_hirom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size) +{ + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = c << 16; + Map[p] = ROM + map_mirror(size, addr); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} + +void CMemory::map_lorom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, uint32 offset) +{ + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = ((c - bank_s) & 0x7f) * 0x8000; + Map[p] = ROM + offset + map_mirror(size, addr) - (i & 0x8000); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} + +void CMemory::map_hirom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, uint32 offset) +{ + uint32 c, i, p, addr; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + addr = (c - bank_s) << 16; + Map[p] = ROM + offset + map_mirror(size, addr); + BlockIsROM[p] = TRUE; + BlockIsRAM[p] = FALSE; + } + } +} + +void CMemory::map_space (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint8 *data) +{ + uint32 c, i, p; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + Map[p] = data; + BlockIsROM[p] = FALSE; + BlockIsRAM[p] = TRUE; + } + } +} + +void CMemory::map_index (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, int index, int type) +{ + uint32 c, i, p; + bool8 isROM, isRAM; + + isROM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_RAM)) ? FALSE : TRUE; + isRAM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_ROM)) ? FALSE : TRUE; + + for (c = bank_s; c <= bank_e; c++) + { + for (i = addr_s; i <= addr_e; i += 0x1000) + { + p = (c << 4) | (i >> 12); + Map[p] = (uint8 *) index; + BlockIsROM[p] = isROM; + BlockIsRAM[p] = isRAM; + } + } +} + +void CMemory::map_System (void) +{ + // will be overwritten + map_space(0x00, 0x3f, 0x0000, 0x1fff, RAM); + map_index(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O); + map_index(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O); + map_space(0x80, 0xbf, 0x0000, 0x1fff, RAM); + map_index(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O); +} + +void CMemory::map_WRAM (void) +{ + // will overwrite others + map_space(0x7e, 0x7e, 0x0000, 0xffff, RAM); + map_space(0x7f, 0x7f, 0x0000, 0xffff, RAM + 0x10000); +} + +void CMemory::map_LoROMSRAM (void) +{ + map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM); +} + +void CMemory::map_HiROMSRAM (void) +{ + map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); + map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); +} + +void CMemory::map_DSP (void) +{ + switch (DSP0.maptype) + { + case M_DSP1_LOROM_S: + map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP1_LOROM_L: + map_index(0x60, 0x6f, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xe0, 0xef, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP1_HIROM: + map_index(0x00, 0x1f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0x80, 0x9f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP2_LOROM: + map_index(0x20, 0x3f, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0x20, 0x3f, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP3_LOROM: + map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + break; + + case M_DSP4_LOROM: + map_index(0x30, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + map_index(0xb0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); + break; + } +} + +void CMemory::map_C4 (void) +{ + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O); +} + +void CMemory::map_OBC1 (void) +{ + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O); +} + +void CMemory::map_SetaRISC (void) +{ + map_index(0x00, 0x3f, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O); +} + +void CMemory::map_SetaDSP (void) +{ + // where does the SETA chip access, anyway? + // please confirm this? + map_index(0x68, 0x6f, 0x0000, 0x7fff, MAP_SETA_DSP, MAP_TYPE_RAM); + // and this! + map_index(0x60, 0x67, 0x0000, 0x3fff, MAP_SETA_DSP, MAP_TYPE_I_O); + + // ST-0010: + // map_index(0x68, 0x6f, 0x0000, 0x0fff, MAP_SETA_DSP, ?); +} + +void CMemory::map_WriteProtectROM (void) +{ + memmove((void *) WriteMap, (void *) Map, sizeof(Map)); + + for (int c = 0; c < 0x1000; c++) + { + if (BlockIsROM[c]) + WriteMap[c] = (uint8 *) MAP_NONE; + } +} + +void CMemory::Map_Initialize (void) +{ + for (int c = 0; c < 0x1000; c++) + { + Map[c] = (uint8 *) MAP_NONE; + WriteMap[c] = (uint8 *) MAP_NONE; + BlockIsROM[c] = FALSE; + BlockIsRAM[c] = FALSE; + } +} + +void CMemory::Map_LoROMMap (void) +{ + printf("Map_LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + if (Settings.DSP) + map_DSP(); + else + if (Settings.C4) + map_C4(); + else + if (Settings.OBC1) + map_OBC1(); + else + if (Settings.SETA == ST_018) + map_SetaRISC(); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_NoMAD1LoROMMap (void) +{ + printf("Map_NoMAD1LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + map_index(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + map_index(0xf0, 0xff, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_JumboLoROMMap (void) +{ + // XXX: Which game uses this? + printf("Map_JumboLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0); + map_lorom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_ROM24MBSLoROMMap (void) +{ + // PCB: BSC-1A5M-01, BSC-1A7M-10 + printf("Map_ROM24MBSLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0); + map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000); + map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x100000, 0x200000); + map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SRAM512KLoROMMap (void) +{ + printf("Map_SRAM512KLoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + map_space(0x70, 0x70, 0x0000, 0xffff, SRAM); + map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x8000); + map_space(0x72, 0x72, 0x0000, 0xffff, SRAM + 0x10000); + map_space(0x73, 0x73, 0x0000, 0xffff, SRAM + 0x18000); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SufamiTurboLoROMMap (void) +{ + printf("Map_SufamiTurboLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + + if (Multi.sramSizeA) + { + map_index(0x60, 0x63, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + map_index(0xe0, 0xe3, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + } + + if (Multi.sramSizeB) + { + map_index(0x70, 0x73, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM); + map_index(0xf0, 0xf3, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM); + } + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SufamiTurboPseudoLoROMMap (void) +{ + // for combined images + printf("Map_SufamiTurboPseudoLoROMMap\n"); + map_System(); + + map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000); + map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, 0x100000, 0x200000); + map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0); + map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000); + map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, 0x100000, 0x200000); + + // I don't care :P + map_space(0x60, 0x63, 0x8000, 0xffff, SRAM - 0x8000); + map_space(0xe0, 0xe3, 0x8000, 0xffff, SRAM - 0x8000); + map_space(0x70, 0x73, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000); + map_space(0xf0, 0xf3, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SuperFXLoROMMap (void) +{ + printf("Map_SuperFXLoROMMap\n"); + map_System(); + + // Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K + // block is repeated twice in each 64K block. + for (int c = 0; c < 64; c++) + { + memmove(&ROM[0x200000 + c * 0x10000], &ROM[c * 0x8000], 0x8000); + memmove(&ROM[0x208000 + c * 0x10000], &ROM[c * 0x8000], 0x8000); + } + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); + + map_space(0x00, 0x3f, 0x6000, 0x7fff, SRAM - 0x6000); + map_space(0x80, 0xbf, 0x6000, 0x7fff, SRAM - 0x6000); + map_space(0x70, 0x70, 0x0000, 0xffff, SRAM); + map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x10000); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SetaDSPLoROMMap (void) +{ + printf("Map_SetaDSPLoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x40, 0x7f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_lorom(0xc0, 0xff, 0x8000, 0xffff, CalculatedSize); + + map_SetaDSP(); + + map_LoROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SDD1LoROMMap (void) +{ + printf("Map_SDD1LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); // will be overwritten dynamically + + map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM); + + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SA1LoROMMap (void) +{ + printf("Map_SA1LoROMMap\n"); + map_System(); + + map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); + + map_space(0x00, 0x3f, 0x3000, 0x3fff, FillRAM); + map_space(0x80, 0xbf, 0x3000, 0x3fff, FillRAM); + map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O); + map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O); + + for (int c = 0x40; c < 0x80; c++) + map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000); + + map_WRAM(); + + map_WriteProtectROM(); + + // Now copy the map and correct it for the SA1 CPU. + memmove((void *) SA1.Map, (void *) Map, sizeof(Map)); + memmove((void *) SA1.WriteMap, (void *) WriteMap, sizeof(WriteMap)); + + // SA-1 Banks 00->3f and 80->bf + for (int c = 0x000; c < 0x400; c += 0x10) + { + SA1.Map[c + 0] = SA1.Map[c + 0x800] = FillRAM + 0x3000; + SA1.Map[c + 1] = SA1.Map[c + 0x801] = (uint8 *) MAP_NONE; + SA1.WriteMap[c + 0] = SA1.WriteMap[c + 0x800] = FillRAM + 0x3000; + SA1.WriteMap[c + 1] = SA1.WriteMap[c + 0x801] = (uint8 *) MAP_NONE; + } + + // SA-1 Banks 60->6f + for (int c = 0x600; c < 0x700; c++) + SA1.Map[c] = SA1.WriteMap[c] = (uint8 *) MAP_BWRAM_BITMAP; + + BWRAM = SRAM; +} + +void CMemory::Map_HiROMMap (void) +{ + printf("Map_HiROMMap\n"); + map_System(); + + map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize); + map_hirom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize); + map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize); + map_hirom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize); + + if (Settings.DSP) + map_DSP(); + + map_HiROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_ExtendedHiROMMap (void) +{ + printf("Map_ExtendedHiROMMap\n"); + map_System(); + + map_hirom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000); + map_hirom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0); + map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0); + + map_HiROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SameGameHiROMMap (void) +{ + printf("Map_SameGameHiROMMap\n"); + map_System(); + + map_hirom_offset(0x00, 0x1f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0x40, 0x5f, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0x60, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0x80, 0x9f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + map_hirom_offset(0xc0, 0xdf, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA); + map_hirom_offset(0xe0, 0xff, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB); + + map_HiROMSRAM(); + map_WRAM(); + + map_WriteProtectROM(); +} + +void CMemory::Map_SPC7110HiROMMap (void) +{ + printf("Map_SPC7110HiROMMap\n"); + map_System(); + + map_index(0x00, 0x00, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); + map_hirom(0x00, 0x0f, 0x8000, 0xffff, CalculatedSize); + map_index(0x30, 0x30, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); + map_index(0x50, 0x50, 0x0000, 0xffff, MAP_SPC7110_DRAM, MAP_TYPE_ROM); + map_hirom(0x80, 0x8f, 0x8000, 0xffff, CalculatedSize); + map_hirom_offset(0xc0, 0xcf, 0x0000, 0xffff, CalculatedSize, 0); + map_index(0xd0, 0xff, 0x0000, 0xffff, MAP_SPC7110_ROM, MAP_TYPE_ROM); + + map_WRAM(); + + map_WriteProtectROM(); +} + +// checksum + +uint16 CMemory::checksum_calc_sum (uint8 *data, uint32 length) +{ + uint16 sum = 0; + + for (uint32 i = 0; i < length; i++) + sum += data[i]; + + return (sum); +} + +uint16 CMemory::checksum_mirror_sum (uint8 *start, uint32 &length, uint32 mask) +{ + // from NSRT + while (!(length & mask)) + mask >>= 1; + + uint16 part1 = checksum_calc_sum(start, mask); + uint16 part2 = 0; + + uint32 next_length = length - mask; + if (next_length) + { + part2 = checksum_mirror_sum(start + mask, next_length, mask >> 1); + + while (next_length < mask) + { + next_length += next_length; + part2 += part2; + } + + length = mask + mask; + } + + return (part1 + part2); +} + +void CMemory::Checksum_Calculate (void) +{ + // from NSRT + uint16 sum = 0; + + if (Settings.BS && !Settings.BSXItself) + sum = checksum_calc_sum(ROM, CalculatedSize) - checksum_calc_sum(ROM + (HiROM ? 0xffb0 : 0x7fb0), 48); + else + if (Settings.SPC7110) + { + sum = checksum_calc_sum(ROM, CalculatedSize); + if (CalculatedSize == 0x300000) + sum += sum; + } + else + { + if (CalculatedSize & 0x7fff) + sum = checksum_calc_sum(ROM, CalculatedSize); + else + { + uint32 length = CalculatedSize; + sum = checksum_mirror_sum(ROM, length); + } + } + + CalculatedChecksum = sum; +} + +// information + +const char * CMemory::MapType (void) +{ + return (HiROM ? ((ExtendedFormat != NOPE) ? "ExHiROM": "HiROM") : "LoROM"); +} + +const char * CMemory::StaticRAMSize (void) +{ + static char str[20]; + + if (SRAMSize > 16) + strcpy(str, "Corrupt"); + else + sprintf(str, "%dKbits", 8 * (SRAMMask + 1) / 1024); + + return (str); +} + +const char * CMemory::Size (void) +{ + static char str[20]; + + if (Multi.cartType == 4) + strcpy(str, "N/A"); + else + if (ROMSize < 7 || ROMSize - 7 > 23) + strcpy(str, "Corrupt"); + else + sprintf(str, "%dMbits", 1 << (ROMSize - 7)); + + return (str); +} + +const char * CMemory::Revision (void) +{ + static char str[20]; + + sprintf(str, "1.%d", HiROM ? ((ExtendedFormat != NOPE) ? ROM[0x40ffdb] : ROM[0xffdb]) : ROM[0x7fdb]); + + return (str); +} + +const char * CMemory::KartContents (void) +{ + static char str[64]; + static const char *contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" }; + + char chip[16]; + + if (ROMType == 0 && !Settings.BS) + return ("ROM"); + + if (Settings.BS) + strcpy(chip, "+BS"); + else + if (Settings.SuperFX) + strcpy(chip, "+Super FX"); + else + if (Settings.SDD1) + strcpy(chip, "+S-DD1"); + else + if (Settings.OBC1) + strcpy(chip, "+OBC1"); + else + if (Settings.SA1) + strcpy(chip, "+SA-1"); + else + if (Settings.SPC7110RTC) + strcpy(chip, "+SPC7110+RTC"); + else + if (Settings.SPC7110) + strcpy(chip, "+SPC7110"); + else + if (Settings.SRTC) + strcpy(chip, "+S-RTC"); + else + if (Settings.C4) + strcpy(chip, "+C4"); + else + if (Settings.SETA == ST_010) + strcpy(chip, "+ST-010"); + else + if (Settings.SETA == ST_011) + strcpy(chip, "+ST-011"); + else + if (Settings.SETA == ST_018) + strcpy(chip, "+ST-018"); + else + if (Settings.DSP) + sprintf(chip, "+DSP-%d", Settings.DSP); + else + strcpy(chip, ""); + + sprintf(str, "%s%s", contents[(ROMType & 0xf) % 3], chip); + + return (str); +} + +const char * CMemory::Country (void) +{ + switch (ROMRegion) + { + case 0: return("Japan"); + case 1: return("USA and Canada"); + case 2: return("Oceania, Europe and Asia"); + case 3: return("Sweden"); + case 4: return("Finland"); + case 5: return("Denmark"); + case 6: return("France"); + case 7: return("Holland"); + case 8: return("Spain"); + case 9: return("Germany, Austria and Switzerland"); + case 10: return("Italy"); + case 11: return("Hong Kong and China"); + case 12: return("Indonesia"); + case 13: return("South Korea"); + default: return("Unknown"); + } +} + +const char * CMemory::PublishingCompany (void) +{ + if (CompanyId >= (int) (sizeof(nintendo_licensees) / sizeof(nintendo_licensees[0])) || CompanyId < 0) + return ("Unknown"); + + if (nintendo_licensees[CompanyId] == NULL) + return ("Unknown"); + + return (nintendo_licensees[CompanyId]); +} + +void CMemory::MakeRomInfoText (char *romtext) +{ + char temp[256]; + + romtext[0] = 0; + + sprintf(temp, " Cart Name: %s", ROMName); + strcat(romtext, temp); + sprintf(temp, "\n Game Code: %s", ROMId); + strcat(romtext, temp); + sprintf(temp, "\n Contents: %s", KartContents()); + strcat(romtext, temp); + sprintf(temp, "\n Map: %s", MapType()); + strcat(romtext, temp); + sprintf(temp, "\n Speed: 0x%02X (%s)", ROMSpeed, (ROMSpeed & 0x10) ? "FastROM" : "SlowROM"); + strcat(romtext, temp); + sprintf(temp, "\n Type: 0x%02X", ROMType); + strcat(romtext, temp); + sprintf(temp, "\n Size (calculated): %dMbits", CalculatedSize / 0x20000); + strcat(romtext, temp); + sprintf(temp, "\n Size (header): %s", Size()); + strcat(romtext, temp); + sprintf(temp, "\n SRAM size: %s", StaticRAMSize()); + strcat(romtext, temp); + sprintf(temp, "\nChecksum (calculated): 0x%04X", CalculatedChecksum); + strcat(romtext, temp); + sprintf(temp, "\n Checksum (header): 0x%04X", ROMChecksum); + strcat(romtext, temp); + sprintf(temp, "\n Complement (header): 0x%04X", ROMComplementChecksum); + strcat(romtext, temp); + sprintf(temp, "\n Video Output: %s", (ROMRegion > 12 || ROMRegion < 2) ? "NTSC 60Hz" : "PAL 50Hz"); + strcat(romtext, temp); + sprintf(temp, "\n Revision: %s", Revision()); + strcat(romtext, temp); + sprintf(temp, "\n Licensee: %s", PublishingCompany()); + strcat(romtext, temp); + sprintf(temp, "\n Region: %s", Country()); + strcat(romtext, temp); + sprintf(temp, "\n CRC32: 0x%08X", ROMCRC32); + strcat(romtext, temp); +} + +// hack + +bool8 CMemory::match_na (const char *str) +{ + return (strcmp(ROMName, str) == 0); +} + +bool8 CMemory::match_nn (const char *str) +{ + return (strncmp(ROMName, str, strlen(str)) == 0); +} + +bool8 CMemory::match_nc (const char *str) +{ + return (strncasecmp(ROMName, str, strlen(str)) == 0); +} + +bool8 CMemory::match_id (const char *str) +{ + return (strncmp(ROMId, str, strlen(str)) == 0); +} + +void CMemory::ApplyROMFixes (void) +{ + Settings.Shutdown = Settings.ShutdownMaster; + Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster; + + //// Warnings + + // Reject strange hacked games + if ((ROMCRC32 == 0x6810aa95) || + (ROMCRC32 == 0x340f23e5) || + (ROMCRC32 == 0x77fd806a) || + (match_nn("HIGHWAY BATTLE 2")) || + (match_na("FX SKIING NINTENDO 96") && (ROM[0x7fda] == 0)) || + (match_nn("HONKAKUHA IGO GOSEI") && (ROM[0xffd5] != 0x31))) + { + Settings.DisplayColor = BUILD_PIXEL(31, 0, 0); + SET_UI_COLOR(255, 0, 0); + } + + //// APU timing hacks :( + + Timings.APUSpeedup = 0; + + if (!Settings.DisableGameSpecificHacks) + { + if (match_id("AVCJ")) // Rendering Ranger R2 + Timings.APUSpeedup = 4; + + if (match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki + match_id("JG ") || // Illusion of Gaia + match_id("CQ ") || // Stunt Race FX + match_na("SOULBLADER - 1") || // Soul Blader + match_na("SOULBLAZER - 1 USA") || // Soul Blazer + match_na("SLAP STICK 1 JPN") || // Slap Stick + match_id("E9 ") || // Robotrek + match_nn("ACTRAISER") || // Actraiser + match_nn("ActRaiser-2") || // Actraiser 2 + match_id("AQT") || // Tenchi Souzou, Terranigma + match_id("ATV") || // Tales of Phantasia + match_id("ARF") || // Star Ocean + match_id("APR") || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan + match_id("A4B") || // Super Bomberman 4 + match_id("Y7 ") || // U.F.O. Kamen Yakisoban - Present Ban + match_id("Y9 ") || // U.F.O. Kamen Yakisoban - Shihan Ban + match_id("APB") || // Super Bomberman - Panic Bomber W + match_na("DARK KINGDOM") || // Dark Kingdom + match_na("ZAN3 SFC") || // Zan III Spirits + match_na("HIOUDEN") || // Hiouden - Mamono-tachi Tono Chikai + match_na("\xC3\xDD\xBC\xC9\xB3\xC0") || // Tenshi no Uta + match_na("FORTUNE QUEST") || // Fortune Quest - Dice wo Korogase + match_na("FISHING TO BASSING") || // Shimono Masaki no Fishing To Bassing + match_na("OHMONO BLACKBASS") || // Oomono Black Bass Fishing - Jinzouko Hen + match_na("MASTERS") || // Harukanaru Augusta 2 - Masters + match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0") || // Kamen Rider + match_na("ZENKI TENCHIMEIDOU") || // Kishin Douji Zenki - Tenchi Meidou + match_nn("TokyoDome '95Battle 7") || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7 + match_nn("SWORD WORLD SFC") || // Sword World SFC/2 + match_nn("LETs PACHINKO(") || // BS Lets Pachinko Nante Gindama 1/2/3/4 + match_nn("THE FISHING MASTER") || // Mark Davis The Fishing Master + match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5 + match_na("HEIWA Parlor!Mini8") || // Parlor mini 8 + match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever! + Timings.APUSpeedup = 1; + } + + S9xAPUTimingSetSpeedup(Timings.APUSpeedup); + + //// Other timing hacks :( + + Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100; + Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC; + + if (!Settings.DisableGameSpecificHacks) + { + // The HC counter (CPU.Cycles for snes9x) passes over the WRAM refresh point (HC~536) + // while preparing to jump to the IRQ vector address. + // That is to say, the WRAM refresh point is passed over in S9xOpcode_IRQ(). + // Then, HDMA starts just after $210e is half updated, and it causes the flicker of the ground. + // IRQ timing is bad? HDMA timing is bad? else? + if (match_na("GUNDAMW ENDLESSDUEL")) // Shin Kidou Senki Gundam W - Endless Duel + { + Timings.HDMAStart -= 10; + Timings.HBlankStart -= 10; + printf("HDMA timing hack: %d\n", Timings.HDMAStart); + } + + // Due to Snes9x's very inaccurate timings, + // HDMA transfer to $210D-$2114 between the first and second writings to the same addresses. + if (match_na("POWER RANGERS FIGHT")) // Mighty Morphin Power Rangers - The Fighting Edition + { + Timings.HDMAStart -= 10; + Timings.HBlankStart -= 10; + printf("HDMA timing hack: %d\n", Timings.HDMAStart); + } + + if (match_na("SFX SUPERBUTOUDEN2")) // Dragon Ball Z - Super Butouden 2 + { + Timings.HDMAStart += 20; + Timings.HBlankStart += 20; + printf("HDMA timing hack: %d\n", Timings.HDMAStart); + } + } + + if (!Settings.DisableGameSpecificHacks) + { + // The delay to sync CPU and DMA which Snes9x cannot emulate. + // Some games need really severe delay timing... + if (match_na("BATTLE GRANDPRIX")) // Battle Grandprix + { + Timings.DMACPUSync = 20; + printf("DMA sync: %d\n", Timings.DMACPUSync); + } + } + + if (!Settings.DisableGameSpecificHacks) + { + // Opcode-based emulators cannot escape from "reading $4211/BPL" infinite loop... + // The true IRQ can be triggered inside an opcode. + if (match_na("TRAVERSE")) // Traverse - Starlight & Prairie + { + Timings.IRQPendCount = 1; + printf("IRQ count hack: %d\n", Timings.IRQPendCount); + } + + // An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0. + // If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further. + // If Snes9x jumps into the IRQ handler before escaping from the loop, + // Snes9x cannot escape from the loop permanently because the RTI is in the next V-blank. + if (match_na("Aero the AcroBat 2")) + { + Timings.IRQPendCount = 2; + printf("IRQ count hack: %d\n", Timings.IRQPendCount); + } + } + + if (!Settings.DisableGameSpecificHacks) + { + // XXX: What's happening? + if (match_na("X-MEN")) // Spider-Man and the X-Men + { + Settings.BlockInvalidVRAMAccess = FALSE; + printf("Invalid VRAM access hack\n"); + } + } + + //// CPU speed-ups (CPU_Shutdown()) + + // Force disabling a speed-up hack + // Games which spool sound samples between the SNES and sound CPU using + // H-DMA as the sample is playing. + if (match_na("EARTHWORM JIM 2") || // Earth Worm Jim 2 + match_na("PRIMAL RAGE") || // Primal Rage + match_na("CLAY FIGHTER") || // Clay Fighter + match_na("ClayFighter 2") || // Clay Fighter 2 + match_na("WeaponLord") || // Weapon Lord + match_nn("WAR 2410") || // War 2410 + match_id("ARF") || // Star Ocean + match_id("A4WJ") || // Mini Yonku Shining Scorpion - Let's & Go!! + match_nn("NHL") || + match_nc("MADDEN")) + { + if (Settings.Shutdown) + printf("Disabled CPU shutdown hack.\n"); + Settings.Shutdown = FALSE; + } + + // SA-1 + SA1.WaitAddress = 0xffffffff; + SA1.WaitByteAddress1 = NULL; + SA1.WaitByteAddress2 = NULL; + + if (Settings.SA1) + { + // Itoi Shigesato no Bass Tsuri No.1 (J) + if (match_id("ZBPJ")) + { + SA1.WaitAddress = 0x0093f1; + SA1.WaitByteAddress1 = FillRAM + 0x304a; + } + + // Daisenryaku Expert WWII (J) + if (match_id("AEVJ")) + { + SA1.WaitAddress = 0x0ed18d; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + + // Derby Jockey 2 (J) + if (match_id("A2DJ")) + { + SA1.WaitAddress = 0x008b62; + } + + // Dragon Ball Z - Hyper Dimension (J) + if (match_id("AZIJ")) + { + SA1.WaitAddress = 0x008083; + SA1.WaitByteAddress1 = FillRAM + 0x3020; + } + + // SD Gundam G NEXT (J) + if (match_id("ZX3J")) + { + SA1.WaitAddress = 0x0087f2; + SA1.WaitByteAddress1 = FillRAM + 0x30c4; + } + + // Shougi no Hanamichi (J) + if (match_id("AARJ")) + { + SA1.WaitAddress = 0xc1f85a; + SA1.WaitByteAddress1 = SRAM + 0x0c64; + SA1.WaitByteAddress2 = SRAM + 0x0c66; + } + + // Asahi Shinbun Rensai Katou Hifumi Kudan Shougi Shingiryu (J) + if (match_id("A23J")) + { + SA1.WaitAddress = 0xc25037; + SA1.WaitByteAddress1 = SRAM + 0x0c06; + SA1.WaitByteAddress2 = SRAM + 0x0c08; + } + + // Taikyoku Igo - Idaten (J) + if (match_id("AIIJ")) + { + SA1.WaitAddress = 0xc100be; + SA1.WaitByteAddress1 = SRAM + 0x1002; + SA1.WaitByteAddress2 = SRAM + 0x1004; + } + + // Takemiya Masaki Kudan no Igo Taishou (J) + if (match_id("AITJ")) + { + SA1.WaitAddress = 0x0080b7; + } + + // J. League '96 Dream Stadium (J) + if (match_id("AJ6J")) + { + SA1.WaitAddress = 0xc0f74a; + } + + // Jumpin' Derby (J) + if (match_id("AJUJ")) + { + SA1.WaitAddress = 0x00d926; + } + + // Kakinoki Shougi (J) + if (match_id("AKAJ")) + { + SA1.WaitAddress = 0x00f070; + } + + // Hoshi no Kirby 3 (J), Kirby's Dream Land 3 (U) + if (match_id("AFJJ") || match_id("AFJE")) + { + SA1.WaitAddress = 0x0082d4; + SA1.WaitByteAddress1 = SRAM + 0x72a4; + } + + // Hoshi no Kirby - Super Deluxe (J) + if (match_id("AKFJ")) + { + SA1.WaitAddress = 0x008c93; + SA1.WaitByteAddress1 = FillRAM + 0x300a; + SA1.WaitByteAddress2 = FillRAM + 0x300e; + } + + // Kirby Super Star (U) + if (match_id("AKFE")) + { + SA1.WaitAddress = 0x008cb8; + SA1.WaitByteAddress1 = FillRAM + 0x300a; + SA1.WaitByteAddress2 = FillRAM + 0x300e; + } + + // Super Mario RPG (J), (U) + if (match_id("ARWJ") || match_id("ARWE")) + { + SA1.WaitAddress = 0xc0816f; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + + // Marvelous (J) + if (match_id("AVRJ")) + { + SA1.WaitAddress = 0x0085f2; + SA1.WaitByteAddress1 = FillRAM + 0x3024; + } + + // Harukanaru Augusta 3 - Masters New (J) + if (match_id("AO3J")) + { + SA1.WaitAddress = 0x00dddb; + SA1.WaitByteAddress1 = FillRAM + 0x37b4; + } + + // Jikkyou Oshaberi Parodius (J) + if (match_id("AJOJ")) + { + SA1.WaitAddress = 0x8084e5; + } + + // Super Bomberman - Panic Bomber W (J) + if (match_id("APBJ")) + { + SA1.WaitAddress = 0x00857a; + } + + // Pebble Beach no Hatou New - Tournament Edition (J) + if (match_id("AONJ")) + { + SA1.WaitAddress = 0x00df33; + SA1.WaitByteAddress1 = FillRAM + 0x37b4; + } + + // PGA European Tour (U) + if (match_id("AEPE")) + { + SA1.WaitAddress = 0x003700; + SA1.WaitByteAddress1 = FillRAM + 0x3102; + } + + // PGA Tour 96 (U) + if (match_id("A3GE")) + { + SA1.WaitAddress = 0x003700; + SA1.WaitByteAddress1 = FillRAM + 0x3102; + } + + // Power Rangers Zeo - Battle Racers (U) + if (match_id("A4RE")) + { + SA1.WaitAddress = 0x009899; + SA1.WaitByteAddress1 = FillRAM + 0x3000; + } + + // SD F-1 Grand Prix (J) + if (match_id("AGFJ")) + { + SA1.WaitAddress = 0x0181bc; + } + + // Saikousoku Shikou Shougi Mahjong (J) + if (match_id("ASYJ")) + { + SA1.WaitAddress = 0x00f2cc; + SA1.WaitByteAddress1 = SRAM + 0x7ffe; + SA1.WaitByteAddress2 = SRAM + 0x7ffc; + } + + // Shougi Saikyou II (J) + if (match_id("AX2J")) + { + SA1.WaitAddress = 0x00d675; + } + + // Mini Yonku Shining Scorpion - Let's & Go!! (J) + if (match_id("A4WJ")) + { + SA1.WaitAddress = 0xc048be; + } + + // Shin Shougi Club (J) + if (match_id("AHJJ")) + { + SA1.WaitAddress = 0xc1002a; + SA1.WaitByteAddress1 = SRAM + 0x0806; + SA1.WaitByteAddress2 = SRAM + 0x0808; + } + + // rest games: + // Habu Meijin no Omoshiro Shougi (J) + // Hayashi Kaihou Kudan no Igo Taidou (J) + // Shougi Saikyou (J) + // Super Robot Wars Gaiden (J) + // Super Shougi 3 - Kitaihei (J) + } + + //// SRAM initial value + + if (!Settings.DisableGameSpecificHacks) + { + if (match_na("HITOMI3")) + { + SRAMSize = 1; + SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1; + } + + // SRAM value fixes + if (match_na("SUPER DRIFT OUT") || // Super Drift Out + match_na("SATAN IS OUR FATHER!") || + match_na("goemon 4")) // Ganbare Goemon Kirakira Douchuu + SNESGameFixes.SRAMInitialValue = 0x00; + + // Additional game fixes by sanmaiwashi ... + // XXX: unnecessary? + if (match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari + SNESGameFixes.SRAMInitialValue = 0x6b; + + // others: BS and ST-01x games are 0x00. + } + + //// OAM hacks :( + + if (!Settings.DisableGameSpecificHacks) + { + // OAM hacks because we don't fully understand the behavior of the SNES. + // Totally wacky display in 2P mode... + // seems to need a disproven behavior, so we're definitely overlooking some other bug? + if (match_nn("UNIRACERS")) // Uniracers + { + SNESGameFixes.Uniracers = TRUE; + printf("Applied Uniracers hack.\n"); + } + } +} + +// UPS % IPS + +static uint32 ReadUPSPointer (const uint8 *data, unsigned &addr, unsigned size) +{ + uint32 offset = 0, shift = 1; + while(addr < size) { + uint8 x = data[addr++]; + offset += (x & 0x7f) * shift; + if(x & 0x80) break; + shift <<= 7; + offset += shift; + } + return offset; +} + +//NOTE: UPS patches are *never* created against a headered ROM! +//this is per the UPS file specification. however, do note that it is +//technically possible for a non-compliant patcher to ignore this requirement. +//therefore, it is *imperative* that no emulator support such patches. +//thusly, we ignore the "long offset" parameter below. failure to do so would +//completely invalidate the purpose of UPS; which is to avoid header vs +//no-header patching errors that result in IPS patches having a 50/50 chance of +//being applied correctly. + +static bool8 ReadUPSPatch (Reader *r, long, int32 &rom_size) +{ + //Reader lacks size() and rewind(), so we need to read in the file to get its size + uint8 *data = new uint8[8 * 1024 * 1024]; //allocate a lot of memory, better safe than sorry ... + uint32 size = 0; + while(true) { + int value = r->get_char(); + if(value == EOF) break; + data[size++] = value; + if(size >= 8 * 1024 * 1024) { + //prevent buffer overflow: SNES-made UPS patches should never be this big anyway ... + delete[] data; + return false; + } + } + + //4-byte header + 1-byte input size + 1-byte output size + 4-byte patch CRC32 + 4-byte unpatched CRC32 + 4-byte patched CRC32 + if(size < 18) { delete[] data; return false; } //patch is too small + + uint32 addr = 0; + if(data[addr++] != 'U') { delete[] data; return false; } //patch has an invalid header + if(data[addr++] != 'P') { delete[] data; return false; } //... + if(data[addr++] != 'S') { delete[] data; return false; } //... + if(data[addr++] != '1') { delete[] data; return false; } //... + + uint32 patch_crc32 = caCRC32(data, size - 4); //don't include patch CRC32 itself in CRC32 calculation + uint32 rom_crc32 = caCRC32(Memory.ROM, rom_size); + uint32 px_crc32 = (data[size - 12] << 0) + (data[size - 11] << 8) + (data[size - 10] << 16) + (data[size - 9] << 24); + uint32 py_crc32 = (data[size - 8] << 0) + (data[size - 7] << 8) + (data[size - 6] << 16) + (data[size - 5] << 24); + uint32 pp_crc32 = (data[size - 4] << 0) + (data[size - 3] << 8) + (data[size - 2] << 16) + (data[size - 1] << 24); + if(patch_crc32 != pp_crc32) { delete[] data; return false; } //patch is corrupted + if((rom_crc32 != px_crc32) && (rom_crc32 != py_crc32)) { delete[] data; return false; } //patch is for a different ROM + + uint32 px_size = ReadUPSPointer(data, addr, size); + uint32 py_size = ReadUPSPointer(data, addr, size); + uint32 out_size = ((uint32) rom_size == px_size) ? py_size : px_size; + if(out_size > CMemory::MAX_ROM_SIZE) { delete[] data; return false; } //applying this patch will overflow Memory.ROM buffer + + //fill expanded area with 0x00s; so that XORing works as expected below. + //note that this is needed (and works) whether output ROM is larger or smaller than pre-patched ROM + for(unsigned i = min((uint32) rom_size, out_size); i < max((uint32) rom_size, out_size); i++) { + Memory.ROM[i] = 0x00; + } + + uint32 relative = 0; + while(addr < size - 12) { + relative += ReadUPSPointer(data, addr, size); + while(addr < size - 12) { + uint8 x = data[addr++]; + Memory.ROM[relative++] ^= x; + if(!x) break; + } + } + + rom_size = out_size; + delete[] data; + + uint32 out_crc32 = caCRC32(Memory.ROM, rom_size); + if(((rom_crc32 == px_crc32) && (out_crc32 == py_crc32)) + || ((rom_crc32 == py_crc32) && (out_crc32 == px_crc32)) + ) { + return true; + } else { + //technically, reaching here means that patching has failed. + //we should return false, but unfortunately Memory.ROM has already + //been modified above and cannot be undone. to do this properly, we + //would need to make a copy of Memory.ROM, apply the patch, and then + //copy that back to Memory.ROM. + // + //however, the only way for this case to happen is if the UPS patch file + //itself is corrupted, which should be detected by the patch CRC32 check + //above anyway. errors due to the wrong ROM or patch file being used are + //already caught above. + fprintf(stderr, "WARNING: UPS patching appears to have failed.\nGame may not be playable.\n"); + return true; + } +} + +static long ReadInt (Reader *r, unsigned nbytes) +{ + long v = 0; + + while (nbytes--) + { + int c = r->get_char(); + if (c == EOF) + return (-1); + v = (v << 8) | (c & 0xFF); + } + + return (v); +} + +static bool8 ReadIPSPatch (Reader *r, long offset, int32 &rom_size) +{ + const int32 IPS_EOF = 0x00454F46l; + int32 ofs; + char fname[6]; + + fname[5] = 0; + for (int i = 0; i < 5; i++) + { + int c = r->get_char(); + if (c == EOF) + return (0); + fname[i] = (char) c; + } + + if (strncmp(fname, "PATCH", 5)) + return (0); + + for (;;) + { + long len, rlen; + int rchar; + + ofs = ReadInt(r, 3); + if (ofs == -1) + return (0); + + if (ofs == IPS_EOF) + break; + + ofs -= offset; + + len = ReadInt(r, 2); + if (len == -1) + return (0); + + if (len) + { + if (ofs + len > CMemory::MAX_ROM_SIZE) + return (0); + + while (len--) + { + rchar = r->get_char(); + if (rchar == EOF) + return (0); + Memory.ROM[ofs++] = (uint8) rchar; + } + + if (ofs > rom_size) + rom_size = ofs; + } + else + { + rlen = ReadInt(r, 2); + if (rlen == -1) + return (0); + + rchar = r->get_char(); + if (rchar == EOF) + return (0); + + if (ofs + rlen > CMemory::MAX_ROM_SIZE) + return (0); + + while (rlen--) + Memory.ROM[ofs++] = (uint8) rchar; + + if (ofs > rom_size) + rom_size = ofs; + } + } + + ofs = ReadInt(r, 3); + if (ofs != -1 && ofs - offset < rom_size) + rom_size = ofs - offset; + + return (1); +} + +#ifdef UNZIP_SUPPORT +static int unzFindExtension (unzFile &file, const char *ext, bool restart, bool print) +{ + unz_file_info info; + int port, l = strlen(ext); + + if (restart) + port = unzGoToFirstFile(file); + else + port = unzGoToNextFile(file); + + while (port == UNZ_OK) + { + int len; + char name[132]; + + unzGetCurrentFileInfo(file, &info, name, 128, NULL, 0, NULL, 0); + len = strlen(name); + + if (len >= l + 1 && name[len - l - 1] == '.' && strcasecmp(name + len - l, ext) == 0 && unzOpenCurrentFile(file) == UNZ_OK) + { + if (print) + printf("Using IPS or UPS patch %s", name); + + return (port); + } + + port = unzGoToNextFile(file); + } + + return (port); +} +#endif + +void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &rom_size) +{ + if (Settings.NoPatch) + return; + + STREAM patch_file = NULL; + uint32 i; + long offset = header ? 512 : 0; + int ret; + bool flag; + char dir[_MAX_DIR + 1], drive[_MAX_DRIVE + 1], name[_MAX_FNAME + 1], ext[_MAX_EXT + 1], ips[_MAX_EXT + 3], fname[PATH_MAX + 1]; + const char *n; + + // UPS + + _splitpath(rom_filename, drive, dir, name, ext); + _makepath(fname, drive, dir, name, "ups"); + + if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) + { + printf("Using UPS patch %s", fname); + + ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + return; + } + else + printf(" failed!\n"); + } + +#ifdef UNZIP_SUPPORT + if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip")) + { + unzFile file = unzOpen(rom_filename); + if (file) + { + int port = unzFindExtension(file, "ups"); + if (port == UNZ_OK) + { + printf(" in %s", rom_filename); + + ret = ReadUPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + printf("!\n"); + else + printf(" failed!\n"); + } + } + } +#endif + + n = S9xGetFilename(".ups", IPS_DIR); + + if ((patch_file = OPEN_STREAM(n, "rb")) != NULL) + { + printf("Using UPS patch %s", n); + + ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + return; + } + else + printf(" failed!\n"); + } + + // IPS + + _splitpath(rom_filename, drive, dir, name, ext); + _makepath(fname, drive, dir, name, "ips"); + + if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL) + { + printf("Using IPS patch %s", fname); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + return; + } + else + printf(" failed!\n"); + } + + if (_MAX_EXT > 6) + { + i = 0; + flag = false; + + do + { + snprintf(ips, 8, "%03d.ips", i); + _makepath(fname, drive, dir, name, ips); + + if (!(patch_file = OPEN_STREAM(fname, "rb"))) + break; + + printf("Using IPS patch %s", fname); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i < 1000); + + if (flag) + return; + } + + if (_MAX_EXT > 3) + { + i = 0; + flag = false; + + do + { + snprintf(ips, _MAX_EXT + 2, "ips%d", i); + if (strlen(ips) > _MAX_EXT) + break; + _makepath(fname, drive, dir, name, ips); + + if (!(patch_file = OPEN_STREAM(fname, "rb"))) + break; + + printf("Using IPS patch %s", fname); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i != 0); + + if (flag) + return; + } + + if (_MAX_EXT > 2) + { + i = 0; + flag = false; + + do + { + snprintf(ips, 4, "ip%d", i); + _makepath(fname, drive, dir, name, ips); + + if (!(patch_file = OPEN_STREAM(fname, "rb"))) + break; + + printf("Using IPS patch %s", fname); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i < 10); + + if (flag) + return; + } + +#ifdef UNZIP_SUPPORT + if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip")) + { + unzFile file = unzOpen(rom_filename); + if (file) + { + int port = unzFindExtension(file, "ips"); + while (port == UNZ_OK) + { + printf(" in %s", rom_filename); + + ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + printf(" failed!\n"); + + port = unzFindExtension(file, "ips", false); + } + + if (!flag) + { + i = 0; + + do + { + snprintf(ips, 8, "%03d.ips", i); + + if (unzFindExtension(file, ips) != UNZ_OK) + break; + + printf(" in %s", rom_filename); + + ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + + if (unzFindExtension(file, ips, false, false) == UNZ_OK) + printf("WARNING: Ignoring extra .%s files!\n", ips); + } while (++i < 1000); + } + + if (!flag) + { + i = 0; + + do + { + snprintf(ips, _MAX_EXT + 2, "ips%d", i); + if (strlen(ips) > _MAX_EXT) + break; + + if (unzFindExtension(file, ips) != UNZ_OK) + break; + + printf(" in %s", rom_filename); + + ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + + if (unzFindExtension(file, ips, false, false) == UNZ_OK) + printf("WARNING: Ignoring extra .%s files!\n", ips); + } while (++i != 0); + } + + if (!flag) + { + i = 0; + + do + { + snprintf(ips, 4, "ip%d", i); + + if (unzFindExtension(file, ips) != UNZ_OK) + break; + + printf(" in %s", rom_filename); + + ret = ReadIPSPatch(new unzReader(file), offset, rom_size); + unzCloseCurrentFile(file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + + if (unzFindExtension(file, ips, false, false) == UNZ_OK) + printf("WARNING: Ignoring extra .%s files!\n", ips); + } while (++i < 10); + } + + assert(unzClose(file) == UNZ_OK); + + if (flag) + return; + } + } +#endif + + n = S9xGetFilename(".ips", IPS_DIR); + + if ((patch_file = OPEN_STREAM(n, "rb")) != NULL) + { + printf("Using IPS patch %s", n); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + return; + } + else + printf(" failed!\n"); + } + + if (_MAX_EXT > 6) + { + i = 0; + flag = false; + + do + { + snprintf(ips, 9, ".%03d.ips", i); + n = S9xGetFilename(ips, IPS_DIR); + + if (!(patch_file = OPEN_STREAM(n, "rb"))) + break; + + printf("Using IPS patch %s", n); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i < 1000); + + if (flag) + return; + } + + if (_MAX_EXT > 3) + { + i = 0; + flag = false; + + do + { + snprintf(ips, _MAX_EXT + 3, ".ips%d", i); + if (strlen(ips) > _MAX_EXT + 1) + break; + n = S9xGetFilename(ips, IPS_DIR); + + if (!(patch_file = OPEN_STREAM(n, "rb"))) + break; + + printf("Using IPS patch %s", n); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i != 0); + + if (flag) + return; + } + + if (_MAX_EXT > 2) + { + i = 0; + flag = false; + + do + { + snprintf(ips, 5, ".ip%d", i); + n = S9xGetFilename(ips, IPS_DIR); + + if (!(patch_file = OPEN_STREAM(n, "rb"))) + break; + + printf("Using IPS patch %s", n); + + ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size); + CLOSE_STREAM(patch_file); + + if (ret) + { + printf("!\n"); + flag = true; + } + else + { + printf(" failed!\n"); + break; + } + } while (++i < 10); + + if (flag) + return; + } +} diff --git a/memmap.h b/memmap.h new file mode 100644 index 00000000..561cdccd --- /dev/null +++ b/memmap.h @@ -0,0 +1,389 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _MEMMAP_H_ +#define _MEMMAP_H_ + +#define MEMMAP_BLOCK_SIZE (0x1000) +#define MEMMAP_NUM_BLOCKS (0x1000000 / MEMMAP_BLOCK_SIZE) +#define MEMMAP_SHIFT (12) +#define MEMMAP_MASK (MEMMAP_BLOCK_SIZE - 1) + +struct CMemory +{ + enum + { MAX_ROM_SIZE = 0x800000 }; + + enum file_formats + { FILE_ZIP, FILE_JMA, FILE_DEFAULT }; + + enum + { NOPE, YEAH, BIGFIRST, SMALLFIRST }; + + enum + { MAP_TYPE_I_O, MAP_TYPE_ROM, MAP_TYPE_RAM }; + + enum + { + MAP_CPU, + MAP_PPU, + MAP_LOROM_SRAM, + MAP_LOROM_SRAM_B, + MAP_HIROM_SRAM, + MAP_DSP, + MAP_SA1RAM, + MAP_BWRAM, + MAP_BWRAM_BITMAP, + MAP_BWRAM_BITMAP2, + MAP_SPC7110_ROM, + MAP_SPC7110_DRAM, + MAP_RONLY_SRAM, + MAP_C4, + MAP_OBC_RAM, + MAP_SETA_DSP, + MAP_SETA_RISC, + MAP_BSX, + MAP_NONE, + MAP_LAST + }; + + uint8 NSRTHeader[32]; + int32 HeaderCount; + + uint8 *RAM; + uint8 *ROM; + uint8 *SRAM; + uint8 *VRAM; + uint8 *FillRAM; + uint8 *BWRAM; + uint8 *C4RAM; + uint8 *OBC1RAM; + uint8 *BSRAM; + uint8 *BIOSROM; + + uint8 *Map[MEMMAP_NUM_BLOCKS]; + uint8 *WriteMap[MEMMAP_NUM_BLOCKS]; + uint8 BlockIsRAM[MEMMAP_NUM_BLOCKS]; + uint8 BlockIsROM[MEMMAP_NUM_BLOCKS]; + uint8 MemorySpeed[MEMMAP_NUM_BLOCKS]; + uint8 ExtendedFormat; + + char ROMFilename[PATH_MAX + 1]; + char ROMName[ROM_NAME_LEN]; + char RawROMName[ROM_NAME_LEN]; + char ROMId[5]; + int32 CompanyId; + uint8 ROMRegion; + uint8 ROMSpeed; + uint8 ROMType; + uint8 ROMSize; + uint32 ROMChecksum; + uint32 ROMComplementChecksum; + uint32 ROMCRC32; + int32 ROMFramesPerSecond; + + bool8 HiROM; + bool8 LoROM; + uint8 SRAMSize; + uint32 SRAMMask; + uint32 CalculatedSize; + uint32 CalculatedChecksum; + + // ports can assign this to perform some custom action upon loading a ROM (such as adjusting controls) + void (*PostRomInitFunc) (void); + + bool8 Init (void); + void Deinit (void); + + int ScoreHiROM (bool8, int32 romoff = 0); + int ScoreLoROM (bool8, int32 romoff = 0); + uint32 HeaderRemove (uint32, int32 &, uint8 *); + uint32 FileLoader (uint8 *, const char *, int32); + bool8 LoadROM (const char *); + bool8 LoadMultiCart (const char *, const char *); + bool8 LoadSufamiTurbo (const char *, const char *); + bool8 LoadSameGame (const char *, const char *); + bool8 LoadSRAM (const char *); + bool8 SaveSRAM (const char *); + void ClearSRAM (bool8 onlyNonSavedSRAM = 0); + bool8 LoadSRTC (void); + bool8 SaveSRTC (void); + + char * Safe (const char *); + char * SafeANK (const char *); + void ParseSNESHeader (uint8 *); + void InitROM (void); + void FixROMSpeed (void); + void ResetSpeedMap (void); + + uint32 map_mirror (uint32, uint32); + void map_lorom (uint32, uint32, uint32, uint32, uint32); + void map_hirom (uint32, uint32, uint32, uint32, uint32); + void map_lorom_offset (uint32, uint32, uint32, uint32, uint32, uint32); + void map_hirom_offset (uint32, uint32, uint32, uint32, uint32, uint32); + void map_space (uint32, uint32, uint32, uint32, uint8 *); + void map_index (uint32, uint32, uint32, uint32, int, int); + void map_System (void); + void map_WRAM (void); + void map_LoROMSRAM (void); + void map_HiROMSRAM (void); + void map_DSP (void); + void map_C4 (void); + void map_OBC1 (void); + void map_SetaRISC (void); + void map_SetaDSP (void); + void map_WriteProtectROM (void); + void Map_Initialize (void); + void Map_LoROMMap (void); + void Map_NoMAD1LoROMMap (void); + void Map_JumboLoROMMap (void); + void Map_ROM24MBSLoROMMap (void); + void Map_SRAM512KLoROMMap (void); + void Map_SufamiTurboLoROMMap (void); + void Map_SufamiTurboPseudoLoROMMap (void); + void Map_SuperFXLoROMMap (void); + void Map_SetaDSPLoROMMap (void); + void Map_SDD1LoROMMap (void); + void Map_SA1LoROMMap (void); + void Map_HiROMMap (void); + void Map_ExtendedHiROMMap (void); + void Map_SameGameHiROMMap (void); + void Map_SPC7110HiROMMap (void); + + uint16 checksum_calc_sum (uint8 *, uint32); + uint16 checksum_mirror_sum (uint8 *, uint32 &, uint32 mask = 0x800000); + void Checksum_Calculate (void); + + bool8 match_na (const char *); + bool8 match_nn (const char *); + bool8 match_nc (const char *); + bool8 match_id (const char *); + void ApplyROMFixes (void); + void CheckForAnyPatch (const char *, bool8, int32 &); + + void MakeRomInfoText (char *); + + const char * MapType (void); + const char * StaticRAMSize (void); + const char * Size (void); + const char * Revision (void); + const char * KartContents (void); + const char * Country (void); + const char * PublishingCompany (void); +}; + +struct SMulti +{ + int cartType; + int32 cartSizeA, cartSizeB; + int32 sramSizeA, sramSizeB; + uint32 sramMaskA, sramMaskB; + uint32 cartOffsetA, cartOffsetB; + uint8 *sramA, *sramB; + char fileNameA[PATH_MAX + 1], fileNameB[PATH_MAX + 1]; +}; + +extern CMemory Memory; +extern SMulti Multi; + +#if defined(ZSNES_FX) || defined(ZSNES_C4) +START_EXTERN_C +extern uint8 *ROM; +extern uint8 *SRAM; +extern uint8 *RegRAM; +END_EXTERN_C +#endif + +void S9xAutoSaveSRAM (void); +bool8 LoadZip(const char *, int32 *, int32 *, uint8 *); + +enum s9xwrap_t +{ + WRAP_NONE, + WRAP_BANK, + WRAP_PAGE +}; + +enum s9xwriteorder_t +{ + WRITE_01, + WRITE_10 +}; + +#include "getset.h" + +#endif diff --git a/messages.h b/messages.h new file mode 100644 index 00000000..f346a7ce --- /dev/null +++ b/messages.h @@ -0,0 +1,228 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _MESSAGES_H_ +#define _MESSAGES_H_ + +// Types of message sent to S9xMessage() +enum +{ + S9X_TRACE, + S9X_DEBUG, + S9X_WARNING, + S9X_INFO, + S9X_ERROR, + S9X_FATAL_ERROR +}; + +// Individual message numbers +enum +{ + S9X_ROM_INFO, + S9X_HEADERS_INFO, + S9X_CONFIG_INFO, + S9X_ROM_CONFUSING_FORMAT_INFO, + S9X_ROM_INTERLEAVED_INFO, + S9X_SOUND_DEVICE_OPEN_FAILED, + S9X_APU_STOPPED, + S9X_USAGE, + S9X_GAME_GENIE_CODE_ERROR, + S9X_ACTION_REPLY_CODE_ERROR, + S9X_GOLD_FINGER_CODE_ERROR, + S9X_DEBUG_OUTPUT, + S9X_DMA_TRACE, + S9X_HDMA_TRACE, + S9X_WRONG_FORMAT, + S9X_WRONG_VERSION, + S9X_ROM_NOT_FOUND, + S9X_FREEZE_FILE_NOT_FOUND, + S9X_PPU_TRACE, + S9X_TRACE_DSP1, + S9X_FREEZE_ROM_NAME, + S9X_HEADER_WARNING, + S9X_NETPLAY_NOT_SERVER, + S9X_FREEZE_FILE_INFO, + S9X_TURBO_MODE, + S9X_SOUND_NOT_BUILT, + S9X_MOVIE_INFO, + S9X_WRONG_MOVIE_SNAPSHOT, + S9X_NOT_A_MOVIE_SNAPSHOT, + S9X_SNAPSHOT_INCONSISTENT, + S9X_AVI_INFO +}; + +#endif diff --git a/missing.h b/missing.h new file mode 100644 index 00000000..9a41fab1 --- /dev/null +++ b/missing.h @@ -0,0 +1,256 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 DEBUGGER + +#ifndef _MISSING_H_ +#define _MISSING_H_ + +struct MissingHDMA +{ + uint8 used; + uint8 bbus_address; + uint8 abus_bank; + uint16 abus_address; + uint8 indirect_address; + uint8 force_table_address_write; + uint8 force_table_address_read; + uint8 line_count_write; + uint8 line_count_read; +}; + +struct Missing +{ + struct MissingHDMA hdma[8]; + uint8 emulate6502; + uint8 decimal_mode; + uint8 mv_8bit_index; + uint8 mv_8bit_acc; + uint8 interlace; + uint8 lines_239; + uint8 pseudo_512; + uint8 modes[8]; + uint8 mode7_fx; + uint8 mode7_flip; + uint8 mode7_bgmode; + uint8 direct; + uint8 matrix_multiply; + uint8 oam_read; + uint8 vram_read; + uint8 cgram_read; + uint8 wram_read; + uint8 dma_read; + uint8 vram_inc; + uint8 vram_full_graphic_inc; + uint8 virq; + uint8 hirq; + uint16 virq_pos; + uint16 hirq_pos; + uint8 h_v_latch; + uint8 h_counter_read; + uint8 v_counter_read; + uint8 fast_rom; + uint8 window1[6]; + uint8 window2[6]; + uint8 sprite_priority_rotation; + uint8 subscreen; + uint8 subscreen_add; + uint8 subscreen_sub; + uint8 fixed_colour_add; + uint8 fixed_colour_sub; + uint8 mosaic; + uint8 sprite_double_height; + uint8 dma_channels; + uint8 dma_this_frame; + uint8 oam_address_read; + uint8 bg_offset_read; + uint8 matrix_read; + uint8 hdma_channels; + uint8 hdma_this_frame; + uint16 unknownppu_read; + uint16 unknownppu_write; + uint16 unknowncpu_read; + uint16 unknowncpu_write; + uint16 unknowndsp_read; + uint16 unknowndsp_write; +}; + +extern struct Missing missing; + +#endif + +#endif diff --git a/movie.cpp b/movie.cpp new file mode 100644 index 00000000..f8044ddb --- /dev/null +++ b/movie.cpp @@ -0,0 +1,1201 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +// Input recording/playback code +// (c) Copyright 2004 blip + +#ifndef __WIN32__ +#include +#endif +#include "snes9x.h" +#include "memmap.h" +#include "controls.h" +#include "snapshot.h" +#include "movie.h" +#include "language.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif + +#ifdef __WIN32__ +#include +#ifndef W_OK +#define W_OK 2 +#endif +#define ftruncate chsize +#endif + +#define SMV_MAGIC 0x1a564d53 // SMV0x1a +#define SMV_VERSION 5 +#define SMV_HEADER_SIZE 64 +#define SMV_EXTRAROMINFO_SIZE 30 +#define BUFFER_GROWTH_SIZE 4096 + +enum MovieState +{ + MOVIE_STATE_NONE = 0, + MOVIE_STATE_PLAY, + MOVIE_STATE_RECORD +}; + +struct SMovie +{ + enum MovieState State; + + FILE *File; + char Filename[PATH_MAX + 1]; + char ROMName[23]; + uint32 ROMCRC32; + uint32 MovieId; + uint32 Version; + + uint32 SaveStateOffset; + uint32 ControllerDataOffset; + + uint8 ControllersMask; + uint8 Opts; + uint8 SyncFlags; + uint32 MaxFrame; + uint32 MaxSample; + uint32 CurrentFrame; + uint32 CurrentSample; + uint32 BytesPerSample; + uint32 RerecordCount; + bool8 ReadOnly; + uint8 PortType[2]; + int8 PortIDs[2][4]; + + uint8 *InputBuffer; + uint8 *InputBufferPtr; + uint32 InputBufferSize; +}; + +static struct SMovie Movie; + +static uint8 prevPortType[2]; +static int8 prevPortIDs[2][4]; +static bool8 prevMouseMaster, prevSuperScopeMaster, prevJustifierMaster, prevMultiPlayer5Master; + +static uint8 Read8 (uint8 *&); +static uint16 Read16 (uint8 *&); +static uint32 Read32 (uint8 *&); +static void Write8 (uint8, uint8 *&); +static void Write16 (uint16, uint8 *&); +static void Write32 (uint32, uint8 *&); +static void store_previous_settings (void); +static void restore_previous_settings (void); +static void store_movie_settings (void); +static void restore_movie_settings (void); +static int bytes_per_sample (void); +static void reserve_buffer_space (uint32); +static void reset_controllers (void); +static void read_frame_controller_data (bool); +static void write_frame_controller_data (void); +static void flush_movie (void); +static void truncate_movie (void); +static int read_movie_header (FILE *, SMovie *); +static int read_movie_extrarominfo (FILE *, SMovie *); +static void write_movie_header (FILE *, SMovie *); +static void write_movie_extrarominfo (FILE *, SMovie *); +static void change_state (MovieState); + +// HACK: reduce movie size by not storing changes that can only affect polled input in the movie for these types, +// because currently no port sets these types to polling +#define SKIPPED_POLLING_PORT_TYPE(x) (((x) == CTL_NONE) || ((x) == CTL_JOYPAD) || ((x) == CTL_MP5)) + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif + + +static uint8 Read8 (uint8 *&ptr) +{ + uint8 v = *ptr++; + return (v); +} + +static uint16 Read16 (uint8 *&ptr) +{ + uint16 v = READ_WORD(ptr); + ptr += 2; + return (v); +} + +static uint32 Read32 (uint8 *&ptr) +{ + uint32 v = READ_DWORD(ptr); + ptr += 4; + return (v); +} + +static void Write8 (uint8 v, uint8 *&ptr) +{ + *ptr++ = v; +} + +static void Write16 (uint16 v, uint8 *&ptr) +{ + WRITE_WORD(ptr, v); + ptr += 2; +} + +static void Write32 (uint32 v, uint8 *&ptr) +{ + WRITE_DWORD(ptr, v); + ptr += 4; +} + +static void store_previous_settings (void) +{ + for (int i = 0; i < 2; i++) + { + enum controllers pt; + S9xGetController(i, &pt, &prevPortIDs[i][0], &prevPortIDs[i][1], &prevPortIDs[i][2], &prevPortIDs[i][3]); + prevPortType[i] = (uint8) pt; + } + + prevMouseMaster = Settings.MouseMaster; + prevSuperScopeMaster = Settings.SuperScopeMaster; + prevJustifierMaster = Settings.JustifierMaster; + prevMultiPlayer5Master = Settings.MultiPlayer5Master; +} + +static void restore_previous_settings (void) +{ + Settings.MouseMaster = prevMouseMaster; + Settings.SuperScopeMaster = prevSuperScopeMaster; + Settings.JustifierMaster = prevJustifierMaster; + Settings.MultiPlayer5Master = prevMultiPlayer5Master; + + S9xSetController(0, (enum controllers) prevPortType[0], prevPortIDs[0][0], prevPortIDs[0][1], prevPortIDs[0][2], prevPortIDs[0][3]); + S9xSetController(1, (enum controllers) prevPortType[1], prevPortIDs[1][0], prevPortIDs[1][1], prevPortIDs[1][2], prevPortIDs[1][3]); +} + +static void store_movie_settings (void) +{ + for (int i = 0; i < 2; i++) + { + enum controllers pt; + S9xGetController(i, &pt, &Movie.PortIDs[i][0], &Movie.PortIDs[i][1], &Movie.PortIDs[i][2], &Movie.PortIDs[i][3]); + Movie.PortType[i] = (uint8) pt; + } +} + +static void restore_movie_settings (void) +{ + Settings.MouseMaster = (Movie.PortType[0] == CTL_MOUSE || Movie.PortType[1] == CTL_MOUSE); + Settings.SuperScopeMaster = (Movie.PortType[0] == CTL_SUPERSCOPE || Movie.PortType[1] == CTL_SUPERSCOPE); + Settings.JustifierMaster = (Movie.PortType[0] == CTL_JUSTIFIER || Movie.PortType[1] == CTL_JUSTIFIER); + Settings.MultiPlayer5Master = (Movie.PortType[0] == CTL_MP5 || Movie.PortType[1] == CTL_MP5); + + S9xSetController(0, (enum controllers) Movie.PortType[0], Movie.PortIDs[0][0], Movie.PortIDs[0][1], Movie.PortIDs[0][2], Movie.PortIDs[0][3]); + S9xSetController(1, (enum controllers) Movie.PortType[1], Movie.PortIDs[1][0], Movie.PortIDs[1][1], Movie.PortIDs[1][2], Movie.PortIDs[1][3]); +} + +static int bytes_per_sample (void) +{ + int num_controllers = 0; + + for (int i = 0; i < 8; i++) + { + if (Movie.ControllersMask & (1 << i)) + num_controllers++; + } + + int bytes = CONTROLLER_DATA_SIZE * num_controllers; + + for (int p = 0; p < 2; p++) + { + if (Movie.PortType[p] == CTL_MOUSE) + bytes += MOUSE_DATA_SIZE; + else + if (Movie.PortType[p] == CTL_SUPERSCOPE) + bytes += SCOPE_DATA_SIZE; + else + if (Movie.PortType[p] == CTL_JUSTIFIER) + bytes += JUSTIFIER_DATA_SIZE; + } + + return (bytes); +} + +static void reserve_buffer_space (uint32 space_needed) +{ + if (space_needed > Movie.InputBufferSize) + { + uint32 ptr_offset = Movie.InputBufferPtr - Movie.InputBuffer; + uint32 alloc_chunks = space_needed / BUFFER_GROWTH_SIZE; + + Movie.InputBufferSize = BUFFER_GROWTH_SIZE * (alloc_chunks + 1); + Movie.InputBuffer = (uint8 *) realloc(Movie.InputBuffer, Movie.InputBufferSize); + Movie.InputBufferPtr = Movie.InputBuffer + ptr_offset; + } +} + +static void reset_controllers (void) +{ + for (int i = 0; i < 8; i++) + MovieSetJoypad(i, 0); + + uint8 clearedMouse[MOUSE_DATA_SIZE]; + ZeroMemory(clearedMouse, MOUSE_DATA_SIZE); + clearedMouse[4] = 1; + + uint8 clearedScope[SCOPE_DATA_SIZE]; + ZeroMemory(clearedScope, SCOPE_DATA_SIZE); + + uint8 clearedJustifier[JUSTIFIER_DATA_SIZE]; + ZeroMemory(clearedJustifier, JUSTIFIER_DATA_SIZE); + + for (int p = 0; p < 2; p++) + { + MovieSetMouse(p, clearedMouse, true); + MovieSetScope(p, clearedScope); + MovieSetJustifier(p, clearedJustifier); + } +} + +static void read_frame_controller_data (bool addFrame) +{ + // reset code check + if (Movie.InputBufferPtr[0] == 0xff) + { + bool reset = true; + for (int i = 1; i < (int) Movie.BytesPerSample; i++) + { + if (Movie.InputBufferPtr[i] != 0xff) + { + reset = false; + break; + } + } + + if (reset) + { + Movie.InputBufferPtr += Movie.BytesPerSample; + S9xSoftReset(); + return; + } + } + + for (int i = 0; i < 8; i++) + { + if (Movie.ControllersMask & (1 << i)) + MovieSetJoypad(i, Read16(Movie.InputBufferPtr)); + else + MovieSetJoypad(i, 0); // pretend the controller is disconnected + } + + for (int p = 0; p < 2; p++) + { + if (Movie.PortType[p] == CTL_MOUSE) + { + uint8 buf[MOUSE_DATA_SIZE]; + memcpy(buf, Movie.InputBufferPtr, MOUSE_DATA_SIZE); + Movie.InputBufferPtr += MOUSE_DATA_SIZE; + MovieSetMouse(p, buf, !addFrame); + } + else + if (Movie.PortType[p] == CTL_SUPERSCOPE) + { + uint8 buf[SCOPE_DATA_SIZE]; + memcpy(buf, Movie.InputBufferPtr, SCOPE_DATA_SIZE); + Movie.InputBufferPtr += SCOPE_DATA_SIZE; + MovieSetScope(p, buf); + } + else + if (Movie.PortType[p] == CTL_JUSTIFIER) + { + uint8 buf[JUSTIFIER_DATA_SIZE]; + memcpy(buf, Movie.InputBufferPtr, JUSTIFIER_DATA_SIZE); + Movie.InputBufferPtr += JUSTIFIER_DATA_SIZE; + MovieSetJustifier(p, buf); + } + } +} + +static void write_frame_controller_data (void) +{ + reserve_buffer_space((uint32) (Movie.InputBufferPtr + Movie.BytesPerSample - Movie.InputBuffer)); + + for (int i = 0; i < 8; i++) + { + if (Movie.ControllersMask & (1 << i)) + Write16(MovieGetJoypad(i), Movie.InputBufferPtr); + else + MovieSetJoypad(i, 0); // pretend the controller is disconnected + } + + for (int p = 0; p < 2; p++) + { + if (Movie.PortType[p] == CTL_MOUSE) + { + uint8 buf[MOUSE_DATA_SIZE]; + MovieGetMouse(p, buf); + memcpy(Movie.InputBufferPtr, buf, MOUSE_DATA_SIZE); + Movie.InputBufferPtr += MOUSE_DATA_SIZE; + } + else + if (Movie.PortType[p] == CTL_SUPERSCOPE) + { + uint8 buf[SCOPE_DATA_SIZE]; + MovieGetScope(p, buf); + memcpy(Movie.InputBufferPtr, buf, SCOPE_DATA_SIZE); + Movie.InputBufferPtr += SCOPE_DATA_SIZE; + } + else + if (Movie.PortType[p] == CTL_JUSTIFIER) + { + uint8 buf[JUSTIFIER_DATA_SIZE]; + MovieGetJustifier(p, buf); + memcpy(Movie.InputBufferPtr, buf, JUSTIFIER_DATA_SIZE); + Movie.InputBufferPtr += JUSTIFIER_DATA_SIZE; + } + } +} + +static void flush_movie (void) +{ + if (!Movie.File) + return; + + fseek(Movie.File, 0, SEEK_SET); + write_movie_header(Movie.File, &Movie); + fseek(Movie.File, Movie.ControllerDataOffset, SEEK_SET); + + size_t ignore; + ignore = fwrite(Movie.InputBuffer, 1, Movie.BytesPerSample * (Movie.MaxSample + 1), Movie.File); +} + +static void truncate_movie (void) +{ + if (!Movie.File || !Settings.MovieTruncate) + return; + + if (Movie.SaveStateOffset > Movie.ControllerDataOffset) + return; + + int ignore; + ignore = ftruncate(fileno(Movie.File), Movie.ControllerDataOffset + Movie.BytesPerSample * (Movie.MaxSample + 1)); +} + +static int read_movie_header (FILE *fd, SMovie *movie) +{ + uint32 value; + uint8 buf[SMV_HEADER_SIZE], *ptr = buf; + + if (fread(buf, 1, SMV_HEADER_SIZE, fd) != SMV_HEADER_SIZE) + return (WRONG_FORMAT); + + value = Read32(ptr); + if (value != SMV_MAGIC) + return (WRONG_FORMAT); + + value = Read32(ptr); + if(value > SMV_VERSION || value < 4) + return (WRONG_VERSION); + + movie->Version = value; + movie->MovieId = Read32(ptr); + movie->RerecordCount = Read32(ptr); + movie->MaxFrame = Read32(ptr); + movie->ControllersMask = Read8(ptr); + movie->Opts = Read8(ptr); + ptr++; + movie->SyncFlags = Read8(ptr); + movie->SaveStateOffset = Read32(ptr); + movie->ControllerDataOffset = Read32(ptr); + movie->MaxSample = Read32(ptr); + movie->PortType[0] = Read8(ptr); + movie->PortType[1] = Read8(ptr); + for (int p = 0; p < 2; p++) + { + for (int i = 0; i < 4; i++) + movie->PortIDs[p][i] = Read8(ptr); + } + + if (movie->MaxSample < movie->MaxFrame) + movie->MaxSample = movie->MaxFrame; + + return (SUCCESS); +} + +static int read_movie_extrarominfo (FILE *fd, SMovie *movie) +{ + uint8 buf[SMV_EXTRAROMINFO_SIZE], *ptr = buf; + + fseek(fd, movie->SaveStateOffset - SMV_EXTRAROMINFO_SIZE, SEEK_SET); + + if (fread(buf, 1, SMV_EXTRAROMINFO_SIZE, fd) != SMV_EXTRAROMINFO_SIZE) + return (WRONG_FORMAT); + + ptr += 3; // zero bytes + movie->ROMCRC32 = Read32(ptr); + strncpy(movie->ROMName, (char *) ptr, 23); + + return (SUCCESS); +} + +static void write_movie_header (FILE *fd, SMovie *movie) +{ + uint8 buf[SMV_HEADER_SIZE], *ptr = buf; + + ZeroMemory(buf, sizeof(buf)); + + Write32(SMV_MAGIC, ptr); + Write32(SMV_VERSION, ptr); + Write32(movie->MovieId, ptr); + Write32(movie->RerecordCount, ptr); + Write32(movie->MaxFrame, ptr); + Write8(movie->ControllersMask, ptr); + Write8(movie->Opts, ptr); + ptr++; + Write8(movie->SyncFlags, ptr); + Write32(movie->SaveStateOffset, ptr); + Write32(movie->ControllerDataOffset, ptr); + Write32(movie->MaxSample, ptr); + Write8(movie->PortType[0], ptr); + Write8(movie->PortType[1], ptr); + for (int p = 0; p < 2; p++) + { + for (int i = 0; i < 4; i++) + Write8(movie->PortIDs[p][i], ptr); + } + + size_t ignore; + ignore = fwrite(buf, 1, SMV_HEADER_SIZE, fd); +} + +static void write_movie_extrarominfo (FILE *fd, SMovie *movie) +{ + uint8 buf[SMV_EXTRAROMINFO_SIZE], *ptr = buf; + + Write8(0, ptr); + Write8(0, ptr); + Write8(0, ptr); + Write32(movie->ROMCRC32, ptr); + strncpy((char *) ptr, movie->ROMName, 23); + + size_t ignore; + ignore = fwrite(buf, 1, SMV_EXTRAROMINFO_SIZE, fd); +} + +static void change_state (MovieState new_state) +{ + if (new_state == Movie.State) + return; + + if (Movie.State == MOVIE_STATE_RECORD) + flush_movie(); + + if (new_state == MOVIE_STATE_NONE) + { + truncate_movie(); + fclose(Movie.File); + Movie.File = NULL; + + if (S9xMoviePlaying() || S9xMovieRecording()) + restore_previous_settings(); + } + + Movie.State = new_state; +} + +void S9xMovieFreeze (uint8 **buf, uint32 *size) +{ + if (!S9xMovieActive()) + return; + + uint32 size_needed; + uint8 *ptr; + + size_needed = sizeof(Movie.MovieId) + sizeof(Movie.CurrentFrame) + sizeof(Movie.MaxFrame) + sizeof(Movie.CurrentSample) + sizeof(Movie.MaxSample); + size_needed += (uint32) (Movie.BytesPerSample * (Movie.MaxSample + 1)); + *size = size_needed; + + *buf = new uint8[size_needed]; + ptr = *buf; + if (!ptr) + return; + + Write32(Movie.MovieId, ptr); + Write32(Movie.CurrentFrame, ptr); + Write32(Movie.MaxFrame, ptr); + Write32(Movie.CurrentSample, ptr); + Write32(Movie.MaxSample, ptr); + + memcpy(ptr, Movie.InputBuffer, Movie.BytesPerSample * (Movie.MaxSample + 1)); +} + +int S9xMovieUnfreeze (uint8 *buf, uint32 size) +{ + if (!S9xMovieActive()) + return (FILE_NOT_FOUND); + + if (size < sizeof(Movie.MovieId) + sizeof(Movie.CurrentFrame) + sizeof(Movie.MaxFrame) + sizeof(Movie.CurrentSample) + sizeof(Movie.MaxSample)) + return (WRONG_FORMAT); + + uint8 *ptr = buf; + + uint32 movie_id = Read32(ptr); + uint32 current_frame = Read32(ptr); + uint32 max_frame = Read32(ptr); + uint32 current_sample = Read32(ptr); + uint32 max_sample = Read32(ptr); + uint32 space_needed = (Movie.BytesPerSample * (max_sample + 1)); + + if (current_frame > max_frame || current_sample > max_sample || space_needed > size) + return (WRONG_MOVIE_SNAPSHOT); + + if (Settings.WrongMovieStateProtection) + if (movie_id != Movie.MovieId) + if (max_frame < Movie.MaxFrame || max_sample < Movie.MaxSample || memcmp(Movie.InputBuffer, ptr, space_needed)) + return (WRONG_MOVIE_SNAPSHOT); + + if (!Movie.ReadOnly) + { + change_state(MOVIE_STATE_RECORD); + + Movie.CurrentFrame = current_frame; + Movie.MaxFrame = max_frame; + Movie.CurrentSample = current_sample; + Movie.MaxSample = max_sample; + Movie.RerecordCount++; + + store_movie_settings(); + + reserve_buffer_space(space_needed); + memcpy(Movie.InputBuffer, ptr, space_needed); + + flush_movie(); + fseek(Movie.File, Movie.ControllerDataOffset + (Movie.BytesPerSample * (Movie.CurrentSample + 1)), SEEK_SET); + } + else + { + if (current_frame > Movie.MaxFrame || current_sample > Movie.MaxSample || memcmp(Movie.InputBuffer, ptr, space_needed)) + return (SNAPSHOT_INCONSISTENT); + + change_state(MOVIE_STATE_PLAY); + + Movie.CurrentFrame = current_frame; + Movie.CurrentSample = current_sample; + } + + Movie.InputBufferPtr = Movie.InputBuffer + (Movie.BytesPerSample * Movie.CurrentSample); + read_frame_controller_data(true); + + return (SUCCESS); +} + +int S9xMovieOpen (const char *filename, bool8 read_only) +{ + FILE *fd; + STREAM stream; + int result; + int fn; + + if (!(fd = fopen(filename, "rb+"))) + { + if (!(fd = fopen(filename, "rb"))) + return (FILE_NOT_FOUND); + else + read_only = TRUE; + } + + change_state(MOVIE_STATE_NONE); + + result = read_movie_header(fd, &Movie); + if (result != SUCCESS) + { + fclose(fd); + return (result); + } + + read_movie_extrarominfo(fd, &Movie); + + fn = dup(fileno(fd)); + fclose(fd); + + store_previous_settings(); + restore_movie_settings(); + + lseek(fn, Movie.SaveStateOffset, SEEK_SET); + stream = REOPEN_STREAM(fn, "rb"); + if (!stream) + return (FILE_NOT_FOUND); + + if (Movie.Opts & MOVIE_OPT_FROM_RESET) + { + S9xReset(); + reset_controllers(); + result = (READ_STREAM(Memory.SRAM, 0x20000, stream) == 0x20000) ? SUCCESS : WRONG_FORMAT; + } + else + result = S9xUnfreezeFromStream(stream); + + CLOSE_STREAM(stream); + + if (result != SUCCESS) + return (result); + + if (!(fd = fopen(filename, "rb+"))) + { + if (!(fd = fopen(filename, "rb"))) + return (FILE_NOT_FOUND); + else + read_only = TRUE; + } + + if (fseek(fd, Movie.ControllerDataOffset, SEEK_SET)) + return (WRONG_FORMAT); + + Movie.File = fd; + Movie.BytesPerSample = bytes_per_sample(); + Movie.InputBufferPtr = Movie.InputBuffer; + reserve_buffer_space(Movie.BytesPerSample * (Movie.MaxSample + 1)); + + size_t ignore; + ignore = fread(Movie.InputBufferPtr, 1, Movie.BytesPerSample * (Movie.MaxSample + 1), fd); + + // read "baseline" controller data + if (Movie.MaxSample && Movie.MaxFrame) + read_frame_controller_data(true); + + Movie.CurrentFrame = 0; + Movie.CurrentSample = 0; + Movie.ReadOnly = read_only; + strncpy(Movie.Filename, filename, PATH_MAX + 1); + Movie.Filename[PATH_MAX] = 0; + + change_state(MOVIE_STATE_PLAY); + + S9xUpdateFrameCounter(-1); + + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_REPLAY); + + return (SUCCESS); +} + +int S9xMovieCreate (const char *filename, uint8 controllers_mask, uint8 opts, const wchar_t *metadata, int metadata_length) +{ + FILE *fd; + STREAM stream; + int fn; + + if (controllers_mask == 0) + return (WRONG_FORMAT); + + if (!(fd = fopen(filename, "wb"))) + return (FILE_NOT_FOUND); + + if (metadata_length > MOVIE_MAX_METADATA) + metadata_length = MOVIE_MAX_METADATA; + + change_state(MOVIE_STATE_NONE); + + store_previous_settings(); + store_movie_settings(); + + Movie.MovieId = (uint32) time(NULL); + Movie.RerecordCount = 0; + Movie.MaxFrame = 0; + Movie.MaxSample = 0; + Movie.SaveStateOffset = SMV_HEADER_SIZE + (sizeof(uint16) * metadata_length) + SMV_EXTRAROMINFO_SIZE; + Movie.ControllerDataOffset = 0; + Movie.ControllersMask = controllers_mask; + Movie.Opts = opts; + Movie.SyncFlags = MOVIE_SYNC_DATA_EXISTS | MOVIE_SYNC_HASROMINFO; + + write_movie_header(fd, &Movie); + + // convert wchar_t metadata string/array to a uint16 array + // XXX: UTF-8 is much better... + if (metadata_length > 0) + { + uint8 meta_buf[sizeof(uint16) * MOVIE_MAX_METADATA]; + for (int i = 0; i < metadata_length; i++) + { + uint16 c = (uint16) metadata[i]; + meta_buf[i * 2] = (uint8) (c & 0xff); + meta_buf[i * 2 + 1] = (uint8) ((c >> 8) & 0xff); + } + + size_t ignore; + ignore = fwrite(meta_buf, sizeof(uint16), metadata_length, fd); + } + + Movie.ROMCRC32 = Memory.ROMCRC32; + strncpy(Movie.ROMName, Memory.RawROMName, 23); + + write_movie_extrarominfo(fd, &Movie); + + fn = dup(fileno(fd)); + fclose(fd); + + stream = REOPEN_STREAM(fn, "ab"); + if (!stream) + return (FILE_NOT_FOUND); + + if (opts & MOVIE_OPT_FROM_RESET) + { + S9xReset(); + reset_controllers(); + WRITE_STREAM(Memory.SRAM, 0x20000, stream); + } + else + S9xFreezeToStream(stream); + + CLOSE_STREAM(stream); + + if (!(fd = fopen(filename, "rb+"))) + return (FILE_NOT_FOUND); + + fseek(fd, 0, SEEK_END); + Movie.ControllerDataOffset = (uint32) ftell(fd); + + // 16-byte align the controller input, for hex-editing friendliness if nothing else + while (Movie.ControllerDataOffset % 16) + { + fputc(0xcc, fd); // arbitrary + Movie.ControllerDataOffset++; + } + + // write "baseline" controller data + Movie.File = fd; + Movie.BytesPerSample = bytes_per_sample(); + Movie.InputBufferPtr = Movie.InputBuffer; + write_frame_controller_data(); + + Movie.CurrentFrame = 0; + Movie.CurrentSample = 0; + Movie.ReadOnly = false; + strncpy(Movie.Filename, filename, PATH_MAX + 1); + Movie.Filename[PATH_MAX] = 0; + + change_state(MOVIE_STATE_RECORD); + + S9xUpdateFrameCounter(-1); + + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_RECORD); + + return (SUCCESS); +} + +int S9xMovieGetInfo (const char *filename, struct MovieInfo *info) +{ + FILE *fd; + SMovie local_movie; + int metadata_length; + int result, i; + + flush_movie(); + + ZeroMemory(info, sizeof(*info)); + + if (!(fd = fopen(filename, "rb"))) + return (FILE_NOT_FOUND); + + result = read_movie_header(fd, &local_movie); + if (result != SUCCESS) + return (result); + + info->TimeCreated = (time_t) local_movie.MovieId; + info->Version = local_movie.Version; + info->Opts = local_movie.Opts; + info->SyncFlags = local_movie.SyncFlags; + info->ControllersMask = local_movie.ControllersMask; + info->RerecordCount = local_movie.RerecordCount; + info->LengthFrames = local_movie.MaxFrame; + info->LengthSamples = local_movie.MaxSample; + info->PortType[0] = local_movie.PortType[0]; + info->PortType[1] = local_movie.PortType[1]; + + if (local_movie.SaveStateOffset > SMV_HEADER_SIZE) + { + uint8 meta_buf[sizeof(uint16) * MOVIE_MAX_METADATA]; + int curRomInfoSize = (local_movie.SyncFlags & MOVIE_SYNC_HASROMINFO) ? SMV_EXTRAROMINFO_SIZE : 0; + + metadata_length = ((int) local_movie.SaveStateOffset - SMV_HEADER_SIZE - curRomInfoSize) / sizeof(uint16); + metadata_length = (metadata_length >= MOVIE_MAX_METADATA) ? MOVIE_MAX_METADATA - 1 : metadata_length; + metadata_length = (int) fread(meta_buf, sizeof(uint16), metadata_length, fd); + + for (i = 0; i < metadata_length; i++) + { + uint16 c = meta_buf[i * 2] | (meta_buf[i * 2 + 1] << 8); + info->Metadata[i] = (wchar_t) c; + } + + info->Metadata[i] = '\0'; + } + else + info->Metadata[0] = '\0'; + + read_movie_extrarominfo(fd, &local_movie); + + info->ROMCRC32 = local_movie.ROMCRC32; + strncpy(info->ROMName, local_movie.ROMName, 23); + + fclose(fd); + + if (access(filename, W_OK)) + info->ReadOnly = true; + + return (SUCCESS); +} + +void S9xMovieUpdate (bool addFrame) +{ + switch (Movie.State) + { + case MOVIE_STATE_PLAY: + { + if (Movie.CurrentFrame >= Movie.MaxFrame || Movie.CurrentSample >= Movie.MaxSample) + { + change_state(MOVIE_STATE_NONE); + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_END); + return; + } + else + { + if (addFrame) + S9xUpdateFrameCounter(); + else + if (SKIPPED_POLLING_PORT_TYPE(Movie.PortType[0]) && SKIPPED_POLLING_PORT_TYPE(Movie.PortType[1])) + return; + + read_frame_controller_data(addFrame); + Movie.CurrentSample++; + if (addFrame) + Movie.CurrentFrame++; + } + + break; + } + + case MOVIE_STATE_RECORD: + { + if (addFrame) + S9xUpdateFrameCounter(); + else + if (SKIPPED_POLLING_PORT_TYPE(Movie.PortType[0]) && SKIPPED_POLLING_PORT_TYPE(Movie.PortType[1])) + return; + + write_frame_controller_data(); + Movie.MaxSample = ++Movie.CurrentSample; + if (addFrame) + Movie.MaxFrame = ++Movie.CurrentFrame; + + size_t ignore; + ignore = fwrite((Movie.InputBufferPtr - Movie.BytesPerSample), 1, Movie.BytesPerSample, Movie.File); + + break; + } + + default: + { + if (addFrame) + S9xUpdateFrameCounter(); + + break; + } + } +} + +void S9xMovieUpdateOnReset (void) +{ + if (Movie.State == MOVIE_STATE_RECORD) + { + reserve_buffer_space((uint32) (Movie.InputBufferPtr + Movie.BytesPerSample - Movie.InputBuffer)); + memset(Movie.InputBufferPtr, 0xFF, Movie.BytesPerSample); + Movie.InputBufferPtr += Movie.BytesPerSample; + Movie.MaxSample = ++Movie.CurrentSample; + Movie.MaxFrame = ++Movie.CurrentFrame; + + size_t ignore; + ignore = fwrite((Movie.InputBufferPtr - Movie.BytesPerSample), 1, Movie.BytesPerSample, Movie.File); + } +} + +void S9xMovieInit (void) +{ + ZeroMemory(&Movie, sizeof(Movie)); + Movie.State = MOVIE_STATE_NONE; +} + +void S9xMovieStop (bool8 suppress_message) +{ + if (Movie.State != MOVIE_STATE_NONE) + { + change_state(MOVIE_STATE_NONE); + + if (!suppress_message) + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_INFO_STOP); + } +} + +void S9xMovieShutdown (void) +{ + if (S9xMovieActive()) + S9xMovieStop(TRUE); +} + +bool8 S9xMovieActive (void) +{ + return (Movie.State != MOVIE_STATE_NONE); +} + +bool8 S9xMoviePlaying (void) +{ + return (Movie.State == MOVIE_STATE_PLAY); +} + +bool8 S9xMovieRecording (void) +{ + return (Movie.State == MOVIE_STATE_RECORD); +} + +uint8 S9xMovieControllers (void) +{ + return (Movie.ControllersMask); +} + +bool8 S9xMovieReadOnly (void) +{ + if (!S9xMovieActive()) + return (FALSE); + return (Movie.ReadOnly); +} + +uint32 S9xMovieGetId (void) +{ + if (!S9xMovieActive()) + return (0); + return (Movie.MovieId); +} + +uint32 S9xMovieGetLength (void) +{ + if (!S9xMovieActive()) + return (0); + return (Movie.MaxFrame); +} + +uint32 S9xMovieGetFrameCounter (void) +{ + if (!S9xMovieActive()) + return (0); + return (Movie.CurrentFrame); +} + +void S9xMovieToggleRecState (void) +{ + Movie.ReadOnly = !Movie.ReadOnly; + + if (Movie.ReadOnly) + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, "Movie is now read-only."); + else + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, "Movie is now read+write."); +} + +void S9xMovieToggleFrameDisplay (void) +{ + Settings.DisplayMovieFrame = !Settings.DisplayMovieFrame; + S9xReRefresh(); +} + +void S9xUpdateFrameCounter (int offset) +{ + extern bool8 pad_read; + + offset++; + + if (!Settings.DisplayMovieFrame) + *GFX.FrameDisplayString = 0; + else + if (Movie.State == MOVIE_STATE_RECORD) + sprintf(GFX.FrameDisplayString, "Recording frame: %d%s", + max(0, (int) (Movie.CurrentFrame + offset)), pad_read || !Settings.MovieNotifyIgnored ? "" : " (ignored)"); + else + if (Movie.State == MOVIE_STATE_PLAY) + sprintf(GFX.FrameDisplayString, "Playing frame: %d / %d", + max(0, (int) (Movie.CurrentFrame + offset)), Movie.MaxFrame); +#ifdef NETPLAY_SUPPORT + else + if (Settings.NetPlay) + sprintf(GFX.FrameDisplayString, "%s frame: %d", Settings.NetPlayServer ? "Server" : "Client", + max(0, (int) (NetPlay.FrameCount + offset))); +#endif +} diff --git a/movie.h b/movie.h new file mode 100644 index 00000000..f1fb2bb0 --- /dev/null +++ b/movie.h @@ -0,0 +1,254 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _MOVIE_H_ +#define _MOVIE_H_ + +#define MOVIE_OPT_FROM_SNAPSHOT 0 +#define MOVIE_OPT_FROM_RESET (1 << 0) +#define MOVIE_OPT_PAL (1 << 1) +#define MOVIE_OPT_NOSAVEDATA (1 << 2) +#define MOVIE_SYNC_DATA_EXISTS 0x01 +#define MOVIE_SYNC_OBSOLETE 0x02 +#define MOVIE_SYNC_LEFTRIGHT 0x04 +#define MOVIE_SYNC_VOLUMEENVX 0x08 +#define MOVIE_SYNC_FAKEMUTE 0x10 +#define MOVIE_SYNC_SYNCSOUND 0x20 +#define MOVIE_SYNC_HASROMINFO 0x40 +#define MOVIE_SYNC_NOCPUSHUTDOWN 0x80 +#define MOVIE_MAX_METADATA 512 + +#define CONTROLLER_DATA_SIZE 2 +#define MOUSE_DATA_SIZE 5 +#define SCOPE_DATA_SIZE 6 +#define JUSTIFIER_DATA_SIZE 11 + +struct MovieInfo +{ + time_t TimeCreated; + uint32 Version; + uint32 LengthFrames; + uint32 LengthSamples; + uint32 RerecordCount; + uint8 Opts; + uint8 ControllersMask; + uint8 SyncFlags; + bool8 ReadOnly; + uint8 PortType[2]; + wchar_t Metadata[MOVIE_MAX_METADATA]; + uint32 ROMCRC32; + char ROMName[23]; +}; + +// methods used by the user-interface code +int S9xMovieOpen (const char *, bool8); +int S9xMovieCreate (const char *, uint8, uint8, const wchar_t *, int); +int S9xMovieGetInfo (const char *, struct MovieInfo *); +void S9xMovieStop (bool8); +void S9xMovieToggleRecState (void); +void S9xMovieToggleFrameDisplay (void); +const char * S9xChooseMovieFilename (bool8); + +// methods used by the emulation +void S9xMovieInit (void); +void S9xMovieShutdown (void); +void S9xMovieUpdate (bool a = true); +void S9xMovieUpdateOnReset (void); +void S9xUpdateFrameCounter (int o = 0); +void S9xMovieFreeze (uint8 **, uint32 *); +int S9xMovieUnfreeze (uint8 *, uint32); + +// accessor functions +bool8 S9xMovieActive (void); +bool8 S9xMoviePlaying (void); +bool8 S9xMovieRecording (void); +bool8 S9xMovieReadOnly (void); +uint8 S9xMovieControllers (void); +uint32 S9xMovieGetId (void); +uint32 S9xMovieGetLength (void); +uint32 S9xMovieGetFrameCounter (void); + +uint16 MovieGetJoypad (int); +void MovieSetJoypad (int, uint16); +bool MovieGetMouse (int, uint8 d[MOUSE_DATA_SIZE]); +void MovieSetMouse (int, uint8 d[MOUSE_DATA_SIZE], bool); +bool MovieGetScope (int, uint8 d[SCOPE_DATA_SIZE]); +void MovieSetScope (int, uint8 d[SCOPE_DATA_SIZE]); +bool MovieGetJustifier (int, uint8 d[JUSTIFIER_DATA_SIZE]); +void MovieSetJustifier (int, uint8 d[JUSTIFIER_DATA_SIZE]); + +#endif diff --git a/netplay.cpp b/netplay.cpp new file mode 100644 index 00000000..2b244235 --- /dev/null +++ b/netplay.cpp @@ -0,0 +1,1226 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 NETPLAY_SUPPORT +#ifdef _DEBUG + #define NP_DEBUG 1 +#endif + +#define NP_DEBUG 3 // FF-FIXME + +#include +#include +#include +#include +#include + +#ifdef __WIN32__ + #include + #include + #include "win32/wsnes9x.h" + + #define ioctl ioctlsocket + #define close closesocket + #define read(a,b,c) recv(a, b, c, 0) + #define write(a,b,c) send(a, b, c, 0) +#else + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + #ifdef __SVR4 + #include + #endif +#endif + +#ifdef USE_THREADS +#include +#include +#include +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "netplay.h" +#include "snapshot.h" +#include "display.h" + +void S9xNPClientLoop (void *); +bool8 S9xNPLoadROM (uint32 len); +bool8 S9xNPLoadROMDialog (const char *); +bool8 S9xNPGetROMImage (uint32 len); +void S9xNPGetSRAMData (uint32 len); +void S9xNPGetFreezeFile (uint32 len); + +unsigned long START = 0; + +bool8 S9xNPConnect (); + +bool8 S9xNPConnectToServer (const char *hostname, int port, + const char *rom_name) +{ + if (!S9xNPInitialise ()) + return (FALSE); + + S9xNPDisconnect (); + + NetPlay.MySequenceNum = 0; + NetPlay.ServerSequenceNum = 0; + NetPlay.Connected = FALSE; + NetPlay.Abort = FALSE; + NetPlay.Player = 0; + NetPlay.Paused = FALSE; + NetPlay.PercentageComplete = 0; + NetPlay.Socket = 0; + if (NetPlay.ServerHostName) + free ((char *) NetPlay.ServerHostName); + NetPlay.ServerHostName = strdup (hostname); + if (NetPlay.ROMName) + free ((char *) NetPlay.ROMName); + NetPlay.ROMName = strdup (rom_name); + NetPlay.Port = port; + NetPlay.PendingWait4Sync = FALSE; + +#ifdef __WIN32__ + if (GUI.ClientSemaphore == NULL) + GUI.ClientSemaphore = CreateSemaphore (NULL, 0, NP_JOYPAD_HIST_SIZE, NULL); + + if (NetPlay.ReplyEvent == NULL) + NetPlay.ReplyEvent = CreateEvent (NULL, FALSE, FALSE, NULL); + + _beginthread (S9xNPClientLoop, 0, NULL); + + return (TRUE); +#endif + + return S9xNPConnect(); +} + +bool8 S9xNPConnect () +{ + struct sockaddr_in address; + struct hostent *hostinfo; + unsigned int addr; + + address.sin_family = AF_INET; + address.sin_port = htons (NetPlay.Port); +#ifdef NP_DEBUG + printf ("CLIENT: Looking up server's hostname (%s) @%ld\n", NetPlay.ServerHostName, S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Looking up server's hostname..."); + if ((int) (addr = inet_addr (NetPlay.ServerHostName)) == -1) + { + if ((hostinfo = gethostbyname (NetPlay.ServerHostName))) + { + memcpy ((char *)&address.sin_addr, hostinfo->h_addr, + hostinfo->h_length); + } + else + { + S9xNPSetError ("\ +Unable to look up server's IP address from hostname.\n\n\ +Unknown hostname or may be your nameserver isn't set\n\ +up correctly?"); + return (FALSE); + } + } + else + { + memcpy ((char *)&address.sin_addr, &addr, sizeof (addr)); + } + +#ifdef NP_DEBUG + printf ("CLIENT: Creating socket @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Creating network socket..."); + if ((NetPlay.Socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) + { + S9xNPSetError ("Creating network socket failed."); + return (FALSE); + } + +#ifdef NP_DEBUG + printf ("CLIENT: Trying to connect to server @%ld...\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Trying to connect to Snes9X server..."); + + if (connect (NetPlay.Socket, (struct sockaddr *) &address, sizeof (address)) < 0) + { + char buf [100]; +#ifdef __WIN32__ + if (WSAGetLastError () == WSAECONNREFUSED) +#else + if (errno == ECONNREFUSED) +#endif + { + S9xNPSetError ("\ +Connection to remote server socket refused:\n\n\ +Is there actually a Snes9X NetPlay server running\n\ +on the remote machine on this port?"); + } + else + { + sprintf (buf, "Connection to server failed with error number %d", +#ifdef __WIN32__ + WSAGetLastError () +#else + errno +#endif + ); + S9xNPDisconnect (); + } + return (FALSE); + } + NetPlay.Connected = TRUE; + +#ifdef NP_DEBUG + printf ("CLIENT: Sending 'HELLO' message @%ld...\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Sending 'HELLO' message..."); + /* Send the server a HELLO packet*/ + int len = 7 + 4 + strlen (NetPlay.ROMName) + 1; + uint8 *tmp = new uint8 [len]; + uint8 *ptr = tmp; + + *ptr++ = NP_CLNT_MAGIC; + *ptr++ = NetPlay.MySequenceNum++; + *ptr++ = NP_CLNT_HELLO; + WRITE_LONG (ptr, len); + ptr += 4; +#ifdef __WIN32__ + uint32 ft = Settings.FrameTime; + + WRITE_LONG (ptr, ft); +#else + WRITE_LONG (ptr, Settings.FrameTime); +#endif + ptr += 4; + strcpy ((char *) ptr, NetPlay.ROMName); + + if (!S9xNPSendData (NetPlay.Socket, tmp, len)) + { + S9xNPSetError ("Sending 'HELLO' message failed."); + S9xNPDisconnect (); + delete tmp; + return (FALSE); + } + delete tmp; + +#ifdef NP_DEBUG + printf ("CLIENT: Waiting for 'WELCOME' reply from server @%ld...\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Waiting for 'HELLO' reply from server..."); + + uint8 header [7]; + + if (!S9xNPGetData (NetPlay.Socket, header, 7) || + header [0] != NP_SERV_MAGIC || header [1] != 0 || + (header [2] & 0x1f) != NP_SERV_HELLO) + { + S9xNPSetError ("Error in 'HELLO' reply packet received from server."); + S9xNPDisconnect (); + return (FALSE); + } +#ifdef NP_DEBUG + printf ("CLIENT: Got 'WELCOME' reply @%ld\n", S9xGetMilliTime () - START); +#endif + len = READ_LONG (&header [3]); + if (len > 256) + { + S9xNPSetError ("Error in 'HELLO' reply packet received from server."); + S9xNPDisconnect (); + return (FALSE); + } + uint8 *data = new uint8 [len]; + if (!S9xNPGetData (NetPlay.Socket, data, len - 7)) + { + S9xNPSetError ("Error in 'HELLO' reply packet received from server."); + delete data; + S9xNPDisconnect (); + return (FALSE); + } + + if (data [0] != NP_VERSION) + { + S9xNPSetError ("\ +The Snes9X NetPlay server implements a different\n\ +version of the protocol. Disconnecting."); + delete data; + S9xNPDisconnect (); + return (FALSE); + } + + NetPlay.FrameCount = READ_LONG (&data [2]); + + if (!(header [2] & 0x80) && + strcmp ((char *) data + 4 + 2, NetPlay.ROMName) != 0) + { + if (!S9xNPLoadROMDialog ((char *) data + 4 + 2)) + { + delete data; + S9xNPDisconnect (); + return (FALSE); + } + } + NetPlay.Player = data [1]; + delete data; + + NetPlay.PendingWait4Sync = TRUE; + Settings.NetPlay = TRUE; + S9xNPResetJoypadReadPos (); + NetPlay.ServerSequenceNum = 1; + +#ifdef NP_DEBUG + printf ("CLIENT: Sending 'READY' to server @%ld...\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Sending 'READY' to the server..."); + + return (S9xNPSendReady ((header [2] & 0x80) ? + NP_CLNT_WAITING_FOR_ROM_IMAGE : + NP_CLNT_READY)); +} + +bool8 S9xNPSendReady (uint8 op) +{ + uint8 ready [7]; + uint8 *ptr = ready; + *ptr++ = NP_CLNT_MAGIC; + *ptr++ = NetPlay.MySequenceNum++; + *ptr++ = op; + WRITE_LONG (ptr, 7); + ptr += 4; + + if (!S9xNPSendData (NetPlay.Socket, ready, 7)) + { + S9xNPDisconnect (); + S9xNPSetError ("Sending 'READY' message failed."); + return (FALSE); + } + + return (TRUE); +} + +bool8 S9xNPSendPause (bool8 paused) +{ +#ifdef NP_DEBUG + printf ("CLIENT: Pause - %s @%ld\n", paused ? "YES" : "NO", S9xGetMilliTime () - START); +#endif + uint8 pause [7]; + uint8 *ptr = pause; + *ptr++ = NP_CLNT_MAGIC; + *ptr++ = NetPlay.MySequenceNum++; + *ptr++ = NP_CLNT_PAUSE | (paused ? 0x80 : 0); + WRITE_LONG (ptr, 7); + ptr += 4; + + if (!S9xNPSendData (NetPlay.Socket, pause, 7)) + { + S9xNPSetError ("Sending 'PAUSE' message failed."); + S9xNPDisconnect (); + return (FALSE); + } + + return (TRUE); +} + +#ifdef __WIN32__ +void S9xNPClientLoop (void *) +{ + NetPlay.Waiting4EmulationThread = FALSE; + + if (S9xNPConnect ()) + { + S9xClearPause (PAUSE_NETPLAY_CONNECT); + while (NetPlay.Connected) + { + if (S9xNPWaitForHeartBeat ()) + { + LONG prev; + if (!ReleaseSemaphore (GUI.ClientSemaphore, 1, &prev)) + { +#ifdef NP_DEBUG + printf ("CLIENT: ReleaseSemaphore failed - already hit max count (%d) %ld\n", NP_JOYPAD_HIST_SIZE, S9xGetMilliTime () - START); +#endif + S9xNPSetWarning ("NetPlay: Client may be out of sync with server."); + } + else + { + if (!NetPlay.Waiting4EmulationThread && + prev == (int) NetPlay.MaxBehindFrameCount) + { + NetPlay.Waiting4EmulationThread = TRUE; + S9xNPSendPause (TRUE); + } + } + } + else + S9xNPDisconnect (); + } + } + else + { + S9xClearPause (PAUSE_NETPLAY_CONNECT); + } +#ifdef NP_DEBUG + printf ("CLIENT: Client thread exiting @%ld\n", S9xGetMilliTime () - START); +#endif +} +#endif + +bool8 S9xNPCheckForHeartBeat (uint32 time_msec) +{ + fd_set read_fds; + struct timeval timeout; + int res; + int i; + + int max_fd = NetPlay.Socket; + + FD_ZERO (&read_fds); + FD_SET (NetPlay.Socket, &read_fds); + + timeout.tv_sec = 0; + timeout.tv_usec = time_msec * 1000; + res = select (max_fd + 1, &read_fds, NULL, NULL, &timeout); + + i = (res > 0 && FD_ISSET(NetPlay.Socket, &read_fds)); + +#if defined(NP_DEBUG) && NP_DEBUG >= 4 + printf ("CLIENT: S9xCheckForHeartBeat %s @%ld\n", (i?"successful":"still waiting"), S9xGetMilliTime () - START); +#endif + + return i; +} + +bool8 S9xNPWaitForHeartBeatDelay (uint32 time_msec) +{ + if (!S9xNPCheckForHeartBeat(time_msec)) + return FALSE; + + if (!S9xNPWaitForHeartBeat()) + { + S9xNPDisconnect(); + return FALSE; + } + + return TRUE; +} + +bool8 S9xNPWaitForHeartBeat () +{ + uint8 header [3 + 4 + 4 * 5]; + + while (S9xNPGetData (NetPlay.Socket, header, 3 + 4)) + { + if (header [0] != NP_SERV_MAGIC) + { + S9xNPSetError ("Bad magic value from server while waiting for heart-beat message\n"); + S9xNPDisconnect (); + return (FALSE); + } + if (header [1] != NetPlay.ServerSequenceNum) + { + char buf [200]; + sprintf (buf, "Unexpected message sequence number from server, expected %d, got %d\n", NetPlay.ServerSequenceNum, header [1]); + S9xNPSetWarning (buf); + NetPlay.ServerSequenceNum = header [1] + 1; + } + else + NetPlay.ServerSequenceNum++; + + if ((header [2] & 0x1f) == NP_SERV_JOYPAD) + { + // Top 2 bits + 1 of opcode is joypad data count. + int num = (header [2] >> 6) + 1; + + if (num) + { + if (!S9xNPGetData (NetPlay.Socket, header + 3 + 4, num * 4)) + { + S9xNPSetError ("Error while receiving 'JOYPAD' message."); + S9xNPDisconnect (); + return (FALSE); + } + } + NetPlay.Frame [NetPlay.JoypadWriteInd] = READ_LONG (&header [3]); + + int i; + + for (i = 0; i < num; i++) + NetPlay.Joypads [NetPlay.JoypadWriteInd][i] = READ_LONG (&header [3 + 4 + i * sizeof (uint32)]); + + for (i = 0; i < NP_MAX_CLIENTS; i++) + NetPlay.JoypadsReady [NetPlay.JoypadWriteInd][i] = TRUE; + + NetPlay.Paused = (header [2] & 0x20) != 0; + + NetPlay.JoypadWriteInd = (NetPlay.JoypadWriteInd + 1) % NP_JOYPAD_HIST_SIZE; + + if (NetPlay.JoypadWriteInd != (NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE) + { + //printf ("(%d)", (NetPlay.JoypadWriteInd - NetPlay.JoypadReadInd) % NP_JOYPAD_HIST_SIZE); fflush (stdout); + } +//printf ("CLIENT: HB: @%d\n", S9xGetMilliTime () - START); + return (TRUE); + } + else + { + uint32 len = READ_LONG (&header [3]); + switch (header [2] & 0x1f) + { + case NP_SERV_RESET: +#ifdef NP_DEBUG + printf ("CLIENT: RESET received @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPDiscardHeartbeats (); + S9xReset (); + NetPlay.FrameCount = READ_LONG (&header [3]); + S9xNPResetJoypadReadPos (); + S9xNPSendReady (); + break; + case NP_SERV_PAUSE: + NetPlay.Paused = (header [2] & 0x20) != 0; + if (NetPlay.Paused) + S9xNPSetWarning("CLIENT: Server has paused."); + else + S9xNPSetWarning("CLIENT: Server has resumed."); + break; + case NP_SERV_LOAD_ROM: +#ifdef NP_DEBUG + printf ("CLIENT: LOAD_ROM received @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPDiscardHeartbeats (); + if (S9xNPLoadROM (len - 7)) + S9xNPSendReady (NP_CLNT_LOADED_ROM); + break; + case NP_SERV_ROM_IMAGE: +#ifdef NP_DEBUG + printf ("CLIENT: ROM_IMAGE received @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPDiscardHeartbeats (); + if (S9xNPGetROMImage (len - 7)) + S9xNPSendReady (NP_CLNT_RECEIVED_ROM_IMAGE); + break; + case NP_SERV_SRAM_DATA: +#ifdef NP_DEBUG + printf ("CLIENT: SRAM_DATA received @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPDiscardHeartbeats (); + S9xNPGetSRAMData (len - 7); + break; + case NP_SERV_FREEZE_FILE: +#ifdef NP_DEBUG + printf ("CLIENT: FREEZE_FILE received @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPDiscardHeartbeats (); + S9xNPGetFreezeFile (len - 7); + S9xNPResetJoypadReadPos (); + S9xNPSendReady (); + break; + default: +#ifdef NP_DEBUG + printf ("CLIENT: UNKNOWN received @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPDisconnect (); + return (FALSE); + } + } + } + + S9xNPDisconnect (); + return (FALSE); +} + +bool8 S9xNPLoadROMDialog (const char *rom_name) +{ + NetPlay.Answer = FALSE; + +#ifdef __WIN32__ + ResetEvent (NetPlay.ReplyEvent); + +#ifdef NP_DEBUG + printf ("CLIENT: Asking GUI thread to open ROM load dialog...\n"); +#endif + + PostMessage (GUI.hWnd, WM_USER + 3, (uint32) rom_name, (uint32) rom_name); + +#ifdef NP_DEBUG + printf ("CLIENT: Waiting for reply from GUI thread...\n"); +#endif + + WaitForSingleObject (NetPlay.ReplyEvent, INFINITE); + +#ifdef NP_DEBUG + printf ("CLIENT: Got reply from GUI thread (%d)\n", NetPlay.Answer); +#endif + +#else + NetPlay.Answer = TRUE; +#endif + + return (NetPlay.Answer); +} + +bool8 S9xNPLoadROM (uint32 len) +{ + uint8 *data = new uint8 [len]; + + S9xNPSetAction ("Receiving ROM name..."); + if (!S9xNPGetData (NetPlay.Socket, data, len)) + { + S9xNPSetError ("Error while receiving ROM name."); + delete data; + S9xNPDisconnect (); + return (FALSE); + } + + S9xNPSetAction ("Opening LoadROM dialog..."); + if (!S9xNPLoadROMDialog ((char *) data)) + { + S9xNPSetError ("Disconnected from NetPlay server because you are playing a different game!"); + delete data; + S9xNPDisconnect (); + return (FALSE); + } + delete data; + return (TRUE); +} + +bool8 S9xNPGetROMImage (uint32 len) +{ + uint8 rom_info [5]; + + S9xNPSetAction ("Receiving ROM information..."); + if (!S9xNPGetData (NetPlay.Socket, rom_info, 5)) + { + S9xNPSetError ("Error while receiving ROM information."); + S9xNPDisconnect (); + return (FALSE); + } + uint32 CalculatedSize = READ_LONG (&rom_info [1]); +#ifdef NP_DEBUG + printf ("CLIENT: Hi-ROM: %s, Size: %04x\n", rom_info [0] ? "Y" : "N", CalculatedSize); +#endif + if (CalculatedSize + 5 >= len || + CalculatedSize >= CMemory::MAX_ROM_SIZE) + { + S9xNPSetError ("Size error in ROM image data received from server."); + S9xNPDisconnect (); + return (FALSE); + } + + Memory.HiROM = rom_info [0]; + Memory.LoROM = !Memory.HiROM; + Memory.HeaderCount = 0; + Memory.CalculatedSize = CalculatedSize; + + // Load up ROM image +#ifdef NP_DEBUG + printf ("CLIENT: Receiving ROM image @%ld...\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Receiving ROM image..."); + if (!S9xNPGetData (NetPlay.Socket, Memory.ROM, Memory.CalculatedSize)) + { + S9xNPSetError ("Error while receiving ROM image from server."); + Settings.StopEmulation = TRUE; + S9xNPDisconnect (); + return (FALSE); + } +#ifdef NP_DEBUG + printf ("CLIENT: Receiving ROM filename @%ld...\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Receiving ROM filename..."); + uint32 filename_len = len - Memory.CalculatedSize - 5; + if (filename_len > PATH_MAX || + !S9xNPGetData (NetPlay.Socket, (uint8 *) Memory.ROMFilename, filename_len)) + { + S9xNPSetError ("Error while receiving ROM filename from server."); + S9xNPDisconnect (); + Settings.StopEmulation = TRUE; + return (FALSE); + } + Memory.InitROM (); + S9xReset (); + S9xNPResetJoypadReadPos (); + Settings.StopEmulation = FALSE; + +#ifdef __WIN32__ + PostMessage (GUI.hWnd, WM_NULL, 0, 0); +#endif + + return (TRUE); +} + +void S9xNPGetSRAMData (uint32 len) +{ + if (len > 0x10000) + { + S9xNPSetError ("Length error in S-RAM data received from server."); + S9xNPDisconnect (); + return; + } + S9xNPSetAction ("Receiving S-RAM data..."); + if (len > 0 && !S9xNPGetData (NetPlay.Socket, Memory.SRAM, len)) + { + S9xNPSetError ("Error while receiving S-RAM data from server."); + S9xNPDisconnect (); + } + S9xNPSetAction ("", TRUE); +} + +void S9xNPGetFreezeFile (uint32 len) +{ + uint8 frame_count [4]; + +#ifdef NP_DEBUG + printf ("CLIENT: Receiving freeze file information @%ld...\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Receiving freeze file information..."); + if (!S9xNPGetData (NetPlay.Socket, frame_count, 4)) + { + S9xNPSetError ("Error while receiving freeze file information from server."); + S9xNPDisconnect (); + return; + } + NetPlay.FrameCount = READ_LONG (frame_count); + +#ifdef NP_DEBUG + printf ("CLIENT: Receiving freeze file @%ld...\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Receiving freeze file..."); + uint8 *data = new uint8 [len]; + if (!S9xNPGetData (NetPlay.Socket, data, len - 4)) + { + S9xNPSetError ("Error while receiving freeze file from server."); + S9xNPDisconnect (); + delete data; + return; + } + S9xNPSetAction ("", TRUE); + + //FIXME: Setting umask here wouldn't hurt. + FILE *file; +#ifdef HAVE_MKSTEMP + int fd; + char fname[] = "/tmp/snes9x_fztmpXXXXXX"; + if ((fd = mkstemp(fname)) >= 0) + { + if ((file = fdopen (fd, "wb"))) +#else + char fname [L_tmpnam]; + if (tmpnam (fname)) + { + if ((file = fopen (fname, "wb"))) +#endif + { + if (fwrite (data, 1, len, file) == len) + { + fclose(file); +#ifndef __WIN32__ + /* We need .s96 extension, else .s96 is addded by unix code */ + char buf[PATH_MAX +1 ]; + + strncpy(buf, fname, PATH_MAX); + strcat(buf, ".s96"); + + rename(fname, buf); + + if (!S9xUnfreezeGame (buf)) +#else + if (!S9xUnfreezeGame (fname)) +#endif + S9xNPSetError ("Unable to load freeze file just received."); + } else { + S9xNPSetError ("Failed to write to temporary freeze file."); + fclose(file); + } + } else + S9xNPSetError ("Failed to create temporary freeze file."); + remove (fname); + } else + S9xNPSetError ("Unable to get name for temporary freeze file."); + delete data; +} + +uint32 S9xNPGetJoypad (int which1) +{ + if (Settings.NetPlay && which1 < 8) + { +#ifdef NP_DEBUG + if(!NetPlay.JoypadsReady [NetPlay.JoypadReadInd][which1]) + { + S9xNPSetWarning ("Missing input from server!"); + } +#endif + NetPlay.JoypadsReady [NetPlay.JoypadReadInd][which1] = FALSE; + + return (NetPlay.Joypads [NetPlay.JoypadReadInd][which1]); + } + + return (0); +} + +void S9xNPStepJoypadHistory () +{ + if ((NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE != NetPlay.JoypadWriteInd) + { + NetPlay.JoypadReadInd = (NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE; + if (NetPlay.FrameCount != NetPlay.Frame [NetPlay.JoypadReadInd]) + { + S9xNPSetWarning ("This Snes9X session may be out of sync with the server."); +#ifdef NP_DEBUG + printf ("*** CLIENT: client out of sync with server (%d, %d) @%ld\n", NetPlay.FrameCount, NetPlay.Frame [NetPlay.JoypadReadInd], S9xGetMilliTime () - START); +#endif + } + } + else + { +#ifdef NP_DEBUG + printf ("*** CLIENT: S9xNPStepJoypadHistory NOT OK@%ld\n", S9xGetMilliTime () - START); +#endif + } +} + + +void S9xNPResetJoypadReadPos () +{ +#ifdef NP_DEBUG + printf ("CLIENT: ResetJoyReadPos @%ld\n", S9xGetMilliTime () - START); fflush (stdout); +#endif + NetPlay.JoypadWriteInd = 0; + NetPlay.JoypadReadInd = NP_JOYPAD_HIST_SIZE - 1; + for (int h = 0; h < NP_JOYPAD_HIST_SIZE; h++) + memset ((void *) &NetPlay.Joypads [h], 0, sizeof (NetPlay.Joypads [0])); + for (int h = 0; h < NP_JOYPAD_HIST_SIZE; h++) + memset ((void *) &NetPlay.JoypadsReady [h], 0, sizeof (NetPlay.JoypadsReady [0])); +} + +bool8 S9xNPSendJoypadUpdate (uint32 joypad) +{ + uint8 data [7]; + uint8 *ptr = data; + + *ptr++ = NP_CLNT_MAGIC; + *ptr++ = NetPlay.MySequenceNum++; + *ptr++ = NP_CLNT_JOYPAD; + + joypad |= 0x80000000; + + WRITE_LONG (ptr, joypad); + if (!S9xNPSendData (NetPlay.Socket, data, 7)) + { + S9xNPSetError ("Error while sending joypad data server."); + S9xNPDisconnect (); + return (FALSE); + } + return (TRUE); +} + +void S9xNPDisconnect () +{ + close (NetPlay.Socket); + NetPlay.Socket = -1; + NetPlay.Connected = FALSE; + Settings.NetPlay = FALSE; +} + +bool8 S9xNPSendData (int socket, const uint8 *data, int length) +{ + int len = length; + const uint8 *ptr = data; + + NetPlay.PercentageComplete = 0; + + do + { + if (NetPlay.Abort) + return (FALSE); + + int num_bytes = len; + + // Write the data in small chunks, allowing this thread to spot an + // abort request from another thread. + if (num_bytes > 512) + num_bytes = 512; + + int sent = write (socket, (char *) ptr, num_bytes); + if (sent < 0) + { + if (errno == EINTR +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif + ) + { +#ifdef NP_DEBUG + printf ("CLIENT: EINTR, EAGAIN or EWOULDBLOCK while sending data @%ld\n", S9xGetMilliTime () - START); +#endif + continue; + } + return (FALSE); + } + else + if (sent == 0) + return (FALSE); + len -= sent; + ptr += sent; + + NetPlay.PercentageComplete = (uint8) (((length - len) * 100) / length); + } while (len > 0); + + return (TRUE); +} + +bool8 S9xNPGetData (int socket, uint8 *data, int length) +{ + int len = length; + uint8 *ptr = data; + int chunk = length / 50; + + if (chunk < 1024) + chunk = 1024; + + NetPlay.PercentageComplete = 0; + do + { + if (NetPlay.Abort) + return (FALSE); + + int num_bytes = len; + + // Read the data in small chunks, allowing this thread to spot an + // abort request from another thread. + if (num_bytes > chunk) + num_bytes = chunk; + + int got = read (socket, (char *) ptr, num_bytes); + if (got < 0) + { + if (errno == EINTR +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif +#ifdef WSAEWOULDBLOCK + || errno == WSAEWOULDBLOCK +#endif + ) + { +#ifdef NP_DEBUG + printf ("CLIENT: EINTR, EAGAIN or EWOULDBLOCK while receiving data @%ld\n", S9xGetMilliTime () - START); +#endif + continue; + } +#ifdef WSAEMSGSIZE + if (errno != WSAEMSGSIZE) + return (FALSE); + else + { + got = num_bytes; +#ifdef NP_DEBUG + printf ("CLIENT: WSAEMSGSIZE, actual bytes %d while receiving data @%ld\n", got, S9xGetMilliTime () - START); +#endif + } +#else + return (FALSE); +#endif + } + else + if (got == 0) + return (FALSE); + + len -= got; + ptr += got; + + if (!Settings.NetPlayServer && length > 1024) + { + NetPlay.PercentageComplete = (uint8) (((length - len) * 100) / length); +#ifdef __WIN32__ + PostMessage (GUI.hWnd, WM_USER, NetPlay.PercentageComplete, + NetPlay.PercentageComplete); + Sleep (0); +#endif + } + + } while (len > 0); + + return (TRUE); +} + +bool8 S9xNPInitialise () +{ +#ifdef __WIN32__ + static bool8 initialised = FALSE; + + if (!initialised) + { + initialised = TRUE; + WSADATA data; + +#ifdef NP_DEBUG + START = S9xGetMilliTime (); + + printf ("CLIENT/SERVER: Initialising WinSock @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Initialising Windows sockets interface..."); + if (WSAStartup (MAKEWORD (1, 0), &data) != 0) + { + S9xNPSetError ("Call to init Windows sockets failed. Do you have WinSock2 installed?"); + return (FALSE); + } + } +#endif + return (TRUE); +} + +void S9xNPDiscardHeartbeats () +{ + // Discard any pending heartbeats and wait for any frame that is currently + // being emulated to complete. +#ifdef NP_DEBUG + printf ("CLIENT: DiscardHeartbeats @%ld, finished @", S9xGetMilliTime () - START); + fflush (stdout); +#endif + +#ifdef __WIN32__ + while (WaitForSingleObject (GUI.ClientSemaphore, 200) == WAIT_OBJECT_0) + ; +#endif + +#ifdef NP_DEBUG + printf ("%ld\n", S9xGetMilliTime () - START); +#endif + NetPlay.Waiting4EmulationThread = FALSE; +} + +void S9xNPSetAction (const char *action, bool8 force) +{ +#ifdef NP_DEBUG + printf ("NPSetAction: %s, forced = %d %ld\n", action, force, S9xGetMilliTime () - START); +#endif + if (force || !Settings.NetPlayServer) + { + strncpy (NetPlay.ActionMsg, action, NP_MAX_ACTION_LEN - 1); + NetPlay.ActionMsg [NP_MAX_ACTION_LEN - 1] = 0; +#ifdef __WIN32__ + PostMessage (GUI.hWnd, WM_USER, 0, 0); + Sleep (0); +#endif + } +} + +void S9xNPSetError (const char *error) +{ +#if defined(NP_DEBUG) && NP_DEBUG == 2 + printf("ERROR: %s\n", error); + fflush (stdout); +#endif + strncpy (NetPlay.ErrorMsg, error, NP_MAX_ACTION_LEN - 1); + NetPlay.ErrorMsg [NP_MAX_ACTION_LEN - 1] = 0; +#ifdef __WIN32__ + PostMessage (GUI.hWnd, WM_USER + 1, 0, 0); + Sleep (0); +#endif +} + +void S9xNPSetWarning (const char *warning) +{ +#if defined(NP_DEBUG) && NP_DEBUG == 3 + printf("Warning: %s\n", warning); + fflush (stdout); +#endif + strncpy (NetPlay.WarningMsg, warning, NP_MAX_ACTION_LEN - 1); + NetPlay.WarningMsg [NP_MAX_ACTION_LEN - 1] = 0; +#ifdef __WIN32__ + PostMessage (GUI.hWnd, WM_USER + 2, 0, 0); + Sleep (0); +#endif +} +#endif diff --git a/netplay.h b/netplay.h new file mode 100644 index 00000000..b28bcace --- /dev/null +++ b/netplay.h @@ -0,0 +1,375 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _NETPLAY_H_ +#define _NETPLAY_H_ + +/* + * Client to server joypad update + * + * magic 1 + * sequence_no 1 + * opcode 1 + * joypad data 4 + * + * Server to client joypad update + * magic 1 + * sequence_no 1 + * opcode 1 + num joypads (top 3 bits) + * joypad data 4 * n + */ + +//#define NP_DEBUG 1 + +#define NP_VERSION 10 +#define NP_JOYPAD_HIST_SIZE 120 +#define NP_DEFAULT_PORT 6096 + +#define NP_MAX_CLIENTS 8 + +#define NP_SERV_MAGIC 'S' +#define NP_CLNT_MAGIC 'C' + +#define NP_CLNT_HELLO 0 +#define NP_CLNT_JOYPAD 1 +#define NP_CLNT_RESET 2 +#define NP_CLNT_PAUSE 3 +#define NP_CLNT_LOAD_ROM 4 +#define NP_CLNT_ROM_IMAGE 5 +#define NP_CLNT_FREEZE_FILE 6 +#define NP_CLNT_SRAM_DATA 7 +#define NP_CLNT_READY 8 +#define NP_CLNT_LOADED_ROM 9 +#define NP_CLNT_RECEIVED_ROM_IMAGE 10 +#define NP_CLNT_WAITING_FOR_ROM_IMAGE 11 + +#define NP_SERV_HELLO 0 +#define NP_SERV_JOYPAD 1 +#define NP_SERV_RESET 2 +#define NP_SERV_PAUSE 3 +#define NP_SERV_LOAD_ROM 4 +#define NP_SERV_ROM_IMAGE 5 +#define NP_SERV_FREEZE_FILE 6 +#define NP_SERV_SRAM_DATA 7 +#define NP_SERV_READY 8 + +struct SNPClient +{ + volatile uint8 SendSequenceNum; + volatile uint8 ReceiveSequenceNum; + volatile bool8 Connected; + volatile bool8 SaidHello; + volatile bool8 Paused; + volatile bool8 Ready; + int Socket; + char *ROMName; + char *HostName; + char *Who; +}; + +enum { + NP_SERVER_SEND_ROM_IMAGE, + NP_SERVER_SYNC_ALL, + NP_SERVER_SYNC_CLIENT, + NP_SERVER_SEND_FREEZE_FILE_ALL, + NP_SERVER_SEND_ROM_LOAD_REQUEST_ALL, + NP_SERVER_RESET_ALL, + NP_SERVER_SEND_SRAM_ALL, + NP_SERVER_SEND_SRAM +}; + +#define NP_MAX_TASKS 20 + +struct NPServerTask +{ + uint32 Task; + void *Data; +}; + +struct SNPServer +{ + struct SNPClient Clients [NP_MAX_CLIENTS]; + int NumClients; + volatile struct NPServerTask TaskQueue [NP_MAX_TASKS]; + volatile uint32 TaskHead; + volatile uint32 TaskTail; + int Socket; + uint32 FrameTime; + uint32 FrameCount; + char ROMName [30]; + uint32 Joypads [NP_MAX_CLIENTS]; + bool8 ClientPaused; + uint32 Paused; + bool8 SendROMImageOnConnect; + bool8 SyncByReset; +}; + +#define NP_MAX_ACTION_LEN 200 + +struct SNetPlay +{ + volatile uint8 MySequenceNum; + volatile uint8 ServerSequenceNum; + volatile bool8 Connected; + volatile bool8 Abort; + volatile uint8 Player; + volatile bool8 ClientsReady [NP_MAX_CLIENTS]; + volatile bool8 ClientsPaused [NP_MAX_CLIENTS]; + volatile bool8 Paused; + volatile bool8 PendingWait4Sync; + volatile uint8 PercentageComplete; + volatile bool8 Waiting4EmulationThread; + volatile bool8 Answer; +#ifdef __WIN32__ + HANDLE ReplyEvent; +#endif + volatile int Socket; + char *ServerHostName; + char *ROMName; + int Port; + volatile uint32 JoypadWriteInd; + volatile uint32 JoypadReadInd; + uint32 Joypads [NP_JOYPAD_HIST_SIZE][NP_MAX_CLIENTS]; + uint32 Frame [NP_JOYPAD_HIST_SIZE]; + uint32 FrameCount; + uint32 MaxFrameSkip; + uint32 MaxBehindFrameCount; + bool8 JoypadsReady [NP_JOYPAD_HIST_SIZE][NP_MAX_CLIENTS]; + char ActionMsg [NP_MAX_ACTION_LEN]; + char ErrorMsg [NP_MAX_ACTION_LEN]; + char WarningMsg [NP_MAX_ACTION_LEN]; +}; + +extern "C" struct SNetPlay NetPlay; + +// +// NETPLAY_CLIENT_HELLO message format: +// header +// frame_time (4) +// ROMName (variable) + +#define WRITE_LONG(p, v) { \ +*((p) + 0) = (uint8) ((v) >> 24); \ +*((p) + 1) = (uint8) ((v) >> 16); \ +*((p) + 2) = (uint8) ((v) >> 8); \ +*((p) + 3) = (uint8) ((v) >> 0); \ +} + +#define READ_LONG(p) \ +((((uint8) *((p) + 0)) << 24) | \ + (((uint8) *((p) + 1)) << 16) | \ + (((uint8) *((p) + 2)) << 8) | \ + (((uint8) *((p) + 3)) << 0)) + +bool8 S9xNPConnectToServer (const char *server_name, int port, + const char *rom_name); +bool8 S9xNPWaitForHeartBeat (); +bool8 S9xNPWaitForHeartBeatDelay (uint32 time_msec = 0); +bool8 S9xNPCheckForHeartBeat (uint32 time_msec = 0); +uint32 S9xNPGetJoypad (int which1); +bool8 S9xNPSendJoypadUpdate (uint32 joypad); +void S9xNPDisconnect (); +bool8 S9xNPInitialise (); +bool8 S9xNPSendData (int fd, const uint8 *data, int len); +bool8 S9xNPGetData (int fd, uint8 *data, int len); + +void S9xNPSyncClients (); +void S9xNPStepJoypadHistory (); + +void S9xNPResetJoypadReadPos (); +bool8 S9xNPSendReady (uint8 op = NP_CLNT_READY); +bool8 S9xNPSendPause (bool8 pause); +void S9xNPReset (); +void S9xNPSetAction (const char *action, bool8 force = FALSE); +void S9xNPSetError (const char *error); +void S9xNPSetWarning (const char *warning); +void S9xNPDiscardHeartbeats (); +void S9xNPServerQueueSendingFreezeFile (const char *filename); +void S9xNPServerQueueSyncAll (); +void S9xNPServerQueueSendingROMImage (); +void S9xNPServerQueueSendingLoadROMRequest (const char *filename); + +void S9xNPServerAddTask (uint32 task, void *data); + +bool8 S9xNPStartServer (int port); +void S9xNPStopServer (); +#ifdef __WIN32__ +#define S9xGetMilliTime timeGetTime +#else +uint32 S9xGetMilliTime (); +#endif +#endif diff --git a/obc1.cpp b/obc1.cpp new file mode 100644 index 00000000..9fe98de5 --- /dev/null +++ b/obc1.cpp @@ -0,0 +1,276 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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" + + +uint8 S9xGetOBC1 (uint16 Address) +{ + switch (Address) + { + case 0x7ff0: + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2)]); + + case 0x7ff1: + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 1]); + + case 0x7ff2: + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 2]); + + case 0x7ff3: + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 3]); + + case 0x7ff4: + return (Memory.OBC1RAM[OBC1.basePtr + (OBC1.address >> 2) + 0x200]); + } + + return (Memory.OBC1RAM[Address - 0x6000]); +} + +void S9xSetOBC1 (uint8 Byte, uint16 Address) +{ + switch (Address) + { + case 0x7ff0: + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2)] = Byte; + break; + + case 0x7ff1: + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 1] = Byte; + break; + + case 0x7ff2: + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 2] = Byte; + break; + + case 0x7ff3: + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address << 2) + 3] = Byte; + break; + + case 0x7ff4: + { + uint8 Temp; + Temp = Memory.OBC1RAM[OBC1.basePtr + (OBC1.address >> 2) + 0x200]; + Temp = (Temp & ~(3 << OBC1.shift)) | ((Byte & 3) << OBC1.shift); + Memory.OBC1RAM[OBC1.basePtr + (OBC1.address >> 2) + 0x200] = Temp; + break; + } + + case 0x7ff5: + if (Byte & 1) + OBC1.basePtr = 0x1800; + else + OBC1.basePtr = 0x1c00; + break; + + case 0x7ff6: + OBC1.address = Byte & 0x7f; + OBC1.shift = (Byte & 3) << 1; + break; + } + + Memory.OBC1RAM[Address - 0x6000] = Byte; +} + +void S9xResetOBC1 (void) +{ + for (int i = 0; i <= 0x1fff; i++) + Memory.OBC1RAM[i] = 0xff; + + if (Memory.OBC1RAM[0x1ff5] & 1) + OBC1.basePtr = 0x1800; + else + OBC1.basePtr = 0x1c00; + + OBC1.address = Memory.OBC1RAM[0x1ff6] & 0x7f; + OBC1.shift = (Memory.OBC1RAM[0x1ff6] & 3) << 1; +} + +uint8 * S9xGetBasePointerOBC1 (uint16 Address) +{ + if (Address >= 0x7ff0 && Address <= 0x7ff6) + return (NULL); + return (Memory.OBC1RAM - 0x6000); +} + +uint8 * S9xGetMemPointerOBC1 (uint16 Address) +{ + if (Address >= 0x7ff0 && Address <= 0x7ff6) + return (NULL); + return (Memory.OBC1RAM + Address - 0x6000); +} diff --git a/obc1.h b/obc1.h new file mode 100644 index 00000000..836850b7 --- /dev/null +++ b/obc1.h @@ -0,0 +1,196 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _OBC1_H_ +#define _OBC1_H_ + +struct SOBC1 +{ + uint16 address; + uint16 basePtr; + uint16 shift; +}; + +extern struct SOBC1 OBC1; + +void S9xSetOBC1 (uint8, uint16); +uint8 S9xGetOBC1 (uint16); +void S9xResetOBC1 (void); +uint8 * S9xGetBasePointerOBC1 (uint16); +uint8 * S9xGetMemPointerOBC1 (uint16); + +#endif diff --git a/pixform.h b/pixform.h new file mode 100644 index 00000000..1760899c --- /dev/null +++ b/pixform.h @@ -0,0 +1,407 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _PIXFORM_H_ +#define _PIXFORM_H_ + +#ifdef GFX_MULTI_FORMAT + +enum { RGB565, RGB555, BGR565, BGR555, GBR565, GBR555, RGB5551 }; + +#define BUILD_PIXEL(R, G, B) ((*GFX.BuildPixel) (R, G, B)) +#define BUILD_PIXEL2(R, G, B) ((*GFX.BuildPixel2) (R, G, B)) +#define DECOMPOSE_PIXEL(PIX, R, G, B) ((*GFX.DecomposePixel) (PIX, R, G, B)) + +extern uint32 MAX_RED; +extern uint32 MAX_GREEN; +extern uint32 MAX_BLUE; +extern uint32 RED_LOW_BIT_MASK; +extern uint32 GREEN_LOW_BIT_MASK; +extern uint32 BLUE_LOW_BIT_MASK; +extern uint32 RED_HI_BIT_MASK; +extern uint32 GREEN_HI_BIT_MASK; +extern uint32 BLUE_HI_BIT_MASK; +extern uint32 FIRST_COLOR_MASK; +extern uint32 SECOND_COLOR_MASK; +extern uint32 THIRD_COLOR_MASK; +extern uint32 ALPHA_BITS_MASK; +extern uint32 GREEN_HI_BIT; +extern uint32 RGB_LOW_BITS_MASK; +extern uint32 RGB_HI_BITS_MASK; +extern uint32 RGB_HI_BITS_MASKx2; +extern uint32 RGB_REMOVE_LOW_BITS_MASK; +extern uint32 FIRST_THIRD_COLOR_MASK; +extern uint32 TWO_LOW_BITS_MASK; +extern uint32 HIGH_BITS_SHIFTED_TWO_MASK; +extern uint32 SPARE_RGB_BIT_MASK; + +#endif + +/* RGB565 format */ +#define BUILD_PIXEL_RGB565(R, G, B) (((int) (R) << 11) | ((int) (G) << 6) | (int) (B)) +#define BUILD_PIXEL2_RGB565(R, G, B) (((int) (R) << 11) | ((int) (G) << 5) | (int) (B)) +#define DECOMPOSE_PIXEL_RGB565(PIX, R, G, B) { (R) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (B) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_RGB565 (1 << 5) + +#define MAX_RED_RGB565 31 +#define MAX_GREEN_RGB565 63 +#define MAX_BLUE_RGB565 31 +#define RED_LOW_BIT_MASK_RGB565 0x0800 +#define GREEN_LOW_BIT_MASK_RGB565 0x0020 +#define BLUE_LOW_BIT_MASK_RGB565 0x0001 +#define RED_HI_BIT_MASK_RGB565 0x8000 +#define GREEN_HI_BIT_MASK_RGB565 0x0400 +#define BLUE_HI_BIT_MASK_RGB565 0x0010 +#define FIRST_COLOR_MASK_RGB565 0xF800 +#define SECOND_COLOR_MASK_RGB565 0x07E0 +#define THIRD_COLOR_MASK_RGB565 0x001F +#define ALPHA_BITS_MASK_RGB565 0x0000 + +/* RGB555 format */ +#define BUILD_PIXEL_RGB555(R, G, B) (((int) (R) << 10) | ((int) (G) << 5) | (int) (B)) +#define BUILD_PIXEL2_RGB555(R, G, B) (((int) (R) << 10) | ((int) (G) << 5) | (int) (B)) +#define DECOMPOSE_PIXEL_RGB555(PIX, R, G, B) { (R) = (PIX) >> 10; (G) = ((PIX) >> 5) & 0x1f; (B) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_RGB555 (1 << 15) + +#define MAX_RED_RGB555 31 +#define MAX_GREEN_RGB555 31 +#define MAX_BLUE_RGB555 31 +#define RED_LOW_BIT_MASK_RGB555 0x0400 +#define GREEN_LOW_BIT_MASK_RGB555 0x0020 +#define BLUE_LOW_BIT_MASK_RGB555 0x0001 +#define RED_HI_BIT_MASK_RGB555 0x4000 +#define GREEN_HI_BIT_MASK_RGB555 0x0200 +#define BLUE_HI_BIT_MASK_RGB555 0x0010 +#define FIRST_COLOR_MASK_RGB555 0x7C00 +#define SECOND_COLOR_MASK_RGB555 0x03E0 +#define THIRD_COLOR_MASK_RGB555 0x001F +#define ALPHA_BITS_MASK_RGB555 0x0000 + +/* BGR565 format */ +#define BUILD_PIXEL_BGR565(R, G, B) (((int) (B) << 11) | ((int) (G) << 6) | (int) (R)) +#define BUILD_PIXEL2_BGR565(R, G, B) (((int) (B) << 11) | ((int) (G) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_BGR565(PIX, R, G, B) { (B) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_BGR565 (1 << 5) + +#define MAX_RED_BGR565 31 +#define MAX_GREEN_BGR565 63 +#define MAX_BLUE_BGR565 31 +#define RED_LOW_BIT_MASK_BGR565 0x0001 +#define GREEN_LOW_BIT_MASK_BGR565 0x0040 +#define BLUE_LOW_BIT_MASK_BGR565 0x0800 +#define RED_HI_BIT_MASK_BGR565 0x0010 +#define GREEN_HI_BIT_MASK_BGR565 0x0400 +#define BLUE_HI_BIT_MASK_BGR565 0x8000 +#define FIRST_COLOR_MASK_BGR565 0xF800 +#define SECOND_COLOR_MASK_BGR565 0x07E0 +#define THIRD_COLOR_MASK_BGR565 0x001F +#define ALPHA_BITS_MASK_BGR565 0x0000 + +/* BGR555 format */ +#define BUILD_PIXEL_BGR555(R, G, B) (((int) (B) << 10) | ((int) (G) << 5) | (int) (R)) +#define BUILD_PIXEL2_BGR555(R, G, B) (((int) (B) << 10) | ((int) (G) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_BGR555(PIX, R, G, B) { (B) = (PIX) >> 10; (G) = ((PIX) >> 5) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_BGR555 (1 << 15) + +#define MAX_RED_BGR555 31 +#define MAX_GREEN_BGR555 31 +#define MAX_BLUE_BGR555 31 +#define RED_LOW_BIT_MASK_BGR555 0x0001 +#define GREEN_LOW_BIT_MASK_BGR555 0x0020 +#define BLUE_LOW_BIT_MASK_BGR555 0x0400 +#define RED_HI_BIT_MASK_BGR555 0x0010 +#define GREEN_HI_BIT_MASK_BGR555 0x0200 +#define BLUE_HI_BIT_MASK_BGR555 0x4000 +#define FIRST_COLOR_MASK_BGR555 0x7C00 +#define SECOND_COLOR_MASK_BGR555 0x03E0 +#define THIRD_COLOR_MASK_BGR555 0x001F +#define ALPHA_BITS_MASK_BGR555 0x0000 + +/* GBR565 format */ +#define BUILD_PIXEL_GBR565(R, G, B) (((int) (G) << 11) | ((int) (B) << 6) | (int) (R)) +#define BUILD_PIXEL2_GBR565(R, G, B) (((int) (G) << 11) | ((int) (B) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_GBR565(PIX, R, G, B) { (G) = (PIX) >> 11; (B) = ((PIX) >> 6) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_GBR565 (1 << 5) + +#define MAX_RED_GBR565 31 +#define MAX_GREEN_GBR565 31 +#define MAX_BLUE_GBR565 63 +#define RED_LOW_BIT_MASK_GBR565 0x0001 +#define GREEN_LOW_BIT_MASK_GBR565 0x0800 +#define BLUE_LOW_BIT_MASK_GBR565 0x0040 +#define RED_HI_BIT_MASK_GBR565 0x0010 +#define GREEN_HI_BIT_MASK_GBR565 0x8000 +#define BLUE_HI_BIT_MASK_GBR565 0x0400 +#define FIRST_COLOR_MASK_GBR565 0xF800 +#define SECOND_COLOR_MASK_GBR565 0x07E0 +#define THIRD_COLOR_MASK_GBR565 0x001F +#define ALPHA_BITS_MASK_GBR565 0x0000 + +/* GBR555 format */ +#define BUILD_PIXEL_GBR555(R, G, B) (((int) (G) << 10) | ((int) (B) << 5) | (int) (R)) +#define BUILD_PIXEL2_GBR555(R, G, B) (((int) (G) << 10) | ((int) (B) << 5) | (int) (R)) +#define DECOMPOSE_PIXEL_GBR555(PIX, R, G, B) { (G) = (PIX) >> 10; (B) = ((PIX) >> 5) & 0x1f; (R) = (PIX) & 0x1f; } +#define SPARE_RGB_BIT_MASK_GBR555 (1 << 15) + +#define MAX_RED_GBR555 31 +#define MAX_GREEN_GBR555 31 +#define MAX_BLUE_GBR555 31 +#define RED_LOW_BIT_MASK_GBR555 0x0001 +#define GREEN_LOW_BIT_MASK_GBR555 0x0400 +#define BLUE_LOW_BIT_MASK_GBR555 0x0020 +#define RED_HI_BIT_MASK_GBR555 0x0010 +#define GREEN_HI_BIT_MASK_GBR555 0x4000 +#define BLUE_HI_BIT_MASK_GBR555 0x0200 +#define FIRST_COLOR_MASK_GBR555 0x7C00 +#define SECOND_COLOR_MASK_GBR555 0x03E0 +#define THIRD_COLOR_MASK_GBR555 0x001F +#define ALPHA_BITS_MASK_GBR555 0x0000 + +/* RGB5551 format */ +#define BUILD_PIXEL_RGB5551(R, G, B) (((int) (R) << 11) | ((int) (G) << 6) | (int) ((B) << 1) | 1) +#define BUILD_PIXEL2_RGB5551(R, G, B) (((int) (R) << 11) | ((int) (G) << 6) | (int) ((B) << 1) | 1) +#define DECOMPOSE_PIXEL_RGB5551(PIX, R, G, B) { (R) = (PIX) >> 11; (G) = ((PIX) >> 6) & 0x1f; (B) = ((PIX) >> 1) & 0x1f; } +#define SPARE_RGB_BIT_MASK_RGB5551 (1) + +#define MAX_RED_RGB5551 31 +#define MAX_GREEN_RGB5551 31 +#define MAX_BLUE_RGB5551 31 +#define RED_LOW_BIT_MASK_RGB5551 0x0800 +#define GREEN_LOW_BIT_MASK_RGB5551 0x0040 +#define BLUE_LOW_BIT_MASK_RGB5551 0x0002 +#define RED_HI_BIT_MASK_RGB5551 0x8000 +#define GREEN_HI_BIT_MASK_RGB5551 0x0400 +#define BLUE_HI_BIT_MASK_RGB5551 0x0020 +#define FIRST_COLOR_MASK_RGB5551 0xf800 +#define SECOND_COLOR_MASK_RGB5551 0x07c0 +#define THIRD_COLOR_MASK_RGB5551 0x003e +#define ALPHA_BITS_MASK_RGB5551 0x0001 + +#ifndef GFX_MULTI_FORMAT + +#define CONCAT(X, Y) X##Y + +// C pre-processor needs a two stage macro define to enable it to concat +// to macro names together to form the name of another macro. +#define BUILD_PIXEL_D(F, R, G, B) CONCAT(BUILD_PIXEL_,F) (R, G, B) +#define BUILD_PIXEL2_D(F, R, G, B) CONCAT(BUILD_PIXEL2_,F) (R, G, B) +#define DECOMPOSE_PIXEL_D(F, PIX, R, G, B) CONCAT(DECOMPOSE_PIXEL_,F) (PIX, R, G, B) + +#define BUILD_PIXEL(R, G, B) BUILD_PIXEL_D(PIXEL_FORMAT, R, G, B) +#define BUILD_PIXEL2(R, G, B) BUILD_PIXEL2_D(PIXEL_FORMAT, R, G, B) +#define DECOMPOSE_PIXEL(PIX, R, G, B) DECOMPOSE_PIXEL_D(PIXEL_FORMAT, PIX, R, G, B) + +#define MAX_RED_D(F) CONCAT(MAX_RED_, F) +#define MAX_GREEN_D(F) CONCAT(MAX_GREEN_, F) +#define MAX_BLUE_D(F) CONCAT(MAX_BLUE_, F) +#define RED_LOW_BIT_MASK_D(F) CONCAT(RED_LOW_BIT_MASK_, F) +#define GREEN_LOW_BIT_MASK_D(F) CONCAT(GREEN_LOW_BIT_MASK_, F) +#define BLUE_LOW_BIT_MASK_D(F) CONCAT(BLUE_LOW_BIT_MASK_, F) +#define RED_HI_BIT_MASK_D(F) CONCAT(RED_HI_BIT_MASK_, F) +#define GREEN_HI_BIT_MASK_D(F) CONCAT(GREEN_HI_BIT_MASK_, F) +#define BLUE_HI_BIT_MASK_D(F) CONCAT(BLUE_HI_BIT_MASK_, F) +#define FIRST_COLOR_MASK_D(F) CONCAT(FIRST_COLOR_MASK_, F) +#define SECOND_COLOR_MASK_D(F) CONCAT(SECOND_COLOR_MASK_, F) +#define THIRD_COLOR_MASK_D(F) CONCAT(THIRD_COLOR_MASK_, F) +#define ALPHA_BITS_MASK_D(F) CONCAT(ALPHA_BITS_MASK_, F) + +#define MAX_RED MAX_RED_D(PIXEL_FORMAT) +#define MAX_GREEN MAX_GREEN_D(PIXEL_FORMAT) +#define MAX_BLUE MAX_BLUE_D(PIXEL_FORMAT) +#define RED_LOW_BIT_MASK RED_LOW_BIT_MASK_D(PIXEL_FORMAT) +#define GREEN_LOW_BIT_MASK GREEN_LOW_BIT_MASK_D(PIXEL_FORMAT) +#define BLUE_LOW_BIT_MASK BLUE_LOW_BIT_MASK_D(PIXEL_FORMAT) +#define RED_HI_BIT_MASK RED_HI_BIT_MASK_D(PIXEL_FORMAT) +#define GREEN_HI_BIT_MASK GREEN_HI_BIT_MASK_D(PIXEL_FORMAT) +#define BLUE_HI_BIT_MASK BLUE_HI_BIT_MASK_D(PIXEL_FORMAT) +#define FIRST_COLOR_MASK FIRST_COLOR_MASK_D(PIXEL_FORMAT) +#define SECOND_COLOR_MASK SECOND_COLOR_MASK_D(PIXEL_FORMAT) +#define THIRD_COLOR_MASK THIRD_COLOR_MASK_D(PIXEL_FORMAT) +#define ALPHA_BITS_MASK ALPHA_BITS_MASK_D(PIXEL_FORMAT) + +#define GREEN_HI_BIT ((MAX_GREEN + 1) >> 1) +#define RGB_LOW_BITS_MASK (RED_LOW_BIT_MASK | GREEN_LOW_BIT_MASK | BLUE_LOW_BIT_MASK) +#define RGB_HI_BITS_MASK (RED_HI_BIT_MASK | GREEN_HI_BIT_MASK | BLUE_HI_BIT_MASK) +#define RGB_HI_BITS_MASKx2 ((RED_HI_BIT_MASK | GREEN_HI_BIT_MASK | BLUE_HI_BIT_MASK) << 1) +#define RGB_REMOVE_LOW_BITS_MASK (~RGB_LOW_BITS_MASK) +#define FIRST_THIRD_COLOR_MASK (FIRST_COLOR_MASK | THIRD_COLOR_MASK) +#define TWO_LOW_BITS_MASK (RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 1)) +#define HIGH_BITS_SHIFTED_TWO_MASK (((FIRST_COLOR_MASK | SECOND_COLOR_MASK | THIRD_COLOR_MASK) & ~TWO_LOW_BITS_MASK ) >> 2) + +#endif + +#endif diff --git a/port.h b/port.h new file mode 100644 index 00000000..f6911329 --- /dev/null +++ b/port.h @@ -0,0 +1,354 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _PORT_H_ +#define _PORT_H_ + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#include + +#ifdef __WIN32__ +#define NOMINMAX +#include +#endif + +#define GFX_MULTI_FORMAT + +#ifdef __WIN32__ +//#define RIGHTSHIFT_IS_SAR +#define RIGHTSHIFT_int8_IS_SAR +#define RIGHTSHIFT_int16_IS_SAR +#define RIGHTSHIFT_int32_IS_SAR +#define SNES_JOY_READ_CALLBACKS +#endif + +#ifdef __MACOSX__ +#undef GFX_MULTI_FORMAT +#define PIXEL_FORMAT RGB555 +#endif + +#ifndef snes9x_types_defined +#define snes9x_types_defined +typedef unsigned char bool8; +#ifdef HAVE_STDINT_H +#include +typedef intptr_t pint; +typedef int8_t int8; +typedef uint8_t uint8; +typedef int16_t int16; +typedef uint16_t uint16; +typedef int32_t int32; +typedef uint32_t uint32; +typedef int64_t int64; +typedef uint64_t uint64; +#else // HAVE_STDINT_H +#ifdef PTR_NOT_INT +typedef long pint; +#else +typedef int pint; +#endif +#ifdef __WIN32__ +#ifdef __BORLANDC__ +#include +#else +typedef signed char int8; +typedef unsigned char uint8; +typedef signed short int16; +typedef unsigned short uint16; +#ifndef WSAAP +// winsock2.h typedefs int32 as well +typedef signed int int32; +#endif +typedef unsigned int uint32; +#endif +typedef unsigned char uint8_t; +typedef signed __int64 int64; +typedef unsigned __int64 uint64; +typedef int socklen_t; +#else // __WIN32__ +typedef signed char int8; +typedef unsigned char uint8; +typedef signed short int16; +typedef unsigned short uint16; +typedef signed int int32; +typedef unsigned int uint32; +#ifdef __GNUC__ +// long long is not part of ISO C++ +__extension__ +#endif +typedef long long int64; +typedef unsigned long long uint64; +#endif // __WIN32__ +#endif // HAVE_STDINT_H +#endif // snes9x_types_defined + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define START_EXTERN_C extern "C" { +#define END_EXTERN_C } + +#ifndef __WIN32__ +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif +#define _MAX_DRIVE 1 +#define _MAX_DIR PATH_MAX +#define _MAX_FNAME PATH_MAX +#define _MAX_EXT PATH_MAX +#define _MAX_PATH PATH_MAX +#else +#ifndef PATH_MAX +#define PATH_MAX _MAX_PATH +#endif +#endif + +#ifndef __WIN32__ +#define ZeroMemory(a, b) memset((a), 0, (b)) +void _splitpath (const char *, char *, char *, char *, char *); +void _makepath (char *, const char *, const char *, const char *, const char *); +#define S9xDisplayString DisplayStringFromBottom +#else +#define snprintf _snprintf +#define strcasecmp stricmp +#define strncasecmp strnicmp +void WinDisplayStringFromBottom(const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); +#define S9xDisplayString WinDisplayStringFromBottom +#endif + +#ifdef __DJGPP +#define SLASH_STR "\\" +#define SLASH_CHAR '\\' +#else +#define SLASH_STR "/" +#define SLASH_CHAR '/' +#endif + +#ifndef SIG_PF +#define SIG_PF void (*) (int) +#endif + +#ifdef __linux +#define TITLE "Snes9x: Linux" +#define SYS_CONFIG_FILE "/etc/snes9x/snes9x.conf" +#endif + +#ifndef TITLE +#define TITLE "Snes9x" +#endif + +#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) +#define LSB_FIRST +#define FAST_LSB_WORD_ACCESS +#else +#define MSB_FIRST +#endif + +#ifdef FAST_LSB_WORD_ACCESS +#define READ_WORD(s) (*(uint16 *) (s)) +#define READ_3WORD(s) (*(uint32 *) (s) & 0x00ffffff) +#define READ_DWORD(s) (*(uint32 *) (s)) +#define WRITE_WORD(s, d) *(uint16 *) (s) = (d) +#define WRITE_3WORD(s, d) *(uint16 *) (s) = (uint16) (d), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16) +#define WRITE_DWORD(s, d) *(uint32 *) (s) = (d) +#else +#define READ_WORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8)) +#define READ_3WORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8) | (*((uint8 *) (s) + 2) << 16)) +#define READ_DWORD(s) (*(uint8 *) (s) | (*((uint8 *) (s) + 1) << 8) | (*((uint8 *) (s) + 2) << 16) | (*((uint8 *) (s) + 3) << 24)) +#define WRITE_WORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8) +#define WRITE_3WORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16) +#define WRITE_DWORD(s, d) *(uint8 *) (s) = (uint8) (d), *((uint8 *) (s) + 1) = (uint8) ((d) >> 8), *((uint8 *) (s) + 2) = (uint8) ((d) >> 16), *((uint8 *) (s) + 3) = (uint8) ((d) >> 24) +#endif + +#define SWAP_WORD(s) (s) = (((s) & 0xff) << 8) | (((s) & 0xff00) >> 8) +#define SWAP_DWORD(s) (s) = (((s) & 0xff) << 24) | (((s) & 0xff00) << 8) | (((s) & 0xff0000) >> 8) | (((s) & 0xff000000) >> 24) + +#include "pixform.h" + +#endif diff --git a/ppu.cpp b/ppu.cpp new file mode 100644 index 00000000..6872f6b3 --- /dev/null +++ b/ppu.cpp @@ -0,0 +1,2233 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "dma.h" +#include "apu/apu.h" +#include "fxemu.h" +#include "sdd1.h" +#include "srtc.h" +#include "controls.h" +#include "movie.h" +#include "display.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif +#ifdef DEBUGGER +#include "debug.h" +#include "missing.h" +#endif + +extern uint8 *HDMAMemPointers[8]; + + +static inline void S9xLatchCounters (bool force) +{ + if (force || (Memory.FillRAM[0x4213] & 0x80)) + { + // Latch h and v counters, like the gun + #ifdef DEBUGGER + missing.h_v_latch = 1; + #endif + #if 0 // #ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; + #endif + + PPU.HVBeamCounterLatched = 1; + PPU.VBeamPosLatched = (uint16) CPU.V_Counter; + + // From byuu: + // All dots are 4 cycles long, except dots 322 and 326. dots 322 and 326 are 6 cycles long. + // This holds true for all scanlines except scanline 240 on non-interlace odd frames. + // The reason for this is because this scanline is only 1360 cycles long, + // instead of 1364 like all other scanlines. + // This makes the effective range of hscan_pos 0-339 at all times. + int32 hc = CPU.Cycles; + + if (Timings.H_Max == Timings.H_Max_Master) // 1364 + { + if (hc >= 1292) + hc -= (ONE_DOT_CYCLE / 2); + if (hc >= 1308) + hc -= (ONE_DOT_CYCLE / 2); + } + + PPU.HBeamPosLatched = (uint16) (hc / ONE_DOT_CYCLE); + + Memory.FillRAM[0x213f] |= 0x40; + } + + if (CPU.V_Counter > PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE)) + PPU.GunVLatch = 1000; +} + +static inline void S9xTryGunLatch (bool force) +{ + if (CPU.V_Counter > PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE)) + { + if (force || (Memory.FillRAM[0x4213] & 0x80)) + { + #ifdef DEBUGGER + missing.h_v_latch = 1; + #endif + #if 0 // #ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PCAtOpcodeStart; + #endif + + PPU.HVBeamCounterLatched = 1; + PPU.VBeamPosLatched = (uint16) PPU.GunVLatch; + PPU.HBeamPosLatched = (uint16) PPU.GunHLatch; + + Memory.FillRAM[0x213f] |= 0x40; + } + + PPU.GunVLatch = 1000; + } +} + +void S9xCheckMissingHTimerPosition (int32 hc) +{ + if (PPU.HTimerPosition == hc) + { + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) + S9xSetIRQ(PPU_IRQ_SOURCE); + else + if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) + S9xSetIRQ(PPU_IRQ_SOURCE); + } +} + +void S9xCheckMissingHTimerHalt (int32 hc_from, int32 range) +{ + if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range))) + { + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) + CPU.IRQPending = 1; + else + if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) + CPU.IRQPending = 1; + } +} + +void S9xCheckMissingHTimerRange (int32 hc_from, int32 range) +{ + if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range))) + { + if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition))) + S9xSetIRQ(PPU_IRQ_SOURCE); + else + if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) + S9xSetIRQ(PPU_IRQ_SOURCE); + } +} + +void S9xUpdateHVTimerPosition (void) +{ + if (PPU.HTimerEnabled) + { + #ifdef DEBUGGER + missing.hirq_pos = PPU.IRQHBeamPos; + #endif + if (PPU.IRQHBeamPos != 0) + { + // IRQ_read + PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE; + if (Timings.H_Max == Timings.H_Max_Master) // 1364 + { + if (PPU.IRQHBeamPos > 322) + PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); + if (PPU.IRQHBeamPos > 326) + PPU.HTimerPosition += (ONE_DOT_CYCLE / 2); + } + + PPU.HTimerPosition += 14; + // /IRQ + PPU.HTimerPosition += 4; + // after CPU executing + PPU.HTimerPosition += 6; + } + else + PPU.HTimerPosition = 10 + 4 + 6; + } + else + PPU.HTimerPosition = 10 + 4 + 6; + + PPU.VTimerPosition = PPU.IRQVBeamPos; + + if ((PPU.HTimerPosition >= Timings.H_Max) && (PPU.IRQHBeamPos < 340)) + { + PPU.HTimerPosition -= Timings.H_Max; + PPU.VTimerPosition++; + // FIXME + if (PPU.VTimerPosition >= Timings.V_Max) + PPU.VTimerPosition = 0; + } + + if (PPU.HTimerPosition < CPU.Cycles) + { + switch (CPU.WhichEvent) + { + case HC_IRQ_1_3_EVENT: + CPU.WhichEvent = HC_HDMA_START_EVENT; + CPU.NextEvent = Timings.HDMAStart; + break; + + case HC_IRQ_3_5_EVENT: + CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT; + CPU.NextEvent = Timings.H_Max; + break; + + case HC_IRQ_5_7_EVENT: + CPU.WhichEvent = HC_HDMA_INIT_EVENT; + CPU.NextEvent = Timings.HDMAInit; + break; + + case HC_IRQ_7_9_EVENT: + CPU.WhichEvent = HC_RENDER_EVENT; + CPU.NextEvent = Timings.RenderPos; + break; + + case HC_IRQ_9_A_EVENT: + CPU.WhichEvent = HC_WRAM_REFRESH_EVENT; + CPU.NextEvent = Timings.WRAMRefreshPos; + break; + + case HC_IRQ_A_1_EVENT: + CPU.WhichEvent = HC_HBLANK_START_EVENT; + CPU.NextEvent = Timings.HBlankStart; + break; + } + } + else + if ((PPU.HTimerPosition < CPU.NextEvent) || (!(CPU.WhichEvent & 1) && (PPU.HTimerPosition == CPU.NextEvent))) + { + CPU.NextEvent = PPU.HTimerPosition; + + switch (CPU.WhichEvent) + { + case HC_HDMA_START_EVENT: + CPU.WhichEvent = HC_IRQ_1_3_EVENT; + break; + + case HC_HCOUNTER_MAX_EVENT: + CPU.WhichEvent = HC_IRQ_3_5_EVENT; + break; + + case HC_HDMA_INIT_EVENT: + CPU.WhichEvent = HC_IRQ_5_7_EVENT; + break; + + case HC_RENDER_EVENT: + CPU.WhichEvent = HC_IRQ_7_9_EVENT; + break; + + case HC_WRAM_REFRESH_EVENT: + CPU.WhichEvent = HC_IRQ_9_A_EVENT; + break; + + case HC_HBLANK_START_EVENT: + CPU.WhichEvent = HC_IRQ_A_1_EVENT; + break; + } + } + else + { + switch (CPU.WhichEvent) + { + case HC_IRQ_1_3_EVENT: + CPU.WhichEvent = HC_HDMA_START_EVENT; + CPU.NextEvent = Timings.HDMAStart; + break; + + case HC_IRQ_3_5_EVENT: + CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT; + CPU.NextEvent = Timings.H_Max; + break; + + case HC_IRQ_5_7_EVENT: + CPU.WhichEvent = HC_HDMA_INIT_EVENT; + CPU.NextEvent = Timings.HDMAInit; + break; + + case HC_IRQ_7_9_EVENT: + CPU.WhichEvent = HC_RENDER_EVENT; + CPU.NextEvent = Timings.RenderPos; + break; + + case HC_IRQ_9_A_EVENT: + CPU.WhichEvent = HC_WRAM_REFRESH_EVENT; + CPU.NextEvent = Timings.WRAMRefreshPos; + break; + + case HC_IRQ_A_1_EVENT: + CPU.WhichEvent = HC_HBLANK_START_EVENT; + CPU.NextEvent = Timings.HBlankStart; + break; + } + } + +#ifdef DEBUGGER + S9xTraceFormattedMessage("--- IRQ settings: H:%d V:%d (%04d, %03d)", PPU.HTimerEnabled, PPU.VTimerEnabled, PPU.HTimerPosition, PPU.VTimerPosition); +#endif +} + +void S9xFixColourBrightness (void) +{ + IPPU.XB = mul_brightness[PPU.Brightness]; + + 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]); + } +} + +void S9xSetPPU (uint8 Byte, uint16 Address) +{ + // MAP_PPU: $2000-$3FFF + + if (CPU.InDMAorHDMA) + { + if (CPU.CurrentDMAorHDMAChannel >= 0 && DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer) + { + // S9xSetPPU() is called to write to DMA[].AAddress + if ((Address & 0xff00) == 0x2100) + { + // Cannot access to Address Bus B ($2100-$21ff) via (H)DMA + return; + } + else + { + // 0x2000-0x3FFF is connected to Address Bus A + // SA1, SuperFX and SRTC are mapped here + // I don't bother for now... + return; + } + } + else + { + // S9xSetPPU() is called to read from $21xx + // Take care of DMA wrapping + if (Address > 0x21ff) + Address = 0x2100 + (Address & 0xff); + } + } + +#ifdef DEBUGGER + if (CPU.InHDMA) + S9xTraceFormattedMessage("--- HDMA PPU %04X -> %02X", Address, Byte); +#endif + + if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3 + // write_port will run the APU until given clock before writing value + S9xAPUWritePort(Address & 3, Byte); + else + if (Address <= 0x2183) + { + switch (Address) + { + case 0x2100: // INIDISP + 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; + } + } + + if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) + { + PPU.OAMAddr = PPU.SavedOAMAddr; + + uint8 tmp = 0; + if (PPU.OAMPriorityRotation) + tmp = (PPU.OAMAddr & 0xfe) >> 1; + if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp) + { + PPU.FirstSprite = tmp; + IPPU.OBJChanged = TRUE; + } + + PPU.OAMFlip = 0; + } + + break; + + case 0x2101: // OBSEL + 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: // OAMADDL + PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte; + PPU.OAMFlip = 2; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif + } + + break; + + case 0x2103: // OAMADDH + PPU.OAMAddr = ((Byte & 1) << 8) | Memory.FillRAM[0x2102]; + PPU.OAMPriorityRotation = (Byte & 0x80) ? 1 : 0; + if (PPU.OAMPriorityRotation) + { + if (PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif + } + } + else + { + if (PPU.FirstSprite != 0) + { + PPU.FirstSprite = 0; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif + } + } + + PPU.OAMFlip = 0; + PPU.OAMReadFlip = 0; + PPU.SavedOAMAddr = PPU.OAMAddr; + + break; + + case 0x2104: // OAMDATA + REGISTER_2104(Byte); + break; + + case 0x2105: // BGMODE + if (Byte != Memory.FillRAM[0x2105]) + { + FLUSH_REDRAW(); + 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; + // BJ: BG3Priority only takes effect if BGMode == 1 and the bit is set + PPU.BG3Priority = ((Byte & 0x0f) == 0x09); + if (PPU.BGMode == 5 || PPU.BGMode == 6) + IPPU.Interlace = Memory.FillRAM[0x2133] & 1; + else + IPPU.Interlace = 0; + #ifdef DEBUGGER + missing.modes[PPU.BGMode] = 1; + #endif + } + + break; + + case 0x2106: // MOSAIC + if (Byte != Memory.FillRAM[0x2106]) + { + FLUSH_REDRAW(); + PPU.MosaicStart = CPU.V_Counter; + if (PPU.MosaicStart > PPU.ScreenHeight) + PPU.MosaicStart = 0; + PPU.Mosaic = (Byte >> 4) + 1; + PPU.BGMosaic[0] = (Byte & 1); + PPU.BGMosaic[1] = (Byte & 2); + PPU.BGMosaic[2] = (Byte & 4); + PPU.BGMosaic[3] = (Byte & 8); + #ifdef DEBUGGER + if ((Byte & 0xf0) && (Byte & 0x0f)) + missing.mosaic = 1; + #endif + } + + break; + + case 0x2107: // BG1SC + if (Byte != Memory.FillRAM[0x2107]) + { + FLUSH_REDRAW(); + PPU.BG[0].SCSize = Byte & 3; + PPU.BG[0].SCBase = (Byte & 0x7c) << 8; + } + + break; + + case 0x2108: // BG2SC + if (Byte != Memory.FillRAM[0x2108]) + { + FLUSH_REDRAW(); + PPU.BG[1].SCSize = Byte & 3; + PPU.BG[1].SCBase = (Byte & 0x7c) << 8; + } + + break; + + case 0x2109: // BG3SC + if (Byte != Memory.FillRAM[0x2109]) + { + FLUSH_REDRAW(); + PPU.BG[2].SCSize = Byte & 3; + PPU.BG[2].SCBase = (Byte & 0x7c) << 8; + } + + break; + + case 0x210a: // BG4SC + if (Byte != Memory.FillRAM[0x210a]) + { + FLUSH_REDRAW(); + PPU.BG[3].SCSize = Byte & 3; + PPU.BG[3].SCBase = (Byte & 0x7c) << 8; + } + + break; + + case 0x210b: // BG12NBA + 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: // BG34NBA + 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: // BG1HOFS, M7HOFS + PPU.BG[0].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[0].HOffset >> 8) & 7); + PPU.M7HOFS = (Byte << 8) | PPU.M7byte; + PPU.BGnxOFSbyte = Byte; + PPU.M7byte = Byte; + break; + + case 0x210e: // BG1VOFS, M7VOFS + PPU.BG[0].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.M7VOFS = (Byte << 8) | PPU.M7byte; + PPU.BGnxOFSbyte = Byte; + PPU.M7byte = Byte; + break; + + case 0x210f: // BG2HOFS + PPU.BG[1].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[1].HOffset >> 8) & 7); + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2110: // BG2VOFS + PPU.BG[1].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2111: // BG3HOFS + PPU.BG[2].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[2].HOffset >> 8) & 7); + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2112: // BG3VOFS + PPU.BG[2].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2113: // BG4HOFS + PPU.BG[3].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[3].HOffset >> 8) & 7); + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2114: // BG4VOFS + PPU.BG[3].VOffset = (Byte << 8) | PPU.BGnxOFSbyte; + PPU.BGnxOFSbyte = Byte; + break; + + case 0x2115: // VMAIN + 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; + } + + if (Byte & 0x0c) + { + static uint16 Shift[4] = { 0, 5, 6, 7 }; + static uint16 IncCount[4] = { 0, 32, 64, 128 }; + + uint8 i = (Byte & 0x0c) >> 2; + PPU.VMA.FullGraphicCount = IncCount[i]; + PPU.VMA.Mask1 = IncCount[i] * 8 - 1; + PPU.VMA.Shift = Shift[i]; + #ifdef DEBUGGER + missing.vram_full_graphic_inc = (Byte & 0x0c) >> 2; + #endif + } + else + PPU.VMA.FullGraphicCount = 0; + #ifdef DEBUGGER + if (Byte & 3) + missing.vram_inc = Byte & 3; + #endif + break; + + case 0x2116: // VMADDL + PPU.VMA.Address &= 0xff00; + PPU.VMA.Address |= Byte; + #ifdef CORRECT_VRAM_READS + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); + #else + IPPU.FirstVRAMRead = TRUE; + #endif + break; + + case 0x2117: // VMADDH + PPU.VMA.Address &= 0x00ff; + PPU.VMA.Address |= Byte << 8; + #ifdef CORRECT_VRAM_READS + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); + #else + IPPU.FirstVRAMRead = TRUE; + #endif + break; + + case 0x2118: // VMDATAL + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + REGISTER_2118(Byte); + break; + + case 0x2119: // VMDATAH + #ifndef CORRECT_VRAM_READS + IPPU.FirstVRAMRead = TRUE; + #endif + REGISTER_2119(Byte); + break; + + case 0x211a: // M7SEL + if (Byte != Memory.FillRAM[0x211a]) + { + FLUSH_REDRAW(); + PPU.Mode7Repeat = Byte >> 6; + if (PPU.Mode7Repeat == 1) + PPU.Mode7Repeat = 0; + PPU.Mode7VFlip = (Byte & 2) >> 1; + PPU.Mode7HFlip = Byte & 1; + } + + break; + + case 0x211b: // M7A + PPU.MatrixA = PPU.M7byte | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + PPU.M7byte = Byte; + break; + + case 0x211c: // M7B + PPU.MatrixB = PPU.M7byte | (Byte << 8); + PPU.Need16x8Mulitply = TRUE; + PPU.M7byte = Byte; + break; + + case 0x211d: // M7C + PPU.MatrixC = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + + case 0x211e: // M7D + PPU.MatrixD = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + + case 0x211f: // M7X + PPU.CentreX = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + + case 0x2120: // M7Y + PPU.CentreY = PPU.M7byte | (Byte << 8); + PPU.M7byte = Byte; + break; + + case 0x2121: // CGADD + PPU.CGFLIP = 0; + PPU.CGFLIPRead = 0; + PPU.CGADD = Byte; + break; + + case 0x2122: // CGDATA + REGISTER_2122(Byte); + break; + + case 0x2123: // W12SEL + 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: // W34SEL + 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: // WOBJSEL + 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: // WH0 + if (Byte != Memory.FillRAM[0x2126]) + { + FLUSH_REDRAW(); + PPU.Window1Left = Byte; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x2127: // WH1 + if (Byte != Memory.FillRAM[0x2127]) + { + FLUSH_REDRAW(); + PPU.Window1Right = Byte; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x2128: // WH2 + if (Byte != Memory.FillRAM[0x2128]) + { + FLUSH_REDRAW(); + PPU.Window2Left = Byte; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x2129: // WH3 + if (Byte != Memory.FillRAM[0x2129]) + { + FLUSH_REDRAW(); + PPU.Window2Right = Byte; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x212a: // WBGLOG + 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: // WOBJLOG + if (Byte != Memory.FillRAM[0x212b]) + { + FLUSH_REDRAW(); + PPU.ClipWindowOverlapLogic[4] = (Byte & 0x03); + PPU.ClipWindowOverlapLogic[5] = (Byte & 0x0c) >> 2; + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x212c: // TM + if (Byte != Memory.FillRAM[0x212c]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x212d: // TS + if (Byte != Memory.FillRAM[0x212d]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + #ifdef DEBUGGER + if (Byte & 0x1f) + missing.subscreen = 1; + #endif + } + + break; + + case 0x212e: // TMW + if (Byte != Memory.FillRAM[0x212e]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x212f: // TSW + if (Byte != Memory.FillRAM[0x212f]) + { + FLUSH_REDRAW(); + PPU.RecomputeClipWindows = TRUE; + } + + break; + + case 0x2130: // CGWSEL + 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: // CGADSUB + if (Byte != Memory.FillRAM[0x2131]) + { + FLUSH_REDRAW(); + #ifdef DEBUGGER + if (Byte & 0x80) + { + if (Memory.FillRAM[0x2130] & 0x02) + missing.subscreen_sub = 1; + else + missing.fixed_colour_sub = 1; + } + else + { + if (Memory.FillRAM[0x2130] & 0x02) + missing.subscreen_add = 1; + else + missing.fixed_colour_add = 1; + } + #endif + } + + break; + + case 0x2132: // COLDATA + if (Byte != Memory.FillRAM[0x2132]) + { + FLUSH_REDRAW(); + if (Byte & 0x80) + PPU.FixedColourBlue = Byte & 0x1f; + if (Byte & 0x40) + PPU.FixedColourGreen = Byte & 0x1f; + if (Byte & 0x20) + PPU.FixedColourRed = Byte & 0x1f; + } + + break; + + case 0x2133: // SETINI + if (Byte != Memory.FillRAM[0x2133]) + { + if ((Memory.FillRAM[0x2133] ^ Byte) & 8) + { + FLUSH_REDRAW(); + IPPU.PseudoHires = Byte & 8; + } + + if (Byte & 0x04) + { + PPU.ScreenHeight = SNES_HEIGHT_EXTENDED; + if (IPPU.DoubleHeightPixels) + IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1; + else + IPPU.RenderedScreenHeight = PPU.ScreenHeight; + #ifdef DEBUGGER + missing.lines_239 = 1; + #endif + } + else + PPU.ScreenHeight = SNES_HEIGHT; + + if ((Memory.FillRAM[0x2133] ^ Byte) & 3) + { + FLUSH_REDRAW(); + if ((Memory.FillRAM[0x2133] ^ Byte) & 2) + IPPU.OBJChanged = TRUE; + if (PPU.BGMode == 5 || PPU.BGMode == 6) + IPPU.Interlace = Byte & 1; + IPPU.InterlaceOBJ = Byte & 2; + } + #ifdef DEBUGGER + if (Byte & 0x40) + missing.mode7_bgmode = 1; + if (Byte & 0x08) + missing.pseudo_512 = 1; + if (Byte & 0x02) + missing.sprite_double_height = 1; + if (Byte & 0x01) + missing.interlace = 1; + #endif + } + + break; + + case 0x2134: // MPYL + case 0x2135: // MPYM + case 0x2136: // MPYH + case 0x2137: // SLHV + case 0x2138: // OAMDATAREAD + case 0x2139: // VMDATALREAD + case 0x213a: // VMDATAHREAD + case 0x213b: // CGDATAREAD + case 0x213c: // OPHCT + case 0x213d: // OPVCT + case 0x213e: // STAT77 + case 0x213f: // STAT78 + return; + + case 0x2180: // WMDATA + if (!CPU.InWRAMDMAorHDMA) + REGISTER_2180(Byte); + break; + + case 0x2181: // WMADDL + if (!CPU.InWRAMDMAorHDMA) + { + PPU.WRAM &= 0x1ff00; + PPU.WRAM |= Byte; + } + + break; + + case 0x2182: // WMADDM + if (!CPU.InWRAMDMAorHDMA) + { + PPU.WRAM &= 0x100ff; + PPU.WRAM |= Byte << 8; + } + + break; + + case 0x2183: // WMADDH + if (!CPU.InWRAMDMAorHDMA) + { + PPU.WRAM &= 0x0ffff; + PPU.WRAM |= Byte << 16; + PPU.WRAM &= 0x1ffff; + } + + break; + } + } + else + { + if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff) + { + S9xSetSuperFX(Byte, Address); + return; + } + else + if (Settings.SA1 && Address >= 0x2200) + { + if (Address <= 0x23ff) + S9xSetSA1(Byte, Address); + else + Memory.FillRAM[Address] = Byte; + return; + } + else + if (Settings.BS && Address >= 0x2188 && Address <= 0x219f) + S9xSetBSXPPU(Byte, Address); + else + if (Settings.SRTC && Address == 0x2801) + S9xSetSRTC(Byte, Address); + #ifdef DEBUGGER + else + { + 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 + } + + Memory.FillRAM[Address] = Byte; +} + +uint8 S9xGetPPU (uint16 Address) +{ + // MAP_PPU: $2000-$3FFF + + if (Address < 0x2100) + return (OpenBus); + + if (CPU.InDMAorHDMA) + { + if (CPU.CurrentDMAorHDMAChannel >= 0 && !DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer) + { + // S9xGetPPU() is called to read from DMA[].AAddress + if ((Address & 0xff00) == 0x2100) + // Cannot access to Address Bus B ($2100-$21FF) via (H)DMA + return (OpenBus); + else + // $2200-$3FFF are connected to Address Bus A + // SA1, SuperFX and SRTC are mapped here + // I don't bother for now... + return (OpenBus); + } + else + { + // S9xGetPPU() is called to write to $21xx + // Take care of DMA wrapping + if (Address > 0x21ff) + Address = 0x2100 + (Address & 0xff); + } + } + + if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3 + // read_port will run the APU until given APU time before reading value + return (S9xAPUReadPort(Address & 3)); + else + if (Address <= 0x2183) + { + uint8 byte; + + switch (Address) + { + case 0x2104: // OAMDATA + case 0x2105: // BGMODE + case 0x2106: // MOSAIC + case 0x2108: // BG2SC + case 0x2109: // BG3SC + case 0x210a: // BG4SC + case 0x2114: // BG4VOFS + case 0x2115: // VMAIN + case 0x2116: // VMADDL + case 0x2118: // VMDATAL + case 0x2119: // VMDATAH + case 0x211a: // M7SEL + case 0x2124: // W34SEL + case 0x2125: // WOBJSEL + case 0x2126: // WH0 + case 0x2128: // WH2 + case 0x2129: // WH3 + case 0x212a: // WBGLOG + return (PPU.OpenBus1); + + case 0x2134: // MPYL + case 0x2135: // MPYM + case 0x2136: // MPYH + 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 (PPU.OpenBus1 = Memory.FillRAM[Address]); + + case 0x2137: // SLHV + S9xLatchCounters(0); + return (OpenBus); + + case 0x2138: // OAMDATAREAD + if (PPU.OAMAddr & 0x100) + { + if (!(PPU.OAMFlip & 1)) + byte = PPU.OAMData[(PPU.OAMAddr & 0x10f) << 1]; + else + { + byte = PPU.OAMData[((PPU.OAMAddr & 0x10f) << 1) + 1]; + PPU.OAMAddr = (PPU.OAMAddr + 1) & 0x1ff; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif + } + } + } + else + { + if (!(PPU.OAMFlip & 1)) + byte = PPU.OAMData[PPU.OAMAddr << 1]; + else + { + byte = PPU.OAMData[(PPU.OAMAddr << 1) + 1]; + ++PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + #ifdef DEBUGGER + missing.sprite_priority_rotation = 1; + #endif + } + } + } + + PPU.OAMFlip ^= 1; + #ifdef DEBUGGER + missing.oam_read = 1; + #endif + return (PPU.OpenBus1 = byte); + + case 0x2139: // VMDATALREAD + #ifdef CORRECT_VRAM_READS + byte = IPPU.VRAMReadBuffer & 0xff; + if (!PPU.VMA.High) + { + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); + + PPU.VMA.Address += PPU.VMA.Increment; + } + #else + if (IPPU.FirstVRAMRead) + byte = Memory.VRAM[(PPU.VMA.Address << 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) - 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; + } + #endif + #ifdef DEBUGGER + missing.vram_read = 1; + #endif + return (PPU.OpenBus1 = byte); + + case 0x213a: // VMDATAHREAD + #ifdef CORRECT_VRAM_READS + byte = (IPPU.VRAMReadBuffer >> 8) & 0xff; + if (PPU.VMA.High) + { + if (PPU.VMA.FullGraphicCount) + { + uint32 addr = PPU.VMA.Address; + uint32 rem = addr & PPU.VMA.Mask1; + uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3); + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff)); + } + else + IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff)); + + PPU.VMA.Address += PPU.VMA.Increment; + } + #else + 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; + } + #endif + #ifdef DEBUGGER + missing.vram_read = 1; + #endif + return (PPU.OpenBus1 = byte); + + case 0x213b: // CGDATAREAD + if (PPU.CGFLIPRead) + byte = (PPU.OpenBus2 & 0x80) | ((PPU.CGDATA[PPU.CGADD++] >> 8) & 0x7f); + else + byte = PPU.CGDATA[PPU.CGADD] & 0xff; + PPU.CGFLIPRead ^= 1; + #ifdef DEBUGGER + missing.cgram_read = 1; + #endif + return (PPU.OpenBus2 = byte); + + case 0x213c: // OPHCT + S9xTryGunLatch(false); + if (PPU.HBeamFlip) + byte = (PPU.OpenBus2 & 0xfe) | ((PPU.HBeamPosLatched >> 8) & 0x01); + else + byte = (uint8) PPU.HBeamPosLatched; + PPU.HBeamFlip ^= 1; + #ifdef DEBUGGER + missing.h_counter_read = 1; + #endif + return (PPU.OpenBus2 = byte); + + case 0x213d: // OPVCT + S9xTryGunLatch(false); + if (PPU.VBeamFlip) + byte = (PPU.OpenBus2 & 0xfe) | ((PPU.VBeamPosLatched >> 8) & 0x01); + else + byte = (uint8) PPU.VBeamPosLatched; + PPU.VBeamFlip ^= 1; + #ifdef DEBUGGER + missing.v_counter_read = 1; + #endif + return (PPU.OpenBus2 = byte); + + case 0x213e: // STAT77 + FLUSH_REDRAW(); + byte = (PPU.OpenBus1 & 0x10) | PPU.RangeTimeOver | Model->_5C77; + return (PPU.OpenBus1 = byte); + + case 0x213f: // STAT78 + S9xTryGunLatch(false); + PPU.VBeamFlip = PPU.HBeamFlip = 0; + byte = (PPU.OpenBus2 & 0x20) | (Memory.FillRAM[0x213f] & 0xc0) | (Settings.PAL ? 0x10 : 0) | Model->_5C78; + Memory.FillRAM[0x213f] &= ~0x40; + return (PPU.OpenBus2 = byte); + + case 0x2180: // WMDATA + if (!CPU.InWRAMDMAorHDMA) + { + byte = Memory.RAM[PPU.WRAM++]; + PPU.WRAM &= 0x1ffff; + } + else + byte = OpenBus; + #ifdef DEBUGGER + missing.wram_read = 1; + #endif + return (byte); + + default: + return (OpenBus); + } + } + else + { + if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff) + return (S9xGetSuperFX(Address)); + else + if (Settings.SA1 && Address >= 0x2200) + return (S9xGetSA1(Address)); + else + if (Settings.BS && Address >= 0x2188 && Address <= 0x219f) + return (S9xGetBSXPPU(Address)); + else + if (Settings.SRTC && Address == 0x2800) + return (S9xGetSRTC(Address)); + else + switch (Address) + { + case 0x21c2: + if (Model->_5C77 == 2) + return (0x20); + return (OpenBus); + + case 0x21c3: + if (Model->_5C77 == 2) + return (0); + return (OpenBus); + + default: + return (OpenBus); + } + } +} + +void S9xSetCPU (uint8 Byte, uint16 Address) +{ + if (Address < 0x4200) + { + CPU.Cycles += ONE_CYCLE; // XSlow + + switch (Address) + { + case 0x4016: // JOYSER0 + S9xSetJoypadLatch(Byte & 1); + break; + + case 0x4017: // JOYSER1 + return; + + default: + break; + } + } + else + if ((Address & 0xff80) == 0x4300) + { + if (CPU.InDMAorHDMA) + return; + + int d = (Address >> 4) & 0x7; + + switch (Address & 0xf) + { + case 0x0: // 0x43x0: DMAPx + DMA[d].ReverseTransfer = (Byte & 0x80) ? TRUE : FALSE; + DMA[d].HDMAIndirectAddressing = (Byte & 0x40) ? TRUE : FALSE; + DMA[d].UnusedBit43x0 = (Byte & 0x20) ? TRUE : FALSE; + DMA[d].AAddressDecrement = (Byte & 0x10) ? TRUE : FALSE; + DMA[d].AAddressFixed = (Byte & 0x08) ? TRUE : FALSE; + DMA[d].TransferMode = (Byte & 7); + return; + + case 0x1: // 0x43x1: BBADx + DMA[d].BAddress = Byte; + return; + + case 0x2: // 0x43x2: A1TxL + DMA[d].AAddress &= 0xff00; + DMA[d].AAddress |= Byte; + return; + + case 0x3: // 0x43x3: A1TxH + DMA[d].AAddress &= 0xff; + DMA[d].AAddress |= Byte << 8; + return; + + case 0x4: // 0x43x4: A1Bx + DMA[d].ABank = Byte; + HDMAMemPointers[d] = NULL; + return; + + case 0x5: // 0x43x5: DASxL + DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff00; + DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte; + HDMAMemPointers[d] = NULL; + return; + + case 0x6: // 0x43x6: DASxH + DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff; + DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte << 8; + HDMAMemPointers[d] = NULL; + return; + + case 0x7: // 0x43x7: DASBx + DMA[d].IndirectBank = Byte; + HDMAMemPointers[d] = NULL; + return; + + case 0x8: // 0x43x8: A2AxL + DMA[d].Address &= 0xff00; + DMA[d].Address |= Byte; + HDMAMemPointers[d] = NULL; + return; + + case 0x9: // 0x43x9: A2AxH + DMA[d].Address &= 0xff; + DMA[d].Address |= Byte << 8; + HDMAMemPointers[d] = NULL; + return; + + case 0xa: // 0x43xa: NLTRx + if (Byte & 0x7f) + { + DMA[d].LineCount = Byte & 0x7f; + DMA[d].Repeat = !(Byte & 0x80); + } + else + { + DMA[d].LineCount = 128; + DMA[d].Repeat = !!(Byte & 0x80); + } + + return; + + case 0xb: // 0x43xb: ????x + case 0xf: // 0x43xf: mirror of 0x43xb + DMA[d].UnknownByte = Byte; + return; + + default: + break; + } + } + else + { + uint16 pos; + + switch (Address) + { + case 0x4200: // NMITIMEN + if (Byte & 0x20) + { + PPU.VTimerEnabled = TRUE; + #ifdef DEBUGGER + missing.virq = 1; + missing.virq_pos = PPU.IRQVBeamPos; + #endif + } + else + PPU.VTimerEnabled = FALSE; + + if (Byte & 0x10) + { + PPU.HTimerEnabled = TRUE; + #ifdef DEBUGGER + missing.hirq = 1; + missing.hirq_pos = PPU.IRQHBeamPos; + #endif + } + else + PPU.HTimerEnabled = FALSE; + + S9xUpdateHVTimerPosition(); + + // The case that IRQ will trigger in an instruction such as STA $4200. + // FIXME: not true but good enough for Snes9x, I think. + S9xCheckMissingHTimerRange(CPU.PrevCycles, CPU.Cycles - CPU.PrevCycles); + + if (!(Byte & 0x30)) + S9xClearIRQ(PPU_IRQ_SOURCE); + + // NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard. + if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) && + (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (Memory.FillRAM[0x4210] & 0x80)) + { + // FIXME: triggered at HC+=6, checked just before the final CPU cycle, + // then, when to call S9xOpcode_NMI()? + CPU.Flags |= NMI_FLAG; + Timings.NMITriggerPos = CPU.Cycles + 6 + 6; + } + + break; + + case 0x4201: // WRIO + if ((Byte & 0x80) == 0 && (Memory.FillRAM[0x4213] & 0x80) == 0x80) + S9xLatchCounters(1); + else + S9xTryGunLatch((Byte & 0x80) ? true : false); + Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = Byte; + break; + + case 0x4202: // WRMPYA + break; + + case 0x4203: // WRMPYB + { + uint32 res = Memory.FillRAM[0x4202] * Byte; + // FIXME: The update occurs 8 machine cycles after $4203 is set. + Memory.FillRAM[0x4216] = (uint8) res; + Memory.FillRAM[0x4217] = (uint8) (res >> 8); + break; + } + + case 0x4204: // WRDIVL + case 0x4205: // WRDIVH + break; + + case 0x4206: // WRDIVB + { + uint16 a = Memory.FillRAM[0x4204] + (Memory.FillRAM[0x4205] << 8); + uint16 div = Byte ? a / Byte : 0xffff; + uint16 rem = Byte ? a % Byte : a; + // FIXME: The update occurs 16 machine cycles after $4206 is set. + Memory.FillRAM[0x4214] = (uint8) div; + Memory.FillRAM[0x4215] = div >> 8; + Memory.FillRAM[0x4216] = (uint8) rem; + Memory.FillRAM[0x4217] = rem >> 8; + break; + } + + case 0x4207: // HTIMEL + pos = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte; + if (PPU.IRQHBeamPos != pos) + S9xUpdateHVTimerPosition(); + #ifdef DEBUGGER + missing.hirq_pos = PPU.IRQHBeamPos; + #endif + break; + + case 0x4208: // HTIMEH + pos = PPU.IRQHBeamPos; + PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8); + if (PPU.IRQHBeamPos != pos) + S9xUpdateHVTimerPosition(); + #ifdef DEBUGGER + missing.hirq_pos = PPU.IRQHBeamPos; + #endif + break; + + case 0x4209: // VTIMEL + pos = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte; + if (PPU.IRQVBeamPos != pos) + S9xUpdateHVTimerPosition(); + #ifdef DEBUGGER + missing.virq_pos = PPU.IRQVBeamPos; + #endif + break; + + case 0x420a: // VTIMEH + pos = PPU.IRQVBeamPos; + PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8); + if (PPU.IRQVBeamPos != pos) + S9xUpdateHVTimerPosition(); + #ifdef DEBUGGER + missing.virq_pos = PPU.IRQVBeamPos; + #endif + break; + + case 0x420b: // MDMAEN + if (CPU.InDMAorHDMA) + return; + // XXX: Not quite right... + if (Byte) + CPU.Cycles += Timings.DMACPUSync; + if (Byte & 0x01) + S9xDoDMA(0); + if (Byte & 0x02) + S9xDoDMA(1); + if (Byte & 0x04) + S9xDoDMA(2); + if (Byte & 0x08) + S9xDoDMA(3); + if (Byte & 0x10) + S9xDoDMA(4); + if (Byte & 0x20) + S9xDoDMA(5); + if (Byte & 0x40) + S9xDoDMA(6); + if (Byte & 0x80) + S9xDoDMA(7); + #ifdef DEBUGGER + missing.dma_this_frame = Byte; + missing.dma_channels = Byte; + #endif + break; + + case 0x420c: // HDMAEN + if (CPU.InDMAorHDMA) + return; + if (Settings.DisableHDMA) + Byte = 0; + Memory.FillRAM[0x420c] = Byte; + // Yoshi's Island, Genjyu Ryodan, Mortal Kombat, Tales of Phantasia + PPU.HDMA = Byte & ~PPU.HDMAEnded; + #ifdef DEBUGGER + missing.hdma_this_frame |= Byte; + missing.hdma_channels |= Byte; + #endif + break; + + case 0x420d: // MEMSEL + 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(); + } + + break; + + case 0x4210: // RDNMI + #if 0 + Memory.FillRAM[0x4210] = Model->_5A22; + #endif + return; + + case 0x4211: // TIMEUP + #if 0 + S9xClearIRQ(PPU_IRQ_SOURCE); + #endif + return; + + case 0x4212: // HVBJOY + case 0x4213: // RDIO + case 0x4214: // RDDIVL + case 0x4215: // RDDIVH + case 0x4216: // RDMPYL + case 0x4217: // RDMPYH + case 0x4218: // JOY1L + case 0x4219: // JOY1H + case 0x421a: // JOY2L + case 0x421b: // JOY2H + case 0x421c: // JOY3L + case 0x421d: // JOY3H + case 0x421e: // JOY4L + case 0x421f: // JOY4H + return; + + default: + if (Settings.SPC7110 && Address >= 0x4800) + S9xSetSPC7110(Byte, Address); + else + if (Settings.SDD1 && Address >= 0x4804 && Address <= 0x4807) + S9xSetSDD1MemoryMap(Address - 0x4804, Byte & 7); + break; + } + } + + Memory.FillRAM[Address] = Byte; +} + +uint8 S9xGetCPU (uint16 Address) +{ + if (Address < 0x4200) + { + #ifdef SNES_JOY_READ_CALLBACKS + extern bool8 pad_read; + if (Address == 0x4016 || Address == 0x4017) + { + S9xOnSNESPadRead(); + pad_read = TRUE; + } + #endif + + CPU.Cycles += ONE_CYCLE; // XSlow + + switch (Address) + { + case 0x4016: // JOYSER0 + case 0x4017: // JOYSER1 + return (S9xReadJOYSERn(Address)); + + default: + return (OpenBus); + } + } + else + if ((Address & 0xff80) == 0x4300) + { + if (CPU.InDMAorHDMA) + return (OpenBus); + + int d = (Address >> 4) & 0x7; + + switch (Address & 0xf) + { + case 0x0: // 0x43x0: DMAPx + return ((DMA[d].ReverseTransfer ? 0x80 : 0) | + (DMA[d].HDMAIndirectAddressing ? 0x40 : 0) | + (DMA[d].UnusedBit43x0 ? 0x20 : 0) | + (DMA[d].AAddressDecrement ? 0x10 : 0) | + (DMA[d].AAddressFixed ? 0x08 : 0) | + (DMA[d].TransferMode & 7)); + + case 0x1: // 0x43x1: BBADx + return (DMA[d].BAddress); + + case 0x2: // 0x43x2: A1TxL + return (DMA[d].AAddress & 0xff); + + case 0x3: // 0x43x3: A1TxH + return (DMA[d].AAddress >> 8); + + case 0x4: // 0x43x4: A1Bx + return (DMA[d].ABank); + + case 0x5: // 0x43x5: DASxL + return (DMA[d].DMACount_Or_HDMAIndirectAddress & 0xff); + + case 0x6: // 0x43x6: DASxH + return (DMA[d].DMACount_Or_HDMAIndirectAddress >> 8); + + case 0x7: // 0x43x7: DASBx + return (DMA[d].IndirectBank); + + case 0x8: // 0x43x8: A2AxL + return (DMA[d].Address & 0xff); + + case 0x9: // 0x43x9: A2AxH + return (DMA[d].Address >> 8); + + case 0xa: // 0x43xa: NLTRx + return (DMA[d].LineCount ^ (DMA[d].Repeat ? 0x00 : 0x80)); + + case 0xb: // 0x43xb: ????x + case 0xf: // 0x43xf: mirror of 0x43xb + return (DMA[d].UnknownByte); + + default: + return (OpenBus); + } + } + else + { + uint8 byte; + + switch (Address) + { + case 0x4210: // RDNMI + #ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; + #endif + byte = Memory.FillRAM[0x4210]; + Memory.FillRAM[0x4210] = Model->_5A22; + return ((byte & 0x80) | (OpenBus & 0x70) | Model->_5A22); + + case 0x4211: // TIMEUP + byte = (CPU.IRQActive & PPU_IRQ_SOURCE) ? 0x80 : 0; + S9xClearIRQ(PPU_IRQ_SOURCE); + return (byte | (OpenBus & 0x7f)); + + case 0x4212: // HVBJOY + #ifdef CPU_SHUTDOWN + CPU.WaitAddress = CPU.PBPCAtOpcodeStart; + #endif + return (REGISTER_4212() | (OpenBus & 0x3e)); + + case 0x4213: // RDIO + return (Memory.FillRAM[0x4213]); + + case 0x4214: // RDDIVL + case 0x4215: // RDDIVH + case 0x4216: // RDMPYL + case 0x4217: // RDMPYH + return (Memory.FillRAM[Address]); + + case 0x4218: // JOY1L + case 0x4219: // JOY1H + case 0x421a: // JOY2L + case 0x421b: // JOY2H + case 0x421c: // JOY3L + case 0x421d: // JOY3H + case 0x421e: // JOY4L + case 0x421f: // JOY4H + #ifdef SNES_JOY_READ_CALLBACKS + extern bool8 pad_read; + if (Memory.FillRAM[0x4200] & 1) + { + S9xOnSNESPadRead(); + pad_read = TRUE; + } + #endif + return (Memory.FillRAM[Address]); + + default: + if (Settings.SPC7110 && Address >= 0x4800) + return (S9xGetSPC7110(Address)); + if (Settings.SDD1 && Address >= 0x4800 && Address <= 0x4807) + return (Memory.FillRAM[Address]); + return (OpenBus); + } + } +} + +void S9xResetPPU (void) +{ + S9xSoftResetPPU(); + S9xControlsReset(); + PPU.M7HOFS = 0; + PPU.M7VOFS = 0; + PPU.M7byte = 0; +} + +void S9xSoftResetPPU (void) +{ + S9xControlsSoftReset(); + + PPU.VMA.High = 0; + PPU.VMA.Increment = 1; + PPU.VMA.Address = 0; + PPU.VMA.FullGraphicCount = 0; + PPU.VMA.Shift = 0; + + PPU.WRAM = 0; + + for (int c = 0; c < 4; c++) + { + PPU.BG[c].SCBase = 0; + PPU.BG[c].HOffset = 0; + PPU.BG[c].VOffset = 0; + PPU.BG[c].BGSize = 0; + PPU.BG[c].NameBase = 0; + PPU.BG[c].SCSize = 0; + } + + PPU.BGMode = 0; + PPU.BG3Priority = 0; + + PPU.CGFLIP = 0; + PPU.CGFLIPRead = 0; + PPU.CGADD = 0; + + for (int 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); + } + + for (int c = 0; c < 128; c++) + { + PPU.OBJ[c].HPos = 0; + PPU.OBJ[c].VPos = 0; + PPU.OBJ[c].HFlip = 0; + PPU.OBJ[c].VFlip = 0; + PPU.OBJ[c].Name = 0; + PPU.OBJ[c].Priority = 0; + PPU.OBJ[c].Palette = 0; + PPU.OBJ[c].Size = 0; + } + + PPU.OBJThroughMain = FALSE; + PPU.OBJThroughSub = FALSE; + PPU.OBJAddition = FALSE; + PPU.OBJNameBase = 0; + PPU.OBJNameSelect = 0; + PPU.OBJSizeSelect = 0; + + PPU.OAMAddr = 0; + PPU.SavedOAMAddr = 0; + PPU.OAMPriorityRotation = 0; + PPU.OAMFlip = 0; + PPU.OAMReadFlip = 0; + PPU.OAMTileAddress = 0; + PPU.OAMWriteRegister = 0; + ZeroMemory(PPU.OAMData, 512 + 32); + + PPU.FirstSprite = 0; + PPU.LastSprite = 127; + PPU.RangeTimeOver = 0; + + PPU.HTimerEnabled = FALSE; + PPU.VTimerEnabled = FALSE; + PPU.HTimerPosition = Timings.H_Max + 1; + PPU.VTimerPosition = Timings.V_Max + 1; + PPU.IRQHBeamPos = 0x1ff; + PPU.IRQVBeamPos = 0x1ff; + + PPU.HBeamFlip = 0; + PPU.VBeamFlip = 0; + PPU.HBeamPosLatched = 0; + PPU.VBeamPosLatched = 0; + PPU.GunHLatch = 0; + PPU.GunVLatch = 1000; + PPU.HVBeamCounterLatched = 0; + + PPU.Mode7HFlip = FALSE; + PPU.Mode7VFlip = FALSE; + PPU.Mode7Repeat = 0; + PPU.MatrixA = 0; + PPU.MatrixB = 0; + PPU.MatrixC = 0; + PPU.MatrixD = 0; + PPU.CentreX = 0; + PPU.CentreY = 0; + + PPU.Mosaic = 0; + PPU.BGMosaic[0] = FALSE; + PPU.BGMosaic[1] = FALSE; + PPU.BGMosaic[2] = FALSE; + PPU.BGMosaic[3] = FALSE; + + PPU.Window1Left = 1; + PPU.Window1Right = 0; + PPU.Window2Left = 1; + PPU.Window2Right = 0; + PPU.RecomputeClipWindows = TRUE; + + for (int c = 0; c < 6; c++) + { + PPU.ClipCounts[c] = 0; + PPU.ClipWindowOverlapLogic[c] = CLIP_OR; + PPU.ClipWindow1Enable[c] = FALSE; + PPU.ClipWindow2Enable[c] = FALSE; + PPU.ClipWindow1Inside[c] = TRUE; + PPU.ClipWindow2Inside[c] = TRUE; + } + + PPU.ForcedBlanking = TRUE; + + PPU.FixedColourRed = 0; + PPU.FixedColourGreen = 0; + PPU.FixedColourBlue = 0; + PPU.Brightness = 0; + PPU.ScreenHeight = SNES_HEIGHT; + + PPU.Need16x8Mulitply = FALSE; + PPU.BGnxOFSbyte = 0; + + PPU.HDMA = 0; + PPU.HDMAEnded = 0; + + PPU.OpenBus1 = 0; + PPU.OpenBus2 = 0; + + for (int c = 0; c < 2; c++) + memset(&IPPU.Clip[c], 0, sizeof(struct ClipData)); + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; + IPPU.DirectColourMapsNeedRebuild = TRUE; + ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD], MAX_2BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES); + ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD], MAX_4BIT_TILES); +#ifdef CORRECT_VRAM_READS + IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better? +#else + IPPU.FirstVRAMRead = FALSE; +#endif + IPPU.Interlace = FALSE; + IPPU.InterlaceOBJ = FALSE; + IPPU.DoubleWidthPixels = FALSE; + IPPU.DoubleHeightPixels = FALSE; + IPPU.CurrentLine = 0; + IPPU.PreviousLine = 0; + IPPU.XB = NULL; + for (int c = 0; c < 256; c++) + IPPU.ScreenColors[c] = c; + IPPU.MaxBrightness = 0; + IPPU.RenderThisFrame = TRUE; + IPPU.RenderedScreenWidth = SNES_WIDTH; + IPPU.RenderedScreenHeight = SNES_HEIGHT; + IPPU.FrameCount = 0; + IPPU.RenderedFramesCount = 0; + IPPU.DisplayedRenderedFrameCount = 0; + IPPU.SkippedFrames = 0; + IPPU.FrameSkip = 0; + + S9xFixColourBrightness(); + + for (int 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; +} diff --git a/ppu.h b/ppu.h new file mode 100644 index 00000000..7f20e897 --- /dev/null +++ b/ppu.h @@ -0,0 +1,752 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _PPU_H_ +#define _PPU_H_ + +#define FIRST_VISIBLE_LINE 1 + +#define TILE_2BIT 0 +#define TILE_4BIT 1 +#define TILE_8BIT 2 +#define TILE_2BIT_EVEN 3 +#define TILE_2BIT_ODD 4 +#define TILE_4BIT_EVEN 5 +#define TILE_4BIT_ODD 6 + +#define MAX_2BIT_TILES 4096 +#define MAX_4BIT_TILES 2048 +#define MAX_8BIT_TILES 1024 + +#define CLIP_OR 0 +#define CLIP_AND 1 +#define CLIP_XOR 2 +#define CLIP_XNOR 3 + +#define PPU_IRQ_SOURCE (1 << 1) +#define GSU_IRQ_SOURCE (1 << 2) +#define SA1_IRQ_SOURCE (1 << 7) +#define SA1_DMA_IRQ_SOURCE (1 << 5) + +struct ClipData +{ + uint8 Count; + uint8 DrawMode[6]; + uint16 Left[6]; + uint16 Right[6]; +}; + +struct InternalPPU +{ + struct ClipData Clip[2][6]; + bool8 ColorsChanged; + bool8 OBJChanged; + bool8 DirectColourMapsNeedRebuild; + uint8 *TileCache[7]; + uint8 *TileCached[7]; +#ifdef CORRECT_VRAM_READS + uint16 VRAMReadBuffer; +#else + bool8 FirstVRAMRead; +#endif + bool8 Interlace; + bool8 InterlaceOBJ; + bool8 PseudoHires; + bool8 DoubleWidthPixels; + bool8 DoubleHeightPixels; + int CurrentLine; + int PreviousLine; + uint8 *XB; + uint32 Red[256]; + uint32 Green[256]; + uint32 Blue[256]; + uint16 ScreenColors[256]; + uint8 MaxBrightness; + bool8 RenderThisFrame; + int RenderedScreenWidth; + int RenderedScreenHeight; + uint32 FrameCount; + uint32 RenderedFramesCount; + uint32 DisplayedRenderedFrameCount; + uint32 TotalEmulatedFrames; + uint32 SkippedFrames; + uint32 FrameSkip; +}; + +struct SOBJ +{ + int16 HPos; + uint16 VPos; + uint8 HFlip; + uint8 VFlip; + uint16 Name; + uint8 Priority; + uint8 Palette; + uint8 Size; +}; + +struct SPPU +{ + struct + { + bool8 High; + uint8 Increment; + uint16 Address; + uint16 Mask1; + uint16 FullGraphicCount; + uint16 Shift; + } VMA; + + uint32 WRAM; + + struct + { + uint16 SCBase; + uint16 HOffset; + uint16 VOffset; + uint8 BGSize; + uint16 NameBase; + uint16 SCSize; + } BG[4]; + + uint8 BGMode; + uint8 BG3Priority; + + bool8 CGFLIP; + uint8 CGFLIPRead; + uint8 CGADD; + uint16 CGDATA[256]; + + struct SOBJ OBJ[128]; + bool8 OBJThroughMain; + bool8 OBJThroughSub; + bool8 OBJAddition; + uint16 OBJNameBase; + uint16 OBJNameSelect; + uint8 OBJSizeSelect; + + uint16 OAMAddr; + uint16 SavedOAMAddr; + uint8 OAMPriorityRotation; + uint8 OAMFlip; + uint8 OAMReadFlip; + uint16 OAMTileAddress; + uint16 OAMWriteRegister; + uint8 OAMData[512 + 32]; + + uint8 FirstSprite; + uint8 LastSprite; + uint8 RangeTimeOver; + + bool8 HTimerEnabled; + bool8 VTimerEnabled; + short HTimerPosition; + short VTimerPosition; + uint16 IRQHBeamPos; + uint16 IRQVBeamPos; + + uint8 HBeamFlip; + uint8 VBeamFlip; + uint16 HBeamPosLatched; + uint16 VBeamPosLatched; + uint16 GunHLatch; + uint16 GunVLatch; + uint8 HVBeamCounterLatched; + + bool8 Mode7HFlip; + bool8 Mode7VFlip; + uint8 Mode7Repeat; + short MatrixA; + short MatrixB; + short MatrixC; + short MatrixD; + short CentreX; + short CentreY; + short M7HOFS; + short M7VOFS; + + uint8 Mosaic; + uint8 MosaicStart; + bool8 BGMosaic[4]; + + uint8 Window1Left; + uint8 Window1Right; + uint8 Window2Left; + uint8 Window2Right; + bool8 RecomputeClipWindows; + uint8 ClipCounts[6]; + uint8 ClipWindowOverlapLogic[6]; + uint8 ClipWindow1Enable[6]; + uint8 ClipWindow2Enable[6]; + bool8 ClipWindow1Inside[6]; + bool8 ClipWindow2Inside[6]; + + bool8 ForcedBlanking; + + uint8 FixedColourRed; + uint8 FixedColourGreen; + uint8 FixedColourBlue; + uint8 Brightness; + uint16 ScreenHeight; + + bool8 Need16x8Mulitply; + uint8 BGnxOFSbyte; + uint8 M7byte; + + uint8 HDMA; + uint8 HDMAEnded; + + uint8 OpenBus1; + uint8 OpenBus2; +}; + +extern uint16 SignExtend[2]; +extern struct SPPU PPU; +extern struct InternalPPU IPPU; + +void S9xResetPPU (void); +void S9xSoftResetPPU (void); +void S9xSetPPU (uint8, uint16); +uint8 S9xGetPPU (uint16); +void S9xSetCPU (uint8, uint16); +uint8 S9xGetCPU (uint16); +void S9xUpdateHVTimerPosition (void); +void S9xCheckMissingHTimerPosition (int32); +void S9xCheckMissingHTimerRange (int32, int32); +void S9xCheckMissingHTimerHalt (int32, int32); +void S9xFixColourBrightness (void); +void S9xDoAutoJoypad (void); + +#include "gfx.h" +#include "memmap.h" + +typedef struct +{ + uint8 _5C77; + uint8 _5C78; + uint8 _5A22; +} SnesModel; + +extern SnesModel *Model; +extern SnesModel M1SNES; +extern SnesModel M2SNES; + +#define MAX_5C77_VERSION 0x01 +#define MAX_5C78_VERSION 0x03 +#define MAX_5A22_VERSION 0x02 + +static inline void FLUSH_REDRAW (void) +{ + if (IPPU.PreviousLine != IPPU.CurrentLine) + S9xUpdateScreen(); +} + +static inline void REGISTER_2104 (uint8 Byte) +{ + if (PPU.OAMAddr & 0x100) + { + int addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1); + if (Byte != PPU.OAMData[addr]) + { + FLUSH_REDRAW(); + PPU.OAMData[addr] = Byte; + IPPU.OBJChanged = TRUE; + + // X position high bit, and sprite size (x4) + struct SOBJ *pObj = &PPU.OBJ[(addr & 0x1f) * 4]; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 0) & 1]; + pObj++->Size = Byte & 2; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 2) & 1]; + pObj++->Size = Byte & 8; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 4) & 1]; + pObj++->Size = Byte & 32; + pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 6) & 1]; + pObj->Size = Byte & 128; + } + + PPU.OAMFlip ^= 1; + if (!(PPU.OAMFlip & 1)) + { + ++PPU.OAMAddr; + PPU.OAMAddr &= 0x1ff; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + } + } + else + { + if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1)) + IPPU.OBJChanged = TRUE; + } + } + else + if (!(PPU.OAMFlip & 1)) + { + PPU.OAMWriteRegister &= 0xff00; + PPU.OAMWriteRegister |= Byte; + PPU.OAMFlip |= 1; + if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1)) + IPPU.OBJChanged = TRUE; + } + else + { + PPU.OAMWriteRegister &= 0x00ff; + uint8 lowbyte = (uint8) (PPU.OAMWriteRegister); + uint8 highbyte = Byte; + PPU.OAMWriteRegister |= Byte << 8; + + int addr = (PPU.OAMAddr << 1); + if (lowbyte != PPU.OAMData[addr] || highbyte != PPU.OAMData[addr + 1]) + { + FLUSH_REDRAW(); + PPU.OAMData[addr] = lowbyte; + PPU.OAMData[addr + 1] = highbyte; + IPPU.OBJChanged = TRUE; + if (addr & 2) + { + // Tile + PPU.OBJ[addr = PPU.OAMAddr >> 1].Name = PPU.OAMWriteRegister & 0x1ff; + // priority, h and v flip. + PPU.OBJ[addr].Palette = (highbyte >> 1) & 7; + PPU.OBJ[addr].Priority = (highbyte >> 4) & 3; + PPU.OBJ[addr].HFlip = (highbyte >> 6) & 1; + PPU.OBJ[addr].VFlip = (highbyte >> 7) & 1; + } + else + { + // X position (low) + PPU.OBJ[addr = PPU.OAMAddr >> 1].HPos &= 0xff00; + PPU.OBJ[addr].HPos |= lowbyte; + // Sprite Y position + PPU.OBJ[addr].VPos = highbyte; + } + } + + PPU.OAMFlip &= ~1; + ++PPU.OAMAddr; + if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1)) + { + PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1; + IPPU.OBJChanged = TRUE; + } + } +} + +// This code is correct, however due to Snes9x's inaccurate timings, some games might be broken by this chage. :( +#ifdef DEBUGGER +#define CHECK_INBLANK() \ + if (!PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \ + { \ + printf("Invalid VRAM acess at (%04d, %04d) blank:%d\n", CPU.Cycles, CPU.V_Counter, PPU.ForcedBlanking); \ + if (Settings.BlockInvalidVRAMAccess) \ + return; \ + } +#else +#define CHECK_INBLANK() \ + if (Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \ + return; +#endif + +static inline void REGISTER_2118 (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 address; + + if (PPU.VMA.FullGraphicCount) + { + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; + Memory.VRAM[address] = Byte; + } + else + Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (!PPU.VMA.High) + { + #ifdef DEBUGGER + if (Settings.TraceVRAM && !CPU.InDMAorHDMA) + printf("VRAM write byte: $%04X (%d, %d)\n", PPU.VMA.Address, Memory.FillRAM[0x2115] & 3, (Memory.FillRAM[0x2115] & 0x0c) >> 2); + #endif + PPU.VMA.Address += PPU.VMA.Increment; + } +} + +static inline void REGISTER_2119 (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 address; + + if (PPU.VMA.FullGraphicCount) + { + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff; + Memory.VRAM[address] = Byte; + } + else + Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xffff] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (PPU.VMA.High) + { + #ifdef DEBUGGER + if (Settings.TraceVRAM && !CPU.InDMAorHDMA) + printf("VRAM write word: $%04X (%d, %d)\n", PPU.VMA.Address, Memory.FillRAM[0x2115] & 3, (Memory.FillRAM[0x2115] & 0x0c) >> 2); + #endif + PPU.VMA.Address += PPU.VMA.Increment; + } +} + +static inline void REGISTER_2118_tile (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + uint32 address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff; + + Memory.VRAM[address] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +} + +static inline void REGISTER_2119_tile (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 rem = PPU.VMA.Address & PPU.VMA.Mask1; + uint32 address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff; + + Memory.VRAM[address] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +} + +static inline void REGISTER_2118_linear (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 address; + + Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (!PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +} + +static inline void REGISTER_2119_linear (uint8 Byte) +{ + CHECK_INBLANK(); + + uint32 address; + + Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xffff] = Byte; + + IPPU.TileCached[TILE_2BIT][address >> 4] = FALSE; + IPPU.TileCached[TILE_4BIT][address >> 5] = FALSE; + IPPU.TileCached[TILE_8BIT][address >> 6] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = FALSE; + IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = FALSE; + IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = FALSE; + + if (PPU.VMA.High) + PPU.VMA.Address += PPU.VMA.Increment; +} + +static inline void REGISTER_2122 (uint8 Byte) +{ + if (PPU.CGFLIP) + { + if ((Byte & 0x7f) != (PPU.CGDATA[PPU.CGADD] >> 8)) + { + FLUSH_REDRAW(); + PPU.CGDATA[PPU.CGADD] &= 0x00ff; + PPU.CGDATA[PPU.CGADD] |= (Byte & 0x7f) << 8; + IPPU.ColorsChanged = TRUE; + IPPU.Blue[PPU.CGADD] = IPPU.XB[(Byte >> 2) & 0x1f]; + IPPU.Green[PPU.CGADD] = IPPU.XB[(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; + IPPU.ScreenColors[PPU.CGADD] = (uint16) BUILD_PIXEL(IPPU.Red[PPU.CGADD], IPPU.Green[PPU.CGADD], IPPU.Blue[PPU.CGADD]); + } + + PPU.CGADD++; + } + else + { + if (Byte != (uint8) (PPU.CGDATA[PPU.CGADD] & 0xff)) + { + FLUSH_REDRAW(); + PPU.CGDATA[PPU.CGADD] &= 0x7f00; + PPU.CGDATA[PPU.CGADD] |= Byte; + IPPU.ColorsChanged = TRUE; + IPPU.Red[PPU.CGADD] = IPPU.XB[Byte & 0x1f]; + IPPU.Green[PPU.CGADD] = IPPU.XB[(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f]; + IPPU.ScreenColors[PPU.CGADD] = (uint16) BUILD_PIXEL(IPPU.Red[PPU.CGADD], IPPU.Green[PPU.CGADD], IPPU.Blue[PPU.CGADD]); + } + } + + PPU.CGFLIP ^= 1; +} + +static inline void REGISTER_2180 (uint8 Byte) +{ + Memory.RAM[PPU.WRAM++] = Byte; + PPU.WRAM &= 0x1ffff; +} + +static inline uint8 REGISTER_4212 (void) +{ + uint8 byte = 0; + + if ((CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3)) + byte = 1; + if ((CPU.Cycles < Timings.HBlankEnd) || (CPU.Cycles >= Timings.HBlankStart)) + byte |= 0x40; + if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) + byte |= 0x80; + + return (byte); +} + +#endif diff --git a/reader.cpp b/reader.cpp new file mode 100644 index 00000000..fa7ba1ec --- /dev/null +++ b/reader.cpp @@ -0,0 +1,353 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + +// Abstract the details of reading from zip files versus FILE *'s. + +#include +#ifdef UNZIP_SUPPORT +#include "unzip.h" +#endif +#include "snes9x.h" +#include "reader.h" + + +// Generic constructor/destructor + +Reader::Reader (void) +{ + return; +} + +Reader::~Reader (void) +{ + return; +} + +// Generic getline function, based on gets. Reimlpement if you can do better. + +char * Reader::getline (void) +{ + bool eof; + std::string ret; + + ret = getline(eof); + if (ret.size() == 0 && eof) + return (NULL); + + return (strdup(ret.c_str())); +} + +std::string Reader::getline (bool &eof) +{ + char buf[1024]; + std::string ret; + + eof = false; + ret.clear(); + + do + { + if (gets(buf, sizeof(buf)) == NULL) + { + eof = true; + break; + } + + ret.append(buf); + } + while (*ret.rbegin() != '\n'); + + return (ret); +} + +// snes9x.h STREAM reader + +fReader::fReader (STREAM f) +{ + fp = f; +} + +fReader::~fReader (void) +{ + return; +} + +int fReader::get_char (void) +{ + return (GETC_STREAM(fp)); +} + +char * fReader::gets (char *buf, size_t len) +{ + return (GETS_STREAM(buf, len, fp)); +} + +size_t fReader::read (char *buf, size_t len) +{ + return (READ_STREAM(buf, len, fp)); +} + +// unzip reader + +#ifdef UNZIP_SUPPORT + +unzReader::unzReader (unzFile &v) +{ + file = v; + head = NULL; + numbytes = 0; +} + +unzReader::~unzReader (void) +{ + return; +} + +int unzReader::get_char (void) +{ + unsigned char c; + + if (numbytes <= 0) + { + numbytes = unzReadCurrentFile(file, buffer, unz_BUFFSIZ); + if (numbytes <= 0) + return (EOF); + head = buffer; + } + + c = *head; + head++; + numbytes--; + + return ((int) c); +} + +char * unzReader::gets (char *buf, size_t len) +{ + size_t i; + int c; + + for (i = 0; i < len - 1; i++) + { + c = get_char(); + if (c == EOF) + { + if (i == 0) + return (NULL); + break; + } + + buf[i] = (char) c; + if (buf[i] == '\n') + break; + } + + buf[i] = '\0'; + + return (buf); +} + +size_t unzReader::read (char *buf, size_t len) +{ + if (len == 0) + return (len); + + if (len <= numbytes) + { + memcpy(buf, head, len); + numbytes -= len; + head += len; + return (len); + } + + size_t numread = 0; + if (numbytes > 0) + { + memcpy(buf, head, numbytes); + numread += numbytes; + head = NULL; + numbytes = 0; + } + + int l = unzReadCurrentFile(file, buf + numread, len - numread); + if (l > 0) + numread += l; + + return (numread); +} + +#endif diff --git a/reader.h b/reader.h new file mode 100644 index 00000000..2019cc1a --- /dev/null +++ b/reader.h @@ -0,0 +1,228 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _READER_H_ +#define _READER_H_ + +class Reader +{ + public: + Reader (void); + virtual ~Reader (void); + virtual int get_char (void) = 0; + virtual char * gets (char *, size_t) = 0; + virtual char * getline (void); // free() when done + virtual std::string getline (bool &); + virtual size_t read (char *, size_t) = 0; +}; + +class fReader : public Reader +{ + public: + fReader (STREAM); + virtual ~fReader (void); + virtual int get_char (void); + virtual char * gets (char *, size_t); + virtual size_t read (char *, size_t); + + private: + STREAM fp; +}; + +#ifdef UNZIP_SUPPORT + +#define unz_BUFFSIZ 1024 + +class unzReader : public Reader +{ + public: + unzReader (unzFile &); + virtual ~unzReader (void); + virtual int get_char (void); + virtual char * gets (char *, size_t); + virtual size_t read (char *, size_t); + + private: + unzFile file; + char buffer[unz_BUFFSIZ]; + char *head; + size_t numbytes; +}; + +#endif + +#endif diff --git a/sa1.cpp b/sa1.cpp new file mode 100644 index 00000000..8ec6904a --- /dev/null +++ b/sa1.cpp @@ -0,0 +1,1110 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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" + +uint8 SA1OpenBus; + +static void S9xSA1Reset (void); +static void S9xSA1SetBWRAMMemMap (uint8); +static void S9xSetSA1MemMap (uint32, uint8); +static void S9xSA1CharConv2 (void); +static void S9xSA1DMA (void); +static void S9xSA1ReadVariableLengthData (bool8, bool8); + + +void S9xSA1Init (void) +{ + 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; + SA1.S9xOpcodes = NULL; +} + +static void S9xSA1Reset (void) +{ + SA1Registers.PBPC = 0; + SA1Registers.PB = 0; + SA1Registers.PCw = 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.PCBase = NULL; + S9xSA1SetPCBase(SA1Registers.PBPC); + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; + + S9xSA1UnpackStatus(); + S9xSA1FixCycles(); + SA1.Executing = TRUE; + SA1.BWRAM = Memory.SRAM; + Memory.FillRAM[0x2225] = 0; +} + +static void S9xSA1SetBWRAMMemMap (uint8 val) +{ + if (val & 0x80) + { + for (int 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 (int 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 S9xSA1PostLoadState (void) +{ + SA1.ShiftedPB = (uint32) SA1Registers.PB << 16; + SA1.ShiftedDB = (uint32) SA1Registers.DB << 16; + + S9xSA1SetPCBase(SA1Registers.PBPC); + 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; +} + +void S9xSA1ExecuteDuringSleep (void) +{ +#if 0 + if (SA1.Executing) + { + while (CPU.Cycles < CPU.NextEvent) + { + S9xSA1MainLoop(); + CPU.Cycles += TWO_CYCLES * 2; + } + } +#endif +} + +static void S9xSetSA1MemMap (uint32 which1, uint8 map) +{ + int start = which1 * 0x100 + 0xc00; + int start2 = which1 * 0x200; + + if (which1 >= 2) + start2 += 0x400; + + for (int c = 0; c < 0x100; c += 16) + { + uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 12)]; + for (int i = c; i < c + 16; i++) + Memory.Map[start + i] = SA1.Map[start + i] = block; + } + + for (int c = 0; c < 0x200; c += 16) + { + uint8 *block = &Memory.ROM[(map & 7) * 0x100000 + (c << 11) - 0x8000]; + for (int i = c + 8; i < c + 16; i++) + Memory.Map[start2 + i] = SA1.Map[start2 + i] = block; + } +} + +uint8 S9xGetSA1 (uint32 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 0x230c: + return (Memory.FillRAM[0x230c]); + + case 0x230d: + { + uint8 byte = Memory.FillRAM[0x230d]; + + if (Memory.FillRAM[0x2258] & 0x80) + S9xSA1ReadVariableLengthData(TRUE, FALSE); + + return (byte); + } + + default: + printf("R: %04x\n", address); + break; + } + + return (Memory.FillRAM[address]); +} + +void S9xSetSA1 (uint8 byte, uint32 address) +{ + switch (address) + { + case 0x2200: + SA1.Waiting = (byte & 0x60) != 0; + //SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; + + if (!(byte & 0x20) && (Memory.FillRAM[0x2200] & 0x20)) + S9xSA1Reset(); + + if (byte & 0x80) + { + Memory.FillRAM[0x2301] |= 0x80; + if (Memory.FillRAM[0x220a] & 0x80) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= SNES_IRQ_SOURCE; + SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes; + } + } + + if (byte & 0x10) + { + Memory.FillRAM[0x2301] |= 0x10; + #ifdef DEBUGGER + printf("###SA1 NMI\n"); + #endif + if (Memory.FillRAM[0x220a] & 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 0x2203: + //printf("SA1 reset vector: %04x\n", byte | (Memory.FillRAM[0x2204] << 8)); + break; + + case 0x2204: + //printf("SA1 reset vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2203]); + break; + + case 0x2205: + //printf("SA1 NMI vector: %04x\n", byte | (Memory.FillRAM[0x2206] << 8)); + break; + + case 0x2206: + //printf("SA1 NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2205]); + break; + + case 0x2207: + //printf("SA1 IRQ vector: %04x\n", byte | (Memory.FillRAM[0x2208] << 8)); + break; + + case 0x2208: + //printf("SA1 IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2207]); + break; + + case 0x2209: + Memory.FillRAM[0x2209] = byte; + + if (byte & 0x80) + Memory.FillRAM[0x2300] |= 0x80; + + if (byte & Memory.FillRAM[0x2201] & 0x80) + S9xSetIRQ(SA1_IRQ_SOURCE); + + break; + + case 0x220a: + if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80)) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= SNES_IRQ_SOURCE; + //SA1.Executing = !SA1.Waiting; + } + + if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40)) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= TIMER_IRQ_SOURCE; + //SA1.Executing = !SA1.Waiting; + } + + if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20)) + { + SA1.Flags |= IRQ_FLAG; + SA1.IRQActive |= DMA_IRQ_SOURCE; + //SA1.Executing = !SA1.Waiting; + } + + if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10)) + { + #ifdef DEBUGGER + printf("###SA1 NMI\n"); + #endif + } + + 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_FLAG; + + break; + + case 0x220c: + //printf("SNES NMI vector: %04x\n", byte | (Memory.FillRAM[0x220d] << 8)); + break; + + case 0x220d: + //printf("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220c]); + break; + + case 0x220e: + //printf("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM[0x220f] << 8)); + break; + + case 0x220f: + //printf("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220e]); + break; + + case 0x2210: + #if 0 + printf("Timer %s\n", (byte & 0x80) ? "linear" : "HV"); + printf("Timer H-IRQ %s\n", (byte & 1) ? "enabled" : "disabled"); + printf("Timer V-IRQ %s\n", (byte & 2) ? "enabled" : "disabled"); + #endif + break; + + case 0x2211: + //printf("Timer reset\n"); + break; + + case 0x2212: + //printf("H-Timer %04x\n", byte | (Memory.FillRAM[0x2213] << 8)); + break; + + case 0x2213: + //printf("H-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2212]); + break; + + case 0x2214: + //printf("V-Timer %04x\n", byte | (Memory.FillRAM[0x2215] << 8)); + break; + + case 0x2215: + //printf("V-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2214]); + break; + + case 0x2220: + case 0x2221: + case 0x2222: + case 0x2223: + //printf("MMC: %02x\n", byte); + S9xSetSA1MemMap(address - 0x2220, byte); + break; + + case 0x2224: + //printf("BWRAM image SNES %02x -> 0x6000\n", byte); + Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000; + break; + + case 0x2225: + //printf("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM[0x2225]); + if (byte != Memory.FillRAM[0x2225]) + S9xSA1SetBWRAMMemMap(byte); + break; + + case 0x2226: + //printf("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled"); + break; + + case 0x2227: + //printf("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled"); + break; + + case 0x2228: + //printf("BW-RAM write protect area %02x\n", byte); + break; + + case 0x2229: + //printf("I-RAM SNES write protect area %02x\n", byte); + break; + + case 0x222a: + //printf("I-RAM SA1 write protect area %02x\n", byte); + break; + + case 0x2230: + #if 0 + printf("SA1 DMA %s\n", (byte & 0x80) ? "enabled" : "disabled"); + printf("DMA priority %s\n", (byte & 0x40) ? "DMA" : "SA1"); + printf("DMA %s\n", (byte & 0x20) ? "char conv" : "normal"); + printf("DMA type %s\n", (byte & 0x10) ? "BW-RAM -> I-RAM" : "SA1 -> I-RAM"); + printf("DMA distination %s\n", (byte & 4) ? "BW-RAM" : "I-RAM"); + printf("DMA source %s\n", DMAsource[byte & 3]); + #endif + break; + + case 0x2231: + if (byte & 0x80) + SA1.in_char_dma = FALSE; + #if 0 + printf("CHDEND %s\n", (byte & 0x80) ? "complete" : "incomplete"); + printf("DMA colour mode %d\n", byte & 3); + printf("virtual VRAM width %d\n", (byte >> 2) & 7); + #endif + break; + + case 0x2232: + case 0x2233: + case 0x2234: + Memory.FillRAM[address] = byte; + #if 0 + printf("DMA source start %06x\n", Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16)); + #endif + break; + + case 0x2235: + Memory.FillRAM[0x2235] = byte; + break; + + case 0x2236: + Memory.FillRAM[0x2236] = 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; + } + + break; + + case 0x2237: + Memory.FillRAM[0x2237] = byte; + + if ((Memory.FillRAM[0x2230] & 0xa4) == 0x84) // Normal DMA to BW-RAM + S9xSA1DMA(); + #if 0 + printf("DMA dest address %06x\n", Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16)); + #endif + break; + + case 0x2238: + case 0x2239: + Memory.FillRAM[address] = byte; + #if 0 + printf("DMA length %04x\n", Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8)); + #endif + break; + + case 0x223f: + //printf("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4); + SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4; + break; + + case 0x2240: + case 0x2241: + case 0x2242: + case 0x2243: + case 0x2244: + case 0x2245: + case 0x2246: + case 0x2247: + case 0x2248: + case 0x2249: + case 0x224a: + case 0x224b: + case 0x224c: + case 0x224d: + case 0x224e: + #if 0 + if (!(SA1.Flags & TRACE_FLAG)) + { + TraceSA1(); + Trace(); + } + #endif + Memory.FillRAM[address] = byte; + break; + + case 0x224f: + Memory.FillRAM[0x224f] = byte; + + if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // Char conversion 2 DMA enabled + { + memmove(&Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM[0x2240], 16); + SA1.in_char_dma = (SA1.in_char_dma + 1) & 7; + if ((SA1.in_char_dma & 3) == 0) + S9xSA1CharConv2(); + } + + break; + + 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 + SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16); + break; + + case 2: // cumulative sum + default: + 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: // Variable bit-field start address + case 0x225a: + case 0x225b: + Memory.FillRAM[address] = byte; + // XXX: ??? + SA1.variable_bit_pos = 0; + S9xSA1ReadVariableLengthData(FALSE, TRUE); + return; + + default: + //printf("W: %02x->%04x\n", byte, address); + break; + } + + if (address >= 0x2200 && address <= 0x22ff) + Memory.FillRAM[address] = byte; +} + +static void S9xSA1CharConv2 (void) +{ + 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; + + switch (depth) + { + case 2: + case 4: + break; + + case 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; + } + + break; + } +} + +static void S9xSA1DMA (void) +{ + 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, *d; + + switch (Memory.FillRAM[0x2230] & 3) + { + case 0: // ROM + s = SA1.Map[((src & 0xffffff) >> MEMMAP_SHIFT)]; + if (s >= (uint8 *) CMemory::MAP_LAST) + s += (src & 0xffff); + else + s = Memory.ROM + (src & 0xffff); + break; + + case 1: // BW-RAM + src &= Memory.SRAMMask; + len &= 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 &= Memory.SRAMMask; + len &= 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_FLAG; + SA1.IRQActive |= DMA_IRQ_SOURCE; + //SA1.Executing = !SA1.Waiting; + } +} + +static 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); + } +} + +uint8 S9xSA1GetByte (uint32 address) +{ + uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + return (*(GetAddress + (address & 0xffff))); + + switch ((pint) GetAddress) + { + case CMemory::MAP_PPU: + return (S9xGetSA1(address & 0xffff)); + + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + return (*(Memory.SRAM + (address & 0xffff))); + + case CMemory::MAP_BWRAM: + return (*(SA1.BWRAM + ((address & 0x7fff) - 0x6000))); + + case CMemory::MAP_BWRAM_BITMAP: + 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); + + case CMemory::MAP_BWRAM_BITMAP2: + 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); + + default: + return (SA1OpenBus); + } +} + +uint16 S9xSA1GetWord (uint32 address, s9xwrap_t w) +{ + PC_t a; + + SA1OpenBus = S9xSA1GetByte(address); + + switch (w) + { + case WRAP_PAGE: + a.xPBPC = address; + a.B.xPCl++; + return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); + + case WRAP_BANK: + a.xPBPC = address; + a.W.xPC++; + return (SA1OpenBus | (S9xSA1GetByte(a.xPBPC) << 8)); + + case WRAP_NONE: + default: + return (SA1OpenBus | (S9xSA1GetByte(address + 1) << 8)); + } +} + +void S9xSA1SetByte (uint8 byte, uint32 address) +{ + uint8 *SetAddress = SA1.WriteMap[(address & 0xffffff) >> MEMMAP_SHIFT]; + + if (SetAddress >= (uint8 *) CMemory::MAP_LAST) + { + *(SetAddress + (address & 0xffff)) = byte; + return; + } + + switch ((pint) SetAddress) + { + case CMemory::MAP_PPU: + S9xSetSA1(byte, address & 0xffff); + return; + + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + *(Memory.SRAM + (address & 0xffff)) = byte; + return; + + case CMemory::MAP_BWRAM: + *(SA1.BWRAM + ((address & 0x7fff) - 0x6000)) = byte; + return; + + case CMemory::MAP_BWRAM_BITMAP: + address -= 0x600000; + if (SA1.VirtualBitmapFormat == 2) + { + uint8 *ptr = &Memory.SRAM[(address >> 2) & 0xffff]; + *ptr &= ~(3 << ((address & 3) << 1)); + *ptr |= (byte & 3) << ((address & 3) << 1); + } + else + { + uint8 *ptr = &Memory.SRAM[(address >> 1) & 0xffff]; + *ptr &= ~(15 << ((address & 1) << 2)); + *ptr |= (byte & 15) << ((address & 1) << 2); + } + + return; + + case CMemory::MAP_BWRAM_BITMAP2: + address = (address & 0xffff) - 0x6000; + if (SA1.VirtualBitmapFormat == 2) + { + uint8 *ptr = &SA1.BWRAM[(address >> 2) & 0xffff]; + *ptr &= ~(3 << ((address & 3) << 1)); + *ptr |= (byte & 3) << ((address & 3) << 1); + } + else + { + uint8 *ptr = &SA1.BWRAM[(address >> 1) & 0xffff]; + *ptr &= ~(15 << ((address & 1) << 2)); + *ptr |= (byte & 15) << ((address & 1) << 2); + } + + return; + + default: + return; + } +} + +void S9xSA1SetWord (uint16 Word, uint32 address, enum s9xwrap_t w, enum s9xwriteorder_t o) +{ + PC_t a; + + if (!o) + S9xSA1SetByte((uint8) Word, address); + + switch (w) + { + case WRAP_PAGE: + a.xPBPC = address; + a.B.xPCl++; + S9xSA1SetByte(Word >> 8, a.xPBPC); + break; + + case WRAP_BANK: + a.xPBPC = address; + a.W.xPC++; + S9xSA1SetByte(Word >> 8, a.xPBPC); + break; + + case WRAP_NONE: + default: + S9xSA1SetByte(Word >> 8, address + 1); + break; + } + + if (o) + S9xSA1SetByte((uint8) Word, address); +} + +void S9xSA1SetPCBase (uint32 address) +{ + SA1Registers.PBPC = address & 0xffffff; + SA1.ShiftedPB = address & 0xff0000; + + uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT]; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + SA1.PCBase = GetAddress; + return; + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + SA1.PCBase = NULL; + else + SA1.PCBase = (Memory.SRAM + ((((address & 0xff0000) >> 1) | (address & 0x7fff)) & Memory.SRAMMask)) - (address & 0xffff); + return; + + case CMemory::MAP_HIROM_SRAM: + if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK) + SA1.PCBase = NULL; + else + SA1.PCBase = (Memory.SRAM + (((address & 0x7fff) - 0x6000 + ((address & 0xf0000) >> 3)) & Memory.SRAMMask)) - (address & 0xffff); + return; + + case CMemory::MAP_BWRAM: + SA1.PCBase = SA1.BWRAM - 0x6000 - (address & 0x8000); + return; + + case CMemory::MAP_SA1RAM: + SA1.PCBase = Memory.SRAM; + return; + + default: + SA1.PCBase = NULL; + return; + } +} diff --git a/sa1.h b/sa1.h new file mode 100644 index 00000000..7849c8c8 --- /dev/null +++ b/sa1.h @@ -0,0 +1,323 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _SA1_H_ +#define _SA1_H_ + +struct SSA1Registers +{ + uint8 DB; + pair P; + pair A; + pair D; + pair S; + pair X; + pair Y; + PC_t PC; +}; + +struct SSA1 +{ + struct SOpcodes *S9xOpcodes; + uint8 *S9xOpLengths; + uint8 _Carry; + uint8 _Zero; + uint8 _Negative; + uint8 _Overflow; + bool8 CPUExecuting; + uint32 ShiftedPB; + uint32 ShiftedDB; + + uint32 Flags; + uint8 *PCBase; + bool8 IRQActive; + bool8 Waiting; + bool8 WaitingForInterrupt; + uint32 WaitAddress; + uint32 WaitCounter; + uint32 PBPCAtOpcodeStart; + uint8 *WaitByteAddress1; + uint8 *WaitByteAddress2; + + uint8 *Map[MEMMAP_NUM_BLOCKS]; + uint8 *WriteMap[MEMMAP_NUM_BLOCKS]; + uint8 *BWRAM; + + bool8 Executing; + bool8 overflow; + bool8 in_char_dma; + int16 op1; + int16 op2; + int32 arithmetic_op; + int64 sum; + uint8 VirtualBitmapFormat; + uint8 variable_bit_pos; +}; + +#define SA1CheckCarry() (SA1._Carry) +#define SA1CheckZero() (SA1._Zero == 0) +#define SA1CheckIRQ() (SA1Registers.PL & IRQ) +#define SA1CheckDecimal() (SA1Registers.PL & Decimal) +#define SA1CheckIndex() (SA1Registers.PL & IndexFlag) +#define SA1CheckMemory() (SA1Registers.PL & MemoryFlag) +#define SA1CheckOverflow() (SA1._Overflow) +#define SA1CheckNegative() (SA1._Negative & 0x80) +#define SA1CheckEmulation() (SA1Registers.P.W & Emulation) + +#define SA1SetFlags(f) (SA1Registers.P.W |= (f)) +#define SA1ClearFlags(f) (SA1Registers.P.W &= ~(f)) +#define SA1CheckFlag(f) (SA1Registers.PL & (f)) + +extern struct SSA1Registers SA1Registers; +extern struct SSA1 SA1; +extern uint8 SA1OpenBus; +extern struct SOpcodes S9xSA1OpcodesM1X1[256]; +extern struct SOpcodes S9xSA1OpcodesM1X0[256]; +extern struct SOpcodes S9xSA1OpcodesM0X1[256]; +extern struct SOpcodes S9xSA1OpcodesM0X0[256]; +extern uint8 S9xOpLengthsM1X1[256]; +extern uint8 S9xOpLengthsM1X0[256]; +extern uint8 S9xOpLengthsM0X1[256]; +extern uint8 S9xOpLengthsM0X0[256]; + +uint8 S9xSA1GetByte (uint32); +void S9xSA1SetByte (uint8, uint32); +uint16 S9xSA1GetWord (uint32, enum s9xwrap_t w = WRAP_NONE); +void S9xSA1SetWord (uint16, uint32, enum s9xwrap_t w = WRAP_NONE, enum s9xwriteorder_t o = WRITE_01); +void S9xSA1SetPCBase (uint32); +uint8 S9xGetSA1 (uint32); +void S9xSetSA1 (uint8, uint32); +void S9xSA1Init (void); +void S9xSA1MainLoop (void); +void S9xSA1ExecuteDuringSleep (void); +void S9xSA1PostLoadState (void); + +#define SNES_IRQ_SOURCE (1 << 7) +#define TIMER_IRQ_SOURCE (1 << 6) +#define DMA_IRQ_SOURCE (1 << 5) + +static inline void S9xSA1UnpackStatus (void) +{ + SA1._Zero = (SA1Registers.PL & Zero) == 0; + SA1._Negative = (SA1Registers.PL & Negative); + SA1._Carry = (SA1Registers.PL & Carry); + SA1._Overflow = (SA1Registers.PL & Overflow) >> 6; +} + +static inline void S9xSA1PackStatus (void) +{ + SA1Registers.PL &= ~(Zero | Negative | Carry | Overflow); + SA1Registers.PL |= SA1._Carry | ((SA1._Zero == 0) << 1) | (SA1._Negative & 0x80) | (SA1._Overflow << 6); +} + +static inline void S9xSA1FixCycles (void) +{ + if (SA1CheckEmulation()) + { + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; + } + else + if (SA1CheckMemory()) + { + if (SA1CheckIndex()) + { + SA1.S9xOpcodes = S9xSA1OpcodesM1X1; + SA1.S9xOpLengths = S9xOpLengthsM1X1; + } + else + { + SA1.S9xOpcodes = S9xSA1OpcodesM1X0; + SA1.S9xOpLengths = S9xOpLengthsM1X0; + } + } + else + { + if (SA1CheckIndex()) + { + SA1.S9xOpcodes = S9xSA1OpcodesM0X1; + SA1.S9xOpLengths = S9xOpLengthsM0X1; + } + else + { + SA1.S9xOpcodes = S9xSA1OpcodesM0X0; + SA1.S9xOpLengths = S9xOpLengthsM0X0; + } + } +} + +#endif diff --git a/sa1cpu.cpp b/sa1cpu.cpp new file mode 100644 index 00000000..dd79509e --- /dev/null +++ b/sa1cpu.cpp @@ -0,0 +1,299 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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" + +#define CPU SA1 +#define ICPU SA1 +#define Registers SA1Registers +#define OpenBus SA1OpenBus +#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 S9xOpcodesE1 S9xSA1OpcodesE1 +#define S9xOpcodesSlow S9xSA1OpcodesSlow +#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 Absolute SA1Absolute +#define AbsoluteLong SA1AbsoluteLong +#define AbsoluteIndirect SA1AbsoluteIndirect +#define AbsoluteIndirectLong SA1AbsoluteIndirectLong +#define AbsoluteIndexedIndirect SA1AbsoluteIndexedIndirect +#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 +#define SA1_OPCODES + +#include "cpuops.cpp" + + +void S9xSA1MainLoop (void) +{ +#if 0 + if (SA1.Flags & NMI_FLAG) + { + SA1.Flags &= ~NMI_FLAG; + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; + } + + S9xSA1Opcode_NMI(); + } +#endif + + if (SA1.Flags & IRQ_FLAG) + { + if (SA1.IRQActive) + { + if (SA1.WaitingForInterrupt) + { + SA1.WaitingForInterrupt = FALSE; + SA1Registers.PCw++; + } + + if (!SA1CheckFlag(IRQ)) + S9xSA1Opcode_IRQ(); + } + else + SA1.Flags &= ~IRQ_FLAG; + } + + for (int i = 0; i < 3 && SA1.Executing; i++) + { + #ifdef DEBUGGER + if (SA1.Flags & TRACE_FLAG) + S9xSA1Trace(); + #endif + + #ifdef CPU_SHUTDOWN + SA1.PBPCAtOpcodeStart = SA1Registers.PBPC; + #endif + + register uint8 Op; + register struct SOpcodes *Opcodes; + + if (SA1.PCBase) + { + SA1OpenBus = Op = SA1.PCBase[Registers.PCw]; + Opcodes = SA1.S9xOpcodes; + } + else + { + Op = S9xSA1GetByte(Registers.PBPC); + Opcodes = S9xOpcodesSlow; + } + + if ((SA1Registers.PCw & MEMMAP_MASK) + SA1.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE) + { + uint32 oldPC = SA1Registers.PBPC; + S9xSA1SetPCBase(SA1Registers.PBPC); + SA1Registers.PBPC = oldPC; + Opcodes = S9xSA1OpcodesSlow; + } + + Registers.PCw++; + (*Opcodes[Op].S9xOpcode)(); + } +} diff --git a/sar.h b/sar.h new file mode 100644 index 00000000..f53de57a --- /dev/null +++ b/sar.h @@ -0,0 +1,223 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _SAR_H_ +#define _SAR_H_ + +#ifdef RIGHTSHIFT_IS_SAR +#define SAR(b, n) ((b) >> (n)) +#else + +static inline int8 SAR (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) +{ +#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) +{ +#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) +{ +#ifndef RIGHTSHIFT_int64_IS_SAR + if (b < 0) + return ((b >> n) | (-1 << (64 - n))); +#endif + return (b >> n); +} + +#endif + +#endif diff --git a/screenshot.cpp b/screenshot.cpp new file mode 100644 index 00000000..6c0aec72 --- /dev/null +++ b/screenshot.cpp @@ -0,0 +1,315 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 HAVE_LIBPNG +#include +#endif +#include "snes9x.h" +#include "memmap.h" +#include "display.h" +#include "screenshot.h" + + +bool8 S9xDoScreenshot (int width, int height) +{ + Settings.TakeScreenshot = FALSE; + +#ifdef HAVE_LIBPNG + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + png_color_8 sig_bit; + int imgwidth, imgheight; + const char *fname; + + fname = S9xGetFilenameInc(".png", SCREENSHOT_DIR); + + fp = fopen(fname, "wb"); + if (!fp) + { + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); + } + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + fclose(fp); + unlink(fname); + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + fclose(fp); + unlink(fname); + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + unlink(fname); + S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); + return (FALSE); + } + + imgwidth = width; + imgheight = height; + + if (Settings.StretchScreenshots == 1) + { + if (width > SNES_WIDTH && height <= SNES_HEIGHT_EXTENDED) + imgheight = height << 1; + } + else + if (Settings.StretchScreenshots == 2) + { + if (width <= SNES_WIDTH) + imgwidth = width << 1; + if (height <= SNES_HEIGHT_EXTENDED) + imgheight = height << 1; + } + + png_init_io(png_ptr, fp); + + png_set_IHDR(png_ptr, info_ptr, imgwidth, imgheight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + sig_bit.red = 5; + sig_bit.green = 5; + sig_bit.blue = 5; + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, &sig_bit); + + png_write_info(png_ptr, info_ptr); + + png_set_packing(png_ptr); + + png_byte *row_pointer = new png_byte[png_get_rowbytes(png_ptr, info_ptr)]; + uint16 *screen = GFX.Screen; + + for (int y = 0; y < height; y++, screen += GFX.RealPPL) + { + png_byte *rowpix = row_pointer; + + for (int x = 0; x < width; x++) + { + uint32 r, g, b; + + DECOMPOSE_PIXEL(screen[x], r, g, b); + + *(rowpix++) = r; + *(rowpix++) = g; + *(rowpix++) = b; + + if (imgwidth != width) + { + *(rowpix++) = r; + *(rowpix++) = g; + *(rowpix++) = b; + } + } + + png_write_row(png_ptr, row_pointer); + if (imgheight != height) + png_write_row(png_ptr, row_pointer); + } + + delete [] row_pointer; + + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + + fclose(fp); + + fprintf(stderr, "%s saved.\n", fname); + + const char *base = S9xBasename(fname); + sprintf(String, "Saved screenshot %s", base); + S9xMessage(S9X_INFO, 0, String); + + return (TRUE); +#else + fprintf(stderr, "Screenshot support not available (libpng was not found at build time).\n"); + return (FALSE); +#endif +} diff --git a/screenshot.h b/screenshot.h new file mode 100644 index 00000000..6839ba09 --- /dev/null +++ b/screenshot.h @@ -0,0 +1,183 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _SCREENSHOT_H_ +#define _SCREENSHOT_H_ + +bool8 S9xDoScreenshot (int, int); + +#endif diff --git a/sdd1.cpp b/sdd1.cpp new file mode 100644 index 00000000..40cd4c9b --- /dev/null +++ b/sdd1.cpp @@ -0,0 +1,211 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "sdd1.h" +#include "display.h" + + +void S9xSetSDD1MemoryMap (uint32 bank, uint32 value) +{ + bank = 0xc00 + bank * 0x100; + value = value * 1024 * 1024; + + for (int c = 0; c < 0x100; c += 16) + { + uint8 *block = &Memory.ROM[value + (c << 12)]; + for (int i = c; i < c + 16; i++) + Memory.Map[i + bank] = block; + } +} + +void S9xResetSDD1 (void) +{ + memset(&Memory.FillRAM[0x4800], 0, 4); + for (int i = 0; i < 4; i++) + { + Memory.FillRAM[0x4804 + i] = i; + S9xSetSDD1MemoryMap(i, i); + } +} + +void S9xSDD1PostLoadState (void) +{ + for (int i = 0; i < 4; i++) + S9xSetSDD1MemoryMap(i, Memory.FillRAM[0x4804 + i]); +} diff --git a/sdd1.h b/sdd1.h new file mode 100644 index 00000000..7419b5ba --- /dev/null +++ b/sdd1.h @@ -0,0 +1,185 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _SDD1_H_ +#define _SDD1_H_ + +void S9xSetSDD1MemoryMap (uint32, uint32); +void S9xResetSDD1 (void); +void S9xSDD1PostLoadState (void); + +#endif diff --git a/sdd1emu.cpp b/sdd1emu.cpp new file mode 100644 index 00000000..c4f4d36b --- /dev/null +++ b/sdd1emu.cpp @@ -0,0 +1,503 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "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; + } +} + +#if 0 +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; + } +} +#endif diff --git a/sdd1emu.h b/sdd1emu.h new file mode 100644 index 00000000..5722b4b6 --- /dev/null +++ b/sdd1emu.h @@ -0,0 +1,183 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _SDD1EMU_H_ +#define _SDD1EMU_H_ + +void SDD1_decompress (uint8 *, uint8 *, int); + +#endif diff --git a/server.cpp b/server.cpp new file mode 100644 index 00000000..7be5236e --- /dev/null +++ b/server.cpp @@ -0,0 +1,1463 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 NETPLAY_SUPPORT +#ifdef _DEBUG + #define NP_DEBUG 1 +#endif + +#include +#include +#include +#include +#include +#ifdef HAVE_STRINGS_H + #include +#endif + +#ifdef __WIN32__ + + #include + #include + #include "win32/wsnes9x.h" + #define ioctl ioctlsocket + #define close closesocket + #define read(a,b,c) recv(a, b, c, 0) + #define write(a,b,c) send(a, b, c, 0) + #define gettimeofday(a,b) S9xGetTimeOfDay (a) + #define exit(a) _endthread() + void S9xGetTimeOfDay (struct timeval *n); +#else + #include + #include + + #include + #include + #include + #include + #include + #include + + #ifdef __SVR4 + #include + #endif + +#endif // !__WIN32__ + +#include "snes9x.h" +#include "memmap.h" +#include "snapshot.h" +#include "netplay.h" + +#ifdef __WIN32__ +#define NP_ONE_CLIENT 1 +#else +#define NP_ONE_CLIENT 0 +#endif + +struct SNPServer NPServer; + +extern unsigned long START; + +void S9xNPSendToAllClients (uint8 *data, int len); +bool8 S9xNPLoadFreezeFile (const char *fname, uint8 *&data, uint32 &len); +void S9xNPSendFreezeFile (int c, uint8 *data, uint32 len); +void S9xNPNoClientReady (int start_index = NP_ONE_CLIENT); +void S9xNPRecomputePause (); +void S9xNPWaitForEmulationToComplete (); +void S9xNPSendROMImageToAllClients (); +bool8 S9xNPSendROMImageToClient (int client); +void S9xNPSendSRAMToClient (int c); +void S9xNPSendSRAMToAllClients (); +void S9xNPSyncClient (int); +void S9xNPSendROMLoadRequest (const char *filename); +void S9xNPSendFreezeFileToAllClients (const char *filename); +void S9xNPStopServer (); + +void S9xNPShutdownClient (int c, bool8 report_error = FALSE) +{ + if (NPServer.Clients [c].Connected) + { + NPServer.Clients [c].Connected = FALSE; + NPServer.Clients [c].SaidHello = FALSE; + + close (NPServer.Clients [c].Socket); +#ifdef NP_DEBUG + printf ("SERVER: Player %d disconnecting @%ld\n", c + 1, S9xGetMilliTime () - START); +#endif + if (report_error) + { + sprintf (NetPlay.ErrorMsg, + "Player %d on '%s' has disconnected.", c + 1, + NPServer.Clients [c].HostName); + S9xNPSetWarning (NetPlay.ErrorMsg); + } + + if (NPServer.Clients [c].HostName) + { + free ((char *) NPServer.Clients [c].HostName); + NPServer.Clients [c].HostName = NULL; + } + if (NPServer.Clients [c].ROMName) + { + free ((char *) NPServer.Clients [c].ROMName); + NPServer.Clients [c].ROMName = NULL; + } + if (NPServer.Clients [c].Who) + { + free ((char *) NPServer.Clients [c].Who); + NPServer.Clients [c].Who = NULL; + } + NPServer.Joypads [c] = 0; + NPServer.NumClients--; + S9xNPRecomputePause (); + } +} + +static bool8 S9xNPSGetData (int socket, uint8 *data, int length) +{ + int len = length; + uint8 *ptr = data; + + do + { + int num_bytes = len; + + // Read the data in small chunks, allowing this thread to spot an + // abort request from another thread. + if (num_bytes > 512) + num_bytes = 512; + + int got = read (socket, (char *) ptr, num_bytes); + if (got < 0) + { + if (errno == EINTR +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif +#ifdef WSAEWOULDBLOCK + || errno == WSAEWOULDBLOCK +#endif + ) + continue; +#ifdef WSAEMSGSIZE + if (errno != WSAEMSGSIZE) + return (FALSE); + else + { + got = num_bytes; +#ifdef NP_DEBUG + printf ("SERVER: WSAEMSGSIZE, actual bytes %d while receiving data @%d\n", got, S9xGetMilliTime () - START); +#endif + } +#else + return (FALSE); +#endif + } + else + if (got == 0) + return (FALSE); + + len -= got; + ptr += got; + } while (len > 0); + + return (TRUE); +} + +static bool8 S9xNPSSendData (int fd, const uint8 *data, int length) +{ + int Percent = 0; + int len = length; + int chunk = length / 50; + + if (chunk < 1024) + chunk = 1024; + + do + { + int num_bytes = len; + + // Write the data in small chunks, allowing this thread to spot an + // abort request from another thread. + if (num_bytes > chunk) + num_bytes = chunk; + + int sent; + sent = write (fd, (char *) data, len); + + if (sent < 0) + { + if (errno == EINTR +#ifdef EAGAIN + || errno == EAGAIN +#endif +#ifdef EWOULDBLOCK + || errno == EWOULDBLOCK +#endif + ) + { +#ifdef NP_DEBUG + printf ("SERVER: EINTR, EAGAIN or EWOULDBLOCK while sending data @%ld\n", S9xGetMilliTime () - START); +#endif + continue; + } + return (FALSE); + } + else + if (sent == 0) + return (FALSE); + len -= sent; + data += sent; + if (length > 1024) + { + Percent = (uint8) (((length - len) * 100) / length); +#ifdef __WIN32__ + PostMessage (GUI.hWnd, WM_USER, Percent, Percent); + Sleep (0); +#endif + } + } while (len > 0); + + return (TRUE); +} + +void S9xNPSendHeartBeat () +{ + int len = 3; + uint8 data [3 + 4 * 5]; + uint8 *ptr = data; + int n; + + for (n = NP_MAX_CLIENTS - 1; n >= 0; n--) + { + if (NPServer.Clients [n].SaidHello) + break; + } + + if (n >= 0) + { + bool8 Paused = NPServer.Paused != 0; + + NPServer.FrameCount++; + *ptr++ = NP_SERV_MAGIC; + *ptr++ = 0; // Individual client sequence number will get placed here + *ptr++ = NP_SERV_JOYPAD | (n << 6) | ((Paused != 0) << 5); + + WRITE_LONG (ptr, NPServer.FrameCount); + len += 4; + ptr += 4; + + int i; + + for (i = 0; i <= n; i++) + { + WRITE_LONG (ptr, NPServer.Joypads [i]); + len += 4; + ptr += 4; + } + + S9xNPSendToAllClients (data, len); + } +} + +void S9xNPSendToAllClients (uint8 *data, int len) +{ + int i; + + for (i = 0; i < NP_MAX_CLIENTS; i++) + { + if (NPServer.Clients [i].SaidHello) + { + data [1] = NPServer.Clients [i].SendSequenceNum++; + if (!S9xNPSSendData (NPServer.Clients [i].Socket, data, len)) + S9xNPShutdownClient (i, TRUE); + } + } +} + +void S9xNPProcessClient (int c) +{ + uint8 header [7]; + uint8 *data; + uint32 len; + uint8 *ptr; + + if (!S9xNPSGetData (NPServer.Clients [c].Socket, header, 7)) + { + S9xNPSetWarning ("SERVER: Failed to get message header from client.\n"); + S9xNPShutdownClient (c, TRUE); + return; + } + if (header [0] != NP_CLNT_MAGIC) + { + S9xNPSetWarning ("SERVER: Bad header magic value received from client.\n"); + S9xNPShutdownClient (c, TRUE); + return; + } + + if (header [1] != NPServer.Clients [c].ReceiveSequenceNum) + { +#ifdef NP_DEBUG + printf ("SERVER: Messages lost from '%s', expected %d, got %d\n", + NPServer.Clients [c].HostName ? + NPServer.Clients [c].HostName : "Unknown", + NPServer.Clients [c].ReceiveSequenceNum, + header [1]); +#endif + sprintf (NetPlay.WarningMsg, + "SERVER: Messages lost from '%s', expected %d, got %d\n", + NPServer.Clients [c].HostName ? + NPServer.Clients [c].HostName : "Unknown", + NPServer.Clients [c].ReceiveSequenceNum, + header [1]); + NPServer.Clients [c].ReceiveSequenceNum = header [1] + 1; + S9xNPSetWarning (NetPlay.WarningMsg); + } + else + NPServer.Clients [c].ReceiveSequenceNum++; + + len = READ_LONG (&header [3]); + + switch (header [2] & 0x3f) + { + case NP_CLNT_HELLO: +#ifdef NP_DEBUG + printf ("SERVER: Got HELLO from client @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("Got HELLO from client...", TRUE); + if (len > 0x10000) + { + S9xNPSetWarning ("SERVER: Client HELLO message length error."); + S9xNPShutdownClient (c, TRUE); + return; + } + data = new uint8 [len - 7]; + if (!S9xNPSGetData (NPServer.Clients [c].Socket, data, len - 7)) + { + S9xNPSetWarning ("SERVER: Failed to get HELLO message content from client."); + S9xNPShutdownClient (c, TRUE); + return; + } + + if (NPServer.NumClients <= NP_ONE_CLIENT) + { + NPServer.FrameTime = READ_LONG (data); + strncpy (NPServer.ROMName, (char *) &data [4], 29); + NPServer.ROMName [29] = 0; + } + + NPServer.Clients [c].ROMName = strdup ((char *) &data [4]); +#ifdef NP_DEBUG + printf ("SERVER: Client is playing: %s, Frame Time: %d @%ld\n", data + 4, READ_LONG (data), S9xGetMilliTime () - START); +#endif + + NPServer.Clients [c].SendSequenceNum = 0; + + len = 7 + 1 + 1 + 4 + strlen (NPServer.ROMName) + 1; + + delete data; + ptr = data = new uint8 [len]; + *ptr++ = NP_SERV_MAGIC; + *ptr++ = NPServer.Clients [c].SendSequenceNum++; + + if (NPServer.SendROMImageOnConnect && + NPServer.NumClients > NP_ONE_CLIENT) + *ptr++ = NP_SERV_HELLO | 0x80; + else + *ptr++ = NP_SERV_HELLO; + WRITE_LONG (ptr, len); + ptr += 4; + *ptr++ = NP_VERSION; + *ptr++ = c + 1; + WRITE_LONG (ptr, NPServer.FrameCount); + ptr += 4; + strcpy ((char *) ptr, NPServer.ROMName); + +#ifdef NP_DEBUG + printf ("SERVER: Sending welcome information to client @%ld...\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("SERVER: Sending welcome information to new client...", TRUE); + if (!S9xNPSSendData (NPServer.Clients [c].Socket, data, len)) + { + S9xNPSetWarning ("SERVER: Failed to send welcome message to client."); + S9xNPShutdownClient (c, TRUE); + return; + } + delete data; +#ifdef NP_DEBUG + printf ("SERVER: Waiting for a response from the client @%ld...\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("SERVER: Waiting for a response from the client...", TRUE); + break; + + case NP_CLNT_LOADED_ROM: +#ifdef NP_DEBUG + printf ("SERVER: Client %d loaded requested ROM @%ld...\n", c, S9xGetMilliTime () - START); +#endif + NPServer.Clients [c].SaidHello = TRUE; + NPServer.Clients [c].Ready = FALSE; + NPServer.Clients [c].Paused = FALSE; + S9xNPRecomputePause (); + S9xNPWaitForEmulationToComplete (); + + if (NPServer.SyncByReset) + { + S9xNPServerAddTask (NP_SERVER_SEND_SRAM, (void *) c); + S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); + } + else + S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); + break; + + case NP_CLNT_RECEIVED_ROM_IMAGE: +#ifdef NP_DEBUG + printf ("SERVER: Client %d received ROM image @%ld...\n", c, S9xGetMilliTime () - START); +#endif + NPServer.Clients [c].SaidHello = TRUE; + NPServer.Clients [c].Ready = FALSE; + NPServer.Clients [c].Paused = FALSE; + S9xNPRecomputePause (); + S9xNPWaitForEmulationToComplete (); + + if (NPServer.SyncByReset) + { + S9xNPServerAddTask (NP_SERVER_SEND_SRAM, (void *) c); + S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); + } + else + S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); + + break; + + case NP_CLNT_WAITING_FOR_ROM_IMAGE: +#ifdef NP_DEBUG + printf ("SERVER: Client %d waiting for ROM image @%ld...\n", c, S9xGetMilliTime () - START); +#endif + NPServer.Clients [c].SaidHello = TRUE; + NPServer.Clients [c].Ready = FALSE; + NPServer.Clients [c].Paused = FALSE; + S9xNPRecomputePause (); + S9xNPSendROMImageToClient (c); + break; + + case NP_CLNT_READY: +#ifdef NP_DEBUG + printf ("SERVER: Client %d ready @%ld...\n", c, S9xGetMilliTime () - START); +#endif + if (NPServer.Clients [c].SaidHello) + { + NPServer.Clients [c].Paused = FALSE; + NPServer.Clients [c].Ready = TRUE; + + S9xNPRecomputePause (); + break; + } + NPServer.Clients [c].SaidHello = TRUE; + NPServer.Clients [c].Ready = TRUE; + NPServer.Clients [c].Paused = FALSE; + S9xNPRecomputePause (); + +//printf ("SERVER: SaidHello = TRUE, SeqNum = %d @%d\n", NPServer.Clients [c].SendSequenceNum, S9xGetMilliTime () - START); + if (NPServer.NumClients > NP_ONE_CLIENT) + { + if (!NPServer.SendROMImageOnConnect) + { + S9xNPWaitForEmulationToComplete (); + + if (NPServer.SyncByReset) + { + S9xNPServerAddTask (NP_SERVER_SEND_SRAM, (void *) c); + S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); + } + else +#ifdef __WIN32__ + S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); +#else + /* We need to resync all clients on new player connect as we don't have a 'reference game' */ + S9xNPServerAddTask (NP_SERVER_SYNC_ALL, (void *) c); +#endif + } + } + else + { + NPServer.Clients [c].Ready = TRUE; + S9xNPRecomputePause (); + } + break; + case NP_CLNT_JOYPAD: + NPServer.Joypads [c] = len; + break; + case NP_CLNT_PAUSE: +#ifdef NP_DEBUG + printf ("SERVER: Client %d Paused: %s @%ld\n", c, (header [2] & 0x80) ? "YES" : "NO", S9xGetMilliTime () - START); +#endif + NPServer.Clients [c].Paused = (header [2] & 0x80) != 0; + if (NPServer.Clients [c].Paused) + sprintf (NetPlay.WarningMsg, "SERVER: Client %d has paused.", c + 1); + else + sprintf (NetPlay.WarningMsg, "SERVER: Client %d has resumed.", c + 1); + S9xNPSetWarning (NetPlay.WarningMsg); + S9xNPRecomputePause (); + break; + } +} + +void S9xNPAcceptClient (int Listen, bool8 block) +{ + struct sockaddr_in remote_address; + struct linger val2; + struct hostent *host; + int new_fd; + int i; + +#ifdef NP_DEBUG + printf ("SERVER: attempting to accept new client connection @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("SERVER: Attempting to accept client connection...", TRUE); + memset (&remote_address, 0, sizeof (remote_address)); + socklen_t len = sizeof (remote_address); + + new_fd = accept (Listen, (struct sockaddr *)&remote_address, &len); + + S9xNPSetAction ("Setting socket options...", TRUE); + val2.l_onoff = 1; + val2.l_linger = 0; + if (setsockopt (new_fd, SOL_SOCKET, SO_LINGER, + (char *) &val2, sizeof (val2)) < 0) + { + S9xNPSetError ("Setting socket options failed."); + close (new_fd); + return; + } + + for (i = 0; i < NP_MAX_CLIENTS; i++) + { + if (!NPServer.Clients [i].Connected) + { + NPServer.NumClients++; + NPServer.Clients [i].Socket = new_fd; + NPServer.Clients [i].SendSequenceNum = 0; + NPServer.Clients [i].ReceiveSequenceNum = 0; + NPServer.Clients [i].Connected = TRUE; + NPServer.Clients [i].SaidHello = FALSE; + NPServer.Clients [i].Paused = FALSE; + NPServer.Clients [i].Ready = FALSE; + NPServer.Clients [i].ROMName = NULL; + NPServer.Clients [i].HostName = NULL; + NPServer.Clients [i].Who = NULL; + break; + } + } + + if (i >= NP_MAX_CLIENTS) + { + S9xNPSetError ("SERVER: Maximum number of NetPlay Clients have already connected."); + close (new_fd); + return; + } + + if (remote_address.sin_family == AF_INET) + { +#ifdef NP_DEBUG + printf ("SERVER: Looking up new client's hostname @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("SERVER: Looking up new client's hostname...", TRUE); + host = gethostbyaddr ((char *) &remote_address.sin_addr, + sizeof (remote_address.sin_addr), AF_INET); + + if (host) + { +#ifdef NP_DEBUG + printf ("SERVER: resolved new client's hostname (%s) @%ld\n", host->h_name, S9xGetMilliTime () - START); +#endif + sprintf (NetPlay.WarningMsg, "SERVER: Player %d on %s has connected.", i + 1, host->h_name); + NPServer.Clients [i].HostName = strdup (host->h_name); + } + else + { + char *ip = inet_ntoa (remote_address.sin_addr); + if (ip) + NPServer.Clients [i].HostName = strdup (ip); +#ifdef NP_DEBUG + printf ("SERVER: couldn't resolve new client's hostname (%s) @%ld\n", ip ? ip : "Unknown", S9xGetMilliTime () - START); +#endif + sprintf (NetPlay.WarningMsg, "SERVER: Player %d on %s has connected.", i + 1, ip ? ip : "Unknown"); + } + S9xNPSetWarning (NetPlay.WarningMsg); + } +#ifdef NP_DEBUG + printf ("SERVER: waiting for HELLO message from new client @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPSetAction ("SERVER: Waiting for HELLO message from new client..."); +} + +static bool8 server_continue = TRUE; + +static bool8 S9xNPServerInit (int port) +{ + struct sockaddr_in address; + int i; + int val; + + if (!S9xNPInitialise ()) + return (FALSE); + + for (i = 0; i < NP_MAX_CLIENTS; i++) + { + NPServer.Clients [i].SendSequenceNum = 0; + NPServer.Clients [i].ReceiveSequenceNum = 0; + NPServer.Clients [i].Connected = FALSE; + NPServer.Clients [i].SaidHello = FALSE; + NPServer.Clients [i].Paused = FALSE; + NPServer.Clients [i].Ready = FALSE; + NPServer.Clients [i].Socket = 0; + NPServer.Clients [i].ROMName = NULL; + NPServer.Clients [i].HostName = NULL; + NPServer.Clients [i].Who = NULL; + NPServer.Joypads [i] = 0; + } + + NPServer.NumClients = 0; + NPServer.FrameCount = 0; + +#ifdef NP_DEBUG + printf ("SERVER: Creating socket @%ld\n", S9xGetMilliTime () - START); +#endif + if ((NPServer.Socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) + { + S9xNPSetError ("NetPlay Server: Can't create listening socket."); + return (FALSE); + } + + val = 1; + setsockopt (NPServer.Socket, SOL_SOCKET, SO_REUSEADDR, + (char *)&val, sizeof (val)); + + memset (&address, 0, sizeof (address)); + address.sin_family = AF_INET; + address.sin_addr.s_addr = htonl (INADDR_ANY); + address.sin_port = htons (port); + +#ifdef NP_DEBUG + printf ("SERVER: Binding socket to address and port @%ld\n", S9xGetMilliTime () - START); +#endif + if (bind (NPServer.Socket, (struct sockaddr *) &address, sizeof (address)) < 0) + { + S9xNPSetError ("NetPlay Server: Can't bind socket to port number.\nPort already in use?"); + return (FALSE); + } + +#ifdef NP_DEBUG + printf ("SERVER: Getting socket to listen @%ld\n", S9xGetMilliTime () - START); +#endif + if (listen (NPServer.Socket, NP_MAX_CLIENTS) < 0) + { + S9xNPSetError ("NetPlay Server: Can't get new socket to listen."); + return (FALSE); + } + +#ifdef NP_DEBUG + printf ("SERVER: Init complete @%ld\n", S9xGetMilliTime () - START); +#endif + return (TRUE); +} + +void S9xNPSendServerPause (bool8 paused) +{ +#ifdef NP_DEBUG + printf ("SERVER: Pause - %s @%ld\n", paused ? "YES" : "NO", S9xGetMilliTime () - START); +#endif + uint8 pause [7]; + uint8 *ptr = pause; + *ptr++ = NP_SERV_MAGIC; + *ptr++ = 0; + *ptr++ = NP_SERV_PAUSE | (paused ? 0x20 : 0); + WRITE_LONG (ptr, NPServer.FrameCount); + S9xNPSendToAllClients (pause, 7); +} + +void S9xNPServerLoop (void *) +{ +#ifdef __WIN32__ + BOOL success = FALSE; +#else + bool8 success = FALSE; + static struct timeval next1 = {0, 0}; + struct timeval now; +#endif + + int pausedState = -1, newPausedState = -1; + + while (server_continue) + { + fd_set read_fds; + struct timeval timeout; + int res; + int i; + + int max_fd = NPServer.Socket; + +#ifdef __WIN32__ + Sleep (0); +#endif + + if (success && !(Settings.Paused && !Settings.FrameAdvance) && !Settings.StopEmulation && + !Settings.ForcedPause && !NPServer.Paused) + { + S9xNPSendHeartBeat (); + newPausedState = 0; + } + else + { + newPausedState = 1; + } + + if(pausedState != newPausedState) + { + pausedState = newPausedState; +// S9xNPSendServerPause(pausedState); // XXX: doesn't seem to work yet... + } + + do + { + FD_ZERO (&read_fds); + FD_SET (NPServer.Socket, &read_fds); + for (i = 0; i < NP_MAX_CLIENTS; i++) + { + if (NPServer.Clients [i].Connected) + { + FD_SET (NPServer.Clients [i].Socket, &read_fds); + if (NPServer.Clients [i].Socket > max_fd) + max_fd = NPServer.Clients [i].Socket; + } + } + + timeout.tv_sec = 0; + timeout.tv_usec = 1000; + res = select (max_fd + 1, &read_fds, NULL, NULL, &timeout); + + if (res > 0) + { + if (FD_ISSET (NPServer.Socket, &read_fds)) + S9xNPAcceptClient (NPServer.Socket, FALSE); + + for (i = 0; i < NP_MAX_CLIENTS; i++) + { + if (NPServer.Clients [i].Connected && + FD_ISSET (NPServer.Clients [i].Socket, &read_fds)) + { + S9xNPProcessClient (i); + } + } + } + } while (res > 0); + +#ifdef __WIN32__ + success = WaitForSingleObject (GUI.ServerTimerSemaphore, 200) == WAIT_OBJECT_0; +#else + while (gettimeofday (&now, NULL) < 0) ; + + /* If there is no known "next" frame, initialize it now */ + if (next1.tv_sec == 0) { next1 = now; ++next1.tv_usec; } + + success=FALSE; + + if (timercmp(&next1, &now, >)) + { + /* If we're ahead of time, sleep a while */ + unsigned timeleft = + (next1.tv_sec - now.tv_sec) * 1000000 + + next1.tv_usec - now.tv_usec; + usleep(timeleft<(200*1000)?timeleft:(200*1000)); + } + + if (!timercmp(&next1, &now, >)) + { + + /* Calculate the timestamp of the next frame. */ + next1.tv_usec += Settings.FrameTime; + if (next1.tv_usec >= 1000000) + { + next1.tv_sec += next1.tv_usec / 1000000; + next1.tv_usec %= 1000000; + } + success=TRUE; + } +#endif + + while (NPServer.TaskHead != NPServer.TaskTail) + { + void *task_data = NPServer.TaskQueue [NPServer.TaskHead].Data; + +#if defined(NP_DEBUG) && NP_DEBUG == 2 + printf ("SERVER: task %d @%ld\n", NPServer.TaskQueue [NPServer.TaskHead].Task, S9xGetMilliTime () - START); +#endif + + switch (NPServer.TaskQueue [NPServer.TaskHead].Task) + { + case NP_SERVER_SEND_ROM_IMAGE: + S9xNPSendROMImageToAllClients (); + break; + case NP_SERVER_SYNC_CLIENT: + NPServer.Clients [(pint) task_data].Ready = FALSE; + S9xNPRecomputePause (); + S9xNPSyncClient ((pint) task_data); + break; + case NP_SERVER_SYNC_ALL: + S9xNPSyncClients (); + break; + case NP_SERVER_SEND_FREEZE_FILE_ALL: + S9xNPSendFreezeFileToAllClients ((char *) task_data); + free ((char *) task_data); + break; + case NP_SERVER_SEND_ROM_LOAD_REQUEST_ALL: + S9xNPSendROMLoadRequest ((char *) task_data); + free ((char *) task_data); + break; + case NP_SERVER_RESET_ALL: + S9xNPNoClientReady (0); + S9xNPWaitForEmulationToComplete (); + S9xNPSetAction ("SERVER: Sending RESET to all clients...", TRUE); +#ifdef NP_DEBUG + printf ("SERVER: Sending RESET to all clients @%ld\n", S9xGetMilliTime () - START); +#endif + { + uint8 reset [7]; + uint8 *ptr; + + ptr = reset; + *ptr++ = NP_SERV_MAGIC; + *ptr++ = 0; + *ptr++ = NP_SERV_RESET; + WRITE_LONG (ptr, NPServer.FrameCount); + S9xNPSendToAllClients (reset, 7); + } + S9xNPSetAction ("", TRUE); + break; + case NP_SERVER_SEND_SRAM: + NPServer.Clients [(pint) task_data].Ready = FALSE; + S9xNPRecomputePause (); + S9xNPWaitForEmulationToComplete (); + S9xNPSendSRAMToClient ((pint) task_data); + break; + + case NP_SERVER_SEND_SRAM_ALL: + S9xNPNoClientReady (); + S9xNPWaitForEmulationToComplete (); + S9xNPSendSRAMToAllClients (); + break; + + default: + S9xNPSetError ("SERVER: *** Unknown task ***\n"); + break; + } + NPServer.TaskHead = (NPServer.TaskHead + 1) % NP_MAX_TASKS; + } + } +#ifdef NP_DEBUG + printf ("SERVER: Server thread exiting @%ld\n", S9xGetMilliTime () - START); +#endif + S9xNPStopServer (); +} + +bool8 S9xNPStartServer (int port) +{ + static int p; + +#ifdef NP_DEBUG + printf ("SERVER: Starting server on port %d @%ld\n", port, S9xGetMilliTime () - START); +#endif + p = port; + server_continue = TRUE; + if (S9xNPServerInit (port)) +#ifdef __WIN32__ + return (_beginthread (S9xNPServerLoop, 0, &p) != (uintptr_t)(~0)); +#else + S9xNPServerLoop(NULL); + return (TRUE); +#endif + + return (FALSE); +} + +void S9xNPStopServer () +{ +#ifdef NP_DEBUG + printf ("SERVER: Stopping server @%ld\n", S9xGetMilliTime () - START); +#endif + server_continue = FALSE; + close (NPServer.Socket); + + for (int i = 0; i < NP_MAX_CLIENTS; i++) + { + if (NPServer.Clients [i].Connected) + S9xNPShutdownClient(i, FALSE); + } +} + +#ifdef __WIN32__ +void S9xGetTimeOfDay (struct timeval *n) +{ + unsigned long t = S9xGetMilliTime (); + + n->tv_sec = t / 1000; + n->tv_usec = (t % 1000) * 1000; +} +#endif + +void S9xNPSendROMImageToAllClients () +{ + S9xNPNoClientReady (); + S9xNPWaitForEmulationToComplete (); + + int c; + + for (c = NP_ONE_CLIENT; c < NP_MAX_CLIENTS; c++) + { + if (NPServer.Clients [c].SaidHello) + S9xNPSendROMImageToClient (c); + } + + if (NPServer.SyncByReset) + { + S9xNPServerAddTask (NP_SERVER_SEND_SRAM_ALL, 0); + S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); + } + else + S9xNPSyncClient (-1); +} + +bool8 S9xNPSendROMImageToClient (int c) +{ +#ifdef NP_DEBUG + printf ("SERVER: Sending ROM image to player %d @%ld\n", c + 1, S9xGetMilliTime () - START); +#endif + sprintf (NetPlay.ActionMsg, "Sending ROM image to player %d...", c + 1); + S9xNPSetAction (NetPlay.ActionMsg, TRUE); + + uint8 header [7 + 1 + 4]; + uint8 *ptr = header; + int len = sizeof (header) + Memory.CalculatedSize + + strlen (Memory.ROMFilename) + 1; + *ptr++ = NP_SERV_MAGIC; + *ptr++ = NPServer.Clients [c].SendSequenceNum++; + *ptr++ = NP_SERV_ROM_IMAGE; + WRITE_LONG (ptr, len); + ptr += 4; + *ptr++ = Memory.HiROM; + WRITE_LONG (ptr, Memory.CalculatedSize); + + if (!S9xNPSSendData (NPServer.Clients [c].Socket, header, sizeof (header)) || + !S9xNPSSendData (NPServer.Clients [c].Socket, Memory.ROM, + Memory.CalculatedSize) || + !S9xNPSSendData (NPServer.Clients [c].Socket, (uint8 *) Memory.ROMFilename, + strlen (Memory.ROMFilename) + 1)) + { + S9xNPShutdownClient (c, TRUE); + return (FALSE); + } + return (TRUE); +} + +void S9xNPSyncClients () +{ + S9xNPNoClientReady (); + S9xNPSyncClient (-1); +} + +void S9xNPSyncClient (int client) +{ +#ifdef HAVE_MKSTEMP + char fname[] = "/tmp/snes9x_fztmpXXXXXX"; + int fd=-1; +#else + char fname [L_tmpnam]; +#endif + + S9xNPWaitForEmulationToComplete (); + + S9xNPSetAction ("SERVER: Freezing game...", TRUE); +#ifdef HAVE_MKSTEMP + if ( ((fd=mkstemp(fname)) >= 0) && S9xFreezeGame(fname) ) +#else + if ( tmpnam(fname) && S9xFreezeGame(fname) ) +#endif + { + uint8 *data; + uint32 len; + + S9xNPSetAction ("SERVER: Loading freeze file...", TRUE); + if (S9xNPLoadFreezeFile (fname, data, len)) + { + int c; + + if (client < 0) + { + for (c = NP_ONE_CLIENT; c < NP_MAX_CLIENTS; c++) + { + if (NPServer.Clients [c].SaidHello) + { + NPServer.Clients [c].Ready = FALSE; + S9xNPRecomputePause (); + S9xNPSendFreezeFile (c, data, len); + } + } + } + else + { + NPServer.Clients [client].Ready = FALSE; + S9xNPRecomputePause (); + S9xNPSendFreezeFile (client, data, len); + } + delete data; + } + remove (fname); + } +#ifdef HAVE_MKSTEMP + if (fd != -1) + close(fd); +#endif +} + +bool8 S9xNPLoadFreezeFile (const char *fname, uint8 *&data, uint32 &len) +{ + FILE *ff; + + if ((ff = fopen (fname, "rb"))) + { + fseek (ff, 0, SEEK_END); + len = ftell (ff); + fseek (ff, 0, SEEK_SET); + + data = new uint8 [len]; + bool8 ok = (fread (data, 1, len, ff) == len); + fclose (ff); + + return (ok); + } + return (FALSE); +} + +void S9xNPSendFreezeFile (int c, uint8 *data, uint32 len) +{ +#ifdef NP_DEBUG + printf ("SERVER: Sending freeze file to player %d @%ld\n", c + 1, S9xGetMilliTime () - START); +#endif + + sprintf (NetPlay.ActionMsg, "SERVER: Sending freeze-file to player %d...", c + 1); + S9xNPSetAction (NetPlay.ActionMsg, TRUE); + uint8 header [7 + 4]; + uint8 *ptr = header; + + *ptr++ = NP_SERV_MAGIC; + *ptr++ = NPServer.Clients [c].SendSequenceNum++; + *ptr++ = NP_SERV_FREEZE_FILE; + WRITE_LONG (ptr, len + 7 + 4); + ptr += 4; + WRITE_LONG (ptr, NPServer.FrameCount); + + if (!S9xNPSSendData (NPServer.Clients [c].Socket, header, 7 + 4) || + !S9xNPSSendData (NPServer.Clients [c].Socket, data, len)) + { + S9xNPShutdownClient (c, TRUE); + } + S9xNPSetAction ("", TRUE); +} + +void S9xNPRecomputePause () +{ + int c; + + for (c = 0; c < NP_MAX_CLIENTS; c++) + { + if (NPServer.Clients [c].SaidHello && + (!NPServer.Clients [c].Ready || NPServer.Clients [c].Paused)) + { +#if defined(NP_DEBUG) && NP_DEBUG == 2 + printf ("SERVER: Paused because of client %d (%d,%d) @%ld\n", c, NPServer.Clients [c].Ready, NPServer.Clients [c].Paused, S9xGetMilliTime () - START); +#endif + NPServer.Paused = TRUE; + return; + } + } +#if defined(NP_DEBUG) && NP_DEBUG == 2 + printf ("SERVER: not paused @%ld\n", S9xGetMilliTime () - START); +#endif + NPServer.Paused = FALSE; +} + +void S9xNPNoClientReady (int start_index) +{ + int c; + + for (c = start_index; c < NP_MAX_CLIENTS; c++) + NPServer.Clients [c].Ready = FALSE; + S9xNPRecomputePause (); +} + +void S9xNPSendROMLoadRequest (const char *filename) +{ + S9xNPNoClientReady (); + + int len = 7 + strlen (filename) + 1; + uint8 *data = new uint8 [len]; + uint8 *ptr = data; + *ptr++ = NP_SERV_MAGIC; + *ptr++ = 0; + *ptr++ = NP_SERV_LOAD_ROM; + WRITE_LONG (ptr, len); + ptr += 4; + strcpy ((char *) ptr, filename); + + for (int i = NP_ONE_CLIENT; i < NP_MAX_CLIENTS; i++) + { + if (NPServer.Clients [i].SaidHello) + { +#ifdef NP_DEBUG + printf ("SERVER: Sending load ROM requesting to player %d @%ld\n", i + 1, S9xGetMilliTime () - START); +#endif + sprintf (NetPlay.WarningMsg, "SERVER: sending ROM load request to player %d...", i + 1); + S9xNPSetAction (NetPlay.WarningMsg, TRUE); + data [1] = NPServer.Clients [i].SendSequenceNum++; + if (!S9xNPSSendData (NPServer.Clients [i].Socket, data, len)) + { + S9xNPShutdownClient (i, TRUE); + } + } + } + delete data; +} + +void S9xNPSendSRAMToAllClients () +{ + int i; + + for (i = NP_ONE_CLIENT; i < NP_MAX_CLIENTS; i++) + { + if (NPServer.Clients [i].SaidHello) + S9xNPSendSRAMToClient (i); + } +} + +void S9xNPSendSRAMToClient (int c) +{ +#ifdef NP_DEBUG + printf ("SERVER: Sending S-RAM data to player %d @%ld\n", c + 1, S9xGetMilliTime () - START); +#endif + uint8 sram [7]; + int SRAMSize = Memory.SRAMSize ? + (1 << (Memory.SRAMSize + 3)) * 128 : 0; + if (SRAMSize > 0x10000) + SRAMSize = 0x10000; + int len = 7 + SRAMSize; + + sprintf (NetPlay.ActionMsg, "SERVER: Sending S-RAM to player %d...", c + 1); + S9xNPSetAction (NetPlay.ActionMsg, TRUE); + + uint8 *ptr = sram; + *ptr++ = NP_SERV_MAGIC; + *ptr++ = NPServer.Clients [c].SendSequenceNum++; + *ptr++ = NP_SERV_SRAM_DATA; + WRITE_LONG (ptr, len); + if (!S9xNPSSendData (NPServer.Clients [c].Socket, + sram, sizeof (sram)) || + (len > 7 && + !S9xNPSSendData (NPServer.Clients [c].Socket, + Memory.SRAM, len - 7))) + { + S9xNPShutdownClient (c, TRUE); + } +} + +void S9xNPSendFreezeFileToAllClients (const char *filename) +{ + uint8 *data; + uint32 len; + + if (NPServer.NumClients > NP_ONE_CLIENT && S9xNPLoadFreezeFile (filename, data, len)) + { + S9xNPNoClientReady (); + + for (int c = NP_ONE_CLIENT; c < NP_MAX_CLIENTS; c++) + { + if (NPServer.Clients [c].SaidHello) + S9xNPSendFreezeFile (c, data, len); + } + delete data; + } +} + +void S9xNPServerAddTask (uint32 task, void *data) +{ + NPServer.TaskQueue [NPServer.TaskTail].Task = task; + NPServer.TaskQueue [NPServer.TaskTail].Data = data; + + NPServer.TaskTail = (NPServer.TaskTail + 1) % NP_MAX_TASKS; +} + +void S9xNPReset () +{ + S9xNPNoClientReady (0); + S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); +} + +void S9xNPWaitForEmulationToComplete () +{ +#ifdef NP_DEBUG + printf ("SERVER: WaitForEmulationToComplete start @%ld\n", S9xGetMilliTime () - START); +#endif + + while (!NetPlay.PendingWait4Sync && NetPlay.Connected && + !Settings.ForcedPause && !Settings.StopEmulation && + !(Settings.Paused && !Settings.FrameAdvance)) + { +#ifdef __WIN32__ + Sleep (40); +#endif + } +#ifdef NP_DEBUG + printf ("SERVER: WaitForEmulationToComplete end @%ld\n", S9xGetMilliTime () - START); +#endif +} + +void S9xNPServerQueueSyncAll () +{ + if (Settings.NetPlay && Settings.NetPlayServer && + NPServer.NumClients > NP_ONE_CLIENT) + { + S9xNPNoClientReady (); + S9xNPDiscardHeartbeats (); + S9xNPServerAddTask (NP_SERVER_SYNC_ALL, 0); + } +} + +void S9xNPServerQueueSendingROMImage () +{ + if (Settings.NetPlay && Settings.NetPlayServer && + NPServer.NumClients > NP_ONE_CLIENT) + { + S9xNPNoClientReady (); + S9xNPDiscardHeartbeats (); + S9xNPServerAddTask (NP_SERVER_SEND_ROM_IMAGE, 0); + } +} + +void S9xNPServerQueueSendingFreezeFile (const char *filename) +{ + if (Settings.NetPlay && Settings.NetPlayServer && + NPServer.NumClients > NP_ONE_CLIENT) + { + S9xNPNoClientReady (); + S9xNPDiscardHeartbeats (); + S9xNPServerAddTask (NP_SERVER_SEND_FREEZE_FILE_ALL, + (void *) strdup (filename)); + } +} + +void S9xNPServerQueueSendingLoadROMRequest (const char *filename) +{ + if (Settings.NetPlay && Settings.NetPlayServer && + NPServer.NumClients > NP_ONE_CLIENT) + { + S9xNPNoClientReady (); + S9xNPDiscardHeartbeats (); + S9xNPServerAddTask (NP_SERVER_SEND_ROM_LOAD_REQUEST_ALL, + (void *) strdup (filename)); + } +} + +#ifndef __WIN32__ +uint32 S9xGetMilliTime () +{ + static bool8 first = TRUE; + static long start_sec; + struct timeval tv; + + gettimeofday (&tv, NULL); + if (first) + { + start_sec = tv.tv_sec; + first = FALSE; + } + return ((uint32) ((tv.tv_sec - start_sec) * 1000 + tv.tv_usec / 1000)); +} +#endif +#endif diff --git a/seta.cpp b/seta.cpp new file mode 100644 index 00000000..e7fd24c9 --- /dev/null +++ b/seta.cpp @@ -0,0 +1,193 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "seta.h" + +uint8 (*GetSETA) (uint32) = &S9xGetST010; +void (*SetSETA) (uint32, uint8) = &S9xSetST010; + + +uint8 S9xGetSetaDSP (uint32 Address) +{ + return (GetSETA(Address)); +} + +void S9xSetSetaDSP (uint8 Byte, uint32 Address) +{ + SetSETA (Address, Byte); +} diff --git a/seta.h b/seta.h new file mode 100644 index 00000000..ee49097c --- /dev/null +++ b/seta.h @@ -0,0 +1,238 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _SETA_H_ +#define _SETA_H_ + +#define ST_010 0x01 +#define ST_011 0x02 +#define ST_018 0x03 + +struct SST010 +{ + uint8 input_params[16]; + uint8 output_params[16]; + uint8 op_reg; + uint8 execute; + bool8 control_enable; +}; + +struct SST011 +{ + bool8 waiting4command; + uint8 status; + uint8 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; +}; + +struct SST018 +{ + bool8 waiting4command; + uint8 status; + uint8 part_command; + uint8 pass; + uint32 command; + uint32 in_count; + uint32 in_index; + uint32 out_count; + uint32 out_index; + uint8 parameters[512]; + uint8 output[512]; +}; + +extern struct SST010 ST010; +extern struct SST011 ST011; +extern struct SST018 ST018; + +uint8 S9xGetST010 (uint32); +void S9xSetST010 (uint32, uint8); +uint8 S9xGetST011 (uint32); +void S9xSetST011 (uint32, uint8); +uint8 S9xGetST018 (uint32); +void S9xSetST018 (uint8, uint32); +uint8 S9xGetSetaDSP (uint32); +void S9xSetSetaDSP (uint8, uint32); + +extern uint8 (*GetSETA) (uint32); +extern void (*SetSETA) (uint32, uint8); + +#endif diff --git a/seta010.cpp b/seta010.cpp new file mode 100644 index 00000000..45cf8779 --- /dev/null +++ b/seta010.cpp @@ -0,0 +1,863 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "seta.h" + +static 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 +}; + +static const uint8 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 } +}; + +// Mode 7 scaling constants for all raster lines +static 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 +}; + +#ifndef PI +#define PI 3.1415926535897932384626433832795 +#endif + +#define ST010_WORD(offset) (Memory.SRAM[offset + 1] << 8) | Memory.SRAM[offset] + + +static int16 ST010_Sin (int16 Theta) +{ + return (ST010_SinTable[(Theta >> 8) & 0xff]); +} + +static int16 ST010_Cos (int16 Theta) +{ + return (ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff]); +} + +static void ST010_OP01 (int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &Quadrant, int16 &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; +} + +static void ST010_Scale (int16 Multiplier, int16 X0, int16 Y0, int32 &X1, int32 &Y1) +{ + X1 = X0 * Multiplier << 1; + Y1 = Y0 * Multiplier << 1; +} + +static void ST010_Multiply (int16 Multiplicand, int16 Multiplier, int32 &Product) +{ + Product = Multiplicand * Multiplier << 1; +} + +static void ST010_Rotate (int16 Theta, int16 X0, int16 Y0, int16 &X1, int16 &Y1) +{ + X1 = (Y0 * ST010_Sin(Theta) >> 15) + (X0 * ST010_Cos(Theta) >> 15); + Y1 = (Y0 * ST010_Cos(Theta) >> 15) - (X0 * ST010_Sin(Theta) >> 15); +} + +static 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); + } +} + +/* +static void SETA_Distance (int16 Y0, int16 X0, int16 &Distance) +{ + if (X0 < 0) + X0 = -X0; + if (Y0 < 0) + Y0 = -Y0; + + Distance = ((X0 * 0x7af0) + 0x4000) >> 15; +} +*/ + +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 & Memory.SRAMMask]); +} + +void S9xSetST010 (uint32 Address, uint8 Byte) +{ + if (!(Address & 0x80000)) + { + ST010.control_enable = TRUE; + return; + } + +#ifdef DEBUGGER + printf("Write %06X:%02X\n", Address, Byte); +#endif + + 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 & 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(*(uint16 *) (Memory.SRAM + 0x0024), (uint16 *) (Memory.SRAM + 0x0040), (uint16 *) (Memory.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 *) (Memory.SRAM + 0x0080)); + + Offset = 0; + + for (Pos = 0; Pos < Positions; Pos++) + { + Memory.SRAM[0x0040 + Offset] = (uint8) (Places[Pos]); + Memory.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(*(int16 *) &Memory.SRAM[0x0004], *(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int32 &) Memory.SRAM[0x0010], (int32 &) Memory.SRAM[0x0014]); + #else + int32 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(*(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int32 &) Memory.SRAM[0x0010]); + #else + int32 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(*(int16 *) &Memory.SRAM[0x0004], *(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int16 &) Memory.SRAM[0x0010], (int16 &) Memory.SRAM[0x0012]); + #else + int16 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(*(int16 *) &Memory.SRAM[0x0000], *(int16 *) &Memory.SRAM[0x0002], (int16 &) Memory.SRAM[0x0000], (int16 &) Memory.SRAM[0x0002], (int16 &) Memory.SRAM[0x0004], (int16 &) Memory.SRAM[0x0010]); + #else + int16 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: + { + int32 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 = Memory.SRAM[0xC4] | (Memory.SRAM[0xC5] << 8) | (Memory.SRAM[0xC6] << 16) | (Memory.SRAM[0xC7] << 24); + int32 xpos = Memory.SRAM[0xC8] | (Memory.SRAM[0xC9] << 8) | (Memory.SRAM[0xCA] << 16) | (Memory.SRAM[0xCB] << 24); + uint16 rot = Memory.SRAM[0xCC] | (Memory.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 + Memory.SRAM[0xD2] = 0xFF; + Memory.SRAM[0xD3] = 0xFF; + Memory.SRAM[0xDA] = 0; + Memory.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 (o1 < rot) + if (abs(o1 - rot) > 0x8000) + { + 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_speed < speed) + speed = 0; + else + speed = 0xff00; + } + + // adjust direction by so many degrees + // be careful of negative adjustments + if ((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) + { + if (o1 < rot) + rot -= 0x280; + else + if (o1 > rot) + 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; + + Memory.SRAM[0x00C0] = (uint8) (ypos_max); + Memory.SRAM[0x00C1] = (uint8) (ypos_max >> 8); + Memory.SRAM[0x00C2] = (uint8) (xpos_max); + Memory.SRAM[0x00C3] = (uint8) (xpos_max >> 8); + Memory.SRAM[0x00C4] = (uint8) (ypos); + Memory.SRAM[0x00C5] = (uint8) (ypos >> 8); + Memory.SRAM[0x00C6] = (uint8) (ypos >> 16); + Memory.SRAM[0x00C7] = (uint8) (ypos >> 24); + Memory.SRAM[0x00C8] = (uint8) (xpos); + Memory.SRAM[0x00C9] = (uint8) (xpos >> 8); + Memory.SRAM[0x00CA] = (uint8) (xpos >> 16); + Memory.SRAM[0x00CB] = (uint8) (xpos >> 24); + Memory.SRAM[0x00CC] = (uint8) (rot); + Memory.SRAM[0x00CD] = (uint8) (rot >> 8); + Memory.SRAM[0x00D4] = (uint8) (speed); + Memory.SRAM[0x00D5] = (uint8) (speed >> 8); + Memory.SRAM[0x00DC] = (uint8) (flags); + Memory.SRAM[0x00DD] = (uint8) (flags >> 8); + + break; + } + + default: + #ifdef DEBUGGER + printf("Unknown Op\n"); + #endif + break; + } + + // lower signal: op processed + ST010.op_reg = 0; + ST010.execute = 0; + } +} diff --git a/seta011.cpp b/seta011.cpp new file mode 100644 index 00000000..b49a8b8b --- /dev/null +++ b/seta011.cpp @@ -0,0 +1,309 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "seta.h" + +static uint8 board[9][9]; // shougi playboard +static int line = 0; // line counter + + +uint8 S9xGetST011 (uint32 Address) +{ + uint8 t; + uint16 address = (uint16) Address & 0xFFFF; + + line++; + + // status check + if (address == 0x01) + t = 0xFF; + else + t = Memory.SRAM[address]; // read directly from s-ram + +#ifdef DEBUGGER + if (address < 0x150) + printf("ST011 R: %06X %02X\n", Address, t); +#endif + + return (t); +} + +void S9xSetST011 (uint32 Address, uint8 Byte) +{ + static bool reset = false; + uint16 address = (uint16) Address & 0xFFFF; + + line++; + + if (!reset) + { + // bootup values + ST011.waiting4command = true; + reset = true; + } + +#ifdef DEBUGGER + if (address < 0x150) + printf("ST011 W: %06X %02X\n", Address, Byte); +#endif + + 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/seta018.cpp b/seta018.cpp new file mode 100644 index 00000000..24efb5c8 --- /dev/null +++ b/seta018.cpp @@ -0,0 +1,353 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "seta.h" + +static int line; // line counter + + +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; + +#ifdef DEBUGGER + printf("ST018 R: %06X %02X\n", Address, t); +#endif + + return (t); +} + +void S9xSetST018 (uint8 Byte, uint32 Address) +{ + static bool reset = false; + uint16 address = (uint16) Address & 0xFFFF; + +#ifdef DEBUGGER + printf("ST018 W: %06X %02X\n", Address, Byte); +#endif + + 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.in_index = 0; + ST018.out_index = 0; + ST018.part_command = 0; // 3-byte commands + ST018.pass = 0; // data streams into the chip + ST018.command <<= 8; + ST018.command |= Byte; + + 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) + { + // qctually 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/snapshot.cpp b/snapshot.cpp new file mode 100644 index 00000000..3d2c0f51 --- /dev/null +++ b/snapshot.cpp @@ -0,0 +1,2281 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "dma.h" +#include "apu/apu.h" +#include "fxinst.h" +#include "fxemu.h" +#include "sdd1.h" +#include "srtc.h" +#include "snapshot.h" +#include "controls.h" +#include "movie.h" +#include "display.h" +#include "language.h" + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +typedef struct +{ + int offset; + int offset2; + int size; + int type; + uint16 debuted_in; + uint16 deleted_in; + const char *name; +} FreezeData; + +enum +{ + INT_V, + uint8_ARRAY_V, + uint16_ARRAY_V, + uint32_ARRAY_V, + uint8_INDIR_ARRAY_V, + uint16_INDIR_ARRAY_V, + uint32_INDIR_ARRAY_V, + POINTER_V +}; + +#define COUNT(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0])) +#define Offset(field, structure) ((int) (((char *) (&(((structure) NULL)->field))) - ((char *) NULL))) +#define OFFSET(f) Offset(f, STRUCT *) +#define DUMMY(f) Offset(f, struct Obsolete *) +#define DELETED(f) (-1) + +#define INT_ENTRY(save_version_introduced, field) \ +{ \ + OFFSET(field), \ + 0, \ + sizeof(((STRUCT *) NULL)->field), \ + INT_V, \ + save_version_introduced, \ + 9999, \ + #field \ +} + +#define ARRAY_ENTRY(save_version_introduced, field, count, elemType) \ +{ \ + OFFSET(field), \ + 0, \ + count, \ + elemType, \ + save_version_introduced, \ + 9999, \ + #field \ +} + +#define POINTER_ENTRY(save_version_introduced, field, relativeToField) \ +{ \ + OFFSET(field), \ + OFFSET(relativeToField), \ + 4, \ + POINTER_V, \ + save_version_introduced, \ + 9999, \ + #field \ +} + +#define OBSOLETE_INT_ENTRY(save_version_introduced, save_version_removed, field) \ +{ \ + DUMMY(field), \ + 0, \ + sizeof(((struct Obsolete *) NULL)->field), \ + INT_V, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +#define OBSOLETE_ARRAY_ENTRY(save_version_introduced, save_version_removed, field, count, elemType) \ +{ \ + DUMMY(field), \ + 0, \ + count, \ + elemType, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +#define OBSOLETE_POINTER_ENTRY(save_version_introduced, save_version_removed, field, relativeToField) \ +{ \ + DUMMY(field), \ + DUMMY(relativeToField), \ + 4, \ + POINTER_V, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +#define DELETED_INT_ENTRY(save_version_introduced, save_version_removed, field, size) \ +{ \ + DELETED(field), \ + 0, \ + size, \ + INT_V, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +#define DELETED_ARRAY_ENTRY(save_version_introduced, save_version_removed, field, count, elemType) \ +{ \ + DELETED(field), \ + 0, \ + count, \ + elemType, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +#define DELETED_POINTER_ENTRY(save_version_introduced, save_version_removed, field, relativeToField) \ +{ \ + DELETED(field), \ + DELETED(relativeToField), \ + 4, \ + POINTER_V, \ + save_version_introduced, \ + save_version_removed, \ + #field \ +} + +struct SDMASnapshot +{ + struct SDMA dma[8]; +}; + +struct SnapshotMovieInfo +{ + uint32 MovieInputDataSize; +}; + +struct SnapshotScreenshotInfo +{ + uint16 Width; + uint16 Height; + uint8 Interlaced; + uint8 Data[MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3]; +}; + +static struct Obsolete +{ + uint8 reserved; +} Obsolete; + +#define STRUCT struct SCPUState + +static FreezeData SnapCPU[] = +{ + INT_ENTRY(6, Cycles), + INT_ENTRY(6, PrevCycles), + INT_ENTRY(6, V_Counter), + INT_ENTRY(6, Flags), + INT_ENTRY(6, IRQActive), + INT_ENTRY(6, IRQPending), + INT_ENTRY(6, MemSpeed), + INT_ENTRY(6, MemSpeedx2), + INT_ENTRY(6, FastROMSpeed), + INT_ENTRY(6, InDMA), + INT_ENTRY(6, InHDMA), + INT_ENTRY(6, InDMAorHDMA), + INT_ENTRY(6, InWRAMDMAorHDMA), + INT_ENTRY(6, HDMARanInDMA), + INT_ENTRY(6, WhichEvent), + INT_ENTRY(6, NextEvent), + INT_ENTRY(6, WaitingForInterrupt), + INT_ENTRY(6, WaitAddress), + INT_ENTRY(6, WaitCounter), + INT_ENTRY(6, PBPCAtOpcodeStart) +}; + +#undef STRUCT +#define STRUCT struct SRegisters + +static FreezeData SnapRegisters[] = +{ + INT_ENTRY(6, PB), + INT_ENTRY(6, DB), + INT_ENTRY(6, P.W), + INT_ENTRY(6, A.W), + INT_ENTRY(6, D.W), + INT_ENTRY(6, S.W), + INT_ENTRY(6, X.W), + INT_ENTRY(6, Y.W), + INT_ENTRY(6, PCw) +}; + +#undef STRUCT +#define STRUCT struct SPPU + +static FreezeData SnapPPU[] = +{ + INT_ENTRY(6, VMA.High), + INT_ENTRY(6, VMA.Increment), + INT_ENTRY(6, VMA.Address), + INT_ENTRY(6, VMA.Mask1), + INT_ENTRY(6, VMA.FullGraphicCount), + INT_ENTRY(6, VMA.Shift), + INT_ENTRY(6, WRAM), +#define O(N) \ + INT_ENTRY(6, BG[N].SCBase), \ + INT_ENTRY(6, BG[N].HOffset), \ + INT_ENTRY(6, BG[N].VOffset), \ + INT_ENTRY(6, BG[N].BGSize), \ + INT_ENTRY(6, BG[N].NameBase), \ + INT_ENTRY(6, BG[N].SCSize) + O(0), O(1), O(2), O(3), +#undef O + INT_ENTRY(6, BGMode), + INT_ENTRY(6, BG3Priority), + INT_ENTRY(6, CGFLIP), + INT_ENTRY(6, CGFLIPRead), + INT_ENTRY(6, CGADD), + ARRAY_ENTRY(6, CGDATA, 256, uint16_ARRAY_V), +#define O(N) \ + INT_ENTRY(6, OBJ[N].HPos), \ + INT_ENTRY(6, OBJ[N].VPos), \ + INT_ENTRY(6, OBJ[N].HFlip), \ + INT_ENTRY(6, OBJ[N].VFlip), \ + INT_ENTRY(6, OBJ[N].Name), \ + INT_ENTRY(6, OBJ[N].Priority), \ + INT_ENTRY(6, OBJ[N].Palette), \ + INT_ENTRY(6, OBJ[N].Size) + 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 + INT_ENTRY(6, OBJThroughMain), + INT_ENTRY(6, OBJThroughSub), + INT_ENTRY(6, OBJAddition), + INT_ENTRY(6, OBJNameBase), + INT_ENTRY(6, OBJNameSelect), + INT_ENTRY(6, OBJSizeSelect), + INT_ENTRY(6, OAMAddr), + INT_ENTRY(6, SavedOAMAddr), + INT_ENTRY(6, OAMPriorityRotation), + INT_ENTRY(6, OAMFlip), + INT_ENTRY(6, OAMReadFlip), + INT_ENTRY(6, OAMTileAddress), + INT_ENTRY(6, OAMWriteRegister), + ARRAY_ENTRY(6, OAMData, 512 + 32, uint8_ARRAY_V), + INT_ENTRY(6, FirstSprite), + INT_ENTRY(6, LastSprite), + INT_ENTRY(6, HTimerEnabled), + INT_ENTRY(6, VTimerEnabled), + INT_ENTRY(6, HTimerPosition), + INT_ENTRY(6, VTimerPosition), + INT_ENTRY(6, IRQHBeamPos), + INT_ENTRY(6, IRQVBeamPos), + INT_ENTRY(6, HBeamFlip), + INT_ENTRY(6, VBeamFlip), + INT_ENTRY(6, HBeamPosLatched), + INT_ENTRY(6, VBeamPosLatched), + INT_ENTRY(6, GunHLatch), + INT_ENTRY(6, GunVLatch), + INT_ENTRY(6, HVBeamCounterLatched), + INT_ENTRY(6, Mode7HFlip), + INT_ENTRY(6, Mode7VFlip), + INT_ENTRY(6, Mode7Repeat), + INT_ENTRY(6, MatrixA), + INT_ENTRY(6, MatrixB), + INT_ENTRY(6, MatrixC), + INT_ENTRY(6, MatrixD), + INT_ENTRY(6, CentreX), + INT_ENTRY(6, CentreY), + INT_ENTRY(6, M7HOFS), + INT_ENTRY(6, M7VOFS), + INT_ENTRY(6, Mosaic), + INT_ENTRY(6, MosaicStart), + ARRAY_ENTRY(6, BGMosaic, 4, uint8_ARRAY_V), + INT_ENTRY(6, Window1Left), + INT_ENTRY(6, Window1Right), + INT_ENTRY(6, Window2Left), + INT_ENTRY(6, Window2Right), + INT_ENTRY(6, RecomputeClipWindows), +#define O(N) \ + INT_ENTRY(6, ClipCounts[N]), \ + INT_ENTRY(6, ClipWindowOverlapLogic[N]), \ + INT_ENTRY(6, ClipWindow1Enable[N]), \ + INT_ENTRY(6, ClipWindow2Enable[N]), \ + INT_ENTRY(6, ClipWindow1Inside[N]), \ + INT_ENTRY(6, ClipWindow2Inside[N]) + O(0), O(1), O(2), O(3), O(4), O(5), +#undef O + INT_ENTRY(6, ForcedBlanking), + INT_ENTRY(6, FixedColourRed), + INT_ENTRY(6, FixedColourGreen), + INT_ENTRY(6, FixedColourBlue), + INT_ENTRY(6, Brightness), + INT_ENTRY(6, ScreenHeight), + INT_ENTRY(6, Need16x8Mulitply), + INT_ENTRY(6, BGnxOFSbyte), + INT_ENTRY(6, M7byte), + INT_ENTRY(6, HDMA), + INT_ENTRY(6, HDMAEnded), + INT_ENTRY(6, OpenBus1), + INT_ENTRY(6, OpenBus2) +}; + +#undef STRUCT +#define STRUCT struct SDMASnapshot + +static FreezeData SnapDMA[] = +{ +#define O(N) \ + INT_ENTRY(6, dma[N].ReverseTransfer), \ + INT_ENTRY(6, dma[N].HDMAIndirectAddressing), \ + INT_ENTRY(6, dma[N].UnusedBit43x0), \ + INT_ENTRY(6, dma[N].AAddressFixed), \ + INT_ENTRY(6, dma[N].AAddressDecrement), \ + INT_ENTRY(6, dma[N].TransferMode), \ + INT_ENTRY(6, dma[N].BAddress), \ + INT_ENTRY(6, dma[N].AAddress), \ + INT_ENTRY(6, dma[N].ABank), \ + INT_ENTRY(6, dma[N].DMACount_Or_HDMAIndirectAddress), \ + INT_ENTRY(6, dma[N].IndirectBank), \ + INT_ENTRY(6, dma[N].Address), \ + INT_ENTRY(6, dma[N].Repeat), \ + INT_ENTRY(6, dma[N].LineCount), \ + INT_ENTRY(6, dma[N].UnknownByte), \ + INT_ENTRY(6, dma[N].DoTransfer) + O(0), O(1), O(2), O(3), O(4), O(5), O(6), O(7) +#undef O +}; + +#undef STRUCT +#define STRUCT struct SControlSnapshot + +static FreezeData SnapControls[] = +{ + INT_ENTRY(6, ver), + ARRAY_ENTRY(6, port1_read_idx, 2, uint8_ARRAY_V), + ARRAY_ENTRY(6, dummy1, 4, uint8_ARRAY_V), + ARRAY_ENTRY(6, port2_read_idx, 2, uint8_ARRAY_V), + ARRAY_ENTRY(6, dummy2, 4, uint8_ARRAY_V), + ARRAY_ENTRY(6, mouse_speed, 2, uint8_ARRAY_V), + INT_ENTRY(6, justifier_select), + ARRAY_ENTRY(6, dummy3, 8, uint8_ARRAY_V), + INT_ENTRY(6, pad_read), + INT_ENTRY(6, pad_read_last), + ARRAY_ENTRY(6, internal, 60, uint8_ARRAY_V) +}; + +#undef STRUCT +#define STRUCT struct STimings + +static FreezeData SnapTimings[] = +{ + INT_ENTRY(6, H_Max_Master), + INT_ENTRY(6, H_Max), + INT_ENTRY(6, V_Max_Master), + INT_ENTRY(6, V_Max), + INT_ENTRY(6, HBlankStart), + INT_ENTRY(6, HBlankEnd), + INT_ENTRY(6, HDMAInit), + INT_ENTRY(6, HDMAStart), + INT_ENTRY(6, NMITriggerPos), + INT_ENTRY(6, WRAMRefreshPos), + INT_ENTRY(6, RenderPos), + INT_ENTRY(6, InterlaceField), + INT_ENTRY(6, DMACPUSync), + INT_ENTRY(6, NMIDMADelay), + INT_ENTRY(6, IRQPendCount), + INT_ENTRY(6, APUSpeedup) +}; + +#ifndef ZSNES_FX + +#undef STRUCT +#define STRUCT struct FxRegs_s + +static FreezeData SnapFX[] = +{ + ARRAY_ENTRY(6, avReg, 16, uint32_ARRAY_V), + INT_ENTRY(6, vColorReg), + INT_ENTRY(6, vPlotOptionReg), + INT_ENTRY(6, vStatusReg), + INT_ENTRY(6, vPrgBankReg), + INT_ENTRY(6, vRomBankReg), + INT_ENTRY(6, vRamBankReg), + INT_ENTRY(6, vCacheBaseReg), + INT_ENTRY(6, vCacheFlags), + INT_ENTRY(6, vLastRamAdr), + POINTER_ENTRY(6, pvDreg, avRegAddr), + POINTER_ENTRY(6, pvSreg, avRegAddr), + INT_ENTRY(6, vRomBuffer), + INT_ENTRY(6, vPipe), + INT_ENTRY(6, vPipeAdr), + INT_ENTRY(6, vSign), + INT_ENTRY(6, vZero), + INT_ENTRY(6, vCarry), + INT_ENTRY(6, vOverflow), + INT_ENTRY(6, vErrorCode), + INT_ENTRY(6, vIllegalAddress), + INT_ENTRY(6, bBreakPoint), + INT_ENTRY(6, vBreakPoint), + INT_ENTRY(6, vStepPoint), + INT_ENTRY(6, nRamBanks), + INT_ENTRY(6, nRomBanks), + INT_ENTRY(6, vMode), + INT_ENTRY(6, vPrevMode), + POINTER_ENTRY(6, pvScreenBase, pvRam), +#define O(N) \ + POINTER_ENTRY(6, apvScreen[N], pvRam) + 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), +#undef O + ARRAY_ENTRY(6, x, 32, uint32_ARRAY_V), + INT_ENTRY(6, vScreenHeight), + INT_ENTRY(6, vScreenRealHeight), + INT_ENTRY(6, vPrevScreenHeight), + INT_ENTRY(6, vScreenSize), + POINTER_ENTRY(6, pvRamBank, apvRamBank), + POINTER_ENTRY(6, pvRomBank, apvRomBank), + POINTER_ENTRY(6, pvPrgBank, apvRomBank), +#define O(N) \ + POINTER_ENTRY(6, apvRamBank[N], pvRam) + O(0), O(1), O(2), O(3), +#undef O + INT_ENTRY(6, bCacheActive), + POINTER_ENTRY(6, pvCache, pvRegisters), + ARRAY_ENTRY(6, avCacheBackup, 512, uint8_ARRAY_V), + INT_ENTRY(6, vCounter), + INT_ENTRY(6, vInstCount), + INT_ENTRY(6, vSCBRDirty) +}; + +#endif + +#undef STRUCT +#define STRUCT struct SSA1 + +static FreezeData SnapSA1[] = +{ + INT_ENTRY(6, CPUExecuting), + INT_ENTRY(6, ShiftedPB), + INT_ENTRY(6, ShiftedDB), + INT_ENTRY(6, Flags), + INT_ENTRY(6, IRQActive), + INT_ENTRY(6, Waiting), + INT_ENTRY(6, WaitingForInterrupt), + INT_ENTRY(6, WaitAddress), + INT_ENTRY(6, WaitCounter), + INT_ENTRY(6, PBPCAtOpcodeStart), + INT_ENTRY(6, Executing), + INT_ENTRY(6, overflow), + INT_ENTRY(6, in_char_dma), + INT_ENTRY(6, op1), + INT_ENTRY(6, op2), + INT_ENTRY(6, arithmetic_op), + INT_ENTRY(6, sum), + INT_ENTRY(6, VirtualBitmapFormat), + INT_ENTRY(6, variable_bit_pos) +}; + +#undef STRUCT +#define STRUCT struct SSA1Registers + +static FreezeData SnapSA1Registers[] = +{ + INT_ENTRY(6, PB), + INT_ENTRY(6, DB), + INT_ENTRY(6, P.W), + INT_ENTRY(6, A.W), + INT_ENTRY(6, D.W), + INT_ENTRY(6, S.W), + INT_ENTRY(6, X.W), + INT_ENTRY(6, Y.W), + INT_ENTRY(6, PCw) +}; + +#undef STRUCT +#define STRUCT struct SDSP1 + +static FreezeData SnapDSP1[] = +{ + INT_ENTRY(6, waiting4command), + INT_ENTRY(6, first_parameter), + INT_ENTRY(6, command), + INT_ENTRY(6, in_count), + INT_ENTRY(6, in_index), + INT_ENTRY(6, out_count), + INT_ENTRY(6, out_index), + ARRAY_ENTRY(6, parameters, 512, uint8_ARRAY_V), + ARRAY_ENTRY(6, output, 512, uint8_ARRAY_V), + INT_ENTRY(6, CentreX), + INT_ENTRY(6, CentreY), + INT_ENTRY(6, VOffset), + INT_ENTRY(6, VPlane_C), + INT_ENTRY(6, VPlane_E), + INT_ENTRY(6, SinAas), + INT_ENTRY(6, CosAas), + INT_ENTRY(6, SinAzs), + INT_ENTRY(6, CosAzs), + INT_ENTRY(6, SinAZS), + INT_ENTRY(6, CosAZS), + INT_ENTRY(6, SecAZS_C1), + INT_ENTRY(6, SecAZS_E1), + INT_ENTRY(6, SecAZS_C2), + INT_ENTRY(6, SecAZS_E2), + INT_ENTRY(6, Nx), + INT_ENTRY(6, Ny), + INT_ENTRY(6, Nz), + INT_ENTRY(6, Gx), + INT_ENTRY(6, Gy), + INT_ENTRY(6, Gz), + INT_ENTRY(6, C_Les), + INT_ENTRY(6, E_Les), + INT_ENTRY(6, G_Les), +#define O(N) \ + ARRAY_ENTRY(6, matrixA[N], 3, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, matrixB[N], 3, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, matrixC[N], 3, uint16_ARRAY_V) + O(0), O(1), O(2), +#undef O + INT_ENTRY(6, Op00Multiplicand), + INT_ENTRY(6, Op00Multiplier), + INT_ENTRY(6, Op00Result), + INT_ENTRY(6, Op20Multiplicand), + INT_ENTRY(6, Op20Multiplier), + INT_ENTRY(6, Op20Result), + INT_ENTRY(6, Op10Coefficient), + INT_ENTRY(6, Op10Exponent), + INT_ENTRY(6, Op10CoefficientR), + INT_ENTRY(6, Op10ExponentR), + INT_ENTRY(6, Op04Angle), + INT_ENTRY(6, Op04Radius), + INT_ENTRY(6, Op04Sin), + INT_ENTRY(6, Op04Cos), + INT_ENTRY(6, Op0CA), + INT_ENTRY(6, Op0CX1), + INT_ENTRY(6, Op0CY1), + INT_ENTRY(6, Op0CX2), + INT_ENTRY(6, Op0CY2), + INT_ENTRY(6, Op02FX), + INT_ENTRY(6, Op02FY), + INT_ENTRY(6, Op02FZ), + INT_ENTRY(6, Op02LFE), + INT_ENTRY(6, Op02LES), + INT_ENTRY(6, Op02AAS), + INT_ENTRY(6, Op02AZS), + INT_ENTRY(6, Op02VOF), + INT_ENTRY(6, Op02VVA), + INT_ENTRY(6, Op02CX), + INT_ENTRY(6, Op02CY), + INT_ENTRY(6, Op0AVS), + INT_ENTRY(6, Op0AA), + INT_ENTRY(6, Op0AB), + INT_ENTRY(6, Op0AC), + INT_ENTRY(6, Op0AD), + INT_ENTRY(6, Op06X), + INT_ENTRY(6, Op06Y), + INT_ENTRY(6, Op06Z), + INT_ENTRY(6, Op06H), + INT_ENTRY(6, Op06V), + INT_ENTRY(6, Op06M), + INT_ENTRY(6, Op01m), + INT_ENTRY(6, Op01Zr), + INT_ENTRY(6, Op01Xr), + INT_ENTRY(6, Op01Yr), + INT_ENTRY(6, Op11m), + INT_ENTRY(6, Op11Zr), + INT_ENTRY(6, Op11Xr), + INT_ENTRY(6, Op11Yr), + INT_ENTRY(6, Op21m), + INT_ENTRY(6, Op21Zr), + INT_ENTRY(6, Op21Xr), + INT_ENTRY(6, Op21Yr), + INT_ENTRY(6, Op0DX), + INT_ENTRY(6, Op0DY), + INT_ENTRY(6, Op0DZ), + INT_ENTRY(6, Op0DF), + INT_ENTRY(6, Op0DL), + INT_ENTRY(6, Op0DU), + INT_ENTRY(6, Op1DX), + INT_ENTRY(6, Op1DY), + INT_ENTRY(6, Op1DZ), + INT_ENTRY(6, Op1DF), + INT_ENTRY(6, Op1DL), + INT_ENTRY(6, Op1DU), + INT_ENTRY(6, Op2DX), + INT_ENTRY(6, Op2DY), + INT_ENTRY(6, Op2DZ), + INT_ENTRY(6, Op2DF), + INT_ENTRY(6, Op2DL), + INT_ENTRY(6, Op2DU), + INT_ENTRY(6, Op03F), + INT_ENTRY(6, Op03L), + INT_ENTRY(6, Op03U), + INT_ENTRY(6, Op03X), + INT_ENTRY(6, Op03Y), + INT_ENTRY(6, Op03Z), + INT_ENTRY(6, Op13F), + INT_ENTRY(6, Op13L), + INT_ENTRY(6, Op13U), + INT_ENTRY(6, Op13X), + INT_ENTRY(6, Op13Y), + INT_ENTRY(6, Op13Z), + INT_ENTRY(6, Op23F), + INT_ENTRY(6, Op23L), + INT_ENTRY(6, Op23U), + INT_ENTRY(6, Op23X), + INT_ENTRY(6, Op23Y), + INT_ENTRY(6, Op23Z), + INT_ENTRY(6, Op14Zr), + INT_ENTRY(6, Op14Xr), + INT_ENTRY(6, Op14Yr), + INT_ENTRY(6, Op14U), + INT_ENTRY(6, Op14F), + INT_ENTRY(6, Op14L), + INT_ENTRY(6, Op14Zrr), + INT_ENTRY(6, Op14Xrr), + INT_ENTRY(6, Op14Yrr), + INT_ENTRY(6, Op0EH), + INT_ENTRY(6, Op0EV), + INT_ENTRY(6, Op0EX), + INT_ENTRY(6, Op0EY), + INT_ENTRY(6, Op0BX), + INT_ENTRY(6, Op0BY), + INT_ENTRY(6, Op0BZ), + INT_ENTRY(6, Op0BS), + INT_ENTRY(6, Op1BX), + INT_ENTRY(6, Op1BY), + INT_ENTRY(6, Op1BZ), + INT_ENTRY(6, Op1BS), + INT_ENTRY(6, Op2BX), + INT_ENTRY(6, Op2BY), + INT_ENTRY(6, Op2BZ), + INT_ENTRY(6, Op2BS), + INT_ENTRY(6, Op28X), + INT_ENTRY(6, Op28Y), + INT_ENTRY(6, Op28Z), + INT_ENTRY(6, Op28R), + INT_ENTRY(6, Op1CX), + INT_ENTRY(6, Op1CY), + INT_ENTRY(6, Op1CZ), + INT_ENTRY(6, Op1CXBR), + INT_ENTRY(6, Op1CYBR), + INT_ENTRY(6, Op1CZBR), + INT_ENTRY(6, Op1CXAR), + INT_ENTRY(6, Op1CYAR), + INT_ENTRY(6, Op1CZAR), + INT_ENTRY(6, Op1CX1), + INT_ENTRY(6, Op1CY1), + INT_ENTRY(6, Op1CZ1), + INT_ENTRY(6, Op1CX2), + INT_ENTRY(6, Op1CY2), + INT_ENTRY(6, Op1CZ2), + INT_ENTRY(6, Op0FRamsize), + INT_ENTRY(6, Op0FPass), + INT_ENTRY(6, Op2FUnknown), + INT_ENTRY(6, Op2FSize), + INT_ENTRY(6, Op08X), + INT_ENTRY(6, Op08Y), + INT_ENTRY(6, Op08Z), + INT_ENTRY(6, Op08Ll), + INT_ENTRY(6, Op08Lh), + INT_ENTRY(6, Op18X), + INT_ENTRY(6, Op18Y), + INT_ENTRY(6, Op18Z), + INT_ENTRY(6, Op18R), + INT_ENTRY(6, Op18D), + INT_ENTRY(6, Op38X), + INT_ENTRY(6, Op38Y), + INT_ENTRY(6, Op38Z), + INT_ENTRY(6, Op38R), + INT_ENTRY(6, Op38D) +}; + +#undef STRUCT +#define STRUCT struct SDSP2 + +static FreezeData SnapDSP2[] = +{ + INT_ENTRY(6, waiting4command), + INT_ENTRY(6, command), + INT_ENTRY(6, in_count), + INT_ENTRY(6, in_index), + INT_ENTRY(6, out_count), + INT_ENTRY(6, out_index), + ARRAY_ENTRY(6, parameters, 512, uint8_ARRAY_V), + ARRAY_ENTRY(6, output, 512, uint8_ARRAY_V), + INT_ENTRY(6, Op05HasLen), + INT_ENTRY(6, Op05Len), + INT_ENTRY(6, Op05Transparent), + INT_ENTRY(6, Op06HasLen), + INT_ENTRY(6, Op06Len), + INT_ENTRY(6, Op09Word1), + INT_ENTRY(6, Op09Word2), + INT_ENTRY(6, Op0DHasLen), + INT_ENTRY(6, Op0DOutLen), + INT_ENTRY(6, Op0DInLen) +}; + +#undef STRUCT +#define STRUCT struct SDSP4 + +static FreezeData SnapDSP4[] = +{ + INT_ENTRY(6, waiting4command), + INT_ENTRY(6, half_command), + INT_ENTRY(6, command), + INT_ENTRY(6, in_count), + INT_ENTRY(6, in_index), + INT_ENTRY(6, out_count), + INT_ENTRY(6, out_index), + ARRAY_ENTRY(6, parameters, 512, uint8_ARRAY_V), + ARRAY_ENTRY(6, output, 512, uint8_ARRAY_V), + INT_ENTRY(6, byte), + INT_ENTRY(6, address), + INT_ENTRY(6, Logic), + INT_ENTRY(6, lcv), + INT_ENTRY(6, distance), + INT_ENTRY(6, raster), + INT_ENTRY(6, segments), + INT_ENTRY(6, world_x), + INT_ENTRY(6, world_y), + INT_ENTRY(6, world_dx), + INT_ENTRY(6, world_dy), + INT_ENTRY(6, world_ddx), + INT_ENTRY(6, world_ddy), + INT_ENTRY(6, world_xenv), + INT_ENTRY(6, world_yofs), + INT_ENTRY(6, view_x1), + INT_ENTRY(6, view_y1), + INT_ENTRY(6, view_x2), + INT_ENTRY(6, view_y2), + INT_ENTRY(6, view_dx), + INT_ENTRY(6, view_dy), + INT_ENTRY(6, view_xofs1), + INT_ENTRY(6, view_yofs1), + INT_ENTRY(6, view_xofs2), + INT_ENTRY(6, view_yofs2), + INT_ENTRY(6, view_yofsenv), + INT_ENTRY(6, view_turnoff_x), + INT_ENTRY(6, view_turnoff_dx), + INT_ENTRY(6, viewport_cx), + INT_ENTRY(6, viewport_cy), + INT_ENTRY(6, viewport_left), + INT_ENTRY(6, viewport_right), + INT_ENTRY(6, viewport_top), + INT_ENTRY(6, viewport_bottom), + INT_ENTRY(6, sprite_x), + INT_ENTRY(6, sprite_y), + INT_ENTRY(6, sprite_attr), + INT_ENTRY(6, sprite_size), + INT_ENTRY(6, sprite_clipy), + INT_ENTRY(6, sprite_count), +#define O(N) \ + ARRAY_ENTRY(6, poly_clipLf[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_clipRt[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_ptr[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_raster[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_top[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_bottom[N], 2, uint16_ARRAY_V), \ + ARRAY_ENTRY(6, poly_cx[N], 2, uint16_ARRAY_V) + O(0), O(1), +#undef O + ARRAY_ENTRY(6, poly_start, 2, uint16_ARRAY_V), + ARRAY_ENTRY(6, poly_plane, 2, uint16_ARRAY_V), + ARRAY_ENTRY(6, OAM_attr, 16, uint16_ARRAY_V), + INT_ENTRY(6, OAM_index), + INT_ENTRY(6, OAM_bits), + INT_ENTRY(6, OAM_RowMax), + ARRAY_ENTRY(6, OAM_Row, 32, uint16_ARRAY_V) +}; + +#undef STRUCT +#define STRUCT struct SST010 + +static FreezeData SnapST010[] = +{ + ARRAY_ENTRY(6, input_params, 16, uint8_ARRAY_V), + ARRAY_ENTRY(6, output_params, 16, uint8_ARRAY_V), + INT_ENTRY(6, op_reg), + INT_ENTRY(6, execute), + INT_ENTRY(6, control_enable) +}; + +#undef STRUCT +#define STRUCT struct SOBC1 + +static FreezeData SnapOBC1[] = +{ + INT_ENTRY(6, address), + INT_ENTRY(6, basePtr), + INT_ENTRY(6, shift) +}; + +#undef STRUCT +#define STRUCT struct SSPC7110Snapshot + +static FreezeData SnapSPC7110Snap[] = +{ + INT_ENTRY(6, r4801), + INT_ENTRY(6, r4802), + INT_ENTRY(6, r4803), + INT_ENTRY(6, r4804), + INT_ENTRY(6, r4805), + INT_ENTRY(6, r4806), + INT_ENTRY(6, r4807), + INT_ENTRY(6, r4808), + INT_ENTRY(6, r4809), + INT_ENTRY(6, r480a), + INT_ENTRY(6, r480b), + INT_ENTRY(6, r480c), + INT_ENTRY(6, r4811), + INT_ENTRY(6, r4812), + INT_ENTRY(6, r4813), + INT_ENTRY(6, r4814), + INT_ENTRY(6, r4815), + INT_ENTRY(6, r4816), + INT_ENTRY(6, r4817), + INT_ENTRY(6, r4818), + INT_ENTRY(6, r481x), + INT_ENTRY(6, r4814_latch), + INT_ENTRY(6, r4815_latch), + INT_ENTRY(6, r4820), + INT_ENTRY(6, r4821), + INT_ENTRY(6, r4822), + INT_ENTRY(6, r4823), + INT_ENTRY(6, r4824), + INT_ENTRY(6, r4825), + INT_ENTRY(6, r4826), + INT_ENTRY(6, r4827), + INT_ENTRY(6, r4828), + INT_ENTRY(6, r4829), + INT_ENTRY(6, r482a), + INT_ENTRY(6, r482b), + INT_ENTRY(6, r482c), + INT_ENTRY(6, r482d), + INT_ENTRY(6, r482e), + INT_ENTRY(6, r482f), + INT_ENTRY(6, r4830), + INT_ENTRY(6, r4831), + INT_ENTRY(6, r4832), + INT_ENTRY(6, r4833), + INT_ENTRY(6, r4834), + INT_ENTRY(6, dx_offset), + INT_ENTRY(6, ex_offset), + INT_ENTRY(6, fx_offset), + INT_ENTRY(6, r4840), + INT_ENTRY(6, r4841), + INT_ENTRY(6, r4842), + INT_ENTRY(6, rtc_state), + INT_ENTRY(6, rtc_mode), + INT_ENTRY(6, rtc_index), + INT_ENTRY(6, decomp_mode), + INT_ENTRY(6, decomp_offset), + ARRAY_ENTRY(6, decomp_buffer, SPC7110_DECOMP_BUFFER_SIZE, uint8_ARRAY_V), + INT_ENTRY(6, decomp_buffer_rdoffset), + INT_ENTRY(6, decomp_buffer_wroffset), + INT_ENTRY(6, decomp_buffer_length), +#define O(N) \ + INT_ENTRY(6, context[N].index), \ + INT_ENTRY(6, context[N].invert) + 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) +#undef O +}; + +#undef STRUCT +#define STRUCT struct SSRTCSnapshot + +static FreezeData SnapSRTCSnap[] = +{ + INT_ENTRY(6, rtc_mode), + INT_ENTRY(6, rtc_index) +}; + +#undef STRUCT +#define STRUCT struct SBSX + +static FreezeData SnapBSX[] = +{ + INT_ENTRY(6, dirty), + INT_ENTRY(6, dirty2), + INT_ENTRY(6, bootup), + INT_ENTRY(6, flash_enable), + INT_ENTRY(6, write_enable), + INT_ENTRY(6, read_enable), + INT_ENTRY(6, flash_command), + INT_ENTRY(6, old_write), + INT_ENTRY(6, new_write), + INT_ENTRY(6, out_index), + ARRAY_ENTRY(6, output, 32, uint8_ARRAY_V), + ARRAY_ENTRY(6, PPU, 32, uint8_ARRAY_V), + ARRAY_ENTRY(6, MMC, 16, uint8_ARRAY_V), + ARRAY_ENTRY(6, prevMMC, 16, uint8_ARRAY_V), + ARRAY_ENTRY(6, test2192, 32, uint8_ARRAY_V) +}; + +#undef STRUCT +#define STRUCT struct SnapshotScreenshotInfo + +static FreezeData SnapScreenshot[] = +{ + INT_ENTRY(6, Width), + INT_ENTRY(6, Height), + INT_ENTRY(6, Interlaced), + ARRAY_ENTRY(6, Data, MAX_SNES_WIDTH * MAX_SNES_HEIGHT * 3, uint8_ARRAY_V) +}; + +#undef STRUCT +#define STRUCT struct SnapshotMovieInfo + +static FreezeData SnapMovie[] = +{ + INT_ENTRY(6, MovieInputDataSize) +}; + +static int UnfreezeBlock (STREAM, const char *, uint8 *, int); +static int UnfreezeBlockCopy (STREAM, const char *, uint8 **, int); +static int UnfreezeStruct (STREAM, const char *, void *, FreezeData *, int, int); +static int UnfreezeStructCopy (STREAM, const char *, uint8 **, FreezeData *, int, int); +static void UnfreezeStructFromCopy (void *, FreezeData *, int, uint8 *, int); +static void FreezeBlock (STREAM, const char *, uint8 *, int); +static void FreezeStruct (STREAM, const char *, void *, FreezeData *, int); + + +void S9xResetSaveTimer (bool8 dontsave) +{ + static time_t t = -1; + + if (!Settings.DontSaveOopsSnapshot && !dontsave && t != -1 && time(NULL) - t > 300) + { + char filename[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, def, ext); + sprintf(filename, "%s%s%s.%.*s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, _MAX_EXT - 1, "oops"); + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, SAVE_INFO_OOPS); + S9xFreezeGame(filename); + } + + t = time(NULL); +} + +bool8 S9xFreezeGame (const char *filename) +{ + STREAM stream = NULL; + + if (S9xOpenSnapshotFile(filename, FALSE, &stream)) + { + S9xFreezeToStream(stream); + S9xCloseSnapshotFile(stream); + + S9xResetSaveTimer(TRUE); + + const char *base = S9xBasename(filename); + if (S9xMovieActive()) + sprintf(String, MOVIE_INFO_SNAPSHOT " %s", base); + else + sprintf(String, SAVE_INFO_SNAPSHOT " %s", base); + + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); + + return (TRUE); + } + + return (FALSE); +} + +bool8 S9xUnfreezeGame (const char *filename) +{ + STREAM stream = NULL; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + const char *base = S9xBasename(filename); + + _splitpath(filename, drive, dir, def, ext); + S9xResetSaveTimer(!strcmp(ext, "oops") || !strcmp(ext, "oop") || !strcmp(ext, ".oops") || !strcmp(ext, ".oop")); + + if (S9xOpenSnapshotFile(filename, TRUE, &stream)) + { + int result; + + result = S9xUnfreezeFromStream(stream); + S9xCloseSnapshotFile(stream); + + if (result != SUCCESS) + { + switch (result) + { + case WRONG_FORMAT: + S9xMessage(S9X_ERROR, S9X_WRONG_FORMAT, SAVE_ERR_WRONG_FORMAT); + break; + + case WRONG_VERSION: + S9xMessage(S9X_ERROR, S9X_WRONG_VERSION, SAVE_ERR_WRONG_VERSION); + break; + + case WRONG_MOVIE_SNAPSHOT: + S9xMessage(S9X_ERROR, S9X_WRONG_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_WRONG_MOVIE); + break; + + case NOT_A_MOVIE_SNAPSHOT: + S9xMessage(S9X_ERROR, S9X_NOT_A_MOVIE_SNAPSHOT, MOVIE_ERR_SNAPSHOT_NOT_MOVIE); + break; + + case SNAPSHOT_INCONSISTENT: + S9xMessage(S9X_ERROR, S9X_SNAPSHOT_INCONSISTENT, MOVIE_ERR_SNAPSHOT_INCONSISTENT); + break; + + case FILE_NOT_FOUND: + default: + sprintf(String, SAVE_ERR_ROM_NOT_FOUND, base); + S9xMessage(S9X_ERROR, S9X_ROM_NOT_FOUND, String); + break; + } + + return (FALSE); + } + + if (S9xMovieActive()) + { + if (S9xMovieReadOnly()) + sprintf(String, MOVIE_INFO_REWIND " %s", base); + else + sprintf(String, MOVIE_INFO_RERECORD " %s", base); + } + else + sprintf(String, SAVE_INFO_LOAD " %s", base); + + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); + + return (TRUE); + } + + sprintf(String, SAVE_ERR_SAVE_NOT_FOUND, base); + S9xMessage(S9X_INFO, S9X_FREEZE_FILE_INFO, String); + + return (FALSE); +} + +void S9xFreezeToStream (STREAM stream) +{ + char buffer[1024]; + + S9xSetSoundMute(TRUE); + +#ifdef ZSNES_FX + if (Settings.SuperFX) + S9xSuperFXPreSaveState(); +#endif + + sprintf(buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION); + WRITE_STREAM(buffer, strlen(buffer), stream); + + sprintf(buffer, "NAM:%06d:%s%c", (int) strlen(Memory.ROMFilename) + 1, Memory.ROMFilename, 0); + WRITE_STREAM(buffer, strlen(buffer) + 1, stream); + + FreezeStruct(stream, "CPU", &CPU, SnapCPU, COUNT(SnapCPU)); + + FreezeStruct(stream, "REG", &Registers, SnapRegisters, COUNT(SnapRegisters)); + + FreezeStruct(stream, "PPU", &PPU, SnapPPU, COUNT(SnapPPU)); + + struct SDMASnapshot dma_snap; + for (int d = 0; d < 8; d++) + dma_snap.dma[d] = DMA[d]; + FreezeStruct(stream, "DMA", &dma_snap, SnapDMA, COUNT(SnapDMA)); + + FreezeBlock (stream, "VRA", Memory.VRAM, 0x10000); + + FreezeBlock (stream, "RAM", Memory.RAM, 0x20000); + + FreezeBlock (stream, "SRA", Memory.SRAM, 0x20000); + + FreezeBlock (stream, "FIL", Memory.FillRAM, 0x8000); + + uint8 soundsnapshot[SPC_SAVE_STATE_BLOCK_SIZE]; + S9xAPUSaveState(soundsnapshot); + FreezeBlock (stream, "SND", soundsnapshot, SPC_SAVE_STATE_BLOCK_SIZE); + + struct SControlSnapshot ctl_snap; + S9xControlPreSaveState(&ctl_snap); + FreezeStruct(stream, "CTL", &ctl_snap, SnapControls, COUNT(SnapControls)); + + FreezeStruct(stream, "TIM", &Timings, SnapTimings, COUNT(SnapTimings)); + +#ifndef ZSNES_FX + if (Settings.SuperFX) + { + GSU.avRegAddr = (uint8 *) &GSU.avReg; + FreezeStruct(stream, "SFX", &GSU, SnapFX, COUNT(SnapFX)); + } +#endif + + if (Settings.SA1) + { + S9xSA1PackStatus(); + FreezeStruct(stream, "SA1", &SA1, SnapSA1, COUNT(SnapSA1)); + FreezeStruct(stream, "SAR", &SA1Registers, SnapSA1Registers, COUNT(SnapSA1Registers)); + } + + if (Settings.DSP == 1) + FreezeStruct(stream, "DP1", &DSP1, SnapDSP1, COUNT(SnapDSP1)); + + if (Settings.DSP == 2) + FreezeStruct(stream, "DP2", &DSP2, SnapDSP2, COUNT(SnapDSP2)); + + if (Settings.DSP == 4) + FreezeStruct(stream, "DP4", &DSP4, SnapDSP4, COUNT(SnapDSP4)); + + if (Settings.C4) +#ifndef ZSNES_C4 + FreezeBlock (stream, "CX4", Memory.C4RAM, 8192); +#else + FreezeBlock (stream, "CX4", C4Ram, 8192); +#endif + + if (Settings.SETA == ST_010) + FreezeStruct(stream, "ST0", &ST010, SnapST010, COUNT(SnapST010)); + + if (Settings.OBC1) + { + FreezeStruct(stream, "OBC", &OBC1, SnapOBC1, COUNT(SnapOBC1)); + FreezeBlock (stream, "OBM", Memory.OBC1RAM, 8192); + } + + if (Settings.SPC7110) + { + S9xSPC7110PreSaveState(); + FreezeStruct(stream, "S71", &s7snap, SnapSPC7110Snap, COUNT(SnapSPC7110Snap)); + } + + if (Settings.SRTC) + { + S9xSRTCPreSaveState(); + FreezeStruct(stream, "SRT", &srtcsnap, SnapSRTCSnap, COUNT(SnapSRTCSnap)); + } + + if (Settings.SRTC || Settings.SPC7110RTC) + FreezeBlock (stream, "CLK", RTCData.reg, 20); + + if (Settings.BS) + FreezeStruct(stream, "BSX", &BSX, SnapBSX, COUNT(SnapBSX)); + + if (Settings.SnapshotScreenshots) + { + SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; + + ssi->Width = min(IPPU.RenderedScreenWidth, MAX_SNES_WIDTH); + ssi->Height = min(IPPU.RenderedScreenHeight, MAX_SNES_HEIGHT); + ssi->Interlaced = GFX.DoInterlace; + + uint8 *rowpix = ssi->Data; + uint16 *screen = GFX.Screen; + + for (int y = 0; y < ssi->Height; y++, screen += GFX.RealPPL) + { + for (int x = 0; x < ssi->Width; x++) + { + uint32 r, g, b; + + DECOMPOSE_PIXEL(screen[x], r, g, b); + *(rowpix++) = r; + *(rowpix++) = g; + *(rowpix++) = b; + } + } + + memset(rowpix, 0, sizeof(ssi->Data) + ssi->Data - rowpix); + + FreezeStruct(stream, "SHO", ssi, SnapScreenshot, COUNT(SnapScreenshot)); + + delete ssi; + } + + if (S9xMovieActive()) + { + uint8 *movie_freeze_buf; + uint32 movie_freeze_size; + + S9xMovieFreeze(&movie_freeze_buf, &movie_freeze_size); + if (movie_freeze_buf) + { + struct SnapshotMovieInfo mi; + + mi.MovieInputDataSize = movie_freeze_size; + FreezeStruct(stream, "MOV", &mi, SnapMovie, COUNT(SnapMovie)); + FreezeBlock (stream, "MID", movie_freeze_buf, movie_freeze_size); + + delete [] movie_freeze_buf; + } + } + +#ifdef ZSNES_FX + if (Settings.SuperFX) + S9xSuperFXPostSaveState(); +#endif + + S9xSetSoundMute(FALSE); +} + +int S9xUnfreezeFromStream (STREAM stream) +{ + int result = SUCCESS; + int version, len; + char buffer[PATH_MAX + 1]; + + len = strlen(SNAPSHOT_MAGIC) + 1 + 4 + 1; + if (READ_STREAM(buffer, len, stream) != len) + return (WRONG_FORMAT); + + if (strncmp(buffer, SNAPSHOT_MAGIC, strlen(SNAPSHOT_MAGIC)) != 0) + return (WRONG_FORMAT); + + version = atoi(&buffer[strlen(SNAPSHOT_MAGIC) + 1]); + if (version > SNAPSHOT_VERSION) + return (WRONG_VERSION); + + result = UnfreezeBlock(stream, "NAM", (uint8 *) buffer, PATH_MAX); + if (result != SUCCESS) + return (result); + + uint8 *local_cpu = NULL; + uint8 *local_registers = NULL; + uint8 *local_ppu = NULL; + uint8 *local_dma = NULL; + uint8 *local_vram = NULL; + uint8 *local_ram = NULL; + uint8 *local_sram = NULL; + uint8 *local_fillram = NULL; + uint8 *local_apu_sound = NULL; + uint8 *local_control_data = NULL; + uint8 *local_timing_data = NULL; + uint8 *local_superfx = NULL; + uint8 *local_sa1 = NULL; + uint8 *local_sa1_registers = NULL; + uint8 *local_dsp1 = NULL; + uint8 *local_dsp2 = NULL; + uint8 *local_dsp4 = NULL; + uint8 *local_cx4_data = NULL; + uint8 *local_st010 = NULL; + uint8 *local_obc1 = NULL; + uint8 *local_obc1_data = NULL; + uint8 *local_spc7110 = NULL; + uint8 *local_srtc = NULL; + uint8 *local_rtc_data = NULL; + uint8 *local_bsx_data = NULL; + uint8 *local_screenshot = NULL; + uint8 *local_movie_data = NULL; + + do + { + result = UnfreezeStructCopy(stream, "CPU", &local_cpu, SnapCPU, COUNT(SnapCPU), version); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "REG", &local_registers, SnapRegisters, COUNT(SnapRegisters), version); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "PPU", &local_ppu, SnapPPU, COUNT(SnapPPU), version); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "DMA", &local_dma, SnapDMA, COUNT(SnapDMA), version); + if (result != SUCCESS) + break; + + result = UnfreezeBlockCopy (stream, "VRA", &local_vram, 0x10000); + if (result != SUCCESS) + break; + + result = UnfreezeBlockCopy (stream, "RAM", &local_ram, 0x20000); + if (result != SUCCESS) + break; + + result = UnfreezeBlockCopy (stream, "SRA", &local_sram, 0x20000); + if (result != SUCCESS) + break; + + result = UnfreezeBlockCopy (stream, "FIL", &local_fillram, 0x8000); + if (result != SUCCESS) + break; + + result = UnfreezeBlockCopy (stream, "SND", &local_apu_sound, SPC_SAVE_STATE_BLOCK_SIZE); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "CTL", &local_control_data, SnapControls, COUNT(SnapControls), version); + if (result != SUCCESS) + break; + + result = UnfreezeStructCopy(stream, "TIM", &local_timing_data, SnapTimings, COUNT(SnapTimings), version); + if (result != SUCCESS) + break; + + #ifndef ZSNES_FX + result = UnfreezeStructCopy(stream, "SFX", &local_superfx, SnapFX, COUNT(SnapFX), version); + if (result != SUCCESS && Settings.SuperFX) + break; + #endif + + result = UnfreezeStructCopy(stream, "SA1", &local_sa1, SnapSA1, COUNT(SnapSA1), version); + if (result != SUCCESS && Settings.SA1) + break; + + result = UnfreezeStructCopy(stream, "SAR", &local_sa1_registers, SnapSA1Registers, COUNT(SnapSA1Registers), version); + if (result != SUCCESS && Settings.SA1) + break; + + result = UnfreezeStructCopy(stream, "DP1", &local_dsp1, SnapDSP1, COUNT(SnapDSP1), version); + if (result != SUCCESS && Settings.DSP == 1) + break; + + result = UnfreezeStructCopy(stream, "DP2", &local_dsp2, SnapDSP2, COUNT(SnapDSP2), version); + if (result != SUCCESS && Settings.DSP == 2) + break; + + result = UnfreezeStructCopy(stream, "DP4", &local_dsp4, SnapDSP4, COUNT(SnapDSP4), version); + if (result != SUCCESS && Settings.DSP == 4) + break; + + result = UnfreezeBlockCopy (stream, "CX4", &local_cx4_data, 8192); + if (result != SUCCESS && Settings.C4) + break; + + result = UnfreezeStructCopy(stream, "ST0", &local_st010, SnapST010, COUNT(SnapST010), version); + if (result != SUCCESS && Settings.SETA == ST_010) + break; + + result = UnfreezeStructCopy(stream, "OBC", &local_obc1, SnapOBC1, COUNT(SnapOBC1), version); + if (result != SUCCESS && Settings.OBC1) + break; + + result = UnfreezeBlockCopy (stream, "OBM", &local_obc1_data, 8192); + if (result != SUCCESS && Settings.OBC1) + break; + + result = UnfreezeStructCopy(stream, "S71", &local_spc7110, SnapSPC7110Snap, COUNT(SnapSPC7110Snap), version); + if (result != SUCCESS && Settings.SPC7110) + break; + + result = UnfreezeStructCopy(stream, "SRT", &local_srtc, SnapSRTCSnap, COUNT(SnapSRTCSnap), version); + if (result != SUCCESS && Settings.SRTC) + break; + + result = UnfreezeBlockCopy (stream, "CLK", &local_rtc_data, 20); + if (result != SUCCESS && (Settings.SRTC || Settings.SPC7110RTC)) + break; + + result = UnfreezeStructCopy(stream, "BSX", &local_bsx_data, SnapBSX, COUNT(SnapBSX), version); + if (result != SUCCESS && Settings.BS) + break; + + result = UnfreezeStructCopy(stream, "SHO", &local_screenshot, SnapScreenshot, COUNT(SnapScreenshot), version); + + SnapshotMovieInfo mi; + + result = UnfreezeStruct(stream, "MOV", &mi, SnapMovie, COUNT(SnapMovie), version); + if (result != SUCCESS) + { + if (S9xMovieActive()) + { + result = NOT_A_MOVIE_SNAPSHOT; + break; + } + } + else + { + result = UnfreezeBlockCopy(stream, "MID", &local_movie_data, mi.MovieInputDataSize); + if (result != SUCCESS) + { + if (S9xMovieActive()) + { + result = NOT_A_MOVIE_SNAPSHOT; + break; + } + } + + if (S9xMovieActive()) + { + result = S9xMovieUnfreeze(local_movie_data, mi.MovieInputDataSize); + if (result != SUCCESS) + break; + } + } + + result = SUCCESS; + } while (false); + + if (result == SUCCESS) + { + uint32 old_flags = CPU.Flags; + uint32 sa1_old_flags = SA1.Flags; + + S9xSetSoundMute(TRUE); + + S9xReset(); + + UnfreezeStructFromCopy(&CPU, SnapCPU, COUNT(SnapCPU), local_cpu, version); + + UnfreezeStructFromCopy(&Registers, SnapRegisters, COUNT(SnapRegisters), local_registers, version); + + UnfreezeStructFromCopy(&PPU, SnapPPU, COUNT(SnapPPU), local_ppu, version); + + struct SDMASnapshot dma_snap; + UnfreezeStructFromCopy(&dma_snap, SnapDMA, COUNT(SnapDMA), local_dma, version); + + memcpy(Memory.VRAM, local_vram, 0x10000); + + memcpy(Memory.RAM, local_ram, 0x20000); + + memcpy(Memory.SRAM, local_sram, 0x20000); + + memcpy(Memory.FillRAM, local_fillram, 0x8000); + + S9xAPULoadState(local_apu_sound); + + struct SControlSnapshot ctl_snap; + UnfreezeStructFromCopy(&ctl_snap, SnapControls, COUNT(SnapControls), local_control_data, version); + + UnfreezeStructFromCopy(&Timings, SnapTimings, COUNT(SnapTimings), local_timing_data, version); + + #ifndef ZSNES_FX + if (local_superfx) + { + GSU.avRegAddr = (uint8 *) &GSU.avReg; + UnfreezeStructFromCopy(&GSU, SnapFX, COUNT(SnapFX), local_superfx, version); + } + #endif + + if (local_sa1) + UnfreezeStructFromCopy(&SA1, SnapSA1, COUNT(SnapSA1), local_sa1, version); + + if (local_sa1_registers) + UnfreezeStructFromCopy(&SA1Registers, SnapSA1Registers, COUNT(SnapSA1Registers), local_sa1_registers, version); + + if (local_dsp1) + UnfreezeStructFromCopy(&DSP1, SnapDSP1, COUNT(SnapDSP1), local_dsp1, version); + + if (local_dsp2) + UnfreezeStructFromCopy(&DSP2, SnapDSP2, COUNT(SnapDSP2), local_dsp2, version); + + if (local_dsp4) + UnfreezeStructFromCopy(&DSP4, SnapDSP4, COUNT(SnapDSP4), local_dsp4, version); + + if (local_cx4_data) + #ifndef ZSNES_C4 + memcpy(Memory.C4RAM, local_cx4_data, 8192); + #else + memcpy(C4Ram, local_cx4_data, 8192); + #endif + + if (local_st010) + UnfreezeStructFromCopy(&ST010, SnapST010, COUNT(SnapST010), local_st010, version); + + if (local_obc1) + UnfreezeStructFromCopy(&OBC1, SnapOBC1, COUNT(SnapOBC1), local_obc1, version); + + if (local_obc1_data) + memcpy(Memory.OBC1RAM, local_obc1_data, 8192); + + if (local_spc7110) + UnfreezeStructFromCopy(&s7snap, SnapSPC7110Snap, COUNT(SnapSPC7110Snap), local_spc7110, version); + + if (local_srtc) + UnfreezeStructFromCopy(&srtcsnap, SnapSRTCSnap, COUNT(SnapSRTCSnap), local_srtc, version); + + if (local_rtc_data) + memcpy(RTCData.reg, local_rtc_data, 20); + + if (local_bsx_data) + UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version); + + CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG); + ICPU.ShiftedPB = Registers.PB << 16; + ICPU.ShiftedDB = Registers.DB << 16; + S9xSetPCBase(Registers.PBPC); + S9xUnpackStatus(); + S9xFixCycles(); + Memory.FixROMSpeed(); + + for (int d = 0; d < 8; d++) + DMA[d] = dma_snap.dma[d]; + CPU.InDMA = CPU.InHDMA = FALSE; + CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = FALSE; + CPU.HDMARanInDMA = 0; + + S9xFixColourBrightness(); + IPPU.ColorsChanged = TRUE; + IPPU.OBJChanged = TRUE; + IPPU.RenderThisFrame = TRUE; + + uint8 hdma_byte = Memory.FillRAM[0x420c]; + S9xSetCPU(hdma_byte, 0x420c); + + S9xControlPostLoadState(&ctl_snap); + + #ifndef ZSNES_FX + if (local_superfx) + { + GSU.pfPlot = fx_PlotTable[GSU.vMode]; + GSU.pfRpix = fx_PlotTable[GSU.vMode + 5]; + } + #else + if (Settings.SuperFX) + S9xSuperFXPostLoadState(); + #endif + + if (local_sa1 && local_sa1_registers) + { + SA1.Flags |= sa1_old_flags & TRACE_FLAG; + S9xSA1PostLoadState(); + } + + if (Settings.SDD1) + S9xSDD1PostLoadState(); + + if (local_spc7110) + S9xSPC7110PostLoadState(version); + + if (local_srtc) + S9xSRTCPostLoadState(version); + + if (local_bsx_data) + S9xBSXPostLoadState(); + + if (local_movie_data) + { + // restore last displayed pad_read status + extern bool8 pad_read, pad_read_last; + bool8 pad_read_temp = pad_read; + + pad_read = pad_read_last; + S9xUpdateFrameCounter(-1); + pad_read = pad_read_temp; + } + + if (local_screenshot) + { + SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; + + UnfreezeStructFromCopy(ssi, SnapScreenshot, COUNT(SnapScreenshot), local_screenshot, version); + + IPPU.RenderedScreenWidth = min(ssi->Width, IMAGE_WIDTH); + IPPU.RenderedScreenHeight = min(ssi->Height, IMAGE_HEIGHT); + const bool8 scaleDownX = IPPU.RenderedScreenWidth < ssi->Width; + const bool8 scaleDownY = IPPU.RenderedScreenHeight < ssi->Height && ssi->Height > SNES_HEIGHT_EXTENDED; + GFX.DoInterlace = Settings.SupportHiRes ? ssi->Interlaced : 0; + + uint8 *rowpix = ssi->Data; + uint16 *screen = GFX.Screen; + + for (int y = 0; y < IPPU.RenderedScreenHeight; y++, screen += GFX.RealPPL) + { + for (int x = 0; x < IPPU.RenderedScreenWidth; x++) + { + uint32 r, g, b; + + r = *(rowpix++); + g = *(rowpix++); + b = *(rowpix++); + + if (scaleDownX) + { + r = (r + *(rowpix++)) >> 1; + g = (g + *(rowpix++)) >> 1; + b = (b + *(rowpix++)) >> 1; + + if (x + x + 1 >= ssi->Width) + break; + } + + screen[x] = BUILD_PIXEL(r, g, b); + } + + if (scaleDownY) + { + rowpix += 3 * ssi->Width; + if (y + y + 1 >= ssi->Height) + break; + } + } + + // black out what we might have missed + for (uint32 y = IPPU.RenderedScreenHeight; y < (uint32) (IMAGE_HEIGHT); y++) + memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL * 2); + + delete ssi; + } + else + { + // couldn't load graphics, so black out the screen instead + for (uint32 y = 0; y < (uint32) (IMAGE_HEIGHT); y++) + memset(GFX.Screen + y * GFX.RealPPL, 0, GFX.RealPPL * 2); + } + + S9xSetSoundMute(FALSE); + } + + if (local_cpu) delete [] local_cpu; + if (local_registers) delete [] local_registers; + if (local_ppu) delete [] local_ppu; + if (local_dma) delete [] local_dma; + if (local_vram) delete [] local_vram; + if (local_ram) delete [] local_ram; + if (local_sram) delete [] local_sram; + if (local_fillram) delete [] local_fillram; + if (local_apu_sound) delete [] local_apu_sound; + if (local_control_data) delete [] local_control_data; + if (local_timing_data) delete [] local_timing_data; + if (local_superfx) delete [] local_superfx; + if (local_sa1) delete [] local_sa1; + if (local_sa1_registers) delete [] local_sa1_registers; + if (local_dsp1) delete [] local_dsp1; + if (local_dsp2) delete [] local_dsp2; + if (local_dsp4) delete [] local_dsp4; + if (local_cx4_data) delete [] local_cx4_data; + if (local_st010) delete [] local_st010; + if (local_obc1) delete [] local_obc1; + if (local_obc1_data) delete [] local_obc1_data; + if (local_spc7110) delete [] local_spc7110; + if (local_srtc) delete [] local_srtc; + if (local_rtc_data) delete [] local_rtc_data; + if (local_bsx_data) delete [] local_bsx_data; + if (local_screenshot) delete [] local_screenshot; + if (local_movie_data) delete [] local_movie_data; + + return (result); +} + +static int FreezeSize (int size, int type) +{ + switch (type) + { + case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: + return (size * 4); + + case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: + return (size * 2); + + default: + return (size); + } +} + +static void FreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, int num_fields) +{ + int len = 0; + int i, j; + + for (i = 0; i < num_fields; i++) + { + if (SNAPSHOT_VERSION < fields[i].debuted_in) + { + fprintf(stderr, "%s[%p]: field has bad debuted_in value %d, > %d.", name, (void *) fields, fields[i].debuted_in, SNAPSHOT_VERSION); + continue; + } + + if (SNAPSHOT_VERSION < fields[i].deleted_in) + len += FreezeSize(fields[i].size, fields[i].type); + } + + uint8 *block = new uint8[len]; + uint8 *ptr = block; + uint8 *addr; + uint16 word; + uint32 dword; + int64 qword; + int relativeAddr; + + for (i = 0; i < num_fields; i++) + { + if (SNAPSHOT_VERSION >= fields[i].deleted_in || SNAPSHOT_VERSION < fields[i].debuted_in) + continue; + + addr = (uint8 *) base + fields[i].offset; + + // determine real address of indirect-type fields + // (where the structure contains a pointer to an array rather than the array itself) + if (fields[i].type == uint8_INDIR_ARRAY_V || fields[i].type == uint16_INDIR_ARRAY_V || fields[i].type == uint32_INDIR_ARRAY_V) + addr = (uint8 *) (*((pint *) addr)); + + // convert pointer-type saves from absolute to relative pointers + if (fields[i].type == POINTER_V) + { + uint8 *pointer = (uint8 *) *((pint *) ((uint8 *) base + fields[i].offset)); + uint8 *relativeTo = (uint8 *) *((pint *) ((uint8 *) base + fields[i].offset2)); + relativeAddr = pointer - relativeTo; + addr = (uint8 *) &relativeAddr; + } + + switch (fields[i].type) + { + case INT_V: + case POINTER_V: + switch (fields[i].size) + { + case 1: + *ptr++ = *(addr); + break; + + case 2: + word = *((uint16 *) (addr)); + *ptr++ = (uint8) (word >> 8); + *ptr++ = (uint8) word; + break; + + case 4: + dword = *((uint32 *) (addr)); + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + break; + + case 8: + qword = *((int64 *) (addr)); + *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: + case uint8_INDIR_ARRAY_V: + memmove(ptr, addr, fields[i].size); + ptr += fields[i].size; + + break; + + case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: + for (j = 0; j < fields[i].size; j++) + { + word = *((uint16 *) (addr + j * 2)); + *ptr++ = (uint8) (word >> 8); + *ptr++ = (uint8) word; + } + + break; + + case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: + for (j = 0; j < fields[i].size; j++) + { + dword = *((uint32 *) (addr + j * 4)); + *ptr++ = (uint8) (dword >> 24); + *ptr++ = (uint8) (dword >> 16); + *ptr++ = (uint8) (dword >> 8); + *ptr++ = (uint8) dword; + } + + break; + } + } + + FreezeBlock(stream, name, block, len); + delete [] block; +} + +static void FreezeBlock (STREAM stream, const char *name, uint8 *block, int size) +{ + char buffer[20]; + + // check if it fits in 6 digits. (letting it go over and using strlen isn't safe) + if (size <= 999999) + sprintf(buffer, "%s:%06d:", name, size); + else + { + // to make it fit, pack it in the bytes instead of as digits + sprintf(buffer, "%s:------:", name); + buffer[6] = (unsigned char) ((unsigned) size >> 24); + buffer[7] = (unsigned char) ((unsigned) size >> 16); + buffer[8] = (unsigned char) ((unsigned) size >> 8); + buffer[9] = (unsigned char) ((unsigned) size >> 0); + } + + buffer[11] = 0; + + WRITE_STREAM(buffer, 11, stream); + WRITE_STREAM(block, size, stream); +} + +static int UnfreezeBlock (STREAM stream, const char *name, uint8 *block, int size) +{ + char buffer[20]; + int len = 0, rem = 0; + long rewind = FIND_STREAM(stream); + + size_t l = READ_STREAM(buffer, 11, stream); + buffer[l] = 0; + + if (l != 11 || strncmp(buffer, name, 3) != 0 || buffer[3] != ':') + { + err: + fprintf(stdout, "absent: %s(%d); next: '%.11s'\n", name, size, buffer); + REVERT_STREAM(stream, FIND_STREAM(stream) - l, 0); + return (WRONG_FORMAT); + } + + if (buffer[4] == '-') + { + len = (((unsigned char) buffer[6]) << 24) + | (((unsigned char) buffer[7]) << 16) + | (((unsigned char) buffer[8]) << 8) + | (((unsigned char) buffer[9]) << 0); + } + else + len = atoi(buffer + 4); + + if (len <= 0) + goto err; + + if (len > size) + { + rem = len - size; + len = size; + } + + ZeroMemory(block, size); + + if (READ_STREAM(block, len, stream) != len) + { + REVERT_STREAM(stream, rewind, 0); + return (WRONG_FORMAT); + } + + if (rem) + { + char *junk = new char[rem]; + len = READ_STREAM(junk, rem, stream); + delete [] junk; + if (len != rem) + { + REVERT_STREAM(stream, rewind, 0); + return (WRONG_FORMAT); + } + } + + return (SUCCESS); +} + +static int UnfreezeBlockCopy (STREAM stream, const char *name, uint8 **block, int size) +{ + int result; + + *block = new uint8[size]; + + result = UnfreezeBlock(stream, name, *block, size); + if (result != SUCCESS) + { + delete [] (*block); + *block = NULL; + return (result); + } + + return (SUCCESS); +} + +static int UnfreezeStruct (STREAM stream, const char *name, void *base, FreezeData *fields, int num_fields, int version) +{ + int result; + uint8 *block = NULL; + + result = UnfreezeStructCopy(stream, name, &block, fields, num_fields, version); + if (result != SUCCESS) + { + if (block != NULL) + delete [] block; + return (result); + } + + UnfreezeStructFromCopy(base, fields, num_fields, block, version); + delete [] block; + + return (SUCCESS); +} + +static int UnfreezeStructCopy (STREAM stream, const char *name, uint8 **block, FreezeData *fields, int num_fields, int version) +{ + int len = 0; + + for (int i = 0; i < num_fields; i++) + { + if (version >= fields[i].debuted_in && version < fields[i].deleted_in) + len += FreezeSize(fields[i].size, fields[i].type); + } + + return (UnfreezeBlockCopy(stream, name, block, len)); +} + +static void UnfreezeStructFromCopy (void *sbase, FreezeData *fields, int num_fields, uint8 *block, int version) +{ + uint8 *ptr = block; + uint16 word; + uint32 dword; + int64 qword; + uint8 *addr; + void *base; + int relativeAddr; + int i, j; + + for (i = 0; i < num_fields; i++) + { + if (version < fields[i].debuted_in || version >= fields[i].deleted_in) + continue; + + base = (SNAPSHOT_VERSION >= fields[i].deleted_in) ? ((void *) &Obsolete) : sbase; + addr = (uint8 *) base + fields[i].offset; + + if (fields[i].type == uint8_INDIR_ARRAY_V || fields[i].type == uint16_INDIR_ARRAY_V || fields[i].type == uint32_INDIR_ARRAY_V) + addr = (uint8 *) (*((pint *) addr)); + + switch (fields[i].type) + { + case INT_V: + case POINTER_V: + switch (fields[i].size) + { + case 1: + if (fields[i].offset < 0) + { + ptr++; + break; + } + + *(addr) = *ptr++; + break; + + case 2: + if (fields[i].offset < 0) + { + ptr += 2; + break; + } + + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) (addr)) = word; + break; + + case 4: + if (fields[i].offset < 0) + { + ptr += 4; + break; + } + + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) (addr)) = dword; + break; + + case 8: + if (fields[i].offset < 0) + { + ptr += 8; + break; + } + + 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 *) (addr)) = qword; + break; + + default: + assert(0); + break; + } + + break; + + case uint8_ARRAY_V: + case uint8_INDIR_ARRAY_V: + if (fields[i].offset >= 0) + memmove(addr, ptr, fields[i].size); + ptr += fields[i].size; + + break; + + case uint16_ARRAY_V: + case uint16_INDIR_ARRAY_V: + if (fields[i].offset < 0) + { + ptr += fields[i].size * 2; + break; + } + + for (j = 0; j < fields[i].size; j++) + { + word = *ptr++ << 8; + word |= *ptr++; + *((uint16 *) (addr + j * 2)) = word; + } + + break; + + case uint32_ARRAY_V: + case uint32_INDIR_ARRAY_V: + if (fields[i].offset < 0) + { + ptr += fields[i].size * 4; + break; + } + + for (j = 0; j < fields[i].size; j++) + { + dword = *ptr++ << 24; + dword |= *ptr++ << 16; + dword |= *ptr++ << 8; + dword |= *ptr++; + *((uint32 *) (addr + j * 4)) = dword; + } + + break; + } + + if (fields[i].type == POINTER_V) + { + relativeAddr = (int) *((pint *) ((uint8 *) base + fields[i].offset)); + uint8 *relativeTo = (uint8 *) *((pint *) ((uint8 *) base + fields[i].offset2)); + *((pint *) (addr)) = (pint) (relativeTo + relativeAddr); + } + } +} + +bool8 S9xSPCDump (const char *filename) +{ + FILE *fs; + uint8 buf[SNES_SPC::spc_file_size]; + size_t ignore; + + fs = fopen(filename, "wb"); + if (!fs) + return (FALSE); + + S9xSetSoundMute(TRUE); + + spc_core->init_header(buf); + spc_core->save_spc(buf); + + ignore = fwrite(buf, SNES_SPC::spc_file_size, 1, fs); + + fclose(fs); + + S9xSetSoundMute(FALSE); + + return (TRUE); +} diff --git a/snapshot.h b/snapshot.h new file mode 100644 index 00000000..b3ead241 --- /dev/null +++ b/snapshot.h @@ -0,0 +1,199 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _SNAPSHOT_H_ +#define _SNAPSHOT_H_ + +#define SNAPSHOT_MAGIC "#!s9xsnp" +#define SNAPSHOT_VERSION 6 + +#define SUCCESS 1 +#define WRONG_FORMAT (-1) +#define WRONG_VERSION (-2) +#define FILE_NOT_FOUND (-3) +#define WRONG_MOVIE_SNAPSHOT (-4) +#define NOT_A_MOVIE_SNAPSHOT (-5) +#define SNAPSHOT_INCONSISTENT (-6) + +void S9xResetSaveTimer (bool8); +bool8 S9xFreezeGame (const char *); +bool8 S9xUnfreezeGame (const char *); +void S9xFreezeToStream (STREAM); +int S9xUnfreezeFromStream (STREAM); +bool8 S9xSPCDump (const char *); + +#endif diff --git a/snes9x.cpp b/snes9x.cpp new file mode 100644 index 00000000..79fe2ad7 --- /dev/null +++ b/snes9x.cpp @@ -0,0 +1,922 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 HAVE_STRINGS_H +#include +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "controls.h" +#include "crosshairs.h" +#include "cheats.h" +#include "display.h" +#include "conffile.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif + +#ifdef DEBUGGER +extern FILE *trace; +#endif + +#define S9X_CONF_FILE_NAME "snes9x.conf" + +static char *rom_filename = NULL; + +static bool parse_controller_spec (int, const char *); +static void parse_crosshair_spec (enum crosscontrols, const char *); +static bool try_load_config_file (const char *, ConfigFile &); + + +static bool parse_controller_spec (int port, const char *arg) +{ + if (!strcasecmp(arg, "none")) + S9xSetController(port, CTL_NONE, 0, 0, 0, 0); + else + if (!strncasecmp(arg, "pad", 3) && arg[3] >= '1' && arg[3] <= '8' && arg[4] == '\0') + S9xSetController(port, CTL_JOYPAD, arg[3] - '1', 0, 0, 0); + else + if (!strncasecmp(arg, "mouse", 5) && arg[5] >= '1' && arg[5] <= '2' && arg[6] == '\0') + S9xSetController(port, CTL_MOUSE, arg[5] - '1', 0, 0, 0); + else + if (!strcasecmp(arg, "superscope")) + S9xSetController(port, CTL_SUPERSCOPE, 0, 0, 0, 0); + else + if (!strcasecmp(arg, "justifier")) + S9xSetController(port, CTL_JUSTIFIER, 0, 0, 0, 0); + else + if (!strcasecmp(arg, "two-justifiers")) + S9xSetController(port, CTL_JUSTIFIER, 1, 0, 0, 0); + else + if (!strncasecmp(arg, "mp5:", 4) && ((arg[4] >= '1' && arg[4] <= '8') || arg[4] == 'n') && + ((arg[5] >= '1' && arg[5] <= '8') || arg[5] == 'n') && + ((arg[6] >= '1' && arg[6] <= '8') || arg[6] == 'n') && + ((arg[7] >= '1' && arg[7] <= '8') || arg[7] == 'n') && arg[8] == '\0') + S9xSetController(port, CTL_MP5, (arg[4] == 'n') ? -1 : arg[4] - '1', + (arg[5] == 'n') ? -1 : arg[5] - '1', + (arg[6] == 'n') ? -1 : arg[6] - '1', + (arg[7] == 'n') ? -1 : arg[7] - '1'); + else + return (false); + + return (true); +} + +static void parse_crosshair_spec (enum crosscontrols ctl, const char *spec) +{ + int idx = -1, i; + const char *fg = NULL, *bg = NULL, *s = spec; + + if (s[0] == '"') + { + s++; + for (i = 0; s[i] != '\0'; i++) + if (s[i] == '"' && s[i - 1] != '\\') + break; + + idx = 31 - ctl; + + std::string fname(s, i); + if (!S9xLoadCrosshairFile(idx, fname.c_str())) + return; + + s += i + 1; + } + else + { + if (isdigit(*s)) + { + idx = *s - '0'; + s++; + } + + if (isdigit(*s)) + { + idx = idx * 10 + *s - '0'; + s++; + } + + if (idx > 31) + { + fprintf(stderr, "Invalid crosshair spec '%s'.\n", spec); + return; + } + } + + while (*s != '\0' && isspace(*s)) + s++; + + if (*s != '\0') + { + fg = s; + + while (isalnum(*s)) + s++; + + if (*s != '/' || !isalnum(s[1])) + { + fprintf(stderr, "Invalid crosshair spec '%s.'\n", spec); + return; + } + + bg = ++s; + + while (isalnum(*s)) + s++; + + if (*s != '\0') + { + fprintf(stderr, "Invalid crosshair spec '%s'.\n", spec); + return; + } + } + + S9xSetControllerCrosshair(ctl, idx, fg, bg); +} + +static bool try_load_config_file (const char *fname, ConfigFile &conf) +{ + STREAM fp; + + fp = OPEN_STREAM(fname, "r"); + if (fp) + { + fprintf(stdout, "Reading config file %s.\n", fname); + conf.LoadFile(new fReader(fp)); + CLOSE_STREAM(fp); + return (true); + } + + return (false); +} + +void S9xLoadConfigFiles (char **argv, int argc) +{ + static ConfigFile conf; // static because some of its functions return pointers + conf.Clear(); + + bool skip = false; + for (int i = 0; i < argc; i++) + { + if (!strcasecmp(argv[i], "-nostdconf")) + { + skip = true; + break; + } + } + + if (!skip) + { + #ifdef SYS_CONFIG_FILE + try_load_config_file(SYS_CONFIG_FILE, conf); + S9xParsePortConfig(conf, 0); + #endif + + std::string fname; + + fname = S9xGetDirectory(DEFAULT_DIR); + fname += SLASH_STR S9X_CONF_FILE_NAME; + try_load_config_file(fname.c_str(), conf); + } + else + fprintf(stderr, "Skipping standard config files.\n"); + + for (int i = 0; i < argc - 1; i++) + if (!strcasecmp(argv[i], "-conf")) + try_load_config_file(argv[++i], conf); + + // Parse config file here + + // ROM + + Settings.ForceInterleaved2 = conf.GetBool("ROM::Interleaved2", false); + Settings.ForceInterleaveGD24 = conf.GetBool("ROM::InterleaveGD24", false); + Settings.ApplyCheats = conf.GetBool("ROM::Cheat", false); + Settings.NoPatch = !conf.GetBool("ROM::Patch", true); + + Settings.ForceLoROM = conf.GetBool("ROM::LoROM", false); + Settings.ForceHiROM = conf.GetBool("ROM::HiROM", false); + if (Settings.ForceLoROM) + Settings.ForceHiROM = false; + + Settings.ForcePAL = conf.GetBool("ROM::PAL", false); + Settings.ForceNTSC = conf.GetBool("ROM::NTSC", false); + if (Settings.ForcePAL) + Settings.ForceNTSC = false; + + if (conf.Exists("ROM::Header")) + { + Settings.ForceHeader = conf.GetBool("ROM::Header", false); + Settings.ForceNoHeader = !Settings.ForceHeader; + } + + if (conf.Exists("ROM::Interleaved")) + { + Settings.ForceInterleaved = conf.GetBool("ROM::Interleaved", false); + Settings.ForceNotInterleaved = !Settings.ForceInterleaved; + } + + rom_filename = conf.GetStringDup("ROM::Filename", NULL); + + // Sound + + Settings.SoundSync = conf.GetBool("Sound::Sync", true); + Settings.SixteenBitSound = conf.GetBool("Sound::16BitSound", true); + Settings.Stereo = conf.GetBool("Sound::Stereo", true); + Settings.ReverseStereo = conf.GetBool("Sound::ReverseStereo", false); + Settings.SoundPlaybackRate = conf.GetUInt("Sound::Rate", 32000); + Settings.SoundInputRate = conf.GetUInt("Sound::InputRate", 32000); + Settings.Mute = conf.GetBool("Sound::Mute", false); + + // Display + + Settings.SupportHiRes = conf.GetBool("Display::HiRes", true); + Settings.Transparency = conf.GetBool("Display::Transparency", true); + Settings.DisableGraphicWindows = !conf.GetBool("Display::GraphicWindows", true); + Settings.DisplayFrameRate = conf.GetBool("Display::DisplayFrameRate", false); + Settings.DisplayWatchedAddresses = conf.GetBool("Display::DisplayWatchedAddresses", false); + Settings.DisplayPressedKeys = conf.GetBool("Display::DisplayInput", false); + Settings.DisplayMovieFrame = conf.GetBool("Display::DisplayFrameCount", false); + Settings.AutoDisplayMessages = conf.GetBool("Display::MessagesInImage", true); + Settings.InitialInfoStringTimeout = conf.GetInt ("Display::MessageDisplayTime", 120); + + // Settings + + Settings.BSXBootup = conf.GetBool("Settings::BSXBootup", false); + Settings.TurboMode = conf.GetBool("Settings::TurboMode", false); + Settings.TurboSkipFrames = conf.GetUInt("Settings::TurboFrameSkip", 15); + Settings.MovieTruncate = conf.GetBool("Settings::MovieTruncateAtEnd", false); + Settings.MovieNotifyIgnored = conf.GetBool("Settings::MovieNotifyIgnored", false); + Settings.WrongMovieStateProtection = conf.GetBool("Settings::WrongMovieStateProtection", true); + Settings.StretchScreenshots = conf.GetInt ("Settings::StretchScreenshots", 1); + Settings.SnapshotScreenshots = conf.GetBool("Settings::SnapshotScreenshots", true); + Settings.DontSaveOopsSnapshot = conf.GetBool("Settings::DontSaveOopsSnapshot", false); + Settings.AutoSaveDelay = conf.GetUInt("Settings::AutoSaveDelay", 0); + + if (conf.Exists("Settings::FrameTime")) + Settings.FrameTimePAL = Settings.FrameTimeNTSC = conf.GetUInt("Settings::FrameTime", 16667); + + if (!strcasecmp(conf.GetString("Settings::FrameSkip", "Auto"), "Auto")) + Settings.SkipFrames = AUTO_FRAMERATE; + else + Settings.SkipFrames = conf.GetUInt("Settings::FrameSkip", 0) + 1; + + // Controls + + Settings.MouseMaster = conf.GetBool("Controls::MouseMaster", true); + Settings.SuperScopeMaster = conf.GetBool("Controls::SuperscopeMaster", true); + Settings.JustifierMaster = conf.GetBool("Controls::JustifierMaster", true); + Settings.MultiPlayer5Master = conf.GetBool("Controls::MP5Master", true); + Settings.UpAndDown = conf.GetBool("Controls::AllowLeftRight", false); + + if (conf.Exists("Controls::Port1")) + parse_controller_spec(0, conf.GetString("Controls::Port1")); + if (conf.Exists("Controls::Port2")) + parse_controller_spec(1, conf.GetString("Controls::Port2")); + + if (conf.Exists("Controls::Mouse1Crosshair")) + parse_crosshair_spec(X_MOUSE1, conf.GetString("Controls::Mouse1Crosshair")); + if (conf.Exists("Controls::Mouse2Crosshair")) + parse_crosshair_spec(X_MOUSE2, conf.GetString("Controls::Mouse2Crosshair")); + if (conf.Exists("Controls::SuperscopeCrosshair")) + parse_crosshair_spec(X_SUPERSCOPE, conf.GetString("Controls::SuperscopeCrosshair")); + if (conf.Exists("Controls::Justifier1Crosshair")) + parse_crosshair_spec(X_JUSTIFIER1, conf.GetString("Controls::Justifier1Crosshair")); + if (conf.Exists("Controls::Justifier2Crosshair")) + parse_crosshair_spec(X_JUSTIFIER2, conf.GetString("Controls::Justifier2Crosshair")); + + // Hack + + Settings.DisableGameSpecificHacks = !conf.GetBool("Hack::EnableGameSpecificHacks", true); + Settings.BlockInvalidVRAMAccess = !conf.GetBool("Hack::AllowInvalidVRAMAccess", false); + Settings.ShutdownMaster = conf.GetBool("Hack::SpeedHacks", false); + Settings.DisableIRQ = conf.GetBool("Hack::DisableIRQ", false); + Settings.DisableHDMA = conf.GetBool("Hack::DisableHDMA", false); + Settings.HDMATimingHack = conf.GetInt ("Hack::HDMATiming", 100); + + // Netplay + +#ifdef NETPLAY_SUPPORT + Settings.NetPlay = conf.GetBool("Netplay::Enable"); + + Settings.Port = NP_DEFAULT_PORT; + if (conf.Exists("Netplay::Port")) + Settings.Port = -(int) conf.GetUInt("Netplay::Port"); + + Settings.ServerName[0] = '\0'; + if (conf.Exists("Netplay::Server")) + conf.GetString("Netplay::Server", Settings.ServerName, 128); +#endif + + // Debug + +#ifdef DEBUGGER + if (conf.GetBool("DEBUG::Debugger", false)) + CPU.Flags |= DEBUG_MODE_FLAG; + + if (conf.GetBool("DEBUG::Trace", false)) + { + if (!trace) + trace = fopen("trace.log", "wb"); + CPU.Flags |= TRACE_FLAG; + } +#endif + + S9xParsePortConfig(conf, 1); + S9xVerifyControllers(); +} + +void S9xUsage (void) +{ + /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */ + + S9xMessage(S9X_INFO, S9X_USAGE, ""); + S9xMessage(S9X_INFO, S9X_USAGE, "Snes9x " VERSION); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + S9xMessage(S9X_INFO, S9X_USAGE, "usage: snes9x [options] "); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + // SOUND OPTIONS + S9xMessage(S9X_INFO, S9X_USAGE, "-soundsync Synchronize sound as far as possible"); + S9xMessage(S9X_INFO, S9X_USAGE, "-playbackrate Set sound playback rate"); + S9xMessage(S9X_INFO, S9X_USAGE, "-inputrate Set sound input rate"); + S9xMessage(S9X_INFO, S9X_USAGE, "-reversestereo Reverse stereo sound output"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nostereo Disable stereo sound output"); + S9xMessage(S9X_INFO, S9X_USAGE, "-eightbit Use 8bit sound instead of 16bit"); + S9xMessage(S9X_INFO, S9X_USAGE, "-mute Mute sound"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + // DISPLAY OPTIONS + S9xMessage(S9X_INFO, S9X_USAGE, "-displayframerate Display the frame rate counter"); + S9xMessage(S9X_INFO, S9X_USAGE, "-displaykeypress Display input of all controllers and peripherals"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nohires (Not recommended) Disable support for hi-res and"); + S9xMessage(S9X_INFO, S9X_USAGE, " interlace modes"); + S9xMessage(S9X_INFO, S9X_USAGE, "-notransparency (Not recommended) Disable transparency effects"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nowindows (Not recommended) Disable graphic window effects"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + // CONTROLLER OPTIONS + S9xMessage(S9X_INFO, S9X_USAGE, "-nomp5 Disable emulation of the Multiplayer 5 adapter"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nomouse Disable emulation of the SNES mouse"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nosuperscope Disable emulation of the Superscope"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nojustifier Disable emulation of the Konami Justifier"); + S9xMessage(S9X_INFO, S9X_USAGE, "-port# Specify which controller to emulate in port 1/2"); + S9xMessage(S9X_INFO, S9X_USAGE, " Controllers: none No controller"); + S9xMessage(S9X_INFO, S9X_USAGE, " pad# Joypad number 1-8"); + S9xMessage(S9X_INFO, S9X_USAGE, " mouse# Mouse number 1-2"); + S9xMessage(S9X_INFO, S9X_USAGE, " superscope Superscope (not useful with -port1)"); + S9xMessage(S9X_INFO, S9X_USAGE, " justifier Blue Justifier (not useful with -port1)"); + S9xMessage(S9X_INFO, S9X_USAGE, " two-justifiers Blue & Pink Justifiers"); + S9xMessage(S9X_INFO, S9X_USAGE, " mp5:#### MP5 with the 4 named pads (1-8 or n)"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + // ROM OPTIONS + S9xMessage(S9X_INFO, S9X_USAGE, "-hirom Force Hi-ROM memory map"); + S9xMessage(S9X_INFO, S9X_USAGE, "-lorom Force Lo-ROM memory map"); + S9xMessage(S9X_INFO, S9X_USAGE, "-ntsc Force NTSC timing (60 frames/sec)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-pal Force PAL timing (50 frames/sec)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nointerleave Assume the ROM image is not in interleaved"); + S9xMessage(S9X_INFO, S9X_USAGE, " format"); + S9xMessage(S9X_INFO, S9X_USAGE, "-interleaved Assume the ROM image is in interleaved format"); + S9xMessage(S9X_INFO, S9X_USAGE, "-interleaved2 Assume the ROM image is in interleaved 2 format"); + S9xMessage(S9X_INFO, S9X_USAGE, "-interleavedgd24 Assume the ROM image is in interleaved gd24"); + S9xMessage(S9X_INFO, S9X_USAGE, " format"); + S9xMessage(S9X_INFO, S9X_USAGE, "-noheader Assume the ROM image doesn't have a header of a"); + S9xMessage(S9X_INFO, S9X_USAGE, " copier"); + S9xMessage(S9X_INFO, S9X_USAGE, "-header Assume the ROM image has a header of a copier"); + S9xMessage(S9X_INFO, S9X_USAGE, "-bsxbootup Boot up BS games from BS-X"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + // PATCH/CHEAT OPTIONS + S9xMessage(S9X_INFO, S9X_USAGE, "-nopatch Do not apply any available IPS patches"); + S9xMessage(S9X_INFO, S9X_USAGE, "-cheat Apply saved cheats"); + S9xMessage(S9X_INFO, S9X_USAGE, "-gamegenie Supply a Game Genie code"); + S9xMessage(S9X_INFO, S9X_USAGE, "-actionreplay Supply a Pro-Action Reply code"); + S9xMessage(S9X_INFO, S9X_USAGE, "-goldfinger Supply a Gold Finger code"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + +#ifdef NETPLAY_SUPPORT + // NETPLAY OPTIONS + S9xMessage(S9X_INFO, S9X_USAGE, "-net Enable netplay"); + S9xMessage(S9X_INFO, S9X_USAGE, "-port Use port for netplay (use with -net)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-server Use the specified server for netplay"); + S9xMessage(S9X_INFO, S9X_USAGE, " (use with -net)"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); +#endif + + // HACKING OR DEBUGGING OPTIONS +#ifdef DEBUGGER + S9xMessage(S9X_INFO, S9X_USAGE, "-debug Set the Debugger flag"); + S9xMessage(S9X_INFO, S9X_USAGE, "-trace Begin CPU instruction tracing"); +#endif + S9xMessage(S9X_INFO, S9X_USAGE, "-noirq (Not recommended) Disable IRQ emulation"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nohdma (Not recommended) Disable HDMA emulation"); + S9xMessage(S9X_INFO, S9X_USAGE, "-hdmatiming <1-199> (Not recommended) Changes HDMA transfer timings"); + S9xMessage(S9X_INFO, S9X_USAGE, "-cpushutdown (Not recommended) Skip emulation until the next"); + S9xMessage(S9X_INFO, S9X_USAGE, " event comes"); + S9xMessage(S9X_INFO, S9X_USAGE, "-invalidvramaccess (Not recommended) Allow invalid VRAM access"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + // OTHER OPTIONS + S9xMessage(S9X_INFO, S9X_USAGE, "-frameskip Screen update frame skip rate"); + S9xMessage(S9X_INFO, S9X_USAGE, "-frametime Milliseconds per frame for frameskip auto-adjust"); + S9xMessage(S9X_INFO, S9X_USAGE, "-upanddown Override protection from pressing left+right or"); + S9xMessage(S9X_INFO, S9X_USAGE, " up+down together"); + S9xMessage(S9X_INFO, S9X_USAGE, "-conf Use specified conf file (after standard files)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-nostdconf Do not load the standard config files"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + S9xExtraUsage(); + + S9xMessage(S9X_INFO, S9X_USAGE, ""); + S9xMessage(S9X_INFO, S9X_USAGE, "ROM image can be compressed with zip, gzip, JMA, or compress."); + + exit(1); +} + +char * S9xParseArgs (char **argv, int argc) +{ + for (int i = 1; i < argc; i++) + { + if (*argv[i] == '-') + { + if (!strcasecmp(argv[i], "-help")) + S9xUsage(); + else + + // SOUND OPTIONS + + if (!strcasecmp(argv[i], "-soundsync")) + Settings.SoundSync = TRUE; + else + if (!strcasecmp(argv[i], "-playbackrate")) + { + if (i + 1 < argc) + { + Settings.SoundPlaybackRate = atoi(argv[++i]); + if (Settings.SoundPlaybackRate < 8192) + Settings.SoundPlaybackRate = 8192; + } + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-inputrate")) + { + if (i + 1 < argc) + { + Settings.SoundInputRate = atoi(argv[++i]); + if (Settings.SoundInputRate < 8192) + Settings.SoundInputRate = 8192; + } + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-reversestereo")) + Settings.ReverseStereo = TRUE; + else + if (!strcasecmp(argv[i], "-nostereo")) + Settings.Stereo = FALSE; + else + if (!strcasecmp(argv[i], "-eightbit")) + Settings.SixteenBitSound = FALSE; + else + if (!strcasecmp(argv[i], "-mute")) + Settings.Mute = TRUE; + else + + // DISPLAY OPTIONS + + if (!strcasecmp(argv[i], "-displayframerate")) + Settings.DisplayFrameRate = TRUE; + else + if (!strcasecmp(argv[i], "-displaykeypress")) + Settings.DisplayPressedKeys = TRUE; + else + if (!strcasecmp(argv[i], "-nohires")) + Settings.SupportHiRes = FALSE; + else + if (!strcasecmp(argv[i], "-notransparency")) + Settings.Transparency = FALSE; + else + if (!strcasecmp(argv[i], "-nowindows")) + Settings.DisableGraphicWindows = TRUE; + else + + // CONTROLLER OPTIONS + + if (!strcasecmp(argv[i], "-nomp5")) + Settings.MultiPlayer5Master = FALSE; + else + if (!strcasecmp(argv[i], "-nomouse")) + Settings.MouseMaster = FALSE; + else + if (!strcasecmp(argv[i], "-nosuperscope")) + Settings.SuperScopeMaster = FALSE; + else + if (!strcasecmp(argv[i], "-nojustifier")) + Settings.JustifierMaster = FALSE; + else + if (!strcasecmp(argv[i], "-port1") || + !strcasecmp(argv[i], "-port2")) + { + if (i + 1 < argc) + { + i++; + if (!parse_controller_spec(argv[i - 1][5] - '1', argv[i])) + S9xUsage(); + } + else + S9xUsage(); + } + else + + // ROM OPTIONS + + if (!strcasecmp(argv[i], "-hirom")) + Settings.ForceHiROM = TRUE; + else + if (!strcasecmp(argv[i], "-lorom")) + Settings.ForceLoROM = TRUE; + else + if (!strcasecmp(argv[i], "-ntsc")) + Settings.ForceNTSC = TRUE; + else + if (!strcasecmp(argv[i], "-pal")) + Settings.ForcePAL = TRUE; + else + if (!strcasecmp(argv[i], "-nointerleave")) + Settings.ForceNotInterleaved = TRUE; + else + if (!strcasecmp(argv[i], "-interleaved")) + Settings.ForceInterleaved = TRUE; + else + if (!strcasecmp(argv[i], "-interleaved2")) + Settings.ForceInterleaved2 = TRUE; + else + if (!strcasecmp(argv[i], "-interleavedgd24")) + Settings.ForceInterleaveGD24 = TRUE; + else + if (!strcasecmp(argv[i], "-noheader")) + Settings.ForceNoHeader = TRUE; + else + if (!strcasecmp(argv[i], "-header")) + Settings.ForceHeader = TRUE; + else + if (!strcasecmp(argv[i], "-bsxbootup")) + Settings.BSXBootup = TRUE; + else + + // PATCH/CHEAT OPTIONS + + if (!strcasecmp(argv[i], "-nopatch")) + Settings.NoPatch = TRUE; + else + if (!strcasecmp(argv[i], "-cheat")) + Settings.ApplyCheats = TRUE; + else + if (!strcasecmp(argv[i], "-gamegenie")) + { + 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], "-actionreplay")) + { + 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], "-goldfinger")) + { + 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 + + // NETPLAY OPTIONS + + #ifdef NETPLAY_SUPPORT + if (!strcasecmp(argv[i], "-net")) + Settings.NetPlay = TRUE; + else + if (!strcasecmp(argv[i], "-port")) + { + if (i + 1 < argc) + Settings.Port = -atoi(argv[++i]); + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-server")) + { + if (i + 1 < argc) + { + strncpy(Settings.ServerName, argv[++i], 127); + Settings.ServerName[127] = 0; + } + else + S9xUsage(); + } + else + #endif + + // HACKING OR DEBUGGING OPTIONS + + #ifdef DEBUGGER + if (!strcasecmp(argv[i], "-debug")) + CPU.Flags |= DEBUG_MODE_FLAG; + else + if (!strcasecmp(argv[i], "-trace")) + { + if (!trace) + trace = fopen("trace.log", "wb"); + CPU.Flags |= TRACE_FLAG; + } + else + #endif + + if (!strcasecmp(argv[i], "-noirq")) + Settings.DisableIRQ = TRUE; + else + if (!strcasecmp(argv[i], "-nohdma")) + Settings.DisableHDMA = TRUE; + else + if (!strcasecmp(argv[i], "-hdmatiming")) + { + if (i + 1 < argc) + { + int p = atoi(argv[++i]); + if (p > 0 && p < 200) + Settings.HDMATimingHack = p; + } + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-cpushutdown")) + Settings.ShutdownMaster = TRUE; + else + if (!strcasecmp(argv[i], "-invalidvramaccess")) + Settings.BlockInvalidVRAMAccess = FALSE; + else + + // OTHER OPTIONS + + if (!strcasecmp(argv[i], "-frameskip")) + { + if (i + 1 < argc) + Settings.SkipFrames = atoi(argv[++i]) + 1; + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-frametime")) + { + if (i + 1 < argc) + Settings.FrameTimePAL = Settings.FrameTimeNTSC = atoi(argv[++i]); + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-upanddown")) + Settings.UpAndDown = TRUE; + else + if (!strcasecmp(argv[i], "-conf")) + { + if (++i >= argc) + S9xUsage(); + // Else do nothing, S9xLoadConfigFiles() handled it. + } + else + if (!strcasecmp(argv[i], "-nostdconf")) + { + // Do nothing, S9xLoadConfigFiles() handled it. + } + else + S9xParseArg(argv, i, argc); + } + else + rom_filename = argv[i]; + } + + S9xVerifyControllers(); + + return (rom_filename); +} diff --git a/snes9x.h b/snes9x.h new file mode 100644 index 00000000..2b75bd7b --- /dev/null +++ b/snes9x.h @@ -0,0 +1,477 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _SNES9X_H_ +#define _SNES9X_H_ + +#ifndef VERSION +#define VERSION "1.52" +#endif + +#include "port.h" +#include "65c816.h" +#include "messages.h" + +#ifdef ZLIB +#include +#define STREAM gzFile +#define READ_STREAM(p, l, s) gzread(s, p, l) +#define WRITE_STREAM(p, l, s) gzwrite(s, p, l) +#define GETS_STREAM(p, l, s) gzgets(s, p, l) +#define GETC_STREAM(s) gzgetc(s) +#define OPEN_STREAM(f, m) gzopen(f, m) +#define REOPEN_STREAM(f, m) gzdopen(f, m) +#define FIND_STREAM(f) gztell(f) +#define REVERT_STREAM(f, o, s) gzseek(f, o, s) +#define CLOSE_STREAM(s) gzclose(s) +#else +#define STREAM FILE * +#define READ_STREAM(p, l, s) fread(p, 1, l, s) +#define WRITE_STREAM(p, l, s) fwrite(p, 1, l, s) +#define GETS_STREAM(p, l, s) fgets(p, l, s) +#define GETC_STREAM(s) fgetc(s) +#define OPEN_STREAM(f, m) fopen(f, m) +#define REOPEN_STREAM(f, m) fdopen(f, m) +#define FIND_STREAM(f) ftell(f) +#define REVERT_STREAM(f, o, s) fseek(f, o, s) +#define CLOSE_STREAM(s) fclose(s) +#endif + +#define SNES_WIDTH 256 +#define SNES_HEIGHT 224 +#define SNES_HEIGHT_EXTENDED 239 +#define MAX_SNES_WIDTH (SNES_WIDTH * 2) +#define MAX_SNES_HEIGHT (SNES_HEIGHT_EXTENDED * 2) +#define IMAGE_WIDTH (Settings.SupportHiRes ? MAX_SNES_WIDTH : SNES_WIDTH) +#define IMAGE_HEIGHT (Settings.SupportHiRes ? MAX_SNES_HEIGHT : SNES_HEIGHT_EXTENDED) + +#define NTSC_MASTER_CLOCK 21477272.0 +#define PAL_MASTER_CLOCK 21281370.0 + +#define SNES_MAX_NTSC_VCOUNTER 262 +#define SNES_MAX_PAL_VCOUNTER 312 +#define SNES_HCOUNTER_MAX 341 + +#define ONE_CYCLE 6 +#define SLOW_ONE_CYCLE 8 +#define TWO_CYCLES 12 +#define ONE_DOT_CYCLE 4 + +#define SNES_CYCLES_PER_SCANLINE (SNES_HCOUNTER_MAX * ONE_DOT_CYCLE) +#define SNES_SCANLINE_TIME (SNES_CYCLES_PER_SCANLINE / NTSC_MASTER_CLOCK) + +#define SNES_WRAM_REFRESH_HC_v1 530 +#define SNES_WRAM_REFRESH_HC_v2 538 +#define SNES_WRAM_REFRESH_CYCLES 40 + +#define SNES_HBLANK_START_HC 1096 // H=274 +#define SNES_HDMA_START_HC 1106 // FIXME: not true +#define SNES_HBLANK_END_HC 4 // H=1 +#define SNES_HDMA_INIT_HC 20 // FIXME: not true +#define SNES_RENDER_START_HC (48 * ONE_DOT_CYCLE) // FIXME: Snes9x renders a line at a time. + +#define SNES_TR_MASK (1 << 4) +#define SNES_TL_MASK (1 << 5) +#define SNES_X_MASK (1 << 6) +#define SNES_A_MASK (1 << 7) +#define SNES_RIGHT_MASK (1 << 8) +#define SNES_LEFT_MASK (1 << 9) +#define SNES_DOWN_MASK (1 << 10) +#define SNES_UP_MASK (1 << 11) +#define SNES_START_MASK (1 << 12) +#define SNES_SELECT_MASK (1 << 13) +#define SNES_Y_MASK (1 << 14) +#define SNES_B_MASK (1 << 15) + +#define DEBUG_MODE_FLAG (1 << 0) // debugger +#define TRACE_FLAG (1 << 1) // debugger +#define SINGLE_STEP_FLAG (1 << 2) // debugger +#define BREAK_FLAG (1 << 3) // debugger +#define NMI_FLAG (1 << 7) // CPU +#define IRQ_FLAG (1 << 11) // CPU +#define SCAN_KEYS_FLAG (1 << 4) // CPU +#define HALTED_FLAG (1 << 12) // APU +#define FRAME_ADVANCE_FLAG (1 << 9) + +#define ROM_NAME_LEN 23 +#define AUTO_FRAMERATE 200 + +struct SCPUState +{ + int32 Cycles; + int32 PrevCycles; + int32 V_Counter; + uint32 Flags; + uint8 *PCBase; + bool8 IRQActive; + int32 IRQPending; + int32 MemSpeed; + int32 MemSpeedx2; + int32 FastROMSpeed; + bool8 InDMA; + bool8 InHDMA; + bool8 InDMAorHDMA; + bool8 InWRAMDMAorHDMA; + uint8 HDMARanInDMA; + int32 CurrentDMAorHDMAChannel; + uint8 WhichEvent; + int32 NextEvent; + bool8 WaitingForInterrupt; + uint32 WaitAddress; + uint32 WaitCounter; + uint32 PBPCAtOpcodeStart; + uint32 AutoSaveTimer; + bool8 SRAMModified; +}; + +enum +{ + HC_HBLANK_START_EVENT = 1, + HC_IRQ_1_3_EVENT = 2, + HC_HDMA_START_EVENT = 3, + HC_IRQ_3_5_EVENT = 4, + HC_HCOUNTER_MAX_EVENT = 5, + HC_IRQ_5_7_EVENT = 6, + HC_HDMA_INIT_EVENT = 7, + HC_IRQ_7_9_EVENT = 8, + HC_RENDER_EVENT = 9, + HC_IRQ_9_A_EVENT = 10, + HC_WRAM_REFRESH_EVENT = 11, + HC_IRQ_A_1_EVENT = 12 +}; + +struct STimings +{ + int32 H_Max_Master; + int32 H_Max; + int32 V_Max_Master; + int32 V_Max; + int32 HBlankStart; + int32 HBlankEnd; + int32 HDMAInit; + int32 HDMAStart; + int32 NMITriggerPos; + int32 WRAMRefreshPos; + int32 RenderPos; + bool8 InterlaceField; + int32 DMACPUSync; // The cycles to synchronize DMA and CPU. Snes9x cannot emulate correctly. + int32 NMIDMADelay; // The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly. + int32 IRQPendCount; // This value is just a hack, because Snes9x cannot emulate any events in an opcode. + int32 APUSpeedup; +}; + +struct SSettings +{ + bool8 TraceDMA; + bool8 TraceHDMA; + bool8 TraceVRAM; + bool8 TraceUnknownRegisters; + bool8 TraceDSP; + bool8 TraceHCEvent; + + bool8 SuperFX; + uint8 DSP; + bool8 SA1; + bool8 C4; + bool8 SDD1; + bool8 SPC7110; + bool8 SPC7110RTC; + bool8 OBC1; + uint8 SETA; + bool8 SRTC; + bool8 BS; + bool8 BSXItself; + bool8 BSXBootup; + bool8 MouseMaster; + bool8 SuperScopeMaster; + bool8 JustifierMaster; + bool8 MultiPlayer5Master; + + bool8 ForceLoROM; + bool8 ForceHiROM; + bool8 ForceHeader; + bool8 ForceNoHeader; + bool8 ForceInterleaved; + bool8 ForceInterleaved2; + bool8 ForceInterleaveGD24; + bool8 ForceNotInterleaved; + bool8 ForcePAL; + bool8 ForceNTSC; + bool8 PAL; + uint32 FrameTimePAL; + uint32 FrameTimeNTSC; + uint32 FrameTime; + + bool8 SoundSync; + bool8 SixteenBitSound; + uint32 SoundPlaybackRate; + uint32 SoundInputRate; + bool8 Stereo; + bool8 ReverseStereo; + bool8 Mute; + + bool8 SupportHiRes; + bool8 Transparency; + uint8 BG_Forced; + bool8 DisableGraphicWindows; + + bool8 DisplayFrameRate; + bool8 DisplayWatchedAddresses; + bool8 DisplayPressedKeys; + bool8 DisplayMovieFrame; + bool8 AutoDisplayMessages; + uint32 InitialInfoStringTimeout; + uint16 DisplayColor; + + bool8 Multi; + char CartAName[PATH_MAX + 1]; + char CartBName[PATH_MAX + 1]; + + bool8 DisableGameSpecificHacks; + bool8 ShutdownMaster; + bool8 Shutdown; + bool8 BlockInvalidVRAMAccessMaster; + bool8 BlockInvalidVRAMAccess; + bool8 DisableIRQ; + bool8 DisableHDMA; + int32 HDMATimingHack; + + bool8 ForcedPause; + bool8 Paused; + bool8 StopEmulation; + + uint32 SkipFrames; + uint32 TurboSkipFrames; + uint32 AutoMaxSkipFrames; + bool8 TurboMode; + uint32 HighSpeedSeek; + bool8 FrameAdvance; + + bool8 NetPlay; + bool8 NetPlayServer; + char ServerName[128]; + int Port; + + bool8 MovieTruncate; + bool8 MovieNotifyIgnored; + bool8 WrongMovieStateProtection; + bool8 DumpStreams; + int DumpStreamsMaxFrames; + + bool8 TakeScreenshot; + int8 StretchScreenshots; + bool8 SnapshotScreenshots; + + bool8 ApplyCheats; + bool8 NoPatch; + int32 AutoSaveDelay; + bool8 DontSaveOopsSnapshot; + bool8 UpAndDown; + + bool8 OpenGLEnable; +}; + +struct SSNESGameFixes +{ + uint8 SRAMInitialValue; + uint8 Uniracers; +}; + +enum +{ + PAUSE_NETPLAY_CONNECT = (1 << 0), + PAUSE_TOGGLE_FULL_SCREEN = (1 << 1), + PAUSE_EXIT = (1 << 2), + PAUSE_MENU = (1 << 3), + PAUSE_INACTIVE_WINDOW = (1 << 4), + PAUSE_WINDOW_ICONISED = (1 << 5), + PAUSE_RESTORE_GUI = (1 << 6), + PAUSE_FREEZE_FILE = (1 << 7) +}; + +void S9xSetPause(uint32); +void S9xClearPause(uint32); +void S9xExit(void); +void S9xMessage(int, int, const char *); + +extern struct SSettings Settings; +extern struct SCPUState CPU; +extern struct STimings Timings; +extern struct SSNESGameFixes SNESGameFixes; +extern char String[513]; + +#endif diff --git a/spc7110.cpp b/spc7110.cpp new file mode 100644 index 00000000..4f9c0fc4 --- /dev/null +++ b/spc7110.cpp @@ -0,0 +1,483 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/***** + * SPC7110 emulator - version 0.03 (2008-08-10) + * Copyright (c) 2008, byuu and neviksti + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * The software is provided "as is" and the author disclaims all warranties + * with regard to this software including all implied warranties of + * merchantibility and fitness, in no event shall the author be liable for + * any special, direct, indirect, or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in an + * action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + *****/ + + +#include + +#include "snes9x.h" +#include "memmap.h" +#include "srtc.h" +#include "display.h" + +#define memory_cartrom_size() Memory.CalculatedSize +#define memory_cartrom_read(a) Memory.ROM[(a)] +#define memory_cartrtc_read(a) RTCData.reg[(a)] +#define memory_cartrtc_write(a, b) { RTCData.reg[(a)] = (b); } +#define cartridge_info_spc7110rtc Settings.SPC7110RTC +#define cpu_regs_mdr OpenBus + +#include "spc7110emu.h" +#include "spc7110emu.cpp" + +SPC7110 s7emu; + +static void SetSPC7110SRAMMap (uint8); + + +void S9xInitSPC7110 (void) +{ + s7emu.power(); + memset(RTCData.reg, 0, 20); +} + +void S9xResetSPC7110 (void) +{ + s7emu.reset(); +} + +static void SetSPC7110SRAMMap (uint8 newstate) +{ + if (newstate & 0x80) + { + Memory.Map[0x006] = (uint8 *) Memory.MAP_HIROM_SRAM; + Memory.Map[0x007] = (uint8 *) Memory.MAP_HIROM_SRAM; + Memory.Map[0x306] = (uint8 *) Memory.MAP_HIROM_SRAM; + Memory.Map[0x307] = (uint8 *) Memory.MAP_HIROM_SRAM; + } + else + { + Memory.Map[0x006] = (uint8 *) Memory.MAP_RONLY_SRAM; + Memory.Map[0x007] = (uint8 *) Memory.MAP_RONLY_SRAM; + Memory.Map[0x306] = (uint8 *) Memory.MAP_RONLY_SRAM; + Memory.Map[0x307] = (uint8 *) Memory.MAP_RONLY_SRAM; + } +} + +uint8 * S9xGetBasePointerSPC7110 (uint32 address) +{ + uint32 i; + + switch (address & 0xf00000) + { + case 0xd00000: + i = s7emu.dx_offset; + break; + + case 0xe00000: + i = s7emu.ex_offset; + break; + + case 0xf00000: + i = s7emu.fx_offset; + break; + + default: + i = 0; + break; + } + + i += address & 0x0f0000; + + return (&Memory.ROM[i]); +} + +uint8 S9xGetSPC7110Byte (uint32 address) +{ + uint32 i; + + switch (address & 0xf00000) + { + case 0xd00000: + i = s7emu.dx_offset; + break; + + case 0xe00000: + i = s7emu.ex_offset; + break; + + case 0xf00000: + i = s7emu.fx_offset; + break; + + default: + i = 0; + break; + } + + i += address & 0x0fffff; + + return (Memory.ROM[i]); +} + +uint8 S9xGetSPC7110 (uint16 address) +{ + if (!Settings.SPC7110RTC && address > 0x483f) + return (OpenBus); + + return (s7emu.mmio_read(address)); +} + +void S9xSetSPC7110 (uint8 byte, uint16 address) +{ + if (!Settings.SPC7110RTC && address > 0x483f) + return; + + if (address == 0x4830) + SetSPC7110SRAMMap(byte); + + s7emu.mmio_write(address, byte); +} + +void S9xSPC7110PreSaveState (void) +{ + s7snap.r4801 = s7emu.r4801; + s7snap.r4802 = s7emu.r4802; + s7snap.r4803 = s7emu.r4803; + s7snap.r4804 = s7emu.r4804; + s7snap.r4805 = s7emu.r4805; + s7snap.r4806 = s7emu.r4806; + s7snap.r4807 = s7emu.r4807; + s7snap.r4808 = s7emu.r4808; + s7snap.r4809 = s7emu.r4809; + s7snap.r480a = s7emu.r480a; + s7snap.r480b = s7emu.r480b; + s7snap.r480c = s7emu.r480c; + + s7snap.r4811 = s7emu.r4811; + s7snap.r4812 = s7emu.r4812; + s7snap.r4813 = s7emu.r4813; + s7snap.r4814 = s7emu.r4814; + s7snap.r4815 = s7emu.r4815; + s7snap.r4816 = s7emu.r4816; + s7snap.r4817 = s7emu.r4817; + s7snap.r4818 = s7emu.r4818; + + s7snap.r481x = s7emu.r481x; + + s7snap.r4814_latch = s7emu.r4814_latch ? TRUE : FALSE; + s7snap.r4815_latch = s7emu.r4815_latch ? TRUE : FALSE; + + s7snap.r4820 = s7emu.r4820; + s7snap.r4821 = s7emu.r4821; + s7snap.r4822 = s7emu.r4822; + s7snap.r4823 = s7emu.r4823; + s7snap.r4824 = s7emu.r4824; + s7snap.r4825 = s7emu.r4825; + s7snap.r4826 = s7emu.r4826; + s7snap.r4827 = s7emu.r4827; + s7snap.r4828 = s7emu.r4828; + s7snap.r4829 = s7emu.r4829; + s7snap.r482a = s7emu.r482a; + s7snap.r482b = s7emu.r482b; + s7snap.r482c = s7emu.r482c; + s7snap.r482d = s7emu.r482d; + s7snap.r482e = s7emu.r482e; + s7snap.r482f = s7emu.r482f; + + s7snap.r4830 = s7emu.r4830; + s7snap.r4831 = s7emu.r4831; + s7snap.r4832 = s7emu.r4832; + s7snap.r4833 = s7emu.r4833; + s7snap.r4834 = s7emu.r4834; + + s7snap.dx_offset = (uint32) s7emu.dx_offset; + s7snap.ex_offset = (uint32) s7emu.ex_offset; + s7snap.fx_offset = (uint32) s7emu.fx_offset; + + s7snap.r4840 = s7emu.r4840; + s7snap.r4841 = s7emu.r4841; + s7snap.r4842 = s7emu.r4842; + + s7snap.rtc_state = (int32) s7emu.rtc_state; + s7snap.rtc_mode = (int32) s7emu.rtc_mode; + s7snap.rtc_index = (uint32) s7emu.rtc_index; + + s7snap.decomp_mode = (uint32) s7emu.decomp.decomp_mode; + s7snap.decomp_offset = (uint32) s7emu.decomp.decomp_offset; + + for (int i = 0; i < SPC7110_DECOMP_BUFFER_SIZE; i++) + s7snap.decomp_buffer[i] = s7emu.decomp.decomp_buffer[i]; + + s7snap.decomp_buffer_rdoffset = (uint32) s7emu.decomp.decomp_buffer_rdoffset; + s7snap.decomp_buffer_wroffset = (uint32) s7emu.decomp.decomp_buffer_wroffset; + s7snap.decomp_buffer_length = (uint32) s7emu.decomp.decomp_buffer_length; + + for (int i = 0; i < 32; i++) + { + s7snap.context[i].index = s7emu.decomp.context[i].index; + s7snap.context[i].invert = s7emu.decomp.context[i].invert; + } +} + +void S9xSPC7110PostLoadState (int version) +{ + s7emu.r4801 = s7snap.r4801; + s7emu.r4802 = s7snap.r4802; + s7emu.r4803 = s7snap.r4803; + s7emu.r4804 = s7snap.r4804; + s7emu.r4805 = s7snap.r4805; + s7emu.r4806 = s7snap.r4806; + s7emu.r4807 = s7snap.r4807; + s7emu.r4808 = s7snap.r4808; + s7emu.r4809 = s7snap.r4809; + s7emu.r480a = s7snap.r480a; + s7emu.r480b = s7snap.r480b; + s7emu.r480c = s7snap.r480c; + + s7emu.r4811 = s7snap.r4811; + s7emu.r4812 = s7snap.r4812; + s7emu.r4813 = s7snap.r4813; + s7emu.r4814 = s7snap.r4814; + s7emu.r4815 = s7snap.r4815; + s7emu.r4816 = s7snap.r4816; + s7emu.r4817 = s7snap.r4817; + s7emu.r4818 = s7snap.r4818; + + s7emu.r481x = s7snap.r481x; + + s7emu.r4814_latch = s7snap.r4814_latch ? true : false; + s7emu.r4815_latch = s7snap.r4815_latch ? true : false; + + s7emu.r4820 = s7snap.r4820; + s7emu.r4821 = s7snap.r4821; + s7emu.r4822 = s7snap.r4822; + s7emu.r4823 = s7snap.r4823; + s7emu.r4824 = s7snap.r4824; + s7emu.r4825 = s7snap.r4825; + s7emu.r4826 = s7snap.r4826; + s7emu.r4827 = s7snap.r4827; + s7emu.r4828 = s7snap.r4828; + s7emu.r4829 = s7snap.r4829; + s7emu.r482a = s7snap.r482a; + s7emu.r482b = s7snap.r482b; + s7emu.r482c = s7snap.r482c; + s7emu.r482d = s7snap.r482d; + s7emu.r482e = s7snap.r482e; + s7emu.r482f = s7snap.r482f; + + s7emu.r4830 = s7snap.r4830; + s7emu.r4831 = s7snap.r4831; + s7emu.r4832 = s7snap.r4832; + s7emu.r4833 = s7snap.r4833; + s7emu.r4834 = s7snap.r4834; + + s7emu.dx_offset = (unsigned) s7snap.dx_offset; + s7emu.ex_offset = (unsigned) s7snap.ex_offset; + s7emu.fx_offset = (unsigned) s7snap.fx_offset; + + s7emu.r4840 = s7snap.r4840; + s7emu.r4841 = s7snap.r4841; + s7emu.r4842 = s7snap.r4842; + + s7emu.rtc_state = (SPC7110::RTC_State) s7snap.rtc_state; + s7emu.rtc_mode = (SPC7110::RTC_Mode) s7snap.rtc_mode; + s7emu.rtc_index = (unsigned) s7snap.rtc_index; + + s7emu.decomp.decomp_mode = (unsigned) s7snap.decomp_mode; + s7emu.decomp.decomp_offset = (unsigned) s7snap.decomp_offset; + + for (int i = 0; i < SPC7110_DECOMP_BUFFER_SIZE; i++) + s7emu.decomp.decomp_buffer[i] = s7snap.decomp_buffer[i]; + + s7emu.decomp.decomp_buffer_rdoffset = (unsigned) s7snap.decomp_buffer_rdoffset; + s7emu.decomp.decomp_buffer_wroffset = (unsigned) s7snap.decomp_buffer_wroffset; + s7emu.decomp.decomp_buffer_length = (unsigned) s7snap.decomp_buffer_length; + + for (int i = 0; i < 32; i++) + { + s7emu.decomp.context[i].index = s7snap.context[i].index; + s7emu.decomp.context[i].invert = s7snap.context[i].invert; + } + + s7emu.update_time(0); +} diff --git a/spc7110.h b/spc7110.h new file mode 100644 index 00000000..7002b509 --- /dev/null +++ b/spc7110.h @@ -0,0 +1,275 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _SPC7110_H_ +#define _SPC7110_H_ + +#define SPC7110_DECOMP_BUFFER_SIZE 64 + +// for snapshot only +struct SSPC7110Snapshot +{ + uint8 r4801; + uint8 r4802; + uint8 r4803; + uint8 r4804; + uint8 r4805; + uint8 r4806; + uint8 r4807; + uint8 r4808; + uint8 r4809; + uint8 r480a; + uint8 r480b; + uint8 r480c; + + uint8 r4811; + uint8 r4812; + uint8 r4813; + uint8 r4814; + uint8 r4815; + uint8 r4816; + uint8 r4817; + uint8 r4818; + + uint8 r481x; + + bool8 r4814_latch; // bool + bool8 r4815_latch; // bool + + uint8 r4820; + uint8 r4821; + uint8 r4822; + uint8 r4823; + uint8 r4824; + uint8 r4825; + uint8 r4826; + uint8 r4827; + uint8 r4828; + uint8 r4829; + uint8 r482a; + uint8 r482b; + uint8 r482c; + uint8 r482d; + uint8 r482e; + uint8 r482f; + + uint8 r4830; + uint8 r4831; + uint8 r4832; + uint8 r4833; + uint8 r4834; + + uint32 dx_offset; // unsigned + uint32 ex_offset; // unsigned + uint32 fx_offset; // unsigned + + uint8 r4840; + uint8 r4841; + uint8 r4842; + + int32 rtc_state; // enum RTC_State + int32 rtc_mode; // enum RTC_Mode + uint32 rtc_index; // unsigned + + uint32 decomp_mode; // unsigned + uint32 decomp_offset; // unsigned + + uint8 decomp_buffer[SPC7110_DECOMP_BUFFER_SIZE]; + + uint32 decomp_buffer_rdoffset; // unsigned + uint32 decomp_buffer_wroffset; // unsigned + uint32 decomp_buffer_length; // unsigned + + struct ContextState + { + uint8 index; + uint8 invert; + } context[32]; +}; + +extern struct SSPC7110Snapshot s7snap; + +void S9xInitSPC7110 (void); +void S9xResetSPC7110 (void); +void S9xSPC7110PreSaveState (void); +void S9xSPC7110PostLoadState (int); +void S9xSetSPC7110 (uint8, uint16); +uint8 S9xGetSPC7110 (uint16); +uint8 S9xGetSPC7110Byte (uint32); +uint8 * S9xGetBasePointerSPC7110 (uint32); + +#endif diff --git a/spc7110dec.cpp b/spc7110dec.cpp new file mode 100644 index 00000000..65d55868 --- /dev/null +++ b/spc7110dec.cpp @@ -0,0 +1,529 @@ +/***** + * SPC7110 emulator - version 0.03 (2008-08-10) + * Copyright (c) 2008, byuu and neviksti + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * The software is provided "as is" and the author disclaims all warranties + * with regard to this software including all implied warranties of + * merchantibility and fitness, in no event shall the author be liable for + * any special, direct, indirect, or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in an + * action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + *****/ + + +#ifdef _SPC7110EMU_CPP_ + +uint8 SPC7110Decomp::read() { + if(decomp_buffer_length == 0) { + //decompress at least (decomp_buffer_size / 2) bytes to the buffer + switch(decomp_mode) { + case 0: mode0(false); break; + case 1: mode1(false); break; + case 2: mode2(false); break; + default: return 0x00; + } + } + + uint8 data = decomp_buffer[decomp_buffer_rdoffset++]; + decomp_buffer_rdoffset &= decomp_buffer_size - 1; + decomp_buffer_length--; + return data; +} + +void SPC7110Decomp::write(uint8 data) { + decomp_buffer[decomp_buffer_wroffset++] = data; + decomp_buffer_wroffset &= decomp_buffer_size - 1; + decomp_buffer_length++; +} + +uint8 SPC7110Decomp::dataread() { + unsigned size = memory_cartrom_size() - 0x100000; + while(decomp_offset >= size) decomp_offset -= size; + return memory_cartrom_read(0x100000 + decomp_offset++); +} + +void SPC7110Decomp::init(unsigned mode, unsigned offset, unsigned index) { + decomp_mode = mode; + decomp_offset = offset; + + decomp_buffer_rdoffset = 0; + decomp_buffer_wroffset = 0; + decomp_buffer_length = 0; + + //reset context states + for(unsigned i = 0; i < 32; i++) { + context[i].index = 0; + context[i].invert = 0; + } + + switch(decomp_mode) { + case 0: mode0(true); break; + case 1: mode1(true); break; + case 2: mode2(true); break; + } + + //decompress up to requested output data index + while(index--) read(); +} + +// + +void SPC7110Decomp::mode0(bool init) { + static uint8 val, in, span; + static int out, inverts, lps, in_count; + + if(init == true) { + out = inverts = lps = 0; + span = 0xff; + val = dataread(); + in = dataread(); + in_count = 8; + return; + } + + while(decomp_buffer_length < (decomp_buffer_size >> 1)) { + for(unsigned bit = 0; bit < 8; bit++) { + //get context + uint8 mask = (1 << (bit & 3)) - 1; + uint8 con = mask + ((inverts & mask) ^ (lps & mask)); + if(bit > 3) con += 15; + + //get prob and mps + unsigned prob = probability(con); + unsigned mps = (((out >> 15) & 1) ^ context[con].invert); + + //get bit + unsigned flag_lps; + if(val <= span - prob) { //mps + span = span - prob; + out = (out << 1) + mps; + flag_lps = 0; + } else { //lps + val = val - (span - (prob - 1)); + span = prob - 1; + out = (out << 1) + 1 - mps; + flag_lps = 1; + } + + //renormalize + unsigned shift = 0; + while(span < 0x7f) { + shift++; + + span = (span << 1) + 1; + val = (val << 1) + (in >> 7); + + in <<= 1; + if(--in_count == 0) { + in = dataread(); + in_count = 8; + } + } + + //update processing info + lps = (lps << 1) + flag_lps; + inverts = (inverts << 1) + context[con].invert; + + //update context state + if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; + if(flag_lps) context[con].index = next_lps(con); + else if(shift) context[con].index = next_mps(con); + } + + //save byte + write(out); + } +} + +void SPC7110Decomp::mode1(bool init) { + static unsigned pixelorder[4], realorder[4]; + static uint8 in, val, span; + static int out, inverts, lps, in_count; + + if(init == true) { + for(unsigned i = 0; i < 4; i++) pixelorder[i] = i; + out = inverts = lps = 0; + span = 0xff; + val = dataread(); + in = dataread(); + in_count = 8; + return; + } + + while(decomp_buffer_length < (decomp_buffer_size >> 1)) { + for(unsigned pixel = 0; pixel < 8; pixel++) { + //get first symbol context + unsigned a = ((out >> (1 * 2)) & 3); + unsigned b = ((out >> (7 * 2)) & 3); + unsigned c = ((out >> (8 * 2)) & 3); + unsigned con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c); + + //update pixel order + unsigned m, n; + for(m = 0; m < 4; m++) if(pixelorder[m] == a) break; + for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1]; + pixelorder[0] = a; + + //calculate the real pixel order + for(m = 0; m < 4; m++) realorder[m] = pixelorder[m]; + + //rotate reference pixel c value to top + for(m = 0; m < 4; m++) if(realorder[m] == c) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = c; + + //rotate reference pixel b value to top + for(m = 0; m < 4; m++) if(realorder[m] == b) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = b; + + //rotate reference pixel a value to top + for(m = 0; m < 4; m++) if(realorder[m] == a) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = a; + + //get 2 symbols + for(unsigned bit = 0; bit < 2; bit++) { + //get prob + unsigned prob = probability(con); + + //get symbol + unsigned flag_lps; + if(val <= span - prob) { //mps + span = span - prob; + flag_lps = 0; + } else { //lps + val = val - (span - (prob - 1)); + span = prob - 1; + flag_lps = 1; + } + + //renormalize + unsigned shift = 0; + while(span < 0x7f) { + shift++; + + span = (span << 1) + 1; + val = (val << 1) + (in >> 7); + + in <<= 1; + if(--in_count == 0) { + in = dataread(); + in_count = 8; + } + } + + //update processing info + lps = (lps << 1) + flag_lps; + inverts = (inverts << 1) + context[con].invert; + + //update context state + if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; + if(flag_lps) context[con].index = next_lps(con); + else if(shift) context[con].index = next_mps(con); + + //get next context + con = 5 + (con << 1) + ((lps ^ inverts) & 1); + } + + //get pixel + b = realorder[(lps ^ inverts) & 3]; + out = (out << 2) + b; + } + + //turn pixel data into bitplanes + unsigned data = morton_2x8(out); + write(data >> 8); + write(data >> 0); + } +} + +void SPC7110Decomp::mode2(bool init) { + static unsigned pixelorder[16], realorder[16]; + static uint8 bitplanebuffer[16], buffer_index; + static uint8 in, val, span; + static int out0, out1, inverts, lps, in_count; + + if(init == true) { + for(unsigned i = 0; i < 16; i++) pixelorder[i] = i; + buffer_index = 0; + out0 = out1 = inverts = lps = 0; + span = 0xff; + val = dataread(); + in = dataread(); + in_count = 8; + return; + } + + while(decomp_buffer_length < (decomp_buffer_size >> 1)) { + for(unsigned pixel = 0; pixel < 8; pixel++) { + //get first symbol context + unsigned a = ((out0 >> (0 * 4)) & 15); + unsigned b = ((out0 >> (7 * 4)) & 15); + unsigned c = ((out1 >> (0 * 4)) & 15); + unsigned con = 0; + unsigned refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c); + + //update pixel order + unsigned m, n; + for(m = 0; m < 16; m++) if(pixelorder[m] == a) break; + for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1]; + pixelorder[0] = a; + + //calculate the real pixel order + for(m = 0; m < 16; m++) realorder[m] = pixelorder[m]; + + //rotate reference pixel c value to top + for(m = 0; m < 16; m++) if(realorder[m] == c) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = c; + + //rotate reference pixel b value to top + for(m = 0; m < 16; m++) if(realorder[m] == b) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = b; + + //rotate reference pixel a value to top + for(m = 0; m < 16; m++) if(realorder[m] == a) break; + for(n = m; n > 0; n--) realorder[n] = realorder[n - 1]; + realorder[0] = a; + + //get 4 symbols + for(unsigned bit = 0; bit < 4; bit++) { + //get prob + unsigned prob = probability(con); + + //get symbol + unsigned flag_lps; + if(val <= span - prob) { //mps + span = span - prob; + flag_lps = 0; + } else { //lps + val = val - (span - (prob - 1)); + span = prob - 1; + flag_lps = 1; + } + + //renormalize + unsigned shift = 0; + while(span < 0x7f) { + shift++; + + span = (span << 1) + 1; + val = (val << 1) + (in >> 7); + + in <<= 1; + if(--in_count == 0) { + in = dataread(); + in_count = 8; + } + } + + //update processing info + lps = (lps << 1) + flag_lps; + unsigned invertbit = context[con].invert; + inverts = (inverts << 1) + invertbit; + + //update context state + if(flag_lps & toggle_invert(con)) context[con].invert ^= 1; + if(flag_lps) context[con].index = next_lps(con); + else if(shift) context[con].index = next_mps(con); + + //get next context + con = mode2_context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0); + } + + //get pixel + b = realorder[(lps ^ inverts) & 0x0f]; + out1 = (out1 << 4) + ((out0 >> 28) & 0x0f); + out0 = (out0 << 4) + b; + } + + //convert pixel data into bitplanes + unsigned data = morton_4x8(out0); + write(data >> 24); + write(data >> 16); + bitplanebuffer[buffer_index++] = data >> 8; + bitplanebuffer[buffer_index++] = data >> 0; + + if(buffer_index == 16) { + for(unsigned i = 0; i < 16; i++) write(bitplanebuffer[i]); + buffer_index = 0; + } + } +} + +// + +const uint8 SPC7110Decomp::evolution_table[53][4] = { +//{ prob, nextlps, nextmps, toggle invert }, + + { 0x5a, 1, 1, 1 }, + { 0x25, 6, 2, 0 }, + { 0x11, 8, 3, 0 }, + { 0x08, 10, 4, 0 }, + { 0x03, 12, 5, 0 }, + { 0x01, 15, 5, 0 }, + + { 0x5a, 7, 7, 1 }, + { 0x3f, 19, 8, 0 }, + { 0x2c, 21, 9, 0 }, + { 0x20, 22, 10, 0 }, + { 0x17, 23, 11, 0 }, + { 0x11, 25, 12, 0 }, + { 0x0c, 26, 13, 0 }, + { 0x09, 28, 14, 0 }, + { 0x07, 29, 15, 0 }, + { 0x05, 31, 16, 0 }, + { 0x04, 32, 17, 0 }, + { 0x03, 34, 18, 0 }, + { 0x02, 35, 5, 0 }, + + { 0x5a, 20, 20, 1 }, + { 0x48, 39, 21, 0 }, + { 0x3a, 40, 22, 0 }, + { 0x2e, 42, 23, 0 }, + { 0x26, 44, 24, 0 }, + { 0x1f, 45, 25, 0 }, + { 0x19, 46, 26, 0 }, + { 0x15, 25, 27, 0 }, + { 0x11, 26, 28, 0 }, + { 0x0e, 26, 29, 0 }, + { 0x0b, 27, 30, 0 }, + { 0x09, 28, 31, 0 }, + { 0x08, 29, 32, 0 }, + { 0x07, 30, 33, 0 }, + { 0x05, 31, 34, 0 }, + { 0x04, 33, 35, 0 }, + { 0x04, 33, 36, 0 }, + { 0x03, 34, 37, 0 }, + { 0x02, 35, 38, 0 }, + { 0x02, 36, 5, 0 }, + + { 0x58, 39, 40, 1 }, + { 0x4d, 47, 41, 0 }, + { 0x43, 48, 42, 0 }, + { 0x3b, 49, 43, 0 }, + { 0x34, 50, 44, 0 }, + { 0x2e, 51, 45, 0 }, + { 0x29, 44, 46, 0 }, + { 0x25, 45, 24, 0 }, + + { 0x56, 47, 48, 1 }, + { 0x4f, 47, 49, 0 }, + { 0x47, 48, 50, 0 }, + { 0x41, 49, 51, 0 }, + { 0x3c, 50, 52, 0 }, + { 0x37, 51, 43, 0 }, +}; + +const uint8 SPC7110Decomp::mode2_context_table[32][2] = { +//{ next 0, next 1 }, + + { 1, 2 }, + + { 3, 8 }, + { 13, 14 }, + + { 15, 16 }, + { 17, 18 }, + { 19, 20 }, + { 21, 22 }, + { 23, 24 }, + { 25, 26 }, + { 25, 26 }, + { 25, 26 }, + { 25, 26 }, + { 25, 26 }, + { 27, 28 }, + { 29, 30 }, + + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + { 31, 31 }, + + { 31, 31 }, +}; + +uint8 SPC7110Decomp::probability (unsigned n) { return evolution_table[context[n].index][0]; } +uint8 SPC7110Decomp::next_lps (unsigned n) { return evolution_table[context[n].index][1]; } +uint8 SPC7110Decomp::next_mps (unsigned n) { return evolution_table[context[n].index][2]; } +bool SPC7110Decomp::toggle_invert(unsigned n) { return evolution_table[context[n].index][3]; } + +unsigned SPC7110Decomp::morton_2x8(unsigned data) { + //reverse morton lookup: de-interleave two 8-bit values + //15, 13, 11, 9, 7, 5, 3, 1 -> 15- 8 + //14, 12, 10, 8, 6, 4, 2, 0 -> 7- 0 + return morton16[0][(data >> 0) & 255] + morton16[1][(data >> 8) & 255]; +} + +unsigned SPC7110Decomp::morton_4x8(unsigned data) { + //reverse morton lookup: de-interleave four 8-bit values + //31, 27, 23, 19, 15, 11, 7, 3 -> 31-24 + //30, 26, 22, 18, 14, 10, 6, 2 -> 23-16 + //29, 25, 21, 17, 13, 9, 5, 1 -> 15- 8 + //28, 24, 20, 16, 12, 8, 4, 0 -> 7- 0 + return morton32[0][(data >> 0) & 255] + morton32[1][(data >> 8) & 255] + + morton32[2][(data >> 16) & 255] + morton32[3][(data >> 24) & 255]; +} + +// + +void SPC7110Decomp::reset() { + //mode 3 is invalid; this is treated as a special case to always return 0x00 + //set to mode 3 so that reading decomp port before starting first decomp will return 0x00 + decomp_mode = 3; + + decomp_buffer_rdoffset = 0; + decomp_buffer_wroffset = 0; + decomp_buffer_length = 0; +} + +SPC7110Decomp::SPC7110Decomp() { + decomp_buffer = new uint8_t[decomp_buffer_size]; + reset(); + + //initialize reverse morton lookup tables + for(unsigned i = 0; i < 256; i++) { + #define map(x, y) (((i >> x) & 1) << y) + //2x8-bit + morton16[1][i] = map(7, 15) + map(6, 7) + map(5, 14) + map(4, 6) + + map(3, 13) + map(2, 5) + map(1, 12) + map(0, 4); + morton16[0][i] = map(7, 11) + map(6, 3) + map(5, 10) + map(4, 2) + + map(3, 9) + map(2, 1) + map(1, 8) + map(0, 0); + //4x8-bit + morton32[3][i] = map(7, 31) + map(6, 23) + map(5, 15) + map(4, 7) + + map(3, 30) + map(2, 22) + map(1, 14) + map(0, 6); + morton32[2][i] = map(7, 29) + map(6, 21) + map(5, 13) + map(4, 5) + + map(3, 28) + map(2, 20) + map(1, 12) + map(0, 4); + morton32[1][i] = map(7, 27) + map(6, 19) + map(5, 11) + map(4, 3) + + map(3, 26) + map(2, 18) + map(1, 10) + map(0, 2); + morton32[0][i] = map(7, 25) + map(6, 17) + map(5, 9) + map(4, 1) + + map(3, 24) + map(2, 16) + map(1, 8) + map(0, 0); + #undef map + } +} + +SPC7110Decomp::~SPC7110Decomp() { + delete[] decomp_buffer; +} + +#endif diff --git a/spc7110dec.h b/spc7110dec.h new file mode 100644 index 00000000..3a9c7ce3 --- /dev/null +++ b/spc7110dec.h @@ -0,0 +1,67 @@ +/***** + * SPC7110 emulator - version 0.03 (2008-08-10) + * Copyright (c) 2008, byuu and neviksti + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * The software is provided "as is" and the author disclaims all warranties + * with regard to this software including all implied warranties of + * merchantibility and fitness, in no event shall the author be liable for + * any special, direct, indirect, or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in an + * action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + *****/ + + +#ifndef _SPC7110DEC_H_ +#define _SPC7110DEC_H_ + +class SPC7110Decomp { +public: + uint8 read(); + void init(unsigned mode, unsigned offset, unsigned index); + void reset(); + + SPC7110Decomp(); + ~SPC7110Decomp(); + + unsigned decomp_mode; + unsigned decomp_offset; + + //read() will spool chunks half the size of decomp_buffer_size + enum { decomp_buffer_size = SPC7110_DECOMP_BUFFER_SIZE }; //must be >= 64, and must be a power of two + uint8 *decomp_buffer; + unsigned decomp_buffer_rdoffset; + unsigned decomp_buffer_wroffset; + unsigned decomp_buffer_length; + + void write(uint8 data); + uint8 dataread(); + + void mode0(bool init); + void mode1(bool init); + void mode2(bool init); + + static const uint8 evolution_table[53][4]; + static const uint8 mode2_context_table[32][2]; + + struct ContextState { + uint8 index; + uint8 invert; + } context[32]; + + uint8 probability(unsigned n); + uint8 next_lps(unsigned n); + uint8 next_mps(unsigned n); + bool toggle_invert(unsigned n); + + unsigned morton16[2][256]; + unsigned morton32[4][256]; + unsigned morton_2x8(unsigned data); + unsigned morton_4x8(unsigned data); +}; + +#endif diff --git a/spc7110emu.cpp b/spc7110emu.cpp new file mode 100644 index 00000000..364116a4 --- /dev/null +++ b/spc7110emu.cpp @@ -0,0 +1,645 @@ +/***** + * SPC7110 emulator - version 0.03 (2008-08-10) + * Copyright (c) 2008, byuu and neviksti + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * The software is provided "as is" and the author disclaims all warranties + * with regard to this software including all implied warranties of + * merchantibility and fitness, in no event shall the author be liable for + * any special, direct, indirect, or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in an + * action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + *****/ + + +#define _SPC7110EMU_CPP_ + +#include "spc7110dec.cpp" + +const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + +void SPC7110::power() { + reset(); +} + +void SPC7110::reset() { + r4801 = 0x00; + r4802 = 0x00; + r4803 = 0x00; + r4804 = 0x00; + r4805 = 0x00; + r4806 = 0x00; + r4807 = 0x00; + r4808 = 0x00; + r4809 = 0x00; + r480a = 0x00; + r480b = 0x00; + r480c = 0x00; + + decomp.reset(); + + r4811 = 0x00; + r4812 = 0x00; + r4813 = 0x00; + r4814 = 0x00; + r4815 = 0x00; + r4816 = 0x00; + r4817 = 0x00; + r4818 = 0x00; + + r481x = 0x00; + r4814_latch = false; + r4815_latch = false; + + r4820 = 0x00; + r4821 = 0x00; + r4822 = 0x00; + r4823 = 0x00; + r4824 = 0x00; + r4825 = 0x00; + r4826 = 0x00; + r4827 = 0x00; + r4828 = 0x00; + r4829 = 0x00; + r482a = 0x00; + r482b = 0x00; + r482c = 0x00; + r482d = 0x00; + r482e = 0x00; + r482f = 0x00; + + r4830 = 0x00; + mmio_write(0x4831, 0); + mmio_write(0x4832, 1); + mmio_write(0x4833, 2); + r4834 = 0x00; + + r4840 = 0x00; + r4841 = 0x00; + r4842 = 0x00; + + if(cartridge_info_spc7110rtc) { + rtc_state = RTCS_Inactive; + rtc_mode = RTCM_Linear; + rtc_index = 0; + } +} + +unsigned SPC7110::datarom_addr(unsigned addr) { + unsigned size = memory_cartrom_size() - 0x100000; + while(addr >= size) addr -= size; + return addr + 0x100000; +} + +unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); } +unsigned SPC7110::data_adjust() { return r4814 + (r4815 << 8); } +unsigned SPC7110::data_increment() { return r4816 + (r4817 << 8); } +void SPC7110::set_data_pointer(unsigned addr) { r4811 = addr; r4812 = addr >> 8; r4813 = addr >> 16; } +void SPC7110::set_data_adjust(unsigned addr) { r4814 = addr; r4815 = addr >> 8; } + +void SPC7110::update_time(int offset) { + time_t rtc_time + = (memory_cartrtc_read(16) << 0) + | (memory_cartrtc_read(17) << 8) + | (memory_cartrtc_read(18) << 16) + | (memory_cartrtc_read(19) << 24); + time_t current_time = time(0) - offset; + + //sizeof(time_t) is platform-dependent; though memory::cartrtc needs to be platform-agnostic. + //yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by + //accounting for overflow at the cost of 1-bit precision (to catch underflow). this will allow + //memory::cartrtc timestamp to remain valid for up to ~34 years from the last update, even if + //time_t overflows. calculation should be valid regardless of number representation, time_t size, + //or whether time_t is signed or unsigned. + time_t diff + = (current_time >= rtc_time) + ? (current_time - rtc_time) + : (std::numeric_limits::max() - rtc_time + current_time + 1); //compensate for overflow + if(diff > std::numeric_limits::max() / 2) diff = 0; //compensate for underflow + + bool update = true; + if(memory_cartrtc_read(13) & 1) update = false; //do not update if CR0 timer disable flag is set + if(memory_cartrtc_read(15) & 3) update = false; //do not update if CR2 timer disable flags are set + + if(diff > 0 && update == true) { + unsigned second = memory_cartrtc_read( 0) + memory_cartrtc_read( 1) * 10; + unsigned minute = memory_cartrtc_read( 2) + memory_cartrtc_read( 3) * 10; + unsigned hour = memory_cartrtc_read( 4) + memory_cartrtc_read( 5) * 10; + unsigned day = memory_cartrtc_read( 6) + memory_cartrtc_read( 7) * 10; + unsigned month = memory_cartrtc_read( 8) + memory_cartrtc_read( 9) * 10; + unsigned year = memory_cartrtc_read(10) + memory_cartrtc_read(11) * 10; + unsigned weekday = memory_cartrtc_read(12); + + day--; + month--; + year += (year >= 90) ? 1900 : 2000; //range = 1990-2089 + + second += diff; + while(second >= 60) { + second -= 60; + + minute++; + if(minute < 60) continue; + minute = 0; + + hour++; + if(hour < 24) continue; + hour = 0; + + day++; + weekday = (weekday + 1) % 7; + unsigned days = months[month % 12]; + if(days == 28) { + bool leapyear = false; + if((year % 4) == 0) { + leapyear = true; + if((year % 100) == 0 && (year % 400) != 0) leapyear = false; + } + if(leapyear) days++; + } + if(day < days) continue; + day = 0; + + month++; + if(month < 12) continue; + month = 0; + + year++; + } + + day++; + month++; + year %= 100; + + memory_cartrtc_write( 0, second % 10); + memory_cartrtc_write( 1, second / 10); + memory_cartrtc_write( 2, minute % 10); + memory_cartrtc_write( 3, minute / 10); + memory_cartrtc_write( 4, hour % 10); + memory_cartrtc_write( 5, hour / 10); + memory_cartrtc_write( 6, day % 10); + memory_cartrtc_write( 7, day / 10); + memory_cartrtc_write( 8, month % 10); + memory_cartrtc_write( 9, month / 10); + memory_cartrtc_write(10, year % 10); + memory_cartrtc_write(11, (year / 10) % 10); + memory_cartrtc_write(12, weekday % 7); + } + + memory_cartrtc_write(16, current_time >> 0); + memory_cartrtc_write(17, current_time >> 8); + memory_cartrtc_write(18, current_time >> 16); + memory_cartrtc_write(19, current_time >> 24); +} + +uint8 SPC7110::mmio_read(unsigned addr) { + addr &= 0xffff; + + switch(addr) { + //================== + //decompression unit + //================== + + case 0x4800: { + uint16 counter = (r4809 + (r480a << 8)); + counter--; + r4809 = counter; + r480a = counter >> 8; + return decomp.read(); + } + case 0x4801: return r4801; + case 0x4802: return r4802; + case 0x4803: return r4803; + case 0x4804: return r4804; + case 0x4805: return r4805; + case 0x4806: return r4806; + case 0x4807: return r4807; + case 0x4808: return r4808; + case 0x4809: return r4809; + case 0x480a: return r480a; + case 0x480b: return r480b; + case 0x480c: { + uint8 status = r480c; + r480c &= 0x7f; + return status; + } + + //============== + //data port unit + //============== + + case 0x4810: { + if(r481x != 0x07) return 0x00; + + unsigned addr = data_pointer(); + unsigned adjust = data_adjust(); + if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend + + unsigned adjustaddr = addr; + if(r4818 & 2) { + adjustaddr += adjust; + set_data_adjust(adjust + 1); + } + + uint8 data = memory_cartrom_read(datarom_addr(adjustaddr)); + if(!(r4818 & 2)) { + unsigned increment = (r4818 & 1) ? data_increment() : 1; + if(r4818 & 4) increment = (int16)increment; //16-bit sign extend + + if((r4818 & 16) == 0) { + set_data_pointer(addr + increment); + } else { + set_data_adjust(adjust + increment); + } + } + + return data; + } + case 0x4811: return r4811; + case 0x4812: return r4812; + case 0x4813: return r4813; + case 0x4814: return r4814; + case 0x4815: return r4815; + case 0x4816: return r4816; + case 0x4817: return r4817; + case 0x4818: return r4818; + case 0x481a: { + if(r481x != 0x07) return 0x00; + + unsigned addr = data_pointer(); + unsigned adjust = data_adjust(); + if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend + + uint8 data = memory_cartrom_read(datarom_addr(addr + adjust)); + if((r4818 & 0x60) == 0x60) { + if((r4818 & 16) == 0) { + set_data_pointer(addr + adjust); + } else { + set_data_adjust(adjust + adjust); + } + } + + return data; + } + + //========= + //math unit + //========= + + case 0x4820: return r4820; + case 0x4821: return r4821; + case 0x4822: return r4822; + case 0x4823: return r4823; + case 0x4824: return r4824; + case 0x4825: return r4825; + case 0x4826: return r4826; + case 0x4827: return r4827; + case 0x4828: return r4828; + case 0x4829: return r4829; + case 0x482a: return r482a; + case 0x482b: return r482b; + case 0x482c: return r482c; + case 0x482d: return r482d; + case 0x482e: return r482e; + case 0x482f: { + uint8 status = r482f; + r482f &= 0x7f; + return status; + } + + //=================== + //memory mapping unit + //=================== + + case 0x4830: return r4830; + case 0x4831: return r4831; + case 0x4832: return r4832; + case 0x4833: return r4833; + case 0x4834: return r4834; + + //==================== + //real-time clock unit + //==================== + + case 0x4840: return r4840; + case 0x4841: { + if(rtc_state == RTCS_Inactive || rtc_state == RTCS_ModeSelect) return 0x00; + + r4842 = 0x80; + uint8 data = memory_cartrtc_read(rtc_index); + rtc_index = (rtc_index + 1) & 15; + return data; + } + case 0x4842: { + uint8 status = r4842; + r4842 &= 0x7f; + return status; + } + } + + return cpu_regs_mdr; +} + +void SPC7110::mmio_write(unsigned addr, uint8 data) { + addr &= 0xffff; + + switch(addr) { + //================== + //decompression unit + //================== + + case 0x4801: r4801 = data; break; + case 0x4802: r4802 = data; break; + case 0x4803: r4803 = data; break; + case 0x4804: r4804 = data; break; + case 0x4805: r4805 = data; break; + case 0x4806: { + r4806 = data; + + unsigned table = (r4801 + (r4802 << 8) + (r4803 << 16)); + unsigned index = (r4804 << 2); + //unsigned length = (r4809 + (r480a << 8)); + unsigned addr = datarom_addr(table + index); + unsigned mode = (memory_cartrom_read(addr + 0)); + unsigned offset = (memory_cartrom_read(addr + 1) << 16) + + (memory_cartrom_read(addr + 2) << 8) + + (memory_cartrom_read(addr + 3) << 0); + + decomp.init(mode, offset, (r4805 + (r4806 << 8)) << mode); + r480c = 0x80; + } break; + + case 0x4807: r4807 = data; break; + case 0x4808: r4808 = data; break; + case 0x4809: r4809 = data; break; + case 0x480a: r480a = data; break; + case 0x480b: r480b = data; break; + + //============== + //data port unit + //============== + + case 0x4811: r4811 = data; r481x |= 0x01; break; + case 0x4812: r4812 = data; r481x |= 0x02; break; + case 0x4813: r4813 = data; r481x |= 0x04; break; + case 0x4814: { + r4814 = data; + r4814_latch = true; + if(!r4815_latch) break; + if(!(r4818 & 2)) break; + if(r4818 & 0x10) break; + + if((r4818 & 0x60) == 0x20) { + unsigned increment = data_adjust() & 0xff; + if(r4818 & 8) increment = (int8)increment; //8-bit sign extend + set_data_pointer(data_pointer() + increment); + } else if((r4818 & 0x60) == 0x40) { + unsigned increment = data_adjust(); + if(r4818 & 8) increment = (int16)increment; //16-bit sign extend + set_data_pointer(data_pointer() + increment); + } + } break; + case 0x4815: { + r4815 = data; + r4815_latch = true; + if(!r4814_latch) break; + if(!(r4818 & 2)) break; + if(r4818 & 0x10) break; + + if((r4818 & 0x60) == 0x20) { + unsigned increment = data_adjust() & 0xff; + if(r4818 & 8) increment = (int8)increment; //8-bit sign extend + set_data_pointer(data_pointer() + increment); + } else if((r4818 & 0x60) == 0x40) { + unsigned increment = data_adjust(); + if(r4818 & 8) increment = (int16)increment; //16-bit sign extend + set_data_pointer(data_pointer() + increment); + } + } break; + case 0x4816: r4816 = data; break; + case 0x4817: r4817 = data; break; + case 0x4818: { + if(r481x != 0x07) break; + + r4818 = data; + r4814_latch = r4815_latch = false; + } break; + + //========= + //math unit + //========= + + case 0x4820: r4820 = data; break; + case 0x4821: r4821 = data; break; + case 0x4822: r4822 = data; break; + case 0x4823: r4823 = data; break; + case 0x4824: r4824 = data; break; + case 0x4825: { + r4825 = data; + + if(r482e & 1) { + //signed 16-bit x 16-bit multiplication + int16 r0 = (int16)(r4824 + (r4825 << 8)); + int16 r1 = (int16)(r4820 + (r4821 << 8)); + + signed result = r0 * r1; + r4828 = result; + r4829 = result >> 8; + r482a = result >> 16; + r482b = result >> 24; + } else { + //unsigned 16-bit x 16-bit multiplication + uint16 r0 = (uint16)(r4824 + (r4825 << 8)); + uint16 r1 = (uint16)(r4820 + (r4821 << 8)); + + unsigned result = r0 * r1; + r4828 = result; + r4829 = result >> 8; + r482a = result >> 16; + r482b = result >> 24; + } + + r482f = 0x80; + } break; + case 0x4826: r4826 = data; break; + case 0x4827: { + r4827 = data; + + if(r482e & 1) { + //signed 32-bit x 16-bit division + int32 dividend = (int32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24)); + int16 divisor = (int16)(r4826 + (r4827 << 8)); + + int32 quotient; + int16 remainder; + + if(divisor) { + quotient = (int32)(dividend / divisor); + remainder = (int32)(dividend % divisor); + } else { + //illegal division by zero + quotient = 0; + remainder = dividend & 0xffff; + } + + r4828 = quotient; + r4829 = quotient >> 8; + r482a = quotient >> 16; + r482b = quotient >> 24; + + r482c = remainder; + r482d = remainder >> 8; + } else { + //unsigned 32-bit x 16-bit division + uint32 dividend = (uint32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24)); + uint16 divisor = (uint16)(r4826 + (r4827 << 8)); + + uint32 quotient; + uint16 remainder; + + if(divisor) { + quotient = (uint32)(dividend / divisor); + remainder = (uint16)(dividend % divisor); + } else { + //illegal division by zero + quotient = 0; + remainder = dividend & 0xffff; + } + + r4828 = quotient; + r4829 = quotient >> 8; + r482a = quotient >> 16; + r482b = quotient >> 24; + + r482c = remainder; + r482d = remainder >> 8; + } + + r482f = 0x80; + } break; + + case 0x482e: { + //reset math unit + r4820 = r4821 = r4822 = r4823 = 0; + r4824 = r4825 = r4826 = r4827 = 0; + r4828 = r4829 = r482a = r482b = 0; + r482c = r482d = 0; + + r482e = data; + } break; + + //=================== + //memory mapping unit + //=================== + + case 0x4830: r4830 = data; break; + + case 0x4831: { + r4831 = data; + dx_offset = datarom_addr((data & 7) * 0x100000); + } break; + + case 0x4832: { + r4832 = data; + ex_offset = datarom_addr((data & 7) * 0x100000); + } break; + + case 0x4833: { + r4833 = data; + fx_offset = datarom_addr((data & 7) * 0x100000); + } break; + + case 0x4834: r4834 = data; break; + + //==================== + //real-time clock unit + //==================== + + case 0x4840: { + r4840 = data; + if(!(r4840 & 1)) { + //disable RTC + rtc_state = RTCS_Inactive; + update_time(); + } else { + //enable RTC + r4842 = 0x80; + rtc_state = RTCS_ModeSelect; + } + } break; + + case 0x4841: { + r4841 = data; + + switch(rtc_state) { + case RTCS_ModeSelect: { + if(data == RTCM_Linear || data == RTCM_Indexed) { + r4842 = 0x80; + rtc_state = RTCS_IndexSelect; + rtc_mode = (RTC_Mode)data; + rtc_index = 0; + } + } break; + + case RTCS_IndexSelect: { + r4842 = 0x80; + rtc_index = data & 15; + if(rtc_mode == RTCM_Linear) rtc_state = RTCS_Write; + } break; + + case RTCS_Write: { + r4842 = 0x80; + + //control register 0 + if(rtc_index == 13) { + //increment second counter + if(data & 2) update_time(+1); + + //round minute counter + if(data & 8) { + update_time(); + + unsigned second = memory_cartrtc_read( 0) + memory_cartrtc_read( 1) * 10; + //clear seconds + memory_cartrtc_write(0, 0); + memory_cartrtc_write(1, 0); + + if(second >= 30) update_time(+60); + } + } + + //control register 2 + if(rtc_index == 15) { + //disable timer and clear second counter + if((data & 1) && !(memory_cartrtc_read(15) & 1)) { + update_time(); + + //clear seconds + memory_cartrtc_write(0, 0); + memory_cartrtc_write(1, 0); + } + + //disable timer + if((data & 2) && !(memory_cartrtc_read(15) & 2)) { + update_time(); + } + } + + memory_cartrtc_write(rtc_index, data & 15); + rtc_index = (rtc_index + 1) & 15; + } break; + + case RTCS_Inactive: { + } break; + } //switch(rtc_state) + } break; + } +} + +SPC7110::SPC7110() { +} diff --git a/spc7110emu.h b/spc7110emu.h new file mode 100644 index 00000000..5f66fecc --- /dev/null +++ b/spc7110emu.h @@ -0,0 +1,136 @@ +/***** + * SPC7110 emulator - version 0.03 (2008-08-10) + * Copyright (c) 2008, byuu and neviksti + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * The software is provided "as is" and the author disclaims all warranties + * with regard to this software including all implied warranties of + * merchantibility and fitness, in no event shall the author be liable for + * any special, direct, indirect, or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether in an + * action of contract, negligence or other tortious action, arising out of + * or in connection with the use or performance of this software. + *****/ + + +#ifndef _SPC7110EMU_H_ +#define _SPC7110EMU_H_ + +#include "spc7110dec.h" + +class SPC7110 { +public: + void init(); + void enable(); + void power(); + void reset(); + + unsigned datarom_addr(unsigned addr); + + unsigned data_pointer(); + unsigned data_adjust(); + unsigned data_increment(); + void set_data_pointer(unsigned addr); + void set_data_adjust(unsigned addr); + + void update_time(int offset = 0); + time_t create_time(); + + uint8 mmio_read (unsigned addr); + void mmio_write(unsigned addr, uint8 data); + + uint8 read (unsigned addr); + void write(unsigned addr, uint8 data); + + //spc7110decomp + void decomp_init(); + uint8 decomp_read(); + + SPC7110(); + + //================== + //decompression unit + //================== + uint8 r4801; //compression table low + uint8 r4802; //compression table high + uint8 r4803; //compression table bank + uint8 r4804; //compression table index + uint8 r4805; //decompression buffer index low + uint8 r4806; //decompression buffer index high + uint8 r4807; //??? + uint8 r4808; //??? + uint8 r4809; //compression length low + uint8 r480a; //compression length high + uint8 r480b; //decompression control register + uint8 r480c; //decompression status + + SPC7110Decomp decomp; + + //============== + //data port unit + //============== + uint8 r4811; //data pointer low + uint8 r4812; //data pointer high + uint8 r4813; //data pointer bank + uint8 r4814; //data adjust low + uint8 r4815; //data adjust high + uint8 r4816; //data increment low + uint8 r4817; //data increment high + uint8 r4818; //data port control register + + uint8 r481x; + + bool r4814_latch; + bool r4815_latch; + + //========= + //math unit + //========= + uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0 + uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1 + uint8 r4822; //32-bit dividend B2 + uint8 r4823; //32-bit dividend B3 + uint8 r4824; //16-bit multiplier B0 + uint8 r4825; //16-bit multiplier B1 + uint8 r4826; //16-bit divisor B0 + uint8 r4827; //16-bit divisor B1 + uint8 r4828; //32-bit product B0, 32-bit quotient B0 + uint8 r4829; //32-bit product B1, 32-bit quotient B1 + uint8 r482a; //32-bit product B2, 32-bit quotient B2 + uint8 r482b; //32-bit product B3, 32-bit quotient B3 + uint8 r482c; //16-bit remainder B0 + uint8 r482d; //16-bit remainder B1 + uint8 r482e; //math control register + uint8 r482f; //math status + + //=================== + //memory mapping unit + //=================== + uint8 r4830; //SRAM write enable + uint8 r4831; //$[d0-df]:[0000-ffff] mapping + uint8 r4832; //$[e0-ef]:[0000-ffff] mapping + uint8 r4833; //$[f0-ff]:[0000-ffff] mapping + uint8 r4834; //??? + + unsigned dx_offset; + unsigned ex_offset; + unsigned fx_offset; + + //==================== + //real-time clock unit + //==================== + uint8 r4840; //RTC latch + uint8 r4841; //RTC index/data port + uint8 r4842; //RTC status + + enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write } rtc_state; + enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c } rtc_mode; + unsigned rtc_index; + + static const unsigned months[12]; +}; + +#endif diff --git a/srtc.cpp b/srtc.cpp new file mode 100644 index 00000000..9c7e28ab --- /dev/null +++ b/srtc.cpp @@ -0,0 +1,243 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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-RTC emulation code + * Copyright (c) byuu + *****/ + + +#include + +#include "snes9x.h" +#include "memmap.h" +#include "srtc.h" +#include "display.h" + +#define memory_cartrtc_read(a) RTCData.reg[(a)] +#define memory_cartrtc_write(a, b) { RTCData.reg[(a)] = (b); } +#define cpu_regs_mdr OpenBus + +static inline unsigned max (unsigned a, unsigned b) +{ + return ((a > b) ? a : b); +} + +static inline unsigned min (unsigned a, unsigned b) +{ + return ((a < b) ? a : b); +} + +#include "srtcemu.h" +#include "srtcemu.cpp" + +static SRTC srtcemu; + + +void S9xInitSRTC (void) +{ + srtcemu.power(); + memset(RTCData.reg, 0, 20); +} + +void S9xResetSRTC (void) +{ + srtcemu.reset(); +} + +void S9xSetSRTC (uint8 data, uint16 address) +{ + srtcemu.mmio_write(address, data); +} + +uint8 S9xGetSRTC (uint16 address) +{ + return (srtcemu.mmio_read(address)); +} + +void S9xSRTCPreSaveState (void) +{ + srtcsnap.rtc_mode = (int32) srtcemu.rtc_mode; + srtcsnap.rtc_index = (int32) srtcemu.rtc_index; +} + +void S9xSRTCPostLoadState (int) +{ + srtcemu.rtc_mode = (SRTC::RTC_Mode) srtcsnap.rtc_mode; + srtcemu.rtc_index = (signed) srtcsnap.rtc_index; + + srtcemu.update_time(); +} diff --git a/srtc.h b/srtc.h new file mode 100644 index 00000000..8bc441cb --- /dev/null +++ b/srtc.h @@ -0,0 +1,203 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _SRTC_H_ +#define _SRTC_H_ + +struct SRTCData +{ + uint8 reg[20]; +}; + +// for snapshot only +struct SSRTCSnapshot +{ + int32 rtc_mode; // enum RTC_Mode + int32 rtc_index; // signed +}; + +extern struct SRTCData RTCData; +extern struct SSRTCSnapshot srtcsnap; + +void S9xInitSRTC (void); +void S9xResetSRTC (void); +void S9xSRTCPreSaveState (void); +void S9xSRTCPostLoadState (int); +void S9xSetSRTC (uint8, uint16); +uint8 S9xGetSRTC (uint16); + +#endif diff --git a/srtcemu.cpp b/srtcemu.cpp new file mode 100644 index 00000000..c5358435 --- /dev/null +++ b/srtcemu.cpp @@ -0,0 +1,223 @@ +/***** + * S-RTC emulation code + * Copyright (c) byuu + *****/ + + +#define _SRTCEMU_CPP_ + +const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + +void SRTC::power() { + reset(); +} + +void SRTC::reset() { + rtc_mode = RTCM_Read; + rtc_index = -1; + update_time(); +} + +void SRTC::update_time() { + time_t rtc_time + = (memory_cartrtc_read(16) << 0) + | (memory_cartrtc_read(17) << 8) + | (memory_cartrtc_read(18) << 16) + | (memory_cartrtc_read(19) << 24); + time_t current_time = time(0); + + //sizeof(time_t) is platform-dependent; though memory::cartrtc needs to be platform-agnostic. + //yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by + //accounting for overflow at the cost of 1-bit precision (to catch underflow). this will allow + //memory::cartrtc timestamp to remain valid for up to ~34 years from the last update, even if + //time_t overflows. calculation should be valid regardless of number representation, time_t size, + //or whether time_t is signed or unsigned. + time_t diff + = (current_time >= rtc_time) + ? (current_time - rtc_time) + : (std::numeric_limits::max() - rtc_time + current_time + 1); //compensate for overflow + if(diff > std::numeric_limits::max() / 2) diff = 0; //compensate for underflow + + if(diff > 0) { + unsigned second = memory_cartrtc_read( 0) + memory_cartrtc_read( 1) * 10; + unsigned minute = memory_cartrtc_read( 2) + memory_cartrtc_read( 3) * 10; + unsigned hour = memory_cartrtc_read( 4) + memory_cartrtc_read( 5) * 10; + unsigned day = memory_cartrtc_read( 6) + memory_cartrtc_read( 7) * 10; + unsigned month = memory_cartrtc_read( 8); + unsigned year = memory_cartrtc_read( 9) + memory_cartrtc_read(10) * 10 + memory_cartrtc_read(11) * 100; + unsigned weekday = memory_cartrtc_read(12); + + day--; + month--; + year += 1000; + + second += diff; + while(second >= 60) { + second -= 60; + + minute++; + if(minute < 60) continue; + minute = 0; + + hour++; + if(hour < 24) continue; + hour = 0; + + day++; + weekday = (weekday + 1) % 7; + unsigned days = months[month % 12]; + if(days == 28) { + bool leapyear = false; + if((year % 4) == 0) { + leapyear = true; + if((year % 100) == 0 && (year % 400) != 0) leapyear = false; + } + if(leapyear) days++; + } + if(day < days) continue; + day = 0; + + month++; + if(month < 12) continue; + month = 0; + + year++; + } + + day++; + month++; + year -= 1000; + + memory_cartrtc_write( 0, second % 10); + memory_cartrtc_write( 1, second / 10); + memory_cartrtc_write( 2, minute % 10); + memory_cartrtc_write( 3, minute / 10); + memory_cartrtc_write( 4, hour % 10); + memory_cartrtc_write( 5, hour / 10); + memory_cartrtc_write( 6, day % 10); + memory_cartrtc_write( 7, day / 10); + memory_cartrtc_write( 8, month); + memory_cartrtc_write( 9, year % 10); + memory_cartrtc_write(10, (year / 10) % 10); + memory_cartrtc_write(11, year / 100); + memory_cartrtc_write(12, weekday % 7); + } + + memory_cartrtc_write(16, current_time >> 0); + memory_cartrtc_write(17, current_time >> 8); + memory_cartrtc_write(18, current_time >> 16); + memory_cartrtc_write(19, current_time >> 24); +} + +//returns day of week for specified date +//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday +//usage: weekday(2008, 1, 1) returns weekday of January 1st, 2008 +unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) { + unsigned y = 1900, m = 1; //epoch is 1900-01-01 + unsigned sum = 0; //number of days passed since epoch + + year = max(1900, year); + month = max(1, min(12, month)); + day = max(1, min(31, day)); + + while(y < year) { + bool leapyear = false; + if((y % 4) == 0) { + leapyear = true; + if((y % 100) == 0 && (y % 400) != 0) leapyear = false; + } + sum += leapyear ? 366 : 365; + y++; + } + + while(m < month) { + unsigned days = months[m - 1]; + if(days == 28) { + bool leapyear = false; + if((y % 4) == 0) { + leapyear = true; + if((y % 100) == 0 && (y % 400) != 0) leapyear = false; + } + if(leapyear) days++; + } + sum += days; + m++; + } + + sum += day - 1; + return (sum + 1) % 7; //1900-01-01 was a Monday +} + +uint8 SRTC::mmio_read(unsigned addr) { + addr &= 0xffff; + + if(addr == 0x2800) { + if(rtc_mode != RTCM_Read) return 0x00; + + if(rtc_index < 0) { + update_time(); + rtc_index++; + return 0x0f; + } else if(rtc_index > 12) { + rtc_index = -1; + return 0x0f; + } else { + return memory_cartrtc_read(rtc_index++); + } + } + + return cpu_regs_mdr; +} + +void SRTC::mmio_write(unsigned addr, uint8 data) { + addr &= 0xffff; + + if(addr == 0x2801) { + data &= 0x0f; //only the low four bits are used + + if(data == 0x0d) { + rtc_mode = RTCM_Read; + rtc_index = -1; + return; + } + + if(data == 0x0e) { + rtc_mode = RTCM_Command; + return; + } + + if(data == 0x0f) return; //unknown behavior + + if(rtc_mode == RTCM_Write) { + if(rtc_index >= 0 && rtc_index < 12) { + memory_cartrtc_write(rtc_index++, data); + + if(rtc_index == 12) { + //day of week is automatically calculated and written + unsigned day = memory_cartrtc_read( 6) + memory_cartrtc_read( 7) * 10; + unsigned month = memory_cartrtc_read( 8); + unsigned year = memory_cartrtc_read( 9) + memory_cartrtc_read(10) * 10 + memory_cartrtc_read(11) * 100; + year += 1000; + + memory_cartrtc_write(rtc_index++, weekday(year, month, day)); + } + } + } else if(rtc_mode == RTCM_Command) { + if(data == 0) { + rtc_mode = RTCM_Write; + rtc_index = 0; + } else if(data == 4) { + rtc_mode = RTCM_Ready; + rtc_index = -1; + for(unsigned i = 0; i < 13; i++) memory_cartrtc_write(i, 0); + } else { + //unknown behavior + rtc_mode = RTCM_Ready; + } + } + } +} + +SRTC::SRTC() { +} diff --git a/srtcemu.h b/srtcemu.h new file mode 100644 index 00000000..fc1af24f --- /dev/null +++ b/srtcemu.h @@ -0,0 +1,30 @@ +/***** + * S-RTC emulation code + * Copyright (c) byuu + *****/ + + +#ifndef _SRTCEMU_H_ +#define _SRTCEMU_H_ + +class SRTC { +public: + void update_time(); + unsigned weekday(unsigned year, unsigned month, unsigned day); + + void init(); + void enable(); + void power(); + void reset(); + + uint8 mmio_read (unsigned addr); + void mmio_write(unsigned addr, uint8 data); + + SRTC(); + + static const unsigned months[12]; + enum RTC_Mode { RTCM_Ready, RTCM_Command, RTCM_Read, RTCM_Write } rtc_mode; + signed rtc_index; +}; + +#endif diff --git a/tile.cpp b/tile.cpp new file mode 100644 index 00000000..286f0eba --- /dev/null +++ b/tile.cpp @@ -0,0 +1,1532 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + +// This file includes itself multiple times. +// The other option would be to have 4 files, where A includes B, and B includes C 3 times, and C includes D 5 times. +// Look for the following marker to find where the divisions are. + +// Top-level compilation. + +#ifndef _NEWTILE_CPP +#define _NEWTILE_CPP + +#include "snes9x.h" +#include "ppu.h" +#include "tile.h" + +static uint32 pixbit[8][16]; +static uint8 hrbit_odd[256]; +static uint8 hrbit_even[256]; + + +void S9xInitTileRenderer (void) +{ + register int i; + + for (i = 0; i < 16; i++) + { + register uint32 b = 0; + + #ifdef LSB_FIRST + if (i & 8) + b |= 1; + if (i & 4) + b |= 1 << 8; + if (i & 2) + b |= 1 << 16; + if (i & 1) + b |= 1 << 24; + #else + if (i & 8) + b |= 1 << 24; + if (i & 4) + b |= 1 << 16; + if (i & 2) + b |= 1 << 8; + if (i & 1) + b |= 1; + #endif + + for (uint8 bitshift = 0; bitshift < 8; bitshift++) + pixbit[bitshift][i] = b << bitshift; + } + + for (i = 0; i < 256; i++) + { + register uint8 m = 0; + register uint8 s = 0; + + if (i & 0x80) + s |= 8; + if (i & 0x40) + m |= 8; + if (i & 0x20) + s |= 4; + if (i & 0x10) + m |= 4; + if (i & 0x08) + s |= 2; + if (i & 0x04) + m |= 2; + if (i & 0x02) + s |= 1; + if (i & 0x01) + m |= 1; + + hrbit_odd[i] = m; + hrbit_even[i] = s; + } +} + +// Here are the tile converters, selected by S9xSelectTileConverter(). +// Really, except for the definition of DOBIT and the number of times it is called, they're all the same. + +#define DOBIT(n, i) \ + if ((pix = *(tp + (n)))) \ + { \ + p1 |= pixbit[(i)][pix >> 4]; \ + p2 |= pixbit[(i)][pix & 0xf]; \ + } + +static uint8 ConvertTile2 (uint8 *pCache, uint32 TileAddr, uint32) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +static uint8 ConvertTile4 (uint8 *pCache, uint32 TileAddr, uint32) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +static uint8 ConvertTile8 (uint8 *pCache, uint32 TileAddr, uint32) +{ + register uint8 *tp = &Memory.VRAM[TileAddr]; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + for (line = 8; line != 0; line--, tp += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + DOBIT(32, 4); + DOBIT(33, 5); + DOBIT(48, 6); + DOBIT(49, 7); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +#undef DOBIT + +#define DOBIT(n, i) \ + if ((pix = hrbit_odd[*(tp1 + (n))])) \ + p1 |= pixbit[(i)][pix]; \ + if ((pix = hrbit_odd[*(tp2 + (n))])) \ + p2 |= pixbit[(i)][pix]; + +static uint8 ConvertTile2h_odd (uint8 *pCache, uint32 TileAddr, uint32 Tile) +{ + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + if (Tile == 0x3ff) + tp2 = tp1 - (0x3ff << 4); + else + tp2 = tp1 + (1 << 4); + + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +static uint8 ConvertTile4h_odd (uint8 *pCache, uint32 TileAddr, uint32 Tile) +{ + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + if (Tile == 0x3ff) + tp2 = tp1 - (0x3ff << 5); + else + tp2 = tp1 + (1 << 5); + + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +#undef DOBIT + +#define DOBIT(n, i) \ + if ((pix = hrbit_even[*(tp1 + (n))])) \ + p1 |= pixbit[(i)][pix]; \ + if ((pix = hrbit_even[*(tp2 + (n))])) \ + p2 |= pixbit[(i)][pix]; + +static uint8 ConvertTile2h_even (uint8 *pCache, uint32 TileAddr, uint32 Tile) +{ + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + if (Tile == 0x3ff) + tp2 = tp1 - (0x3ff << 4); + else + tp2 = tp1 + (1 << 4); + + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +static uint8 ConvertTile4h_even (uint8 *pCache, uint32 TileAddr, uint32 Tile) +{ + register uint8 *tp1 = &Memory.VRAM[TileAddr], *tp2; + uint32 *p = (uint32 *) pCache; + uint32 non_zero = 0; + uint8 line; + + if (Tile == 0x3ff) + tp2 = tp1 - (0x3ff << 5); + else + tp2 = tp1 + (1 << 5); + + for (line = 8; line != 0; line--, tp1 += 2, tp2 += 2) + { + uint32 p1 = 0; + uint32 p2 = 0; + register uint8 pix; + + DOBIT( 0, 0); + DOBIT( 1, 1); + DOBIT(16, 2); + DOBIT(17, 3); + *p++ = p1; + *p++ = p2; + non_zero |= p1 | p2; + } + + return (non_zero ? TRUE : BLANK_TILE); +} + +#undef DOBIT + +// First-level include: Get all the renderers. + +#include "tile.cpp" + +// Functions to select which converter and renderer to use. + +void S9xSelectTileRenderers (int BGMode, bool8 sub, bool8 obj) +{ + void (**DT) (uint32, uint32, uint32, uint32); + void (**DCT) (uint32, uint32, uint32, uint32, uint32, uint32); + void (**DMP) (uint32, uint32, uint32, uint32, uint32, uint32); + void (**DB) (uint32, uint32, uint32); + void (**DM7BG1) (uint32, uint32, int); + void (**DM7BG2) (uint32, uint32, int); + bool8 M7M1, M7M2; + + M7M1 = PPU.BGMosaic[0] && PPU.Mosaic > 1; + M7M2 = PPU.BGMosaic[1] && PPU.Mosaic > 1; + + if (!IPPU.DoubleWidthPixels) + { + DT = Renderers_DrawTile16Normal1x1; + DCT = Renderers_DrawClippedTile16Normal1x1; + DMP = Renderers_DrawMosaicPixel16Normal1x1; + DB = Renderers_DrawBackdrop16Normal1x1; + DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Normal1x1 : Renderers_DrawMode7BG1Normal1x1; + DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal1x1 : Renderers_DrawMode7BG2Normal1x1; + GFX.LinesPerTile = 8; + } + else + { + bool8 hires, interlace; + + if (obj) // OBJ + { + hires = (BGMode == 5 || BGMode == 6 || IPPU.PseudoHires); + interlace = IPPU.InterlaceOBJ; + } + else + if (BGMode == 5 || BGMode == 6) + { + hires = TRUE; + interlace = IPPU.Interlace; + } + else + { + hires = IPPU.PseudoHires; + interlace = FALSE; + } + + if (sub) + hires = FALSE; + + if (hires && interlace) + { + DT = Renderers_DrawTile16HiresInterlace; + DCT = Renderers_DrawClippedTile16HiresInterlace; + DMP = Renderers_DrawMosaicPixel16HiresInterlace; + DB = Renderers_DrawBackdrop16Hires; + DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Hires : Renderers_DrawMode7BG1Hires; + DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Hires : Renderers_DrawMode7BG2Hires; + GFX.LinesPerTile = 4; + } + else + if (hires) + { + DT = Renderers_DrawTile16Hires; + DCT = Renderers_DrawClippedTile16Hires; + DMP = Renderers_DrawMosaicPixel16Hires; + DB = Renderers_DrawBackdrop16Hires; + DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Hires : Renderers_DrawMode7BG1Hires; + DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Hires : Renderers_DrawMode7BG2Hires; + GFX.LinesPerTile = 8; + } + else + if (interlace) + { + DT = Renderers_DrawTile16Interlace; + DCT = Renderers_DrawClippedTile16Interlace; + DMP = Renderers_DrawMosaicPixel16Interlace; + DB = Renderers_DrawBackdrop16Normal2x1; + DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Normal2x1 : Renderers_DrawMode7BG1Normal2x1; + DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal2x1 : Renderers_DrawMode7BG2Normal2x1; + GFX.LinesPerTile = 4; + } + else + { + DT = Renderers_DrawTile16Normal2x1; + DCT = Renderers_DrawClippedTile16Normal2x1; + DMP = Renderers_DrawMosaicPixel16Normal2x1; + DB = Renderers_DrawBackdrop16Normal2x1; + DM7BG1 = M7M1 ? Renderers_DrawMode7MosaicBG1Normal2x1 : Renderers_DrawMode7BG1Normal2x1; + DM7BG2 = M7M2 ? Renderers_DrawMode7MosaicBG2Normal2x1 : Renderers_DrawMode7BG2Normal2x1; + GFX.LinesPerTile = 8; + } + } + + GFX.DrawTileNomath = DT[0]; + GFX.DrawClippedTileNomath = DCT[0]; + GFX.DrawMosaicPixelNomath = DMP[0]; + GFX.DrawBackdropNomath = DB[0]; + GFX.DrawMode7BG1Nomath = DM7BG1[0]; + GFX.DrawMode7BG2Nomath = DM7BG2[0]; + + int i; + + if (!Settings.Transparency) + i = 0; + else + { + i = (Memory.FillRAM[0x2131] & 0x80) ? 4 : 1; + if (Memory.FillRAM[0x2131] & 0x40) + { + i++; + if (Memory.FillRAM[0x2130] & 2) + i++; + } + } + + GFX.DrawTileMath = DT[i]; + GFX.DrawClippedTileMath = DCT[i]; + GFX.DrawMosaicPixelMath = DMP[i]; + GFX.DrawBackdropMath = DB[i]; + GFX.DrawMode7BG1Math = DM7BG1[i]; + GFX.DrawMode7BG2Math = DM7BG2[i]; +} + +void S9xSelectTileConverter (int depth, bool8 hires, bool8 sub, bool8 mosaic) +{ + switch (depth) + { + case 8: + BG.ConvertTile = BG.ConvertTileFlip = ConvertTile8; + BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_8BIT]; + BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_8BIT]; + BG.TileShift = 6; + BG.PaletteShift = 0; + BG.PaletteMask = 0; + BG.DirectColourMode = Memory.FillRAM[0x2130] & 1; + + break; + + case 4: + if (hires) + { + if (sub || mosaic) + { + BG.ConvertTile = ConvertTile4h_even; + BG.Buffer = IPPU.TileCache[TILE_4BIT_EVEN]; + BG.Buffered = IPPU.TileCached[TILE_4BIT_EVEN]; + BG.ConvertTileFlip = ConvertTile4h_odd; + BG.BufferFlip = IPPU.TileCache[TILE_4BIT_ODD]; + BG.BufferedFlip = IPPU.TileCached[TILE_4BIT_ODD]; + } + else + { + BG.ConvertTile = ConvertTile4h_odd; + BG.Buffer = IPPU.TileCache[TILE_4BIT_ODD]; + BG.Buffered = IPPU.TileCached[TILE_4BIT_ODD]; + BG.ConvertTileFlip = ConvertTile4h_even; + BG.BufferFlip = IPPU.TileCache[TILE_4BIT_EVEN]; + BG.BufferedFlip = IPPU.TileCached[TILE_4BIT_EVEN]; + } + } + else + { + BG.ConvertTile = BG.ConvertTileFlip = ConvertTile4; + BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_4BIT]; + BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_4BIT]; + } + + BG.TileShift = 5; + BG.PaletteShift = 10 - 4; + BG.PaletteMask = 7 << 4; + BG.DirectColourMode = FALSE; + + break; + + case 2: + if (hires) + { + if (sub || mosaic) + { + BG.ConvertTile = ConvertTile2h_even; + BG.Buffer = IPPU.TileCache[TILE_2BIT_EVEN]; + BG.Buffered = IPPU.TileCached[TILE_2BIT_EVEN]; + BG.ConvertTileFlip = ConvertTile2h_odd; + BG.BufferFlip = IPPU.TileCache[TILE_2BIT_ODD]; + BG.BufferedFlip = IPPU.TileCached[TILE_2BIT_ODD]; + } + else + { + BG.ConvertTile = ConvertTile2h_odd; + BG.Buffer = IPPU.TileCache[TILE_2BIT_ODD]; + BG.Buffered = IPPU.TileCached[TILE_2BIT_ODD]; + BG.ConvertTileFlip = ConvertTile2h_even; + BG.BufferFlip = IPPU.TileCache[TILE_2BIT_EVEN]; + BG.BufferedFlip = IPPU.TileCached[TILE_2BIT_EVEN]; + } + } + else + { + BG.ConvertTile = BG.ConvertTileFlip = ConvertTile2; + BG.Buffer = BG.BufferFlip = IPPU.TileCache[TILE_2BIT]; + BG.Buffered = BG.BufferedFlip = IPPU.TileCached[TILE_2BIT]; + } + + BG.TileShift = 4; + BG.PaletteShift = 10 - 2; + BG.PaletteMask = 7 << 2; + BG.DirectColourMode = FALSE; + + break; + } +} + +/*****************************************************************************/ +#else +#ifndef NAME1 // First-level: Get all the renderers. +/*****************************************************************************/ + +#define GET_CACHED_TILE() \ + uint32 TileNumber; \ + uint32 TileAddr = BG.TileAddress + ((Tile & 0x3ff) << BG.TileShift); \ + if (Tile & 0x100) \ + TileAddr += BG.NameSelect; \ + TileAddr &= 0xffff; \ + TileNumber = TileAddr >> BG.TileShift; \ + if (Tile & H_FLIP) \ + { \ + pCache = &BG.BufferFlip[TileNumber << 6]; \ + if (!BG.BufferedFlip[TileNumber]) \ + BG.BufferedFlip[TileNumber] = BG.ConvertTileFlip(pCache, TileAddr, Tile & 0x3ff); \ + } \ + else \ + { \ + pCache = &BG.Buffer[TileNumber << 6]; \ + if (!BG.Buffered[TileNumber]) \ + BG.Buffered[TileNumber] = BG.ConvertTile(pCache, TileAddr, Tile & 0x3ff); \ + } + +#define IS_BLANK_TILE() \ + (BG.Buffered[TileNumber] == BLANK_TILE) + +#define SELECT_PALETTE() \ + if (BG.DirectColourMode) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps(); \ + GFX.RealScreenColors = DirectColourMaps[(Tile >> 10) & 7]; \ + } \ + else \ + GFX.RealScreenColors = &IPPU.ScreenColors[((Tile >> BG.PaletteShift) & BG.PaletteMask) + BG.StartPalette]; \ + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors + +#define NOMATH(Op, Main, Sub, SD) \ + (Main) + +#define REGMATH(Op, Main, Sub, SD) \ + (COLOR_##Op((Main), ((SD) & 0x20) ? (Sub) : GFX.FixedColour)) + +#define MATHF1_2(Op, Main, Sub, SD) \ + (GFX.ClipColors ? (COLOR_##Op((Main), GFX.FixedColour)) : (COLOR_##Op##1_2((Main), GFX.FixedColour))) + +#define MATHS1_2(Op, Main, Sub, SD) \ + (GFX.ClipColors ? REGMATH(Op, Main, Sub, SD) : (((SD) & 0x20) ? COLOR_##Op##1_2((Main), (Sub)) : COLOR_##Op((Main), GFX.FixedColour))) + +// Basic routine to render an unclipped tile. +// Input parameters: +// BPSTART = either StartLine or (StartLine * 2 + BG.InterlaceLine), +// so interlace modes can render every other line from the tile. +// PITCH = 1 or 2, again so interlace can count lines properly. +// DRAW_PIXEL(N, M) is a routine to actually draw the pixel. N is the pixel in the row to draw, +// and M is a test which if false means the pixel should be skipped. +// Z1 is the "draw if Z1 > cur_depth". +// Z2 is the "cur_depth = new_depth". OBJ need the two separate. +// Pix is the pixel to draw. + +#define Z1 GFX.Z1 +#define Z2 GFX.Z2 + +#define DRAW_TILE() \ + uint8 *pCache; \ + register int32 l; \ + register uint8 *bp, Pix; \ + \ + GET_CACHED_TILE(); \ + if (IS_BLANK_TILE()) \ + return; \ + SELECT_PALETTE(); \ + \ + if (!(Tile & (V_FLIP | H_FLIP))) \ + { \ + bp = pCache + BPSTART; \ + for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ + { \ + DRAW_PIXEL(0, Pix = bp[0]); \ + DRAW_PIXEL(1, Pix = bp[1]); \ + DRAW_PIXEL(2, Pix = bp[2]); \ + DRAW_PIXEL(3, Pix = bp[3]); \ + DRAW_PIXEL(4, Pix = bp[4]); \ + DRAW_PIXEL(5, Pix = bp[5]); \ + DRAW_PIXEL(6, Pix = bp[6]); \ + DRAW_PIXEL(7, Pix = bp[7]); \ + } \ + } \ + else \ + if (!(Tile & V_FLIP)) \ + { \ + bp = pCache + BPSTART; \ + for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ + { \ + DRAW_PIXEL(0, Pix = bp[7]); \ + DRAW_PIXEL(1, Pix = bp[6]); \ + DRAW_PIXEL(2, Pix = bp[5]); \ + DRAW_PIXEL(3, Pix = bp[4]); \ + DRAW_PIXEL(4, Pix = bp[3]); \ + DRAW_PIXEL(5, Pix = bp[2]); \ + DRAW_PIXEL(6, Pix = bp[1]); \ + DRAW_PIXEL(7, Pix = bp[0]); \ + } \ + } \ + else \ + if (!(Tile & H_FLIP)) \ + { \ + bp = pCache + 56 - BPSTART; \ + for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ + { \ + DRAW_PIXEL(0, Pix = bp[0]); \ + DRAW_PIXEL(1, Pix = bp[1]); \ + DRAW_PIXEL(2, Pix = bp[2]); \ + DRAW_PIXEL(3, Pix = bp[3]); \ + DRAW_PIXEL(4, Pix = bp[4]); \ + DRAW_PIXEL(5, Pix = bp[5]); \ + DRAW_PIXEL(6, Pix = bp[6]); \ + DRAW_PIXEL(7, Pix = bp[7]); \ + } \ + } \ + else \ + { \ + bp = pCache + 56 - BPSTART; \ + for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ + { \ + DRAW_PIXEL(0, Pix = bp[7]); \ + DRAW_PIXEL(1, Pix = bp[6]); \ + DRAW_PIXEL(2, Pix = bp[5]); \ + DRAW_PIXEL(3, Pix = bp[4]); \ + DRAW_PIXEL(4, Pix = bp[3]); \ + DRAW_PIXEL(5, Pix = bp[2]); \ + DRAW_PIXEL(6, Pix = bp[1]); \ + DRAW_PIXEL(7, Pix = bp[0]); \ + } \ + } + +#define NAME1 DrawTile16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 LineCount + +// Second-level include: Get the DrawTile16 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef ARGS +#undef DRAW_TILE +#undef Z1 +#undef Z2 + +// Basic routine to render a clipped tile. Inputs same as above. + +#define Z1 GFX.Z1 +#define Z2 GFX.Z2 + +#define DRAW_TILE() \ + uint8 *pCache; \ + register int32 l; \ + register uint8 *bp, Pix, w; \ + \ + GET_CACHED_TILE(); \ + if (IS_BLANK_TILE()) \ + return; \ + SELECT_PALETTE(); \ + \ + if (!(Tile & (V_FLIP | H_FLIP))) \ + { \ + bp = pCache + BPSTART; \ + for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ + { \ + w = Width; \ + switch (StartPixel) \ + { \ + case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; \ + case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; \ + case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; \ + case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; \ + case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; \ + case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; \ + case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; \ + case 7: DRAW_PIXEL(7, Pix = bp[7]); break; \ + } \ + } \ + } \ + else \ + if (!(Tile & V_FLIP)) \ + { \ + bp = pCache + BPSTART; \ + for (l = LineCount; l > 0; l--, bp += 8 * PITCH, Offset += GFX.PPL) \ + { \ + w = Width; \ + switch (StartPixel) \ + { \ + case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; \ + case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; \ + case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; \ + case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; \ + case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; \ + case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; \ + case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; \ + case 7: DRAW_PIXEL(7, Pix = bp[0]); break; \ + } \ + } \ + } \ + else \ + if (!(Tile & H_FLIP)) \ + { \ + bp = pCache + 56 - BPSTART; \ + for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ + { \ + w = Width; \ + switch (StartPixel) \ + { \ + case 0: DRAW_PIXEL(0, Pix = bp[0]); if (!--w) break; \ + case 1: DRAW_PIXEL(1, Pix = bp[1]); if (!--w) break; \ + case 2: DRAW_PIXEL(2, Pix = bp[2]); if (!--w) break; \ + case 3: DRAW_PIXEL(3, Pix = bp[3]); if (!--w) break; \ + case 4: DRAW_PIXEL(4, Pix = bp[4]); if (!--w) break; \ + case 5: DRAW_PIXEL(5, Pix = bp[5]); if (!--w) break; \ + case 6: DRAW_PIXEL(6, Pix = bp[6]); if (!--w) break; \ + case 7: DRAW_PIXEL(7, Pix = bp[7]); break; \ + } \ + } \ + } \ + else \ + { \ + bp = pCache + 56 - BPSTART; \ + for (l = LineCount; l > 0; l--, bp -= 8 * PITCH, Offset += GFX.PPL) \ + { \ + w = Width; \ + switch (StartPixel) \ + { \ + case 0: DRAW_PIXEL(0, Pix = bp[7]); if (!--w) break; \ + case 1: DRAW_PIXEL(1, Pix = bp[6]); if (!--w) break; \ + case 2: DRAW_PIXEL(2, Pix = bp[5]); if (!--w) break; \ + case 3: DRAW_PIXEL(3, Pix = bp[4]); if (!--w) break; \ + case 4: DRAW_PIXEL(4, Pix = bp[3]); if (!--w) break; \ + case 5: DRAW_PIXEL(5, Pix = bp[2]); if (!--w) break; \ + case 6: DRAW_PIXEL(6, Pix = bp[1]); if (!--w) break; \ + case 7: DRAW_PIXEL(7, Pix = bp[0]); break; \ + } \ + } \ + } + +#define NAME1 DrawClippedTile16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartPixel, uint32 Width, uint32 StartLine, uint32 LineCount + +// Second-level include: Get the DrawClippedTile16 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef ARGS +#undef DRAW_TILE +#undef Z1 +#undef Z2 + +// Basic routine to render a single mosaic pixel. +// DRAW_PIXEL, BPSTART, Z1, Z2 and Pix are the same as above, but PITCH is not used. + +#define Z1 GFX.Z1 +#define Z2 GFX.Z2 + +#define DRAW_TILE() \ + uint8 *pCache; \ + register int32 l, w; \ + register uint8 Pix; \ + \ + GET_CACHED_TILE(); \ + if (IS_BLANK_TILE()) \ + return; \ + SELECT_PALETTE(); \ + \ + if (Tile & H_FLIP) \ + StartPixel = 7 - StartPixel; \ + \ + if (Tile & V_FLIP) \ + Pix = pCache[56 - BPSTART + StartPixel]; \ + else \ + Pix = pCache[BPSTART + StartPixel]; \ + \ + if (Pix) \ + { \ + for (l = LineCount; l > 0; l--, Offset += GFX.PPL) \ + { \ + for (w = Width - 1; w >= 0; w--) \ + DRAW_PIXEL(w, 1); \ + } \ + } + +#define NAME1 DrawMosaicPixel16 +#define ARGS uint32 Tile, uint32 Offset, uint32 StartLine, uint32 StartPixel, uint32 Width, uint32 LineCount + +// Second-level include: Get the DrawMosaicPixel16 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef ARGS +#undef DRAW_TILE +#undef Z1 +#undef Z2 + +// Basic routine to render the backdrop. +// DRAW_PIXEL is the same as above, but since we're just replicating a single pixel there's no need for PITCH or BPSTART +// (or interlace at all, really). +// The backdrop is always depth = 1, so Z1 = Z2 = 1. And backdrop is always color 0. + +#define NO_INTERLACE 1 +#define Z1 1 +#define Z2 1 +#define Pix 0 + +#define DRAW_TILE() \ + register uint32 l, x; \ + \ + GFX.RealScreenColors = IPPU.ScreenColors; \ + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ + \ + for (l = GFX.StartY; l <= GFX.EndY; l++, Offset += GFX.PPL) \ + { \ + for (x = Left; x < Right; x++) \ + DRAW_PIXEL(x, 1); \ + } + +#define NAME1 DrawBackdrop16 +#define ARGS uint32 Offset, uint32 Left, uint32 Right + +// Second-level include: Get the DrawBackdrop16 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef ARGS +#undef DRAW_TILE +#undef Pix +#undef Z1 +#undef Z2 +#undef NO_INTERLACE + +// Basic routine to render a chunk of a Mode 7 BG. +// Mode 7 has no interlace, so BPSTART and PITCH are unused. +// We get some new parameters, so we can use the same DRAW_TILE to do BG1 or BG2: +// DCMODE tests if Direct Color should apply. +// BG is the BG, so we use the right clip window. +// MASK is 0xff or 0x7f, the 'color' portion of the pixel. +// We define Z1/Z2 to either be constant 5 or to vary depending on the 'priority' portion of the pixel. + +#define CLIP_10_BIT_SIGNED(a) (((a) & 0x2000) ? ((a) | ~0x3ff) : ((a) & 0x3ff)) + +extern struct SLineMatrixData LineMatrixData[240]; + +#define NO_INTERLACE 1 +#define Z1 (D + 7) +#define Z2 (D + 7) +#define MASK 0xff +#define DCMODE (Memory.FillRAM[0x2130] & 1) +#define BG 0 + +#define DRAW_TILE_NORMAL() \ + uint8 *VRAM1 = Memory.VRAM + 1; \ + \ + if (DCMODE) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps(); \ + GFX.RealScreenColors = DirectColourMaps[0]; \ + } \ + else \ + GFX.RealScreenColors = IPPU.ScreenColors; \ + \ + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ + \ + int aa, cc; \ + int startx; \ + \ + uint32 Offset = GFX.StartY * GFX.PPL; \ + struct SLineMatrixData *l = &LineMatrixData[GFX.StartY]; \ + \ + for (uint32 Line = GFX.StartY; Line <= GFX.EndY; Line++, Offset += GFX.PPL, l++) \ + { \ + int yy, starty; \ + \ + int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; \ + int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; \ + \ + int32 CentreX = ((int32) l->CentreX << 19) >> 19; \ + int32 CentreY = ((int32) l->CentreY << 19) >> 19; \ + \ + if (PPU.Mode7VFlip) \ + starty = 255 - (int) (Line + 1); \ + else \ + starty = Line + 1; \ + \ + yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); \ + \ + int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); \ + int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); \ + \ + if (PPU.Mode7HFlip) \ + { \ + startx = Right - 1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } \ + else \ + { \ + startx = Left; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ + \ + int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); \ + int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); \ + int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); \ + \ + uint8 Pix; \ + \ + if (!PPU.Mode7Repeat) \ + { \ + for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) \ + { \ + int X = ((AA + BB) >> 8) & 0x3ff; \ + int Y = ((CC + DD) >> 8) & 0x3ff; \ + \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + \ + DRAW_PIXEL(x, Pix = (b & MASK)); \ + } \ + } \ + else \ + { \ + for (uint32 x = Left; x < Right; x++, AA += aa, CC += cc) \ + { \ + int X = ((AA + BB) >> 8); \ + int Y = ((CC + DD) >> 8); \ + \ + uint8 b; \ + \ + if (((X | Y) & ~0x3ff) == 0) \ + { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + } \ + else \ + if (PPU.Mode7Repeat == 3) \ + b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + else \ + continue; \ + \ + DRAW_PIXEL(x, Pix = (b & MASK)); \ + } \ + } \ + } + +#define DRAW_TILE_MOSAIC() \ + uint8 *VRAM1 = Memory.VRAM + 1; \ + \ + if (DCMODE) \ + { \ + if (IPPU.DirectColourMapsNeedRebuild) \ + S9xBuildDirectColourMaps(); \ + GFX.RealScreenColors = DirectColourMaps[0]; \ + } \ + else \ + GFX.RealScreenColors = IPPU.ScreenColors; \ + \ + GFX.ScreenColors = GFX.ClipColors ? BlackColourMap : GFX.RealScreenColors; \ + \ + int aa, cc; \ + int startx, StartY = GFX.StartY; \ + \ + int HMosaic = 1, VMosaic = 1, MosaicStart = 0; \ + int32 MLeft = Left, MRight = Right; \ + \ + if (PPU.BGMosaic[0]) \ + { \ + VMosaic = PPU.Mosaic; \ + MosaicStart = ((uint32) GFX.StartY - PPU.MosaicStart) % VMosaic; \ + StartY -= MosaicStart; \ + } \ + \ + if (PPU.BGMosaic[BG]) \ + { \ + HMosaic = PPU.Mosaic; \ + MLeft -= MLeft % HMosaic; \ + MRight += HMosaic - 1; \ + MRight -= MRight % HMosaic; \ + } \ + \ + uint32 Offset = StartY * GFX.PPL; \ + struct SLineMatrixData *l = &LineMatrixData[StartY]; \ + \ + for (uint32 Line = StartY; Line <= GFX.EndY; Line += VMosaic, Offset += VMosaic * GFX.PPL, l += VMosaic) \ + { \ + if (Line + VMosaic > GFX.EndY) \ + VMosaic = GFX.EndY - Line + 1; \ + \ + int yy, starty; \ + \ + int32 HOffset = ((int32) l->M7HOFS << 19) >> 19; \ + int32 VOffset = ((int32) l->M7VOFS << 19) >> 19; \ + \ + int32 CentreX = ((int32) l->CentreX << 19) >> 19; \ + int32 CentreY = ((int32) l->CentreY << 19) >> 19; \ + \ + if (PPU.Mode7VFlip) \ + starty = 255 - (int) (Line + 1); \ + else \ + starty = Line + 1; \ + \ + yy = CLIP_10_BIT_SIGNED(VOffset - CentreY); \ + \ + int BB = ((l->MatrixB * starty) & ~63) + ((l->MatrixB * yy) & ~63) + (CentreX << 8); \ + int DD = ((l->MatrixD * starty) & ~63) + ((l->MatrixD * yy) & ~63) + (CentreY << 8); \ + \ + if (PPU.Mode7HFlip) \ + { \ + startx = MRight - 1; \ + aa = -l->MatrixA; \ + cc = -l->MatrixC; \ + } \ + else \ + { \ + startx = MLeft; \ + aa = l->MatrixA; \ + cc = l->MatrixC; \ + } \ + \ + int xx = CLIP_10_BIT_SIGNED(HOffset - CentreX); \ + int AA = l->MatrixA * startx + ((l->MatrixA * xx) & ~63); \ + int CC = l->MatrixC * startx + ((l->MatrixC * xx) & ~63); \ + \ + uint8 Pix; \ + uint8 ctr = 1; \ + \ + if (!PPU.Mode7Repeat) \ + { \ + for (int32 x = MLeft; x < MRight; x++, AA += aa, CC += cc) \ + { \ + if (--ctr) \ + continue; \ + ctr = HMosaic; \ + \ + int X = ((AA + BB) >> 8) & 0x3ff; \ + int Y = ((CC + DD) >> 8) & 0x3ff; \ + \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + uint8 b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + \ + if ((Pix = (b & MASK))) \ + { \ + for (int32 h = MosaicStart; h < VMosaic; h++) \ + { \ + for (int32 w = x + HMosaic - 1; w >= x; w--) \ + DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); \ + } \ + } \ + } \ + } \ + else \ + { \ + for (int32 x = MLeft; x < MRight; x++, AA += aa, CC += cc) \ + { \ + if (--ctr) \ + continue; \ + ctr = HMosaic; \ + \ + int X = ((AA + BB) >> 8); \ + int Y = ((CC + DD) >> 8); \ + \ + uint8 b; \ + \ + if (((X | Y) & ~0x3ff) == 0) \ + { \ + uint8 *TileData = VRAM1 + (Memory.VRAM[((Y & ~7) << 5) + ((X >> 2) & ~1)] << 7); \ + b = *(TileData + ((Y & 7) << 4) + ((X & 7) << 1)); \ + } \ + else \ + if (PPU.Mode7Repeat == 3) \ + b = *(VRAM1 + ((Y & 7) << 4) + ((X & 7) << 1)); \ + else \ + continue; \ + \ + if ((Pix = (b & MASK))) \ + { \ + for (int32 h = MosaicStart; h < VMosaic; h++) \ + { \ + for (int32 w = x + HMosaic - 1; w >= x; w--) \ + DRAW_PIXEL(w + h * GFX.PPL, (w >= (int32) Left && w < (int32) Right)); \ + } \ + } \ + } \ + } \ + \ + MosaicStart = 0; \ + } + +#define DRAW_TILE() DRAW_TILE_NORMAL() +#define NAME1 DrawMode7BG1 +#define ARGS uint32 Left, uint32 Right, int D + +// Second-level include: Get the DrawMode7BG1 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef DRAW_TILE + +#define DRAW_TILE() DRAW_TILE_MOSAIC() +#define NAME1 DrawMode7MosaicBG1 + +// Second-level include: Get the DrawMode7MosaicBG1 renderers. + +#include "tile.cpp" + +#undef DRAW_TILE +#undef NAME1 +#undef Z1 +#undef Z2 +#undef MASK +#undef DCMODE +#undef BG + +#define NAME1 DrawMode7BG2 +#define DRAW_TILE() DRAW_TILE_NORMAL() +#define Z1 (D + ((b & 0x80) ? 11 : 3)) +#define Z2 (D + ((b & 0x80) ? 11 : 3)) +#define MASK 0x7f +#define DCMODE 0 +#define BG 1 + +// Second-level include: Get the DrawMode7BG2 renderers. + +#include "tile.cpp" + +#undef NAME1 +#undef DRAW_TILE + +#define DRAW_TILE() DRAW_TILE_MOSAIC() +#define NAME1 DrawMode7MosaicBG2 + +// Second-level include: Get the DrawMode7MosaicBG2 renderers. + +#include "tile.cpp" + +#undef MASK +#undef DCMODE +#undef BG +#undef NAME1 +#undef ARGS +#undef DRAW_TILE +#undef DRAW_TILE_NORMAL +#undef DRAW_TILE_MOSAIC +#undef Z1 +#undef Z2 +#undef NO_INTERLACE + +/*****************************************************************************/ +#else +#ifndef NAME2 // Second-level: Get all the NAME1 renderers. +/*****************************************************************************/ + +#define BPSTART StartLine +#define PITCH 1 + +// The 1x1 pixel plotter, for speedhacking modes. + +#define DRAW_PIXEL(N, M) \ + if (Z1 > GFX.DB[Offset + N] && (M)) \ + { \ + GFX.S[Offset + N] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + N], GFX.SubZBuffer[Offset + N]); \ + GFX.DB[Offset + N] = Z2; \ + } + +#define NAME2 Normal1x1 + +// Third-level include: Get the Normal1x1 renderers. + +#include "tile.cpp" + +#undef NAME2 +#undef DRAW_PIXEL + +// The 2x1 pixel plotter, for normal rendering when we've used hires/interlace already this frame. + +#define DRAW_PIXEL_N2x1(N, M) \ + if (Z1 > GFX.DB[Offset + 2 * N] && (M)) \ + { \ + GFX.S[Offset + 2 * N] = GFX.S[Offset + 2 * N + 1] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); \ + GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; \ + } + +#define DRAW_PIXEL(N, M) DRAW_PIXEL_N2x1(N, M) +#define NAME2 Normal2x1 + +// Third-level include: Get the Normal2x1 renderers. + +#include "tile.cpp" + +#undef NAME2 +#undef DRAW_PIXEL + +// Hires pixel plotter, this combines the main and subscreen pixels as appropriate to render hires or pseudo-hires images. +// Use it only on the main screen, subscreen should use Normal2x1 instead. +// Hires math: +// Main pixel is mathed as normal: Main(x, y) * Sub(x, y). +// Sub pixel is mathed somewhat weird: Basically, for Sub(x + 1, y) we apply the same operation we applied to Main(x, y) +// (e.g. no math, add fixed, add1/2 subscreen) using Main(x, y) as the "corresponding subscreen pixel". +// Also, color window clipping clips Sub(x + 1, y) if Main(x, y) is clipped, not Main(x + 1, y). +// We don't know how Sub(0, y) is handled. + +#define DRAW_PIXEL_H2x1(N, M) \ + if (Z1 > GFX.DB[Offset + 2 * N] && (M)) \ + { \ + GFX.S[Offset + 2 * N] = MATH(GFX.ScreenColors[Pix], GFX.SubScreen[Offset + 2 * N], GFX.SubZBuffer[Offset + 2 * N]); \ + GFX.S[Offset + 2 * N + 1] = MATH((GFX.ClipColors ? 0 : GFX.SubScreen[Offset + 2 * N + 2]), GFX.RealScreenColors[Pix], GFX.SubZBuffer[Offset + 2 * N]); \ + GFX.DB[Offset + 2 * N] = GFX.DB[Offset + 2 * N + 1] = Z2; \ + } + +#define DRAW_PIXEL(N, M) DRAW_PIXEL_H2x1(N, M) +#define NAME2 Hires + +// Third-level include: Get the Hires renderers. + +#include "tile.cpp" + +#undef NAME2 +#undef DRAW_PIXEL + +// Interlace: Only draw every other line, so we'll redefine BPSTART and PITCH to do so. +// Otherwise, it's the same as Normal2x1/Hires2x1. + +#undef BPSTART +#undef PITCH + +#define BPSTART (StartLine * 2 + BG.InterlaceLine) +#define PITCH 2 + +#ifndef NO_INTERLACE + +#define DRAW_PIXEL(N, M) DRAW_PIXEL_N2x1(N, M) +#define NAME2 Interlace + +// Third-level include: Get the Interlace renderers. + +#include "tile.cpp" + +#undef NAME2 +#undef DRAW_PIXEL + +#define DRAW_PIXEL(N, M) DRAW_PIXEL_H2x1(N, M) +#define NAME2 HiresInterlace + +// Third-level include: Get the HiresInterlace renderers. + +#include "tile.cpp" + +#undef NAME2 +#undef DRAW_PIXEL + +#endif + +#undef BPSTART +#undef PITCH + +/*****************************************************************************/ +#else // Third-level: Renderers for each math mode for NAME1 + NAME2. +/*****************************************************************************/ + +#define CONCAT3(A, B, C) A##B##C +#define MAKENAME(A, B, C) CONCAT3(A, B, C) + +static void MAKENAME(NAME1, _, NAME2) (ARGS) +{ +#define MATH(A, B, C) NOMATH(x, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, Add_, NAME2) (ARGS) +{ +#define MATH(A, B, C) REGMATH(ADD, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, AddF1_2_, NAME2) (ARGS) +{ +#define MATH(A, B, C) MATHF1_2(ADD, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, AddS1_2_, NAME2) (ARGS) +{ +#define MATH(A, B, C) MATHS1_2(ADD, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, Sub_, NAME2) (ARGS) +{ +#define MATH(A, B, C) REGMATH(SUB, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, SubF1_2_, NAME2) (ARGS) +{ +#define MATH(A, B, C) MATHF1_2(SUB, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void MAKENAME(NAME1, SubS1_2_, NAME2) (ARGS) +{ +#define MATH(A, B, C) MATHS1_2(SUB, A, B, C) + DRAW_TILE(); +#undef MATH +} + +static void (*MAKENAME(Renderers_, NAME1, NAME2)[7]) (ARGS) = +{ + MAKENAME(NAME1, _, NAME2), + MAKENAME(NAME1, Add_, NAME2), + MAKENAME(NAME1, AddF1_2_, NAME2), + MAKENAME(NAME1, AddS1_2_, NAME2), + MAKENAME(NAME1, Sub_, NAME2), + MAKENAME(NAME1, SubF1_2_, NAME2), + MAKENAME(NAME1, SubS1_2_, NAME2) +}; + +#undef MAKENAME +#undef CONCAT3 + +#endif +#endif +#endif diff --git a/tile.h b/tile.h new file mode 100644 index 00000000..d4bd94f9 --- /dev/null +++ b/tile.h @@ -0,0 +1,185 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 _TILE_H_ +#define _TILE_H_ + +void S9xInitTileRenderer (void); +void S9xSelectTileRenderers (int, bool8, bool8); +void S9xSelectTileConverter (int, bool8, bool8, bool8); + +#endif diff --git a/unix/Makefile.in b/unix/Makefile.in new file mode 100644 index 00000000..29ce24fd --- /dev/null +++ b/unix/Makefile.in @@ -0,0 +1,118 @@ +@S9XZSNESFX@ +@S9XZSNESC4@ +@S9XDEBUGGER@ +@S9XNETPLAY@ +@S9XZIP@ +@S9XJMA@ + +# Fairly good and special-char-safe descriptor of the os being built on. +OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"` +BUILDDIR = . + +OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../reader.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o +DEFS = -DMITSHM -DCPU_SHUTDOWN -DSPC700_SHUTDOWN -DCORRECT_VRAM_READS + +ifdef S9XZSNESFX +OBJECTS += ../i386/fxemu2.o ../i386/fxemu2b.o ../i386/fxemu2c.o ../i386/fxtable.o ../i386/sfxproc.o ../i386/zsnes.o +else +OBJECTS += ../fxinst.o ../fxemu.o +ifdef S9XDEBUGGER +OBJECTS += ../fxdbg.o +endif +endif + +ifdef S9XZSNESC4 +OBJECTS += ../i386/c4.o ../i386/zsnesc4.o ../c4.o +else +OBJECTS += ../c4.o ../c4emu.o +endif + +ifdef S9XDEBUGGER +OBJECTS += ../debug.o +endif + +ifdef S9XNETPLAY +OBJECTS += ../netplay.o ../server.o +endif + +ifdef S9XZIP +OBJECTS += ../loadzip.o ../unzip/ioapi.o ../unzip/unzip.o +endif + +ifdef S9XJMA +OBJECTS += ../jma/7zlzma.o ../jma/crc32.o ../jma/iiostrm.o ../jma/inbyte.o ../jma/jma.o ../jma/lzma.o ../jma/lzmadec.o ../jma/s9x-jma.o ../jma/winout.o +endif + +CCC = @CXX@ +CC = @CC@ +NASM = @S9XNASM@ +GASM = @CXX@ +INCLUDES = -I. -I.. -I../apu/ -I../unzip/ -I../jma/ -I../filter/ + +CCFLAGS = @S9XFLGS@ @S9XDEFS@ $(DEFS) +CFLAGS = $(CCFLAGS) + +.SUFFIXES: .o .cpp .c .cc .h .m .i .s .asm .obj + +all: Makefile configure snes9x + +Makefile: configure Makefile.in + @echo "Makefile is older than configure or in-file. Run configure or touch Makefile." + exit 1 + +configure: configure.ac + @echo "configure is older than in-file. Run autoconf or touch configure." + exit 1 + +snes9x: $(OBJECTS) + $(CCC) $(INCLUDES) -o $@ $(OBJECTS) -lm @S9XLIBS@ + +../jma/s9x-jma.o: ../jma/s9x-jma.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +../jma/7zlzma.o: ../jma/7zlzma.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +../jma/crc32.o: ../jma/crc32.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +../jma/iiostrm.o: ../jma/iiostrm.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +../jma/inbyte.o: ../jma/inbyte.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +../jma/jma.o: ../jma/jma.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +../jma/lzma.o: ../jma/lzma.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +../jma/lzmadec.o: ../jma/lzmadec.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ +../jma/winout.o: ../jma/winout.cpp + $(CCC) $(INCLUDES) -c $(CCFLAGS) -fexceptions $*.cpp -o $@ + +.cpp.o: + $(CCC) $(INCLUDES) -c $(CCFLAGS) $*.cpp -o $@ + +.c.o: + $(CC) $(INCLUDES) -c $(CCFLAGS) $*.c -o $@ + +.cpp.S: + $(GASM) $(INCLUDES) -S $(CCFLAGS) $*.cpp -o $@ + +.cpp.i: + $(GASM) $(INCLUDES) -E $(CCFLAGS) $*.cpp -o $@ + +.S.o: + $(GASM) $(INCLUDES) -c $(CCFLAGS) $*.S -o $@ + +.S.i: + $(GASM) $(INCLUDES) -c -E $(CCFLAGS) $*.S -o $@ + +.s.o: + @echo Compiling $*.s + sh-elf-as -little $*.s -o $@ + +.asm.o: + $(NASM) -f elf -DELF @S9XDEFS@ -i../i386/ -o $@ $*.asm + +.obj.o: + cp $*.obj $*.o + +clean: + rm -f $(OBJECTS) diff --git a/unix/config.guess b/unix/config.guess new file mode 100644 index 00000000..e5716eea --- /dev/null +++ b/unix/config.guess @@ -0,0 +1,1555 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2009-02-03' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:[3456]*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + EM64T | authenticamd | genuineintel) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^CPU/{ + s: ::g + p + }'`" + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' + /^LIBC/{ + s: ::g + p + }'`" + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/unix/config.sub b/unix/config.sub new file mode 100644 index 00000000..d546a94b --- /dev/null +++ b/unix/config.sub @@ -0,0 +1,1685 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +# Free Software Foundation, Inc. + +timestamp='2009-02-03' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/unix/configure b/unix/configure new file mode 100644 index 00000000..22cf14c9 --- /dev/null +++ b/unix/configure @@ -0,0 +1,9460 @@ +#! /bin/sh +# From configure.ac Revision: 1.52 . +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.61 for Snes9x 1.52. +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + +if test "x$CONFIG_SHELL" = x; then + if (eval ":") 2>/dev/null; then + as_have_required=yes +else + as_have_required=no +fi + + if test $as_have_required = yes && (eval ": +(as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=\$LINENO + as_lineno_2=\$LINENO + test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && + test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } +") 2> /dev/null; then + : +else + as_candidate_shells= + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + case $as_dir in + /*) + for as_base in sh bash ksh sh5; do + as_candidate_shells="$as_candidate_shells $as_dir/$as_base" + done;; + esac +done +IFS=$as_save_IFS + + + for as_shell in $as_candidate_shells $SHELL; do + # Try only shells that exist, to save several forks. + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { ("$as_shell") 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +_ASEOF +}; then + CONFIG_SHELL=$as_shell + as_have_required=yes + if { "$as_shell" 2> /dev/null <<\_ASEOF +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + +: +(as_func_return () { + (exit $1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = "$1" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test $exitcode = 0) || { (exit 1); exit 1; } + +( + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } + +_ASEOF +}; then + break +fi + +fi + + done + + if test "x$CONFIG_SHELL" != x; then + for as_var in BASH_ENV ENV + do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + done + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + + if test $as_have_required = no; then + echo This script requires a shell more modern than all the + echo shells that I found on your system. Please install a + echo modern shell, or manually run the script under such a + echo shell if you do have one. + { (exit 1); exit 1; } +fi + + +fi + +fi + + + +(eval "as_func_return () { + (exit \$1) +} +as_func_success () { + as_func_return 0 +} +as_func_failure () { + as_func_return 1 +} +as_func_ret_success () { + return 0 +} +as_func_ret_failure () { + return 1 +} + +exitcode=0 +if as_func_success; then + : +else + exitcode=1 + echo as_func_success failed. +fi + +if as_func_failure; then + exitcode=1 + echo as_func_failure succeeded. +fi + +if as_func_ret_success; then + : +else + exitcode=1 + echo as_func_ret_success failed. +fi + +if as_func_ret_failure; then + exitcode=1 + echo as_func_ret_failure succeeded. +fi + +if ( set x; as_func_ret_success y && test x = \"\$1\" ); then + : +else + exitcode=1 + echo positional parameters were not saved. +fi + +test \$exitcode = 0") || { + echo No shell found that supports shell functions. + echo Please tell autoconf@gnu.org about your system, + echo including any error possibly output before this + echo message +} + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + +exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Identity of this package. +PACKAGE_NAME='Snes9x' +PACKAGE_TARNAME='snes9x' +PACKAGE_VERSION='1.52' +PACKAGE_STRING='Snes9x 1.52' +PACKAGE_BUGREPORT='' + +ac_unique_file="unix.cpp" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='SHELL +PATH_SEPARATOR +PACKAGE_NAME +PACKAGE_TARNAME +PACKAGE_VERSION +PACKAGE_STRING +PACKAGE_BUGREPORT +exec_prefix +prefix +program_transform_name +bindir +sbindir +libexecdir +datarootdir +datadir +sysconfdir +sharedstatedir +localstatedir +includedir +oldincludedir +docdir +infodir +htmldir +dvidir +pdfdir +psdir +libdir +localedir +mandir +DEFS +ECHO_C +ECHO_N +ECHO_T +LIBS +build_alias +host_alias +target_alias +build +build_cpu +build_vendor +build_os +host +host_cpu +host_vendor +host_os +target +target_cpu +target_vendor +target_os +CC +CFLAGS +LDFLAGS +CPPFLAGS +ac_ct_CC +EXEEXT +OBJEXT +CXX +CXXFLAGS +ac_ct_CXX +S9XNASM +CXXCPP +GREP +EGREP +XMKMF +X_CFLAGS +X_PRE_LIBS +X_LIBS +X_EXTRA_LIBS +S9XFLGS +S9XDEFS +S9XLIBS +S9XZSNESFX +S9XZSNESC4 +S9XDEBUGGER +S9XNETPLAY +S9XZIP +S9XJMA +LIBOBJS +LTLIBOBJS' +ac_subst_files='' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CXX +CXXFLAGS +CCC +CXXCPP +XMKMF' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` + eval enable_$ac_feature=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=\$ac_optarg ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/[-.]/_/g'` + eval with_$ac_package=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute directory names. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; } +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + { echo "$as_me: error: Working directory cannot be determined" >&2 + { (exit 1); exit 1; }; } +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + { echo "$as_me: error: pwd does not report name of working directory" >&2 + { (exit 1); exit 1; }; } + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$0" || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 + { (exit 1); exit 1; }; } + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures Snes9x 1.52 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/snes9x] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +X features: + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of Snes9x 1.52:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-debug leave debug information in the final binary + (default: no) + --enable-mtune use the specified value for the -mtune/-mcpu flag + (default: no) + --enable-zsnes-asm build with ZSNES C4 and SuperFX assembler cores if + available (default: no) + --enable-gamepad enable gamepad support if available (default: yes) + --enable-debugger enable debugger (default: no) + --enable-netplay enable netplay support (default: no) + --enable-gzip enable GZIP support through zlib (default: yes) + --enable-zip enable ZIP support through zlib (default: yes) + --enable-jma enable JMA support (default: yes) + --enable-screenshot enable screenshot support through libpng (default: + yes) + --enable-sound enable sound if available (default: yes) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-x use the X Window System + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + XMKMF Path to xmkmf, Makefile generator for X Window System + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +Snes9x configure 1.52 +generated by GNU Autoconf 2.61 + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by Snes9x $as_me 1.52, which was +generated by GNU Autoconf 2.61. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args '$ac_arg'" + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + set x "$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + set x "$prefix/share/config.site" "$prefix/etc/config.site" +else + set x "$ac_default_prefix/share/config.site" \ + "$ac_default_prefix/etc/config.site" +fi +shift +for ac_site_file +do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + + + + + + + + + + + + + + + + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 +echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} + { (exit 1); exit 1; }; } +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 +echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} + { (exit 1); exit 1; }; } + +{ echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6; } +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 +echo "$as_me: error: invalid value of canonical build" >&2;} + { (exit 1); exit 1; }; };; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6; } +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 +echo "$as_me: error: invalid value of canonical host" >&2;} + { (exit 1); exit 1; }; };; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ echo "$as_me:$LINENO: checking target system type" >&5 +echo $ECHO_N "checking target system type... $ECHO_C" >&6; } +if test "${ac_cv_target+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5 +echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;} + { (exit 1); exit 1; }; } +fi + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_target" >&5 +echo "${ECHO_T}$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) { { echo "$as_me:$LINENO: error: invalid value of canonical target" >&5 +echo "$as_me: error: invalid value of canonical target" >&2;} + { (exit 1); exit 1; }; };; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 +echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; } +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +# +# List of possible output files, starting from the most likely. +# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) +# only as a last resort. b.out is created by i960 compilers. +ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' +# +# The IRIX 6 linker writes into existing files which may not be +# executable, retaining their permissions. Remove them first so a +# subsequent execution test works. +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { (ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi + +{ echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6; } +if test -z "$ac_file"; then + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; } +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +{ echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6; } + +{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; } +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 +echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cc_c89=$ac_arg +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6; } ;; + xno) + { echo "$as_me:$LINENO: result: unsupported" >&5 +echo "${ECHO_T}unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;; +esac + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&5 +echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools +whose name does not start with the host triplet. If you think this +configuration is useful to you, please write to autoconf@gnu.org." >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +echo "$as_me:$LINENO: checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (ac_try="$ac_compiler --version >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler --version >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -v >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -v >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (ac_try="$ac_compiler -V >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compiler -V >&5") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_compiler_gnu=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + CXXFLAGS="" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +S9XFLGS="" +S9XDEFS="" +S9XLIBS="" + + + +# ***************************** +# *** Execution begins here *** +# ***************************** + +# Remove -g and -O2 flags manually. + +if test "x$CFLAGS" != "x"; then + CFLAGS="`echo \"$CFLAGS\" | sed -e 's/-g//'`" + CFLAGS="`echo \"$CFLAGS\" | sed -e 's/-O2//'`" +fi + +if test "x$CXXFLAGS" != "x"; then + CXXFLAGS="`echo \"$CXXFLAGS\" | sed -e 's/-g//'`" + CXXFLAGS="`echo \"$CXXFLAGS\" | sed -e 's/-O2//'`" +fi + +# Test what compiler flags we should use. + +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then + enableval=$enable_debug; +else + enable_debug="no" +fi + + +if test "x$enable_debug" = "xyes"; then + + + { echo "$as_me:$LINENO: checking whether g++ accepts -g" >&5 +echo $ECHO_N "checking whether g++ accepts -g... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -g" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_g="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_g="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_g" = "xyes"; then + S9XFLGS="$S9XFLGS -g" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + fi + + + { echo "$as_me:$LINENO: checking whether g++ accepts -O0" >&5 +echo $ECHO_N "checking whether g++ accepts -O0... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_o0+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -O0" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_o0="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_o0="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_o0" = "xyes"; then + S9XFLGS="$S9XFLGS -O0" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + fi + +else + + { echo "$as_me:$LINENO: checking whether g++ accepts -O3" >&5 +echo $ECHO_N "checking whether g++ accepts -O3... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_o3+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -O3" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_o3="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_o3="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_o3" = "xyes"; then + S9XFLGS="$S9XFLGS -O3" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + + { echo "$as_me:$LINENO: checking whether g++ accepts -O2" >&5 +echo $ECHO_N "checking whether g++ accepts -O2... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_o2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -O2" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_o2="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_o2="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_o2" = "xyes"; then + S9XFLGS="$S9XFLGS -O2" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + + { echo "$as_me:$LINENO: checking whether g++ accepts -O1" >&5 +echo $ECHO_N "checking whether g++ accepts -O1... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_o1+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -O1" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_o1="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_o1="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_o1" = "xyes"; then + S9XFLGS="$S9XFLGS -O1" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + fi + + fi + + fi + + + { echo "$as_me:$LINENO: checking whether g++ accepts -fomit-frame-pointer" >&5 +echo $ECHO_N "checking whether g++ accepts -fomit-frame-pointer... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_omit_frame_pointer+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -fomit-frame-pointer" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_omit_frame_pointer="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_omit_frame_pointer="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_omit_frame_pointer" = "xyes"; then + S9XFLGS="$S9XFLGS -fomit-frame-pointer" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + fi + +fi + +# Check whether --enable-mtune was given. +if test "${enable_mtune+set}" = set; then + enableval=$enable_mtune; +else + enable_mtune="no" +fi + + +if test "x$enable_mtune" != "xno"; then + + { echo "$as_me:$LINENO: checking whether g++ accepts -mtune=\"$enable_mtune\"" >&5 +echo $ECHO_N "checking whether g++ accepts -mtune=\"$enable_mtune\"... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_mtune+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -mtune="$enable_mtune"" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_mtune="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_mtune="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_mtune" = "xyes"; then + S9XFLGS="$S9XFLGS -mtune="$enable_mtune"" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + { echo "$as_me:$LINENO: WARNING: -mtune failed, trying -mcpu..." >&5 +echo "$as_me: WARNING: -mtune failed, trying -mcpu..." >&2;} + + { echo "$as_me:$LINENO: checking whether g++ accepts -mcpu=\"$enable_mtune\"" >&5 +echo $ECHO_N "checking whether g++ accepts -mcpu=\"$enable_mtune\"... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_mcpu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -mcpu="$enable_mtune"" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_mcpu="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_mcpu="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_mcpu" = "xyes"; then + S9XFLGS="$S9XFLGS -mcpu="$enable_mtune"" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { { echo "$as_me:$LINENO: error: Please specify a working value for --enable-mtune." >&5 +echo "$as_me: error: Please specify a working value for --enable-mtune." >&2;} + { (exit 1); exit 1; }; } + fi + + + fi + +fi + + + { echo "$as_me:$LINENO: checking whether g++ accepts -fno-exceptions" >&5 +echo $ECHO_N "checking whether g++ accepts -fno-exceptions... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_no_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -fno-exceptions" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_no_exceptions="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_no_exceptions="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_no_exceptions" = "xyes"; then + S9XFLGS="$S9XFLGS -fno-exceptions" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + fi + + + { echo "$as_me:$LINENO: checking whether g++ accepts -fno-rtti" >&5 +echo $ECHO_N "checking whether g++ accepts -fno-rtti... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_no_rtti+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -fno-rtti" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_no_rtti="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_no_rtti="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_no_rtti" = "xyes"; then + S9XFLGS="$S9XFLGS -fno-rtti" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + fi + + + { echo "$as_me:$LINENO: checking whether g++ accepts -pedantic" >&5 +echo $ECHO_N "checking whether g++ accepts -pedantic... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_pedantic+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -pedantic" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_pedantic="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_pedantic="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_pedantic" = "xyes"; then + S9XFLGS="$S9XFLGS -pedantic" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + fi + + + { echo "$as_me:$LINENO: checking whether g++ accepts -Wall" >&5 +echo $ECHO_N "checking whether g++ accepts -Wall... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_Wall+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -Wall" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_Wall="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_Wall="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_Wall" = "xyes"; then + S9XFLGS="$S9XFLGS -Wall" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + fi + + + { echo "$as_me:$LINENO: checking whether g++ accepts -W" >&5 +echo $ECHO_N "checking whether g++ accepts -W... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_W+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -W" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_W="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_W="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_W" = "xyes"; then + S9XFLGS="$S9XFLGS -W" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + fi + + + { echo "$as_me:$LINENO: checking whether g++ accepts -Wno-unused-parameter" >&5 +echo $ECHO_N "checking whether g++ accepts -Wno-unused-parameter... $ECHO_C" >&6; } + + if test "${snes9x_cv_option_Wno_unused_parameter+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS -Wno-unused-parameter" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_cv_option_Wno_unused_parameter="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_cv_option_Wno_unused_parameter="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + +fi + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_cv_option_Wno_unused_parameter" = "xyes"; then + S9XFLGS="$S9XFLGS -Wno-unused-parameter" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + + fi + + +# Check if the CPU is x86. + +{ echo "$as_me:$LINENO: checking whether the CPU is x86" >&5 +echo $ECHO_N "checking whether the CPU is x86... $ECHO_C" >&6; } + +if test "${snes9x_cv_x86_cpu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + case "$target" in + i686-*-* | i586-*-* | i486-*-* | i386-*-*) + snes9x_cv_x86_cpu="yes" + ;; + *) + snes9x_cv_x86_cpu="no" + ;; + esac + +fi + + +{ echo "$as_me:$LINENO: result: $snes9x_cv_x86_cpu" >&5 +echo "${ECHO_T}$snes9x_cv_x86_cpu" >&6; } + +# Enable ZSNES C4 and SuperFX assembler cores if CPU is x86. + +S9XZSNESFX="#S9XZSNESFX=1" +S9XZSNESC4="#S9XZSNESC4=1" +S9XNASM="" + +# Check whether --enable-zsnes_asm was given. +if test "${enable_zsnes_asm+set}" = set; then + enableval=$enable_zsnes_asm; +else + enable_zsnes_asm="no" +fi + + +if test "x$enable_zsnes_asm" = "xyes"; then + if test "x$snes9x_cv_x86_cpu" = "xyes"; then + # Extract the first word of "nasm", so it can be a program name with args. +set dummy nasm; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_S9XNASM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $S9XNASM in + [\\/]* | ?:[\\/]*) + ac_cv_path_S9XNASM="$S9XNASM" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_S9XNASM="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + test -z "$ac_cv_path_S9XNASM" && ac_cv_path_S9XNASM="no" + ;; +esac +fi +S9XNASM=$ac_cv_path_S9XNASM +if test -n "$S9XNASM"; then + { echo "$as_me:$LINENO: result: $S9XNASM" >&5 +echo "${ECHO_T}$S9XNASM" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + if test "x$S9XNASM" != "xno"; then + S9XZSNESFX="S9XZSNESFX=1" + S9XZSNESC4="S9XZSNESC4=1" + S9XDEFS="$S9XDEFS -DZSNES_FX -DZSNES_C4" + else + { echo "$as_me:$LINENO: WARNING: nasm not found. Build without ZSNES assembler cores." >&5 +echo "$as_me: WARNING: nasm not found. Build without ZSNES assembler cores." >&2;} + enable_zsnes_asm="no" + fi + else + { echo "$as_me:$LINENO: WARNING: Your CPU is not x86. Build without ZSNES assembler cores." >&5 +echo "$as_me: WARNING: Your CPU is not x86. Build without ZSNES assembler cores." >&2;} + enable_zsnes_asm="no" + fi +fi + +# Check if the OS is Linux. + +{ echo "$as_me:$LINENO: checking whether the OS is Linux" >&5 +echo $ECHO_N "checking whether the OS is Linux... $ECHO_C" >&6; } + +if test "${snes9x_cv_linux_os+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + case "$target" in + *-*-linux*) + snes9x_cv_linux_os="yes" + ;; + *) + snes9x_cv_linux_os="no" + ;; + esac + +fi + + +{ echo "$as_me:$LINENO: result: $snes9x_cv_linux_os" >&5 +echo "${ECHO_T}$snes9x_cv_linux_os" >&6; } + +# Enable gamepad support on Linux. + +# Check whether --enable-gamepad was given. +if test "${enable_gamepad+set}" = set; then + enableval=$enable_gamepad; +else + enable_gamepad="yes" +fi + + +if test "x$enable_gamepad" = "xyes"; then + if test "x$snes9x_cv_linux_os" = "xyes"; then + S9XDEFS="$S9XDEFS -DJOYSTICK_SUPPORT" + else + { echo "$as_me:$LINENO: WARNING: Your OS is not Linux. Build without gamepad support." >&5 +echo "$as_me: WARNING: Your OS is not Linux. Build without gamepad support." >&2;} + enable_gamepad="no" + fi +fi + +# Enable debugger. + +S9XDEBUGGER="#S9XDEBUGGER=1" + +# Check whether --enable-debugger was given. +if test "${enable_debugger+set}" = set; then + enableval=$enable_debugger; +else + enable_debugger="no" +fi + + +if test "x$enable_debugger" = "xyes"; then + S9XDEBUGGER="S9XDEBUGGER=1" + S9XDEFS="$S9XDEFS -DDEBUGGER" +fi + +# Enable netplay support if requested. + +S9XNETPLAY="#S9XNETPLAY=1" + +# Check whether --enable-netplay was given. +if test "${enable_netplay+set}" = set; then + enableval=$enable_netplay; +else + enable_netplay="no" +fi + + +if test "x$enable_netplay" = "xyes"; then + S9XNETPLAY="S9XNETPLAY=1" + S9XDEFS="$S9XDEFS -DNETPLAY_SUPPORT" +fi + +# Enable GZIP support through zlib. + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi + +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi + +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 +echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Extract the first word of "grep ggrep" to use in msg output +if test -z "$GREP"; then +set dummy grep ggrep; ac_prog_name=$2 +if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_GREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + # Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_GREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +GREP="$ac_cv_path_GREP" +if test -z "$GREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_GREP=$GREP +fi + + +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 +echo "${ECHO_T}$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + # Extract the first word of "egrep" to use in msg output +if test -z "$EGREP"; then +set dummy egrep; ac_prog_name=$2 +if test "${ac_cv_path_EGREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_path_EGREP_found=false +# Loop through the user's path and test for each of PROGNAME-LIST +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + # Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + ac_count=`expr $ac_count + 1` + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + + $ac_path_EGREP_found && break 3 + done +done + +done +IFS=$as_save_IFS + + +fi + +EGREP="$ac_cv_path_EGREP" +if test -z "$EGREP"; then + { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 +echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} + { (exit 1); exit 1; }; } +fi + +else + ac_cv_path_EGREP=$EGREP +fi + + + fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 +echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_header_stdc=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f -r conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f -r conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +if test "${snes9x_cv_zlib+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "${ac_cv_header_zlib_h+set}" = set; then + { echo "$as_me:$LINENO: checking for zlib.h" >&5 +echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6; } +if test "${ac_cv_header_zlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_zlib_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking zlib.h usability" >&5 +echo $ECHO_N "checking zlib.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking zlib.h presence" >&5 +echo $ECHO_N "checking zlib.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: zlib.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: zlib.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: zlib.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: zlib.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: zlib.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: zlib.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: zlib.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: zlib.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: zlib.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for zlib.h" >&5 +echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6; } +if test "${ac_cv_header_zlib_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_zlib_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5 +echo "${ECHO_T}$ac_cv_header_zlib_h" >&6; } + +fi +if test $ac_cv_header_zlib_h = yes; then + { echo "$as_me:$LINENO: checking for gzread in -lz" >&5 +echo $ECHO_N "checking for gzread in -lz... $ECHO_C" >&6; } +if test "${ac_cv_lib_z_gzread+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gzread (); +int +main () +{ +return gzread (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_z_gzread=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_z_gzread=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_gzread" >&5 +echo "${ECHO_T}$ac_cv_lib_z_gzread" >&6; } +if test $ac_cv_lib_z_gzread = yes; then + snes9x_cv_zlib="yes" +else + snes9x_cv_zlib="no" +fi + +else + snes9x_cv_zlib="no" +fi + + + +fi + + +# Check whether --enable-gzip was given. +if test "${enable_gzip+set}" = set; then + enableval=$enable_gzip; +else + enable_gzip="yes" +fi + + +if test "x$enable_gzip" = "xyes"; then + if test "x$snes9x_cv_zlib" = "xyes"; then + S9XDEFS="$S9XDEFS -DZLIB" + S9XLIBS="$S9XLIBS -lz" + else + { echo "$as_me:$LINENO: WARNING: zlib not found. Build without GZIP support." >&5 +echo "$as_me: WARNING: zlib not found. Build without GZIP support." >&2;} + enable_gzip="no" + fi +fi + +# Enable ZIP support through zlib. + +S9XZIP="#S9XZIP=1" + +# Check whether --enable-zip was given. +if test "${enable_zip+set}" = set; then + enableval=$enable_zip; +else + enable_zip="yes" +fi + + +if test "x$enable_zip" = "xyes"; then + if test "x$snes9x_cv_zlib" = "xyes"; then + S9XZIP="S9XZIP=1" + S9XDEFS="$S9XDEFS -DUNZIP_SUPPORT" + if test "x$enable_gzip" = "xno"; then + S9XLIBS="$S9XLIBS -lz" + fi + else + { echo "$as_me:$LINENO: WARNING: zlib not found. Build without ZIP support." >&5 +echo "$as_me: WARNING: zlib not found. Build without ZIP support." >&2;} + enable_zip="no" + fi +fi + +# Enable JMA support. + +S9XJMA="#S9XJMA=1" + +# Check whether --enable-jma was given. +if test "${enable_jma+set}" = set; then + enableval=$enable_jma; +else + enable_jma="yes" +fi + + +if test "x$enable_jma" = "xyes"; then + S9XJMA="S9XJMA=1" + S9XDEFS="$S9XDEFS -DJMA_SUPPORT" +fi + +# Enable screenshot support through libpng. + +if test "${snes9x_cv_libpng+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + + if test "${ac_cv_header_png_h+set}" = set; then + { echo "$as_me:$LINENO: checking for png.h" >&5 +echo $ECHO_N "checking for png.h... $ECHO_C" >&6; } +if test "${ac_cv_header_png_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_png_h" >&5 +echo "${ECHO_T}$ac_cv_header_png_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking png.h usability" >&5 +echo $ECHO_N "checking png.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking png.h presence" >&5 +echo $ECHO_N "checking png.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: png.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: png.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: png.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: png.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: png.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: png.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: png.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: png.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: png.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for png.h" >&5 +echo $ECHO_N "checking for png.h... $ECHO_C" >&6; } +if test "${ac_cv_header_png_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_png_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_png_h" >&5 +echo "${ECHO_T}$ac_cv_header_png_h" >&6; } + +fi +if test $ac_cv_header_png_h = yes; then + { echo "$as_me:$LINENO: checking for png_init_io in -lpng" >&5 +echo $ECHO_N "checking for png_init_io in -lpng... $ECHO_C" >&6; } +if test "${ac_cv_lib_png_png_init_io+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpng $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char png_init_io (); +int +main () +{ +return png_init_io (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_png_png_init_io=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_png_png_init_io=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_init_io" >&5 +echo "${ECHO_T}$ac_cv_lib_png_png_init_io" >&6; } +if test $ac_cv_lib_png_png_init_io = yes; then + snes9x_cv_libpng="yes" +else + snes9x_cv_libpng="no" +fi + +else + snes9x_cv_libpng="no" +fi + + + +fi + + +# Check whether --enable-screenshot was given. +if test "${enable_screenshot+set}" = set; then + enableval=$enable_screenshot; +else + enable_screenshot="yes" +fi + + +if test "x$enable_screenshot" = "xyes"; then + if test "x$snes9x_cv_libpng" = "xyes"; then + S9XDEFS="$S9XDEFS -DHAVE_LIBPNG" + S9XLIBS="$S9XLIBS -lpng" + else + { echo "$as_me:$LINENO: WARNING: libpng not found. Build without screenshot support." >&5 +echo "$as_me: WARNING: libpng not found. Build without screenshot support." >&2;} + enable_screenshot="no" + fi +fi + +# Check for functions + +{ echo "$as_me:$LINENO: checking for mkstemp" >&5 +echo $ECHO_N "checking for mkstemp... $ECHO_C" >&6; } +if test "${ac_cv_func_mkstemp+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define mkstemp to an innocuous variant, in case declares mkstemp. + For example, HP-UX 11i declares gettimeofday. */ +#define mkstemp innocuous_mkstemp + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char mkstemp (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef mkstemp + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char mkstemp (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_mkstemp || defined __stub___mkstemp +choke me +#endif + +int +main () +{ +return mkstemp (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_mkstemp=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_mkstemp=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_mkstemp" >&5 +echo "${ECHO_T}$ac_cv_func_mkstemp" >&6; } +if test $ac_cv_func_mkstemp = yes; then + + S9XDEFS="$S9XDEFS -DHAVE_MKSTEMP" + +fi + + +# Check X11 + +{ echo "$as_me:$LINENO: checking for X" >&5 +echo $ECHO_N "checking for X... $ECHO_C" >&6; } + + +# Check whether --with-x was given. +if test "${with_x+set}" = set; then + withval=$with_x; +fi + +# $have_x is `yes', `no', `disabled', or empty when we do not yet know. +if test "x$with_x" = xno; then + # The user explicitly disabled X. + have_x=disabled +else + case $x_includes,$x_libraries in #( + *\'*) { { echo "$as_me:$LINENO: error: Cannot use X directory names containing '" >&5 +echo "$as_me: error: Cannot use X directory names containing '" >&2;} + { (exit 1); exit 1; }; };; #( + *,NONE | NONE,*) if test "${ac_cv_have_x+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # One or both of the vars are not set, and there is no cached value. +ac_x_includes=no ac_x_libraries=no +rm -f -r conftest.dir +if mkdir conftest.dir; then + cd conftest.dir + cat >Imakefile <<'_ACEOF' +incroot: + @echo incroot='${INCROOT}' +usrlibdir: + @echo usrlibdir='${USRLIBDIR}' +libdir: + @echo libdir='${LIBDIR}' +_ACEOF + if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then + # GNU make sometimes prints "make[1]: Entering...", which would confuse us. + for ac_var in incroot usrlibdir libdir; do + eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" + done + # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. + for ac_extension in a so sl dylib la dll; do + if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && + test -f "$ac_im_libdir/libX11.$ac_extension"; then + ac_im_usrlibdir=$ac_im_libdir; break + fi + done + # Screen out bogus values from the imake configuration. They are + # bogus both because they are the default anyway, and because + # using them would break gcc on systems where it needs fixed includes. + case $ac_im_incroot in + /usr/include) ac_x_includes= ;; + *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; + esac + case $ac_im_usrlibdir in + /usr/lib | /lib) ;; + *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; + esac + fi + cd .. + rm -f -r conftest.dir +fi + +# Standard set of common directories for X headers. +# Check X11 before X11Rn because it is often a symlink to the current release. +ac_x_header_dirs=' +/usr/X11/include +/usr/X11R6/include +/usr/X11R5/include +/usr/X11R4/include + +/usr/include/X11 +/usr/include/X11R6 +/usr/include/X11R5 +/usr/include/X11R4 + +/usr/local/X11/include +/usr/local/X11R6/include +/usr/local/X11R5/include +/usr/local/X11R4/include + +/usr/local/include/X11 +/usr/local/include/X11R6 +/usr/local/include/X11R5 +/usr/local/include/X11R4 + +/usr/X386/include +/usr/x386/include +/usr/XFree86/include/X11 + +/usr/include +/usr/local/include +/usr/unsupported/include +/usr/athena/include +/usr/local/x11r5/include +/usr/lpp/Xamples/include + +/usr/openwin/include +/usr/openwin/share/include' + +if test "$ac_x_includes" = no; then + # Guess where to find include files, by looking for Xlib.h. + # First, try using that file with no special directory specified. + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + # We can compile using X headers with no special include directory. +ac_x_includes= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + for ac_dir in $ac_x_header_dirs; do + if test -r "$ac_dir/X11/Xlib.h"; then + ac_x_includes=$ac_dir + break + fi +done +fi + +rm -f conftest.err conftest.$ac_ext +fi # $ac_x_includes = no + +if test "$ac_x_libraries" = no; then + # Check for the libraries. + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS=$LIBS + LIBS="-lX11 $LIBS" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +int +main () +{ +XrmInitialize () + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + LIBS=$ac_save_LIBS +# We can link X programs with no special library path. +ac_x_libraries= +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + LIBS=$ac_save_LIBS +for ac_dir in `echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` +do + # Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl dylib la dll; do + if test -r "$ac_dir/libX11.$ac_extension"; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi # $ac_x_libraries = no + +case $ac_x_includes,$ac_x_libraries in #( + no,* | *,no | *\'*) + # Didn't find X, or a directory has "'" in its name. + ac_cv_have_x="have_x=no";; #( + *) + # Record where we found X for the cache. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$ac_x_includes'\ + ac_x_libraries='$ac_x_libraries'" +esac +fi +;; #( + *) have_x=yes;; + esac + eval "$ac_cv_have_x" +fi # $with_x != no + +if test "$have_x" != yes; then + { echo "$as_me:$LINENO: result: $have_x" >&5 +echo "${ECHO_T}$have_x" >&6; } + no_x=yes +else + # If each of the values was on the command line, it overrides each guess. + test "x$x_includes" = xNONE && x_includes=$ac_x_includes + test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries + # Update the cache value to reflect the command line values. + ac_cv_have_x="have_x=yes\ + ac_x_includes='$x_includes'\ + ac_x_libraries='$x_libraries'" + { echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 +echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6; } +fi + +if test "$no_x" = yes; then + # Not all programs may use this symbol, but it does not hurt to define it. + +cat >>confdefs.h <<\_ACEOF +#define X_DISPLAY_MISSING 1 +_ACEOF + + X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= +else + if test -n "$x_includes"; then + X_CFLAGS="$X_CFLAGS -I$x_includes" + fi + + # It would also be nice to do this for all -L options, not just this one. + if test -n "$x_libraries"; then + X_LIBS="$X_LIBS -L$x_libraries" + # For Solaris; some versions of Sun CC require a space after -R and + # others require no space. Words are not sufficient . . . . + { echo "$as_me:$LINENO: checking whether -R must be followed by a space" >&5 +echo $ECHO_N "checking whether -R must be followed by a space... $ECHO_C" >&6; } + ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" + ac_xsave_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + X_LIBS="$X_LIBS -R$x_libraries" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + LIBS="$ac_xsave_LIBS -R $x_libraries" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + X_LIBS="$X_LIBS -R $x_libraries" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: result: neither works" >&5 +echo "${ECHO_T}neither works" >&6; } +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + ac_cxx_werror_flag=$ac_xsave_cxx_werror_flag + LIBS=$ac_xsave_LIBS + fi + + # Check for system-dependent libraries X programs must link with. + # Do this before checking for the system-independent R6 libraries + # (-lICE), since we may need -lsocket or whatever for X linking. + + if test "$ISC" = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" + else + # Martyn Johnson says this is needed for Ultrix, if the X + # libraries were built with DECnet support. And Karl Berry says + # the Alpha needs dnet_stub (dnet does not exist). + ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char XOpenDisplay (); +int +main () +{ +return XOpenDisplay (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + { echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet" >&5 +echo $ECHO_N "checking for dnet_ntoa in -ldnet... $ECHO_C" >&6; } +if test "${ac_cv_lib_dnet_dnet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_dnet_dnet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dnet_dnet_ntoa=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_dnet_dnet_ntoa" >&6; } +if test $ac_cv_lib_dnet_dnet_ntoa = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" +fi + + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + { echo "$as_me:$LINENO: checking for dnet_ntoa in -ldnet_stub" >&5 +echo $ECHO_N "checking for dnet_ntoa in -ldnet_stub... $ECHO_C" >&6; } +if test "${ac_cv_lib_dnet_stub_dnet_ntoa+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldnet_stub $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dnet_ntoa (); +int +main () +{ +return dnet_ntoa (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_dnet_stub_dnet_ntoa=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_dnet_stub_dnet_ntoa=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 +echo "${ECHO_T}$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } +if test $ac_cv_lib_dnet_stub_dnet_ntoa = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" +fi + + fi +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$ac_xsave_LIBS" + + # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, + # to get the SysV transport functions. + # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) + # needs -lnsl. + # The nsl library prevents programs from opening the X display + # on Irix 5.2, according to T.E. Dickey. + # The functions gethostbyname, getservbyname, and inet_addr are + # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. + { echo "$as_me:$LINENO: checking for gethostbyname" >&5 +echo $ECHO_N "checking for gethostbyname... $ECHO_C" >&6; } +if test "${ac_cv_func_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define gethostbyname to an innocuous variant, in case declares gethostbyname. + For example, HP-UX 11i declares gettimeofday. */ +#define gethostbyname innocuous_gethostbyname + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef gethostbyname + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_gethostbyname || defined __stub___gethostbyname +choke me +#endif + +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_gethostbyname=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_func_gethostbyname" >&6; } + + if test $ac_cv_func_gethostbyname = no; then + { echo "$as_me:$LINENO: checking for gethostbyname in -lnsl" >&5 +echo $ECHO_N "checking for gethostbyname in -lnsl... $ECHO_C" >&6; } +if test "${ac_cv_lib_nsl_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_nsl_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_nsl_gethostbyname=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_nsl_gethostbyname" >&6; } +if test $ac_cv_lib_nsl_gethostbyname = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" +fi + + if test $ac_cv_lib_nsl_gethostbyname = no; then + { echo "$as_me:$LINENO: checking for gethostbyname in -lbsd" >&5 +echo $ECHO_N "checking for gethostbyname in -lbsd... $ECHO_C" >&6; } +if test "${ac_cv_lib_bsd_gethostbyname+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbsd $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gethostbyname (); +int +main () +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_bsd_gethostbyname=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_bsd_gethostbyname=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_bsd_gethostbyname" >&5 +echo "${ECHO_T}$ac_cv_lib_bsd_gethostbyname" >&6; } +if test $ac_cv_lib_bsd_gethostbyname = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" +fi + + fi + fi + + # lieder@skyler.mavd.honeywell.com says without -lsocket, + # socket/setsockopt and other routines are undefined under SCO ODT + # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary + # on later versions), says Simon Leinen: it contains gethostby* + # variants that don't use the name server (or something). -lsocket + # must be given before -lnsl if both are needed. We assume that + # if connect needs -lnsl, so does gethostbyname. + { echo "$as_me:$LINENO: checking for connect" >&5 +echo $ECHO_N "checking for connect... $ECHO_C" >&6; } +if test "${ac_cv_func_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define connect to an innocuous variant, in case declares connect. + For example, HP-UX 11i declares gettimeofday. */ +#define connect innocuous_connect + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char connect (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef connect + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_connect || defined __stub___connect +choke me +#endif + +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_connect=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_connect" >&5 +echo "${ECHO_T}$ac_cv_func_connect" >&6; } + + if test $ac_cv_func_connect = no; then + { echo "$as_me:$LINENO: checking for connect in -lsocket" >&5 +echo $ECHO_N "checking for connect in -lsocket... $ECHO_C" >&6; } +if test "${ac_cv_lib_socket_connect+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char connect (); +int +main () +{ +return connect (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_socket_connect=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_socket_connect=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_connect" >&5 +echo "${ECHO_T}$ac_cv_lib_socket_connect" >&6; } +if test $ac_cv_lib_socket_connect = yes; then + X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" +fi + + fi + + # Guillermo Gomez says -lposix is necessary on A/UX. + { echo "$as_me:$LINENO: checking for remove" >&5 +echo $ECHO_N "checking for remove... $ECHO_C" >&6; } +if test "${ac_cv_func_remove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define remove to an innocuous variant, in case declares remove. + For example, HP-UX 11i declares gettimeofday. */ +#define remove innocuous_remove + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char remove (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef remove + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char remove (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_remove || defined __stub___remove +choke me +#endif + +int +main () +{ +return remove (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_remove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_remove=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_remove" >&5 +echo "${ECHO_T}$ac_cv_func_remove" >&6; } + + if test $ac_cv_func_remove = no; then + { echo "$as_me:$LINENO: checking for remove in -lposix" >&5 +echo $ECHO_N "checking for remove in -lposix... $ECHO_C" >&6; } +if test "${ac_cv_lib_posix_remove+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char remove (); +int +main () +{ +return remove (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_posix_remove=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_posix_remove=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_posix_remove" >&5 +echo "${ECHO_T}$ac_cv_lib_posix_remove" >&6; } +if test $ac_cv_lib_posix_remove = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" +fi + + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + { echo "$as_me:$LINENO: checking for shmat" >&5 +echo $ECHO_N "checking for shmat... $ECHO_C" >&6; } +if test "${ac_cv_func_shmat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define shmat to an innocuous variant, in case declares shmat. + For example, HP-UX 11i declares gettimeofday. */ +#define shmat innocuous_shmat + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shmat (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef shmat + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shmat (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_shmat || defined __stub___shmat +choke me +#endif + +int +main () +{ +return shmat (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_func_shmat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_func_shmat=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +{ echo "$as_me:$LINENO: result: $ac_cv_func_shmat" >&5 +echo "${ECHO_T}$ac_cv_func_shmat" >&6; } + + if test $ac_cv_func_shmat = no; then + { echo "$as_me:$LINENO: checking for shmat in -lipc" >&5 +echo $ECHO_N "checking for shmat in -lipc... $ECHO_C" >&6; } +if test "${ac_cv_lib_ipc_shmat+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lipc $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shmat (); +int +main () +{ +return shmat (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_ipc_shmat=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_ipc_shmat=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_ipc_shmat" >&5 +echo "${ECHO_T}$ac_cv_lib_ipc_shmat" >&6; } +if test $ac_cv_lib_ipc_shmat = yes; then + X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" +fi + + fi + fi + + # Check for libraries that X11R6 Xt/Xaw programs need. + ac_save_LDFLAGS=$LDFLAGS + test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" + # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to + # check for ICE first), but we must link in the order -lSM -lICE or + # we get undefined symbols. So assume we have SM if we have ICE. + # These have to be linked with before -lX11, unlike the other + # libraries we check for below, so use a different variable. + # John Interrante, Karl Berry + { echo "$as_me:$LINENO: checking for IceConnectionNumber in -lICE" >&5 +echo $ECHO_N "checking for IceConnectionNumber in -lICE... $ECHO_C" >&6; } +if test "${ac_cv_lib_ICE_IceConnectionNumber+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lICE $X_EXTRA_LIBS $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char IceConnectionNumber (); +int +main () +{ +return IceConnectionNumber (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + ac_cv_lib_ICE_IceConnectionNumber=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_ICE_IceConnectionNumber=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 +echo "${ECHO_T}$ac_cv_lib_ICE_IceConnectionNumber" >&6; } +if test $ac_cv_lib_ICE_IceConnectionNumber = yes; then + X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" +fi + + LDFLAGS=$ac_save_LDFLAGS + +fi + +if test "x$no_x" = "xyes"; then + { { echo "$as_me:$LINENO: error: X11 is required." >&5 +echo "$as_me: error: X11 is required." >&2;} + { (exit 1); exit 1; }; } +else + S9XFLGS="$S9XFLGS $X_CFLAGS" + S9XLIBS="$S9XLIBS $X_PRE_LIBS -lX11 -lXext $X_LIBS $X_EXTRA_LIBS" +fi + +# Check for headers + +snes9x_have_stdint_h=""; + +if test "${ac_cv_header_strings_h+set}" = set; then + { echo "$as_me:$LINENO: checking for strings.h" >&5 +echo $ECHO_N "checking for strings.h... $ECHO_C" >&6; } +if test "${ac_cv_header_strings_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_strings_h" >&5 +echo "${ECHO_T}$ac_cv_header_strings_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking strings.h usability" >&5 +echo $ECHO_N "checking strings.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking strings.h presence" >&5 +echo $ECHO_N "checking strings.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: strings.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: strings.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: strings.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: strings.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: strings.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: strings.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: strings.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: strings.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: strings.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: strings.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: strings.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for strings.h" >&5 +echo $ECHO_N "checking for strings.h... $ECHO_C" >&6; } +if test "${ac_cv_header_strings_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_strings_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_strings_h" >&5 +echo "${ECHO_T}$ac_cv_header_strings_h" >&6; } + +fi +if test $ac_cv_header_strings_h = yes; then + + S9XDEFS="$S9XDEFS -DHAVE_STRINGS_H" + +fi + + + +if test "${ac_cv_header_sys_ioctl_h+set}" = set; then + { echo "$as_me:$LINENO: checking for sys/ioctl.h" >&5 +echo $ECHO_N "checking for sys/ioctl.h... $ECHO_C" >&6; } +if test "${ac_cv_header_sys_ioctl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_ioctl_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_ioctl_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking sys/ioctl.h usability" >&5 +echo $ECHO_N "checking sys/ioctl.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking sys/ioctl.h presence" >&5 +echo $ECHO_N "checking sys/ioctl.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: sys/ioctl.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: sys/ioctl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ioctl.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: sys/ioctl.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: sys/ioctl.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: sys/ioctl.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ioctl.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: sys/ioctl.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ioctl.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: sys/ioctl.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ioctl.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: sys/ioctl.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ioctl.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: sys/ioctl.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: sys/ioctl.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: sys/ioctl.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for sys/ioctl.h" >&5 +echo $ECHO_N "checking for sys/ioctl.h... $ECHO_C" >&6; } +if test "${ac_cv_header_sys_ioctl_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_sys_ioctl_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_ioctl_h" >&5 +echo "${ECHO_T}$ac_cv_header_sys_ioctl_h" >&6; } + +fi +if test $ac_cv_header_sys_ioctl_h = yes; then + + S9XDEFS="$S9XDEFS -DHAVE_SYS_IOCTL_H" + +fi + + + +if test "${ac_cv_header_stdint_h+set}" = set; then + { echo "$as_me:$LINENO: checking for stdint.h" >&5 +echo $ECHO_N "checking for stdint.h... $ECHO_C" >&6; } +if test "${ac_cv_header_stdint_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdint_h" >&5 +echo "${ECHO_T}$ac_cv_header_stdint_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking stdint.h usability" >&5 +echo $ECHO_N "checking stdint.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking stdint.h presence" >&5 +echo $ECHO_N "checking stdint.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: stdint.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: stdint.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: stdint.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: stdint.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: stdint.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: stdint.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: stdint.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: stdint.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: stdint.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: stdint.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: stdint.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: stdint.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: stdint.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: stdint.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: stdint.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: stdint.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for stdint.h" >&5 +echo $ECHO_N "checking for stdint.h... $ECHO_C" >&6; } +if test "${ac_cv_header_stdint_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_stdint_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_stdint_h" >&5 +echo "${ECHO_T}$ac_cv_header_stdint_h" >&6; } + +fi +if test $ac_cv_header_stdint_h = yes; then + + S9XDEFS="$S9XDEFS -DHAVE_STDINT_H" + snes9x_have_stdint_h="-DHAVE_STDINT_H" + +fi + + + + + +for ac_header in unistd.h sys/socket.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Check whether the size of pointer is int. + +if test "x$snes9x_have_stdint_h" = "x"; then + { echo "$as_me:$LINENO: checking whether the size of pointer is int" >&5 +echo $ECHO_N "checking whether the size of pointer is int... $ECHO_C" >&6; } + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + int main (void) + { + return (!(sizeof(void *) == sizeof(int))); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_ptr_is_int="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_ptr_is_int="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + + if test "x$snes9x_ptr_is_int" = "xyes"; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + S9XDEFS="$S9XDEFS -DPTR_NOT_INT" + fi +fi + +# Check whether right shift is arithmetic or not + + + + + { echo "$as_me:$LINENO: checking whether right shift int8 is arithmetic" >&5 +echo $ECHO_N "checking whether right shift int8 is arithmetic... $ECHO_C" >&6; } + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS $snes9x_have_stdint_h" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #ifdef HAVE_STDINT_H + #include + typedef int8_t int8; + typedef int16_t int16; + typedef int32_t int32; + typedef int64_t int64; + #else + typedef signed char int8; + typedef signed short int16; + typedef signed int int32; + #ifdef __GNUC__ + __extension__ + #endif + typedef long long int64; + #endif + + int main (void) + { + int8 i; + + i = -1; + i >>= 1; + + return (i < 0 ? 0 : 1); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_sar_int8="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_sar_int8="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_sar_int8" = "xno"; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + else + S9XDEFS="$S9XDEFS -DRIGHTSHIFT_int8_IS_SAR" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + fi + + + { echo "$as_me:$LINENO: checking whether right shift int16 is arithmetic" >&5 +echo $ECHO_N "checking whether right shift int16 is arithmetic... $ECHO_C" >&6; } + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS $snes9x_have_stdint_h" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #ifdef HAVE_STDINT_H + #include + typedef int8_t int8; + typedef int16_t int16; + typedef int32_t int32; + typedef int64_t int64; + #else + typedef signed char int8; + typedef signed short int16; + typedef signed int int32; + #ifdef __GNUC__ + __extension__ + #endif + typedef long long int64; + #endif + + int main (void) + { + int16 i; + + i = -1; + i >>= 1; + + return (i < 0 ? 0 : 1); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_sar_int16="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_sar_int16="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_sar_int16" = "xno"; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + else + S9XDEFS="$S9XDEFS -DRIGHTSHIFT_int16_IS_SAR" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + fi + + + { echo "$as_me:$LINENO: checking whether right shift int32 is arithmetic" >&5 +echo $ECHO_N "checking whether right shift int32 is arithmetic... $ECHO_C" >&6; } + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS $snes9x_have_stdint_h" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #ifdef HAVE_STDINT_H + #include + typedef int8_t int8; + typedef int16_t int16; + typedef int32_t int32; + typedef int64_t int64; + #else + typedef signed char int8; + typedef signed short int16; + typedef signed int int32; + #ifdef __GNUC__ + __extension__ + #endif + typedef long long int64; + #endif + + int main (void) + { + int32 i; + + i = -1; + i >>= 1; + + return (i < 0 ? 0 : 1); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_sar_int32="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_sar_int32="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_sar_int32" = "xno"; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + else + S9XDEFS="$S9XDEFS -DRIGHTSHIFT_int32_IS_SAR" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + fi + + + { echo "$as_me:$LINENO: checking whether right shift int64 is arithmetic" >&5 +echo $ECHO_N "checking whether right shift int64 is arithmetic... $ECHO_C" >&6; } + + OLD_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$OLD_CXXFLAGS $snes9x_have_stdint_h" + + if test "$cross_compiling" = yes; then + { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run test program while cross compiling +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #ifdef HAVE_STDINT_H + #include + typedef int8_t int8; + typedef int16_t int16; + typedef int32_t int32; + typedef int64_t int64; + #else + typedef signed char int8; + typedef signed short int16; + typedef signed int int32; + #ifdef __GNUC__ + __extension__ + #endif + typedef long long int64; + #endif + + int main (void) + { + int64 i; + + i = -1; + i >>= 1; + + return (i < 0 ? 0 : 1); + } + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + snes9x_sar_int64="yes" +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +snes9x_sar_int64="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + + CXXFLAGS="$OLD_CXXFLAGS" + + if test "x$snes9x_sar_int64" = "xno"; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + else + S9XDEFS="$S9XDEFS -DRIGHTSHIFT_int64_IS_SAR" + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + fi + + +if test "x$snes9x_sar_int8" = "xyes" -a "x$snes9x_sar_int16" = "xyes" -a "x$snes9x_sar_int32" = "xyes" -a "x$snes9x_sar_int64" = "xyes"; then + S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/-DRIGHTSHIFT_int8_IS_SAR//'`" + S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/-DRIGHTSHIFT_int16_IS_SAR//'`" + S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/-DRIGHTSHIFT_int32_IS_SAR//'`" + S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/-DRIGHTSHIFT_int64_IS_SAR//'`" + S9XDEFS="$S9XDEFS -DRIGHTSHIFT_IS_SAR" +fi + +# Check if we have sound code for this platform. + +# Check whether --enable-sound was given. +if test "${enable_sound+set}" = set; then + enableval=$enable_sound; +else + enable_sound="yes" +fi + + +if test "x$enable_sound" = "xyes"; then + { echo "$as_me:$LINENO: checking whether sound is supported on this platform" >&5 +echo $ECHO_N "checking whether sound is supported on this platform... $ECHO_C" >&6; } + if test "x$snes9x_cv_linux_os" = "xyes"; then + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + { echo "$as_me:$LINENO: WARNING: Your OS is not Linux. Build without sound support." >&5 +echo "$as_me: WARNING: Your OS is not Linux. Build without sound support." >&2;} + enable_sound="no" + fi +fi + +if test "x$enable_sound" = "xyes"; then + if test "${ac_cv_header_pthread_h+set}" = set; then + { echo "$as_me:$LINENO: checking for pthread.h" >&5 +echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6; } +if test "${ac_cv_header_pthread_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 +echo "${ECHO_T}$ac_cv_header_pthread_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking pthread.h usability" >&5 +echo $ECHO_N "checking pthread.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking pthread.h presence" >&5 +echo $ECHO_N "checking pthread.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: pthread.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: pthread.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: pthread.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: pthread.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: pthread.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: pthread.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: pthread.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: pthread.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: pthread.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: pthread.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for pthread.h" >&5 +echo $ECHO_N "checking for pthread.h... $ECHO_C" >&6; } +if test "${ac_cv_header_pthread_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_pthread_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_pthread_h" >&5 +echo "${ECHO_T}$ac_cv_header_pthread_h" >&6; } + +fi +if test $ac_cv_header_pthread_h = yes; then + + S9XDEFS="$S9XDEFS -DUSE_THREADS" + S9XLIBS="$S9XLIBS -lpthread" + +fi + + +else + S9XDEFS="$S9XDEFS -DNOSOUND" +fi + +# Output. + +S9XFLGS="$CXXFLAGS $CPPFLAGS $LDFLAGS $S9XFLGS" +S9XLIBS="$LIBS $S9XLIBS" + +S9XFLGS="`echo \"$S9XFLGS\" | sed -e 's/ */ /g'`" +S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/ */ /g'`" +S9XLIBS="`echo \"$S9XLIBS\" | sed -e 's/ */ /g'`" +S9XFLGS="`echo \"$S9XFLGS\" | sed -e 's/^ *//'`" +S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/^ *//'`" +S9XLIBS="`echo \"$S9XLIBS\" | sed -e 's/^ *//'`" + + + + + + + + + + + + +rm config.info 2>/dev/null + +cat >config.info <confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 +echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + *) $as_unset $ac_var ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { echo "$as_me:$LINENO: updating cache $cache_file" >&5 +echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 +echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in + *posix*) set -o posix ;; +esac + +fi + + + + +# PATH needs CR +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + +# Support unset when possible. +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +as_nl=' +' +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + { (exit 1); exit 1; } +fi + +# Work around bugs in pre-3.0 UWIN ksh. +for as_var in ENV MAIL MAILPATH +do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# CDPATH. +$as_unset CDPATH + + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line after each line using $LINENO; the second 'sed' + # does the real work. The second script uses 'N' to pair each + # line-number line with the line containing $LINENO, and appends + # trailing '-' during substitution so that $LINENO is not a special + # case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # scripts with optimization help from Paolo Bonzini. Blame Lee + # E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in +-n*) + case `echo 'x\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + *) ECHO_C='\c';; + esac;; +*) + ECHO_N='-n';; +esac + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir +fi +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 + +# Save the log message, to keep $[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by Snes9x $as_me 1.52, which was +generated by GNU Autoconf 2.61. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# Files that config.status was made for. +config_files="$ac_config_files" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +Snes9x config.status 1.52 +configured by $0, generated by GNU Autoconf 2.61, + with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2006 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + CONFIG_SHELL=$SHELL + export CONFIG_SHELL + exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +# +# Set up the sed scripts for CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "$CONFIG_FILES"; then + +_ACEOF + + + +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF +SHELL!$SHELL$ac_delim +PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim +PACKAGE_NAME!$PACKAGE_NAME$ac_delim +PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim +PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim +PACKAGE_STRING!$PACKAGE_STRING$ac_delim +PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim +exec_prefix!$exec_prefix$ac_delim +prefix!$prefix$ac_delim +program_transform_name!$program_transform_name$ac_delim +bindir!$bindir$ac_delim +sbindir!$sbindir$ac_delim +libexecdir!$libexecdir$ac_delim +datarootdir!$datarootdir$ac_delim +datadir!$datadir$ac_delim +sysconfdir!$sysconfdir$ac_delim +sharedstatedir!$sharedstatedir$ac_delim +localstatedir!$localstatedir$ac_delim +includedir!$includedir$ac_delim +oldincludedir!$oldincludedir$ac_delim +docdir!$docdir$ac_delim +infodir!$infodir$ac_delim +htmldir!$htmldir$ac_delim +dvidir!$dvidir$ac_delim +pdfdir!$pdfdir$ac_delim +psdir!$psdir$ac_delim +libdir!$libdir$ac_delim +localedir!$localedir$ac_delim +mandir!$mandir$ac_delim +DEFS!$DEFS$ac_delim +ECHO_C!$ECHO_C$ac_delim +ECHO_N!$ECHO_N$ac_delim +ECHO_T!$ECHO_T$ac_delim +LIBS!$LIBS$ac_delim +build_alias!$build_alias$ac_delim +host_alias!$host_alias$ac_delim +target_alias!$target_alias$ac_delim +build!$build$ac_delim +build_cpu!$build_cpu$ac_delim +build_vendor!$build_vendor$ac_delim +build_os!$build_os$ac_delim +host!$host$ac_delim +host_cpu!$host_cpu$ac_delim +host_vendor!$host_vendor$ac_delim +host_os!$host_os$ac_delim +target!$target$ac_delim +target_cpu!$target_cpu$ac_delim +target_vendor!$target_vendor$ac_delim +target_os!$target_os$ac_delim +CC!$CC$ac_delim +CFLAGS!$CFLAGS$ac_delim +LDFLAGS!$LDFLAGS$ac_delim +CPPFLAGS!$CPPFLAGS$ac_delim +ac_ct_CC!$ac_ct_CC$ac_delim +EXEEXT!$EXEEXT$ac_delim +OBJEXT!$OBJEXT$ac_delim +CXX!$CXX$ac_delim +CXXFLAGS!$CXXFLAGS$ac_delim +ac_ct_CXX!$ac_ct_CXX$ac_delim +S9XNASM!$S9XNASM$ac_delim +CXXCPP!$CXXCPP$ac_delim +GREP!$GREP$ac_delim +EGREP!$EGREP$ac_delim +XMKMF!$XMKMF$ac_delim +X_CFLAGS!$X_CFLAGS$ac_delim +X_PRE_LIBS!$X_PRE_LIBS$ac_delim +X_LIBS!$X_LIBS$ac_delim +X_EXTRA_LIBS!$X_EXTRA_LIBS$ac_delim +S9XFLGS!$S9XFLGS$ac_delim +S9XDEFS!$S9XDEFS$ac_delim +S9XLIBS!$S9XLIBS$ac_delim +S9XZSNESFX!$S9XZSNESFX$ac_delim +S9XZSNESC4!$S9XZSNESC4$ac_delim +S9XDEBUGGER!$S9XDEBUGGER$ac_delim +S9XNETPLAY!$S9XNETPLAY$ac_delim +S9XZIP!$S9XZIP$ac_delim +S9XJMA!$S9XJMA$ac_delim +LIBOBJS!$LIBOBJS$ac_delim +LTLIBOBJS!$LTLIBOBJS$ac_delim +_ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 79; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 +echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` +if test -n "$ac_eof"; then + ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` + ac_eof=`expr $ac_eof + 1` +fi + +cat >>$CONFIG_STATUS <<_ACEOF +cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end +_ACEOF +sed ' +s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g +s/^/s,@/; s/!/@,|#_!!_#|/ +:n +t n +s/'"$ac_delim"'$/,g/; t +s/$/\\/; p +N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n +' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF +:end +s/|#_!!_#|//g +CEOF$ac_eof +_ACEOF + + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF +fi # test -n "$CONFIG_FILES" + + +for ac_tag in :F $CONFIG_FILES +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 +echo "$as_me: error: Invalid tag $ac_tag." >&2;} + { (exit 1); exit 1; }; };; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 +echo "$as_me: error: cannot find input file: $ac_f" >&2;} + { (exit 1); exit 1; }; };; + esac + ac_file_inputs="$ac_file_inputs $ac_f" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input="Generated from "`IFS=: + echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + fi + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin";; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + { as_dir="$ac_dir" + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 +echo "$as_me: error: cannot create directory $as_dir" >&2;} + { (exit 1); exit 1; }; }; } + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= + +case `sed -n '/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p +' $ac_file_inputs` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s&@configure_input@&$configure_input&;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out"; rm -f "$tmp/out";; + *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; + esac + ;; + + + + esac + +done # for ac_tag + + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/unix/configure.ac b/unix/configure.ac new file mode 100644 index 00000000..c7f9dab1 --- /dev/null +++ b/unix/configure.ac @@ -0,0 +1,501 @@ +AC_PREREQ([2.60]) +AC_INIT([Snes9x], [1.52], [], [snes9x]) +AC_REVISION([$Revision: 1.52 $]) + +AC_CONFIG_SRCDIR([unix.cpp]) + +AC_CANONICAL_TARGET + +AC_PROG_CC +AC_PROG_CXX +AC_LANG([C++]) + +S9XFLGS="" +S9XDEFS="" +S9XLIBS="" + +AC_DEFUN([AC_S9X_COMPILER_FLAG], +[ + AC_MSG_CHECKING([whether g++ accepts $1]) + + AC_CACHE_VAL([snes9x_cv_option_$2], + [ + OLD_CXXFLAGS="[$]CXXFLAGS" + CXXFLAGS="[$]OLD_CXXFLAGS $1" + + AC_TRY_RUN( + [ + int foo; + + int main (int argc, char **argv) + { + /* The following code triggs gcc:s generation of aline opcodes, + which some versions of as does not support. */ + + if (argc > 0) + argc = 0; + + return (argc); + } + ], + [snes9x_cv_option_$2="yes"], [snes9x_cv_option_$2="no"]) + ]) + + CXXFLAGS="[$]OLD_CXXFLAGS" + + if test "x[$]snes9x_cv_option_$2" = "xyes"; then + S9XFLGS="[$]S9XFLGS $1" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + $3 + fi +]) + +# ***************************** +# *** Execution begins here *** +# ***************************** + +# Remove -g and -O2 flags manually. + +if test "x$CFLAGS" != "x"; then + CFLAGS="`echo \"$CFLAGS\" | sed -e 's/-g//'`" + CFLAGS="`echo \"$CFLAGS\" | sed -e 's/-O2//'`" +fi + +if test "x$CXXFLAGS" != "x"; then + CXXFLAGS="`echo \"$CXXFLAGS\" | sed -e 's/-g//'`" + CXXFLAGS="`echo \"$CXXFLAGS\" | sed -e 's/-O2//'`" +fi + +# Test what compiler flags we should use. + +AC_ARG_ENABLE([debug], + [AS_HELP_STRING([--enable-debug], + [leave debug information in the final binary (default: no)])], + [], [enable_debug="no"]) + +if test "x$enable_debug" = "xyes"; then + AC_S9X_COMPILER_FLAG([-g], [g]) + AC_S9X_COMPILER_FLAG([-O0], [o0]) +else + AC_S9X_COMPILER_FLAG([-O3], [o3], [ + AC_S9X_COMPILER_FLAG([-O2], [o2], [ + AC_S9X_COMPILER_FLAG([-O1], [o1])])]) + AC_S9X_COMPILER_FLAG([-fomit-frame-pointer], [omit_frame_pointer]) +fi + +AC_ARG_ENABLE([mtune], + [AS_HELP_STRING([--enable-mtune], + [use the specified value for the -mtune/-mcpu flag (default: no)])], + [], [enable_mtune="no"]) + +if test "x$enable_mtune" != "xno"; then + AC_S9X_COMPILER_FLAG([-mtune="$enable_mtune"], [mtune], + [ + AC_MSG_WARN([-mtune failed, trying -mcpu...]) + AC_S9X_COMPILER_FLAG([-mcpu="$enable_mtune"], [mcpu], + [AC_MSG_ERROR([Please specify a working value for --enable-mtune.])]) + ]) +fi + +AC_S9X_COMPILER_FLAG([-fno-exceptions], [no_exceptions]) +AC_S9X_COMPILER_FLAG([-fno-rtti], [no_rtti]) +AC_S9X_COMPILER_FLAG([-pedantic], [pedantic]) +AC_S9X_COMPILER_FLAG([-Wall], [Wall]) +AC_S9X_COMPILER_FLAG([-W], [W]) +AC_S9X_COMPILER_FLAG([-Wno-unused-parameter], [Wno_unused_parameter]) + +# Check if the CPU is x86. + +AC_MSG_CHECKING([whether the CPU is x86]) + +AC_CACHE_VAL([snes9x_cv_x86_cpu], +[ + case "$target" in + i686-*-* | i586-*-* | i486-*-* | i386-*-*) + snes9x_cv_x86_cpu="yes" + ;; + *) + snes9x_cv_x86_cpu="no" + ;; + esac +]) + +AC_MSG_RESULT([$snes9x_cv_x86_cpu]) + +# Enable ZSNES C4 and SuperFX assembler cores if CPU is x86. + +S9XZSNESFX="#S9XZSNESFX=1" +S9XZSNESC4="#S9XZSNESC4=1" +S9XNASM="" + +AC_ARG_ENABLE([zsnes_asm], + [AS_HELP_STRING([--enable-zsnes-asm], + [build with ZSNES C4 and SuperFX assembler cores if available (default: no)])], + [], [enable_zsnes_asm="no"]) + +if test "x$enable_zsnes_asm" = "xyes"; then + if test "x$snes9x_cv_x86_cpu" = "xyes"; then + AC_PATH_PROG([S9XNASM], [nasm], [no]) + if test "x$S9XNASM" != "xno"; then + S9XZSNESFX="S9XZSNESFX=1" + S9XZSNESC4="S9XZSNESC4=1" + S9XDEFS="$S9XDEFS -DZSNES_FX -DZSNES_C4" + else + AC_MSG_WARN([nasm not found. Build without ZSNES assembler cores.]) + enable_zsnes_asm="no" + fi + else + AC_MSG_WARN([Your CPU is not x86. Build without ZSNES assembler cores.]) + enable_zsnes_asm="no" + fi +fi + +# Check if the OS is Linux. + +AC_MSG_CHECKING([whether the OS is Linux]) + +AC_CACHE_VAL([snes9x_cv_linux_os], +[ + case "$target" in + *-*-linux*) + snes9x_cv_linux_os="yes" + ;; + *) + snes9x_cv_linux_os="no" + ;; + esac +]) + +AC_MSG_RESULT([$snes9x_cv_linux_os]) + +# Enable gamepad support on Linux. + +AC_ARG_ENABLE([gamepad], + [AS_HELP_STRING([--enable-gamepad], + [enable gamepad support if available (default: yes)])], + [], [enable_gamepad="yes"]) + +if test "x$enable_gamepad" = "xyes"; then + if test "x$snes9x_cv_linux_os" = "xyes"; then + S9XDEFS="$S9XDEFS -DJOYSTICK_SUPPORT" + else + AC_MSG_WARN([Your OS is not Linux. Build without gamepad support.]) + enable_gamepad="no" + fi +fi + +# Enable debugger. + +S9XDEBUGGER="#S9XDEBUGGER=1" + +AC_ARG_ENABLE([debugger], + [AS_HELP_STRING([--enable-debugger], + [enable debugger (default: no)])], + [], [enable_debugger="no"]) + +if test "x$enable_debugger" = "xyes"; then + S9XDEBUGGER="S9XDEBUGGER=1" + S9XDEFS="$S9XDEFS -DDEBUGGER" +fi + +# Enable netplay support if requested. + +S9XNETPLAY="#S9XNETPLAY=1" + +AC_ARG_ENABLE([netplay], + [AS_HELP_STRING([--enable-netplay], + [enable netplay support (default: no)])], + [], [enable_netplay="no"]) + +if test "x$enable_netplay" = "xyes"; then + S9XNETPLAY="S9XNETPLAY=1" + S9XDEFS="$S9XDEFS -DNETPLAY_SUPPORT" +fi + +# Enable GZIP support through zlib. + +AC_CACHE_VAL([snes9x_cv_zlib], +[ + AC_CHECK_HEADER([zlib.h], + [AC_CHECK_LIB([z], [gzread], [snes9x_cv_zlib="yes"], [snes9x_cv_zlib="no"])], + [snes9x_cv_zlib="no"]) +]) + +AC_ARG_ENABLE([gzip], + [AS_HELP_STRING([--enable-gzip], + [enable GZIP support through zlib (default: yes)])], + [], [enable_gzip="yes"]) + +if test "x$enable_gzip" = "xyes"; then + if test "x$snes9x_cv_zlib" = "xyes"; then + S9XDEFS="$S9XDEFS -DZLIB" + S9XLIBS="$S9XLIBS -lz" + else + AC_MSG_WARN([zlib not found. Build without GZIP support.]) + enable_gzip="no" + fi +fi + +# Enable ZIP support through zlib. + +S9XZIP="#S9XZIP=1" + +AC_ARG_ENABLE([zip], + [AS_HELP_STRING([--enable-zip], + [enable ZIP support through zlib (default: yes)])], + [], [enable_zip="yes"]) + +if test "x$enable_zip" = "xyes"; then + if test "x$snes9x_cv_zlib" = "xyes"; then + S9XZIP="S9XZIP=1" + S9XDEFS="$S9XDEFS -DUNZIP_SUPPORT" + if test "x$enable_gzip" = "xno"; then + S9XLIBS="$S9XLIBS -lz" + fi + else + AC_MSG_WARN([zlib not found. Build without ZIP support.]) + enable_zip="no" + fi +fi + +# Enable JMA support. + +S9XJMA="#S9XJMA=1" + +AC_ARG_ENABLE([jma], + [AS_HELP_STRING([--enable-jma], + [enable JMA support (default: yes)])], + [], [enable_jma="yes"]) + +if test "x$enable_jma" = "xyes"; then + S9XJMA="S9XJMA=1" + S9XDEFS="$S9XDEFS -DJMA_SUPPORT" +fi + +# Enable screenshot support through libpng. + +AC_CACHE_VAL([snes9x_cv_libpng], +[ + AC_CHECK_HEADER([png.h], + [AC_CHECK_LIB([png], [png_init_io], [snes9x_cv_libpng="yes"], [snes9x_cv_libpng="no"])], + [snes9x_cv_libpng="no"]) +]) + +AC_ARG_ENABLE([screenshot], + [AS_HELP_STRING([--enable-screenshot], + [enable screenshot support through libpng (default: yes)])], + [], [enable_screenshot="yes"]) + +if test "x$enable_screenshot" = "xyes"; then + if test "x$snes9x_cv_libpng" = "xyes"; then + S9XDEFS="$S9XDEFS -DHAVE_LIBPNG" + S9XLIBS="$S9XLIBS -lpng" + else + AC_MSG_WARN([libpng not found. Build without screenshot support.]) + enable_screenshot="no" + fi +fi + +# Check for functions + +AC_CHECK_FUNC([mkstemp], +[ + S9XDEFS="$S9XDEFS -DHAVE_MKSTEMP" +]) + +# Check X11 + +AC_PATH_XTRA +if test "x$no_x" = "xyes"; then + AC_MSG_ERROR([X11 is required.]) +else + S9XFLGS="$S9XFLGS $X_CFLAGS" + S9XLIBS="$S9XLIBS $X_PRE_LIBS -lX11 -lXext $X_LIBS $X_EXTRA_LIBS" +fi + +# Check for headers + +snes9x_have_stdint_h=""; + +AC_CHECK_HEADER([strings.h], +[ + S9XDEFS="$S9XDEFS -DHAVE_STRINGS_H" +]) + +AC_CHECK_HEADER([sys/ioctl.h], +[ + S9XDEFS="$S9XDEFS -DHAVE_SYS_IOCTL_H" +]) + +AC_CHECK_HEADER([stdint.h], +[ + S9XDEFS="$S9XDEFS -DHAVE_STDINT_H" + snes9x_have_stdint_h="-DHAVE_STDINT_H" +]) + +AC_CHECK_HEADERS([unistd.h sys/socket.h]) + +# Check whether the size of pointer is int. + +if test "x$snes9x_have_stdint_h" = "x"; then + AC_MSG_CHECKING([whether the size of pointer is int]) + + AC_TRY_RUN( + [ + int main (void) + { + return (!(sizeof(void *) == sizeof(int))); + } + ], + [snes9x_ptr_is_int="yes"], [snes9x_ptr_is_int="no"]) + + if test "x$snes9x_ptr_is_int" = "xyes"; then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + S9XDEFS="$S9XDEFS -DPTR_NOT_INT" + fi +fi + +# Check whether right shift is arithmetic or not + +AC_DEFUN([AC_S9X_CHECK_SAR], +[ + AC_MSG_CHECKING([whether right shift $1 is arithmetic]) + + OLD_CXXFLAGS="[$]CXXFLAGS" + CXXFLAGS="[$]OLD_CXXFLAGS $snes9x_have_stdint_h" + + AC_TRY_RUN( + [ + #ifdef HAVE_STDINT_H + #include + typedef int8_t int8; + typedef int16_t int16; + typedef int32_t int32; + typedef int64_t int64; + #else + typedef signed char int8; + typedef signed short int16; + typedef signed int int32; + #ifdef __GNUC__ + __extension__ + #endif + typedef long long int64; + #endif + + int main (void) + { + $1 i; + + i = -1; + i >>= 1; + + return (i < 0 ? 0 : 1); + } + ], + [snes9x_sar_$1="yes"], [snes9x_sar_$1="no"]) + + CXXFLAGS="[$]OLD_CXXFLAGS" + + if test "x$snes9x_sar_$1" = "xno"; then + AC_MSG_RESULT([no]) + else + S9XDEFS="$S9XDEFS -DRIGHTSHIFT_$1_IS_SAR" + AC_MSG_RESULT([yes]) + fi +]) + +AC_S9X_CHECK_SAR([int8]) +AC_S9X_CHECK_SAR([int16]) +AC_S9X_CHECK_SAR([int32]) +AC_S9X_CHECK_SAR([int64]) + +if test "x$snes9x_sar_int8" = "xyes" -a "x$snes9x_sar_int16" = "xyes" -a "x$snes9x_sar_int32" = "xyes" -a "x$snes9x_sar_int64" = "xyes"; then + S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/-DRIGHTSHIFT_int8_IS_SAR//'`" + S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/-DRIGHTSHIFT_int16_IS_SAR//'`" + S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/-DRIGHTSHIFT_int32_IS_SAR//'`" + S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/-DRIGHTSHIFT_int64_IS_SAR//'`" + S9XDEFS="$S9XDEFS -DRIGHTSHIFT_IS_SAR" +fi + +# Check if we have sound code for this platform. + +AC_ARG_ENABLE([sound], + [AS_HELP_STRING([--enable-sound], + [enable sound if available (default: yes)])], + [], [enable_sound="yes"]) + +if test "x$enable_sound" = "xyes"; then + AC_MSG_CHECKING([whether sound is supported on this platform]) + if test "x$snes9x_cv_linux_os" = "xyes"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_WARN([Your OS is not Linux. Build without sound support.]) + enable_sound="no" + fi +fi + +if test "x$enable_sound" = "xyes"; then + AC_CHECK_HEADER([pthread.h], + [ + S9XDEFS="$S9XDEFS -DUSE_THREADS" + S9XLIBS="$S9XLIBS -lpthread" + ]) +else + S9XDEFS="$S9XDEFS -DNOSOUND" +fi + +# Output. + +S9XFLGS="$CXXFLAGS $CPPFLAGS $LDFLAGS $S9XFLGS" +S9XLIBS="$LIBS $S9XLIBS" + +S9XFLGS="`echo \"$S9XFLGS\" | sed -e 's/ */ /g'`" +S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/ */ /g'`" +S9XLIBS="`echo \"$S9XLIBS\" | sed -e 's/ */ /g'`" +S9XFLGS="`echo \"$S9XFLGS\" | sed -e 's/^ *//'`" +S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/^ *//'`" +S9XLIBS="`echo \"$S9XLIBS\" | sed -e 's/^ *//'`" + +AC_SUBST(S9XFLGS) +AC_SUBST(S9XDEFS) +AC_SUBST(S9XLIBS) +AC_SUBST(S9XZSNESFX) +AC_SUBST(S9XZSNESC4) +AC_SUBST(S9XNASM) +AC_SUBST(S9XDEBUGGER) +AC_SUBST(S9XNETPLAY) +AC_SUBST(S9XZIP) +AC_SUBST(S9XJMA) + +rm config.info 2>/dev/null + +cat >config.info < + + + + + + + Snes9x for Unix + + +

Snes9x for Unix

+

Introduction

+

What is Snes9x?

+

+ Snes9x is a portable, freeware Super Nintendo Entertainment System (SNES) emulator. It basically allows you to play most games designed for the SNES and Super Famicom Nintendo game systems on your Mac, Linux, Windows and so on. The games include some real gems that were only ever released in Japan. +

+

+ The original Snes9x project was founded by Gary Henderson and Jerremy Koot as a collaboration of their earlier attempts at SNES emulation (Snes96 and Snes97.) Over the years the project has grown and has collected some of the greatest talent in the emulation community (at least of the SNES variety) some of which have been listed in the credits section, others have helped but have been loss in the course of time. +

+

Why Emulate the SNES?

+

+ Well, there are many reasons for this. The main reason is for nostalgic purposes. In this day and age, it's hard to find an SNES and many good games. Plus, many of us over the course of time have lost our beloved consoles (may they R.I.P) but still have our original carts. With no other means to play them, we turn to emulators. Besides this there are many conveniences of doing this on the computer instead of dragging out your old system. +

+

Advantages consist of :

+
    +
  • ability to save in any location of the game, despite how the game was designed. It's amazingly useful when you don't want to redo the same level over and over.
  • +
  • built-in peripherals. This is anything from multi-taps, to super scopes, to cheat devices.
  • +
  • ability to rip sprites and music for your own personal use.
  • +
  • easier to organize and no stacks of cartridges.
  • +
  • filters can be used to enhance graphics and sounds on old games.
  • +
+

As with all things there are disadvantages though :

+
    +
  • if you have an ancient computer, you aren't likely to get a playable experience.
  • +
  • some games are still unemulated (though this a very tiny minority.)
  • +
  • the emulator can be difficult for new users to configure.
  • +
+

Getting Started

+

+ Usage: +

+
    +
  • snes9x [options] <ROM image file>
  • +
+

+ Use -help option to see available options. +

+

+ SNES ROM images come in lots of different formats. Snes9x supports zipped ROMs as long as there is only 1 per zip file. Also Snes9x can open gzip/jma compressed file. +

+

Game Color System

+

+ By default, Snes9x displays the ROM information when a ROM is first loaded. Depending on the colors used you can tell whether or not a ROM is a good working ROM, or if it's been altered or is corrupted. +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + +
    whitethe ROM should be a perfect working copy.
    greenthe ROM is mode 1 interleaved.
    orangethe ROM is mode 2 interleaved.
    aquathe ROM is Game Doctor 24M interleaved.
    yellowthe ROM has probably been altered. Either it's a translation, PD ROM, hacked, or possibly a bad ROM. It may also be an overdumped ROM.
    redthe ROM is definitely hacked and that a proper version should be exist. Some ROM Tools such as NSRT can also fix these ROMs.
  • +
+

+ When asking for help on the Snes9x forums, please list the color and CRC32 that is displayed. This will help to find out what the problem is. +

+

+ These colors do NOT signify whether a game will work or not. It is just a means for reference so we can understand what may or may not be a problem. Most often the problem with games that don't work it's because they are corrupt or are a bad dump and should be redumped. +

+

SNES Joypad Emulation

+

+ The default key mapping for joypad 1 is as follows: +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    U or UpUp direction
    J or DownDown direction
    H or LeftLeft direction
    K or RightRight direction
    DA button
    CB button
    SX button
    XY button
    AL button
    ZR button
    SpaceSelect button
    ReturnStart button
  • +
+

+ And the default key mapping for joypad 2 is as follows: +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Keypad 8Up direction
    Keypad 2Down direction
    Keypad 4Left direction
    Keypad 6Right direction
    Page UpA button
    Page DownB button
    HomeX button
    EndY button
    InsertL button
    DeleteR button
    Keypad +Select button
    Keypad EnterStart button
  • +
+

Pausing and Quitting the Game

+

+ Don't forget how to pause the game and quit Snes9x. +

+
    +
  • + + + + + + + + + + +
    ESCquits Snes9x.
    Pause or Scroll Lockpauses the game.
  • +
+

Requirements

+

System Requirements

+

+ Relatively fast CPU like Pentium 2 or PowerPC G3 300MHz or higher, and 16MB memory or more.
+ Certain games use added hardware which will require a faster machine. The specs listed above is the minimum to use Snes9x in any playable form. It is recommended that you get a semi-modern machine with a 800MHz CPU if you want good results. A 1GHz CPU is recommended for those that want a near perfect experience. +

+

+ X Window System with 15, 16, 24 or 32-bit color depth. For maximum emulation speed, have the X server switched to 15 or 16-bit. +

+

Software

+

+ You will need access to SNES ROM images in .smc, .sfc, .fig, etc., format otherwise you will have nothing to run! Some home-brewed ROM images can be downloaded from http://www.zophar.com/.
+ Please note, it is illegal in most countries to have commercial ROM images without also owning the actual SNES ROM cartridges, and even then you may be liable under various EULAs. +

+

Controllers Support

+

Input Devices

+

+ The real SNES has two ports to connect input devices. Usually 1P and 2P SNES joypads are connected but various devices and adopters can be plugged. +

+

+ Use -port1 and/or -port2 options to specify which input device to be emulated in each port. +

+
    +
  • + + + + + + + + + + + + + + + + + + +
    Multi Player 5known as Multi Tap; a five player adapter, allowing up to five people to play at once on games that supported it.
    SNES Mousea 2-button mouse, originally supplied with a paint program.
    Super Scopea light-gun; it used infrared to provide wireless communication between the gun and the console unit.
    Justifiera gun similar to Super Scope, supported with one gun-shooting game.
  • +
+

+ Snes9x can emulate those input devices with the keyboard and mouse. The default mapping is as follows: +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + +
    Mouse LeftSNES Mouse Left button / SuperScope Fire button / Justifier trigger
    Mouse RightSNES Mouse Right button / SuperScope Cursor button / Justifier Start button
    Mouse Centerwhen you want to shot offscreen, fire with pressing this button.
    `SuperScope Turbo toggle switch
    /SuperScope Pause button
  • +
+

Peripherals Support

+

Satellaview

+

+ Snes9x partially emulates Satellaview system, so-called BS-X. To play BS games or read BS magazines with the BS-X base cartridge, do the following. +

+
    +
  • If you have .srm files of BS games which were created by Snes9x 1.43 or earlier, trash them first.
  • +
  • Prepare the BS-X ROM image. Make sure the file is uncompressed and doesn't have a header.
  • +
  • Rename the BS-X ROM image to 'BS-X.bin'.
  • +
  • Put BS-X.bin in the proper directory. ~/.snes9x/bios by default.
  • +
  • Launch BS-X.bin as you usually play SNES games.
  • +
  • Set your name and gender.
  • +
  • Launch a BS game. The game is launched for the first time and its .srm doesn't exist, so BS-X.srm is loaded instead.
  • +
  • Once you launched the game, its .srm is created and loaded from the next time.
  • +
+

+ If you launch a BS game for the first time without BS-X.srm, maybe the game doesn't work properly.
+ To boot up BS games from BS-X town, use -bsxbootup option. +

+

Sufami Turbo

+

+ To play Sufami Turbo games, do the following. +

+
    +
  • Prepare the Sufami Turbo base cartridge ROM image. Make sure the file is uncompressed and doesn't have a header.
  • +
  • Rename the base cartridge ROM image to 'STBIOS.bin'.
  • +
  • Put STBIOS.bin in the proper directory. ~/.snes9x/bios by default.
  • +
  • Use -multi, -carta and -cartb options to play games. +
    +
    -multi
    +
    BIOS only
    +
    -multi -carta game1.smc
    +
    BIOS + game1.smc in Slot A
    +
    -multi -cartb game2.smc
    +
    BIOS + game2.smc in Slot B
    +
    -multi -carta game1.smc -cartb game2.smc
    +
    BIOS + game1.smc in Slot A + game2.smc in Slot B
    +
  • +
+

+ Note that the base cartridge can initialize SRAM for only the game in slot A, so you have to set every game in slot A and launch at least once.
+ If no games are set in the slots, only the base cartridge runs.
+ If you have a combined ROM image, split it to each games and the base cartridge. NSRT will help you. +

+

Other Multiple Cartridge Games

+

+ Use -multi option as follows: +

+
    +
  • -multi -carta maincart.smc -cartb addon.smc
  • +
+

+ Currently supported: Same Game +

+

Game Saving

+

+ Many SNES games take a very long time to complete from start to finish, so they allowed your progress to be saved at the predefined places chosen by the game designers. The game cartridge contains a battery-backed RAM, known as SRAM, and your save data remain in this SRAM until the battery shutoff. +

+

+ Snes9x has two methods for saving games. One is the same as of the real SNES shown above; emulating SRAM. The SRAM contents are saved into a file (.srm) so you don't need to be worried about the battery shutoff. The other is more convenient way than the real SNES; 'freezing' or 'snapshotting' the game. It means saving the whole game state anywhere you want, beyond the game designers' intent - ideal for saving your game just before a tricky bit! +

+

Using the SRAM File

+

+ It's easy enough, just save the game as you do with the real SNES. Snes9x outputs the contents of the emulated SRAM into a file (.srm) when you load a new game or quit Snes9x. This file is automatically loaded the next time you play the game. Files are stored in ~/.snes9x/sram by default. +

+

Freezing and Defrosting the Game State

+

+ Snes9x provides 9 slots for freezing the whole of your game state. During the game, press Shift + F1 to F9 to save the state, and just F1 to F9 to load it again later. Files are stored in ~/.snes9x/savestate by default. +

+

Real-Time Clock Emulation

+

+ Some games have a battery-backed real-time clock (RTC) in their cartridge to bring a real-time event in the game. Snes9x saves the state of RTC into a file (.rtc), stored in ~/.snes9x/sram by default, and also into a freeze file.
+ Note that because it's a 'real-time' clock, when these files are loaded, the emulated clock is automatically advanced in reference to your system's time and date. +

+

Fool-Proof System

+

+ If you quit the game by error without saving your long-time progress, try to press F10 key and find '.oops' file in the same directory as freeze files. It's a freeze file automatically generated if you don't save anything for a long time. +

+

Cheat Support

+

+ Cheat codes allow you to cheat at games. They might give you more lives, infinite health, enable special powers normally only activated when a special item is found, and etc. Three major formats are well-known: Game Genie, Pro-Action Reply (PAR) and Gold Finger. Many existing codes can be found via Internet. +

+

+ Snes9x supports all the three formats. Cheats are saved in .cht files and are automatically loaded the next time a game with the same filename is loaded. +

+

+ Technically, a cheat code consists of two elements; an address in SNES memory map where you want to overwrite, and a value which is overwritten on the address.
+ Beware of cheat codes designed for a ROM from a different region compared to the one you are playing or for a different version of the ROM; the source of the cheats should tell you which region and for which version of the game they were designed for. If you use a code designed for a different region or version of your game, the game might crash or do other weird things because the cheat address might be different between regions and versions. +

+

How to Enter Cheat Code

+

+ Use -gamegenie, -actionreplay and -goldfinger options to enter your cheat code. Files are stored in ~/.snes9x/cheat by default. +

+

Movie Support

+

+ Movie support allows you to record your actions while playing a game. This can be used for your own personal playback or to show other people that you can do something without them having to be around when you did it. +

+

Recording the Movie

+

+ Press Shift + 1 to begin recording and Shift + 2 to stop recording. Also you can use -recordmovie option to record from the start of the game. +

+

Playing Back the Movie

+

+ Press Shift + 3 and enter the movie filename (.smv) to play the movie. Also you can use -playmovie option to play the movie recorded from the start of the game. +

+

Miscellaneous

+

Where the Files are Stored

+

+ By default, ~/.snes9x is used to load/save files related to Snes9x. The subdirectories Snes9x refers to are as follows: +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    romROM image files
    sramSRAM files (.srm), RTC files (.rtc)
    savestatefreeze (snapshot, savestate) files
    screenshotscreenshot files
    spcSPC files (.spc)
    cheatcheat files (.cht)
    patchIPS files (.ips)
    biosBIOS image files
  • +
+

Using IPS or UPS Patch

+

+ Snes9x automatically patches without overwriting the ROM image. +

+
    +
  • Put the IPS or UPS file into the proper directory. ~/.snes9x/patch by default.
  • +
  • Rename the name to the same as the ROM image (except extension, it is '.ips' or '.ups').
  • +
  • (IPS only) If you want to use multiple IPS files at a time, set their extensions to '.000.ips', '.001.ips', ...
  • +
  • Open and load the ROM image.
  • +
+

SPC File Dumping

+

+ SPC file (.spc) is the freeze state of only sound part, so it is known as SNES music data file. Dump the SPC file by Snes9x and play the file by SPC players. +

+

+ Press Alt/Control + F1 to dump a SPC file. It's stored in ~/.snes9x/spc by default.
+ Note that the actual dumping occurs at the next note-on event so that you can dump the BGM from just the beginning. +

+

Additional Keyboard Controls

+

+ Snes9x has various functions to play games with fun. The default mapping is as follows: +

+
    +
  • + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Control + Shift + ESChardware reset as you turn off and on the power switch.
    Shift + ESCsoftware reset as you press the reset button.
    F12saves the freeze file you specify.
    F11loads the freeze file you specify.
    Shift + F1-F9quickly saves a freeze file into the slot 1-9.
    F1-F9quickly loads a freeze file from the slot 1-9.
    F10tries to load the fool-proof freeze file you specify.
    Alt/Control + F1dumps a SPC file.
    Print Screentakes a screenshot.
    Shift + 1begins recording a movie.
    Shift + 2ends recording a movie.
    Shift + 3plays the movie you specify.
    Tabturbo mode while pressing.
    Shift + Tabtoggles turbo mode on/off.
    =increases frame skip rate / switches to auto-frame rate adjustment.
    -decreases frame skip rate / switches to auto-frame rate adjustment.
    Shift + =increases frame time in 1ms steps: works only with auto-frame rate adjustment.
    Shift + -decreases frame time in 1ms steps: works only with auto-frame rate adjustment.
    Alt + =increases frame skip rate in turbo mode.
    Alt + -decreases frame skip rate in turbo mode.
    Control + =increases speed in turbo mode.
    Control + -decreases speed in turbo mode.
    6toggles swapping of joypad one and two.
    Alt/Control + F4-F11toggles sound channel 1-8 on/off.
    Alt/Control + F12enables all sound channels.
    1-4toggles background 1-4 on/off.
    5toggles sprites on/off.
    9(not recommended) toggles transparency effects on/off.
    Backspace(not recommended) toggles emulation of graphics window effects on/off.
    0(not recommended) toggles H-DMA emulation on/off.
  • +
+

Gamepad Support

+

+ The Linux port makes use of the v1.x joystick kernel drivers written by Vojtech Pavlik to allow the use of a wide variety of different gamepad types to control SNES games.
+ If you are still using the older versions of the drivers, you can download the latest driver version from http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/.
+ Refer to the documentation that comes with the drivers to enable support for your type of gamepad in Snes9x. +

+

Configuring Settings and Key Mapping

+

+ The Unix port of Snes9x reads the preferences file snes9x.conf when launching, if it exists.
+ To make your snes9x.conf, copy the template file snes9x.conf.default, rename it to 'snes9x.conf', put it in the proper directory (~/.snes9x by default), and edit it as you like. The document control-inputs.txt will help you to edit the keyboard/gamepad mapping. +

+

Building Snes9x from Source

+

+ The source release of Snes9x comes with a configure file that will try to make a Makefile suitable for your system. To invoke it go into the snes9x/unix directory inside the distribution:
+

+
    +
  • cd snes9x-1.xx-src/snes9x/unix
  • +
+

+ Then run configure and finish with running make if it went well. +

+
    +
  • ./configure
    + make
  • +
+

+ configure takes several arguments. Further documentation about this is available by running ./configure --help. +

+

Compatibility

+

Compatibility with Other Ports

+

+ All the files generated by Snes9x are compatible between platforms, except for the extension of the freeze files. +

+

Compatibility with Other SNES Emulators

+

+ Cheat files (.cht) are common between Snes9x and ZSNES. RTC files (.rtc) are common between Snes9x and bsnes. SRAM files (.srm) should be common among all SNES emulators. +

+

Problems

+

Problems with ROMs

+

+ If Snes9x just displays a black screen for over 10 seconds after you've loaded a ROM image, then one of the following could be true: +

+
    +
  • You just loaded some random ROM image and it isn't even a SNES game or you only have part of the image. Snes9x only emulates games designed for the Super NES, not NES, or Master System, or Game Boy, or <insert your favorite old games system here>.
  • +
  • Someone has edited the Nintendo ROM information area inside the ROM image and Snes9x can't work out what format the ROM image is in. Try playing around with the ROM format options.
  • +
  • The ROM image is corrupt. If you're loading from CD, I know it might sound silly, but is the CD dirty? Clean, unhacked ROM images will display [checksum ok] when first loaded, corrupt or hacked ROMs display [bad checksum].
  • +
  • The original SNES ROM cartridge had additional hardware inside that is not emulated yet and might never be.
  • +
  • You might be using a file that is compressed in a way Snes9x does not understand.
  • +
+

+ The following ROMs are known to currently not to work with any version of Snes9x: +

+
    +
  • + + + + + + + + + + + + + + +
    SD Gundam GXDSP-3
    Hayazashi Nidan Morita ShougiSeta-11
    Hayazashi Nidan Morita Shougi 2Seta-18
  • +
+

Problems with Sounds

+

+ If you hear crackling noise during the game, try these options to eliminate the noise. +

+
    +
  • +
    -buffersize
    +
    Sound generating buffer size in millisecond. Larger value will be safe from crackling noise, but may cause lag.
    +
    -fragmentsize
    +
    Fragment size of the system sound driver in byte. It must be a power of 2, and must be the value the driver accepts.
    +
    -soundsync
    +
    When this option is on, Snes9x tries and ensures all available samples are buffered so there are no overruns.
    +
    -inputrate
    +
    Adjusts the sound rate through resampling. For every -inputrate samples generated by the SNES, -playbackrate samples will be produced.
    +
  • +
+

Technical Information

+

What's Emulated?

+
    +
  • 65c816 main CPU.
  • +
  • Variable length machine cycles.
  • +
  • 8 channel DMA and H-DMA.
  • +
  • H-IRQ, V-IRQ and NMI.
  • +
  • Sony SPC700 sound CPU.
  • +
  • Sound DSP, with eight 16-bit, stereo channels, compressed samples, hardware envelope processing, echo, pitch modulation and digital FIR sound filter.
  • +
  • SRAM, a battery-backed RAM.
  • +
  • All background modes, 0 to 7.
  • +
  • All screen resolutions, 256x224, 256x239, 512x224, 512x239, 512x448 and 512x478.
  • +
  • Pseudo hi-res mode.
  • +
  • 8x8, 16x8 and 16x16 tile sizes, flipped in either direction.
  • +
  • 32x32, 32x64, 64x32 and 64x64 screen tile sizes.
  • +
  • Vertical and horizontal offset-per-tile.
  • +
  • 128 8x8, 16x16, 32x32 and 64x64 sprites, flipped in either direction.
  • +
  • Sub-screen and fixed color blending effects.
  • +
  • Mosaic effects.
  • +
  • Mode 7 screen rotation, scaling and screen flipping.
  • +
  • Single and dual graphic clip windows, with all four logic combination modes.
  • +
  • Color blending effects only inside or outside a window.
  • +
  • Palette changes during frame.
  • +
  • Direct color mode - uses tile and palette-group data directly as RGB value.
  • +
  • SNES Mouse.
  • +
  • Super Scope, emulated using computer mouse.
  • +
  • Justifier, by Konami, similar to the Super Scope and used only in Lethal Enforcers.
  • +
  • Multi Player 5, allowing up to five people to play games simultaneously on games that support that many players.
  • +
  • Super FX, a fast RISC CPU used in several games.
  • +
  • SA-1, a faster version of main CPU with some functions, used in several games.
  • +
  • DSP-1, a custom chip used in several games, mainly racing games.
  • +
  • DSP-2, a custom chip used only in Dungeon Master.
  • +
  • DSP-4, a custom chip used only in Top Gear 3000.
  • +
  • C4, a sprite scaler/rotator/line drawer/simple maths co-processor chip used only in Megaman X2 and X3.
  • +
  • Seta-10, a custom chip used only in F1 Race of Champions 2.
  • +
  • OBC1, a sprite management chip used only in Metal Combat.
  • +
  • S-DD1, a data decompression chip used only in Star Ocean and Street Fighter 2 Alpha.
  • +
  • SPC7110, similar in use to S-DD1, used in a few Hadoson games.
  • +
  • S-RTC, a real-time clock chip, used only in Dai Kaijyu Monogatari 2.
  • +
  • Satellaview and BS-X, only partially.
  • +
+

What's Not?

+
    +
  • Exact sub-cycle timings of communication among most of parts - main CPU, sound CPU, DMA, H-DMA, IRQ, NMI, and so on. Snes9x cannot run games that require severe timings!
  • +
  • Any other odd chips that manufactures sometimes placed inside the cartridge to enhance games and as a nice side-effect, also act as an anti-piracy measure. (DSP-3, Seta-11 and Seta-18, as examples)
  • +
  • The expansion slot found in many carts.
  • +
+

Custom Chips

+

Super FX

+

+ The Super FX is a 10.5/21MHz RISC CPU developed by Argonaut Software used as a game enhancer by several game titles. Released SNES Super FX games included Yoshi's Island, Doom, Winter Gold, Dirt Trax FX, StarFox, Stunt Race FX and Vortex. +

+

SA-1

+

+ The SA-1 is a fast, custom 65c816 8/16-bit processor, the same as inside the SNES itself, but clocked at 10MHz compared to a maximum of 3.58MHz for the CPU inside the SNES. The SA-1 isn't just a CPU; it also contains some extra circuits developed by Nintendo which includes some very fast RAM, a memory mapper, DMA and, several real-time timers. +

+

C4

+

+ The C4 is custom Capcom chip used only in the Megaman X2 and Megaman X3 games. It can scale and rotate images, draw line-vector objects and do some simple maths to rotate them. +

+

S-DD1

+

+ The S-DD1 is a custom data decompression chip that can decompress data in real-time as the SNES DMA's data from the ROM to RAM. Only two games use the chip: Star Ocean and Street Fighter Alpha 2. +

+

SPC7110

+

+ The SPC7110 is a compression and memory mapping chip. It provides a few extra features as well. It functions as an RTC interface, and has a multiply/divide unit that has more precision than the SNES. The SPC7110 is found only in 4 games: Super Power League 4, Far East of Eden Zero, Far East of Eden Zero - Shounen Jump no Shou and Momotaro Dentetsu Happy. +

+

Others

+

+ Other known custom chips: DSP-1, DSP-2, DSP-3, DSP-4, Seta-10, Seta-11, Seta-18, OBC1 and S-RTC. +

+

Credits

+
    +
  • Jerremy Koot for all his hard work on previous versions of Snes96, Snes97 and Snes9x.
  • +
  • Ivar for the original Super FX C emulation, DSP-1 emulation work and information on both chips.
  • +
  • zsKnight and _Demo_ for the Intel Super FX assembler, DSP-1 and C4 emulation code.
  • +
  • zsKnight and _Demo_ for all the other ideas and code I've nicked off them; they've nicked lots of my ideas and information too!
  • +
  • John Weidman and Darkforce for the S-RTC emulation information and code.
  • +
  • Kreed and Maxim Stepin for excellent image enhancer routines.
  • +
  • Nose000 for code changes to support various Japanese SNES games.
  • +
  • Neill Corlett for the IPS patching support code.
  • +
  • DiskDude's SNES Kart v1.6 document for the Game Genie(TM) and Pro-Action Replay cheat system information.
  • +
  • Lord ESNES for some nice chats and generally useful stuff.
  • +
  • Lee Hyde (lee@jlp1.demon.co.uk) for his quest for sound information and the Windows 95 icon.
  • +
  • Shawn Hargreaves for the rather good Allegro 3.0 DOS library.
  • +
  • Robert Grubbs for the SideWinder information - although I didn't use his actual driver in the end.
  • +
  • Steve Snake for his insights into SNES sound sample decompression.
  • +
  • Vojtech Pavlik for the Linux joystick driver patches.
  • +
  • Maciej Babinski for the basics of Linux's DGA X server extensions.
  • +
  • Alexander Larsson for the GGI Linux port code.
  • +
  • Harald Fielker for the original sound interpolation code (never used directly due to problems).
  • +
  • Takehiro TOMINAGA for many speed up suggestions and bug fixes.
  • +
  • Predicador for the Windows icon.
  • +
  • Lindsey Dubb for the mode 7 bi-linear filter code and the improved color addition and subtraction code.
  • +
  • Anti Resonance for his super-human efforts to help get his fast sound CPU core and sound DSP core working in Snes9x.
  • +
  • Brad Martin and TRAC for better and refined sound emulation.
  • +
  • ernstp and entonne for patches and testing on Linux PPC.
  • +
  • byuu for the most exact timing information and tons of the newest technical findings.
  • +
  • Blargg for the most accurate timings between sound CPU and DSP and exact sound emulation codes.
  • +
  • pagefault, TRAC, Dark Force, byuu, and others who have donated ideas and/or code to the project.
  • +
+

+ Nintendo is a trademark.
+ Super NES, Super Famicon, Super Scope and Super FX are trademarks of Nintendo.
+ Sufami Turbo is a trademark of Bandai Co., Ltd.
+ Game Genie is a trademark of Lewis Galoob Toys, Inc.
+ Pro Action Replay is a trademark of Datel Inc.
+ Macintosh, Mac and Mac OS X are trademarks of Apple Computer, Inc.
+ UNIX is a trademark of The Open Group.
+ Linux is a trademark of Linus Torvalds.
+ Windows is a trademark of Microsoft Corp.
+ Intel is a trademark of Intel Corp.
+ PowerPC is a trademark of International Business Machines Corp.
+ Sony is a trademark of Sony Corp.
+ Konami and Justifier are trademarks of Konami Corp.
+ Hudson is a trademark of Husdon Soft Co., Ltd.
+ Capcom is a trademark of Capcom Co., Ltd. +

+

+ Gary Henderson +

+

+ Edited for Unix port by: zones (kasumitokoduck@yahoo.com)
+ Updated most recently by: 2009/12/20 zones +

+ + diff --git a/unix/install-sh b/unix/install-sh new file mode 100644 index 00000000..4d4a9519 --- /dev/null +++ b/unix/install-sh @@ -0,0 +1,323 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2005-05-14.22 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= +dstarg= +no_target_directory= + +usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: +-c (ignored) +-d create directories instead of installing files. +-g GROUP $chgrpprog installed files to GROUP. +-m MODE $chmodprog installed files to MODE. +-o USER $chownprog installed files to USER. +-s $stripprog installed files. +-t DIRECTORY install into DIRECTORY. +-T report an error if DSTFILE is a directory. +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -c) shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit $?;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t) dstarg=$2 + shift + shift + continue;; + + -T) no_target_directory=true + shift + continue;; + + --version) echo "$0 $scriptversion"; exit $?;; + + *) # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + test -n "$dir_arg$dstarg" && break + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dstarg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dstarg" + shift # fnord + fi + shift # arg + dstarg=$arg + done + break;; + esac +done + +if test -z "$1"; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src ;; + esac + + if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + mkdircmd=: + chmodcmd= + else + mkdircmd=$mkdirprog + fi + else + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dstarg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dstarg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dstarg: Is a directory" >&2 + exit 1 + fi + dst=$dst/`basename "$src"` + fi + fi + + # This sed command emulates the dirname command. + dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` + + # Make sure that the destination directory exists. + + # Skip lots of stat calls in the usual case. + if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + shift + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + if test ! -d "$pathcomp"; then + $mkdirprog "$pathcomp" + # mkdir can fail with a `File exist' error in case several + # install-sh are creating the directory concurrently. This + # is OK. + test -d "$pathcomp" || exit + fi + pathcomp=$pathcomp/ + done + fi + + if test -n "$dir_arg"; then + $doit $mkdircmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + + else + dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Copy the file name to the temp name. + $doit $cpprog "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now rename the file to the real destination. + { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ + || { + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit 1 + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + } + } + fi || { (exit 1); exit 1; } +done + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit 0 +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/unix/unix.cpp b/unix/unix.cpp new file mode 100644 index 00000000..ad50023c --- /dev/null +++ b/unix/unix.cpp @@ -0,0 +1,1865 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 +#include +#include +#ifdef HAVE_STRINGS_H +#include +#endif +#ifdef USE_THREADS +#include +#include +#endif +#include +#include +#include +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +#ifndef NOSOUND +#include +#include +#endif +#ifdef JOYSTICK_SUPPORT +#include +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "apu/apu.h" +#include "gfx.h" +#include "snapshot.h" +#include "controls.h" +#include "cheats.h" +#include "movie.h" +#include "logger.h" +#include "display.h" +#include "conffile.h" +#ifdef NETPLAY_SUPPORT +#include "netplay.h" +#endif +#ifdef DEBUGGER +#include "debug.h" +#endif + +#ifdef NETPLAY_SUPPORT +#ifdef _DEBUG +#define NP_DEBUG 2 +#endif +#endif + +typedef std::pair strpair_t; + +ConfigFile::secvec_t keymaps; + +#define FIXED_POINT 0x10000 +#define FIXED_POINT_SHIFT 16 +#define FIXED_POINT_REMAINDER 0xffff +#define SOUND_BUFFER_SIZE (1024 * 16) +#define SOUND_BUFFER_SIZE_MASK (SOUND_BUFFER_SIZE - 1) + +static volatile bool8 block_signal = FALSE; +static volatile bool8 block_generate_sound = FALSE; + +static const char *sound_device = NULL; + +static const char *s9x_base_dir = NULL, + *rom_filename = NULL, + *snapshot_filename = NULL, + *play_smv_filename = NULL, + *record_smv_filename = NULL; + +static char default_dir[PATH_MAX + 1]; + +static const char dirNames[13][32] = +{ + "", // DEFAULT_DIR + "", // HOME_DIR + "", // ROMFILENAME_DIR + "rom", // ROM_DIR + "sram", // SRAM_DIR + "savestate", // SNAPSHOT_DIR + "screenshot", // SCREENSHOT_DIR + "spc", // SPC_DIR + "cheat", // CHEAT_DIR + "patch", // IPS_DIR + "bios", // BIOS_DIR + "log", // LOG_DIR + "" +}; + +struct SUnixSettings +{ + bool8 JoystickEnabled; + bool8 ThreadSound; + uint32 SoundBufferSize; + uint32 SoundFragmentSize; +}; + +struct SoundStatus +{ + int sound_fd; + uint32 fragment_size; + uint32 err_counter; + uint32 err_rate; + int32 samples_mixed_so_far; + int32 play_position; +}; + +static SUnixSettings unixSettings; +static SoundStatus so; + +#ifndef NOSOUND +static uint8 Buf[SOUND_BUFFER_SIZE]; +#endif + +#ifdef USE_THREADS +static pthread_t thread; +static pthread_mutex_t mutex; +#endif + +#ifdef JOYSTICK_SUPPORT +static uint8 js_mod[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +static int js_fd[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; +static const char *js_device[8] = { "/dev/js0", "/dev/js1", "/dev/js2", "/dev/js3", "/dev/js4", "/dev/js5", "/dev/js6", "/dev/js7" }; +#endif + +#ifdef NETPLAY_SUPPORT +static uint32 joypads[8]; +static uint32 old_joypads[8]; +#endif + +bool8 S9xMapDisplayInput (const char *, s9xcommand_t *); +s9xcommand_t S9xGetDisplayCommandT (const char *); +char * S9xGetDisplayCommandName (s9xcommand_t); +void S9xHandleDisplayCommand (s9xcommand_t, int16, int16); +bool S9xDisplayPollButton (uint32, bool *); +bool S9xDisplayPollAxis (uint32, int16 *); +bool S9xDisplayPollPointer (uint32, int16 *, int16 *); + +static long log2 (long); +static void SoundTrigger (void); +static void InitTimer (void); +static void NSRTControllerSetup (void); +static int make_snes9x_dirs (void); +#ifndef NOSOUND +static void * S9xProcessSound (void *); +#endif +#ifdef JOYSTICK_SUPPORT +static void InitJoysticks (void); +static void ReadJoysticks (void); +#endif + + +void _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext) +{ + *drive = 0; + + const char *slash = strrchr(path, SLASH_CHAR), + *dot = strrchr(path, '.'); + + if (dot && slash && dot < slash) + dot = NULL; + + if (!slash) + { + *dir = 0; + + strcpy(fname, path); + + if (dot) + { + fname[dot - path] = 0; + strcpy(ext, dot + 1); + } + else + *ext = 0; + } + else + { + strcpy(dir, path); + dir[slash - path] = 0; + + strcpy(fname, slash + 1); + + if (dot) + { + fname[dot - slash - 1] = 0; + strcpy(ext, dot + 1); + } + else + *ext = 0; + } +} + +void _makepath (char *path, const char *, const char *dir, const char *fname, const char *ext) +{ + if (dir && *dir) + { + strcpy(path, dir); + strcat(path, SLASH_STR); + } + else + *path = 0; + + strcat(path, fname); + + if (ext && *ext) + { + strcat(path, "."); + strcat(path, ext); + } +} + +static long log2 (long num) +{ + long n = 0; + + while (num >>= 1) + n++; + + return (n); +} + +void S9xExtraUsage (void) +{ + /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */ + + S9xMessage(S9X_INFO, S9X_USAGE, "-multi Enable multi cartridge system"); + S9xMessage(S9X_INFO, S9X_USAGE, "-carta ROM in slot A (use with -multi)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-cartb ROM in slot B (use with -multi)"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + +#ifdef JOYSTICK_SUPPORT + S9xMessage(S9X_INFO, S9X_USAGE, "-nogamepad Disable gamepad reading"); + S9xMessage(S9X_INFO, S9X_USAGE, "-paddev1 Specify gamepad device 1"); + S9xMessage(S9X_INFO, S9X_USAGE, "-paddev1 Specify gamepad device 2"); + S9xMessage(S9X_INFO, S9X_USAGE, "-paddev1 Specify gamepad device 3"); + S9xMessage(S9X_INFO, S9X_USAGE, "-paddev1 Specify gamepad device 4"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); +#endif + +#ifdef USE_THREADS + S9xMessage(S9X_INFO, S9X_USAGE, "-threadsound Use a separate thread to output sound"); +#endif + S9xMessage(S9X_INFO, S9X_USAGE, "-buffersize Sound generating buffer size in millisecond"); + S9xMessage(S9X_INFO, S9X_USAGE, "-fragmentsize Sound playback buffer fragment size in bytes"); + S9xMessage(S9X_INFO, S9X_USAGE, "-sounddev Specify sound device"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + S9xMessage(S9X_INFO, S9X_USAGE, "-loadsnapshot Load snapshot file at start"); + S9xMessage(S9X_INFO, S9X_USAGE, "-playmovie Start emulator playing the .smv file"); + S9xMessage(S9X_INFO, S9X_USAGE, "-recordmovie Start emulator recording the .smv file"); + S9xMessage(S9X_INFO, S9X_USAGE, "-dumpstreams Save audio/video data to disk"); + S9xMessage(S9X_INFO, S9X_USAGE, "-dumpmaxframes Stop emulator after saving specified number of"); + S9xMessage(S9X_INFO, S9X_USAGE, " frames (use with -dumpstreams)"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + + S9xExtraDisplayUsage(); +} + +void S9xParseArg (char **argv, int &i, int argc) +{ + if (!strcasecmp(argv[i], "-multi")) + Settings.Multi = TRUE; + else + if (!strcasecmp(argv[i], "-carta")) + { + if (i + 1 < argc) + strncpy(Settings.CartAName, argv[++i], _MAX_PATH); + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-cartb")) + { + if (i + 1 < argc) + strncpy(Settings.CartBName, argv[++i], _MAX_PATH); + else + S9xUsage(); + } + else +#ifdef JOYSTICK_SUPPORT + if (!strcasecmp(argv[i], "-nogamepad")) + unixSettings.JoystickEnabled = FALSE; + else + if (!strncasecmp(argv[i], "-paddev", 7) && + argv[i][7] >= '1' && argv[i][7] <= '8' && argv[i][8] == '\0') + { + int j = argv[i][7] - '1'; + + if (i + 1 < argc) + js_device[j] = argv[++i]; + else + S9xUsage(); + } + else +#endif +#ifdef USE_THREADS + if (!strcasecmp(argv[i], "-threadsound")) + unixSettings.ThreadSound = TRUE; + else +#endif + if (!strcasecmp(argv[i], "-buffersize")) + { + if (i + 1 < argc) + unixSettings.SoundBufferSize = atoi(argv[++i]); + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-fragmentsize")) + { + if (i + 1 < argc) + unixSettings.SoundFragmentSize = atoi(argv[++i]); + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-sounddev")) + { + if (i + 1 < argc) + sound_device = argv[++i]; + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-loadsnapshot")) + { + if (i + 1 < argc) + snapshot_filename = argv[++i]; + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-playmovie")) + { + if (i + 1 < argc) + play_smv_filename = argv[++i]; + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-recordmovie")) + { + if (i + 1 < argc) + record_smv_filename = argv[++i]; + else + S9xUsage(); + } + else + if (!strcasecmp(argv[i], "-dumpstreams")) + Settings.DumpStreams = TRUE; + else + if (!strcasecmp(argv[i], "-dumpmaxframes")) + Settings.DumpStreamsMaxFrames = atoi(argv[++i]); + else + S9xParseDisplayArg(argv, i, argc); +} + +static void NSRTControllerSetup (void) +{ + if (!strncmp((const char *) Memory.NSRTHeader + 24, "NSRT", 4)) + { + // First plug in both, they'll change later as needed + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); + + switch (Memory.NSRTHeader[29]) + { + case 0x00: // Everything goes + break; + + case 0x10: // Mouse in Port 0 + S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0); + break; + + case 0x01: // Mouse in Port 1 + S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0); + break; + + case 0x03: // Super Scope in Port 1 + S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0); + break; + + case 0x06: // Multitap in Port 1 + S9xSetController(1, CTL_MP5, 1, 2, 3, 4); + break; + + case 0x66: // Multitap in Ports 0 and 1 + S9xSetController(0, CTL_MP5, 0, 1, 2, 3); + S9xSetController(1, CTL_MP5, 4, 5, 6, 7); + break; + + case 0x08: // Multitap in Port 1, Mouse in new Port 1 + S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0); + // There should be a toggle here for putting in Multitap instead + break; + + case 0x04: // Pad or Super Scope in Port 1 + S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0); + // There should be a toggle here for putting in a pad instead + break; + + case 0x05: // Justifier - Must ask user... + S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0); + // There should be a toggle here for how many justifiers + break; + + case 0x20: // Pad or Mouse in Port 0 + S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0); + // There should be a toggle here for putting in a pad instead + break; + + case 0x22: // Pad or Mouse in Port 0 & 1 + S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0); + S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0); + // There should be a toggles here for putting in pads instead + break; + + case 0x24: // Pad or Mouse in Port 0, Pad or Super Scope in Port 1 + // There should be a toggles here for what to put in, I'm leaving it at gamepad for now + break; + + case 0x27: // Pad or Mouse in Port 0, Pad or Mouse or Super Scope in Port 1 + // There should be a toggles here for what to put in, I'm leaving it at gamepad for now + break; + + // Not Supported yet + case 0x99: // Lasabirdie + break; + + case 0x0A: // Barcode Battler + break; + } + } +} + +void S9xParsePortConfig (ConfigFile &conf, int pass) +{ + s9x_base_dir = conf.GetStringDup("Unix::BaseDir", default_dir); + snapshot_filename = conf.GetStringDup("Unix::SnapshotFilename", NULL); + play_smv_filename = conf.GetStringDup("Unix::PlayMovieFilename", NULL); + record_smv_filename = conf.GetStringDup("Unix::RecordMovieFilename", NULL); + +#ifdef JOYSTICK_SUPPORT + unixSettings.JoystickEnabled = conf.GetBool ("Unix::EnableGamePad", true); + js_device[0] = conf.GetStringDup("Unix::PadDevice1", NULL); + js_device[1] = conf.GetStringDup("Unix::PadDevice2", NULL); + js_device[2] = conf.GetStringDup("Unix::PadDevice3", NULL); + js_device[3] = conf.GetStringDup("Unix::PadDevice4", NULL); + js_device[4] = conf.GetStringDup("Unix::PadDevice5", NULL); + js_device[5] = conf.GetStringDup("Unix::PadDevice6", NULL); + js_device[6] = conf.GetStringDup("Unix::PadDevice7", NULL); + js_device[7] = conf.GetStringDup("Unix::PadDevice8", NULL); +#endif + +#ifdef USE_THREADS + unixSettings.ThreadSound = conf.GetBool ("Unix::ThreadSound", false); +#endif + unixSettings.SoundBufferSize = conf.GetUInt ("Unix::SoundBufferSize", 100); + unixSettings.SoundFragmentSize = conf.GetUInt ("Unix::SoundFragmentSize", 2048); + sound_device = conf.GetStringDup("Unix::SoundDevice", "/dev/dsp"); + + keymaps.clear(); + if (!conf.GetBool("Unix::ClearAllControls", false)) + { + #if 0 + // Using an axis to control Pseudo-pointer #1 + keymaps.push_back(strpair_t("J00:Axis0", "AxisToPointer 1h Var")); + keymaps.push_back(strpair_t("J00:Axis1", "AxisToPointer 1v Var")); + keymaps.push_back(strpair_t("PseudoPointer1", "Pointer C=2 White/Black Superscope")); + #elif 0 + // Using an Axis for Pseudo-buttons + keymaps.push_back(strpair_t("J00:Axis0", "AxisToButtons 1/0 T=50%")); + keymaps.push_back(strpair_t("J00:Axis1", "AxisToButtons 3/2 T=50%")); + keymaps.push_back(strpair_t("PseudoButton0", "Joypad1 Right")); + keymaps.push_back(strpair_t("PseudoButton1", "Joypad1 Left")); + keymaps.push_back(strpair_t("PseudoButton2", "Joypad1 Down")); + keymaps.push_back(strpair_t("PseudoButton3", "Joypad1 Up")); + #else + // Using 'Joypad# Axis' + keymaps.push_back(strpair_t("J00:Axis0", "Joypad1 Axis Left/Right T=50%")); + keymaps.push_back(strpair_t("J00:Axis1", "Joypad1 Axis Up/Down T=50%")); + #endif + keymaps.push_back(strpair_t("J00:B0", "Joypad1 X")); + keymaps.push_back(strpair_t("J00:B1", "Joypad1 A")); + keymaps.push_back(strpair_t("J00:B2", "Joypad1 B")); + keymaps.push_back(strpair_t("J00:B3", "Joypad1 Y")); + #if 1 + keymaps.push_back(strpair_t("J00:B6", "Joypad1 L")); + #else + // Show off joypad-meta + keymaps.push_back(strpair_t("J00:X+B6", "JS1 Meta1")); + keymaps.push_back(strpair_t("J00:M1+B1", "Joypad1 Turbo A")); + #endif + keymaps.push_back(strpair_t("J00:B7", "Joypad1 R")); + keymaps.push_back(strpair_t("J00:B8", "Joypad1 Select")); + keymaps.push_back(strpair_t("J00:B11", "Joypad1 Start")); + } + + std::string section = S9xParseDisplayConfig(conf, 1); + + ConfigFile::secvec_t sec = conf.GetSection((section + " Controls").c_str()); + for (ConfigFile::secvec_t::iterator c = sec.begin(); c != sec.end(); c++) + keymaps.push_back(*c); +} + +static int make_snes9x_dirs (void) +{ + if (strlen(s9x_base_dir) + 1 + sizeof(dirNames[0]) > PATH_MAX + 1) + return (-1); + + mkdir(s9x_base_dir, 0755); + + for (int i = 0; i < LAST_DIR; i++) + { + if (dirNames[i][0]) + { + char s[PATH_MAX + 1]; + snprintf(s, PATH_MAX + 1, "%s%s%s", s9x_base_dir, SLASH_STR, dirNames[i]); + mkdir(s, 0755); + } + } + + return (0); +} + +const char * S9xGetDirectory (enum s9x_getdirtype dirtype) +{ + static char s[PATH_MAX + 1]; + + if (dirNames[dirtype][0]) + snprintf(s, PATH_MAX + 1, "%s%s%s", s9x_base_dir, SLASH_STR, dirNames[dirtype]); + else + { + switch (dirtype) + { + case DEFAULT_DIR: + strncpy(s, s9x_base_dir, PATH_MAX + 1); + s[PATH_MAX] = 0; + break; + + case HOME_DIR: + strncpy(s, getenv("HOME"), PATH_MAX + 1); + s[PATH_MAX] = 0; + break; + + case ROMFILENAME_DIR: + strncpy(s, Memory.ROMFilename, PATH_MAX + 1); + s[PATH_MAX] = 0; + + for (int i = strlen(s); i >= 0; i--) + { + if (s[i] == SLASH_CHAR) + { + s[i] = 0; + break; + } + } + + break; + + default: + s[0] = 0; + break; + } + } + + return (s); +} + +const char * S9xGetFilename (const char *ex, enum s9x_getdirtype dirtype) +{ + static char s[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + snprintf(s, PATH_MAX + 1, "%s%s%s%s", S9xGetDirectory(dirtype), SLASH_STR, fname, ex); + + return (s); +} + +const char * S9xGetFilenameInc (const char *ex, enum s9x_getdirtype dirtype) +{ + static char s[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + unsigned int i = 0; + const char *d; + struct stat buf; + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + d = S9xGetDirectory(dirtype); + + do + snprintf(s, PATH_MAX + 1, "%s%s%s.%03d%s", d, SLASH_STR, fname, i++, ex); + while (stat(s, &buf) == 0 && i < 1000); + + return (s); +} + +const char * S9xBasename (const char *f) +{ + const char *p; + + if ((p = strrchr(f, '/')) != NULL || (p = strrchr(f, '\\')) != NULL) + return (p + 1); + + return (f); +} + +const char * S9xChooseFilename (bool8 read_only) +{ + char s[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + const char *filename; + char title[64]; + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + snprintf(s, PATH_MAX + 1, "%s.frz", fname); + sprintf(title, "%s snapshot filename", read_only ? "Select load" : "Choose save"); + + S9xSetSoundMute(TRUE); + filename = S9xSelectFilename(s, S9xGetDirectory(SNAPSHOT_DIR), "frz", title); + S9xSetSoundMute(FALSE); + + return (filename); +} + +const char * S9xChooseMovieFilename (bool8 read_only) +{ + char s[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + const char *filename; + char title[64]; + + _splitpath(Memory.ROMFilename, drive, dir, fname, ext); + snprintf(s, PATH_MAX + 1, "%s.smv", fname); + sprintf(title, "Choose movie %s filename", read_only ? "playback" : "record"); + + S9xSetSoundMute(TRUE); + filename = S9xSelectFilename(s, S9xGetDirectory(HOME_DIR), "smv", title); + S9xSetSoundMute(FALSE); + + return (filename); +} + +bool8 S9xOpenSnapshotFile (const char *filename, bool8 read_only, STREAM *file) +{ + char s[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(filename, drive, dir, fname, ext); + + if (*drive || *dir == SLASH_CHAR || (strlen(dir) > 1 && *dir == '.' && *(dir + 1) == SLASH_CHAR)) + { + strncpy(s, filename, PATH_MAX + 1); + s[PATH_MAX] = 0; + } + else + snprintf(s, PATH_MAX + 1, "%s%s%s", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, fname); + + if (!*ext && strlen(s) <= PATH_MAX - 4) + strcat(s, ".frz"); + + if ((*file = OPEN_STREAM(s, read_only ? "rb" : "wb"))) + return (TRUE); + + return (FALSE); +} + +void S9xCloseSnapshotFile (STREAM file) +{ + CLOSE_STREAM(file); +} + +bool8 S9xInitUpdate (void) +{ + return (TRUE); +} + +bool8 S9xDeinitUpdate (int width, int height) +{ + S9xPutImage(width, height); + return (TRUE); +} + +bool8 S9xContinueUpdate (int width, int height) +{ + return (TRUE); +} + +void S9xToggleSoundChannel (int c) +{ + static uint8 sound_switch = 255; + + if (c == 8) + sound_switch = 255; + else + sound_switch ^= 1 << c; + + S9xSetSoundControl(sound_switch); +} + +void S9xAutoSaveSRAM (void) +{ + Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR)); +} + +void S9xSyncSpeed (void) +{ + if (Settings.SoundSync) + { + while (!S9xSyncSound()) + usleep(0); + } + + if (Settings.DumpStreams) + return; + +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlay && NetPlay.Connected) + { + #if defined(NP_DEBUG) && NP_DEBUG == 2 + printf("CLIENT: SyncSpeed @%d\n", S9xGetMilliTime()); + #endif + + S9xNPSendJoypadUpdate(old_joypads[0]); + for (int J = 0; J < 8; J++) + joypads[J] = S9xNPGetJoypad(J); + + if (!S9xNPCheckForHeartBeat()) + { + NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay(100); + #if defined(NP_DEBUG) && NP_DEBUG == 2 + if (NetPlay.PendingWait4Sync) + printf("CLIENT: PendingWait4Sync1 @%d\n", S9xGetMilliTime()); + #endif + + IPPU.RenderThisFrame = TRUE; + IPPU.SkippedFrames = 0; + } + else + { + NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay(200); + #if defined(NP_DEBUG) && NP_DEBUG == 2 + if (NetPlay.PendingWait4Sync) + printf("CLIENT: PendingWait4Sync2 @%d\n", S9xGetMilliTime()); + #endif + + if (IPPU.SkippedFrames < NetPlay.MaxFrameSkip) + { + IPPU.RenderThisFrame = FALSE; + IPPU.SkippedFrames++; + } + else + { + IPPU.RenderThisFrame = TRUE; + IPPU.SkippedFrames = 0; + } + } + + if (!NetPlay.PendingWait4Sync) + { + NetPlay.FrameCount++; + S9xNPStepJoypadHistory(); + } + + return; + } +#endif + + if (Settings.HighSpeedSeek > 0) + Settings.HighSpeedSeek--; + + if (Settings.TurboMode) + { + if ((++IPPU.FrameSkip >= Settings.TurboSkipFrames) && !Settings.HighSpeedSeek) + { + IPPU.FrameSkip = 0; + IPPU.SkippedFrames = 0; + IPPU.RenderThisFrame = TRUE; + } + else + { + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = FALSE; + } + + return; + } + + static struct timeval next1 = { 0, 0 }; + struct timeval now; + + while (gettimeofday(&now, NULL) == -1) ; + + // If there is no known "next" frame, initialize it now. + if (next1.tv_sec == 0) + { + next1 = now; + next1.tv_usec++; + } + + // If we're on AUTO_FRAMERATE, we'll display frames always only if there's excess time. + // Otherwise we'll display the defined amount of frames. + unsigned limit = (Settings.SkipFrames == AUTO_FRAMERATE) ? (timercmp(&next1, &now, <) ? 10 : 1) : Settings.SkipFrames; + + IPPU.RenderThisFrame = (++IPPU.SkippedFrames >= limit) ? TRUE : FALSE; + + if (IPPU.RenderThisFrame) + IPPU.SkippedFrames = 0; + else + { + // If we were behind the schedule, check how much it is. + if (timercmp(&next1, &now, <)) + { + unsigned lag = (now.tv_sec - next1.tv_sec) * 1000000 + now.tv_usec - next1.tv_usec; + if (lag >= 500000) + { + // More than a half-second behind means probably pause. + // The next line prevents the magic fast-forward effect. + next1 = now; + } + } + } + + // Delay until we're completed this frame. + // Can't use setitimer because the sound code already could be using it. We don't actually need it either. + while (timercmp(&next1, &now, >)) + { + // If we're ahead of time, sleep a while. + unsigned timeleft = (next1.tv_sec - now.tv_sec) * 1000000 + next1.tv_usec - now.tv_usec; + usleep(timeleft); + + while (gettimeofday(&now, NULL) == -1) ; + // Continue with a while-loop because usleep() could be interrupted by a signal. + } + + // Calculate the timestamp of the next frame. + next1.tv_usec += Settings.FrameTime; + if (next1.tv_usec >= 1000000) + { + next1.tv_sec += next1.tv_usec / 1000000; + next1.tv_usec %= 1000000; + } +} + +bool8 S9xMapInput (const char *n, s9xcommand_t *cmd) +{ + int i, j, d; + char *c; + char buf[4] = "M1+"; + + if (!strncmp(n, "PseudoPointer", 13) && n[13] >= '1' && n[13] <= '8' && n[14] == '\0') + return (S9xMapPointer(PseudoPointerBase + (n[13] - '1'), *cmd, false)); + + if (!strncmp(n, "PseudoButton", 12) && isdigit(n[12]) && (j = strtol(n + 12, &c, 10)) < 256 && (c == NULL || *c == '\0')) + return (S9xMapButton(PseudoButtonBase + j, *cmd, false)); + + if (n[0] != 'J' || !isdigit(n[1]) || !isdigit(n[2]) || n[3] != ':') + goto unrecog; + + d = ((n[1] - '0') * 10 + (n[2] - '0')) << 24; + d |= 0x80000000; + i = 4; + if (!strncmp(n + i, "X+", 2)) + { + d |= 0x4000; + i += 2; + } + else + { + for (buf[1] = '1'; buf[1] <= '8'; buf[1]++) + { + if (!strncmp(n + i, buf, 3)) + { + d |= 1 << (buf[1] - '1' + 16); + i += 3; + } + } + } + + if (!strncmp(n + i, "Axis", 4)) + { + d |= 0x8000; + i += 4; + } + else + if (n[i] == 'B') + i++; + else + goto unrecog; + + d |= j = strtol(n + i, &c, 10); + if ((c != NULL && *c != '\0') || j > 0x3fff) + goto unrecog; + + if (d & 0x8000) + return (S9xMapAxis(d, *cmd, false)); + + return (S9xMapButton(d, *cmd, false)); + +unrecog: + return (S9xMapDisplayInput(n, cmd)); +} + +bool S9xPollButton (uint32 id, bool *pressed) +{ + return (S9xDisplayPollButton(id, pressed)); +} + +bool S9xPollAxis (uint32 id, int16 *value) +{ + return (S9xDisplayPollAxis(id, value)); +} + +bool S9xPollPointer (uint32 id, int16 *x, int16 *y) +{ + return (S9xDisplayPollPointer(id, x, y)); +} + +s9xcommand_t S9xGetPortCommandT (const char *n) +{ + s9xcommand_t cmd; + + cmd.type = S9xBadMapping; + cmd.multi_press = 0; + cmd.button_norpt = 0; + cmd.port[0] = 0; + cmd.port[1] = 0; + cmd.port[2] = 0; + cmd.port[3] = 0; + + if (!strncmp(n, "JS", 2) && n[2] >= '1' && n[2] <= '8') + { + if (!strncmp(n + 3, " Meta", 5) && n[8] >= '1' && n[8] <= '8' && n[9] == '\0') + { + cmd.type = S9xButtonPort; + cmd.port[1] = 0; + cmd.port[2] = n[2] - '1'; + cmd.port[3] = 1 << (n[8] - '1'); + + return (cmd); + } + else + if (!strncmp(n + 3, " ToggleMeta", 11) && n[14] >= '1' && n[14] <= '8' && n[15] == '\0') + { + cmd.type = S9xButtonPort; + cmd.port[1] = 1; + cmd.port[2] = n[2] - '1'; + cmd.port[3] = 1 << (n[13] - '1'); + + return (cmd); + } + } + + return (S9xGetDisplayCommandT(n)); +} + +char * S9xGetPortCommandName (s9xcommand_t cmd) +{ + std::string x; + + switch (cmd.type) + { + case S9xButtonPort: + if (cmd.port[0] != 0) + break; + + switch (cmd.port[1]) + { + case 0: + x = "JS"; + x += (int) cmd.port[2]; + x += " Meta"; + x += (int) cmd.port[3]; + return (strdup(x.c_str())); + + case 1: + x = "JS"; + x += (int) cmd.port[2]; + x += " ToggleMeta"; + x += (int) cmd.port[3]; + return (strdup(x.c_str())); + } + + break; + + case S9xAxisPort: + break; + + case S9xPointerPort: + break; + } + + return (S9xGetDisplayCommandName(cmd)); +} + +void S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2) +{ +#ifdef JOYSTICK_SUPPORT + switch (cmd.type) + { + case S9xButtonPort: + if (cmd.port[0] != 0) + break; + + switch (cmd.port[1]) + { + case 0: + if (data1) + js_mod[cmd.port[2]] |= cmd.port[3]; + else + js_mod[cmd.port[2]] &= ~cmd.port[3]; + break; + + case 1: + if (data1) + js_mod[cmd.port[2]] ^= cmd.port[3]; + break; + } + + break; + + case S9xAxisPort: + break; + + case S9xPointerPort: + break; + } + + S9xHandleDisplayCommand(cmd, data1, data2); +#endif +} + +void S9xSetupDefaultKeymap (void) +{ + s9xcommand_t cmd; + + S9xUnmapAllControls(); + + for (ConfigFile::secvec_t::iterator i = keymaps.begin(); i != keymaps.end(); i++) + { + cmd = S9xGetPortCommandT(i->second.c_str()); + + if (cmd.type == S9xBadMapping) + { + cmd = S9xGetCommandT(i->second.c_str()); + if (cmd.type == S9xBadMapping) + { + std::string s("Unrecognized command '"); + s += i->second + "'"; + perror(s.c_str()); + continue; + } + } + + if (!S9xMapInput(i->first.c_str(), &cmd)) + { + std::string s("Could not map '"); + s += i->second + "' to '" + i->first + "'"; + perror(s.c_str()); + continue; + } + } + + keymaps.clear(); +} + +void S9xInitInputDevices (void) +{ +#ifdef JOYSTICK_SUPPORT + InitJoysticks(); +#endif +} + +#ifdef JOYSTICK_SUPPORT + +static void InitJoysticks (void) +{ +#ifdef JSIOCGVERSION + int version; + unsigned char axes, buttons; + + if ((js_fd[0] = open(js_device[0], O_RDONLY | O_NONBLOCK)) == -1) + { + fprintf(stderr, "joystick: No joystick found.\n"); + return; + } + + if (ioctl(js_fd[0], JSIOCGVERSION, &version) == -1) + { + fprintf(stderr, "joystick: You need at least driver version 1.0 for joystick support.\n"); + close(js_fd[0]); + return; + } + + for (int i = 1; i < 8; i++) + js_fd[i] = open(js_device[i], O_RDONLY | O_NONBLOCK); + +#ifdef JSIOCGNAME + char name[130]; + + bzero(name, 128); + + if (ioctl(js_fd[0], JSIOCGNAME(128), name) > 0) + { + printf("Using %s (%s) as joystick1\n", name, js_device[0]); + + for (int i = 1; i < 8; i++) + { + if (js_fd[i] > 0) + { + ioctl(js_fd[i], JSIOCGNAME(128), name); + printf (" and %s (%s) as joystick%d\n", name, js_device[i], i + 1); + } + } + } + else +#endif + { + ioctl(js_fd[0], JSIOCGAXES, &axes); + ioctl(js_fd[0], JSIOCGBUTTONS, &buttons); + printf("Using %d-axis %d-button joystick (%s) as joystick1\n", axes, buttons, js_device[0]); + + for (int i = 1; i < 8; i++) + { + if (js_fd[i] > 0) + { + ioctl(js_fd[i], JSIOCGAXES, &axes); + ioctl(js_fd[i], JSIOCGBUTTONS, &buttons); + printf(" and %d-axis %d-button joystick (%s) as joystick%d\n", axes, buttons, js_device[i], i + 1); + } + } + } +#endif +} + +static void ReadJoysticks (void) +{ +#ifdef JSIOCGVERSION + struct js_event js_ev; + + for (int i = 0; i < 8 && js_fd[i] >= 0; i++) + { + while (read(js_fd[i], &js_ev, sizeof(struct js_event)) == sizeof(struct js_event)) + { + switch (js_ev.type & ~JS_EVENT_INIT) + { + case JS_EVENT_AXIS: + S9xReportAxis(0x8000c000 | (i << 24) | js_ev.number, js_ev.value); + S9xReportAxis(0x80008000 | (i << 24) | (js_mod[i] << 16) | js_ev.number, js_ev.value); + break; + + case JS_EVENT_BUTTON: + S9xReportButton(0x80004000 | (i << 24) | js_ev.number, js_ev.value); + S9xReportButton(0x80000000 | (i << 24) | (js_mod[i] << 16) | js_ev.number, js_ev.value); + break; + } + } + } +#endif +} + +#endif + +static void SoundTrigger (void) +{ +#ifndef NOSOUND + S9xProcessSound(NULL); +#endif +} + +static void InitTimer (void) +{ +#ifndef NOSOUND + struct itimerval timeout; +#endif + struct sigaction sa; + +#ifdef USE_THREADS + if (unixSettings.ThreadSound) + { + pthread_mutex_init(&mutex, NULL); + pthread_create(&thread, NULL, S9xProcessSound, NULL); + return; + } +#endif + + sa.sa_handler = (SIG_PF) SoundTrigger; + +#ifdef SA_RESTART + sa.sa_flags = SA_RESTART; +#else + sa.sa_flags = 0; +#endif + +#ifndef NOSOUND // FIXME: Kludge to get calltree running. Remove later. + sigemptyset(&sa.sa_mask); + sigaction(SIGALRM, &sa, NULL); + + timeout.it_interval.tv_sec = 0; + timeout.it_interval.tv_usec = 10000; + timeout.it_value.tv_sec = 0; + timeout.it_value.tv_usec = 10000; + if (setitimer(ITIMER_REAL, &timeout, NULL) < 0) + perror("setitimer"); +#endif +} + +bool8 S9xOpenSoundDevice (void) +{ +#ifndef NOSOUND + int J, K; + + so.sound_fd = open(sound_device, O_WRONLY | O_NONBLOCK); + if (so.sound_fd == -1) + return (FALSE); + + J = log2(unixSettings.SoundFragmentSize) | (3 << 16); + if (ioctl(so.sound_fd, SNDCTL_DSP_SETFRAGMENT, &J) == -1) + return (FALSE); + + J = K = Settings.SixteenBitSound ? AFMT_S16_NE : AFMT_U8; + if (ioctl(so.sound_fd, SNDCTL_DSP_SETFMT, &J) == -1 || J != K) + return (FALSE); + + J = K = Settings.Stereo ? 1 : 0; + if (ioctl(so.sound_fd, SNDCTL_DSP_STEREO, &J) == -1 || J != K) + return (FALSE); + + J = K = Settings.SoundPlaybackRate; + if (ioctl(so.sound_fd, SNDCTL_DSP_SPEED, &J) == -1 || J != K) + return (FALSE); + + J = 0; + if (ioctl(so.sound_fd, SNDCTL_DSP_GETBLKSIZE, &J) == -1) + return (FALSE); + + so.fragment_size = J; + printf("fragment size: %d\n", J); +#endif + + return (TRUE); +} + +#ifndef NOSOUND + +static void * S9xProcessSound (void *) +{ + // If threads in use, this is to loop indefinitely. + // If not, this will be called by timer. + + audio_buf_info info; + if (!unixSettings.ThreadSound && (ioctl(so.sound_fd, SNDCTL_DSP_GETOSPACE, &info) == -1 || info.bytes < (int) so.fragment_size)) + return (NULL); + +#ifdef USE_THREADS + do + { +#endif + + int sample_count = so.fragment_size; + if (Settings.SixteenBitSound) + sample_count >>= 1; + +#ifdef USE_THREADS + if (unixSettings.ThreadSound) + pthread_mutex_lock(&mutex); + else +#endif + if (block_signal) + return (NULL); + + block_generate_sound = TRUE; + + if (so.samples_mixed_so_far < sample_count) + { + unsigned ofs = so.play_position + (Settings.SixteenBitSound ? (so.samples_mixed_so_far << 1) : so.samples_mixed_so_far); + S9xMixSamples(Buf + (ofs & SOUND_BUFFER_SIZE_MASK), sample_count - so.samples_mixed_so_far); + so.samples_mixed_so_far = sample_count; + } + + unsigned bytes_to_write = sample_count; + if (Settings.SixteenBitSound) + bytes_to_write <<= 1; + + unsigned byte_offset = so.play_position; + so.play_position += bytes_to_write; + so.play_position &= SOUND_BUFFER_SIZE_MASK; + +#ifdef USE_THREADS + if (unixSettings.ThreadSound) + pthread_mutex_unlock(&mutex); +#endif + + block_generate_sound = FALSE; + + for (;;) + { + int I = bytes_to_write; + if (byte_offset + I > SOUND_BUFFER_SIZE) + I = SOUND_BUFFER_SIZE - byte_offset; + if (I == 0) + break; + + I = write(so.sound_fd, (char *) Buf + byte_offset, I); + if (I > 0) + { + bytes_to_write -= I; + byte_offset += I; + byte_offset &= SOUND_BUFFER_SIZE_MASK; + } + else + if (I < 0 && errno != EINTR) + break; + } + + so.samples_mixed_so_far -= sample_count; + +#ifdef USE_THREADS + } while (unixSettings.ThreadSound); +#endif + + return (NULL); +} + +#endif + +void S9xExit (void) +{ + S9xMovieShutdown(); + + S9xSetSoundMute(TRUE); + Settings.StopEmulation = TRUE; + +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlay) + S9xNPDisconnect(); +#endif + + Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR)); + S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); + S9xResetSaveTimer(FALSE); + + S9xUnmapAllControls(); + S9xDeinitDisplay(); + Memory.Deinit(); + S9xDeinitAPU(); + + exit(0); +} + +#ifdef DEBUGGER +static void sigbrkhandler (int) +{ + CPU.Flags |= DEBUG_MODE_FLAG; + signal(SIGINT, (SIG_PF) sigbrkhandler); +} +#endif + +int main (int argc, char **argv) +{ + if (argc < 2) + S9xUsage(); + + printf("\n\nSnes9x " VERSION " for unix\n"); + + snprintf(default_dir, PATH_MAX + 1, "%s%s%s", getenv("HOME"), SLASH_STR, ".snes9x"); + + ZeroMemory(&Settings, sizeof(Settings)); + Settings.MouseMaster = TRUE; + Settings.SuperScopeMaster = TRUE; + Settings.JustifierMaster = TRUE; + Settings.MultiPlayer5Master = TRUE; + Settings.FrameTimePAL = 20000; + Settings.FrameTimeNTSC = 16667; + Settings.SixteenBitSound = TRUE; + Settings.Stereo = TRUE; + Settings.SoundPlaybackRate = 32000; + Settings.SoundInputRate = 32000; + Settings.SupportHiRes = TRUE; + Settings.Transparency = TRUE; + Settings.AutoDisplayMessages = TRUE; + Settings.InitialInfoStringTimeout = 120; + Settings.HDMATimingHack = 100; + Settings.BlockInvalidVRAMAccessMaster = TRUE; + Settings.StopEmulation = TRUE; + Settings.WrongMovieStateProtection = TRUE; + Settings.DumpStreamsMaxFrames = -1; + Settings.StretchScreenshots = 1; + Settings.SnapshotScreenshots = TRUE; + Settings.SkipFrames = AUTO_FRAMERATE; + Settings.TurboSkipFrames = 15; + Settings.CartAName[0] = 0; + Settings.CartBName[0] = 0; +#ifdef NETPLAY_SUPPORT + Settings.ServerName[0] = 0; +#endif + +#ifdef JOYSTICK_SUPPORT + unixSettings.JoystickEnabled = TRUE; +#else + unixSettings.JoystickEnabled = FALSE; +#endif + unixSettings.ThreadSound = TRUE; + unixSettings.SoundBufferSize = 100; + unixSettings.SoundFragmentSize = 2048; + + ZeroMemory(&so, sizeof(so)); + + CPU.Flags = 0; + + S9xLoadConfigFiles(argv, argc); + rom_filename = S9xParseArgs(argv, argc); + + make_snes9x_dirs(); + + if (!Memory.Init() || !S9xInitAPU()) + { + fprintf(stderr, "Snes9x: Memory allocation failure - not enough RAM/virtual memory available.\nExiting...\n"); + Memory.Deinit(); + S9xDeinitAPU(); + exit(1); + } + + S9xInitSound(unixSettings.SoundBufferSize, 0); + S9xSetSoundMute(TRUE); + + S9xReportControllers(); + +#ifdef GFX_MULTI_FORMAT + S9xSetRenderPixelFormat(RGB565); +#endif + + uint32 saved_flags = CPU.Flags; + bool8 loaded = FALSE; + + if (Settings.Multi) + { + loaded = Memory.LoadMultiCart(Settings.CartAName, Settings.CartBName); + + if (!loaded) + { + char s1[PATH_MAX + 1], s2[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + s1[0] = s2[0] = 0; + + if (Settings.CartAName[0]) + { + _splitpath(Settings.CartAName, drive, dir, fname, ext); + snprintf(s1, PATH_MAX + 1, "%s%s%s", S9xGetDirectory(ROM_DIR), SLASH_STR, fname); + if (ext[0] && (strlen(s1) <= PATH_MAX - 1 - strlen(ext))) + { + strcat(s1, "."); + strcat(s1, ext); + } + } + + if (Settings.CartBName[0]) + { + _splitpath(Settings.CartBName, drive, dir, fname, ext); + snprintf(s2, PATH_MAX + 1, "%s%s%s", S9xGetDirectory(ROM_DIR), SLASH_STR, fname); + if (ext[0] && (strlen(s2) <= PATH_MAX - 1 - strlen(ext))) + { + strcat(s2, "."); + strcat(s2, ext); + } + } + + loaded = Memory.LoadMultiCart(s1, s2); + } + } + else + if (rom_filename) + { + loaded = Memory.LoadROM(rom_filename); + + if (!loaded && rom_filename[0]) + { + char s[PATH_MAX + 1]; + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + _splitpath(rom_filename, drive, dir, fname, ext); + snprintf(s, PATH_MAX + 1, "%s%s%s", S9xGetDirectory(ROM_DIR), SLASH_STR, fname); + if (ext[0] && (strlen(s) <= PATH_MAX - 1 - strlen(ext))) + { + strcat(s, "."); + strcat(s, ext); + } + + loaded = Memory.LoadROM(s); + } + } + + if (!loaded) + { + fprintf(stderr, "Error opening the ROM file.\n"); + exit(1); + } + + NSRTControllerSetup(); + Memory.LoadSRAM(S9xGetFilename(".srm", SRAM_DIR)); + S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); + + CPU.Flags = saved_flags; + Settings.StopEmulation = FALSE; + +#ifdef DEBUGGER + struct sigaction sa; + sa.sa_handler = sigbrkhandler; +#ifdef SA_RESTART + sa.sa_flags = SA_RESTART; +#else + sa.sa_flags = 0; +#endif + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, NULL); +#endif + + S9xInitInputDevices(); + S9xInitDisplay(argc, argv); + S9xSetupDefaultKeymap(); + S9xTextMode(); + +#ifdef NETPLAY_SUPPORT + if (strlen(Settings.ServerName) == 0) + { + char *server = getenv("S9XSERVER"); + if (server) + { + strncpy(Settings.ServerName, server, 127); + Settings.ServerName[127] = 0; + } + } + + char *port = getenv("S9XPORT"); + if (Settings.Port >= 0 && port) + Settings.Port = atoi(port); + else + if (Settings.Port < 0) + Settings.Port = -Settings.Port; + + if (Settings.NetPlay) + { + NetPlay.MaxFrameSkip = 10; + + if (!S9xNPConnectToServer(Settings.ServerName, Settings.Port, Memory.ROMName)) + { + fprintf(stderr, "Failed to connect to server %s on port %d.\n", Settings.ServerName, Settings.Port); + S9xExit(); + } + + fprintf(stderr, "Connected to server %s on port %d as player #%d playing %s.\n", Settings.ServerName, Settings.Port, NetPlay.Player, Memory.ROMName); + } +#endif + + if (play_smv_filename) + { + uint32 flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); + if (S9xMovieOpen(play_smv_filename, TRUE) != SUCCESS) + exit(1); + CPU.Flags |= flags; + } + else + if (record_smv_filename) + { + uint32 flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); + if (S9xMovieCreate(record_smv_filename, 0xFF, MOVIE_OPT_FROM_RESET, NULL, 0) != SUCCESS) + exit(1); + CPU.Flags |= flags; + } + else + if (snapshot_filename) + { + uint32 flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG); + if (!S9xUnfreezeGame(snapshot_filename)) + exit(1); + CPU.Flags |= flags; + } + + S9xGraphicsMode(); + + sprintf(String, "\"%s\" %s: %s", Memory.ROMName, TITLE, VERSION); + S9xSetTitle(String); + +#ifdef JOYSTICK_SUPPORT + uint32 JoypadSkip = 0; +#endif + + InitTimer(); + S9xSetSoundMute(FALSE); + +#ifdef NETPLAY_SUPPORT + bool8 NP_Activated = Settings.NetPlay; +#endif + + while (1) + { + #ifdef NETPLAY_SUPPORT + if (NP_Activated) + { + if (NetPlay.PendingWait4Sync && !S9xNPWaitForHeartBeatDelay(100)) + { + S9xProcessEvents(FALSE); + continue; + } + + for (int J = 0; J < 8; J++) + old_joypads[J] = MovieGetJoypad(J); + + for (int J = 0; J < 8; J++) + MovieSetJoypad(J, joypads[J]); + + if (NetPlay.Connected) + { + if (NetPlay.PendingWait4Sync) + { + NetPlay.PendingWait4Sync = FALSE; + NetPlay.FrameCount++; + S9xNPStepJoypadHistory(); + } + } + else + { + fprintf(stderr, "Lost connection to server.\n"); + S9xExit(); + } + } + #endif + + #ifdef DEBUGGER + if (!Settings.Paused || (CPU.Flags & (DEBUG_MODE_FLAG | SINGLE_STEP_FLAG))) + #else + if (!Settings.Paused) + #endif + S9xMainLoop(); + + #ifdef NETPLAY_SUPPORT + if (NP_Activated) + { + for (int J = 0; J < 8; J++) + MovieSetJoypad(J, old_joypads[J]); + } + #endif + + #ifdef DEBUGGER + if (Settings.Paused || (CPU.Flags & DEBUG_MODE_FLAG)) + #else + if (Settings.Paused) + #endif + S9xSetSoundMute(TRUE); + + #ifdef DEBUGGER + if (CPU.Flags & DEBUG_MODE_FLAG) + S9xDoDebug(); + else + #endif + if (Settings.Paused) + { + S9xProcessEvents(FALSE); + usleep(100000); + } + + #ifdef JOYSTICK_SUPPORT + if (unixSettings.JoystickEnabled && (JoypadSkip++ & 1) == 0) + ReadJoysticks(); + #endif + + S9xProcessEvents(FALSE); + + #ifdef DEBUGGER + if (!Settings.Paused && !(CPU.Flags & DEBUG_MODE_FLAG)) + #else + if (!Settings.Paused) + #endif + S9xSetSoundMute(FALSE); + } + + return (0); +} diff --git a/unix/x11.cpp b/unix/x11.cpp new file mode 100644 index 00000000..cf509496 --- /dev/null +++ b/unix/x11.cpp @@ -0,0 +1,1298 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 +#ifdef HAVE_STRINGS_H +#include +#endif +#include +#include + +#include +#include +#include +#include + +#ifdef MITSHM +#include +#include +#include +#endif + +#include "snes9x.h" +#include "memmap.h" +#include "ppu.h" +#include "controls.h" +#include "movie.h" +#include "logger.h" +#include "conffile.h" +#include "blit.h" +#include "display.h" + +struct GUIData +{ + Display *display; + Screen *screen; + Visual *visual; + GC gc; + int screen_num; + int depth; + int pixel_format; + int bytes_per_pixel; + uint32 red_shift; + uint32 blue_shift; + uint32 green_shift; + uint32 red_size; + uint32 green_size; + uint32 blue_size; + Window window; + XImage *image; + uint8 *snes_buffer; + uint8 *filter_buffer; + uint8 *blit_screen; + uint32 blit_screen_pitch; + bool8 need_convert; + Cursor point_cursor; + Cursor cross_hair_cursor; + int video_mode; + int mouse_x; + int mouse_y; + bool8 mod1_pressed; + bool8 no_repeat; +#ifdef MITSHM + XShmSegmentInfo sm_info; + bool8 use_shared_memory; +#endif +}; + +static struct GUIData GUI; + +typedef std::pair strpair_t; +extern std::vector keymaps; + +typedef void (* Blitter) (uint8 *, int, uint8 *, int, int, int); + +#ifdef __linux +// Select seems to be broken in 2.x.x kernels - if a signal interrupts a +// select system call with a zero timeout, the select call is restarted but +// with an infinite timeout! The call will block until data arrives on the +// selected fd(s). +// +// The workaround is to stop the X library calling select in the first +// place! Replace XPending - which polls for data from the X server using +// select - with an ioctl call to poll for data and then only call the blocking +// XNextEvent if data is waiting. +#define SELECT_BROKEN_FOR_SIGNALS +#endif + +enum +{ + VIDEOMODE_BLOCKY = 1, + VIDEOMODE_TV, + VIDEOMODE_SMOOTH, + VIDEOMODE_SUPEREAGLE, + VIDEOMODE_2XSAI, + VIDEOMODE_SUPER2XSAI, + VIDEOMODE_EPX, + VIDEOMODE_HQ2X +}; + +static int ErrorHandler (Display *, XErrorEvent *); +static bool8 CheckForPendingXEvents (Display *); +static void SetXRepeat (bool8); +static void SetupImage (void); +static void TakedownImage (void); +static void Repaint (bool8); +static void Convert16To24 (int, int); +static void Convert16To24Packed (int, int); + + +void S9xExtraDisplayUsage (void) +{ + /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */ + + S9xMessage(S9X_INFO, S9X_USAGE, "-setrepeat Allow altering keyboard auto-repeat"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); + S9xMessage(S9X_INFO, S9X_USAGE, "-v1 Video mode: Blocky (default)"); + S9xMessage(S9X_INFO, S9X_USAGE, "-v2 Video mode: TV"); + S9xMessage(S9X_INFO, S9X_USAGE, "-v3 Video mode: Smooth"); + S9xMessage(S9X_INFO, S9X_USAGE, "-v4 Video mode: SuperEagle"); + S9xMessage(S9X_INFO, S9X_USAGE, "-v5 Video mode: 2xSaI"); + S9xMessage(S9X_INFO, S9X_USAGE, "-v6 Video mode: Super2xSaI"); + S9xMessage(S9X_INFO, S9X_USAGE, "-v7 Video mode: EPX"); + S9xMessage(S9X_INFO, S9X_USAGE, "-v8 Video mode: hq2x"); + S9xMessage(S9X_INFO, S9X_USAGE, ""); +} + +void S9xParseDisplayArg (char **argv, int &i, int argc) +{ + if (!strcasecmp(argv[i], "-setrepeat")) + GUI.no_repeat = FALSE; + else + if (!strncasecmp(argv[i], "-v", 2)) + { + switch (argv[i][2]) + { + case '1': GUI.video_mode = VIDEOMODE_BLOCKY; break; + case '2': GUI.video_mode = VIDEOMODE_TV; break; + case '3': GUI.video_mode = VIDEOMODE_SMOOTH; break; + case '4': GUI.video_mode = VIDEOMODE_SUPEREAGLE; break; + case '5': GUI.video_mode = VIDEOMODE_2XSAI; break; + case '6': GUI.video_mode = VIDEOMODE_SUPER2XSAI; break; + case '7': GUI.video_mode = VIDEOMODE_EPX; break; + case '8': GUI.video_mode = VIDEOMODE_HQ2X; break; + } + } + else + S9xUsage(); +} + +const char * S9xParseDisplayConfig (ConfigFile &conf, int pass) +{ + if (pass != 1) + return ("Unix/X11"); + + if (!conf.GetBool("Unix::ClearAllControls", false)) + { + keymaps.push_back(strpair_t("K00:k", "Joypad1 Right")); + keymaps.push_back(strpair_t("K00:Right", "Joypad1 Right")); + keymaps.push_back(strpair_t("K00:h", "Joypad1 Left")); + keymaps.push_back(strpair_t("K00:Left", "Joypad1 Left")); + keymaps.push_back(strpair_t("K00:j", "Joypad1 Down")); + keymaps.push_back(strpair_t("K00:n", "Joypad1 Down")); + keymaps.push_back(strpair_t("K00:Down", "Joypad1 Down")); + keymaps.push_back(strpair_t("K00:u", "Joypad1 Up")); + keymaps.push_back(strpair_t("K00:Up", "Joypad1 Up")); + keymaps.push_back(strpair_t("K00:Return", "Joypad1 Start")); + keymaps.push_back(strpair_t("K00:space", "Joypad1 Select")); + keymaps.push_back(strpair_t("K00:S+d", "Joypad1 ToggleTurbo A")); + keymaps.push_back(strpair_t("K00:C+d", "Joypad1 ToggleSticky A")); + keymaps.push_back(strpair_t("K00:d", "Joypad1 A")); + keymaps.push_back(strpair_t("K00:S+c", "Joypad1 ToggleTurbo B")); + keymaps.push_back(strpair_t("K00:C+c", "Joypad1 ToggleSticky B")); + keymaps.push_back(strpair_t("K00:c", "Joypad1 B")); + keymaps.push_back(strpair_t("K00:S+s", "Joypad1 ToggleTurbo X")); + keymaps.push_back(strpair_t("K00:C+s", "Joypad1 ToggleSticky X")); + keymaps.push_back(strpair_t("K00:s", "Joypad1 X")); + keymaps.push_back(strpair_t("K00:S+x", "Joypad1 ToggleTurbo Y")); + keymaps.push_back(strpair_t("K00:C+x", "Joypad1 ToggleSticky Y")); + keymaps.push_back(strpair_t("K00:x", "Joypad1 Y")); + keymaps.push_back(strpair_t("K00:S+a", "Joypad1 ToggleTurbo L")); + keymaps.push_back(strpair_t("K00:S+v", "Joypad1 ToggleTurbo L")); + keymaps.push_back(strpair_t("K00:C+a", "Joypad1 ToggleSticky L")); + keymaps.push_back(strpair_t("K00:C+v", "Joypad1 ToggleSticky L")); + keymaps.push_back(strpair_t("K00:a", "Joypad1 L")); + keymaps.push_back(strpair_t("K00:v", "Joypad1 L")); + keymaps.push_back(strpair_t("K00:S+z", "Joypad1 ToggleTurbo R")); + keymaps.push_back(strpair_t("K00:C+z", "Joypad1 ToggleSticky R")); + keymaps.push_back(strpair_t("K00:z", "Joypad1 R")); + + keymaps.push_back(strpair_t("K00:KP_Left", "Joypad2 Left")); + keymaps.push_back(strpair_t("K00:KP_Right", "Joypad2 Right")); + keymaps.push_back(strpair_t("K00:KP_Up", "Joypad2 Up")); + keymaps.push_back(strpair_t("K00:KP_Down", "Joypad2 Down")); + keymaps.push_back(strpair_t("K00:KP_Enter", "Joypad2 Start")); + keymaps.push_back(strpair_t("K00:KP_Add", "Joypad2 Select")); + keymaps.push_back(strpair_t("K00:Prior", "Joypad2 A")); + keymaps.push_back(strpair_t("K00:Next", "Joypad2 B")); + keymaps.push_back(strpair_t("K00:Home", "Joypad2 X")); + keymaps.push_back(strpair_t("K00:End", "Joypad2 Y")); + keymaps.push_back(strpair_t("K00:Insert", "Joypad2 L")); + keymaps.push_back(strpair_t("K00:Delete", "Joypad2 R")); + + keymaps.push_back(strpair_t("K00:A+F4", "SoundChannel0")); + keymaps.push_back(strpair_t("K00:C+F4", "SoundChannel0")); + keymaps.push_back(strpair_t("K00:A+F5", "SoundChannel1")); + keymaps.push_back(strpair_t("K00:C+F5", "SoundChannel1")); + keymaps.push_back(strpair_t("K00:A+F6", "SoundChannel2")); + keymaps.push_back(strpair_t("K00:C+F6", "SoundChannel2")); + keymaps.push_back(strpair_t("K00:A+F7", "SoundChannel3")); + keymaps.push_back(strpair_t("K00:C+F7", "SoundChannel3")); + keymaps.push_back(strpair_t("K00:A+F8", "SoundChannel4")); + keymaps.push_back(strpair_t("K00:C+F8", "SoundChannel4")); + keymaps.push_back(strpair_t("K00:A+F9", "SoundChannel5")); + keymaps.push_back(strpair_t("K00:C+F9", "SoundChannel5")); + keymaps.push_back(strpair_t("K00:A+F10", "SoundChannel6")); + keymaps.push_back(strpair_t("K00:C+F10", "SoundChannel6")); + keymaps.push_back(strpair_t("K00:A+F11", "SoundChannel7")); + keymaps.push_back(strpair_t("K00:C+F11", "SoundChannel7")); + keymaps.push_back(strpair_t("K00:A+F12", "SoundChannelsOn")); + keymaps.push_back(strpair_t("K00:C+F12", "SoundChannelsOn")); + + keymaps.push_back(strpair_t("K00:S+1", "BeginRecordingMovie")); + keymaps.push_back(strpair_t("K00:S+2", "EndRecordingMovie")); + keymaps.push_back(strpair_t("K00:S+3", "LoadMovie")); + keymaps.push_back(strpair_t("K00:A+F1", "SaveSPC")); + keymaps.push_back(strpair_t("K00:C+F1", "SaveSPC")); + keymaps.push_back(strpair_t("K00:F10", "LoadOopsFile")); + keymaps.push_back(strpair_t("K00:A+F2", "LoadFreezeFile")); + keymaps.push_back(strpair_t("K00:C+F2", "LoadFreezeFile")); + keymaps.push_back(strpair_t("K00:F11", "LoadFreezeFile")); + keymaps.push_back(strpair_t("K00:A+F3", "SaveFreezeFile")); + keymaps.push_back(strpair_t("K00:C+F3", "SaveFreezeFile")); + keymaps.push_back(strpair_t("K00:F12", "SaveFreezeFile")); + keymaps.push_back(strpair_t("K00:F1", "QuickLoad000")); + keymaps.push_back(strpair_t("K00:F2", "QuickLoad001")); + keymaps.push_back(strpair_t("K00:F3", "QuickLoad002")); + keymaps.push_back(strpair_t("K00:F4", "QuickLoad003")); + keymaps.push_back(strpair_t("K00:F5", "QuickLoad004")); + keymaps.push_back(strpair_t("K00:F6", "QuickLoad005")); + keymaps.push_back(strpair_t("K00:F7", "QuickLoad006")); + keymaps.push_back(strpair_t("K00:F8", "QuickLoad007")); + keymaps.push_back(strpair_t("K00:F9", "QuickLoad008")); + keymaps.push_back(strpair_t("K00:S+F1", "QuickSave000")); + keymaps.push_back(strpair_t("K00:S+F2", "QuickSave001")); + keymaps.push_back(strpair_t("K00:S+F3", "QuickSave002")); + keymaps.push_back(strpair_t("K00:S+F4", "QuickSave003")); + keymaps.push_back(strpair_t("K00:S+F5", "QuickSave004")); + keymaps.push_back(strpair_t("K00:S+F6", "QuickSave005")); + keymaps.push_back(strpair_t("K00:S+F7", "QuickSave006")); + keymaps.push_back(strpair_t("K00:S+F8", "QuickSave007")); + keymaps.push_back(strpair_t("K00:S+F9", "QuickSave008")); + + keymaps.push_back(strpair_t("K00:Scroll_Lock", "Pause")); + keymaps.push_back(strpair_t("K00:CS+Escape", "Reset")); + keymaps.push_back(strpair_t("K00:S+Escape", "SoftReset")); + keymaps.push_back(strpair_t("K00:Escape", "ExitEmu")); + keymaps.push_back(strpair_t("K00:Tab", "EmuTurbo")); + keymaps.push_back(strpair_t("K00:S+Tab", "ToggleEmuTurbo")); + keymaps.push_back(strpair_t("K00:A+equal", "IncEmuTurbo")); + keymaps.push_back(strpair_t("K00:A+minus", "DecEmuTurbo")); + keymaps.push_back(strpair_t("K00:C+equal", "IncTurboSpeed")); + keymaps.push_back(strpair_t("K00:C+minus", "DecTurboSpeed")); + keymaps.push_back(strpair_t("K00:equal", "IncFrameRate")); + keymaps.push_back(strpair_t("K00:minus", "DecFrameRate")); + keymaps.push_back(strpair_t("K00:S+equal", "IncFrameTime")); + keymaps.push_back(strpair_t("K00:S+minus", "DecFrameTime")); + keymaps.push_back(strpair_t("K00:6", "SwapJoypads")); + keymaps.push_back(strpair_t("K00:Print", "Screenshot")); + + keymaps.push_back(strpair_t("K00:1", "ToggleBG0")); + keymaps.push_back(strpair_t("K00:2", "ToggleBG1")); + keymaps.push_back(strpair_t("K00:3", "ToggleBG2")); + keymaps.push_back(strpair_t("K00:4", "ToggleBG3")); + keymaps.push_back(strpair_t("K00:5", "ToggleSprites")); + keymaps.push_back(strpair_t("K00:0", "ToggleHDMA")); + keymaps.push_back(strpair_t("K00:9", "ToggleTransparency")); + keymaps.push_back(strpair_t("K00:BackSpace", "ClipWindows")); + keymaps.push_back(strpair_t("K00:A+Escape", "Debugger")); + + keymaps.push_back(strpair_t("M00:B0", "{Mouse1 L,Superscope Fire,Justifier1 Trigger}")); + keymaps.push_back(strpair_t("M00:B1", "{Justifier1 AimOffscreen Trigger,Superscope AimOffscreen}")); + keymaps.push_back(strpair_t("M00:B2", "{Mouse1 R,Superscope Cursor,Justifier1 Start}")); + keymaps.push_back(strpair_t("M00:Pointer", "Pointer Mouse1+Superscope+Justifier1")); + keymaps.push_back(strpair_t("K00:grave", "Superscope ToggleTurbo")); + keymaps.push_back(strpair_t("K00:slash", "Superscope Pause")); + } + + GUI.no_repeat = !conf.GetBool("Unix/X11::SetKeyRepeat", TRUE); + + if (conf.Exists("Unix/X11::VideoMode")) + { + GUI.video_mode = conf.GetUInt("Unix/X11::VideoMode", VIDEOMODE_BLOCKY); + if (GUI.video_mode < 1 || GUI.video_mode > 8) + GUI.video_mode = VIDEOMODE_BLOCKY; + } + else + GUI.video_mode = VIDEOMODE_BLOCKY; + + return ("Unix/X11"); +} + +static void FatalError (const char *str) +{ + fprintf(stderr, "%s\n", str); + S9xExit(); +} + +static int ErrorHandler (Display *display, XErrorEvent *event) +{ +#ifdef MITSHM + GUI.use_shared_memory = FALSE; +#endif + return (0); +} + +void S9xInitDisplay (int argc, char **argv) +{ + GUI.display = XOpenDisplay(NULL); + if (GUI.display == NULL) + FatalError("Failed to connect to X server."); + + GUI.screen = DefaultScreenOfDisplay(GUI.display); + GUI.screen_num = XScreenNumberOfScreen(GUI.screen); + GUI.visual = DefaultVisualOfScreen(GUI.screen); + + XVisualInfo plate, *matches; + int count; + + plate.visualid = XVisualIDFromVisual(GUI.visual); + matches = XGetVisualInfo(GUI.display, VisualIDMask, &plate, &count); + if (!count) + FatalError("Your X Window System server is unwell!"); + + GUI.depth = matches[0].depth; + if ((GUI.depth != 15 && GUI.depth != 16 && GUI.depth != 24) || (matches[0].c_class != TrueColor)) + FatalError("Requiers 15, 16, 24 or 32-bit color depth supporting TrueColor."); + + GUI.red_shift = ffs(matches[0].red_mask) - 1; + GUI.green_shift = ffs(matches[0].green_mask) - 1; + GUI.blue_shift = ffs(matches[0].blue_mask) - 1; + GUI.red_size = matches[0].red_mask >> GUI.red_shift; + GUI.green_size = matches[0].green_mask >> GUI.green_shift; + GUI.blue_size = matches[0].blue_mask >> GUI.blue_shift; + if (GUI.depth == 16 && GUI.green_size == 63) + GUI.green_shift++; + + XFree(matches); + + switch (GUI.depth) + { + default: + case 32: + case 24: + S9xSetRenderPixelFormat(RGB555); + GUI.pixel_format = 555; + break; + + case 16: + if (GUI.red_size != GUI.green_size || GUI.blue_size != GUI.green_size) + { + // 565 format + if (GUI.green_shift > GUI.blue_shift && GUI.green_shift > GUI.red_shift) + S9xSetRenderPixelFormat(GBR565); + else + if (GUI.red_shift > GUI.blue_shift) + S9xSetRenderPixelFormat(RGB565); + else + S9xSetRenderPixelFormat(BGR565); + + GUI.pixel_format = 565; + break; + } + // FALL ... + case 15: + if (GUI.green_shift > GUI.blue_shift && GUI.green_shift > GUI.red_shift) + S9xSetRenderPixelFormat(GBR555); + else + if (GUI.red_shift > GUI.blue_shift) + S9xSetRenderPixelFormat(RGB555); + else + S9xSetRenderPixelFormat(BGR555); + + GUI.pixel_format = 555; + break; + } + + S9xBlitFilterInit(); + S9xBlit2xSaIFilterInit(); + S9xBlitHQ2xFilterInit(); + + XSetWindowAttributes attrib; + + memset(&attrib, 0, sizeof(attrib)); + attrib.background_pixel = BlackPixelOfScreen(GUI.screen); + attrib.colormap = XCreateColormap(GUI.display, RootWindowOfScreen(GUI.screen), GUI.visual, AllocNone); + + GUI.window = XCreateWindow(GUI.display, RootWindowOfScreen(GUI.screen), + (WidthOfScreen(GUI.screen) - SNES_WIDTH * 2) / 2, (HeightOfScreen(GUI.screen) - SNES_HEIGHT_EXTENDED * 2) / 2, + SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, 0, GUI.depth, InputOutput, GUI.visual, CWBackPixel | CWColormap, &attrib); + + static XColor bg, fg; + static char data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + Pixmap bitmap; + + bitmap = XCreateBitmapFromData(GUI.display, GUI.window, data, 8, 8); + GUI.point_cursor = XCreatePixmapCursor(GUI.display, bitmap, bitmap, &fg, &bg, 0, 0); + XDefineCursor(GUI.display, GUI.window, GUI.point_cursor); + GUI.cross_hair_cursor = XCreateFontCursor(GUI.display, XC_crosshair); + + GUI.gc = DefaultGCOfScreen(GUI.screen); + + XSizeHints Hints; + XWMHints WMHints; + + memset((void *) &Hints, 0, sizeof(XSizeHints)); + memset((void *) &WMHints, 0, sizeof(XWMHints)); + + Hints.flags = PSize | PMinSize | PMaxSize; + Hints.min_width = Hints.max_width = Hints.base_width = SNES_WIDTH * 2; + Hints.min_height = Hints.max_height = Hints.base_height = SNES_HEIGHT_EXTENDED * 2; + WMHints.input = True; + WMHints.flags = InputHint; + + XSetWMHints(GUI.display, GUI.window, &WMHints); + XSetWMNormalHints(GUI.display, GUI.window, &Hints); + XSelectInput(GUI.display, GUI.window, FocusChangeMask | ExposureMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask); + + XMapRaised(GUI.display, GUI.window); + XClearWindow(GUI.display, GUI.window); + + SetupImage(); + + switch (GUI.depth) + { + default: + case 32: + GUI.bytes_per_pixel = 4; + break; + + case 24: + if (GUI.image->bits_per_pixel == 24) + GUI.bytes_per_pixel = 3; + else + GUI.bytes_per_pixel = 4; + break; + + case 15: + case 16: + GUI.bytes_per_pixel = 2; + break; + } +} + +void S9xDeinitDisplay (void) +{ + S9xTextMode(); + TakedownImage(); + XSync(GUI.display, False); + XCloseDisplay(GUI.display); + S9xBlitFilterDeinit(); + S9xBlit2xSaIFilterDeinit(); + S9xBlitHQ2xFilterDeinit(); +} + +static void TakedownImage (void) +{ + if (GUI.snes_buffer) + { + free(GUI.snes_buffer); + GUI.snes_buffer = NULL; + } + + if (GUI.filter_buffer) + { + free(GUI.filter_buffer); + GUI.filter_buffer = NULL; + } + + if (GUI.image) + { + #ifdef MITSHM + if (GUI.use_shared_memory) + { + XShmDetach(GUI.display, &GUI.sm_info); + GUI.image->data = NULL; + XDestroyImage(GUI.image); + if (GUI.sm_info.shmaddr) + shmdt(GUI.sm_info.shmaddr); + if (GUI.sm_info.shmid >= 0) + shmctl(GUI.sm_info.shmid, IPC_RMID, 0); + GUI.image = NULL; + } + else + #endif + { + XDestroyImage(GUI.image); + GUI.image = NULL; + } + } + + S9xGraphicsDeinit(); +} + +static void SetupImage (void) +{ + TakedownImage(); + +#ifdef MITSHM + GUI.use_shared_memory = TRUE; + + int major, minor; + Bool shared; + + if (!XShmQueryVersion(GUI.display, &major, &minor, &shared) || !shared) + GUI.image = NULL; + else + GUI.image = XShmCreateImage(GUI.display, GUI.visual, GUI.depth, ZPixmap, NULL, &GUI.sm_info, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2); + + if (!GUI.image) + GUI.use_shared_memory = FALSE; + else + { + GUI.sm_info.shmid = shmget(IPC_PRIVATE, GUI.image->bytes_per_line * GUI.image->height, IPC_CREAT | 0777); + if (GUI.sm_info.shmid < 0) + { + XDestroyImage(GUI.image); + GUI.use_shared_memory = FALSE; + } + else + { + GUI.image->data = GUI.sm_info.shmaddr = (char *) shmat(GUI.sm_info.shmid, 0, 0); + if (!GUI.image->data) + { + XDestroyImage(GUI.image); + shmctl(GUI.sm_info.shmid, IPC_RMID, 0); + GUI.use_shared_memory = FALSE; + } + else + { + GUI.sm_info.readOnly = False; + + XSetErrorHandler(ErrorHandler); + XShmAttach(GUI.display, &GUI.sm_info); + XSync(GUI.display, False); + + // X Error handler might clear GUI.use_shared_memory if XShmAttach failed. + if (!GUI.use_shared_memory) + { + XDestroyImage(GUI.image); + shmdt(GUI.sm_info.shmaddr); + shmctl(GUI.sm_info.shmid, IPC_RMID, 0); + } + } + } + } + + if (!GUI.use_shared_memory) + { + fprintf(stderr, "use_shared_memory failed, switching to XPutImage.\n"); +#endif + GUI.image = XCreateImage(GUI.display, GUI.visual, GUI.depth, ZPixmap, 0, NULL, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, BitmapUnit(GUI.display), 0); + GUI.image->data = (char *) malloc(GUI.image->bytes_per_line * GUI.image->height); + if (!GUI.image || !GUI.image->data) + FatalError("XCreateImage failed."); +#ifdef MITSHM + } +#endif + +#ifdef LSB_FIRST + GUI.image->byte_order = LSBFirst; +#else + GUI.image->byte_order = MSBFirst; +#endif + + GFX.Pitch = SNES_WIDTH * 2 * 2; + GUI.snes_buffer = (uint8 *) calloc(GFX.Pitch * ((SNES_HEIGHT_EXTENDED + 4) * 2), 1); + if (!GUI.snes_buffer) + FatalError("Failed to allocate GUI.snes_buffer."); + + GFX.Screen = (uint16 *) (GUI.snes_buffer + (GFX.Pitch * 2 * 2)); + + GUI.filter_buffer = (uint8 *) calloc((SNES_WIDTH * 2) * 2 * (SNES_HEIGHT_EXTENDED * 2), 1); + if (!GUI.filter_buffer) + FatalError("Failed to allocate GUI.filter_buffer."); + + if (GUI.depth == 15 || GUI.depth == 16) + { + GUI.blit_screen_pitch = GUI.image->bytes_per_line; + GUI.blit_screen = (uint8 *) GUI.image->data; + GUI.need_convert = FALSE; + } + else + { + GUI.blit_screen_pitch = (SNES_WIDTH * 2) * 2; + GUI.blit_screen = GUI.filter_buffer; + GUI.need_convert = TRUE; + } + + S9xGraphicsInit(); +} + +void S9xPutImage (int width, int height) +{ + static int prevWidth = 0, prevHeight = 0; + int copyWidth, copyHeight; + Blitter blitFn = NULL; + + if (GUI.video_mode == VIDEOMODE_BLOCKY || GUI.video_mode == VIDEOMODE_TV || GUI.video_mode == VIDEOMODE_SMOOTH) + if ((width <= SNES_WIDTH) && ((prevWidth != width) || (prevHeight != height))) + S9xBlitClearDelta(); + + if (width <= SNES_WIDTH) + { + copyWidth = width * 2; + copyHeight = height * 2; + + switch (GUI.video_mode) + { + case VIDEOMODE_BLOCKY: blitFn = S9xBlitPixScaled16; break; + case VIDEOMODE_TV: blitFn = S9xBlitPixScaledTV16; break; + case VIDEOMODE_SMOOTH: blitFn = S9xBlitPixSmooth16; break; + case VIDEOMODE_SUPEREAGLE: blitFn = S9xBlitPixSuperEagle16; break; + case VIDEOMODE_2XSAI: blitFn = S9xBlitPix2xSaI16; break; + case VIDEOMODE_SUPER2XSAI: blitFn = S9xBlitPixSuper2xSaI16; break; + case VIDEOMODE_EPX: blitFn = S9xBlitPixEPX16; break; + case VIDEOMODE_HQ2X: blitFn = S9xBlitPixHQ2x16; break; + } + } + else + if (height <= SNES_HEIGHT_EXTENDED) + { + copyWidth = width; + copyHeight = height * 2; + + switch (GUI.video_mode) + { + default: blitFn = S9xBlitPixHiRes16; break; + case VIDEOMODE_TV: blitFn = S9xBlitPixHiResTV16; break; + } + } + else + { + copyWidth = width; + copyHeight = height; + + blitFn = S9xBlitPixSmall16; + } + + blitFn((uint8 *) GFX.Screen, GFX.Pitch, GUI.blit_screen, GUI.blit_screen_pitch, width, height); + + if (height < prevHeight) + { + int p = GUI.blit_screen_pitch >> 2; + for (int y = SNES_HEIGHT * 2; y < SNES_HEIGHT_EXTENDED * 2; y++) + { + uint32 *d = (uint32 *) (GUI.blit_screen + y * GUI.blit_screen_pitch); + for (int x = 0; x < p; x++) + *d++ = 0; + } + } + + if (GUI.need_convert) + { + if (GUI.bytes_per_pixel == 3) + Convert16To24Packed(copyWidth, copyHeight); + else + Convert16To24(copyWidth, copyHeight); + } + + Repaint(TRUE); + + prevWidth = width; + prevHeight = height; +} + +static void Convert16To24 (int width, int height) +{ + if (GUI.pixel_format == 565) + { + for (int y = 0; y < height; y++) + { + uint16 *s = (uint16 *) (GUI.blit_screen + y * GUI.blit_screen_pitch); + uint32 *d = (uint32 *) (GUI.image->data + y * GUI.image->bytes_per_line); + + for (int x = 0; x < width; x++) + { + uint32 pixel = *s++; + *d++ = (((pixel >> 11) & 0x1f) << (GUI.red_shift + 3)) | (((pixel >> 6) & 0x1f) << (GUI.green_shift + 3)) | ((pixel & 0x1f) << (GUI.blue_shift + 3)); + } + } + } + else + { + for (int y = 0; y < height; y++) + { + uint16 *s = (uint16 *) (GUI.blit_screen + y * GUI.blit_screen_pitch); + uint32 *d = (uint32 *) (GUI.image->data + y * GUI.image->bytes_per_line); + + for (int x = 0; x < width; x++) + { + uint32 pixel = *s++; + *d++ = (((pixel >> 10) & 0x1f) << (GUI.red_shift + 3)) | (((pixel >> 5) & 0x1f) << (GUI.green_shift + 3)) | ((pixel & 0x1f) << (GUI.blue_shift + 3)); + } + } + } +} + +static void Convert16To24Packed (int width, int height) +{ + if (GUI.pixel_format == 565) + { + for (int y = 0; y < height; y++) + { + uint16 *s = (uint16 *) (GUI.blit_screen + y * GUI.blit_screen_pitch); + uint8 *d = (uint8 *) (GUI.image->data + y * GUI.image->bytes_per_line); + + #ifdef LSB_FIRST + if (GUI.red_shift < GUI.blue_shift) + #else + if (GUI.red_shift > GUI.blue_shift) + #endif + { + for (int x = 0; x < width; x++) + { + uint32 pixel = *s++; + *d++ = (pixel >> (11 - 3)) & 0xf8; + *d++ = (pixel >> (6 - 3)) & 0xf8; + *d++ = (pixel & 0x1f) << 3; + } + } + else + { + for (int x = 0; x < width; x++) + { + uint32 pixel = *s++; + *d++ = (pixel & 0x1f) << 3; + *d++ = (pixel >> (6 - 3)) & 0xf8; + *d++ = (pixel >> (11 - 3)) & 0xf8; + } + } + } + } + else + { + for (int y = 0; y < height; y++) + { + uint16 *s = (uint16 *) (GUI.blit_screen + y * GUI.blit_screen_pitch); + uint8 *d = (uint8 *) (GUI.image->data + y * GUI.image->bytes_per_line); + + #ifdef LSB_FIRST + if (GUI.red_shift < GUI.blue_shift) + #else + if (GUI.red_shift > GUI.blue_shift) + #endif + { + for (int x = 0; x < width; x++) + { + uint32 pixel = *s++; + *d++ = (pixel >> (10 - 3)) & 0xf8; + *d++ = (pixel >> (5 - 3)) & 0xf8; + *d++ = (pixel & 0x1f) << 3; + } + } + else + { + for (int x = 0; x < width; x++) + { + uint32 pixel = *s++; + *d++ = (pixel & 0x1f) << 3; + *d++ = (pixel >> (5 - 3)) & 0xf8; + *d++ = (pixel >> (10 - 3)) & 0xf8; + } + } + } + } +} + +static void Repaint (bool8 isFrameBoundry) +{ +#ifdef MITSHM + if (GUI.use_shared_memory) + { + XShmPutImage(GUI.display, GUI.window, GUI.gc, GUI.image, 0, 0, 0, 0, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, False); + XSync(GUI.display, False); + } + else +#endif + XPutImage(GUI.display, GUI.window, GUI.gc, GUI.image, 0, 0, 0, 0, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2); + + Window root, child; + int root_x, root_y, x, y; + unsigned int mask; + + // Use QueryPointer to sync X server and as a side effect also gets current pointer position for SNES mouse emulation. + XQueryPointer(GUI.display, GUI.window, &root, &child, &root_x, &root_y, &x, &y, &mask); + + if (x >= 0 && y >= 0 && x < SNES_WIDTH * 2 && y < SNES_HEIGHT_EXTENDED * 2) + { + GUI.mouse_x = x >> 1; + GUI.mouse_y = y >> 1; + + if (mask & Mod1Mask) + { + if (!GUI.mod1_pressed) + { + GUI.mod1_pressed = TRUE; + XDefineCursor(GUI.display, GUI.window, GUI.cross_hair_cursor); + } + } + else + if (GUI.mod1_pressed) + { + GUI.mod1_pressed = FALSE; + XDefineCursor(GUI.display, GUI.window, GUI.point_cursor); + } + } + + if (Settings.DumpStreams && isFrameBoundry) + S9xVideoLogger(GUI.image->data, SNES_WIDTH * 2, SNES_HEIGHT_EXTENDED * 2, GUI.bytes_per_pixel, GUI.image->bytes_per_line); +} + +void S9xTextMode (void) +{ + SetXRepeat(TRUE); +} + +void S9xGraphicsMode (void) +{ + SetXRepeat(FALSE); +} + +static bool8 CheckForPendingXEvents (Display *display) +{ +#ifdef SELECT_BROKEN_FOR_SIGNALS + int arg = 0; + + return (XEventsQueued(display, QueuedAlready) || (ioctl(ConnectionNumber(display), FIONREAD, &arg) == 0 && arg)); +#else + return (XPending(display)); +#endif +} + +void S9xProcessEvents (bool8 block) +{ + while (block || CheckForPendingXEvents(GUI.display)) + { + XEvent event; + + XNextEvent(GUI.display, &event); + block = FALSE; + + switch (event.type) + { + case KeyPress: + case KeyRelease: + S9xReportButton(((event.xkey.state & (ShiftMask | Mod1Mask | ControlMask | Mod4Mask)) << 8) | event.xkey.keycode, event.type == KeyPress); + #if 1 + { + KeyCode kc = XKeysymToKeycode(GUI.display, XKeycodeToKeysym(GUI.display, event.xkey.keycode, 0)); + if (event.xkey.keycode != kc) + S9xReportButton(((event.xkey.state & (ShiftMask | Mod1Mask | ControlMask | Mod4Mask)) << 8) | kc, event.type == KeyPress); + } + #endif + break; + + case FocusIn: + SetXRepeat(FALSE); + XFlush(GUI.display); + break; + + case FocusOut: + SetXRepeat(TRUE); + XFlush(GUI.display); + break; + + case ConfigureNotify: + break; + + case ButtonPress: + case ButtonRelease: + S9xReportButton(0x40000000 | (event.xbutton.button - 1), event.type == ButtonPress); + break; + + case Expose: + Repaint(FALSE); + break; + } + } +} + +const char * S9xSelectFilename (const char *def, const char *dir1, const char *ext1, const char *title) +{ + static char s[PATH_MAX + 1]; + char buffer[PATH_MAX + 1]; + + SetXRepeat(TRUE); + + printf("\n%s (default: %s): ", title, def); + fflush(stdout); + + SetXRepeat(FALSE); + + if (fgets(buffer, PATH_MAX + 1, stdin)) + { + char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; + + char *p = buffer; + while (isspace(*p)) + p++; + if (!*p) + { + strncpy(buffer, def, PATH_MAX + 1); + buffer[PATH_MAX] = 0; + p = buffer; + } + + char *q = strrchr(p, '\n'); + if (q) + *q = 0; + + _splitpath(p, drive, dir, fname, ext); + _makepath(s, drive, *dir ? dir : dir1, fname, *ext ? ext : ext1); + + return (s); + } + + return (NULL); +} + +void S9xMessage (int type, int number, const char *message) +{ + const int max = 36 * 3; + static char buffer[max + 1]; + + fprintf(stdout, "%s\n", message); + strncpy(buffer, message, max + 1); + buffer[max] = 0; + S9xSetInfoString(buffer); +} + +const char * S9xStringInput (const char *message) +{ + static char buffer[256]; + + printf("%s: ", message); + fflush(stdout); + + if (fgets(buffer, sizeof(buffer) - 2, stdin)) + return (buffer); + + return (NULL); +} + +void S9xSetTitle (const char *string) +{ + XStoreName(GUI.display, GUI.window, string); + XFlush(GUI.display); +} + +static void SetXRepeat (bool8 state) +{ + if (state) + XAutoRepeatOn(GUI.display); + else + XAutoRepeatOff(GUI.display); +} + +s9xcommand_t S9xGetDisplayCommandT (const char *n) +{ + s9xcommand_t cmd; + + cmd.type = S9xBadMapping; + cmd.multi_press = 0; + cmd.button_norpt = 0; + cmd.port[0] = 0xff; + cmd.port[1] = 0; + cmd.port[2] = 0; + cmd.port[3] = 0; + + return (cmd); +} + +char * S9xGetDisplayCommandName (s9xcommand_t cmd) +{ + return (strdup("None")); +} + +void S9xHandleDisplayCommand (s9xcommand_t cmd, int16 data1, int16 data2) +{ + return; +} + +bool8 S9xMapDisplayInput (const char *n, s9xcommand_t *cmd) +{ + int i, d; + + if (!isdigit(n[1]) || !isdigit(n[2]) || n[3] != ':') + goto unrecog; + + d = ((n[1] - '0') * 10 + (n[2] - '0')) << 24; + + switch (n[0]) + { + case 'K': + { + KeyCode kc; + KeySym ks; + + d |= 0x00000000; + + for (i = 4; n[i] != '\0' && n[i] != '+'; i++) ; + + if (n[i] == '\0' || i == 4) + i = 4; + else + { + for (i = 4; n[i] != '+'; i++) + { + switch (n[i]) + { + case 'S': d |= ShiftMask << 8; break; + case 'C': d |= ControlMask << 8; break; + case 'A': d |= Mod1Mask << 8; break; + case 'M': d |= Mod4Mask << 8; break; + default: goto unrecog; + } + } + + i++; + } + + if ((ks = XStringToKeysym(n + i)) == NoSymbol) + goto unrecog; + if ((kc = XKeysymToKeycode(GUI.display, ks)) == 0) + goto unrecog; + + d |= kc & 0xff; + + return (S9xMapButton(d, *cmd, false)); + } + + case 'M': + { + char *c; + int j; + + d |= 0x40000000; + + if (!strncmp(n + 4, "Pointer", 7)) + { + d |= 0x8000; + + if (n[11] == '\0') + return (S9xMapPointer(d, *cmd, true)); + + i = 11; + } + else + if (n[4] == 'B') + i = 5; + else + goto unrecog; + + d |= j = strtol(n + i, &c, 10); + + if ((c != NULL && *c != '\0') || j > 0x7fff) + goto unrecog; + + if (d & 0x8000) + return (S9xMapPointer(d, *cmd, true)); + + return (S9xMapButton(d, *cmd, false)); + } + + default: + break; + } + +unrecog: + char *err = new char[strlen(n) + 34]; + + sprintf(err, "Unrecognized input device name '%s'", n); + perror(err); + delete [] err; + + return (false); +} + +bool S9xDisplayPollButton (uint32 id, bool *pressed) +{ + return (false); +} + +bool S9xDisplayPollAxis (uint32 id, int16 *value) +{ + return (false); +} + +bool S9xDisplayPollPointer (uint32 id, int16 *x, int16 *y) +{ + if ((id & 0xc0008000) != 0x40008000) + return (false); + + int d = (id >> 24) & 0x3f, + n = id & 0x7fff; + + if (d != 0 || n != 0) + return (false); + + *x = GUI.mouse_x; + *y = GUI.mouse_y; + + return (true); +} + +void S9xSetPalette (void) +{ + return; +} diff --git a/unzip/crypt.h b/unzip/crypt.h new file mode 100644 index 00000000..622f4bc2 --- /dev/null +++ b/unzip/crypt.h @@ -0,0 +1,132 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) + const char *passwd; /* password string */ + unsigned char *buf; /* where to write header */ + int bufSize; + unsigned long* pkeys; + const unsigned long* pcrc_32_tab; + unsigned long crcForCrypting; +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/unzip/ioapi.c b/unzip/ioapi.c new file mode 100644 index 00000000..f1bee23e --- /dev/null +++ b/unzip/ioapi.c @@ -0,0 +1,177 @@ +/* ioapi.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#include +#include +#include + +#include "zlib.h" +#include "ioapi.h" + + + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +voidpf ZCALLBACK fopen_file_func OF(( + voidpf opaque, + const char* filename, + int mode)); + +uLong ZCALLBACK fread_file_func OF(( + voidpf opaque, + voidpf stream, + void* buf, + uLong size)); + +uLong ZCALLBACK fwrite_file_func OF(( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size)); + +long ZCALLBACK ftell_file_func OF(( + voidpf opaque, + voidpf stream)); + +long ZCALLBACK fseek_file_func OF(( + voidpf opaque, + voidpf stream, + uLong offset, + int origin)); + +int ZCALLBACK fclose_file_func OF(( + voidpf opaque, + voidpf stream)); + +int ZCALLBACK ferror_file_func OF(( + voidpf opaque, + voidpf stream)); + + +voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) + voidpf opaque; + const char* filename; + int mode; +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + + +uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + + +uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + const void* buf; + uLong size; +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +long ZCALLBACK ftell_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + +long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) + voidpf opaque; + voidpf stream; + uLong offset; + int origin; +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + fseek((FILE *)stream, offset, fseek_origin); + return ret; +} + +int ZCALLBACK fclose_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +int ZCALLBACK ferror_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/unzip/ioapi.h b/unzip/ioapi.h new file mode 100644 index 00000000..7d457baa --- /dev/null +++ b/unzip/ioapi.h @@ -0,0 +1,75 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#ifndef _ZLIBIOAPI_H +#define _ZLIBIOAPI_H + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + +#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) +#define ZCALLBACK CALLBACK +#else +#define ZCALLBACK +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + + + +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) +#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) +#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) +#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) +#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/unzip/iowin32.c b/unzip/iowin32.c new file mode 100644 index 00000000..a9b5f783 --- /dev/null +++ b/unzip/iowin32.c @@ -0,0 +1,270 @@ +/* iowin32.c -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + This IO API version uses the Win32 API (for Microsoft Windows) + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#include + +#include "zlib.h" +#include "ioapi.h" +#include "iowin32.h" + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE (0xFFFFFFFF) +#endif + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +voidpf ZCALLBACK win32_open_file_func OF(( + voidpf opaque, + const char* filename, + int mode)); + +uLong ZCALLBACK win32_read_file_func OF(( + voidpf opaque, + voidpf stream, + void* buf, + uLong size)); + +uLong ZCALLBACK win32_write_file_func OF(( + voidpf opaque, + voidpf stream, + const void* buf, + uLong size)); + +long ZCALLBACK win32_tell_file_func OF(( + voidpf opaque, + voidpf stream)); + +long ZCALLBACK win32_seek_file_func OF(( + voidpf opaque, + voidpf stream, + uLong offset, + int origin)); + +int ZCALLBACK win32_close_file_func OF(( + voidpf opaque, + voidpf stream)); + +int ZCALLBACK win32_error_file_func OF(( + voidpf opaque, + voidpf stream)); + +typedef struct +{ + HANDLE hf; + int error; +} WIN32FILE_IOWIN; + +voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode) + voidpf opaque; + const char* filename; + int mode; +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = 0; + voidpf ret=NULL; + + dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0; + + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + { + dwDesiredAccess = GENERIC_READ; + dwCreationDisposition = OPEN_EXISTING; + dwShareMode = FILE_SHARE_READ; + } + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + { + dwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + dwCreationDisposition = OPEN_EXISTING; + } + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + { + dwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + dwCreationDisposition = CREATE_ALWAYS; + } + + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, + dwCreationDisposition, dwFlagsAndAttributes, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + hFile = NULL; + + if (hFile != NULL) + { + WIN32FILE_IOWIN w32fiow; + w32fiow.hf = hFile; + w32fiow.error = 0; + ret = malloc(sizeof(WIN32FILE_IOWIN)); + if (ret==NULL) + CloseHandle(hFile); + else *((WIN32FILE_IOWIN*)ret) = w32fiow; + } + return ret; +} + + +uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + void* buf; + uLong size; +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + if (!ReadFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + + return ret; +} + + +uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size) + voidpf opaque; + voidpf stream; + const void* buf; + uLong size; +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + + if (hFile !=NULL) + if (!WriteFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + + return ret; +} + +long ZCALLBACK win32_tell_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + long ret=-1; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); + if (dwSet == INVALID_SET_FILE_POINTER) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=(long)dwSet; + } + return ret; +} + +long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin) + voidpf opaque; + voidpf stream; + uLong offset; + int origin; +{ + DWORD dwMoveMethod=0xFFFFFFFF; + HANDLE hFile = NULL; + + long ret=-1; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END : + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + dwMoveMethod = FILE_BEGIN; + break; + default: return -1; + } + + if (hFile != NULL) + { + DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod); + if (dwSet == INVALID_SET_FILE_POINTER) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=0; + } + return ret; +} + +int ZCALLBACK win32_close_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret=-1; + + if (stream!=NULL) + { + HANDLE hFile; + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + CloseHandle(hFile); + ret=0; + } + free(stream); + } + return ret; +} + +int ZCALLBACK win32_error_file_func (opaque, stream) + voidpf opaque; + voidpf stream; +{ + int ret=-1; + if (stream!=NULL) + { + ret = ((WIN32FILE_IOWIN*)stream) -> error; + } + return ret; +} + +void fill_win32_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = win32_open_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell_file = win32_tell_file_func; + pzlib_filefunc_def->zseek_file = win32_seek_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque=NULL; +} diff --git a/unzip/iowin32.h b/unzip/iowin32.h new file mode 100644 index 00000000..a3a437ad --- /dev/null +++ b/unzip/iowin32.h @@ -0,0 +1,21 @@ +/* iowin32.h -- IO base function header for compress/uncompress .zip + files using zlib + zip or unzip API + This IO API version uses the Win32 API (for Microsoft Windows) + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +#ifdef __cplusplus +} +#endif diff --git a/unzip/miniunz.c b/unzip/miniunz.c new file mode 100644 index 00000000..f5999388 --- /dev/null +++ b/unzip/miniunz.c @@ -0,0 +1,585 @@ +/* + miniunz.c + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant +*/ + + +#include +#include +#include +#include +#include +#include + +#ifdef unix +# include +# include +#else +# include +# include +#endif + +#include "unzip.h" + +#define CASESENSITIVITY (0) +#define WRITEBUFFERSIZE (8192) +#define MAXFILENAME (256) + +#ifdef WIN32 +#define USEWIN32IOAPI +#include "iowin32.h" +#endif +/* + mini unzip, demo of unzip package + + usage : + Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] + + list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT + if it exists +*/ + + +/* change_file_date : change the date/time of a file + filename : the filename of the file where date/time must be modified + dosdate : the new date at the MSDos format (4 bytes) + tmu_date : the SAME new date at the tm_unz format */ +void change_file_date(filename,dosdate,tmu_date) + const char *filename; + uLong dosdate; + tm_unz tmu_date; +{ +#ifdef WIN32 + HANDLE hFile; + FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; + + hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE, + 0,NULL,OPEN_EXISTING,0,NULL); + GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); + DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); + LocalFileTimeToFileTime(&ftLocal,&ftm); + SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); + CloseHandle(hFile); +#else +#ifdef unix + struct utimbuf ut; + struct tm newdate; + newdate.tm_sec = tmu_date.tm_sec; + newdate.tm_min=tmu_date.tm_min; + newdate.tm_hour=tmu_date.tm_hour; + newdate.tm_mday=tmu_date.tm_mday; + newdate.tm_mon=tmu_date.tm_mon; + if (tmu_date.tm_year > 1900) + newdate.tm_year=tmu_date.tm_year - 1900; + else + newdate.tm_year=tmu_date.tm_year ; + newdate.tm_isdst=-1; + + ut.actime=ut.modtime=mktime(&newdate); + utime(filename,&ut); +#endif +#endif +} + + +/* mymkdir and change_file_date are not 100 % portable + As I don't know well Unix, I wait feedback for the unix portion */ + +int mymkdir(dirname) + const char* dirname; +{ + int ret=0; +#ifdef WIN32 + ret = mkdir(dirname); +#else +#ifdef unix + ret = mkdir (dirname,0775); +#endif +#endif + return ret; +} + +int makedir (newdir) + char *newdir; +{ + char *buffer ; + char *p; + int len = (int)strlen(newdir); + + if (len <= 0) + return 0; + + buffer = (char*)malloc(len+1); + strcpy(buffer,newdir); + + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mymkdir(buffer) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mymkdir(buffer) == -1) && (errno == ENOENT)) + { + printf("couldn't create directory %s\n",buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + +void do_banner() +{ + printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); + printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); +} + +void do_help() +{ + printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ + " -e Extract without pathname (junk paths)\n" \ + " -x Extract with pathname\n" \ + " -v list files\n" \ + " -l list files\n" \ + " -d directory to extract into\n" \ + " -o overwrite files without prompting\n" \ + " -p extract crypted file using password\n\n"); +} + + +int do_list(uf) + unzFile uf; +{ + uLong i; + unz_global_info gi; + int err; + + err = unzGetGlobalInfo (uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); + printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); + for (i=0;i0) + ratio = (file_info.compressed_size*100)/file_info.uncompressed_size; + + /* display a '*' if the file is crypted */ + if ((file_info.flag & 1) != 0) + charCrypt='*'; + + if (file_info.compression_method==0) + string_method="Stored"; + else + if (file_info.compression_method==Z_DEFLATED) + { + uInt iLevel=(uInt)((file_info.flag & 0x6)/2); + if (iLevel==0) + string_method="Defl:N"; + else if (iLevel==1) + string_method="Defl:X"; + else if ((iLevel==2) || (iLevel==3)) + string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ + } + else + string_method="Unkn. "; + + printf("%7lu %6s%c%7lu %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", + file_info.uncompressed_size,string_method, + charCrypt, + file_info.compressed_size, + ratio, + (uLong)file_info.tmu_date.tm_mon + 1, + (uLong)file_info.tmu_date.tm_mday, + (uLong)file_info.tmu_date.tm_year % 100, + (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, + (uLong)file_info.crc,filename_inzip); + if ((i+1)='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + } + + if (rep == 'N') + skip = 1; + + if (rep == 'A') + *popt_overwrite=1; + } + + if ((skip==0) && (err==UNZ_OK)) + { + fout=fopen(write_filename,"wb"); + + /* some zipfile don't contain directory alone before file */ + if ((fout==NULL) && ((*popt_extract_without_path)==0) && + (filename_withoutpath!=(char*)filename_inzip)) + { + char c=*(filename_withoutpath-1); + *(filename_withoutpath-1)='\0'; + makedir(write_filename); + *(filename_withoutpath-1)=c; + fout=fopen(write_filename,"wb"); + } + + if (fout==NULL) + { + printf("error opening %s\n",write_filename); + } + } + + if (fout!=NULL) + { + printf(" extracting: %s\n",write_filename); + + do + { + err = unzReadCurrentFile(uf,buf,size_buf); + if (err<0) + { + printf("error %d with zipfile in unzReadCurrentFile\n",err); + break; + } + if (err>0) + if (fwrite(buf,err,1,fout)!=1) + { + printf("error in writing extracted file\n"); + err=UNZ_ERRNO; + break; + } + } + while (err>0); + if (fout) + fclose(fout); + + if (err==0) + change_file_date(write_filename,file_info.dosDate, + file_info.tmu_date); + } + + if (err==UNZ_OK) + { + err = unzCloseCurrentFile (uf); + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzCloseCurrentFile\n",err); + } + } + else + unzCloseCurrentFile(uf); /* don't lose the error */ + } + + free(buf); + return err; +} + + +int do_extract(uf,opt_extract_without_path,opt_overwrite,password) + unzFile uf; + int opt_extract_without_path; + int opt_overwrite; + const char* password; +{ + uLong i; + unz_global_info gi; + int err; + FILE* fout=NULL; + + err = unzGetGlobalInfo (uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + + for (i=0;i +#include +#include +#include +#include +#include + +#ifdef unix +# include +# include +# include +# include +#else +# include +# include +#endif + +#include "zip.h" + +#ifdef WIN32 +#define USEWIN32IOAPI +#include "iowin32.h" +#endif + + + +#define WRITEBUFFERSIZE (16384) +#define MAXFILENAME (256) + +#ifdef WIN32 +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret = 0; + { + FILETIME ftLocal; + HANDLE hFind; + WIN32_FIND_DATA ff32; + + hFind = FindFirstFile(f,&ff32); + if (hFind != INVALID_HANDLE_VALUE) + { + FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); + FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); + FindClose(hFind); + ret = 1; + } + } + return ret; +} +#else +#ifdef unix +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret=0; + struct stat s; /* results of stat() */ + struct tm* filedate; + time_t tm_t=0; + + if (strcmp(f,"-")!=0) + { + char name[MAXFILENAME+1]; + int len = strlen(f); + if (len > MAXFILENAME) + len = MAXFILENAME; + + strncpy(name, f,MAXFILENAME-1); + /* strncpy doesnt append the trailing NULL, of the string is too long. */ + name[ MAXFILENAME ] = '\0'; + + if (name[len - 1] == '/') + name[len - 1] = '\0'; + /* not all systems allow stat'ing a file with / appended */ + if (stat(name,&s)==0) + { + tm_t = s.st_mtime; + ret = 1; + } + } + filedate = localtime(&tm_t); + + tmzip->tm_sec = filedate->tm_sec; + tmzip->tm_min = filedate->tm_min; + tmzip->tm_hour = filedate->tm_hour; + tmzip->tm_mday = filedate->tm_mday; + tmzip->tm_mon = filedate->tm_mon ; + tmzip->tm_year = filedate->tm_year; + + return ret; +} +#else +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + return 0; +} +#endif +#endif + + + + +int check_exist_file(filename) + const char* filename; +{ + FILE* ftestexist; + int ret = 1; + ftestexist = fopen(filename,"rb"); + if (ftestexist==NULL) + ret = 0; + else + fclose(ftestexist); + return ret; +} + +void do_banner() +{ + printf("MiniZip 1.01b, demo of zLib + Zip package written by Gilles Vollant\n"); + printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); +} + +void do_help() +{ + printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \ + " -o Overwrite existing file.zip\n" \ + " -a Append to existing file.zip\n" \ + " -0 Store only\n" \ + " -1 Compress faster\n" \ + " -9 Compress better\n\n"); +} + +/* calculate the CRC32 of a file, + because to encrypt a file, we need known the CRC32 of the file before */ +int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) +{ + unsigned long calculate_crc=0; + int err=ZIP_OK; + FILE * fin = fopen(filenameinzip,"rb"); + unsigned long size_read = 0; + unsigned long total_read = 0; + if (fin==NULL) + { + err = ZIP_ERRNO; + } + + if (err == ZIP_OK) + do + { + err = ZIP_OK; + size_read = (int)fread(buf,1,size_buf,fin); + if (size_read < size_buf) + if (feof(fin)==0) + { + printf("error in reading %s\n",filenameinzip); + err = ZIP_ERRNO; + } + + if (size_read>0) + calculate_crc = crc32(calculate_crc,buf,size_read); + total_read += size_read; + + } while ((err == ZIP_OK) && (size_read>0)); + + if (fin) + fclose(fin); + + *result_crc=calculate_crc; + printf("file %s crc %x\n",filenameinzip,calculate_crc); + return err; +} + +int main(argc,argv) + int argc; + char *argv[]; +{ + int i; + int opt_overwrite=0; + int opt_compress_level=Z_DEFAULT_COMPRESSION; + int zipfilenamearg = 0; + char filename_try[MAXFILENAME+16]; + int zipok; + int err=0; + int size_buf=0; + void* buf=NULL; + const char* password=NULL; + + + do_banner(); + if (argc==1) + { + do_help(); + return 0; + } + else + { + for (i=1;i='0') && (c<='9')) + opt_compress_level = c-'0'; + + if (((c=='p') || (c=='P')) && (i+1='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + if (rep=='N') + zipok = 0; + if (rep=='A') + opt_overwrite = 2; + } + } + + if (zipok==1) + { + zipFile zf; + int errclose; +# ifdef USEWIN32IOAPI + zlib_filefunc_def ffunc; + fill_win32_filefunc(&ffunc); + zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); +# else + zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0); +# endif + + if (zf == NULL) + { + printf("error opening %s\n",filename_try); + err= ZIP_ERRNO; + } + else + printf("creating %s\n",filename_try); + + for (i=zipfilenamearg+1;(i='0') || (argv[i][1]<='9'))) && + (strlen(argv[i]) == 2))) + { + FILE * fin; + int size_read; + const char* filenameinzip = argv[i]; + zip_fileinfo zi; + unsigned long crcFile=0; + + zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = + zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; + zi.dosDate = 0; + zi.internal_fa = 0; + zi.external_fa = 0; + filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); + +/* + err = zipOpenNewFileInZip(zf,filenameinzip,&zi, + NULL,0,NULL,0,NULL / * comment * /, + (opt_compress_level != 0) ? Z_DEFLATED : 0, + opt_compress_level); +*/ + if ((password != NULL) && (err==ZIP_OK)) + err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); + + err = zipOpenNewFileInZip3(zf,filenameinzip,&zi, + NULL,0,NULL,0,NULL /* comment*/, + (opt_compress_level != 0) ? Z_DEFLATED : 0, + opt_compress_level,0, + /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + password,crcFile); + + if (err != ZIP_OK) + printf("error in opening %s in zipfile\n",filenameinzip); + else + { + fin = fopen(filenameinzip,"rb"); + if (fin==NULL) + { + err=ZIP_ERRNO; + printf("error in opening %s for reading\n",filenameinzip); + } + } + + if (err == ZIP_OK) + do + { + err = ZIP_OK; + size_read = (int)fread(buf,1,size_buf,fin); + if (size_read < size_buf) + if (feof(fin)==0) + { + printf("error in reading %s\n",filenameinzip); + err = ZIP_ERRNO; + } + + if (size_read>0) + { + err = zipWriteInFileInZip (zf,buf,size_read); + if (err<0) + { + printf("error in writing %s in the zipfile\n", + filenameinzip); + } + + } + } while ((err == ZIP_OK) && (size_read>0)); + + if (fin) + fclose(fin); + + if (err<0) + err=ZIP_ERRNO; + else + { + err = zipCloseFileInZip(zf); + if (err!=ZIP_OK) + printf("error in closing %s in the zipfile\n", + filenameinzip); + } + } + } + errclose = zipClose(zf,NULL); + if (errclose != ZIP_OK) + printf("error in closing %s\n",filename_try); + } + else + { + do_help(); + } + + free(buf); + return 0; +} diff --git a/unzip/mztools.c b/unzip/mztools.c new file mode 100644 index 00000000..8a50ee43 --- /dev/null +++ b/unzip/mztools.c @@ -0,0 +1,281 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +/* Code */ +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#define READ_8(adr) ((unsigned char)*(adr)) +#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) +#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) + +#define WRITE_8(buff, n) do { \ + *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ +} while(0) +#define WRITE_16(buff, n) do { \ + WRITE_8((unsigned char*)(buff), n); \ + WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ +} while(0) +#define WRITE_32(buff, n) do { \ + WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ + WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ +} while(0) + +extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) +const char* file; +const char* fileOut; +const char* fileOutTmp; +uLong* nRecovered; +uLong* bytesRecovered; +{ + int err = Z_OK; + FILE* fpZip = fopen(file, "rb"); + FILE* fpOut = fopen(fileOut, "wb"); + FILE* fpOutCD = fopen(fileOutTmp, "wb"); + if (fpZip != NULL && fpOut != NULL) { + int entries = 0; + uLong totalBytes = 0; + char header[30]; + char filename[256]; + char extra[1024]; + int offset = 0; + int offsetCD = 0; + while ( fread(header, 1, 30, fpZip) == 30 ) { + int currentOffset = offset; + + /* File entry */ + if (READ_32(header) == 0x04034b50) { + unsigned int version = READ_16(header + 4); + unsigned int gpflag = READ_16(header + 6); + unsigned int method = READ_16(header + 8); + unsigned int filetime = READ_16(header + 10); + unsigned int filedate = READ_16(header + 12); + unsigned int crc = READ_32(header + 14); /* crc */ + unsigned int cpsize = READ_32(header + 18); /* compressed size */ + unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ + unsigned int fnsize = READ_16(header + 26); /* file name length */ + unsigned int extsize = READ_16(header + 28); /* extra field length */ + filename[0] = extra[0] = '\0'; + + /* Header */ + if (fwrite(header, 1, 30, fpOut) == 30) { + offset += 30; + } else { + err = Z_ERRNO; + break; + } + + /* Filename */ + if (fnsize > 0) { + if (fread(filename, 1, fnsize, fpZip) == fnsize) { + if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { + offset += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fread(extra, 1, extsize, fpZip) == extsize) { + if (fwrite(extra, 1, extsize, fpOut) == extsize) { + offset += extsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } + + /* Data */ + { + int dataSize = cpsize; + if (dataSize == 0) { + dataSize = uncpsize; + } + if (dataSize > 0) { + char* data = malloc(dataSize); + if (data != NULL) { + if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { + if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { + offset += dataSize; + totalBytes += dataSize; + } else { + err = Z_ERRNO; + } + } else { + err = Z_ERRNO; + } + free(data); + if (err != Z_OK) { + break; + } + } else { + err = Z_MEM_ERROR; + break; + } + } + } + + /* Central directory entry */ + { + char header[46]; + char* comment = ""; + int comsize = (int) strlen(comment); + WRITE_32(header, 0x02014b50); + WRITE_16(header + 4, version); + WRITE_16(header + 6, version); + WRITE_16(header + 8, gpflag); + WRITE_16(header + 10, method); + WRITE_16(header + 12, filetime); + WRITE_16(header + 14, filedate); + WRITE_32(header + 16, crc); + WRITE_32(header + 20, cpsize); + WRITE_32(header + 24, uncpsize); + WRITE_16(header + 28, fnsize); + WRITE_16(header + 30, extsize); + WRITE_16(header + 32, comsize); + WRITE_16(header + 34, 0); /* disk # */ + WRITE_16(header + 36, 0); /* int attrb */ + WRITE_32(header + 38, 0); /* ext attrb */ + WRITE_32(header + 42, currentOffset); + /* Header */ + if (fwrite(header, 1, 46, fpOutCD) == 46) { + offsetCD += 46; + + /* Filename */ + if (fnsize > 0) { + if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { + offsetCD += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { + offsetCD += extsize; + } else { + err = Z_ERRNO; + break; + } + } + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { + offsetCD += comsize; + } else { + err = Z_ERRNO; + break; + } + } + + + } else { + err = Z_ERRNO; + break; + } + } + + /* Success */ + entries++; + + } else { + break; + } + } + + /* Final central directory */ + { + int entriesZip = entries; + char header[22]; + char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; + int comsize = (int) strlen(comment); + if (entriesZip > 0xffff) { + entriesZip = 0xffff; + } + WRITE_32(header, 0x06054b50); + WRITE_16(header + 4, 0); /* disk # */ + WRITE_16(header + 6, 0); /* disk # */ + WRITE_16(header + 8, entriesZip); /* hack */ + WRITE_16(header + 10, entriesZip); /* hack */ + WRITE_32(header + 12, offsetCD); /* size of CD */ + WRITE_32(header + 16, offset); /* offset to CD */ + WRITE_16(header + 20, comsize); /* comment */ + + /* Header */ + if (fwrite(header, 1, 22, fpOutCD) == 22) { + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { + err = Z_ERRNO; + } + } + + } else { + err = Z_ERRNO; + } + } + + /* Final merge (file + central directory) */ + fclose(fpOutCD); + if (err == Z_OK) { + fpOutCD = fopen(fileOutTmp, "rb"); + if (fpOutCD != NULL) { + int nRead; + char buffer[8192]; + while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { + if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { + err = Z_ERRNO; + break; + } + } + fclose(fpOutCD); + } + } + + /* Close */ + fclose(fpZip); + fclose(fpOut); + + /* Wipe temporary file */ + (void)remove(fileOutTmp); + + /* Number of recovered entries */ + if (err == Z_OK) { + if (nRecovered != NULL) { + *nRecovered = entries; + } + if (bytesRecovered != NULL) { + *bytesRecovered = totalBytes; + } + } + } else { + err = Z_STREAM_ERROR; + } + return err; +} diff --git a/unzip/mztools.h b/unzip/mztools.h new file mode 100644 index 00000000..eee78dc5 --- /dev/null +++ b/unzip/mztools.h @@ -0,0 +1,31 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +#ifndef _zip_tools_H +#define _zip_tools_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#include "unzip.h" + +/* Repair a ZIP file (missing central directory) + file: file to recover + fileOut: output file after recovery + fileOutTmp: temporary file name used for recovery +*/ +extern int ZEXPORT unzRepair(const char* file, + const char* fileOut, + const char* fileOutTmp, + uLong* nRecovered, + uLong* bytesRecovered); + +#endif diff --git a/unzip/unzip.c b/unzip/unzip.c new file mode 100644 index 00000000..82896bd4 --- /dev/null +++ b/unzip/unzip.c @@ -0,0 +1,1608 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + Read unzip.h for more info +*/ + +/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of +compatibility with older software. The following is from the original crypt.c. Code +woven in by Terry Thorsen 1/2003. +*/ +/* + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html +*/ +/* + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + */ + +/* + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + */ + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info_internal_s +{ + uLong offset_curfile;/* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + + uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + uLong offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + uLong pos_local_extrafield; /* position in the local extra field in read*/ + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + uLong rest_read_compressed; /* number of byte to be decompressed */ + uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + uLong num_file; /* number of the current file in the zipfile*/ + uLong pos_in_central_dir; /* pos of the current file in the central dir*/ + uLong current_file_ok; /* flag about the usability of the current file*/ + uLong central_pos; /* position of the beginning of the central dir*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; +# endif +} unz_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been sucessfully opened for reading. +*/ + + +local int unzlocal_getByte OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + int *pi; +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unzlocal_getShort OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i = 0; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unzlocal_getLong OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i = 0; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (fileName1,fileName2) + const char* fileName1; + const char* fileName2; +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity) + const char* fileName1; + const char* fileName2; + int iCaseSensitivity; +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong unzlocal_SearchCentralDir OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream)); + +local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def) + const char *path; + zlib_filefunc_def* pzlib_filefunc_def; +{ + unz_s us; + unz_s *s; + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&us.z_filefunc); + else + us.z_filefunc = *pzlib_filefunc_def; + + us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + if (ZSEEK(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* zipfile comment length */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info) + unzFile file; + unz_global_info *pglobal_info; +{ + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + + +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) + uLong ulDosDate; + tm_unz* ptm; +{ + uLong uDate; + uDate = (uLong)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info *pfile_info, + unz_file_info_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unzlocal_GetCurrentFileInfoInternal (file, + pfile_info, + pfile_info_internal, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + unz_file_info_internal *pfile_info_internal; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + unz_s* s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (ZSEEK(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + + if ((err==UNZ_OK) && (extraField!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek += file_info.size_file_extra - uSizeRead; + } + else + lSeek+=file_info.size_file_extra; + + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo (file, + pfile_info, + szFileName, fileNameBufferSize, + extraField, extraFieldBufferSize, + szComment, commentBufferSize) + unzFile file; + unz_file_info *pfile_info; + char *szFileName; + uLong fileNameBufferSize; + void *extraField; + uLong extraFieldBufferSize; + char *szComment; + uLong commentBufferSize; +{ + return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (file) + unzFile file; +{ + int err=UNZ_OK; + unz_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (file) + unzFile file; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzipStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity) + unzFile file; + const char *szFileName; + int iCaseSensitivity; +{ + unz_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info cur_file_infoSaved; + unz_file_info_internal cur_file_info_internalSaved; + uLong num_fileSaved; + uLong pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; // offset in file + uLong num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGoToFilePos(file, file_pos) + unzFile file; + unz_file_pos* file_pos; +{ + unz_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, + poffset_local_extrafield, + psize_local_extrafield) + unz_s* s; + uInt* piSizeVar; + uLong *poffset_local_extrafield; + uInt *psize_local_extrafield; +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && + ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) + unzFile file; + int* method; + int* level; + int raw; + const char* password; +{ + int err=UNZ_OK; + uInt iSizeVar; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uLong offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, + &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip_read_info_s*) + ALLOC(sizeof(file_in_zip_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->compression_method = + s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_DEFLATED) && + (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=1; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (file) + unzFile file; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (file, password) + unzFile file; + const char* password; +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) + unzFile file; + int* method; + int* level; + int raw; +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (file, buf, len) + unzFile file; + voidp buf; + unsigned len; +{ + int err=UNZ_OK; + uInt iRead = 0; + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (file) + unzFile file; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (file,buf,len) + unzFile file; + voidp buf; + unsigned len; +{ + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + uInt read_now; + uLong size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzipOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (file) + unzFile file; +{ + int err=UNZ_OK; + + unz_s* s; + file_in_zip_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) + unzFile file; + char *szComment; + uLong uSizeBuf; +{ + /* int err=UNZ_OK; */ + unz_s* s; + uLong uReadThis ; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern uLong ZEXPORT unzGetOffset (file) + unzFile file; +{ + unz_s* s; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern int ZEXPORT unzSetOffset (file, pos) + unzFile file; + uLong pos; +{ + unz_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} diff --git a/unzip/unzip.h b/unzip/unzip.h new file mode 100644 index 00000000..b247937c --- /dev/null +++ b/unzip/unzip.h @@ -0,0 +1,354 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _unz_H +#define _unz_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz_H */ diff --git a/unzip/zip.c b/unzip/zip.c new file mode 100644 index 00000000..f1948013 --- /dev/null +++ b/unzip/zip.c @@ -0,0 +1,1220 @@ +/* zip.c -- IO on .zip files using zlib + Version 1.01e, February 12th, 2005 + + 27 Dec 2004 Rolf Kalbermatter + Modification to zipOpen2 to support globalComment retrieval. + + Copyright (C) 1998-2005 Gilles Vollant + + Read zip.h for more info +*/ + + +#include +#include +#include +#include +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif +const char zip_copyright[] = + " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignement */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + uLong pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralheader; /* size of the central header for cur file */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + int raw; /* 1 for directly writing raw data */ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; + int encrypt; +#ifndef NOCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const unsigned long* pcrc_32_tab; + int crypt_header_size; +#endif +} curfile_info; + +typedef struct +{ + zlib_filefunc_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile_info ci; /* info on the file curretly writing */ + + uLong begin_pos; /* position of the beginning of the zipfile */ + uLong add_position_when_writting_offset; + uLong number_entry; +#ifndef NO_ADDFILEINEXISTINGZIP + char *globalcomment; +#endif +} zip_internal; + + + +#ifndef NOCRYPT +#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +#include "crypt.h" +#endif + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(ldi) + linkedlist_datablock_internal* ldi; +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(ll) + linkedlist_data* ll; +{ + ll->first_block = ll->last_block = NULL; +} + +/* Unused +local void free_linkedlist(ll) + linkedlist_data* ll; +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} +*/ + +local int add_data_in_datablock(ll,buf,len) + linkedlist_data* ll; + const void* buf; + uLong len; +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;ifilled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + + +/****************************************************************************/ + +#ifndef NO_ADDFILEINEXISTINGZIP +/* =========================================================================== + Inputs a long in LSB order to the given file + nbByte == 1, 2 or 4 (byte, short or long) +*/ + +local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, uLong x, int nbByte)); +local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong x; + int nbByte; +{ + unsigned char buf[4]; + int n; + for (n = 0; n < nbByte; n++) + { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (x != 0) + { /* data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } + + if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte)); +local void ziplocal_putValue_inmemory (dest, x, nbByte) + void* dest; + uLong x; + int nbByte; +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + + if (x != 0) + { /* data overflow - hack for ZIP64 */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } +} + +/****************************************************************************/ + + +local uLong ziplocal_TmzDateToDosDate(ptm,dosDate) + const tm_zip* ptm; + uLong dosDate; +{ + uLong year = (uLong)ptm->tm_year; + if (year>1980) + year-=1980; + else if (year>80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +local int ziplocal_getByte OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + int *pi; +{ + unsigned char c; + int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return ZIP_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def,filestream)) + return ZIP_ERRNO; + else + return ZIP_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int ziplocal_getShort OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i = 0; + int err; + + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int ziplocal_getLong OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; + uLong *pX; +{ + uLong x ; + int i = 0; + int err; + + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==ZIP_OK) + err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local uLong ziplocal_SearchCentralDir OF(( + const zlib_filefunc_def* pzlib_filefunc_def, + voidpf filestream)); + +local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream) + const zlib_filefunc_def* pzlib_filefunc_def; + voidpf filestream; +{ + unsigned char* buf; + uLong uSizeFile; + uLong uBackRead; + uLong uMaxBack=0xffff; /* maximum size of global comment */ + uLong uPosFound=0; + + if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); + if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} +#endif /* !NO_ADDFILEINEXISTINGZIP*/ + +/************************************************************/ +extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def) + const char *pathname; + int append; + zipcharpc* globalcomment; + zlib_filefunc_def* pzlib_filefunc_def; +{ + zip_internal ziinit; + zip_internal* zi; + int err=ZIP_OK; + + + if (pzlib_filefunc_def==NULL) + fill_fopen_filefunc(&ziinit.z_filefunc); + else + ziinit.z_filefunc = *pzlib_filefunc_def; + + ziinit.filestream = (*(ziinit.z_filefunc.zopen_file)) + (ziinit.z_filefunc.opaque, + pathname, + (append == APPEND_STATUS_CREATE) ? + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); + + if (ziinit.filestream == NULL) + return NULL; + ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + ziinit.add_position_when_writting_offset = 0; + init_linkedlist(&(ziinit.central_dir)); + + + zi = (zip_internal*)ALLOC(sizeof(zip_internal)); + if (zi==NULL) + { + ZCLOSE(ziinit.z_filefunc,ziinit.filestream); + return NULL; + } + + /* now we add file in a zipfile */ +# ifndef NO_ADDFILEINEXISTINGZIP + ziinit.globalcomment = NULL; + if (append == APPEND_STATUS_ADDINZIP) + { + uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + + uLong size_central_dir; /* size of the central directory */ + uLong offset_central_dir; /* offset of start of central directory */ + uLong central_pos,uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + uLong number_entry; + uLong number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + uLong size_comment; + + central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream); + if (central_pos==0) + err=ZIP_ERRNO; + + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((number_entry_CD!=number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* zipfile global comment length */ + if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((central_pos0) + { + ziinit.globalcomment = ALLOC(size_comment+1); + if (ziinit.globalcomment) + { + size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment); + ziinit.globalcomment[size_comment]=0; + } + } + + byte_before_the_zipfile = central_pos - + (offset_central_dir+size_central_dir); + ziinit.add_position_when_writting_offset = byte_before_the_zipfile; + + { + uLong size_central_dir_to_read = size_central_dir; + size_t buf_size = SIZEDATA_INDATABLOCK; + void* buf_read = (void*)ALLOC(buf_size); + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + offset_central_dir + byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + while ((size_central_dir_to_read>0) && (err==ZIP_OK)) + { + uLong read_this = SIZEDATA_INDATABLOCK; + if (read_this > size_central_dir_to_read) + read_this = size_central_dir_to_read; + if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this) + err=ZIP_ERRNO; + + if (err==ZIP_OK) + err = add_data_in_datablock(&ziinit.central_dir,buf_read, + (uLong)read_this); + size_central_dir_to_read-=read_this; + } + TRYFREE(buf_read); + } + ziinit.begin_pos = byte_before_the_zipfile; + ziinit.number_entry = number_entry_CD; + + if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, + offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + } + + if (globalcomment) + { + *globalcomment = ziinit.globalcomment; + } +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + + if (err != ZIP_OK) + { +# ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(ziinit.globalcomment); +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + TRYFREE(zi); + return NULL; + } + else + { + *zi = ziinit; + return (zipFile)zi; + } +} + +extern zipFile ZEXPORT zipOpen (pathname, append) + const char *pathname; + int append; +{ + return zipOpen2(pathname,append,NULL,NULL); +} + +extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; + int raw; + int windowBits; + int memLevel; + int strategy; + const char* password; + uLong crcForCrypting; +{ + zip_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + +# ifdef NOCRYPT + if (password != NULL) + return ZIP_PARAMERROR; +# endif + + if (file == NULL) + return ZIP_PARAMERROR; + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; + + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = (uInt)strlen(comment); + + size_filename = (uInt)strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate); + } + + zi->ci.flag = 0; + if ((level==8) || (level==9)) + zi->ci.flag |= 2; + if ((level==2)) + zi->ci.flag |= 4; + if ((level==1)) + zi->ci.flag |= 6; + if (password != NULL) + zi->ci.flag |= 1; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.encrypt = 0; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.raw = raw; + zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ; + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + + size_extrafield_global + size_comment; + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader); + + ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2); + ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4); + + for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ + size_extrafield_global+i) = *(comment+i); + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + /* write the local header */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2); + + if ((err==ZIP_OK) && (size_filename>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) + err = ZIP_ERRNO; + + if ((err==ZIP_OK) && (size_extrafield_local>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local) + !=size_extrafield_local) + err = ZIP_ERRNO; + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)0; + + if (windowBits>0) + windowBits = -windowBits; + + err = deflateInit2(&zi->ci.stream, level, + Z_DEFLATED, windowBits, memLevel, strategy); + + if (err==Z_OK) + zi->ci.stream_initialised = 1; + } +# ifndef NOCRYPT + zi->ci.crypt_header_size = 0; + if ((err==Z_OK) && (password != NULL)) + { + unsigned char bufHead[RAND_HEAD_LEN]; + unsigned int sizeHead; + zi->ci.encrypt = 1; + zi->ci.pcrc_32_tab = get_crc_table(); + /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ + + sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); + zi->ci.crypt_header_size = sizeHead; + + if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) + err = ZIP_ERRNO; + } +# endif + + if (err==Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; + int raw; +{ + return zipOpenNewFileInZip3 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level) + zipFile file; + const char* filename; + const zip_fileinfo* zipfi; + const void* extrafield_local; + uInt size_extrafield_local; + const void* extrafield_global; + uInt size_extrafield_global; + const char* comment; + int method; + int level; +{ + return zipOpenNewFileInZip2 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0); +} + +local int zipFlushWriteBuffer(zi) + zip_internal* zi; +{ + int err=ZIP_OK; + + if (zi->ci.encrypt != 0) + { +#ifndef NOCRYPT + uInt i; + int t; + for (i=0;ici.pos_in_buffered_data;i++) + zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, + zi->ci.buffered_data[i],t); +#endif + } + if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) + !=zi->ci.pos_in_buffered_data) + err = ZIP_ERRNO; + zi->ci.pos_in_buffered_data = 0; + return err; +} + +extern int ZEXPORT zipWriteInFileInZip (file, buf, len) + zipFile file; + const void* buf; + unsigned len; +{ + zip_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.stream.next_in = (void*)buf; + zi->ci.stream.avail_in = len; + zi->ci.crc32 = crc32(zi->ci.crc32,buf,len); + + while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) + { + if (zi->ci.stream.avail_out == 0) + { + if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + + if(err != ZIP_OK) + break; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_NO_FLUSH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + + } + else + { + uInt copy_this,i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + for (i=0;ici.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + } + + return err; +} + +extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32) + zipFile file; + uLong uncompressed_size; + uLong crc32; +{ + zip_internal* zi; + uLong compressed_size; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (zipFlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + if (zipFlushWriteBuffer(zi)==ZIP_ERRNO) + err = ZIP_ERRNO; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + err=deflateEnd(&zi->ci.stream); + zi->ci.stream_initialised = 0; + } + + if (!zi->ci.raw) + { + crc32 = (uLong)zi->ci.crc32; + uncompressed_size = (uLong)zi->ci.stream.total_in; + } + compressed_size = (uLong)zi->ci.stream.total_out; +# ifndef NOCRYPT + compressed_size += zi->ci.crypt_header_size; +# endif + + ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ + ziplocal_putValue_inmemory(zi->ci.central_header+20, + compressed_size,4); /*compr size*/ + if (zi->ci.stream.data_type == Z_ASCII) + ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); + ziplocal_putValue_inmemory(zi->ci.central_header+24, + uncompressed_size,4); /*uncompr size*/ + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header, + (uLong)zi->ci.size_centralheader); + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); + if (ZSEEK(zi->z_filefunc,zi->filestream, + zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ + + if (err==ZIP_OK) /* compressed size, unknown */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); + + if (ZSEEK(zi->z_filefunc,zi->filestream, + cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipCloseFileInZip (file) + zipFile file; +{ + return zipCloseFileInZipRaw (file,0,0); +} + +extern int ZEXPORT zipClose (file, global_comment) + zipFile file; + const char* global_comment; +{ + zip_internal* zi; + int err = 0; + uLong size_centraldir = 0; + uLong centraldir_pos_inzip; + uInt size_global_comment; + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + +#ifndef NO_ADDFILEINEXISTINGZIP + if (global_comment==NULL) + global_comment = zi->globalcomment; +#endif + if (global_comment==NULL) + size_global_comment = 0; + else + size_global_comment = (uInt)strlen(global_comment); + + centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream); + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block ; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream, + ldi->data,ldi->filled_in_this_block) + !=ldi->filled_in_this_block ) + err = ZIP_ERRNO; + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_datablock(zi->central_dir.first_block); + + if (err==ZIP_OK) /* Magic End */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + + if (err==ZIP_OK) /* size of the central directory */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the + starting disk number */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream, + (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); + + if (err==ZIP_OK) /* zipfile comment length */ + err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); + + if ((err==ZIP_OK) && (size_global_comment>0)) + if (ZWRITE(zi->z_filefunc,zi->filestream, + global_comment,size_global_comment) != size_global_comment) + err = ZIP_ERRNO; + + if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0) + if (err == ZIP_OK) + err = ZIP_ERRNO; + +#ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(zi->globalcomment); +#endif + TRYFREE(zi); + + return err; +} diff --git a/unzip/zip.h b/unzip/zip.h new file mode 100644 index 00000000..acacce83 --- /dev/null +++ b/unzip/zip.h @@ -0,0 +1,235 @@ +/* zip.h -- IO for compress .zip files using zlib + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This unzip package allow creates .ZIP file, compatible with PKZip 2.04g + WinZip, InfoZip tools and compatible. + Multi volume ZipFile (span) are not supported. + Encryption compatible with pkzip 2.04g only supported + Old compressions used by old PKZip 1.x are not supported + + For uncompress .zip file, look at unzip.h + + + I WAIT FEEDBACK at mail info@winimage.com + Visit also http://www.winimage.com/zLibDll/unzip.html for evolution + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + +*/ + +/* for more info about .ZIP format, see + http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip + http://www.info-zip.org/pub/infozip/doc/ + PkWare has also a specification at : + ftp://ftp.pkware.com/probdesc.zip +*/ + +#ifndef _zip_H +#define _zip_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif +/* default memLevel */ + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char* zipcharpc; + + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on + an Unix computer "zlib/zlib113.zip". + if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. + (useful if the file contain a self extractor code) + if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will + add files in existing zip (be sure you don't add file that doesn't exist) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. +*/ + +/* Note : there is no delete function into a zipfile. + If you want delete file into a zipfile, you must open a zipfile, and create another + Of couse, you can use RAW reading and writing to copy the file you did not want delte +*/ + +extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def)); + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) +*/ + + +extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw)); + +/* + Same than zipOpenNewFileInZip, except if raw=1, we write raw file + */ + +extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCtypting)); + +/* + Same than zipOpenNewFileInZip2, except + windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCtypting : crc of file to compress (needed for crypting) + */ + + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const void* buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, + uLong uncompressed_size, + uLong crc32)); +/* + Close the current file in the zipfile, for fiel opened with + parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip_H */ diff --git a/win32/AVIOutput.cpp b/win32/AVIOutput.cpp new file mode 100644 index 00000000..05148529 --- /dev/null +++ b/win32/AVIOutput.cpp @@ -0,0 +1,522 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + + + +/* + Win32 AVI Output module + (c) 2004 blip +*/ + +#include +#include +#include "wsnes9x.h" // for GUI.hWnd +#include "AVIOutput.h" + +#define VIDEO_STREAM 0 +#define AUDIO_STREAM 1 + +struct AVIFile +{ + bool valid; + int fps; + int frameskip; + + bool video_added; + BITMAPINFOHEADER bitmap_format; + + bool sound_added; + WAVEFORMATEX wave_format; + + AVISTREAMINFO avi_video_header; + AVISTREAMINFO avi_sound_header; + PAVIFILE avi_file; + PAVISTREAM streams[2]; + PAVISTREAM compressed_streams[2]; + + AVICOMPRESSOPTIONS compress_options[2]; + AVICOMPRESSOPTIONS* compress_options_ptr[2]; + + int video_frames; + int sound_samples; + + long tBytes, ByteBuffer; +}; + +static char saved_cur_avi_fnameandext[MAX_PATH]; +static char saved_avi_fname[MAX_PATH]; +static char saved_avi_ext[MAX_PATH]; +static int avi_segnum=0; +static struct AVIFile saved_avi_info; +static int use_prev_options=0; + +static bool truncate_existing(const char* filename) +{ + // this is only here because AVIFileOpen doesn't seem to do it for us + FILE* fd = fopen(filename, "wb"); + if(fd) + { + fclose(fd); + return true; + } + + return false; +} + +static void clean_up(AVIFile* _avi) +{ + AVIFile& avi = *_avi; + + if(avi.sound_added) + { + if(avi.compressed_streams[AUDIO_STREAM]) + { + AVIStreamClose(avi.compressed_streams[AUDIO_STREAM]); + avi.compressed_streams[AUDIO_STREAM] = NULL; + avi.streams[AUDIO_STREAM] = NULL; // compressed_streams[AUDIO_STREAM] is just a copy of streams[AUDIO_STREAM] + } + } + + if(avi.video_added) + { + if(avi.compressed_streams[VIDEO_STREAM]) + { + AVIStreamClose(avi.compressed_streams[VIDEO_STREAM]); + avi.compressed_streams[VIDEO_STREAM] = NULL; + } + + if(avi.streams[VIDEO_STREAM]) + { + AVIStreamClose(avi.streams[VIDEO_STREAM]); + avi.streams[VIDEO_STREAM] = NULL; + } + } + + if(avi.avi_file) + { + AVIFileClose(avi.avi_file); + avi.avi_file = NULL; + } +} + +#ifdef __cplusplus +extern "C" { +#endif + +void AVICreate(struct AVIFile** avi_out) +{ + *avi_out = new AVIFile; + memset(*avi_out, 0, sizeof(AVIFile)); + AVIFileInit(); +} + +void AVIClose(struct AVIFile** avi_out) +{ + if(*avi_out) + { + clean_up(*avi_out); + delete *avi_out; + } + *avi_out = NULL; + AVIFileExit(); +} + +void AVISetFramerate(const int fps, const int frameskip, struct AVIFile* avi_out) +{ + avi_out->fps = fps; + avi_out->frameskip = frameskip; +} + +void AVISetVideoFormat(const BITMAPINFOHEADER* bitmap_format, struct AVIFile* avi_out) +{ + memcpy(&(avi_out->bitmap_format), bitmap_format, sizeof(BITMAPINFOHEADER)); + avi_out->video_added = true; +} + +void AVISetSoundFormat(const WAVEFORMATEX* wave_format, struct AVIFile* avi_out) +{ + memcpy(&(avi_out->wave_format), wave_format, sizeof(WAVEFORMATEX)); + avi_out->sound_added = true; +} + +int AVIBegin(const char* filename, struct AVIFile* _avi_out) +{ + AVIFile& avi = *_avi_out; + int result = 0; + + do + { + if(!avi.video_added) + break; + + if(!truncate_existing(filename)) + break; + + // open the file + if(FAILED(AVIFileOpen(&avi.avi_file, filename, OF_CREATE | OF_WRITE, NULL))) + break; + + // create the video stream + memset(&avi.avi_video_header, 0, sizeof(AVISTREAMINFO)); + avi.avi_video_header.fccType = streamtypeVIDEO; + avi.avi_video_header.dwScale = avi.frameskip; + avi.avi_video_header.dwRate = avi.fps; + avi.avi_video_header.dwSuggestedBufferSize = avi.bitmap_format.biSizeImage; + if(FAILED(AVIFileCreateStream(avi.avi_file, &avi.streams[VIDEO_STREAM], &avi.avi_video_header))) + break; + + if(use_prev_options) + { + avi.compress_options[VIDEO_STREAM] = saved_avi_info.compress_options[VIDEO_STREAM]; + avi.compress_options_ptr[VIDEO_STREAM] = &avi.compress_options[0]; + } + else + { + // get compression options + memset(&avi.compress_options[VIDEO_STREAM], 0, sizeof(AVICOMPRESSOPTIONS)); + avi.compress_options_ptr[VIDEO_STREAM] = &avi.compress_options[0]; + if(!AVISaveOptions(GUI.hWnd, 0, 1, &avi.streams[VIDEO_STREAM], &avi.compress_options_ptr[VIDEO_STREAM])) + break; + } + + // create compressed stream + if(FAILED(AVIMakeCompressedStream(&avi.compressed_streams[VIDEO_STREAM], avi.streams[VIDEO_STREAM], &avi.compress_options[VIDEO_STREAM], NULL))) + break; + + // set the stream format + if(FAILED(AVIStreamSetFormat(avi.compressed_streams[VIDEO_STREAM], 0, (void*)&avi.bitmap_format, avi.bitmap_format.biSize))) + break; + + // add sound (if requested) + if(avi.sound_added) + { + // create the audio stream + memset(&avi.avi_sound_header, 0, sizeof(AVISTREAMINFO)); + avi.avi_sound_header.fccType = streamtypeAUDIO; + avi.avi_sound_header.dwQuality = (DWORD)-1; + avi.avi_sound_header.dwScale = avi.wave_format.nBlockAlign; + avi.avi_sound_header.dwRate = avi.wave_format.nAvgBytesPerSec; + avi.avi_sound_header.dwSampleSize = avi.wave_format.nBlockAlign; + avi.avi_sound_header.dwInitialFrames = 1; + if(FAILED(AVIFileCreateStream(avi.avi_file, &avi.streams[AUDIO_STREAM], &avi.avi_sound_header))) + break; + + // AVISaveOptions doesn't seem to work for audio streams + // so here we just copy the pointer for the compressed stream + avi.compressed_streams[AUDIO_STREAM] = avi.streams[AUDIO_STREAM]; + + // set the stream format + if(FAILED(AVIStreamSetFormat(avi.compressed_streams[AUDIO_STREAM], 0, (void*)&avi.wave_format, sizeof(WAVEFORMATEX)))) + break; + } + + // initialize counters + avi.video_frames = 0; + avi.sound_samples = 0; + avi.tBytes = 0; + avi.ByteBuffer = 0; + + strncpy(saved_cur_avi_fnameandext,filename,MAX_PATH); + strncpy(saved_avi_fname,filename,MAX_PATH); + char* dot = strrchr(saved_avi_fname, '.'); + if(dot && dot > strrchr(saved_avi_fname, '/') && dot > strrchr(saved_avi_fname, '\\')) + { + strcpy(saved_avi_ext,dot); + dot[0]='\0'; + } + + // success + result = 1; + avi.valid = true; + + } while(false); + + if(!result) + { + clean_up(&avi); + avi.valid = false; + } + + return result; +} + +int AVIGetVideoFormat(const struct AVIFile* avi_out, const BITMAPINFOHEADER** ppFormat) +{ + if(!avi_out->valid || + !avi_out->video_added) + { + if(ppFormat) + { + *ppFormat = NULL; + } + return 0; + } + if(ppFormat) + { + *ppFormat = &avi_out->bitmap_format; + } + return 1; +} + +int AVIGetSoundFormat(const struct AVIFile* avi_out, const WAVEFORMATEX** ppFormat) +{ + if(!avi_out->valid || + !avi_out->sound_added) + { + if(ppFormat) + { + *ppFormat = NULL; + } + return 0; + } + if(ppFormat) + { + *ppFormat = &avi_out->wave_format; + } + return 1; +} + +static int AVINextSegment(struct AVIFile* avi_out) +{ + char avi_fname[MAX_PATH]; + strcpy(avi_fname,saved_avi_fname); + char avi_fname_temp[MAX_PATH]; + sprintf(avi_fname_temp, "%s_part%d%s", avi_fname, avi_segnum+2, saved_avi_ext); + saved_avi_info=*avi_out; + use_prev_options=1; + avi_segnum++; + clean_up(avi_out); + int ret = AVIBegin(avi_fname_temp, avi_out); + use_prev_options=0; + strcpy(saved_avi_fname,avi_fname); + return ret; +} + +void AVIAddVideoFrame(void* bitmap_data, struct AVIFile* avi_out) +{ + if(!avi_out->valid || + !avi_out->video_added) + { + return; + } + + if(FAILED(AVIStreamWrite(avi_out->compressed_streams[VIDEO_STREAM], + avi_out->video_frames, + 1, + bitmap_data, + avi_out->bitmap_format.biSizeImage, + AVIIF_KEYFRAME, NULL, &avi_out->ByteBuffer))) + { + avi_out->valid = false; + return; + } + + avi_out->video_frames++; + avi_out->tBytes += avi_out->ByteBuffer; + + // segment / split AVI when it's almost 2 GB (2000MB, to be precise) + if(!(avi_out->video_frames % 60) && avi_out->tBytes > 2097152000) + AVINextSegment(avi_out); +} + +void AVIAddSoundSamples(void* sound_data, const int num_samples, struct AVIFile* avi_out) +{ + if(!avi_out->valid || + !avi_out->sound_added) + { + return; + } + + int data_length = num_samples * avi_out->wave_format.nBlockAlign; + if(FAILED(AVIStreamWrite(avi_out->compressed_streams[AUDIO_STREAM], + avi_out->sound_samples, + num_samples, + sound_data, + data_length, + 0, NULL, &avi_out->ByteBuffer))) + { + avi_out->valid = false; + return; + } + + avi_out->sound_samples += num_samples; + avi_out->tBytes += avi_out->ByteBuffer; +} + +#ifdef __cplusplus +} +#endif diff --git a/win32/AVIOutput.h b/win32/AVIOutput.h new file mode 100644 index 00000000..ec0f2018 --- /dev/null +++ b/win32/AVIOutput.h @@ -0,0 +1,222 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + + + +/* + Win32 AVI Output module + (c) 2004 blip +*/ + +#ifndef __AVIOUTPUT_H_ +#define __AVIOUTPUT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +// create a new avi output object +void AVICreate(struct AVIFile** avi_out); + +// set up avi output options +void AVISetFramerate(const int fps, const int frameskip, struct AVIFile* avi_out); +void AVISetVideoFormat(const BITMAPINFOHEADER* bitmap_format, struct AVIFile* avi_out); +void AVISetSoundFormat(const WAVEFORMATEX* wave_format, struct AVIFile* avi_out); + +// after setting up output options, start writing with this +// returns 1 if successful, 0 otherwise +// check the return value! +int AVIBegin(const char* filename, struct AVIFile* avi_out); + +// get the format in use from an already existing avi output object +// returns 1 if successful, 0 otherwise +int AVIGetVideoFormat(const struct AVIFile* avi_out, const BITMAPINFOHEADER** ppFormat); +int AVIGetSoundFormat(const struct AVIFile* avi_out, const WAVEFORMATEX** ppFormat); + +// write video frames and sound samples to an avi output object +// that's been successfully Begun() +void AVIAddVideoFrame(void* bitmap_data, struct AVIFile* avi_out); +void AVIAddSoundSamples(void* sound_data, const int num_samples, struct AVIFile* avi_out); + +// when done writing, close and delete the object with this +void AVIClose(struct AVIFile** avi_out); + +#ifdef __cplusplus +} +#endif + +#endif /* __AVIOUTPUT_H_ */ diff --git a/win32/CDirect3D.cpp b/win32/CDirect3D.cpp new file mode 100644 index 00000000..546880e3 --- /dev/null +++ b/win32/CDirect3D.cpp @@ -0,0 +1,728 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +#pragma comment( lib, "d3d9" ) +#pragma comment( lib, "d3dx9" ) +#pragma comment( lib, "DxErr9" ) + +#include "../snes9x.h" + +#include +#include +#include "cdirect3d.h" +#include "win32_display.h" +#include "../gfx.h" +#include "wsnes9x.h" +#include + +#include "../filter/hq2x.h" +#include "../filter/2xsai.h" + +#define RenderMethod ((Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) ? RenderMethodHiRes : RenderMethod) + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +/* CDirect3D::CDirect3D() +sets default values for the variables +*/ +CDirect3D::CDirect3D() +{ + init_done = false; + pD3D = NULL; + pDevice = NULL; + drawSurface = NULL; + vertexBuffer = NULL; + afterRenderWidth = 0; + afterRenderHeight = 0; + quadTextureSize = 0; + fullscreen = false; + iFilterScale = 0; +} + +/* CDirect3D::~CDirect3D() +releases allocated objects +*/ +CDirect3D::~CDirect3D() +{ + DeInitialize(); +} + + +/* CDirect3D::Initialize +Initializes Direct3D (always in window mode) +IN: +hWnd - the HWND of the window in which we render/the focus window for fullscreen +----- +returns true if successful, false otherwise +*/ +bool CDirect3D::Initialize(HWND hWnd) +{ + if(init_done) + return true; + + pD3D = Direct3DCreate9(D3D_SDK_VERSION); + if(pD3D == NULL) { + DXTRACE_ERR_MSGBOX(TEXT("Error creating initial D3D9 object"), 0); + return false; + } + + ZeroMemory(&dPresentParams, sizeof(dPresentParams)); + dPresentParams.hDeviceWindow = hWnd; + dPresentParams.Windowed = TRUE; + dPresentParams.BackBufferCount = GUI.DoubleBuffered?2:1; + dPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD; + dPresentParams.BackBufferFormat = D3DFMT_UNKNOWN; + + HRESULT hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + hWnd, + D3DCREATE_MIXED_VERTEXPROCESSING, + &dPresentParams, + &pDevice); + if(FAILED(hr)) { + DXTRACE_ERR_MSGBOX(TEXT("Error creating D3D9 device"), hr); + return false; + } + + hr = pDevice->CreateVertexBuffer(sizeof(triangleStripVertices),D3DUSAGE_WRITEONLY,FVF_COORDS_TEX,D3DPOOL_MANAGED,&vertexBuffer,NULL); + if(FAILED(hr)) { + DXTRACE_ERR_MSGBOX(TEXT("Error creating vertex buffer"), hr); + return false; + } + + + //VideoMemory controls if we want bilinear filtering + if(GUI.BilinearFilter) { + pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + } else { + pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + } + + pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + + init_done = true; + + return true; + +} + +void CDirect3D::DeInitialize() +{ + DestroyDrawSurface(); + + if(vertexBuffer) { + vertexBuffer->Release(); + vertexBuffer = NULL; + } + + if( pDevice ) { + pDevice->Release(); + pDevice = NULL; + } + + if( pD3D ) { + pD3D->Release(); + pD3D = NULL; + } + + init_done = false; + afterRenderWidth = 0; + afterRenderHeight = 0; + quadTextureSize = 0; + fullscreen = false; + iFilterScale = 0; +} + +/* CDirect3D::Render +does the actual rendering, changes the draw surface if necessary and recalculates +the vertex information if filter output size changes +IN: +Src - the input surface +*/ +void CDirect3D::Render(SSurface Src) +{ + SSurface Dst; + RECT dstRect; + int iNewFilterScale; + D3DLOCKED_RECT lr; + D3DLOCKED_RECT lrConv; + HRESULT hr; + + if(!init_done) return; + + //create a new draw surface if the filter scale changes + //at least factor 2 so we can display unscaled hi-res images + iNewFilterScale = max(2,max(GetFilterScale(GUI.ScaleHiRes),GetFilterScale(GUI.Scale))); + if(iNewFilterScale!=iFilterScale) { + ChangeDrawSurfaceSize(iNewFilterScale); + } + + if(FAILED(hr = pDevice->TestCooperativeLevel())) { + switch(hr) { + case D3DERR_DEVICELOST: //do no rendering until device is restored + return; + case D3DERR_DEVICENOTRESET: //we can reset now + ResetDevice(); + return; + default: + DXTRACE_ERR( TEXT("Internal driver error"), hr); + return; + } + } + + //BlankTexture(drawSurface); + if(FAILED(hr = drawSurface->LockRect(0, &lr, NULL, 0))) { + DXTRACE_ERR_MSGBOX( TEXT("Unable to lock texture"), hr); + return; + } else { + Dst.Surface = (unsigned char *)lr.pBits; + Dst.Height = quadTextureSize; + Dst.Width = quadTextureSize; + Dst.Pitch = lr.Pitch; + + RenderMethod (Src, Dst, &dstRect); + if(!Settings.AutoDisplayMessages) { + WinSetCustomDisplaySurface((void *)Dst.Surface, Dst.Pitch/2, dstRect.right-dstRect.left, dstRect.bottom-dstRect.top, GetFilterScale(GUI.Scale)); + S9xDisplayMessages ((uint16*)Dst.Surface, Dst.Pitch/2, dstRect.right-dstRect.left, dstRect.bottom-dstRect.top, GetFilterScale(GUI.Scale)); + } + + drawSurface->UnlockRect(0); + } + + //if the output size of the render method changes we need new vertices + if(afterRenderHeight != dstRect.bottom || afterRenderWidth != dstRect.right) { + afterRenderHeight = dstRect.bottom; + afterRenderWidth = dstRect.right; + SetupVertices(); + } + + if(!GUI.Stretch||GUI.AspectRatio) + pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + + pDevice->BeginScene(); + + pDevice->SetTexture(0, drawSurface); + pDevice->SetFVF(FVF_COORDS_TEX); + pDevice->SetStreamSource(0,vertexBuffer,0,sizeof(VERTEX)); + pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2); + + pDevice->EndScene(); + + pDevice->Present(NULL, NULL, NULL, NULL); + + return; +} + +/* CDirect3D::CreateDrawSurface +calculates the necessary texture size (multiples of 2) +and creates a new texture +*/ +void CDirect3D::CreateDrawSurface() +{ + int neededSize; + HRESULT hr; + + //we need at least 512 pixels (SNES_WIDTH * 2) so we can start with that value + quadTextureSize = 512; + neededSize = SNES_WIDTH * iFilterScale; + while(quadTextureSize < neededSize) + quadTextureSize *=2; + + if(!drawSurface) { + hr = pDevice->CreateTexture( + quadTextureSize, quadTextureSize, + 1, // 1 level, no mipmaps + 0, // dynamic textures can be locked + D3DFMT_R5G6B5, + D3DPOOL_MANAGED, + &drawSurface, + NULL ); + + if(FAILED(hr)) { + DXTRACE_ERR_MSGBOX(TEXT("Error while creating texture"), hr); + return; + } + } +} + +/* CDirect3D::DestroyDrawSurface +releases the old textures (if allocated) +*/ +void CDirect3D::DestroyDrawSurface() +{ + if(drawSurface) { + drawSurface->Release(); + drawSurface = NULL; + } +} + +/* CDirect3D::BlankTexture +clears a texture (fills it with zeroes) +IN: +texture - the texture to be blanked +----- +returns true if successful, false otherwise +*/ +bool CDirect3D::BlankTexture(LPDIRECT3DTEXTURE9 texture) +{ + D3DLOCKED_RECT lr; + HRESULT hr; + + if(FAILED(hr = texture->LockRect(0, &lr, NULL, 0))) { + DXTRACE_ERR_MSGBOX( TEXT("Unable to lock texture"), hr); + return false; + } else { + memset(lr.pBits, 0, lr.Pitch * quadTextureSize); + texture->UnlockRect(0); + return true; + } +} + +/* CDirect3D::ChangeDrawSurfaceSize +changes the draw surface size: deletes the old textures, creates a new texture +and calculate new vertices +IN: +iScale - the scale that has to fit into the textures +----- +returns true if successful, false otherwise +*/ +bool CDirect3D::ChangeDrawSurfaceSize(int iScale) +{ + iFilterScale = iScale; + + if(pDevice) { + DestroyDrawSurface(); + CreateDrawSurface(); + SetupVertices(); + return true; + } + return false; +} + +/* CDirect3D::SetupVertices +calculates the vertex coordinates +(respecting the stretch and aspect ratio settings) +*/ +void CDirect3D::SetupVertices() +{ + float xFactor; + float yFactor; + float minFactor; + float renderWidthCalc,renderHeightCalc; + RECT drawRect; + int hExtend = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT; + float snesAspect = (float)GUI.AspectWidth/hExtend; + void *pLockedVertexBuffer; + + if(GUI.Stretch) { + if(GUI.AspectRatio) { + //fix for hi-res images with FILTER_NONE + //where we need to correct the aspect ratio + renderWidthCalc = (float)afterRenderWidth; + renderHeightCalc = (float)afterRenderHeight; + if(renderWidthCalc/renderHeightCalc>snesAspect) + renderWidthCalc = renderHeightCalc * snesAspect; + else if(renderWidthCalc/renderHeightCalc dPresentParams.BackBufferWidth) drawRect.right = dPresentParams.BackBufferWidth; + //if(drawRect.bottom > dPresentParams.BackBufferHeight) drawRect.bottom = dPresentParams.BackBufferHeight; + } + + float tX = (float)afterRenderWidth / (float)quadTextureSize; + float tY = (float)afterRenderHeight / (float)quadTextureSize; + + //we need to substract -0.5 from the x/y coordinates to match texture with pixel space + //see http://msdn.microsoft.com/en-us/library/bb219690(VS.85).aspx + triangleStripVertices[0] = VERTEX((float)drawRect.left - 0.5f,(float)drawRect.bottom - 0.5f,0.0f,1.0f,0.0f,tY); + triangleStripVertices[1] = VERTEX((float)drawRect.left - 0.5f,(float)drawRect.top - 0.5f,0.0f,1.0f,0.0f,0.0f); + triangleStripVertices[2] = VERTEX((float)drawRect.right - 0.5f,(float)drawRect.bottom - 0.5f,0.0f,1.0f,tX,tY); + triangleStripVertices[3] = VERTEX((float)drawRect.right - 0.5f,(float)drawRect.top - 0.5f,0.0f,1.0f,tX,0.0f); + + HRESULT hr = vertexBuffer->Lock(0,0,&pLockedVertexBuffer,NULL); + memcpy(pLockedVertexBuffer,triangleStripVertices,sizeof(triangleStripVertices)); + vertexBuffer->Unlock(); +} + +/* CDirect3D::ChangeRenderSize +determines if we need to reset the device (if the size changed) +called with (0,0) whenever we want new settings to take effect +IN: +newWidth,newHeight - the new window size +----- +returns true if successful, false otherwise +*/ +bool CDirect3D::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight) +{ + if(!init_done) + return false; + + //if we already have the desired size no change is necessary + //during fullscreen no changes are allowed + if(fullscreen || dPresentParams.BackBufferWidth == newWidth && dPresentParams.BackBufferHeight == newHeight) + return true; + + if(!ResetDevice()) + return false; + SetupVertices(); + return true; +} + +/* CDirect3D::ResetDevice +resets the device +called if surface was lost or the settings/display size require a device reset +----- +returns true if successful, false otherwise +*/ +bool CDirect3D::ResetDevice() +{ + if(!pDevice) return false; + + HRESULT hr; + + //release prior to reset + DestroyDrawSurface(); + + //zero or unknown values result in the current window size/display settings + dPresentParams.BackBufferWidth = 0; + dPresentParams.BackBufferHeight = 0; + dPresentParams.BackBufferCount = GUI.DoubleBuffered?2:1; + dPresentParams.BackBufferFormat = D3DFMT_UNKNOWN; + dPresentParams.FullScreen_RefreshRateInHz = 0; + dPresentParams.Windowed = true; + dPresentParams.PresentationInterval = GUI.Vsync?D3DPRESENT_INTERVAL_ONE:D3DPRESENT_INTERVAL_IMMEDIATE; + + if(fullscreen) { + dPresentParams.BackBufferWidth = GUI.FullscreenMode.width; + dPresentParams.BackBufferHeight = GUI.FullscreenMode.height; + dPresentParams.BackBufferCount = GUI.DoubleBuffered?2:1; + dPresentParams.Windowed = false; + if(GUI.FullscreenMode.depth == 32) + dPresentParams.BackBufferFormat = D3DFMT_X8R8G8B8; + else + dPresentParams.BackBufferFormat = D3DFMT_R5G6B5; + dPresentParams.FullScreen_RefreshRateInHz = GUI.FullscreenMode.rate; + } + + if(FAILED(hr = pDevice->Reset(&dPresentParams))) { + DXTRACE_ERR(TEXT("Unable to reset device"), hr); + return false; + } + + if(GUI.BilinearFilter) { + pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + } else { + pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + } + + pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + + //recreate the surface + CreateDrawSurface(); + return true; +} + +/* CDirect3D::SetSnes9xColorFormat +sets the color format to 16bit (since the texture is always 16bit) +no depth conversion is necessary (done by D3D) +*/ +void CDirect3D::SetSnes9xColorFormat() +{ + GUI.ScreenDepth = 16; + GUI.BlueShift = 0; + GUI.GreenShift = 6; + GUI.RedShift = 11; + S9xSetRenderPixelFormat (RGB565); + S9xBlit2xSaIFilterInit(); + S9xBlitHQ2xFilterInit(); + GUI.NeedDepthConvert = FALSE; + GUI.DepthConverted = TRUE; + return; +} + +/* CDirect3D::SetFullscreen +enables/disables fullscreen mode +IN: +fullscreen - determines if fullscreen is enabled/disabled +----- +returns true if successful, false otherwise +*/ +bool CDirect3D::SetFullscreen(bool fullscreen) +{ + if(!init_done) + return false; + + if(this->fullscreen==fullscreen) + return true; + + this->fullscreen = fullscreen; + if(!ResetDevice()) + return false; + + //present here to get a fullscreen blank even if no rendering is done + pDevice->Present(NULL,NULL,NULL,NULL); + SetupVertices(); + return true; +} + +/* CDirect3D::EnumModes +enumerates possible display modes (only 16 and 32 bit) and fills the vector +IN: +modeVector - pointer to the mode vector +*/ +void CDirect3D::EnumModes(std::vector *modeVector) +{ + D3DDISPLAYMODE d3dMode; + int modeCount,index; + dMode mode; + + if(!init_done) + return; + + //enumerate 32bit modes + modeCount = pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT,D3DFMT_X8R8G8B8); + for(int i=0;iEnumAdapterModes(D3DADAPTER_DEFAULT,D3DFMT_X8R8G8B8,i,&d3dMode)==D3D_OK) { + mode.width = d3dMode.Width; + mode.height = d3dMode.Height; + mode.rate = d3dMode.RefreshRate; + mode.depth = 32; + + modeVector->push_back(mode); + } + + } + + //enumerate 16bit modes + modeCount = pD3D->GetAdapterModeCount(D3DADAPTER_DEFAULT,D3DFMT_R5G6B5); + for(int i=0;iEnumAdapterModes(D3DADAPTER_DEFAULT,D3DFMT_R5G6B5,i,&d3dMode)==D3D_OK) { + mode.width = d3dMode.Width; + mode.height = d3dMode.Height; + mode.rate = d3dMode.RefreshRate; + mode.depth = 16; + + modeVector->push_back(mode); + } + + } +} + +/* CDirect3D::ApplyDisplayChanges +calls changerendersize to apply new display settings +----- +returns true if successful, false otherwise +*/ +bool CDirect3D::ApplyDisplayChanges(void) +{ + return ChangeRenderSize(0,0); +} diff --git a/win32/CDirect3D.h b/win32/CDirect3D.h new file mode 100644 index 00000000..6bc1f47f --- /dev/null +++ b/win32/CDirect3D.h @@ -0,0 +1,235 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 W9XDIRECT3D_H +#define W9XDIRECT3D_H + +#include +#include +#include "render.h" +#include "wsnes9x.h" +#include "IS9xDisplayOutput.h" + +#define FVF_COORDS_TEX D3DFVF_XYZRHW | D3DFVF_TEX1 + +typedef struct _VERTEX { + float x, y, z; + float rhw; + float tx, ty; + _VERTEX() {} + _VERTEX(float x,float y,float z,float rhw,float tx,float ty) { + this->x=x;this->y=y;this->z=z;this->rhw=rhw;this->tx=tx;this->ty=ty; + } +} VERTEX; //our custom vertex with a constuctor for easier assignment + +class CDirect3D: public IS9xDisplayOutput +{ +private: + bool init_done; //has initialize been called? + LPDIRECT3D9 pD3D; + LPDIRECT3DDEVICE9 pDevice; + LPDIRECT3DTEXTURE9 drawSurface; //the texture used for all drawing operations + + LPDIRECT3DVERTEXBUFFER9 vertexBuffer; + D3DPRESENT_PARAMETERS dPresentParams; + int iFilterScale; //the current maximum filter scale (at least 2) + unsigned int afterRenderWidth, afterRenderHeight; //dimensions after filter has been applied + unsigned int quadTextureSize; //size of the texture (only multiples of 2) + bool fullscreen; //are we currently displaying in fullscreen mode + + VERTEX triangleStripVertices[4]; //the 4 vertices that make up our display rectangle + + bool BlankTexture(LPDIRECT3DTEXTURE9 texture); + void CreateDrawSurface(); + void DestroyDrawSurface(); + bool ChangeDrawSurfaceSize(int iScale); + void SetupVertices(); + bool ResetDevice(); + +public: + CDirect3D(); + ~CDirect3D(); + bool Initialize(HWND hWnd); + void DeInitialize(); + void Render(SSurface Src); + bool ChangeRenderSize(unsigned int newWidth, unsigned int newHeight); + bool ApplyDisplayChanges(void); + bool SetFullscreen(bool fullscreen); + void SetSnes9xColorFormat(); + void EnumModes(std::vector *modeVector); +}; + +#endif \ No newline at end of file diff --git a/win32/CDirectDraw.cpp b/win32/CDirectDraw.cpp new file mode 100644 index 00000000..271499ea --- /dev/null +++ b/win32/CDirectDraw.cpp @@ -0,0 +1,861 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + + + +// CDirectDraw.cpp: implementation of the CDirectDraw class. +// +////////////////////////////////////////////////////////////////////// + +#include "wsnes9x.h" +#include "../snes9x.h" +#include "../gfx.h" +#include "CDirectDraw.h" +#include "win32_display.h" + +#include "../filter/hq2x.h" +#include "../filter/2xsai.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +CDirectDraw::CDirectDraw() +{ + lpDD = NULL; + lpDDClipper = NULL; + lpDDPalette = NULL; + + lpDDSPrimary2 = NULL; + lpDDSOffScreen2 = NULL; + + width = height = -1; + depth = -1; + doubleBuffered = false; + dDinitialized = false; +} + +CDirectDraw::~CDirectDraw() +{ + DeInitialize(); +} + +bool CDirectDraw::Initialize (HWND hWnd) +{ + if(dDinitialized) + return true; + + dErr = DirectDrawCreate (NULL, &lpDD, NULL); + if(FAILED(dErr)) + return false; + + dErr = lpDD -> CreateClipper (0, &lpDDClipper, NULL); + if(FAILED(dErr)) + return false; + + dErr = lpDDClipper->SetHWnd (0, hWnd); + if(FAILED(dErr)) + return false; + + if (!SetDisplayMode (GUI.FullscreenMode.width, GUI.FullscreenMode.height, max(GetFilterScale(GUI.Scale), GetFilterScale(GUI.ScaleHiRes)), GUI.FullscreenMode.depth, GUI.FullscreenMode.rate, + TRUE, GUI.DoubleBuffered)) + { + MessageBox( GUI.hWnd, Languages[ GUI.Language].errModeDD, TEXT("Snes9X - DirectDraw(7)"), MB_OK | MB_ICONSTOP); + return (false); + } + + dDinitialized = true; + + return (true); +} + +void CDirectDraw::DeInitialize() +{ + if (lpDD != NULL) + { + if (lpDDSPrimary2 != NULL) + { + lpDDSPrimary2->Release(); + lpDDSPrimary2 = NULL; + } + if (lpDDSOffScreen2 != NULL) + { + lpDDSOffScreen2->PageUnlock(0); + lpDDSOffScreen2->Release(); + lpDDSOffScreen2 = NULL; + } + if (lpDDClipper != NULL) + { + lpDDClipper->Release(); + lpDDClipper = NULL; + } + if (lpDDPalette != NULL) + { + lpDDPalette->Release(); + lpDDPalette = NULL; + } + lpDD->Release(); + lpDD = NULL; + } + dDinitialized = false; +} + +bool CDirectDraw::SetDisplayMode( + int pWidth, int pHeight, int pScale, + char pDepth, int pRefreshRate, bool pWindowed, bool pDoubleBuffered) +{ + if(pScale < 2) pScale = 2; + + static bool BLOCK = false; + DDSURFACEDESC ddsd; + PALETTEENTRY PaletteEntries [256]; + + if (BLOCK) + return (false); + + BLOCK = true; + + if (pWindowed) + pDoubleBuffered = false; + + if (pDepth == 0) + pDepth = depth; + + if (lpDDSPrimary2 != NULL) + { + lpDDSPrimary2->Release(); + lpDDSPrimary2 = NULL; + } + if (lpDDSOffScreen2 != NULL) + { + lpDDSOffScreen2->PageUnlock(0); + lpDDSOffScreen2->Release(); + lpDDSOffScreen2 = NULL; + } + if( lpDDPalette != NULL) + { + lpDDPalette->Release(); + lpDDPalette = NULL; + } + + lpDD->FlipToGDISurface(); + + if (pWindowed) + { + lpDD->RestoreDisplayMode(); + + ZeroMemory (&ddsd, sizeof (ddsd)); + + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_PIXELFORMAT; + dErr = lpDD->GetDisplayMode (&ddsd); + if (FAILED(dErr)) + pDepth = 8; + else + { + if (ddsd.ddpfPixelFormat.dwFlags&DDPF_RGB) + pDepth = (char) ddsd.ddpfPixelFormat.dwRGBBitCount; + else + pDepth = 8; + } + if (pDepth == 8) + dErr = lpDD->SetCooperativeLevel (GUI.hWnd, DDSCL_FULLSCREEN| + DDSCL_EXCLUSIVE|DDSCL_ALLOWREBOOT); + else + dErr = lpDD->SetCooperativeLevel (GUI.hWnd, DDSCL_NORMAL|DDSCL_ALLOWREBOOT); + } + else + { + dErr = lpDD->SetCooperativeLevel (GUI.hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_ALLOWREBOOT); + // XXX: TODO: use pRefreshRate! + dErr = lpDD->SetDisplayMode (pWidth, pHeight, pDepth); + } + + if (FAILED(dErr)) + { + BLOCK = false; + return false; + } + + ZeroMemory (&ddsd, sizeof (ddsd)); + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + if(GUI.BilinearFilter) + { + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | (GUI.LocalVidMem ? DDSCAPS_LOCALVIDMEM : DDSCAPS_NONLOCALVIDMEM); + } + else + { + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + } + ddsd.dwWidth = SNES_WIDTH * pScale; + ddsd.dwHeight = SNES_HEIGHT_EXTENDED * pScale; + + LPDIRECTDRAWSURFACE lpDDSOffScreen; + if (FAILED(lpDD->CreateSurface (&ddsd, &lpDDSOffScreen, NULL))) + { + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | (GUI.LocalVidMem ? DDSCAPS_NONLOCALVIDMEM : DDSCAPS_LOCALVIDMEM); + if(!GUI.BilinearFilter || FAILED(lpDD->CreateSurface (&ddsd, &lpDDSOffScreen, NULL))) + { + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + if(!GUI.BilinearFilter || FAILED(lpDD->CreateSurface (&ddsd, &lpDDSOffScreen, NULL))) + { + BLOCK = false; + return (false); + } + } + } + + if (FAILED (lpDDSOffScreen->QueryInterface (IID_IDirectDrawSurface2, + (void **)&lpDDSOffScreen2))) + { + lpDDSOffScreen->Release(); + BLOCK = false; + return (false); + } + lpDDSOffScreen2->PageLock(0); + lpDDSOffScreen->Release(); + + ZeroMemory (&ddsd, sizeof (ddsd)); + if (pDoubleBuffered) + { + ddsd.dwSize = sizeof( ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; + GUI.NumFlipFrames = 3; + ddsd.dwBackBufferCount = 2; + } + else + { + GUI.NumFlipFrames = 1; + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + } + + LPDIRECTDRAWSURFACE lpDDSPrimary; + + dErr = lpDD->CreateSurface (&ddsd, &lpDDSPrimary, NULL); + if( FAILED(dErr) ) + { + if (pDoubleBuffered) + { + ddsd.dwBackBufferCount = 1; + GUI.NumFlipFrames = 2; + if (FAILED(dErr = lpDD->CreateSurface (&ddsd, &lpDDSPrimary, NULL))) + { + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + pDoubleBuffered = false; + GUI.NumFlipFrames = 1; + dErr = lpDD->CreateSurface (&ddsd, &lpDDSPrimary, NULL); + } + } + + if (FAILED(dErr)) + { + BLOCK = false; + lpDDSOffScreen2->PageUnlock(0); + lpDDSOffScreen2->Release(); + lpDDSOffScreen2 = NULL; + + return (false); + } + } + + ZeroMemory (&DDPixelFormat, sizeof (DDPixelFormat)); + DDPixelFormat.dwSize = sizeof (DDPixelFormat); + lpDDSPrimary->GetPixelFormat (&DDPixelFormat); + + clipped = true; + if((!pWindowed && pDoubleBuffered) || FAILED(lpDDSPrimary->SetClipper( lpDDClipper))) + clipped = false; + + if (FAILED (lpDDSPrimary->QueryInterface (IID_IDirectDrawSurface2, (void **)&lpDDSPrimary2))) + { + BLOCK = false; + lpDDSPrimary->Release(); + lpDDSPrimary = NULL; + + return (FALSE); + } + + lpDDSPrimary->Release(); + lpDDSPrimary = NULL; + + if((!pWindowed && pDoubleBuffered) || FAILED(lpDDSPrimary2->SetClipper( lpDDClipper))) + clipped = false; + + if (pDepth == 8) + { + dErr = lpDD->CreatePalette (DDPCAPS_8BIT | DDPCAPS_ALLOW256, + PaletteEntries, &lpDDPalette, NULL); + if( FAILED(dErr)) + { + lpDDPalette = NULL; + BLOCK = false; + return false; + } + } + + depth = pDepth; + height = pHeight; + width = pWidth; + doubleBuffered = pDoubleBuffered; + BLOCK = false; + + return (true); +} + +void CDirectDraw::GetPixelFormat () +{ + if (lpDDSPrimary2) + { + ZeroMemory (&DDPixelFormat, sizeof (DDPixelFormat)); + DDPixelFormat.dwSize = sizeof (DDPixelFormat); + lpDDSPrimary2->GetPixelFormat (&DDPixelFormat); + } +} + +static bool LockSurface2 (LPDIRECTDRAWSURFACE2 lpDDSurface, SSurface *lpSurface) +{ + DDSURFACEDESC ddsd; + HRESULT hResult; + int retry; + + ddsd.dwSize = sizeof (ddsd); + + retry = 0; + while (true) + { + hResult = lpDDSurface->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL); + + if( hResult == DD_OK) + { + lpSurface->Width = ddsd.dwWidth; + lpSurface->Height = ddsd.dwHeight; + lpSurface->Pitch = ddsd.lPitch; + lpSurface->Surface = (unsigned char *)ddsd.lpSurface; + return (true); + } + + if (hResult == DDERR_SURFACELOST) + { + retry++; + if (retry > 5) + return (false); + + hResult = lpDDSurface->Restore(); + GUI.ScreenCleared = true; + if (hResult != DD_OK) + return (false); + + continue; + } + + if (hResult != DDERR_WASSTILLDRAWING) + return (false); + } +} + +void CDirectDraw::Render(SSurface Src) +{ + LPDIRECTDRAWSURFACE2 lpDDSurface2 = NULL; + LPDIRECTDRAWSURFACE2 pDDSurface = NULL; + SSurface Dst; + RECT srcRect; + + RECT dstRect = { 0, 512, 0, 448 }; + + DDSCAPS caps; + + ZeroMemory(&caps,sizeof(DDSCAPS)); + caps.dwCaps = DDSCAPS_BACKBUFFER; + + if (lpDDSPrimary2->GetAttachedSurface (&caps, &pDDSurface) != DD_OK || + pDDSurface == NULL) + { + lpDDSurface2 = lpDDSPrimary2; + } + else + lpDDSurface2 = pDDSurface; + + lpDDSurface2 = lpDDSOffScreen2; + if (!LockSurface2 (lpDDSurface2, &Dst)) + return; + + if (!GUI.DepthConverted) + { + SSurface tmp; + static BYTE buf [256 * 239 * 4*3*3]; + + tmp.Surface = buf; + + if(GUI.Scale == FILTER_NONE) { + tmp.Pitch = Src.Pitch; + tmp.Width = Src.Width; + tmp.Height = Src.Height; + } else { + tmp.Pitch = Dst.Pitch; + tmp.Width = Dst.Width; + tmp.Height = Dst.Height; + } + RenderMethod (Src, tmp, &srcRect); + ConvertDepth (&tmp, &Dst, &srcRect); + } + else + { + RenderMethod (Src, Dst, &srcRect); + } + + if(!Settings.AutoDisplayMessages) { + WinSetCustomDisplaySurface((void *)Dst.Surface, (Dst.Pitch*8/GUI.ScreenDepth), srcRect.right-srcRect.left, srcRect.bottom-srcRect.top, GetFilterScale(GUI.Scale)); + S9xDisplayMessages ((uint16*)Dst.Surface, Dst.Pitch/2, srcRect.right-srcRect.left, srcRect.bottom-srcRect.top, GetFilterScale(GUI.Scale)); + } + + RECT lastRect = SizeHistory [GUI.FlipCounter % GUI.NumFlipFrames]; + POINT p; + + if (GUI.Stretch) + { + p.x = p.y = 0; + ClientToScreen (GUI.hWnd, &p); + GetClientRect (GUI.hWnd, &dstRect); +// dstRect.bottom = int(double(dstRect.bottom) * double(239.0 / 240.0)); + + if(GUI.AspectRatio) + { + int width = dstRect.right - dstRect.left; + int height = dstRect.bottom - dstRect.top; + + int oldWidth = GUI.AspectWidth; + int oldHeight = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT; + int newWidth, newHeight; + + if(oldWidth * height > oldHeight * width) + { + newWidth = width; + newHeight = oldHeight*width/oldWidth; + } + else + { + newWidth = oldWidth*height/oldHeight; + newHeight = height; + } + int xOffset = (width - newWidth)/2; + int yOffset = (height - newHeight)/2; + + dstRect.right = dstRect.left + newWidth; + dstRect.bottom = dstRect.top + newHeight; + + OffsetRect(&dstRect, p.x + xOffset, p.y + yOffset); + } + else + { + OffsetRect(&dstRect, p.x, p.y); + } + } + else + { + GetClientRect (GUI.hWnd, &dstRect); + int width = srcRect.right - srcRect.left; + int height = srcRect.bottom - srcRect.top; + + //if (GUI.Scale == 1) + //{ + // width = MAX_SNES_WIDTH; + // if (height < 240) + // height *= 2; + //} + p.x = ((dstRect.right - dstRect.left) - width) >> 1; + p.y = ((dstRect.bottom - dstRect.top) - height) >> 1; + + if(p.y < 0) p.y = 0; + if(p.x < 0) p.x = 0; + + ClientToScreen (GUI.hWnd, &p); + + dstRect.top = p.y; + dstRect.left = p.x; + dstRect.bottom = dstRect.top + height; + dstRect.right = dstRect.left + width; + } + + lpDDSurface2->Unlock (Dst.Surface); + + ZeroMemory(&caps,sizeof(DDSCAPS)); + caps.dwCaps = DDSCAPS_BACKBUFFER; + + if (lpDDSPrimary2->GetAttachedSurface (&caps, &pDDSurface) != DD_OK || + pDDSurface == NULL) + { + lpDDSurface2 = lpDDSPrimary2; + } + else + lpDDSurface2 = pDDSurface; + + // actually draw it onto the screen (unless in fullscreen mode; see UpdateBackBuffer() for that) + while (lpDDSurface2->Blt (&dstRect, lpDDSOffScreen2, &srcRect, DDBLT_WAIT, NULL) == DDERR_SURFACELOST) + lpDDSurface2->Restore (); + + + RECT rect; + DDBLTFX fx; + + memset (&fx, 0, sizeof (fx)); + fx.dwSize = sizeof (fx); + + if (GUI.FlipCounter >= GUI.NumFlipFrames) + { + if (lastRect.top < dstRect.top) + { + rect.top = lastRect.top; + rect.bottom = dstRect.top; + rect.left = min(lastRect.left, dstRect.left); + rect.right = max(lastRect.right, dstRect.right); + lpDDSurface2->Blt (&rect, NULL, &rect, + DDBLT_WAIT | DDBLT_COLORFILL, &fx); + } + if (lastRect.bottom > dstRect.bottom) + { + rect.left = min(lastRect.left, dstRect.left); + rect.right = max(lastRect.right, dstRect.right); + rect.top = dstRect.bottom; + rect.bottom = lastRect.bottom; + lpDDSurface2->Blt (&rect, NULL, &rect, + DDBLT_WAIT | DDBLT_COLORFILL, &fx); + } + if (lastRect.left < dstRect.left) + { + rect.left = lastRect.left; + rect.right = dstRect.left; + rect.top = dstRect.top; + rect.bottom = dstRect.bottom; + lpDDSurface2->Blt (&rect, NULL, &rect, + DDBLT_WAIT | DDBLT_COLORFILL, &fx); + } + if (lastRect.right > dstRect.right) + { + rect.left = dstRect.right; + rect.right = lastRect.right; + rect.top = dstRect.top; + rect.bottom = dstRect.bottom; + lpDDSurface2->Blt (&rect, NULL, &rect, + DDBLT_WAIT | DDBLT_COLORFILL, &fx); + } + } + + lpDDSPrimary2->Flip (NULL, GUI.Vsync?DDFLIP_WAIT:DDFLIP_NOVSYNC); + + SizeHistory [GUI.FlipCounter % GUI.NumFlipFrames] = dstRect; +} + +bool CDirectDraw::ApplyDisplayChanges(void) +{ + return true; +} + +bool CDirectDraw::ChangeRenderSize(unsigned int newWidth, unsigned int newHeight) +{ + return true; +} + +bool CDirectDraw::SetFullscreen(bool fullscreen) +{ + if (!SetDisplayMode (GUI.FullscreenMode.width, GUI.FullscreenMode.height, max(GetFilterScale(GUI.Scale), GetFilterScale(GUI.ScaleHiRes)), GUI.FullscreenMode.depth, GUI.FullscreenMode.rate, !fullscreen, GUI.DoubleBuffered)) + { + MessageBox( GUI.hWnd, Languages[ GUI.Language].errModeDD, TEXT("Snes9X - DirectDraw(2)"), MB_OK | MB_ICONSTOP); + return false; + } + return true; +} + +int ffs (uint32 mask) +{ + int m = 0; + if (mask) + { + while (!(mask & (1 << m))) + m++; + + return (m); + } + + return (0); +} + +void CDirectDraw::SetSnes9xColorFormat() +{ + GUI.ScreenDepth = DDPixelFormat.dwRGBBitCount; + if (GUI.ScreenDepth == 15) + GUI.ScreenDepth = 16; + + GUI.RedShift = ffs (DDPixelFormat.dwRBitMask); + GUI.GreenShift = ffs (DDPixelFormat.dwGBitMask); + GUI.BlueShift = ffs (DDPixelFormat.dwBBitMask); + + if((DDPixelFormat.dwFlags&DDPF_RGB) != 0 && + GUI.ScreenDepth == 16 && + DDPixelFormat.dwRBitMask == 0xF800 && + DDPixelFormat.dwGBitMask == 0x07E0 && + DDPixelFormat.dwBBitMask == 0x001F) + { + S9xSetRenderPixelFormat (RGB565); + } + else + if( (DDPixelFormat.dwFlags&DDPF_RGB) != 0 && + GUI.ScreenDepth == 16 && + DDPixelFormat.dwRBitMask == 0x7C00 && + DDPixelFormat.dwGBitMask == 0x03E0 && + DDPixelFormat.dwBBitMask == 0x001F) + { + S9xSetRenderPixelFormat (RGB555); + } + else + if((DDPixelFormat.dwFlags&DDPF_RGB) != 0 && + GUI.ScreenDepth == 16 && + DDPixelFormat.dwRBitMask == 0x001F && + DDPixelFormat.dwGBitMask == 0x07E0 && + DDPixelFormat.dwBBitMask == 0xF800) + { + S9xSetRenderPixelFormat (BGR565); + } + else + if( (DDPixelFormat.dwFlags&DDPF_RGB) != 0 && + GUI.ScreenDepth == 16 && + DDPixelFormat.dwRBitMask == 0x001F && + DDPixelFormat.dwGBitMask == 0x03E0 && + DDPixelFormat.dwBBitMask == 0x7C00) + { + S9xSetRenderPixelFormat (BGR555); + } + else + if (DDPixelFormat.dwRGBBitCount == 8 || + DDPixelFormat.dwRGBBitCount == 24 || + DDPixelFormat.dwRGBBitCount == 32) + { + S9xSetRenderPixelFormat (RGB565); + } + + if ((GUI.ScreenDepth == 24 || GUI.ScreenDepth == 32)) + GUI.NeedDepthConvert = TRUE; + + GUI.DepthConverted = !GUI.NeedDepthConvert; + + if ((GUI.ScreenDepth == 24 || GUI.ScreenDepth == 32)) + { + GUI.RedShift += 3; + GUI.GreenShift += 3; + GUI.BlueShift += 3; + } + + S9xBlit2xSaIFilterInit(); + S9xBlitHQ2xFilterInit(); +} + +HRESULT CALLBACK EnumModesCallback( LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext) +{ + dMode curmode; + std::vector *modeVector=(std::vector *)lpContext; + HWND hDlg = (HWND)lpContext; + + if((lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount != 15 && + lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount != 16 && + lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount != 32) || + (lpDDSurfaceDesc->dwWidth < SNES_WIDTH || + lpDDSurfaceDesc->dwHeight < SNES_HEIGHT_EXTENDED)) + { + // let them muck with the .cfg file if they really want to set such a poor display mode + return DDENUMRET_OK; // keep going without adding mode to list + } + + curmode.width=lpDDSurfaceDesc->dwWidth; + curmode.height=lpDDSurfaceDesc->dwHeight; + curmode.depth=lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount; + curmode.rate=lpDDSurfaceDesc->dwRefreshRate; + + modeVector->push_back(curmode); + + return DDENUMRET_OK; +} + + +void CDirectDraw::EnumModes(std::vector *modeVector) +{ + lpDD->EnumDisplayModes(DDEDM_REFRESHRATES,NULL,(void *)modeVector,(LPDDENUMMODESCALLBACK)EnumModesCallback); +} + diff --git a/win32/CDirectDraw.h b/win32/CDirectDraw.h new file mode 100644 index 00000000..530edb60 --- /dev/null +++ b/win32/CDirectDraw.h @@ -0,0 +1,234 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + + + +// CDirectDraw.h: interface for the CDirectDraw class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(CDIRECTDRAW_H_INCLUDED) +#define CDIRECTDRAW_H_INCLUDED + +#include "IS9xDisplayOutput.h" + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +class CDirectDraw: public IS9xDisplayOutput +{ +public: + HRESULT dErr; + LPDIRECTDRAW lpDD; + LPDIRECTDRAWCLIPPER lpDDClipper; + LPDIRECTDRAWPALETTE lpDDPalette; + + LPDIRECTDRAWSURFACE2 lpDDSPrimary2; + LPDIRECTDRAWSURFACE2 lpDDSOffScreen2; + + RECT SizeHistory [10]; + + int width, height; + char depth; + bool doubleBuffered; + bool clipped; + bool dDinitialized; + + DDPIXELFORMAT DDPixelFormat; +public: + bool SetDisplayMode( + int pWidth, int pHeight, int pScale, + char pDepth, int pRefreshRate, bool pWindowed, + bool pDoubleBuffered); + void GetPixelFormat (); + void DeInitialize(); + bool Initialize (HWND hWnd); + + void Render(SSurface Src); + bool ApplyDisplayChanges(void); + bool ChangeRenderSize(unsigned int newWidth, unsigned int newHeight); + bool SetFullscreen(bool fullscreen); + void SetSnes9xColorFormat(); + + void EnumModes(std::vector *modeVector); + + CDirectDraw(); + virtual ~CDirectDraw(); +}; + +#endif // !defined(CDIRECTDRAW_H_INCLUDED) diff --git a/win32/CDirectSound.cpp b/win32/CDirectSound.cpp new file mode 100644 index 00000000..c0f1e547 --- /dev/null +++ b/win32/CDirectSound.cpp @@ -0,0 +1,516 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + + + +// CDirectSound.cpp: implementation of the CDirectSound class. +// +////////////////////////////////////////////////////////////////////// + +#include "wsnes9x.h" +#include "../snes9x.h" +#include "../apu/apu.h" +#include "CDirectSound.h" +#include + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +CDirectSound::CDirectSound() +{ + lpDS = NULL; + lpDSB = NULL; + lpDSBPrimary = NULL; + + initDone = NULL; + blockCount = 0; + blockSize = 0; + bufferSize = 0; + blockSamples = 0; + hTimer = NULL; + hTimerQueue = NULL; +} + +CDirectSound::~CDirectSound() +{ + DeInitDirectSound(); +} + +/* CDirectSound::InitDirectSound +initializes the DirectSound object, the timer queue for the mixing timer, and sets the cooperation level +----- +returns true if successful, false otherwise +*/ +bool CDirectSound::InitDirectSound () +{ + HRESULT dErr; + + if(initDone) + return true; + + if (!lpDS) + { + dErr = DirectSoundCreate (NULL, &lpDS, NULL); + if (dErr != DS_OK) + { + MessageBox (GUI.hWnd, TEXT("\ +Unable to initialise DirectSound. You will not be able to hear any\n\ +sound effects or music while playing.\n\n\ +It is usually caused by not having DirectX installed, another\n\ +application that has already opened DirectSound in exclusive\n\ +mode or the Windows WAVE device has been opened."), + TEXT("Snes9X - Unable to Open DirectSound"), + MB_OK | MB_ICONWARNING); + return (false); + } + } + initDone = true; + dErr = lpDS->SetCooperativeLevel (GUI.hWnd, DSSCL_PRIORITY | DSSCL_EXCLUSIVE); + if (!SUCCEEDED(dErr)) + { + dErr = lpDS->SetCooperativeLevel (GUI.hWnd, DSSCL_PRIORITY); + if (!SUCCEEDED(dErr)) + { + if (!SUCCEEDED(lpDS -> SetCooperativeLevel (GUI.hWnd, DSSCL_NORMAL))) + { + DeInitDirectSound(); + initDone = false; + } + if (initDone) + MessageBox (GUI.hWnd, TEXT("\ +Unable to set DirectSound's priority cooperative level.\n\ +Another application is dicating the sound playback rate,\n\ +sample size and mono/stereo setting."), + TEXT("Snes9X - Unable to Set DirectSound priority"), + MB_OK | MB_ICONWARNING); + else + MessageBox (GUI.hWnd, TEXT("\ +Unable to set any DirectSound cooperative level. You will\n\ +not be able to hear any sound effects or music while playing.\n\n\ +It is usually caused by another application that has already\n\ +opened DirectSound in exclusive mode."), + TEXT("Snes9X - Unable to DirectSound"), + MB_OK | MB_ICONWARNING); + } + } + + hTimerQueue = CreateTimerQueue(); + if(!hTimerQueue) { + DeInitDirectSound(); + return false; + } + + return (initDone); +} + +/* CDirectSound::DeInitDirectSound +releases all DirectSound objects and buffers +*/ +void CDirectSound::DeInitDirectSound() +{ + initDone = false; + + DeInitSoundBuffer(); + + if( lpDS != NULL) + { + lpDS->SetCooperativeLevel (GUI.hWnd, DSSCL_NORMAL); + lpDS->Release (); + lpDS = NULL; + } + if(hTimerQueue) { + DeleteTimerQueueEx(hTimer,NULL); + hTimerQueue = NULL; + } +} + +/* CDirectSound::InitSoundBuffer +creates the DirectSound buffers and allocates the temp buffer for SoundSync +----- +returns true if successful, false otherwise +*/ +bool CDirectSound::InitSoundBuffer() +{ + DSBUFFERDESC dsbd; + WAVEFORMATEX wfx,wfx_actual; + HRESULT dErr; + + blockCount = 4; + blockTime = GUI.SoundBufferSize / blockCount; + + blockSamples = (Settings.SoundPlaybackRate * blockTime * (Settings.Stereo ? 2 : 1)) / 1000; + blockSize = blockSamples * (Settings.SixteenBitSound ? 2 : 1); + bufferSize = blockSize * blockCount; + + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = Settings.Stereo ? 2 : 1; + wfx.nSamplesPerSec = Settings.SoundPlaybackRate; + wfx.nBlockAlign = (Settings.SixteenBitSound ? 2 : 1) * (Settings.Stereo ? 2 : 1); + wfx.wBitsPerSample = Settings.SixteenBitSound ? 16 : 8; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + wfx.cbSize = 0; + + ZeroMemory (&dsbd, sizeof(DSBUFFERDESC) ); + dsbd.dwSize = sizeof(dsbd); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_STICKYFOCUS; + + dErr = lpDS->CreateSoundBuffer (&dsbd, &lpDSBPrimary, NULL); + if (dErr != DS_OK) + { + lpDSB = NULL; + return (false); + } + + lpDSBPrimary->SetFormat (&wfx); + if (lpDSBPrimary->GetFormat (&wfx_actual, sizeof (wfx_actual), NULL) == DS_OK) + { + if(wfx.nSamplesPerSec!=wfx_actual.nSamplesPerSec || + wfx_actual.nChannels != wfx.nChannels || wfx.wBitsPerSample != wfx_actual.wBitsPerSample) { + return false; + } + } + + lpDSBPrimary->Play (0, 0, DSBPLAY_LOOPING); + + ZeroMemory (&dsbd, sizeof (dsbd)); + dsbd.dwSize = sizeof( dsbd); + dsbd.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLVOLUME | + DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY; + dsbd.dwBufferBytes = bufferSize; + dsbd.lpwfxFormat = &wfx; + + if (lpDS->CreateSoundBuffer (&dsbd, &lpDSB, NULL) != DS_OK) + { + lpDSBPrimary->Release (); + lpDSBPrimary = NULL; + lpDSB->Release(); + lpDSB = NULL; + return (false); + } + + return true; +} + +/* CDirectSound::DeInitSoundBuffer +deinitializes the DirectSound/temp buffers and stops the mixing timer +*/ +void CDirectSound::DeInitSoundBuffer() +{ + if(hTimer) { + if(!DeleteTimerQueueTimer(hTimerQueue,hTimer,INVALID_HANDLE_VALUE)) + DeleteTimerQueueTimer(hTimerQueue,hTimer,INVALID_HANDLE_VALUE); + hTimer = NULL; + } + if( lpDSB != NULL) + { + lpDSB->Stop (); + lpDSB->Release(); + lpDSB = NULL; + } + if( lpDSBPrimary != NULL) + { + lpDSBPrimary->Stop (); + lpDSBPrimary->Release(); + lpDSBPrimary = NULL; + } +} + +/* CDirectSound::SetupSound +applies sound setting changes by recreating the buffers and starting a new mixing timer +it fills the buffer before starting playback +----- +returns true if successful, false otherwise +*/ +bool CDirectSound::SetupSound() +{ + HRESULT hResult; + + if(!initDone) + return false; + + DeInitSoundBuffer(); + InitSoundBuffer(); + + BYTE *B1; + DWORD S1; + hResult = lpDSB->Lock (0, 0, (void **)&B1, + &S1, NULL, NULL, DSBLOCK_ENTIREBUFFER); + if (hResult == DSERR_BUFFERLOST) + { + lpDSB->Restore (); + hResult = lpDSB->Lock (0, 0, (void **)&B1, + &S1, NULL, NULL, DSBLOCK_ENTIREBUFFER); + } + if (!SUCCEEDED(hResult)) + { + hResult = lpDSB -> Unlock (B1, S1, NULL, NULL); + return true; + } + + S9xMixSamples(B1,blockSamples * blockCount); + lpDSB->Unlock(B1,S1,NULL,NULL); + + lpDSB->Play (0, 0, DSBPLAY_LOOPING); + + last_block = blockCount - 1; + + + if(!CreateTimerQueueTimer(&hTimer,hTimerQueue,SoundTimerCallback,(void *)this,blockTime/2,blockTime/2,WT_EXECUTEINIOTHREAD)) { + DeInitSoundBuffer(); + return false; + } + + return (true); +} + +/* CDirectSound::ProcessSound +Finishes core sample creation, syncronizes the buffer access. +*/ +void CDirectSound::ProcessSound() +{ + EnterCriticalSection(&GUI.SoundCritSect); + + S9xFinalizeSamples(); + + LeaveCriticalSection(&GUI.SoundCritSect); +} + +/* CDirectSound::MixSound +the mixing function called by the mix timer +uses the current play position to decide if a new block can be filled with audio data +synchronizes the core buffer access with a critical section +*/ +void CDirectSound::MixSound() +{ + DWORD play_pos = 0, write_pos = 0; + HRESULT hResult; + DWORD curr_block; + + + lpDSB->GetCurrentPosition (&play_pos, NULL); + + curr_block = ((play_pos / blockSize) + blockCount) % blockCount; + + if (curr_block != last_block) + { + BYTE *B1, *B2; + DWORD S1, S2; + + write_pos = curr_block * blockSize; + last_block = curr_block; + + hResult = lpDSB->Lock (write_pos, blockSize, (void **)&B1, + &S1, (void **)&B2, &S2, 0); + if (hResult == DSERR_BUFFERLOST) + { + lpDSB->Restore (); + hResult = lpDSB->Lock (write_pos, blockSize, + (void **)&B1, &S1, (void **)&B2, + &S2, 0); + } + if (!SUCCEEDED(hResult)) + { + hResult = lpDSB -> Unlock (B1, S1, B2, S2); + return; + } + + EnterCriticalSection(&GUI.SoundCritSect); + if (B1) + { + S9xMixSamples(B1,(Settings.SixteenBitSound?S1>>1:S1)); + } + if (B2) + { + S9xMixSamples(B2,(Settings.SixteenBitSound?S2>>1:S2)); + } + LeaveCriticalSection(&GUI.SoundCritSect); + + + hResult = lpDSB -> Unlock (B1, S1, B2, S2); + if (!SUCCEEDED(hResult)) + return; + } +} + +/* CDirectSound::SoundTimerCallback +Timer callback that tries to mix a new block. Called twice each block. +*/ +VOID CALLBACK CDirectSound::SoundTimerCallback(PVOID lpParameter,BOOLEAN TimerOrWaitFired) { + CDirectSound *S9xDirectSound = (CDirectSound *)lpParameter; + S9xDirectSound->MixSound(); +} + diff --git a/win32/CDirectSound.h b/win32/CDirectSound.h new file mode 100644 index 00000000..0ad11f2d --- /dev/null +++ b/win32/CDirectSound.h @@ -0,0 +1,238 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + + +// CDirectSound.h: interface for the CDirectSound class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(DIRECTSOUND_H_INCLUDED) +#define DIRECTSOUND_H_INCLUDED + +#include +#include "IS9xSoundOutput.h" + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +class CDirectSound : public IS9xSoundOutput +{ +private: + LPDIRECTSOUND lpDS; + LPDIRECTSOUNDBUFFER lpDSB; // the buffer used for mixing + LPDIRECTSOUNDBUFFER lpDSBPrimary; + + int blockCount; // number of blocks in the buffer + int blockSize; // bytes in one block + int blockSamples; + int bufferSize; // bytes in the whole buffer + int blockTime; + + DWORD last_block; // the last block that was mixed + + bool initDone; // has init been called successfully? + HANDLE hTimerQueue; // handle to the mixing thread + HANDLE hTimer; + + volatile bool threadExit; // mixing thread exit signal + + bool InitDirectSound (); + void DeInitDirectSound(); + + bool InitSoundBuffer(); + void DeInitSoundBuffer(); + + static VOID CALLBACK CDirectSound::SoundTimerCallback(PVOID lpParameter,BOOLEAN TimerOrWaitFired); + + void ProcessSound(); + void MixSound(); + +public: + CDirectSound(); + ~CDirectSound(); + + // Inherited from IS9xSoundOutput + bool InitSoundOutput(void) { return InitDirectSound(); } + void DeInitSoundOutput(void) { DeInitDirectSound(); } + bool SetupSound(void); + +}; + +extern CDirectSound DirectSound; + +#endif // !defined(DIRECTSOUND_H_INCLUDED) diff --git a/win32/CFMOD.cpp b/win32/CFMOD.cpp new file mode 100644 index 00000000..13f99aed --- /dev/null +++ b/win32/CFMOD.cpp @@ -0,0 +1,366 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 FMOD_SUPPORT +#include "CFMOD.h" +#include "../snes9x.h" +#include "../apu/apu.h" +#include "wsnes9x.h" + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +/* Construction/Destruction +*/ +CFMOD::CFMOD(void) +{ + initDone = false; + fmod_stream = NULL; +} + +CFMOD::~CFMOD(void) +{ + DeInitFMOD(); +} + +/* CFMOD::InitStream +initializes FMOD and the output stream that will call our callback function +----- +returns true if successful, false otherwise +*/ +bool CFMOD::InitStream() +{ + if (!FSOUND_Init (Settings.SoundPlaybackRate, 16, 0)) + { + MessageBox (GUI.hWnd, "\ +Unable to initialise FMOD sound system. You will not be able to hear\n\ +any sound effects or music while playing.\n\n\ +It is usually caused by not having DirectX installed or another\n\ +application that has already opened DirectSound in exclusive\n\ +mode or the Windows WAVE device has been opened.", + "Snes9X - Unable to Open FMOD", + MB_OK | MB_ICONWARNING); + DeInitStream(); + return false; + } + + sampleCount = (Settings.SoundPlaybackRate * GUI.SoundBufferSize/2 ) / 1000; + if (Settings.Stereo) + sampleCount *= 2; + bufferSize = sampleCount * (Settings.SixteenBitSound?2:1); + fmod_stream = FSOUND_Stream_Create (FMODStreamCallback, bufferSize, + FSOUND_LOOP_OFF | + FSOUND_STREAMABLE | + FSOUND_SIGNED | + FSOUND_LOOP_NORMAL | + (Settings.SixteenBitSound ? + FSOUND_16BITS : FSOUND_8BITS) | + (Settings.Stereo ? + FSOUND_STEREO : FSOUND_MONO), + Settings.SoundPlaybackRate, (void *)this); + + if (!fmod_stream || + FSOUND_Stream_Play (FSOUND_FREE, fmod_stream) == -1) + { + MessageBox (GUI.hWnd, "\ +Unable to create or play an FMOD sound stream. You will not be able\n\ +to hear any sound effects or music while playing.", + "Snes9X - Unable to Open FMOD", + MB_OK | MB_ICONWARNING); + DeInitStream(); + return false; + } + return true; +} + +/* CFMOD::DeInitStream +stops playback and closes the stream +*/ +void CFMOD::DeInitStream() +{ + if (fmod_stream) + { + FSOUND_StopSound (0); + FSOUND_Stream_Stop (fmod_stream); + FSOUND_Stream_Close (fmod_stream); + FSOUND_Close (); + fmod_stream = NULL; + } +} + +/* CFMOD::InitFMOD +sets the sound driver to be used by FMOD +----- +returns true if successful, false otherwise +*/ +bool CFMOD::InitFMOD() +{ + if(initDone) + return true; + + switch (GUI.SoundDriver) + { + default: + case WIN_FMOD_DIRECT_SOUND_DRIVER: + FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND); + break; + case WIN_FMOD_WAVE_SOUND_DRIVER: + FSOUND_SetOutput(FSOUND_OUTPUT_WINMM); + break; + case WIN_FMOD_A3D_SOUND_DRIVER: + FSOUND_SetOutput(FSOUND_OUTPUT_A3D); + break; + } + + FSOUND_SetDriver(0); + + initDone = true; + return true; +} + +void CFMOD::DeInitFMOD() +{ + DeInitStream(); +} + +/* CFMOD::SetupSound +applies current sound settings by recreating the stream +----- +returns true if successful, false otherwise +*/ +bool CFMOD::SetupSound() +{ + + DeInitStream(); + if(!InitStream()) { + return false; + } + + return true; +} + +/* CFMOD::ProcessSound +Finishes core sample creation, syncronizes the buffer access. +*/ +void CFMOD::ProcessSound() +{ + EnterCriticalSection(&GUI.SoundCritSect); + + S9xFinalizeSamples(); + + LeaveCriticalSection(&GUI.SoundCritSect); +} + +/* CFMOD::FMODStreamCallback +the callback that mixes into the stream +synchronizes the buffer access with a critical section +IN: +stream - the stream object, unused +buff - the buffer to mix into +len - number of bytes in the buffer +param - pointer to the CFMOD object +*/ + +// The FMOD API changed the return type of the stream callback function +// somewhere between version 3.20 and 3.33. The FMOD API defines a version +// string but you can't test for that at compile time. Instead, I've picked on +// a symbol that wasn't defined in version 3.20 to test for the change in API. +#if !defined (FSOUND_LOADRAW) +void +#else +signed char +#endif +F_CALLBACKAPI CFMOD::FMODStreamCallback (FSOUND_STREAM *stream, void *buff, int len, void *param) +{ + CFMOD *S9xFMOD=(CFMOD *)param; + int sample_count = Settings.SixteenBitSound?len>>1:len; + + EnterCriticalSection(&GUI.SoundCritSect); + + S9xMixSamples((unsigned char *) buff, sample_count); + + LeaveCriticalSection(&GUI.SoundCritSect); + + + +#if defined (FSOUND_LOADRAW) + return (1); +#endif +} + +#endif \ No newline at end of file diff --git a/win32/CFMOD.h b/win32/CFMOD.h new file mode 100644 index 00000000..9ecfe6a5 --- /dev/null +++ b/win32/CFMOD.h @@ -0,0 +1,221 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 CFMOD_H +#define CFMOD_H +#include "fmod.h" +#include "IS9xSoundOutput.h" + +class CFMOD: public IS9xSoundOutput +{ + bool initDone; // has init been called successfully? + + FSOUND_STREAM *fmod_stream; // the stream object + + int sampleCount; + int bufferSize; + + bool InitFMOD(); + void DeInitFMOD(); + + bool InitStream(); + void DeInitStream(); + + void ProcessSound(); + + // The FMOD API changed the return type of the stream callback function + // somewhere between version 3.20 and 3.33. The FMOD API defines a version + // string but you can't test for that at compile time. Instead, I've picked on + // a symbol that wasn't defined in version 3.20 to test for the change in API. + #if !defined (FSOUND_LOADRAW) + void + #else + signed char + #endif + static F_CALLBACKAPI FMODStreamCallback (FSOUND_STREAM *stream, void *buff, int len, void *param); + +public: + CFMOD(void); + ~CFMOD(void); + + // Inherited from IS9xSoundOutput + bool InitSoundOutput(void) { return InitFMOD(); } + void DeInitSoundOutput(void) { DeInitFMOD(); } + bool SetupSound(void); +}; + +#endif \ No newline at end of file diff --git a/win32/CFMODEx.cpp b/win32/CFMODEx.cpp new file mode 100644 index 00000000..09f9035e --- /dev/null +++ b/win32/CFMODEx.cpp @@ -0,0 +1,141 @@ +#ifdef FMODEX_SUPPORT +#ifndef FMOD_SUPPORT +#include "CFMODEx.h" +#include "wsnes9x.h" +#include "../snes9x.h" +#include "../apu/apu.h" + +CFMODEx::CFMODEx(void) +{ + initDone = false; + fmodStream = NULL; + + fmodSystem = NULL; +} + +CFMODEx::~CFMODEx(void) +{ + DeInitFMODEx(); + if(fmodSystem) + fmodSystem->release(); +} + +bool CFMODEx::InitStream() +{ + FMOD_CREATESOUNDEXINFO createSoundExInfo={0}; + createSoundExInfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); + createSoundExInfo.defaultfrequency = Settings.SoundPlaybackRate; + createSoundExInfo.numchannels = (Settings.Stereo?2:1); + createSoundExInfo.format = (Settings.SixteenBitSound?FMOD_SOUND_FORMAT_PCM16:FMOD_SOUND_FORMAT_PCM8); + createSoundExInfo.pcmreadcallback = FMODExStreamCallback; + createSoundExInfo.suggestedsoundtype = FMOD_SOUND_TYPE_USER; + //fmodSystem->getDSPBufferSize(&temp,NULL); + // 768 was the bufferSize in FMOD + sampleCount = (Settings.SoundPlaybackRate * GUI.SoundBufferSize/2 ) / 1000; + if (Settings.Stereo) + sampleCount *= 2; + bufferSize = sampleCount * (Settings.SixteenBitSound?2:1); + createSoundExInfo.length = bufferSize; + createSoundExInfo.decodebuffersize = bufferSize/4; + + FMOD_RESULT fr = fmodSystem->createStream(NULL,FMOD_OPENUSER | FMOD_LOOP_NORMAL | FMOD_OPENRAW,&createSoundExInfo,&fmodStream); + + if(!(fr==FMOD_OK)) { + return false; + } + + fr = fmodSystem->playSound(FMOD_CHANNEL_FREE,fmodStream,0,NULL); + + return true; +} + +void CFMODEx::DeInitStream() +{ + if (fmodStream) + { + fmodStream->release(); + fmodStream = NULL; + } +} + +bool CFMODEx::InitFMODEx() +{ + if(initDone) + return true; + + FMOD_RESULT fr; + + if(!(FMOD::System_Create(&fmodSystem)==FMOD_OK)) + return false; + + switch (GUI.SoundDriver) + { + default: + case WIN_FMODEX_DEFAULT_DRIVER: + fr = fmodSystem->setOutput(FMOD_OUTPUTTYPE_AUTODETECT); + break; + case WIN_FMODEX_ASIO_DRIVER: + fr = fmodSystem->setOutput(FMOD_OUTPUTTYPE_ASIO); + break; + case WIN_FMODEX_OPENAL_DRIVER: + fr = fmodSystem->setOutput(FMOD_OUTPUTTYPE_OPENAL); + break; + } + + fr = fmodSystem->init(2,FMOD_INIT_NORMAL,0); + + if(fr!=FMOD_OK) + return false; + + initDone = true; + return true; +} + +void CFMODEx::DeInitFMODEx() +{ + initDone = false; + DeInitStream(); + if(fmodSystem) { + fmodSystem->release(); + fmodSystem = NULL; + } +} + +bool CFMODEx::SetupSound() +{ + if(!initDone) + return false; + + DeInitStream(); + return InitStream(); +} + +void CFMODEx::ProcessSound() +{ + EnterCriticalSection(&GUI.SoundCritSect); + + S9xFinalizeSamples(); + + LeaveCriticalSection(&GUI.SoundCritSect); +} + +FMOD_RESULT F_CALLBACK CFMODEx::FMODExStreamCallback( + FMOD_SOUND * sound, + void * data, + unsigned int datalen + ) +{ + int sample_count = datalen; + + sample_count >>= (Settings.SixteenBitSound?1:0); + + EnterCriticalSection(&GUI.SoundCritSect); + + S9xMixSamples((unsigned char *) data, sample_count); + + LeaveCriticalSection(&GUI.SoundCritSect); + + return FMOD_OK; +} +#endif +#endif \ No newline at end of file diff --git a/win32/CFMODEx.h b/win32/CFMODEx.h new file mode 100644 index 00000000..2d4f1b4d --- /dev/null +++ b/win32/CFMODEx.h @@ -0,0 +1,40 @@ +#ifndef CFMODEX_H +#define CFMODEX_H +#include "../../FMODEx/api/inc/fmod.hpp" +#include "IS9xSoundOutput.h" + +class CFMODEx: public IS9xSoundOutput +{ + bool initDone; + + FMOD::System *fmodSystem; + FMOD::Sound *fmodStream; + + + int sampleCount; + int bufferSize; + + bool InitFMODEx(); + void DeInitFMODEx(); + + bool InitStream(); + void DeInitStream(); + + static FMOD_RESULT F_CALLBACK FMODExStreamCallback( + FMOD_SOUND * sound, + void * data, + unsigned int datalen + ); + +public: + CFMODEx(void); + ~CFMODEx(void); + + // Inherited from IS9xSoundOutput + bool InitSoundOutput(void) { return InitFMODEx(); } + void DeInitSoundOutput(void) { DeInitFMODEx(); } + bool SetupSound(); + void ProcessSound(); +}; + +#endif \ No newline at end of file diff --git a/win32/CXAudio2.cpp b/win32/CXAudio2.cpp new file mode 100644 index 00000000..f801e23f --- /dev/null +++ b/win32/CXAudio2.cpp @@ -0,0 +1,403 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "CXAudio2.h" +#include "../snes9x.h" +#include "../apu/apu.h" +#include "wsnes9x.h" +#include +#include + +/* CXAudio2 + Implements audio output through XAudio2. + Basic idea: one master voice and one source voice are created; + the source voice consumes buffers queued by PushBuffer, plays them through + the master voice and calls OnBufferEnd after each buffer. + ProcessSound copies new samples into the buffer and queues them for playback. +*/ + +/* Construction/Destruction +*/ +CXAudio2::CXAudio2(void) +{ + pXAudio2 = NULL; + pSourceVoice = NULL; + pMasterVoice = NULL; + + sum_bufferSize = singleBufferBytes \ + = singleBufferSamples = blockCount = 0; + soundBuffer = NULL; + initDone = false; +} + +CXAudio2::~CXAudio2(void) +{ + DeInitXAudio2(); +} + +/* CXAudio2::InitXAudio2 +initializes the XAudio2 object +----- +returns true if successful, false otherwise +*/ +bool CXAudio2::InitXAudio2(void) +{ + if(initDone) + return true; + + HRESULT hr; + if ( FAILED(hr = XAudio2Create( &pXAudio2, 0 , XAUDIO2_DEFAULT_PROCESSOR ) ) ) { + DXTRACE_ERR_MSGBOX(TEXT("Unable to create XAudio2 object."),hr); + MessageBox (GUI.hWnd, TEXT("\ +Unable to initialize XAudio2. You will not be able to hear any\n\ +sound effects or music while playing.\n\n\ +It is usually caused by not having a recent DirectX release installed."), + TEXT("Snes9X - Unable to Initialize XAudio2"), + MB_OK | MB_ICONWARNING); + return false; + } + initDone = true; + return true; +} + +/* CXAudio2::InitVoices +initializes the voice objects with the current audio settings +----- +returns true if successful, false otherwise +*/ +bool CXAudio2::InitVoices(void) +{ + HRESULT hr; + if ( FAILED(hr = pXAudio2->CreateMasteringVoice( &pMasterVoice, (Settings.Stereo?2:1), + Settings.SoundPlaybackRate, 0, 0 , NULL ) ) ) { + DXTRACE_ERR_MSGBOX(TEXT("Unable to create mastering voice."),hr); + return false; + } + + WAVEFORMATEX wfx; + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = Settings.Stereo ? 2 : 1; + wfx.nSamplesPerSec = Settings.SoundPlaybackRate; + wfx.nBlockAlign = (Settings.SixteenBitSound ? 2 : 1) * (Settings.Stereo ? 2 : 1); + wfx.wBitsPerSample = Settings.SixteenBitSound ? 16 : 8; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + wfx.cbSize = 0; + + if( FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx, + XAUDIO2_VOICE_NOSRC , XAUDIO2_DEFAULT_FREQ_RATIO, this, NULL, NULL ) ) ) { + DXTRACE_ERR_MSGBOX(TEXT("Unable to create source voice."),hr); + return false; + } + + return true; +} + +/* CXAudio2::DeInitXAudio2 +deinitializes all objects +*/ +void CXAudio2::DeInitXAudio2(void) +{ + initDone = false; + DeInitVoices(); + if(pXAudio2) { + pXAudio2->Release(); + pXAudio2 = NULL; + } +} + +/* CXAudio2::DeInitVoices +deinitializes the voice objects and buffers +*/ +void CXAudio2::DeInitVoices(void) +{ + if(pSourceVoice) { + StopPlayback(); + pSourceVoice->DestroyVoice(); + pSourceVoice = NULL; + } + if(pMasterVoice) { + pMasterVoice->DestroyVoice(); + pMasterVoice = NULL; + } + if(soundBuffer) { + delete [] soundBuffer; + soundBuffer = NULL; + } +} + +/* CXAudio2::OnBufferEnd +callback function called by the source voice +IN: +pBufferContext - unused +*/ +void CXAudio2::OnBufferEnd(void *pBufferContext) +{ + InterlockedDecrement(&bufferCount); +} + +/* CXAudio2::PushBuffer +pushes one buffer onto the source voice playback queue +IN: +AudioBytes - size of the buffer +pAudioData - pointer to the buffer +pContext - context passed to the callback, currently unused +*/ +void CXAudio2::PushBuffer(UINT32 AudioBytes,BYTE *pAudioData,void *pContext) +{ + XAUDIO2_BUFFER xa2buffer={0}; + xa2buffer.AudioBytes=AudioBytes; + xa2buffer.pAudioData=pAudioData; + xa2buffer.pContext=pContext; + InterlockedIncrement(&bufferCount); + pSourceVoice->SubmitSourceBuffer(&xa2buffer); +} + +/* CXAudio2::SetupSound +applies current sound settings by recreating the voice objects and buffers +----- +returns true if successful, false otherwise +*/ +bool CXAudio2::SetupSound() +{ + if(!initDone) + return false; + + DeInitVoices(); + + blockCount = 8; + UINT32 blockTime = GUI.SoundBufferSize / blockCount; + + singleBufferSamples = (Settings.SoundPlaybackRate * blockTime * (Settings.Stereo ? 2 : 1)) / 1000; + singleBufferBytes = singleBufferSamples * (Settings.SixteenBitSound ? 2 : 1); + sum_bufferSize = singleBufferBytes * blockCount; + + if (InitVoices()) + { + soundBuffer = new uint8[sum_bufferSize]; + writeOffset = 0; + } + else { + DeInitVoices(); + return false; + } + + bufferCount = 0; + + BeginPlayback(); + + return true; +} + +void CXAudio2::BeginPlayback() +{ + pSourceVoice->Start(0); +} + +void CXAudio2::StopPlayback() +{ + pSourceVoice->Stop(0); +} + +/* CXAudio2::ProcessSound +The mixing function called by the sound core when new samples are available. +SoundBuffer is divided into blockCount blocks. If there are enought available samples and a free block, +the block is filled and queued to the source voice. bufferCount is increased by pushbuffer and decreased by +the OnBufferComplete callback. +*/ +void CXAudio2::ProcessSound() +{ + S9xFinalizeSamples(); + + if(!initDone) + return; + + BYTE * curBuffer; + + UINT32 availableSamples; + UINT32 availableBytes; + + availableSamples = S9xGetSampleCount(); + availableBytes = availableSamples * (Settings.SixteenBitSound ? 2 : 1); + + while(availableSamples > singleBufferSamples && bufferCount < blockCount) { + curBuffer = soundBuffer + writeOffset; + S9xMixSamples(curBuffer,singleBufferSamples); + PushBuffer(singleBufferBytes,curBuffer,NULL); + writeOffset+=singleBufferBytes; + writeOffset%=sum_bufferSize; + } +} \ No newline at end of file diff --git a/win32/CXAudio2.h b/win32/CXAudio2.h new file mode 100644 index 00000000..9626e0cc --- /dev/null +++ b/win32/CXAudio2.h @@ -0,0 +1,235 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 CXHAUDIO2_H +#define CXAUDIO2_H +#include "XAudio2.h" +#include "../snes9x.h" +#include +#include "IS9xSoundOutput.h" + +class CXAudio2 : public IXAudio2VoiceCallback, public IS9xSoundOutput +{ +private: + IXAudio2SourceVoice *pSourceVoice; + IXAudio2 *pXAudio2; + IXAudio2MasteringVoice* pMasterVoice; + + bool initDone; // has init been called successfully? + + volatile LONG bufferCount; // currently submitted XAudio2 buffers + + UINT32 sum_bufferSize; // the size of soundBuffer + UINT32 singleBufferSamples; // samples in one block + UINT32 singleBufferBytes; // bytes in one block + UINT32 blockCount; // soundBuffer is divided into blockCount blocks + // currently set to 4 + + UINT32 writeOffset; // offset into the buffer for the next block + uint8 *soundBuffer; // the buffer itself + + bool InitVoices(void); + void DeInitVoices(void); + + void PushBuffer(UINT32 AudioBytes,BYTE *pAudioData,void *pContext); + void BeginPlayback(void); + void StopPlayback(void); + void ProcessSound(void); + bool InitXAudio2(void); + void DeInitXAudio2(void); + +public: + CXAudio2(void); + ~CXAudio2(void); + + // inherited from IXAudio2VoiceCallback - we only use OnBufferEnd + STDMETHODIMP_(void) OnBufferEnd(void *pBufferContext); + STDMETHODIMP_(void) OnBufferStart(void *pBufferContext){} + STDMETHODIMP_(void) OnLoopEnd(void *pBufferContext){} + STDMETHODIMP_(void) OnStreamEnd() {} + STDMETHODIMP_(void) OnVoiceError(void *pBufferContext, HRESULT Error) {} + STDMETHODIMP_(void) OnVoiceProcessingPassEnd() {} + STDMETHODIMP_(void) OnVoiceProcessingPassStart(UINT32 BytesRequired) {} + + + // Inherited from IS9xSoundOutput + bool InitSoundOutput(void) { return InitXAudio2(); } + void DeInitSoundOutput(void) { DeInitXAudio2(); } + bool SetupSound(void); +}; + +#endif \ No newline at end of file diff --git a/win32/IS9xDisplayOutput.h b/win32/IS9xDisplayOutput.h new file mode 100644 index 00000000..b1e1dd64 --- /dev/null +++ b/win32/IS9xDisplayOutput.h @@ -0,0 +1,204 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 IS9XDISPLAYOUTPUT_H +#define IS9XDISPLAYOUTPUT_H +#include "../port.h" +#include "render.h" +#include + +/* IS9xDisplayOutput + Interface for display driver. +*/ +class IS9xDisplayOutput +{ +private: + +public: + virtual bool Initialize(HWND hWnd)=0; + virtual void DeInitialize()=0; + virtual void Render(SSurface Src)=0; + virtual bool ChangeRenderSize(unsigned int newWidth, unsigned int newHeight)=0; + virtual bool ApplyDisplayChanges(void)=0; + virtual bool SetFullscreen(bool fullscreen)=0; + virtual void SetSnes9xColorFormat()=0; + virtual void EnumModes(std::vector *modeVector)=0; +}; + + +#endif \ No newline at end of file diff --git a/win32/IS9xSoundOutput.h b/win32/IS9xSoundOutput.h new file mode 100644 index 00000000..b4ad2b94 --- /dev/null +++ b/win32/IS9xSoundOutput.h @@ -0,0 +1,205 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 IS9XSOUNDOUTPUT_H +#define IS9XSOUNDOUTPUT_H +#include "../port.h" + +/* IS9xSoundOutput + Interface for the sound output. +*/ + +class IS9xSoundOutput { +public: + // InitSoundOutput should initialize the sound output but not start playback + virtual bool InitSoundOutput(void)=0; + + // DeInitSoundOutput should stop playback and uninitialize the output + virtual void DeInitSoundOutput(void)=0; + + // SetupSound should apply the current sound settings for outputbuffers/devices and + // (re)start playback + virtual bool SetupSound()=0; + + // ProcessSound should call S9xFinalizeSamples and queue new available samples into the + // Host sound system. If the sound system is callback based, ProcessSound should do a syncronized + // S9xFinalizeSamples and return. + virtual void ProcessSound()=0; +}; + +#endif \ No newline at end of file diff --git a/win32/InputCustom.cpp b/win32/InputCustom.cpp new file mode 100644 index 00000000..5e3b878e --- /dev/null +++ b/win32/InputCustom.cpp @@ -0,0 +1,1326 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 __MINGW32__ +#define _WIN32_IE 0x0501 +#define _WIN32_WINNT 0x0501 +#endif + +#define STRICT +#include +#include +#include + +#if (((defined(_MSC_VER) && _MSC_VER >= 1300)) || defined(__MINGW32__)) + // both MINGW and VS.NET use fstream instead of fstream.h which is deprecated + #include + using namespace std; +#else + // for VC++ 6 + #include +#endif + +#include "InputCustom.h" +#include "wsnes9x.h" +#include "wlanguage.h" + +static TCHAR szClassName[] = _T("InputCustom"); +static TCHAR szHotkeysClassName[] = _T("InputCustomHot"); + +static LRESULT CALLBACK InputCustomWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK HotInputCustomWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + + +extern SJoyState JoystickF [16]; + +HWND funky; +//WPARAM tid; + + +void JoystickChanged( short ID, short Movement) +{ + // don't allow two changes to happen too close together in time + { + static bool first = true; + static DWORD lastTime = 0; + if(first || timeGetTime() - lastTime > 300) // 0.3 seconds + { + first = false; + lastTime = timeGetTime(); + } + else + { + return; // too soon after last change + } + } + + WORD JoyKey; + + JoyKey = 0x8000; + JoyKey |= (WORD)(ID << 8); + JoyKey |= Movement; + SendMessage(funky,WM_USER+45,JoyKey,0); +// KillTimer(funky,tid); +} + +int FunkyNormalize(int cur, int min, int max) +{ + int Result = 0; + + if ((max - min) == 0) + + return (Result); + + Result = cur - min; + Result = (Result * 200) / (max - min); + Result -= 100; + + return Result; +} + + +void CheckAxis (short joy, short control, int val, + int min, int max, + bool &first, bool &second) +{ + + + + if (FunkyNormalize (val, min, max) < -S9X_JOY_NEUTRAL) + + { + second = false; + if (!first) + { + JoystickChanged (joy, control); + first = true; + + } + } + else + first = false; + + if (FunkyNormalize (val, min, max) > S9X_JOY_NEUTRAL) + { + first = false; + if (!second) + { + JoystickChanged (joy, (short) (control + 1)); + second = true; + } + } + else + second = false; +} + +void FunkyJoyStickTimer() +{ + JOYINFOEX jie; + + for (short C = 0; C != 16; C ++) + { + + jie.dwSize = sizeof( jie); + jie.dwFlags = JOY_RETURNALL; + + if (joyGetPosEx (JOYSTICKID1 + C, &jie) != JOYERR_NOERROR) + continue; + + CheckAxis (C, 0, jie.dwXpos, + JoystickF[C].Caps.wXmin, JoystickF[C].Caps.wXmax, + JoystickF[C].Left, JoystickF[C].Right); + CheckAxis (C, 2, jie.dwYpos, + JoystickF[C].Caps.wYmin, JoystickF[C].Caps.wYmax, + JoystickF[C].Up, JoystickF[C].Down); + if(JoystickF[C].Caps.wCaps & JOYCAPS_HASZ) + { + CheckAxis (C, 41, jie.dwZpos, + JoystickF[C].Caps.wZmin, JoystickF[C].Caps.wZmax, + JoystickF[C].ZUp, JoystickF[C].ZDown); + } + if(JoystickF[C].Caps.wCaps & JOYCAPS_HASR) + { + CheckAxis (C, 43, jie.dwRpos, + JoystickF[C].Caps.wRmin, JoystickF[C].Caps.wRmax, + JoystickF[C].RUp, JoystickF[C].RDown); + } + if(JoystickF[C].Caps.wCaps & JOYCAPS_HASU) + { + CheckAxis (C, 45, jie.dwUpos, + JoystickF[C].Caps.wUmin, JoystickF[C].Caps.wUmax, + JoystickF[C].UUp, JoystickF[C].UDown); + } + if(JoystickF[C].Caps.wCaps & JOYCAPS_HASV) + { + CheckAxis (C, 47, jie.dwVpos, + JoystickF[C].Caps.wVmin, JoystickF[C].Caps.wVmax, + JoystickF[C].VUp, JoystickF[C].VDown); + } + + switch (jie.dwPOV) + { + case JOY_POVBACKWARD: + if( !JoystickF[C].PovDown) + { JoystickChanged( C, 7); } + + JoystickF[C].PovDown = true; + JoystickF[C].PovUp = false; + JoystickF[C].PovLeft = false; + JoystickF[C].PovRight = false; + JoystickF[C].PovDnLeft = false; + JoystickF[C].PovDnRight = false; + JoystickF[C].PovUpLeft = false; + JoystickF[C].PovUpRight = false; + break; + case 4500: + if( !JoystickF[C].PovUpRight) + { JoystickChanged( C, 52); } + JoystickF[C].PovDown = false; + JoystickF[C].PovUp = false; + JoystickF[C].PovLeft = false; + JoystickF[C].PovRight = false; + JoystickF[C].PovDnLeft = false; + JoystickF[C].PovDnRight = false; + JoystickF[C].PovUpLeft = false; + JoystickF[C].PovUpRight = true; + break; + case 13500: + if( !JoystickF[C].PovDnRight) + { JoystickChanged( C, 50); } + JoystickF[C].PovDown = false; + JoystickF[C].PovUp = false; + JoystickF[C].PovLeft = false; + JoystickF[C].PovRight = false; + JoystickF[C].PovDnLeft = false; + JoystickF[C].PovDnRight = true; + JoystickF[C].PovUpLeft = false; + JoystickF[C].PovUpRight = false; + break; + case 22500: + if( !JoystickF[C].PovDnLeft) + { JoystickChanged( C, 49); } + JoystickF[C].PovDown = false; + JoystickF[C].PovUp = false; + JoystickF[C].PovLeft = false; + JoystickF[C].PovRight = false; + JoystickF[C].PovDnLeft = true; + JoystickF[C].PovDnRight = false; + JoystickF[C].PovUpLeft = false; + JoystickF[C].PovUpRight = false; + break; + case 31500: + if( !JoystickF[C].PovUpLeft) + { JoystickChanged( C, 51); } + JoystickF[C].PovDown = false; + JoystickF[C].PovUp = false; + JoystickF[C].PovLeft = false; + JoystickF[C].PovRight = false; + JoystickF[C].PovDnLeft = false; + JoystickF[C].PovDnRight = false; + JoystickF[C].PovUpLeft = true; + JoystickF[C].PovUpRight = false; + break; + + case JOY_POVFORWARD: + if( !JoystickF[C].PovUp) + { JoystickChanged( C, 6); } + + JoystickF[C].PovDown = false; + JoystickF[C].PovUp = true; + JoystickF[C].PovLeft = false; + JoystickF[C].PovRight = false; + JoystickF[C].PovDnLeft = false; + JoystickF[C].PovDnRight = false; + JoystickF[C].PovUpLeft = false; + JoystickF[C].PovUpRight = false; + break; + + case JOY_POVLEFT: + if( !JoystickF[C].PovLeft) + { JoystickChanged( C, 4); } + + JoystickF[C].PovDown = false; + JoystickF[C].PovUp = false; + JoystickF[C].PovLeft = true; + JoystickF[C].PovRight = false; + JoystickF[C].PovDnLeft = false; + JoystickF[C].PovDnRight = false; + JoystickF[C].PovUpLeft = false; + JoystickF[C].PovUpRight = false; + break; + + case JOY_POVRIGHT: + if( !JoystickF[C].PovRight) + { JoystickChanged( C, 5); } + + JoystickF[C].PovDown = false; + JoystickF[C].PovUp = false; + JoystickF[C].PovLeft = false; + JoystickF[C].PovRight = true; + JoystickF[C].PovDnLeft = false; + JoystickF[C].PovDnRight = false; + JoystickF[C].PovUpLeft = false; + JoystickF[C].PovUpRight = false; + break; + + default: + JoystickF[C].PovDown = false; + JoystickF[C].PovUp = false; + JoystickF[C].PovLeft = false; + JoystickF[C].PovRight = false; + JoystickF[C].PovDnLeft = false; + JoystickF[C].PovDnRight = false; + JoystickF[C].PovUpLeft = false; + JoystickF[C].PovUpRight = false; + break; + } + + for( short B = 0; B != 32; B ++, jie.dwButtons >>= 1) + if( (jie.dwButtons&1)) + { + if( !JoystickF[C].Button[B]) + { + JoystickChanged( C, (short)(8+B)); + JoystickF[C].Button[B] = true; + } + } + else + { JoystickF[C].Button[B] = false; } + + } + +} + +void TranslateKey(WORD keyz,char *out) +{ +// sprintf(out,"%d",keyz); +// return; + + char temp[128]; + if(keyz&0x8000) + { + sprintf(out,GAMEDEVICE_JOYNUMPREFIX,((keyz>>8)&0xF)); + switch(keyz&0xFF) + { + case 0: strcat(out,GAMEDEVICE_XNEG); break; + case 1: strcat(out,GAMEDEVICE_XPOS); break; + case 2: strcat(out,GAMEDEVICE_YPOS); break; + case 3: strcat(out,GAMEDEVICE_YNEG); break; + case 4: strcat(out,GAMEDEVICE_POVLEFT); break; + case 5: strcat(out,GAMEDEVICE_POVRIGHT); break; + case 6: strcat(out,GAMEDEVICE_POVUP); break; + case 7: strcat(out,GAMEDEVICE_POVDOWN); break; + case 49: strcat(out,GAMEDEVICE_POVDNLEFT); break; + case 50: strcat(out,GAMEDEVICE_POVDNRIGHT); break; + case 51: strcat(out,GAMEDEVICE_POVUPLEFT); break; + case 52: strcat(out,GAMEDEVICE_POVUPRIGHT); break; + case 41: strcat(out,GAMEDEVICE_ZPOS); break; + case 42: strcat(out,GAMEDEVICE_ZNEG); break; + case 43: strcat(out,GAMEDEVICE_RPOS); break; + case 44: strcat(out,GAMEDEVICE_RNEG); break; + case 45: strcat(out,GAMEDEVICE_UPOS); break; + case 46: strcat(out,GAMEDEVICE_UNEG); break; + case 47: strcat(out,GAMEDEVICE_VPOS); break; + case 48: strcat(out,GAMEDEVICE_VNEG); break; + default: + if ((keyz & 0xff) > 40) + { + sprintf(temp,GAMEDEVICE_JOYBUTPREFIX,keyz&0xFF); + strcat(out,temp); + break; + } + + sprintf(temp,GAMEDEVICE_BUTTON,(keyz&0xFF)-8); + strcat(out,temp); + break; + + } + return; + } + sprintf(out,GAMEDEVICE_KEY,keyz); + if((keyz>='0' && keyz<='9')||(keyz>='A' &&keyz<='Z')) + { + sprintf(out,"%c",keyz); + return; + } + + if( keyz >= VK_NUMPAD0 && keyz <= VK_NUMPAD9) + { + + sprintf(out,GAMEDEVICE_NUMPADPREFIX,'0'+(keyz-VK_NUMPAD0)); + + return ; + } + switch(keyz) + { + case 0: sprintf(out,GAMEDEVICE_DISABLED); break; + case VK_TAB: sprintf(out,GAMEDEVICE_VK_TAB); break; + case VK_BACK: sprintf(out,GAMEDEVICE_VK_BACK); break; + case VK_CLEAR: sprintf(out,GAMEDEVICE_VK_CLEAR); break; + case VK_RETURN: sprintf(out,GAMEDEVICE_VK_RETURN); break; + case VK_LSHIFT: sprintf(out,GAMEDEVICE_VK_LSHIFT); break; + case VK_RSHIFT: sprintf(out,GAMEDEVICE_VK_RSHIFT); break; + case VK_LCONTROL: sprintf(out,GAMEDEVICE_VK_LCONTROL); break; + case VK_RCONTROL: sprintf(out,GAMEDEVICE_VK_RCONTROL); break; + case VK_LMENU: sprintf(out,GAMEDEVICE_VK_LMENU); break; + case VK_RMENU: sprintf(out,GAMEDEVICE_VK_RMENU); break; + case VK_PAUSE: sprintf(out,GAMEDEVICE_VK_PAUSE); break; + case VK_CANCEL: sprintf(out,GAMEDEVICE_VK_PAUSE); break; // the Pause key can resolve to either "Pause" or "Cancel" depending on when it's pressed + case VK_CAPITAL: sprintf(out,GAMEDEVICE_VK_CAPITAL); break; + case VK_ESCAPE: sprintf(out,GAMEDEVICE_VK_ESCAPE); break; + case VK_SPACE: sprintf(out,GAMEDEVICE_VK_SPACE); break; + case VK_PRIOR: sprintf(out,GAMEDEVICE_VK_PRIOR); break; + case VK_NEXT: sprintf(out,GAMEDEVICE_VK_NEXT); break; + case VK_HOME: sprintf(out,GAMEDEVICE_VK_HOME); break; + case VK_END: sprintf(out,GAMEDEVICE_VK_END); break; + case VK_LEFT: sprintf(out,GAMEDEVICE_VK_LEFT ); break; + case VK_RIGHT: sprintf(out,GAMEDEVICE_VK_RIGHT); break; + case VK_UP: sprintf(out,GAMEDEVICE_VK_UP); break; + case VK_DOWN: sprintf(out,GAMEDEVICE_VK_DOWN); break; + case VK_SELECT: sprintf(out,GAMEDEVICE_VK_SELECT); break; + case VK_PRINT: sprintf(out,GAMEDEVICE_VK_PRINT); break; + case VK_EXECUTE: sprintf(out,GAMEDEVICE_VK_EXECUTE); break; + case VK_SNAPSHOT: sprintf(out,GAMEDEVICE_VK_SNAPSHOT); break; + case VK_INSERT: sprintf(out,GAMEDEVICE_VK_INSERT); break; + case VK_DELETE: sprintf(out,GAMEDEVICE_VK_DELETE); break; + case VK_HELP: sprintf(out,GAMEDEVICE_VK_HELP); break; + case VK_LWIN: sprintf(out,GAMEDEVICE_VK_LWIN); break; + case VK_RWIN: sprintf(out,GAMEDEVICE_VK_RWIN); break; + case VK_APPS: sprintf(out,GAMEDEVICE_VK_APPS); break; + case VK_MULTIPLY: sprintf(out,GAMEDEVICE_VK_MULTIPLY); break; + case VK_ADD: sprintf(out,GAMEDEVICE_VK_ADD); break; + case VK_SEPARATOR: sprintf(out,GAMEDEVICE_VK_SEPARATOR); break; + case /*VK_OEM_1*/0xBA: sprintf(out,GAMEDEVICE_VK_OEM_1); break; + case /*VK_OEM_2*/0xBF: sprintf(out,GAMEDEVICE_VK_OEM_2); break; + case /*VK_OEM_3*/0xC0: sprintf(out,GAMEDEVICE_VK_OEM_3); break; + case /*VK_OEM_4*/0xDB: sprintf(out,GAMEDEVICE_VK_OEM_4); break; + case /*VK_OEM_5*/0xDC: sprintf(out,GAMEDEVICE_VK_OEM_5); break; + case /*VK_OEM_6*/0xDD: sprintf(out,GAMEDEVICE_VK_OEM_6); break; + case /*VK_OEM_7*/0xDE: sprintf(out,GAMEDEVICE_VK_OEM_7); break; + case /*VK_OEM_COMMA*/0xBC: sprintf(out,GAMEDEVICE_VK_OEM_COMMA );break; + case /*VK_OEM_PERIOD*/0xBE: sprintf(out,GAMEDEVICE_VK_OEM_PERIOD);break; + case VK_SUBTRACT: sprintf(out,GAMEDEVICE_VK_SUBTRACT); break; + case VK_DECIMAL: sprintf(out,GAMEDEVICE_VK_DECIMAL); break; + case VK_DIVIDE: sprintf(out,GAMEDEVICE_VK_DIVIDE); break; + case VK_NUMLOCK: sprintf(out,GAMEDEVICE_VK_NUMLOCK); break; + case VK_SCROLL: sprintf(out,GAMEDEVICE_VK_SCROLL); break; + case /*VK_OEM_MINUS*/0xBD: sprintf(out,GAMEDEVICE_VK_OEM_MINUS); break; + case /*VK_OEM_PLUS*/0xBB: sprintf(out,GAMEDEVICE_VK_OEM_PLUS); break; + case VK_SHIFT: sprintf(out,GAMEDEVICE_VK_SHIFT); break; + case VK_CONTROL: sprintf(out,GAMEDEVICE_VK_CONTROL); break; + case VK_MENU: sprintf(out,GAMEDEVICE_VK_MENU); break; + case VK_F1: sprintf(out,GAMEDEVICE_VK_F1); break; + case VK_F2: sprintf(out,GAMEDEVICE_VK_F2); break; + case VK_F3: sprintf(out,GAMEDEVICE_VK_F3); break; + case VK_F4: sprintf(out,GAMEDEVICE_VK_F4); break; + case VK_F5: sprintf(out,GAMEDEVICE_VK_F5); break; + case VK_F6: sprintf(out,GAMEDEVICE_VK_F6); break; + case VK_F7: sprintf(out,GAMEDEVICE_VK_F7); break; + case VK_F8: sprintf(out,GAMEDEVICE_VK_F8); break; + case VK_F9: sprintf(out,GAMEDEVICE_VK_F9); break; + case VK_F10: sprintf(out,GAMEDEVICE_VK_F10); break; + case VK_F11: sprintf(out,GAMEDEVICE_VK_F11); break; + case VK_F12: sprintf(out,GAMEDEVICE_VK_F12); break; + } + + return ; + + + +} + +bool IsReserved (WORD Key, int modifiers) +{ + // keys that do other stuff in Windows + if(Key == VK_CAPITAL || Key == VK_NUMLOCK || Key == VK_SCROLL || Key == VK_SNAPSHOT + || Key == VK_LWIN || Key == VK_RWIN || Key == VK_APPS || Key == /*VK_SLEEP*/0x5F + || (Key == VK_F4 && (modifiers & CUSTKEY_ALT_MASK) != 0)) // alt-f4 (behaves unlike accelerators) + return true; + + // menu shortcuts (accelerators) -- TODO: should somehow parse GUI.Accelerators for this information + if(modifiers == CUSTKEY_CTRL_MASK + && (Key == 'O') + || modifiers == CUSTKEY_ALT_MASK + && (Key == VK_F5 || Key == VK_F7 || Key == VK_F8 || Key == VK_F9 + || Key == 'R' || Key == 'T' || Key == /*VK_OEM_4*/0xDB || Key == /*VK_OEM_6*/0xDD + || Key == 'E' || Key == 'A' || Key == VK_RETURN || Key == VK_DELETE)) + return true; + + return false; +} + +int GetNumHotKeysAssignedTo (WORD Key, int modifiers) +{ + int count = 0; + { + #define MATCHES_KEY(k) \ + (modifiers == CustomKeys.k.modifiers \ + && Key != 0 && Key != VK_ESCAPE \ + && (Key == CustomKeys.k.key \ + || (Key == VK_SHIFT && (CustomKeys.k.modifiers & CUSTKEY_SHIFT_MASK) != 0) \ + || (Key == VK_MENU && (CustomKeys.k.modifiers & CUSTKEY_ALT_MASK) != 0) \ + || (Key == VK_CONTROL && (CustomKeys.k.modifiers & CUSTKEY_CTRL_MASK) != 0) \ + || (CustomKeys.k.key == VK_SHIFT) \ + || (CustomKeys.k.key == VK_MENU) \ + || (CustomKeys.k.key == VK_CONTROL))) + + if(MATCHES_KEY(SpeedUp)) count++; + if(MATCHES_KEY(SpeedDown)) count++; + if(MATCHES_KEY(Pause)) count++; + if(MATCHES_KEY(FrameAdvance)) count++; + if(MATCHES_KEY(SkipUp)) count++; + if(MATCHES_KEY(SkipDown)) count++; + if(MATCHES_KEY(ScopeTurbo)) count++; + if(MATCHES_KEY(ScopePause)) count++; + if(MATCHES_KEY(FrameCount)) count++; + if(MATCHES_KEY(ReadOnly)) count++; + for(int i = 0 ; i < 10 ; i++) { + if(MATCHES_KEY(Save[i])) count++; + if(MATCHES_KEY(Load[i])) count++; + if(MATCHES_KEY(SelectSave[i])) count++; + } + if(MATCHES_KEY(FastForward)) count++; + if(MATCHES_KEY(ShowPressed)) count++; + if(MATCHES_KEY(SaveScreenShot)) count++; + if(MATCHES_KEY(SlotPlus)) count++; + if(MATCHES_KEY(SlotMinus)) count++; + if(MATCHES_KEY(SlotSave)) count++; + if(MATCHES_KEY(SlotLoad)) count++; + if(MATCHES_KEY(BGL1)) count++; + if(MATCHES_KEY(BGL2)) count++; + if(MATCHES_KEY(BGL3)) count++; + if(MATCHES_KEY(BGL4)) count++; + if(MATCHES_KEY(BGL5)) count++; + if(MATCHES_KEY(ClippingWindows)) count++; +// if(MATCHES_KEY(BGLHack)) count++; + if(MATCHES_KEY(Transparency)) count++; + if(MATCHES_KEY(GLCube)) count++; +// if(MATCHES_KEY(InterpMode7)) count++; + if(MATCHES_KEY(JoypadSwap)) count++; + if(MATCHES_KEY(SwitchControllers)) count++; + if(MATCHES_KEY(TurboA)) count++; + if(MATCHES_KEY(TurboB)) count++; + if(MATCHES_KEY(TurboY)) count++; + if(MATCHES_KEY(TurboX)) count++; + if(MATCHES_KEY(TurboL)) count++; + if(MATCHES_KEY(TurboR)) count++; + if(MATCHES_KEY(TurboStart)) count++; + if(MATCHES_KEY(TurboSelect)) count++; + if(MATCHES_KEY(TurboLeft)) count++; + if(MATCHES_KEY(TurboUp)) count++; + if(MATCHES_KEY(TurboRight)) count++; + if(MATCHES_KEY(TurboDown)) count++; + if(MATCHES_KEY(ResetGame)) count++; + if(MATCHES_KEY(ToggleCheats)) count++; + + #undef MATCHES_KEY + } + return count; +} + +int GetNumButtonsAssignedTo (WORD Key) +{ + int count = 0; + for(int J = 0; J < 5*2; J++) + { + // don't want to report conflicts with disabled keys + if(!Joypad[J%5].Enabled || Key == 0 || Key == VK_ESCAPE) + continue; + + if(Key == Joypad[J].Left) count++; + if(Key == Joypad[J].Right) count++; + if(Key == Joypad[J].Left_Up) count++; + if(Key == Joypad[J].Left_Down) count++; + if(Key == Joypad[J].Right_Up) count++; + if(Key == Joypad[J].Right_Down) count++; + if(Key == Joypad[J].Up) count++; + if(Key == Joypad[J].Down) count++; + if(Key == Joypad[J].Start) count++; + if(Key == Joypad[J].Select) count++; + if(Key == Joypad[J].A) count++; + if(Key == Joypad[J].B) count++; + if(Key == Joypad[J].X) count++; + if(Key == Joypad[J].Y) count++; + if(Key == Joypad[J].L) count++; + if(Key == Joypad[J].R) count++; + } + return count; +} + +COLORREF CheckButtonKey( WORD Key) +{ + COLORREF red,magenta,blue,white; + red =RGB(255,0,0); + magenta =RGB(255,0,255); + blue = RGB(0,0,255); + white = RGB(255,255,255); + + // Check for conflict with reserved windows keys + if(IsReserved(Key,0)) + return red; + + // Check for conflict with Snes9X hotkeys + if(GetNumHotKeysAssignedTo(Key,0) > 0) + return magenta; + + // Check for duplicate button keys + if(GetNumButtonsAssignedTo(Key) > 1) + return blue; + + return white; +} + +COLORREF CheckHotKey( WORD Key, int modifiers) +{ + COLORREF red,magenta,blue,white; + red =RGB(255,0,0); + magenta =RGB(255,0,255); + blue = RGB(0,0,255); + white = RGB(255,255,255); + + // Check for conflict with reserved windows keys + if(IsReserved(Key,modifiers)) + return red; + + // Check for conflict with button keys + if(modifiers == 0 && GetNumButtonsAssignedTo(Key) > 0) + return magenta; + + // Check for duplicate Snes9X hotkeys + if(GetNumHotKeysAssignedTo(Key,modifiers) > 1) + return blue; + + return white; +} + +void InitInputCustomControl() +{ + + WNDCLASSEX wc; + + wc.cbSize = sizeof(wc); + wc.lpszClassName = szClassName; + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = InputCustomWndProc; + wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.hIcon = 0; + wc.lpszMenuName = 0; + wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_BTNFACE); + wc.style = 0; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(InputCust *); + wc.hIconSm = 0; + + + RegisterClassEx(&wc); + +} +void InitKeyCustomControl() +{ + + WNDCLASSEX wc; + + wc.cbSize = sizeof(wc); + wc.lpszClassName = szHotkeysClassName; + wc.hInstance = GetModuleHandle(0); + wc.lpfnWndProc = HotInputCustomWndProc; + wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.hIcon = 0; + wc.lpszMenuName = 0; + wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_BTNFACE); + wc.style = 0; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(InputCust *); + wc.hIconSm = 0; + + + RegisterClassEx(&wc); + +} +HWND CreateInputCustom(HWND hwndParent) +{ + HWND hwndCtrl; + + hwndCtrl = CreateWindowEx( + WS_EX_CLIENTEDGE, // give it a standard border + szClassName, + _T("A custom control"), + WS_VISIBLE | WS_CHILD, + 0, 0, 100, 100, + hwndParent, + NULL, GetModuleHandle(0), NULL + ); + + return hwndCtrl; +} +InputCust * GetInputCustom(HWND hwnd) +{ + return (InputCust *)GetWindowLong(hwnd, 0); +} + +void SetInputCustom(HWND hwnd, InputCust *icp) +{ + SetWindowLong(hwnd, 0, (LONG)icp); +} + +LRESULT InputCustom_OnPaint(InputCust *ccp, WPARAM wParam, LPARAM lParam) +{ + HDC hdc; + PAINTSTRUCT ps; + HANDLE hOldFont; + TCHAR szText[200]; + RECT rect; + SIZE sz; + int x,y; + + // Get a device context for this window + hdc = BeginPaint(ccp->hwnd, &ps); + + // Set the font we are going to use + hOldFont = SelectObject(hdc, ccp->hFont); + + // Set the text colours + SetTextColor(hdc, ccp->crForeGnd); + SetBkColor (hdc, ccp->crBackGnd); + + // Find the text to draw + GetWindowText(ccp->hwnd, szText, sizeof(szText)); + + // Work out where to draw + GetClientRect(ccp->hwnd, &rect); + + + // Find out how big the text will be + GetTextExtentPoint32(hdc, szText, lstrlen(szText), &sz); + + // Center the text + x = (rect.right - sz.cx) / 2; + y = (rect.bottom - sz.cy) / 2; + + // Draw the text + ExtTextOut(hdc, x, y, ETO_OPAQUE, &rect, szText, lstrlen(szText), 0); + + // Restore the old font when we have finished + SelectObject(hdc, hOldFont); + + // Release the device context + EndPaint(ccp->hwnd, &ps); + + return 0; +} + +static LRESULT CALLBACK InputCustomWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + // retrieve the custom structure POINTER for THIS window + InputCust *icp = GetInputCustom(hwnd); + HWND pappy = (HWND__ *)GetWindowLongPtr(hwnd,GWL_HWNDPARENT); + funky= hwnd; + + static HWND selectedItem = NULL; + + char temp[100]; + COLORREF col; + switch(msg) + { + + case WM_GETDLGCODE: + return DLGC_WANTARROWS|DLGC_WANTALLKEYS|DLGC_WANTCHARS; + break; + + + case WM_NCCREATE: + + // Allocate a new CustCtrl structure for this window. + icp = (InputCust *) malloc( sizeof(InputCust) ); + + // Failed to allocate, stop window creation. + if(icp == NULL) return FALSE; + + // Initialize the CustCtrl structure. + icp->hwnd = hwnd; + icp->crForeGnd = GetSysColor(COLOR_WINDOWTEXT); + icp->crBackGnd = GetSysColor(COLOR_WINDOW); + icp->hFont = (HFONT__ *) GetStockObject(DEFAULT_GUI_FONT); + + // Assign the window text specified in the call to CreateWindow. + SetWindowText(hwnd, ((CREATESTRUCT *)lParam)->lpszName); + + // Attach custom structure to this window. + SetInputCustom(hwnd, icp); + + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + + selectedItem = NULL; + + SetTimer(hwnd,777,125,NULL); + + // Continue with window creation. + return TRUE; + + // Clean up when the window is destroyed. + case WM_NCDESTROY: + free(icp); + break; + case WM_PAINT: + return InputCustom_OnPaint(icp,wParam,lParam); + break; + case WM_ERASEBKGND: + return 1; + case WM_USER+45: + case WM_KEYDOWN: + TranslateKey(wParam,temp); + col = CheckButtonKey(wParam); + + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + SetWindowText(hwnd,temp); + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + SendMessage(pappy,WM_USER+43,wParam,(LPARAM)hwnd); + + break; + case WM_USER+44: + + TranslateKey(wParam,temp); + if(IsWindowEnabled(hwnd)) + { + col = CheckButtonKey(wParam); + } + else + { + col = RGB( 192,192,192); + } + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + SetWindowText(hwnd,temp); + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + + break; + + case WM_SETFOCUS: + { + selectedItem = hwnd; + col = RGB( 0,255,0); + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); +// tid = wParam; + + break; + } + case WM_KILLFOCUS: + { + selectedItem = NULL; + SendMessage(pappy,WM_USER+46,wParam,(LPARAM)hwnd); // refresh fields on deselect + break; + } + + case WM_TIMER: + if(hwnd == selectedItem) + { + FunkyJoyStickTimer(); + } + SetTimer(hwnd,777,125,NULL); + break; + case WM_LBUTTONDOWN: + SetFocus(hwnd); + break; + case WM_ENABLE: + COLORREF col; + if(wParam) + { + col = RGB( 255,255,255); + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + } + else + { + col = RGB( 192,192,192); + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + } + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + return true; + default: + break; + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +static void TranslateKeyWithModifiers(int wParam, int modifiers, char * outStr) +{ + + // if the key itself is a modifier, special case output: + if(wParam == VK_SHIFT) + strcpy(outStr, "Shift"); + else if(wParam == VK_MENU) + strcpy(outStr, "Alt"); + else if(wParam == VK_CONTROL) + strcpy(outStr, "Control"); + else + { + // otherwise, prepend the modifier(s) + if(wParam != VK_ESCAPE && wParam != 0) + { + if((modifiers & CUSTKEY_CTRL_MASK) != 0) + { + sprintf(outStr,HOTKEYS_CONTROL_MOD); + outStr += strlen(HOTKEYS_CONTROL_MOD); + } + if((modifiers & CUSTKEY_ALT_MASK) != 0) + { + sprintf(outStr,HOTKEYS_ALT_MOD); + outStr += strlen(HOTKEYS_ALT_MOD); + } + if((modifiers & CUSTKEY_SHIFT_MASK) != 0) + { + sprintf(outStr,HOTKEYS_SHIFT_MOD); + outStr += strlen(HOTKEYS_SHIFT_MOD); + } + } + + // and append the translated non-modifier key + TranslateKey(wParam,outStr); + } +} + +static bool keyPressLock = false; + +static LRESULT CALLBACK HotInputCustomWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + // retrieve the custom structure POINTER for THIS window + InputCust *icp = GetInputCustom(hwnd); + HWND pappy = (HWND__ *)GetWindowLongPtr(hwnd,GWL_HWNDPARENT); + funky= hwnd; + + static HWND selectedItem = NULL; + + char temp[100]; + COLORREF col; + switch(msg) + { + + case WM_GETDLGCODE: + return DLGC_WANTARROWS|DLGC_WANTALLKEYS|DLGC_WANTCHARS; + break; + + + case WM_NCCREATE: + + // Allocate a new CustCtrl structure for this window. + icp = (InputCust *) malloc( sizeof(InputCust) ); + + // Failed to allocate, stop window creation. + if(icp == NULL) return FALSE; + + // Initialize the CustCtrl structure. + icp->hwnd = hwnd; + icp->crForeGnd = GetSysColor(COLOR_WINDOWTEXT); + icp->crBackGnd = GetSysColor(COLOR_WINDOW); + icp->hFont = (HFONT__ *) GetStockObject(DEFAULT_GUI_FONT); + + // Assign the window text specified in the call to CreateWindow. + SetWindowText(hwnd, ((CREATESTRUCT *)lParam)->lpszName); + + // Attach custom structure to this window. + SetInputCustom(hwnd, icp); + + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + + keyPressLock = false; + + selectedItem = NULL; + + SetTimer(hwnd,747,125,NULL); + + // Continue with window creation. + return TRUE; + + // Clean up when the window is destroyed. + case WM_NCDESTROY: + free(icp); + break; + case WM_PAINT: + return InputCustom_OnPaint(icp,wParam,lParam); + break; + case WM_ERASEBKGND: + return 1; +/* + case WM_KEYUP: + { + int count = 0; + for(int i=0;i<256;i++) + if(GetAsyncKeyState(i)) + count++; + + if(count < 2) + { + int p = count; + } + if(count < 1) + { + int p = count; + } + + TranslateKey(wParam,temp); + col = CheckButtonKey(wParam); + + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + SetWindowText(hwnd,temp); + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + SendMessage(pappy,WM_USER+43,wParam,(LPARAM)hwnd); + } + break; +*/ + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + + { + int count = 0; + for(int i=2;i<256;i++) + { + if(i >= VK_LSHIFT && i <= VK_RMENU) + continue; + if(GetAsyncKeyState(i)) + count++; + } + + if(count <= 1) + { + keyPressLock = false; + } + } + + // no break + + case WM_USER+45: + // assign a hotkey: + { + // don't assign pure modifiers on key-down (they're assigned on key-up) + if(wParam == VK_SHIFT || wParam == VK_MENU || wParam == VK_CONTROL) + break; + + int modifiers = 0; + if(GetAsyncKeyState(VK_MENU)) + modifiers |= CUSTKEY_ALT_MASK; + if(GetAsyncKeyState(VK_CONTROL)) + modifiers |= CUSTKEY_CTRL_MASK; + if(GetAsyncKeyState(VK_SHIFT)) + modifiers |= CUSTKEY_SHIFT_MASK; + + TranslateKeyWithModifiers(wParam, modifiers, temp); + + col = CheckHotKey(wParam,modifiers); +/// if(col == RGB(255,0,0)) // un-redify +/// col = RGB(255,255,255); + + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + SetWindowText(hwnd,temp); + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + SendMessage(pappy,WM_USER+43,wParam,(LPARAM)hwnd); + + keyPressLock = true; + + } + break; + case WM_SYSKEYUP: + case WM_KEYUP: + if(!keyPressLock) + { + int count = 0; + for(int i=2;i<256;i++) + { + if(i >= VK_LSHIFT && i <= VK_RMENU) + continue; + if(GetAsyncKeyState(i)) + count++; + } + + if(count <= 1) + { + if(wParam == VK_SHIFT || wParam == VK_MENU || wParam == VK_CONTROL) + { + if(wParam == VK_SHIFT) + sprintf(temp, "Shift"); + if(wParam == VK_MENU) + sprintf(temp, "Alt"); + if(wParam == VK_CONTROL) + sprintf(temp, "Control"); + + col = CheckHotKey(wParam,0); + + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + SetWindowText(hwnd,temp); + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + SendMessage(pappy,WM_USER+43,wParam,(LPARAM)hwnd); + } + } + } + break; + case WM_USER+44: + + // set a hotkey field: + { + int modifiers = lParam; + + TranslateKeyWithModifiers(wParam, modifiers, temp); + + if(IsWindowEnabled(hwnd)) + { + col = CheckHotKey(wParam,modifiers); +/// if(col == RGB(255,0,0)) // un-redify +/// col = RGB(255,255,255); + } + else + { + col = RGB( 192,192,192); + } + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + SetWindowText(hwnd,temp); + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + } + break; + + case WM_SETFOCUS: + { + selectedItem = hwnd; + col = RGB( 0,255,0); + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); +// tid = wParam; + + break; + } + case WM_KILLFOCUS: + { + selectedItem = NULL; + SendMessage(pappy,WM_USER+46,wParam,(LPARAM)hwnd); // refresh fields on deselect + break; + } + + case WM_TIMER: + if(hwnd == selectedItem) + { + FunkyJoyStickTimer(); + } + SetTimer(hwnd,747,125,NULL); + break; + case WM_LBUTTONDOWN: + SetFocus(hwnd); + break; + case WM_ENABLE: + COLORREF col; + if(wParam) + { + col = RGB( 255,255,255); + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + } + else + { + col = RGB( 192,192,192); + icp->crForeGnd = ((~col) & 0x00ffffff); + icp->crBackGnd = col; + } + InvalidateRect(icp->hwnd, NULL, FALSE); + UpdateWindow(icp->hwnd); + return true; + default: + break; + } + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + diff --git a/win32/InputCustom.h b/win32/InputCustom.h new file mode 100644 index 00000000..3698f3eb --- /dev/null +++ b/win32/InputCustom.h @@ -0,0 +1,208 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 CUSTCTRL_INCLUDED +#define CUSTCTRL_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +void InitInputCustomControl(void); +HWND CreateInputCustom(HWND hwndParent); +void InitKeyCustomControl(void); +HWND CreateKeyCustom(HWND hwndParent); + +typedef struct +{ + COLORREF crForeGnd; // Foreground text colour + COLORREF crBackGnd; // Background text colour + HFONT hFont; // The font + HWND hwnd; // The control's window handle +} InputCust; +COLORREF CheckButtonKey( WORD Key); +COLORREF CheckHotKey( WORD Key, int modifiers); +InputCust * GetInputCustom(HWND hwnd); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/win32/Valid.Ext b/win32/Valid.Ext new file mode 100644 index 00000000..60d3cd9b --- /dev/null +++ b/win32/Valid.Ext @@ -0,0 +1,24 @@ +N +smcN +zipY +gzY +swcN +figN +058N +078N +japN +usaN +048N +eurN +sfcN +1N +mgdN +ufoN +binN +gd3N +mghN +gd7N +ausN +dx2N +aN +jmaY \ No newline at end of file diff --git a/win32/docs/faqs-windows.txt b/win32/docs/faqs-windows.txt new file mode 100644 index 00000000..5991a7b9 --- /dev/null +++ b/win32/docs/faqs-windows.txt @@ -0,0 +1,260 @@ +FAQ for Windows Port + + +Wassail, +This is the much anticipated and highly informative Frequently Asked Questions +article, which contains, believe it or not, Frequently Asked Questions! This +time around we have also included Frequently Answered Answers! I shall be your +host on this gleeful sojourn through a text document where anything can, but +probably won't, happen. On our first section of this mystical journey you shall +see various frequently asked questions, as well as their answers! + +The majority of the things in this FAQ are based off the Windows port of Snes9x. +While some of the information is relevant to most, or all, ports, no gaurantees +are made that what is said will be accurate for all versions. + +-------------------------------------------------------------------------------- + +Chapter 1: + +Emulator Specific Questions + Or + It's Not The Size Of An Emulator That Counts; It's How You Use It. + +Q: When is the next version (of Snes9x) coming out? + A: Chances are it will be coming out when enough changes have been made to +suitably make a release. You can generally guesstimate the release date by +paying attention to the Developers forum at snes9x.com. But don't ask them when +the next release will be. + +Q: Why do my games run too fast? + A: Through proper nutrition and training an increase in abilities is often +found. It is possible that certain ROMs, whilst training for the annual Rohm +race, surpassed a sane limit. Generally not allowing them to run will cause +atrophy, making them somewhat slower. Seriously though, try using the + and/or - +keys to adjust the emulated speed. If that doesn't do anything, try holding down +Shift and pressing the - key a bunch of times first. In the display settings +make sure the "Use Frame Limiter" and "Automatic Frame Skipping" boxes are +checked. Also try pressing Tab and make sure your Tab key isn't stuck down. + +Q: Why doesn't Snes9x support transparencies? + A: It does! Make sure the "Transparency" box is checked in the settings menu. + +Q: I recently purchased a gamepad controller. Will it work on Snes9x? + A: More than likely yes. Any USB compatable controller will work. Generally +this means any controller made within the past 7 years or so. If you are having +problems consider updating drivers and recalibrating your controller. + +Q: In Snes9x my gamepad is having trouble inputting any diagonal directions on +the D-Pad. How can I fix this? + A: While setting up your controller functions in Snes9x, make sure you do not +setup the diagonal buttons; leave them blank. Ye olde Snes only had 4 buttons on +the D-Pad: Up, down, left and right. By pressing two directions you would go in +the appropriate diagonal direction (game specific, of course). If you have +accidently set a value in the diagonal boxes already either select them one at a +time and hit "Escape", or press the "Toggle Diagonals" button. + +Q: Soooooo... Why the heck do you have diagonals in the controller setup anyway? + A: Simple really. Some people enjoy using the keyboard, or have no other +choice. In the next chapter the topic of keyboard input limitations will be +addressed. Being able to input the diagonals can help hinder that occurrence. It +can also make keyboard usage a bit easier... assigning the directional controls +to the number pad for instance. + +Q: I gotsid me a translation patch (.ips) for my game. Now what do I do so I can +use it? + A: Make sure both your ROM image and .ips file are in the same folder. Finally +make sure they have the exact same name (minus file extensions, of course). As +an example "Pie.smc" should have "Pie.ips" and "Super_Pie3(E).smc" should have +"Super_Pie3(E).ips". Now open up Snes9x, load your ROM and voila! It should be +noted that IPS patches are almost always designed for use with a specific dump +of a ROM. If you are positive you are using it correctly, but it still does not +work, consider trying a ROM from a different source. + +Q: I think my options in Snes9x got screwed up, how do I reset them? + A: Snes9x uses a config file, so you can edit your options there in any text +editor if you're having problems. You can safely delete your config file (called +snes9x.conf) to reset all of the options. If it doesn't let you delete or change +it, make sure to close Snes9x first. + +Q: I had a bad checksummed game that didn't work so I adjusted the header, but +it still doesn't work :( Why? + A: It should be noted that while it is possible to plop a ROM into Snestool, +or several other programs, and adjust the header size to be the same as a proper +"good checksum" ROM, this merely mimics the appearance of a good ROM. Any +problems still found within its evil will remain. One could compare it to +covering up a circumorbital haematoma with a paper bag. + +-------------------------------------------------------------------------------- + +Chapter 2: + +Game Specific Questions + Or + How I Learned To Stop Worrying And Love The ROM + +Q: Why doesn't game X work? + A: There are four possible answers to this question, depending on the +scenario. Answer one is that it does work, but your ROM dump is incorrect (this +MAY be fixed by reattaching your cartridge to your copier and redumping). Answer +two is that we have found a solution or a hack to the problem, but have not yet +implemented a fix. Answer three, a subsidiary of answer two, is that we do NOT +know what is wrong with it, and as such have not yet implemented a fix. Answer +four is that Snes9x CANNOT emulate the game correctly due to its poor +implementation around timings between emulated units. + +Q: Why doesn't Snes9x display SD3/Secret of Mana/other hi-res games properly? + A: Some games had resolution changes at certain parts during the game that +affect the pixel size of what is shown on screen. Due to the way this is handled +some games require specific options to keep "right". First, make sure that +Hi-res support is selected in the option menus, that option can slow down +performance on slower machines, although it is now on by default. Second, it is +recommended your filter option is set to anything except "none." "Simple 2X" is +a good choice. Note: In the event the "Hi-res" option is greyed out, make sure +your display resolution is at least 512 x 480. + +Q: Why can't I press many buttons at once? Especially in Chrono Trigger. + A: Most standard keyboards (There are a few exceptions, though only a few) can +only output so much data to the compter at a time. As such your computer is +often unable to carry-out the instructions you have given it. There are +solutions abound, of course, and here they are now: Lovely recommendation one is +to rearrange the keymapping in Snes9x so that all the necessary buttons are on a +single keystroke... That way you can press 1 key and have it do all the actions. +The draw back to this is that if you set "a" to jump and shoot you will be +unable to jump without shooting, or shoot without jumping, until you change it +back. The super sexy recommendation number 2 is to set the ctrl and alt keys to +some of the necessary buttons. The draw back to this is that often these buttons +can cause problems if used in tandum with other keys, due to Windows shortcuts. +You may, for instance, be using alt to jump and while in midair hit f4 to load a +savestate... That will close the program, which is bad. Finally, and the method +I personally recommend, is to purchase a gamepad. The draw backs to this are +that it requires time and money. + +-------------------------------------------------------------------------------- + +Chapter 3: +All About Netplay + Or + More Slow Than A Quadriplegic Ninja Turtle, But Only Half As Entertaining + +Q: Snes9x netplay sucks, can I make it better? + A: Yes, yes you can! Snes9x is open source so all you need to make netplay +better is advanced programming knowledge and a will to improve upon the Snes9x +code. At present time Snes9x is more for LANplay, best used in a small network +of local computers. I recommend ZSNES (http://www.zsnes.com/) and zbattle +(http://www.zbattle.net/) for your random chaotic netplay needs. + +Q: I am using a Windows port of Snes9x. My friend is using a Mac. Can we +netplay? + A: Yes... Just not with each other. Snes9x, at this time, does not support +cross-platform netplay. + +Q: Yea who don know dat but when i do what do afta y find som1 (now that I have +someone to play with, what do I do?) + A: An excellent... ...question. I couldn't have worded it better myself. +Despite my sarcasm however I must cringe at the fact I can actually understand +it enough to answer. The answer depends on if you are acting as the server/host +or the client. If you are the host you must first find your IP address and give +it to the person you intend to play online with. Next open Snes9x, load the ROM +you wish to netplay, and then from the netplay menu, select "Act as Server." +Then you wait until the client connects... Now, if you are the client, first +receive the IP address from the host, open Snes9x, and open the ROM you wish to +netplay. Select "Connect to Server" from the netplay menu, and fill out the +necessary information. Server address should contain the IP address of the host. +After that is done click "Connect." Assuming both parties have done their role +correctly, a netplay match should soon start. + +Q: How do I chat with my partner during netplay? + A: I personally recommend yelling really loudly, but the telephone is also a +somewhat plausible answer I suppose. Seriously. + +Q: Can I play with more than 2 players? + A: Indeed you can. Basically the same steps to starting a multiplayer game +apply, however there are a few important differences. Obviously the game you +wish to multiplay in must support three or more players. Now then, make sure +that you, as well as everyone intending to play, has selected the "Enable +Multitap 5" option from the input menu. If you don't do this it just won't work. + +-------------------------------------------------------------------------------- + +Chapter 4: +Miscellaneous Questions + Or + Q-Bert Is My Only Friend + +Q: Is it legal? + A: This has been asked time and again, and the answer is yes. Developing, +downloading, or using the emulator, Snes9x, is completely legal. Downloading +games, called ROMS, however is not. If you own the original cartridge of a game, +you are still not entitled to download the ROM image of that game. You may +create a single backup image of your own cartridge via proper hardware, but it +must be YOUR cartridge and is only usable in place of the original... so only +one may be active at any time. Many sites claim that you may legally download +ROMs for up to 24 hours before they must be deleted. This is also wrong; you +can't legally download these for "trial" purposes. You can't download ROMs for +educational purposes either. If you wish to use Super Nintendo Entertainment +System games for educational purposes, contact your closest Nintendo Outlet and +discuss educational programming with them. Finally, a small number of ROMs are +labeled "(PD)". This means public domain, and these games are not under +copyright. As such they are legal to download at your hearts content. These +include programs created by internet users such as yourself for use in Super +Nintendo emulators. As of this time there are no commercial videogames in the +public domain. + +Q: My friend, Tibby, says that you are wrong and that game companies don't care +if you download games! + A: Whilst not actually a question, and more of a statement, I am afraid Tibby +is incorrect. Feel free to peruse the various legal documentation sprawled +throughout the World Wide Web or your local constituency. As for the blatant +generalization that companies do not care; At least one does, and truthfully +many more do as well, as such the statement is obviously a fallacy. For those +who think it is not fair, or shouldn't be the way it is... perhaps not, though +as holders of a copyright it is up to Nintendo to decide how and when their +products are distributed. + +Q: I just purchased your fine program off eBay for $19.89, but my friend says I +can download it for free. Can you guys give me my money back? + A: Okay, this question hasn't actually been asked, however our free +downloadable program does seem to get sold on eBay more often than it should, +which is to say at all. We cannot reimburse anyone who was unlucky enough to be +scammed into purchasing Snes9x, just as McDonalds cannot reimburse you if you +purchased 100 Happy Meals from a random stranger and he gave you a frozen fish. +If you find yourself in this situation... Purchasing Snes9x, not frozen fish... +Please take the time to inform eBay via their heavily disguised investigations +department, and leave any negative feedback that you wish. It would also be +appreciated by the Snes9x team if you could mention where and when this happened +so that we can take measures to stop it from happening again. While the fact we +aren't making money from the program in no way bothers us (It is freeware after +all), that some grubby bastards are does. + +Q: So err, where exactly do I contact y'all, eh? + A: The most convenient way to contact us would be via www.snes9x.com. There is +a forum that is checked at least 12 times a day by regulars, and at least a few +of us can actually give some advice. E-mail is also a possibility, though it is +much slower, and you'll hafta find the e-mail addresses on your own. Be sure to +read the FAQ and Read me before posting, as things already answered many a time +will probably result in random insults or heavy sarcasm. + +-------------------------------------------------------------------------------- + +Chapter 5: +The Conclusion + Or + That Block Of Words And Various Punctuation Symbols At The End Of The Document + That Isn't Totally Dissimilar To Something That May, Or May Not, Be Considered + A Conclusion Given The Contents Held Within The Paragraph(s) It Contains + +I hope you enjoyed this jaunt through the magical land of FAQs. Much has been +said but, obviously, there is still room to grow and expand. Should you feel you +have a question worthy of this vast tome of knowledge please leave it in the +"board feedback" section of the Snes9x Forum. I have been your host and shall +return again next time with an even greater FAQ. + +I would like to take the time to thank the vast plethora of people who have +helped me conjur this machination of goodness. However, in the annals of time I +have probably forgotten many of those who have given me advice, defintions, +technologial information and cookies. It would be unfair to only mention the +small portion of names I remember from an excessivley long and ever-expanding +list. As such, I won't. Toodles. + +Knowledge is power; Learn it well diff --git a/win32/docs/how2compile.txt b/win32/docs/how2compile.txt new file mode 100644 index 00000000..d73c7eb1 --- /dev/null +++ b/win32/docs/how2compile.txt @@ -0,0 +1,45 @@ +Various software and tools are required to compile Snes9x on Windows: + +- Microsoft Visual C++ 7.1 or Microsoft Visual C++ 6.0 SP5 with the + latest Platform SDK, to compile all the C++ source code. + The current official binary is compiled with Visual Studio 2008 + +- A recent DirectX SDK. The official binary is compiled against the June 2008 SDK. + +- nasm(optional). I use version 0.97. Used to assemble the optional ZSNES FX and C4 core + included in Snes9x. Download from www.web-sites.co.uk/nasm + Note: the official binary does not use the asm files. + +- zlib(optional) - The release binaries are built against a static zlib compiled + against VC's multi-threaded C runtime and renamed to zlibmt.lib, to avoid linker conflicts. + removing ZLIB from the preprocessor definitions and zlibmt.lib from the library + listing will disable zip support. + (the zlib directory should reside at win32/../../zlib, i.e. 2 directories up, the + lib file is expected in win32/../../zlib/lib) + +- libpng(optional) - Like zlib, this is a renamed libpng.lib, built against the same + C runtime for the same reasons. Building your own is as simple as changing the runtime + used by libpng's own project files, compiling, renaming the result to libpngmt.lib + HAVE_LIBPNG is the define used to include this code, used for screenshots. + (the libpng directory should reside at win32/../../libpng, i.e. 2 directories up) + +- fmod(optional) - Versions 3.20 and above. Used to provide extra sound output + options that increases hardware compatibility with some PC hardware. + Version 3.33 broke A3D support on some hardware so I reverted back to + version 3.20. However, I'm told 3.40, just released at time of writing, fixes the problem. + Download from www.fmod.org Unpack into a temp folder and copy the API + sub-folder contents into win32/../../fmod. Disable fmod support by removing the + FMOD_SUPPORT from the Preprocessor Definitions text box. + +- fmod ex(optional) - Used to provide extra sound output. Cannot be used at the same time as + normal FMOD support. Disable fmod support by removing the FMODEX_SUPPORT from the Preprocessor + Definitions text box. + +- To compile Snes9x: + Run the MAKEASM.BAT script. nasmw will need to be on your path + for the script to work. Only necessary if you want to compile with ZSNES_C4 or ZSNES_FX + Start up Visual C++. + Load the Snes9x project file. + Select the desired configuration and build. + The Release configuration may build significantly slower than Debug. + Then you can run it. diff --git a/win32/docs/readme-windows.txt b/win32/docs/readme-windows.txt new file mode 100644 index 00000000..04133126 --- /dev/null +++ b/win32/docs/readme-windows.txt @@ -0,0 +1,809 @@ +Snes9x: The Portable Super Nintendo Entertainment System Emulator +================================================================= +Files included in the Snes9x archive: + Snes9x.exe + fmod.dll + readme-windows.txt + faqs-windows.txt + changes.txt + snes9x-license.txt + +version 1.52 January, 2010 +Home page: http://www.snes9x.com/ + + + +Contents +======== + +Introduction +Getting Started +Requirements +Controllers Support +Game Saving +Cheat Support +Movie Support +Netplay Support +Miscellaneous +Compatibility +Problems +Technical Information +Credits + + + +Introduction +============ + +What is Snes9x? +--------------- +Snes9x is a portable, freeware Super Nintendo Entertainment System (SNES) +emulator. It basically allows you to play most games designed for the SNES and +Super Famicom Nintendo game systems on your Mac, Linux, Windows and so on. The +games include some real gems that were only ever released in Japan. + +The original Snes9x project was founded by Gary Henderson and Jerremy Koot as a +collaboration of their earlier attempts at SNES emulation (Snes96 and Snes97.) +Over the years the project has grown and has collected some of the greatest +talent in the emulation community (at least of the SNES variety) some of which +have been listed in the credits section, others have helped but have been loss +in the course of time. + +Why Emulate the SNES? +--------------------- +Well, there are many reasons for this. The main reason is for nostalgic +purposes. In this day and age, it's hard to find an SNES and many good games. +Plus, many of us over the course of time have lost our beloved consoles (may +they R.I.P) but still have our original carts. With no other means to play them, +we turn to emulators. Besides this there are many conveniences of doing this on +the computer instead of dragging out your old system. + +Advantages consist of: +- ability to save in any location of the game, despite how the game was + designed. It's amazingly useful when you don't want to redo the same level + over and over. +- built-in peripherals. This is anything from multi-taps, to super scopes, to + cheat devices. +- ability to rip sprites and music for your own personal use. +- easier to organize and no stacks of cartridges. +- filters can be used to enhance graphics and sounds on old games. + +As with all things there are disadvantages though: +- if you have an ancient computer, you aren't likely to get a playable + experience. +- some games are still unemulated (though this a very tiny minority.) +- the emulator can be difficult for new users to configure. + + + +Getting Started +=============== + +Launch Snes9x using the Windows explorer to locate the directory where you +un-zipped the snes9x.exe and the fmod.dll files and double-click on the +snes9x.exe executable. You could create a shortcut to Snes9x and drag that icon +out onto your desktop. + +Loading Games +------------- +Use the Open option from the File menu to open the ROM load dialog. The dialog +allows you to browse your computer to locate the directory where you have stored +your SNES games. Single-click and then press Load to load and start the game. + +SNES ROM images come in lots of different formats. Snes9x supports zipped ROMs +as long as there is only 1 per zip file. Also Snes9x can open gzip/jma +compressed file. + +Game Color System +----------------- +Snes9x displays the ROM information when a ROM is first loaded. Depending on the +colors used you can tell whether or not a ROM is a good working ROM, or if it's +been altered or is corrupted. + + white the ROM should be a perfect working copy. + green the ROM is mode 1 interleaved. + orange the ROM is mode 2 interleaved. + aqua the ROM is Game Doctor 24M interleaved. + yellow the ROM has probably been altered. Either it's a translation, PD ROM, + hacked, or possibly a bad ROM. It may also be an overdumped ROM. + red the ROM is definitely hacked and that a proper version should be + exist. Some ROM Tools such as NSRT can also fix these ROMs. + +When asking for help on the Snes9x forums, please list the color and CRC32 that +is displayed. This will help to find out what the problem is. + +These colors do NOT signify whether a game will work or not. It is just a means +for reference so we can understand what may or may not be a problem. Most often +the problem with games that don't work it's because they are corrupt or are a +bad dump and should be redumped. + +SNES Joypad Emulation +--------------------- +The default key mapping for joypad 1 is as follows: + + 'up arrow' Up direction + 'down arrow' Down direction + 'left arrow' Left direction + 'right arrow' Right direction + 'V' A button + 'C' B button + 'D' X button + 'X' Y button + 'A' L button + 'S' R button + 'Enter' Select button + 'Space' Start button + + + +Requirements +============ + +System Requirements +------------------- +Windows 98/2000/XP/Vista/7. +DirectX 6.1b or later. +300MHz processor BARE MINIMUM (1GHz+ rec for best settings.) +16MB RAM BARE MINIMUM. +DirectSound capable sound card. + +Certain games use added hardware which will require a faster machine. The specs +listed above is the minimum to use Snes9x in any playable form. It is +recommended that you get a semi-modern machine with a 800MHz CPU if you want +good results. A 1GHz CPU is recommended for those that want a near perfect +experience. + +Software +-------- +You will need access to SNES ROM images in .smc, .sfc, .fig, etc., format +otherwise you will have nothing to run! Some home-brewed ROM images can be +downloaded from http://www.zophar.com/. +Please note, it is illegal in most countries to have commercial ROM images +without also owning the actual SNES ROM cartridges, and even then you may be +liable under various EULAs. + + + +Controllers Support +=================== + +The real SNES has two ports to connect input devices. Usually 1P and 2P SNES +joypads are connected but various devices and adopters can be plugged. + +Multi Player 5 + known as Multi Tap; a five player adapter, allowing up to five people to play + at once on games that supported it. + +SNES Mouse + a 2-button mouse, originally supplied with a paint program. + +Super Scope + a light-gun; it used infrared to provide wireless communication between the + gun and the console unit. + +Justifier + a gun similar to Super Scope, supported with one gun-shooting game. + +Snes9x can emulate those input devices with the keyboard, mouse and gamepad. + +Configuring Keyboard and Gamepad +-------------------------------- +Add support for your gamepad and calibrate it using Windows' applet from the +Windows control panel BEFORE starting Snes9x, then use Joy-pad Configuration +dialog in Snes9x to customize the keyboard/gamepad to SNES joypad mappings. + +The dialog is easy to use: select which SNES joypad you are configuring using +the combo box (#1 to #5). Make sure that you click the 'enabled' box on that +controller or Snes9x won't recognize a controller being plugged in. Click on the +text box next to 'UP' and then press the key on the keyboard or button on your +gamepad that you would like to perform the UP action. The focus will +automatically move on to the 'RIGHT' text box, press the key or gamepad button +that you want to perform the RIGHT action, and so on until you've customized all +the SNES joypad buttons. + +Use of the special diagonal keys should only be used by keyboard users who are +having problems pressing more then one or 2 buttons at a time. First you must +hit 'toggle diagonals' so that you are able to change them. + +Using Input Devices +------------------- +SNES Mouse, Super Scope, Justifier and Multi Player 5 are disabled by default, +but you can enable them like so: + +First, load your game. Then select the optional controller you want enabled from +the Input menu. Or, the controller is selectable by pressing '7' to cycle to it. + +If you use NSRT to add header information to your ROMs, Snes9x will +automatically detect this information and choose the best controller +configuration for you when the game starts up. Incompatible choices will also be +grayed out from the Input menu, but if you really want, they remain selectable +by pressing '7'. + +The default key mapping for input devices is as follows: + + '`' Superscope turbo button. + '~' Superscope pause button. + '7' rotates between Multi Player 5, SNES mouse on port 1, SNES mouse on port + 2, SuperScope and Justifier emulation. (need to enable special + controllers in the menu first) + + + +Game Saving +=========== + +Many SNES games take a very long time to complete from start to finish, so they +allowed your progress to be saved at the predefined places chosen by the game +designers. The game cartridge contains a battery-backed RAM, known as SRAM, and +your save data remain in this SRAM until the battery shutoff. + +Snes9x has two methods for saving games. One is the same as of the real SNES +shown above; emulating SRAM. The SRAM contents are saved into a file (.srm) so +you don't need to be worried about the battery shutoff. The other is more +convenient way than the real SNES; 'freezing' or 'snapshotting' the game. It +means saving the whole game state anywhere you want, beyond the game designers' +intent - ideal for saving your game just before a tricky bit! + +Freeze files and SRAM files are normally written to and read from the folder +called Saves where your snes9x.exe is located, but sometimes this is not +desirable or possible, especially if it’s a CD-ROM, which is of course is +usually read-only! You can change the folder where Snes9x saves and loads freeze +and SRAM files using the Settings Dialog, available from the Options menu. + +Using the SRAM File +------------------- +It's easy enough, just save the game as you do with the real SNES. Snes9x +outputs the contents of the emulated SRAM into a file (.srm) when you load a new +game or quit Snes9x. This file is automatically loaded the next time you play +the game. + +Freezing and Defrosting the Game State +-------------------------------------- +Snes9x provides 9 slots for freezing the whole of your game state. During the +game, press Shift+F1 to F9 to save a game, and just F1 to F9 to load it again +later. + +Real-Time Clock Emulation +------------------------- +Some games have a battery-backed real-time clock (RTC) in their cartridge to +bring a real-time event in the game. Snes9x saves the state of RTC into a file +(.rtc) and also into a freeze file. Note that because it's a 'real-time' clock, +when these files are loaded, the emulated clock is automatically advanced in +reference to your system's time and date. + +Fool-Proof System +----------------- +If you quit the game by error without saving your long-time progress, try to +find '.oops' file in the same folder as freeze files. If it exists, try to load +it. It's a freeze file automatically generated if you don't save anything for a +long time. + + + +Cheat Support +============= + +Cheat codes allow you to cheat at games. They might give you more lives, +infinite health, enable special powers normally only activated when a special +item is found, and etc. Two major formats are well-known: Game Genie and +Pro-Action Reply (PAR). Many existing Game Genie and PAR codes can be found via +Internet. + +Snes9x supports both Game Genie and PAR. Also you can find your own cheat code. +Cheats are saved in .cht files and are automatically loaded the next time a game +with the same filename is loaded. + +Technically, a cheat code consists of two elements; an address in SNES memory +map where you want to overwrite, and a value which is overwritten on the +address. Beware of cheat codes designed for a ROM from a different region +compared to the one you are playing or for a different version of the ROM; the +source of the cheats should tell you which region and for which version of the +game they were designed for. If you use a code designed for a different region +or version of your game, the game might crash or do other weird things because +the cheat address might be different between regions and versions. + +Cheat Code Entry +---------------- +Use the Cheat Code Entry and Editor dialog from the Cheats menu to enter Game +Genie or PAR cheat codes. Type in a Game Genie or PAR code into the 'Enter Cheat +Code' text edit box and press Return key. Be sure to include the '-' when typing +in a Game Genie code. You can then type in an optional short description as a +reminder to yourself of what function the cheat performs. Press Return key again +or click the Add button to add the cheat to the list. + +Note that the Add button remains insensitive while 'Enter Cheat Code' text edit +box is empty or contains an invalid code. The cheat code is always translated +into an address and value pair and displayed in the cheat list as such. + +It is also possible to enter cheats as an address and value pair. Type in the +address into the 'Address' text edit box then type the value into the 'Value' +text edit box. The value is normally entered in decimal, but if you prefix the +value with a '$' or append an 'h' then you can enter the value in hex. + +Double-clicking on an cheat line from the list in the dialog or clicking on the +'En' column toggles an individual cheat on and off. All cheats can be switched +on and off by checking and unchecking the 'Apply cheats' item from the Cheat +menu. + +Selecting a cheat from the list causes its details to be filled into the text +edit boxes in the dialog box; the details can then be edited and the Change +button pressed to commit the edits. Note that the 'Enter Cheat Code' text edit +box always redisplays the cheat code as a Pro-Action Replay code regardless of +whether you originally entered it as a Game Genie or Pro-Action Replay code. + +Selecting a cheat from the list then pressing the Delete button permanently +removes that cheat. + +Cheat Search +------------ +Snes9x also allows new cheats to be found using the Search for New Cheats +dialog, again available from the Cheats menu. The easiest way to describe the +dialog is to walk through an example. + +Let’s give ourselves infinite health and lives on Ocean's Addams Family platform +game: + +Load up the game; keep pressing the start button (Return key by default) to skip +past the title screens until you actually start playing the game. You'll notice +the game starts with 2 health hearts and 5 lives. Remember that information, it +will come in useful later. + +Launch the Cheat Search dialog for the first time; Alt+A is its accelerator. +Press the Reset button just in case you've used the dialog before, leave the +Search Type and Data Size radio boxes at their default values and press OK. + +Play the game for a while until you loose a life by just keep walking into +baddies, when the game restarts and the life counter displays 4, launch the +Cheat Search dialog again but this time press the Search button rather than +Reset. The number of items in the list will reduce, each line shows a memory +location, its current value and its previous value; what we're looking for is +the memory location where the game stores its life counter. + +Look at address line 7E00AC, its current value is 4 and its previous value was +5. Didn't we start with 5 lives? Looks interesting... + +Note that some games store the current life counter as displayed on the screen, +while others store current number of lives minus 1. Looks like Addams Family +stores the actual life count as displayed on the screen. + +Just to make sure you've found the correct location, press OK on the dialog, and +play the game until you loose another life. Launch the Cheat Search dialog again +after the life counter on screen has been updated and press the Search button. +Now there are even fewer items in the list, but 7E00AC is there again, this time +the current value is 3 and the previous value was 4. Looks very much like we've +found the correct location. + +Now that we're happy we've found the correct location, click on the 7E00AC +address line in the list and then press the Add Cheat button. Another dialog, +Cheat Details, will be displayed. Type in a new value of say 5, this will be +number of lives that will be displayed by the lives counter. Don't be greedy; +some games display a junk life counter or might even crash if you enter a value +that's too high; Snes9x keeps the value constant anyway, so even if you do loose +a life and life counter goes down by one, less than 20ms later, Snes9x resets +the counter back to the value you chose! + +If the memory location you add a cheat on proves to be wrong, just go to the +Cheat Code Editor dialog and delete the incorrect entry. + +Now let’s try and find the Addams Family health counter. While two hearts are +displayed on the screen, visit the Cheat Search dialog and press the Reset +button followed by OK. Play the game until you loose a heart by touching a +baddie, then visit the Cheat Search dialog again. + +Press the Search button to update the list with all memory locations that have +gone down in value since the last dialog visit. We're going to have to try and +find the heart memory location now because there were only two hearts to start +with. + +Look at address line 7E00C3, its current value is 1 and its previous value was +2. Scrolling through the list doesn't reveal any other likely memory locations, +so let’s try our luck. Click on the 7E00C3 line, press the Add Cheat button and +type in a new value of say 4 into the dialog that appears and press OK. Press OK +on the Search for New Cheats dialog to return to the game. + +At first sight it looks like 7E00C3 wasn't the correct memory location because +the number of hearts displayed on screen hasn't gone up, but fear not, some +games don't continually update health and life displays until they think they +need to. Crash into another baddie - instead of dying, the number of hearts +displayed jumps up to 4! We've found the correct location after all! + +Now every time you play Addams Family you'll have infinite lives and health. +Have fun finding cheats for other games. + + + +Movie Support +============= + +Movie support allows you to record your actions while playing a game. This can +be used for your own personal playback or to show other people that you can do +something without them having to be around when you did it. + +Recording the Movie +------------------- +Simply click File menu and click on Movie. Click the Record button. Here you can +decide when to start recording. If you want to record from the very start of a +game, click on 'Record from reset.' If you want to start recording from where +you are already in a game, click 'Record from now.' You can also choose which +controllers to record. If you are playing by yourself leave joypad 1 as the only +one selected. The more controllers you choose to record the larger the file size +will be. + +Playing Back the Movie +---------------------- +To play back a movie you recorded, click File menu, Movie, Play and select the +file to play. Make sure the movie was recorded with the same ROM that you have +loaded. + +Re-recording the Movie +---------------------- +If you make a mistake while recording a movie, there is a movie re-record +function. Simply create a freeze file anytime while recording. If you want to +re-record, load the freeze file and it will bring up the message 'movie +re-record'. Loading any freeze file while a movie is playing or recording will +cause this to happen. If you want to watch a video with no chance to +accidentally alter it, check 'Open as read only' when you go to play it. + + + +Netplay Support +=============== + +Netplay support allows up to five players to sit in front of different computers +and simultaneously play the same game, or just watch someone else play a game. +All the computers have to be connected to a network that allows TCP/IP traffic +to flow between them; this includes a local Ethernet-style network, a +direct-cable connection, or, if you're lucky and have short ping times, the +Internet. + +How to Netplay +-------------- +It's currently easier if you use Snes9x in windowed mode while using netplay, +mainly because netplay currently displays status information in the window's +title bar, and it might be necessary to setup a separate chat application so you +can talk to the other players when deciding what game to play next. + +One machine has to act as a server which other players (client sessions) connect +to. The 'master' player, player 1, uses the server machine; the master decides +what game to play. The server machine should be selected to be the fastest +machine on the fastest connection in the group taking part due to the extra +functions it has to perform. + +Load up a game, then select the 'Act as server' option from the Netplay menu to +become a netplay server; the 'network', in whatever form it takes, will need to +be initialized, if necessary, before you do this. Then just wait for other +players to connect... + +Clients connect to the server using the 'Connect to server...' dialog, again +available from the Netplay menu. Type in the IP address or host name of the +machine running the Snes9x server session and press OK. The first remote client +to connect will become player 2, and so on. Start Menu->Run->winipcfg will tell +you your current IP address, but note that many ISPs will allocate you a new IP +address each time you sign in. + +The server will request the client loads up the correct game first before +joining the game. Then the server will either send the client SRAM data and +reset all players' games if the 'Sync Using Reset Game' option is checked, or +send it a freeze file to get the new client in sync with the other player's +progress in a game. + +If the master player loads a different game, the server will request that the +clients load the game. If the master player loads a freeze file, the server will +automatically send that to remote clients. + +Client sessions must be able to keep up with the server at all times - if they +can't, either because the machine is just too slow, or its busy, the games will +get out of sync and it will be impossible to successfully play a multi-player +game... + +...To make sure this doesn't happen, don't move the Snes9x window unnecessarily +and don't use Ctrl+Alt+Del to display the task manager while playing. Also stop +any unnecessary applications and as many background tasks as possible. Even +something as simple as a text editor might periodically write unsaved data to +the disk, stealing CPU time away from Snes9x causing it to skip a frame or delay +a sound effect; not a problem for most games, but the Bomberman series (the best +multi-player games on the SNES) sync the game to sound samples finishing. + + + +Miscellaneous +============= + +Using IPS or UPS Patch +---------------------- +Snes9x automatically patches without overwriting the ROM image. + +- Put the IPS or UPS file into the same folder as the ROM image. +- Rename the name to the same as the ROM image (except extension, it is '.ips' + or '.ups'). +- (IPS only) If you want to use multiple IPS files at a time, set their + extensions to '.000.ips', '.001.ips', ... +- Open and load the ROM image. + +Additional Keyboard Controls +---------------------------- +Snes9x has various functions to play games with fun. The default mapping is as +follows. Go to Input > Customize Hotkeys... to configure these and more. + + 'Pause' pauses or unpauses the emulator. + 'Escape' shows or hides the menu bar. + 'Alt'+'Enter' toggles between full-screen and windowed mode. + 'Ctrl'+'Shift'+'R' resets the game. + 'Shift'+'F1-F9' saves a freeze file into the slot 1-9. + 'F1-F9' loads a freeze file from the slot 1-9. + 'F12' takes a screenshot. + 'Shift'+'Page Down' toggles turbo on the 'A' button. Note: toggles for all + controllers. + 'Shift'+'End' toggles turbo on the 'B' button... + 'Shift'+'Page Up' toggles turbo on the 'X' button... + 'Shift'+'Home' toggles turbo on the 'Y' button... + 'Shift'+'Ins' toggles turbo on the 'L' button... + 'Shift'+'Del' toggles turbo on the 'R' button... + 'Shift'+'[' toggles turbo on the 'Select' button... + 'Shift'+']' toggles turbo on the 'Start' button... + '6' toggles swapping of joypad one and two. + 'Shift'+'=' increases frame rendering skip rate, making the screen + updates more jerky but speeding up the game. + 'Shift'+'-' decreases frame rendering skip rate, making the screen + updates more smoothly, but potentially slowing down the + game. Repeatedly pressing the key will eventually switch + to auto-frame skip rate where the rate is dynamically + adjusted to keep a constant game play speed. + '-' increases emulated frame time by 1ms - slowing down the + game. (auto-frame skip must be on) + '=' decreases emulated frame time by 1ms - speeding up the + game. (auto-frame skip must be on) + '\' pauses the game, or slowly advances gameplay if it's + already paused. To return to normal, press the 'Pause' + key. + 'Tab' turbo mode. + ',' toggles display of input, so you can see which SNES + buttons are registering as pressed. + '.' toggles movie frame display on/off. Movie must be open. + 'Shift'+'8' toggles movie read-only status. Movie must be open. + '1-4' toggles background 1-4 on/off. + '5' toggles sprites on/off + '9' (not recommended) toggles transparency effects on/off. + '8' (not recommended) toggles emulation of graphics window + effects on/off. + '0' (not recommended) toggles H-DMA emulation on/off. + + + +Compatibility +============= + +Compatibility with Other Ports +------------------------------ +All the files generated by Snes9x are compatible between platforms, except for +the extension of the freeze files. + +Compatibility with Other SNES Emulators +--------------------------------------- +Cheat files (.cht) are common between Snes9x and ZSNES. RTC files (.rtc) are +common between Snes9x and bsnes. SRAM files (.srm) should be common among all +SNES emulators. + + + +Problems +======== + +Problems with ROMs +------------------ +If Snes9x just displays a black screen for over 10 seconds after you've loaded a +ROM image, then one of the following could be true: + +- You just loaded some random ROM image and it isn't even a SNES game or you + only have part of the image. Snes9x only emulates games designed for the Super + NES, not NES, or Master System, or Game Boy, or . +- Someone has edited the Nintendo ROM information area inside the ROM image and + Snes9x can't work out what format the ROM image is in. Try playing around with + the ROM format options on the ROM load dialog. +- The ROM image is corrupt. If you're loading from CD, I know it might sound + silly, but is the CD dirty? Clean, unhacked ROM images will display [checksum + ok] when first loaded, corrupt or hacked ROMs display [bad checksum]. +- The original SNES ROM cartridge had additional hardware inside that is not + emulated yet and might never be. +- You might be using a file that is compressed in a way Snes9x does not + understand. + +The following ROMs are known to currently not to work with any version of +Snes9x: + + SD Gundam GX DSP-3 + Hayazashi Nidan Morita Shougi Seta-11 + Hayazashi Nidan Morita Shougi 2 Seta-18 + +Problems with Sounds +-------------------- +No sound coming from any SNES game using Snes9x? Could be any or all of these: + +- If all sound menu options are grayed out, or an error dialog about Snes9x not + being able to initialize DirectSound is displayed - then DirectSound could not + initialize itself. Make sure DirectX 6 or above is installed and your sound + card is supported by DirectX. + Installing the latest drivers for your sound card might help. Another Windows + application might have opened DirectSound in exclusive mode or opened the + Windows WAVE device - WinAmp uses the Windows WAVE device by default - in + which case you will need to stop that application and then restart Snes9x. It + is possible to switch WinAmp to use DirectSound, in which case both Snes9x and + WinAmp output can be heard at the same time. + If your sound card isn't supported by DirectX very well (or not at all) you + will have to use FMOD's WAVE output option; but WAVE output introduces a 0.15s + delay between Snes9x generating sample data and you hearing it. Select FMOD's + WAVE output by choosing the 'FMOD Windows Multimedia' sound driver option from + the Sound Settings dialog. +- The sound card's volume level might be set too low. Snes9x doesn't alter the + card's master volume level so you might need to adjust it using the sound + card's mixer/volume controls usually available from the task bar or start + menu. +- Make sure your speakers and turned on, plugged in and the volume controls are + set to a suitable level. + + + +Technical Information +===================== + +What's Emulated? +---------------- +- 65c816 main CPU. +- Variable length machine cycles. +- 8 channel DMA and H-DMA. +- H-IRQ, V-IRQ and NMI. +- Sony SPC700 sound CPU. +- Sound DSP, with eight 16-bit, stereo channels, compressed samples, hardware + envelope processing, echo, pitch modulation and digital FIR sound filter. +- SRAM, a battery-backed RAM. +- All background modes, 0 to 7. +- All screen resolutions, 256x224, 256x239, 512x224, 512x239, 512x448 and + 512x478. +- Pseudo hi-res mode. +- 8x8, 16x8 and 16x16 tile sizes, flipped in either direction. +- 32x32, 32x64, 64x32 and 64x64 screen tile sizes. +- Vertical and horizontal offset-per-tile. +- 128 8x8, 16x16, 32x32 and 64x64 sprites, flipped in either direction. +- Sub-screen and fixed color blending effects. +- Mosaic effects. +- Mode 7 screen rotation, scaling and screen flipping. +- Single and dual graphic clip windows, with all four logic combination modes. +- Color blending effects only inside or outside a window. +- Palette changes during frame. +- Direct color mode - uses tile and palette-group data directly as RGB value. +- SNES Mouse. +- Super Scope, emulated using computer mouse. +- Justifier, by Konami, similar to the Super Scope and used only in Lethal + Enforcers. +- Multi Player 5, allowing up to five people to play games simultaneously on + games that support that many players. +- Super FX, a fast RISC CPU used in several games. +- SA-1, a faster version of main CPU with some functions, used in several games. +- DSP-1, a custom chip used in several games, mainly racing games. +- DSP-2, a custom chip used only in Dungeon Master. +- DSP-4, a custom chip used only in Top Gear 3000. +- C4, a sprite scaler/rotator/line drawer/simple maths co-processor chip used + only in Megaman X2 and X3. +- Seta-10, a custom chip used only in F1 Race of Champions 2. +- OBC1, a sprite management chip used only in Metal Combat. +- S-DD1, a data decompression chip used only in Star Ocean and Street Fighter 2 + Alpha. +- SPC7110, similar in use to S-DD1, used in a few Hadoson games. +- S-RTC, a real-time clock chip, used only in Dai Kaijyu Monogatari 2. +- Satellaview and BS-X, only partially. + +What's Not? +----------- +- Exact sub-cycle timings of communication among most of parts - main CPU, sound + CPU, DMA, H-DMA, IRQ, NMI, and so on. Snes9x cannot run games that require + severe timings! +- Any other odd chips that manufactures sometimes placed inside the cartridge to + enhance games and as a nice side-effect, also act as an anti-piracy measure. + (DSP-3, Seta-11 and Seta-18, as examples) +- The expansion slot found in many carts. + +Custom Chips +------------ +Super FX + The Super FX is a 10.5/21MHz RISC CPU developed by Argonaut Software used as a + game enhancer by several game titles. Released SNES Super FX games included + Yoshi's Island, Doom, Winter Gold, Dirt Trax FX, StarFox, Stunt Race FX and + Vortex. + +SA-1 + The SA-1 is a fast, custom 65c816 8/16-bit processor, the same as inside the + SNES itself, but clocked at 10MHz compared to a maximum of 3.58MHz for the CPU + inside the SNES. The SA-1 isn't just a CPU; it also contains some extra + circuits developed by Nintendo which includes some very fast RAM, a memory + mapper, DMA and, several real-time timers. + +C4 + The C4 is custom Capcom chip used only in the Megaman X2 and Megaman X3 games. + It can scale and rotate images, draw line-vector objects and do some simple + maths to rotate them. + +S-DD1 + The S-DD1 is a custom data decompression chip that can decompress data in + real-time as the SNES DMA's data from the ROM to RAM. Only two games use the + chip: Star Ocean and Street Fighter Alpha 2. + +SPC7110 + The SPC7110 is a compression and memory mapping chip. It provides a few extra + features as well. It functions as an RTC interface, and has a multiply/divide + unit that has more precision than the SNES. The SPC7110 is found only in 4 + games: Super Power League 4, Far East of Eden Zero, Far East of Eden Zero - + Shounen Jump no Shou and Momotaro Dentetsu Happy. + +Others + Other known custom chips: DSP-1, DSP-2, DSP-3, DSP-4, Seta-10, Seta-11, + Seta-18, OBC1 and S-RTC. + + + +Credits +======= + +- Jerremy Koot for all his hard work on previous versions of Snes96, Snes97 and + Snes9x. +- Ivar for the original Super FX C emulation, DSP-1 emulation work and + information on both chips. +- zsKnight and _Demo_ for the Intel Super FX assembler, DSP-1 and C4 emulation + code. +- zsKnight and _Demo_ for all the other ideas and code I've nicked off them; + they've nicked lots of my ideas and information too! +- John Weidman and Darkforce for the S-RTC emulation information and code. +- Kreed and Maxim Stepin for excellent image enhancer routines. +- Nose000 for code changes to support various Japanese SNES games. +- Neill Corlett for the IPS patching support code. +- DiskDude's SNES Kart v1.6 document for the Game Genie(TM) and Pro-Action + Replay cheat system information. +- Lord ESNES for some nice chats and generally useful stuff. +- Lee Hyde (lee@jlp1.demon.co.uk) for his quest for sound information and the + Windows 95 icon. +- Shawn Hargreaves for the rather good Allegro 3.0 DOS library. +- Robert Grubbs for the SideWinder information - although I didn't use his + actual driver in the end. +- Steve Snake for his insights into SNES sound sample decompression. +- Vojtech Pavlik for the Linux joystick driver patches. +- Maciej Babinski for the basics of Linux's DGA X server extensions. +- Alexander Larsson for the GGI Linux port code. +- Harald Fielker for the original sound interpolation code (never used directly + due to problems). +- Takehiro TOMINAGA for many speed up suggestions and bug fixes. +- Predicador for the Windows icon. +- Lindsey Dubb for the mode 7 bi-linear filter code and the improved color + addition and subtraction code. +- Anti Resonance for his super-human efforts to help get his fast sound CPU core + and sound DSP core working in Snes9x. +- Brad Martin and TRAC for better and refined sound emulation. +- ernstp and entonne for patches and testing on Linux PPC. +- byuu for the most exact timing information and tons of the newest technical + findings. +- Blargg for the most accurate timings between sound CPU and DSP and exact sound + emulation codes. +- pagefault, TRAC, Dark Force, byuu, and others who have donated ideas and/or + code to the project. + + + +Nintendo is a trademark. +Super NES, Super Famicon, Super Scope and Super FX are trademarks of Nintendo. +Sufami Turbo is a trademark of Bandai Co., Ltd. +Game Genie is a trademark of Lewis Galoob Toys, Inc. +Pro Action Replay is a trademark of Datel Inc. +Macintosh, Mac and Mac OS X are trademarks of Apple Computer, Inc. +UNIX is a trademark of The Open Group. +Linux is a trademark of Linus Torvalds. +Windows is a trademark of Microsoft Corp. +Intel is a trademark of Intel Corp. +PowerPC is a trademark of International Business Machines Corp. +Sony is a trademark of Sony Corp. +Konami and Justifier are trademarks of Konami Corp. +Hudson is a trademark of Husdon Soft Co., Ltd. +Capcom is a trademark of Capcom Co., Ltd. + +Gary Henderson + +Edited for Windows port by: zones (kasumitokoduck@yahoo.com) +Updated most recently by: 2010/01/01 zones diff --git a/win32/makeasm.bat b/win32/makeasm.bat new file mode 100644 index 00000000..35246cba --- /dev/null +++ b/win32/makeasm.bat @@ -0,0 +1,8 @@ +nasmw -dZSNES_FX -dZSNES_C4 -f win32 -i . -i ../i386/ -o ../i386/fxemu2.obj ../i386/fxemu2.asm +nasmw -dZSNES_FX -dZSNES_C4 -f win32 -i . -i ../i386/ -o ../i386/fxemu2b.obj ../i386/fxemu2b.asm +nasmw -dZSNES_FX -dZSNES_C4 -f win32 -i . -i ../i386/ -o ../i386/fxemu2c.obj ../i386/fxemu2c.asm +nasmw -dZSNES_FX -dZSNES_C4 -f win32 -i . -i ../i386/ -o ../i386/fxtable.obj ../i386/fxtable.asm +nasmw -dZSNES_FX -dZSNES_C4 -f win32 -i . -i ../i386/ -o ../i386/sfxproc.obj ../i386/sfxproc.asm +nasmw -dZSNES_FX -dZSNES_C4 -f win32 -i . -i ../i386/ -o ../i386/zsnes.obj ../i386/zsnes.asm +nasmw -dZSNES_FX -dZSNES_C4 -f win32 -i . -i ../i386/ -o ../i386/c4.obj ../i386/c4.asm +nasmw -dZSNES_FX -dZSNES_C4 -f win32 -i . -i ../i386/ -o ../i386/zsnesc4.obj ../i386/zsnesc4.asm diff --git a/win32/objfix.c b/win32/objfix.c new file mode 100644 index 00000000..ad2535b0 --- /dev/null +++ b/win32/objfix.c @@ -0,0 +1,129 @@ +/* +Copyright (c) 1998-2005 Charles Bilyue'. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include + +int open_error(const char *filename, const char *mode) +{ + printf("Failure opening %s for %s\n",filename,mode); + return 1; +} + +int main(int argc, char **argv) +{ + int c; + int section_count; + FILE *in, *out; + unsigned char section_header[40]; + + if (argc < 2 || argc > 3) + { + printf("Fixes MS Win32 object files to be compatible with the incorrect\n"); + printf(" implementation in MinGW32.\n"); + printf("Usage: objfix infile [outfile]\n"); + return 1; + } + + in = fopen(argv[1], (argc == 2 ? "rb+" : "rb")); + if (!in) return open_error(argv[1], (argc == 2 ? "read" : "update")); + + if (argc == 3) + { + out = fopen(argv[2], "wb"); + if (!out) return open_error(argv[1], (argc == 2 ? "read" : "update")); + } + else + { + out = NULL; + } + + if (out) + { + fputc(fgetc(in), out); + fputc(fgetc(in), out); + + fputc(section_count = fgetc(in), out); + fputc(c = fgetc(in), out); + section_count += c << 8; + + for (c = 4; c < 0x14; c++) + { + fputc(fgetc(in), out); + } + + for (c = 0; c < section_count; c++) + { + fread(section_header, 1, 40, in); + + if (!strncmp(section_header, ".bss", 8)) + { + memcpy(section_header + 8, section_header + 16, 4); + memset(section_header + 16, 0, 4); + } + else + { + memset(section_header + 8, 0, 4); + } + + fwrite(section_header, 1, 40, out); + } + + while ((c = fgetc(in)) != EOF) + { + fputc(c, out); + } + } + else + { + fgetc(in); + fgetc(in); + + section_count = fgetc(in); + section_count += fgetc(in) << 8; + + fseek(in, 0x14, SEEK_SET); + + for (c = 0; c < section_count; c++) + { + fread(section_header, 1, 40, in); + + fseek(in, -40, SEEK_CUR); + + if (!strncmp(section_header, ".bss", 8)) + { + memcpy(section_header + 8, section_header + 16, 4); + memset(section_header + 16, 0, 4); + } + else + { + memset(section_header + 8, 0, 4); + } + + fwrite(section_header, 1, 40, in); + + fseek(in, 0, SEEK_CUR); + } + } + + fclose(in); + if (out) fclose(out); + + return 0; +} diff --git a/win32/render.cpp b/win32/render.cpp new file mode 100644 index 00000000..e3afe9fa --- /dev/null +++ b/win32/render.cpp @@ -0,0 +1,2594 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + + + +/* Render.CPP + * ---------- + * Video output filters for the Windows port. + */ + +#include "../port.h" +#include "wsnes9x.h" +#include "../snes9x.h" +#include +#include "render.h" +#include "../ppu.h" +#include "../gfx.h" +#include +#include "../gfx.h" +#include "../filter/2xsai.h" +#include "../filter/hq2x.h" +#include "snes_ntsc.h" + +// Private Prototypes, should not be called directly +void RenderPlain (SSurface Src, SSurface Dst, RECT *); +void RenderForced1X (SSurface Src, SSurface Dst, RECT *); +void RenderSimple2X (SSurface Src, SSurface Dst, RECT *); +void RenderFakeTV (SSurface Src, SSurface Dst, RECT *); +void RenderSuperEagle (SSurface Src, SSurface Dst, RECT *); +void Render2xSaI (SSurface Src, SSurface Dst, RECT *); +void RenderSuper2xSaI (SSurface Src, SSurface Dst, RECT *); +void RenderTVMode (SSurface Src, SSurface Dst, RECT *); +template void RenderHQ2X (SSurface Src, SSurface Dst, RECT *rect); +template void RenderHQ3X (SSurface Src, SSurface Dst, RECT *rect); +void RenderLQ3XB (SSurface Src, SSurface Dst, RECT *rect); +void RenderHQ4X (SSurface Src, SSurface Dst, RECT *rect); +void RenderEPXA (SSurface Src, SSurface Dst, RECT *); +void RenderEPXB (SSurface Src, SSurface Dst, RECT *); +void RenderEPXC (SSurface Src, SSurface Dst, RECT *); +void RenderEPX3 (SSurface Src, SSurface Dst, RECT *); +void RenderSimple3X (SSurface Src, SSurface Dst, RECT *); +void RenderSimple4X (SSurface Src, SSurface Dst, RECT *); +void RenderTVMode3X (SSurface Src, SSurface Dst, RECT *); +void RenderDotMatrix3X (SSurface Src, SSurface Dst, RECT *); +void RenderBlarggNTSCComposite(SSurface Src, SSurface Dst, RECT *); +void RenderBlarggNTSCSvideo(SSurface Src, SSurface Dst, RECT *); +void RenderBlarggNTSCRgb(SSurface Src, SSurface Dst, RECT *); +void RenderBlarggNTSC(SSurface Src, SSurface Dst, RECT *); +// Contains the pointer to the now active render method +TRenderMethod RenderMethod = RenderPlain; +TRenderMethod RenderMethodHiRes = RenderPlain; + +// Used as change log +static uint8 ChangeLog1 [EXT_PITCH * MAX_SNES_HEIGHT]; +static uint8 ChangeLog2 [EXT_PITCH * MAX_SNES_HEIGHT]; +static uint8 ChangeLog3 [EXT_PITCH * MAX_SNES_HEIGHT]; + +uint8 *ChangeLog [3] = { + ChangeLog1, ChangeLog2, ChangeLog3 +}; + +START_EXTERN_C +uint8 snes9x_clear_change_log = 0; +END_EXTERN_C + +TRenderMethod FilterToMethod(RenderFilter filterID) +{ + switch(filterID) + { + default: + case FILTER_NONE: return RenderPlain; + case FILTER_SIMPLE1X: return RenderForced1X; + case FILTER_SIMPLE2X: return RenderSimple2X; + case FILTER_SCANLINES: return RenderFakeTV; + case FILTER_TVMODE: return RenderTVMode; + case FILTER_SUPEREAGLE: return RenderSuperEagle; + case FILTER_SUPER2XSAI: return RenderSuper2xSaI; + case FILTER_2XSAI: return Render2xSaI; + case FILTER_HQ2X: return RenderHQ2X; + case FILTER_HQ2XS: return RenderHQ2X; + case FILTER_HQ2XBOLD: return RenderHQ2X; + case FILTER_EPXA: return RenderEPXA; + case FILTER_EPXB: return RenderEPXB; + case FILTER_EPXC: return RenderEPXC; + case FILTER_SIMPLE3X: return RenderSimple3X; + case FILTER_TVMODE3X: return RenderTVMode3X; + case FILTER_DOTMATRIX3X:return RenderDotMatrix3X; + case FILTER_HQ3X: return RenderHQ3X; + case FILTER_HQ3XS: return RenderHQ3X; + case FILTER_HQ3XBOLD: return RenderHQ3X; + case FILTER_LQ3XBOLD: return RenderLQ3XB; + case FILTER_EPX3: return RenderEPX3; + case FILTER_BLARGGCOMP: return RenderBlarggNTSCComposite; + case FILTER_BLARGGSVID: return RenderBlarggNTSCSvideo; + case FILTER_BLARGGRGB: return RenderBlarggNTSCRgb; + case FILTER_SIMPLE4X: return RenderSimple4X; + case FILTER_HQ4X: return RenderHQ4X; + } +} + +const char* GetFilterName(RenderFilter filterID) +{ + switch(filterID) + { + default: return "Unknown"; + case FILTER_NONE: return "None"; + case FILTER_SIMPLE1X: return "Forced 1X"; + case FILTER_SIMPLE2X: return "Simple 2X"; + case FILTER_SCANLINES: return "Scanlines"; + case FILTER_TVMODE: return "TV Mode"; + case FILTER_BLARGGCOMP: return "Blargg's NTSC (Composite)"; + case FILTER_BLARGGSVID: return "Blargg's NTSC (S-Video)"; + case FILTER_BLARGGRGB: return "Blargg's NTSC (RGB)"; + case FILTER_SUPEREAGLE: return "SuperEagle"; + case FILTER_SUPER2XSAI: return "Super2xSaI"; + case FILTER_2XSAI: return "2xSaI"; + case FILTER_HQ2X: return "hq2x"; + case FILTER_HQ2XS: return "hq2xS"; + case FILTER_HQ2XBOLD: return "hq2xBold"; + case FILTER_EPXA: return "EPX A"; + case FILTER_EPXB: return "EPX B"; + case FILTER_EPXC: return "EPX C"; + case FILTER_SIMPLE3X: return "Simple 3X"; + case FILTER_TVMODE3X: return "TV Mode 3X"; + case FILTER_DOTMATRIX3X: return "Dot Matrix 3X"; + case FILTER_HQ3X: return "hq3x"; + case FILTER_HQ3XS: return "hq3xS"; + case FILTER_HQ3XBOLD: return "hq3xBold"; + case FILTER_LQ3XBOLD: return "lq3xBold"; + case FILTER_EPX3: return "EPX3"; + case FILTER_SIMPLE4X: return "Simple 4X"; + case FILTER_HQ4X: return "hq4x"; + } +} + +int GetFilterScale(RenderFilter filterID) +{ + switch(filterID) + { + case FILTER_NONE: + case FILTER_SIMPLE1X: + return 1; + + default: + return 2; + + case FILTER_SIMPLE3X: + case FILTER_TVMODE3X: + case FILTER_DOTMATRIX3X: + case FILTER_HQ3X: + case FILTER_HQ3XS: + case FILTER_HQ3XBOLD: + case FILTER_LQ3XBOLD: + case FILTER_EPX3: + case FILTER_BLARGGCOMP: + case FILTER_BLARGGSVID: + case FILTER_BLARGGRGB: + return 3; + case FILTER_SIMPLE4X: + case FILTER_HQ4X: + return 4; + } +} + +bool GetFilterHiResSupport(RenderFilter filterID) +{ + switch(filterID) + { + case FILTER_NONE: + case FILTER_SIMPLE1X: + case FILTER_SIMPLE2X: + case FILTER_SCANLINES: + case FILTER_BLARGGCOMP: + case FILTER_BLARGGSVID: + case FILTER_BLARGGRGB: + case FILTER_TVMODE: + case FILTER_SIMPLE3X: + case FILTER_SIMPLE4X: + case FILTER_HQ4X: + return true; + + default: + return false; + } +} + +inline static bool GetFilter32BitSupport(RenderFilter filterID) +{ + switch(filterID) + { + case FILTER_NONE: + case FILTER_SIMPLE1X: + case FILTER_SIMPLE2X: + case FILTER_SIMPLE3X: + case FILTER_EPXA: + case FILTER_EPXB: + case FILTER_EPXC: + case FILTER_EPX3: + case FILTER_SCANLINES: + case FILTER_TVMODE3X: + case FILTER_DOTMATRIX3X: + return true; + + default: + return false; + } +} + +void SelectRenderMethod() +{ + TRenderMethod OldRenderMethod = RenderMethod; + TRenderMethod OldRenderMethodHiRes = RenderMethodHiRes; + + RenderMethod = FilterToMethod(GUI.Scale); + RenderMethodHiRes = FilterToMethod(GUI.ScaleHiRes); + + if (GUI.ScreenCleared || OldRenderMethod != RenderMethod || OldRenderMethodHiRes != RenderMethodHiRes) + snes9x_clear_change_log = GUI.NumFlipFrames; + + GUI.ScreenCleared = false; + + GUI.DepthConverted = !GUI.NeedDepthConvert; + if(GUI.ScreenDepth == 32 && + ((GetFilter32BitSupport(GUI.Scale) && (IPPU.RenderedScreenHeight <= SNES_HEIGHT_EXTENDED && IPPU.RenderedScreenWidth < 512)) || + (GetFilter32BitSupport(GUI.ScaleHiRes) && (IPPU.RenderedScreenHeight > SNES_HEIGHT_EXTENDED || IPPU.RenderedScreenWidth == 512)))) + { + // filter supports converting + GUI.DepthConverted = true; + } +} + +#define R5G6B5 // windows port uses RGB565 + +#ifdef R5G6B5 + #define Mask_2 0x07E0 // 00000 111111 00000 + #define Mask13 0xF81F // 11111 000000 11111 + #define Mask_1 0x001F // 00000 000000 11111 + #define Mask_3 0xF800 // 11111 000000 00000 + #define CONVERT_16_TO_32(pixel) \ + (((((pixel) >> 11) ) << /*RedShift+3*/ 19) | \ + ((((pixel) >> 6) & 0x1f) << /*GreenShift+3*/11) | \ + (((pixel) & 0x1f) << /*BlueShift+3*/ 3)) + #define NUMBITS (16) +#else + #define Mask_2 0x03E0 // 00000 11111 00000 + #define Mask13 0x7C1F // 11111 00000 11111 + #define Mask_1 0x001F // 00000 00000 11111 + #define Mask_3 0x7C00 // 11111 00000 00000 + #define CONVERT_16_TO_32(pixel) \ + (((((pixel) >> 10) ) << /*RedShift+3*/ 19) | \ + ((((pixel) >> 5) & 0x1f) << /*GreenShift+3*/11) | \ + (((pixel) & 0x1f) << /*BlueShift+3*/ 3)) + #define NUMBITS (15) +#endif + +static int RGBtoYUV[1<> 1) & Mask_2) + \ + (((((c1) & Mask13) + ((c2) & Mask13)) >> 1) & Mask13))) +#define Interp01(c1, c2) \ + ((((c1) == (c2)) ? (c1) : \ + (((((((c1) & Mask_2) * 3) + ((c2) & Mask_2)) >> 2) & Mask_2) + \ + ((((((c1) & Mask13) * 3) + ((c2) & Mask13)) >> 2) & Mask13)))) +#define Halve(c1) \ + ((((((c1) & Mask_2)) >> 1) & Mask_2) + \ + (((((c1) & Mask13)) >> 1) & Mask13)) +#define ThreeQuarters(c1) \ + ((((((c1) & Mask_2)*3) >> 2) & Mask_2) + \ + (((((c1) & Mask13)*3) >> 2) & Mask13)) + +#ifdef LSB_FIRST + #define TWO_PIX(left,right) ((left) | ((right) << 16)) + #define THREE_PIX(left,middle,right) uint48((left) | ((middle) << 16), (right)) + #define TWO_PIX_32(left,right) (CONVERT_16_TO_32(left) | ((uint64)CONVERT_16_TO_32(right) << 32)) + #define THREE_PIX_32(left,middle,right) uint96(CONVERT_16_TO_32(left) | ((uint64)CONVERT_16_TO_32(middle) << 32), CONVERT_16_TO_32(right)) +#else + #define TWO_PIX(left,right) ((right) | ((left) << 16)) + #define THREE_PIX(left,middle,right) uint48((middle) | ((left) << 16), (right)) // is this right? +// #define THREE_PIX(left,middle,right) uint48((right) | ((middle) << 16), (left)) // or this? +#endif + + + +// stretches a single line +inline void DoubleLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = *lpSrc; + *lpDst++ = *lpSrc++; + } +} +inline void TripleLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = *lpSrc; + *lpDst++ = *lpSrc; + *lpDst++ = *lpSrc++; + } +} +inline void QuadrupleLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = *lpSrc; + *lpDst++ = *lpSrc; + *lpDst++ = *lpSrc; + *lpDst++ = *lpSrc++; + } +} +inline void ThreeHalfLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width-=2){ + *lpDst++ = *lpSrc; + *lpDst++ = Interp05(*lpSrc, *(lpSrc+1)); + *lpDst++ = *(lpSrc+1); + lpSrc+=2; + } +} +inline void HalfLine16( uint16 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = Interp05(*lpSrc, *(lpSrc+1)); + lpSrc+=2; + } +} +inline void DoubleLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + lpSrc++; + } +} +inline void QuadrupleLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + lpSrc++; + } +} +inline void SingleLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + lpSrc++; + } +} +inline void HalfLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + const uint16 color = Interp05(*lpSrc, *(lpSrc+1)); + *lpDst++ = CONVERT_16_TO_32(color); + lpSrc+=2; + } +} +inline void TripleLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width--){ + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + lpSrc++; + } +} +inline void ThreeHalfLine32( uint32 *lpDst, uint16 *lpSrc, unsigned int Width){ + while(Width-=2){ + *lpDst++ = CONVERT_16_TO_32(*lpSrc); + const uint16 color = Interp05(*lpSrc, *(lpSrc+1)); + *lpDst++ = CONVERT_16_TO_32(color); + *lpDst++ = CONVERT_16_TO_32(*(lpSrc+1)); + lpSrc+=2; + } +} + + +inline void SetRect(RECT* rect, int width, int height, int scale) +{ + rect->left = 0; + rect->right = width * scale; + rect->top = 0; + rect->bottom = (height - (GUI.HeightExtend?0:15)) * scale; +} + + +// No enlargement, just render to the screen +void RenderPlain (SSurface Src, SSurface Dst, RECT *rect) +{ + SetRect(rect, Src.Width, Src.Height, 1); + if(Src.Height > SNES_HEIGHT_EXTENDED) + rect->bottom -= (GUI.HeightExtend?0:15); + const uint32 srcHeight = (rect->bottom - rect->top); + + uint16 *lpSrc = reinterpret_cast(Src.Surface); + const unsigned int srcPitch = Src.Pitch >> 1; + + if(GUI.ScreenDepth == 16) + { + const unsigned int dstPitch = Dst.Pitch >> 1; + uint16 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + + for (unsigned int H = 0; H != srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch) + memcpy (lpDst, lpSrc, Src.Width << 1); + } + else if(GUI.ScreenDepth == 32) + { + const unsigned int dstPitch = Dst.Pitch >> 2; + uint32 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + + for (unsigned int H = 0; H != srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch) + SingleLine32(lpDst, lpSrc, Src.Width); + } +} + +void RenderForced1X( SSurface Src, SSurface Dst, RECT *rect) +{ + uint16 *lpSrc; + unsigned int H; + + SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 1); + const uint32 srcHeight = (rect->bottom - rect->top); + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast(Src.Surface); + + if(GUI.ScreenDepth == 16) + { + const unsigned int dstPitch = Dst.Pitch >> 1; + uint16 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + if (Src.Height <= SNES_HEIGHT_EXTENDED) + if(Src.Width != 512) + for (H = 0; H != srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch) + memcpy (lpDst, lpSrc, Src.Width << 1); + else + for (H = 0; H < srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch) + HalfLine16 (lpDst, lpSrc, Src.Width); + else + if(Src.Width != 512) + for (H = 0; H != Src.Height; H+=2, lpDst += dstPitch, lpSrc += srcPitch<<1) + memcpy (lpDst, lpSrc, Src.Width << 1); + else + for (H = 0; H < Src.Height >> 1; H++, lpDst += dstPitch, lpSrc += srcPitch<<1) + HalfLine16 (lpDst, lpSrc, Src.Width); + } + else if(GUI.ScreenDepth == 32) + { + const unsigned int dstPitch = Dst.Pitch >> 2; + uint32 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + if (Src.Height <= SNES_HEIGHT_EXTENDED) + if(Src.Width != 512) + for (H = 0; H != srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch) + SingleLine32 (lpDst, lpSrc, Src.Width); + else + for (H = 0; H < srcHeight; H++, lpDst += dstPitch, lpSrc += srcPitch) + HalfLine32 (lpDst, lpSrc, Src.Width); + else + if(Src.Width != 512) + for (H = 0; H != Src.Height; H+=2, lpDst += dstPitch, lpSrc += srcPitch<<1) + SingleLine32 (lpDst, lpSrc, Src.Width); + else + for (H = 0; H < Src.Height >> 1; H++, lpDst += dstPitch, lpSrc += srcPitch<<1) + HalfLine32 (lpDst, lpSrc, Src.Width); + } +} + +// Enlarge 2x using Fake TV mode when the Snes9x is not rendering in HiRes +// FakeTV mode = a black line between each other line (scanlines) +void RenderFakeTV( SSurface Src, SSurface Dst, RECT *rect) +{ + uint16 *lpSrc; + unsigned int H; + + SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 2); + const uint32 srcHeight = (rect->bottom - rect->top)/2; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast(Src.Surface); + + if(GUI.ScreenDepth == 16) + { + const unsigned int dstPitch = Dst.Pitch >> 1; + uint16 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + if(Src.Height <= SNES_HEIGHT_EXTENDED) + if(Src.Width != 512) + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + memset (lpDst, 0, 512*2), lpDst += dstPitch; + else + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + memcpy (lpDst, lpSrc, Src.Width << 1), lpDst += dstPitch, + memset (lpDst, 0, 512*2), lpDst += dstPitch; + else + if(Src.Width != 512) + for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch << 1) + DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + memset (lpDst, 0, 512*2), lpDst += dstPitch; + else + for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch << 1) + memcpy (lpDst, lpSrc, Src.Width << 1), lpDst += dstPitch, + memset (lpDst, 0, 512*2), lpDst += dstPitch; + } + else if(GUI.ScreenDepth == 32) + { + const unsigned int dstPitch = Dst.Pitch >> 2; + uint32 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + if(Src.Height <= SNES_HEIGHT_EXTENDED) + if(Src.Width != 512) + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + memset (lpDst, 0, 512*4), lpDst += dstPitch; + else + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + SingleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + memset (lpDst, 0, 512*4), lpDst += dstPitch; + else + if(Src.Width != 512) + for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch << 1) + DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + memset (lpDst, 0, 512*4), lpDst += dstPitch; + else + for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch << 1) + SingleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + memset (lpDst, 0, 512*4), lpDst += dstPitch; + } +} + +void RenderSimple2X( SSurface Src, SSurface Dst, RECT *rect) +{ + // just copy if it's high res in both dimensions + if(Src.Height > SNES_HEIGHT_EXTENDED && Src.Width == 512) + {RenderPlain (Src, Dst, rect); return;} + + uint16 *lpSrc; + unsigned int H; + + SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 2); + const uint32 srcHeight = (rect->bottom - rect->top)/2; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast(Src.Surface); + + if(GUI.ScreenDepth == 16) + { + const unsigned int dstPitch = Dst.Pitch >> 1; + uint16 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + if (Src.Height <= SNES_HEIGHT_EXTENDED) + if(Src.Width != 512) + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + memcpy (lpDst, lpSrc, Src.Width << 1), lpDst += dstPitch, + memcpy (lpDst, lpSrc, Src.Width << 1), lpDst += dstPitch; + else + for (H = 0; H < Src.Height; H++, lpSrc += srcPitch) + DoubleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + } + else if(GUI.ScreenDepth == 32) + { + const unsigned int dstPitch = Dst.Pitch >> 2; + uint32 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + if (Src.Height <= SNES_HEIGHT_EXTENDED) + if(Src.Width != 512) + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + SingleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + SingleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < Src.Height; H++, lpSrc += srcPitch) + DoubleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + } +} + +void RenderSuperEagle (SSurface Src, SSurface Dst, RECT *rect) +{ + if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + {RenderSimple2X (Src, Dst, rect); return;} + + unsigned char *lpSrc, *lpDst; + + SetRect(rect, Src.Width, Src.Height, 2); + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + lpDst += rect->top * Dst.Pitch + rect->left * 2; + + SuperEagle (lpSrc, Src.Pitch, + lpDst, Dst.Pitch, Src.Width, Src.Height); + + if (snes9x_clear_change_log) + snes9x_clear_change_log--; +} + +void Render2xSaI (SSurface Src, SSurface Dst, RECT *rect) +{ + unsigned char *lpSrc, *lpDst; + + // If Snes9x is rendering anything in HiRes, then just copy, don't interpolate + if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + { + RenderSimple2X (Src, Dst, rect); + return; + } + + SetRect(rect, Src.Width, Src.Height, 2); + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + lpDst += rect->top * Dst.Pitch + rect->left * 2; + + _2xSaI (lpSrc, Src.Pitch, + lpDst, Dst.Pitch, Src.Width, Src.Height); + + if (snes9x_clear_change_log) + snes9x_clear_change_log--; +} + +void RenderSuper2xSaI (SSurface Src, SSurface Dst, RECT *rect) +{ + if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + {RenderSimple2X (Src, Dst, rect); return;} + + unsigned char *lpSrc, *lpDst; + + SetRect(rect, Src.Width, Src.Height, 2); + + lpSrc = Src.Surface; + lpDst = Dst.Surface; + lpDst += rect->top * Dst.Pitch + rect->left * 2; + + Super2xSaI (lpSrc, Src.Pitch, + lpDst, Dst.Pitch, Src.Width, Src.Height); + + if (snes9x_clear_change_log) + snes9x_clear_change_log--; +} + +void RenderTVMode ( SSurface Src, SSurface Dst, RECT *rect) +{ + // XXX: this filter's hi-res support for double-height modes is NYI + if (Src.Height > SNES_HEIGHT_EXTENDED) + { + snes9x_clear_change_log = GUI.NumFlipFrames; + RenderSimple2X (Src, Dst, rect); + return; + } + + uint8 *nextLine, *finish; + uint32 colorMask = ~(RGB_LOW_BITS_MASK | (RGB_LOW_BITS_MASK << 16)); + uint32 lowPixelMask = RGB_LOW_BITS_MASK; + uint8 *srcPtr = Src.Surface; + uint8 *dstPtr = Dst.Surface; + uint32 srcPitch = Src.Pitch; + uint32 dstPitch = Dst.Pitch; + int width = Src.Width; + int height = Src.Height; + uint8 *deltaPtr = ChangeLog [GUI.FlipCounter % GUI.NumFlipFrames]; + + SetRect(rect, 256, height, 2); + + dstPtr += rect->top * Dst.Pitch + rect->left * 2; + nextLine = dstPtr + dstPitch; + + if (width == 256) + { + do + { + uint32 *bP = (uint32 *) srcPtr; + uint32 *xP = (uint32 *) deltaPtr; + uint32 *dP = (uint32 *) dstPtr; + uint32 *nL = (uint32 *) nextLine; + uint32 currentPixel; + uint32 nextPixel; + uint32 currentDelta; + uint32 nextDelta; + + finish = (uint8 *) bP + ((width + 2) << 1); + nextPixel = *bP++; + nextDelta = *xP++; + + do + { + currentPixel = nextPixel; + currentDelta = nextDelta; + nextPixel = *bP++; + nextDelta = *xP++; + + if (snes9x_clear_change_log || + nextPixel != nextDelta || currentPixel != currentDelta) + { + uint32 colorA, colorB, product, darkened; + + *(xP - 2) = currentPixel; + #ifdef LSB_FIRST + colorA = currentPixel & 0xffff; + colorB = (currentPixel & 0xffff0000) >> 16; + #else + colorA = (currentPixel & 0xffff0000) >> 16; + colorB = currentPixel & 0xffff; + #endif + + *(dP) = product = TWO_PIX(colorA, (((colorA & colorMask) >> 1) + + ((colorB & colorMask) >> 1) + + (colorA & colorB & lowPixelMask))); + + darkened = (product = ((product & colorMask) >> 1)); + darkened += (product = ((product & colorMask) >> 1)); + darkened += (product & colorMask) >> 1; + *(nL) = darkened; + + #ifdef LSB_FIRST + colorA = nextPixel & 0xffff; + #else + colorA = (nextPixel & 0xffff0000) >> 16; + #endif + *(dP + 1) = product = TWO_PIX(colorB, (((colorA & colorMask) >> 1) + + ((colorB & colorMask) >> 1) + + (colorA & colorB & lowPixelMask))); + darkened = (product = ((product & colorMask) >> 1)); + darkened += (product = ((product & colorMask) >> 1)); + darkened += (product & colorMask) >> 1; + *(nL + 1) = darkened; + } + + dP += 2; + nL += 2; + } while ((uint8 *) bP < finish); + + deltaPtr += srcPitch; + srcPtr += srcPitch; + dstPtr += dstPitch * 2; + nextLine += dstPitch * 2; + } + while (--height); + + if (snes9x_clear_change_log) + snes9x_clear_change_log--; + } + else + { + snes9x_clear_change_log = GUI.NumFlipFrames; + + do + { + uint32 *bP = (uint32 *) srcPtr; + uint32 *xP = (uint32 *) deltaPtr; + uint32 *dP = (uint32 *) dstPtr; + uint32 *nL = (uint32 *) nextLine; + uint32 currentPixel; + uint32 nextPixel; + uint32 currentDelta; + uint32 nextDelta; + + finish = (uint8 *) bP + ((width + 2) << 1); + nextPixel = *bP++; + nextDelta = *xP++; + + do + { + currentPixel = nextPixel; + currentDelta = nextDelta; + nextPixel = *bP++; + nextDelta = *xP++; + + if (snes9x_clear_change_log || + nextPixel != nextDelta || currentPixel != currentDelta) + { + uint32 colorA, colorB, product, darkened; + + *(xP - 1) = currentPixel; + #ifdef LSB_FIRST + colorA = currentPixel & 0xffff; + colorB = (currentPixel & 0xffff0000) >> 16; + #else + colorA = (currentPixel & 0xffff0000) >> 16; + colorB = currentPixel & 0xffff; + #endif + product = TWO_PIX(colorA, (((colorA & colorMask) >> 1) + + ((colorB & colorMask) >> 1) + + (colorA & colorB & lowPixelMask))); + + *(dP) = currentPixel; + darkened = (product = ((product & colorMask) >> 1)); + darkened += (product = ((product & colorMask) >> 1)); + darkened += (product & colorMask) >> 1; + *(nL) = darkened; + } + + dP += 1; + nL += 1; + } while ((uint8 *) bP < finish); + + deltaPtr += srcPitch; + srcPtr += srcPitch; + dstPtr += dstPitch * 2; + nextLine += dstPitch * 2; + } + while (--height); + } +} + + +void RenderSimple3X( SSurface Src, SSurface Dst, RECT *rect) +{ + uint16 *lpSrc; + unsigned int H; + + SetRect(rect, 256, 239, 3); + const uint32 srcHeight = (rect->bottom - rect->top)/3; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast(Src.Surface); + + if(GUI.ScreenDepth == 16) + { + const unsigned int dstPitch = Dst.Pitch >> 1; + uint16 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + if (Src.Height <= SNES_HEIGHT_EXTENDED) + if(Src.Width != 512) + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + if(Src.Width != 512) + for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch) + TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, lpSrc += srcPitch, + TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + TripleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch) + ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, lpSrc += srcPitch, + ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + ThreeHalfLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + } + else if(GUI.ScreenDepth == 32) + { + const unsigned int dstPitch = Dst.Pitch >> 2; + uint32 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + if (Src.Height <= SNES_HEIGHT_EXTENDED) + if(Src.Width != 512) + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + if(Src.Width != 512) + for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch) + TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, lpSrc += srcPitch, + TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + TripleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < Src.Height >> 1; H++, lpSrc += srcPitch) + ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, lpSrc += srcPitch, + ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + ThreeHalfLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + } +} + +#ifdef LSB_FIRST +#pragma pack(push, 1) +struct uint48 +{ + uint32 L; + uint16 R; + inline uint48(uint32 left, uint16 right) + { + L = left; + R = right; + } +}; +struct uint96 +{ + uint64 L; + uint32 R; + inline uint96(uint64 left, uint32 right) + { + L = left; + R = right; + } +}; +#pragma pack(pop) +#else +#error NYI for !LSB_FIRST +#endif + +// assert that sizeof(uint48) == 6 bytes +//static int compiler_error_sizeof_uint48_notequal_6 [(sizeof(uint48)== 6)?1:0] = {0}; +//static int compiler_error_sizeof_uint96_notequal_12 [(sizeof(uint96)==12)?1:0] = {0}; + + +// shared EPX-type loop macros +// All of these parameters will be constant values, +// so I hope the compiler is smart enough to optimize away "if(0) ..." + +#define DrawRows(scale,diags) \ + { \ + h = srcHeight - 1; \ + DoRow(0,1,scale,diags); \ + for (h = srcHeight - 2; h; h--) \ + DoRow(1,1,scale,diags); \ + DoRow(1,0,scale,diags); \ + } + +#define DoRow(topValid,botValid,scale,diags) \ + { \ + w = srcWidth - 1; \ + InitLine(topValid,botValid,scale,diags); \ + DrawPix(0,topValid,0,botValid); \ + for (w = srcWidth - 2; w; w--) \ + { \ + NextPixel(topValid,botValid,1,diags); \ + DrawPix(topValid,topValid,botValid,botValid); \ + } \ + NextPixel(topValid,botValid,0,diags); \ + DrawPix(topValid,0,botValid,0); \ + srcPtr += srcPitch; \ + dstPtr += dstPitch * scale; \ + } + +#define InitLine(topValid, botValid, scale, diags) \ + { \ + if(topValid) uP = (uint16 *) (srcPtr - srcPitch); \ + if(botValid) lP = (uint16 *) (srcPtr + srcPitch); \ + sP = (uint16 *) srcPtr; \ + dP1 = (destType *) dstPtr; \ + dP2 = (destType *) (dstPtr + dstPitch); \ + if(scale>=3) dP3 = (destType *) (dstPtr + (dstPitch<<1)); \ + if(topValid) colorD = *uP++; \ + if(botValid) colorB = *lP++; \ + colorX = *sP++; \ + colorC = *sP; \ + if(diags) if(topValid) colorH = *uP; \ + if(diags) if(botValid) colorG = *lP; \ + } + +#define NextPixel(topValid, botValid, rightValid, diags) \ + { \ + colorA = colorX; \ + colorX = colorC; \ + if(rightValid) colorC = *++sP; \ + if(diags) { \ + if(botValid){ \ + colorF = colorB; \ + colorB = colorG; \ + if(rightValid) colorG = *++lP; \ + } \ + if(topValid){ \ + colorE = colorD; \ + colorD = colorH; \ + if(rightValid) colorH = *++uP; \ + } \ + } else { \ + if(botValid) colorB = *lP++; \ + if(topValid) colorD = *uP++; \ + } \ + } + +#define DrawInit(scale,uintDest) \ + uint8 *srcPtr = Src.Surface, *dstPtr = Dst.Surface; \ + const uint32 srcPitch = Src.Pitch, dstPitch = Dst.Pitch; \ + SetRect(rect, 256, Src.Height, scale); \ + dstPtr += rect->top * Dst.Pitch + rect->left * 2; \ + const uint32 srcHeight = (rect->bottom - rect->top)/scale; \ + const uint32 srcWidth = (rect->right - rect->left)/scale; \ + uint16 colorX, colorA, colorB, colorC, colorD, colorE=0, colorF=0, colorG=0, colorH=0; \ + uint16 *sP, *uP, *lP; \ + typedef uintDest destType; \ + destType *dP1, *dP2, *dP3=0; \ + int w, h; + + +// code for rendering the image enlarged 2X with EPX +void RenderEPXA (SSurface Src, SSurface Dst, RECT *rect) +{ + if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + {RenderSimple2X (Src, Dst, rect); return;} + + // all we have to do now is define what to do at each pixel + // (it's a 2x filter, so for each pixel we draw 2x2 = 4 pixels) + // based on the current pixel and the surrounding 4 pixels + + // D + // A X C + // B + #define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \ + { /* on10 on11 */ \ + if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \ + && (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX))) \ + { \ + *dP1++ = _TWO_PIX((on00 && colorD == colorA) ? colorD : colorX, /* we set 2 pixels at a time (the pointer size is the size of (scale=2) pixels)*/\ + (on01 && colorC == colorD) ? colorC : colorX); \ + *dP2++ = _TWO_PIX((on10 && colorA == colorB) ? colorA : colorX, /* also set the 2 pixels below those*/\ + (on11 && colorB == colorC) ? colorB : colorX); \ + } else { \ + *dP1++ = _TWO_PIX(colorX, colorX); \ + *dP2++ = _TWO_PIX(colorX, colorX); \ + } \ + } + + // this renderer supports 32-bit or 16-bit rendering (see GetFilter32BitSupport()) + // so we must switch based on depth to handle both modes. + // we could choose to only support 16-bit, but that would impose a performance penalty + // for color conversion from the increasingly-commonly-used 32-bit depth + if(GUI.ScreenDepth == 32) + { +#define _TWO_PIX TWO_PIX_32 // define _TWO_PIX to combine two 32-bit pixels at a time + DrawInit(2,uint64); // initialize with the scale and an int as big as 2 pixels + DrawRows(2,0); // scale is 2x, and diags (8 surrounding pixels) is off since we only need 4 surrounding +#undef _TWO_PIX + } + else // 16-bit, same deal but with smaller pointer size and different 2-pixel combiner + { +#define _TWO_PIX TWO_PIX // define _TWO_PIX to combine two 16-bit pixels at a time + DrawInit(2,uint32); // initialize with the scale and an int as big as 2 pixels + DrawRows(2,0); // scale is 2x, and diags (8 surrounding pixels) is off since we only need 4 surrounding +#undef _TWO_PIX + } + + + #undef DrawPix +} + +// code for improved 2X EPX, which tends to do better with diagonal edges than regular EPX +void RenderEPXB (SSurface Src, SSurface Dst, RECT *rect) +{ + if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + {RenderSimple2X (Src, Dst, rect); return;} + + // E D H + // A X C + // F B G + #define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \ + { /* on10 on11 */ \ + if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \ + && (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX)) \ + && ((!on00||!on01||!on10|!on11) || \ + ((colorX == colorA) || (colorX == colorB) || (colorX == colorC) || (colorX == colorD) || /* diagonal */ \ + (((colorE != colorG) || (colorX == colorF) || (colorX == colorH)) && /* edge */ \ + ((colorF != colorH) || (colorX == colorE) || (colorX == colorG)))))) /* smoothing */ \ + { \ + *dP1++ = _TWO_PIX((on00 && colorD == colorA && (colorX != colorE || colorX != colorG || colorD != colorH || colorA != colorF)) ? colorD : colorX, \ + (on01 && colorC == colorD && (colorX != colorH || colorX != colorF || colorC != colorG || colorD != colorE)) ? colorC : colorX); \ + *dP2++ = _TWO_PIX((on10 && colorA == colorB && (colorX != colorF || colorX != colorH || colorA != colorE || colorB != colorG)) ? colorA : colorX, \ + (on11 && colorB == colorC && (colorX != colorG || colorX != colorE || colorB != colorF || colorC != colorH)) ? colorB : colorX); \ + } else { \ + *dP1++ = _TWO_PIX(colorX, colorX); \ + *dP2++ = _TWO_PIX(colorX, colorX); \ + } \ + } + + // again, this supports 32-bit or 16-bit rendering + if(GUI.ScreenDepth == 32) + { +#define _TWO_PIX TWO_PIX_32 + DrawInit(2,uint64); + DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels +#undef _TWO_PIX + } + else + { +#define _TWO_PIX TWO_PIX + DrawInit(2,uint32); + DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels +#undef _TWO_PIX + } + + #undef DrawPix +} + +void RenderEPX3 (SSurface Src, SSurface Dst, RECT *rect) +{ + if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + {RenderSimple3X (Src, Dst, rect); return;} + + // E D H + // A X C + // F B G + + #define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \ + { /* on10 on11 */ \ + if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \ + && (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX))) \ + { \ + const bool XnE = colorX != colorE; \ + const bool XnF = colorX != colorF; \ + const bool XnG = colorX != colorG; \ + const bool XnH = colorX != colorH; \ + const bool DA = on00 && colorD == colorA && (XnE || XnG || colorD != colorH || colorA != colorF); \ + const bool AB = on10 && colorA == colorB && (XnF || XnH || colorA != colorE || colorB != colorG); \ + const bool BC = on11 && colorB == colorC && (XnG || XnE || colorB != colorF || colorC != colorH); \ + const bool CD = on01 && colorC == colorD && (XnH || XnF || colorC != colorG || colorD != colorE); \ + if (!on00||!on01||!on10||!on11 || ((colorA != colorC) && (colorB != colorD) && \ + ((colorX == colorA) || (colorX==colorB) || (colorX==colorC) || (colorX==colorD) || (colorX==colorE) || (colorX==colorF) || (colorX==colorG) || (colorX==colorH)))) \ + { \ + *dP1++ = _THREE_PIX(on00 && DA ? colorA : colorX, on00&&on01 && ((CD && XnE) || (DA && XnH)) ? colorD : colorX, on01 && CD ? colorC : colorX); \ + *dP2++ = _THREE_PIX(on00&&on10 && ((DA && XnF) || (AB && XnE)) ? colorA : colorX, colorX, on01&&on11 && ((BC && XnH) || (CD && XnG)) ? colorC : colorX); \ + *dP3++ = _THREE_PIX(on10 && AB ? colorA : colorX, on10&&on11 && ((AB && XnG) || (BC && XnF)) ? colorB : colorX, on11 && BC ? colorC : colorX); \ + } else { \ + *dP1++ = _THREE_PIX(on00 && DA && (colorX!=colorB&&colorX!=colorC) ? colorA : colorX, colorX, on01 && CD && (colorX!=colorA&&colorX!=colorB) ? colorC : colorX); \ + *dP2++ = _THREE_PIX(colorX,colorX,colorX); \ + *dP3++ = _THREE_PIX(on10 && AB && (colorX!=colorC&&colorX!=colorD) ? colorA : colorX, colorX, on11 && BC && (colorX!=colorD&&colorX!=colorA) ? colorC : colorX); \ + } \ + } else { \ + *dP1++ = _THREE_PIX(colorX, colorX, colorX); \ + *dP2++ = _THREE_PIX(colorX, colorX, colorX); \ + *dP3++ = _THREE_PIX(colorX, colorX, colorX); \ + } \ + } + + if(GUI.ScreenDepth == 32) + { +#define _THREE_PIX THREE_PIX_32 + DrawInit(3,uint96); // initialize with the scale and an int as big as 3 pixels + DrawRows(3,1); +#undef _THREE_PIX + } + else + { +#define _THREE_PIX THREE_PIX + DrawInit(3,uint48); + DrawRows(3,1); +#undef _THREE_PIX + } + + #undef DrawPix +} + +#define Interp44(c1, c2, c3, c4) \ + ((((((c1) & Mask_2) * 5 + ((c2) & Mask_2) + ((c3) & Mask_2) + ((c4) & Mask_2)) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 5 + ((c2) & Mask13) + ((c3) & Mask13) + ((c4) & Mask13)) >> 3) & Mask13)) + +#define Interp11(c1, c2) \ + ((((c1) == (c2)) ? (c1) : \ + (((((((c1) & Mask_2) * 3) + ((c2) & Mask_2) * 5) >> 3) & Mask_2) + \ + ((((((c1) & Mask13) * 3) + ((c2) & Mask13) * 5) >> 3) & Mask13)))) + +// EPX3 scaled down to 2X +void RenderEPXC (SSurface Src, SSurface Dst, RECT *rect) +{ + if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + {RenderSimple2X (Src, Dst, rect); return;} + + // E D H + // A X C + // F B G + #define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \ + { /* on10 on11 */ \ + if ((((on00||on10)?colorA:colorX) != ((on01||on11)?colorC:colorX)) \ + && (((on10||on11)?colorB:colorX) != ((on00||on01)?colorD:colorX))) \ + { \ + const bool XnE = colorX != colorE; \ + const bool XnF = colorX != colorF; \ + const bool XnG = colorX != colorG; \ + const bool XnH = colorX != colorH; \ + const bool DA = on00 && colorD == colorA && (XnE || XnG || colorD != colorH || colorA != colorF); \ + const bool AB = on10 && colorA == colorB && (XnF || XnH || colorA != colorE || colorB != colorG); \ + const bool BC = on11 && colorB == colorC && (XnG || XnE || colorB != colorF || colorC != colorH); \ + const bool CD = on01 && colorC == colorD && (XnH || XnF || colorC != colorG || colorD != colorE); \ + if (!on00||!on01||!on10||!on11 || ((colorA != colorC) && (colorB != colorD) && \ + ((colorX == colorA) || (colorX==colorB) || (colorX==colorC) || (colorX==colorD) || (colorX==colorE) || (colorX==colorF) || (colorX==colorG) || (colorX==colorH)))) \ + { \ + const uint16 colorAA = on00&&on10 && ((DA && XnF) || (AB && XnE)) ? colorA : colorX; \ + const uint16 colorBB = on10&&on11 && ((AB && XnG) || (BC && XnF)) ? colorB : colorX; \ + const uint16 colorCC = on01&&on11 && ((BC && XnH) || (CD && XnG)) ? colorC : colorX; \ + const uint16 colorDD = on00&&on01 && ((CD && XnE) || (DA && XnH)) ? colorD : colorX; \ + *dP1++ = _TWO_PIX(Interp44(on00 && DA ? colorA : colorX, colorDD, colorAA, colorX), Interp44(on01 && CD ? colorC : colorX, colorBB, colorCC, colorX)); \ + *dP2++ = _TWO_PIX(Interp44(on10 && AB ? colorA : colorX, colorAA, colorBB, colorX), Interp44(on11 && BC ? colorC : colorX, colorCC, colorDD, colorX)); \ + } else { \ + *dP1++ = _TWO_PIX(Interp01(colorX, on00 && DA && (colorX!=colorB&&colorX!=colorC) ? colorA : colorX), Interp01(colorX, on01 && CD && (colorX!=colorA&&colorX!=colorB) ? colorC : colorX)); \ + *dP2++ = _TWO_PIX(Interp01(colorX, on10 && AB && (colorX!=colorC&&colorX!=colorD) ? colorA : colorX), Interp01(colorX, on11 && BC && (colorX!=colorD&&colorX!=colorA) ? colorC : colorX)); \ + } \ + } else { \ + *dP1++ = _TWO_PIX(colorX, colorX); \ + *dP2++ = _TWO_PIX(colorX, colorX); \ + } \ + } + + if(GUI.ScreenDepth == 32) + { +#define _TWO_PIX TWO_PIX_32 + DrawInit(2,uint64); + DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels +#undef _TWO_PIX + } + else + { +#define _TWO_PIX TWO_PIX + DrawInit(2,uint32); + DrawRows(2,1); // 2x scale, and diags is on since we do use all 8 surrounding pixels +#undef _TWO_PIX + } + + #undef DrawPix +} + +void RenderTVMode3X (SSurface Src, SSurface Dst, RECT *rect) +{ + if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + {RenderSimple3X (Src, Dst, rect); return;} + + // E D H + // A X C + // F B G + + #define Interp05TQ(c1,c2) ThreeQuarters(Interp05(c1,c2)) + + #define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \ + { /* on10 on11 */ \ + if(!on00) {colorE = 0; if(!on01) {colorD = 0; colorX = Halve(colorX); }} \ + if(!on01) {colorH = 0; if(!on11) {colorC = 0; colorX = Halve(colorX); }} \ + if(!on10) {colorF = 0; if(!on00) {colorA = 0; colorX = Halve(colorX); }} \ + if(!on11) {colorG = 0; if(!on10) {colorB = 0; colorX = Halve(colorX); }} \ + if ((colorA == colorC) && (colorB == colorD) && (colorX == colorA) && (colorF == colorG) && (colorE == colorH) && (colorX == colorF) && (colorF == colorE)) \ + { \ + const uint16 colorX2 = ThreeQuarters(colorX); \ + *dP1++ = _THREE_PIX(colorX, colorX, colorX); \ + *dP2++ = _THREE_PIX(colorX, colorX, colorX); \ + *dP3++ = _THREE_PIX(colorX2, colorX2, colorX2); \ + } \ + else \ + { \ + *dP1++ = _THREE_PIX(Interp05((colorE&Mask_1)|(colorD&(Mask_3|Mask_2)), (colorA&Mask_1)|(colorX&(Mask_3|Mask_2))), \ + Interp05(colorD,colorX), \ + Interp05((colorD&(Mask_2|Mask_1))|(colorH&Mask_3), (colorX&(Mask_2|Mask_1))|(colorC&Mask_3))); \ + *dP2++ = _THREE_PIX(((colorA&Mask_1)|(colorX&(Mask_3|Mask_2))), \ + colorX, \ + ((colorX&(Mask_2|Mask_1))|(colorC&Mask_3))); \ + *dP3++ = _THREE_PIX(Interp05TQ((colorA&Mask_1)|(colorX&(Mask_3|Mask_2)), (colorF&Mask_1)|(colorB&(Mask_3|Mask_2))), \ + Interp05TQ(colorB,colorX), \ + Interp05TQ((colorX&(Mask_2|Mask_1))|(colorC&Mask_3), (colorB&(Mask_2|Mask_1))|(colorG&Mask_3))); \ + } \ + } + + if(GUI.ScreenDepth == 32) + { +#define _THREE_PIX THREE_PIX_32 + DrawInit(3,uint96); + DrawRows(3,1); +#undef _THREE_PIX + } + else + { +#define _THREE_PIX THREE_PIX + DrawInit(3,uint48); + DrawRows(3,1); +#undef _THREE_PIX + } + + #undef DrawPix +} + +void RenderDotMatrix3X (SSurface Src, SSurface Dst, RECT *rect) +{ + if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + {RenderSimple3X (Src, Dst, rect); return;} + + #define DrawPix(on00,on01,on10,on11) /* on00 on01 */ \ + { /* on10 on11 */ \ + const uint16 colorXA = COLOR_ADD(colorX,colorX); \ + const uint16 colorXS = COLOR_SUB(colorXA,colorX); \ + const uint16 colorX2 = COLOR_SUB(colorX,colorXS); \ + *dP1++ = _THREE_PIX(colorX2, colorX, colorX2); \ + *dP2++ = _THREE_PIX(colorX, colorXA, colorX); \ + *dP3++ = _THREE_PIX(colorX2, colorX, colorX2); \ + } + + if(GUI.ScreenDepth == 32) + { +#define _THREE_PIX THREE_PIX_32 + DrawInit(3,uint96); + DrawRows(3,0); +#undef _THREE_PIX + } + else + { +#define _THREE_PIX THREE_PIX + DrawInit(3,uint48); + DrawRows(3,0); +#undef _THREE_PIX + } + + #undef DrawPix +} + +#undef DoRow +#undef InitLine +#undef NextPixel +#undef DrawRows +#undef DrawInit + + + + + +//////////////////////////////////////////////////////////////////////////////// +// HQ2X stuff follows) +//////////////////////////////////////////////////////////////////////////////// + + + +#define Ymask 0xFF0000 +#define Umask 0x00FF00 +#define Vmask 0x0000FF +#define trY 0x300000 +#define trU 0x000700 +#define trV 0x000006 + + + + +#define Interp02(c1, c2, c3) \ + ((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 2) & Mask_2) + \ + (((((c1) & Mask13) * 2 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 2) & Mask13)) + +#define Interp06(c1, c2, c3) \ + ((((((c1) & Mask_2) * 5 + ((c2) & Mask_2) * 2 + ((c3) & Mask_2) ) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 5 + ((c2) & Mask13) * 2 + ((c3) & Mask13) ) >> 3) & Mask13)) + +#define Interp07(c1, c2, c3) \ + ((((((c1) & Mask_2) * 6 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 6 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 3) & Mask13)) + +#define Interp09(c1, c2, c3) \ + ((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) * 3 + ((c3) & Mask_2) * 3) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 2 + ((c2) & Mask13) * 3 + ((c3) & Mask13) * 3) >> 3) & Mask13)) + +#define Interp10(c1, c2, c3) \ + ((((((c1) & Mask_2) * 14 + ((c2) & Mask_2) + ((c3) & Mask_2) ) >> 4) & Mask_2) + \ + (((((c1) & Mask13) * 14 + ((c2) & Mask13) + ((c3) & Mask13) ) >> 4) & Mask13)) + +#define PIXEL00_0 *(dp) = w5 +#define PIXEL00_10 *(dp) = Interp01(w5, w1) +#define PIXEL00_11 *(dp) = Interp01(w5, w4) +#define PIXEL00_12 *(dp) = Interp01(w5, w2) +#define PIXEL00_20 *(dp) = Interp02(w5, w4, w2) +#define PIXEL00_21 *(dp) = Interp02(w5, w1, w2) +#define PIXEL00_22 *(dp) = Interp02(w5, w1, w4) +#define PIXEL00_60 *(dp) = Interp06(w5, w2, w4) +#define PIXEL00_61 *(dp) = Interp06(w5, w4, w2) +#define PIXEL00_70 *(dp) = Interp07(w5, w4, w2) +#define PIXEL00_90 *(dp) = Interp09(w5, w4, w2) +#define PIXEL00_100 *(dp) = Interp10(w5, w4, w2) + +#define PIXEL01_0 *(dp + 1) = w5 +#define PIXEL01_10 *(dp + 1) = Interp01(w5, w3) +#define PIXEL01_11 *(dp + 1) = Interp01(w5, w2) +#define PIXEL01_12 *(dp + 1) = Interp01(w5, w6) +#define PIXEL01_20 *(dp + 1) = Interp02(w5, w2, w6) +#define PIXEL01_21 *(dp + 1) = Interp02(w5, w3, w6) +#define PIXEL01_22 *(dp + 1) = Interp02(w5, w3, w2) +#define PIXEL01_60 *(dp + 1) = Interp06(w5, w6, w2) +#define PIXEL01_61 *(dp + 1) = Interp06(w5, w2, w6) +#define PIXEL01_70 *(dp + 1) = Interp07(w5, w2, w6) +#define PIXEL01_90 *(dp + 1) = Interp09(w5, w2, w6) +#define PIXEL01_100 *(dp + 1) = Interp10(w5, w2, w6) + +#define PIXEL10_0 *(dp + dst1line) = w5 +#define PIXEL10_10 *(dp + dst1line) = Interp01(w5, w7) +#define PIXEL10_11 *(dp + dst1line) = Interp01(w5, w8) +#define PIXEL10_12 *(dp + dst1line) = Interp01(w5, w4) +#define PIXEL10_20 *(dp + dst1line) = Interp02(w5, w8, w4) +#define PIXEL10_21 *(dp + dst1line) = Interp02(w5, w7, w4) +#define PIXEL10_22 *(dp + dst1line) = Interp02(w5, w7, w8) +#define PIXEL10_60 *(dp + dst1line) = Interp06(w5, w4, w8) +#define PIXEL10_61 *(dp + dst1line) = Interp06(w5, w8, w4) +#define PIXEL10_70 *(dp + dst1line) = Interp07(w5, w8, w4) +#define PIXEL10_90 *(dp + dst1line) = Interp09(w5, w8, w4) +#define PIXEL10_100 *(dp + dst1line) = Interp10(w5, w8, w4) + +#define PIXEL11_0 *(dp + dst1line + 1) = w5 +#define PIXEL11_10 *(dp + dst1line + 1) = Interp01(w5, w9) +#define PIXEL11_11 *(dp + dst1line + 1) = Interp01(w5, w6) +#define PIXEL11_12 *(dp + dst1line + 1) = Interp01(w5, w8) +#define PIXEL11_20 *(dp + dst1line + 1) = Interp02(w5, w6, w8) +#define PIXEL11_21 *(dp + dst1line + 1) = Interp02(w5, w9, w8) +#define PIXEL11_22 *(dp + dst1line + 1) = Interp02(w5, w9, w6) +#define PIXEL11_60 *(dp + dst1line + 1) = Interp06(w5, w8, w6) +#define PIXEL11_61 *(dp + dst1line + 1) = Interp06(w5, w6, w8) +#define PIXEL11_70 *(dp + dst1line + 1) = Interp07(w5, w6, w8) +#define PIXEL11_90 *(dp + dst1line + 1) = Interp09(w5, w6, w8) +#define PIXEL11_100 *(dp + dst1line + 1) = Interp10(w5, w6, w8) + +#define Absolute(c) \ +(!(c & (1 << 31)) ? c : (~c + 1)) + + +static inline bool Diff(int c1, int c2) +{ + int c1y = (c1 & Ymask) - (c2 & Ymask); + if (Absolute(c1y) > trY) return true; + int c1u = (c1 & Umask) - (c2 & Umask); + if (Absolute(c1u) > trU) return true; + int c1v = (c1 & Vmask) - (c2 & Vmask); + if (Absolute(c1v) > trV) return true; + + return false; +} + +void InitLUTsWin32(void) +{ + int c, r, g, b, y, u, v; + + for (c = 0 ; c < (1<> 3; + r = (int)((c & 0xF800)) >> 8; +#else + b = (int)((c & 0x1F)) << 3; + g = (int)((c & 0x3E0)) >> 2; + r = (int)((c & 0x7C00)) >> 7; +#endif + RGBtoBright[c] = r+r+r + g+g+g + b+b; + + y = (int)( 0.256788f*r + 0.504129f*g + 0.097906f*b + 0.5f) + 16; + u = (int)(-0.148223f*r - 0.290993f*g + 0.439216f*b + 0.5f) + 128; + v = (int)( 0.439216f*r - 0.367788f*g - 0.071427f*b + 0.5f) + 128; + + RGBtoYUV[c] = (y << 16) + (u << 8) + v; + } +} + +#define HQ2XCASES \ + case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: PIXEL00_20; PIXEL01_20; PIXEL10_20; PIXEL11_20; break; \ + case 2: case 34: case 130: case 162: PIXEL00_22; PIXEL01_21; PIXEL10_20; PIXEL11_20; break; \ + case 16: case 17: case 48: case 49: PIXEL00_20; PIXEL01_22; PIXEL10_20; PIXEL11_21; break; \ + case 64: case 65: case 68: case 69: PIXEL00_20; PIXEL01_20; PIXEL10_21; PIXEL11_22; break; \ + case 8: case 12: case 136: case 140: PIXEL00_21; PIXEL01_20; PIXEL10_22; PIXEL11_20; break; \ + case 3: case 35: case 131: case 163: PIXEL00_11; PIXEL01_21; PIXEL10_20; PIXEL11_20; break; \ + case 6: case 38: case 134: case 166: PIXEL00_22; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \ + case 20: case 21: case 52: case 53: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_21; break; \ + case 144: case 145: case 176: case 177: PIXEL00_20; PIXEL01_22; PIXEL10_20; PIXEL11_12; break; \ + case 192: case 193: case 196: case 197: PIXEL00_20; PIXEL01_20; PIXEL10_21; PIXEL11_11; break; \ + case 96: case 97: case 100: case 101: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_22; break; \ + case 40: case 44: case 168: case 172: PIXEL00_21; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \ + case 9: case 13: case 137: case 141: PIXEL00_12; PIXEL01_20; PIXEL10_22; PIXEL11_20; break; \ + case 18: case 50: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_20; PIXEL10_20; PIXEL11_21; break; \ + case 80: case 81: PIXEL00_20; PIXEL01_22; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_20; break; \ + case 72: case 76: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_20; PIXEL11_22; break; \ + case 10: case 138: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_20; PIXEL01_21; PIXEL10_22; PIXEL11_20; break; \ + case 66: PIXEL00_22; PIXEL01_21; PIXEL10_21; PIXEL11_22; break; \ + case 24: PIXEL00_21; PIXEL01_22; PIXEL10_22; PIXEL11_21; break; \ + case 7: case 39: case 135: PIXEL00_11; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \ + case 148: case 149: case 180: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_12; break; \ + case 224: case 228: case 225: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_11; break; \ + case 41: case 169: case 45: PIXEL00_12; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \ + case 22: case 54: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_20; PIXEL11_21; break; \ + case 208: case 209: PIXEL00_20; PIXEL01_22; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 104: case 108: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 11: case 139: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_22; PIXEL11_20; break; \ + case 19: case 51: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_10; else PIXEL00_60, PIXEL01_90; PIXEL10_20; PIXEL11_21; break; \ + case 146: case 178: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_20; break; \ + case 84: case 85: PIXEL00_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_10; else PIXEL01_60, PIXEL11_90; PIXEL10_21; break; \ + case 112: case 113: PIXEL00_20; PIXEL01_22; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_10; else PIXEL10_61, PIXEL11_90; break; \ + case 200: case 204: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \ + case 73: case 77: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_10; else PIXEL00_61, PIXEL10_90; PIXEL01_20; PIXEL11_22; break; \ + case 42: case 170: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_21; PIXEL11_20; break; \ + case 14: case 142: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_22; PIXEL11_20; break; \ + case 67: PIXEL00_11; PIXEL01_21; PIXEL10_21; PIXEL11_22; break; \ + case 70: PIXEL00_22; PIXEL01_12; PIXEL10_21; PIXEL11_22; break; \ + case 28: PIXEL00_21; PIXEL01_11; PIXEL10_22; PIXEL11_21; break; \ + case 152: PIXEL00_21; PIXEL01_22; PIXEL10_22; PIXEL11_12; break; \ + case 194: PIXEL00_22; PIXEL01_21; PIXEL10_21; PIXEL11_11; break; \ + case 98: PIXEL00_22; PIXEL01_21; PIXEL10_12; PIXEL11_22; break; \ + case 56: PIXEL00_21; PIXEL01_22; PIXEL10_11; PIXEL11_21; break; \ + case 25: PIXEL00_12; PIXEL01_22; PIXEL10_22; PIXEL11_21; break; \ + case 26: case 31: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_21; break; \ + case 82: case 214: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 88: case 248: PIXEL00_21; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 74: case 107: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 27: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_22; PIXEL11_21; break; \ + case 86: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; PIXEL11_10; break; \ + case 216: PIXEL00_21; PIXEL01_22; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 106: PIXEL00_10; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 30: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_21; break; \ + case 210: PIXEL00_22; PIXEL01_10; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 120: PIXEL00_21; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 75: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_10; PIXEL11_22; break; \ + case 29: PIXEL00_12; PIXEL01_11; PIXEL10_22; PIXEL11_21; break; \ + case 198: PIXEL00_22; PIXEL01_12; PIXEL10_21; PIXEL11_11; break; \ + case 184: PIXEL00_21; PIXEL01_22; PIXEL10_11; PIXEL11_12; break; \ + case 99: PIXEL00_11; PIXEL01_21; PIXEL10_12; PIXEL11_22; break; \ + case 57: PIXEL00_12; PIXEL01_22; PIXEL10_11; PIXEL11_21; break; \ + case 71: PIXEL00_11; PIXEL01_12; PIXEL10_21; PIXEL11_22; break; \ + case 156: PIXEL00_21; PIXEL01_11; PIXEL10_22; PIXEL11_12; break; \ + case 226: PIXEL00_22; PIXEL01_21; PIXEL10_12; PIXEL11_11; break; \ + case 60: PIXEL00_21; PIXEL01_11; PIXEL10_11; PIXEL11_21; break; \ + case 195: PIXEL00_11; PIXEL01_21; PIXEL10_21; PIXEL11_11; break; \ + case 102: PIXEL00_22; PIXEL01_12; PIXEL10_12; PIXEL11_22; break; \ + case 153: PIXEL00_12; PIXEL01_22; PIXEL10_22; PIXEL11_12; break; \ + case 58: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_21; break; \ + case 83: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 92: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 202: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \ + case 78: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_22; break; \ + case 154: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_22; PIXEL11_12; break; \ + case 114: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 89: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 90: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 55: case 23: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_0; else PIXEL00_60, PIXEL01_90; PIXEL10_20; PIXEL11_21; break; \ + case 182: case 150: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_20; break; \ + case 213: case 212: PIXEL00_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_0; else PIXEL01_60, PIXEL11_90; PIXEL10_21; break; \ + case 241: case 240: PIXEL00_20; PIXEL01_22; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_0; else PIXEL10_61, PIXEL11_90; break; \ + case 236: case 232: PIXEL00_21; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \ + case 109: case 105: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_0; else PIXEL00_61, PIXEL10_90; PIXEL01_20; PIXEL11_22; break; \ + case 171: case 43: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_21; PIXEL11_20; break; \ + case 143: case 15: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_22; PIXEL11_20; break; \ + case 124: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 203: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; PIXEL10_10; PIXEL11_11; break; \ + case 62: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_11; PIXEL11_21; break; \ + case 211: PIXEL00_11; PIXEL01_10; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 118: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_12; PIXEL11_10; break; \ + case 217: PIXEL00_12; PIXEL01_22; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 110: PIXEL00_10; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 155: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_22; PIXEL11_12; break; \ + case 188: PIXEL00_21; PIXEL01_11; PIXEL10_11; PIXEL11_12; break; \ + case 185: PIXEL00_12; PIXEL01_22; PIXEL10_11; PIXEL11_12; break; \ + case 61: PIXEL00_12; PIXEL01_11; PIXEL10_11; PIXEL11_21; break; \ + case 157: PIXEL00_12; PIXEL01_11; PIXEL10_22; PIXEL11_12; break; \ + case 103: PIXEL00_11; PIXEL01_12; PIXEL10_12; PIXEL11_22; break; \ + case 227: PIXEL00_11; PIXEL01_21; PIXEL10_12; PIXEL11_11; break; \ + case 230: PIXEL00_22; PIXEL01_12; PIXEL10_12; PIXEL11_11; break; \ + case 199: PIXEL00_11; PIXEL01_12; PIXEL10_21; PIXEL11_11; break; \ + case 220: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 158: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_22; PIXEL11_12; break; \ + case 234: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_11; break; \ + case 242: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 59: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_21; break; \ + case 121: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 87: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 79: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_22; break; \ + case 122: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 94: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 218: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 91: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 229: PIXEL00_20; PIXEL01_20; PIXEL10_12; PIXEL11_11; break; \ + case 167: PIXEL00_11; PIXEL01_12; PIXEL10_20; PIXEL11_20; break; \ + case 173: PIXEL00_12; PIXEL01_20; PIXEL10_11; PIXEL11_20; break; \ + case 181: PIXEL00_20; PIXEL01_11; PIXEL10_20; PIXEL11_12; break; \ + case 186: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_11; PIXEL11_12; break; \ + case 115: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 93: PIXEL00_12; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 206: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \ + case 205: case 201: PIXEL00_12; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_10; else PIXEL10_70; PIXEL11_11; break; \ + case 174: case 46: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_10; else PIXEL00_70; PIXEL01_12; PIXEL10_11; PIXEL11_20; break; \ + case 179: case 147: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_10; else PIXEL01_70; PIXEL10_20; PIXEL11_12; break; \ + case 117: case 116: PIXEL00_20; PIXEL01_11; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_10; else PIXEL11_70; break; \ + case 189: PIXEL00_12; PIXEL01_11; PIXEL10_11; PIXEL11_12; break; \ + case 231: PIXEL00_11; PIXEL01_12; PIXEL10_12; PIXEL11_11; break; \ + case 126: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 219: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 125: if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL00_12, PIXEL10_0; else PIXEL00_61, PIXEL10_90; PIXEL01_11; PIXEL11_10; break; \ + case 221: PIXEL00_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL01_11, PIXEL11_0; else PIXEL01_60, PIXEL11_90; PIXEL10_10; break; \ + case 207: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL01_12; else PIXEL00_90, PIXEL01_61; PIXEL10_10; PIXEL11_11; break; \ + case 238: PIXEL00_10; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0, PIXEL11_11; else PIXEL10_90, PIXEL11_60; break; \ + case 190: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0, PIXEL11_12; else PIXEL01_90, PIXEL11_61; PIXEL10_11; break; \ + case 187: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0, PIXEL10_11; else PIXEL00_90, PIXEL10_60; PIXEL01_10; PIXEL11_12; break; \ + case 243: PIXEL00_11; PIXEL01_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL10_12, PIXEL11_0; else PIXEL10_61, PIXEL11_90; break; \ + case 119: if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL00_11, PIXEL01_0; else PIXEL00_60, PIXEL01_90; PIXEL10_12; PIXEL11_10; break; \ + case 237: case 233: PIXEL00_12; PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \ + case 175: case 47: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; PIXEL10_11; PIXEL11_20; break; \ + case 183: case 151: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_20; PIXEL11_12; break; \ + case 245: case 244: PIXEL00_20; PIXEL01_11; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 250: PIXEL00_10; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 123: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 95: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_10; PIXEL11_10; break; \ + case 222: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 252: PIXEL00_21; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 249: PIXEL00_12; PIXEL01_22; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 235: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_21; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \ + case 111: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_22; break; \ + case 63: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_11; PIXEL11_21; break; \ + case 159: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_22; PIXEL11_12; break; \ + case 215: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_21; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 246: PIXEL00_22; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 254: PIXEL00_10; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 253: PIXEL00_12; PIXEL01_11; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 251: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; PIXEL01_10; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 239: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; PIXEL01_12; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; PIXEL11_11; break; \ + case 127: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_20; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_20; PIXEL11_10; break; \ + case 191: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_11; PIXEL11_12; break; \ + case 223: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_20; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_10; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_20; break; \ + case 247: PIXEL00_11; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; PIXEL10_12; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; \ + case 255: if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) PIXEL00_0; else PIXEL00_100; if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) PIXEL01_0; else PIXEL01_100; if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) PIXEL10_0; else PIXEL10_100; if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) PIXEL11_0; else PIXEL11_100; break; + +template +void RenderHQ2X (SSurface Src, SSurface Dst, RECT *rect) +{ + // If Snes9x is rendering anything in HiRes, then just copy, don't interpolate + if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + { + RenderSimple2X (Src, Dst, rect); + return; + } + + uint8 *srcPtr = Src.Surface; + uint8 *dstPtr = Dst.Surface; + uint32 srcPitch = Src.Pitch; + uint32 dstPitch = Dst.Pitch; + int width = Src.Width; + int height = Src.Height; + + SetRect(rect, 256, height, 2); + + dstPtr += rect->top * Dst.Pitch + rect->left * 2; + + if(GuiScale==FILTER_HQ2X) { + HQ2X_16(Src.Surface,Src.Pitch,dstPtr,Dst.Pitch,Src.Width,Src.Height); + return; + } + + int w1, w2, w3, w4, w5, w6, w7, w8, w9; + + uint32 src1line = srcPitch >> 1; + uint32 dst1line = dstPitch >> 1; + uint16 *sp = (uint16 *) srcPtr; + uint16 *dp = (uint16 *) dstPtr; + + const int* RGBtoYUVtable = RGBtoYUV; + + uint32 pattern; + int l, y; + + while (height--) + { + sp--; + + w1 = *(sp - src1line); + w4 = *(sp); + w7 = *(sp + src1line); + + sp++; + + w2 = *(sp - src1line); + w5 = *(sp); + w8 = *(sp + src1line); + + for (l = width; l; l--) + { + sp++; + + w3 = *(sp - src1line); + w6 = *(sp); + w9 = *(sp + src1line); + + pattern = 0; + + switch(GuiScale) + { + case FILTER_HQ2XBOLD: { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if ((w1 != w5) && ((RGBtoBright[w1] > avg) != diff5)) pattern |= (1 << 0); + if ((w2 != w5) && ((RGBtoBright[w2] > avg) != diff5)) pattern |= (1 << 1); + if ((w3 != w5) && ((RGBtoBright[w3] > avg) != diff5)) pattern |= (1 << 2); + if ((w4 != w5) && ((RGBtoBright[w4] > avg) != diff5)) pattern |= (1 << 3); + if ((w6 != w5) && ((RGBtoBright[w6] > avg) != diff5)) pattern |= (1 << 4); + if ((w7 != w5) && ((RGBtoBright[w7] > avg) != diff5)) pattern |= (1 << 5); + if ((w8 != w5) && ((RGBtoBright[w8] > avg) != diff5)) pattern |= (1 << 6); + if ((w9 != w5) && ((RGBtoBright[w9] > avg) != diff5)) pattern |= (1 << 7); + } break; + + case FILTER_HQ2XS: { + bool nosame = true; + if(w1 == w5 || w3 == w5 || w7 == w5 || w9 == w5) + nosame = false; + + if(nosame) + { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if((RGBtoBright[w1] > avg) != diff5) pattern |= (1 << 0); + if((RGBtoBright[w2] > avg) != diff5) pattern |= (1 << 1); + if((RGBtoBright[w3] > avg) != diff5) pattern |= (1 << 2); + if((RGBtoBright[w4] > avg) != diff5) pattern |= (1 << 3); + if((RGBtoBright[w6] > avg) != diff5) pattern |= (1 << 4); + if((RGBtoBright[w7] > avg) != diff5) pattern |= (1 << 5); + if((RGBtoBright[w8] > avg) != diff5) pattern |= (1 << 6); + if((RGBtoBright[w9] > avg) != diff5) pattern |= (1 << 7); + } + else + { + y = RGBtoYUV[w5]; + if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7); + } + } break; + default: + case FILTER_HQ2X: // never reached, normal hq is handled by the core hq files + y = RGBtoYUVtable[w5]; + if ((w1 != w5) && (Diff(y, RGBtoYUVtable[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUVtable[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUVtable[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUVtable[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUVtable[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUVtable[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUVtable[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUVtable[w9]))) pattern |= (1 << 7); + break; + } + + switch (pattern) + { + HQ2XCASES + } + + w1 = w2; w4 = w5; w7 = w8; + w2 = w3; w5 = w6; w8 = w9; + + dp += 2; + } + + dp += ((dst1line - width) << 1); + sp += (src1line - width); + } +} + + + + + + + + + + + + + + +#define PIXEL00_1M *(dp) = Interp01(w5, w1); +#define PIXEL00_1U *(dp) = Interp01(w5, w2); +#define PIXEL00_1L *(dp) = Interp01(w5, w4); +#define PIXEL00_2 *(dp) = Interp02(w5, w4, w2); +#define PIXEL00_4 *(dp) = Interp04(w5, w4, w2); +#define PIXEL00_5 *(dp) = Interp05(w4, w2); +#define PIXEL00_C *(dp) = w5; + +#define PIXEL01_1 *(dp + 1) = Interp01(w5, w2); +#define PIXEL01_3 *(dp + 1) = Interp03(w5, w2); +#define PIXEL01_6 *(dp + 1) = Interp01(w2, w5); +#define PIXEL01_C *(dp + 1) = w5; + +#define PIXEL02_1M *(dp + 2) = Interp01(w5, w3); +#define PIXEL02_1U *(dp + 2) = Interp01(w5, w2); +#define PIXEL02_1R *(dp + 2) = Interp01(w5, w6); +#define PIXEL02_2 *(dp + 2) = Interp02(w5, w2, w6); +#define PIXEL02_4 *(dp + 2) = Interp04(w5, w2, w6); +#define PIXEL02_5 *(dp + 2) = Interp05(w2, w6); +#define PIXEL02_C *(dp + 2) = w5; + +#define PIXEL10_1 *(dp + dst1line) = Interp01(w5, w4); +#define PIXEL10_3 *(dp + dst1line) = Interp03(w5, w4); +#define PIXEL10_6 *(dp + dst1line) = Interp01(w4, w5); +#define PIXEL10_C *(dp + dst1line) = w5; + +#define PIXEL11 *(dp + dst1line + 1) = w5; + +#define PIXEL12_1 *(dp + dst1line + 2) = Interp01(w5, w6); +#define PIXEL12_3 *(dp + dst1line + 2) = Interp03(w5, w6); +#define PIXEL12_6 *(dp + dst1line + 2) = Interp01(w6, w5); +#define PIXEL12_C *(dp + dst1line + 2) = w5; + +#define PIXEL20_1M *(dp + dst1line + dst1line) = Interp01(w5, w7); +#define PIXEL20_1D *(dp + dst1line + dst1line) = Interp01(w5, w8); +#define PIXEL20_1L *(dp + dst1line + dst1line) = Interp01(w5, w4); +#define PIXEL20_2 *(dp + dst1line + dst1line) = Interp02(w5, w8, w4); +#define PIXEL20_4 *(dp + dst1line + dst1line) = Interp04(w5, w8, w4); +#define PIXEL20_5 *(dp + dst1line + dst1line) = Interp05(w8, w4); +#define PIXEL20_C *(dp + dst1line + dst1line) = w5; + +#define PIXEL21_1 *(dp + dst1line + dst1line + 1) = Interp01(w5, w8); +#define PIXEL21_3 *(dp + dst1line + dst1line + 1) = Interp03(w5, w8); +#define PIXEL21_6 *(dp + dst1line + dst1line + 1) = Interp01(w8, w5); +#define PIXEL21_C *(dp + dst1line + dst1line + 1) = w5; + +#define PIXEL22_1M *(dp + dst1line + dst1line + 2) = Interp01(w5, w9); +#define PIXEL22_1D *(dp + dst1line + dst1line + 2) = Interp01(w5, w8); +#define PIXEL22_1R *(dp + dst1line + dst1line + 2) = Interp01(w5, w6); +#define PIXEL22_2 *(dp + dst1line + dst1line + 2) = Interp02(w5, w6, w8); +#define PIXEL22_4 *(dp + dst1line + dst1line + 2) = Interp04(w5, w6, w8); +#define PIXEL22_5 *(dp + dst1line + dst1line + 2) = Interp05(w6, w8); +#define PIXEL22_C *(dp + dst1line + dst1line + 2) = w5; + +#define Interp03(c1, c2) \ + (((c1 == c2) ? c1 : \ + ((((((c1) & Mask_2) * 7 + ((c2) & Mask_2)) >> 3) & Mask_2) + \ + (((((c1) & Mask13) * 7 + ((c2) & Mask13)) >> 3) & Mask13)))) + +#define Interp04(c1, c2, c3) \ + ((((((c1) & Mask_2) * 2 + ((c2) & Mask_2) * 7 + ((c3) & Mask_2) * 7) >> 4) & Mask_2) + \ + (((((c1) & Mask13) * 2 + ((c2) & Mask13) * 7 + ((c3) & Mask13) * 7) >> 4) & Mask13)) + +#define HQ3XCASES \ + case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 2: case 34: case 130: case 162: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 16: case 17: case 48: case 49: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 64: case 65: case 68: case 69: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 8: case 12: case 136: case 140: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 3: case 35: case 131: case 163: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 6: case 38: case 134: case 166: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 20: case 21: case 52: case 53: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 144: case 145: case 176: case 177: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\ + case 192: case 193: case 196: case 197: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 96: case 97: case 100: case 101: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 40: case 44: case 168: case 172: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\ + case 9: case 13: case 137: case 141: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 18: case 50: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_1M PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 80: case 81: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_1M } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 72: case 76: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_1M PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 10: case 138: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 66: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 24: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 7: case 39: case 135: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 148: case 149: case 180: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\ + case 224: case 228: case 225: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 41: case 169: case 45: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\ + case 22: case 54: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 208: case 209: { PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 104: case 108: { PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 11: case 139: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 19: case 51: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL12_C } else { PIXEL00_2 PIXEL01_6 PIXEL02_5 PIXEL12_1 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 146: case 178: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_1M PIXEL12_C PIXEL22_1D } else { PIXEL01_1 PIXEL02_5 PIXEL12_6 PIXEL22_2 } PIXEL00_1M PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 break; }\ + case 84: case 85: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL02_1U PIXEL12_C PIXEL21_C PIXEL22_1M } else { PIXEL02_2 PIXEL12_6 PIXEL21_1 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL10_1 PIXEL11 PIXEL20_1M break; }\ + case 112: case 113: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL20_1L PIXEL21_C PIXEL22_1M } else { PIXEL12_1 PIXEL20_2 PIXEL21_6 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 break; }\ + case 200: case 204: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_1M PIXEL21_C PIXEL22_1R } else { PIXEL10_1 PIXEL20_5 PIXEL21_6 PIXEL22_2 } PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 break; }\ + case 73: case 77: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL00_1U PIXEL10_C PIXEL20_1M PIXEL21_C } else { PIXEL00_2 PIXEL10_6 PIXEL20_5 PIXEL21_1 } PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 PIXEL22_1M break; }\ + case 42: case 170: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M PIXEL01_C PIXEL10_C PIXEL20_1D } else { PIXEL00_5 PIXEL01_1 PIXEL10_6 PIXEL20_2 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL21_1 PIXEL22_2 break; }\ + case 14: case 142: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_C } else { PIXEL00_5 PIXEL01_6 PIXEL02_2 PIXEL10_1 } PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 67: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 70: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 28: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 152: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 194: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 98: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 56: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 25: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 26: case 31: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL11 PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 82: case 214: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\ + case 88: case 248: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\ + case 74: case 107: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 27: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 86: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 216: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 106: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 30: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 210: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 120: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 75: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 29: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1M break; }\ + case 198: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 184: { PIXEL00_1M PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 99: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 57: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 71: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 156: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 226: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 60: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 195: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 102: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 153: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 58: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 83: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 92: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 202: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 78: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1M break; }\ + case 154: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 114: { PIXEL00_1M PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 89: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 90: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 55: case 23: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL00_1L PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL00_2 PIXEL01_6 PIXEL02_5 PIXEL12_1 } PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 PIXEL22_1M break; }\ + case 182: case 150: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C PIXEL22_1D } else { PIXEL01_1 PIXEL02_5 PIXEL12_6 PIXEL22_2 } PIXEL00_1M PIXEL10_1 PIXEL11 PIXEL20_2 PIXEL21_1 break; }\ + case 213: case 212: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL02_1U PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL02_2 PIXEL12_6 PIXEL21_1 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL10_1 PIXEL11 PIXEL20_1M break; }\ + case 241: case 240: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL20_1L PIXEL21_C PIXEL22_C } else { PIXEL12_1 PIXEL20_2 PIXEL21_6 PIXEL22_5 } PIXEL00_2 PIXEL01_1 PIXEL02_1M PIXEL10_1 PIXEL11 break; }\ + case 236: case 232: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C PIXEL22_1R } else { PIXEL10_1 PIXEL20_5 PIXEL21_6 PIXEL22_2 } PIXEL00_1M PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 break; }\ + case 109: case 105: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL00_1U PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL00_2 PIXEL10_6 PIXEL20_5 PIXEL21_1 } PIXEL01_1 PIXEL02_2 PIXEL11 PIXEL12_1 PIXEL22_1M break; }\ + case 171: case 43: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C PIXEL20_1D } else { PIXEL00_5 PIXEL01_1 PIXEL10_6 PIXEL20_2 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL21_1 PIXEL22_2 break; }\ + case 143: case 15: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL02_1R PIXEL10_C } else { PIXEL00_5 PIXEL01_6 PIXEL02_2 PIXEL10_1 } PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_1 PIXEL22_2 break; }\ + case 124: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 203: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 62: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 211: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 118: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 217: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 110: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 155: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 188: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 185: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 61: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 157: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 103: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 227: { PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 230: { PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 199: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 220: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 158: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 234: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1M PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1R break; }\ + case 242: { PIXEL00_1M PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL20_1L if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 59: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 121: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 87: { PIXEL00_1L if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_1 PIXEL11 PIXEL20_1M PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 79: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1R PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1M break; }\ + case 122: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 94: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 218: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 91: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 229: { PIXEL00_2 PIXEL01_1 PIXEL02_2 PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 167: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_2 PIXEL21_1 PIXEL22_2 break; }\ + case 173: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\ + case 181: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\ + case 186: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 115: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 93: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 206: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 205: case 201: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_1M } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 174: case 46: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_1M } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\ + case 179: case 147: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_1M } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\ + case 117: case 116: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_1M } else { PIXEL22_2 } break; }\ + case 189: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 231: { PIXEL00_1L PIXEL01_C PIXEL02_1R PIXEL10_1 PIXEL11 PIXEL12_1 PIXEL20_1L PIXEL21_C PIXEL22_1R break; }\ + case 126: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_4 PIXEL12_3 } PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 219: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_4 PIXEL01_3 PIXEL10_3 } PIXEL02_1M PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_4 } break; }\ + case 125: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL00_1U PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL00_2 PIXEL10_6 PIXEL20_5 PIXEL21_1 } PIXEL01_1 PIXEL02_1U PIXEL11 PIXEL12_C PIXEL22_1M break; }\ + case 221: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL02_1U PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL02_2 PIXEL12_6 PIXEL21_1 PIXEL22_5 } PIXEL00_1U PIXEL01_1 PIXEL10_C PIXEL11 PIXEL20_1M break; }\ + case 207: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL02_1R PIXEL10_C } else { PIXEL00_5 PIXEL01_6 PIXEL02_2 PIXEL10_1 } PIXEL11 PIXEL12_1 PIXEL20_1M PIXEL21_C PIXEL22_1R break; }\ + case 238: { if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C PIXEL22_1R } else { PIXEL10_1 PIXEL20_5 PIXEL21_6 PIXEL22_2 } PIXEL00_1M PIXEL01_C PIXEL02_1R PIXEL11 PIXEL12_1 break; }\ + case 190: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C PIXEL22_1D } else { PIXEL01_1 PIXEL02_5 PIXEL12_6 PIXEL22_2 } PIXEL00_1M PIXEL10_C PIXEL11 PIXEL20_1D PIXEL21_1 break; }\ + case 187: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C PIXEL20_1D } else { PIXEL00_5 PIXEL01_1 PIXEL10_6 PIXEL20_2 } PIXEL02_1M PIXEL11 PIXEL12_C PIXEL21_1 PIXEL22_1D break; }\ + case 243: { if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL20_1L PIXEL21_C PIXEL22_C } else { PIXEL12_1 PIXEL20_2 PIXEL21_6 PIXEL22_5 } PIXEL00_1L PIXEL01_C PIXEL02_1M PIXEL10_1 PIXEL11 break; }\ + case 119: { if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL00_1L PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL00_2 PIXEL01_6 PIXEL02_5 PIXEL12_1 } PIXEL10_1 PIXEL11 PIXEL20_1L PIXEL21_C PIXEL22_1M break; }\ + case 237: case 233: { PIXEL00_1U PIXEL01_1 PIXEL02_2 PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 175: case 47: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 PIXEL20_1D PIXEL21_1 PIXEL22_2 break; }\ + case 183: case 151: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_2 PIXEL21_1 PIXEL22_1D break; }\ + case 245: case 244: { PIXEL00_2 PIXEL01_1 PIXEL02_1U PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\ + case 250: { PIXEL00_1M PIXEL01_C PIXEL02_1M PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\ + case 123: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 95: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL11 PIXEL20_1M PIXEL21_C PIXEL22_1M break; }\ + case 222: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\ + case 252: { PIXEL00_1M PIXEL01_1 PIXEL02_1U PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\ + case 249: { PIXEL00_1U PIXEL01_1 PIXEL02_1M PIXEL10_C PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\ + case 235: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 111: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 63: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL10_C PIXEL11 PIXEL20_1D PIXEL21_1 PIXEL22_1M break; }\ + case 159: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL11 PIXEL12_C PIXEL20_1M PIXEL21_1 PIXEL22_1D break; }\ + case 215: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\ + case 246: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\ + case 254: { PIXEL00_1M if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C } else { PIXEL01_3 PIXEL02_4 } PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C } else { PIXEL10_3 PIXEL20_4 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL21_C PIXEL22_C } else { PIXEL12_3 PIXEL21_3 PIXEL22_2 } break; }\ + case 253: { PIXEL00_1U PIXEL01_1 PIXEL02_1U PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\ + case 251: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C } else { PIXEL00_4 PIXEL01_3 } PIXEL02_1M PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL10_C PIXEL20_C PIXEL21_C } else { PIXEL10_3 PIXEL20_2 PIXEL21_3 } if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL12_C PIXEL22_C } else { PIXEL12_3 PIXEL22_4 } break; }\ + case 239: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C PIXEL02_1R PIXEL10_C PIXEL11 PIXEL12_1 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C PIXEL22_1R break; }\ + case 127: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL01_C PIXEL10_C } else { PIXEL00_2 PIXEL01_3 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C PIXEL12_C } else { PIXEL02_4 PIXEL12_3 } PIXEL11 if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C PIXEL21_C } else { PIXEL20_4 PIXEL21_3 } PIXEL22_1M break; }\ + case 191: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C PIXEL20_1D PIXEL21_1 PIXEL22_1D break; }\ + case 223: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C PIXEL10_C } else { PIXEL00_4 PIXEL10_3 } if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL01_C PIXEL02_C PIXEL12_C } else { PIXEL01_3 PIXEL02_2 PIXEL12_3 } PIXEL11 PIXEL20_1M if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL21_C PIXEL22_C } else { PIXEL21_3 PIXEL22_4 } break; }\ + case 247: { PIXEL00_1L PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_1 PIXEL11 PIXEL12_C PIXEL20_1L PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; }\ + case 255: { if (Diff(RGBtoYUVtable[w4], RGBtoYUVtable[w2])) { PIXEL00_C } else { PIXEL00_2 } PIXEL01_C if (Diff(RGBtoYUVtable[w2], RGBtoYUVtable[w6])) { PIXEL02_C } else { PIXEL02_2 } PIXEL10_C PIXEL11 PIXEL12_C if (Diff(RGBtoYUVtable[w8], RGBtoYUVtable[w4])) { PIXEL20_C } else { PIXEL20_2 } PIXEL21_C if (Diff(RGBtoYUVtable[w6], RGBtoYUVtable[w8])) { PIXEL22_C } else { PIXEL22_2 } break; } + + +template +void RenderHQ3X (SSurface Src, SSurface Dst, RECT *rect) +{ + // If Snes9x is rendering anything in HiRes, then just copy, don't interpolate + if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + { + RenderSimple3X (Src, Dst, rect); + return; + } + + uint8 *srcPtr = Src.Surface; + uint8 *dstPtr = Dst.Surface; + uint32 srcPitch = Src.Pitch; + uint32 dstPitch = Dst.Pitch; + int width = Src.Width; + int height = Src.Height; + + SetRect(rect, 256, height, 3); + + dstPtr += rect->top * Dst.Pitch + rect->left * 2; + + if(GuiScale==FILTER_HQ2X) { + HQ3X_16(Src.Surface,Src.Pitch,dstPtr,Dst.Pitch,Src.Width,Src.Height); + return; + } + + int w1, w2, w3, w4, w5, w6, w7, w8, w9; + + uint32 src1line = srcPitch >> 1; + uint32 dst1line = dstPitch >> 1; + uint16 *sp = (uint16 *) srcPtr; + uint16 *dp = (uint16 *) dstPtr; + + const int* RGBtoYUVtable = RGBtoYUV; + + uint32 pattern; + int l, y; + + while (height--) + { + sp--; + + w1 = *(sp - src1line); + w4 = *(sp); + w7 = *(sp + src1line); + + sp++; + + w2 = *(sp - src1line); + w5 = *(sp); + w8 = *(sp + src1line); + + for (l = width; l; l--) + { + sp++; + + w3 = *(sp - src1line); + w6 = *(sp); + w9 = *(sp + src1line); + + pattern = 0; + + switch(GuiScale) + { + case FILTER_HQ3XBOLD: { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if ((w1 != w5) && ((RGBtoBright[w1] > avg) != diff5)) pattern |= (1 << 0); + if ((w2 != w5) && ((RGBtoBright[w2] > avg) != diff5)) pattern |= (1 << 1); + if ((w3 != w5) && ((RGBtoBright[w3] > avg) != diff5)) pattern |= (1 << 2); + if ((w4 != w5) && ((RGBtoBright[w4] > avg) != diff5)) pattern |= (1 << 3); + if ((w6 != w5) && ((RGBtoBright[w6] > avg) != diff5)) pattern |= (1 << 4); + if ((w7 != w5) && ((RGBtoBright[w7] > avg) != diff5)) pattern |= (1 << 5); + if ((w8 != w5) && ((RGBtoBright[w8] > avg) != diff5)) pattern |= (1 << 6); + if ((w9 != w5) && ((RGBtoBright[w9] > avg) != diff5)) pattern |= (1 << 7); + } break; + + case FILTER_HQ3XS: { + bool nosame = true; + if(w1 == w5 || w3 == w5 || w7 == w5 || w9 == w5) + nosame = false; + + if(nosame) + { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if((RGBtoBright[w1] > avg) != diff5) pattern |= (1 << 0); + if((RGBtoBright[w2] > avg) != diff5) pattern |= (1 << 1); + if((RGBtoBright[w3] > avg) != diff5) pattern |= (1 << 2); + if((RGBtoBright[w4] > avg) != diff5) pattern |= (1 << 3); + if((RGBtoBright[w6] > avg) != diff5) pattern |= (1 << 4); + if((RGBtoBright[w7] > avg) != diff5) pattern |= (1 << 5); + if((RGBtoBright[w8] > avg) != diff5) pattern |= (1 << 6); + if((RGBtoBright[w9] > avg) != diff5) pattern |= (1 << 7); + } + else + { + y = RGBtoYUV[w5]; + if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7); + } + } break; + default: + case FILTER_HQ3X: // never reached, normal hq is handled by the core hq files + y = RGBtoYUVtable[w5]; + if ((w1 != w5) && (Diff(y, RGBtoYUVtable[w1]))) pattern |= (1 << 0); + if ((w2 != w5) && (Diff(y, RGBtoYUVtable[w2]))) pattern |= (1 << 1); + if ((w3 != w5) && (Diff(y, RGBtoYUVtable[w3]))) pattern |= (1 << 2); + if ((w4 != w5) && (Diff(y, RGBtoYUVtable[w4]))) pattern |= (1 << 3); + if ((w6 != w5) && (Diff(y, RGBtoYUVtable[w6]))) pattern |= (1 << 4); + if ((w7 != w5) && (Diff(y, RGBtoYUVtable[w7]))) pattern |= (1 << 5); + if ((w8 != w5) && (Diff(y, RGBtoYUVtable[w8]))) pattern |= (1 << 6); + if ((w9 != w5) && (Diff(y, RGBtoYUVtable[w9]))) pattern |= (1 << 7); + break; + } + + switch (pattern) + { + HQ3XCASES + } + + w1 = w2; w4 = w5; w7 = w8; + w2 = w3; w5 = w6; w8 = w9; + + dp += 3; + } + + dp += ((dst1line - width) * 3); + sp += (src1line - width); + } +} + + +#undef Interp02 +#undef Interp06 +#undef Interp07 +#undef Interp10 +#undef Interp03 +#undef Interp01 +#undef Interp09 +#undef Interp04 +#define Interp02(c1, c2, c3) (c1) // choose majority +#define Interp06(c1, c2, c3) (c1) +#define Interp07(c1, c2, c3) (c1) +#define Interp10(c1, c2, c3) (c1) +#define Interp03(c1, c2) (c1) +#define Interp01(c1, c2) (c1) +#define Interp09(c1, c2, c3) Interp05(c2,c3) // 50/50 split of majority +#define Interp04(c1, c2, c3) Interp05(c2,c3) + +// same as RenderHQ3XB except mostly choosing colors instead of blending them +void RenderLQ3XB (SSurface Src, SSurface Dst, RECT *rect) +{ + // If Snes9x is rendering anything in HiRes, then just copy, don't interpolate + if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + { + RenderSimple3X (Src, Dst, rect); + return; + } + + uint8 *srcPtr = Src.Surface; + uint8 *dstPtr = Dst.Surface; + uint32 srcPitch = Src.Pitch; + uint32 dstPitch = Dst.Pitch; + int width = Src.Width; + int height = Src.Height; + + SetRect(rect, 256, height, 3); + + dstPtr += rect->top * Dst.Pitch + rect->left * 2; + int w1, w2, w3, w4, w5, w6, w7, w8, w9; + + uint32 src1line = srcPitch >> 1; + uint32 dst1line = dstPitch >> 1; + uint16 *sp = (uint16 *) srcPtr; + uint16 *dp = (uint16 *) dstPtr; + + const int* RGBtoYUVtable = RGBtoYUV; + + uint32 pattern; + int l;//, y; + + while (height--) + { + sp--; + + w1 = *(sp - src1line); + w4 = *(sp); + w7 = *(sp + src1line); + + sp++; + + w2 = *(sp - src1line); + w5 = *(sp); + w8 = *(sp + src1line); + + for (l = width; l; l--) + { + sp++; + + w3 = *(sp - src1line); + w6 = *(sp); + w9 = *(sp + src1line); + + pattern = 0; + + { + const uint16 avg = (RGBtoBright[w1] + RGBtoBright[w2] + RGBtoBright[w3] + RGBtoBright[w4] + RGBtoBright[w5] + RGBtoBright[w6] + RGBtoBright[w7] + RGBtoBright[w8] + RGBtoBright[w9]) / 9; + const bool diff5 = RGBtoBright[w5] > avg; + if ((w1 != w5) && ((RGBtoBright[w1] > avg) != diff5)) pattern |= (1 << 0); + if ((w2 != w5) && ((RGBtoBright[w2] > avg) != diff5)) pattern |= (1 << 1); + if ((w3 != w5) && ((RGBtoBright[w3] > avg) != diff5)) pattern |= (1 << 2); + if ((w4 != w5) && ((RGBtoBright[w4] > avg) != diff5)) pattern |= (1 << 3); + if ((w6 != w5) && ((RGBtoBright[w6] > avg) != diff5)) pattern |= (1 << 4); + if ((w7 != w5) && ((RGBtoBright[w7] > avg) != diff5)) pattern |= (1 << 5); + if ((w8 != w5) && ((RGBtoBright[w8] > avg) != diff5)) pattern |= (1 << 6); + if ((w9 != w5) && ((RGBtoBright[w9] > avg) != diff5)) pattern |= (1 << 7); + } + + switch (pattern) + { + HQ3XCASES + } + + w1 = w2; w4 = w5; w7 = w8; + w2 = w3; w5 = w6; w8 = w9; + + dp += 3; + } + + dp += ((dst1line - width) * 3); + sp += (src1line - width); + } +} + + +#undef Interp02 +#undef Interp06 +#undef Interp07 +#undef Interp10 +#undef Interp03 +#undef Interp01 +#undef Interp09 +#undef Interp04 + +static void DoubleHeightInPlace ( uint16 *lpSurface, unsigned int surfaceRowPixels, unsigned int width, unsigned int height) +{ + unsigned int targetHeight=height*2; + uint16 *lpSrc=lpSurface+surfaceRowPixels*height; + uint16 *lpDst=lpSurface+surfaceRowPixels*targetHeight; + for(int i=targetHeight;i;i-=2) { + memcpy(lpDst,lpSrc,width*2),lpDst-=surfaceRowPixels, + memcpy(lpDst,lpSrc,width*2),lpDst-=surfaceRowPixels; + lpSrc-=surfaceRowPixels; + } +} + +static void DoubleWidthInPlace ( uint16 *lpSurface, unsigned int surfaceRowPixels, unsigned int width, unsigned int height) +{ + unsigned int targetWidth=width*2; + uint16 *lpSrc=lpSurface+width+height*surfaceRowPixels; + uint16 *lpDst=lpSurface+targetWidth+height*surfaceRowPixels; + for(int i=height;i;i--) { + for(int j=width;j;j--) { + *lpDst-- = *lpSrc; + *lpDst-- = *lpSrc; + lpSrc--; + } + lpSrc-=(surfaceRowPixels - width); + lpDst-=(surfaceRowPixels - targetWidth); + } +} + +void RenderHQ4X (SSurface Src, SSurface Dst, RECT *rect) +{ + uint8 *dstPtr = Dst.Surface; + + SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 4); + dstPtr += rect->top * Dst.Pitch + rect->left * 2; + + if (Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + { + HQ2X_16(Src.Surface,Src.Pitch,dstPtr,Dst.Pitch,Src.Width,Src.Height); + if(Src.Height<=SNES_HEIGHT_EXTENDED) + DoubleHeightInPlace((uint16 *)dstPtr,Dst.Pitch>>1,Src.Width*2,Src.Height*2); + else if(Src.Width==SNES_WIDTH) + DoubleWidthInPlace((uint16 *)dstPtr,Dst.Pitch>>1,Src.Width*2,Src.Height*2); + return; + } + + HQ4X_16(Src.Surface,Src.Pitch,dstPtr,Dst.Pitch,Src.Width,Src.Height); +} + +void RenderSimple4X( SSurface Src, SSurface Dst, RECT *rect) +{ + uint16 *lpSrc; + unsigned int H; + + SetRect(rect, SNES_WIDTH, SNES_HEIGHT_EXTENDED, 4); + const uint32 srcHeight = (rect->bottom - rect->top)/4; + + const unsigned int srcPitch = Src.Pitch >> 1; + lpSrc = reinterpret_cast(Src.Surface); + + if(GUI.ScreenDepth == 16) + { + const unsigned int dstPitch = Dst.Pitch >> 1; + uint16 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + if (Src.Height <= SNES_HEIGHT_EXTENDED) + if(Src.Width != 512) + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + if(Src.Width != 512) + for (H = 0; H < Src.Height; H++, lpSrc += srcPitch) + QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + QuadrupleLine16 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < Src.Height; H++, lpSrc += srcPitch) + DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine16(lpDst, lpSrc, Src.Width), lpDst += dstPitch; + } + else if(GUI.ScreenDepth == 32) + { + const unsigned int dstPitch = Dst.Pitch >> 2; + uint32 *lpDst = reinterpret_cast(Dst.Surface) + rect->top * dstPitch + rect->left; + if (Src.Height <= SNES_HEIGHT_EXTENDED) + if(Src.Width != 512) + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < srcHeight; H++, lpSrc += srcPitch) + DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + if(Src.Width != 512) + for (H = 0; H < Src.Height; H++, lpSrc += srcPitch) + QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch, + QuadrupleLine32 (lpDst, lpSrc, Src.Width), lpDst += dstPitch; + else + for (H = 0; H < Src.Height; H++, lpSrc += srcPitch) + DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch, + DoubleLine32(lpDst, lpSrc, Src.Width), lpDst += dstPitch; + } +} + + +enum BlarggMode { UNINITIALIZED,BLARGGCOMPOSITE,BLARGGSVIDEO,BLARGGRGB }; + +snes_ntsc_t *ntsc = NULL; +BlarggMode blarggMode = UNINITIALIZED; + +void RenderBlarggNTSCComposite( SSurface Src, SSurface Dst, RECT *rect) +{ + if(!ntsc) { + ntsc = (snes_ntsc_t *)malloc(sizeof(snes_ntsc_t)); + } + if(blarggMode!=BLARGGCOMPOSITE) { + snes_ntsc_setup_t setup = snes_ntsc_composite; + setup.merge_fields = 1; + snes_ntsc_init( ntsc, &setup ); + blarggMode=BLARGGCOMPOSITE; + } + RenderBlarggNTSC(Src,Dst,rect); +} + +void RenderBlarggNTSCSvideo( SSurface Src, SSurface Dst, RECT *rect) +{ + if(!ntsc) { + ntsc = (snes_ntsc_t *)malloc(sizeof(snes_ntsc_t)); + } + if(blarggMode!=BLARGGSVIDEO) { + snes_ntsc_setup_t setup = snes_ntsc_svideo; + setup.merge_fields = 1; + snes_ntsc_init( ntsc, &setup ); + blarggMode=BLARGGSVIDEO; + } + RenderBlarggNTSC(Src,Dst,rect); +} + +void RenderBlarggNTSCRgb( SSurface Src, SSurface Dst, RECT *rect) +{ + if(!ntsc) { + ntsc = (snes_ntsc_t *)malloc(sizeof(snes_ntsc_t)); + } + if(blarggMode!=BLARGGRGB) { + snes_ntsc_setup_t setup = snes_ntsc_rgb; + setup.merge_fields = 1; + snes_ntsc_init( ntsc, &setup ); + blarggMode=BLARGGRGB; + } + RenderBlarggNTSC(Src,Dst,rect); +} + +void RenderBlarggNTSC( SSurface Src, SSurface Dst, RECT *rect) +{ + SetRect(rect, 256, 239, 2); + rect->right = 604; + + const unsigned int srcRowPixels = Src.Pitch/2; + + if(Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) + snes_ntsc_blit_hires( ntsc, (unsigned short *)Src.Surface, srcRowPixels, 0,Src.Width, Src.Height, Dst.Surface, Dst.Pitch ); + else + snes_ntsc_blit( ntsc, (unsigned short *)Src.Surface, srcRowPixels, 0,Src.Width, Src.Height, Dst.Surface, Dst.Pitch ); + + //Blargg's filter produces half-height output, so we have to double the height again (unless we have double height hi-res) + if(Src.Height <= SNES_HEIGHT_EXTENDED) + for (int y = rect->bottom / 2; --y >= 0; ) + { + unsigned char const* in = Dst.Surface + y * Dst.Pitch; + unsigned char* out = Dst.Surface + y * 2 * Dst.Pitch; + for (int n = rect->right; n; --n ) + { + unsigned prev = *(unsigned short*) in; + unsigned next = *(unsigned short*) (in + Dst.Pitch); + /* mix 16-bit rgb without losing low bits */ + unsigned mixed = prev + next + ((prev ^ next) & 0x0821); + /* darken by 12% */ + *(unsigned short*) out = prev; + *(unsigned short*) (out + Dst.Pitch) = (mixed >> 1) - (mixed >> 4 & 0x18E3); + in += 2; + out += 2; + } + } + +} diff --git a/win32/render.h b/win32/render.h new file mode 100644 index 00000000..2ad453df --- /dev/null +++ b/win32/render.h @@ -0,0 +1,202 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 RENDER_H +#define RENDER_H + + +/* Render.h + * ---------- + * This file contains all the prototypes, structers and variables used and defined by render.cpp + */ + +struct SSurface { + unsigned char *Surface; + + unsigned int Pitch; + unsigned int Width, Height; +}; + +typedef void (*TRenderMethod)( SSurface Src, SSurface Dst, RECT *); + +void SelectRenderMethod(); +void InitLUTsWin32(); + +extern TRenderMethod RenderMethod; +extern TRenderMethod RenderMethodHiRes; + +#endif \ No newline at end of file diff --git a/win32/rsrc/bitmap2.bmp b/win32/rsrc/bitmap2.bmp new file mode 100644 index 00000000..7ed8de7d Binary files /dev/null and b/win32/rsrc/bitmap2.bmp differ diff --git a/win32/rsrc/cdd.bmp b/win32/rsrc/cdd.bmp new file mode 100644 index 00000000..845a2698 Binary files /dev/null and b/win32/rsrc/cdd.bmp differ diff --git a/win32/rsrc/closedfold.bmp b/win32/rsrc/closedfold.bmp new file mode 100644 index 00000000..d6ecab90 Binary files /dev/null and b/win32/rsrc/closedfold.bmp differ diff --git a/win32/rsrc/hd.bmp b/win32/rsrc/hd.bmp new file mode 100644 index 00000000..07a2f78a Binary files /dev/null and b/win32/rsrc/hd.bmp differ diff --git a/win32/rsrc/hiddir.bmp b/win32/rsrc/hiddir.bmp new file mode 100644 index 00000000..292998c2 Binary files /dev/null and b/win32/rsrc/hiddir.bmp differ diff --git a/win32/rsrc/icon1.ico b/win32/rsrc/icon1.ico new file mode 100644 index 00000000..cd889bcb Binary files /dev/null and b/win32/rsrc/icon1.ico differ diff --git a/win32/rsrc/nd.bmp b/win32/rsrc/nd.bmp new file mode 100644 index 00000000..0c70fa77 Binary files /dev/null and b/win32/rsrc/nd.bmp differ diff --git a/win32/rsrc/nodrop.cur b/win32/rsrc/nodrop.cur new file mode 100644 index 00000000..f5358492 Binary files /dev/null and b/win32/rsrc/nodrop.cur differ diff --git a/win32/rsrc/openfold.bmp b/win32/rsrc/openfold.bmp new file mode 100644 index 00000000..475746c5 Binary files /dev/null and b/win32/rsrc/openfold.bmp differ diff --git a/win32/rsrc/pad.bmp b/win32/rsrc/pad.bmp new file mode 100644 index 00000000..62d43b41 Binary files /dev/null and b/win32/rsrc/pad.bmp differ diff --git a/win32/rsrc/ram.bmp b/win32/rsrc/ram.bmp new file mode 100644 index 00000000..ffdf96f7 Binary files /dev/null and b/win32/rsrc/ram.bmp differ diff --git a/win32/rsrc/rd.bmp b/win32/rsrc/rd.bmp new file mode 100644 index 00000000..8b649030 Binary files /dev/null and b/win32/rsrc/rd.bmp differ diff --git a/win32/rsrc/resource.h b/win32/rsrc/resource.h new file mode 100644 index 00000000..f237fc14 --- /dev/null +++ b/win32/rsrc/resource.h @@ -0,0 +1,485 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by snes9x.rc +// +#define IDR_RT_MANIFEST2 1 +#define IDR_MENU_US 101 +#define IDC_CURSOR_SCOPE 101 +#define IDC_CURSOR_BLANK 102 +#define IDD_SOUND_OPTS 102 +#define IDR_SNES9X_ACCELERATORS 103 +#define IDD_ROM_INFO 104 +#define IDD_ABOUT 105 +#define IDD_EMU_SETTINGS 106 +#define IDD_OPEN_ROM 107 +#define IDD_NETCONNECT 109 +#define IDD_NPOPTIONS 110 +#define IDB_OPENFOLDER 111 +#define IDD_CHEATER 111 +#define IDB_CLOSEDFOLDER 112 +#define IDB_CDDRIVE 113 +#define IDB_NETDRIVE 114 +#define IDB_HARDDRIVE 115 +#define IDD_NEWDISPLAY 123 +#define IDD_NETPLAYPROGRESS 124 +#define IDD_INPUTCONFIG 125 +#define IDB_JOYPAD 127 +#define IDD_CHEAT_SEARCH 129 +#define IDD_CHEAT_FROM_SEARCH 131 +#define IDB_PAD 133 +#define IDD_OPENMOVIE 134 +#define IDD_CREATEMOVIE 135 +#define IDD_KEYCUSTOM 136 +#define IDI_ICON1 144 +#define IDB_REMOVABLE 145 +#define IDB_RAMDISK 146 +#define IDB_UNKNOWN 147 +#define IDB_LOCKEDFOLDER 148 +#define IDB_HIDDENFOLDER 149 +#define IDD_MULTICART 150 +#define IDC_DRIVER 1001 +#define IDC_BUFLEN 1002 +#define IDC_RATE 1003 +#define IDC_MIX 1004 +#define IDC_16BIT 1005 +#define IDC_STEREO 1006 +#define IDC_REV_STEREO 1007 +#define IDC_LINEAR_INTER 1008 +#define IDC_SYNC_TO_SOUND_CPU 1009 +#define IDC_ECHO 1011 +#define IDC_CLEARSRAM 1011 +#define IDC_CACHING 1012 +#define IDC_MASTER_VOL 1013 +#define IDC_SPC700ON 1014 +#define IDC_ANTIRES 1015 +#define IDC_MUTE 1016 +#define IDC_SKIP_TYPE 1017 +#define IDC_SCROLLBAR1 1018 +#define IDC_FMUT 1018 +#define IDC_VRAM_DISPLAY 1019 +#define IDC_WIP1 1019 +#define IDC_ADDRESS 1020 +#define IDC_FAMT 1020 +#define IDC_ROM_DATA 1051 +#define IDC_WARNINGS 1052 +#define IDC_DISCLAIMER 1053 +#define IDC_CUSTOM_FOLDER_FIELD 1054 +#define IDC_BROWSE 1055 +#define IDC_CANCEL 1056 +#define IDC_AUTO_SAVE_DELAY 1057 +#define IDC_MAX_SKIP 1058 +#define IDC_TURBO_SKIP 1059 +#define IDC_TOGGLE_TURBO 1060 +#define IDC_SRAM_SPIN 1061 +#define IDC_SPIN_MAX_SKIP 1062 +#define IDC_SPIN_TURBO_SKIP 1063 +#define IDC_ROM_DIR 1064 +#define IDC_INACTIVE_PAUSE 1064 +#define IDC_INTERLEAVE 1065 +#define IDC_CONFIG_NAME_BOX 1065 +#define IDC_VIDEO_MODE 1066 +#define IDC_CUSTOMROMOPEN 1066 +#define IDC_HEADER 1067 +#define IDC_ROMLIST 1068 +#define IDC_MEM_TYPE 1069 +#define IDC_HOSTNAME 1086 +#define IDC_PORTNUMBER 1087 +#define IDC_CLEARHISTORY 1088 +#define IDC_STATIC2 1089 +#define IDC_MULTICART_BIOSNOTFOUND 1089 +#define IDC_EDIT1 1090 +#define IDC_UP 1090 +#define IDC_VALUE_ENTER 1090 +#define IDC_MOVIE_METADATA 1090 +#define IDC_MULTICART_EDITA 1090 +#define IDC_INRATEEDIT 1090 +#define IDC_PAUSEINTERVAL 1091 +#define IDC_UPRIGHT 1091 +#define IDC_MULTICART_BIOSEDIT 1091 +#define IDC_SKIPCOUNT 1091 +#define IDC_MAXSKIP 1092 +#define IDC_MULTICART_EDITB 1092 +#define IDC_PAUSESPIN 1093 +#define IDC_DWNRIGHT 1093 +#define IDC_SYNCBYRESET 1094 +#define IDC_DOWN 1094 +#define IDC_SENDROM 1095 +#define IDC_DWNLEFT 1095 +#define IDC_ACTASSERVER 1096 +#define IDC_LEFT 1096 +#define IDC_MAXSPIN 1097 +#define IDC_UPLEFT 1097 +#define IDC_SELECT 1098 +#define IDC_PORTNUMBERA 1099 +#define IDC_START 1099 +#define IDC_L 1100 +#define IDC_VIDEOLIST 1101 +#define IDC_R 1101 +#define IDC_SELECT2 1101 +#define IDC_Y 1102 +#define IDC_B 1103 +#define IDC_A 1104 +#define IDC_X 1105 +#define IDC_RIGHT 1106 +#define IDC_SHOWFPS 1108 +#define IDC_STRETCH 1109 +#define IDC_FULLSCREEN 1110 +#define IDC_EMUFULLSCREEN 1111 +#define IDC_TRANS 1113 +#define IDC_HIRES 1114 +#define IDC_CHEAT_CODE 1115 +#define IDC_FILTERBOX 1116 +#define IDC_FILTERBOX2 1117 +#define IDC_AUTOFRAME 1118 +#define IDC_LIMITFRAMES 1119 +#define IDC_FRAMERATESKIPSLIDER 1120 +#define IDC_TOGGLE 1121 +#define IDC_DBLBUFFER 1122 +#define IDC_CURRMODE 1123 +#define IDC_DELETE_CHEAT 1124 +#define IDC_NPPROGRESS 1124 +#define IDC_BILINEAR 1124 +#define IDC_UPDATE_CHEAT 1125 +#define IDC_JPCOMBO 1125 +#define IDC_HIRESLABEL 1125 +#define IDC_CLEAR_CHEATS 1126 +#define IDC_JPTOGGLE 1126 +#define IDC_LOCALVIDMEM 1126 +#define IDC_CHEAT_DESCRIPTION 1127 +#define IDC_KEYBOARD 1127 +#define IDC_ALLOWLEFTRIGHT 1127 +#define IDC_CHEAT_ADDRESS 1128 +#define IDC_CHEAT_BYTE 1129 +#define IDC_ADD_CHEAT 1130 +#define IDC_CHEAT_LIST 1131 +#define IDC_PICTURE 1132 +#define IDC_ADDYS 1133 +#define IDC_OK 1134 +#define IDC_C_SEARCH 1134 +#define IDC_RED 1135 +#define IDC_C_ADD 1135 +#define IDC_BLUE 1136 +#define IDC_C_RESET 1136 +#define IDC_LABEL_BLUE 1136 +#define IDC_1_BYTE 1137 +#define IDC_2_BYTE 1138 +#define IDC_3_BYTE 1139 +#define IDC_4_BYTE 1140 +#define IDC_LESS_THAN 1141 +#define IDC_GREATER_THAN 1142 +#define IDC_LESS_THAN_EQUAL 1143 +#define IDC_GREATER_THAN_EQUAL 1144 +#define IDC_EQUAL 1145 +#define IDC_NOT_EQUAL 1146 +#define IDC_UNSIGNED 1149 +#define IDC_SIGNED 1150 +#define IDC_HEX 1151 +#define IDC_ENTER_LABEL 1152 +#define IDC_DIAGTOGGLE 1153 +#define IDC_C_WATCH 1153 +#define IDC_UNDO 1154 +#define IDC_C_CLEARWATCH 1154 +#define IDC_COMBO1 1155 +#define IDC_C_LOADWATCH 1155 +#define IDC_OUTPUTMETHOD 1155 +#define IDC_NC_ADDRESS 1156 +#define IDC_C_SAVEWATCH 1156 +#define IDC_ASPECTDROP 1156 +#define IDC_NC_CURRVAL 1157 +#define IDC_RESOLUTION 1157 +#define IDC_NC_PREVVAL 1158 +#define IDC_NC_NEWVAL 1159 +#define IDC_NC_DESC 1160 +#define IDC_LABEL_UP 1161 +#define IDC_LABEL_LEFT 1162 +#define IDC_LABEL_DOWN 1163 +#define IDC_LABEL_RIGHT 1164 +#define IDC_LABEL_B 1165 +#define IDC_LABEL_A 1166 +#define IDC_LABEL_Y 1167 +#define IDC_LABEL_RIGHT2 1167 +#define IDC_LABEL_X 1168 +#define IDC_LABEL_START 1169 +#define IDC_LABEL_SELECT 1170 +#define IDC_LABEL_L 1171 +#define IDC_LABEL_R 1172 +#define IDC_LABEL_UPLEFT 1173 +#define IDC_LABEL_R2 1173 +#define IDC_LABEL_UPRIGHT 1174 +#define IDC_LABEL_R3 1174 +#define IDC_LABEL_DOWNRIGHT 1175 +#define IDC_LABEL_DOWNLEFT 1176 +#define IDC_LABEL_FREEZE 1177 +#define IDC_LABEL_ASRAM 1178 +#define IDC_LABEL_SMAX 1179 +#define IDC_LABEL_STURBO 1180 +#define IDC_LABEL_ASRAM_TEXT 1181 +#define IDC_LABEL_UP2 1181 +#define IDC_LABEL_SMAX_TEXT 1182 +#define IDC_LABEL_UP3 1182 +#define IDC_LABEL_STURBO_TEXT 1183 +#define IDC_LABEL_UP4 1183 +#define IDC_PORTNUMBLOCK 1184 +#define IDC_LABEL_UP5 1184 +#define IDC_CLIENTSETTINGSBLOCK 1185 +#define IDC_LABEL_UP6 1185 +#define IDC_SERVERSETTINGSBLOCK 1186 +#define IDC_LABEL_UP7 1186 +#define IDC_LABEL_PORTNUM 1187 +#define IDC_LABEL_UP8 1187 +#define IDC_LABEL_PAUSEINTERVAL 1188 +#define IDC_LABEL_UP9 1188 +#define IDC_LABEL_PAUSEINTERVAL_TEXT 1189 +#define IDC_LABEL_UP10 1189 +#define IDC_LABEL_MAXSKIP 1190 +#define IDC_LABEL_UP11 1190 +#define IDC_LABEL_CHEAT_CODE 1191 +#define IDC_LABEL_UP12 1191 +#define IDC_LABEL_CHEAT_DESCRIPTION 1192 +#define IDC_LABEL_UP13 1192 +#define IDC_LABEL_CHEAT_ADDRESS 1193 +#define IDC_LABEL_UP14 1193 +#define IDC_LABEL_CHEAT_BYTE 1194 +#define IDC_LABEL_UP15 1194 +#define IDC_LABEL_SERVERADDY 1195 +#define IDC_LABEL_UP16 1195 +#define IDC_LABEL_UP17 1196 +#define IDC_LABEL_UP18 1197 +#define IDC_HEIGHT_EXTEND 1198 +#define IDC_LABEL_UP19 1198 +#define IDC_ASPECT 1199 +#define IDC_MESSAGES_IN_IMAGE 1200 +#define IDC_RECORD_NOW 1201 +#define IDC_RECORD_RESET 1202 +#define IDC_JOY1 1203 +#define IDC_JOY2 1204 +#define IDC_JOY3 1205 +#define IDC_JOY4 1206 +#define IDC_JOY5 1207 +#define IDC_MOVIE_PATH 1208 +#define IDC_SAVE1 1208 +#define IDC_BROWSE_MOVIE 1209 +#define IDC_SAVE2 1209 +#define IDC_MOVIE_DATE 1210 +#define IDC_SAVE3 1210 +#define IDC_MOVIE_LENGTH 1211 +#define IDC_SAVE4 1211 +#define IDC_MOVIE_FRAMES 1212 +#define IDC_SAVE5 1212 +#define IDC_MOVIE_RERECORD 1213 +#define IDC_SAVE6 1213 +#define IDC_SAVE7 1214 +#define IDC_SAVE8 1215 +#define IDC_LOADEDFROMMOVIE 1215 +#define IDC_SAVE9 1216 +#define IDC_MOVIEROMINFO 1216 +#define IDC_SAVE10 1217 +#define IDC_CURRENTROMINFO 1217 +#define IDC_SAVE11 1219 +#define IDC_DISPLAY_INPUT 1220 +#define IDC_SAVE12 1220 +#define IDC_SAVE13 1221 +#define IDC_SAVE14 1222 +#define IDC_SAVE15 1223 +#define IDC_SAVE16 1224 +#define IDC_SAVE17 1225 +#define IDC_SAVE18 1226 +#define IDC_SAVE19 1227 +#define IDC_SAVE20 1228 +#define IDC_LABEL_UP20 1229 +#define IDC_LABEL_UP21 1230 +#define IDC_LABEL_UP22 1234 +#define IDC_SLOTMINUS 1235 +#define IDC_LABEL_UP23 1236 +#define IDC_SLOTPLUS 1237 +#define IDC_LABEL_UP24 1238 +#define IDC_SLOTSAVE 1239 +#define IDC_LABEL_UP25 1240 +#define IDC_SLOTLOAD 1241 +#define IDC_READONLY 1242 +#define IDC_HKCOMBO 1243 +#define IDC_LABEL_HK1 1244 +#define IDC_LABEL_HK2 1245 +#define IDC_LABEL_HK3 1246 +#define IDC_LABEL_HK4 1247 +#define IDC_LABEL_HK5 1248 +#define IDC_LABEL_HK6 1249 +#define IDC_LABEL_HK7 1250 +#define IDC_LABEL_HK8 1251 +#define IDC_LABEL_HK9 1252 +#define IDC_LABEL_HK10 1253 +#define IDC_LABEL_HK11 1254 +#define IDC_LABEL_HK12 1255 +#define IDC_LABEL_HK13 1256 +#define IDC_PLAYWARN 1257 +#define IDC_HOTKEY1 2000 +#define IDC_HOTKEY2 2001 +#define IDC_HOTKEY3 2002 +#define IDC_HOTKEY4 2003 +#define IDC_HOTKEY5 2004 +#define IDC_HOTKEY6 2005 +#define IDC_HOTKEY7 2006 +#define IDC_HOTKEY8 2007 +#define IDC_HOTKEY9 2008 +#define IDC_HOTKEY10 2009 +#define IDC_HOTKEY11 2010 +#define IDC_HOTKEY12 2011 +#define IDC_HOTKEY13 2012 +#define IDC_PREV 2147 +#define IDC_ENTERED 2148 +#define IDC_ENTEREDADDRESS 2157 +#define IDC_REFRESHLIST 2158 +#define IDC_DIRCOMBO 3000 +#define IDC_LABEL_MOVIEINFOBOX 3002 +#define IDC_LABEL_STARTSETTINGS 3003 +#define IDC_LABEL_CONTROLLERSETTINGS 3004 +#define IDC_LABEL_SYNCSETTINGS 3005 +#define IDC_MULTICART_SWAP 3006 +#define IDC_MULTICART_CLEARA 3007 +#define IDC_MULTICART_CLEARB 3008 +#define IDC_MULTICART_BROWSEA 3009 +#define IDC_MULTICART_BROWSEB 3010 +#define IDC_FIXEDSKIP 3011 +#define IDC_INRATE 3011 +#define IDC_INRATETEXT 3012 +#define IDC_SPIN_MAX_SKIP_DISP 3013 +#define IDC_SPIN_MAX_SKIP_DISP_FIXED 3014 +#define ID_FILE_EXIT 40001 +#define ID_LANGUAGE_ENGLISH 40002 +#define ID_LANGUAGE_NEDERLANDS 40003 +#define ID_WINDOW_HIDEMENUBAR 40004 +#define ID_SOUND_NOSOUND 40021 +#define ID_OPTIONS_JOYPAD 40022 +#define ID_WINDOW_SHOWFPS 40023 +#define ID_OPTIONS_DISPLAY 40024 +#define ID_FILE_RESET 40025 +#define ID_FILE_PAUSE 40026 +#define ID_SOUND_INTERPOLATED 40027 +#define ID_SOUND_SYNC 40028 +#define ID_WINDOW_FULLSCREEN 40029 +#define ID_SOUND_16BIT 40030 +#define ID_SOUND_STEREO 40031 +#define ID_WINDOW_STRETCH 40032 +#define ID_SOUND_8000HZ 40033 +#define ID_SOUND_11025HZ 40034 +#define ID_SOUND_22050HZ 40035 +#define ID_SOUND_44100HZ 40036 +#define ID_SOUND_30000HZ 40037 +#define ID_FILE_SAVE1 40045 +#define ID_FILE_SAVE2 40046 +#define ID_FILE_SAVE3 40047 +#define ID_FILE_SAVE4 40048 +#define ID_FILE_SAVE5 40049 +#define ID_FILE_SAVE6 40050 +#define ID_FILE_SAVE7 40051 +#define ID_FILE_SAVE8 40052 +#define ID_FILE_SAVE9 40053 +#define ID_FILE_LOAD1 40054 +#define ID_FILE_LOAD2 40055 +#define ID_FILE_LOAD3 40056 +#define ID_FILE_LOAD4 40057 +#define ID_FILE_LOAD5 40058 +#define ID_FILE_LOAD6 40059 +#define ID_FILE_LOAD7 40060 +#define ID_FILE_LOAD8 40061 +#define ID_FILE_LOAD9 40062 +#define ID_CHEAT_ENTER 40063 +#define ID_CHEAT_SEARCH 40064 +#define ID_CHEAT_APPLY 40065 +#define ID_HELP_ABOUT 40067 +#define ID_SOUND_OPTIONS 40068 +#define ID_OPTIONS_EMULATION 40069 +#define ID_OPTIONS_SETTINGS 40070 +#define ID_DEBUG_TRACE 40071 +#define ID_DEBUG_TRACE_SPC 40072 +#define ID_DEBUG_TRACE_SA1 40073 +#define ID_DEBUG_TRACE_DSP1 40074 +#define ID_DEBUG_FRAME_ADVANCE 40075 +#define ID_DEBUG_SNES_STATUS 40076 +#define ID_NETPLAY_SERVER 40077 +#define ID_NETPLAY_CONNECT 40078 +#define ID_NETPLAY_DISCONNECT 40079 +#define ID_NETPLAY_OPTIONS 40080 +#define ID_NETPLAY_ROM 40081 +#define ID_NETPLAY_SYNC 40082 +#define ID_NETPLAY_SEND_ROM_ON_CONNECT 40083 +#define ID_NETPLAY_SYNC_BY_RESET 40084 +#define ID_SOUND_48000HZ 40085 +#define ID_SOUND_16000HZ 40086 +#define ID_SOUND_35000HZ 40087 +#define ID_SOUND_REVERSE_STEREO 40088 +#define ID_FILE_SAVE_SRAM_DATA 40089 +#define ID_RECENT_DUMMY 40090 +#define IDM_ROM_INFO 40094 +#define ID_SOUND_32000HZ 40095 +#define ID_TURBO_START 40096 +#define ID_TURBO_SELECT 40097 +#define ID_TURBO_L 40098 +#define ID_TURBO_R 40099 +#define ID_TURBO_Y 40100 +#define ID_TURBO_X 40101 +#define ID_TURBO_B 40102 +#define ID_TURBO_A 40103 +#define IDM_ENABLE_MULTITAP 40104 +#define IDM_MOUSE_TOGGLE 40105 +#define IDM_SCOPE_TOGGLE 40106 +#define IDM_CATCH_UP_SOUND 40107 +#define IDM_GFX_PACKS 40108 +#define IDM_JUSTIFIER 40109 +#define ID_SCREENSHOT 40110 +#define ID_FILE_MOVIE_PLAY 40113 +#define ID_FILE_MOVIE_STOP 40114 +#define ID_FILE_MOVIE_RECORD 40115 +#define ID_FILE_MOVIE_ENABLERECORDING 40116 +#define ID_FILE_WRITE_AVI 40116 +#define ID_FILE_STOP_AVI 40117 +#define ID_OPTIONS_KEYCUSTOM 40118 +#define ID_WINDOW_ 40119 +#define ID_WINDOW_VIDMEM 40122 +#define ID_WINDOW_ASPECTRATIO 40123 +#define ID_TURBO_LEFT 40124 +#define ID_TURBO_UP 40125 +#define ID_TURBO_RIGHT 40126 +#define ID_TURBO_DOWN 40127 +#define IDM_MOUSE_SWAPPED 40133 +#define IDM_JUSTIFIERS 40134 +#define IDM_MULTITAP8 40135 +#define IDM_SNES_JOYPAD 40137 +#define ID_SOUND_CHANNELS 40138 +#define ID_CHANNELS_CHANNEL1 40139 +#define ID_CHANNELS_CHANNEL2 40140 +#define ID_CHANNELS_CHANNEL3 40141 +#define ID_CHANNELS_CHANNEL4 40142 +#define ID_CHANNELS_CHANNEL5 40143 +#define ID_CHANNELS_CHANNEL6 40144 +#define ID_CHANNELS_CHANNEL7 40145 +#define ID_CHANNELS_CHANNEL8 40146 +#define ID_CHANNELS_ENABLEALL 40147 +#define ID_CHEAT_SEARCH_MODAL 40148 +#define ID_SAVESCREENSHOT 40151 +#define ID_FILE_LOAD_GAME 40152 +#define ID_FILE_LOADMULTICART 40153 +#define ID_SOUND_16MS 40154 +#define ID_SOUND_32MS 40155 +#define ID_SOUND_48MS 40156 +#define ID_SOUND_64MS 40157 +#define ID_SOUND_80MS 40158 +#define ID_SOUND_96MS 40159 +#define ID_SOUND_112MS 40160 +#define ID_SOUND_128MS 40161 +#define ID_SOUND_144MS 40162 +#define ID_SOUND_160MS 40163 +#define ID_SOUND_176MS 40164 +#define ID_SOUND_194MS 40165 +#define ID_SOUND_210MS 40166 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 151 +#define _APS_NEXT_COMMAND_VALUE 40154 +#define _APS_NEXT_CONTROL_VALUE 3014 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/win32/rsrc/rodir.bmp b/win32/rsrc/rodir.bmp new file mode 100644 index 00000000..02b49944 Binary files /dev/null and b/win32/rsrc/rodir.bmp differ diff --git a/win32/rsrc/snes9x.rc b/win32/rsrc/snes9x.rc new file mode 100644 index 00000000..06da198e --- /dev/null +++ b/win32/rsrc/snes9x.rc @@ -0,0 +1,987 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +IDC_CURSOR_SCOPE CURSOR "nodrop.cur" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_SNES9X_ACCELERATORS ACCELERATORS +BEGIN + "E", ID_CHEAT_ENTER, VIRTKEY, ALT, NOINVERT + "A", ID_CHEAT_SEARCH, VIRTKEY, ALT, NOINVERT + "O", ID_FILE_LOAD_GAME, VIRTKEY, CONTROL, NOINVERT + VK_F5, ID_OPTIONS_DISPLAY, VIRTKEY, ALT, NOINVERT + VK_F7, ID_OPTIONS_JOYPAD, VIRTKEY, ALT, NOINVERT + VK_F9, ID_OPTIONS_KEYCUSTOM, VIRTKEY, ALT, NOINVERT + VK_F8, ID_OPTIONS_SETTINGS, VIRTKEY, ALT, NOINVERT + "[", ID_SOUND_INTERPOLATED, ASCII, ALT, NOINVERT + "T", ID_SOUND_OPTIONS, VIRTKEY, ALT, NOINVERT + "R", ID_SOUND_REVERSE_STEREO, VIRTKEY, ALT, NOINVERT + "]", ID_SOUND_SYNC, ASCII, ALT, NOINVERT + VK_RETURN, ID_WINDOW_FULLSCREEN, VIRTKEY, ALT, NOINVERT + VK_BACK, ID_WINDOW_STRETCH, VIRTKEY, ALT, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SOUND_OPTS DIALOGEX 0, 0, 300, 144 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "Sound Settings" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + GROUPBOX "Sound Quality",IDC_STATIC,7,7,286,112,0,WS_EX_TRANSPARENT + DEFPUSHBUTTON "&OK",IDOK,178,120,56,16 + COMBOBOX IDC_DRIVER,65,24,106,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Sound Driver:",IDC_STATIC,13,25,49,11 + COMBOBOX IDC_BUFLEN,65,56,106,101,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Buffer Length:",IDC_STATIC,13,58,49,11 + COMBOBOX IDC_RATE,65,40,106,171,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Playback Rate:",IDC_STATIC,13,41,49,11 + CONTROL "&16 Bit playback",IDC_16BIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,24,96,10 + CONTROL "&Stereo",IDC_STEREO,"Button",BS_AUTOCHECKBOX | BS_NOTIFY | WS_TABSTOP,183,38,93,10 + CONTROL "&Reverse Stereo",IDC_REV_STEREO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,53,94,10 + CONTROL "&Synchronize with sound core",IDC_SYNC_TO_SOUND_CPU, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,68,102,10 + PUSHBUTTON "&Cancel",IDCANCEL,237,120,56,16 + CONTROL "&Mute sound",IDC_MUTE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,83,93,12 + CONTROL "Frame Advance mu&te",IDC_FAMT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,183,98,90,12 + CONTROL "",IDC_INRATE,"msctls_trackbar32",TBS_AUTOTICKS | TBS_BOTH | WS_TABSTOP,12,88,157,26 + EDITTEXT IDC_INRATEEDIT,65,74,105,12,ES_AUTOHSCROLL | ES_NUMBER + LTEXT "Input Rate:",IDC_INRATETEXT,14,74,46,11 +END + +IDD_ROM_INFO DIALOG 0, 0, 233, 185 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "Rom Info" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,85,164,50,14 + EDITTEXT IDC_ROM_DATA,7,7,219,146,ES_MULTILINE | ES_READONLY + LTEXT "",IDC_WARNINGS,7,145,219,15,SS_CENTERIMAGE +END + +IDD_ABOUT DIALOGEX 0, 0, 232, 181 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "APP - About Dialog" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,90,160,50,14 + EDITTEXT IDC_DISCLAIMER,7,7,218,148,ES_MULTILINE | ES_NOHIDESEL | ES_READONLY,WS_EX_STATICEDGE +END + +IDD_EMU_SETTINGS DIALOGEX 0, 0, 319, 148 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "APP - Emulator Settings" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + EDITTEXT IDC_CUSTOM_FOLDER_FIELD,91,28,163,14,ES_AUTOHSCROLL + PUSHBUTTON "&Browse...",IDC_BROWSE,264,27,48,14 + EDITTEXT IDC_AUTO_SAVE_DELAY,91,47,49,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "Spin2",IDC_SRAM_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,301,51,11,13 + EDITTEXT IDC_MAX_SKIP,91,66,49,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "Spin3",IDC_SPIN_MAX_SKIP,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,298,70,11,13 + EDITTEXT IDC_TURBO_SKIP,91,85,49,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "Spin4",IDC_SPIN_TURBO_SKIP,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,296,94,11,13 + CONTROL "Toggled Turbo Mode",IDC_TOGGLE_TURBO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,103,123,12 + DEFPUSHBUTTON "&OK",IDOK,215,127,46,14 + PUSHBUTTON "&Cancel",IDCANCEL,266,127,46,14 + RTEXT "Directory",IDC_LABEL_FREEZE,53,28,32,14,SS_CENTERIMAGE + RTEXT "Auto-Save S-RAM",IDC_LABEL_ASRAM,21,47,64,14,SS_CENTERIMAGE + RTEXT "Skip at most",IDC_LABEL_SMAX,40,66,45,14,SS_CENTERIMAGE + RTEXT "Skip rendering",IDC_LABEL_STURBO,32,85,51,14,SS_CENTERIMAGE + LTEXT "seconds after last change (0 disables auto-save)",IDC_LABEL_ASRAM_TEXT,146,47,161,14,SS_CENTERIMAGE + LTEXT "frames in auto-frame rate mode",IDC_LABEL_SMAX_TEXT,146,66,138,14,SS_CENTERIMAGE + LTEXT "frames in Turbo mode",IDC_LABEL_STURBO_TEXT,146,85,92,14,SS_CENTERIMAGE + CONTROL "Pause When Inactive",IDC_INACTIVE_PAUSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,116,100,12 + LTEXT "Config file",IDC_STATIC,54,11,34,11 + EDITTEXT IDC_CONFIG_NAME_BOX,91,9,49,14,ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER + LTEXT "all of Snes9x's settings are stored in this file",IDC_STATIC,147,11,160,11 + COMBOBOX IDC_DIRCOMBO,7,29,44,30,CBS_DROPDOWNLIST | WS_TABSTOP + CONTROL "Custom ROM Open Dialog",IDC_CUSTOMROMOPEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,91,130,117,12 +END + +IDD_OPEN_ROM DIALOGEX 0, 0, 430, 223 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "Open ROM" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + CONTROL "Tree1",IDC_ROM_DIR,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | TVS_NOTOOLTIPS | WS_BORDER | WS_TABSTOP,4,4,154,192,WS_EX_CLIENTEDGE + CONTROL "List1",IDC_ROMLIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_OWNERDATA | WS_TABSTOP,161,4,266,192,WS_EX_CLIENTEDGE + COMBOBOX IDC_MEM_TYPE,5,208,66,57,CBS_DROPDOWNLIST | WS_TABSTOP + COMBOBOX IDC_INTERLEAVE,85,208,89,64,CBS_DROPDOWNLIST | WS_TABSTOP + COMBOBOX IDC_VIDEO_MODE,182,208,66,61,CBS_DROPDOWNLIST | WS_TABSTOP + COMBOBOX IDC_HEADER,256,208,73,44,CBS_DROPDOWNLIST | WS_TABSTOP + DEFPUSHBUTTON "&Open ROM",IDOK,335,205,44,15 + PUSHBUTTON "&Cancel",IDCANCEL,380,205,44,15 + LTEXT "Interleave Mode:",IDC_STATIC,85,198,69,8,NOT WS_GROUP + LTEXT "Memory Type:",IDC_STATIC,5,198,58,10,NOT WS_GROUP + LTEXT "Video System:",IDC_STATIC,181,198,54,8,NOT WS_GROUP + LTEXT "Header:",IDC_STATIC,256,198,54,8,NOT WS_GROUP +END + +IDD_NPOPTIONS DIALOGEX 0, 0, 187, 161 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION +CAPTION "Netplay Options" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + GROUPBOX "Port Settings",IDC_PORTNUMBLOCK,5,5,180,25,0,WS_EX_TRANSPARENT + RTEXT "Socket Port Number",IDC_LABEL_PORTNUM,10,15,85,10,SS_CENTERIMAGE + EDITTEXT IDC_PORTNUMBERA,100,15,25,12,ES_RIGHT | ES_AUTOHSCROLL + GROUPBOX "Client Settings",IDC_CLIENTSETTINGSBLOCK,5,35,180,40,0,WS_EX_TRANSPARENT + RTEXT "Ask Server to Pause when",IDC_LABEL_PAUSEINTERVAL,10,45,85,10,SS_CENTERIMAGE + EDITTEXT IDC_PAUSEINTERVAL,100,45,30,12,ES_RIGHT | ES_AUTOHSCROLL + CONTROL "Spin1",IDC_PAUSESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | WS_TABSTOP,120,45,10,12 + LTEXT "frames behind",IDC_LABEL_PAUSEINTERVAL_TEXT,135,45,45,12,SS_CENTERIMAGE + RTEXT "Maximum Frame Rate Skip",IDC_LABEL_MAXSKIP,10,60,85,10,SS_CENTERIMAGE + EDITTEXT IDC_MAXSKIP,100,60,30,12,ES_RIGHT | ES_AUTOHSCROLL + CONTROL "Spin2",IDC_MAXSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | WS_TABSTOP,120,60,10,12 + GROUPBOX "Server Settings",IDC_SERVERSETTINGSBLOCK,5,80,180,60,0,WS_EX_TRANSPARENT + CONTROL "Send ROM Image to Client on Connect",IDC_SENDROM,"Button",BS_AUTOCHECKBOX | BS_LEFT | BS_VCENTER | WS_TABSTOP,10,105,173,15 + CONTROL "Act as Server",IDC_ACTASSERVER,"Button",BS_AUTOCHECKBOX | BS_LEFT | BS_VCENTER | WS_TABSTOP,10,120,174,15 + DEFPUSHBUTTON "OK",IDOK,80,145,50,14 + PUSHBUTTON "Cancel",IDCANCEL,135,145,50,14 + CONTROL "Sync By Reset",IDC_SYNCBYRESET,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,90,174,15 +END + +IDD_NEWDISPLAY DIALOGEX 0, 0, 353, 184 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION +CAPTION "Display Settings" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,239,163,50,14 + PUSHBUTTON "Cancel",IDCANCEL,296,163,50,14 + COMBOBOX IDC_OUTPUTMETHOD,68,17,101,38,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "Fullscreen",IDC_FULLSCREEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,36,48,10 + CONTROL "Emulate Fullscreen",IDC_EMUFULLSCREEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,47,75,10 + CONTROL "Stretch Image",IDC_STRETCH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,58,60,10 + CONTROL "Maintain Aspect Ratio",IDC_ASPECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,69,81,8 + COMBOBOX IDC_ASPECTDROP,104,67,63,41,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "Bilinear Filtering",IDC_BILINEAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,80,75,8 + CONTROL "Show Frame Rate",IDC_SHOWFPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,91,73,8 + CONTROL "Automatic",IDC_AUTOFRAME,"Button",BS_AUTORADIOBUTTON,11,126,43,8 + CONTROL "Fixed",IDC_FIXEDSKIP,"Button",BS_AUTORADIOBUTTON,11,143,43,10 + EDITTEXT IDC_MAXSKIP,133,125,35,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SPIN_MAX_SKIP_DISP,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,169,127,11,13 + EDITTEXT IDC_SKIPCOUNT,133,142,35,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "",IDC_SPIN_MAX_SKIP_DISP_FIXED,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,169,139,11,13 + COMBOBOX IDC_FILTERBOX,186,17,153,90,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_FILTERBOX2,217,33,122,90,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Resolution",IDC_CURRMODE,187,71,41,8 + COMBOBOX IDC_RESOLUTION,234,69,105,95,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "Enable Triple Buffering",IDC_DBLBUFFER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,187,85,87,10 + CONTROL "Transparency Effects",IDC_TRANS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,187,113,153,10 + CONTROL "Hi Resolution Support",IDC_HIRES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,187,124,85,10 + CONTROL "Extend Height of SNES Image",IDC_HEIGHT_EXTEND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,187,135,111,10 + CONTROL "Display messages before applying filters",IDC_MESSAGES_IN_IMAGE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,187,146,140,10 + GROUPBOX "Frame Skipping:",IDC_STATIC,7,113,167,46,0,WS_EX_TRANSPARENT + GROUPBOX "SNES Image",IDC_STATIC,180,103,166,57,0,WS_EX_TRANSPARENT + GROUPBOX "Output Image Processing",IDC_STATIC,179,7,166,46,0,WS_EX_TRANSPARENT + GROUPBOX "Fullscreen Display Settings",IDC_STATIC,179,56,166,44,0,WS_EX_TRANSPARENT + LTEXT "Hi Res:",IDC_HIRESLABEL,186,36,31,8 + GROUPBOX "General",IDC_STATIC,7,7,167,99,0,WS_EX_TRANSPARENT + LTEXT "Max skipped frames:",IDC_STATIC,62,126,67,8 + LTEXT "Amount skipped:",IDC_STATIC,62,144,67,8 + LTEXT "Output Method",IDC_STATIC,10,19,51,11 +END + +IDD_CHEATER DIALOGEX 0, 0, 262, 218 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "Cheat Entry and Editor" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + CONTROL "List1",IDC_CHEAT_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,5,5,200,125,WS_EX_CLIENTEDGE + PUSHBUTTON "&Add",IDC_ADD_CHEAT,215,5,40,15,WS_DISABLED + PUSHBUTTON "&Delete",IDC_DELETE_CHEAT,215,25,40,15,WS_DISABLED + PUSHBUTTON "&Update",IDC_UPDATE_CHEAT,215,45,40,15,WS_DISABLED + PUSHBUTTON "C&lear",IDC_CLEAR_CHEATS,215,65,40,15 + EDITTEXT IDC_CHEAT_CODE,86,134,118,15,ES_UPPERCASE | ES_AUTOHSCROLL + EDITTEXT IDC_CHEAT_DESCRIPTION,85,154,119,15,ES_AUTOHSCROLL + EDITTEXT IDC_CHEAT_ADDRESS,85,175,44,15,ES_UPPERCASE | ES_AUTOHSCROLL + EDITTEXT IDC_CHEAT_BYTE,215,175,26,15,ES_UPPERCASE | ES_AUTOHSCROLL + PUSHBUTTON "&OK",IDOK,93,196,50,15 + PUSHBUTTON "&Cancel",IDCANCEL,151,196,50,15 + RTEXT "Enter Cheat Code:",IDC_LABEL_CHEAT_CODE,23,134,59,15,SS_CENTERIMAGE + RTEXT "Cheat Description",IDC_LABEL_CHEAT_DESCRIPTION,19,154,61,15,SS_CENTERIMAGE + RTEXT "Cheat Address (hex)",IDC_LABEL_CHEAT_ADDRESS,18,175,64,15,SS_CENTERIMAGE + RTEXT "New Value (dec or hex)",IDC_LABEL_CHEAT_BYTE,134,175,74,15,SS_CENTERIMAGE +END + +IDD_NETPLAYPROGRESS DIALOG 0, 0, 186, 61 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Static",IDC_STATIC,5,0,160,20 + CONTROL "Progress1",IDC_NPPROGRESS,"msctls_progress32",WS_BORDER,5,30,160,25 +END + +IDD_INPUTCONFIG DIALOGEX 0, 0, 327, 150 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION +CAPTION " " +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + COMBOBOX IDC_JPCOMBO,12,11,77,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "Enabled",IDC_JPTOGGLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,100,13,42,10 + CONTROL "WOG!",IDC_UP,"InputCustom",WS_TABSTOP,50,39,71,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_LEFT,"InputCustom",WS_TABSTOP,50,52,71,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_DOWN,"InputCustom",WS_TABSTOP,50,65,71,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_RIGHT,"InputCustom",WS_TABSTOP,50,78,71,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_B,"InputCustom",WS_TABSTOP,50,91,71,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_A,"InputCustom",WS_TABSTOP,50,104,71,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_Y,"InputCustom",WS_TABSTOP,50,117,71,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_X,"InputCustom",WS_TABSTOP,50,129,71,12,WS_EX_CLIENTEDGE + CONTROL " ",IDC_START,"InputCustom",WS_TABSTOP,161,39,71,12,WS_EX_CLIENTEDGE + CONTROL " ",IDC_SELECT,"InputCustom",WS_TABSTOP,161,52,71,12,WS_EX_CLIENTEDGE + CONTROL " ",IDC_L,"InputCustom",WS_TABSTOP,161,65,71,12,WS_EX_CLIENTEDGE + CONTROL " ",IDC_R,"InputCustom",WS_TABSTOP,161,78,71,12,WS_EX_CLIENTEDGE + CONTROL " ",IDC_UPLEFT,"InputCustom",WS_DISABLED | WS_TABSTOP,161,91,71,12,WS_EX_CLIENTEDGE + CONTROL " ",IDC_UPRIGHT,"InputCustom",WS_DISABLED | WS_TABSTOP,161,104,71,12,WS_EX_CLIENTEDGE + CONTROL " ",IDC_DWNRIGHT,"InputCustom",WS_DISABLED | WS_TABSTOP,161,117,71,12,WS_EX_CLIENTEDGE + CONTROL " ",IDC_DWNLEFT,"InputCustom",WS_DISABLED | WS_TABSTOP,161,129,71,12,WS_EX_CLIENTEDGE + PUSHBUTTON "Cancel",IDCANCEL,242,127,39,14 + PUSHBUTTON "OK",IDOK,282,127,41,14 + LTEXT "Blue means the button is already mapped.\nPink means it conflicts with a custom hotkey.\nRed means it's reserved by Windows.\nButtons can be disabled using Escape.",IDC_LABEL_BLUE,166,0,157,32 + RTEXT "UP",IDC_LABEL_UP,8,42,38,8 + RTEXT "RIGHT",IDC_LABEL_RIGHT,6,81,41,8 + RTEXT "LEFT",IDC_LABEL_LEFT,9,55,37,8 + RTEXT "DOWN",IDC_LABEL_DOWN,8,68,39,8 + RTEXT "A",IDC_LABEL_A,8,106,38,8 + RTEXT "X",IDC_LABEL_X,7,132,39,8 + RTEXT "B",IDC_LABEL_B,9,94,37,8 + RTEXT "Y",IDC_LABEL_Y,6,120,40,8 + RTEXT "L",IDC_LABEL_L,134,67,24,8 + RTEXT "START",IDC_LABEL_START,134,41,24,8 + RTEXT "R",IDC_LABEL_R,134,80,24,8 + RTEXT "SELECT",IDC_LABEL_SELECT,130,54,28,8 + RTEXT "UP LEFT",IDC_LABEL_UPLEFT,128,94,30,8 + RTEXT "DN RIGHT",IDC_LABEL_DOWNRIGHT,122,120,36,8 + RTEXT "UP RIGHT",IDC_LABEL_UPRIGHT,122,107,36,8 + RTEXT "DN LEFT",IDC_LABEL_DOWNLEFT,127,132,31,8 + CONTROL 133,IDC_STATIC,"Static",SS_BITMAP,243,39,80,74 + CONTROL "Allow Left+Rt/Up+Dn",IDC_ALLOWLEFTRIGHT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,243,115,80,11 + GROUPBOX "Controller",IDC_STATIC,5,1,142,28,0,WS_EX_TRANSPARENT + GROUPBOX "Buttons",IDC_STATIC,5,30,234,117,0,WS_EX_TRANSPARENT +END + +IDD_CHEAT_SEARCH DIALOGEX 0, 0, 272, 275 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "Cheat Search" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "&OK",IDOK,161,253,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,218,253,50,14 + CONTROL "List1",IDC_ADDYS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP,7,7,201,152,WS_EX_CLIENTEDGE + PUSHBUTTON "&Search",IDC_C_SEARCH,215,7,52,16 + PUSHBUTTON "&Add Cheat",IDC_C_ADD,215,29,52,16,WS_DISABLED + PUSHBUTTON "&Reset",IDC_C_RESET,215,51,52,16 + CONTROL "1 byte",IDC_1_BYTE,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,212,172,42,11 + CONTROL "2 bytes",IDC_2_BYTE,"Button",BS_AUTORADIOBUTTON,212,185,42,11 + CONTROL "3 bytes",IDC_3_BYTE,"Button",BS_AUTORADIOBUTTON,212,198,42,11 + CONTROL "4 bytes",IDC_4_BYTE,"Button",BS_AUTORADIOBUTTON,212,211,42,11 + GROUPBOX "Data Size",IDC_STATIC,205,162,54,66,0,WS_EX_TRANSPARENT + GROUPBOX "Comparison Type",IDC_STATIC,7,162,114,86,0,WS_EX_TRANSPARENT + CONTROL "< (Less Than)",IDC_LESS_THAN,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,170,90,11 + CONTROL "> (Greater Than)",IDC_GREATER_THAN,"Button",BS_AUTORADIOBUTTON,13,182,90,11 + CONTROL "<= (Less Than or Equal to)",IDC_LESS_THAN_EQUAL,"Button",BS_AUTORADIOBUTTON,13,194,106,11 + CONTROL ">= (Greater than or Equal To)",IDC_GREATER_THAN_EQUAL, + "Button",BS_AUTORADIOBUTTON,13,206,105,11 + CONTROL "= (Equal To)",IDC_EQUAL,"Button",BS_AUTORADIOBUTTON,13,218,90,11 + CONTROL "!= (Not Equal To)",IDC_NOT_EQUAL,"Button",BS_AUTORADIOBUTTON,13,230,90,11 + GROUPBOX "Data Type",IDC_STATIC,125,206,75,43,0,WS_EX_TRANSPARENT + GROUPBOX "Compare To",IDC_STATIC,125,162,75,42,0,WS_EX_TRANSPARENT + CONTROL "Previous Value",IDC_PREV,"Button",BS_AUTORADIOBUTTON | WS_GROUP,129,171,67,10 + CONTROL "Entered Value",IDC_ENTERED,"Button",BS_AUTORADIOBUTTON,129,181,67,10 + CONTROL "Entered Address",IDC_ENTEREDADDRESS,"Button",BS_AUTORADIOBUTTON,129,192,67,10 + CONTROL "Unsigned (>=0)",IDC_UNSIGNED,"Button",BS_AUTORADIOBUTTON | WS_GROUP,129,216,67,10 + CONTROL "Signed (+/-)",IDC_SIGNED,"Button",BS_AUTORADIOBUTTON,129,226,67,10 + CONTROL "Hexadecimal",IDC_HEX,"Button",BS_AUTORADIOBUTTON,129,236,67,10 + EDITTEXT IDC_VALUE_ENTER,72,253,83,12,ES_UPPERCASE | ES_AUTOHSCROLL | WS_DISABLED + RTEXT "Enter a Value:",IDC_ENTER_LABEL,7,253,54,12,SS_CENTERIMAGE | WS_DISABLED + PUSHBUTTON "&Watch",IDC_C_WATCH,215,91,52,16 + PUSHBUTTON "&Clear Watches",IDC_C_CLEARWATCH,215,108,52,16 + PUSHBUTTON "&Load Watches",IDC_C_LOADWATCH,215,125,52,16 + PUSHBUTTON "Sa&ve Watches",IDC_C_SAVEWATCH,215,142,52,16 +END + +IDD_CHEAT_FROM_SEARCH DIALOG 0, 0, 187, 143 +STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU +CAPTION "Cheat Details" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "&OK",IDOK,85,123,45,13 + PUSHBUTTON "&Cancel",IDCANCEL,135,123,45,13 + EDITTEXT IDC_NC_ADDRESS,79,7,101,12,ES_AUTOHSCROLL + EDITTEXT IDC_NC_CURRVAL,79,31,101,12,ES_AUTOHSCROLL + EDITTEXT IDC_NC_PREVVAL,79,55,101,12,ES_AUTOHSCROLL + EDITTEXT IDC_NC_NEWVAL,79,79,101,12,ES_AUTOHSCROLL + EDITTEXT IDC_NC_DESC,79,103,101,12,ES_AUTOHSCROLL + RTEXT "Address",IDC_STATIC,7,7,70,12,SS_CENTERIMAGE + RTEXT "Current Value",IDC_STATIC,7,31,70,12,SS_CENTERIMAGE + RTEXT "Previous Value",IDC_STATIC,7,55,70,12,SS_CENTERIMAGE + RTEXT "New Value",IDC_STATIC,7,79,70,12,SS_CENTERIMAGE + RTEXT "Description",IDC_STATIC,7,103,70,12,SS_CENTERIMAGE +END + +IDD_OPENMOVIE DIALOGEX 0, 0, 304, 223 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Play Movie" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,187,200,50,14 + PUSHBUTTON "Cancel",IDCANCEL,246,200,50,14 + EDITTEXT IDC_MOVIE_PATH,7,18,230,13,ES_AUTOHSCROLL + LTEXT "Movie File",IDC_STATIC,7,7,33,8 + PUSHBUTTON "&Browse...",IDC_BROWSE_MOVIE,248,17,48,14 + LTEXT "Recording Date:",IDC_STATIC,15,55,53,8 + LTEXT "Length:",IDC_STATIC,43,64,25,8 + LTEXT "Frames:",IDC_STATIC,43,73,26,8 + LTEXT "Re-record Count:",IDC_STATIC,13,82,55,8 + LTEXT "DATE",IDC_MOVIE_DATE,71,55,81,8 + LTEXT "LENGTH",IDC_MOVIE_LENGTH,71,64,81,8 + LTEXT "FRAMES",IDC_MOVIE_FRAMES,71,73,81,8 + LTEXT "RERECORD",IDC_MOVIE_RERECORD,71,82,81,8 + LTEXT "Author Info:",IDC_LABEL_MOVIEINFOBOX,30,99,38,8 + CONTROL "Open Read-Only",IDC_READONLY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,7,69,10 + LTEXT "Static",IDC_MOVIE_METADATA,70,99,226,21,WS_BORDER + GROUPBOX "Record Options",IDC_LABEL_STARTSETTINGS,7,133,77,61 + CONTROL "Record from now",IDC_RECORD_NOW,"Button",BS_AUTORADIOBUTTON | WS_DISABLED | WS_GROUP | WS_TABSTOP,11,169,70,10 + CONTROL "Record from reset",IDC_RECORD_RESET,"Button",BS_AUTORADIOBUTTON | WS_DISABLED | WS_TABSTOP,11,154,72,10 + CONTROL "Joypad 1",IDC_JOY1,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,98,142,45,10 + CONTROL "Joypad 3",IDC_JOY3,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,98,162,45,10 + CONTROL "Joypad 2",IDC_JOY2,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,98,152,45,10 + CONTROL "Joypad 4",IDC_JOY4,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,98,172,45,10 + CONTROL "Joypad 5",IDC_JOY5,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,98,183,45,10 + GROUPBOX "Record Controllers",IDC_LABEL_CONTROLLERSETTINGS,89,133,69,61 + GROUPBOX "Emulator Sync Settings",IDC_LABEL_SYNCSETTINGS,163,133,133,61 + CONTROL "Allow Left+Right / Up+Down",IDC_ALLOWLEFTRIGHT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,153,118,11 + CONTROL "Sync samples with sound CPU",IDC_SYNC_TO_SOUND_CPU, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,166,117,10 + LTEXT " ",IDC_LOADEDFROMMOVIE,169,124,127,8 + LTEXT "Movie's ROM: CRC32=Unknown, Name=Unknown",IDC_MOVIEROMINFO,8,35,1024,8 + LTEXT "Current ROM: CRC32=Unknown, Name=Unknown",IDC_CURRENTROMINFO,9,43,287,9 + LTEXT " ",IDC_PLAYWARN,10,203,167,15 +END + +IDD_CREATEMOVIE DIALOGEX 0, 0, 303, 150 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Record Movie" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,187,129,50,14 + PUSHBUTTON "Cancel",IDCANCEL,246,129,50,14 + EDITTEXT IDC_MOVIE_PATH,7,18,230,13,ES_AUTOHSCROLL + LTEXT "Movie File",IDC_STATIC,7,7,33,8 + PUSHBUTTON "&Browse...",IDC_BROWSE_MOVIE,248,17,48,14 + GROUPBOX "Record Options",IDC_LABEL_STARTSETTINGS,7,38,77,61 + CONTROL "Record from now",IDC_RECORD_NOW,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,11,65,70,10 + CONTROL "Record from reset",IDC_RECORD_RESET,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,11,52,72,10 + CONTROL "Joypad 1",IDC_JOY1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,47,45,10 + CONTROL "Joypad 3",IDC_JOY3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,67,45,10 + CONTROL "Joypad 2",IDC_JOY2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,57,45,10 + CONTROL "Joypad 4",IDC_JOY4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,77,45,10 + CONTROL "Joypad 5",IDC_JOY5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,98,87,45,10 + GROUPBOX "Record Controllers",IDC_LABEL_CONTROLLERSETTINGS,89,38,69,61 + EDITTEXT IDC_MOVIE_METADATA,67,105,229,14,ES_AUTOHSCROLL + LTEXT "Author Info:",IDC_STATIC,18,108,43,8,0,WS_EX_RIGHT + GROUPBOX "Emulator Sync Settings",IDC_LABEL_SYNCSETTINGS,163,38,133,61 + CONTROL "Allow Left+Right / Up+Down",IDC_ALLOWLEFTRIGHT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,62,118,10 + CONTROL "Sync samples with sound CPU",IDC_SYNC_TO_SOUND_CPU, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,172,75,117,10 + CONTROL "Clear SRAM",IDC_CLEARSRAM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,83,70,10 +END + +IDD_KEYCUSTOM DIALOGEX 0, 0, 349, 203 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION +CAPTION "Customize Special Keys" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,66,182,50,14 + PUSHBUTTON "OK",IDOK,16,182,50,14 + RTEXT "speed +",IDC_LABEL_HK1,4,8,58,8 + RTEXT "frame advance",IDC_LABEL_HK4,2,47,59,8 + RTEXT "speed -",IDC_LABEL_HK2,3,21,59,8 + RTEXT "pause",IDC_LABEL_HK3,2,34,60,8 + RTEXT "skip +",IDC_LABEL_HK6,2,74,60,8 + RTEXT "movie frame count",IDC_LABEL_HK11,0,138,62,8 + RTEXT "superscope turbo",IDC_LABEL_HK8,0,98,62,8 + RTEXT "movie read-only",IDC_LABEL_HK12,3,150,59,8 + RTEXT "superscope pause",IDC_LABEL_HK9,2,111,60,8 + RTEXT "skip -",IDC_LABEL_HK7,3,85,59,8 + CONTROL "",IDC_HOTKEY1,"InputCustomHot",WS_TABSTOP,66,5,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY2,"InputCustomHot",WS_TABSTOP,66,18,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY3,"InputCustomHot",WS_TABSTOP,66,31,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY4,"InputCustomHot",WS_TABSTOP,66,45,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY5,"InputCustomHot",WS_TABSTOP,66,58,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY6,"InputCustomHot",WS_TABSTOP,66,70,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY7,"InputCustomHot",WS_TABSTOP,66,83,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY8,"InputCustomHot",WS_TABSTOP,66,96,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY9,"InputCustomHot",WS_TABSTOP,66,109,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY10,"InputCustomHot",WS_TABSTOP,66,122,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY11,"InputCustomHot",WS_TABSTOP,66,135,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY12,"InputCustomHot",WS_TABSTOP,66,149,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_HOTKEY13,"InputCustomHot",WS_TABSTOP,66,162,98,12,WS_EX_CLIENTEDGE + CONTROL "",IDC_SAVE1,"InputCustomHot",WS_TABSTOP,192,5,60,12,WS_EX_CLIENTEDGE + RTEXT "save1",IDC_LABEL_UP2,170,21,20,8 + CONTROL "",IDC_SAVE2,"InputCustomHot",WS_TABSTOP,192,18,60,12,WS_EX_CLIENTEDGE + RTEXT "save2",IDC_LABEL_UP3,170,34,20,8 + CONTROL "",IDC_SAVE3,"InputCustomHot",WS_TABSTOP,192,31,60,12,WS_EX_CLIENTEDGE + RTEXT "save3",IDC_LABEL_UP4,170,47,20,8 + CONTROL "",IDC_SAVE4,"InputCustomHot",WS_TABSTOP,192,45,60,12,WS_EX_CLIENTEDGE + RTEXT "save4",IDC_LABEL_UP5,170,58,20,8 + CONTROL "",IDC_SAVE5,"InputCustomHot",WS_TABSTOP,192,58,60,12,WS_EX_CLIENTEDGE + RTEXT "save5",IDC_LABEL_UP6,170,72,20,8 + CONTROL "",IDC_SAVE6,"InputCustomHot",WS_TABSTOP,192,71,60,12,WS_EX_CLIENTEDGE + RTEXT "save6",IDC_LABEL_UP7,170,85,20,8 + CONTROL "",IDC_SAVE7,"InputCustomHot",WS_TABSTOP,192,82,60,12,WS_EX_CLIENTEDGE + RTEXT "save7",IDC_LABEL_UP8,170,98,20,8 + CONTROL "",IDC_SAVE8,"InputCustomHot",WS_TABSTOP,192,96,60,12,WS_EX_CLIENTEDGE + RTEXT "save8",IDC_LABEL_UP9,170,112,20,8 + CONTROL "",IDC_SAVE9,"InputCustomHot",WS_TABSTOP,192,109,60,12,WS_EX_CLIENTEDGE + RTEXT "save9",IDC_LABEL_UP10,170,125,20,8 + CONTROL "",IDC_SAVE10,"InputCustomHot",WS_TABSTOP,192,122,60,12,WS_EX_CLIENTEDGE + RTEXT "save0",IDC_LABEL_UP11,170,8,20,8 + CONTROL "",IDC_SAVE11,"InputCustomHot",WS_TABSTOP,279,5,60,12,WS_EX_CLIENTEDGE + RTEXT "load1",IDC_LABEL_UP12,257,21,20,8 + CONTROL "",IDC_SAVE12,"InputCustomHot",WS_TABSTOP,279,18,60,12,WS_EX_CLIENTEDGE + RTEXT "load2",IDC_LABEL_UP13,257,34,20,8 + CONTROL "",IDC_SAVE13,"InputCustomHot",WS_TABSTOP,279,31,60,12,WS_EX_CLIENTEDGE + RTEXT "load3",IDC_LABEL_UP14,257,48,20,8 + CONTROL "",IDC_SAVE14,"InputCustomHot",WS_TABSTOP,279,45,60,12,WS_EX_CLIENTEDGE + RTEXT "load4",IDC_LABEL_UP15,257,61,20,8 + CONTROL "",IDC_SAVE15,"InputCustomHot",WS_TABSTOP,279,58,60,12,WS_EX_CLIENTEDGE + RTEXT "load5",IDC_LABEL_UP16,257,72,20,8 + CONTROL "",IDC_SAVE16,"InputCustomHot",WS_TABSTOP,279,71,60,12,WS_EX_CLIENTEDGE + RTEXT "load6",IDC_LABEL_UP17,257,85,20,8 + CONTROL "",IDC_SAVE17,"InputCustomHot",WS_TABSTOP,279,82,60,12,WS_EX_CLIENTEDGE + RTEXT "load7",IDC_LABEL_UP18,257,98,20,8 + CONTROL "",IDC_SAVE18,"InputCustomHot",WS_TABSTOP,279,96,60,12,WS_EX_CLIENTEDGE + RTEXT "load8",IDC_LABEL_UP19,257,111,20,8 + CONTROL "",IDC_SAVE19,"InputCustomHot",WS_TABSTOP,279,109,60,12,WS_EX_CLIENTEDGE + RTEXT "load9",IDC_LABEL_UP20,257,125,20,8 + CONTROL "",IDC_SAVE20,"InputCustomHot",WS_TABSTOP,279,122,60,12,WS_EX_CLIENTEDGE + RTEXT "load0",IDC_LABEL_UP21,257,8,20,8 + RTEXT "fast forward",IDC_LABEL_HK5,3,61,58,8 + RTEXT "show pressed keys",IDC_LABEL_HK10,1,125,61,8 + RTEXT "save screenshot",IDC_LABEL_HK13,3,163,59,8 + RTEXT "slot-",IDC_LABEL_UP22,170,138,20,8 + CONTROL "",IDC_SLOTMINUS,"InputCustomHot",WS_TABSTOP,192,135,60,12,WS_EX_CLIENTEDGE + RTEXT "slot+",IDC_LABEL_UP23,257,138,20,8 + CONTROL "",IDC_SLOTPLUS,"InputCustomHot",WS_TABSTOP,279,135,60,12,WS_EX_CLIENTEDGE + RTEXT "save#",IDC_LABEL_UP24,166,151,23,8 + CONTROL "",IDC_SLOTSAVE,"InputCustomHot",WS_TABSTOP,192,149,60,12,WS_EX_CLIENTEDGE + RTEXT "load#",IDC_LABEL_UP25,253,151,23,8 + CONTROL "",IDC_SLOTLOAD,"InputCustomHot",WS_TABSTOP,279,149,60,12,WS_EX_CLIENTEDGE + LTEXT "Blue means the hotkey is already mapped.\nPink means it conflicts with a game button.\nRed means it's reserved by Windows.\nA hotkey can be disabled using Escape.",IDC_LABEL_BLUE,208,164,136,32 + COMBOBOX IDC_HKCOMBO,134,183,60,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + +IDD_MULTICART DIALOGEX 0, 0, 407, 90 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Open MultiCart" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,343,66,50,14 + PUSHBUTTON "Cancel",IDCANCEL,286,66,50,14 + EDITTEXT IDC_MULTICART_EDITA,44,7,226,14,ES_AUTOHSCROLL + PUSHBUTTON "Swap A and B",IDC_MULTICART_SWAP,7,69,58,14 + EDITTEXT IDC_MULTICART_EDITB,44,27,226,14,ES_AUTOHSCROLL + LTEXT "Slot A :",IDC_STATIC,10,9,31,8 + LTEXT "Slot B :",IDC_STATIC,10,29,31,8 + PUSHBUTTON "Clear",IDC_MULTICART_CLEARA,343,7,50,14 + PUSHBUTTON "Clear",IDC_MULTICART_CLEARB,343,27,50,14 + PUSHBUTTON "Browse...",IDC_MULTICART_BROWSEA,279,7,57,14 + PUSHBUTTON "Browse...",IDC_MULTICART_BROWSEB,279,27,57,14 + LTEXT "BIOS :",IDC_STATIC,11,50,26,8 + EDITTEXT IDC_MULTICART_BIOSEDIT,44,48,226,14,ES_AUTOHSCROLL | ES_READONLY + LTEXT "not found",IDC_MULTICART_BIOSNOTFOUND,280,50,54,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_SOUND_OPTS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 293 + TOPMARGIN, 7 + BOTTOMMARGIN, 136 + END + + IDD_ROM_INFO, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 226 + TOPMARGIN, 7 + BOTTOMMARGIN, 178 + END + + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 225 + TOPMARGIN, 7 + BOTTOMMARGIN, 174 + END + + IDD_EMU_SETTINGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 312 + BOTTOMMARGIN, 141 + END + + IDD_OPEN_ROM, DIALOG + BEGIN + LEFTMARGIN, 3 + RIGHTMARGIN, 424 + TOPMARGIN, 3 + BOTTOMMARGIN, 221 + END + + IDD_NEWDISPLAY, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 346 + TOPMARGIN, 7 + BOTTOMMARGIN, 177 + END + + IDD_CHEATER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 255 + TOPMARGIN, 7 + BOTTOMMARGIN, 211 + END + + IDD_NETPLAYPROGRESS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 54 + END + + IDD_INPUTCONFIG, DIALOG + BEGIN + LEFTMARGIN, 1 + RIGHTMARGIN, 323 + VERTGUIDE, 77 + VERTGUIDE, 92 + BOTTOMMARGIN, 141 + HORZGUIDE, 122 + END + + IDD_CHEAT_SEARCH, DIALOG + BEGIN + LEFTMARGIN, 7 + TOPMARGIN, 7 + BOTTOMMARGIN, 268 + END + + IDD_CHEAT_FROM_SEARCH, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 180 + TOPMARGIN, 7 + BOTTOMMARGIN, 136 + END + + IDD_OPENMOVIE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 297 + TOPMARGIN, 7 + BOTTOMMARGIN, 219 + HORZGUIDE, 31 + HORZGUIDE, 55 + HORZGUIDE, 120 + HORZGUIDE, 133 + HORZGUIDE, 191 + END + + IDD_CREATEMOVIE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 296 + TOPMARGIN, 7 + BOTTOMMARGIN, 143 + HORZGUIDE, 31 + HORZGUIDE, 38 + HORZGUIDE, 99 + END + + IDD_KEYCUSTOM, DIALOG + BEGIN + RIGHTMARGIN, 346 + VERTGUIDE, 72 + VERTGUIDE, 92 + BOTTOMMARGIN, 197 + END + + IDD_MULTICART, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 400 + TOPMARGIN, 7 + BOTTOMMARGIN, 83 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_OPENFOLDER BITMAP "openfold.bmp" +IDB_CLOSEDFOLDER BITMAP "closedfold.bmp" +IDB_CDDRIVE BITMAP "cdd.bmp" +IDB_NETDRIVE BITMAP "nd.bmp" +IDB_HARDDRIVE BITMAP "hd.bmp" +IDB_PAD BITMAP "pad.bmp" +IDB_REMOVABLE BITMAP "rd.bmp" +IDB_RAMDISK BITMAP "ram.bmp" +IDB_UNKNOWN BITMAP "ud.bmp" +IDB_LOCKEDFOLDER BITMAP "rodir.bmp" +IDB_HIDDENFOLDER BITMAP "hiddir.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "icon1.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Dutch (Netherlands) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NLD) +#ifdef _WIN32 +LANGUAGE LANG_DUTCH, SUBLANG_DUTCH +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,5,2,0 + PRODUCTVERSION 1,5,2,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904b0" + BEGIN + VALUE "CompanyName", "http://www.snes9x.com" + VALUE "FileDescription", "Snes9XW" + VALUE "FileVersion", "1.52" + VALUE "InternalName", "Snes9X" + VALUE "LegalCopyright", "Copyright 1996-2010" + VALUE "OriginalFilename", "Snes9X.exe" + VALUE "ProductName", "Snes9X SNES Emulator" + VALUE "ProductVersion", "1.52" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1200 + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Dutch (Netherlands) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.K.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_NETCONNECT DIALOGEX 0, 0, 227, 61 +STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION +CAPTION "Connect to Server" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "&OK",IDOK,120,45,50,14 + PUSHBUTTON "Canccel",IDCANCEL,175,45,50,14 + RTEXT "Server Address",IDC_LABEL_SERVERADDY,5,5,50,14,SS_CENTERIMAGE + PUSHBUTTON "Clear History",IDC_CLEARHISTORY,175,5,50,14 + RTEXT "Port Number",IDC_LABEL_PORTNUM,5,25,50,14,SS_CENTERIMAGE + EDITTEXT IDC_PORTNUMBER,60,25,25,14,ES_AUTOHSCROLL + COMBOBOX IDC_HOSTNAME,60,5,110,40,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU_US MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "L&oad Game...\tCtrl+O", ID_FILE_LOAD_GAME + POPUP "Recent &Games" + BEGIN + MENUITEM "Dummy", ID_RECENT_DUMMY, INACTIVE + END + POPUP "&Save Game Position" + BEGIN + MENUITEM "Slot #&1", ID_FILE_SAVE1 + MENUITEM "Slot #&2", ID_FILE_SAVE2, GRAYED + MENUITEM "Slot #&3", ID_FILE_SAVE3, GRAYED + MENUITEM "Slot #&4", ID_FILE_SAVE4, GRAYED + MENUITEM "Slot #&5", ID_FILE_SAVE5, GRAYED + MENUITEM "Slot #&6", ID_FILE_SAVE6, GRAYED + MENUITEM "Slot #&7", ID_FILE_SAVE7, GRAYED + MENUITEM "Slot #&8", ID_FILE_SAVE8, GRAYED + MENUITEM "Slot #&9", ID_FILE_SAVE9, GRAYED + END + POPUP "&Load Game Position" + BEGIN + MENUITEM "Slot #&1", ID_FILE_LOAD1 + MENUITEM "Slot #&2", ID_FILE_LOAD2, GRAYED + MENUITEM "Slot #&3", ID_FILE_LOAD3, GRAYED + MENUITEM "Slot #&4", ID_FILE_LOAD4, GRAYED + MENUITEM "Slot #&5", ID_FILE_LOAD5, GRAYED + MENUITEM "Slot #&6", ID_FILE_LOAD6, GRAYED + MENUITEM "Slot #&7", ID_FILE_LOAD7, GRAYED + MENUITEM "Slot #&8", ID_FILE_LOAD8, GRAYED + MENUITEM "Slot #&9", ID_FILE_LOAD9, GRAYED + END + MENUITEM "Load MultiCart...", ID_FILE_LOADMULTICART + MENUITEM SEPARATOR + POPUP "Save Other" + BEGIN + MENUITEM "Save Screenshot", ID_SAVESCREENSHOT + MENUITEM "Sa&ve S-RAM Data", ID_FILE_SAVE_SRAM_DATA, GRAYED + END + MENUITEM "ROM Information...", IDM_ROM_INFO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Movie Play...", ID_FILE_MOVIE_PLAY, GRAYED + MENUITEM "Movie Record...", ID_FILE_MOVIE_RECORD, GRAYED + MENUITEM "Movie Stop", ID_FILE_MOVIE_STOP, GRAYED + MENUITEM SEPARATOR + MENUITEM "Record AVI...", ID_FILE_WRITE_AVI, GRAYED + MENUITEM "Stop AVI Recording", ID_FILE_STOP_AVI, GRAYED + MENUITEM SEPARATOR + MENUITEM "&Reset Game", ID_FILE_RESET, GRAYED + MENUITEM "&Pause", ID_FILE_PAUSE, GRAYED + MENUITEM "E&xit\tAlt+F4", ID_FILE_EXIT + END + POPUP "&Options" + BEGIN + MENUITEM "&Display Configuration...\tAlt+F5", ID_OPTIONS_DISPLAY + MENUITEM "&Settings...\tAlt+F8", ID_OPTIONS_SETTINGS + END + POPUP "&Input" + BEGIN + MENUITEM "&Input Configuration...\tAlt+F7", 40022 + MENUITEM "&Customize Hotkeys...\tAlt+F9", ID_OPTIONS_KEYCUSTOM + MENUITEM SEPARATOR + MENUITEM "Use SNES Joypad(s)", IDM_SNES_JOYPAD + MENUITEM "Use SNES Mouse", IDM_MOUSE_TOGGLE + MENUITEM "Use Super Scope", IDM_SCOPE_TOGGLE + MENUITEM "Use Super Multitap (5-player)", IDM_ENABLE_MULTITAP + MENUITEM "Use Konami Justifier", IDM_JUSTIFIER + MENUITEM "Use Mouse in alternate port", IDM_MOUSE_SWAPPED + MENUITEM "Use Multitaps (8-player)", IDM_MULTITAP8 + MENUITEM "Use Dual Justifiers", IDM_JUSTIFIERS + END + POPUP "&Sound" + BEGIN + POPUP "&Playback Rate" + BEGIN + MENUITEM "&Mute Sound", ID_SOUND_NOSOUND + MENUITEM "8KHz", ID_SOUND_8000HZ, GRAYED + MENUITEM "11KHz", ID_SOUND_11025HZ, GRAYED + MENUITEM "16KHz", ID_SOUND_16000HZ, GRAYED + MENUITEM "22KHz", ID_SOUND_22050HZ, GRAYED + MENUITEM "30KHz", ID_SOUND_30000HZ, GRAYED + MENUITEM "32KHz (SNES)", ID_SOUND_32000HZ, GRAYED + MENUITEM "35KHz", ID_SOUND_35000HZ, GRAYED + MENUITEM "44KHz", ID_SOUND_44100HZ, GRAYED + MENUITEM "48KHz", ID_SOUND_48000HZ, GRAYED + END + POPUP "&Buffer Length" + BEGIN + MENUITEM "16ms", ID_SOUND_16MS + MENUITEM "32ms", ID_SOUND_32MS, GRAYED + MENUITEM "48ms", ID_SOUND_48MS, GRAYED + MENUITEM "64ms", ID_SOUND_64MS, GRAYED + MENUITEM "80ms", ID_SOUND_80MS, GRAYED + MENUITEM "96ms", ID_SOUND_96MS, GRAYED + MENUITEM "112ms", ID_SOUND_112MS, GRAYED + MENUITEM "128ms", ID_SOUND_128MS, GRAYED + MENUITEM "144ms", ID_SOUND_144MS, GRAYED + MENUITEM "160ms", ID_SOUND_160MS, GRAYED + MENUITEM "176ms", ID_SOUND_176MS, GRAYED + MENUITEM "194ms", ID_SOUND_194MS, GRAYED + MENUITEM "210ms", ID_SOUND_210MS, GRAYED + END + POPUP "&Channels" + BEGIN + MENUITEM "Channel &1", ID_CHANNELS_CHANNEL1 + MENUITEM "Channel &2", ID_CHANNELS_CHANNEL2 + MENUITEM "Channel &3", ID_CHANNELS_CHANNEL3 + MENUITEM "Channel &4", ID_CHANNELS_CHANNEL4 + MENUITEM "Channel &5", ID_CHANNELS_CHANNEL5 + MENUITEM "Channel &6", ID_CHANNELS_CHANNEL6 + MENUITEM "Channel &7", ID_CHANNELS_CHANNEL7 + MENUITEM "Channel &8", ID_CHANNELS_CHANNEL8 + MENUITEM SEPARATOR + MENUITEM "Enable All", ID_CHANNELS_ENABLEALL + END + MENUITEM "&16-Bit Sound", ID_SOUND_16BIT + MENUITEM "&Stereo", ID_SOUND_STEREO + MENUITEM "&Reverse Stereo\tAlt+R", ID_SOUND_REVERSE_STEREO + MENUITEM SEPARATOR + MENUITEM "S&ync Sound\tAlt+]", ID_SOUND_SYNC + MENUITEM "&Settings...\tAlt+T", ID_SOUND_OPTIONS + END + POPUP "&Window" + BEGIN + MENUITEM "&Hide menubar\tEsc", ID_WINDOW_HIDEMENUBAR + MENUITEM "&Full Screen\tAlt+Enter", ID_WINDOW_FULLSCREEN + MENUITEM "&Stretch Image\tAlt+Backspace", 40032 + MENUITEM "&Maintain Aspect Ratio", 40123 + MENUITEM "Stretch with &Video Card", ID_WINDOW_VIDMEM + MENUITEM SEPARATOR + POPUP "&Language" + BEGIN + MENUITEM "&English", ID_LANGUAGE_ENGLISH, CHECKED + MENUITEM "&Nederlands", ID_LANGUAGE_NEDERLANDS, GRAYED + END + END + POPUP "&Cheat" + BEGIN + MENUITEM "&Game Genie, Pro-Action Replay Codes\tAlt+E", ID_CHEAT_ENTER + MENUITEM "&Search for New Cheats", ID_CHEAT_SEARCH_MODAL, GRAYED + MENUITEM "Search for New Cheats (active)\tAlt+A", 40064, GRAYED + MENUITEM "&Apply Cheats", ID_CHEAT_APPLY, CHECKED, GRAYED + END + POPUP "&Netplay" + BEGIN + MENUITEM "&Connect to Server...", ID_NETPLAY_CONNECT + MENUITEM "&Disconnect from Server", ID_NETPLAY_DISCONNECT + MENUITEM SEPARATOR + MENUITEM "&Act as Server", ID_NETPLAY_SERVER + MENUITEM "&Re-sync all Clients Using Freeze File Now", ID_NETPLAY_SYNC + MENUITEM "&Send ROM Image to Clients Now", ID_NETPLAY_ROM + MENUITEM "S&end ROM Image to Clients", ID_NETPLAY_SEND_ROM_ON_CONNECT + MENUITEM "S&ync Using Reset Game", ID_NETPLAY_SYNC_BY_RESET, CHECKED + MENUITEM SEPARATOR + MENUITEM "&Options...", ID_NETPLAY_OPTIONS + END + POPUP "&Help" + BEGIN + MENUITEM "&About...", ID_HELP_ABOUT + END +END + +#endif // English (U.K.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/win32/rsrc/ud.bmp b/win32/rsrc/ud.bmp new file mode 100644 index 00000000..ff8dd145 Binary files /dev/null and b/win32/rsrc/ud.bmp differ diff --git a/win32/snes9xw.sln b/win32/snes9xw.sln new file mode 100644 index 00000000..594843f8 --- /dev/null +++ b/win32/snes9xw.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Snes9X", "snes9xw.vcproj", "{B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + C core|Win32 = C core|Win32 + Debug|Win32 = Debug|Win32 + Debug+ASM|Win32 = Debug+ASM|Win32 + Release|Win32 = Release|Win32 + Release+ASM|Win32 = Release+ASM|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}.C core|Win32.ActiveCfg = C core|Win32 + {B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}.C core|Win32.Build.0 = C core|Win32 + {B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}.Debug|Win32.ActiveCfg = Debug|Win32 + {B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}.Debug|Win32.Build.0 = Debug|Win32 + {B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}.Debug+ASM|Win32.ActiveCfg = Debug+ASM|Win32 + {B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}.Debug+ASM|Win32.Build.0 = Debug+ASM|Win32 + {B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}.Release|Win32.ActiveCfg = Release|Win32 + {B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}.Release|Win32.Build.0 = Release|Win32 + {B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}.Release+ASM|Win32.ActiveCfg = Release+ASM|Win32 + {B86059D8-C9A6-46BE-8FBA-3170C54F1DFD}.Release+ASM|Win32.Build.0 = Release+ASM|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/win32/snes9xw.vcproj b/win32/snes9xw.vcproj new file mode 100644 index 00000000..bfe0383a --- /dev/null +++ b/win32/snes9xw.vcproj @@ -0,0 +1,3144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win32/snes_ntsc.c b/win32/snes_ntsc.c new file mode 100644 index 00000000..f622baf8 --- /dev/null +++ b/win32/snes_ntsc.c @@ -0,0 +1,251 @@ +/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */ + +#include "snes_ntsc.h" + +/* Copyright (C) 2006-2007 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +snes_ntsc_setup_t const snes_ntsc_monochrome = { 0,-1, 0, 0,.2, 0,.2,-.2,-.2,-1, 1, 0, 0 }; +snes_ntsc_setup_t const snes_ntsc_composite = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; +snes_ntsc_setup_t const snes_ntsc_svideo = { 0, 0, 0, 0,.2, 0,.2, -1, -1, 0, 1, 0, 0 }; +snes_ntsc_setup_t const snes_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1, 1, 0, 0 }; + +#define alignment_count 3 +#define burst_count 3 +#define rescale_in 8 +#define rescale_out 7 + +#define artifacts_mid 1.0f +#define fringing_mid 1.0f +#define std_decoder_hue 0 + +#define rgb_bits 7 /* half normal range to allow for doubled hires pixels */ +#define gamma_size 32 + +#include "snes_ntsc_impl.h" + +/* 3 input pixels -> 8 composite samples */ +pixel_info_t const snes_ntsc_pixels [alignment_count] = { + { PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } }, + { PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } }, + { PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } }, +}; + +static void merge_kernel_fields( snes_ntsc_rgb_t* io ) +{ + int n; + for ( n = burst_size; n; --n ) + { + snes_ntsc_rgb_t p0 = io [burst_size * 0] + rgb_bias; + snes_ntsc_rgb_t p1 = io [burst_size * 1] + rgb_bias; + snes_ntsc_rgb_t p2 = io [burst_size * 2] + rgb_bias; + /* merge colors without losing precision */ + io [burst_size * 0] = + ((p0 + p1 - ((p0 ^ p1) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + io [burst_size * 1] = + ((p1 + p2 - ((p1 ^ p2) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + io [burst_size * 2] = + ((p2 + p0 - ((p2 ^ p0) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; + ++io; + } +} + +static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ) +{ + int n; + for ( n = burst_count; n; --n ) + { + unsigned i; + for ( i = 0; i < rgb_kernel_size / 2; i++ ) + { + snes_ntsc_rgb_t error = color - + out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] - + out [i + 7] - out [i + 5 +14] - out [i + 3 +28]; + DISTRIBUTE_ERROR( i+3+28, i+5+14, i+7 ); + } + out += alignment_count * rgb_kernel_size; + } +} + +void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ) +{ + int merge_fields; + int entry; + init_t impl; + if ( !setup ) + setup = &snes_ntsc_composite; + init( &impl, setup ); + + merge_fields = setup->merge_fields; + if ( setup->artifacts <= -1 && setup->fringing <= -1 ) + merge_fields = 1; + + for ( entry = 0; entry < snes_ntsc_palette_size; entry++ ) + { + /* Reduce number of significant bits of source color. Clearing the + low bits of R and B were least notictable. Modifying green was too + noticeable. */ + int ir = entry >> 8 & 0x1E; + int ig = entry >> 4 & 0x1F; + int ib = entry << 1 & 0x1E; + + #if SNES_NTSC_BSNES_COLORTBL + if ( setup->bsnes_colortbl ) + { + int bgr15 = (ib << 10) | (ig << 5) | ir; + unsigned long rgb16 = setup->bsnes_colortbl [bgr15]; + ir = rgb16 >> 11 & 0x1E; + ig = rgb16 >> 6 & 0x1F; + ib = rgb16 & 0x1E; + } + #endif + + { + float rr = impl.to_float [ir]; + float gg = impl.to_float [ig]; + float bb = impl.to_float [ib]; + + float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i ); + + int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g ); + snes_ntsc_rgb_t rgb = PACK_RGB( r, g, b ); + + snes_ntsc_rgb_t* out = ntsc->table [entry]; + gen_kernel( &impl, y, i, q, out ); + if ( merge_fields ) + merge_kernel_fields( out ); + correct_errors( rgb, out ); + } + } +} + +#ifndef SNES_NTSC_NO_BLITTERS + +void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, + int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) +{ + int chunk_count = (in_width - 1) / snes_ntsc_in_chunk; + for ( ; in_height; --in_height ) + { + SNES_NTSC_IN_T const* line_in = input; + SNES_NTSC_BEGIN_ROW( ntsc, burst_phase, + snes_ntsc_black, snes_ntsc_black, SNES_NTSC_ADJ_IN( *line_in ) ); + snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out; + int n; + ++line_in; + + for ( n = chunk_count; n; --n ) + { + /* order of input and output pixels must not be altered */ + SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) ); + SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) ); + SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) ); + SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); + + line_in += 3; + line_out += 7; + } + + /* finish final pixels */ + SNES_NTSC_COLOR_IN( 0, snes_ntsc_black ); + SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 1, snes_ntsc_black ); + SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 2, snes_ntsc_black ); + SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); + + burst_phase = (burst_phase + 1) % snes_ntsc_burst_count; + input += in_row_width; + rgb_out = (char*) rgb_out + out_pitch; + } +} + +void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, + int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) +{ + int chunk_count = (in_width - 2) / (snes_ntsc_in_chunk * 2); + for ( ; in_height; --in_height ) + { + SNES_NTSC_IN_T const* line_in = input; + SNES_NTSC_HIRES_ROW( ntsc, burst_phase, + snes_ntsc_black, snes_ntsc_black, snes_ntsc_black, + SNES_NTSC_ADJ_IN( line_in [0] ), + SNES_NTSC_ADJ_IN( line_in [1] ) ); + snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out; + int n; + line_in += 2; + + for ( n = chunk_count; n; --n ) + { + /* twice as many input pixels per chunk */ + SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) ); + SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) ); + SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) ); + SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 3, SNES_NTSC_ADJ_IN( line_in [3] ) ); + SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 4, SNES_NTSC_ADJ_IN( line_in [4] ) ); + SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 5, SNES_NTSC_ADJ_IN( line_in [5] ) ); + SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); + + line_in += 6; + line_out += 7; + } + + SNES_NTSC_COLOR_IN( 0, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 1, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 2, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 3, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 4, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); + + SNES_NTSC_COLOR_IN( 5, snes_ntsc_black ); + SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); + SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); + + burst_phase = (burst_phase + 1) % snes_ntsc_burst_count; + input += in_row_width; + rgb_out = (char*) rgb_out + out_pitch; + } +} + +#endif diff --git a/win32/snes_ntsc.h b/win32/snes_ntsc.h new file mode 100644 index 00000000..87fdd262 --- /dev/null +++ b/win32/snes_ntsc.h @@ -0,0 +1,206 @@ +/* SNES NTSC video filter */ + +/* snes_ntsc 0.2.2 */ +#ifndef SNES_NTSC_H +#define SNES_NTSC_H + +#include "snes_ntsc_config.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown +in parenthesis and should remain fairly stable in future versions. */ +typedef struct snes_ntsc_setup_t +{ + /* Basic parameters */ + double hue; /* -1 = -180 degrees +1 = +180 degrees */ + double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */ + double contrast; /* -1 = dark (0.5) +1 = light (1.5) */ + double brightness; /* -1 = dark (0.5) +1 = light (1.5) */ + double sharpness; /* edge contrast enhancement/blurring */ + + /* Advanced parameters */ + double gamma; /* -1 = dark (1.5) +1 = light (0.5) */ + double resolution; /* image resolution */ + double artifacts; /* artifacts caused by color changes */ + double fringing; /* color artifacts caused by brightness changes */ + double bleed; /* color bleed (color resolution reduction) */ + int merge_fields; /* if 1, merges even and odd fields together to reduce flicker */ + float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */ + + unsigned long const* bsnes_colortbl; /* undocumented; set to 0 */ +} snes_ntsc_setup_t; + +/* Video format presets */ +extern snes_ntsc_setup_t const snes_ntsc_composite; /* color bleeding + artifacts */ +extern snes_ntsc_setup_t const snes_ntsc_svideo; /* color bleeding only */ +extern snes_ntsc_setup_t const snes_ntsc_rgb; /* crisp image */ +extern snes_ntsc_setup_t const snes_ntsc_monochrome;/* desaturated + artifacts */ + +/* Initializes and adjusts parameters. Can be called multiple times on the same +snes_ntsc_t object. Can pass NULL for either parameter. */ +typedef struct snes_ntsc_t snes_ntsc_t; +void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ); + +/* Filters one or more rows of pixels. Input pixel format is set by SNES_NTSC_IN_FORMAT +and output RGB depth is set by SNES_NTSC_OUT_DEPTH. Both default to 16-bit RGB. +In_row_width is the number of pixels to get to the next input row. Out_pitch +is the number of *bytes* to get to the next output row. */ +void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, + long in_row_width, int burst_phase, int in_width, int in_height, + void* rgb_out, long out_pitch ); + +void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, + long in_row_width, int burst_phase, int in_width, int in_height, + void* rgb_out, long out_pitch ); + +/* Number of output pixels written by low-res blitter for given input width. Width +might be rounded down slightly; use SNES_NTSC_IN_WIDTH() on result to find rounded +value. Guaranteed not to round 256 down at all. */ +#define SNES_NTSC_OUT_WIDTH( in_width ) \ + ((((in_width) - 1) / snes_ntsc_in_chunk + 1) * snes_ntsc_out_chunk) + +/* Number of low-res input pixels that will fit within given output width. Might be +rounded down slightly; use SNES_NTSC_OUT_WIDTH() on result to find rounded +value. */ +#define SNES_NTSC_IN_WIDTH( out_width ) \ + (((out_width) / snes_ntsc_out_chunk - 1) * snes_ntsc_in_chunk + 1) + + +/* Interface for user-defined custom blitters */ + +enum { snes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */ +enum { snes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */ +enum { snes_ntsc_black = 0 }; /* palette index for black */ +enum { snes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */ + +/* Begins outputting row and starts three pixels. First pixel will be cut off a bit. +Use snes_ntsc_black for unused pixels. Declares variables, so must be before first +statement in a block (unless you're using C++). */ +#define SNES_NTSC_BEGIN_ROW( ntsc, burst, pixel0, pixel1, pixel2 ) \ + char const* ktable = \ + (char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\ + SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, SNES_NTSC_IN_FORMAT, ktable ) + +/* Begins input pixel */ +#define SNES_NTSC_COLOR_IN( index, color ) \ + SNES_NTSC_COLOR_IN_( index, color, SNES_NTSC_IN_FORMAT, ktable ) + +/* Generates output pixel. Bits can be 24, 16, 15, 14, 32 (treated as 24), or 0: +24: RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8 RGB) +16: RRRRRGGG GGGBBBBB (5-6-5 RGB) +15: RRRRRGG GGGBBBBB (5-5-5 RGB) +14: BBBBBGG GGGRRRRR (5-5-5 BGR, native SNES format) + 0: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format; x = junk bits) */ +#define SNES_NTSC_RGB_OUT( index, rgb_out, bits ) \ + SNES_NTSC_RGB_OUT_14_( index, rgb_out, bits, 1 ) + +/* Hires equivalents */ +#define SNES_NTSC_HIRES_ROW( ntsc, burst, pixel1, pixel2, pixel3, pixel4, pixel5 ) \ + char const* ktable = \ + (char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\ + unsigned const snes_ntsc_pixel1_ = (pixel1);\ + snes_ntsc_rgb_t const* kernel1 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel1_ );\ + unsigned const snes_ntsc_pixel2_ = (pixel2);\ + snes_ntsc_rgb_t const* kernel2 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel2_ );\ + unsigned const snes_ntsc_pixel3_ = (pixel3);\ + snes_ntsc_rgb_t const* kernel3 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel3_ );\ + unsigned const snes_ntsc_pixel4_ = (pixel4);\ + snes_ntsc_rgb_t const* kernel4 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel4_ );\ + unsigned const snes_ntsc_pixel5_ = (pixel5);\ + snes_ntsc_rgb_t const* kernel5 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel5_ );\ + snes_ntsc_rgb_t const* kernel0 = kernel1;\ + snes_ntsc_rgb_t const* kernelx0;\ + snes_ntsc_rgb_t const* kernelx1 = kernel1;\ + snes_ntsc_rgb_t const* kernelx2 = kernel1;\ + snes_ntsc_rgb_t const* kernelx3 = kernel1;\ + snes_ntsc_rgb_t const* kernelx4 = kernel1;\ + snes_ntsc_rgb_t const* kernelx5 = kernel1 + +#define SNES_NTSC_HIRES_OUT( x, rgb_out, bits ) {\ + snes_ntsc_rgb_t raw_ =\ + kernel0 [ x ] + kernel2 [(x+5)%7+14] + kernel4 [(x+3)%7+28] +\ + kernelx0 [(x+7)%7+7] + kernelx2 [(x+5)%7+21] + kernelx4 [(x+3)%7+35] +\ + kernel1 [(x+6)%7 ] + kernel3 [(x+4)%7+14] + kernel5 [(x+2)%7+28] +\ + kernelx1 [(x+6)%7+7] + kernelx3 [(x+4)%7+21] + kernelx5 [(x+2)%7+35];\ + SNES_NTSC_CLAMP_( raw_, 0 );\ + SNES_NTSC_RGB_OUT_( rgb_out, (bits), 0 );\ +} + + +/* private */ +enum { snes_ntsc_entry_size = 128 }; +enum { snes_ntsc_palette_size = 0x2000 }; +typedef unsigned long snes_ntsc_rgb_t; +struct snes_ntsc_t { + snes_ntsc_rgb_t table [snes_ntsc_palette_size] [snes_ntsc_entry_size]; +}; +enum { snes_ntsc_burst_size = snes_ntsc_entry_size / snes_ntsc_burst_count }; + +#define SNES_NTSC_RGB16( ktable, n ) \ + (snes_ntsc_rgb_t const*) (ktable + ((n & 0x001E) | (n >> 1 & 0x03E0) | (n >> 2 & 0x3C00)) * \ + (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t))) + +#define SNES_NTSC_BGR15( ktable, n ) \ + (snes_ntsc_rgb_t const*) (ktable + ((n << 9 & 0x3C00) | (n & 0x03E0) | (n >> 10 & 0x001E)) * \ + (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t))) + +/* common 3->7 ntsc macros */ +#define SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, ENTRY, table ) \ + unsigned const snes_ntsc_pixel0_ = (pixel0);\ + snes_ntsc_rgb_t const* kernel0 = ENTRY( table, snes_ntsc_pixel0_ );\ + unsigned const snes_ntsc_pixel1_ = (pixel1);\ + snes_ntsc_rgb_t const* kernel1 = ENTRY( table, snes_ntsc_pixel1_ );\ + unsigned const snes_ntsc_pixel2_ = (pixel2);\ + snes_ntsc_rgb_t const* kernel2 = ENTRY( table, snes_ntsc_pixel2_ );\ + snes_ntsc_rgb_t const* kernelx0;\ + snes_ntsc_rgb_t const* kernelx1 = kernel0;\ + snes_ntsc_rgb_t const* kernelx2 = kernel0 + +#define SNES_NTSC_RGB_OUT_14_( x, rgb_out, bits, shift ) {\ + snes_ntsc_rgb_t raw_ =\ + kernel0 [x ] + kernel1 [(x+12)%7+14] + kernel2 [(x+10)%7+28] +\ + kernelx0 [(x+7)%14] + kernelx1 [(x+ 5)%7+21] + kernelx2 [(x+ 3)%7+35];\ + SNES_NTSC_CLAMP_( raw_, shift );\ + SNES_NTSC_RGB_OUT_( rgb_out, bits, shift );\ +} + +/* common ntsc macros */ +#define snes_ntsc_rgb_builder ((1L << 21) | (1 << 11) | (1 << 1)) +#define snes_ntsc_clamp_mask (snes_ntsc_rgb_builder * 3 / 2) +#define snes_ntsc_clamp_add (snes_ntsc_rgb_builder * 0x101) +#define SNES_NTSC_CLAMP_( io, shift ) {\ + snes_ntsc_rgb_t sub = (io) >> (9-(shift)) & snes_ntsc_clamp_mask;\ + snes_ntsc_rgb_t clamp = snes_ntsc_clamp_add - sub;\ + io |= clamp;\ + clamp -= sub;\ + io &= clamp;\ +} + +#define SNES_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\ + unsigned color_;\ + kernelx##index = kernel##index;\ + kernel##index = (color_ = (color), ENTRY( table, color_ ));\ +} + +/* x is always zero except in snes_ntsc library */ +#define SNES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\ + if ( bits == 16 )\ + rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\ + if ( bits == 24 || bits == 32 )\ + rgb_out = (raw_>>(5-x)&0xFF0000)|(raw_>>(3-x)&0xFF00)|(raw_>>(1-x)&0xFF);\ + if ( bits == 15 )\ + rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\ + if ( bits == 14 )\ + rgb_out = (raw_>>(24-x)& 0x001F)|(raw_>>(9-x)&0x03E0)|(raw_<<(6+x)&0x7C00);\ + if ( bits == 0 )\ + rgb_out = raw_ << x;\ +} + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/win32/snes_ntsc_config.h b/win32/snes_ntsc_config.h new file mode 100644 index 00000000..88cb0ed1 --- /dev/null +++ b/win32/snes_ntsc_config.h @@ -0,0 +1,26 @@ +/* Configure library by modifying this file */ + +#ifndef SNES_NTSC_CONFIG_H +#define SNES_NTSC_CONFIG_H + +/* Format of source pixels */ +#define SNES_NTSC_IN_FORMAT SNES_NTSC_RGB16 +/* #define SNES_NTSC_IN_FORMAT SNES_NTSC_BGR15 */ + +/* The following affect the built-in blitter only; a custom blitter can +handle things however it wants. */ + +/* Bits per pixel of output. Can be 15, 16, 32, or 24 (same as 32). */ +#define SNES_NTSC_OUT_DEPTH 16 + +/* Type of input pixel values */ +#define SNES_NTSC_IN_T unsigned short + +/* Each raw pixel input value is passed through this. You might want to mask +the pixel index if you use the high bits as flags, etc. */ +#define SNES_NTSC_ADJ_IN( in ) in + +/* For each pixel, this is the basic operation: +output_color = SNES_NTSC_ADJ_IN( SNES_NTSC_IN_T ) */ + +#endif diff --git a/win32/snes_ntsc_impl.h b/win32/snes_ntsc_impl.h new file mode 100644 index 00000000..1d7adc78 --- /dev/null +++ b/win32/snes_ntsc_impl.h @@ -0,0 +1,439 @@ +/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */ + +/* Common implementation of NTSC filters */ + +#include +#include + +/* Copyright (C) 2006 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +details. You should have received a copy of the GNU Lesser General Public +License along with this module; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ + +#define DISABLE_CORRECTION 0 + +#undef PI +#define PI 3.14159265358979323846f + +#ifndef LUMA_CUTOFF + #define LUMA_CUTOFF 0.20 +#endif +#ifndef gamma_size + #define gamma_size 1 +#endif +#ifndef rgb_bits + #define rgb_bits 8 +#endif +#ifndef artifacts_max + #define artifacts_max (artifacts_mid * 1.5f) +#endif +#ifndef fringing_max + #define fringing_max (fringing_mid * 2) +#endif +#ifndef STD_HUE_CONDITION + #define STD_HUE_CONDITION( setup ) 1 +#endif + +#define ext_decoder_hue (std_decoder_hue + 15) +#define rgb_unit (1 << rgb_bits) +#define rgb_offset (rgb_unit * 2 + 0.5f) + +enum { burst_size = snes_ntsc_entry_size / burst_count }; +enum { kernel_half = 16 }; +enum { kernel_size = kernel_half * 2 + 1 }; + +typedef struct init_t +{ + float to_rgb [burst_count * 6]; + float to_float [gamma_size]; + float contrast; + float brightness; + float artifacts; + float fringing; + float kernel [rescale_out * kernel_size * 2]; +} init_t; + +#define ROTATE_IQ( i, q, sin_b, cos_b ) {\ + float t;\ + t = i * cos_b - q * sin_b;\ + q = i * sin_b + q * cos_b;\ + i = t;\ +} + +static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup ) +{ +#if rescale_out > 1 + float kernels [kernel_size * 2]; +#else + float* const kernels = impl->kernel; +#endif + + /* generate luma (y) filter using sinc kernel */ + { + /* sinc with rolloff (dsf) */ + float const rolloff = 1 + (float) setup->sharpness * (float) 0.032; + float const maxh = 32; + float const pow_a_n = (float) pow( rolloff, maxh ); + float sum; + int i; + /* quadratic mapping to reduce negative (blurring) range */ + float to_angle = (float) setup->resolution + 1; + to_angle = PI / maxh * (float) LUMA_CUTOFF * (to_angle * to_angle + 1); + + kernels [kernel_size * 3 / 2] = maxh; /* default center value */ + for ( i = 0; i < kernel_half * 2 + 1; i++ ) + { + int x = i - kernel_half; + float angle = x * to_angle; + /* instability occurs at center point with rolloff very close to 1.0 */ + if ( x || pow_a_n > (float) 1.056 || pow_a_n < (float) 0.981 ) + { + float rolloff_cos_a = rolloff * (float) cos( angle ); + float num = 1 - rolloff_cos_a - + pow_a_n * (float) cos( maxh * angle ) + + pow_a_n * rolloff * (float) cos( (maxh - 1) * angle ); + float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff; + float dsf = num / den; + kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - (float) 0.5; + } + } + + /* apply blackman window and find sum */ + sum = 0; + for ( i = 0; i < kernel_half * 2 + 1; i++ ) + { + float x = PI * 2 / (kernel_half * 2) * i; + float blackman = 0.42f - 0.5f * (float) cos( x ) + 0.08f * (float) cos( x * 2 ); + sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman); + } + + /* normalize kernel */ + sum = 1.0f / sum; + for ( i = 0; i < kernel_half * 2 + 1; i++ ) + { + int x = kernel_size * 3 / 2 - kernel_half + i; + kernels [x] *= sum; + assert( kernels [x] == kernels [x] ); /* catch numerical instability */ + } + } + + /* generate chroma (iq) filter using gaussian kernel */ + { + float const cutoff_factor = -0.03125f; + float cutoff = (float) setup->bleed; + int i; + + if ( cutoff < 0 ) + { + /* keep extreme value accessible only near upper end of scale (1.0) */ + cutoff *= cutoff; + cutoff *= cutoff; + cutoff *= cutoff; + cutoff *= -30.0f / 0.65f; + } + cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff; + + for ( i = -kernel_half; i <= kernel_half; i++ ) + kernels [kernel_size / 2 + i] = (float) exp( i * i * cutoff ); + + /* normalize even and odd phases separately */ + for ( i = 0; i < 2; i++ ) + { + float sum = 0; + int x; + for ( x = i; x < kernel_size; x += 2 ) + sum += kernels [x]; + + sum = 1.0f / sum; + for ( x = i; x < kernel_size; x += 2 ) + { + kernels [x] *= sum; + assert( kernels [x] == kernels [x] ); /* catch numerical instability */ + } + } + } + + /* + printf( "luma:\n" ); + for ( i = kernel_size; i < kernel_size * 2; i++ ) + printf( "%f\n", kernels [i] ); + printf( "chroma:\n" ); + for ( i = 0; i < kernel_size; i++ ) + printf( "%f\n", kernels [i] ); + */ + + /* generate linear rescale kernels */ + #if rescale_out > 1 + { + float weight = 1.0f; + float* out = impl->kernel; + int n = rescale_out; + do + { + float remain = 0; + int i; + weight -= 1.0f / rescale_in; + for ( i = 0; i < kernel_size * 2; i++ ) + { + float cur = kernels [i]; + float m = cur * weight; + *out++ = m + remain; + remain = cur - m; + } + } + while ( --n ); + } + #endif +} + +static float const default_decoder [6] = + { 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f }; + +static void init( init_t* impl, snes_ntsc_setup_t const* setup ) +{ + impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset; + impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit; + #ifdef default_palette_contrast + if ( !setup->palette ) + impl->contrast *= default_palette_contrast; + #endif + + impl->artifacts = (float) setup->artifacts; + if ( impl->artifacts > 0 ) + impl->artifacts *= artifacts_max - artifacts_mid; + impl->artifacts = impl->artifacts * artifacts_mid + artifacts_mid; + + impl->fringing = (float) setup->fringing; + if ( impl->fringing > 0 ) + impl->fringing *= fringing_max - fringing_mid; + impl->fringing = impl->fringing * fringing_mid + fringing_mid; + + init_filters( impl, setup ); + + /* generate gamma table */ + if ( gamma_size > 1 ) + { + float const to_float = 1.0f / (gamma_size - (gamma_size > 1)); + float const gamma = 1.1333f - (float) setup->gamma * 0.5f; + /* match common PC's 2.2 gamma to TV's 2.65 gamma */ + int i; + for ( i = 0; i < gamma_size; i++ ) + impl->to_float [i] = + (float) pow( i * to_float, gamma ) * impl->contrast + impl->brightness; + } + + /* setup decoder matricies */ + { + float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue; + float sat = (float) setup->saturation + 1; + float const* decoder = setup->decoder_matrix; + if ( !decoder ) + { + decoder = default_decoder; + if ( STD_HUE_CONDITION( setup ) ) + hue += PI / 180 * (std_decoder_hue - ext_decoder_hue); + } + + { + float s = (float) sin( hue ) * sat; + float c = (float) cos( hue ) * sat; + float* out = impl->to_rgb; + int n; + + n = burst_count; + do + { + float const* in = decoder; + int n = 3; + do + { + float i = *in++; + float q = *in++; + *out++ = i * c - q * s; + *out++ = i * s + q * c; + } + while ( --n ); + if ( burst_count <= 1 ) + break; + ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */ + } + while ( --n ); + } + } +} + +/* kernel generation */ + +#define RGB_TO_YIQ( r, g, b, y, i ) (\ + (y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\ + (i = (r) * 0.596f - (g) * 0.275f - (b) * 0.321f),\ + ((r) * 0.212f - (g) * 0.523f + (b) * 0.311f)\ +) + +#define YIQ_TO_RGB( y, i, q, to_rgb, type, r, g ) (\ + r = (type) (y + to_rgb [0] * i + to_rgb [1] * q),\ + g = (type) (y + to_rgb [2] * i + to_rgb [3] * q),\ + (type) (y + to_rgb [4] * i + to_rgb [5] * q)\ +) + +#define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1) + +enum { rgb_kernel_size = burst_size / alignment_count }; +enum { rgb_bias = rgb_unit * 2 * snes_ntsc_rgb_builder }; + +typedef struct pixel_info_t +{ + int offset; + float negate; + float kernel [4]; +} pixel_info_t; + +#if rescale_in > 1 + #define PIXEL_OFFSET_( ntsc, scaled ) \ + (kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \ + (kernel_size * 2 * scaled)) + + #define PIXEL_OFFSET( ntsc, scaled ) \ + PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\ + (((scaled) + rescale_out * 10) % rescale_out) ),\ + (1.0f - (((ntsc) + 100) & 2)) +#else + #define PIXEL_OFFSET( ntsc, scaled ) \ + (kernel_size / 2 + (ntsc) - (scaled)),\ + (1.0f - (((ntsc) + 100) & 2)) +#endif + +extern pixel_info_t const snes_ntsc_pixels [alignment_count]; + +/* Generate pixel at all burst phases and column alignments */ +static void gen_kernel( init_t* impl, float y, float i, float q, snes_ntsc_rgb_t* out ) +{ + /* generate for each scanline burst phase */ + float const* to_rgb = impl->to_rgb; + int burst_remain = burst_count; + y -= rgb_offset; + do + { + /* Encode yiq into *two* composite signals (to allow control over artifacting). + Convolve these with kernels which: filter respective components, apply + sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack + into integer. Based on algorithm by NewRisingSun. */ + pixel_info_t const* pixel = snes_ntsc_pixels; + int alignment_remain = alignment_count; + do + { + /* negate is -1 when composite starts at odd multiple of 2 */ + float const yy = y * impl->fringing * pixel->negate; + float const ic0 = (i + yy) * pixel->kernel [0]; + float const qc1 = (q + yy) * pixel->kernel [1]; + float const ic2 = (i - yy) * pixel->kernel [2]; + float const qc3 = (q - yy) * pixel->kernel [3]; + + float const factor = impl->artifacts * pixel->negate; + float const ii = i * factor; + float const yc0 = (y + ii) * pixel->kernel [0]; + float const yc2 = (y - ii) * pixel->kernel [2]; + + float const qq = q * factor; + float const yc1 = (y + qq) * pixel->kernel [1]; + float const yc3 = (y - qq) * pixel->kernel [3]; + + float const* k = &impl->kernel [pixel->offset]; + int n; + ++pixel; + for ( n = rgb_kernel_size; n; --n ) + { + float i = k[0]*ic0 + k[2]*ic2; + float q = k[1]*qc1 + k[3]*qc3; + float y = k[kernel_size+0]*yc0 + k[kernel_size+1]*yc1 + + k[kernel_size+2]*yc2 + k[kernel_size+3]*yc3 + rgb_offset; + if ( rescale_out <= 1 ) + k--; + else if ( k < &impl->kernel [kernel_size * 2 * (rescale_out - 1)] ) + k += kernel_size * 2 - 1; + else + k -= kernel_size * 2 * (rescale_out - 1) + 2; + { + int r, g, b = YIQ_TO_RGB( y, i, q, to_rgb, int, r, g ); + *out++ = PACK_RGB( r, g, b ) - rgb_bias; + } + } + } + while ( alignment_count > 1 && --alignment_remain ); + + if ( burst_count <= 1 ) + break; + + to_rgb += 6; + + ROTATE_IQ( i, q, -0.866025f, -0.5f ); /* -120 degrees */ + } + while ( --burst_remain ); +} + +static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ); + +#if DISABLE_CORRECTION + #define CORRECT_ERROR( a ) { out [i] += rgb_bias; } + #define DISTRIBUTE_ERROR( a, b, c ) { out [i] += rgb_bias; } +#else + #define CORRECT_ERROR( a ) { out [a] += error; } + #define DISTRIBUTE_ERROR( a, b, c ) {\ + snes_ntsc_rgb_t fourth = (error + 2 * snes_ntsc_rgb_builder) >> 2;\ + fourth &= (rgb_bias >> 1) - snes_ntsc_rgb_builder;\ + fourth -= rgb_bias >> 2;\ + out [a] += fourth;\ + out [b] += fourth;\ + out [c] += fourth;\ + out [i] += error - (fourth * 3);\ + } +#endif + +#define RGB_PALETTE_OUT( rgb, out_ )\ +{\ + unsigned char* out = (out_);\ + snes_ntsc_rgb_t clamped = (rgb);\ + SNES_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\ + out [0] = (unsigned char) (clamped >> 21);\ + out [1] = (unsigned char) (clamped >> 11);\ + out [2] = (unsigned char) (clamped >> 1);\ +} + +/* blitter related */ + +#ifndef restrict + #if defined (__GNUC__) + #define restrict __restrict__ + #elif defined (_MSC_VER) && _MSC_VER > 1300 + #define restrict __restrict + #else + /* no support for restricted pointers */ + #define restrict + #endif +#endif + +#include + +#if SNES_NTSC_OUT_DEPTH <= 16 + #if USHRT_MAX == 0xFFFF + typedef unsigned short snes_ntsc_out_t; + #else + #error "Need 16-bit int type" + #endif + +#else + #if UINT_MAX == 0xFFFFFFFF + typedef unsigned int snes_ntsc_out_t; + #elif ULONG_MAX == 0xFFFFFFFF + typedef unsigned long snes_ntsc_out_t; + #else + #error "Need 32-bit int type" + #endif + +#endif diff --git a/win32/wconfig.cpp b/win32/wconfig.cpp new file mode 100644 index 00000000..8018fa18 --- /dev/null +++ b/win32/wconfig.cpp @@ -0,0 +1,1218 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + +// all windows-specific command line and config file parsing/saving/loading +// this stuff was moved out of wsnes.cpp, to keep things a little tidier + +// note: +// if you want to force all users of a new version to have a +// particular setting reset to its given default, +// change the name string of that setting (in WinRegisterConfigItems) +// to something a little different... +// but if it's not in a windows-specific category, make sure you change its name elsewhere too + +#include "../port.h" +#include "../snes9x.h" +#include "wsnes9x.h" +#include "wlanguage.h" +#include "../display.h" +#include "../conffile.h" +#include "../spc7110.h" +#include "../gfx.h" +#include "../snapshot.h" +#ifdef NETPLAY_SUPPORT + #include "../netplay.h" + extern SNPServer NPServer; +#endif +#include + +static void WinDeleteRegistryEntries (); +void WinSetDefaultValues (); +void WinDeleteRecentGamesList (); + +HANDLE configMutex = NULL; + +void S9xParseArg (char **argv, int &i, int argc) +{ + if (strcasecmp (argv [i], "-restore") == 0) + { + WinDeleteRegistryEntries (); + WinSetDefaultValues (); + } + else if (strcasecmp (argv[i], "-hidemenu") == 0) + { + GUI.HideMenu = true; + } + else if (strcasecmp (argv[i], "-fullscreen") == 0) + { + GUI.FullScreen = true; + } +} + +extern char multiRomA [MAX_PATH]; // lazy, should put in sGUI and add init to {0} somewhere +extern char multiRomB [MAX_PATH]; + +void WinSetDefaultValues () +{ + // TODO: delete the parts that are already covered by the default values in WinRegisterConfigItems + + char temp[4]; + strcpy(temp,"C:\\"); + + GUI.ControllerOption = SNES_JOYPAD; + GUI.ValidControllerOptions = 0xFFFF; + GUI.IgnoreNextMouseMove = false; + + GUI.HideMenu = false; + GUI.window_size.left = 0; + GUI.window_size.right = 524; + GUI.window_size.top = 0; + GUI.window_size.bottom = 524; + GUI.FullscreenMode.width = 640; + GUI.FullscreenMode.height = 480; + GUI.FullscreenMode.depth = 16; + GUI.Scale = FILTER_NONE; + GUI.NextScale = FILTER_NONE; + GUI.ScaleHiRes = FILTER_NONE; + GUI.NextScaleHiRes = FILTER_NONE; + GUI.DoubleBuffered = false; + GUI.FullScreen = false; + GUI.Stretch = false; + GUI.FlipCounter = 0; + GUI.NumFlipFrames = 1; + GUI.BilinearFilter = false; + GUI.ScreenCleared = true; + GUI.LockDirectories = false; + GUI.window_maximized = false; + + WinDeleteRecentGamesList (); + + // ROM Options + memset (&Settings, 0, sizeof (Settings)); + + Settings.ForceLoROM = false; + Settings.ForceInterleaved = false; + + Settings.ForceNotInterleaved = false; + Settings.ForceInterleaved = false; + Settings.ForceInterleaved2 = false; + + Settings.ForcePAL = false; + Settings.ForceNTSC = false; + Settings.ForceHeader = false; + Settings.ForceNoHeader = false; + + // Sound options + Settings.SoundSync = FALSE; + Settings.Mute = FALSE; + Settings.SoundPlaybackRate = 32000; + Settings.SixteenBitSound = TRUE; + Settings.Stereo = TRUE; + Settings.ReverseStereo = FALSE; + GUI.SoundChannelEnable=255; + GUI.FAMute = FALSE; + + // Tracing options + Settings.TraceDMA = false; + Settings.TraceHDMA = false; + Settings.TraceVRAM = false; + Settings.TraceUnknownRegisters = false; + Settings.TraceDSP = false; + + // ROM timing options (see also H_Max above) + Settings.PAL = false; + Settings.FrameTimePAL = 20000; + Settings.FrameTimeNTSC = 16667; + Settings.FrameTime = 16667; + + // CPU options + Settings.HDMATimingHack = 100; + Settings.Shutdown = false; + Settings.ShutdownMaster = false; + Settings.BlockInvalidVRAMAccess = true; + Settings.DisableIRQ = false; + Settings.Paused = false; + Timings.H_Max = SNES_CYCLES_PER_SCANLINE; + Timings.HBlankStart = (256 * Timings.H_Max) / SNES_HCOUNTER_MAX; + Settings.SkipFrames = AUTO_FRAMERATE; + + // ROM image and peripheral options + Settings.MultiPlayer5Master = false; + Settings.SuperScopeMaster = false; + Settings.MouseMaster = false; + Settings.SuperFX = false; + + // SNES graphics options + Settings.DisableGraphicWindows = false; + Settings.DisableHDMA = false; + GUI.HeightExtend = false; + Settings.DisplayFrameRate = false; +// Settings.SixteenBit = true; + Settings.Transparency = true; + Settings.SupportHiRes = true; + Settings.AutoDisplayMessages = false; // this port supports text display on post-rendered surface + + Settings.DisplayPressedKeys = 0; + GUI.CurrentSaveSlot = 0; + Settings.AutoSaveDelay = 15; + Settings.ApplyCheats = true; + + Settings.TurboMode = false; + Settings.TurboSkipFrames = 15; + GUI.TurboModeToggle = true; + Settings.AutoMaxSkipFrames = 1; + +#ifdef NETPLAY_SUPPORT + Settings.Port = 1996; + NetPlay.MaxFrameSkip = 10; + NetPlay.MaxBehindFrameCount = 10; + NPServer.SyncByReset = true; + NPServer.SendROMImageOnConnect = false; +#endif + + GUI.FreezeFileDir [0] = 0; + Settings.TakeScreenshot=false; + Settings.StretchScreenshots=1; + + GUI.EmulatedFullscreen = false; + + GUI.Language=0; +} + + +static bool try_save(const char *fname, ConfigFile &conf){ + STREAM fp; + if((fp=OPEN_STREAM(fname, "w"))!=NULL){ + fprintf(stdout, "Saving config file %s\n", fname); + CLOSE_STREAM(fp); + conf.SaveTo(fname); + return true; + } + return false; +} + +static char rom_filename [MAX_PATH] = {0,}; + +static bool S9xSaveConfigFile(ConfigFile &conf){ + + configMutex = CreateMutex(NULL, FALSE, "Snes9xConfigMutex"); + int times = 0; + DWORD waitVal = WAIT_TIMEOUT; + while(waitVal == WAIT_TIMEOUT && ++times <= 150) // wait at most 15 seconds + waitVal = WaitForSingleObject(configMutex, 100); + + // save over the .conf file if it already exists, otherwise save over the .cfg file + std::string fname; + fname=S9xGetDirectory(DEFAULT_DIR); + fname+=SLASH_STR S9X_CONF_FILE_NAME; + + // ensure previous config file is not lost if we crash while writing the new one + std::string ftemp; + { + CopyFile(fname.c_str(), (fname + ".autobak").c_str(), FALSE); + + ftemp=S9xGetDirectory(DEFAULT_DIR); + ftemp+=SLASH_STR "config_error"; + FILE* tempfile = fopen(ftemp.c_str(), "wb"); + if(tempfile) fclose(tempfile); + } + + bool ret = try_save(fname.c_str(), conf); + + remove(ftemp.c_str()); + remove((fname + ".autobak").c_str()); + + ReleaseMutex(configMutex); + CloseHandle(configMutex); + + return ret; +} + + +static void WinDeleteRegistryEntries () +{ +// WinDeleteRegKey (HKEY_CURRENT_USER, S9X_REG_KEY_BASE); +} + +static inline char *SkipSpaces (char *p) +{ + while (*p && isspace (*p)) + p++; + + return (p); +} + +const char* WinParseCommandLineAndLoadConfigFile (char *line) +{ + // Break the command line up into an array of string pointers, each pointer + // points at a separate word or character sequence enclosed in quotes. + +#define MAX_PARAMETERS 100 + char *p = line; + static char *parameters [MAX_PARAMETERS]; + int count = 0; + + parameters [count++] = "Snes9XW"; + + while (count < MAX_PARAMETERS && *p) + { + p = SkipSpaces (p); + if (*p == '"') + { + p++; + parameters [count++] = p; + while (*p && *p != '"') + p++; + *p++ = 0; + } + else + if (*p == '\'') + { + p++; + parameters [count++] = p; + while (*p && *p != '\'') + p++; + *p++ = 0; + } + else + { + parameters [count++] = p; + while (*p && !isspace (*p)) + p++; + if (!*p) + break; + *p++ = 0; + } + } + + configMutex = CreateMutex(NULL, FALSE, "Snes9xConfigMutex"); + int times = 0; + DWORD waitVal = WAIT_TIMEOUT; + while(waitVal == WAIT_TIMEOUT && ++times <= 150) // wait at most 15 seconds + waitVal = WaitForSingleObject(configMutex, 100); + + // ensure previous config file is not lost if we crashed while writing a new one + { + std::string ftemp; + ftemp=S9xGetDirectory(DEFAULT_DIR); + ftemp+=SLASH_STR "config_error"; + FILE* tempfile = fopen(ftemp.c_str(), "rb"); + if(tempfile) + { + fclose(tempfile); + + std::string fname; + for(int i=0; i<2; i++) + { + fname=S9xGetDirectory(DEFAULT_DIR); + if(i == 0) fname+=SLASH_STR "snes9x.conf"; + else if(i == 1) fname+=SLASH_STR "snes9x.cfg"; + + tempfile = fopen((fname + ".autobak").c_str(), "rb"); + if(tempfile) + { + fclose(tempfile); + MoveFileEx((fname + ".autobak").c_str(), fname.c_str(), MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH); + } + } + remove(ftemp.c_str()); + } + } + + S9xLoadConfigFiles(parameters, count); + + ReleaseMutex(configMutex); + CloseHandle(configMutex); + + const char* rf = S9xParseArgs (parameters, count); + /*if(rf) + strcpy(rom_filename, rf); + else + rom_filename[0] = '\0';*/ + + return rf; +} + +#define S(x) GAMEDEVICE_VK_##x +#define SO(x) GAMEDEVICE_VK_OEM_##x +static const char* keyToString [256] = +{ + "Unassigned","LMB","RMB","Break","MMB","XMB1","XMB2","0x07", + S(BACK),S(TAB),"0x0A","0x0B",S(CLEAR),S(RETURN),"0x0E","0x0F", + S(SHIFT),S(CONTROL),S(MENU),S(PAUSE),S(CAPITAL),"Kana","0x16","Junja", + "Final","Kanji","0x1A",S(ESCAPE),"Convert","NonConvert","Accept","ModeChange", + S(SPACE),S(PRIOR),S(NEXT),S(END),S(HOME),S(LEFT),S(UP),S(RIGHT), + S(DOWN),S(SELECT),S(PRINT),S(EXECUTE),S(SNAPSHOT),S(INSERT),S(DELETE),S(HELP), + "0","1","2","3","4","5","6","7", + "8","9","0x3A","0x3B","0x3C","0x3D","0x3E","0x3F", + "0x40","A","B","C","D","E","F","G", + "H","I","J","K","L","M","N","O", + "P","Q","R","S","T","U","V","W", + "X","Y","Z",S(LWIN),S(RWIN),S(APPS),"0x5E","Sleep", + "Pad0","Pad1","Pad2","Pad3","Pad4","Pad5","Pad6","Pad7", + "Pad8","Pad9",S(MULTIPLY),S(ADD),S(SEPARATOR),S(SUBTRACT),S(DECIMAL),S(DIVIDE), + S(F1),S(F2),S(F3),S(F4),S(F5),S(F6),S(F7),S(F8), + S(F9),S(F10),S(F11),S(F12),"F13","F14","F15","F16", + "F17","F18","F19","F20","F21","F22","F23","F24", + "0x88","0x89","0x8A","0x8B","0x8C","0x8D","0x8E","0x8F", + S(NUMLOCK),S(SCROLL),"PadEqual","Masshou","Touroku","Loya","Roya","0x97", + "0x98","0x99","0x9A","0x9B","0x9C","0x9D","0x9E","0x9F", + S(LSHIFT),S(RSHIFT),S(LCONTROL),S(RCONTROL),S(LMENU),S(RMENU),"BrowserBack","BrowserForward", + "BrowserRefresh","BrowserStop","BrowserSearch","BrowserFavorites","BrowserHome","VolumeMute","VolumeDown","VolumeUp", + "MediaNextTrack","MediaPrevTrack","MediaStop","MediaPlayPause","LaunchMail","MediaSelect","LaunchApp1","LaunchApp2", + "0xB8","0xB9",";","+",",",SO(MINUS),".",SO(2), + SO(3),"0xC1","0xC2","0xC3","0xC4","0xC5","0xC6","0xC7", + "0xC8","0xC9","0xCA","0xCB","0xCC","0xCD","0xCE","0xCF", + "0xD0","0xD1","0xD2","0xD3","0xD4","0xD5","0xD6","0xD7", + "0xD8","0xD9","0xDA",SO(4),"Backslash",SO(6),"'","OEM8", + "0xE0","AX","<>","ICOHelp","ICO00","Process","ICOClear","Packet", + "0xE8","Reset","Jump","PA1_2","PA2","PA3","WSCTRL","CUSEL", + "Attention2","Finish","Copy","Auto","ENLW","Backtab","Attention","CRSEL", + "EXSEL","EREOF","Play","Zoom","NoName","PA1","Clear2","0xFF" +}; +static const char* keyToAlternateString [256] = +{ + "none","LeftClick","RightClick","Cancel","MiddleClick","","","","Back","","","","","Return","","", + "","","Menu","","","","","","","","","Escape","","","","", + "","PageUp","PageDown","","","","","","","","PrintScreen","","","Ins","Del","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "NumLock","ScrollLock","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","",SO(1),SO(PLUS),SO(COMMA),"Minus",SO(PERIOD),"?", + "","","","","","","","","","","","","","","","", + "","","","oem_pa1","","","","","","","","LBracket","|","RBracket",SO(7),"", + "ATTN2","","","","","","","","","","","","","","ATTN","", + "","","","","","","","","","","","","","","","" +}; +#undef S +#undef SO + + + + +// We will maintain our own list of items to put in the config file, +// so that each config item has only one point of change across both saving and loading +// and to allow us to manage custom types of config items, such as virtual key codes represented as strings + +enum ConfigItemType { + CIT_BOOL, CIT_INT, CIT_UINT, CIT_STRING, CIT_INVBOOL, CIT_BOOLONOFF, CIT_INVBOOLONOFF, CIT_VKEY, CIT_VKEYMOD +}; + +struct ConfigItem +{ + const char* name; + void* addr; + int size; + void* def; + const char* comment; + ConfigItemType type; + + ConfigItem(const char* nname, void* naddr, int nsize, void* ndef, const char* ncomment, ConfigItemType ntype) { + addr = naddr; name = nname; size = nsize; def = ndef; comment = ncomment; type = ntype; + } + + void Get(ConfigFile& conf) { + switch(type) + { + case CIT_BOOL: + case CIT_BOOLONOFF: + if(size == 1) *(uint8 *)addr = (uint8) conf.GetBool(name, def!=0); + if(size == 2) *(uint16*)addr = (uint16)conf.GetBool(name, def!=0); + if(size == 4) *(uint32*)addr = (uint32)conf.GetBool(name, def!=0); + if(size == 8) *(uint64*)addr = (uint64)conf.GetBool(name, def!=0); + break; + case CIT_INT: + if(size == 1) *(uint8 *)addr = (uint8) conf.GetInt(name, reinterpret_cast(def)); + if(size == 2) *(uint16*)addr = (uint16)conf.GetInt(name, reinterpret_cast(def)); + if(size == 4) *(uint32*)addr = (uint32)conf.GetInt(name, reinterpret_cast(def)); + if(size == 8) *(uint64*)addr = (uint64)conf.GetInt(name, reinterpret_cast(def)); + break; + case CIT_UINT: + if(size == 1) *(uint8 *)addr = (uint8) conf.GetUInt(name, reinterpret_cast(def)); + if(size == 2) *(uint16*)addr = (uint16)conf.GetUInt(name, reinterpret_cast(def)); + if(size == 4) *(uint32*)addr = (uint32)conf.GetUInt(name, reinterpret_cast(def)); + if(size == 8) *(uint64*)addr = (uint64)conf.GetUInt(name, reinterpret_cast(def)); + break; + case CIT_STRING: + strncpy((char*)addr, conf.GetString(name, reinterpret_cast(def)), size-1); + ((char*)addr)[size-1] = '\0'; + break; + case CIT_INVBOOL: + case CIT_INVBOOLONOFF: + if(size == 1) *(uint8 *)addr = (uint8) !conf.GetBool(name, def!=0); + if(size == 2) *(uint16*)addr = (uint16)!conf.GetBool(name, def!=0); + if(size == 4) *(uint32*)addr = (uint32)!conf.GetBool(name, def!=0); + if(size == 8) *(uint64*)addr = (uint64)!conf.GetBool(name, def!=0); + break; + case CIT_VKEY: + { + uint16 keyNum = (uint16)conf.GetUInt(name, reinterpret_cast(def)); + const char* keyStr = conf.GetString(name); + if(keyStr) + { + for(int i=0;i<512;i++) + { + if(i<256) // keys + { + if(!strcasecmp(keyStr,keyToString[i]) || + (*keyToAlternateString[i] && !strcasecmp(keyStr,keyToAlternateString[i]))) + { + keyNum = i; + break; + } + } + else // joystick: + { + char temp [128]; + extern void TranslateKey(WORD keyz,char *out); + TranslateKey(0x8000|(i-256),temp); + if(strlen(keyStr)>3 && !strcasecmp(keyStr+3,temp+3)) + { + for(int j = 0 ; j < 16 ; j++) + { + if(keyStr[2]-'0' == j || keyStr[2]-'a' == j-10) + { + keyNum = 0x8000|(i-256)|(j<<8); + i = 512; + break; + } + } + } + } + } + } + if(size == 1) *(uint8 *)addr = (uint8) keyNum; + if(size == 2) *(uint16*)addr = (uint16)keyNum; + if(size == 4) *(uint32*)addr = (uint32)keyNum; + if(size == 8) *(uint64*)addr = (uint64)keyNum; + } + break; + case CIT_VKEYMOD: + { + uint16 modNum = 0; + const char* modStr = conf.GetString(name); + if(modStr) { + if(strstr(modStr, "ft") || strstr(modStr, "FT")) modNum |= CUSTKEY_SHIFT_MASK; + if(strstr(modStr, "tr") || strstr(modStr, "TR")) modNum |= CUSTKEY_CTRL_MASK; + if(strstr(modStr, "lt") || strstr(modStr, "LT")) modNum |= CUSTKEY_ALT_MASK; + } + if(!modNum && (!modStr || strcasecmp(modStr, "none"))) + modNum = conf.GetUInt(name, reinterpret_cast(def)); + if(size == 1) *(uint8 *)addr = (uint8) modNum; + if(size == 2) *(uint16*)addr = (uint16)modNum; + if(size == 4) *(uint32*)addr = (uint32)modNum; + if(size == 8) *(uint64*)addr = (uint64)modNum; + } + break; + } + + // if it had a comment, override our own with it + const char* newComment = conf.GetComment(name); + if(newComment && *newComment) + comment = newComment; + } + + void Set(ConfigFile& conf) { + switch(type) + { + case CIT_BOOL: + if(size == 1) conf.SetBool(name, 0!=(*(uint8 *)addr), "TRUE","FALSE", comment); + if(size == 2) conf.SetBool(name, 0!=(*(uint16*)addr), "TRUE","FALSE", comment); + if(size == 4) conf.SetBool(name, 0!=(*(uint32*)addr), "TRUE","FALSE", comment); + if(size == 8) conf.SetBool(name, 0!=(*(uint64*)addr), "TRUE","FALSE", comment); + break; + case CIT_BOOLONOFF: + if(size == 1) conf.SetBool(name, 0!=(*(uint8 *)addr), "ON","OFF", comment); + if(size == 2) conf.SetBool(name, 0!=(*(uint16*)addr), "ON","OFF", comment); + if(size == 4) conf.SetBool(name, 0!=(*(uint32*)addr), "ON","OFF", comment); + if(size == 8) conf.SetBool(name, 0!=(*(uint64*)addr), "ON","OFF", comment); + break; + case CIT_INT: + if(size == 1) conf.SetInt(name, (int32)(*(uint8 *)addr), comment); + if(size == 2) conf.SetInt(name, (int32)(*(uint16*)addr), comment); + if(size == 4) conf.SetInt(name, (int32)(*(uint32*)addr), comment); + if(size == 8) conf.SetInt(name, (int32)(*(uint64*)addr), comment); + break; + case CIT_UINT: + if(size == 1) conf.SetUInt(name, (uint32)(*(uint8 *)addr), 10, comment); + if(size == 2) conf.SetUInt(name, (uint32)(*(uint16*)addr), 10, comment); + if(size == 4) conf.SetUInt(name, (uint32)(*(uint32*)addr), 10, comment); + if(size == 8) conf.SetUInt(name, (uint32)(*(uint64*)addr), 10, comment); + break; + case CIT_STRING: + if((char*)addr) + conf.SetString(name, (char*)addr, comment); + break; + case CIT_INVBOOL: + if(size == 1) conf.SetBool(name, 0==(*(uint8 *)addr), "TRUE","FALSE", comment); + if(size == 2) conf.SetBool(name, 0==(*(uint16*)addr), "TRUE","FALSE", comment); + if(size == 4) conf.SetBool(name, 0==(*(uint32*)addr), "TRUE","FALSE", comment); + if(size == 8) conf.SetBool(name, 0==(*(uint64*)addr), "TRUE","FALSE", comment); + break; + case CIT_INVBOOLONOFF: + if(size == 1) conf.SetBool(name, 0==(*(uint8 *)addr), "ON","OFF", comment); + if(size == 2) conf.SetBool(name, 0==(*(uint16*)addr), "ON","OFF", comment); + if(size == 4) conf.SetBool(name, 0==(*(uint32*)addr), "ON","OFF", comment); + if(size == 8) conf.SetBool(name, 0==(*(uint64*)addr), "ON","OFF", comment); + break; + case CIT_VKEY: + { + uint16 keyNum = 0; + if(size == 1) keyNum = (uint8)(*(uint8 *)addr); + if(size == 2) keyNum = (uint16)(*(uint16*)addr); + if(size == 4) keyNum = (uint16)(*(uint32*)addr); + if(size == 8) keyNum = (uint16)(*(uint64*)addr); + if(keyNum < 256) conf.SetString(name, keyToString[keyNum], comment); + else if(keyNum & 0x8000) { + char temp [128]; + extern void TranslateKey(WORD keyz,char *out); + TranslateKey(keyNum,temp); + conf.SetString(name, temp, comment); + } + else conf.SetUInt(name, keyNum, 16, comment); + } + break; + case CIT_VKEYMOD: + { + uint16 modNum = 0; + if(size == 1) modNum = (uint8)(*(uint8 *)addr); + if(size == 2) modNum = (uint16)(*(uint16*)addr); + if(size == 4) modNum = (uint16)(*(uint32*)addr); + if(size == 8) modNum = (uint16)(*(uint64*)addr); + std::string modStr; + if(modNum & CUSTKEY_CTRL_MASK) modStr += "Ctrl "; + if(modNum & CUSTKEY_ALT_MASK) modStr += "Alt "; + if(modNum & CUSTKEY_SHIFT_MASK) modStr += "Shift "; + if(!(modNum & (CUSTKEY_CTRL_MASK|CUSTKEY_ALT_MASK|CUSTKEY_SHIFT_MASK))) modStr = "none"; + else modStr.erase(modStr.length()-1); + conf.SetString(name, modStr, comment); + } + break; + } + } +}; + +std::vector configItems; +// var must be a persistent variable. In the case of strings, it must point to a writeable character array. +#define AddItemC(name, var, def, comment, type) configItems.push_back(ConfigItem((const char*)(CATEGORY "::" name), (void*)(pint)(&var), sizeof(var), (void*)(pint)def, (const char*)comment, (ConfigItemType)type)) +#define AddItem(name, var, def, type) AddItemC(name,var,def,"",type) +#define AddUInt(name, var, def) AddItem(name,var,def,CIT_UINT) +#define AddInt(name, var, def) AddItem(name,var,def,CIT_INT) +#define AddBool(name, var, def) AddItem(name,var,def,CIT_BOOL) +#define AddBool2(name, var, def) AddItem(name,var,def,CIT_BOOLONOFF) +#define AddInvBool(name, var, def) AddItem(name,var,def,CIT_INVBOOL) +#define AddInvBool2(name, var, def) AddItem(name,var,def,CIT_INVBOOLONOFF) +#define AddVKey(name, var, def) AddItem(name,var,def,CIT_VKEY) +#define AddVKMod(name, var, def) AddItem(name,var,def,CIT_VKEYMOD) +#define AddUIntC(name, var, def, comment) AddItemC(name,var,def,comment,CIT_UINT) +#define AddIntC(name, var, def, comment) AddItemC(name,var,def,comment,CIT_INT) +#define AddBoolC(name, var, def, comment) AddItemC(name,var,def,comment,CIT_BOOL) +#define AddBool2C(name, var, def, comment) AddItemC(name,var,def,comment,CIT_BOOLONOFF) +#define AddInvBoolC(name, var, def, comment) AddItemC(name,var,def,comment,CIT_INVBOOL) +#define AddInvBool2C(name, var, def, comment) AddItemC(name,var,def,comment,CIT_INVBOOLONOFF) +#define AddStringC(name, var, buflen, def, comment) configItems.push_back(ConfigItem((const char*)(CATEGORY "::" name), (void*)(pint)var, buflen, (void*)(pint)def, (const char*)comment, CIT_STRING)) +#define AddString(name, var, buflen, def) AddStringC(name, var, buflen, def, "") + +static char filterString [1024], filterString2 [1024], snapVerString [256]; +static bool niceAlignment, showComments, readOnlyConfig; +static int configSort; +static BOOL loadedShutdownMaster; +static BOOL preSaveShutdownMaster; + +void WinPreSave(ConfigFile& conf) +{ + strcpy(filterString, "output filter: "); + for(int i=0;i GetSystemMetrics(SM_CXSCREEN)+30) GUI.window_size.left = GetSystemMetrics(SM_CXSCREEN)+30-GUI.window_size.right; + if(GUI.window_size.top+GUI.window_size.bottom > GetSystemMetrics(SM_CYSCREEN)+30) GUI.window_size.top = GetSystemMetrics(SM_CYSCREEN)+30-GUI.window_size.bottom;*/ + int extra_width = 2*(GetSystemMetrics(SM_CXBORDER) + + GetSystemMetrics(SM_CXDLGFRAME)); + int extra_height = 2*(GetSystemMetrics(SM_CYBORDER) + + GetSystemMetrics(SM_CYDLGFRAME)) + + GetSystemMetrics(SM_CYCAPTION) + + (GUI.HideMenu ? 0 : (GetSystemMetrics(SM_CYMENU) + + (GUI.window_size.right <= 392 ? GetSystemMetrics(SM_CYMENU) : 0) + // HACK: accounts for menu wrapping (when width is small) + (GUI.window_size.right <= 208 ? GetSystemMetrics(SM_CYMENU) : 0) + + (GUI.window_size.right <= 148 ? GetSystemMetrics(SM_CYMENU) : 0))); + GUI.window_size.right += GUI.window_size.left; + GUI.window_size.bottom += GUI.window_size.top; + GUI.window_size.right += extra_width; + GUI.window_size.bottom += extra_height; + /*switch(Settings.SoundPlaybackRate){ + case 1: Settings.SoundPlaybackRate = 8000; break; + case 2: Settings.SoundPlaybackRate = 11025; break; + case 3: Settings.SoundPlaybackRate = 16000; break; + case 4: Settings.SoundPlaybackRate = 22050; break; + case 5: Settings.SoundPlaybackRate = 30000; break; + case 6: Settings.SoundPlaybackRate = 32000; break; + case 7: Settings.SoundPlaybackRate = 35000; break; + case 8: Settings.SoundPlaybackRate = 44100; break; + case 9: Settings.SoundPlaybackRate = 48000; break; + }*/ + Settings.ShutdownMaster = preSaveShutdownMaster; // revert temp change +} +void WinPostLoad(ConfigFile& conf) +{ + int i; + GUI.NextScale = GUI.Scale; + if(Settings.DisplayPressedKeys) Settings.DisplayPressedKeys = 2; + for(i=0;i<8;i++) Joypad[i+8].Enabled = Joypad[i].Enabled; + if(GUI.MaxRecentGames < 1) GUI.MaxRecentGames = 1; + if(GUI.MaxRecentGames > MAX_RECENT_GAMES_LIST_SIZE) GUI.MaxRecentGames = MAX_RECENT_GAMES_LIST_SIZE; + bool gap = false; + for(i=0;i + +#include +//#define DEBUGGER + +#ifndef max +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +BYTE *ScreenBuf1 = NULL; +BYTE *ScreenBuffer = NULL; + +struct SJoyState Joystick [16]; +uint32 joypads [8]; +bool8 do_frame_adjust=false; + +// avi variables +static uint8* avi_buffer = NULL; +static uint8* avi_sound_buffer = NULL; +static int avi_sound_bytes_per_sample = 0; +static int avi_sound_samples_per_update = 0; +static int avi_width = 0; +static int avi_height = 0; +static uint32 avi_skip_frames = 0; +static bool pre_avi_soundsync = true; +//void Convert8To24 (SSurface *src, SSurface *dst, RECT *srect); +void Convert16To24 (SSurface *src, SSurface *dst, RECT *srect); +void DoAVIOpen(const char* filename); +void DoAVIClose(int reason); + +void S9xWinScanJoypads (); + +typedef struct +{ + uint8 red; + uint8 green; + uint8 blue; +} Colour; + +void ConvertDepth (SSurface *src, SSurface *dst, RECT *); +static Colour FixedColours [256]; +static uint8 palette [0x10000]; + +FILE *trace_fs = NULL; + +int __fastcall Normalize (int cur, int min, int max) +{ + int Result = 0; + + if ((max - min) == 0) + return (Result); + + Result = cur - min; + Result = (Result * 200) / (max - min); + Result -= 100; + + return (Result); +} + +void S9xTextMode( void) +{ +} + +void S9xGraphicsMode () +{ +} + +void S9xExit( void) +{ + SendMessage (GUI.hWnd, WM_COMMAND, ID_FILE_EXIT, 0); +} + +const char *S9xGetFilename (const char *ex, enum s9x_getdirtype dirtype) +{ + static char filename [PATH_MAX + 1]; + char dir [_MAX_DIR + 1]; + char drive [_MAX_DRIVE + 1]; + char fname [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + _snprintf(filename, sizeof(filename), "%s" SLASH_STR "%s%s", + S9xGetDirectory(dirtype), fname, ex); + return (filename); +} + +const void S9xGetLastDirectory (char* buffer, int buf_len) +{ + if(buf_len <= 0) + return; + + GetCurrentDirectory(buf_len, buffer); +} + +#define IS_SLASH(x) ((x) == '\\' || (x) == '/') +static char startDirectory [PATH_MAX]; +static bool startDirectoryValid = false; + +const char *S9xGetDirectory (enum s9x_getdirtype dirtype) +{ +// _fullpath + if(!startDirectoryValid) + { + // directory from which the executable was launched +// GetCurrentDirectory(PATH_MAX, startDirectory); + + // directory of the executable's location: + GetModuleFileName(NULL, startDirectory, PATH_MAX); + for(int i=strlen(startDirectory); i>=0; i--){ + if(IS_SLASH(startDirectory[i])){ + startDirectory[i]='\0'; + break; + } + } + + startDirectoryValid = true; + } + + SetCurrentDirectory(startDirectory); // makes sure relative paths are relative to the application's location + + const char* rv = startDirectory; + + switch(dirtype){ + default: + case DEFAULT_DIR: + case HOME_DIR: + break; + + case SCREENSHOT_DIR: + rv = GUI.ScreensDir; + break; + + case ROM_DIR: + rv = GUI.RomDir; + break; + + case SRAM_DIR: + rv = GUI.SRAMFileDir; + break; + + case BIOS_DIR: + rv = GUI.BiosDir; + break; + + case SPC_DIR: + rv = GUI.SPCDir; + break; + + case IPS_DIR: + case CHEAT_DIR: + rv = GUI.PatchDir; + break; + + case SNAPSHOT_DIR: + rv = GUI.FreezeFileDir; + break; + + case ROMFILENAME_DIR: { + static char filename [PATH_MAX]; + strcpy(filename, Memory.ROMFilename); + if(!filename[0]) + rv = GUI.RomDir; + for(int i=strlen(filename); i>=0; i--){ + if(IS_SLASH(filename[i])){ + filename[i]='\0'; + break; + } + } + rv = filename; + } + break; + } + + mkdir(rv); + + return rv; +} + +///*extern "C"*/ const char *S9xGetFilename (const char *e) +//{ +// static char filename [_MAX_PATH + 1]; +// char drive [_MAX_DRIVE + 1]; +// char dir [_MAX_DIR + 1]; +// char fname [_MAX_FNAME + 1]; +// char ext [_MAX_EXT + 1]; +// +// if (strlen (GUI.FreezeFileDir)) +// { +// _splitpath (Memory.ROMFilename, drive, dir, fname, ext); +// strcpy (filename, GUI.FreezeFileDir); +// strcat (filename, TEXT("\\")); +// strcat (filename, fname); +// strcat (filename, e); +// } +// else +// { +// _splitpath (Memory.ROMFilename, drive, dir, fname, ext); +// _makepath (filename, drive, dir, fname, e); +// } +// +// return (filename); +//} + +const char *S9xGetFilenameInc (const char *e, enum s9x_getdirtype dirtype) +{ + static char filename [PATH_MAX + 1]; + char dir [_MAX_DIR + 1]; + char drive [_MAX_DRIVE + 1]; + char fname [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + unsigned int i=0; + const char *d; + + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + d=S9xGetDirectory(dirtype); + do { + _snprintf(filename, sizeof(filename), "%s\\%s%03d%s", d, fname, i, e); + i++; + } while(_access (filename, 0) == 0 && i!=0); + + return (filename); +} + +bool8 S9xOpenSnapshotFile( const char *fname, bool8 read_only, STREAM *file) +{ + char filename [_MAX_PATH + 1]; + char drive [_MAX_DRIVE + 1]; + char dir [_MAX_DIR + 1]; + char fn [_MAX_FNAME + 1]; + char ext [_MAX_EXT + 1]; + + _splitpath( fname, drive, dir, fn, ext); + _makepath( filename, drive, dir, fn, ext[0] == '\0' ? ".000" : ext); + + if (read_only) + { + if ((*file = OPEN_STREAM (filename, "rb"))) + return (TRUE); + } + else + { + if ((*file = OPEN_STREAM (filename, "wb"))) + return (TRUE); + FILE *fs = fopen (filename, "rb"); + if (fs) + { + sprintf (String, "Freeze file \"%s\" exists but is read only", + filename); + fclose (fs); + S9xMessage (S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, String); + } + else + { + sprintf (String, "Cannot create freeze file \"%s\". Directory is read-only or does not exist.", filename); + + S9xMessage (S9X_ERROR, S9X_FREEZE_FILE_NOT_FOUND, String); + } + } + return (FALSE); +} + +void S9xCloseSnapshotFile( STREAM file) +{ + CLOSE_STREAM (file); +} + +void S9xMessage (int type, int, const char *str) +{ +#ifdef DEBUGGER + static FILE *out = NULL; + + if (out == NULL) + out = fopen ("out.txt", "w"); + + fprintf (out, "%s\n", str); +#endif + + S9xSetInfoString (str); + + // if we can't draw on the screen, messagebox it + // also send to stderr/stdout depending on message type + switch(type) + { + case S9X_INFO: + if(Settings.StopEmulation) + fprintf(stdout, "%s\n", str); + break; + case S9X_WARNING: + fprintf(stdout, "%s\n", str); + if(Settings.StopEmulation) + MessageBox(GUI.hWnd, str, "Warning", MB_OK | MB_ICONWARNING); + break; + case S9X_ERROR: + fprintf(stderr, "%s\n", str); + if(Settings.StopEmulation) + MessageBox(GUI.hWnd, str, "Error", MB_OK | MB_ICONERROR); + break; + case S9X_FATAL_ERROR: + fprintf(stderr, "%s\n", str); + if(Settings.StopEmulation) + MessageBox(GUI.hWnd, str, "Fatal Error", MB_OK | MB_ICONERROR); + break; + default: + fprintf(stdout, "%s\n", str); + break; + } +} + +/*unsigned long _interval = 10; +long _buffernos = 4; +long _blocksize = 4400; +long _samplecount = 440; +long _maxsamplecount = 0; +long _buffersize = 0; + +bool StartPlaying = false; +DWORD _lastblock = 0; +bool8 pending_setup = false; +long pending_rate = 0; +bool8 pending_16bit = false; +bool8 pending_stereo = false;*/ +extern uint8 *syncSoundBuffer; + +//static bool8 block_signal = FALSE; +//static volatile bool8 pending_signal = FALSE; + +extern unsigned long START; + +void S9xSyncSpeed( void) +{ +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlay) + { +#if defined (NP_DEBUG) && NP_DEBUG == 2 + printf ("CLIENT: SyncSpeed @%d\n", timeGetTime () - START); +#endif + S9xWinScanJoypads (); + + LONG prev; + BOOL success; + + // Wait for heart beat from server + if ((success = ReleaseSemaphore (GUI.ClientSemaphore, 1, &prev)) && + prev == 0) + { + // No heartbeats already arrived, have to wait for one. + // Mop up the ReleaseSemaphore test above... + WaitForSingleObject (GUI.ClientSemaphore, 0); + + // ... and then wait for the real sync-signal from the + // client loop thread. + NetPlay.PendingWait4Sync = WaitForSingleObject (GUI.ClientSemaphore, 100) != WAIT_OBJECT_0; +#if defined (NP_DEBUG) && NP_DEBUG == 2 + if (NetPlay.PendingWait4Sync) + printf ("CLIENT: PendingWait4Sync1 @%d\n", timeGetTime () - START); +#endif + IPPU.RenderThisFrame = TRUE; + IPPU.SkippedFrames = 0; + } + else + { + if (success) + { + // Once for the ReleaseSemaphore above... + WaitForSingleObject (GUI.ClientSemaphore, 0); + if (prev == 4 && NetPlay.Waiting4EmulationThread) + { + // Reached the lower behind count threshold - tell the + // server its safe to start sending sync pulses again. + NetPlay.Waiting4EmulationThread = FALSE; + S9xNPSendPause (FALSE); + } + +#if defined (NP_DEBUG) && NP_DEBUG == 2 + if (prev > 1) + { + printf ("CLIENT: SyncSpeed prev: %d @%d\n", prev, timeGetTime () - START); + } +#endif + } + else + { +#ifdef NP_DEBUG + printf ("*** CLIENT: SyncSpeed: Release failed @ %d\n", timeGetTime () - START); +#endif + } + + // ... and again to mop up the already-waiting sync-signal + NetPlay.PendingWait4Sync = WaitForSingleObject (GUI.ClientSemaphore, 200) != WAIT_OBJECT_0; +#if defined (NP_DEBUG) && NP_DEBUG == 2 + if (NetPlay.PendingWait4Sync) + printf ("CLIENT: PendingWait4Sync2 @%d\n", timeGetTime () - START); +#endif + + if (IPPU.SkippedFrames < NetPlay.MaxFrameSkip) + { + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = FALSE; + } + else + { + IPPU.RenderThisFrame = TRUE; + IPPU.SkippedFrames = 0; + } + } + // Give up remainder of time-slice to any other waiting threads, + // if they need any time, that is. + Sleep (0); + if (!NetPlay.PendingWait4Sync) + { + NetPlay.FrameCount++; + S9xNPStepJoypadHistory (); + } + } + else +#endif + + if (!Settings.TurboMode && Settings.SkipFrames == AUTO_FRAMERATE && + !GUI.AVIOut) + { + if (!do_frame_adjust) + { + IPPU.RenderThisFrame = TRUE; + IPPU.SkippedFrames = 0; + } + else + { + if (IPPU.SkippedFrames < Settings.AutoMaxSkipFrames) + { + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = FALSE; + } + else + { + IPPU.RenderThisFrame = TRUE; + IPPU.SkippedFrames = 0; + } + } + } + else + { + uint32 SkipFrames; + if(Settings.TurboMode && !GUI.AVIOut) + SkipFrames = Settings.TurboSkipFrames; + else + SkipFrames = (Settings.SkipFrames == AUTO_FRAMERATE) ? 0 : Settings.SkipFrames; + if (++IPPU.FrameSkip >= SkipFrames) + { + IPPU.FrameSkip = 0; + IPPU.SkippedFrames = 0; + IPPU.RenderThisFrame = TRUE; + } + else + { + IPPU.SkippedFrames++; + IPPU.RenderThisFrame = GUI.AVIOut!=0; + } + } +} + +const char *S9xBasename (const char *f) +{ + const char *p; + if ((p = strrchr (f, '/')) != NULL || (p = strrchr (f, '\\')) != NULL) + return (p + 1); + +#ifdef __DJGPP + if (p = strrchr (f, SLASH_CHAR)) + return (p + 1); +#endif + + return (f); +} + +bool8 S9xReadMousePosition (int which, int &x, int &y, uint32 &buttons) +{ + if (which == 0) + { + x = GUI.MouseX; + y = GUI.MouseY; + buttons = GUI.MouseButtons; + return (TRUE); + } + + return (FALSE); +} + +bool S9xGetState (WORD KeyIdent) +{ + if(KeyIdent == 0 || KeyIdent == VK_ESCAPE) // if it's the 'disabled' key, it's never pressed + return true; + + if(!GUI.BackgroundKeyGamekeys && GUI.hWnd != GetActiveWindow()) + return true; + + if (KeyIdent & 0x8000) // if it's a joystick 'key': + { + int j = (KeyIdent >> 8) & 15; + + switch (KeyIdent & 0xff) + { + case 0: return !Joystick [j].Left; + case 1: return !Joystick [j].Right; + case 2: return !Joystick [j].Up; + case 3: return !Joystick [j].Down; + case 4: return !Joystick [j].PovLeft; + case 5: return !Joystick [j].PovRight; + case 6: return !Joystick [j].PovUp; + case 7: return !Joystick [j].PovDown; + case 49:return !Joystick [j].PovDnLeft; + case 50:return !Joystick [j].PovDnRight; + case 51:return !Joystick [j].PovUpLeft; + case 52:return !Joystick [j].PovUpRight; + case 41:return !Joystick [j].ZUp; + case 42:return !Joystick [j].ZDown; + case 43:return !Joystick [j].RUp; + case 44:return !Joystick [j].RDown; + case 45:return !Joystick [j].UUp; + case 46:return !Joystick [j].UDown; + case 47:return !Joystick [j].VUp; + case 48:return !Joystick [j].VDown; + + default: + if ((KeyIdent & 0xff) > 40) + return true; // not pressed + + return !Joystick [j].Button [(KeyIdent & 0xff) - 8]; + } + } + + // the pause key is special, need this to catch all presses of it + if(KeyIdent == VK_PAUSE) + { + if(GetAsyncKeyState(VK_PAUSE)) // not &'ing this with 0x8000 is intentional and necessary + return false; + } + + return ((GetKeyState (KeyIdent) & 0x80) == 0); +} + +void CheckAxis (int val, int min, int max, bool &first, bool &second) +{ + if (Normalize (val, min, max) < -S9X_JOY_NEUTRAL) + { + second = false; + first = true; + } + else + first = false; + + if (Normalize (val, min, max) > S9X_JOY_NEUTRAL) + { + first = false; + second = true; + } + else + second = false; +} + +void S9xWinScanJoypads () +{ + uint8 PadState[2]; + JOYINFOEX jie; + + for (int C = 0; C != 16; C ++) + { + if (Joystick[C].Attached) + { + jie.dwSize = sizeof (jie); + jie.dwFlags = JOY_RETURNALL; + + if (joyGetPosEx (JOYSTICKID1+C, &jie) != JOYERR_NOERROR) + { + Joystick[C].Attached = false; + continue; + } + + CheckAxis (jie.dwXpos, + Joystick[C].Caps.wXmin, Joystick[C].Caps.wXmax, + Joystick[C].Left, Joystick[C].Right); + CheckAxis (jie.dwYpos, + Joystick[C].Caps.wYmin, Joystick[C].Caps.wYmax, + Joystick[C].Up, Joystick[C].Down); + CheckAxis (jie.dwZpos, + Joystick[C].Caps.wZmin, Joystick[C].Caps.wZmax, + Joystick[C].ZUp, Joystick[C].ZDown); + CheckAxis (jie.dwRpos, + Joystick[C].Caps.wRmin, Joystick[C].Caps.wRmax, + Joystick[C].RUp, Joystick[C].RDown); + CheckAxis (jie.dwUpos, + Joystick[C].Caps.wUmin, Joystick[C].Caps.wUmax, + Joystick[C].UUp, Joystick[C].UDown); + CheckAxis (jie.dwVpos, + Joystick[C].Caps.wVmin, Joystick[C].Caps.wVmax, + Joystick[C].VUp, Joystick[C].VDown); + + switch (jie.dwPOV) + { + case JOY_POVBACKWARD: + Joystick[C].PovDown = true; + Joystick[C].PovUp = false; + Joystick[C].PovLeft = false; + Joystick[C].PovRight = false; + Joystick[C].PovDnLeft = false; + Joystick[C].PovDnRight = false; + Joystick[C].PovUpLeft = false; + Joystick[C].PovUpRight = false; + break; + case 4500: + Joystick[C].PovDown = false; + Joystick[C].PovUp = false; + Joystick[C].PovLeft = false; + Joystick[C].PovRight = false; + Joystick[C].PovDnLeft = false; + Joystick[C].PovDnRight = false; + Joystick[C].PovUpLeft = false; + Joystick[C].PovUpRight = true; + break; + case 13500: + Joystick[C].PovDown = false; + Joystick[C].PovUp = false; + Joystick[C].PovLeft = false; + Joystick[C].PovRight = false; + Joystick[C].PovDnLeft = false; + Joystick[C].PovDnRight = true; + Joystick[C].PovUpLeft = false; + Joystick[C].PovUpRight = false; + break; + case 22500: + Joystick[C].PovDown = false; + Joystick[C].PovUp = false; + Joystick[C].PovLeft = false; + Joystick[C].PovRight = false; + Joystick[C].PovDnLeft = true; + Joystick[C].PovDnRight = false; + Joystick[C].PovUpLeft = false; + Joystick[C].PovUpRight = false; + break; + case 31500: + Joystick[C].PovDown = false; + Joystick[C].PovUp = false; + Joystick[C].PovLeft = false; + Joystick[C].PovRight = false; + Joystick[C].PovDnLeft = false; + Joystick[C].PovDnRight = false; + Joystick[C].PovUpLeft = true; + Joystick[C].PovUpRight = false; + break; + + + case JOY_POVFORWARD: + Joystick[C].PovDown = false; + Joystick[C].PovUp = true; + Joystick[C].PovLeft = false; + Joystick[C].PovRight = false; + Joystick[C].PovDnLeft = false; + Joystick[C].PovDnRight = false; + Joystick[C].PovUpLeft = false; + Joystick[C].PovUpRight = false; + break; + + case JOY_POVLEFT: + Joystick[C].PovDown = false; + Joystick[C].PovUp = false; + Joystick[C].PovLeft = true; + Joystick[C].PovRight = false; + Joystick[C].PovDnLeft = false; + Joystick[C].PovDnRight = false; + Joystick[C].PovUpLeft = false; + Joystick[C].PovUpRight = false; + break; + + case JOY_POVRIGHT: + Joystick[C].PovDown = false; + Joystick[C].PovUp = false; + Joystick[C].PovLeft = false; + Joystick[C].PovRight = true; + Joystick[C].PovDnLeft = false; + Joystick[C].PovDnRight = false; + Joystick[C].PovUpLeft = false; + Joystick[C].PovUpRight = false; + break; + + default: + Joystick[C].PovDown = false; + Joystick[C].PovUp = false; + Joystick[C].PovLeft = false; + Joystick[C].PovRight = false; + Joystick[C].PovDnLeft = false; + Joystick[C].PovDnRight = false; + Joystick[C].PovUpLeft = false; + Joystick[C].PovUpRight = false; + break; + } + + for (int B = 0; B < 32; B ++) + Joystick[C].Button[B] = (jie.dwButtons & (1 << B)) != 0; + } + } + + for (int J = 0; J < 8; J++) + { + if (Joypad [J].Enabled) + { + // toggle checks + { + PadState[0] = 0; + PadState[0] |= ToggleJoypadStorage[J].R||TurboToggleJoypadStorage[J].R ? 16 : 0; + PadState[0] |= ToggleJoypadStorage[J].L||TurboToggleJoypadStorage[J].L ? 32 : 0; + PadState[0] |= ToggleJoypadStorage[J].X||TurboToggleJoypadStorage[J].X ? 64 : 0; + PadState[0] |= ToggleJoypadStorage[J].A||TurboToggleJoypadStorage[J].A ? 128 : 0; + + PadState[1] = 0; + PadState[1] |= ToggleJoypadStorage[J].Right ? 1 : 0; + PadState[1] |= ToggleJoypadStorage[J].Left ? 2 : 0; + PadState[1] |= ToggleJoypadStorage[J].Down ? 4 : 0; + PadState[1] |= ToggleJoypadStorage[J].Up ? 8 : 0; + PadState[1] |= ToggleJoypadStorage[J].Start||TurboToggleJoypadStorage[J].Start ? 16 : 0; + PadState[1] |= ToggleJoypadStorage[J].Select||TurboToggleJoypadStorage[J].Select ? 32 : 0; + PadState[1] |= ToggleJoypadStorage[J].Y||TurboToggleJoypadStorage[J].Y ? 64 : 0; + PadState[1] |= ToggleJoypadStorage[J].B||TurboToggleJoypadStorage[J].B ? 128 : 0; + } + // auto-hold AND regular key/joystick presses + if(S9xGetState(Joypad[J+8].Left)) + { + PadState[0] ^= (!S9xGetState(Joypad[J].R)||!S9xGetState(Joypad[J+8].R)) ? 16 : 0; + PadState[0] ^= (!S9xGetState(Joypad[J].L)||!S9xGetState(Joypad[J+8].L)) ? 32 : 0; + PadState[0] ^= (!S9xGetState(Joypad[J].X)||!S9xGetState(Joypad[J+8].X)) ? 64 : 0; + PadState[0] ^= (!S9xGetState(Joypad[J].A)||!S9xGetState(Joypad[J+8].A)) ? 128 : 0; + + PadState[1] ^= (!S9xGetState(Joypad[J].Right)) ? 1 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].Right_Up)) ? 1 + 8 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].Right_Down)) ? 1 + 4 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].Left)) ? 2 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].Left_Up)) ? 2 + 8 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].Left_Down)) ? 2 + 4 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].Down)) ? 4 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].Up)) ? 8 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].Start)||!S9xGetState(Joypad[J+8].Start)) ? 16 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].Select)||!S9xGetState(Joypad[J+8].Select)) ? 32 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].Y)||!S9xGetState(Joypad[J+8].Y)) ? 64 : 0; + PadState[1] ^= (!S9xGetState(Joypad[J].B)||!S9xGetState(Joypad[J+8].B)) ? 128 : 0; + } + + bool turbofy = !S9xGetState(Joypad[J+8].Up); // All Mod for turbo + + //handle turbo case! (autofire / auto-fire) + if(turbofy || ((GUI.TurboMask&TURBO_A_MASK))&&(PadState[0]&128) || !S9xGetState(Joypad[J+8].A )) PadState[0]^=(joypads[J]&128); + if(turbofy || ((GUI.TurboMask&TURBO_B_MASK))&&(PadState[1]&128) || !S9xGetState(Joypad[J+8].B )) PadState[1]^=((joypads[J]&(128<<8))>>8); + if(turbofy || ((GUI.TurboMask&TURBO_Y_MASK))&&(PadState[1]&64) || !S9xGetState(Joypad[J+8].Y )) PadState[1]^=((joypads[J]&(64<<8))>>8); + if(turbofy || ((GUI.TurboMask&TURBO_X_MASK))&&(PadState[0]&64) || !S9xGetState(Joypad[J+8].X )) PadState[0]^=(joypads[J]&64); + if(turbofy || ((GUI.TurboMask&TURBO_L_MASK))&&(PadState[0]&32) || !S9xGetState(Joypad[J+8].L )) PadState[0]^=(joypads[J]&32); + if(turbofy || ((GUI.TurboMask&TURBO_R_MASK))&&(PadState[0]&16) || !S9xGetState(Joypad[J+8].R )) PadState[0]^=(joypads[J]&16); + if(turbofy || ((GUI.TurboMask&TURBO_STA_MASK))&&(PadState[1]&16) || !S9xGetState(Joypad[J+8].Start )) PadState[1]^=((joypads[J]&(16<<8))>>8); + if(turbofy || ((GUI.TurboMask&TURBO_SEL_MASK))&&(PadState[1]&32) || !S9xGetState(Joypad[J+8].Select)) PadState[1]^=((joypads[J]&(32<<8))>>8); + if( ((GUI.TurboMask&TURBO_LEFT_MASK))&&(PadState[1]&2) ) PadState[1]^=((joypads[J]&(2<<8))>>8); + if( ((GUI.TurboMask&TURBO_UP_MASK))&&(PadState[1]&9) ) PadState[1]^=((joypads[J]&(8<<8))>>8); + if( ((GUI.TurboMask&TURBO_RIGHT_MASK))&&(PadState[1]&1) ) PadState[1]^=((joypads[J]&(1<<8))>>8); + if( ((GUI.TurboMask&TURBO_RIGHT_MASK))&&(PadState[1]&4) ) PadState[1]^=((joypads[J]&(4<<8))>>8); + + if(TurboToggleJoypadStorage[J].A ) PadState[0]^=(joypads[J]&128); + if(TurboToggleJoypadStorage[J].B ) PadState[1]^=((joypads[J]&(128<<8))>>8); + if(TurboToggleJoypadStorage[J].Y ) PadState[1]^=((joypads[J]&(64<<8))>>8); + if(TurboToggleJoypadStorage[J].X ) PadState[0]^=(joypads[J]&64); + if(TurboToggleJoypadStorage[J].L ) PadState[0]^=(joypads[J]&32); + if(TurboToggleJoypadStorage[J].R ) PadState[0]^=(joypads[J]&16); + if(TurboToggleJoypadStorage[J].Start ) PadState[1]^=((joypads[J]&(16<<8))>>8); + if(TurboToggleJoypadStorage[J].Select) PadState[1]^=((joypads[J]&(32<<8))>>8); + //end turbo case... + + + // enforce left+right/up+down disallowance here to + // avoid recording unused l+r/u+d that will cause desyncs + // when played back with l+r/u+d is allowed + if(!Settings.UpAndDown) + { + if((PadState[1] & 2) != 0) + PadState[1] &= ~(1); + if((PadState[1] & 8) != 0) + PadState[1] &= ~(4); + } + + joypads [J] = PadState [0] | (PadState [1] << 8) | 0x80000000; + } + else + joypads [J] = 0; + } +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlay) + { + // Send joypad position update to server + S9xNPSendJoypadUpdate (joypads [GUI.NetplayUseJoypad1 ? 0 : NetPlay.Player-1]); + + // set input from network + for (int J = 0; J < NP_MAX_CLIENTS; J++) + joypads[J] = S9xNPGetJoypad (J); + } +#endif +} + +void InitSnes9X( void) +{ +#ifdef DEBUGGER +// extern FILE *trace; + +// trace = fopen( "SNES9X.TRC", "wt"); + freopen( "SNES9X.OUT", "wt", stdout); + freopen( "SNES9X.ERR", "wt", stderr); + +// CPU.Flags |= TRACE_FLAG; +// APU.Flags |= TRACE_FLAG; +#endif + +//#ifdef GENERATE_OFFSETS_H +// offsets_h = fopen ("offsets.h", "wt"); +// generate_offsets_h (0, NULL); +// fclose (offsets_h); +//#endif + + Memory.Init(); + + extern void S9xPostRomInit(); + Memory.PostRomInitFunc = S9xPostRomInit; + + ScreenBuf1 = new BYTE [EXT_PITCH * EXT_HEIGHT]; + + ScreenBuffer = ScreenBuf1 + EXT_OFFSET; + memset (ScreenBuf1, 0, EXT_PITCH * EXT_HEIGHT); + + GFX.Pitch = EXT_PITCH; + GFX.RealPPL = EXT_PITCH; + GFX.Screen = (uint16*)(ScreenBuf1 + EXT_OFFSET); + + S9xSetWinPixelFormat (); + S9xGraphicsInit(); + + InitializeCriticalSection(&GUI.SoundCritSect); + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + S9xInitAPU(); + + ReInitSound(); + + S9xMovieInit (); + + for (int C = 0; C != 16; C ++) + Joystick[C].Attached = joyGetDevCaps (JOYSTICKID1+C, &Joystick[C].Caps, + sizeof( JOYCAPS)) == JOYERR_NOERROR; +} +void DeinitS9x() +{ + if(ScreenBuf1) + delete [] ScreenBuf1; + DeleteCriticalSection(&GUI.SoundCritSect); + CoUninitialize(); + if(GUI.GunSight) + DestroyCursor(GUI.GunSight);//= LoadCursor (hInstance, MAKEINTRESOURCE (IDC_CURSOR_SCOPE)); + if(GUI.Arrow) + DestroyCursor(GUI.Arrow);// = LoadCursor (NULL, IDC_ARROW); + if(GUI.Accelerators) + DestroyAcceleratorTable(GUI.Accelerators);// = LoadAccelerators (hInstance, MAKEINTRESOURCE (IDR_SNES9X_ACCELERATORS)); +} + +//void Convert8To24 (SSurface *src, SSurface *dst, RECT *srect) +//{ +// uint32 brightness = IPPU.MaxBrightness >> 1; +// uint8 levels [32]; +// int height = srect->bottom - srect->top; +// int width = srect->right - srect->left; +// int offset1 = srect->top * src->Pitch + srect->left; +// int offset2 = ((dst->Height - height) >> 1) * dst->Pitch + +// ((dst->Width - width) >> 1) * 3; +// +// for (int l = 0; l < 32; l++) +// levels [l] = l * brightness; +// +// for (register int y = 0; y < height; y++) +// { +// register uint8 *s = ((uint8 *) src->Surface + y * src->Pitch + offset1); +// register uint8 *d = ((uint8 *) dst->Surface + y * dst->Pitch + offset2); +// +//#ifdef LSB_FIRST +// if (GUI.RedShift < GUI.BlueShift) +//#else +// if (GUI.RedShift > GUI.BlueShift) +//#endif +// { +// // Order is RGB +// for (register int x = 0; x < width; x++) +// { +// uint16 pixel = PPU.CGDATA [*s++]; +// *(d + 0) = levels [(pixel & 0x1f)]; +// *(d + 1) = levels [((pixel >> 5) & 0x1f)]; +// *(d + 2) = levels [((pixel >> 10) & 0x1f)]; +// d += 3; +// } +// } +// else +// { +// // Order is BGR +// for (register int x = 0; x < width; x++) +// { +// uint16 pixel = PPU.CGDATA [*s++]; +// *(d + 0) = levels [((pixel >> 10) & 0x1f)]; +// *(d + 1) = levels [((pixel >> 5) & 0x1f)]; +// *(d + 2) = levels [(pixel & 0x1f)]; +// d += 3; +// } +// } +// } +//} + + +void S9xAutoSaveSRAM () +{ + Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR)); +} + +void S9xSetPause (uint32 mask) +{ + Settings.ForcedPause |= mask; + S9xSetSoundMute(TRUE); +} + +void S9xClearPause (uint32 mask) +{ + Settings.ForcedPause &= ~mask; + if (!Settings.ForcedPause) + { + // Wake up the main loop thread just if its blocked in a GetMessage call. + PostMessage (GUI.hWnd, WM_NULL, 0, 0); + } +} + +bool JustifierOffscreen() +{ + return (bool)((GUI.MouseButtons&2)!=0); +} + +//void JustifierButtons(uint32& justifiers) +//{ +// if(IPPU.Controller==SNES_JUSTIFIER_2) +// { +// if((GUI.MouseButtons&1)||(GUI.MouseButtons&2)) +// { +// justifiers|=0x00200; +// } +// if(GUI.MouseButtons&4) +// { +// justifiers|=0x00800; +// } +// } +// else +// { +// if((GUI.MouseButtons&1)||(GUI.MouseButtons&2)) +// { +// justifiers|=0x00100; +// } +// if(GUI.MouseButtons&4) +// { +// justifiers|=0x00400; +// } +// } +//} + +#ifdef MK_APU_RESAMPLE +void ResampleTo16000HzM16(uint16* input, uint16*output,int output_samples) +{ + int i=0; + for(i=0;i>1; + } +} + +void ResampleTo16000HzS16(uint16* input, uint16*output,int output_samples) +{ + int i=0; + for(i=0;i>1; + output[i+1]=(input[(i*2)+1]+input[(2*(i+1))+1])>>1; + } +} +void ResampleTo8000HzM16(uint16* input, uint16*output,int output_samples) +{ + int i=0; + for(i=0;i>2; + } +} + +void ResampleTo8000HzS16(uint16* input, uint16*output,int output_samples) +{ + int i=0; + for(i=0;i>2; + output[i+1]=(input[(i*4)+1]+input[(4*i)+3]+input[(4*(i+1))+1]+input[(4*(i+1))+3])>>2; + } +} + +void ResampleTo16000HzM8(uint8* input, uint8*output,int output_samples) +{ + int i=0; + for(i=0;i>1; + } +} + +void ResampleTo16000HzS8(uint8* input, uint8*output,int output_samples) +{ + int i=0; + for(i=0;i>1; + output[i+1]=(input[(i*2)+1]+input[(2*(i+1))+1])>>1; + } +} +void ResampleTo8000HzM8(uint8* input, uint8*output,int output_samples) +{ + int i=0; + for(i=0;i>2; + } +} + +void ResampleTo8000HzS8(uint8* input, uint8*output,int output_samples) +{ + int i=0; + for(i=0;i>2; + output[i+1]=(input[(i*4)+1]+input[(4*i)+3]+input[(4*(i+1))+1]+input[(4*(i+1))+3])>>2; + } +} + +#endif + +void DoAVIOpen(const char* filename) +{ + // close current instance + if(GUI.AVIOut) + { + AVIClose(&GUI.AVIOut); + GUI.AVIOut = NULL; + } + + CloseSoundDevice(); + pre_avi_soundsync = Settings.SoundSync; + Settings.SoundSync = false; + + // create new writer + AVICreate(&GUI.AVIOut); + + int framerate = Memory.ROMFramesPerSecond; + int frameskip = Settings.SkipFrames; + if(frameskip == AUTO_FRAMERATE) + frameskip = 1; + else + frameskip++; + + AVISetFramerate(framerate, frameskip, GUI.AVIOut); + + avi_width = IPPU.RenderedScreenWidth; + avi_height = IPPU.RenderedScreenHeight; + avi_skip_frames = Settings.SkipFrames; + + if(GUI.HeightExtend && avi_height < SNES_HEIGHT_EXTENDED) + avi_height = SNES_HEIGHT_EXTENDED; + + if(avi_height % 2 != 0) // most codecs can't handle odd-height images + avi_height++; + + BITMAPINFOHEADER bi; + memset(&bi, 0, sizeof(bi)); + bi.biSize = 0x28; + bi.biPlanes = 1; + bi.biBitCount = 24; + bi.biWidth = avi_width; + bi.biHeight = avi_height; + bi.biSizeImage = 3*bi.biWidth*bi.biHeight; + + AVISetVideoFormat(&bi, GUI.AVIOut); + + WAVEFORMATEX wfx; + + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = Settings.Stereo ? 2 : 1; + wfx.nSamplesPerSec = Settings.SoundPlaybackRate; + wfx.nBlockAlign = (Settings.SixteenBitSound ? 2 : 1) * (Settings.Stereo ? 2 : 1); + wfx.wBitsPerSample = Settings.SixteenBitSound ? 16 : 8; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + wfx.cbSize = 0; + + if(!GUI.Mute) + { + AVISetSoundFormat(&wfx, GUI.AVIOut); + } + + if(!AVIBegin(filename, GUI.AVIOut)) + { + DoAVIClose(2); + GUI.AVIOut = NULL; + return; + } + + avi_sound_samples_per_update = (wfx.nSamplesPerSec * frameskip) / framerate; + avi_sound_bytes_per_sample = wfx.nBlockAlign; + + // init buffers + avi_buffer = new uint8[3*avi_width*avi_height]; + avi_sound_buffer = new uint8[avi_sound_samples_per_update * avi_sound_bytes_per_sample]; +} + +void DoAVIClose(int reason) +{ + if(!GUI.AVIOut) + { + return; + } + + AVIClose(&GUI.AVIOut); + GUI.AVIOut = NULL; + + delete [] avi_buffer; + delete [] avi_sound_buffer; + + avi_buffer = NULL; + avi_sound_buffer = NULL; + + Settings.SoundSync = pre_avi_soundsync; + ReInitSound(); + + switch(reason) + { + case 1: + // emu settings changed + S9xMessage(S9X_INFO, S9X_AVI_INFO, AVI_CONFIGURATION_CHANGED); + break; + case 2: + // create AVI failed + S9xMessage(S9X_INFO, S9X_AVI_INFO, AVI_CREATION_FAILED); + break; + default: + // print nothing + break; + } +} + +void DoAVIVideoFrame(SSurface* source_surface, int Width, int Height/*, bool8 sixteen_bit*/) +{ + static uint32 lastFrameCount=0; + if(!GUI.AVIOut || (IPPU.FrameCount==lastFrameCount)) + { + return; + } + lastFrameCount=IPPU.FrameCount; + + // check configuration + const WAVEFORMATEX* pwfex = NULL; + WAVEFORMATEX wfx; + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = Settings.Stereo ? 2 : 1; + wfx.nSamplesPerSec = Settings.SoundPlaybackRate; + wfx.nBlockAlign = (Settings.SixteenBitSound ? 2 : 1) * (Settings.Stereo ? 2 : 1); + wfx.wBitsPerSample = Settings.SixteenBitSound ? 16 : 8; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + wfx.cbSize = 0; + if(//avi_width != Width || + //avi_height != Height || + avi_skip_frames != Settings.SkipFrames || + (AVIGetSoundFormat(GUI.AVIOut, &pwfex) && memcmp(pwfex, &wfx, sizeof(WAVEFORMATEX)))) + { + DoAVIClose(1); + return; + } + + // convert to bitdepth 24 + SSurface avi_dest_surface; + RECT full_rect; + avi_dest_surface.Surface = avi_buffer; + avi_dest_surface.Pitch = avi_width * 3; + avi_dest_surface.Width = avi_width; + avi_dest_surface.Height = avi_height; + full_rect.top = 0; + full_rect.left = 0; + full_rect.bottom = avi_height; + full_rect.right = avi_width; + //if(sixteen_bit) + //{ + Convert16To24(source_surface, &avi_dest_surface, &full_rect); + //} + //else + //{ + // Convert8To24(source_surface, &avi_dest_surface, &full_rect); + //} + + // flip the image vertically + const int pitch = 3*avi_width; + int y; + for(y=0; y>1; ++y) + { + uint8* lo_8 = avi_buffer+y*pitch; + uint8* hi_8 = avi_buffer+(avi_height-1-y)*pitch; + uint32* lo_32=(uint32*)lo_8; + uint32* hi_32=(uint32*)hi_8; + + int q; + { + register uint32 a, b; + for(q=pitch>>4; q>0; --q) + { + a=*lo_32; b=*hi_32; *lo_32=b; *hi_32=a; ++lo_32; ++hi_32; + a=*lo_32; b=*hi_32; *lo_32=b; *hi_32=a; ++lo_32; ++hi_32; + a=*lo_32; b=*hi_32; *lo_32=b; *hi_32=a; ++lo_32; ++hi_32; + a=*lo_32; b=*hi_32; *lo_32=b; *hi_32=a; ++lo_32; ++hi_32; + } + } + + { + register uint8 c, d; + for(q=(pitch&0x0f); q>0; --q) + { + c=*lo_8; d=*hi_8; *lo_8=d; *hi_8=c; + } + } + } + + // write to AVI + AVIAddVideoFrame(avi_buffer, GUI.AVIOut); + + // generate sound + if(pwfex) + { + const int stereo_multiplier = (Settings.Stereo) ? 2 : 1; + + S9xMixSamples(avi_sound_buffer, avi_sound_samples_per_update*stereo_multiplier); + + AVIAddSoundSamples(avi_sound_buffer, avi_sound_samples_per_update, GUI.AVIOut); + } +} \ No newline at end of file diff --git a/win32/win32_display.cpp b/win32/win32_display.cpp new file mode 100644 index 00000000..8d30e99d --- /dev/null +++ b/win32/win32_display.cpp @@ -0,0 +1,866 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + +/* win32_display.cpp + Contains most of the display related functions of the win32 port. + Delegates relevant function calls to the currently selected IS9xDisplayOutput object. +*/ + +#include "../snes9x.h" +#include "../ppu.h" +#include "../font.h" +#include "wsnes9x.h" +#include "win32_display.h" +#include "CDirect3D.h" +#include "CDirectDraw.h" +#include "IS9xDisplayOutput.h" + +#include "../filter/hq2x.h" +#include "../filter/2xsai.h" + +// available display output methods +CDirect3D Direct3D; +CDirectDraw DirectDraw; + +// Interface used to access the display output +IS9xDisplayOutput *S9xDisplayOutput=&Direct3D; + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +bool8 S9xDeinitUpdate (int, int); +void DoAVIVideoFrame(SSurface* source_surface, int width, int height); + +/* WinRefreshDisplay +repeats the last rendered frame +*/ +void WinRefreshDisplay(void) +{ + S9xDeinitUpdate(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); +} + +void WinChangeWindowSize(unsigned int newWidth, unsigned int newHeight) +{ + S9xDisplayOutput->ChangeRenderSize(newWidth,newHeight); +} + +/* WinDisplayReset +initializes the currently selected display output and +reinitializes the core graphics rendering +----- +returns true if successful, false otherwise +*/ +bool WinDisplayReset(void) +{ + S9xDisplayOutput->DeInitialize(); + switch(GUI.outputMethod) { + case DIRECT3D: + S9xDisplayOutput = &Direct3D; + break; + case DIRECTDRAW: + S9xDisplayOutput = &DirectDraw; + break; + } + if(S9xDisplayOutput->Initialize(GUI.hWnd)) { + S9xGraphicsDeinit(); + S9xSetWinPixelFormat (); + S9xInitUpdate(); + S9xGraphicsInit(); + return true; + } else { + MessageBox (GUI.hWnd, Languages[ GUI.Language].errInitDD, TEXT("Snes9X - Display Failure"), MB_OK | MB_ICONSTOP); + return false; + } +} + +void WinDisplayApplyChanges() +{ + S9xDisplayOutput->ApplyDisplayChanges(); +} + +// we no longer support 8bit modes - no palette necessary +void S9xSetPalette( void) +{ + return; +} + +bool8 S9xInitUpdate (void) +{ + return (TRUE); +} + +#define RenderMethod ((Src.Height > SNES_HEIGHT_EXTENDED || Src.Width == 512) ? RenderMethodHiRes : RenderMethod) + +// only necessary for avi recording +// TODO: check if this can be removed +bool8 S9xContinueUpdate(int Width, int Height) +{ + // called every other frame during interlace + + SSurface Src; + + Src.Width = Width; + if(Height%SNES_HEIGHT) + Src.Height = Height; + else + { + if(Height==SNES_HEIGHT) + Src.Height=SNES_HEIGHT_EXTENDED; + else Src.Height=SNES_HEIGHT_EXTENDED<<1; + } + Src.Pitch = GFX.Pitch; + Src.Surface = (BYTE*)GFX.Screen; + + Height = Src.Height; + + // avi writing + DoAVIVideoFrame(&Src, Width, Height); + + return true; +} + +// do the actual rendering of a frame +bool8 S9xDeinitUpdate (int Width, int Height) +{ + SSurface Src; + + Src.Width = Width; + if(Height%SNES_HEIGHT) + Src.Height = Height; + else + { + if(Height==SNES_HEIGHT) + Src.Height=SNES_HEIGHT_EXTENDED; + else Src.Height=SNES_HEIGHT_EXTENDED<<1; + } + Src.Pitch = GFX.Pitch; + Src.Surface = (BYTE*)GFX.Screen; + + const int OrigHeight = Height; + Height = Src.Height; + + // avi writing + DoAVIVideoFrame(&Src, Width, Height); + + GUI.ScreenCleared = true; + + SelectRenderMethod (); + + // Clear some of the old SNES rendered image + // when the resolution becomes lower in x or y, + // otherwise the image processors (filters) might access + // some of the old rendered data at the edges. + { + static int LastWidth = 0; + static int LastHeight = 0; + + if (Width < LastWidth) + { + const int hh = max(LastHeight, OrigHeight); + for (int i = 0; i < hh; i++) + memset (GFX.Screen + i * (GFX.Pitch>>1) + Width*1, 0, 4); + } + if (OrigHeight < LastHeight) + { + const int ww = max(LastWidth, Width); + for (int i = OrigHeight; i < LastHeight ; i++) + memset (GFX.Screen + i * (GFX.Pitch>>1), 0, ww * 2); + + // also old clear extended height stuff from drawing surface + if((int)Src.Height > OrigHeight) + for (int i = OrigHeight; i < (int)Src.Height ; i++) + memset (Src.Surface + i * Src.Pitch, 0, Src.Pitch); + } + LastWidth = Width; + LastHeight = OrigHeight; + } + + S9xDisplayOutput->Render(Src); + + GUI.FlipCounter++; + + return (true); +} + +/* S9xSetWinPixelFormat +sets default settings and calls the appropriate display object +*/ +void S9xSetWinPixelFormat () +{ + S9xSetRenderPixelFormat (RGB565); + GUI.NeedDepthConvert = FALSE; + GUI.DepthConverted = !GUI.NeedDepthConvert; + + S9xBlit2xSaIFilterDeinit(); + S9xBlitHQ2xFilterDeinit(); + + S9xDisplayOutput->SetSnes9xColorFormat(); +} + +// TODO: abstract the following functions in some way - only necessary for directdraw + +/* DirectDraw only begin */ + +void SwitchToGDI() +{ + if(GUI.outputMethod!=DIRECTDRAW) + return; + + IPPU.ColorsChanged = true; + DirectDraw.lpDD->FlipToGDISurface(); + GUI.FlipCounter = 0; + DirectDraw.lpDDSPrimary2->SetPalette (NULL); +} + +static void ClearSurface (LPDIRECTDRAWSURFACE2 lpDDSurface) +{ + DDBLTFX fx; + + memset (&fx, 0, sizeof (fx)); + fx.dwSize = sizeof (fx); + + while (lpDDSurface->Blt (NULL, DirectDraw.lpDDSPrimary2, NULL, DDBLT_WAIT, NULL) == DDERR_SURFACELOST) + lpDDSurface->Restore (); +} + +void UpdateBackBuffer() +{ + GUI.ScreenCleared = true; + + if (GUI.outputMethod==DIRECTDRAW && GUI.FullScreen) + { + SwitchToGDI(); + + DDBLTFX fx; + + memset (&fx, 0, sizeof (fx)); + fx.dwSize = sizeof (fx); + + while (DirectDraw.lpDDSPrimary2->Blt (NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &fx) == DDERR_SURFACELOST) + DirectDraw.lpDDSPrimary2->Restore (); + + if (GetMenu (GUI.hWnd) != NULL) + DrawMenuBar (GUI.hWnd); + + GUI.FlipCounter = 0; + DDSCAPS caps; + caps.dwCaps = DDSCAPS_BACKBUFFER; + + LPDIRECTDRAWSURFACE2 pDDSurface; + + if (DirectDraw.lpDDSPrimary2->GetAttachedSurface (&caps, &pDDSurface) == DD_OK && + pDDSurface != NULL) + { + ClearSurface (pDDSurface); + DirectDraw.lpDDSPrimary2->Flip (NULL, GUI.Vsync?DDFLIP_WAIT:DDFLIP_NOVSYNC); + while (DirectDraw.lpDDSPrimary2->GetFlipStatus (DDGFS_ISFLIPDONE) != DD_OK) + Sleep (0); + if(DirectDraw.doubleBuffered) + ClearSurface (pDDSurface); + } + } + else + { + if (GetMenu( GUI.hWnd) != NULL) + DrawMenuBar (GUI.hWnd); + } +} + +void RestoreGUIDisplay () +{ + if(GUI.outputMethod!=DIRECTDRAW) + return; + + S9xSetPause (PAUSE_RESTORE_GUI); + + if (GUI.FullScreen && + (GUI.FullscreenMode.width < 640 || GUI.FullscreenMode.height < 400) && + !DirectDraw.SetDisplayMode (640, 480, 1, 0, 60, !GUI.FullScreen, false)) + { + MessageBox (GUI.hWnd, Languages[ GUI.Language].errModeDD, TEXT("Snes9X - DirectDraw(1)"), MB_OK | MB_ICONSTOP); + S9xClearPause (PAUSE_RESTORE_GUI); + return; + } + SwitchToGDI(); + S9xClearPause (PAUSE_RESTORE_GUI); +} + +void RestoreSNESDisplay () +{ + if(GUI.outputMethod!=DIRECTDRAW) + return; + + if (!DirectDraw.SetFullscreen(GUI.FullScreen)) + { + MessageBox (GUI.hWnd, Languages[ GUI.Language].errModeDD, TEXT("Snes9X - DirectDraw(4)"), MB_OK | MB_ICONSTOP); + return; + } + + UpdateBackBuffer(); +} + +/* DirectDraw only end */ + +/* ToggleFullScreen +switches between fullscreen and window mode and saves the window position +if EmulateFullscreen is set we simply create a borderless window that spans the screen +*/ +void ToggleFullScreen () +{ + S9xSetPause (PAUSE_TOGGLE_FULL_SCREEN); + + if(GUI.EmulateFullscreen) { + HMONITOR hm; + MONITORINFO mi; + GUI.EmulatedFullscreen = !GUI.EmulatedFullscreen; + if(GUI.EmulatedFullscreen) { + GetWindowRect (GUI.hWnd, &GUI.window_size); + if(GetMenu(GUI.hWnd)!=NULL) + SetMenu(GUI.hWnd,NULL); + SetWindowLong (GUI.hWnd, GWL_STYLE, WS_POPUP|WS_VISIBLE); + hm = MonitorFromWindow(GUI.hWnd,MONITOR_DEFAULTTONEAREST); + mi.cbSize = sizeof(mi); + GetMonitorInfo(hm,&mi); + SetWindowPos (GUI.hWnd, HWND_TOP, mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top, SWP_DRAWFRAME|SWP_FRAMECHANGED); + } else { + bool maximized = GUI.window_maximized; + SetWindowLong( GUI.hWnd, GWL_STYLE, WS_POPUPWINDOW|WS_CAPTION| + WS_THICKFRAME|WS_VISIBLE|WS_MINIMIZEBOX|WS_MAXIMIZEBOX); + SetMenu(GUI.hWnd,GUI.hMenu); + SetWindowPos (GUI.hWnd, HWND_NOTOPMOST, GUI.window_size.left, GUI.window_size.top, GUI.window_size.right - GUI.window_size.left, GUI.window_size.bottom - GUI.window_size.top, SWP_DRAWFRAME|SWP_FRAMECHANGED); + if(maximized) + ShowWindow(GUI.hWnd, SW_MAXIMIZE); + } + } else { + GUI.FullScreen = !GUI.FullScreen; + if(GUI.FullScreen) { + GetWindowRect (GUI.hWnd, &GUI.window_size); + if(GetMenu(GUI.hWnd)!=NULL) + SetMenu(GUI.hWnd,NULL); + SetWindowLong (GUI.hWnd, GWL_STYLE, WS_POPUP|WS_VISIBLE); + SetWindowPos (GUI.hWnd, HWND_TOP, 0, 0, 0, 0, SWP_DRAWFRAME|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE); + if(!S9xDisplayOutput->SetFullscreen(true)) + GUI.FullScreen = false; + } + if(!GUI.FullScreen) { + bool maximized = GUI.window_maximized; + SetWindowLong( GUI.hWnd, GWL_STYLE, WS_POPUPWINDOW|WS_CAPTION| + WS_THICKFRAME|WS_VISIBLE|WS_MINIMIZEBOX|WS_MAXIMIZEBOX); + SetMenu(GUI.hWnd,GUI.hMenu); + S9xDisplayOutput->SetFullscreen(false); + SetWindowPos (GUI.hWnd, HWND_NOTOPMOST, GUI.window_size.left, GUI.window_size.top, GUI.window_size.right - GUI.window_size.left, GUI.window_size.bottom - GUI.window_size.top, SWP_DRAWFRAME|SWP_FRAMECHANGED); + if(maximized) + ShowWindow(GUI.hWnd, SW_MAXIMIZE); + } + } + S9xGraphicsDeinit(); + S9xSetWinPixelFormat (); + S9xInitUpdate(); + S9xGraphicsInit(); + IPPU.RenderThisFrame = true; + + S9xClearPause (PAUSE_TOGGLE_FULL_SCREEN); +} + +/* S9xOpenSoundDevice +ennumerates the available display modes of the currently selected output +*/ +void WinEnumDisplayModes(std::vector *modeVector) +{ + S9xDisplayOutput->EnumModes(modeVector); +} + +/* Depth conversion functions begin */ + +void Convert16To24 (SSurface *src, SSurface *dst, RECT *srect) +{ + const int height = srect->bottom - srect->top; + const int width = srect->right - srect->left; + const int offset1 = srect->top * src->Pitch + srect->left * 2; + const int offset2 = ((dst->Height - height) >> 1) * dst->Pitch + ((dst->Width - width) >> 1) * 3; + const int snesWidth = src->Width; + const int snesHeight = src->Height; + const bool doubledX = (snesWidth >= width*2) ? true : false; + const bool doubledY = (snesHeight >= height*2) ? true : false; + + for (int y = 0; y < height; y++) + { + register uint16 *s = (uint16 *) ((uint8 *) src->Surface + (doubledY ? y*2 : y) * src->Pitch + offset1); + register uint8 *d = ((uint8 *) dst->Surface + y * dst->Pitch + offset2); + + #define Interp(c1, c2) \ + (c1 == c2) ? c1 : \ + (((((c1 & 0x07E0) + (c2 & 0x07E0)) >> 1) & 0x07E0) + \ + ((((c1 & 0xF81F) + (c2 & 0xF81F)) >> 1) & 0xF81F)) + + if(y >= snesHeight) + { + // beyond SNES image - make the row black + memset(d, 0, width*3); + } + else + +#ifdef LSB_FIRST + if (GUI.RedShift < GUI.BlueShift) +#else + if (GUI.RedShift > GUI.BlueShift) +#endif + { + // Order is RGB + if(!doubledX) + { + for (int x = 0; x < width; x++) + { + uint32 pixel = *s++; + *(d + 0) = (pixel >> (11 - 3)) & 0xf8; + *(d + 1) = (pixel >> (6 - 3)) & 0xf8; + *(d + 2) = (pixel & 0x1f) << 3; + d += 3; + } + } + else // high-res x, blend: + { + for (int x = 0; x < width; x++) + { + uint32 pixel = Interp(s[0],s[1]); + s += 2; + *(d + 0) = (pixel >> (11 - 3)) & 0xf8; + *(d + 1) = (pixel >> (6 - 3)) & 0xf8; + *(d + 2) = (pixel & 0x1f) << 3; + d += 3; + } + } + } + else + { + // Order is BGR + if(!doubledX) + { + for (int x = 0; x < width; x++) + { + uint32 pixel = *s++; + *(d + 0) = (pixel & 0x1f) << 3; + *(d + 1) = (pixel >> (6 - 3)) & 0xf8; + *(d + 2) = (pixel >> (11 - 3)) & 0xf8; + d += 3; + } + } + else // high-res x, blend: + { + for (int x = 0; x < width; x++) + { + uint32 pixel = Interp(s[0],s[1]); + s += 2; + *(d + 0) = (pixel & 0x1f) << 3; + *(d + 1) = (pixel >> (6 - 3)) & 0xf8; + *(d + 2) = (pixel >> (11 - 3)) & 0xf8; + d += 3; + } + } + } + } +} + +void Convert16To32 (SSurface *src, SSurface *dst, RECT *srect) +{ + int height = srect->bottom - srect->top; + int width = srect->right - srect->left; + int offset1 = srect->top * src->Pitch + srect->left * 2; + int offset2 = 0;//((dst->Height - height) >> 1) * dst->Pitch + + //((dst->Width - width) >> 1) * sizeof (uint32); + + for (register int y = 0; y < height; y++) + { + register uint16 *s = (uint16 *) ((uint8 *) src->Surface + y * src->Pitch + offset1); + register uint32 *d = (uint32 *) ((uint8 *) dst->Surface + + y * dst->Pitch + offset2); + for (register int x = 0; x < width; x++) + { + uint32 pixel = *s++; + *d++ = (((pixel >> 11) & 0x1f) << GUI.RedShift) | + (((pixel >> 6) & 0x1f) << GUI.GreenShift) | + ((pixel & 0x1f) << GUI.BlueShift); + } + } +} + +void ConvertDepth (SSurface *src, SSurface *dst, RECT *srect) +{ + // SNES image has been rendered in 16-bit, RGB565 format + switch (GUI.ScreenDepth) + { + case 15: // is this right? + case 16: + break; + case 24: + Convert16To24 (src, dst, srect); + break; + case 32: + Convert16To32 (src, dst, srect); + break; + } +} + +/* Depth conversion functions end */ + + +/* The rest of the functions are recreations of the core string display functions with additional scaling. + They provide the possibility to render the messages into a surface other than the core GFX.Screen. +*/ + +void WinDisplayStringFromBottom (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap) +{ + if(Settings.AutoDisplayMessages) { + WinSetCustomDisplaySurface((void *)GFX.Screen, GFX.RealPPL, IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight, 1); + WinDisplayStringInBuffer(string, linesFromBottom, pixelsFromLeft, allowWrap); + } else + if(GUI.ScreenDepth == 32) { + WinDisplayStringInBuffer(string, linesFromBottom, pixelsFromLeft, allowWrap); + } else { + WinDisplayStringInBuffer(string, linesFromBottom, pixelsFromLeft, allowWrap); + } +} + +static int font_width = 8, font_height = 9; +static void *displayScreen; +int displayPpl, displayWidth, displayHeight, displayScale,fontwidth_scaled,fontheight_scaled; + +void WinSetCustomDisplaySurface(void *screen, int ppl, int width, int height, int scale) +{ + displayScreen=screen; + displayPpl=ppl; + displayWidth=width; + displayHeight=height; + displayScale=scale; + fontwidth_scaled=font_width*displayScale; + fontheight_scaled=font_height*displayScale; +} + +template +void WinDisplayChar (screenPtrType *s, uint8 c) +{ + int h, w; + + int line = ((c - 32) >> 4) * fontheight_scaled; + int offset = ((c - 32) & 15) * fontwidth_scaled; + + + if(displayScale == 1) { + for(h=0; h> 11) ) << /*RedShift+3*/ 19) | \ + ((((pixel) >> 6) & 0x1f) << /*GreenShift+3*/11) | \ + (((pixel) & 0x1f) << /*BlueShift+3*/ 3)) + + if(p == '#') + { + *s = CONVERT_16_TO_32(Settings.DisplayColor); + } + else if(p == '.') + { + static const uint32 black = CONVERT_16_TO_32(BUILD_PIXEL(0,0,0)); + *s = black; + } +} + +#define CHOOSE(c1) ((c1=='#'||X=='#') ? '#' : ((c1=='.'||X=='.') ? '.' : c1)) + +template +static inline void FontPixToScreenEPX(int x, int y, screenPtrType *s) +{ + const char X = font[y][x]; // E D H + const char A = x>0 ?font[y][x-1]:' '; // A X C + const char C = x<143?font[y][x+1]:' '; // F B G + if (A != C) + { + const char D = y>0 ?font[y-1][x]:' '; + const char B = y<125?font[y+1][x]:' '; + if (B != D) + { + FontPixToScreen((D == A) ? CHOOSE(D) : X, s); + FontPixToScreen((C == D) ? CHOOSE(C) : X, s+1); + FontPixToScreen((A == B) ? CHOOSE(A) : X, s+displayPpl); + FontPixToScreen((B == C) ? CHOOSE(B) : X, s+displayPpl+1); + return; + } + } + FontPixToScreen(X, s); + FontPixToScreen(X, s+1); + FontPixToScreen(X, s+displayPpl); + FontPixToScreen(X, s+displayPpl+1); +} +#undef CHOOSE + +#define CHOOSE(c1) ((X=='#') ? '#' : c1) +template +inline void FontPixToScreenEPXSimple3(int x, int y, screenPtrType *s) +{ + const char X = font[y][x]; // E D H + const char A = x>0 ?font[y][x-1]:' '; // A X C + const char C = x<143?font[y][x+1]:' '; // F B G + const char D = y>0 ?font[y-1][x]:' '; + const char B = y<125?font[y+1][x]:' '; + const bool XnE = y>0 &&x>0 ?(X != font[y-1][x-1]):X!=' '; + const bool XnF = y<125&&x<143?(X != font[y+1][x-1]):X!=' '; + const bool XnG = y<125&&x>0 ?(X != font[y+1][x+1]):X!=' '; + const bool XnH = y>0 &&x<143?(X != font[y-1][x+1]):X!=' '; + const bool DA = D == A && (XnE || CHOOSE(D)!=X); + const bool AB = A == B && (XnF || CHOOSE(A)!=X); + const bool BC = B == C && (XnG || CHOOSE(B)!=X); + const bool CD = C == D && (XnH || CHOOSE(C)!=X); + FontPixToScreen(DA ? A : X, s); + FontPixToScreen(X, s+1); + FontPixToScreen(CD ? C : X, s+2); + FontPixToScreen(X, s+displayPpl); + FontPixToScreen(X, s+displayPpl+1); + FontPixToScreen(X, s+displayPpl+2); + FontPixToScreen(AB ? A : X, s+displayPpl+displayPpl); + FontPixToScreen(X, s+displayPpl+displayPpl+1); + FontPixToScreen(BC ? C : X, s+displayPpl+displayPpl+2); +} +#undef CHOOSE + +template +void WinDisplayStringInBuffer (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap) +{ + if (linesFromBottom <= 0) + linesFromBottom = 1; + + screenPtrType *dst = (screenPtrType *)displayScreen + (displayHeight - fontheight_scaled * linesFromBottom) * displayPpl + pixelsFromLeft; + + int len = strlen(string); + int max_chars = displayWidth / (fontwidth_scaled - displayScale); + int char_count = 0; + + for (int i = 0 ; i < len ; i++, char_count++) + { + if (char_count >= max_chars || (uint8) string[i] < 32) + { + if (!allowWrap) + break; + + dst += fontheight_scaled * displayPpl - (fontwidth_scaled - displayScale) * max_chars; + if (dst >= (screenPtrType *)displayScreen + displayHeight * displayPpl) + break; + + char_count -= max_chars; + } + + if ((uint8) string[i] < 32) + continue; + + WinDisplayChar(dst, string[i]); + dst += fontwidth_scaled - displayScale; + } +} \ No newline at end of file diff --git a/win32/win32_display.h b/win32/win32_display.h new file mode 100644 index 00000000..fa1ce4ec --- /dev/null +++ b/win32/win32_display.h @@ -0,0 +1,201 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 WIN32_DISPLAY_H +#define WIN32_DISPLAY_H + +#include "wsnes9x.h" +#include "port.h" +#include "render.h" +#include + +void WinRefreshDisplay(void); +void S9xSetWinPixelFormat (); +void SwitchToGDI(); +void ToggleFullScreen (); +void RestoreGUIDisplay (); +void RestoreSNESDisplay (); +void WinChangeWindowSize(unsigned int newWidth, unsigned int newHeight); +bool WinDisplayReset(void); +void WinDisplayApplyChanges(); +void WinEnumDisplayModes(std::vector *modeVector); +void ConvertDepth (SSurface *src, SSurface *dst, RECT *srect); +void WinDisplayStringFromBottom (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); +void WinSetCustomDisplaySurface(void *screen, int ppl, int width, int height, int scale); +template +void WinDisplayStringInBuffer (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); + +#endif \ No newline at end of file diff --git a/win32/win32_sound.cpp b/win32/win32_sound.cpp new file mode 100644 index 00000000..0aeef4f7 --- /dev/null +++ b/win32/win32_sound.cpp @@ -0,0 +1,275 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 "IS9xSoundOutput.h" +#include "../snes9x.h" +#include "../apu/apu.h" +#include "wsnes9x.h" +#include "CDirectSound.h" +#include "CXAudio2.h" +#include "win32_sound.h" +// FMOD and FMOD Ex cannot be used at the same time +#ifdef FMOD_SUPPORT +#include "CFMOD.h" +#pragma comment(linker,"/DEFAULTLIB:fmodvc.lib") +#elif defined FMODEX_SUPPORT +#include "CFMODEx.h" +#pragma comment(linker,"/DEFAULTLIB:fmodex_vc.lib") +#endif + +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) + +// available sound output methods +CDirectSound S9xDirectSound; +CXAudio2 S9xXAudio2; +// FMOD and FMOD Ex cannot be used at the same time +#ifdef FMOD_SUPPORT +CFMOD S9xFMOD; +#elif defined FMODEX_SUPPORT +CFMODEx S9xFMODEx; +#endif + +// Interface used to access the sound output +IS9xSoundOutput *S9xSoundOutput = &S9xXAudio2; + +/* ReInitSound +reinitializes the sound core with current settings +IN: +mode - 0 disables sound output, 1 enables +----- +returns true if successful, false otherwise +*/ +bool ReInitSound() +{ + Settings.SoundInputRate = CLAMP(Settings.SoundInputRate,8000, 48000); + Settings.SoundPlaybackRate = CLAMP(Settings.SoundPlaybackRate,8000, 48000); + S9xSetSoundMute(GUI.Mute); + if(S9xSoundOutput) + S9xSoundOutput->DeInitSoundOutput(); + return S9xInitSound(GUI.SoundBufferSize,0); +} + +void CloseSoundDevice() { + S9xSoundOutput->DeInitSoundOutput(); + S9xSetSamplesAvailableCallback(NULL,NULL); +} + +/* S9xOpenSoundDevice +called by S9xInitSound - initializes the currently selected sound output and +applies the current sound settings +----- +returns true if successful, false otherwise +*/ +bool8 S9xOpenSoundDevice () +{ + // point the interface to the correct output object + switch(GUI.SoundDriver) { + case WIN_SNES9X_DIRECT_SOUND_DRIVER: + S9xSoundOutput = &S9xDirectSound; + break; +#ifdef FMOD_SUPPORT + case WIN_FMOD_DIRECT_SOUND_DRIVER: + case WIN_FMOD_WAVE_SOUND_DRIVER: + case WIN_FMOD_A3D_SOUND_DRIVER: + S9xSoundOutput = &S9xFMOD; + break; +#elif defined FMODEX_SUPPORT + case WIN_FMODEX_DEFAULT_DRIVER: + case WIN_FMODEX_ASIO_DRIVER: + case WIN_FMODEX_OPENAL_DRIVER: + S9xSoundOutput = &S9xFMODEx; + break; +#endif + case WIN_XAUDIO2_SOUND_DRIVER: + S9xSoundOutput = &S9xXAudio2; + break; + default: // we default to DirectSound + GUI.SoundDriver = WIN_SNES9X_DIRECT_SOUND_DRIVER; + S9xSoundOutput = &S9xDirectSound; + } + if(!S9xSoundOutput->InitSoundOutput()) + return false; + S9xSetSamplesAvailableCallback (S9xSoundCallback, NULL); + return S9xSoundOutput->SetupSound(); +} + +/* S9xSoundCallback +called by the sound core to process generated samples +*/ +void S9xSoundCallback(void *data) +{ + S9xSoundOutput->ProcessSound(); +} \ No newline at end of file diff --git a/win32/win32_sound.h b/win32/win32_sound.h new file mode 100644 index 00000000..0b991a84 --- /dev/null +++ b/win32/win32_sound.h @@ -0,0 +1,184 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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 WIN32_SOUND_H +#define WIN32_SOUND_H + +bool ReInitSound(); +void S9xSoundCallback(void *data); +void CloseSoundDevice(); + +#endif \ No newline at end of file diff --git a/win32/wlanguage.h b/win32/wlanguage.h new file mode 100644 index 00000000..4aacca6d --- /dev/null +++ b/win32/wlanguage.h @@ -0,0 +1,593 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + + + +/* This is where all the GUI text strings will eventually end up */ + +#define WINDOW_TITLE "Snes9X v%s for Windows" + +// the windows registry is no longer used +//#define MY_REG_KEY "Software\\Emulators\\Snes9X" +//#define REG_KEY_VER "1.31" + +#define DISCLAIMER_TEXT "Snes9X v%s for Windows.\r\n" \ + "(c) Copyright 1996 - 2002 Gary Henderson and Jerremy Koot (jkoot@snes9x.com)\r\n" \ + "(c) Copyright 2002 - 2004 Matthew Kendora\r\n" \ + "(c) Copyright 2002 - 2005 Peter Bortas\r\n" \ + "(c) Copyright 2004 - 2005 Joel Yliluoma\r\n" \ + "(c) Copyright 2001 - 2006 John Weidman\r\n" \ + "(c) Copyright 2002 - 2010 Brad Jorsch, funkyass, Kris Bleakley, Nach, zones\r\n" \ + "(c) Copyright 2006 - 2007 nitsuja\r\n" \ + "(c) Copyright 2009 - 2010 BearOso, OV2\r\n\r\n" \ + "Windows Port Authors: Matthew Kendora, funkyass, nitsuja, Nach, blip, OV2.\r\n\r\n" \ + "Snes9X is a Super Nintendo Entertainment System\r\n" \ + "emulator that allows you to play most games designed\r\n" \ + "for the SNES on your PC.\r\n\r\n" \ + "Please visit http://www.snes9x.com for\r\n" \ + "up-to-the-minute information and help on Snes9X.\r\n\r\n" \ + "Nintendo is a trade mark." + + +#define APP_NAME "Snes9x" +// possible global strings +#define SNES9X_INFO "Snes9x: Information" +#define SNES9X_WARN "Snes9x: WARNING!" +#define SNES9X_DXS "Snes9X: DirectSound" +#define SNES9X_SNDQ "Snes9X: Sound CPU Question" +#define SNES9X_NP_ERROR "Snes9X: NetPlay Error" +#define BUTTON_OK "&OK" +#define BUTTON_CANCEL "&Cancel" + +// Gamepad Dialog Strings +#define INPUTCONFIG_TITLE "Input Configuration" +#define INPUTCONFIG_JPTOGGLE "Enabled" +//#define INPUTCONFIG_DIAGTOGGLE "Toggle Diagonals" +//#define INPUTCONFIG_OK "&OK" +//#define INPUTCONFIG_CANCEL "&Cancel" +#define INPUTCONFIG_JPCOMBO "Joypad #%d" +#define INPUTCONFIG_LABEL_UP "Up" +#define INPUTCONFIG_LABEL_DOWN "Down" +#define INPUTCONFIG_LABEL_LEFT "Left" +#define INPUTCONFIG_LABEL_RIGHT "Right" +#define INPUTCONFIG_LABEL_A "A" +#define INPUTCONFIG_LABEL_B "B" +#define INPUTCONFIG_LABEL_X "X" +#define INPUTCONFIG_LABEL_Y "Y" +#define INPUTCONFIG_LABEL_L "L" +#define INPUTCONFIG_LABEL_R "R" +#define INPUTCONFIG_LABEL_START "Start" +#define INPUTCONFIG_LABEL_SELECT "Select" +#define INPUTCONFIG_LABEL_UPLEFT "Up Left" +#define INPUTCONFIG_LABEL_UPRIGHT "Up Right" +#define INPUTCONFIG_LABEL_DOWNRIGHT "Dn Right" +#define INPUTCONFIG_LABEL_DOWNLEFT "Dn Left" +#define INPUTCONFIG_LABEL_BLUE "Blue means the button is already mapped.\nPink means it conflicts with a custom hotkey.\nRed means it's reserved by Windows.\nButtons can be disabled using Escape." +#define INPUTCONFIG_LABEL_UNUSED "" +#define INPUTCONFIG_LABEL_CLEAR_TOGGLES_AND_TURBO "Clear All" +#define INPUTCONFIG_LABEL_MAKE_TURBO "TempTurbo" +#define INPUTCONFIG_LABEL_MAKE_HELD "Autohold" +#define INPUTCONFIG_LABEL_MAKE_TURBO_HELD "Autofire" +#define INPUTCONFIG_LABEL_CONTROLLER_TURBO_PANEL_MOD " Turbo" + +// Hotkeys Dialog Strings +#define HOTKEYS_TITLE "Hotkey Configuration" +#define HOTKEYS_CONTROL_MOD "Ctrl + " +#define HOTKEYS_SHIFT_MOD "Shift + " +#define HOTKEYS_ALT_MOD "Alt + " +#define HOTKEYS_LABEL_BLUE "Blue means the hotkey is already mapped.\nPink means it conflicts with a game button.\nRed means it's reserved by Windows.\nA hotkey can be disabled using Escape." +#define HOTKEYS_HKCOMBO "Page %d" +#define HOTKEYS_LABEL_1_1 "speed +" +#define HOTKEYS_LABEL_1_2 "speed -" +#define HOTKEYS_LABEL_1_3 "pause" +#define HOTKEYS_LABEL_1_4 "frame advance" +#define HOTKEYS_LABEL_1_5 "fast forward" +#define HOTKEYS_LABEL_1_6 "skip +" +#define HOTKEYS_LABEL_1_7 "skip -" +#define HOTKEYS_LABEL_1_8 "superscope turbo" +#define HOTKEYS_LABEL_1_9 "superscope pause" +#define HOTKEYS_LABEL_1_10 "show pressed keys" +#define HOTKEYS_LABEL_1_11 "movie frame count" +#define HOTKEYS_LABEL_1_12 "movie read-only" +#define HOTKEYS_LABEL_1_13 "save screenshot" +#define HOTKEYS_LABEL_2_1 "Graphics Layer 1" +#define HOTKEYS_LABEL_2_2 "Graphics Layer 2" +#define HOTKEYS_LABEL_2_3 "Graphics Layer 3" +#define HOTKEYS_LABEL_2_4 "Graphics Layer 4" +#define HOTKEYS_LABEL_2_5 "Sprites Layer" +#define HOTKEYS_LABEL_2_6 "Clipping Windows" +#define HOTKEYS_LABEL_2_7 "Transparency" +#define HOTKEYS_LABEL_2_8 "HDMA Emulation" +#define HOTKEYS_LABEL_2_9 "GLCube Mode" +#define HOTKEYS_LABEL_2_10 "Switch Controllers" +#define HOTKEYS_LABEL_2_11 "Joypad Swap" +#define HOTKEYS_LABEL_2_12 "Reset Game" +#define HOTKEYS_LABEL_2_13 "Toggle Cheats" +#define HOTKEYS_LABEL_3_1 "Turbo A mode" +#define HOTKEYS_LABEL_3_2 "Turbo B mode" +#define HOTKEYS_LABEL_3_3 "Turbo Y mode" +#define HOTKEYS_LABEL_3_4 "Turbo X mode" +#define HOTKEYS_LABEL_3_5 "Turbo L mode" +#define HOTKEYS_LABEL_3_6 "Turbo R mode" +#define HOTKEYS_LABEL_3_7 "Turbo Start mode" +#define HOTKEYS_LABEL_3_8 "Turbo Select mode" +#define HOTKEYS_LABEL_3_9 "Turbo Left mode" +#define HOTKEYS_LABEL_3_10 "Turbo Up mode" +#define HOTKEYS_LABEL_3_11 "Turbo Right mode" +#define HOTKEYS_LABEL_3_12 "Turbo Down mode" +//#define HOTKEYS_LABEL_4_12 "Interpolate Mode 7" +//#define HOTKEYS_LABEL_4_13 "BG Layering hack" + +// gaming buttons and axes +#define GAMEDEVICE_JOYNUMPREFIX "(J%x)" // don't change this +#define GAMEDEVICE_JOYBUTPREFIX "#[%d]" // don't change this +#define GAMEDEVICE_XNEG "Left" +#define GAMEDEVICE_XPOS "Right" +#define GAMEDEVICE_YPOS "Up" +#define GAMEDEVICE_YNEG "Down" +#define GAMEDEVICE_POVLEFT "POV Left" +#define GAMEDEVICE_POVRIGHT "POV Right" +#define GAMEDEVICE_POVUP "POV Up" +#define GAMEDEVICE_POVDOWN "POV Down" +#define GAMEDEVICE_POVDNLEFT "POV Dn Left" +#define GAMEDEVICE_POVDNRIGHT "POV Dn Right" +#define GAMEDEVICE_POVUPLEFT "POV Up Left" +#define GAMEDEVICE_POVUPRIGHT "POV Up Right" +#define GAMEDEVICE_ZPOS "Z Up" +#define GAMEDEVICE_ZNEG "Z Down" +#define GAMEDEVICE_RPOS "R Up" +#define GAMEDEVICE_RNEG "R Down" +#define GAMEDEVICE_UPOS "U Up" +#define GAMEDEVICE_UNEG "U Down" +#define GAMEDEVICE_VPOS "V Up" +#define GAMEDEVICE_VNEG "V Down" +#define GAMEDEVICE_BUTTON "Button %d" + +// gaming general +#define GAMEDEVICE_DISABLED "Disabled" + +// gaming keys +#define GAMEDEVICE_KEY "#%d" +#define GAMEDEVICE_NUMPADPREFIX "Numpad-%c" +#define GAMEDEVICE_VK_TAB "Tab" +#define GAMEDEVICE_VK_BACK "Backspace" +#define GAMEDEVICE_VK_CLEAR "Delete" +#define GAMEDEVICE_VK_RETURN "Enter" +#define GAMEDEVICE_VK_LSHIFT "LShift" +#define GAMEDEVICE_VK_RSHIFT "RShift" +#define GAMEDEVICE_VK_LCONTROL "LCtrl" +#define GAMEDEVICE_VK_RCONTROL "RCtrl" +#define GAMEDEVICE_VK_LMENU "LAlt" +#define GAMEDEVICE_VK_RMENU "RAlt" +#define GAMEDEVICE_VK_PAUSE "Pause" +#define GAMEDEVICE_VK_CAPITAL "Capslock" +#define GAMEDEVICE_VK_ESCAPE "Disabled" +#define GAMEDEVICE_VK_SPACE "Space" +#define GAMEDEVICE_VK_PRIOR "PgUp" +#define GAMEDEVICE_VK_NEXT "PgDn" +#define GAMEDEVICE_VK_HOME "Home" +#define GAMEDEVICE_VK_END "End" +#define GAMEDEVICE_VK_LEFT "Left" +#define GAMEDEVICE_VK_RIGHT "Right" +#define GAMEDEVICE_VK_UP "Up" +#define GAMEDEVICE_VK_DOWN "Down" +#define GAMEDEVICE_VK_SELECT "Select" +#define GAMEDEVICE_VK_PRINT "Print" +#define GAMEDEVICE_VK_EXECUTE "Execute" +#define GAMEDEVICE_VK_SNAPSHOT "SnapShot" +#define GAMEDEVICE_VK_INSERT "Insert" +#define GAMEDEVICE_VK_DELETE "Delete" +#define GAMEDEVICE_VK_HELP "Help" +#define GAMEDEVICE_VK_LWIN "LWinKey" +#define GAMEDEVICE_VK_RWIN "RWinKey" +#define GAMEDEVICE_VK_APPS "AppKey" +#define GAMEDEVICE_VK_MULTIPLY "Numpad *" +#define GAMEDEVICE_VK_ADD "Numpad +" +#define GAMEDEVICE_VK_SEPARATOR "Separator" +#define GAMEDEVICE_VK_OEM_1 "Semi-Colon" +#define GAMEDEVICE_VK_OEM_7 "Apostrophe" +#define GAMEDEVICE_VK_OEM_COMMA "Comma" +#define GAMEDEVICE_VK_OEM_PERIOD "Period" +#define GAMEDEVICE_VK_SUBTRACT "Numpad -" +#define GAMEDEVICE_VK_DECIMAL "Numpad ." +#define GAMEDEVICE_VK_DIVIDE "Numpad /" +#define GAMEDEVICE_VK_NUMLOCK "Num-lock" +#define GAMEDEVICE_VK_SCROLL "Scroll-lock" +#define GAMEDEVICE_VK_OEM_MINUS "-" +#define GAMEDEVICE_VK_OEM_PLUS "=" +#define GAMEDEVICE_VK_SHIFT "Shift" +#define GAMEDEVICE_VK_CONTROL "Control" +#define GAMEDEVICE_VK_MENU "Alt" +#define GAMEDEVICE_VK_OEM_4 "[" +#define GAMEDEVICE_VK_OEM_6 "]" +#define GAMEDEVICE_VK_OEM_5 "\\" +#define GAMEDEVICE_VK_OEM_2 "/" +#define GAMEDEVICE_VK_OEM_3 "`" +#define GAMEDEVICE_VK_F1 "F1" +#define GAMEDEVICE_VK_F2 "F2" +#define GAMEDEVICE_VK_F3 "F3" +#define GAMEDEVICE_VK_F4 "F4" +#define GAMEDEVICE_VK_F5 "F5" +#define GAMEDEVICE_VK_F6 "F6" +#define GAMEDEVICE_VK_F7 "F7" +#define GAMEDEVICE_VK_F8 "F8" +#define GAMEDEVICE_VK_F9 "F9" +#define GAMEDEVICE_VK_F10 "F10" +#define GAMEDEVICE_VK_F11 "F11" +#define GAMEDEVICE_VK_F12 "F12" + + +//evil things I found in WinProc + +#define WINPROC_TURBOMODE_ON "Fast-Forward Activated" +#define WINPROC_TURBOMODE_OFF "Fast-Forward Deactivated" +#define WINPROC_TURBOMODE_TEXT "Fast-Forward" +#define WINPROC_HDMA_TEXT "HDMA emulation" +#define WINPROC_BG1 "BG#1" //Background Layers +#define WINPROC_BG2 "BG#2" +#define WINPROC_BG3 "BG#3" +#define WINPROC_BG4 "BG#4" +#define WINPROC_SPRITES "Sprites" +#define WINPROC_PADSWAP "Joypad swapping" +#define WINPROC_CONTROLERS0 "Multiplayer 5 on #0" +#define WINPROC_CONTROLERS1 "Joypad on #0" +#define WINPROC_CONTROLERS2 "Mouse on #1" +#define WINPROC_CONTROLERS3 "Mouse on #0" +#define WINPROC_CONTROLERS4 "Superscope on #1" +#define WINPROC_CONTROLERS5 "Justifier 1 on #1" +#define WINPROC_CONTROLERS6 "Justifier 2 on #1" +#define WINPROC_BGHACK "Background layering hack" +#define WINPROC_MODE7INTER "Mode 7 Interpolation" +#define WINPROC_TRANSPARENCY "Transparency effects" +#define WINPROC_CLIPWIN "Graphic clip windows" +#define WINPROC_PAUSE "Pause" +#define WINPROC_EMUFRAMETIME "Emulated frame time: %dms" +#define WINPROC_AUTOSKIP "Auto Frame Skip" +#define WINPROC_FRAMESKIP "Frame skip: %d" +#define WINPROC_TURBO_R_ON "Turbo R Activated" +#define WINPROC_TURBO_R_OFF "Turbo R Deactivated" +#define WINPROC_TURBO_L_ON "Turbo L Activated" +#define WINPROC_TURBO_L_OFF "Turbo L Deactivated" +#define WINPROC_TURBO_X_ON "Turbo X Activated" +#define WINPROC_TURBO_X_OFF "Turbo X Deactivated" +#define WINPROC_TURBO_Y_ON "Turbo Y Activated" +#define WINPROC_TURBO_Y_OFF "Turbo Y Deactivated" +#define WINPROC_TURBO_A_ON "Turbo A Activated" +#define WINPROC_TURBO_A_OFF "Turbo A Deactivated" +#define WINPROC_TURBO_B_ON "Turbo B Activated" +#define WINPROC_TURBO_B_OFF "Turbo B Deactivated" +#define WINPROC_TURBO_SEL_ON "Turbo Select Activated" +#define WINPROC_TURBO_SEL_OFF "Turbo Select Deactivated" +#define WINPROC_TURBO_START_ON "Turbo Start Activated" +#define WINPROC_TURBO_START_OFF "Turbo Start Deactivated" +#define WINPROC_TURBO_LEFT_ON "Turbo Left Activated" +#define WINPROC_TURBO_LEFT_OFF "Turbo Left Deactivated" +#define WINPROC_TURBO_RIGHT_ON "Turbo Right Activated" +#define WINPROC_TURBO_RIGHT_OFF "Turbo Right Deactivated" +#define WINPROC_TURBO_UP_ON "Turbo Up Activated" +#define WINPROC_TURBO_UP_OFF "Turbo Up Deactivated" +#define WINPROC_TURBO_DOWN_ON "Turbo Down Activated" +#define WINPROC_TURBO_DOWN_OFF "Turbo Down Deactivated" +#define WINPROC_FILTER_RESTART "You will need to restart Snes9x before the output image\nprocessing option change will take effect." +#define WINPROC_DISCONNECT "Disconnect from the NetPlay server first." +#define WINPROC_NET_RESTART "Your game will be reset after the ROM has been sent due to\nyour 'Sync Using Reset Game' setting.\n\n" +#define WINPROC_SYNC_SND "Sync sound" + +//Emulator Settings + +#define EMUSET_TITLE "Emulation Settings" +#define EMUSET_LABEL_DIRECTORY "Directory" +#define EMUSET_BROWSE "&Browse..." +#define EMUSET_LABEL_ASRAM "Auto-Save S-RAM" +#define EMUSET_LABEL_ASRAM_TEXT "seconds after last change (0 disables auto-save)" +#define EMUSET_LABEL_SMAX "Skip at most" +#define EMUSET_LABEL_SMAX_TEXT "frames in auto-frame rate mode" +#define EMUSET_LABEL_STURBO "Skip Rendering" +#define EMUSET_LABEL_STURBO_TEXT "frames in fast-forward mode" +#define EMUSET_TOGGLE_TURBO "Toggled fast-forward mode" + +//Netplay Options + +#define NPOPT_TITLE "Netplay Options" +#define NPOPT_LABEL_PORTNUM "Socket Port Number" +#define NPOPT_LABEL_PAUSEINTERVAL "Ask Server to Pause when" +#define NPOPT_LABEL_PAUSEINTERVAL_TEXT "frames behind" +#define NPOPT_LABEL_MAXSKIP "Maximum Frame Rate Skip" +#define NPOPT_SYNCBYRESET "Sync By Reset" +#define NPOPT_SENDROM "Send ROM Image to Client on Connect" +#define NPOPT_ACTASSERVER "Act As Server" +#define NPOPT_PORTNUMBLOCK "Port Settings" +#define NPOPT_CLIENTSETTINGSBLOCK "Client Settings" +#define NPOPT_SERVERSETTINGSBLOCK "Server Settings" + +//Netplay Connect + + +#define NPCON_TITLE "Connect to Server" +#define NPCON_LABEL_SERVERADDY "Server Address" +#define NPCON_LABEL_PORTNUM "Port Number" +#define NPCON_CLEARHISTORY "Clear History" +#define NPCON_ENTERHOST "enter host name..." +#define NPCON_PLEASE_ENTERHOST "Please enter a host name." + + +//Movie Messages + +#define MOVIE_FILETYPE_DESCRIPTION "Snes9x Movie File" +#define MOVIE_LABEL_SYNC_DATA_FROM_MOVIE "LOADED FROM MOVIE:" +#define MOVIE_LABEL_SYNC_DATA_NOT_FROM_MOVIE "SETTINGS NOT IN MOVIE; VERIFY:" +#define MOVIE_ERR_COULD_NOT_OPEN "Could not open movie file." +#define MOVIE_ERR_NOT_FOUND_SHORT "File not found." +#define MOVIE_ERR_NOT_FOUND "The movie file was not found or could not be opened." +#define MOVIE_ERR_WRONG_FORMAT_SHORT "Unrecognized format." +#define MOVIE_ERR_WRONG_FORMAT "The movie file is corrupt or in the wrong format." +#define MOVIE_ERR_WRONG_VERSION_SHORT "Unsupported movie version." +#define MOVIE_ERR_WRONG_VERSION MOVIE_ERR_WRONG_VERSION_SHORT " You need a different version of Snes9x to play this movie." +#define MOVIE_ERR_NOFRAMETOGGLE "No movie; can't toggle frame count" +#define MOVIE_ERR_NOREADONLYTOGGLE "No movie; can't toggle read-only" +#define MOVIE_LABEL_AUTHORINFO "Author Info:" +#define MOVIE_LABEL_ERRORINFO "Error Info:" +#define MOVIE_INFO_MISMATCH " <-- MISMATCH !!!" +#define MOVIE_INFO_CURRENTROM "Current ROM:" +#define MOVIE_INFO_MOVIEROM "Movie's ROM:" +#define MOVIE_INFO_ROMNOTSTORED " (not stored in movie file)" +#define MOVIE_INFO_ROMINFO " crc32=%08X, name=%s" +#define MOVIE_INFO_DIRECTORY " Path: %s" +#define MOVIE_WARNING_MISMATCH "WARNING: You don't have the right ROM loaded!" +#define MOVIE_WARNING_OK "Press OK to start playing the movie." +#define MOVIE_LABEL_STARTSETTINGS "Recording Start" +#define MOVIE_LABEL_CONTSETTINGS "Record Controllers" +#define MOVIE_LABEL_SYNCSETTINGS "Misc. Recording Settings" +#define MOVIE_SHUTDOWNMASTER_WARNING "The \"SpeedHacks\" setting in your snes9x.cfg file is on.\nThis makes emulation less CPU-intensive, but also less accurate,\ncausing some games to lag noticeably more than they should.\nYou might want to reconsider recording a movie under these conditions." + +// Save Messages + +#define FREEZE_INFO_SET_SLOT_N "set slot 00%d" + +// AVI Messages + +#define AVI_CONFIGURATION_CHANGED "AVI recording stopped (configuration settings changed)." +#define AVI_CREATION_FAILED "Failed to create AVI file." + +// Cheat or Cheat Search Messages + +#define SEARCH_TITLE_RANGEERROR "Range Error" +#define SEARCH_TITLE_CHEATERROR "Snes9x Cheat Error" +#define SEARCH_ERR_INVALIDNEWVALUE "You have entered an out of range or invalid value for the new value" +#define SEARCH_ERR_INVALIDCURVALUE "You have entered an out of range or invalid value for\n"\ + "the current value. This value is used when a cheat is unapplied.\n"\ + "(If left blank, no value is restored when the cheat is unapplied)" +#define SEARCH_ERR_INVALIDSEARCHVALUE "Please enter a valid value for a search!" +#define SEARCH_COLUMN_ADDRESS "Address" +#define SEARCH_COLUMN_VALUE "Value" +#define SEARCH_COLUMN_DESCRIPTION "Description" + +// ROM dialog + +#define ROM_COLUMN_FILENAME "File" +#define ROM_COLUMN_DESCRIPTION "Description" +#define ROM_COLUMN_SIZE "Size" +#define ROM_OPTION_AUTODETECT "Auto-Detect" +#define ROM_OPTION_FORCEHEADER "Force Header" +#define ROM_OPTION_FORCENOHEADER "Force No Header" +#define ROM_OPTION_FORCEPAL "Force PAL" +#define ROM_OPTION_FORCENTSC "Force NTSC" +#define ROM_OPTION_FORCEHIROM "Force HiROM" +#define ROM_OPTION_FORCELOROM "Force LoROM" +#define ROM_OPTION_NONINTERLEAVED "Force not interleaved" +#define ROM_OPTION_MODE1 "Force mode 1" +#define ROM_OPTION_MODE2 "Force mode 2" +#define ROM_OPTION_GD24 "Force GD24" +#define ROM_ITEM_NOTAROM "Not a ROM" +#define ROM_ITEM_CANTOPEN "Can't Open File" +#define ROM_ITEM_DESCNOTAVAILABLE "(Not Available)" +#define ROM_ITEM_COMPRESSEDROMDESCRIPTION "" + +// Settings + +#define SETTINGS_TITLE_SELECTFOLDER "Select Folder" +#define SETTINGS_OPTION_DIRECTORY_ROMS "Roms" +#define SETTINGS_OPTION_DIRECTORY_SCREENS "Screenshots" +#define SETTINGS_OPTION_DIRECTORY_MOVIES "Movies" +#define SETTINGS_OPTION_DIRECTORY_SPCS "SPCs" +#define SETTINGS_OPTION_DIRECTORY_SAVES "Saves" +#define SETTINGS_OPTION_DIRECTORY_SRAM "SRAM" +#define SETTINGS_OPTION_DIRECTORY_PATCHESANDCHEATS "Patch&Cheat" +#define SETTINGS_OPTION_DIRECTORY_BIOS "BIOS files" + +// Misc. + +#define INPUT_INFO_DISPLAY_ENABLED "Input display enabled." +#define INPUT_INFO_DISPLAY_DISABLED "Input display disabled." + +#define FILE_INFO_AVI_FILE_TYPE "AVI file" +#define FILE_INFO_TXT_FILE_TYPE "Text file" +#define FILE_INFO_ROM_FILE_TYPE "ROM files or archives" +#define FILE_INFO_UNCROM_FILE_TYPE "Uncompressed ROM files" +#define FILE_INFO_ANY_FILE_TYPE "All files" + +#define ERR_ROM_NOT_FOUND "ROM image \"%s\" was not found or could not be opened." +#define SRM_SAVE_FAILED "Failed to save SRM file." + +#define CHEATS_INFO_ENABLED "Cheats enabled." +#define CHEATS_INFO_DISABLED "Cheats disabled." +#define CHEATS_INFO_ENABLED_NONE "Cheats enabled. (None are active.)" + +#define MULTICART_BIOS_NOT_FOUND "not found!" +#define MULTICART_BIOS_FOUND "" + +#define ABOUT_DIALOG_TITLE "About " diff --git a/win32/wsnes9x.cpp b/win32/wsnes9x.cpp new file mode 100644 index 00000000..cf7f7688 --- /dev/null +++ b/win32/wsnes9x.cpp @@ -0,0 +1,10695 @@ +/*********************************************************************************** + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com), + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2002 - 2004 Matthew Kendora + + (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org) + + (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/) + + (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca), + Kris Bleakley (codeviolation@hotmail.com) + + (c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net), + Nach (n-a-c-h@users.sourceforge.net), + zones (kasumitokoduck@yahoo.com) + + (c) Copyright 2006 - 2007 nitsuja + + (c) Copyright 2009 - 2010 BearOso, + OV2 + + + BS-X C emulator code + (c) Copyright 2005 - 2006 Dreamer Nom, + zones + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com), + Nach, + zsKnight (zsknight@zsnes.com) + + C4 C++ code + (c) Copyright 2003 - 2006 Brad Jorsch, + Nach + + DSP-1 emulator code + (c) Copyright 1998 - 2006 _Demo_, + Andreas Naive (andreasnaive@gmail.com), + Gary Henderson, + Ivar (ivar@snes9x.com), + John Weidman, + Kris Bleakley, + Matthew Kendora, + Nach, + neviksti (neviksti@hotmail.com) + + DSP-2 emulator code + (c) Copyright 2003 John Weidman, + Kris Bleakley, + Lord Nightmare (lord_nightmare@users.sourceforge.net), + Matthew Kendora, + neviksti + + DSP-3 emulator code + (c) Copyright 2003 - 2006 John Weidman, + Kris Bleakley, + Lancer, + z80 gaiden + + DSP-4 emulator code + (c) Copyright 2004 - 2006 Dreamer Nom, + John Weidman, + Kris Bleakley, + Nach, + z80 gaiden + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, + pagefault (pagefault@zsnes.com), + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code used in 1.39-1.51 + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, + John Weidman, + Dark Force + + SPC7110 and RTC C++ emulator code used in 1.52+ + (c) Copyright 2009 byuu, + neviksti + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive, + John Weidman + + S-RTC C emulator code + (c) Copyright 2001 - 2006 byuu, + John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, + John Weidman, + Kris Bleakley, + Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 _Demo_, + pagefault, + zsKnight + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, + Gary Henderson, + John Weidman + + Sound emulator code used in 1.5-1.51 + (c) Copyright 1998 - 2003 Brad Martin + (c) Copyright 1998 - 2006 Charles Bilyue' + + Sound emulator code used in 1.52+ + (c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com) + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + 2xSaI filter + (c) Copyright 1999 - 2001 Derek Liauw Kie Fa + + HQ2x, HQ3x, HQ4x filters + (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com) + + NTSC filter + (c) Copyright 2006 - 2007 Shay Green + + GTK+ GUI code + (c) Copyright 2004 - 2010 BearOso + + Win32 GUI code + (c) Copyright 2003 - 2006 blip, + funkyass, + Matthew Kendora, + Nach, + nitsuja + (c) Copyright 2009 - 2010 OV2 + + Mac OS GUI code + (c) Copyright 1998 - 2001 John Stiles + (c) Copyright 2001 - 2010 zones + + + 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/or 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 or it's derivatives. + + Snes9x is freeware for PERSONAL USE only. Commercial users should + seek permission of the copyright holders first. Commercial use includes, + but is not limited to, charging money for Snes9x or software derived from + Snes9x, including Snes9x or derivatives in commercial game bundles, and/or + using Snes9x as a promotion for your commercial product. + + 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. + ***********************************************************************************/ + + +#pragma comment(linker, \ + "\"/manifestdependency:type='Win32' "\ + "name='Microsoft.Windows.Common-Controls' "\ + "version='6.0.0.0' "\ + "processorArchitecture='*' "\ + "publicKeyToken='6595b64144ccf1df' "\ + "language='*'\"") + + +// Win32 GUI code +// (c) Copyright 2003-2006 blip, Nach, Matthew Kendora, funkyass and nitsuja + +#ifdef __MINGW32__ +#define _WIN32_IE 0x0501 +#define _WIN32_WINNT 0x0501 +#endif + +#include +#include + + +#include "wsnes9x.h" +#include "win32_sound.h" +#include "win32_display.h" +#include "../snes9x.h" +#include "../memmap.h" +#include "../cpuexec.h" +#include "../display.h" +#include "../cheats.h" +#include "../netplay.h" +#include "../apu/apu.h" +#include "../movie.h" +#include "../controls.h" +#include "../conffile.h" +#include "AVIOutput.h" +#include "InputCustom.h" +#include + +#include + +#if (((defined(_MSC_VER) && _MSC_VER >= 1300)) || defined(__MINGW32__)) + // both MINGW and VS.NET use fstream instead of fstream.h which is deprecated + #include + using namespace std; +#else + // for VC++ 6 + #include +#endif + +#include +//#include "string_cache.h" +#include "wlanguage.h" +#include "../language.h" + +//uncomment to find memory leaks, with a line in WinMain +//#define CHECK_MEMORY_LEAKS + +#ifdef CHECK_MEMORY_LEAKS + #include +#endif + +#include +#include +#include +#include + +extern SNPServer NPServer; + +#include + +#ifdef _MSC_VER +#define F_OK 0 +#define X_OK 1 +#define W_OK 2 +#define R_OK 4 +#endif + +__int64 PCBase, PCFrameTime, PCFrameTimeNTSC, PCFrameTimePAL, PCStart, PCEnd; +DWORD PCStartTicks, PCEndTicks; + +int CALLBACK DlgSP7PackConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgSoundConf(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgInfoProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgAboutProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +int CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgMultiROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +LRESULT CALLBACK DlgChildSplitProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgNPProgress(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgPackConfigProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgNetConnect(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgNPOptions(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgFunky(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgInputConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgHotkeyConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgCheatSearch(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgCheatSearchAdd(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgCreateMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +int CALLBACK DlgOpenMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); +HRESULT CALLBACK EnumModesCallback( LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext); + +int CALLBACK test(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +#define NOTKNOWN "Unknown Company " +#define HEADER_SIZE 512 +#define INFO_LEN (0xFF - 0xC0) + +#define WM_CUSTKEYDOWN (WM_USER+50) +#define WM_CUSTKEYUP (WM_USER+51) + + +/*****************************************************************************/ +/* Global variables */ +/*****************************************************************************/ +struct sGUI GUI; +typedef struct sExtList +{ + TCHAR* extension; + bool compressed; + struct sExtList* next; +} ExtList; +HANDLE SoundEvent; + +ExtList* valid_ext=NULL; +void MakeExtFile(void); +void LoadExts(void); + +extern FILE *trace_fs; +extern SCheatData Cheat; +extern bool8 do_frame_adjust; + +HINSTANCE g_hInst; + +#ifdef DEBUGGER +extern "C" void Trace (); +#endif + +static const char *rom_filename = NULL; + +struct SJoypad Joypad[16] = { + { + true, /* Joypad 1 enabled */ + VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, /* Left, Right, Up, Down */ + 0, 0, 0, 0, /* Left_Up, Left_Down, Right_Up, Right_Down */ + VK_SPACE, VK_RETURN, /* Start, Select */ + 'V', 'C', /* A B */ + 'D', 'X', /* X Y */ + 'A', 'S' /* L R */ + }, + { + true, /* Joypad 2 enabled */ + 'J', 'L', 'I', 'K', /* Left, Right, Up, Down */ + 0, 0, 0, 0, /* Left_Up, Left_Down, Right_Up, Right_Down */ + 'P', 'O', /* Start, Select */ + 'H', 'G', /* A B */ + 'T', 'F', /* X Y */ + 'Y', 'U' /* L R */ + }, + { + false, /* Joypad 3 disabled */ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, /* Joypad 4 disabled */ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, /* Joypad 5 disabled */ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 6 disabled */ + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 7 disabled */ + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 8 disabled */ + { + false, /* Joypad 1 Turbo disabled */ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, /* Joypad 2 Turbo disabled */ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, /* Joypad 3 Turbo disabled */ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, /* Joypad 4 Turbo disabled */ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, /* Joypad 5 Turbo disabled */ + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 6 Turbo disabled */ + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 7 Turbo disabled */ + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },/* Joypad 8 Turbo disabled */ +}; + +// stores on/off toggle info for each key of each controller +SJoypad ToggleJoypadStorage [8] = { + { + false, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +}; + +SJoypad TurboToggleJoypadStorage [8] = { + { + false, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { + false, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0 + }, + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +}; + +struct SCustomKeys CustomKeys = { + {/*VK_OEM_PLUS*/0xBB,0}, // speed+ (=) + {/*VK_OEM_MINUS*/0xBD,0}, // speed- (-) + {VK_PAUSE,0}, // pause (PAUSE) + {/*VK_OEM_5*/0xDC,0}, // frame advance (\) + {/*VK_OEM_PLUS*/0xBB,CUSTKEY_SHIFT_MASK}, // skip+ (_) + {/*VK_OEM_MINUS*/0xBD,CUSTKEY_SHIFT_MASK}, // skip- (+) + {/*VK_OEM_3*/0xC0,0}, // superscope turbo (`) + {/*VK_OEM_2*/0xBF,0}, // superscope pause (/) + {/*VK_OEM_PERIOD*/0xBE,0}, // frame counter (.) + {'8',CUSTKEY_SHIFT_MASK}, // movie read-only (*) + {{VK_F1,CUSTKEY_SHIFT_MASK}, // save keys + {VK_F2,CUSTKEY_SHIFT_MASK}, + {VK_F3,CUSTKEY_SHIFT_MASK}, + {VK_F4,CUSTKEY_SHIFT_MASK}, + {VK_F5,CUSTKEY_SHIFT_MASK}, + {VK_F6,CUSTKEY_SHIFT_MASK}, + {VK_F7,CUSTKEY_SHIFT_MASK}, + {VK_F8,CUSTKEY_SHIFT_MASK}, + {VK_F9,CUSTKEY_SHIFT_MASK}, + {VK_F10,CUSTKEY_SHIFT_MASK}}, + {{VK_F1,0}, // load keys + {VK_F2,0}, + {VK_F3,0}, + {VK_F4,0}, + {VK_F5,0}, + {VK_F6,0}, + {VK_F7,0}, + {VK_F8,0}, + {VK_F9,0}, + {VK_F10,0}}, + {VK_TAB,0}, // fast forward (TAB) + {/*VK_OEM_COMMA*/0xBC,0}, // show pressed keys/buttons (,) + {VK_F12,0}, // save screenshot (F12) + {0,0}, // slot plus (disabled by default) + {0,0}, // slot minus (disabled by default) + {0,0}, // slot save (disabled by default) + {0,0}, // slot load (disabled by default) + {'1',0}, // background layer 1 + {'2',0}, // background layer 2 + {'3',0}, // background layer 3 + {'4',0}, // background layer 4 + {'5',0}, // sprite layer + {'8',0}, // Clipping Windows +// {'8',0}, // BG Layering hack + {'9',0}, // Transparency + {'0',0}, // HDMA Emulation + {'6',CUSTKEY_SHIFT_MASK}, // GLCube Mode +// {'9',CUSTKEY_SHIFT_MASK}, // Interpolate Mode 7 + {'6',0}, // Joypad Swap + {'7',0}, // Switch Controllers + {VK_NEXT,CUSTKEY_SHIFT_MASK}, // Turbo A + {VK_END,CUSTKEY_SHIFT_MASK}, // Turbo B + {VK_HOME,CUSTKEY_SHIFT_MASK}, // Turbo Y + {VK_PRIOR,CUSTKEY_SHIFT_MASK}, // Turbo X + {VK_INSERT,CUSTKEY_SHIFT_MASK}, // Turbo L + {VK_DELETE,CUSTKEY_SHIFT_MASK}, // Turbo R + {0,0}, // Turbo Start + {0,0}, // Turbo Select + {0,0}, // Turbo Left + {0,0}, // Turbo Up + {0,0}, // Turbo Right + {0,0}, // Turbo Down + {{0,0}, // Select save slot 0 + {0,0}, // Select save slot 1 + {0,0}, // Select save slot 2 + {0,0}, // Select save slot 3 + {0,0}, // Select save slot 4 + {0,0}, // Select save slot 5 + {0,0}, // Select save slot 6 + {0,0}, // Select save slot 7 + {0,0}, // Select save slot 8 + {0,0}}, // Select save slot 9 + {'R',CUSTKEY_CTRL_MASK|CUSTKEY_SHIFT_MASK}, // Reset Game + {0,0}, // Toggle Cheats +}; + + +struct SSoundRates +{ + uint32 rate; + int ident; +} SoundRates[9] = { + { 8000, ID_SOUND_8000HZ}, + {11025, ID_SOUND_11025HZ}, + {16000, ID_SOUND_16000HZ}, + {22050, ID_SOUND_22050HZ}, + {30000, ID_SOUND_30000HZ}, + {32000, ID_SOUND_32000HZ}, + {35000, ID_SOUND_35000HZ}, + {44100, ID_SOUND_44100HZ}, + {48000, ID_SOUND_48000HZ} +}; + +static uint32 FrameTimings[] = { + 4000, 4000, 8333, 11667, 16667, 20000, 33333, 66667, 133333, 300000, 500000, 1000000, 1000000 +}; + +// Languages supported by Snes9X: Windows +// 0 - English [Default] +// 1 - Dutch/Nederlands +struct sLanguages Languages[] = { + { IDR_MENU_US, + TEXT("Failed to initialize currently selected display output!\n Try switching to a different output method in the display settings."), + TEXT("DirectDraw failed to set the selected display mode!"), + TEXT("DirectSound failed to initialize; no sound will be played."), + TEXT("These settings won't take effect until you restart the emulator."), + TEXT("The frame timer failed to initialize, please do NOT select the automatic framerate option or Snes9X will crash!")} +}; + +struct OpenMovieParams +{ + char Path[_MAX_PATH]; + bool8 ReadOnly; + bool8 DisplayInput; + uint8 ControllersMask; + uint8 Opts; + uint8 SyncFlags; + wchar_t Metadata[MOVIE_MAX_METADATA]; +}; + + + + + +std::vector dm; +/*****************************************************************************/ +/* WinProc */ +/*****************************************************************************/ +void DoAVIOpen(const char* filename); +void DoAVIClose(int reason); +void RestoreGUIDisplay (); +void RestoreSNESDisplay (); +void FreezeUnfreeze (int slot, bool8 freeze); +void CheckDirectoryIsWritable (const char *filename); +static void CheckMenuStates (); +static void ResetFrameTimer (); +bool8 LoadROM (const char *filename); +bool8 LoadMultiROM (const char *filename, const char *filename2); +bool8 S9xLoadROMImage (const TCHAR *string); +#ifdef NETPLAY_SUPPORT +static void EnableServer (bool8 enable); +#endif +void WinDeleteRecentGamesList (); +const char* WinParseCommandLineAndLoadConfigFile (char *line); +void WinRegisterConfigItems (); +void WinSaveConfigFile (); +void WinSetDefaultValues (); +void WinLockConfigFile (); +void WinUnlockConfigFile (); +void WinCleanupConfigData (); + +#include "../ppu.h" +#include "../snapshot.h" +const char *S9xGetFilenameInc (const char *); +void S9xSetRecentGames (); +void S9xAddToRecentGames (const char *filename); +void S9xRemoveFromRecentGames (int i); + +static void absToRel(char* relPath, const char* absPath, const char* baseDir) +{ + strcpy(relPath, absPath); + if(!strncasecmp(absPath, baseDir, strlen(baseDir))) + { + char temp [MAX_PATH]; + temp[MAX_PATH-3]='\0'; + const char* relative = absPath+strlen(baseDir); + while(relative[0]=='\\' || relative[0]=='/') + relative++; + relPath[0]='.'; relPath[1]='\\'; + strcpy(relPath+2, relative); + } +} + +void S9xMouseOn () +{ + if(Settings.StopEmulation) + return; + + if (GUI.ControllerOption==SNES_MOUSE || GUI.ControllerOption==SNES_MOUSE_SWAPPED) + { + if(Settings.Paused) + SetCursor (GUI.Arrow); + else + SetCursor (NULL); + } + else if (GUI.ControllerOption!=SNES_SUPERSCOPE && GUI.ControllerOption!=SNES_JUSTIFIER && GUI.ControllerOption!=SNES_JUSTIFIER_2) + { + SetCursor (GUI.Arrow); + GUI.CursorTimer = 60; + } + else + { + if(Settings.Paused) + SetCursor (GUI.GunSight); + else + SetCursor (NULL); + } +} + +void ChangeInputDevice(void) +{ + Settings.MouseMaster = false; + Settings.JustifierMaster = false; + Settings.SuperScopeMaster = false; + Settings.MultiPlayer5Master = false; + + CheckMenuItem(GUI.hMenu, IDM_ENABLE_MULTITAP, MFS_UNCHECKED); + CheckMenuItem(GUI.hMenu, IDM_JUSTIFIER, MFS_UNCHECKED); + CheckMenuItem(GUI.hMenu, IDM_MOUSE_TOGGLE, MFS_UNCHECKED); + CheckMenuItem(GUI.hMenu, IDM_SCOPE_TOGGLE, MFS_UNCHECKED); + CheckMenuItem(GUI.hMenu, IDM_MOUSE_SWAPPED, MFS_UNCHECKED); + CheckMenuItem(GUI.hMenu, IDM_JUSTIFIERS, MFS_UNCHECKED); + CheckMenuItem(GUI.hMenu, IDM_MULTITAP8, MFS_UNCHECKED); + CheckMenuItem(GUI.hMenu, IDM_SNES_JOYPAD, MFS_UNCHECKED); + + switch(GUI.ControllerOption) + { + case SNES_MOUSE: + Settings.MouseMaster = true; + S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0); + S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); + CheckMenuItem(GUI.hMenu, IDM_MOUSE_TOGGLE, MFS_CHECKED); + break; + case SNES_MOUSE_SWAPPED: + Settings.MouseMaster = true; + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0); + CheckMenuItem(GUI.hMenu, IDM_MOUSE_SWAPPED, MFS_CHECKED); + break; + case SNES_SUPERSCOPE: + Settings.SuperScopeMaster = true; + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0); + CheckMenuItem(GUI.hMenu, IDM_SCOPE_TOGGLE, MFS_CHECKED); + break; + case SNES_MULTIPLAYER5: + Settings.MultiPlayer5Master = true; + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_MP5, 1, 2, 3, 4); + CheckMenuItem(GUI.hMenu, IDM_ENABLE_MULTITAP, MFS_CHECKED); + break; + case SNES_MULTIPLAYER8: + Settings.MultiPlayer5Master = true; + S9xSetController(0, CTL_MP5, 0, 1, 2, 3); + S9xSetController(1, CTL_MP5, 4, 5, 6, 7); + CheckMenuItem(GUI.hMenu, IDM_ENABLE_MULTITAP, MFS_CHECKED); + break; + case SNES_JUSTIFIER: + Settings.JustifierMaster = true; + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_JUSTIFIER, 0, 0, 0, 0); + CheckMenuItem(GUI.hMenu, IDM_JUSTIFIER, MFS_CHECKED); + break; + case SNES_JUSTIFIER_2: + Settings.JustifierMaster = true; + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0); + CheckMenuItem(GUI.hMenu, IDM_JUSTIFIERS, MFS_CHECKED); + break; + default: + case SNES_JOYPAD: + S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); + S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); + CheckMenuItem(GUI.hMenu, IDM_SNES_JOYPAD, MFS_CHECKED); + break; + } + + GUI.ControlForced = 0xff; +} + +static void CenterCursor() +{ + if(GUI.ControllerOption==SNES_MOUSE || GUI.ControllerOption==SNES_MOUSE_SWAPPED) + { + if(GUI.hWnd == GetActiveWindow() && !S9xMoviePlaying()) + { + POINT cur, middle; + RECT size; + + GetClientRect (GUI.hWnd, &size); + middle.x = (size.right - size.left) >> 1; + middle.y = (size.bottom - size.top) >> 1; + ClientToScreen (GUI.hWnd, &middle); + GetCursorPos (&cur); + int dX = middle.x-cur.x; + int dY = middle.y-cur.y; + if(dX || dY) + { + GUI.MouseX -= dX; + GUI.MouseY -= dY; + SetCursorPos (middle.x, middle.y); +// GUI.IgnoreNextMouseMove = true; + } + } + } +} + + +void S9xRestoreWindowTitle () +{ + TCHAR buf [100]; + sprintf (buf, TEXT(WINDOW_TITLE), VERSION); + SetWindowText (GUI.hWnd, buf); +} + +void S9xDisplayStateChange (const char *str, bool8 on) +{ + static char string [100]; + + sprintf (string, "%s %s", str, on ? "on" : "off"); + S9xSetInfoString (string); +} + +static void UpdateScale(RenderFilter & Scale, RenderFilter & NextScale) +{ + Scale = NextScale; +} + +static char InfoString [100]; +static uint32 prevPadReadFrame = (uint32)-1; +static bool skipNextFrameStop = false; + +int HandleKeyMessage(WPARAM wParam, LPARAM lParam) +{ + // update toggles + for (int J = 0; J < 5; J++) + { + extern bool S9xGetState (WORD KeyIdent); + if(Joypad[J].Enabled && (!S9xGetState(Joypad[J+8].Left))) // enabled and Togglify + { + SJoypad & p = ToggleJoypadStorage[J]; + if(wParam == Joypad[J].L) p.L = !p.L; + if(wParam == Joypad[J].R) p.R = !p.R; + if(wParam == Joypad[J].A) p.A = !p.A; + if(wParam == Joypad[J].B) p.B = !p.B; + if(wParam == Joypad[J].Y) p.Y = !p.Y; + if(wParam == Joypad[J].X) p.X = !p.X; + if(wParam == Joypad[J].Start) p.Start = !p.Start; + if(wParam == Joypad[J].Select) p.Select = !p.Select; + if(wParam == Joypad[J].Left) p.Left = !p.Left; + if(wParam == Joypad[J].Right) p.Right = !p.Right; + if(wParam == Joypad[J].Up) p.Up = !p.Up; + if(wParam == Joypad[J].Down) p.Down = !p.Down; +/// if(wParam == Joypad[J].Left_Down) p.Left_Down = !p.Left_Down; +/// if(wParam == Joypad[J].Left_Up) p.Left_Up = !p.Left_Up; +/// if(wParam == Joypad[J].Right_Down) p.Right_Down = !p.Right_Down; +/// if(wParam == Joypad[J].Right_Up) p.Right_Up = !p.Right_Up; + if(!Settings.UpAndDown) + { + if(p.Left && p.Right) + p.Left = p.Right = false; + if(p.Up && p.Down) + p.Up = p.Down = false; + } + } + if(Joypad[J].Enabled && (!S9xGetState(Joypad[J+8].Down))) // enabled and turbo-togglify (TurboTog) + { + SJoypad & p = TurboToggleJoypadStorage[J]; + if(wParam == Joypad[J].L) p.L = !p.L; + if(wParam == Joypad[J].R) p.R = !p.R; + if(wParam == Joypad[J].A) p.A = !p.A; + if(wParam == Joypad[J].B) p.B = !p.B; + if(wParam == Joypad[J].Y) p.Y = !p.Y; + if(wParam == Joypad[J].X) p.X = !p.X; + if(wParam == Joypad[J].Start) p.Start = !p.Start; + if(wParam == Joypad[J].Select) p.Select = !p.Select; +/// if(wParam == Joypad[J].Left) p.Left = !p.Left; +/// if(wParam == Joypad[J].Right) p.Right = !p.Right; +/// if(wParam == Joypad[J].Up) p.Up = !p.Up; +/// if(wParam == Joypad[J].Down) p.Down = !p.Down; +/// if(wParam == Joypad[J].Left_Down) p.Left_Down = !p.Left_Down; +/// if(wParam == Joypad[J].Left_Up) p.Left_Up = !p.Left_Up; +/// if(wParam == Joypad[J].Right_Down) p.Right_Down = !p.Right_Down; +/// if(wParam == Joypad[J].Right_Up) p.Right_Up = !p.Right_Up; +/* if(!Settings.UpAndDown) + { + if(p.Left && p.Right && ) + p.Left = p.Right = false; + if(p.Up && p.Down) + p.Up = p.Down = false; + }*/ + } + if(wParam == Joypad[J+8].Right) // clear all + { + { + SJoypad & p = ToggleJoypadStorage[J]; + p.L = false; + p.R = false; + p.A = false; + p.B = false; + p.Y = false; + p.X = false; + p.Start = false; + p.Select = false; + p.Left = false; + p.Right = false; + p.Up = false; + p.Down = false; + } + { + SJoypad & p = TurboToggleJoypadStorage[J]; + p.L = false; + p.R = false; + p.A = false; + p.B = false; + p.Y = false; + p.X = false; + p.Start = false; + p.Select = false; + p.Left = false; + p.Right = false; + p.Up = false; + p.Down = false; + } + } + } + + + bool hitHotKey = false; + + if(!(wParam == 0 || wParam == VK_ESCAPE)) // if it's the 'disabled' key, it's never pressed as a hotkey + { + int modifiers = 0; + if(GetAsyncKeyState(VK_MENU)) + modifiers |= CUSTKEY_ALT_MASK; + if(GetAsyncKeyState(VK_CONTROL)) + modifiers |= CUSTKEY_CTRL_MASK; + if(GetAsyncKeyState(VK_SHIFT)) + modifiers |= CUSTKEY_SHIFT_MASK; + + { + for(int i = 0 ; i < 10 ; i++) + { + if(wParam == CustomKeys.Save[i].key + && modifiers == CustomKeys.Save[i].modifiers) + { + FreezeUnfreeze (i, true); + hitHotKey = true; + } + if(wParam == CustomKeys.Load[i].key + && modifiers == CustomKeys.Load[i].modifiers) + { + FreezeUnfreeze (i, false); + hitHotKey = true; + } + } + + if(wParam == CustomKeys.SlotSave.key + && modifiers == CustomKeys.SlotSave.modifiers) + { + FreezeUnfreeze (GUI.CurrentSaveSlot, true); + hitHotKey = true; + } + if(wParam == CustomKeys.SlotLoad.key + && modifiers == CustomKeys.SlotLoad.modifiers) + { + FreezeUnfreeze (GUI.CurrentSaveSlot, false); + hitHotKey = true; + } + if(wParam == CustomKeys.SlotPlus.key + && modifiers == CustomKeys.SlotPlus.modifiers) + { + GUI.CurrentSaveSlot++; + if(GUI.CurrentSaveSlot > 9) + GUI.CurrentSaveSlot = 0; + + static char str [64]; + sprintf(str, FREEZE_INFO_SET_SLOT_N, GUI.CurrentSaveSlot); + S9xSetInfoString(str); + + hitHotKey = true; + } + if(wParam == CustomKeys.SlotMinus.key + && modifiers == CustomKeys.SlotMinus.modifiers) + { + GUI.CurrentSaveSlot--; + if(GUI.CurrentSaveSlot < 0) + GUI.CurrentSaveSlot = 9; + + static char str [64]; + sprintf(str, FREEZE_INFO_SET_SLOT_N, GUI.CurrentSaveSlot); + S9xSetInfoString(str); + + hitHotKey = true; + } + } + + + if(wParam == CustomKeys.FrameAdvance.key + && modifiers == CustomKeys.FrameAdvance.modifiers) + { + static DWORD lastTime = 0; + if((int)(timeGetTime() - lastTime) > 20) + { + lastTime = timeGetTime(); + if(Settings.Paused || GUI.FASkipsNonInput) + { + prevPadReadFrame = (uint32)-1; + Settings.Paused = false; + S9xMouseOn(); + GUI.IgnoreNextMouseMove = true; + Settings.Paused = true; + + Settings.FrameAdvance = true; + GUI.FrameAdvanceJustPressed = 2; + // kick the main thread out of GetMessage (just in case) + SendMessage(GUI.hWnd, WM_NULL, 0, 0); + } + else + { + Settings.Paused = true; + } + + CenterCursor(); + } + + hitHotKey = true; + } + if(wParam == CustomKeys.FrameCount.key + && modifiers == CustomKeys.FrameCount.modifiers) + { + if (S9xMovieActive() +#ifdef NETPLAY_SUPPORT + || Settings.NetPlay +#endif + ) + S9xMovieToggleFrameDisplay (); + else + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_ERR_NOFRAMETOGGLE); + hitHotKey = true; + } + if(wParam == CustomKeys.Pause.key + && modifiers == CustomKeys.Pause.modifiers) + { + Settings.Paused = Settings.Paused ^ true; + Settings.FrameAdvance = false; + GUI.FrameAdvanceJustPressed = 0; + CenterCursor(); + if(!Settings.Paused) + S9xMouseOn(); + hitHotKey = true; + } + if(wParam == CustomKeys.ReadOnly.key + && modifiers == CustomKeys.ReadOnly.modifiers) + { + if (S9xMovieActive()) + S9xMovieToggleRecState(); + else + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, MOVIE_ERR_NOREADONLYTOGGLE); + hitHotKey = true; + } + if(wParam == CustomKeys.FastForward.key + && modifiers == CustomKeys.FastForward.modifiers) + { + if(Settings.SPC7110RTC) + return 1; + if (GUI.TurboModeToggle) + { + Settings.TurboMode ^= TRUE; + if (Settings.TurboMode) + S9xMessage (S9X_INFO, S9X_TURBO_MODE, + WINPROC_TURBOMODE_ON); + else + S9xMessage (S9X_INFO, S9X_TURBO_MODE, + WINPROC_TURBOMODE_OFF); + } + else + { + if(!Settings.TurboMode) + S9xMessage (S9X_INFO, S9X_TURBO_MODE, WINPROC_TURBOMODE_TEXT); + Settings.TurboMode = TRUE; + } + hitHotKey = true; + } + if(wParam == CustomKeys.ShowPressed.key + && modifiers == CustomKeys.ShowPressed.modifiers) + { + Settings.DisplayPressedKeys = Settings.DisplayPressedKeys?0:2; + + if(Settings.DisplayPressedKeys==2) + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, INPUT_INFO_DISPLAY_ENABLED); + else + S9xMessage(S9X_INFO, S9X_MOVIE_INFO, INPUT_INFO_DISPLAY_DISABLED); + + hitHotKey = true; + } + if(wParam == CustomKeys.SaveScreenShot.key + && modifiers == CustomKeys.SaveScreenShot.modifiers) + { + Settings.TakeScreenshot=true; + } + if(wParam == CustomKeys.ScopePause.key + && modifiers == CustomKeys.ScopePause.modifiers) + { + GUI.superscope_pause = 1; + hitHotKey = true; + } + if(wParam == CustomKeys.ScopeTurbo.key + && modifiers == CustomKeys.ScopeTurbo.modifiers) + { + GUI.superscope_turbo = 1; + hitHotKey = true; + } + if(wParam == CustomKeys.SkipDown.key + && modifiers == CustomKeys.SkipDown.modifiers) + { + if (Settings.SkipFrames <= 1) + Settings.SkipFrames = AUTO_FRAMERATE; + else + if (Settings.SkipFrames != AUTO_FRAMERATE) + Settings.SkipFrames--; + + if (Settings.SkipFrames == AUTO_FRAMERATE) + S9xSetInfoString (WINPROC_AUTOSKIP); + else + { + sprintf (InfoString, WINPROC_FRAMESKIP, + Settings.SkipFrames - 1); + S9xSetInfoString (InfoString); + } + hitHotKey = true; + } + if(wParam == CustomKeys.SkipUp.key + && modifiers == CustomKeys.SkipUp.modifiers) + { + if (Settings.SkipFrames == AUTO_FRAMERATE) + Settings.SkipFrames = 1; + else + if (Settings.SkipFrames < 10) + Settings.SkipFrames++; + + if (Settings.SkipFrames == AUTO_FRAMERATE) + S9xSetInfoString (WINPROC_AUTOSKIP); + else + { + sprintf (InfoString, WINPROC_FRAMESKIP, + Settings.SkipFrames - 1); + S9xSetInfoString (InfoString); + } + hitHotKey = true; + } + if(wParam == CustomKeys.SpeedDown.key + && modifiers == CustomKeys.SpeedDown.modifiers) + { + // Increase emulated frame time + int i; + for(i=1; FrameTimings[i]compressed) && ext->extension && strlen(ext->extension) < 256) + { + if(!first) + strcat(lpfilterptr, ";*."); + else + { + strcat(lpfilterptr, "*."); + first = false; + } + strcat(lpfilterptr, ext->extension); + extlen_approx += strlen(ext->extension) + 3; + } + ext = ext->next; + } + lpfilterptr += strlen(lpfilterptr); + } + else + strcat0(lpfilterptr, "*.smc"); + strcat0(lpfilterptr, "\0"); + } + strcat0(lpfilterptr, FILE_INFO_ANY_FILE_TYPE); + strcat0(lpfilterptr, "\0*.*\0\0"); + + ZeroMemory((LPVOID)&ofn, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = GUI.hWnd; + ofn.lpstrFilter = lpfilter; + ofn.lpstrFile = szFileName; + ofn.lpstrDefExt = "smc"; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; + ofn.lpstrInitialDir = szPathName; + if(GetOpenFileName(&ofn)) + { + strncpy(filename, ofn.lpstrFile, _MAX_PATH); + return true; + } + return false; + } +} + + +char multiRomA [MAX_PATH] = {0}; // lazy, should put in sGUI and add init to {0} somewhere +char multiRomB [MAX_PATH] = {0}; + + +static bool startingMovie = false; + +HWND cheatSearchHWND = NULL; + + +#define MOVIE_LOCKED_SETTING if(S9xMovieActive()) {MessageBox(GUI.hWnd,TEXT("That setting is locked while a movie is active."),TEXT("Notice"),MB_OK|MB_ICONEXCLAMATION); break;} + +LRESULT CALLBACK WinProc( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + unsigned int i; + //bool showFPS; +#ifdef NETPLAY_SUPPORT + char hostname [100]; +#endif + switch (uMsg) + { + case WM_CREATE: + g_hInst = ((LPCREATESTRUCT)lParam)->hInstance; +#ifndef MK_APU + DeleteMenu(GUI.hMenu,IDM_CATCH_UP_SOUND,MF_BYCOMMAND); +#endif + return 0; + case WM_KEYDOWN: + if(GUI.BackgroundKeyHotkeys) + break; + case WM_CUSTKEYDOWN: + case WM_SYSKEYDOWN: + { + if(!HandleKeyMessage(wParam,lParam)) + return 0; + break; + } + + case WM_KEYUP: + case WM_CUSTKEYUP: + { + int modifiers = 0; + if(GetAsyncKeyState(VK_MENU)) + modifiers |= CUSTKEY_ALT_MASK; + if(GetAsyncKeyState(VK_CONTROL)) + modifiers |= CUSTKEY_CTRL_MASK; + if(GetAsyncKeyState(VK_SHIFT)) + modifiers |= CUSTKEY_SHIFT_MASK; + + if(wParam == CustomKeys.FastForward.key + && modifiers == CustomKeys.FastForward.modifiers) + { + if (!GUI.TurboModeToggle) + Settings.TurboMode = FALSE; + } + if(wParam == CustomKeys.ScopePause.key + && modifiers == CustomKeys.ScopePause.modifiers) + { + GUI.superscope_pause = 0; + } + } + break; + case WM_COMMAND: + switch (wParam & 0xffff) + { + case ID_FILE_WRITE_AVI: + { + RestoreGUIDisplay (); //exit DirectX + OPENFILENAME ofn; + char szFileName[MAX_PATH]; + char szPathName[MAX_PATH]; + SetCurrentDirectory(S9xGetDirectory(DEFAULT_DIR)); + _fullpath(szPathName, GUI.MovieDir, MAX_PATH); + mkdir(szPathName); + + szFileName[0] = '\0'; + + ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) ); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = GUI.hWnd; + ofn.lpstrFilter = FILE_INFO_AVI_FILE_TYPE "\0*.avi\0" FILE_INFO_ANY_FILE_TYPE "\0*.*\0\0"; + ofn.lpstrFile = szFileName; + ofn.lpstrDefExt = "avi"; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; + ofn.lpstrInitialDir = szPathName; + if(GetSaveFileName( &ofn )) + { + DoAVIOpen(szFileName); + } + RestoreSNESDisplay ();// re-enter after dialog + } + break; + case ID_FILE_STOP_AVI: + DoAVIClose(0); + ReInitSound(); // reenable sound output + break; + case ID_FILE_MOVIE_STOP: + S9xMovieStop(FALSE); + break; + case ID_FILE_MOVIE_PLAY: + { + RestoreGUIDisplay (); //exit DirectX + OpenMovieParams op; + memset(&op, 0, sizeof(op)); + if(DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_OPENMOVIE), hWnd, DlgOpenMovie, (LPARAM)&op) && + op.Path[0]!='\0') + { + int err=S9xMovieOpen (op.Path, op.ReadOnly); + if(err!=SUCCESS) + { + _TCHAR* err_string=TEXT(MOVIE_ERR_COULD_NOT_OPEN); + switch(err) + { + case FILE_NOT_FOUND: + err_string=TEXT(MOVIE_ERR_NOT_FOUND); + break; + case WRONG_FORMAT: + err_string=TEXT(MOVIE_ERR_WRONG_FORMAT); + break; + case WRONG_VERSION: + err_string=TEXT(MOVIE_ERR_WRONG_VERSION); + break; + } + MessageBox( hWnd, err_string, TEXT(SNES9X_INFO), MB_OK); + } + } + RestoreSNESDisplay ();// re-enter after dialog + } + break; + case ID_FILE_MOVIE_RECORD: + { + RestoreGUIDisplay (); //exit DirectX + OpenMovieParams op; + memset(&op, 0, sizeof(op)); + if(DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_CREATEMOVIE), hWnd, DlgCreateMovie, (LPARAM)&op) && + op.Path[0]!='\0') + { + if(Settings.ShutdownMaster) + { + static bool seenItOnce = false; + if(!seenItOnce) + { + seenItOnce = true; + MessageBox(hWnd, MOVIE_SHUTDOWNMASTER_WARNING, SNES9X_WARN, MB_OK); + } + } + + startingMovie = true; + int err=S9xMovieCreate (op.Path, op.ControllersMask, op.Opts, op.Metadata, wcslen(op.Metadata)); + startingMovie = false; + if(err!=SUCCESS) + { + _TCHAR* err_string=TEXT(MOVIE_ERR_COULD_NOT_OPEN); + switch(err) + { + case FILE_NOT_FOUND: + err_string=TEXT(MOVIE_ERR_NOT_FOUND); + break; + case WRONG_FORMAT: + err_string=TEXT(MOVIE_ERR_WRONG_FORMAT); + break; + case WRONG_VERSION: + err_string=TEXT(MOVIE_ERR_WRONG_VERSION); + break; + } + MessageBox( hWnd, err_string, TEXT(SNES9X_INFO), MB_OK); + } + } + RestoreSNESDisplay ();// re-enter after dialog + } + break; + case IDM_SNES_JOYPAD: + MOVIE_LOCKED_SETTING + GUI.ControllerOption = SNES_JOYPAD; + ChangeInputDevice(); + break; + case IDM_ENABLE_MULTITAP: + MOVIE_LOCKED_SETTING + GUI.ControllerOption = SNES_MULTIPLAYER5; + ChangeInputDevice(); + break; + case IDM_SCOPE_TOGGLE: + MOVIE_LOCKED_SETTING + GUI.ControllerOption = SNES_SUPERSCOPE; + ChangeInputDevice(); + break; + case IDM_JUSTIFIER: + MOVIE_LOCKED_SETTING + GUI.ControllerOption = SNES_JUSTIFIER; + ChangeInputDevice(); + break; + case IDM_MOUSE_TOGGLE: + MOVIE_LOCKED_SETTING + GUI.ControllerOption = SNES_MOUSE; + ChangeInputDevice(); + break; + case IDM_MOUSE_SWAPPED: + MOVIE_LOCKED_SETTING + GUI.ControllerOption = SNES_MOUSE_SWAPPED; + ChangeInputDevice(); + break; + case IDM_MULTITAP8: + MOVIE_LOCKED_SETTING + GUI.ControllerOption = SNES_MULTIPLAYER8; + ChangeInputDevice(); + break; + case IDM_JUSTIFIERS: + MOVIE_LOCKED_SETTING + GUI.ControllerOption = SNES_JUSTIFIER_2; + ChangeInputDevice(); + break; + + //start turbo + case ID_TURBO_R: + GUI.TurboMask^=TURBO_R_MASK; + if(GUI.TurboMask&TURBO_R_MASK) + S9xSetInfoString (WINPROC_TURBO_R_ON); + else S9xSetInfoString (WINPROC_TURBO_R_OFF); + break; + case ID_TURBO_L: + GUI.TurboMask^=TURBO_L_MASK; + if(GUI.TurboMask&TURBO_L_MASK) + S9xSetInfoString (WINPROC_TURBO_L_ON); + else S9xSetInfoString (WINPROC_TURBO_L_OFF); + break; + case ID_TURBO_A: + GUI.TurboMask^=TURBO_A_MASK; + if(GUI.TurboMask&TURBO_A_MASK) + S9xSetInfoString (WINPROC_TURBO_A_ON); + else S9xSetInfoString (WINPROC_TURBO_A_OFF); + break; + case ID_TURBO_B: + GUI.TurboMask^=TURBO_B_MASK; + if(GUI.TurboMask&TURBO_B_MASK) + S9xSetInfoString (WINPROC_TURBO_B_ON); + else S9xSetInfoString (WINPROC_TURBO_B_OFF); + break; + case ID_TURBO_Y: + GUI.TurboMask^=TURBO_Y_MASK; + if(GUI.TurboMask&TURBO_Y_MASK) + S9xSetInfoString (WINPROC_TURBO_Y_ON); + else S9xSetInfoString (WINPROC_TURBO_Y_OFF); + break; + case ID_TURBO_X: + GUI.TurboMask^=TURBO_X_MASK; + if(GUI.TurboMask&TURBO_X_MASK) + S9xSetInfoString (WINPROC_TURBO_X_ON); + else S9xSetInfoString (WINPROC_TURBO_X_OFF); + break; + case ID_TURBO_START: + GUI.TurboMask^=TURBO_STA_MASK; + if(GUI.TurboMask&TURBO_STA_MASK) + S9xSetInfoString (WINPROC_TURBO_START_ON); + else S9xSetInfoString (WINPROC_TURBO_START_OFF); + break; + case ID_TURBO_SELECT: + GUI.TurboMask^=TURBO_SEL_MASK; + if(GUI.TurboMask&TURBO_SEL_MASK) + S9xSetInfoString (WINPROC_TURBO_SEL_ON); + else S9xSetInfoString (WINPROC_TURBO_SEL_OFF); + break; + case ID_TURBO_LEFT: + GUI.TurboMask^=TURBO_LEFT_MASK; + if(GUI.TurboMask&TURBO_LEFT_MASK) + S9xSetInfoString (WINPROC_TURBO_LEFT_ON); + else S9xSetInfoString (WINPROC_TURBO_LEFT_OFF); + break; + case ID_TURBO_UP: + GUI.TurboMask^=TURBO_UP_MASK; + if(GUI.TurboMask&TURBO_UP_MASK) + S9xSetInfoString (WINPROC_TURBO_UP_ON); + else S9xSetInfoString (WINPROC_TURBO_UP_OFF); + break; + case ID_TURBO_RIGHT: + GUI.TurboMask^=TURBO_RIGHT_MASK; + if(GUI.TurboMask&TURBO_RIGHT_MASK) + S9xSetInfoString (WINPROC_TURBO_RIGHT_ON); + else S9xSetInfoString (WINPROC_TURBO_RIGHT_OFF); + break; + case ID_TURBO_DOWN: + GUI.TurboMask^=TURBO_DOWN_MASK; + if(GUI.TurboMask&TURBO_DOWN_MASK) + S9xSetInfoString (WINPROC_TURBO_DOWN_ON); + else S9xSetInfoString (WINPROC_TURBO_DOWN_OFF); + break; + //end turbo + case ID_OPTIONS_DISPLAY: + { + int old_scale = GUI.NextScale; + + RestoreGUIDisplay (); + + if(GUI.FullScreen) + ToggleFullScreen(); + DialogBox(g_hInst, MAKEINTRESOURCE(IDD_NEWDISPLAY), hWnd, DlgFunky); + + SwitchToGDI(); + + if (GUI.NextScale != old_scale) + { + UpdateScale((RenderFilter &)old_scale, GUI.NextScale); + } + GUI.ScaleHiRes = GUI.NextScaleHiRes; + RestoreSNESDisplay (); + + S9xGraphicsDeinit(); + S9xSetWinPixelFormat (); + S9xInitUpdate(); + S9xGraphicsInit(); + + IPPU.RenderThisFrame = false; + + + RECT rect; + GetClientRect (GUI.hWnd, &rect); + InvalidateRect (GUI.hWnd, &rect, true); + break; + } + + case ID_OPTIONS_JOYPAD: + RestoreGUIDisplay (); + DialogBox(g_hInst, MAKEINTRESOURCE(IDD_INPUTCONFIG), hWnd, DlgInputConfig); + RestoreSNESDisplay (); + break; + + case ID_OPTIONS_KEYCUSTOM: + RestoreGUIDisplay (); + DialogBox(g_hInst, MAKEINTRESOURCE(IDD_KEYCUSTOM), hWnd, DlgHotkeyConfig); + RestoreSNESDisplay (); + break; + + case ID_FILE_LOADMULTICART: + { +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlay && !Settings.NetPlayServer) + { + S9xMessage (S9X_INFO, S9X_NETPLAY_NOT_SERVER, WINPROC_DISCONNECT); + break; + } +#endif + RestoreGUIDisplay (); + + const bool ok = (1 <= DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_MULTICART), GUI.hWnd, DlgMultiROMProc, (LPARAM)NULL)); + + if(ok) + { + if (!Settings.StopEmulation) + { + Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR)); + S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + } + Settings.StopEmulation = !LoadMultiROM (multiRomA, multiRomB); + if (!Settings.StopEmulation) + { + bool8 loadedSRAM = Memory.LoadSRAM (S9xGetFilename (".srm", SRAM_DIR)); + if(!loadedSRAM) // help migration from earlier Snes9x versions by checking ROM directory for savestates + Memory.LoadSRAM (S9xGetFilename (".srm", ROMFILENAME_DIR)); + S9xLoadCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); +// S9xAddToRecentGames (multiRomA, multiRomB); + CheckDirectoryIsWritable (S9xGetFilename (".---", SNAPSHOT_DIR)); + CheckMenuStates (); +#ifdef NETPLAY_SUPPORT + // still valid with multicart ??? + if (NPServer.SendROMImageOnConnect) + S9xNPServerQueueSendingROMImage (); + else + S9xNPServerQueueSendingLoadROMRequest (Memory.ROMName); +#endif + } + + if(GUI.ControllerOption == SNES_SUPERSCOPE) + SetCursor (GUI.GunSight); + else + { + SetCursor (GUI.Arrow); + GUI.CursorTimer = 60; + } + Settings.Paused = false; + } + + RestoreSNESDisplay (); + GUI.ScreenCleared = true; + } + break; + + case ID_FILE_LOAD_GAME: + { + char filename [_MAX_PATH]; + +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlay && !Settings.NetPlayServer) + { + S9xMessage (S9X_INFO, S9X_NETPLAY_NOT_SERVER, + WINPROC_DISCONNECT); + break; + } +#endif + RestoreGUIDisplay (); + + if(DoOpenRomDialog(filename)) + { + if (!Settings.StopEmulation) + { + Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR)); + S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + } + Settings.StopEmulation = !LoadROM (filename); + if (!Settings.StopEmulation) + { + bool8 loadedSRAM = Memory.LoadSRAM (S9xGetFilename (".srm", SRAM_DIR)); + if(!loadedSRAM) // help migration from earlier Snes9x versions by checking ROM directory for savestates + Memory.LoadSRAM (S9xGetFilename (".srm", ROMFILENAME_DIR)); + S9xLoadCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + S9xAddToRecentGames (filename); + CheckDirectoryIsWritable (S9xGetFilename (".---", SNAPSHOT_DIR)); + CheckMenuStates (); +#ifdef NETPLAY_SUPPORT + if (NPServer.SendROMImageOnConnect) + S9xNPServerQueueSendingROMImage (); + else + S9xNPServerQueueSendingLoadROMRequest (Memory.ROMName); +#endif + } + + if(GUI.ControllerOption == SNES_SUPERSCOPE) + SetCursor (GUI.GunSight); + else + { + SetCursor (GUI.Arrow); + GUI.CursorTimer = 60; + } + Settings.Paused = false; + } + + RestoreSNESDisplay (); + GUI.ScreenCleared = true; + } + break; + + case ID_FILE_EXIT: + S9xSetPause (PAUSE_EXIT); + PostMessage (hWnd, WM_DESTROY, 0, 0); + break; + + case ID_WINDOW_HIDEMENUBAR: + if( GetMenu( GUI.hWnd) == NULL) + SetMenu( GUI.hWnd, GUI.hMenu); + else + SetMenu( GUI.hWnd, NULL); + GUI.ScreenCleared = true; + break; + + case ID_LANGUAGE_ENGLISH: + GUI.Language = 0; + + SetMenu( GUI.hWnd, LoadMenu( GUI.hInstance, MAKEINTRESOURCE( Languages[ GUI.Language].idMenu))); + DestroyMenu( GUI.hMenu); + GUI.hMenu = GetMenu( GUI.hWnd); + break; + case ID_LANGUAGE_NEDERLANDS: + GUI.Language = 1; + + SetMenu( GUI.hWnd, LoadMenu( GUI.hInstance, MAKEINTRESOURCE( Languages[ GUI.Language].idMenu))); + DestroyMenu( GUI.hMenu); + GUI.hMenu = GetMenu( GUI.hWnd); + break; +#ifdef NETPLAY_SUPPORT + case ID_NETPLAY_SERVER: + S9xRestoreWindowTitle (); + EnableServer (!Settings.NetPlayServer); + if(Settings.NetPlayServer) + { + char localhostmsg [512]; + // FIXME: need winsock2.h for this, don't know how to include it + //struct addrinfo *aiList = NULL; + //if(getaddrinfo("localhost", Settings.Port, NULL, &aiList) == 0) + //{ + // sprintf(localhostmsg, "Your server address is: %s", aiList->ai_canonname); + // MessageBox(GUI.hWnd,localhostmsg,"Note",MB_OK); + //} + //else + { + char localhostname [256]; + gethostname(localhostname,256); + sprintf(localhostmsg, "Your host name is: %s\nYour port number is: %d", localhostname, Settings.Port); + MessageBox(GUI.hWnd,localhostmsg,"Note",MB_OK); + } + } + break; + case ID_NETPLAY_CONNECT: + RestoreGUIDisplay (); + if(1<=DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_NETCONNECT), hWnd, DlgNetConnect,(LPARAM)&hostname)) + + { + + + S9xSetPause (PAUSE_NETPLAY_CONNECT); + + if (!S9xNPConnectToServer (hostname, Settings.Port, + Memory.ROMName)) + { + S9xClearPause (PAUSE_NETPLAY_CONNECT); + } + } + + RestoreSNESDisplay (); + break; + case ID_NETPLAY_DISCONNECT: + if (Settings.NetPlay) + { + Settings.NetPlay = FALSE; + S9xNPDisconnect (); + } + if (Settings.NetPlayServer) + { + Settings.NetPlayServer = FALSE; + S9xNPStopServer (); + } + break; + case ID_NETPLAY_OPTIONS: + { + bool8 old_netplay_server = Settings.NetPlayServer; + RestoreGUIDisplay (); + if(1<=DialogBox(g_hInst, MAKEINTRESOURCE(IDD_NPOPTIONS), hWnd, DlgNPOptions)) + { + if (old_netplay_server != Settings.NetPlayServer) + { + Settings.NetPlayServer = old_netplay_server; + S9xRestoreWindowTitle (); + EnableServer (!Settings.NetPlayServer); + } + } + RestoreSNESDisplay (); + break; + } + case ID_NETPLAY_SYNC: + S9xNPServerQueueSyncAll (); + break; + case ID_NETPLAY_ROM: + if (NPServer.SyncByReset) + { + if (MessageBox (GUI.hWnd, TEXT(WINPROC_NET_RESTART), TEXT(SNES9X_WARN), + MB_OKCANCEL | MB_ICONWARNING) == IDCANCEL) + break; + } + S9xNPServerQueueSendingROMImage (); + break; + case ID_NETPLAY_SEND_ROM_ON_CONNECT: + NPServer.SendROMImageOnConnect ^= TRUE; + break; + case ID_NETPLAY_SYNC_BY_RESET: + NPServer.SyncByReset ^= TRUE; + break; +#endif + case ID_SOUND_8000HZ: + case ID_SOUND_11025HZ: + case ID_SOUND_16000HZ: + case ID_SOUND_22050HZ: + case ID_SOUND_30000HZ: + case ID_SOUND_35000HZ: + case ID_SOUND_44100HZ: + case ID_SOUND_48000HZ: + case ID_SOUND_32000HZ: + for( i = 0; i < COUNT(SoundRates); i ++) + if (SoundRates[i].ident == (int) wParam) + { + Settings.SoundPlaybackRate = SoundRates [i].rate; + GUI.Mute = false; + ReInitSound(); + break; + } + break; + + case ID_SOUND_16MS: + GUI.SoundBufferSize = 16; + ReInitSound(); + break; + case ID_SOUND_32MS: + GUI.SoundBufferSize = 32; + ReInitSound(); + break; + case ID_SOUND_48MS: + GUI.SoundBufferSize = 48; + ReInitSound(); + break; + case ID_SOUND_64MS: + GUI.SoundBufferSize = 64; + ReInitSound(); + break; + case ID_SOUND_80MS: + GUI.SoundBufferSize = 80; + ReInitSound(); + break; + case ID_SOUND_96MS: + GUI.SoundBufferSize = 96; + ReInitSound(); + break; + case ID_SOUND_112MS: + GUI.SoundBufferSize = 112; + ReInitSound(); + break; + case ID_SOUND_128MS: + GUI.SoundBufferSize = 128; + ReInitSound(); + break; + case ID_SOUND_144MS: + GUI.SoundBufferSize = 144; + ReInitSound(); + break; + case ID_SOUND_160MS: + GUI.SoundBufferSize = 160; + ReInitSound(); + break; + case ID_SOUND_176MS: + GUI.SoundBufferSize = 176; + ReInitSound(); + break; + case ID_SOUND_194MS: + GUI.SoundBufferSize = 194; + ReInitSound(); + break; + case ID_SOUND_210MS: + GUI.SoundBufferSize = 210; + ReInitSound(); + break; + + + case ID_CHANNELS_CHANNEL1: S9xToggleSoundChannel(0); break; + case ID_CHANNELS_CHANNEL2: S9xToggleSoundChannel(1); break; + case ID_CHANNELS_CHANNEL3: S9xToggleSoundChannel(2); break; + case ID_CHANNELS_CHANNEL4: S9xToggleSoundChannel(3); break; + case ID_CHANNELS_CHANNEL5: S9xToggleSoundChannel(4); break; + case ID_CHANNELS_CHANNEL6: S9xToggleSoundChannel(5); break; + case ID_CHANNELS_CHANNEL7: S9xToggleSoundChannel(6); break; + case ID_CHANNELS_CHANNEL8: S9xToggleSoundChannel(7); break; + case ID_CHANNELS_ENABLEALL: S9xToggleSoundChannel(8); break; + + case ID_SOUND_NOSOUND: + S9xSetSoundMute(!GUI.Mute); + GUI.Mute = !GUI.Mute; + break; + + case ID_SOUND_STEREO: + Settings.Stereo = !Settings.Stereo; + ReInitSound(); + break; + case ID_SOUND_REVERSE_STEREO: + Settings.ReverseStereo = !Settings.ReverseStereo; + break; + case ID_SOUND_16BIT: + Settings.SixteenBitSound = !Settings.SixteenBitSound; + ReInitSound(); + break; + case ID_SOUND_SYNC: + Settings.SoundSync = !Settings.SoundSync; + S9xDisplayStateChange (WINPROC_SYNC_SND, Settings.SoundSync); + break; + case ID_SOUND_OPTIONS: + { + RestoreGUIDisplay (); + if(1<=DialogBoxParam(g_hInst,MAKEINTRESOURCE(IDD_SOUND_OPTS),hWnd,DlgSoundConf, (LPARAM)&Settings)) + { + ReInitSound(); + } + RestoreSNESDisplay (); + break; + } + case ID_WINDOW_FULLSCREEN: + ToggleFullScreen (); + break; + case ID_WINDOW_STRETCH: { + GUI.Stretch = !GUI.Stretch; + if(!GUI.Stretch != !GUI.BilinearFilter) { + GUI.BilinearFilter = !GUI.BilinearFilter; + RestoreSNESDisplay (); + } + RECT rect; + GetClientRect (GUI.hWnd, &rect); + InvalidateRect (GUI.hWnd, &rect, true); + } break; + case ID_WINDOW_ASPECTRATIO: { + GUI.AspectRatio = !GUI.AspectRatio; + RECT rect; + GetClientRect (GUI.hWnd, &rect); + InvalidateRect (GUI.hWnd, &rect, true); + } break; + case ID_WINDOW_VIDMEM: { + GUI.BilinearFilter = !GUI.BilinearFilter; + RestoreSNESDisplay (); + RECT rect; + GetClientRect (GUI.hWnd, &rect); + InvalidateRect (GUI.hWnd, &rect, true); + } break; + case ID_SAVESCREENSHOT: + Settings.TakeScreenshot=true; + break; + case ID_FILE_SAVE_SRAM_DATA: { + bool8 success = Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR)); + if(!success) + S9xMessage(S9X_ERROR, S9X_FREEZE_FILE_INFO, SRM_SAVE_FAILED); + } break; + case ID_FILE_RESET: +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlayServer) + { + S9xNPReset (); + ReInitSound(); + } + else + if (!Settings.NetPlay) +#endif + { + S9xMovieUpdateOnReset (); + if(S9xMoviePlaying()) + S9xMovieStop (TRUE); + S9xSoftReset (); + ReInitSound(); + } + if(!S9xMovieRecording()) + Settings.Paused = false; + break; + case ID_FILE_PAUSE: + Settings.Paused = !Settings.Paused; + Settings.FrameAdvance = false; + GUI.FrameAdvanceJustPressed = 0; + break; + case ID_FILE_LOAD1: + FreezeUnfreeze (0, FALSE); + break; + case ID_FILE_LOAD2: + FreezeUnfreeze (1, FALSE); + break; + case ID_FILE_LOAD3: + FreezeUnfreeze (2, FALSE); + break; + case ID_FILE_LOAD4: + FreezeUnfreeze (3, FALSE); + break; + case ID_FILE_LOAD5: + FreezeUnfreeze (4, FALSE); + break; + case ID_FILE_LOAD6: + FreezeUnfreeze (5, FALSE); + break; + case ID_FILE_LOAD7: + FreezeUnfreeze (6, FALSE); + break; + case ID_FILE_LOAD8: + FreezeUnfreeze (7, FALSE); + break; + case ID_FILE_LOAD9: + FreezeUnfreeze (8, FALSE); + break; + case ID_FILE_SAVE1: + FreezeUnfreeze (0, TRUE); + break; + case ID_FILE_SAVE2: + FreezeUnfreeze (1, TRUE); + break; + case ID_FILE_SAVE3: + FreezeUnfreeze (2, TRUE); + break; + case ID_FILE_SAVE4: + FreezeUnfreeze (3, TRUE); + break; + case ID_FILE_SAVE5: + FreezeUnfreeze (4, TRUE); + break; + case ID_FILE_SAVE6: + FreezeUnfreeze (5, TRUE); + break; + case ID_FILE_SAVE7: + FreezeUnfreeze (6, TRUE); + break; + case ID_FILE_SAVE8: + FreezeUnfreeze (7, TRUE); + break; + case ID_FILE_SAVE9: + FreezeUnfreeze (8, TRUE); + break; + case ID_CHEAT_ENTER: + RestoreGUIDisplay (); + S9xRemoveCheats (); + DialogBox(g_hInst, MAKEINTRESOURCE(IDD_CHEATER), hWnd, DlgCheater); + S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + S9xApplyCheats (); + RestoreSNESDisplay (); + break; + case ID_CHEAT_SEARCH: + RestoreGUIDisplay (); + if(!cheatSearchHWND) // create and show non-modal cheat search window + { + cheatSearchHWND = CreateDialog(g_hInst, MAKEINTRESOURCE(IDD_CHEAT_SEARCH), hWnd, DlgCheatSearch); // non-modal/modeless + ShowWindow(cheatSearchHWND, SW_SHOW); + } + else // already open so just reactivate the window + { + SetActiveWindow(cheatSearchHWND); + } + RestoreSNESDisplay (); + break; + case ID_CHEAT_SEARCH_MODAL: + RestoreGUIDisplay (); + DialogBox(g_hInst, MAKEINTRESOURCE(IDD_CHEAT_SEARCH), hWnd, DlgCheatSearch); // modal + S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + RestoreSNESDisplay (); + break; + case ID_CHEAT_APPLY: + Settings.ApplyCheats = !Settings.ApplyCheats; + if (!Settings.ApplyCheats){ + S9xRemoveCheats (); + S9xMessage (S9X_INFO, S9X_GAME_GENIE_CODE_ERROR, CHEATS_INFO_DISABLED); + }else{ + S9xApplyCheats (); + bool on = false; + extern struct SCheatData Cheat; + for (uint32 i = 0; i < Cheat.num_cheats && !on; i++) + if (Cheat.c [i].enabled) + on = true; + S9xMessage (S9X_INFO, S9X_GAME_GENIE_CODE_ERROR, on ? CHEATS_INFO_ENABLED : CHEATS_INFO_ENABLED_NONE); + } + break; + case ID_OPTIONS_SETTINGS: + RestoreGUIDisplay (); + DialogBox(g_hInst, MAKEINTRESOURCE(IDD_EMU_SETTINGS), hWnd, DlgEmulatorProc); + RestoreSNESDisplay (); + break; + case ID_HELP_ABOUT: + RestoreGUIDisplay (); + DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, DlgAboutProc); + RestoreSNESDisplay (); + break; +#ifdef DEBUGGER + case ID_DEBUG_TRACE: + { + Trace (); + break; + } + case ID_DEBUG_FRAME_ADVANCE: + CPU.Flags |= FRAME_ADVANCE_FLAG; + ICPU.FrameAdvanceCount = 1; + Settings.Paused = FALSE; + break; +#endif + case IDM_ROM_INFO: + RestoreGUIDisplay (); + DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ROM_INFO), hWnd, DlgInfoProc); + RestoreSNESDisplay (); + break; + default: + if ((wParam & 0xffff) >= 0xFF00) + { + int i = (wParam & 0xffff) - 0xFF00; + int j = 0; + { + while (j < MAX_RECENT_GAMES_LIST_SIZE && j != i) + j++; + if (i == j) + { +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlay && !Settings.NetPlayServer) + { + S9xMessage (S9X_INFO, S9X_NETPLAY_NOT_SERVER, + WINPROC_DISCONNECT); + break; + } +#endif + if (!Settings.StopEmulation) + { + Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR)); + S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + } + Settings.StopEmulation = !LoadROM (GUI.RecentGames [i]); + if (!Settings.StopEmulation) + { + bool8 loadedSRAM = Memory.LoadSRAM (S9xGetFilename (".srm", SRAM_DIR)); + if(!loadedSRAM) // help migration from earlier Snes9x versions by checking ROM directory for savestates + Memory.LoadSRAM (S9xGetFilename (".srm", ROMFILENAME_DIR)); + S9xLoadCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + S9xAddToRecentGames (GUI.RecentGames [i]); + CheckDirectoryIsWritable (S9xGetFilename (".---", SNAPSHOT_DIR)); + CheckMenuStates (); +#ifdef NETPLAY_SUPPORT + if (NPServer.SendROMImageOnConnect) + S9xNPServerQueueSendingROMImage (); + else + S9xNPServerQueueSendingLoadROMRequest (Memory.ROMName); +#endif + Settings.Paused = false; + } + else + { + sprintf (String, ERR_ROM_NOT_FOUND, GUI.RecentGames [i]); + S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String); + S9xRemoveFromRecentGames(i); + } + } + } + } + break; + } + break; + + case WM_EXITMENULOOP: + UpdateWindow(GUI.hWnd); + //UpdateBackBuffer(); + S9xClearPause (PAUSE_MENU); + break; + + case WM_ENTERMENULOOP: + S9xSetPause (PAUSE_MENU); + CheckMenuStates (); + + SwitchToGDI(); + DrawMenuBar( GUI.hWnd); + break; + + case WM_CLOSE: { + bool maximized = GUI.window_maximized; + ShowWindow(GUI.hWnd, SW_RESTORE); + GUI.window_maximized = maximized; + if (!GUI.FullScreen && !GUI.EmulatedFullscreen) + GetWindowRect (GUI.hWnd, &GUI.window_size); + } break; + + case WM_DESTROY: + Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR)); + GUI.hWnd = NULL; + PostQuitMessage (0); + return (0); + case WM_PAINT: + { + PAINTSTRUCT paint; + + BeginPaint (GUI.hWnd, &paint); + + // refresh screen + WinRefreshDisplay(); + + EndPaint (GUI.hWnd, &paint); + break; + } + case WM_SYSCOMMAND: + { + // Prevent screen saver from starting if not paused + //kode54 says add the ! to fix the screensaver pevention. + if (!(Settings.ForcedPause || Settings.StopEmulation || + (Settings.Paused && !Settings.FrameAdvance)) && + (wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER)) + return (0); + break; + } + case WM_ACTIVATE: + if (LOWORD(wParam) == WA_INACTIVE) + { + if(GUI.InactivePause) + { + S9xSetPause (PAUSE_INACTIVE_WINDOW); + } + } + else + { + Settings.TurboMode = false; +/// if(GUI.InactivePause) + { + S9xClearPause (PAUSE_INACTIVE_WINDOW); + } + IPPU.ColorsChanged = TRUE; + } + break; + case WM_QUERYNEWPALETTE: + // if (!GUI.FullScreen && GUI.ScreenDepth == 8) + // RealizePalette (GUI.WindowDC); + break; + case WM_SIZE: + if (wParam == SIZE_MAXIMIZED) + { + GUI.window_maximized = true; + } + if (wParam == SIZE_RESTORED) + { + GUI.window_maximized = false; + if(GUI.InactivePause) + { + S9xClearPause (PAUSE_WINDOW_ICONISED); + } + } + if (wParam == SIZE_MINIMIZED || wParam == SIZE_MAXHIDE) + { +/// if(GUI.InactivePause) + { + S9xClearPause (PAUSE_WINDOW_ICONISED); + } + } + WinChangeWindowSize(LOWORD(lParam),HIWORD(lParam)); + break; + case WM_MOVE: + //if (!VOODOO_MODE && !GUI.FullScreen && !Settings.ForcedPause) + //{ + // GetWindowRect (GUI.hWnd, &GUI.window_size); + //} + + break; + case WM_ENTERSIZEMOVE: + S9xSetPause(PAUSE_MENU); + break; + case WM_EXITSIZEMOVE: + S9xClearPause(PAUSE_MENU); + break; + case WM_DISPLAYCHANGE: + if (!GUI.FullScreen) + { + WinDisplayReset(); + } + break; + case WM_MOUSEMOVE: + if(Settings.StopEmulation) + { + SetCursor (GUI.Arrow); + break; + } + // Lo-word of lparam is xpos, hi-word is ypos +// if (!GUI.IgnoreNextMouseMove) + { + //POINT p; + //p.x = GET_X_LPARAM(lParam); + //p.y = GET_Y_LPARAM(lParam); + //ClientToScreen (GUI.hWnd, &p); + if ((!Settings.ForcedPause && !Settings.StopEmulation && + !(Settings.Paused && !Settings.FrameAdvance)) && + (GUI.ControllerOption==SNES_MOUSE || GUI.ControllerOption==SNES_MOUSE_SWAPPED) + ) + { + CenterCursor(); + } + else if (GUI.ControllerOption==SNES_SUPERSCOPE || GUI.ControllerOption==SNES_JUSTIFIER || GUI.ControllerOption==SNES_JUSTIFIER_2) + { + RECT size; + GetClientRect (GUI.hWnd, &size); + if(!(GUI.Scale)&&!(GUI.Stretch)) + { + int x,y, startx, starty; + x=GET_X_LPARAM(lParam); + y=GET_Y_LPARAM(lParam); + +// int theight; +// (IPPU.RenderedScreenHeight> 256)? theight= SNES_HEIGHT_EXTENDED<<1: theight = SNES_HEIGHT_EXTENDED; + int theight = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT; + if(IPPU.RenderedScreenHeight > SNES_HEIGHT_EXTENDED) theight <<= 1; + + startx= size.right-IPPU.RenderedScreenWidth; + startx/=2; + starty= size.bottom-theight; + starty/=2; + + if(x(startx+IPPU.RenderedScreenWidth)) + GUI.MouseX=IPPU.RenderedScreenWidth; + else GUI.MouseX=x-startx; + + if(y(starty+theight)) + GUI.MouseY=theight; + else GUI.MouseY=y-starty; + } + else if(!(GUI.Stretch)) + { + int x,y, startx, starty, sizex, sizey; + x=GET_X_LPARAM(lParam); + y=GET_Y_LPARAM(lParam); + + if (IPPU.RenderedScreenWidth>256) + sizex=IPPU.RenderedScreenWidth; + else sizex=IPPU.RenderedScreenWidth*2; + + int theight = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT; + sizey = (IPPU.RenderedScreenHeight > SNES_HEIGHT_EXTENDED) ? theight : (theight << 1); + + startx= size.right-sizex; + startx/=2; + starty= size.bottom-sizey; + starty/=2; + if(x(startx+sizex)) + GUI.MouseX=sizex; + else GUI.MouseX=x-startx; + + if(y(starty+sizey)) + GUI.MouseY=sizey; + else GUI.MouseY=y-starty; + + GUI.MouseX=(GUI.MouseX*IPPU.RenderedScreenWidth)/sizex; + GUI.MouseY=(GUI.MouseY*IPPU.RenderedScreenHeight)/sizey; + } + else + { + int sizex = IPPU.RenderedScreenWidth; + int sizey = GUI.HeightExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT; + sizey = (IPPU.RenderedScreenHeight > SNES_HEIGHT_EXTENDED) ? (sizey << 1) : sizey; + int width = size.right, height = size.bottom, xdiff = 0, ydiff = 0; + if(GUI.AspectRatio) + { + if(width > sizex*height/sizey) + { + xdiff = width - sizex*height/sizey; + width -= xdiff; + xdiff >>= 1; + } + else if(height > sizey*width/sizex) + { + ydiff = height - sizey*width/sizex; + height -= ydiff; + ydiff >>= 1; + } + } + GUI.MouseX=(GET_X_LPARAM(lParam)-xdiff)*sizex/width; + GUI.MouseY=(GET_Y_LPARAM(lParam)-ydiff)*sizey/height; + } + } + else + { +// GUI.MouseX = p.x; +// GUI.MouseY = p.y; + } + } +// else +// GUI.IgnoreNextMouseMove = false; + + if(!GUI.IgnoreNextMouseMove) + S9xMouseOn (); + else + GUI.IgnoreNextMouseMove = false; + return 0; + case WM_LBUTTONDOWN: + S9xMouseOn (); + GUI.MouseButtons |= 1; + break; + case WM_LBUTTONUP: + S9xMouseOn (); + GUI.MouseButtons &= ~1; + break; + case WM_RBUTTONDOWN: + S9xMouseOn (); + GUI.MouseButtons |= 2; + break; + case WM_RBUTTONUP: + S9xMouseOn (); + GUI.MouseButtons &= ~2; + if(GUI.ControllerOption==SNES_JUSTIFIER || GUI.ControllerOption==SNES_JUSTIFIER_2) + { + RECT size; + GetClientRect (GUI.hWnd, &size); + GUI.MouseButtons&=~1; + GUI.MouseX=(IPPU.RenderedScreenWidth*(lParam & 0xffff))/(size.right-size.left); + GUI.MouseY=(((lParam >> 16) & 0xffff)*IPPU.RenderedScreenHeight)/(size.bottom-size.top); + } + break; + case WM_MBUTTONDOWN: + S9xMouseOn (); + GUI.MouseButtons |= 4; + break; + case WM_MBUTTONUP: + S9xMouseOn (); + GUI.MouseButtons &= ~4; + break; +#ifdef NETPLAY_SUPPORT + case WM_USER + 3: + NetPlay.Answer = S9xLoadROMImage ((const char *) lParam); + SetEvent (NetPlay.ReplyEvent); + break; + case WM_USER + 2: + S9xMessage (0, 0, NetPlay.WarningMsg); + break; + case WM_USER + 1: + RestoreGUIDisplay (); + S9xRestoreWindowTitle (); + MessageBox (GUI.hWnd, NetPlay.ErrorMsg, + TEXT(SNES9X_NP_ERROR), MB_OK | MB_ICONSTOP); + RestoreSNESDisplay (); + break; + case WM_USER: + if (NetPlay.ActionMsg [0] == 0) + S9xRestoreWindowTitle (); + else + { + TCHAR buf [NP_MAX_ACTION_LEN + 10]; + + sprintf (buf, TEXT("%s %3d%%"), NetPlay.ActionMsg, (int) lParam); + SetWindowText (GUI.hWnd, buf); + } +#if 0 + if ((int) lParam >= 0) + { + RestoreGUIDisplay (); + DialogBox(g_hInst, MAKEINTRESOURCE(IDD_NETPLAYPROGRESS), hWnd, DlgNPProgress); + } + else + { + DialogBox(g_hInst, MAKEINTRESOURCE(IDD_NETPLAYPROGRESS), hWnd, DlgNPProgress); + RestoreSNESDisplay (); + } +#endif + break; +#endif + } + return DefWindowProc (hWnd, uMsg, wParam, lParam); +} + +/*****************************************************************************/ +/* WinInit */ +/*****************************************************************************/ +BOOL WinInit( HINSTANCE hInstance) +{ + WNDCLASSEX wndclass; + ZeroMemory(&wndclass, sizeof(wndclass)); + wndclass.cbSize = sizeof(wndclass); + + wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wndclass.lpfnWndProc = WinProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1)); + wndclass.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 16, 16, 0); + wndclass.hCursor = NULL; //LoadCursor (NULL, IDC_ARROW); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = TEXT("Snes9X: WndClass"); + wndclass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); + + //// Initialize the struct to zero + //ZeroMemory(&wcx,sizeof(WNDCLASSEX)); + //wcx.cbSize = sizeof(WNDCLASSEX); // Must always be sizeof(WNDCLASSEX) + //wcx.style = CS_HREDRAW|CS_VREDRAW |CS_DBLCLKS ; // Class styles + //wcx.lpfnWndProc = (WNDPROC)MainWndProc; // Pointer to the callback procedure + //wcx.cbClsExtra = 0; // Extra byte to allocate following the wndclassex structure + //wcx.cbWndExtra = 0; // Extra byte to allocate following an instance of the structure + //wcx.hInstance = hInstance; // Instance of the application + //wcx.hIcon = NULL; // Class Icon + //wcx.hCursor = LoadCursor(NULL, IDC_ARROW); // Class Cursor + //wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW); // Background brush + //wcx.lpszMenuName = NULL; // Menu resource + //wcx.lpszClassName = "Lesson2"; // Name of this class + //wcx.hIconSm = NULL; // Small icon for this class + + GUI.hInstance = hInstance; + + if (!RegisterClassEx (&wndclass)) + { + MessageBox (NULL, "Failed to register windows class", "Internal Error", MB_OK | MB_ICONSTOP); + return FALSE; + } + + GUI.hMenu = LoadMenu (hInstance, MAKEINTRESOURCE( Languages[ GUI.Language].idMenu)); + if (GUI.hMenu == NULL) + { + MessageBox (NULL, "Failed to initialize the menu.\nThis could indicate a failure of your operating system;\ntry closing some other windows or programs, or restart your computer, before opening Snes9x again.\nOr, if you compiled this program yourself, ensure that Snes9x was built with the proper resource files.", "Snes9X - Menu Initialization Failure", MB_OK | MB_ICONSTOP); +// return FALSE; // disabled: try to function without the menu + } + + TCHAR buf [100]; + sprintf (buf, TEXT(WINDOW_TITLE), VERSION); + + DWORD dwExStyle; + DWORD dwStyle; + RECT rect; + + rect.left = rect.top = 0; + rect.right = MAX_SNES_WIDTH; + rect.bottom = MAX_SNES_HEIGHT; + dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + dwStyle = WS_OVERLAPPEDWINDOW; + + AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle); + if ((GUI.hWnd = CreateWindowEx ( + dwExStyle, + TEXT("Snes9X: WndClass"), + buf, + WS_CLIPSIBLINGS | + WS_CLIPCHILDREN | + dwStyle, + 0, 0, + rect.right - rect.left, rect.bottom - rect.top, + NULL, + GUI.hMenu, + hInstance, + NULL)) == NULL) + return FALSE; + + GUI.hDC = GetDC (GUI.hWnd); + LoadExts(); + GUI.GunSight = LoadCursor (hInstance, MAKEINTRESOURCE (IDC_CURSOR_SCOPE)); + GUI.Arrow = LoadCursor (NULL, IDC_ARROW); + GUI.Accelerators = LoadAccelerators (hInstance, MAKEINTRESOURCE (IDR_SNES9X_ACCELERATORS)); + Settings.ForcedPause = 0; + Settings.StopEmulation = TRUE; + Settings.Paused = FALSE; + + GUI.AVIOut = NULL; + + return TRUE; +} + + + +void S9xExtraUsage () +{ +} + +// handles joystick hotkey presses +VOID CALLBACK HotkeyTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) +{ +// static int lastTime = timeGetTime(); +// if(timeGetTime() - lastTime > 5) + { + bool S9xGetState (WORD KeyIdent); + + if(GUI.JoystickHotkeys) + { + static int counter = 0; + static uint32 joyState [256]; + for(int i = 0 ; i < 255 ; i++) + { + if(counter%2 && !joyState[i]) + continue; + + bool active = !S9xGetState(0x8000|i); + if(active) + { + if(joyState[i] < ULONG_MAX) // 0xffffffffUL + joyState[i]++; + if(joyState[i] == 1 || joyState[i] >= 12) + PostMessage(GUI.hWnd, WM_CUSTKEYDOWN, (WPARAM)(0x8000|i),(LPARAM)(NULL)); + } + else + if(joyState[i]) + { + joyState[i] = 0; + PostMessage(GUI.hWnd, WM_CUSTKEYUP, (WPARAM)(0x8000|i),(LPARAM)(NULL)); + } + } + counter++; + } + if(GUI.BackgroundKeyHotkeys) + { + static int counter = 0; + static uint32 joyState [256]; + for(int i = 0 ; i < 255 ; i++) + { + if(counter%2 && !joyState[i]) + continue; + + bool active = !S9xGetState(i); + if(active) + { + if(joyState[i] < ULONG_MAX) // 0xffffffffUL + joyState[i]++; + if(joyState[i] == 1 || joyState[i] >= 12) + PostMessage(GUI.hWnd, WM_CUSTKEYDOWN, (WPARAM)(i),(LPARAM)(NULL)); + } + else + joyState[i] = 0; + } + counter++; + } +// lastTime = timeGetTime(); + } +} + +VOID CALLBACK FrameTimer( UINT idEvent, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) +{ + // QueryPerformanceCounter is unreliable on newfangled frequency-switching computers, + // yet is absolutely necessary for best performance on somewhat older computers (even ones that are capable of frequency switching but don't do it very often). + // Thus, we keep two timers and use the QueryPerformanceCounter one unless the other (more accurate but less precise) + // one differs from it by more than a few milliseconds. + + QueryPerformanceCounter((LARGE_INTEGER*)&PCEnd); + PCEndTicks = timeGetTime()*1000; + + const __int64 PCElapsedPrecise = PCEnd - PCStart; + const __int64 PCElapsedAccurate = (__int64)(PCEndTicks - PCStartTicks) * PCBase / 1000000; + const bool useTicksTimer = (abs((int)(PCElapsedPrecise - PCElapsedAccurate)) > (PCBase >> 7)); // if > 7.8 ms difference, settle for accuracy at the sacrifice of precision + + while ((!useTicksTimer && (PCEnd - PCStart ) >= PCFrameTime) || + ( useTicksTimer && (PCEndTicks - PCStartTicks) >= PCFrameTime * 1000000 / PCBase)) + { + if (GUI.FrameCount == GUI.LastFrameCount) + GUI.IdleCount++; + else + { + GUI.IdleCount = 0; + GUI.LastFrameCount = GUI.FrameCount; + } + +#ifdef NETPLAY_SUPPORT + // if (Settings.NetPlay && !Settings.NetPlayServer) + // return; + if (Settings.NetPlay && !Settings.NetPlayServer) + return; + + //- if (Settings.NetPlayServer) + //- { + //- if (Settings.Paused || Settings.StopEmulation || Settings.ForcedPause) + if (Settings.NetPlayServer) + { + //- WaitForSingleObject (GUI.ServerTimerSemaphore, 0); + if ((Settings.Paused && !Settings.FrameAdvance) || Settings.StopEmulation || Settings.ForcedPause) + { + WaitForSingleObject (GUI.ServerTimerSemaphore, 0); + return; + } + ReleaseSemaphore (GUI.ServerTimerSemaphore, 1, NULL); + + if (Settings.NetPlay) + return; + } + else +#endif + { + if (Settings.SkipFrames != AUTO_FRAMERATE || Settings.TurboMode || + (Settings.Paused /*&& !Settings.FrameAdvance*/) || Settings.StopEmulation || Settings.ForcedPause) + { + WaitForSingleObject (GUI.FrameTimerSemaphore, 0); + PCStart = PCEnd; + PCStartTicks = PCEndTicks; + return; + } + // ReleaseSemaphore (GUI.ServerTimerSemaphore, 1, NULL); + ReleaseSemaphore (GUI.FrameTimerSemaphore, 1, NULL); + + // if (Settings.NetPlay) + // return; + // } + // else + //#endif + // if (Settings.SkipFrames != AUTO_FRAMERATE || Settings.TurboMode || + // Settings.Paused || Settings.StopEmulation || Settings.ForcedPause) + // { + // WaitForSingleObject (GUI.FrameTimerSemaphore, 0); + // return; + // } + // ReleaseSemaphore (GUI.FrameTimerSemaphore, 1, NULL); + PCStart += PCFrameTime; + PCStartTicks += (DWORD)(PCFrameTime * 1000000 / PCBase); + } + } +} + +static void EnsureInputDisplayUpdated() +{ + if(GUI.FrameAdvanceJustPressed==1 && Settings.Paused && Settings.DisplayPressedKeys==2 && GUI.ControllerOption != SNES_JOYPAD && GUI.ControllerOption != SNES_MULTIPLAYER5 && GUI.ControllerOption != SNES_MULTIPLAYER8) + WinRefreshDisplay(); +} + +// for "frame advance skips non-input frames" feature +void S9xOnSNESPadRead() +{ + if(!GUI.FASkipsNonInput) + return; + + if(prevPadReadFrame != IPPU.TotalEmulatedFrames) // we want <= 1 calls per frame + { + prevPadReadFrame = IPPU.TotalEmulatedFrames; + + if(Settings.FrameAdvance && Settings.Paused && !skipNextFrameStop) + { + Settings.FrameAdvance = false; + + EnsureInputDisplayUpdated(); + + // wait until either unpause or next frame advance + // note: using GUI.hWnd instead of NULL for PeekMessage/GetMessage breaks some non-modal dialogs + MSG msg; + while (Settings.StopEmulation || (Settings.Paused && !Settings.FrameAdvance) || + Settings.ForcedPause || + PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) + { + if (!GetMessage (&msg, NULL, 0, 0)) + { + PostMessage(GUI.hWnd, WM_QUIT, 0,0); + return; + } + + if (!TranslateAccelerator (GUI.hWnd, GUI.Accelerators, &msg)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + } + + } + else + { + skipNextFrameStop = false; + } + } +} + + +enum +{ + k_HD = 0x80000000, + + k_JP = 0x01000000, + k_MO = 0x02000000, + k_SS = 0x04000000, + k_LG = 0x08000000, + + k_BT = 0x00100000, + k_PT = 0x00200000, + k_PS = 0x00400000, + + k_C1 = 0x00000100, + k_C2 = 0x00000200, + k_C3 = 0x00000400, + k_C4 = 0x00000800, + k_C5 = 0x00001000, + k_C6 = 0x00002000, + k_C7 = 0x00004000, + k_C8 = 0x00008000 +}; + +enum +{ + kWinCMapPad1PX = k_HD | k_BT | k_JP | k_C1, + kWinCMapPad1PA, + kWinCMapPad1PB, + kWinCMapPad1PY, + kWinCMapPad1PL, + kWinCMapPad1PR, + kWinCMapPad1PSelect, + kWinCMapPad1PStart, + kWinCMapPad1PUp, + kWinCMapPad1PDown, + kWinCMapPad1PLeft, + kWinCMapPad1PRight, + + kWinCMapPad2PX = k_HD | k_BT | k_JP | k_C2, + kWinCMapPad2PA, + kWinCMapPad2PB, + kWinCMapPad2PY, + kWinCMapPad2PL, + kWinCMapPad2PR, + kWinCMapPad2PSelect, + kWinCMapPad2PStart, + kWinCMapPad2PUp, + kWinCMapPad2PDown, + kWinCMapPad2PLeft, + kWinCMapPad2PRight, + + kWinCMapPad3PX = k_HD | k_BT | k_JP | k_C3, + kWinCMapPad3PA, + kWinCMapPad3PB, + kWinCMapPad3PY, + kWinCMapPad3PL, + kWinCMapPad3PR, + kWinCMapPad3PSelect, + kWinCMapPad3PStart, + kWinCMapPad3PUp, + kWinCMapPad3PDown, + kWinCMapPad3PLeft, + kWinCMapPad3PRight, + + kWinCMapPad4PX = k_HD | k_BT | k_JP | k_C4, + kWinCMapPad4PA, + kWinCMapPad4PB, + kWinCMapPad4PY, + kWinCMapPad4PL, + kWinCMapPad4PR, + kWinCMapPad4PSelect, + kWinCMapPad4PStart, + kWinCMapPad4PUp, + kWinCMapPad4PDown, + kWinCMapPad4PLeft, + kWinCMapPad4PRight, + + kWinCMapPad5PX = k_HD | k_BT | k_JP | k_C5, + kWinCMapPad5PA, + kWinCMapPad5PB, + kWinCMapPad5PY, + kWinCMapPad5PL, + kWinCMapPad5PR, + kWinCMapPad5PSelect, + kWinCMapPad5PStart, + kWinCMapPad5PUp, + kWinCMapPad5PDown, + kWinCMapPad5PLeft, + kWinCMapPad5PRight, + + kWinCMapPad6PX = k_HD | k_BT | k_JP | k_C6, + kWinCMapPad6PA, + kWinCMapPad6PB, + kWinCMapPad6PY, + kWinCMapPad6PL, + kWinCMapPad6PR, + kWinCMapPad6PSelect, + kWinCMapPad6PStart, + kWinCMapPad6PUp, + kWinCMapPad6PDown, + kWinCMapPad6PLeft, + kWinCMapPad6PRight, + + kWinCMapPad7PX = k_HD | k_BT | k_JP | k_C7, + kWinCMapPad7PA, + kWinCMapPad7PB, + kWinCMapPad7PY, + kWinCMapPad7PL, + kWinCMapPad7PR, + kWinCMapPad7PSelect, + kWinCMapPad7PStart, + kWinCMapPad7PUp, + kWinCMapPad7PDown, + kWinCMapPad7PLeft, + kWinCMapPad7PRight, + + kWinCMapPad8PX = k_HD | k_BT | k_JP | k_C8, + kWinCMapPad8PA, + kWinCMapPad8PB, + kWinCMapPad8PY, + kWinCMapPad8PL, + kWinCMapPad8PR, + kWinCMapPad8PSelect, + kWinCMapPad8PStart, + kWinCMapPad8PUp, + kWinCMapPad8PDown, + kWinCMapPad8PLeft, + kWinCMapPad8PRight, + + kWinCMapMouse1PL = k_HD | k_BT | k_MO | k_C1, + kWinCMapMouse1PR, + kWinCMapMouse2PL = k_HD | k_BT | k_MO | k_C2, + kWinCMapMouse2PR, + + kWinCMapScopeOffscreen = k_HD | k_BT | k_SS | k_C1, + kWinCMapScopeFire, + kWinCMapScopeCursor, + kWinCMapScopeTurbo, + kWinCMapScopePause, + + kWinCMapLGun1Offscreen = k_HD | k_BT | k_LG | k_C1, + kWinCMapLGun1Trigger, + kWinCMapLGun1Start, + kWinCMapLGun2Offscreen = k_HD | k_BT | k_LG | k_C2, + kWinCMapLGun2Trigger, + kWinCMapLGun2Start, + + kWinCMapMouse1Pointer = k_HD | k_PT | k_MO | k_C1, + kWinCMapMouse2Pointer = k_HD | k_PT | k_MO | k_C2, + kWinCMapSuperscopePointer = k_HD | k_PT | k_SS | k_C1, + kWinCMapJustifier1Pointer = k_HD | k_PT | k_LG | k_C1, + + kWinCMapPseudoPtrBase = k_HD | k_PS | k_LG | k_C2 // for Justifier 2P +}; + + + +#define ASSIGN_BUTTONf(n, s) S9xMapButton (n, cmd = S9xGetCommandT(s), false) +#define ASSIGN_BUTTONt(n, s) S9xMapButton (n, cmd = S9xGetCommandT(s), true) +#define ASSIGN_POINTRf(n, s) S9xMapPointer(n, cmd = S9xGetCommandT(s), false) +#define ASSIGN_POINTRt(n, s) S9xMapPointer(n, cmd = S9xGetCommandT(s), true) + +#define KeyIsPressed(km, k) (1 & (((unsigned char *) km) [(k) >> 3] >> ((k) & 7))) + +void S9xSetupDefaultKeymap(void) +{ + s9xcommand_t cmd; + + ASSIGN_BUTTONf(kWinCMapPad1PX, "Joypad1 X"); + ASSIGN_BUTTONf(kWinCMapPad1PA, "Joypad1 A"); + ASSIGN_BUTTONf(kWinCMapPad1PB, "Joypad1 B"); + ASSIGN_BUTTONf(kWinCMapPad1PY, "Joypad1 Y"); + ASSIGN_BUTTONf(kWinCMapPad1PL, "Joypad1 L"); + ASSIGN_BUTTONf(kWinCMapPad1PR, "Joypad1 R"); + ASSIGN_BUTTONf(kWinCMapPad1PSelect, "Joypad1 Select"); + ASSIGN_BUTTONf(kWinCMapPad1PStart, "Joypad1 Start"); + ASSIGN_BUTTONf(kWinCMapPad1PUp, "Joypad1 Up"); + ASSIGN_BUTTONf(kWinCMapPad1PDown, "Joypad1 Down"); + ASSIGN_BUTTONf(kWinCMapPad1PLeft, "Joypad1 Left"); + ASSIGN_BUTTONf(kWinCMapPad1PRight, "Joypad1 Right"); + + ASSIGN_BUTTONf(kWinCMapPad2PX, "Joypad2 X"); + ASSIGN_BUTTONf(kWinCMapPad2PA, "Joypad2 A"); + ASSIGN_BUTTONf(kWinCMapPad2PB, "Joypad2 B"); + ASSIGN_BUTTONf(kWinCMapPad2PY, "Joypad2 Y"); + ASSIGN_BUTTONf(kWinCMapPad2PL, "Joypad2 L"); + ASSIGN_BUTTONf(kWinCMapPad2PR, "Joypad2 R"); + ASSIGN_BUTTONf(kWinCMapPad2PSelect, "Joypad2 Select"); + ASSIGN_BUTTONf(kWinCMapPad2PStart, "Joypad2 Start"); + ASSIGN_BUTTONf(kWinCMapPad2PUp, "Joypad2 Up"); + ASSIGN_BUTTONf(kWinCMapPad2PDown, "Joypad2 Down"); + ASSIGN_BUTTONf(kWinCMapPad2PLeft, "Joypad2 Left"); + ASSIGN_BUTTONf(kWinCMapPad2PRight, "Joypad2 Right"); + + ASSIGN_BUTTONf(kWinCMapPad3PX, "Joypad3 X"); + ASSIGN_BUTTONf(kWinCMapPad3PA, "Joypad3 A"); + ASSIGN_BUTTONf(kWinCMapPad3PB, "Joypad3 B"); + ASSIGN_BUTTONf(kWinCMapPad3PY, "Joypad3 Y"); + ASSIGN_BUTTONf(kWinCMapPad3PL, "Joypad3 L"); + ASSIGN_BUTTONf(kWinCMapPad3PR, "Joypad3 R"); + ASSIGN_BUTTONf(kWinCMapPad3PSelect, "Joypad3 Select"); + ASSIGN_BUTTONf(kWinCMapPad3PStart, "Joypad3 Start"); + ASSIGN_BUTTONf(kWinCMapPad3PUp, "Joypad3 Up"); + ASSIGN_BUTTONf(kWinCMapPad3PDown, "Joypad3 Down"); + ASSIGN_BUTTONf(kWinCMapPad3PLeft, "Joypad3 Left"); + ASSIGN_BUTTONf(kWinCMapPad3PRight, "Joypad3 Right"); + + ASSIGN_BUTTONf(kWinCMapPad4PX, "Joypad4 X"); + ASSIGN_BUTTONf(kWinCMapPad4PA, "Joypad4 A"); + ASSIGN_BUTTONf(kWinCMapPad4PB, "Joypad4 B"); + ASSIGN_BUTTONf(kWinCMapPad4PY, "Joypad4 Y"); + ASSIGN_BUTTONf(kWinCMapPad4PL, "Joypad4 L"); + ASSIGN_BUTTONf(kWinCMapPad4PR, "Joypad4 R"); + ASSIGN_BUTTONf(kWinCMapPad4PSelect, "Joypad4 Select"); + ASSIGN_BUTTONf(kWinCMapPad4PStart, "Joypad4 Start"); + ASSIGN_BUTTONf(kWinCMapPad4PUp, "Joypad4 Up"); + ASSIGN_BUTTONf(kWinCMapPad4PDown, "Joypad4 Down"); + ASSIGN_BUTTONf(kWinCMapPad4PLeft, "Joypad4 Left"); + ASSIGN_BUTTONf(kWinCMapPad4PRight, "Joypad4 Right"); + + ASSIGN_BUTTONf(kWinCMapPad5PX, "Joypad5 X"); + ASSIGN_BUTTONf(kWinCMapPad5PA, "Joypad5 A"); + ASSIGN_BUTTONf(kWinCMapPad5PB, "Joypad5 B"); + ASSIGN_BUTTONf(kWinCMapPad5PY, "Joypad5 Y"); + ASSIGN_BUTTONf(kWinCMapPad5PL, "Joypad5 L"); + ASSIGN_BUTTONf(kWinCMapPad5PR, "Joypad5 R"); + ASSIGN_BUTTONf(kWinCMapPad5PSelect, "Joypad5 Select"); + ASSIGN_BUTTONf(kWinCMapPad5PStart, "Joypad5 Start"); + ASSIGN_BUTTONf(kWinCMapPad5PUp, "Joypad5 Up"); + ASSIGN_BUTTONf(kWinCMapPad5PDown, "Joypad5 Down"); + ASSIGN_BUTTONf(kWinCMapPad5PLeft, "Joypad5 Left"); + ASSIGN_BUTTONf(kWinCMapPad5PRight, "Joypad5 Right"); + + ASSIGN_BUTTONf(kWinCMapPad6PX, "Joypad6 X"); + ASSIGN_BUTTONf(kWinCMapPad6PA, "Joypad6 A"); + ASSIGN_BUTTONf(kWinCMapPad6PB, "Joypad6 B"); + ASSIGN_BUTTONf(kWinCMapPad6PY, "Joypad6 Y"); + ASSIGN_BUTTONf(kWinCMapPad6PL, "Joypad6 L"); + ASSIGN_BUTTONf(kWinCMapPad6PR, "Joypad6 R"); + ASSIGN_BUTTONf(kWinCMapPad6PSelect, "Joypad6 Select"); + ASSIGN_BUTTONf(kWinCMapPad6PStart, "Joypad6 Start"); + ASSIGN_BUTTONf(kWinCMapPad6PUp, "Joypad6 Up"); + ASSIGN_BUTTONf(kWinCMapPad6PDown, "Joypad6 Down"); + ASSIGN_BUTTONf(kWinCMapPad6PLeft, "Joypad6 Left"); + ASSIGN_BUTTONf(kWinCMapPad6PRight, "Joypad6 Right"); + + ASSIGN_BUTTONf(kWinCMapPad7PX, "Joypad7 X"); + ASSIGN_BUTTONf(kWinCMapPad7PA, "Joypad7 A"); + ASSIGN_BUTTONf(kWinCMapPad7PB, "Joypad7 B"); + ASSIGN_BUTTONf(kWinCMapPad7PY, "Joypad7 Y"); + ASSIGN_BUTTONf(kWinCMapPad7PL, "Joypad7 L"); + ASSIGN_BUTTONf(kWinCMapPad7PR, "Joypad7 R"); + ASSIGN_BUTTONf(kWinCMapPad7PSelect, "Joypad7 Select"); + ASSIGN_BUTTONf(kWinCMapPad7PStart, "Joypad7 Start"); + ASSIGN_BUTTONf(kWinCMapPad7PUp, "Joypad7 Up"); + ASSIGN_BUTTONf(kWinCMapPad7PDown, "Joypad7 Down"); + ASSIGN_BUTTONf(kWinCMapPad7PLeft, "Joypad7 Left"); + ASSIGN_BUTTONf(kWinCMapPad7PRight, "Joypad7 Right"); + + ASSIGN_BUTTONf(kWinCMapPad8PX, "Joypad8 X"); + ASSIGN_BUTTONf(kWinCMapPad8PA, "Joypad8 A"); + ASSIGN_BUTTONf(kWinCMapPad8PB, "Joypad8 B"); + ASSIGN_BUTTONf(kWinCMapPad8PY, "Joypad8 Y"); + ASSIGN_BUTTONf(kWinCMapPad8PL, "Joypad8 L"); + ASSIGN_BUTTONf(kWinCMapPad8PR, "Joypad8 R"); + ASSIGN_BUTTONf(kWinCMapPad8PSelect, "Joypad8 Select"); + ASSIGN_BUTTONf(kWinCMapPad8PStart, "Joypad8 Start"); + ASSIGN_BUTTONf(kWinCMapPad8PUp, "Joypad8 Up"); + ASSIGN_BUTTONf(kWinCMapPad8PDown, "Joypad8 Down"); + ASSIGN_BUTTONf(kWinCMapPad8PLeft, "Joypad8 Left"); + ASSIGN_BUTTONf(kWinCMapPad8PRight, "Joypad8 Right"); + + ASSIGN_BUTTONt(kWinCMapMouse1PL, "Mouse1 L"); + ASSIGN_BUTTONt(kWinCMapMouse1PR, "Mouse1 R"); + ASSIGN_BUTTONt(kWinCMapMouse2PL, "Mouse2 L"); + ASSIGN_BUTTONt(kWinCMapMouse2PR, "Mouse2 R"); + + ASSIGN_BUTTONt(kWinCMapScopeOffscreen, "Superscope AimOffscreen"); + ASSIGN_BUTTONt(kWinCMapScopeFire, "Superscope Fire"); + ASSIGN_BUTTONt(kWinCMapScopeCursor, "Superscope Cursor"); + ASSIGN_BUTTONt(kWinCMapScopeTurbo, "Superscope ToggleTurbo"); + ASSIGN_BUTTONt(kWinCMapScopePause, "Superscope Pause"); + + ASSIGN_BUTTONt(kWinCMapLGun1Offscreen, "Justifier1 AimOffscreen"); + ASSIGN_BUTTONt(kWinCMapLGun1Trigger, "Justifier1 Trigger"); + ASSIGN_BUTTONt(kWinCMapLGun1Start, "Justifier1 Start"); + ASSIGN_BUTTONt(kWinCMapLGun2Offscreen, "Justifier2 AimOffscreen"); + ASSIGN_BUTTONt(kWinCMapLGun2Trigger, "Justifier2 Trigger"); + ASSIGN_BUTTONt(kWinCMapLGun2Start, "Justifier2 Start"); + + ASSIGN_POINTRt(kWinCMapMouse1Pointer, "Pointer Mouse1"); + ASSIGN_POINTRt(kWinCMapMouse2Pointer, "Pointer Mouse2"); + ASSIGN_POINTRt(kWinCMapSuperscopePointer, "Pointer Superscope"); + ASSIGN_POINTRt(kWinCMapJustifier1Pointer, "Pointer Justifier1"); + + ASSIGN_POINTRf(PseudoPointerBase, "Pointer Justifier2"); + ASSIGN_BUTTONf(kWinCMapPseudoPtrBase + 0, "ButtonToPointer 1u Med"); + ASSIGN_BUTTONf(kWinCMapPseudoPtrBase + 1, "ButtonToPointer 1d Med"); + ASSIGN_BUTTONf(kWinCMapPseudoPtrBase + 2, "ButtonToPointer 1l Med"); + ASSIGN_BUTTONf(kWinCMapPseudoPtrBase + 3, "ButtonToPointer 1r Med"); +} + +void ControlPadFlagsToS9xReportButtons(int n, uint32 p) +{ + uint32 base = k_HD | k_BT | k_JP | (0x100 << n); + + S9xReportButton(base + 0, (p & 0x0040) != 0); + S9xReportButton(base + 1, (p & 0x0080) != 0); + S9xReportButton(base + 2, (p & 0x8000) != 0); + S9xReportButton(base + 3, (p & 0x4000) != 0); + S9xReportButton(base + 4, (p & 0x0020) != 0); + S9xReportButton(base + 5, (p & 0x0010) != 0); + S9xReportButton(base + 6, (p & 0x2000) != 0); + S9xReportButton(base + 7, (p & 0x1000) != 0); + S9xReportButton(base + 8, (p & 0x0800) != 0); + S9xReportButton(base + 9, (p & 0x0400) != 0); + S9xReportButton(base + 10, (p & 0x0200) != 0); + S9xReportButton(base + 11, (p & 0x0100) != 0); +} + +void ControlPadFlagsToS9xPseudoPointer(uint32 p) +{ + // prevent screwiness caused by trying to move the pointer left+right or up+down + if((p & 0x0c00) == 0x0c00) p &= ~0x0c00; + if((p & 0x0300) == 0x0300) p &= ~0x0300; + + // checks added to prevent a lack of right/down movement from breaking left/up movement + if(!(p & 0x0400)) + S9xReportButton(kWinCMapPseudoPtrBase + 0, (p & 0x0800) != 0); + if(!(p & 0x0800)) + S9xReportButton(kWinCMapPseudoPtrBase + 1, (p & 0x0400) != 0); + if(!(p & 0x0100)) + S9xReportButton(kWinCMapPseudoPtrBase + 2, (p & 0x0200) != 0); + if(!(p & 0x0200)) + S9xReportButton(kWinCMapPseudoPtrBase + 3, (p & 0x0100) != 0); +} + +static void ProcessInput(void) +{ + extern void S9xWinScanJoypads (); +#ifdef NETPLAY_SUPPORT + if (!Settings.NetPlay) +#endif + S9xWinScanJoypads (); + + extern uint32 joypads [8]; + for(int i = 0 ; i < 8 ; i++) + ControlPadFlagsToS9xReportButtons(i, joypads[i]); + + if (GUI.ControllerOption==SNES_JUSTIFIER_2) + ControlPadFlagsToS9xPseudoPointer(joypads[1]); +} + +//static void WinDisplayString (const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); + + + + +/*****************************************************************************/ +/* WinMain */ +/*****************************************************************************/ +void DeinitS9x(void); + +int WINAPI WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + Settings.StopEmulation = TRUE; + + // Redirect stderr and stdout to file. It wouldn't go to any commandline anyway. + FILE* fout = freopen("stdout.txt", "w", stdout); + if(fout) setvbuf(fout, NULL, _IONBF, 0); + FILE* ferr = freopen("stderr.txt", "w", stderr); + if(ferr) setvbuf(ferr, NULL, _IONBF, 0); + + DWORD wSoundTimerRes; + + WinRegisterConfigItems (); + + ConfigFile::SetAlphaSort(false); + ConfigFile::SetTimeSort(false); + rom_filename = WinParseCommandLineAndLoadConfigFile (lpCmdLine); + WinSaveConfigFile (); + WinLockConfigFile (); + + bool maximized = GUI.window_maximized; + + WinInit (hInstance); + if(GUI.HideMenu) + { + SetMenu (GUI.hWnd, NULL); + } + + InitLUTsWin32(); // init win hq2x + + WinDisplayReset(); + + MoveWindow (GUI.hWnd, GUI.window_size.left, + GUI.window_size.top, + GUI.window_size.right - GUI.window_size.left, + GUI.window_size.bottom - GUI.window_size.top, TRUE); + + if (!GUI.FullScreen) + { + RECT rect; + GetClientRect (GUI.hWnd, &rect); + InvalidateRect (GUI.hWnd, &rect, true); + } + + GUI.ControlForced = 0xff; + + S9xSetRecentGames (); + ShowWindow (GUI.hWnd, maximized ? SW_MAXIMIZE : SW_SHOWNORMAL); + /*SetForegroundWindow (GUI.hWnd); + SetFocus (GUI.hWnd);*/ + + // hack for borders-not-shown bug (Windows bug?) on startup + if(!maximized) + { + ShowWindow (GUI.hWnd, SW_HIDE); + ShowWindow (GUI.hWnd, SW_SHOWNORMAL); + } + + if(GUI.FullScreen) { + GUI.FullScreen = false; + ToggleFullScreen(); + } + + void InitSnes9X (void); + InitSnes9X (); + + TIMECAPS tc; + if (timeGetDevCaps(&tc, sizeof(TIMECAPS))== TIMERR_NOERROR) + { +#ifdef __MINGW32__ + wSoundTimerRes = min(max(tc.wPeriodMin, 1), tc.wPeriodMax); +#else + wSoundTimerRes = min(max(tc.wPeriodMin, 1), tc.wPeriodMax); +#endif + timeBeginPeriod (wSoundTimerRes); + } + else + { + wSoundTimerRes = 5; + timeBeginPeriod (wSoundTimerRes); + } + + QueryPerformanceFrequency((LARGE_INTEGER*)&PCBase); + QueryPerformanceCounter((LARGE_INTEGER*)&PCStart); + PCEnd = PCStart; + PCEndTicks = timeGetTime()*1000; + PCStartTicks = timeGetTime()*1000; + PCFrameTime = PCFrameTimeNTSC = (__int64)((float)PCBase / 59.948743718592964824120603015098f); + PCFrameTimePAL = PCBase / 50; + + + Settings.StopEmulation = TRUE; + GUI.hFrameTimer = timeSetEvent (20, 0, FrameTimer, 0, TIME_PERIODIC); + + if(GUI.JoystickHotkeys || GUI.BackgroundKeyHotkeys) + GUI.hHotkeyTimer = timeSetEvent (32, 0, HotkeyTimer, 0, TIME_PERIODIC); + else + GUI.hHotkeyTimer = 0; + + GUI.FrameTimerSemaphore = CreateSemaphore (NULL, 0, 10, NULL); + GUI.ServerTimerSemaphore = CreateSemaphore (NULL, 0, 10, NULL); + + if (GUI.hFrameTimer == 0) + { + MessageBox( GUI.hWnd, Languages[ GUI.Language].errFrameTimer, TEXT("Snes9X - Frame Timer"), MB_OK | MB_ICONINFORMATION); + } + + Settings.StopEmulation = !LoadROM (rom_filename); + + if (!Settings.StopEmulation) + { + bool8 loaded = Memory.LoadSRAM (S9xGetFilename (".srm", SRAM_DIR)); + if(!loaded) // help migration from earlier Snes9x versions by checking ROM directory for savestates + Memory.LoadSRAM (S9xGetFilename (".srm", ROMFILENAME_DIR)); + S9xLoadCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + CheckDirectoryIsWritable (S9xGetFilename (".---", SNAPSHOT_DIR)); + CheckMenuStates (); + } + + if (!Settings.StopEmulation) + { + if (GUI.ControllerOption == SNES_SUPERSCOPE) + SetCursor (GUI.GunSight); + else + { + SetCursor (GUI.Arrow); + GUI.CursorTimer = 60; + } + } + + S9xUnmapAllControls(); + S9xSetupDefaultKeymap(); + ChangeInputDevice(); + + DWORD lastTime = timeGetTime(); + DWORD sSyncTime,sSyncWaited; + + MSG msg; + + while (TRUE) + { + EnsureInputDisplayUpdated(); + + // note: using GUI.hWnd instead of NULL for PeekMessage/GetMessage breaks some non-modal dialogs + while (Settings.StopEmulation || (Settings.Paused && !Settings.FrameAdvance) || + Settings.ForcedPause || + PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) + { + if (!GetMessage (&msg, NULL, 0, 0)) + goto loop_exit; // got WM_QUIT + + if (!TranslateAccelerator (GUI.hWnd, GUI.Accelerators, &msg)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + + S9xSetSoundMute(Settings.ForcedPause || (Settings.Paused && (!Settings.FrameAdvance || GUI.FAMute))); + } + +#ifdef NETPLAY_SUPPORT + if (!Settings.NetPlay || !NetPlay.PendingWait4Sync || + WaitForSingleObject (GUI.ClientSemaphore, 100) != WAIT_TIMEOUT) + { + if (NetPlay.PendingWait4Sync) + { + NetPlay.PendingWait4Sync = FALSE; + NetPlay.FrameCount++; + S9xNPStepJoypadHistory (); + } +#endif + if(watches[0].on) + { + // copy the memory used by each active watch + for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) + { + if(watches[i].on) + { + int address = watches[i].address - 0x7E0000; + const uint8* source; + if(address < 0x20000) + source = Memory.RAM + address ; + else if(address < 0x30000) + source = Memory.SRAM + address - 0x20000; + else + source = Memory.FillRAM + address - 0x30000; + + CopyMemory(Cheat.CWatchRAM + address, source, watches[i].size); + } + } + } + if(cheatSearchHWND) + { + if(timeGetTime() - lastTime >= 100) + { + SendMessage(cheatSearchHWND, WM_COMMAND, (WPARAM)(IDC_REFRESHLIST),(LPARAM)(NULL)); + lastTime = timeGetTime(); + } + } + + // the following is a hack to allow frametimes greater than 100ms, + // without affecting the responsiveness of the GUI + BOOL run_loop=false; + do_frame_adjust=false; + if (Settings.TurboMode || Settings.FrameAdvance || Settings.SkipFrames != AUTO_FRAMERATE +#ifdef NETPLAY_SUPPORT + || Settings.NetPlay +#endif + ) + { + run_loop=true; + } + else + { + LONG prev; + BOOL success; + if ((success = ReleaseSemaphore (GUI.FrameTimerSemaphore, 1, &prev)) && + prev == 0) + { + WaitForSingleObject (GUI.FrameTimerSemaphore, 0); + if (WaitForSingleObject (GUI.FrameTimerSemaphore, 100) == WAIT_OBJECT_0) + { + run_loop=true; + } + } + else + { + if (success) + WaitForSingleObject (GUI.FrameTimerSemaphore, 0); + WaitForSingleObject (GUI.FrameTimerSemaphore, 0); + + run_loop=true; + do_frame_adjust=true; + } + } + + + if(Settings.FrameAdvance) + { + if(GFX.InfoStringTimeout > 4) + GFX.InfoStringTimeout = 4; + + if(!GUI.FASkipsNonInput) + Settings.FrameAdvance = false; + } + if(GUI.FrameAdvanceJustPressed) + GUI.FrameAdvanceJustPressed--; + + if(run_loop) + { + ProcessInput(); + + sSyncTime=timeGetTime(); + + while(!S9xSyncSound()) { + Sleep(0); + sSyncWaited=timeGetTime(); + if(sSyncWaited-sSyncTime > 1000) { + S9xClearSamples(); + break; + } + } + + S9xMainLoop(); + GUI.FrameCount++; + } + +#ifdef NETPLAY_SUPPORT + } +#endif + if (CPU.Flags & DEBUG_MODE_FLAG) + { + Settings.Paused = TRUE; + Settings.FrameAdvance = false; + CPU.Flags &= ~DEBUG_MODE_FLAG; + } + if (GUI.CursorTimer) + { + if (--GUI.CursorTimer == 0) + { + if(!Settings.SuperScopeMaster) + SetCursor (NULL); + } + } + } + +loop_exit: + + Settings.StopEmulation = TRUE; + + // stop sound playback + CloseSoundDevice(); + + if (GUI.hHotkeyTimer) + timeKillEvent (GUI.hHotkeyTimer); + + if( GUI.hFrameTimer) + { + timeKillEvent (GUI.hFrameTimer); + timeEndPeriod (wSoundTimerRes); + } + + if (!Settings.StopEmulation) + { + Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR)); + S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + } + //if (!VOODOO_MODE && !GUI.FullScreen) + // GetWindowRect (GUI.hWnd, &GUI.window_size); + + + // this goes here, because the avi + // recording might have messed with + // the auto frame skip setting + // (it needs to come before WinSave) + DoAVIClose(0); + + S9xMovieShutdown (); // must happen before saving config + + WinUnlockConfigFile (); + WinSaveConfigFile (); + WinCleanupConfigData(); + + Memory.Deinit(); + + S9xGraphicsDeinit(); + S9xDeinitAPU(); + WinDeleteRecentGamesList (); + DeinitS9x(); + +#ifdef CHECK_MEMORY_LEAKS + _CrtDumpMemoryLeaks(); +#endif + return msg.wParam; +} + +void FreezeUnfreeze (int slot, bool8 freeze) +{ + static TCHAR filename [_MAX_PATH + 1]; + TCHAR drive [_MAX_DRIVE + 1]; + TCHAR dir [_MAX_DIR + 1]; + TCHAR fname [_MAX_FNAME + 1]; + TCHAR ext [_MAX_EXT + 1]; + +#ifdef NETPLAY_SUPPORT + if (!freeze && Settings.NetPlay && !Settings.NetPlayServer) + { + S9xMessage (S9X_INFO, S9X_NETPLAY_NOT_SERVER, + "Only the server is allowed to load freeze files."); + return; + } +#endif + + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + static char *digits = "t123456789"; + for(int oldDir = 0; oldDir <= 1; oldDir++) + { + for(int zmv = 0; zmv <= 1; zmv++) + { + if((!oldDir && !zmv) || (!freeze && _access (filename, 0) != 0 && slot < 10)) + { + if(!zmv) + sprintf (ext, TEXT(".%03d"), slot); + else + sprintf (ext, TEXT(".zs%c"), digits [slot]); + if (GUI.FreezeFileDir [0]) + { + strcpy (filename, oldDir ? S9xGetDirectory(ROMFILENAME_DIR) : S9xGetDirectory(SNAPSHOT_DIR)); + strcat (filename, TEXT("\\")); + strcat (filename, fname); + strcat (filename, ext); + } + else + _makepath (filename, drive, dir, fname, ext); + } + } + } + + S9xSetPause (PAUSE_FREEZE_FILE); + + if (freeze) + { +// extern bool diagnostic_freezing; +// if(GetAsyncKeyState('Q') && GetAsyncKeyState('W') && GetAsyncKeyState('E') && GetAsyncKeyState('R')) +// { +// diagnostic_freezing = true; +// } + S9xFreezeGame (filename); +// +// diagnostic_freezing = false; + } + else + { + + if (S9xUnfreezeGame (filename)) + { +// S9xMessage (S9X_INFO, S9X_FREEZE_FILE_INFO, S9xBasename (filename)); +#ifdef NETPLAY_SUPPORT + S9xNPServerQueueSendingFreezeFile (filename); +#endif +// UpdateBackBuffer(); + } + + // fix next frame advance after loading non-skipping state from a skipping state + skipNextFrameStop = true; + } + + S9xClearPause (PAUSE_FREEZE_FILE); +} + +void CheckDirectoryIsWritable (const char *filename) +{ + FILE *fs = fopen (filename, "w+"); + + if (fs == NULL) + MessageBox (GUI.hWnd, TEXT("The folder where Snes9X saves emulated save RAM files and\ngame save positions (freeze files) is currently set to a\nread-only folder.\n\nIf you do not change the game save folder, Snes9X will be\nunable to save your progress in this game. Change the folder\nfrom the Settings Dialog available from the Options menu.\n\nThe default save folder is called Saves, if no value is set.\n"), + TEXT("Snes9X: Unable to save file warning"), + MB_OK | MB_ICONINFORMATION); + else + { + fclose (fs); + remove (filename); + } +} + +static void CheckMenuStates () +{ + MENUITEMINFO mii; + unsigned int i; + + ZeroMemory( &mii, sizeof( mii)); + mii.cbSize = sizeof( mii); + mii.fMask = MIIM_STATE; + + mii.fState = (GUI.FullScreen||GUI.EmulatedFullscreen) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_WINDOW_FULLSCREEN, FALSE, &mii); + + mii.fState = GUI.Stretch ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_WINDOW_STRETCH, FALSE, &mii); + + mii.fState = GUI.Stretch ? (GUI.AspectRatio ? MFS_CHECKED : MFS_UNCHECKED) : MFS_CHECKED|MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_WINDOW_ASPECTRATIO, FALSE, &mii); + + mii.fState = GUI.BilinearFilter ? MFS_CHECKED : MFS_UNCHECKED; + if(!GUI.Stretch) + mii.fState |= MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_WINDOW_VIDMEM, FALSE, &mii); + + mii.fState = (Settings.Paused && !Settings.StopEmulation) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_FILE_PAUSE, FALSE, &mii); + + mii.fState = MFS_UNCHECKED; + if (Settings.StopEmulation) + mii.fState |= MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE_SRAM_DATA, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE1, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE2, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE3, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE4, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE5, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE6, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE7, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE8, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_SAVE9, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD1, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD2, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD3, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD4, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD5, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD6, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD7, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD8, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_LOAD9, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_RESET, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_CHEAT_ENTER, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_CHEAT_SEARCH_MODAL, FALSE, &mii); + + if (GUI.FullScreen) + mii.fState |= MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_CHEAT_SEARCH, FALSE, &mii); + +#ifdef NETPLAY_SUPPORT + if (Settings.NetPlay && !Settings.NetPlayServer) + mii.fState = MFS_DISABLED; + else + mii.fState = Settings.NetPlayServer ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_SERVER, FALSE, &mii); + + mii.fState = Settings.NetPlay && !Settings.NetPlayServer ? 0 : MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_DISCONNECT, FALSE, &mii); + + mii.fState = Settings.NetPlay || Settings.NetPlayServer ? MFS_DISABLED : 0; + SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_CONNECT, FALSE, &mii); + + mii.fState = NPServer.SendROMImageOnConnect ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_SEND_ROM_ON_CONNECT, FALSE, &mii); + + mii.fState = NPServer.SyncByReset ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_SYNC_BY_RESET, FALSE, &mii); + + mii.fState = Settings.NetPlayServer ? 0 : MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_SYNC, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_NETPLAY_ROM, FALSE, &mii); +#endif + + mii.fState = Settings.ApplyCheats ? MFS_CHECKED : MFS_UNCHECKED; + if (Settings.StopEmulation) + mii.fState |= MFS_DISABLED; + SetMenuItemInfo( GUI.hMenu, ID_CHEAT_APPLY, FALSE, &mii); + + mii.fState = MFS_UNCHECKED; + if (GUI.AVIOut) + mii.fState |= MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_SOUND_OPTIONS, FALSE, &mii); + + SetMenuItemInfo (GUI.hMenu, ID_SOUND_NOSOUND, FALSE, &mii); + for (i = 0; i < COUNT(SoundRates); i++) + SetMenuItemInfo (GUI.hMenu, SoundRates[i].ident, FALSE, &mii); + + if (Settings.SoundPlaybackRate == 0 || GUI.Mute) + mii.fState |= MFS_DISABLED; + + SetMenuItemInfo (GUI.hMenu, ID_SOUND_16BIT, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_STEREO, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_SYNC, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_INTERPOLATED, FALSE, &mii); + + SetMenuItemInfo (GUI.hMenu, ID_SOUND_16MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_32MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_48MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_64MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_80MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_96MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_112MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_128MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_144MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_160MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_176MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_194MS, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_SOUND_210MS, FALSE, &mii); + + if (!Settings.Stereo) + mii.fState |= MFS_DISABLED; + + SetMenuItemInfo (GUI.hMenu, ID_SOUND_REVERSE_STEREO, FALSE, &mii); + + mii.fState = MFS_CHECKED; + if (GUI.AVIOut) + mii.fState |= MFS_DISABLED; + + if (Settings.SoundPlaybackRate == 0 || GUI.Mute ) + SetMenuItemInfo (GUI.hMenu, ID_SOUND_NOSOUND, FALSE, &mii); + else + { + for (i = 0; i < COUNT(SoundRates); i++) + { + if (SoundRates [i].rate == Settings.SoundPlaybackRate) + { + SetMenuItemInfo (GUI.hMenu, SoundRates[i].ident, FALSE, &mii); + break; + } + } + } + if (Settings.SoundPlaybackRate == 0 || GUI.Mute) + mii.fState |= MFS_DISABLED; + + int id; + switch (GUI.SoundBufferSize) + { + case 16: id = ID_SOUND_16MS; break; + case 32: id = ID_SOUND_32MS; break; + case 48: id = ID_SOUND_48MS; break; + case 64: id = ID_SOUND_64MS; break; + case 80: id = ID_SOUND_80MS; break; + case 96: id = ID_SOUND_96MS; break; + case 112: id = ID_SOUND_112MS; break; + case 128: id = ID_SOUND_128MS; break; + case 144: id = ID_SOUND_144MS; break; + case 160: id = ID_SOUND_160MS; break; + case 176: id = ID_SOUND_176MS; break; + case 194: id = ID_SOUND_194MS; break; + case 210: id = ID_SOUND_210MS; break; + } + SetMenuItemInfo (GUI.hMenu, id, FALSE, &mii); + + if (Settings.SixteenBitSound) + SetMenuItemInfo (GUI.hMenu, ID_SOUND_16BIT, FALSE, &mii); + if (Settings.Stereo) + SetMenuItemInfo (GUI.hMenu, ID_SOUND_STEREO, FALSE, &mii); + if (Settings.SoundSync) + SetMenuItemInfo (GUI.hMenu, ID_SOUND_SYNC, FALSE, &mii); + + if (!Settings.Stereo) + mii.fState |= MFS_DISABLED; + if (Settings.ReverseStereo) + SetMenuItemInfo (GUI.hMenu, ID_SOUND_REVERSE_STEREO, FALSE, &mii); + +#ifndef DEBUGGER + mii.fState = MFS_DISABLED; +#else + mii.fState = MFS_UNCHECKED; +#endif + SetMenuItemInfo (GUI.hMenu, ID_DEBUG_TRACE, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_DEBUG_TRACE_SPC, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_DEBUG_TRACE_SA1, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_DEBUG_TRACE_DSP1, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_DEBUG_FRAME_ADVANCE, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_DEBUG_SNES_STATUS, FALSE, &mii); + + mii.fState = (!Settings.StopEmulation) ? MFS_ENABLED : MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_FILE_MOVIE_PLAY, FALSE, &mii); + SetMenuItemInfo (GUI.hMenu, ID_FILE_MOVIE_RECORD, FALSE, &mii); + + mii.fState = (S9xMovieActive () && !Settings.StopEmulation) ? MFS_ENABLED : MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_FILE_MOVIE_STOP, FALSE, &mii); + + mii.fState = (!Settings.StopEmulation) ? MFS_ENABLED : MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_FILE_WRITE_AVI, FALSE, &mii); + + mii.fState = (!Settings.StopEmulation && (GUI.AVIOut)) ? MFS_ENABLED : MFS_DISABLED; + SetMenuItemInfo (GUI.hMenu, ID_FILE_STOP_AVI, FALSE, &mii); + + mii.fState = (GUI.SoundChannelEnable & (1 << 0)) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL1, FALSE, &mii); + mii.fState = (GUI.SoundChannelEnable & (1 << 1)) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL2, FALSE, &mii); + mii.fState = (GUI.SoundChannelEnable & (1 << 2)) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL3, FALSE, &mii); + mii.fState = (GUI.SoundChannelEnable & (1 << 3)) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL4, FALSE, &mii); + mii.fState = (GUI.SoundChannelEnable & (1 << 4)) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL5, FALSE, &mii); + mii.fState = (GUI.SoundChannelEnable & (1 << 5)) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL6, FALSE, &mii); + mii.fState = (GUI.SoundChannelEnable & (1 << 6)) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL7, FALSE, &mii); + mii.fState = (GUI.SoundChannelEnable & (1 << 7)) ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo (GUI.hMenu, ID_CHANNELS_CHANNEL8, FALSE, &mii); + + UINT validFlag; + enum controllers controller[2]; + int8 ids[4]; + S9xGetController(0, &controller[0], &ids[0],&ids[1],&ids[2],&ids[3]); + S9xGetController(1, &controller[1], &ids[0],&ids[1],&ids[2],&ids[3]); + + validFlag = (((1< 0; j--) + strcpy(GUI.RecentGames[j], GUI.RecentGames[j-1]); + + strcpy(GUI.RecentGames[0], temp); + } + else + { + // Not in the list, add it. + if(underMax) + // Extend the recent game list length by 1. + memmove(&GUI.RecentGames[1], &GUI.RecentGames[0], MAX_PATH*i); + else + // Throw the last item off the end of the list + memmove(&GUI.RecentGames[1], &GUI.RecentGames[0], MAX_PATH*(i-1)); + + strcpy(GUI.RecentGames[0], filename); + + WinSaveConfigFile(); + } + + S9xSetRecentGames(); +} + +void S9xRemoveFromRecentGames (int i) +{ + if (*GUI.RecentGames [i]) + { + for (int j = i; j < MAX_RECENT_GAMES_LIST_SIZE-1; j++) + strcpy(GUI.RecentGames [j], GUI.RecentGames [j + 1]); + *GUI.RecentGames [MAX_RECENT_GAMES_LIST_SIZE-1] = '\0'; + + S9xSetRecentGames (); + } +} + +void S9xSetRecentGames () +{ + HMENU file = GetSubMenu (GUI.hMenu, 0); + if (file) + { + HMENU recent = GetSubMenu (file, 1); + if (recent) + { + MENUITEMINFO mii; + TCHAR name [256 + 10]; + int i; + + // Clear out the menu first + for (i = GetMenuItemCount (recent) - 1; i >= 0; i--) + RemoveMenu (recent, i, MF_BYPOSITION); + + mii.cbSize = sizeof (mii); + mii.fMask = MIIM_TYPE | MIIM_DATA | MIIM_STATE | MIIM_ID; + mii.fType = MFT_STRING; + mii.fState = MFS_UNCHECKED; + + for (i = 0; i < MAX_RECENT_GAMES_LIST_SIZE && i < GUI.MaxRecentGames && *GUI.RecentGames [i]; i++) + { + // Build up a menu item string in the form: + // 1. + + sprintf (name, TEXT("&%c. "), i < 9 ? '1' + i : 'A' + i - 9); + + // append the game title to name, with formatting modifications as necessary + { + TCHAR baseName [256]; + strcpy (baseName, S9xBasename (GUI.RecentGames [i])); + int pos = strlen (name), baseNameLen = strlen (baseName); + for (int j = 0; j < baseNameLen ; j++) + { + char c = baseName [j]; + name [pos++] = c; + + // & is a special character in Windows menus, + // so we have to change & to && when copying over the game title + // otherwise "Pocky & Rocky (U).smc" will show up as "Pocky _Rocky (U).smc", for example + if(c == '&') + name [pos++] = '&'; + } + name [pos] = '\0'; + } + + mii.dwTypeData = name; + mii.cch = strlen (name) + 1; + mii.wID = 0xFF00 + i; + + InsertMenuItem (recent, 0xFF00 + i, FALSE, &mii); + } + } + } +} + +void WinDeleteRecentGamesList () +{ + for(int i=0;i0?sliderVal:32000; + + WinSaveConfigFile(); + + // already done in WinProc on return + // ReInitSound(); + + } /* FALL THROUGH */ + + case IDCANCEL: + EndDialog(hDlg, 1); + return true; + + case IDC_DRIVER: + if(CBN_SELCHANGE==HIWORD(wParam)) + { + int driver=SendDlgItemMessage(hDlg, IDC_DRIVER, CB_GETITEMDATA, + SendDlgItemMessage(hDlg, IDC_DRIVER, CB_GETCURSEL, 0,0),0); + switch(driver) { + case WIN_SNES9X_DIRECT_SOUND_DRIVER: + SendDlgItemMessage(hDlg,IDC_BUFLEN,CB_SETCURSEL,3,0); + break; + case WIN_XAUDIO2_SOUND_DRIVER: + SendDlgItemMessage(hDlg,IDC_BUFLEN,CB_SETCURSEL,3,0); + break; + default: + SendDlgItemMessage(hDlg,IDC_BUFLEN,CB_SETCURSEL,7,0); + break; + } + return true; + } + else return false; + case IDC_STEREO: + { + if(BN_CLICKED==HIWORD(wParam)||BN_DBLCLK==HIWORD(wParam)) + { + if(IsDlgButtonChecked(hDlg,IDC_STEREO)) + { + EnableWindow(GetDlgItem(hDlg, IDC_REV_STEREO), TRUE); + } + else EnableWindow(GetDlgItem(hDlg, IDC_REV_STEREO), FALSE); + return true; + + } + else return false; + } + case IDC_INRATEEDIT: + if(HIWORD(wParam)==EN_UPDATE) { + Edit_GetText(GetDlgItem(hDlg,IDC_INRATEEDIT),valTxt,10); + int sliderVal=_tstoi(valTxt); + SendDlgItemMessage(hDlg, IDC_INRATE, TBM_SETPOS,TRUE,(sliderVal - 31100)/50); + } + break; + default: return false; + + + } + } + return false; +} + +// SetSelProc +// Callback procedure to set the initial selection of the (folder) browser. +int CALLBACK SetSelProc( HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData ) +{ + if (uMsg==BFFM_INITIALIZED) { + ::SendMessage(hWnd, BFFM_SETSELECTION, TRUE, lpData ); + } + return 0; +} + +const char *StaticRAMBitSize () +{ + static char tmp [20]; + + sprintf (tmp, " (%dKbit)", 8*(Memory.SRAMMask + 1) / 1024); + return (tmp); +} + +int CALLBACK DlgInfoProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG: + WinRefreshDisplay(); + { + char temp[100]; + char romtext[4096]; + sprintf(romtext, "File: %s\r\nName: %s\r\n", Memory.ROMFilename, Memory.ROMName); + sprintf(temp, "Speed: %02X/%s\r\nROM Map: %s\r\nType: %02x\r\n", Memory.ROMSpeed, ((Memory.ROMSpeed&0x10)!=0)?"FastROM":"SlowROM",(Memory.HiROM)?"HiROM":"LoROM",Memory.ROMType); + strcat(romtext, temp); + strcat(romtext, "Kart contents: "); + strcat(romtext, Memory.KartContents ()); + strcat(romtext, "\r\nHeader ROM Size: "); + strcat(romtext, Memory.Size()); + sprintf(temp, "\r\nCalculated ROM Size: %d Mbits", Memory.CalculatedSize/0x20000); + strcat(romtext, temp); + + strcat(romtext, "\r\nSRAM size: "); + strcat(romtext, Memory.StaticRAMSize ()); + strcat(romtext, StaticRAMBitSize()); + strcat(romtext, "\r\nActual Checksum: "); + sprintf(temp, "%04X", Memory.CalculatedChecksum); + strcat(romtext, temp); + strcat(romtext, "\r\nHeader Checksum: "); + sprintf(temp, "%04X", Memory.ROMChecksum); + strcat(romtext, temp); + strcat(romtext, "\r\nHeader Checksum Compliment: "); + sprintf(temp, "%04X", Memory.ROMComplementChecksum); + strcat(romtext, temp); + strcat(romtext, "\r\nOutput: "); + if(Memory.ROMRegion>12||Memory.ROMRegion<2) + strcat(romtext, "NTSC 60Hz"); + else strcat(romtext, "PAL 50Hz"); + + sprintf(temp, "\r\nCRC32:\t%08X", Memory.ROMCRC32); + strcat(romtext, temp); + + + strcat(romtext, "\r\nLicensee: "); + + int tmp=Memory.CompanyId; + if(tmp==0) + tmp=(Memory.HiROM)?Memory.ROM[0x0FFDA]:Memory.ROM[0x7FDA]; + switch(tmp) + // switch(((Memory.ROMSpeed&0x0F)!=0)?Memory.ROM[0x0FFDA]:Memory.ROM[0x7FDA]) + // switch(atoi(Memory.CompanyId)) + // switch(((Memory.CompanyId[0]-'0')*16)+(Memory.CompanyId[1]-'0')) + { + case 0:strcat(romtext, "INVALID COMPANY");break; + case 1:strcat(romtext, "Nintendo");break; + case 2:strcat(romtext, "Ajinomoto");break; + case 3:strcat(romtext, "Imagineer-Zoom");break; + case 4:strcat(romtext, "Chris Gray Enterprises Inc.");break; + case 5:strcat(romtext, "Zamuse");break; + case 6:strcat(romtext, "Falcom");break; + case 7:strcat(romtext, NOTKNOWN "7");break; + case 8:strcat(romtext, "Capcom");break; + case 9:strcat(romtext, "HOT-B");break; + case 10:strcat(romtext, "Jaleco");break; + case 11:strcat(romtext, "Coconuts");break; + case 12:strcat(romtext, "Rage Software");break; + case 13:strcat(romtext, "Micronet"); break; //Acc. ZFE + case 14:strcat(romtext, "Technos");break; + case 15:strcat(romtext, "Mebio Software");break; + case 16:strcat(romtext, "SHOUEi System"); break; //Acc. ZFE + case 17:strcat(romtext, "Starfish");break; //UCON 64 + case 18:strcat(romtext, "Gremlin Graphics");break; + case 19:strcat(romtext, "Electronic Arts");break; + case 20:strcat(romtext, "NCS / Masaya"); break; //Acc. ZFE + case 21:strcat(romtext, "COBRA Team");break; + case 22:strcat(romtext, "Human/Field");break; + case 23:strcat(romtext, "KOEI");break; + case 24:strcat(romtext, "Hudson Soft");break; + case 25:strcat(romtext, "Game Village");break;//uCON64 + case 26:strcat(romtext, "Yanoman");break; + case 27:strcat(romtext, NOTKNOWN "27");break; + case 28:strcat(romtext, "Tecmo");break; + case 29:strcat(romtext, NOTKNOWN "29");break; + case 30:strcat(romtext, "Open System");break; + case 31:strcat(romtext, "Virgin Games");break; + case 32:strcat(romtext, "KSS");break; + case 33:strcat(romtext, "Sunsoft");break; + case 34:strcat(romtext, "POW");break; + case 35:strcat(romtext, "Micro World");break; + case 36:strcat(romtext, NOTKNOWN "36");break; + case 37:strcat(romtext, NOTKNOWN "37");break; + case 38:strcat(romtext, "Enix");break; + case 39:strcat(romtext, "Loriciel/Electro Brain");break;//uCON64 + case 40:strcat(romtext, "Kemco");break; + case 41:strcat(romtext, "Seta Co.,Ltd.");break; + case 42:strcat(romtext, "Culture Brain"); break; //Acc. ZFE + case 43:strcat(romtext, "Irem Japan");break;//Irem? Gun Force J + case 44:strcat(romtext, "Pal Soft"); break; //Acc. ZFE + case 45:strcat(romtext, "Visit Co.,Ltd.");break; + case 46:strcat(romtext, "INTEC Inc."); break; //Acc. ZFE + case 47:strcat(romtext, "System Sacom Corp."); break; //Acc. ZFE + case 48:strcat(romtext, "Viacom New Media");break; //Zoop! + case 49:strcat(romtext, "Carrozzeria");break; + case 50:strcat(romtext, "Dynamic");break; + case 51:strcat(romtext, "Nintendo");break; + case 52:strcat(romtext, "Magifact");break; + case 53:strcat(romtext, "Hect");break; + case 54:strcat(romtext, NOTKNOWN "54");break; + case 55:strcat(romtext, NOTKNOWN "55");break; + case 56:strcat(romtext, "Capcom Europe");break;//Capcom? BOF2(E) MM7 (E) + case 57:strcat(romtext, "Accolade Europe");break;//Accolade?Bubsy 2 (E) + case 58:strcat(romtext, NOTKNOWN "58");break; + case 59:strcat(romtext, "Arcade Zone");break;//uCON64 + case 60:strcat(romtext, "Empire Software");break; + case 61:strcat(romtext, "Loriciel");break; + case 62:strcat(romtext, "Gremlin Graphics"); break; //Acc. ZFE + case 63:strcat(romtext, NOTKNOWN "63");break; + case 64:strcat(romtext, "Seika Corp.");break; + case 65:strcat(romtext, "UBI Soft");break; + case 66:strcat(romtext, NOTKNOWN "66");break; + case 67:strcat(romtext, NOTKNOWN "67");break; + case 68:strcat(romtext, "LifeFitness Exertainment");break;//?? Exertainment Mountain Bike Rally (U).zip + case 69:strcat(romtext, NOTKNOWN "69");break; + case 70:strcat(romtext, "System 3");break; + case 71:strcat(romtext, "Spectrum Holobyte");break; + case 72:strcat(romtext, NOTKNOWN "72");break; + case 73:strcat(romtext, "Irem");break; + case 74:strcat(romtext, NOTKNOWN "74");break; + case 75:strcat(romtext, "Raya Systems/Sculptured Software");break; + case 76:strcat(romtext, "Renovation Products");break; + case 77:strcat(romtext, "Malibu Games/Black Pearl");break; + case 78:strcat(romtext, NOTKNOWN "78");break; + case 79:strcat(romtext, "U.S. Gold");break; + case 80:strcat(romtext, "Absolute Entertainment");break; + case 81:strcat(romtext, "Acclaim");break; + case 82:strcat(romtext, "Activision");break; + case 83:strcat(romtext, "American Sammy");break; + case 84:strcat(romtext, "GameTek");break; + case 85:strcat(romtext, "Hi Tech Expressions");break; + case 86:strcat(romtext, "LJN Toys");break; + case 87:strcat(romtext, NOTKNOWN "87");break; + case 88:strcat(romtext, NOTKNOWN "88");break; + case 89:strcat(romtext, NOTKNOWN "89");break; + case 90:strcat(romtext, "Mindscape");break; + case 91:strcat(romtext, "Romstar, Inc."); break; //Acc. ZFE + case 92:strcat(romtext, NOTKNOWN "92");break; + case 93:strcat(romtext, "Tradewest");break; + case 94:strcat(romtext, NOTKNOWN "94");break; + case 95:strcat(romtext, "American Softworks Corp.");break; + case 96:strcat(romtext, "Titus");break; + case 97:strcat(romtext, "Virgin Interactive Entertainment");break; + case 98:strcat(romtext, "Maxis");break; + case 99:strcat(romtext, "Origin/FCI/Pony Canyon");break;//uCON64 + case 100:strcat(romtext, NOTKNOWN "100");break; + case 101:strcat(romtext, NOTKNOWN "101");break; + case 102:strcat(romtext, NOTKNOWN "102");break; + case 103:strcat(romtext, "Ocean");break; + case 104:strcat(romtext, NOTKNOWN "104");break; + case 105:strcat(romtext, "Electronic Arts");break; + case 106:strcat(romtext, NOTKNOWN "106");break; + case 107:strcat(romtext, "Laser Beam");break; + case 108:strcat(romtext, NOTKNOWN "108");break; + case 109:strcat(romtext, NOTKNOWN "109");break; + case 110:strcat(romtext, "Elite");break; + case 111:strcat(romtext, "Electro Brain");break; + case 112:strcat(romtext, "Infogrames");break; + case 113:strcat(romtext, "Interplay");break; + case 114:strcat(romtext, "LucasArts");break; + case 115:strcat(romtext, "Parker Brothers");break; + case 116:strcat(romtext, "Konami");break;//uCON64 + case 117:strcat(romtext, "STORM");break; + case 118:strcat(romtext, NOTKNOWN "118");break; + case 119:strcat(romtext, NOTKNOWN "119");break; + case 120:strcat(romtext, "THQ Software");break; + case 121:strcat(romtext, "Accolade Inc.");break; + case 122:strcat(romtext, "Triffix Entertainment");break; + case 123:strcat(romtext, NOTKNOWN "123");break; + case 124:strcat(romtext, "Microprose");break; + case 125:strcat(romtext, NOTKNOWN "125");break; + case 126:strcat(romtext, NOTKNOWN "126");break; + case 127:strcat(romtext, "Kemco");break; + case 128:strcat(romtext, "Misawa");break; + case 129:strcat(romtext, "Teichio");break; + case 130:strcat(romtext, "Namco Ltd.");break; + case 131:strcat(romtext, "Lozc");break; + case 132:strcat(romtext, "Koei");break; + case 133:strcat(romtext, NOTKNOWN "133");break; + case 134:strcat(romtext, "Tokuma Shoten Intermedia");break; + case 135:strcat(romtext, "Tsukuda Original"); break; //Acc. ZFE + case 136:strcat(romtext, "DATAM-Polystar");break; + case 137:strcat(romtext, NOTKNOWN "137");break; + case 138:strcat(romtext, NOTKNOWN "138");break; + case 139:strcat(romtext, "Bullet-Proof Software");break; + case 140:strcat(romtext, "Vic Tokai");break; + case 141:strcat(romtext, NOTKNOWN "141");break; + case 142:strcat(romtext, "Character Soft");break; + case 143:strcat(romtext, "I\'\'Max");break; + case 144:strcat(romtext, "Takara");break; + case 145:strcat(romtext, "CHUN Soft");break; + case 146:strcat(romtext, "Video System Co., Ltd.");break; + case 147:strcat(romtext, "BEC");break; + case 148:strcat(romtext, NOTKNOWN "148");break; + case 149:strcat(romtext, "Varie");break; + case 150:strcat(romtext, "Yonezawa / S'Pal Corp."); break; //Acc. ZFE + case 151:strcat(romtext, "Kaneco");break; + case 152:strcat(romtext, NOTKNOWN "152");break; + case 153:strcat(romtext, "Pack in Video");break; + case 154:strcat(romtext, "Nichibutsu");break; + case 155:strcat(romtext, "TECMO");break; + case 156:strcat(romtext, "Imagineer Co.");break; + case 157:strcat(romtext, NOTKNOWN "157");break; + case 158:strcat(romtext, NOTKNOWN "158");break; + case 159:strcat(romtext, NOTKNOWN "159");break; + case 160:strcat(romtext, "Telenet");break; + case 161:strcat(romtext, "Hori"); break; //Acc. uCON64 + case 162:strcat(romtext, NOTKNOWN "162");break; + case 163:strcat(romtext, NOTKNOWN "163");break; + case 164:strcat(romtext, "Konami");break; + case 165:strcat(romtext, "K.Amusement Leasing Co.");break; + case 166:strcat(romtext, NOTKNOWN "166");break; + case 167:strcat(romtext, "Takara");break; + case 168:strcat(romtext, NOTKNOWN "168");break; + case 169:strcat(romtext, "Technos Jap.");break; + case 170:strcat(romtext, "JVC");break; + case 171:strcat(romtext, NOTKNOWN "171");break; + case 172:strcat(romtext, "Toei Animation");break; + case 173:strcat(romtext, "Toho");break; + case 174:strcat(romtext, NOTKNOWN "174");break; + case 175:strcat(romtext, "Namco Ltd.");break; + case 176:strcat(romtext, "Media Rings Corp."); break; //Acc. ZFE + case 177:strcat(romtext, "ASCII Co. Activison");break; + case 178:strcat(romtext, "Bandai");break; + case 179:strcat(romtext, NOTKNOWN "179");break; + case 180:strcat(romtext, "Enix America");break; + case 181:strcat(romtext, NOTKNOWN "181");break; + case 182:strcat(romtext, "Halken");break; + case 183:strcat(romtext, NOTKNOWN "183");break; + case 184:strcat(romtext, NOTKNOWN "184");break; + case 185:strcat(romtext, NOTKNOWN "185");break; + case 186:strcat(romtext, "Culture Brain");break; + case 187:strcat(romtext, "Sunsoft");break; + case 188:strcat(romtext, "Toshiba EMI");break; + case 189:strcat(romtext, "Sony Imagesoft");break; + case 190:strcat(romtext, NOTKNOWN "190");break; + case 191:strcat(romtext, "Sammy");break; + case 192:strcat(romtext, "Taito");break; + case 193:strcat(romtext, NOTKNOWN "193");break; + case 194:strcat(romtext, "Kemco");break; + case 195:strcat(romtext, "Square");break; + case 196:strcat(romtext, "Tokuma Soft");break; + case 197:strcat(romtext, "Data East");break; + case 198:strcat(romtext, "Tonkin House");break; + case 199:strcat(romtext, NOTKNOWN "199");break; + case 200:strcat(romtext, "KOEI");break; + case 201:strcat(romtext, NOTKNOWN "201");break; + case 202:strcat(romtext, "Konami USA");break; + case 203:strcat(romtext, "NTVIC");break; + case 204:strcat(romtext, NOTKNOWN "204");break; + case 205:strcat(romtext, "Meldac");break; + case 206:strcat(romtext, "Pony Canyon");break; + case 207:strcat(romtext, "Sotsu Agency/Sunrise");break; + case 208:strcat(romtext, "Disco/Taito");break; + case 209:strcat(romtext, "Sofel");break; + case 210:strcat(romtext, "Quest Corp.");break; + case 211:strcat(romtext, "Sigma");break; + case 212:strcat(romtext, "Ask Kodansha Co., Ltd."); break; //Acc. ZFE + case 213:strcat(romtext, NOTKNOWN "213");break; + case 214:strcat(romtext, "Naxat");break; + case 215:strcat(romtext, NOTKNOWN "215");break; + case 216:strcat(romtext, "Capcom Co., Ltd.");break; + case 217:strcat(romtext, "Banpresto");break; + case 218:strcat(romtext, "Tomy");break; + case 219:strcat(romtext, "Acclaim");break; + case 220:strcat(romtext, NOTKNOWN "220");break; + case 221:strcat(romtext, "NCS");break; + case 222:strcat(romtext, "Human Entertainment");break; + case 223:strcat(romtext, "Altron");break; + case 224:strcat(romtext, "Jaleco");break; + case 225:strcat(romtext, NOTKNOWN "225");break; + case 226:strcat(romtext, "Yutaka");break; + case 227:strcat(romtext, NOTKNOWN "227");break; + case 228:strcat(romtext, "T&ESoft");break; + case 229:strcat(romtext, "EPOCH Co.,Ltd.");break; + case 230:strcat(romtext, NOTKNOWN "230");break; + case 231:strcat(romtext, "Athena");break; + case 232:strcat(romtext, "Asmik");break; + case 233:strcat(romtext, "Natsume");break; + case 234:strcat(romtext, "King Records");break; + case 235:strcat(romtext, "Atlus");break; + case 236:strcat(romtext, "Sony Music Entertainment");break; + case 237:strcat(romtext, NOTKNOWN "237");break; + case 238:strcat(romtext, "IGS");break; + case 239:strcat(romtext, NOTKNOWN "239");break; + case 240:strcat(romtext, NOTKNOWN "240");break; + case 241:strcat(romtext, "Motown Software");break; + case 242:strcat(romtext, "Left Field Entertainment");break; + case 243:strcat(romtext, "Beam Software");break; + case 244:strcat(romtext, "Tec Magik");break; + case 245:strcat(romtext, NOTKNOWN "245");break; + case 246:strcat(romtext, NOTKNOWN "246");break; + case 247:strcat(romtext, NOTKNOWN "247");break; + case 248:strcat(romtext, NOTKNOWN "248");break; + case 249:strcat(romtext, "Cybersoft");break; + case 250:strcat(romtext, NOTKNOWN "250");break; + case 251:strcat(romtext, "Psygnosis"); break; //Acc. ZFE + case 252:strcat(romtext, NOTKNOWN "252");break; + case 253:strcat(romtext, NOTKNOWN "253");break; + case 254:strcat(romtext, "Davidson"); break; //Acc. uCON64 + case 255:strcat(romtext, NOTKNOWN "255");break; + default:strcat(romtext, NOTKNOWN);break; + } + + strcat(romtext, "\r\nROM Version: "); + sprintf(temp, "1.%d", (Memory.HiROM)?Memory.ROM[0x0FFDB]:Memory.ROM[0x7FDB]); + strcat(romtext, temp); + strcat(romtext, "\r\nRegion: "); + switch(Memory.ROMRegion) + { + case 0: + strcat(romtext, "Japan"); + break; + case 1: + strcat(romtext, "USA/Canada"); + break; + case 2: + strcat(romtext, "Oceania, Europe, and Asia"); + break; + case 3: + strcat(romtext, "Sweden"); + break; + case 4: + strcat(romtext, "Finland"); + break; + case 5: + strcat(romtext, "Denmark"); + break; + case 6: + strcat(romtext, "France"); + break; + case 7: + strcat(romtext, "Holland"); + break; + case 8: + strcat(romtext, "Spain"); + break; + case 9: + strcat(romtext, "Germany, Austria, and Switzerland"); + break; + case 10: + strcat(romtext, "Italy"); + break; + case 11: + strcat(romtext, "Hong Kong and China"); + break; + case 12: + strcat(romtext, "Indonesia"); + break; + case 13: + strcat(romtext, "South Korea"); + break; + case 14:strcat(romtext, "Unknown region 14");break; + default:strcat(romtext, "Unknown region 15");break; + } + SendDlgItemMessage(hDlg, IDC_ROM_DATA, WM_SETTEXT, 0, (LPARAM)romtext); + return true; + break; + } + case WM_CTLCOLORSTATIC: + + if(GUI.InfoColor!=WIN32_WHITE) + { + SetTextColor((HDC)wParam, GUI.InfoColor); + SetBkColor((HDC)wParam, RGB(0,0,0)); + } + return true;break; + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint (hDlg, &ps); + + EndPaint (hDlg, &ps); + } + return true; + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + EndDialog(hDlg, 0); + return true; + break; + default: return false; break; + } + } + default:return false; + } +} + +int CALLBACK DlgAboutProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + + switch(msg) + { + case WM_INITDIALOG: + WinRefreshDisplay(); + { + TCHAR buf[2048];//find better way of dealing. + sprintf(buf,TEXT(DISCLAIMER_TEXT),VERSION); + SetDlgItemText(hDlg, IDC_DISCLAIMER, buf); + SetWindowText(hDlg, TEXT(ABOUT_DIALOG_TITLE) TEXT(APP_NAME)); + } + return true; + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint (hDlg, &ps); + + EndPaint (hDlg, &ps); + } + return true; + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + EndDialog(hDlg, 0); + return true; + break; + default: return false; break; + } + } + default:return false; + } +} +int CALLBACK DlgEmulatorProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static char paths[8][MAX_PATH]; + static int which = 0; + switch(msg) + { + case WM_INITDIALOG: + WinRefreshDisplay(); + { + SetWindowText(hDlg, TEXT(EMUSET_TITLE)); + SetDlgItemText(hDlg, IDC_TOGGLE_TURBO, EMUSET_TOGGLE_TURBO); + SetDlgItemText(hDlg, IDC_LABEL_FREEZE, EMUSET_LABEL_DIRECTORY); + SetDlgItemText(hDlg, IDOK, BUTTON_OK); + SetDlgItemText(hDlg, IDCANCEL, BUTTON_CANCEL); + SetDlgItemText(hDlg, IDC_LABEL_ASRAM, EMUSET_LABEL_ASRAM); + SetDlgItemText(hDlg, IDC_LABEL_ASRAM_TEXT, EMUSET_LABEL_ASRAM_TEXT); + SetDlgItemText(hDlg, IDC_LABEL_SMAX, EMUSET_LABEL_SMAX); + SetDlgItemText(hDlg, IDC_LABEL_SMAX_TEXT, EMUSET_LABEL_SMAX_TEXT); + SetDlgItemText(hDlg, IDC_LABEL_STURBO_TEXT, EMUSET_LABEL_STURBO_TEXT); + SetDlgItemText(hDlg, IDC_LABEL_STURBO, EMUSET_LABEL_STURBO); + SetDlgItemText(hDlg, IDC_BROWSE, EMUSET_BROWSE); + SetDlgItemText(hDlg, IDC_CUSTOM_FOLDER_FIELD, GUI.FreezeFileDir); + SetDlgItemText(hDlg, IDC_CONFIG_NAME_BOX, S9X_CONF_FILE_NAME); + SendDlgItemMessage(hDlg, IDC_SRAM_SPIN, UDM_SETRANGE, 0, MAKELPARAM((short)99, (short)0)); + SendDlgItemMessage(hDlg, IDC_SRAM_SPIN,UDM_SETPOS,0, Settings.AutoSaveDelay); + SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP, UDM_SETRANGE, 0, MAKELPARAM((short)59, (short)0)); + SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP,UDM_SETPOS,0, Settings.AutoMaxSkipFrames); + SendDlgItemMessage(hDlg, IDC_SPIN_TURBO_SKIP, UDM_SETRANGE, 0, MAKELPARAM((short)600, (short)0)); + SendDlgItemMessage(hDlg, IDC_SPIN_TURBO_SKIP,UDM_SETPOS,0, Settings.TurboSkipFrames); + CheckDlgButton(hDlg,IDC_TOGGLE_TURBO,GUI.TurboModeToggle ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_INACTIVE_PAUSE,GUI.InactivePause ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hDlg,IDC_CUSTOMROMOPEN,GUI.CustomRomOpen ? BST_CHECKED : BST_UNCHECKED); + + int inum = 0; + strcpy(paths[inum++],GUI.RomDir); + SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_ROMS); + strcpy(paths[inum++],GUI.ScreensDir); + SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_SCREENS); + strcpy(paths[inum++],GUI.MovieDir); + SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_MOVIES); + strcpy(paths[inum++],GUI.SPCDir); + SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_SPCS); + strcpy(paths[inum++],GUI.FreezeFileDir); + SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_SAVES); + strcpy(paths[inum++],GUI.SRAMFileDir); + SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_SRAM); + strcpy(paths[inum++],GUI.PatchDir); + SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_PATCHESANDCHEATS); + strcpy(paths[inum++],GUI.BiosDir); + SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)SETTINGS_OPTION_DIRECTORY_BIOS); + + SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_SETCURSEL,(WPARAM)0,0); + SetDlgItemText(hDlg, IDC_CUSTOM_FOLDER_FIELD, paths[0]); + which = 0; + + SetCurrentDirectory(S9xGetDirectory(DEFAULT_DIR)); + } + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint (hDlg, &ps); + + EndPaint (hDlg, &ps); + } + return true; + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDC_BROWSE: + { + LPMALLOC lpm=NULL; + LPITEMIDLIST iidl=NULL; + BROWSEINFO bi; + ZeroMemory(&bi, sizeof(BROWSEINFO)); + TCHAR path[MAX_PATH]; + _fullpath(path, paths[which], MAX_PATH); + TCHAR title[]=TEXT(SETTINGS_TITLE_SELECTFOLDER); + bi.hwndOwner=hDlg; + bi.pszDisplayName=path; + bi.lpszTitle=title; + bi.lpfn = SetSelProc; + bi.lParam = (LPARAM)(LPCSTR) path; + iidl=SHBrowseForFolder(&bi); + if(iidl) SHGetPathFromIDList(iidl, path); + + SHGetMalloc(&lpm); + lpm->Free(iidl); + absToRel(paths[which], path, S9xGetDirectory(DEFAULT_DIR)); + SetDlgItemText(hDlg, IDC_CUSTOM_FOLDER_FIELD, paths[which]); + } + break; + case IDC_CUSTOM_FOLDER_FIELD: + which = SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_GETCURSEL,0,0); + GetDlgItemText(hDlg, IDC_CUSTOM_FOLDER_FIELD, paths[which], MAX_PATH); + break; + case IDC_DIRCOMBO: + which = SendDlgItemMessage(hDlg,IDC_DIRCOMBO,CB_GETCURSEL,0,0); + SetDlgItemText(hDlg, IDC_CUSTOM_FOLDER_FIELD, paths[which]); + break; + case IDOK: + { + int inum = 0; + strcpy(GUI.RomDir,paths[inum++]); + strcpy(GUI.ScreensDir,paths[inum++]); + strcpy(GUI.MovieDir,paths[inum++]); + strcpy(GUI.SPCDir,paths[inum++]); + strcpy(GUI.FreezeFileDir,paths[inum++]); + strcpy(GUI.SRAMFileDir,paths[inum++]); + strcpy(GUI.PatchDir,paths[inum++]); + strcpy(GUI.BiosDir,paths[inum++]); + + GUI.TurboModeToggle = (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_TOGGLE_TURBO)); + GUI.InactivePause = (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_INACTIVE_PAUSE)); + GUI.CustomRomOpen = (BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_CUSTOMROMOPEN)); + + Settings.TurboSkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_TURBO_SKIP, UDM_GETPOS, 0,0); + Settings.AutoMaxSkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP, UDM_GETPOS, 0,0); + Settings.AutoSaveDelay=SendDlgItemMessage(hDlg, IDC_SRAM_SPIN, UDM_GETPOS, 0,0); + + WinSaveConfigFile(); + } + /* fall through */ + case IDCANCEL: + EndDialog(hDlg, 0); + return true; + break; + default: return false; break; + } + } + default:return false; + } +} + +#define SKIP_FLOPPY + +bool ExtensionIsValid(const TCHAR * filename) +{ + ExtList* curr=valid_ext; + while(curr!=NULL) + { + if(curr->extension==NULL) + { + if(NULL==strstr(filename, TEXT("."))) + return true; + } + else if(filename[(strlen(filename)-1)-strlen(curr->extension)]=='.') + { + if(0==_strnicmp(&filename[(strlen(filename))-strlen(curr->extension)], + curr->extension, strlen(curr->extension))) + return true; + } + curr=curr->next; + } + return false; +} + +bool IsCompressed(const TCHAR* filename) +{ + ExtList* curr=valid_ext; + while(curr!=NULL) + { + if(curr->extension==NULL) + { + if(NULL==strstr(filename, TEXT("."))) + return curr->compressed; + } + else if(filename[(strlen(filename)-1)-strlen(curr->extension)]=='.') + { + if(0==_strnicmp(&filename[(strlen(filename))-strlen(curr->extension)], + curr->extension, strlen(curr->extension))) + return curr->compressed; + } + curr=curr->next; + } + return false; +} + +inline bool AllASCII(char *b, int size) +{ + for (int i = 0; i < size; i++) + { + if (b[i] < 32 || b[i] > 126) + { + return(false); + } + } + return(true); +} + +inline int InfoScore(char *Buffer) +{ + int score = 0; + if (Buffer[28] + (Buffer[29] << 8) + + Buffer[30] + (Buffer[31] << 8) == 0xFFFF) + { score += 3; } + + if (Buffer[26] == 0x33) { score += 2; } + if ((Buffer[21] & 0xf) < 4) { score += 2; } + if (!(Buffer[61] & 0x80)) { score -= 4; } + if ((1 << (Buffer[23] - 7)) > 48) { score -= 1; } + if (Buffer[25] < 14) { score += 1; } + if (!AllASCII(Buffer, 20)) { score -= 1; } + + return (score); +} + +inline unsigned short sum(unsigned char *array, unsigned int size = HEADER_SIZE) +{ + register unsigned short theSum = 0; + for (register unsigned int i = 0; i < size; i++) + { + theSum += array[i]; + } + return(theSum); +} + +void rominfo(const TCHAR *filename, TCHAR *namebuffer, TCHAR *sizebuffer) +{ + strcpy(namebuffer, ROM_ITEM_DESCNOTAVAILABLE); + strcpy(sizebuffer, "? Mbits"); + + if(IsCompressed(filename)) + { + unzFile uf = unzOpen(filename); + if(uf) + { + unz_file_info info; + if(UNZ_OK == unzGetCurrentFileInfo(uf, &info, 0,0,0,0,0,0)) + { + if (info.uncompressed_size < 0x8000) // Smaller than a block + strcpy(namebuffer, ROM_ITEM_NOTAROM); + else + strcpy(namebuffer, ROM_ITEM_COMPRESSEDROMDESCRIPTION); + + // should subtract header size, so this may be slightly off, but it's better than "? MBits" + double MBitD = (double)(info.uncompressed_size - 0) / 0x100000 * 8; + int MBitI = (int)MBitD; + int sizeIndex; + if(0!=(MBitI / 10)) + { + sizebuffer[0] = MBitI / 10 + '0'; + sizeIndex = 1; + } + else + sizeIndex = 0; + sizebuffer[sizeIndex+0] = MBitI % 10 + '0'; + sizebuffer[sizeIndex+1] = '.'; + sizebuffer[sizeIndex+2] = (char)((MBitD - MBitI) * 10) + '0'; + sizebuffer[sizeIndex+3] = (char)((int)((MBitD - MBitI) * 100) % 10) + '0'; + sizebuffer[sizeIndex+4] = ' '; + sizebuffer[sizeIndex+5] = 'M'; + sizebuffer[sizeIndex+6] = 'b'; + sizebuffer[sizeIndex+7] = 'i'; + sizebuffer[sizeIndex+8] = 't'; + sizebuffer[sizeIndex+9] = '\0'; + } + unzClose(uf); + } + return; + } + + struct stat filestats; + stat(filename, &filestats); + + int HeaderSize = 0; + + if (filestats.st_size >= 0x8000) + { + ifstream ROMFile(filename, ios::in | ios::binary); + if (ROMFile) + { + int HasHeadScore = 0, NoHeadScore = 0, + HeadRemain = filestats.st_size & 0x7FFF; + + switch(HeadRemain) + { + case 0: + NoHeadScore += 3; + break; + + case HEADER_SIZE: + HasHeadScore += 2; + break; + } + + unsigned char HeaderBuffer[HEADER_SIZE]; + ROMFile.read((char *)HeaderBuffer, HEADER_SIZE); + + if (sum(HeaderBuffer) < 2500) { HasHeadScore += 2; } + + //SMC/SWC Header + if (HeaderBuffer[8] == 0xAA && + HeaderBuffer[9] == 0xBB && + HeaderBuffer[10]== 4) + { HasHeadScore += 3; } + //FIG Header + else if ((HeaderBuffer[4] == 0x77 && HeaderBuffer[5] == 0x83) || + (HeaderBuffer[4] == 0xDD && HeaderBuffer[5] == 0x82) || + (HeaderBuffer[4] == 0xDD && HeaderBuffer[5] == 2) || + (HeaderBuffer[4] == 0xF7 && HeaderBuffer[5] == 0x83) || + (HeaderBuffer[4] == 0xFD && HeaderBuffer[5] == 0x82) || + (HeaderBuffer[4] == 0x00 && HeaderBuffer[5] == 0x80) || + (HeaderBuffer[4] == 0x47 && HeaderBuffer[5] == 0x83) || + (HeaderBuffer[4] == 0x11 && HeaderBuffer[5] == 2)) + { HasHeadScore += 2; } + else if (!strncmp("GAME DOCTOR SF 3", (char *)HeaderBuffer, 16)) + { HasHeadScore += 5; } + + HeaderSize = HasHeadScore > NoHeadScore ? HEADER_SIZE : 0; + + bool EHi = false; + if (filestats.st_size - HeaderSize >= 0x500000) + { + ROMFile.seekg(0x40FFC0 + HeaderSize, ios::beg); + ROMFile.read((char *)HeaderBuffer, INFO_LEN); + if (InfoScore((char *)HeaderBuffer) > 1) + { + EHi = true; + strncpy(namebuffer, (char *)HeaderBuffer, 21); + } + } + + if (!EHi) + { + if (filestats.st_size - HeaderSize >= 0x10000) + { + char LoHead[INFO_LEN], HiHead[INFO_LEN]; + + ROMFile.seekg(0x7FC0 + HeaderSize, ios::beg); + ROMFile.read(LoHead, INFO_LEN); + int LoScore = InfoScore(LoHead); + + ROMFile.seekg(0xFFC0 + HeaderSize, ios::beg); + ROMFile.read(HiHead, INFO_LEN); + int HiScore = InfoScore(HiHead); + + strncpy(namebuffer, LoScore > HiScore ? LoHead : HiHead, 21); + + if (filestats.st_size - HeaderSize >= 0x20000) + { + ROMFile.seekg((filestats.st_size - HeaderSize) / 2 + 0x7FC0 + HeaderSize, ios::beg); + ROMFile.read(LoHead, INFO_LEN); + int IntLScore = InfoScore(LoHead) / 2; + + if (IntLScore > LoScore && IntLScore > HiScore) + { + strncpy(namebuffer, LoHead, 21); + } + } + } + else //ROM only has one block + { + ROMFile.seekg(0x7FC0 + HeaderSize, ios::beg); + ROMFile.read(namebuffer, 21); + } + } + ROMFile.close(); + } + else //Couldn't open file + { + strcpy(namebuffer, ROM_ITEM_CANTOPEN); + } + } + else //Smaller than a block + { + strcpy(namebuffer, ROM_ITEM_NOTAROM); + } + + double MBitD = (double)(filestats.st_size - HeaderSize) / 0x100000 * 8; + int MBitI = (int)MBitD; + int sizeIndex; + if(0!=(MBitI / 10)) + { + sizebuffer[0] = MBitI / 10 + '0'; + sizeIndex = 1; + } + else + sizeIndex = 0; + sizebuffer[sizeIndex+0] = MBitI % 10 + '0'; + sizebuffer[sizeIndex+1] = '.'; + sizebuffer[sizeIndex+2] = (char)((MBitD - MBitI) * 10) + '0'; + sizebuffer[sizeIndex+3] = (char)((int)((MBitD - MBitI) * 100) % 10) + '0'; + sizebuffer[sizeIndex+4] = ' '; + sizebuffer[sizeIndex+5] = 'M'; + sizebuffer[sizeIndex+6] = 'b'; + sizebuffer[sizeIndex+7] = 'i'; + sizebuffer[sizeIndex+8] = 't'; + sizebuffer[sizeIndex+9] = '\0'; + namebuffer[21] = '\0'; +} + +void GetPathFromTree( HWND hDlg, UINT tree, TCHAR* selected, HTREEITEM hItem) +{ + TVITEM tv; + TCHAR temp[MAX_PATH]; + temp[0]='\0'; + ZeroMemory(&tv, sizeof(TVITEM)); + HTREEITEM hTreeTemp=hItem; + + if(tv.iImage==7) + { + tv.mask=TVIF_HANDLE|TVIF_IMAGE; + tv.hItem=hTreeTemp; + tv.iImage=6; + TreeView_SetItem(GetDlgItem(hDlg, tree),&tv); + ZeroMemory(&tv, sizeof(TVITEM)); + } + + tv.mask=TVIF_HANDLE|TVIF_TEXT; + tv.hItem=hTreeTemp; + tv.pszText=temp; + tv.cchTextMax =MAX_PATH; + TreeView_GetItem(GetDlgItem(hDlg, tree), &tv); + + sprintf(selected, TEXT("%s"), temp); + while(TreeView_GetParent(GetDlgItem(hDlg, tree), hTreeTemp)) + { + temp[0]='\0'; + hTreeTemp=TreeView_GetParent(GetDlgItem(hDlg, tree), hTreeTemp); + tv.mask=TVIF_HANDLE|TVIF_TEXT; + tv.hItem=hTreeTemp; + tv.pszText=temp; + tv.cchTextMax =MAX_PATH; + TreeView_GetItem(GetDlgItem(hDlg, tree), &tv); + sprintf(temp, TEXT("%s\\%s"),temp, selected); + strcpy(selected, temp); + } +} + +typedef struct RomDataCacheNode +{ + char* fname; + char* rname; + char* rmbits; + struct RomDataCacheNode* next; +} RomDataList; + +void ClearCacheList(RomDataList* rdl) +{ + RomDataList* temp=rdl; + RomDataList* temp2=NULL; + if(rdl==NULL) + return; + do + { + temp2=temp->next; + if(temp->fname) + delete [] temp->fname; + if(temp->rmbits) + delete [] temp->rmbits; + if(temp->rname) + delete [] temp->rname; + delete temp; + temp=temp2; + } + while(temp!=NULL); +} + + +void ExpandDir(char * selected, HTREEITEM hParent, HWND hDlg) +{ + TCHAR temp[MAX_PATH]; + WIN32_FIND_DATA wfd; + ZeroMemory(&wfd, sizeof(WIN32_FIND_DATA)); + strcat(selected, TEXT("\\*")); + HANDLE hFind=FindFirstFile(selected,&wfd); + selected[(strlen(selected)-1)]='\0'; + + do + { + if(wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) + { + if(strcmp(wfd.cFileName, TEXT("."))&&strcmp(wfd.cFileName, TEXT(".."))) + { + //skip these, add the rest. + TV_INSERTSTRUCT tvis; + ZeroMemory(&tvis, sizeof(TV_INSERTSTRUCT)); + tvis.hParent=hParent; + tvis.hInsertAfter=TVI_SORT; + tvis.item.mask = TVIF_STATE | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvis.item.pszText=wfd.cFileName; + tvis.item.cchTextMax=MAX_PATH; + const bool locked = (wfd.dwFileAttributes&(FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_ENCRYPTED|FILE_ATTRIBUTE_OFFLINE))!=0; + const bool hidden = (wfd.dwFileAttributes&(FILE_ATTRIBUTE_HIDDEN))!=0; + tvis.item.iImage=hidden?9:(locked?8:7); + tvis.item.iSelectedImage=locked?8:6; + HTREEITEM hNewTree=TreeView_InsertItem(GetDlgItem(hDlg, IDC_ROM_DIR),&tvis); + + strcpy(temp, selected); + strcat(temp, wfd.cFileName); + strcat(temp, TEXT("\\*")); + + bool subdir=false; + WIN32_FIND_DATA wfd2; + ZeroMemory(&wfd2, sizeof(WIN32_FIND_DATA)); + HANDLE hFind2=FindFirstFile(temp,&wfd2); + do + { + if(wfd2.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) + { + if(strcmp(wfd2.cFileName, TEXT("."))&&strcmp(wfd2.cFileName, TEXT(".."))) + { + subdir=true; + } + } + } + while(FindNextFile(hFind2, &wfd2)&&!subdir); + + if(subdir) + { + TV_INSERTSTRUCT tvis; + ZeroMemory(&tvis, sizeof(TV_INSERTSTRUCT)); + tvis.hParent=hNewTree; + tvis.hInsertAfter=TVI_SORT; + TreeView_InsertItem(GetDlgItem(hDlg, IDC_ROM_DIR),&tvis); + + } + FindClose(hFind2); + + } + } + } + while(FindNextFile(hFind, &wfd)); + + FindClose(hFind); + //scan for folders +} + + + +void ListFilesFromFolder(HWND hDlg, RomDataList** prdl) +{ + RomDataList* rdl= *prdl; + RomDataList* current=NULL; + int count=0; + TVITEM tv; + TCHAR temp[MAX_PATH]; + TCHAR selected[MAX_PATH]; // directory path + temp[0]='\0'; + ZeroMemory(&tv, sizeof(TVITEM)); + HTREEITEM hTreeItem=TreeView_GetSelection(GetDlgItem(hDlg, IDC_ROM_DIR)); + + GetPathFromTree(hDlg, IDC_ROM_DIR, selected, hTreeItem); + + SendDlgItemMessage(hDlg, IDC_ROMLIST, WM_SETREDRAW, FALSE, 0); + ListView_DeleteAllItems(GetDlgItem(hDlg, IDC_ROMLIST)); + ClearCacheList(rdl); + rdl=NULL; + //Add items here. + + WIN32_FIND_DATA wfd; + ZeroMemory(&wfd, sizeof(WIN32_FIND_DATA)); + + strcat(selected, TEXT("\\*")); + + HANDLE hFind=FindFirstFile(selected, &wfd); + selected[(strlen(selected)-1)]='\0'; + do + { + if(wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) + continue; + if(ExtensionIsValid(wfd.cFileName)) + { + RomDataList* newitem=new RomDataList; + ZeroMemory(newitem, sizeof(RomDataList)); + newitem->fname=new char[1+strlen(wfd.cFileName)]; + strcpy(newitem->fname, wfd.cFileName); + + // hide ntldr and no-name files + if(!newitem->fname || !*newitem->fname || (!strcmp(newitem->fname, "ntldr") && strlen(selected)<4)) + continue; + + // too small to be a ROM + if (wfd.nFileSizeLow < 0x8000 && !IsCompressed(wfd.cFileName)) + continue; + + count++; + + if(!rdl) + rdl=newitem; + else + { + if(0>stricmp(newitem->fname,rdl->fname)) + { + newitem->next=rdl; + rdl=newitem; + } + else + { + RomDataList* trail=rdl; + current=rdl->next; + while(current!=NULL&&0fname,current->fname)) + { + trail=current; + current=current->next; + } + newitem->next=current; + trail->next=newitem; + } + } + } + } + while(FindNextFile(hFind, &wfd)); + + FindClose(hFind); + + SendDlgItemMessage(hDlg, IDC_ROMLIST, WM_SETREDRAW, TRUE, 0); + *prdl=rdl; + ListView_SetItemCountEx (GetDlgItem(hDlg, IDC_ROMLIST), count, 0); + ListView_SetItemState (GetDlgItem(hDlg,IDC_ROMLIST), 0, LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); +} + +// load multicart rom dialog +int CALLBACK DlgMultiROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG:{ + WinRefreshDisplay(); + TCHAR path[MAX_PATH]; + SetCurrentDirectory(S9xGetDirectory(BIOS_DIR)); + _fullpath(path, "stbios.bin", MAX_PATH); + SetDlgItemText(hDlg, IDC_MULTICART_BIOSEDIT, path); + FILE* ftemp = fopen(path, "rb"); + if(ftemp) + { + fclose(ftemp); + SetDlgItemText(hDlg, IDC_MULTICART_BIOSNOTFOUND, MULTICART_BIOS_FOUND); + } + else + SetDlgItemText(hDlg, IDC_MULTICART_BIOSNOTFOUND, MULTICART_BIOS_NOT_FOUND); + SetDlgItemText(hDlg, IDC_MULTICART_EDITA, multiRomA); + SetDlgItemText(hDlg, IDC_MULTICART_EDITB, multiRomB); + break;} + case WM_COMMAND: + { + char rom1[MAX_PATH]={0}, rom2[MAX_PATH]={0}; + SetCurrentDirectory(S9xGetDirectory(ROM_DIR)); + switch(LOWORD(wParam)) + { + case IDOK: + GetDlgItemText(hDlg, IDC_MULTICART_EDITA, multiRomA, MAX_PATH); + GetDlgItemText(hDlg, IDC_MULTICART_EDITB, multiRomB, MAX_PATH); + if(*multiRomA) _fullpath(multiRomA, multiRomA, MAX_PATH); + if(*multiRomB) _fullpath(multiRomB, multiRomB, MAX_PATH); + EndDialog(hDlg, 1); + return true; + case IDCANCEL: + EndDialog(hDlg, 0); + return true; + case IDC_MULTICART_SWAP: + GetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom2, MAX_PATH); + GetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom1, MAX_PATH); + if(*rom1) _fullpath(rom1, rom1, MAX_PATH); + if(*rom2) _fullpath(rom2, rom2, MAX_PATH); + SetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom1); + SetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom2); + break; + case IDC_MULTICART_BROWSEA: + if(!DoOpenRomDialog(rom1, true)) + break; + _fullpath(rom1, rom1, MAX_PATH); + SetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom1); + break; + case IDC_MULTICART_BROWSEB: + if(!DoOpenRomDialog(rom2, true)) + break; + _fullpath(rom2, rom2, MAX_PATH); + SetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom2); + break; + case IDC_MULTICART_CLEARA: + rom1[0] = '\0'; + SetDlgItemText(hDlg, IDC_MULTICART_EDITA, rom1); + break; + case IDC_MULTICART_CLEARB: + rom1[1] = '\0'; + SetDlgItemText(hDlg, IDC_MULTICART_EDITB, rom2); + break; + } + } + } + return false; +} + +int CALLBACK DlgOpenROMProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int rv=0; + static HWND hSplit; + static HIMAGELIST hIcons; + static TCHAR *filename; + static RomDataList* rdl; + static int selectionMarkOverride = -1; + static bool initDone = false; + static RomDataList* nextInvalidatedROM = NULL; + static int nextInvalidatedROMCounter = 0; + static HWND romList = NULL; + static HWND dirList = NULL; + switch(msg) + { + case WM_INITDIALOG: + WinRefreshDisplay(); + { + initDone = false; + + // suppress annoying "no disk in drive" errors + SetErrorMode(SEM_FAILCRITICALERRORS); + + romList = GetDlgItem(hDlg,IDC_ROMLIST); + dirList = GetDlgItem(hDlg,IDC_ROM_DIR); + filename=(TCHAR*)lParam; + RECT treeRect; + RECT listRect; + WNDCLASSEX wcex; + TCHAR tempclassname[]=TEXT("S9xSplitter"); + ZeroMemory(&wcex, sizeof(WNDCLASSEX)); + wcex.cbSize=sizeof(WNDCLASSEX); + wcex.hInstance=g_hInst; + wcex.lpfnWndProc=DlgChildSplitProc; + wcex.lpszClassName=tempclassname; + wcex.hbrBackground=(HBRUSH)GetStockObject(LTGRAY_BRUSH); + wcex.hCursor=LoadCursor(NULL, IDC_SIZEWE); +/// wcex.hCursor=LoadCursor(NULL, MAKEINTRESOURCE(IDC_SIZEWE)); +/// ATOM aSplitter=RegisterClassEx(&wcex); + GetWindowRect(dirList, &treeRect); + GetWindowRect(romList, &listRect); + POINT p; + + ListView_SetExtendedListViewStyle(romList, LVS_EX_FULLROWSELECT); + + p.x=treeRect.right; + p.y=treeRect.top; + ScreenToClient(hDlg, &p); + hSplit=CreateWindow(TEXT("S9xSplitter"), TEXT(""),WS_CHILD|WS_VISIBLE , p.x, p.y, listRect.left-treeRect.right , listRect.bottom-listRect.top, hDlg,NULL, g_hInst,0); + + LVCOLUMN col; + static const LPSTR temp1 = TEXT(ROM_COLUMN_FILENAME); + ZeroMemory(&col, sizeof(LVCOLUMN)); + col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH; + col.fmt=LVCFMT_LEFT; + col.iOrder=0; + col.cx=196; + col.cchTextMax=5; + col.pszText=temp1; + + ListView_InsertColumn(romList, 0, &col); + + static const LPSTR temp2 = TEXT(ROM_COLUMN_DESCRIPTION); + ZeroMemory(&col, sizeof(LVCOLUMN)); + col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; + col.fmt=LVCFMT_LEFT; + col.iOrder=1; + col.cx=112; + col.cchTextMax=32; + col.pszText=temp2; + col.iSubItem=1; + + ListView_InsertColumn(romList, 1, &col); + + + static const LPSTR temp3 = TEXT(ROM_COLUMN_SIZE); + ZeroMemory(&col, sizeof(LVCOLUMN)); + col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; + col.fmt=LVCFMT_LEFT; + col.iOrder=2; + col.cx=67; + col.cchTextMax=32; + col.pszText=temp3; + col.iSubItem=2; + + ListView_InsertColumn(romList, 2, &col); + + + SendDlgItemMessage(hDlg, IDC_MEM_TYPE,CB_INSERTSTRING,0,(LPARAM)TEXT(ROM_OPTION_AUTODETECT)); + SendDlgItemMessage(hDlg, IDC_MEM_TYPE,CB_INSERTSTRING,1,(LPARAM)TEXT(ROM_OPTION_FORCEHIROM)); + SendDlgItemMessage(hDlg, IDC_MEM_TYPE,CB_INSERTSTRING,2,(LPARAM)TEXT(ROM_OPTION_FORCELOROM)); + SendDlgItemMessage(hDlg, IDC_MEM_TYPE,CB_SETCURSEL,0,0); + + SendDlgItemMessage(hDlg, IDC_VIDEO_MODE,CB_INSERTSTRING,0,(LPARAM)TEXT(ROM_OPTION_AUTODETECT)); + SendDlgItemMessage(hDlg, IDC_VIDEO_MODE,CB_INSERTSTRING,1,(LPARAM)TEXT(ROM_OPTION_FORCEPAL)); + SendDlgItemMessage(hDlg, IDC_VIDEO_MODE,CB_INSERTSTRING,2,(LPARAM)TEXT(ROM_OPTION_FORCENTSC)); + SendDlgItemMessage(hDlg, IDC_VIDEO_MODE,CB_SETCURSEL,0,0); + + SendDlgItemMessage(hDlg, IDC_HEADER,CB_INSERTSTRING,0,(LPARAM)TEXT(ROM_OPTION_AUTODETECT)); + SendDlgItemMessage(hDlg, IDC_HEADER,CB_INSERTSTRING,1,(LPARAM)TEXT(ROM_OPTION_FORCEHEADER)); + SendDlgItemMessage(hDlg, IDC_HEADER,CB_INSERTSTRING,2,(LPARAM)TEXT(ROM_OPTION_FORCENOHEADER)); + SendDlgItemMessage(hDlg, IDC_HEADER,CB_SETCURSEL,0,0); + + SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_INSERTSTRING,0,(LPARAM)TEXT(ROM_OPTION_AUTODETECT)); + SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_INSERTSTRING,1,(LPARAM)TEXT(ROM_OPTION_NONINTERLEAVED)); + SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_INSERTSTRING,2,(LPARAM)TEXT(ROM_OPTION_MODE1)); + SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_INSERTSTRING,3,(LPARAM)TEXT(ROM_OPTION_MODE2)); + SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_INSERTSTRING,4,(LPARAM)TEXT(ROM_OPTION_GD24)); + SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_SETCURSEL,0,0); + + hIcons=ImageList_Create(16,16,ILC_COLOR24,10,10); + + HANDLE hBitmap; + +#define ADD_IMAGE(IDB_NAME) \ + hBitmap=LoadImage(g_hInst, MAKEINTRESOURCE(IDB_NAME), IMAGE_BITMAP, 0,0, LR_DEFAULTCOLOR|LR_CREATEDIBSECTION); \ + ImageList_Add(hIcons, (HBITMAP)hBitmap, NULL); \ + DeleteObject(hBitmap); + + ADD_IMAGE(IDB_HARDDRIVE); // 0 + ADD_IMAGE(IDB_CDDRIVE); // 1 + ADD_IMAGE(IDB_NETDRIVE); // 2 + ADD_IMAGE(IDB_REMOVABLE); // 3 + ADD_IMAGE(IDB_RAMDISK); // 4 + ADD_IMAGE(IDB_UNKNOWN); // 5 + ADD_IMAGE(IDB_OPENFOLDER); // 6 + ADD_IMAGE(IDB_CLOSEDFOLDER); // 7 + ADD_IMAGE(IDB_LOCKEDFOLDER); // 8 + ADD_IMAGE(IDB_HIDDENFOLDER); // 9 + + TreeView_SetImageList(dirList, hIcons, TVSIL_NORMAL); + +// DWORD dw; + TCHAR buffer[MAX_PATH]; + TCHAR blah[MAX_PATH]; + long result=ERROR_SUCCESS/*-1*/; + HTREEITEM hTreeDrive=NULL; + + char drive [_MAX_DRIVE + 1]; + strcpy (drive,"C:\\"); + + + _fullpath (buffer, S9xGetDirectory(ROM_DIR), MAX_PATH); + _splitpath (buffer, drive, NULL, NULL, NULL); + + DWORD driveMask=GetLogicalDrives(); + +#ifndef SKIP_FLOPPY + for (int i=0;i<26;i++) +#else + for (int i=2;i<26;i++) +#endif + { + if(driveMask&(1<=0) + { + RomDataList* curr=rdl; + for(int i=0;inext; + if(curr && !curr->rname) + { + nextInvalidatedROM = curr; + nextInvalidatedROMCounter = selected; + } + } + + LVHITTESTINFO lvhi; + lvhi.flags = LVHT_ONITEM; + lvhi.iItem = 0; + lvhi.iSubItem = 0; + lvhi.pt.x = 0; + lvhi.pt.y = 0; + ListView_HitTest(romList, &lvhi); + int firstVisibleItem = lvhi.iItem+1; + int lastVisibleItem = firstVisibleItem+20; + + // skip up to 100 things that don't need updating + bool enteredValid = false; + if(nextInvalidatedROM->rname || nextInvalidatedROMCounterlastVisibleItem) + for(int i = 0 ; i < 100 ; i++) + if(nextInvalidatedROM->rname || (!enteredValid && (nextInvalidatedROMCounterlastVisibleItem))) + { + if(!enteredValid && nextInvalidatedROMCounter>=firstVisibleItem && nextInvalidatedROMCounternext; + if(nextInvalidatedROM) + nextInvalidatedROMCounter++; + else + { + nextInvalidatedROM = rdl; + nextInvalidatedROMCounter = 0; + } + } + + // update 1 item, if it needs updating + if(!nextInvalidatedROM->rname) + { + TCHAR path[MAX_PATH]; + TCHAR buffer[32]; + TCHAR buffer2[32]; + GetPathFromTree(hDlg, IDC_ROM_DIR, path, TreeView_GetSelection(dirList)); + strcat(path, "\\"); + strcat(path, nextInvalidatedROM->fname); + rominfo(path, buffer, buffer2); + nextInvalidatedROM->rname=new char[strlen(buffer)+1]; + strcpy(nextInvalidatedROM->rname, buffer); + nextInvalidatedROM->rmbits=new char[strlen(buffer2)+1]; + strcpy(nextInvalidatedROM->rmbits, buffer2); + + ListView_RedrawItems(romList,nextInvalidatedROMCounter,nextInvalidatedROMCounter); + } + + // next timer + nextInvalidatedROM = nextInvalidatedROM->next; + if(nextInvalidatedROM) + nextInvalidatedROMCounter++; + else + { + nextInvalidatedROM = rdl; + nextInvalidatedROMCounter = 0; + } + SetTimer(hDlg,42,600,NULL); + return true; + } + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint (hDlg, &ps); + + EndPaint (hDlg, &ps); + } + return true; + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDOK: + { + LVITEM lvi; + ZeroMemory(&lvi, sizeof(LVITEM)); + //get selections + int list_index = selectionMarkOverride == -1 ? ListView_GetSelectionMark(romList) : selectionMarkOverride; + if(list_index!=-1 && (int)SendMessage(romList, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_SELECTED)!=-1) + { + rv=1; + TCHAR temp[MAX_PATH]; + temp[0]='\0'; + lvi.iItem=list_index; + lvi.mask=LVIF_TEXT; + lvi.pszText=filename; + lvi.cchTextMax=MAX_PATH; + ListView_GetItem(romList, &lvi); + + strcpy(temp, filename); + + HTREEITEM hTreeTemp=TreeView_GetSelection(dirList); + TVITEM tv; + ZeroMemory(&tv, sizeof(TVITEM)); + + tv.mask=TVIF_HANDLE|TVIF_TEXT; + tv.hItem=hTreeTemp; + tv.pszText=temp; + tv.cchTextMax =MAX_PATH; + TreeView_GetItem(dirList, &tv); + sprintf(temp, TEXT("%s\\%s"), temp, filename); + + strcpy(filename, temp); + + while(TreeView_GetParent(dirList, hTreeTemp)!=NULL) + { + temp[0]='\0'; + hTreeTemp=TreeView_GetParent(dirList, hTreeTemp); + tv.mask=TVIF_HANDLE|TVIF_TEXT; + tv.hItem=hTreeTemp; + tv.pszText=temp; + tv.cchTextMax =MAX_PATH; + TreeView_GetItem(dirList, &tv); + sprintf(temp, TEXT("%s\\%s"),temp, filename); + strcpy(filename, temp); + } + + int iTemp=SendDlgItemMessage(hDlg, IDC_MEM_TYPE,CB_GETCURSEL,0,0); + + Settings.ForceHiROM=Settings.ForceLoROM=FALSE; + if(iTemp==1) + Settings.ForceHiROM=TRUE; + else if(iTemp==2) + Settings.ForceLoROM=TRUE; + + iTemp=SendDlgItemMessage(hDlg, IDC_INTERLEAVE,CB_GETCURSEL,0,0); + + Settings.ForceNotInterleaved=Settings.ForceInterleaved=Settings.ForceInterleaved2=Settings.ForceInterleaveGD24=FALSE; + if(iTemp==1) + Settings.ForceNotInterleaved=TRUE; + else if(iTemp==2) + Settings.ForceInterleaved=TRUE; + else if(iTemp==3) + Settings.ForceInterleaved2=TRUE; + else if(iTemp==4) + Settings.ForceInterleaveGD24=TRUE; + + iTemp=SendDlgItemMessage(hDlg, IDC_VIDEO_MODE,CB_GETCURSEL,0,0); + + Settings.ForceNTSC=Settings.ForcePAL=FALSE; + if(iTemp==1) + Settings.ForcePAL=TRUE; + else if(iTemp==2) + Settings.ForceNTSC=TRUE; + + + iTemp=SendDlgItemMessage(hDlg, IDC_HEADER,CB_GETCURSEL,0,0); + + Settings.ForceNoHeader=Settings.ForceHeader=FALSE; + if(iTemp==1) + Settings.ForceHeader=TRUE; + else if(iTemp==2) + Settings.ForceNoHeader=TRUE; + + strcpy(temp, filename); + int i=strlen(temp); + while(temp[i]!='\\' && temp[i]!='/') + { + temp[i]='\0'; + i--; + } + temp[i]='\0'; + + if(!GUI.LockDirectories) + absToRel(GUI.RomDir, temp, S9xGetDirectory(DEFAULT_DIR)); + } + else + { + return false; + } + } + case IDCANCEL: + EndDialog(hDlg, rv); + ClearCacheList(rdl); + rdl=NULL; + DestroyWindow(hSplit); + UnregisterClass(TEXT("S9xSplitter"), g_hInst); + TreeView_DeleteAllItems(dirList); + ListView_DeleteAllItems(romList); + return true; + break; + default: return false; break; + } + } + case WM_NOTIFY: + { + if(lParam == 0) + return false; + NMHDR* pNmh=(NMHDR*)lParam; + static int foundItemOverride = -1; + switch(pNmh->idFrom) + { + case IDC_ROMLIST: + { + switch(pNmh->code) + { + // allow typing in a ROM filename (or part of it) to jump to it + // necessary to implement ourselves because Windows doesn't provide + // this functionality for virtual (owner data) lists such as this + case LVN_ODFINDITEM: + { + LRESULT pResult; + + // pNMHDR has information about the item we should find + // In pResult we should save which item that should be selected + NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)lParam; + + /* pFindInfo->iStart is from which item we should search. + We search to bottom, and then restart at top and will stop + at pFindInfo->iStart, unless we find an item that match + */ + + // Set the default return value to -1 + // That means we didn't find any match. + pResult = -1; + + //Is search NOT based on string? + if( (pFindInfo->lvfi.flags & LVFI_STRING) == 0 ) + { + //This will probably never happend... + return pResult; + } + + //This is the string we search for + LPCSTR searchstr = pFindInfo->lvfi.psz; + + int startPos = pFindInfo->iStart; + //Is startPos outside the list (happens if last item is selected) + if(startPos >= ListView_GetItemCount(romList)) + startPos = 0; + + if(rdl==NULL) + return pResult; + + RomDataList* curr=rdl; + for(int i=0;inext; + + int currentPos=startPos; + pResult=startPos; + + bool looped = false; + + // perform search + do + { + // does this word begin with all characters in searchstr? + if( _tcsnicmp(curr->fname, searchstr, strlen(searchstr)) == 0) + { + // select this item and stop search + pResult = currentPos; + break; + } + else if( _tcsnicmp(curr->fname, searchstr, strlen(searchstr)) > 0) + { + if(looped) + { + pResult = currentPos; + break; + } + + // optimization: the items are ordered alphabetically, so go back to the top since we know it can't be anything further down + curr=rdl; + currentPos = 0; + looped = true; + continue; + } + + //Go to next item + currentPos++; + curr=curr->next; + + //Need to restart at top? + if(currentPos >= ListView_GetItemCount(romList)) + { + currentPos = 0; + curr = rdl; + } + + //Stop if back to start + }while(currentPos != startPos); + + foundItemOverride = pResult; + + // in case previously-selected item is 0 + ListView_SetItemState (romList, 1, LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + + return pResult; // HACK: for some reason this selects the first item instead of what it's returning... current workaround is to manually re-select this return value upon the next changed event + } + break; + case LVN_ITEMCHANGED: + { + // hack - see note directly above + LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lParam; + if(lpnmlv->uNewState & (LVIS_SELECTED|LVIS_FOCUSED)) + { + if(foundItemOverride != -1 && lpnmlv->iItem == 0) + { + ListView_SetItemState (romList, foundItemOverride, LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + ListView_EnsureVisible (romList, foundItemOverride, FALSE); + selectionMarkOverride = foundItemOverride; + foundItemOverride = -1; + } + else + { + selectionMarkOverride = lpnmlv->iItem; + } + } + } + break; + case LVN_GETDISPINFO: + { + if(!initDone) + return false; + int i, j; + RomDataList* curr=rdl; + if(rdl==NULL) + return false; + NMLVDISPINFO * nmlvdi=(NMLVDISPINFO*)lParam; + j=nmlvdi->item.iItem; + for(i=0;inext; + if(curr==NULL) + return false; + //if(curr->rname==NULL && j==(int)SendMessage(romList, LVM_GETNEXTITEM, -1, LVNI_SELECTED)) + //{ + // TCHAR path[MAX_PATH]; + // TCHAR buffer[32]; + // TCHAR buffer2[32]; + // GetPathFromTree(hDlg, IDC_ROM_DIR, path, TreeView_GetSelection(dirList)); + // strcat(path, "\\"); + // strcat(path, curr->fname); + // rominfo(path, buffer, buffer2); + // curr->rname=new char[strlen(buffer)+1]; + // strcpy(curr->rname, buffer); + // curr->rmbits=new char[strlen(buffer2)+1]; + // strcpy(curr->rmbits, buffer2); + //} + + if(nmlvdi->item.iSubItem==0) + { + nmlvdi->item.pszText=curr->fname?curr->fname:(char*)""; + nmlvdi->item.cchTextMax=MAX_PATH; + } + if(nmlvdi->item.iSubItem==1) + { + nmlvdi->item.pszText=curr->rname?curr->rname:(char*)""; + nmlvdi->item.cchTextMax=24; + } + + if(nmlvdi->item.iSubItem==2) + { + nmlvdi->item.pszText=curr->rmbits?curr->rmbits:(char*)""; + nmlvdi->item.cchTextMax=11; + } + // nmlvdi->item.mask=LVIF_TEXT; // This is bad as wine relies on this to not change. + } + break; + case NM_DBLCLK: + { + PostMessage(hDlg, WM_COMMAND, (WPARAM)(IDOK),(LPARAM)(NULL)); + } + default:break; + } + } + break; + case IDC_ROM_DIR: + { + switch(pNmh->code) + { + case TVN_ITEMEXPANDING: + { + TCHAR selected[MAX_PATH]; + NMTREEVIEW* nmTv=(NMTREEVIEW*)lParam; + + while(TreeView_GetChild(dirList,nmTv->itemNew.hItem)) + { + TreeView_DeleteItem(dirList, TreeView_GetChild(dirList,nmTv->itemNew.hItem)); + } + + if(nmTv->action&TVE_EXPAND) + { + + GetPathFromTree(hDlg, IDC_ROM_DIR, selected,nmTv->itemNew.hItem); + ExpandDir(selected, nmTv->itemNew.hItem, hDlg); + } + else + { + TVITEM tv; + ZeroMemory(&tv, sizeof(TVITEM)); + HTREEITEM hTreeTemp=nmTv->itemNew.hItem; + + if(tv.iImage==6) + { + tv.mask=TVIF_HANDLE|TVIF_IMAGE; + tv.hItem=hTreeTemp; + tv.iImage=7; + TreeView_SetItem(dirList,&tv); + } + + + TV_INSERTSTRUCT tvis; + ZeroMemory(&tvis, sizeof(TV_INSERTSTRUCT)); + tvis.hParent=nmTv->itemNew.hItem; + tvis.hInsertAfter=TVI_SORT; + TreeView_InsertItem(dirList,&tvis); + + } + } + return false; + break; + case TVN_SELCHANGED: + { + ListFilesFromFolder(hDlg, &rdl); + nextInvalidatedROM = rdl; + nextInvalidatedROMCounter = 0; + } + default:return false; + } + } + default:return false; + } + } + default:return false; + } +} +LRESULT CALLBACK DlgChildSplitProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static bool PaintSpecial; + static short drag_x; + short temp_x; + switch(msg) + { + case WM_CREATE: + return 0; + case WM_SIZE: + return 0; + case WM_PAINT: + PAINTSTRUCT ps; + GetUpdateRect (hWnd, &ps.rcPaint, true); + ps.hdc=GetDC(hWnd); + ps.fErase=true; + BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + ReleaseDC(hWnd, ps.hdc); + return 0; + case WM_LBUTTONDOWN: + PaintSpecial=true; + drag_x=GET_X_LPARAM(lParam); + SetCapture(hWnd); + return 0; + case WM_LBUTTONUP: + PaintSpecial=false; + temp_x=(GET_X_LPARAM(lParam)-drag_x); + HWND hDlg,hTree,hList; + RECT treeRect; + RECT listRect; + hDlg=GetParent(hWnd); + hTree=GetDlgItem(hDlg, IDC_ROM_DIR); + hList=GetDlgItem(hDlg, IDC_ROMLIST); + GetWindowRect(hTree, &treeRect); + + POINT p; + p.x=temp_x+treeRect.right; + p.y=treeRect.top; + + GetWindowRect(hList, &listRect); + + if(p.x>(listRect.right-50)) + { + temp_x-=(short)(p.x-(listRect.right-50)); + p.x=listRect.right-50; + } + + + ScreenToClient(hDlg, &p); + + if(p.x<50) + { + temp_x+=(short)(50-p.x); + p.x=50; + } + + + MoveWindow( hWnd, p.x, p.y, listRect.left-treeRect.right, listRect.bottom-listRect.top, FALSE); + MoveWindow(hList, p.x+(listRect.left-treeRect.right), p.y,listRect.right-listRect.left-temp_x, listRect.bottom-listRect.top, TRUE); + p.x=treeRect.left; + p.y=treeRect.top; + ScreenToClient(hDlg, &p); + MoveWindow(hTree, p.x, p.y,treeRect.right-treeRect.left+temp_x,treeRect.bottom-treeRect.top, true); + InvalidateRect(hWnd,NULL, true); + ReleaseCapture(); + return 0; + case WM_MOUSEMOVE: + if (wParam & MK_LBUTTON) + { + //move paint location + PaintSpecial=true; + temp_x=(GET_X_LPARAM(lParam)-drag_x); + hDlg=GetParent(hWnd); + hTree=GetDlgItem(hDlg, IDC_ROM_DIR); + hList=GetDlgItem(hDlg, IDC_ROMLIST); + GetWindowRect(hTree, &treeRect); + + p.x=temp_x+treeRect.right; + + p.y=treeRect.top; + GetWindowRect(hList, &listRect); + + if(p.x>(listRect.right-50)) + { + temp_x-=(short)(p.x-(listRect.right-50)); + p.x=listRect.right-50; + } + + + ScreenToClient(hDlg, &p); + + if(p.x<50) + { + temp_x+=(short)(50-p.x); + p.x=50; + } + + MoveWindow(hWnd, p.x, p.y, listRect.left-treeRect.right, listRect.bottom-listRect.top, FALSE); + MoveWindow(hList, p.x+(listRect.left-treeRect.right), p.y,listRect.right-listRect.left-temp_x, listRect.bottom-listRect.top, TRUE); + p.x=treeRect.left; + p.y=treeRect.top; + ScreenToClient(hDlg, &p); + MoveWindow(hTree, p.x, p.y,treeRect.right-treeRect.left+temp_x,treeRect.bottom-treeRect.top, true); + InvalidateRect(hWnd,NULL, true); + } + return 0; + case WM_CAPTURECHANGED: + PaintSpecial=false; + ReleaseCapture(); + return 0; + case WM_DESTROY: + return 0; + default:return DefWindowProc(hWnd, msg, wParam, lParam); + } +} + + + + +#ifdef NETPLAY_SUPPORT +int CALLBACK DlgNetConnect(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ +// HKEY hKey; + char defPort[5]; + char portTemp[5]; + char temp[100]; +// char temp2[5]; + static char* hostname; +// unsigned long cbData; +// static int i; + if(Settings.Port==0) + { + _itoa(1996,defPort,10); + } + else + { + _itoa(Settings.Port,defPort,10); + } + + WORD chkLength; +// if(RegCreateKeyEx(HKEY_CURRENT_USER,MY_REG_KEY "\\1.x\\NetPlayServerHistory",0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS, NULL, &hKey,NULL) == ERROR_SUCCESS){} + + switch (msg) + { + case WM_INITDIALOG: + WinRefreshDisplay(); + SetWindowText(hDlg,NPCON_TITLE); + SetDlgItemText(hDlg,IDC_LABEL_SERVERADDY,NPCON_LABEL_SERVERADDY); + SetDlgItemText(hDlg,IDC_LABEL_PORTNUM,NPCON_LABEL_PORTNUM); + SetDlgItemText(hDlg,IDC_CLEARHISTORY, NPCON_CLEARHISTORY); + SetDlgItemText(hDlg,IDOK,BUTTON_OK); + SetDlgItemText(hDlg,IDCANCEL,BUTTON_CANCEL); + hostname = (char *)lParam; + { + for(int i=0; i65535||atoi(portTemp)<1024) + { + MessageBox(hDlg,"Port Number needs to be between 1024 and 65535","Error",MB_OK); + break; + } + else + { + Settings.Port = atoi(portTemp); + } + //chkLength = (WORD) SendDlgItemMessage(hDlg,IDC_HOSTNAME,EM_LINELENGTH,0,0); + //if(chkLength > 0) + //{ + //SendDlgItemMessage(hDlg,IDC_HOSTNAME,EM_GETLINE,0,(LPARAM)hostname); + SendDlgItemMessage(hDlg,IDC_HOSTNAME,WM_GETTEXT,100,(LPARAM)temp); + if(!strcmp(temp, NPCON_ENTERHOST)) + { + MessageBox(hDlg,NPCON_PLEASE_ENTERHOST,"Error",MB_OK); + break; + } + strcpy(hostname,temp); + //MessageBox(hDlg,temp,"hola",MB_OK); + + // save hostname in recent list + { + int i; + for(i=0; i 0) + { + EndDialog(hDlg,1); + return TRUE; + } + else + { + EndDialog(hDlg,0); + return TRUE; + } + + break; + //} + } + case IDCANCEL: + { + EndDialog(hDlg, 0); + return TRUE; + } + default:break; + } + } + return FALSE; +} +#endif +void SetInfoDlgColor(unsigned char r, unsigned char g, unsigned char b) +{ + GUI.InfoColor=RGB(r,g,b); +} + +void ClearExts(void) +{ + ExtList* temp; + ExtList* curr=valid_ext; + while(curr!=NULL) + { + temp=curr->next; + if(curr->extension) + delete [] curr->extension; + delete curr; + curr=temp; + } + valid_ext=NULL; + +} + +void LoadExts(void) +{ + char buffer[MAX_PATH+2]; + if(valid_ext!=NULL) + { + ClearExts(); + } + ExtList* curr; + valid_ext=new ExtList; + curr=valid_ext; + ZeroMemory(curr, sizeof(ExtList)); + ifstream in; + +#if (((defined(_MSC_VER) && _MSC_VER >= 1300)) || defined(__MINGW32__)) + in.open("Valid.Ext", ios::in); +#else + in.open("Valid.Ext", ios::in|ios::nocreate); +#endif + if (!in.is_open()) + { + in.clear(); + MakeExtFile(); + #if (((defined(_MSC_VER) && _MSC_VER >= 1300)) || defined(__MINGW32__)) + in.open("Valid.Ext", ios::in); + #else + in.open("Valid.Ext", ios::in|ios::nocreate); + #endif + if(!in.is_open()) + { + MessageBox(GUI.hWnd, "Fatal Error: The File \"Valid.Ext\" could not be found or created.", "Error", MB_ICONERROR|MB_OK); + PostQuitMessage(-1); + } + } + + do + { + buffer[0]='\0'; + in.getline(buffer,MAX_PATH+2); + if((*buffer)!='\0') + { + curr->next=new ExtList; + curr=curr->next; + ZeroMemory(curr, sizeof(ExtList)); + if(_strnicmp(buffer+strlen(buffer)-1, "Y", 1)==0) + curr->compressed=true; + if(strlen(buffer)>1) + { + curr->extension=new char[strlen(buffer)-1]; + strncpy(curr->extension, buffer, strlen(buffer)-1); + curr->extension[strlen(buffer)-1]='\0'; + } + else curr->extension=NULL; + } + } + while(!in.eof()); + in.close(); + curr=valid_ext; + valid_ext=valid_ext->next; + delete curr; +} + +void MakeExtFile(void) +{ + ofstream out; + out.open("Valid.Ext"); + + out<<"N" <65535) + { + MessageBox(hDlg,"Port Number needs to be betweeb 1024 and 65535","Error",MB_OK); + break; + } + else + { + Settings.Port = atoi(defPort); + } + //MessageBox(hDlg,defPort,defPort,MB_OK); + Settings.NetPlayServer = IsDlgButtonChecked(hDlg,IDC_ACTASSERVER); + NPServer.SendROMImageOnConnect = IsDlgButtonChecked(hDlg,IDC_SENDROM); + NPServer.SyncByReset = IsDlgButtonChecked(hDlg,IDC_SYNCBYRESET); + + EndDialog(hDlg,0); + WinSaveConfigFile(); + return TRUE; + } + case IDCANCEL: + { + EndDialog(hDlg,0); + return TRUE; + } + } + } + return FALSE; +} +#endif + +void EnableDisableKeyFields (int index, HWND hDlg) +{ + bool enableUnTurboable; + if(index < 5) + { + SetDlgItemText(hDlg,IDC_LABEL_RIGHT,INPUTCONFIG_LABEL_RIGHT); + SetDlgItemText(hDlg,IDC_LABEL_UPLEFT,INPUTCONFIG_LABEL_UPLEFT); + SetDlgItemText(hDlg,IDC_LABEL_UPRIGHT,INPUTCONFIG_LABEL_UPRIGHT); + SetDlgItemText(hDlg,IDC_LABEL_DOWNRIGHT,INPUTCONFIG_LABEL_DOWNRIGHT); + SetDlgItemText(hDlg,IDC_LABEL_UP,INPUTCONFIG_LABEL_UP); + SetDlgItemText(hDlg,IDC_LABEL_LEFT,INPUTCONFIG_LABEL_LEFT); + SetDlgItemText(hDlg,IDC_LABEL_DOWN,INPUTCONFIG_LABEL_DOWN); + SetDlgItemText(hDlg,IDC_LABEL_DOWNLEFT,INPUTCONFIG_LABEL_DOWNLEFT); + enableUnTurboable = true; + } + else + { + SetDlgItemText(hDlg,IDC_LABEL_UP,INPUTCONFIG_LABEL_MAKE_TURBO); + SetDlgItemText(hDlg,IDC_LABEL_LEFT,INPUTCONFIG_LABEL_MAKE_HELD); + SetDlgItemText(hDlg,IDC_LABEL_DOWN,INPUTCONFIG_LABEL_MAKE_TURBO_HELD); + SetDlgItemText(hDlg,IDC_LABEL_RIGHT,INPUTCONFIG_LABEL_CLEAR_TOGGLES_AND_TURBO); + SetDlgItemText(hDlg,IDC_LABEL_UPLEFT,INPUTCONFIG_LABEL_UNUSED); + SetDlgItemText(hDlg,IDC_LABEL_UPRIGHT,INPUTCONFIG_LABEL_UNUSED); + SetDlgItemText(hDlg,IDC_LABEL_DOWNLEFT,INPUTCONFIG_LABEL_UNUSED); + SetDlgItemText(hDlg,IDC_LABEL_DOWNRIGHT,INPUTCONFIG_LABEL_UNUSED); + SetDlgItemText(hDlg,IDC_UPLEFT,INPUTCONFIG_LABEL_UNUSED); + SetDlgItemText(hDlg,IDC_UPRIGHT,INPUTCONFIG_LABEL_UNUSED); + SetDlgItemText(hDlg,IDC_DWNLEFT,INPUTCONFIG_LABEL_UNUSED); + SetDlgItemText(hDlg,IDC_DWNRIGHT,INPUTCONFIG_LABEL_UNUSED); + enableUnTurboable = false; + } + + EnableWindow(GetDlgItem(hDlg,IDC_UPLEFT), enableUnTurboable); + EnableWindow(GetDlgItem(hDlg,IDC_UPRIGHT), enableUnTurboable); + EnableWindow(GetDlgItem(hDlg,IDC_DWNRIGHT), enableUnTurboable); + EnableWindow(GetDlgItem(hDlg,IDC_DWNLEFT), enableUnTurboable); +} + +void UpdateModeComboBox(HWND hComboBox) +{ + TCHAR modeTxt[80]; + bool foundCurMode=false; + dMode curMode; + + dm.clear(); + ComboBox_ResetContent(hComboBox); + WinEnumDisplayModes(&dm); + + for(int i=0;i= 512 && GUI.FullscreenMode.height >= 478) || GUI.Stretch) + Settings.SupportHiRes = IsDlgButtonChecked(hDlg, IDC_HIRES); + else + Settings.SupportHiRes = false; + GUI.HeightExtend = IsDlgButtonChecked(hDlg, IDC_HEIGHT_EXTEND)!=0; + Settings.AutoDisplayMessages = IsDlgButtonChecked(hDlg, IDC_MESSAGES_IN_IMAGE); + GUI.DoubleBuffered = (bool)(IsDlgButtonChecked(hDlg, IDC_DBLBUFFER)==BST_CHECKED); + if(IsDlgButtonChecked(hDlg, IDC_AUTOFRAME)) + { + Settings.SkipFrames=AUTO_FRAMERATE; + Settings.AutoMaxSkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP_DISP, UDM_GETPOS, 0,0); + } + else + { + Settings.SkipFrames=SendDlgItemMessage(hDlg, IDC_SPIN_MAX_SKIP_DISP_FIXED, UDM_GETPOS, 0,0); + } + + + GUI.Stretch = (bool)(IsDlgButtonChecked(hDlg, IDC_STRETCH)==BST_CHECKED); + GUI.AspectRatio = (bool)(IsDlgButtonChecked(hDlg, IDC_ASPECT)==BST_CHECKED); + fullscreenWanted = (bool)(IsDlgButtonChecked(hDlg, IDC_FULLSCREEN)==BST_CHECKED); + GUI.EmulateFullscreen = (bool)(IsDlgButtonChecked(hDlg, IDC_EMUFULLSCREEN)==BST_CHECKED); + Settings.DisplayFrameRate = IsDlgButtonChecked(hDlg, IDC_SHOWFPS); + + index = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION)); + + GUI.FullscreenMode = dm[index]; + + + // we might've changed the region that the game draws over + // (by turning on "maintain aspect ratio", or turning on "extend height" when "maintain aspect ratio" is already on), + // so we must invalidate the window to redraw black + // behind the possibly-newly-revealed areas of the window + RedrawWindow((HWND)GetParent(hDlg),NULL,NULL, RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_ERASENOW); + + WinSaveConfigFile(); + + if(!GUI.FullScreen || (GUI.FullscreenMode.width >= 512 && GUI.FullscreenMode.height >= 478)) + GUI.NextScale = (RenderFilter)SendDlgItemMessage(hDlg,IDC_FILTERBOX,CB_GETCURSEL,0,0); + else + GUI.NextScale = FILTER_NONE; + + if(!GUI.FullScreen || (GUI.FullscreenMode.width >= 512 && GUI.FullscreenMode.height >= 478)) + GUI.NextScaleHiRes = GUI.ScaleHiRes; + else + GUI.NextScaleHiRes = FILTER_SIMPLE1X; + + EndDialog(hDlg,0); + WinDisplayApplyChanges(); + + // if we are emulating fullscreen and now want to change to regular fullscreen + // we want to switch back to the last window size + if(fullscreenWanted && GUI.EmulatedFullscreen && !GUI.EmulateFullscreen) { + GUI.EmulateFullscreen = true; + ToggleFullScreen(); + GUI.EmulateFullscreen = false; + } + if(fullscreenWanted != GUI.EmulatedFullscreen) { + ToggleFullScreen(); + } + + + return false; + + + + case IDCANCEL: + ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_OUTPUTMETHOD),prevOutputMethod); + SendMessage(hDlg,WM_COMMAND,MAKEWPARAM(IDC_OUTPUTMETHOD,CBN_SELCHANGE),0); + + { + //UpdateScale(GUI.Scale, prevScale); + GUI.Scale = GUI.NextScale = (RenderFilter)prevScale; + GUI.ScaleHiRes = GUI.NextScaleHiRes = (RenderFilter)prevScaleHiRes; + GFX.RealPPL = prevPPL; + GUI.Stretch = prevStretch; + Settings.AutoDisplayMessages = prevAutoDisplayMessages; + GUI.BilinearFilter = prevVideoMemory; + GUI.AspectRatio = prevAspectRatio; + GUI.AspectWidth = prevAspectWidth; + GUI.HeightExtend = prevHeightExtend; + + } + + EndDialog(hDlg,0); + + return false; + } + + + } + + return false; +} + +static void set_buttoninfo(int index, HWND hDlg) +{ + SendDlgItemMessage(hDlg,IDC_UP,WM_USER+44,Joypad[index].Up,0); + SendDlgItemMessage(hDlg,IDC_LEFT,WM_USER+44,Joypad[index].Left,0); + SendDlgItemMessage(hDlg,IDC_DOWN,WM_USER+44,Joypad[index].Down,0); + SendDlgItemMessage(hDlg,IDC_RIGHT,WM_USER+44,Joypad[index].Right,0); + SendDlgItemMessage(hDlg,IDC_A,WM_USER+44,Joypad[index].A,0); + SendDlgItemMessage(hDlg,IDC_B,WM_USER+44,Joypad[index].B,0); + SendDlgItemMessage(hDlg,IDC_X,WM_USER+44,Joypad[index].X,0); + SendDlgItemMessage(hDlg,IDC_Y,WM_USER+44,Joypad[index].Y,0); + SendDlgItemMessage(hDlg,IDC_L,WM_USER+44,Joypad[index].L,0); + SendDlgItemMessage(hDlg,IDC_R,WM_USER+44,Joypad[index].R,0); + SendDlgItemMessage(hDlg,IDC_START,WM_USER+44,Joypad[index].Start,0); + SendDlgItemMessage(hDlg,IDC_SELECT,WM_USER+44,Joypad[index].Select,0); + if(index < 5) + { + SendDlgItemMessage(hDlg,IDC_UPLEFT,WM_USER+44,Joypad[index].Left_Up,0); + SendDlgItemMessage(hDlg,IDC_UPRIGHT,WM_USER+44,Joypad[index].Right_Up,0); + SendDlgItemMessage(hDlg,IDC_DWNLEFT,WM_USER+44,Joypad[index].Left_Down,0); + SendDlgItemMessage(hDlg,IDC_DWNRIGHT,WM_USER+44,Joypad[index].Right_Down,0); + } +} + +void TranslateKey(WORD keyz,char *out); +//HWND funky; +SJoyState JoystickF [16]; + + +#ifdef NETPLAY_SUPPORT +int CALLBACK DlgNPProgress(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + SendDlgItemMessage(hDlg,IDC_NPPROGRESS,PBM_SETRANGE,0,(LPARAM)MAKELPARAM (0, 100)); + SendDlgItemMessage(hDlg,IDC_NPPROGRESS,PBM_SETPOS,(WPARAM)(int)NetPlay.PercentageComplete,0); + + return false; +} +#endif +int CALLBACK DlgInputConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + char temp[256]; + short C; + int i, which; + static int index=0; + + + static SJoypad pads[10]; + + + //HBRUSH g_hbrBackground; + + InitInputCustomControl(); +switch(msg) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint (hDlg, &ps); + + EndPaint (hDlg, &ps); + } + return true; + case WM_INITDIALOG: + WinRefreshDisplay(); + SetWindowText(hDlg,INPUTCONFIG_TITLE); + SetDlgItemText(hDlg,IDC_JPTOGGLE,INPUTCONFIG_JPTOGGLE); + SetDlgItemText(hDlg,IDC_OK,BUTTON_OK); + SetDlgItemText(hDlg,IDC_CANCEL,BUTTON_CANCEL); + SetDlgItemText(hDlg,IDC_LABEL_UP,INPUTCONFIG_LABEL_UP); + SetDlgItemText(hDlg,IDC_LABEL_DOWN,INPUTCONFIG_LABEL_DOWN); + SetDlgItemText(hDlg,IDC_LABEL_LEFT,INPUTCONFIG_LABEL_LEFT); + SetDlgItemText(hDlg,IDC_LABEL_A,INPUTCONFIG_LABEL_A); + SetDlgItemText(hDlg,IDC_LABEL_B,INPUTCONFIG_LABEL_B); + SetDlgItemText(hDlg,IDC_LABEL_X,INPUTCONFIG_LABEL_X); + SetDlgItemText(hDlg,IDC_LABEL_Y,INPUTCONFIG_LABEL_Y); + SetDlgItemText(hDlg,IDC_LABEL_L,INPUTCONFIG_LABEL_L); + SetDlgItemText(hDlg,IDC_LABEL_R,INPUTCONFIG_LABEL_R); + SetDlgItemText(hDlg,IDC_LABEL_START,INPUTCONFIG_LABEL_START); + SetDlgItemText(hDlg,IDC_LABEL_SELECT,INPUTCONFIG_LABEL_SELECT); + SetDlgItemText(hDlg,IDC_LABEL_UPRIGHT,INPUTCONFIG_LABEL_UPRIGHT); + SetDlgItemText(hDlg,IDC_LABEL_UPLEFT,INPUTCONFIG_LABEL_UPLEFT); + SetDlgItemText(hDlg,IDC_LABEL_DOWNRIGHT,INPUTCONFIG_LABEL_DOWNRIGHT); + SetDlgItemText(hDlg,IDC_LABEL_DOWNLEFT,INPUTCONFIG_LABEL_DOWNLEFT); + SetDlgItemText(hDlg,IDC_LABEL_BLUE,INPUTCONFIG_LABEL_BLUE); + + for(i=5;i<10;i++) + Joypad[i].Left_Up = Joypad[i].Right_Up = Joypad[i].Left_Down = Joypad[i].Right_Down = 0; + + memcpy(pads, Joypad, 10*sizeof(SJoypad)); + + for( i=0;i<256;i++) + GetAsyncKeyState(i); + + for( C = 0; C != 16; C ++) + JoystickF[C].Attached = joyGetDevCaps( JOYSTICKID1+C, &JoystickF[C].Caps, sizeof( JOYCAPS)) == JOYERR_NOERROR; + + for(i=1;i<6;i++) + { + sprintf(temp,INPUTCONFIG_JPCOMBO,i); + SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)temp); + } + + for(i=6;i<11;i++) + { + sprintf(temp,INPUTCONFIG_JPCOMBO INPUTCONFIG_LABEL_CONTROLLER_TURBO_PANEL_MOD,i-5); + SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)temp); + } + + SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_SETCURSEL,(WPARAM)0,0); + + SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK, Joypad[index].Enabled ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg,IDC_ALLOWLEFTRIGHT,BM_SETCHECK, Settings.UpAndDown ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); + + set_buttoninfo(index,hDlg); + + EnableDisableKeyFields(index,hDlg); + + PostMessage(hDlg,WM_COMMAND, CBN_SELCHANGE<<16, 0); + + SetFocus(GetDlgItem(hDlg,IDC_JPCOMBO)); + + return true; + break; + case WM_CLOSE: + EndDialog(hDlg, 0); + return TRUE; + case WM_USER+46: + // refresh command, for clicking away from a selected field + index = SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_GETCURSEL,0,0); + if(index > 4) index += 3; // skip controllers 6, 7, and 8 in the input dialog + set_buttoninfo(index,hDlg); + return TRUE; + case WM_USER+43: + //MessageBox(hDlg,"USER+43 CAUGHT","moo",MB_OK); + which = GetDlgCtrlID((HWND)lParam); + switch(which) + { + case IDC_UP: + Joypad[index].Up = wParam; + + break; + case IDC_DOWN: + Joypad[index].Down = wParam; + + break; + case IDC_LEFT: + Joypad[index].Left = wParam; + + break; + case IDC_RIGHT: + Joypad[index].Right = wParam; + + break; + case IDC_A: + Joypad[index].A = wParam; + + break; + case IDC_B: + Joypad[index].B = wParam; + + break; + case IDC_X: + Joypad[index].X = wParam; + + break; + case IDC_Y: + Joypad[index].Y = wParam; + + break; + case IDC_L: + Joypad[index].L = wParam; + break; + + case IDC_R: + Joypad[index].R = wParam; + + break; + case IDC_SELECT: + Joypad[index].Select = wParam; + + break; + case IDC_START: + Joypad[index].Start = wParam; + + break; + case IDC_UPLEFT: + Joypad[index].Left_Up = wParam; + + break; + case IDC_UPRIGHT: + Joypad[index].Right_Up = wParam; + + break; + case IDC_DWNLEFT: + Joypad[index].Left_Down = wParam; + + case IDC_DWNRIGHT: + Joypad[index].Right_Down = wParam; + + break; + + } + + set_buttoninfo(index,hDlg); + + PostMessage(hDlg,WM_NEXTDLGCTL,0,0); + return true; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDCANCEL: + memcpy(Joypad, pads, 10*sizeof(SJoypad)); + EndDialog(hDlg,0); + break; + + case IDOK: + Settings.UpAndDown = IsDlgButtonChecked(hDlg, IDC_ALLOWLEFTRIGHT); + WinSaveConfigFile(); + EndDialog(hDlg,0); + break; + + case IDC_JPTOGGLE: // joypad Enable toggle + index = SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_GETCURSEL,0,0); + if(index > 4) index += 3; // skip controllers 6, 7, and 8 in the input dialog + Joypad[index].Enabled=IsDlgButtonChecked(hDlg,IDC_JPTOGGLE); + set_buttoninfo(index, hDlg); // update display of conflicts + break; + + } + switch(HIWORD(wParam)) + { + case CBN_SELCHANGE: + index = SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_GETCURSEL,0,0); + SendDlgItemMessage(hDlg,IDC_JPCOMBO,CB_SETCURSEL,(WPARAM)index,0); + if(index > 4) index += 3; // skip controllers 6, 7, and 8 in the input dialog + if(index < 8) + { + SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK, Joypad[index].Enabled ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); + EnableWindow(GetDlgItem(hDlg,IDC_JPTOGGLE),TRUE); + } + else + { + SendDlgItemMessage(hDlg,IDC_JPTOGGLE,BM_SETCHECK, Joypad[index-8].Enabled ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); + EnableWindow(GetDlgItem(hDlg,IDC_JPTOGGLE),FALSE); + } + + set_buttoninfo(index,hDlg); + + EnableDisableKeyFields(index,hDlg); + + break; + } + return FALSE; + + } + + return FALSE; +} + + +static void set_hotkeyinfo(HWND hDlg) +{ + int index = SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_GETCURSEL,0,0); + + switch(index) + { + case 0: + // set page 1 fields + SendDlgItemMessage(hDlg,IDC_HOTKEY1,WM_USER+44,CustomKeys.SpeedUp.key,CustomKeys.SpeedUp.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY2,WM_USER+44,CustomKeys.SpeedDown.key,CustomKeys.SpeedDown.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY3,WM_USER+44,CustomKeys.Pause.key,CustomKeys.Pause.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY4,WM_USER+44,CustomKeys.FrameAdvance.key,CustomKeys.FrameAdvance.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY5,WM_USER+44,CustomKeys.FastForward.key,CustomKeys.FastForward.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.SkipUp.key,CustomKeys.SkipUp.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.SkipDown.key,CustomKeys.SkipDown.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,CustomKeys.ScopeTurbo.key,CustomKeys.ScopeTurbo.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,CustomKeys.ScopePause.key,CustomKeys.ScopePause.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.ShowPressed.key,CustomKeys.ShowPressed.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.FrameCount.key,CustomKeys.FrameCount.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.ReadOnly.key,CustomKeys.ReadOnly.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,CustomKeys.SaveScreenShot.key,CustomKeys.SaveScreenShot.modifiers); + break; + case 1: + SendDlgItemMessage(hDlg,IDC_HOTKEY1,WM_USER+44,CustomKeys.BGL1.key,CustomKeys.BGL1.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY2,WM_USER+44,CustomKeys.BGL2.key,CustomKeys.BGL2.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY3,WM_USER+44,CustomKeys.BGL3.key,CustomKeys.BGL3.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY4,WM_USER+44,CustomKeys.BGL4.key,CustomKeys.BGL4.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY5,WM_USER+44,CustomKeys.BGL5.key,CustomKeys.BGL5.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.ClippingWindows.key,CustomKeys.ClippingWindows.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.Transparency.key,CustomKeys.Transparency.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,CustomKeys.HDMA.key,CustomKeys.HDMA.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,CustomKeys.GLCube.key,CustomKeys.GLCube.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.SwitchControllers.key,CustomKeys.SwitchControllers.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.JoypadSwap.key,CustomKeys.JoypadSwap.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.ResetGame.key,CustomKeys.ResetGame.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,CustomKeys.ToggleCheats.key,CustomKeys.ToggleCheats.modifiers); +// SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.InterpMode7.key,CustomKeys.InterpMode7.modifiers); +// SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,CustomKeys.BGLHack.key,CustomKeys.BGLHack.modifiers); + break; + case 2: + SendDlgItemMessage(hDlg,IDC_HOTKEY1,WM_USER+44,CustomKeys.TurboA.key,CustomKeys.TurboA.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY2,WM_USER+44,CustomKeys.TurboB.key,CustomKeys.TurboB.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY3,WM_USER+44,CustomKeys.TurboY.key,CustomKeys.TurboY.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY4,WM_USER+44,CustomKeys.TurboX.key,CustomKeys.TurboX.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY5,WM_USER+44,CustomKeys.TurboL.key,CustomKeys.TurboL.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY6,WM_USER+44,CustomKeys.TurboR.key,CustomKeys.TurboR.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY7,WM_USER+44,CustomKeys.TurboStart.key,CustomKeys.TurboStart.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY8,WM_USER+44,CustomKeys.TurboSelect.key,CustomKeys.TurboSelect.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY9,WM_USER+44,CustomKeys.TurboLeft.key,CustomKeys.TurboLeft.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY10,WM_USER+44,CustomKeys.TurboUp.key,CustomKeys.TurboUp.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,CustomKeys.TurboRight.key,CustomKeys.TurboRight.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,CustomKeys.TurboDown.key,CustomKeys.TurboDown.modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,0,0); + break; + case 3: + for(int i = 0 ; i < 10 ; i++) + SendDlgItemMessage(hDlg,IDC_HOTKEY1+i,WM_USER+44,CustomKeys.SelectSave[i].key,CustomKeys.SelectSave[i].modifiers); + SendDlgItemMessage(hDlg,IDC_HOTKEY11,WM_USER+44,0,0); + SendDlgItemMessage(hDlg,IDC_HOTKEY12,WM_USER+44,0,0); + SendDlgItemMessage(hDlg,IDC_HOTKEY13,WM_USER+44,0,0); + break; + } + + SendDlgItemMessage(hDlg,IDC_SLOTPLUS,WM_USER+44,CustomKeys.SlotPlus.key,CustomKeys.SlotPlus.modifiers); + SendDlgItemMessage(hDlg,IDC_SLOTMINUS,WM_USER+44,CustomKeys.SlotMinus.key,CustomKeys.SlotMinus.modifiers); + SendDlgItemMessage(hDlg,IDC_SLOTSAVE,WM_USER+44,CustomKeys.SlotSave.key,CustomKeys.SlotSave.modifiers); + SendDlgItemMessage(hDlg,IDC_SLOTLOAD,WM_USER+44,CustomKeys.SlotLoad.key,CustomKeys.SlotLoad.modifiers); + int i; + for(i = 0 ; i < 10 ; i++) SendDlgItemMessage(hDlg,IDC_SAVE1+i,WM_USER+44,CustomKeys.Save[i].key,CustomKeys.Save[i].modifiers); + for(i = 0 ; i < 10 ; i++) SendDlgItemMessage(hDlg,IDC_SAVE11+i,WM_USER+44,CustomKeys.Load[i].key,CustomKeys.Load[i].modifiers); + + switch(index) + { + case 0: + // set page 1 label text + SetDlgItemText(hDlg,IDC_LABEL_HK1,HOTKEYS_LABEL_1_1); + SetDlgItemText(hDlg,IDC_LABEL_HK2,HOTKEYS_LABEL_1_2); + SetDlgItemText(hDlg,IDC_LABEL_HK3,HOTKEYS_LABEL_1_3); + SetDlgItemText(hDlg,IDC_LABEL_HK4,HOTKEYS_LABEL_1_4); + SetDlgItemText(hDlg,IDC_LABEL_HK5,HOTKEYS_LABEL_1_5); + SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_1_6); + SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_1_7); + SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_1_8); + SetDlgItemText(hDlg,IDC_LABEL_HK9,HOTKEYS_LABEL_1_9); + SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_1_10); + SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_1_11); + SetDlgItemText(hDlg,IDC_LABEL_HK12,HOTKEYS_LABEL_1_12); + SetDlgItemText(hDlg,IDC_LABEL_HK13,HOTKEYS_LABEL_1_13); + break; + case 1: + SetDlgItemText(hDlg,IDC_LABEL_HK1,HOTKEYS_LABEL_2_1); + SetDlgItemText(hDlg,IDC_LABEL_HK2,HOTKEYS_LABEL_2_2); + SetDlgItemText(hDlg,IDC_LABEL_HK3,HOTKEYS_LABEL_2_3); + SetDlgItemText(hDlg,IDC_LABEL_HK4,HOTKEYS_LABEL_2_4); + SetDlgItemText(hDlg,IDC_LABEL_HK5,HOTKEYS_LABEL_2_5); + SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_2_6); + SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_2_7); + SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_2_8); + SetDlgItemText(hDlg,IDC_LABEL_HK9,HOTKEYS_LABEL_2_9); + SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_2_10); + SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_2_11); + SetDlgItemText(hDlg,IDC_LABEL_HK12,HOTKEYS_LABEL_2_12); + SetDlgItemText(hDlg,IDC_LABEL_HK13,HOTKEYS_LABEL_2_13); + break; + case 2: + SetDlgItemText(hDlg,IDC_LABEL_HK1,HOTKEYS_LABEL_3_1); + SetDlgItemText(hDlg,IDC_LABEL_HK2,HOTKEYS_LABEL_3_2); + SetDlgItemText(hDlg,IDC_LABEL_HK3,HOTKEYS_LABEL_3_3); + SetDlgItemText(hDlg,IDC_LABEL_HK4,HOTKEYS_LABEL_3_4); + SetDlgItemText(hDlg,IDC_LABEL_HK5,HOTKEYS_LABEL_3_5); + SetDlgItemText(hDlg,IDC_LABEL_HK6,HOTKEYS_LABEL_3_6); + SetDlgItemText(hDlg,IDC_LABEL_HK7,HOTKEYS_LABEL_3_7); + SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_3_8); + SetDlgItemText(hDlg,IDC_LABEL_HK8,HOTKEYS_LABEL_3_8); + SetDlgItemText(hDlg,IDC_LABEL_HK9,HOTKEYS_LABEL_3_9); + SetDlgItemText(hDlg,IDC_LABEL_HK10,HOTKEYS_LABEL_3_10); + SetDlgItemText(hDlg,IDC_LABEL_HK11,HOTKEYS_LABEL_3_11); + SetDlgItemText(hDlg,IDC_LABEL_HK12,HOTKEYS_LABEL_3_12); + SetDlgItemText(hDlg,IDC_LABEL_HK13,INPUTCONFIG_LABEL_UNUSED); + + break; + case 3: + for(int i = 0 ; i < 10 ; i++) + { + char temp [64]; + sprintf(temp, "Select Slot %d", i); + SetDlgItemText(hDlg,IDC_LABEL_HK1+i,temp); + } + for(int i = 10 ; i < 13 ; i++) + SetDlgItemText(hDlg,IDC_LABEL_HK1+i,INPUTCONFIG_LABEL_UNUSED); + + break; + } +} + +// DlgHotkeyConfig +int CALLBACK DlgHotkeyConfig(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int i, which; + static int index=0; + + + static SCustomKeys keys; + + + //HBRUSH g_hbrBackground; + InitKeyCustomControl(); +switch(msg) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint (hDlg, &ps); + + EndPaint (hDlg, &ps); + } + return true; + case WM_INITDIALOG: + WinRefreshDisplay(); + SetWindowText(hDlg,HOTKEYS_TITLE); + + // insert hotkey page list items + for(i=1 ; i <= 4 ; i++) + { + char temp[256]; + sprintf(temp,HOTKEYS_HKCOMBO,i); + SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_ADDSTRING,0,(LPARAM)(LPCTSTR)temp); + } + + SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_SETCURSEL,(WPARAM)0,0); + + memcpy(&keys, &CustomKeys, sizeof(SCustomKeys)); + for( i=0;i<256;i++) + { + GetAsyncKeyState(i); + } + + SetDlgItemText(hDlg,IDC_LABEL_BLUE,HOTKEYS_LABEL_BLUE); + + set_hotkeyinfo(hDlg); + + PostMessage(hDlg,WM_COMMAND, CBN_SELCHANGE<<16, 0); + + SetFocus(GetDlgItem(hDlg,IDC_HKCOMBO)); + + + return true; + break; + case WM_CLOSE: + EndDialog(hDlg, 0); + return TRUE; + case WM_USER+46: + // refresh command, for clicking away from a selected field + index = SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_GETCURSEL,0,0); + set_hotkeyinfo(hDlg); + return TRUE; + case WM_USER+43: + { + //MessageBox(hDlg,"USER+43 CAUGHT","moo",MB_OK); + int modifiers = 0; + if(GetAsyncKeyState(VK_MENU) || wParam == VK_MENU) + modifiers |= CUSTKEY_ALT_MASK; + if(GetAsyncKeyState(VK_CONTROL) || wParam == VK_CONTROL) + modifiers |= CUSTKEY_CTRL_MASK; + if(GetAsyncKeyState(VK_SHIFT) || wParam == VK_SHIFT) + modifiers |= CUSTKEY_SHIFT_MASK; + + int index = SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_GETCURSEL,0,0); + + which = GetDlgCtrlID((HWND)lParam); + + switch(which) + { + case IDC_HOTKEY1: + if(index == 0) CustomKeys.SpeedUp.key = wParam, CustomKeys.SpeedUp.modifiers = modifiers; + if(index == 1) CustomKeys.BGL1.key = wParam, CustomKeys.BGL1.modifiers = modifiers; + if(index == 2) CustomKeys.TurboA.key = wParam, CustomKeys.TurboA.modifiers = modifiers; + if(index == 3) CustomKeys.SelectSave[0].key = wParam, CustomKeys.SelectSave[0].modifiers = modifiers; + break; + case IDC_HOTKEY2: + if(index == 0) CustomKeys.SpeedDown.key = wParam, CustomKeys.SpeedDown.modifiers = modifiers; + if(index == 1) CustomKeys.BGL2.key = wParam, CustomKeys.BGL2.modifiers = modifiers; + if(index == 2) CustomKeys.TurboB.key = wParam, CustomKeys.TurboB.modifiers = modifiers; + if(index == 3) CustomKeys.SelectSave[1].key = wParam, CustomKeys.SelectSave[1].modifiers = modifiers; + break; + case IDC_HOTKEY3: + if(index == 0) CustomKeys.Pause.key = wParam, CustomKeys.Pause.modifiers = modifiers; + if(index == 1) CustomKeys.BGL3.key = wParam, CustomKeys.BGL3.modifiers = modifiers; + if(index == 2) CustomKeys.TurboY.key = wParam, CustomKeys.TurboY.modifiers = modifiers; + if(index == 3) CustomKeys.SelectSave[2].key = wParam, CustomKeys.SelectSave[2].modifiers = modifiers; + break; + case IDC_HOTKEY4: + if(index == 0) CustomKeys.FrameAdvance.key = wParam, CustomKeys.FrameAdvance.modifiers = modifiers; + if(index == 1) CustomKeys.BGL4.key = wParam, CustomKeys.BGL4.modifiers = modifiers; + if(index == 2) CustomKeys.TurboX.key = wParam, CustomKeys.TurboX.modifiers = modifiers; + if(index == 3) CustomKeys.SelectSave[3].key = wParam, CustomKeys.SelectSave[3].modifiers = modifiers; + break; + case IDC_HOTKEY5: + if(index == 0) CustomKeys.FastForward.key = wParam, CustomKeys.FastForward.modifiers = modifiers; + if(index == 1) CustomKeys.BGL5.key = wParam, CustomKeys.BGL5.modifiers = modifiers; + if(index == 2) CustomKeys.TurboL.key = wParam, CustomKeys.TurboL.modifiers = modifiers; + if(index == 3) CustomKeys.SelectSave[4].key = wParam, CustomKeys.SelectSave[4].modifiers = modifiers; + break; + case IDC_HOTKEY6: + if(index == 0) CustomKeys.SkipUp.key = wParam, CustomKeys.SkipUp.modifiers = modifiers; + if(index == 1) CustomKeys.ClippingWindows.key = wParam, CustomKeys.ClippingWindows.modifiers = modifiers; + if(index == 2) CustomKeys.TurboR.key = wParam, CustomKeys.TurboR.modifiers = modifiers; + if(index == 3) CustomKeys.SelectSave[5].key = wParam, CustomKeys.SelectSave[5].modifiers = modifiers; + break; + case IDC_HOTKEY7: + if(index == 0) CustomKeys.SkipDown.key = wParam, CustomKeys.SkipDown.modifiers = modifiers; + if(index == 1) CustomKeys.Transparency.key = wParam, CustomKeys.Transparency.modifiers = modifiers; + if(index == 2) CustomKeys.TurboStart.key = wParam, CustomKeys.TurboStart.modifiers = modifiers; + if(index == 3) CustomKeys.SelectSave[6].key = wParam, CustomKeys.SelectSave[6].modifiers = modifiers; + break; + case IDC_HOTKEY8: + if(index == 0) CustomKeys.ScopeTurbo.key = wParam, CustomKeys.ScopeTurbo.modifiers = modifiers; + if(index == 1) CustomKeys.HDMA.key = wParam, CustomKeys.HDMA.modifiers = modifiers; + if(index == 2) CustomKeys.TurboSelect.key = wParam, CustomKeys.TurboSelect.modifiers = modifiers; + if(index == 3) CustomKeys.SelectSave[7].key = wParam, CustomKeys.SelectSave[7].modifiers = modifiers; + break; + case IDC_HOTKEY9: + if(index == 0) CustomKeys.ScopePause.key = wParam, CustomKeys.ScopePause.modifiers = modifiers; + if(index == 1) CustomKeys.GLCube.key = wParam, CustomKeys.GLCube.modifiers = modifiers; + if(index == 2) CustomKeys.TurboLeft.key = wParam, CustomKeys.TurboLeft.modifiers = modifiers; + if(index == 3) CustomKeys.SelectSave[8].key = wParam, CustomKeys.SelectSave[8].modifiers = modifiers; + break; + case IDC_HOTKEY10: + if(index == 0) CustomKeys.ShowPressed.key = wParam, CustomKeys.ShowPressed.modifiers = modifiers; + if(index == 1) CustomKeys.SwitchControllers.key = wParam, CustomKeys.SwitchControllers.modifiers = modifiers; + if(index == 2) CustomKeys.TurboUp.key = wParam, CustomKeys.TurboUp.modifiers = modifiers; + if(index == 3) CustomKeys.SelectSave[9].key = wParam, CustomKeys.SelectSave[9].modifiers = modifiers; + break; + case IDC_HOTKEY11: + if(index == 0) CustomKeys.FrameCount.key = wParam, CustomKeys.FrameCount.modifiers = modifiers; + if(index == 1) CustomKeys.JoypadSwap.key = wParam, CustomKeys.JoypadSwap.modifiers = modifiers; + if(index == 2) CustomKeys.TurboRight.key = wParam, CustomKeys.TurboRight.modifiers = modifiers; + break; + case IDC_HOTKEY12: + if(index == 0) CustomKeys.ReadOnly.key = wParam, CustomKeys.ReadOnly.modifiers = modifiers; + if(index == 1) CustomKeys.ResetGame.key = wParam, CustomKeys.ResetGame.modifiers = modifiers; + if(index == 2) CustomKeys.TurboDown.key = wParam, CustomKeys.TurboDown.modifiers = modifiers; +// if(index == 3) CustomKeys.InterpMode7.key = wParam, CustomKeys.InterpMode7.modifiers = modifiers; + break; + case IDC_HOTKEY13: + if(index == 0) CustomKeys.SaveScreenShot.key = wParam, CustomKeys.SaveScreenShot.modifiers = modifiers; + if(index == 1) CustomKeys.ToggleCheats.key = wParam, CustomKeys.ToggleCheats.modifiers = modifiers; +// if(index == 3) CustomKeys.BGLHack.key = wParam, CustomKeys.BGLHack.modifiers = modifiers; + break; + + case IDC_SLOTPLUS: + CustomKeys.SlotPlus.key = wParam; + CustomKeys.SlotPlus.modifiers = modifiers; + break; + + case IDC_SLOTMINUS: + CustomKeys.SlotMinus.key = wParam; + CustomKeys.SlotMinus.modifiers = modifiers; + break; + + case IDC_SLOTLOAD: + CustomKeys.SlotLoad.key = wParam; + CustomKeys.SlotLoad.modifiers = modifiers; + break; + + case IDC_SLOTSAVE: + CustomKeys.SlotSave.key = wParam; + CustomKeys.SlotSave.modifiers = modifiers; + break; + } + + if(which >= IDC_SAVE1 && which <= IDC_SAVE10) + { + CustomKeys.Save[which-IDC_SAVE1].key = wParam; + CustomKeys.Save[which-IDC_SAVE1].modifiers = modifiers; + } + if(which >= IDC_SAVE11 && which <= IDC_SAVE20) + { + CustomKeys.Load[which-IDC_SAVE11].key = wParam; + CustomKeys.Load[which-IDC_SAVE11].modifiers = modifiers; + } + + set_hotkeyinfo(hDlg); + PostMessage(hDlg,WM_NEXTDLGCTL,0,0); +// PostMessage(hDlg,WM_KILLFOCUS,0,0); + } + return true; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDCANCEL: + memcpy(&CustomKeys, &keys, sizeof(SCustomKeys)); + EndDialog(hDlg,0); + break; + case IDOK: + WinSaveConfigFile(); + EndDialog(hDlg,0); + break; + } + switch(HIWORD(wParam)) + { + case CBN_SELCHANGE: + index = SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_GETCURSEL,0,0); + SendDlgItemMessage(hDlg,IDC_HKCOMBO,CB_SETCURSEL,(WPARAM)index,0); + + set_hotkeyinfo(hDlg); + + SetFocus(GetDlgItem(hDlg,IDC_HKCOMBO)); + + break; + } + return FALSE; + + } + + return FALSE; +} + + +template +int ScanAddress(const char* str, IntType& value) +{ + int ret = 0; + if(tolower(*str) == 's') + { + ret = sscanf(str+1, "%x", &value); + value += 0x7E0000 + 0x20000; + } + else if(tolower(*str) == 'i') + { + ret = sscanf(str+1, "%x", &value); + value += 0x7E0000 + 0x30000; + } + else + { + int plus = (*str == '0' && tolower(str[1]) == 'x') ? 2 : 0; + ret = sscanf(str+plus, "%x", &value); + } + return ret; +} + +enum CheatStatus{ + Untouched, + Deleted, + Modified +}; +typedef struct{ +int* index; +DWORD* state; +}CheatTracker; + +#define ITEM_QUERY(a, b, c, d, e) ZeroMemory(&a, sizeof(LV_ITEM)); \ + a.iItem= ListView_GetSelectionMark(GetDlgItem(hDlg, b)); \ + a.iSubItem=c; \ + a.mask=LVIF_TEXT; \ + a.pszText=d; \ + a.cchTextMax=e; \ + ListView_GetItem(GetDlgItem(hDlg, b), &a); + +int CALLBACK DlgCheater(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static bool internal_change; + static bool has_sel; + static int sel_idx; + static uint8 new_sel; + static CheatTracker ct; + switch(msg) + { + case WM_INITDIALOG: + WinRefreshDisplay(); + + ListView_SetExtendedListViewStyle(GetDlgItem(hDlg, IDC_CHEAT_LIST), LVS_EX_FULLROWSELECT|LVS_EX_CHECKBOXES); + + SendDlgItemMessage(hDlg, IDC_CHEAT_CODE, EM_LIMITTEXT, 14, 0); + SendDlgItemMessage(hDlg, IDC_CHEAT_DESCRIPTION, EM_LIMITTEXT, 22, 0); + SendDlgItemMessage(hDlg, IDC_CHEAT_ADDRESS, EM_LIMITTEXT, 6, 0); + SendDlgItemMessage(hDlg, IDC_CHEAT_BYTE, EM_LIMITTEXT, 3, 0); + + LVCOLUMN col; + char temp[32]; + strcpy(temp,SEARCH_COLUMN_ADDRESS); + ZeroMemory(&col, sizeof(LVCOLUMN)); + col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH; + col.fmt=LVCFMT_LEFT; + col.iOrder=0; + col.cx=70; + col.cchTextMax=7; + col.pszText=temp; + + ListView_InsertColumn(GetDlgItem(hDlg,IDC_CHEAT_LIST), 0, &col); + + strcpy(temp,SEARCH_COLUMN_VALUE); + ZeroMemory(&col, sizeof(LVCOLUMN)); + col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; + col.fmt=LVCFMT_LEFT; + col.iOrder=1; + col.cx=43; + col.cchTextMax=3; + col.pszText=temp; + col.iSubItem=1; + + ListView_InsertColumn(GetDlgItem(hDlg,IDC_CHEAT_LIST), 1, &col); + + strcpy(temp,SEARCH_COLUMN_DESCRIPTION); + ZeroMemory(&col, sizeof(LVCOLUMN)); + col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; + col.fmt=LVCFMT_LEFT; + col.iOrder=2; + col.cx=165; + col.cchTextMax=32; + col.pszText=temp; + col.iSubItem=2; + + ListView_InsertColumn(GetDlgItem(hDlg,IDC_CHEAT_LIST), 2, &col); + + ct.index=new int[Cheat.num_cheats]; + ct.state=new DWORD[Cheat.num_cheats]; + + uint32 counter; + for(counter=0; counter=curr_idx) + ct.index[k]++; + } + ct.index[counter]=curr_idx; + ct.state[counter]=Untouched; + + sprintf(buffer, "%02X", Cheat.c[counter].byte); + ZeroMemory(&lvi, sizeof(LVITEM)); + lvi.iItem=curr_idx; + lvi.iSubItem=1; + lvi.mask=LVIF_TEXT; + lvi.pszText=buffer; + lvi.cchTextMax=3; + SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi); + + ZeroMemory(&lvi, sizeof(LVITEM)); + lvi.iItem=curr_idx; + lvi.iSubItem=2; + lvi.mask=LVIF_TEXT; + lvi.pszText=Cheat.c[counter].name; + lvi.cchTextMax=23; + SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi); + + ListView_SetCheckState(GetDlgItem(hDlg,IDC_CHEAT_LIST), curr_idx, Cheat.c[counter].enabled); + + } + return true; + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint (hDlg, &ps); + + EndPaint (hDlg, &ps); + } + return true; + case WM_NOTIFY: + { + switch(LOWORD(wParam)) + { + case IDC_CHEAT_LIST: + if(0==ListView_GetSelectedCount(GetDlgItem(hDlg, IDC_CHEAT_LIST))) + { + EnableWindow(GetDlgItem(hDlg, IDC_DELETE_CHEAT), false); + EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false); + has_sel=false; + sel_idx=-1; + } + else + { + EnableWindow(GetDlgItem(hDlg, IDC_DELETE_CHEAT), true); + if(!has_sel||sel_idx!=ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_CHEAT_LIST))) + { + new_sel=3; + //change + char buf[25]; + LV_ITEM lvi; + + ITEM_QUERY (lvi, IDC_CHEAT_LIST, 0, buf, 7); + + SetDlgItemText(hDlg, IDC_CHEAT_ADDRESS, lvi.pszText); + + ITEM_QUERY (lvi, IDC_CHEAT_LIST, 1, &buf[strlen(buf)], 3); + + SetDlgItemText(hDlg, IDC_CHEAT_CODE, buf); + char temp[4]; + int q; + sscanf(lvi.pszText, "%02X", &q); + sprintf(temp, "%d", q); + SetDlgItemText(hDlg, IDC_CHEAT_BYTE, temp); + + ITEM_QUERY (lvi, IDC_CHEAT_LIST, 2, buf, 24); + + internal_change=true; + SetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, lvi.pszText); + + } + sel_idx=ListView_GetSelectionMark(GetDlgItem(hDlg, IDC_CHEAT_LIST)); + has_sel=true; + } + + return true; + default: return false; + } + } + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDC_CHEAT_DESCRIPTION: + { + switch(HIWORD(wParam)) + { + case EN_CHANGE: + + if(internal_change) + { + internal_change=!internal_change; + return false; + } + if(!has_sel) + return true; + EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), true); + return true; + } + break; + + } + case IDC_ADD_CHEAT: + { + char temp[24]; + GetDlgItemText(hDlg, IDC_CHEAT_CODE, temp, 23); + if(strcmp(temp, "")) + { + int j; + bool skip=false; + int count=1; + uint32 addy; + uint8 byte[3]; + //test game genie + if (NULL==S9xGameGenieToRaw (temp, addy, byte[0])) + skip=true; + //test goldfinger + + // if(!skip + + //test PAR + + if(!skip) + { + if(NULL==S9xProActionReplayToRaw(temp, addy, byte[0])) + skip=true; + } + + if(!skip) + return 0; + + for(j=0; j=curr_idx) + ct.index[k]++; + } + + + sprintf(buffer, "%02X", byte[j]); + ZeroMemory(&lvi, sizeof(LVITEM)); + lvi.iItem=curr_idx; + lvi.iSubItem=1; + lvi.mask=LVIF_TEXT; + lvi.pszText=buffer; + lvi.cchTextMax=2; + SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi); + + GetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, temp, 23); + + ZeroMemory(&lvi, sizeof(LVITEM)); + lvi.iItem=curr_idx; + lvi.iSubItem=2; + lvi.mask=LVIF_TEXT; + lvi.pszText=temp; + lvi.cchTextMax=23; + SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi); + + addy++; + + + } + } + else + { + uint8 byte; + char buffer[7]; + char buffer2[7]; + + GetDlgItemText(hDlg, IDC_CHEAT_ADDRESS, buffer, 7); + GetDlgItemText(hDlg, IDC_CHEAT_BYTE, buffer2, 7); + + int curr_idx=-1; + LVITEM lvi; + ZeroMemory(&lvi, sizeof(LVITEM)); + lvi.mask=LVIF_TEXT; + lvi.pszText=buffer; + lvi.cchTextMax=6; + lvi.iItem=0; + curr_idx=ListView_InsertItem(GetDlgItem(hDlg,IDC_CHEAT_LIST), &lvi); + + int scanres; + if(buffer2[0]=='$') + sscanf(buffer2,"$%2X", (unsigned int*)&scanres); + else sscanf(buffer2,"%d", &scanres); + byte = (uint8)(scanres & 0xff); + + sprintf(buffer2, "%02X", byte); + + ZeroMemory(&lvi, sizeof(LVITEM)); + lvi.iItem=curr_idx; + lvi.iSubItem=1; + lvi.mask=LVIF_TEXT; + lvi.pszText=buffer2; + lvi.cchTextMax=2; + SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi); + + GetDlgItemText(hDlg, IDC_CHEAT_DESCRIPTION, temp, 23); + + ZeroMemory(&lvi, sizeof(LVITEM)); + lvi.iItem=curr_idx; + lvi.iSubItem=2; + lvi.mask=LVIF_TEXT; + lvi.pszText=temp; + lvi.cchTextMax=23; + SendDlgItemMessage(hDlg,IDC_CHEAT_LIST, LVM_SETITEM, 0, (LPARAM)&lvi); + } + } + break; + case IDC_UPDATE_CHEAT: + { + char temp[24]; + GetDlgItemText(hDlg, IDC_CHEAT_CODE, temp, 23); + if(strcmp(temp, "")) + { + int j; + bool skip=false; + int count=1; + uint32 addy; + uint8 byte[3]; + //test game genie + if (NULL==S9xGameGenieToRaw (temp, addy, byte[0])) + skip=true; + //test goldfinger + + // if(!skip + + //test PAR + + if(!skip) + { + if(NULL==S9xProActionReplayToRaw(temp, addy, byte[0])) + skip=true; + } + + if(!skip) + return 0; + + for(j=0;j<(int)Cheat.num_cheats;j++) + { + if(ct.index[j]==sel_idx) + ct.state[j]=Modified; + } + + for(j=0; jsel_idx) + ct.index[j]--; + } + } + ListView_DeleteItem(GetDlgItem(hDlg, IDC_CHEAT_LIST), sel_idx); + + break; + case IDC_CLEAR_CHEATS: + internal_change = true; + SetDlgItemText(hDlg,IDC_CHEAT_CODE,""); + SetDlgItemText(hDlg,IDC_CHEAT_ADDRESS,""); + SetDlgItemText(hDlg,IDC_CHEAT_BYTE,""); + SetDlgItemText(hDlg,IDC_CHEAT_DESCRIPTION,""); + ListView_SetItemState(GetDlgItem(hDlg, IDC_CHEAT_LIST),sel_idx, 0, LVIS_SELECTED|LVIS_FOCUSED); + ListView_SetSelectionMark(GetDlgItem(hDlg, IDC_CHEAT_LIST), -1); + sel_idx=-1; + has_sel=false; + break; + case IDC_CHEAT_CODE: + { + uint32 j, k; + long index; + char buffer[15]; + char buffer2[15]; + POINT point; + switch(HIWORD(wParam)) + { + case EN_CHANGE: + if(internal_change) + { + internal_change=false; + return true; + } + SendMessage((HWND)lParam, WM_GETTEXT, 15,(LPARAM)buffer); + GetCaretPos(&point); + + index = SendMessage((HWND)lParam,(UINT) EM_CHARFROMPOS, 0, (LPARAM) ((point.x&0x0000FFFF) | (((point.y&0x0000FFFF))<<16))); + + k=0; + for(j=0; j='0' && buffer[j]<='9') || (buffer[j]>='A' && buffer[j]<='F') || buffer[j]=='-' || buffer[j]=='X') + { + buffer2[k]=buffer[j]; + k++; + } + else index --; + } + buffer2[k]='\0'; + + if(has_sel&&!new_sel&&strlen(buffer2)!=0) + { + SetDlgItemText(hDlg, IDC_CHEAT_ADDRESS, ""); + SetDlgItemText(hDlg, IDC_CHEAT_BYTE, ""); + + } + + if(new_sel!=0) + new_sel--; + + internal_change=true; + SendMessage((HWND)lParam, WM_SETTEXT, 0,(LPARAM)buffer2); + SendMessage((HWND)lParam, (UINT) EM_SETSEL, (WPARAM) (index), index); + + uint32 addy; + uint8 val; + bool8 sram; + uint8 bytes[3]; + if(NULL==S9xGameGenieToRaw(buffer2, addy, val)||NULL==S9xProActionReplayToRaw(buffer2, addy, val)||NULL==S9xGoldFingerToRaw(buffer2, addy, sram, val, bytes)) + { + if(has_sel) + EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), true); + else EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false); + EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), true); + } + else + { + EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), false); + EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false); + } + + // SetDlgItemText(hDlg, IDC_CHEAT_ADDRESS, ""); + // SetDlgItemText(hDlg, IDC_CHEAT_BYTE, ""); + break; + } + break; + } + case IDC_CHEAT_ADDRESS: + { + uint32 j, k; + long index; + char buffer[7]; + char buffer2[7]; + POINT point; + switch(HIWORD(wParam)) + { + case EN_CHANGE: + if(internal_change) + { + internal_change=false; + return true; + } + SendMessage((HWND)lParam, WM_GETTEXT, 7,(LPARAM)buffer); + GetCaretPos(&point); + + index = SendMessage((HWND)lParam,(UINT) EM_CHARFROMPOS, 0, (LPARAM) ((point.x&0x0000FFFF) | (((point.y&0x0000FFFF))<<16))); + + k=0; + for(j=0; j='0' && buffer[j]<='9') || (buffer[j]>='A' && buffer[j]<='F')) + { + buffer2[k]=buffer[j]; + k++; + } + else index --; + } + buffer2[k]='\0'; + + + internal_change=true; + SendMessage((HWND)lParam, WM_SETTEXT, 0,(LPARAM)buffer2); + SendMessage((HWND)lParam, (UINT) EM_SETSEL, (WPARAM) (index), index); + + SendMessage(GetDlgItem(hDlg, IDC_CHEAT_BYTE), WM_GETTEXT, 4,(LPARAM)buffer); + + if(has_sel&&!new_sel&&0!=strlen(buffer2)) + SetDlgItemText(hDlg, IDC_CHEAT_CODE, ""); + + if(new_sel!=0) + new_sel--; + + if(strlen(buffer2)!=0 && strlen(buffer) !=0) + { + if(has_sel) + EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), true); + else EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false); + EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), true); + } + else + { + EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), false); + EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false); + } + + break; + } + break; + } + case IDC_CHEAT_BYTE: + { + uint32 j, k; + long index; + char buffer[4]; + char buffer2[4]; + POINT point; + switch(HIWORD(wParam)) + { + case EN_CHANGE: + if(internal_change) + { + internal_change=false; + return true; + } + SendMessage((HWND)lParam, WM_GETTEXT, 4,(LPARAM)buffer); + GetCaretPos(&point); + + index = SendMessage((HWND)lParam,(UINT) EM_CHARFROMPOS, 0, (LPARAM) ((point.x&0x0000FFFF) | (((point.y&0x0000FFFF))<<16))); + + k=0; + for(j=0; j='0' && buffer[j]<='9') || (buffer[j]>='A' && buffer[j]<='F') || buffer[j]=='$') + { + buffer2[k]=buffer[j]; + k++; + } + else index --; + } + buffer2[k]='\0'; + + if(has_sel&&!new_sel&&0!=strlen(buffer2)) + SetDlgItemText(hDlg, IDC_CHEAT_CODE, ""); + + if(new_sel!=0) + new_sel--; + + internal_change=true; + SendMessage((HWND)lParam, WM_SETTEXT, 0,(LPARAM)buffer2); + SendMessage((HWND)lParam, (UINT) EM_SETSEL, (WPARAM) (index), index); + + SendMessage(GetDlgItem(hDlg, IDC_CHEAT_ADDRESS), WM_GETTEXT, 7,(LPARAM)buffer); + if(strlen(buffer2)!=0 && strlen(buffer) !=0) + { + if(has_sel) + EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), true); + else EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false); + EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), true); + } + else + { + EnableWindow(GetDlgItem(hDlg, IDC_ADD_CHEAT), false); + EnableWindow(GetDlgItem(hDlg, IDC_UPDATE_CHEAT), false); + } + //SetDlgItemText(hDlg, IDC_CHEAT_CODE, ""); + break; + } + break; + } + case IDOK: + { + int k,l; + bool hit; + unsigned int scanned; + for(k=0;k=0;l--) + { + if(ct.state[l]==Deleted) + { + S9xDeleteCheat(l); + } + } + } + case IDCANCEL: + delete [] ct.index; + delete [] ct.state; + EndDialog(hDlg, 0); + return true; + default:return false; + } + } + default: return false; + } +} + + +#define TEST_BIT(a,v) \ +((a)[(v) >> 5] & (1 << ((v) & 31))) + +static inline int CheatCount(int byteSub) +{ + int a, b=0; +// for(a=0;a<0x32000-byteSub;a++) + for(a=0;a<0x30000-byteSub;a++) // hide IRAM from cheat dialog (it seems not to be searhed correctly) + { + if(TEST_BIT(Cheat.ALL_BITS, a)) + b++; + } + return b; +} + + +struct ICheat +{ + uint32 address; + uint32 new_val; + uint32 saved_val; + int size; + bool8 enabled; + bool8 saved; + char name [22]; + int format; +}; + +bool TestRange(int val_type, S9xCheatDataSize bytes, uint32 value) +{ + if(val_type!=2) + { + if(bytes==S9X_8_BITS) + { + if(value<256) + return true; + else return false; + } + if(bytes==S9X_16_BITS) + { + if(value<65536) + return true; + else return false; + } + if(bytes==S9X_24_BITS) + { + if(value<16777216) + return true; + else return false; + } + //if it reads in, it's a valid 32-bit unsigned! + return true; + } + else + { + if(bytes==S9X_8_BITS) + { + if((int32)value<128 && (int32)value >= -128) + return true; + else return false; + } + if(bytes==S9X_16_BITS) + { + if((int32)value<32768 && (int32)value >= -32768) + return true; + else return false; + } + if(bytes==S9X_24_BITS) + { + if((int32)value<8388608 && (int32)value >= -8388608) + return true; + else return false; + } + //should be handled by sscanf + return true; + } +} + + +int CALLBACK DlgCheatSearch(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static S9xCheatDataSize bytes; + static int val_type; + static int use_entered; + static S9xCheatComparisonType comp_type; + switch(msg) + { + case WM_INITDIALOG: + { + WinRefreshDisplay(); + if(val_type==0) + val_type=1; + ListView_SetExtendedListViewStyle(GetDlgItem(hDlg, IDC_ADDYS), LVS_EX_FULLROWSELECT); + + //defaults + SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_CHECKED, 0); + if(!use_entered) + SendDlgItemMessage(hDlg, IDC_PREV, BM_SETCHECK, BST_CHECKED, 0); + else if(use_entered==1) + { + SendDlgItemMessage(hDlg, IDC_ENTERED, BM_SETCHECK, BST_CHECKED, 0); + EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), true); + EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), true); + } + else if(use_entered==2) + { + SendDlgItemMessage(hDlg, IDC_ENTEREDADDRESS, BM_SETCHECK, BST_CHECKED, 0); + EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), true); + EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), true); + } + SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_CHECKED, 0); + SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_CHECKED, 0); + + if(comp_type==S9X_GREATER_THAN) + { + SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg, IDC_GREATER_THAN, BM_SETCHECK, BST_CHECKED, 0); + } + else if(comp_type==S9X_LESS_THAN_OR_EQUAL) + { + SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg, IDC_LESS_THAN_EQUAL, BM_SETCHECK, BST_CHECKED, 0); + + } + else if(comp_type==S9X_GREATER_THAN_OR_EQUAL) + { + SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg, IDC_GREATER_THAN_EQUAL, BM_SETCHECK, BST_CHECKED, 0); + + } + else if(comp_type==S9X_EQUAL) + { + SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg, IDC_EQUAL, BM_SETCHECK, BST_CHECKED, 0); + + } + else if(comp_type==S9X_NOT_EQUAL) + { + SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg, IDC_NOT_EQUAL, BM_SETCHECK, BST_CHECKED, 0); + + } + + if(val_type==2) + { + SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg, IDC_SIGNED, BM_SETCHECK, BST_CHECKED, 0); + + } + else if(val_type==3) + { + SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg, IDC_HEX, BM_SETCHECK, BST_CHECKED, 0); + } + + if(bytes==S9X_16_BITS) + { + SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg, IDC_2_BYTE, BM_SETCHECK, BST_CHECKED, 0); + } + else if(bytes==S9X_24_BITS) + { + SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg, IDC_3_BYTE, BM_SETCHECK, BST_CHECKED, 0); + } + else if(bytes==S9X_32_BITS) + { + SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg, IDC_4_BYTE, BM_SETCHECK, BST_CHECKED, 0); + } + + LVCOLUMN col; + char temp[32]; + strcpy(temp,"Address"); + ZeroMemory(&col, sizeof(LVCOLUMN)); + col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH; + col.fmt=LVCFMT_LEFT; + col.iOrder=0; + col.cx=70; + col.cchTextMax=7; + col.pszText=temp; + + ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDYS), 0, &col); + + strcpy(temp,"Curr. Value"); + ZeroMemory(&col, sizeof(LVCOLUMN)); + col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; + col.fmt=LVCFMT_LEFT; + col.iOrder=1; + col.cx=104; + col.cchTextMax=3; + col.pszText=temp; + col.iSubItem=1; + + ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDYS), 1, &col); + + strcpy(temp,"Prev. Value"); + ZeroMemory(&col, sizeof(LVCOLUMN)); + col.mask=LVCF_FMT|LVCF_ORDER|LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM; + col.fmt=LVCFMT_LEFT; + col.iOrder=2; + col.cx=104; + col.cchTextMax=32; + col.pszText=temp; + col.iSubItem=2; + + ListView_InsertColumn(GetDlgItem(hDlg,IDC_ADDYS), 2, &col); + + { + int l = CheatCount(bytes); + ListView_SetItemCount (GetDlgItem(hDlg, IDC_ADDYS), l); + } + + } + return true; + + case WM_DESTROY: + { + cheatSearchHWND = NULL; + S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR)); + break; + } + + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint (hDlg, &ps); + + EndPaint (hDlg, &ps); + } + return true; + case WM_NOTIFY: + { + static int selectionMarkOverride = -1; + static int foundItemOverride = -1; + if(wParam == IDC_ADDYS) + { + NMHDR * nmh=(NMHDR*)lParam; + if(nmh->hwndFrom == GetDlgItem(hDlg, IDC_ADDYS) && nmh->code == LVN_GETDISPINFO) + { + static TCHAR buf[12]; // the following code assumes this variable is static + int i, j; + NMLVDISPINFO * nmlvdi=(NMLVDISPINFO*)lParam; + j=nmlvdi->item.iItem; + j++; + for(i=0;i<(0x32000-bytes)&& j>0;i++) + { + if(TEST_BIT(Cheat.ALL_BITS, i)) + j--; + } + if (i>=0x32000 && j!=0) + { + return false; + } + i--; + if(j=nmlvdi->item.iSubItem==0) + { + if(i < 0x20000) + sprintf(buf, "%06X", i+0x7E0000); + else if(i < 0x30000) + sprintf(buf, "s%05X", i-0x20000); + else + sprintf(buf, "i%05X", i-0x30000); + nmlvdi->item.pszText=buf; + nmlvdi->item.cchTextMax=8; + } + if(j=nmlvdi->item.iSubItem==1) + { + int q=0, r=0; + if(i < 0x20000) + for(r=0;r<=bytes;r++) + q+=(Cheat.RAM[i+r])<<(8*r); + else if(i < 0x30000) + for(r=0;r<=bytes;r++) + q+=(Cheat.SRAM[(i-0x20000)+r])<<(8*r); + else + for(r=0;r<=bytes;r++) + q+=(Cheat.FillRAM[(i-0x30000)+r])<<(8*r); + //needs to account for size + switch(val_type) + { + case 1: + sprintf(buf, "%u", q); + break; + case 3: + { + switch(bytes) + { + default: + case S9X_8_BITS:sprintf(buf, "%02X", q&0xFF);break; + case S9X_16_BITS: sprintf(buf, "%04X", q&0xFFFF); break; + case S9X_24_BITS: sprintf(buf, "%06X", q&0xFFFFFF);break; + case S9X_32_BITS: sprintf(buf, "%08X", q);break; + } + } + break; + case 2: + default: + switch(bytes) + { + default: + case S9X_8_BITS: + if((q-128)<0) + sprintf(buf, "%d", q&0xFF); + else sprintf(buf, "%d", q-256); + break; + case S9X_16_BITS: + if((q-32768)<0) + sprintf(buf, "%d", q&0xFFFF); + else sprintf(buf, "%d", q-65536); + break; + case S9X_24_BITS: + if((q-0x800000)<0) + sprintf(buf, "%d", q&0xFFFFFF); + else sprintf(buf, "%d", q-0x1000000); + break; + + case S9X_32_BITS: sprintf(buf, "%d", q);break; + } + break; + } + nmlvdi->item.pszText=buf; + nmlvdi->item.cchTextMax=4; + } + if(j=nmlvdi->item.iSubItem==2) + { + int q=0, r=0; + if(i < 0x20000) + for(r=0;r<=bytes;r++) + q+=(Cheat.CWRAM[i+r])<<(8*r); + else if(i < 0x30000) + for(r=0;r<=bytes;r++) + q+=(Cheat.CSRAM[(i-0x20000)+r])<<(8*r); + else + for(r=0;r<=bytes;r++) + q+=(Cheat.CIRAM[(i-0x30000)+r])<<(8*r); + //needs to account for size + switch(val_type) + { + case 1: + sprintf(buf, "%u", q); + break; + case 3: + { + switch(bytes) + { + default: + case S9X_8_BITS:sprintf(buf, "%02X", q&0xFF);break; + case S9X_16_BITS: sprintf(buf, "%04X", q&0xFFFF); break; + case S9X_24_BITS: sprintf(buf, "%06X", q&0xFFFFFF);break; + case S9X_32_BITS: sprintf(buf, "%08X", q);break; + } + break; + } + case 2: + default: + switch(bytes) + { + default: + case S9X_8_BITS: + if((q-128)<0) + sprintf(buf, "%d", q&0xFF); + else sprintf(buf, "%d", q-256); + break; + case S9X_16_BITS: + if((q-32768)<0) + sprintf(buf, "%d", q&0xFFFF); + else sprintf(buf, "%d", q-65536); + break; + case S9X_24_BITS: + if((q-0x800000)<0) + sprintf(buf, "%d", q&0xFFFFFF); + else sprintf(buf, "%d", q-0x1000000); + break; + + case S9X_32_BITS: sprintf(buf, "%d", q);break; + } + break; + } + nmlvdi->item.pszText=buf; + nmlvdi->item.cchTextMax=4; + } + // nmlvdi->item.mask=LVIF_TEXT; // This is bad as wine relies on this to not change. + + } + else if(nmh->hwndFrom == GetDlgItem(hDlg, IDC_ADDYS) && (nmh->code == (UINT)LVN_ITEMACTIVATE||nmh->code == (UINT)NM_CLICK)) + { + bool enable=true; + if(-1==ListView_GetSelectionMark(nmh->hwndFrom)) + { + enable=false; + } + EnableWindow(GetDlgItem(hDlg, IDC_C_ADD), enable); + } + // allow typing in an address to jump to it + else if(nmh->hwndFrom == GetDlgItem(hDlg, IDC_ADDYS) && nmh->code == (UINT)LVN_ODFINDITEM) + { + LRESULT pResult; + + // pNMHDR has information about the item we should find + // In pResult we should save which item that should be selected + NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)lParam; + + /* pFindInfo->iStart is from which item we should search. + We search to bottom, and then restart at top and will stop + at pFindInfo->iStart, unless we find an item that match + */ + + // Set the default return value to -1 + // That means we didn't find any match. + pResult = -1; + + //Is search NOT based on string? + if( (pFindInfo->lvfi.flags & LVFI_STRING) == 0 ) + { + //This will probably never happend... + return pResult; + } + + //This is the string we search for + LPCSTR searchstr = pFindInfo->lvfi.psz; + + int startPos = pFindInfo->iStart; + //Is startPos outside the list (happens if last item is selected) + if(startPos >= ListView_GetItemCount(GetDlgItem(hDlg,IDC_ADDYS))) + startPos = 0; + + int currentPos, addrPos; + for(addrPos=0,currentPos=0;addrPos<(0x32000-bytes)&¤tPos=0x32000 && addrPos!=0) + break; + + // ignore leading 0's + while(searchstr[0] == '0' && searchstr[1] != '\0') + searchstr++; + + int searchNum = 0; + + ScanAddress(searchstr, searchNum); + + +// if (searchstr[0] != '7') +// break; // all searchable addresses begin with a 7 + + bool looped = false; + + // perform search + do + { + + if(addrPos == searchNum) + { + // select this item and stop search + pResult = currentPos; + break; + } + else if(addrPos > searchNum) + { + if(looped) + { + pResult = currentPos; + break; + } + + // optimization: the items are ordered alphabetically, so go back to the top since we know it can't be anything further down + currentPos = 0; + addrPos = 0; + while(!TEST_BIT(Cheat.ALL_BITS, addrPos)) + addrPos++; + looped = true; + continue; + } + + //Go to next item + addrPos++; + while(!TEST_BIT(Cheat.ALL_BITS, addrPos)) + addrPos++; + currentPos++; + + //Need to restart at top? + if(currentPos >= ListView_GetItemCount(GetDlgItem(hDlg,IDC_ADDYS))) + { + currentPos = 0; + addrPos = 0; + while(!TEST_BIT(Cheat.ALL_BITS, addrPos)) + addrPos++; + } + + //Stop if back to start + }while(currentPos != startPos); + + foundItemOverride = pResult; + + // in case previously-selected item is 0 + ListView_SetItemState (GetDlgItem(hDlg,IDC_ADDYS), 1, LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + + return pResult; // HACK: for some reason this selects the first item instead of what it's returning... current workaround is to manually re-select this return value upon the next changed event + } + else if(nmh->hwndFrom == GetDlgItem(hDlg, IDC_ADDYS) && nmh->code == LVN_ITEMCHANGED) + { + // hack - see note directly above + LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lParam; + if(lpnmlv->uNewState & (LVIS_SELECTED|LVIS_FOCUSED)) + { + if(foundItemOverride != -1 && lpnmlv->iItem == 0) + { + ListView_SetItemState (GetDlgItem(hDlg,IDC_ADDYS), foundItemOverride, LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED); + ListView_EnsureVisible (GetDlgItem(hDlg,IDC_ADDYS), foundItemOverride, FALSE); + selectionMarkOverride = foundItemOverride; + foundItemOverride = -1; + } + else + { + selectionMarkOverride = lpnmlv->iItem; + } + } + } + } + } + break; + case WM_ACTIVATE: + ListView_RedrawItems(GetDlgItem(hDlg, IDC_ADDYS),0, 0x32000); + break; + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDC_LESS_THAN: + case IDC_GREATER_THAN: + case IDC_LESS_THAN_EQUAL: + case IDC_GREATER_THAN_EQUAL: + case IDC_EQUAL: + case IDC_NOT_EQUAL: + if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_LESS_THAN)) + comp_type=S9X_LESS_THAN; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_GREATER_THAN)) + comp_type=S9X_GREATER_THAN; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_LESS_THAN_EQUAL)) + comp_type=S9X_LESS_THAN_OR_EQUAL; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_GREATER_THAN_EQUAL)) + comp_type=S9X_GREATER_THAN_OR_EQUAL; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_EQUAL)) + comp_type=S9X_EQUAL; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_NOT_EQUAL)) + comp_type=S9X_NOT_EQUAL; + + break; + case IDC_1_BYTE: + case IDC_2_BYTE: + case IDC_3_BYTE: + case IDC_4_BYTE: + if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_1_BYTE)) + bytes=S9X_8_BITS; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_2_BYTE)) + bytes=S9X_16_BITS; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_3_BYTE)) + bytes=S9X_24_BITS; + else bytes=S9X_32_BITS; + { + int l = CheatCount(bytes); + ListView_SetItemCount (GetDlgItem(hDlg, IDC_ADDYS), l); + } + + break; + + case IDC_SIGNED: + case IDC_UNSIGNED: + case IDC_HEX: + if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_UNSIGNED)) + val_type=1; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_SIGNED)) + val_type=2; + else val_type=3; + ListView_RedrawItems(GetDlgItem(hDlg, IDC_ADDYS),0, 0x32000); + break; + case IDC_C_ADD: + { + // account for size + struct ICheat cht; +// int idx=-1; + LVITEM lvi; + static TCHAR buf[12]; // the following code assumes this variable is static, I think + ZeroMemory(&cht, sizeof(struct SCheat)); + + //retrieve and convert to SCheat + + if(bytes==S9X_8_BITS) + cht.size=1; + else if (bytes==S9X_16_BITS) + cht.size=2; + else if (bytes==S9X_24_BITS) + cht.size=3; + else if (bytes==S9X_32_BITS) + cht.size=4; + + + ITEM_QUERY(lvi, IDC_ADDYS, 0, buf, 7); + + + ScanAddress(buf, cht.address); + + memset(buf, 0, 7); + if(val_type==1) + { + ITEM_QUERY(lvi, IDC_ADDYS, 1, buf, 12); + sscanf(buf, "%u", &cht.new_val); + memset(buf, 0, 7); + ITEM_QUERY(lvi, IDC_ADDYS, 2, buf, 12); + sscanf(buf, "%u", &cht.saved_val); + } + else if(val_type==3) + { + ITEM_QUERY(lvi, IDC_ADDYS, 1, buf, 12); + sscanf(buf, "%x", &cht.new_val); + memset(buf, 0, 7); + ITEM_QUERY(lvi, IDC_ADDYS, 2, buf, 12); + sscanf(buf, "%x", &cht.saved_val); + } + else + { + ITEM_QUERY(lvi, IDC_ADDYS, 1, buf, 12); + sscanf(buf, "%d", &cht.new_val); + memset(buf, 0, 7); + ITEM_QUERY(lvi, IDC_ADDYS, 2, buf, 12); + sscanf(buf, "%d", &cht.saved_val); + } + cht.format=val_type; + //invoke dialog + if(!DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_CHEAT_FROM_SEARCH), hDlg, DlgCheatSearchAdd, (LPARAM)&cht)) + { + int p; + for(p=0; p>(8*p))&0xFF)); + //add cheat + strcpy(Cheat.c[Cheat.num_cheats-1].name, cht.name); + } + } + } + break; + case IDC_C_RESET: + S9xStartCheatSearch(&Cheat); + { + int l = CheatCount(bytes); + ListView_SetItemCount (GetDlgItem(hDlg, IDC_ADDYS), l); + } + ListView_RedrawItems(GetDlgItem(hDlg, IDC_ADDYS),0, 0x32000); + //val_type=1; + //SendDlgItemMessage(hDlg, IDC_UNSIGNED, BM_SETCHECK, BST_CHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_SIGNED, BM_SETCHECK, BST_UNCHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_HEX, BM_SETCHECK, BST_UNCHECKED, 0); + + //bytes=S9X_8_BITS; + //SendDlgItemMessage(hDlg, IDC_1_BYTE, BM_SETCHECK, BST_CHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_2_BYTE, BM_SETCHECK, BST_UNCHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_3_BYTE, BM_SETCHECK, BST_UNCHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_4_BYTE, BM_SETCHECK, BST_UNCHECKED, 0); + + + //use_entered=0; + //SendDlgItemMessage(hDlg, IDC_PREV, BM_SETCHECK, BST_CHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_ENTERED, BM_SETCHECK, BST_UNCHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_ENTEREDADDRESS, BM_SETCHECK, BST_UNCHECKED, 0); + //EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), false); + //EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), false); + + //comp_type=S9X_LESS_THAN; + //SendDlgItemMessage(hDlg, IDC_LESS_THAN, BM_SETCHECK, BST_CHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_GREATER_THAN, BM_SETCHECK, BST_UNCHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_LESS_THAN_EQUAL, BM_SETCHECK, BST_UNCHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_GREATER_THAN_EQUAL, BM_SETCHECK, BST_UNCHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_EQUAL, BM_SETCHECK, BST_UNCHECKED, 0); + //SendDlgItemMessage(hDlg, IDC_NOT_EQUAL, BM_SETCHECK, BST_UNCHECKED, 0); + return true; + case IDC_C_WATCH: + { + uint32 address = (uint32)-1; + char buf [12]; + LVITEM lvi; + ITEM_QUERY(lvi, IDC_ADDYS, 0, buf, 7); + ScanAddress(buf, address); + { + memset(buf, 0, 7); + + unsigned int i; + for(i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) + if(!watches[i].on || watches[i].address == address) + break; + if(i >= sizeof(watches)/sizeof(*watches)) + i = (unsigned int)(sizeof(watches)/sizeof(*watches)-1); + + watches[i].on = true; + + // account for size + if(bytes==S9X_8_BITS) + watches[i].size=1; + else if (bytes==S9X_16_BITS) + watches[i].size=2; + else if (bytes==S9X_24_BITS) + watches[i].size=3; + else if (bytes==S9X_32_BITS) + watches[i].size=4; + + watches[i].format=val_type; + watches[i].address=address; + strncpy(watches[i].buf,buf,12); + if(address < 0x7E0000 + 0x20000) + sprintf(watches[i].desc, "%6X", address); + else if(address < 0x7E0000 + 0x30000) + sprintf(watches[i].desc, "s%05X", address - 0x7E0000 - 0x20000); + else + sprintf(watches[i].desc, "i%05X", address - 0x7E0000 - 0x30000); + } + { + RECT rect; + GetClientRect (GUI.hWnd, &rect); + InvalidateRect (GUI.hWnd, &rect, true); + } + } + break; + case IDC_C_CLEARWATCH: + { + for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) + watches[i].on = false; + { + RECT rect; + GetClientRect (GUI.hWnd, &rect); + InvalidateRect (GUI.hWnd, &rect, true); + } + } + break; + case IDC_C_LOADWATCH: + { + OPENFILENAME ofn; + char szFileName[MAX_PATH]; + char szPathName[MAX_PATH]; + strcpy(szFileName, "watches"); + _fullpath(szPathName, S9xGetDirectory(CHEAT_DIR), MAX_PATH); + + ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) ); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = GUI.hWnd; + ofn.lpstrFilter = FILE_INFO_TXT_FILE_TYPE "\0*.txt\0" FILE_INFO_ANY_FILE_TYPE "\0*.*\0\0"; + ofn.lpstrFile = szFileName; + ofn.lpstrDefExt = "txt"; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; + ofn.lpstrInitialDir = szPathName; + if(GetOpenFileName( &ofn )) + { + FILE *file = fopen(szFileName, "r"); + if(file) + { + unsigned int i; + for(i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) + watches[i].on = false; + for(i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) + { + char nameStr [32]; + nameStr[0]='?'; nameStr[1]='\0'; + fscanf(file, " address = 0x%x, name = \"%31[^\"]\", size = %d, format = %d\n", &watches[i].address, nameStr, &watches[i].size, &watches[i].format); + if(nameStr[0] == '\0' || nameStr[0] == '?') + { + if(watches[i].address < 0x7E0000 + 0x20000) + sprintf(nameStr, "%06X", watches[i].address); + else if(watches[i].address < 0x7E0000 + 0x30000) + sprintf(nameStr, "s%05X", watches[i].address - 0x7E0000 - 0x20000); + else + sprintf(nameStr, "i%05X", watches[i].address - 0x7E0000 - 0x30000); + } + nameStr[31] = '\0'; + if(!ferror(file)) + { + watches[i].on = true; + watches[i].buf[0] = '\0'; + strncpy(watches[i].desc, nameStr, sizeof(watches[i].desc)); watches[i].desc[sizeof(watches[i].desc)-1]='\0'; + } + if(ferror(file) || feof(file)) + break; + } + fclose(file); + } + } + { + RECT rect; + GetClientRect (GUI.hWnd, &rect); + InvalidateRect (GUI.hWnd, &rect, true); + } + } + break; + case IDC_C_SAVEWATCH: + { + OPENFILENAME ofn; + char szFileName[MAX_PATH]; + char szPathName[MAX_PATH]; + strcpy(szFileName, "watches"); + _fullpath(szPathName, S9xGetDirectory(CHEAT_DIR), MAX_PATH); + + ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) ); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = GUI.hWnd; + ofn.lpstrFilter = FILE_INFO_TXT_FILE_TYPE "\0*.txt\0" FILE_INFO_ANY_FILE_TYPE "\0*.*\0\0"; + ofn.lpstrFile = szFileName; + ofn.lpstrDefExt = "txt"; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; + ofn.lpstrInitialDir = szPathName; + if(GetSaveFileName( &ofn )) + { + FILE *file = fopen(szFileName, "w"); + if(file) + { + for(unsigned int i = 0 ; i < sizeof(watches)/sizeof(*watches) ; i++) + if(watches[i].on) +// fprintf(file, "address = 0x%x, name = \"%6X\", size = %d, format = %d\n", watches[i].address, watches[i].address, watches[i].size, watches[i].format); + fprintf(file, "address = 0x%x, name = \"?\", size = %d, format = %d\n", watches[i].address, watches[i].size, watches[i].format); + fclose(file); + } + } + { + RECT rect; + GetClientRect (GUI.hWnd, &rect); + InvalidateRect (GUI.hWnd, &rect, true); + } + } + break; + + case IDC_REFRESHLIST: + ListView_RedrawItems(GetDlgItem(hDlg, IDC_ADDYS),0, 0x32000); + break; + + case IDC_ENTERED: + case IDC_ENTEREDADDRESS: + case IDC_PREV: + if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_ENTERED)) + { + use_entered=1; + EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), true); + EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), true); + } + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_ENTEREDADDRESS)) + { + use_entered=2; + EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), true); + EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), true); + } + else + { + use_entered=0; + EnableWindow(GetDlgItem(hDlg, IDC_VALUE_ENTER), false); + EnableWindow(GetDlgItem(hDlg, IDC_ENTER_LABEL), false); + } + return true; + break; + case IDC_C_SEARCH: + { + val_type=0; + + if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_LESS_THAN)) + comp_type=S9X_LESS_THAN; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_GREATER_THAN)) + comp_type=S9X_GREATER_THAN; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_LESS_THAN_EQUAL)) + comp_type=S9X_LESS_THAN_OR_EQUAL; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_GREATER_THAN_EQUAL)) + comp_type=S9X_GREATER_THAN_OR_EQUAL; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_EQUAL)) + comp_type=S9X_EQUAL; + else comp_type=S9X_NOT_EQUAL; + + if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_UNSIGNED)) + val_type=1; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_SIGNED)) + val_type=2; + else val_type=3; + + + + if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_1_BYTE)) + bytes=S9X_8_BITS; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_2_BYTE)) + bytes=S9X_16_BITS; + else if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_3_BYTE)) + bytes=S9X_24_BITS; + else bytes=S9X_32_BITS; + + + if(BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_ENTERED) || + BST_CHECKED==IsDlgButtonChecked(hDlg, IDC_ENTEREDADDRESS)) + { + TCHAR buf[20]; + GetDlgItemText(hDlg, IDC_VALUE_ENTER, buf, 20); + uint32 value; + int ret; + if(use_entered==2) + { + ret = ScanAddress(buf, value); + value -= 0x7E0000; + S9xSearchForAddress (&Cheat, comp_type, bytes, value, FALSE); + } + else + { + if(val_type==1) + ret=_stscanf(buf, "%ul", &value); + else if (val_type==2) + ret=_stscanf(buf, "%d", &value); + else ret=_stscanf(buf, "%x", &value); + + + if(ret!=1||!TestRange(val_type, bytes, value)) + { + MessageBox(hDlg, TEXT(SEARCH_ERR_INVALIDSEARCHVALUE), TEXT(SEARCH_TITLE_CHEATERROR), MB_OK); + return true; + } + + S9xSearchForValue (&Cheat, comp_type, + bytes, value, + (val_type==2), FALSE); + } + + } + else + { + S9xSearchForChange (&Cheat, comp_type, + bytes, (val_type==2), FALSE); + } + int l = CheatCount(bytes); + ListView_SetItemCount (GetDlgItem(hDlg, IDC_ADDYS), l); + } + + // if non-modal, update "Prev. Value" column after Search + if(cheatSearchHWND) + { + CopyMemory(Cheat.CWRAM, Cheat.RAM, 0x20000); + CopyMemory(Cheat.CSRAM, Cheat.SRAM, 0x10000); + CopyMemory(Cheat.CIRAM, Cheat.FillRAM, 0x2000); + } + + + ListView_RedrawItems(GetDlgItem(hDlg, IDC_ADDYS),0, 0x32000); + return true; + break; + case IDOK: + CopyMemory(Cheat.CWRAM, Cheat.RAM, 0x20000); + CopyMemory(Cheat.CSRAM, Cheat.SRAM, 0x10000); + CopyMemory(Cheat.CIRAM, Cheat.FillRAM, 0x2000); + /* fall through */ + case IDCANCEL: + if(cheatSearchHWND) + DestroyWindow(hDlg); + else + EndDialog(hDlg, 0); + return true; + default: break; + } + } + default: return false; + } + return false; +} + +int CALLBACK DlgCheatSearchAdd(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static struct ICheat* new_cheat; + int ret=-1; + switch(msg) + { + case WM_INITDIALOG: + WinRefreshDisplay(); + { + TCHAR buf [12]; + new_cheat=(struct ICheat*)lParam; + sprintf(buf, "%06X", new_cheat->address); + SetDlgItemText(hDlg, IDC_NC_ADDRESS, buf); + switch(new_cheat->format) + { + default: + case 1://UNSIGNED + memset(buf,0,12); + sprintf(buf, "%u", new_cheat->new_val); + SetDlgItemText(hDlg, IDC_NC_CURRVAL, buf); + memset(buf,0,12); + sprintf(buf, "%u", new_cheat->saved_val); + SetDlgItemText(hDlg, IDC_NC_PREVVAL, buf); + SetWindowLong(GetDlgItem(hDlg, IDC_NC_NEWVAL), GWL_STYLE, ES_NUMBER |GetWindowLong(GetDlgItem(hDlg, IDC_NC_NEWVAL),GWL_STYLE)); + SetWindowLong(GetDlgItem(hDlg, IDC_NC_CURRVAL), GWL_STYLE, ES_NUMBER |GetWindowLong(GetDlgItem(hDlg, IDC_NC_CURRVAL),GWL_STYLE)); + SetWindowLong(GetDlgItem(hDlg, IDC_NC_PREVVAL), GWL_STYLE, ES_NUMBER |GetWindowLong(GetDlgItem(hDlg, IDC_NC_PREVVAL),GWL_STYLE)); + if(new_cheat->size==1) + { + SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 3, 0); + SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 3, 0); + SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 3, 0); + + } + if(new_cheat->size==2) + { + SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 5, 0); + SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 5, 0); + SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 5, 0); + + } + if(new_cheat->size==3) + { + SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 8, 0); + SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 8, 0); + SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 8, 0); + + } + if(new_cheat->size==4) + { + SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 10, 0); + SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 10, 0); + SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 10, 0); + + } + break; + case 3: + { + char formatstring[10]; + sprintf(formatstring, "%%%02dX",new_cheat->size*2); + memset(buf,0,12); + sprintf(buf, formatstring, new_cheat->new_val); + SetDlgItemText(hDlg, IDC_NC_CURRVAL, buf); + memset(buf,0,12); + sprintf(buf, formatstring, new_cheat->saved_val); + SetDlgItemText(hDlg, IDC_NC_PREVVAL, buf); + SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, new_cheat->size*2, 0); + SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, new_cheat->size*2, 0); + SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, new_cheat->size*2, 0); + + } + break; //HEX + case 2: + memset(buf,0,12); + sprintf(buf, "%d", new_cheat->new_val); + SetDlgItemText(hDlg, IDC_NC_CURRVAL, buf); + memset(buf,0,12); + sprintf(buf, "%d", new_cheat->saved_val); + SetDlgItemText(hDlg, IDC_NC_PREVVAL, buf); + if(new_cheat->size==1) + { + //-128 + SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 4, 0); + SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 4, 0); + SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 4, 0); + } + if(new_cheat->size==2) + { + //-32768 + SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 6, 0); + SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 6, 0); + SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 6, 0); + } + if(new_cheat->size==3) + { + //-8388608 + SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 8, 0); + SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 8, 0); + SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 8, 0); + } + if(new_cheat->size==4) + { + //-2147483648 + SendDlgItemMessage(hDlg, IDC_NC_CURRVAL,EM_SETLIMITTEXT, 11, 0); + SendDlgItemMessage(hDlg, IDC_NC_PREVVAL,EM_SETLIMITTEXT, 11, 0); + SendDlgItemMessage(hDlg, IDC_NC_NEWVAL,EM_SETLIMITTEXT, 11, 0); + } + break; + } + } + return true; + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint (hDlg, &ps); + + EndPaint (hDlg, &ps); + } + return true; + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDOK: + { + int ret = 0; + TCHAR buf[23]; + int temp=new_cheat->size; + S9xCheatDataSize tmp = S9X_8_BITS; + ZeroMemory(new_cheat, sizeof(struct SCheat)); + new_cheat->size=temp; + GetDlgItemText(hDlg, IDC_NC_ADDRESS, buf, 7); + ScanAddress(buf, new_cheat->address); + + if(temp==1) + tmp=S9X_8_BITS; + if(temp==2) + tmp=S9X_16_BITS; + if(temp==3) + tmp=S9X_24_BITS; + if(temp==4) + tmp=S9X_32_BITS; + + + if(0!=GetDlgItemText(hDlg, IDC_NC_NEWVAL, buf, 12)) + { + if(new_cheat->format==2) + ret=sscanf(buf, "%d", &new_cheat->new_val); + else if(new_cheat->format==1) + ret=sscanf(buf, "%u", &new_cheat->new_val); + else if(new_cheat->format==3) + ret=sscanf(buf, "%x", &new_cheat->new_val); + + if(ret!=1 || !TestRange(new_cheat->format, tmp, new_cheat->new_val)) + { + MessageBox(hDlg, SEARCH_ERR_INVALIDNEWVALUE, SEARCH_TITLE_RANGEERROR, MB_OK); + return true; + } + + + if(0==GetDlgItemText(hDlg, IDC_NC_CURRVAL, buf, 12)) + new_cheat->saved=FALSE; + else + { + int i; + if(new_cheat->format==2) + ret=sscanf(buf, "%d", &i); + else if(new_cheat->format==1) + ret=sscanf(buf, "%u", &i); + else if(new_cheat->format==3) + ret=sscanf(buf, "%x", &i); + + if(ret!=1 || !TestRange(new_cheat->format, tmp, i)) + { + MessageBox(hDlg, SEARCH_ERR_INVALIDCURVALUE, SEARCH_TITLE_RANGEERROR, MB_OK); + return true; + } + + + new_cheat->saved_val=i; + new_cheat->saved=TRUE; + } + GetDlgItemText(hDlg, IDC_NC_DESC, new_cheat->name, 23); + + new_cheat->enabled=TRUE; + S9xAddCheat(new_cheat->enabled,new_cheat->saved_val,new_cheat->address,new_cheat->new_val); + strcpy(Cheat.c[Cheat.num_cheats-1].name,new_cheat->name); + ret=0; + } + } + + case IDCANCEL: + EndDialog(hDlg, ret); + return true; + default: break; + } + } + default: return false; + } +} + +static void set_movieinfo(const char* path, HWND hDlg) +{ + MovieInfo m; + int i; + int getInfoResult=FILE_NOT_FOUND; + + if(strlen(path)) + getInfoResult = S9xMovieGetInfo(path, &m); + + if(getInfoResult!=FILE_NOT_FOUND) + { + char* p; + char tmpstr[128]; + strncpy(tmpstr, ctime(&m.TimeCreated), 127); + tmpstr[127]='\0'; + if((p=strrchr(tmpstr, '\n'))) + *p='\0'; + SetWindowTextA(GetDlgItem(hDlg, IDC_MOVIE_DATE), tmpstr); + + uint32 div = Memory.ROMFramesPerSecond; + if(!div) div = 60; + uint32 l=(m.LengthFrames+(div>>1))/div; + uint32 seconds=l%60; + l/=60; + uint32 minutes=l%60; + l/=60; + uint32 hours=l%60; + sprintf(tmpstr, "%02d:%02d:%02d", hours, minutes, seconds); + SetWindowTextA(GetDlgItem(hDlg, IDC_MOVIE_LENGTH), tmpstr); + sprintf(tmpstr, "%u", m.LengthFrames); + SetWindowTextA(GetDlgItem(hDlg, IDC_MOVIE_FRAMES), tmpstr); + sprintf(tmpstr, "%u", m.RerecordCount); + SetWindowTextA(GetDlgItem(hDlg, IDC_MOVIE_RERECORD), tmpstr); + } + else + { + SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_DATE), _T("")); + SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_LENGTH), _T("")); + SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_FRAMES), _T("")); + SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_RERECORD), _T("")); + } + + if(getInfoResult==SUCCESS) + { + // set author comment: + { +/// SetWindowTextW(GetDlgItem(hDlg, IDC_MOVIE_METADATA), m.Metadata); // won't work, because of & symbol + + wchar_t metadata [MOVIE_MAX_METADATA]; + int j, pos = 0, len = wcslen(m.Metadata); + for (j = 0; j < len ; j++) + { + wchar_t c = m.Metadata [j]; + metadata [pos++] = c; + + // & is a special character in Windows fields, + // so we have to change & to && when copying over the game title + // otherwise "Pocky & Rocky" will show up as "Pocky Rocky", for example + if(c == (wchar_t)'&') + metadata [pos++] = (wchar_t)'&'; + } + metadata [pos] = (wchar_t)'\0'; + + SetWindowTextW(GetDlgItem(hDlg, IDC_MOVIE_METADATA), metadata); + } + SetWindowText(GetDlgItem(hDlg, IDC_LABEL_MOVIEINFOBOX), _T(MOVIE_LABEL_AUTHORINFO)); + + if(m.ReadOnly) + { + EnableWindow(GetDlgItem(hDlg, IDC_READONLY), FALSE); + SendDlgItemMessage(hDlg,IDC_READONLY,BM_SETCHECK,BST_CHECKED,0); + } + else + { + EnableWindow(GetDlgItem(hDlg, IDC_READONLY), TRUE); +/// SendDlgItemMessage(hDlg,IDC_READONLY,BM_SETCHECK,BST_UNCHECKED,0); + } + EnableWindow(GetDlgItem(hDlg, IDC_DISPLAY_INPUT), TRUE); + + for(i=0; i<5; ++i) + { + SendDlgItemMessage(hDlg,IDC_JOY1+i,BM_SETCHECK,(m.ControllersMask & (1<3); // can't sync sound to CPU unless using "Snes9x DirectSound" driver + + EnableWindow(GetDlgItem(hDlg, IDC_FMUT), FALSE); + + SetDlgItemText(hDlg,IDC_LABEL_STARTSETTINGS, MOVIE_LABEL_STARTSETTINGS); + SetDlgItemText(hDlg,IDC_LABEL_CONTROLLERSETTINGS, MOVIE_LABEL_CONTSETTINGS); + SetDlgItemText(hDlg,IDC_LABEL_SYNCSETTINGS, MOVIE_LABEL_SYNCSETTINGS); + } + return true; + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDC_ALLOWLEFTRIGHT: + case IDC_FMUT: + case IDC_SYNC_TO_SOUND_CPU: + SetWindowText(GetDlgItem(hDlg, IDC_LOADEDFROMMOVIE), _T("")); + break; + case IDC_BROWSE_MOVIE: + { + OPENFILENAME ofn; + char szFileName[MAX_PATH]; + + szFileName[0] = '\0'; + + ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) ); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hDlg; + ofn.lpstrFilter = MOVIE_FILETYPE_DESCRIPTION "\0*.smv\0" FILE_INFO_ANY_FILE_TYPE "\0*.*\0\0"; + ofn.lpstrFile = szFileName; + ofn.lpstrDefExt = "smv"; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; // hide previously-ignored read-only checkbox (the real read-only box is in the open-movie dialog itself) + ofn.lpstrInitialDir = movieDirectory; + if(GetOpenFileName( &ofn )) + { + SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_PATH), szFileName); + + if(!GUI.LockDirectories) + { + char temp [256]; + GetCurrentDirectory(MAX_PATH, temp); + absToRel(GUI.MovieDir, temp, S9xGetDirectory(DEFAULT_DIR)); + } + + set_movieinfo(szFileName, hDlg); + } + SetCurrentDirectory(movieDirectory); + } + return true; + + case IDC_MOVIE_PATH: + { + char szFileName[MAX_PATH]; + GetWindowText(GetDlgItem(hDlg, IDC_MOVIE_PATH), szFileName, MAX_PATH); + set_movieinfo(szFileName, hDlg); + } + break; + + case IDOK: + { + if(BST_CHECKED==SendDlgItemMessage(hDlg, IDC_READONLY, BM_GETCHECK,0,0)) + { + op->ReadOnly=TRUE; + GUI.MovieReadOnly=TRUE; + } + else + GUI.MovieReadOnly=FALSE; + if(BST_CHECKED==SendDlgItemMessage(hDlg, IDC_DISPLAY_INPUT, BM_GETCHECK,0,0)) + op->DisplayInput=TRUE; + GetDlgItemText(hDlg, IDC_MOVIE_PATH, op->Path, MAX_PATH); + SetCurrentDirectory(movieDirectory); + } + Settings.UpAndDown = IsDlgButtonChecked(hDlg, IDC_ALLOWLEFTRIGHT); + Settings.SoundSync = IsDlgButtonChecked(hDlg, IDC_SYNC_TO_SOUND_CPU); + EndDialog(hDlg, 1); + return true; + + case IDCANCEL: + EndDialog(hDlg, 0); + return true; + + default: + break; + } + } + + default: + return false; + } +} + +// checks if the currently loaded ROM has an SRAM file in the saves directory that we have write access to +static bool existsSRAM () +{ + return(!access(S9xGetFilename(".srm", SRAM_DIR), R_OK|W_OK)); +} + +int CALLBACK DlgCreateMovie(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static OpenMovieParams* op=NULL; + static char movieDirectory [MAX_PATH]; + + switch(msg) + { + case WM_INITDIALOG: + { + WinRefreshDisplay(); + SetCurrentDirectory(S9xGetDirectory(DEFAULT_DIR)); + _fullpath (movieDirectory, GUI.MovieDir, MAX_PATH); + mkdir(movieDirectory); + SetCurrentDirectory(movieDirectory); + + // have to save here or the SRAM file might not exist when we check for it + // (which would cause clear SRAM option to not work) + Memory.SaveSRAM(S9xGetFilename (".srm", SRAM_DIR)); + + + op=(OpenMovieParams*)lParam; + + SendDlgItemMessage(hDlg,IDC_RECORD_RESET,BM_SETCHECK,BST_UNCHECKED,0); + + int i; + for(i=1; i<5; ++i) + { + SendDlgItemMessage(hDlg,IDC_JOY1+i,BM_SETCHECK,BST_UNCHECKED,0); + } + SendDlgItemMessage(hDlg,IDC_JOY1,BM_SETCHECK,BST_CHECKED,0); + + // get default filename + if(Memory.ROMFilename[0]!='\0') + { + static TCHAR filename [_MAX_PATH + 1]; + TCHAR drive [_MAX_DRIVE + 1]; + TCHAR dir [_MAX_DIR + 1]; + TCHAR fname [_MAX_FNAME + 1]; + TCHAR ext [_MAX_EXT + 1]; + _splitpath (Memory.ROMFilename, drive, dir, fname, ext); + _makepath (filename, "", "", fname, "smv"); + SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_PATH), filename); + } + + SendDlgItemMessage(hDlg,IDC_ALLOWLEFTRIGHT,BM_SETCHECK, Settings.UpAndDown ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); + SendDlgItemMessage(hDlg,IDC_SYNC_TO_SOUND_CPU,BM_SETCHECK, Settings.SoundSync ? (WPARAM)BST_CHECKED : (WPARAM)BST_UNCHECKED, 0); + SetWindowText(GetDlgItem(hDlg, IDC_LOADEDFROMMOVIE), _T("")); + + //EnableWindow(GetDlgItem(hDlg, IDC_SYNC_TO_SOUND_CPU), Settings.SoundDriver<1||Settings.SoundDriver>3); // can't sync sound to CPU unless using "Snes9x DirectSound" driver + + SendDlgItemMessage(hDlg,IDC_RECORD_RESET,BM_SETCHECK, (WPARAM)(GUI.MovieStartFromReset ? BST_CHECKED : BST_UNCHECKED), 0); + SendDlgItemMessage(hDlg,IDC_RECORD_NOW,BM_SETCHECK, (WPARAM)(GUI.MovieStartFromReset ? BST_UNCHECKED : BST_CHECKED), 0); + if(existsSRAM()) + { + EnableWindow(GetDlgItem(hDlg, IDC_CLEARSRAM), GUI.MovieStartFromReset); + SendDlgItemMessage(hDlg,IDC_CLEARSRAM,BM_SETCHECK, (WPARAM)(GUI.MovieClearSRAM ? BST_CHECKED : BST_UNCHECKED), 0); + } + else + { + EnableWindow(GetDlgItem(hDlg, IDC_CLEARSRAM), false); + SendDlgItemMessage(hDlg,IDC_CLEARSRAM,BM_SETCHECK, (WPARAM)BST_CHECKED, 0); + } + + SetDlgItemText(hDlg,IDC_LABEL_STARTSETTINGS, MOVIE_LABEL_STARTSETTINGS); + SetDlgItemText(hDlg,IDC_LABEL_CONTROLLERSETTINGS, MOVIE_LABEL_CONTSETTINGS); + SetDlgItemText(hDlg,IDC_LABEL_SYNCSETTINGS, MOVIE_LABEL_SYNCSETTINGS); + } + return true; + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDC_BROWSE_MOVIE: + { + OPENFILENAME ofn; + char szFileName[MAX_PATH]; + + szFileName[0] = '\0'; + + ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) ); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hDlg; + ofn.lpstrFilter = MOVIE_FILETYPE_DESCRIPTION "\0*.smv\0" FILE_INFO_ANY_FILE_TYPE "\0*.*\0\0"; + ofn.lpstrFile = szFileName; + ofn.lpstrDefExt = "smv"; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; + ofn.lpstrInitialDir = movieDirectory; + if(GetSaveFileName( &ofn )) + { + SetWindowText(GetDlgItem(hDlg, IDC_MOVIE_PATH), szFileName); + + if(!GUI.LockDirectories) + { + char temp [256]; + GetCurrentDirectory(MAX_PATH, temp); + absToRel(GUI.MovieDir, temp, S9xGetDirectory(DEFAULT_DIR)); + } + } + SetCurrentDirectory(movieDirectory); + } + return true; + + case IDOK: + { + GetDlgItemText(hDlg, IDC_MOVIE_PATH, op->Path, MAX_PATH); + GetDlgItemTextW(hDlg, IDC_MOVIE_METADATA, op->Metadata, MOVIE_MAX_METADATA); + int i; + for(i=wcslen(op->Metadata); i<32; i++) + wcscat(op->Metadata, L" "); + op->ControllersMask=0; + op->Opts=0; + for(i=0; i<5; ++i) // TODO: should we even bother with 8-controller recording? right now there are only 5 controller buttons in the dialog, so... + { + if(BST_CHECKED==SendDlgItemMessage(hDlg, IDC_JOY1+i, BM_GETCHECK,0,0)) + op->ControllersMask |= (1<Opts |= MOVIE_OPT_FROM_RESET; + GUI.MovieStartFromReset = TRUE; + } + else + GUI.MovieStartFromReset = FALSE; + + Settings.UpAndDown = IsDlgButtonChecked(hDlg, IDC_ALLOWLEFTRIGHT); + Settings.SoundSync = IsDlgButtonChecked(hDlg, IDC_SYNC_TO_SOUND_CPU); + + op->SyncFlags = MOVIE_SYNC_DATA_EXISTS | MOVIE_SYNC_HASROMINFO; + if(Settings.UpAndDown) op->SyncFlags |= MOVIE_SYNC_LEFTRIGHT; + if(Settings.SoundSync) op->SyncFlags |= MOVIE_SYNC_SYNCSOUND; + + if(IsDlgButtonChecked(hDlg, IDC_CLEARSRAM) && IsDlgButtonChecked(hDlg, IDC_RECORD_RESET) && existsSRAM()) + { + GUI.MovieClearSRAM = TRUE; + remove(S9xGetFilename (".srm", SRAM_DIR)); // delete SRAM if it exists (maybe unnecessary?) + remove(S9xGetFilename (".srm", ROMFILENAME_DIR)); + Memory.LoadSRAM(S9xGetFilename (".srm", SRAM_DIR)); // refresh memory (hard reset) + } + else if(!IsDlgButtonChecked(hDlg, IDC_CLEARSRAM) && IsDlgButtonChecked(hDlg, IDC_RECORD_RESET) && existsSRAM()) + { + GUI.MovieClearSRAM = FALSE; + } + SetCurrentDirectory(movieDirectory); + } + EndDialog(hDlg, 1); + return true; + + case IDCANCEL: + EndDialog(hDlg, 0); + return true; + + case IDC_RECORD_NOW: + if(existsSRAM()) + { + EnableWindow(GetDlgItem(hDlg, IDC_CLEARSRAM), false); + } + break; + + case IDC_RECORD_RESET: + if(existsSRAM()) + { + EnableWindow(GetDlgItem(hDlg, IDC_CLEARSRAM), true); + } + break; + + default: + break; + } + } + + default: + return false; + } +} + + + +// MYO +void S9xHandlePortCommand(s9xcommand_t cmd, int16 data1, int16 data2) +{ + return; +} + +// NYI +const char *S9xChooseFilename (bool8 read_only) +{ + return NULL; +} + +// NYI +const char *S9xChooseMovieFilename (bool8 read_only) +{ + return NULL; +} + + +const char * S9xStringInput(const char *msg) +{ + return NULL; +} + +void S9xToggleSoundChannel (int c) +{ + if (c == 8) + GUI.SoundChannelEnable = 255; + else + GUI.SoundChannelEnable ^= 1 << c; + + S9xSetSoundControl(GUI.SoundChannelEnable); +} + +bool S9xPollButton(uint32 id, bool *pressed){ + if(S9xMoviePlaying()) + return false; + + *pressed = false; + +#define CHECK_KEY(controller, button) (!S9xGetState(Joypad[controller].button) || (ToggleJoypadStorage[controller].button && !TurboToggleJoypadStorage[controller].button) || (IPPU.TotalEmulatedFrames%2 == ToggleJoypadStorage[controller].button && TurboToggleJoypadStorage[controller].button)) + + extern bool S9xGetState (WORD KeyIdent); + if (id & k_MO) // mouse + { + switch (id & 0xFF) + { + case 0: *pressed = GUI.MouseButtons & 1 /* Left */ || ((id & k_C1) && (CHECK_KEY(0,A) || CHECK_KEY(0,L))) || ((id & k_C2) && (CHECK_KEY(1,A) || CHECK_KEY(1,L))); break; + case 1: *pressed = GUI.MouseButtons & 2 /* Right */ || ((id & k_C1) && (CHECK_KEY(0,B) || CHECK_KEY(0,R))) || ((id & k_C2) && (CHECK_KEY(1,B) || CHECK_KEY(1,R))); break; + } + } + else + if (id & k_SS) // superscope + { + switch (id & 0xFF) + { + case 0: *pressed = GUI.MouseX <= 0 || GUI.MouseY <= 0 || GUI.MouseX >= IPPU.RenderedScreenWidth || GUI.MouseY >= ((IPPU.RenderedScreenHeight> 256) ? SNES_HEIGHT_EXTENDED<<1 : SNES_HEIGHT_EXTENDED) || CHECK_KEY(1,X); break; + case 2: *pressed = (GUI.MouseButtons & 2) /* Right */ || CHECK_KEY(1,B) || CHECK_KEY(1,R) ; break; + case 3: *pressed = (GUI.MouseButtons & 4) /* Middle */ || GUI.superscope_turbo || CHECK_KEY(1,Y); GUI.superscope_turbo=0; GUI.MouseButtons &= ~4; break; + case 4: *pressed = GUI.superscope_pause || CHECK_KEY(1,Start) || CHECK_KEY(1,Select); break; + case 1: *pressed = (GUI.MouseButtons & 1) /* Left */ || CHECK_KEY(1,A) || CHECK_KEY(1,L); break; + } + } + else + if (id & k_LG) // justifier + { + if (id & k_C1) + { + switch (id & 0xFF) + { + case 0: *pressed = GUI.MouseX <= 0 || GUI.MouseY <= 0 || GUI.MouseX >= IPPU.RenderedScreenWidth || GUI.MouseY >= ((IPPU.RenderedScreenHeight> 256) ? SNES_HEIGHT_EXTENDED<<1 : SNES_HEIGHT_EXTENDED) || CHECK_KEY(0,X) || CHECK_KEY(0,Start); break; + case 1: *pressed = GUI.MouseButtons & 1 /* Left */ || CHECK_KEY(0,A) || CHECK_KEY(0,L); break; + case 2: *pressed = GUI.MouseButtons & 2 /* Right */ || CHECK_KEY(1,B) || CHECK_KEY(1,R); break; + } + } + else + { + switch (id & 0xFF) + { + case 0: *pressed = CHECK_KEY(1,Start) /* 2p Start */ || CHECK_KEY(1,X); break; + case 1: *pressed = CHECK_KEY(1,A) /* 2p A */ || CHECK_KEY(1,L); break; + case 2: *pressed = CHECK_KEY(1,B) /* 2p B */ || CHECK_KEY(1,R); break; + } + } + } + + return (true); +} + +// ??? NYI +bool S9xPollAxis(uint32 id, int16 *value){ + return false; +} + +bool S9xPollPointer(uint32 id, int16 *x, int16 *y){ + if(S9xMoviePlaying()) + return false; + + if (id & k_PT) + { + *x = GUI.MouseX; + *y = GUI.MouseY; + } + else + *x = *y = 0; + return (true); +} + +// adjusts settings based on ROM that was just loaded +void S9xPostRomInit() +{ + // "Cheats are on" message if cheats are on and active, + // to make it less likely that someone will think there is some bug because of + // a lingering cheat they don't realize is on + if (Settings.ApplyCheats) + { + extern struct SCheatData Cheat; + for (uint32 i = 0; i < Cheat.num_cheats; i++) + { + if (Cheat.c [i].enabled) + { + char String2 [1024]; + sprintf(String2, "(CHEATS ARE ON!) %s", String); + strncpy(String, String2, 512); + break; + } + } + } + + if(!S9xMovieActive() && !startingMovie) + { + // revert previously forced control + if(GUI.ControlForced!=0xff) + GUI.ControllerOption = GUI.ControlForced; + int prevController = GUI.ControllerOption; + GUI.ValidControllerOptions = 0xFFFF; + + // NSRT controller settings + if (!strncmp((const char *)Memory.NSRTHeader+24, "NSRT", 4)) + { + switch(Memory.NSRTHeader[29]) + { + default: // unknown or unsupported + break; + case 0x00: // Gamepad / Gamepad + GUI.ControllerOption = SNES_JOYPAD; + GUI.ValidControllerOptions = (1< +#include +#ifndef STRICT +#define STRICT +#endif +#include +#include +#include +#include +#ifndef __BORLANDC__ + +#ifndef __MINGW32__ +#include +#endif + +#include +#endif +#include "rsrc/resource.h" + +#define COUNT(a) (sizeof (a) / sizeof (a[0])) +#define GUI_VERSION 1008 + +extern unsigned char* SoundBuffer; +#define MAX_RECENT_GAMES_LIST_SIZE 32 +#define MAX_RECENT_HOSTS_LIST_SIZE 16 + +/****************************************************************************/ +inline static void Log (const char *str) +{ + FILE *fs = fopen ("snes9x.log", "a"); + + if (fs) + { + fprintf (fs, "%s\n", str); + fflush (fs); + fclose (fs); + } + +} + +enum RenderFilter{ + FILTER_NONE = 0, + FILTER_SIMPLE1X, + + FILTER_SIMPLE2X, + FILTER_SCANLINES, + FILTER_TVMODE, + FILTER_BLARGGCOMP, + FILTER_BLARGGSVID, + FILTER_BLARGGRGB, + FILTER_SUPEREAGLE, + FILTER_SUPER2XSAI, + FILTER_2XSAI, + FILTER_HQ2X, + FILTER_HQ2XS, + FILTER_HQ2XBOLD, + FILTER_EPXA, + FILTER_EPXB, + FILTER_EPXC, + + FILTER_SIMPLE3X, + FILTER_TVMODE3X, + FILTER_DOTMATRIX3X, + FILTER_HQ3X, + FILTER_HQ3XS, + FILTER_HQ3XBOLD, + FILTER_LQ3XBOLD, + FILTER_EPX3, + + FILTER_SIMPLE4X, + FILTER_HQ4X, + + NUM_FILTERS +}; + +enum OutputMethod { + DIRECTDRAW = 0, + DIRECT3D +}; + +struct dMode +{ + long height; + long width; + long depth; + long rate; +}; + +struct sGUI { + HWND hWnd; + HMENU hMenu; + HINSTANCE hInstance; + + DWORD hFrameTimer; + //DWORD hSoundTimer; + DWORD hHotkeyTimer; + HANDLE ClientSemaphore; + HANDLE FrameTimerSemaphore; + HANDLE ServerTimerSemaphore; + + BYTE Language; + + //unsigned long PausedFramesBeforeMutingSound; + /*int Width; + int Height; + int Depth; + int RefreshRate;*/ + dMode FullscreenMode; + RenderFilter Scale; + RenderFilter NextScale; + RenderFilter ScaleHiRes; + RenderFilter NextScaleHiRes; + bool DoubleBuffered; + bool FullScreen; + bool Stretch; + bool HeightExtend; + bool AspectRatio; + bool ScreenCleared; + bool IgnoreNextMouseMove; + RECT window_size; + bool window_maximized; + int MouseX; + int MouseY; + unsigned int MouseButtons; + int superscope_turbo; + int superscope_pause; + int FrameAdvanceJustPressed; + HCURSOR Blank; + HCURSOR GunSight; + HCURSOR Arrow; + int CursorTimer; + HDC hDC; + HACCEL Accelerators; + bool NeedDepthConvert; + bool DepthConverted; + bool BGR; + bool TurboModeToggle; + bool InactivePause; + bool CustomRomOpen; + bool FASkipsNonInput; + bool FAMute; + int ScreenDepth; + int RedShift; + int GreenShift; + int BlueShift; + int ControlForced; + int CurrentSaveSlot; + int MaxRecentGames; + int ControllerOption; + int ValidControllerOptions; + int SoundChannelEnable; + bool BackgroundKeyHotkeys, BackgroundKeyGamekeys; + bool JoystickHotkeys; + bool MovieClearSRAM; + bool MovieStartFromReset; + bool MovieReadOnly; + bool NetplayUseJoypad1; + unsigned int FlipCounter; + unsigned int NumFlipFrames; + + int SoundDriver; + int SoundBufferSize; + bool Mute; + + char RomDir [_MAX_PATH]; + char ScreensDir [_MAX_PATH]; + char MovieDir [_MAX_PATH]; + char SPCDir [_MAX_PATH]; + char FreezeFileDir [_MAX_PATH]; + char SRAMFileDir [_MAX_PATH]; + char PatchDir [_MAX_PATH]; + char BiosDir [_MAX_PATH]; + bool LockDirectories; + + char RecentGames [MAX_RECENT_GAMES_LIST_SIZE][MAX_PATH]; + char RecentHostNames [MAX_RECENT_HOSTS_LIST_SIZE][MAX_PATH]; + + //turbo switches -- SNES-wide + unsigned short TurboMask; + char StarOceanPack[MAX_PATH]; + char SFA2PALPack[MAX_PATH]; + char SFA2NTSCPack[MAX_PATH]; + char SFZ2Pack[MAX_PATH]; + char SJNSPack[MAX_PATH]; + char FEOEZPack[MAX_PATH]; + char SPL4Pack[MAX_PATH]; + char MDHPack[MAX_PATH]; + COLORREF InfoColor; + bool HideMenu; + bool BilinearFilter; + bool LocalVidMem; + bool Vsync; // XXX: unused - OV2: used in Direct3D mode + // avi writing + struct AVIFile* AVIOut; + OutputMethod outputMethod; + int AspectWidth; + bool EmulateFullscreen; + bool EmulatedFullscreen; + long FrameCount; + long LastFrameCount; + unsigned long IdleCount; + // used for sync sound synchronization + CRITICAL_SECTION SoundCritSect; +}; + +//TURBO masks +#define TURBO_A_MASK 0x0001 +#define TURBO_B_MASK 0x0002 +#define TURBO_X_MASK 0x0004 +#define TURBO_Y_MASK 0x0008 +#define TURBO_L_MASK 0x0010 +#define TURBO_R_MASK 0x0020 +#define TURBO_STA_MASK 0x0040 +#define TURBO_SEL_MASK 0x0080 +#define TURBO_LEFT_MASK 0x0100 +#define TURBO_UP_MASK 0x0200 +#define TURBO_RIGHT_MASK 0x0400 +#define TURBO_DOWN_MASK 0x0800 + +struct sLanguages { + int idMenu; + TCHAR *errInitDD; + TCHAR *errModeDD; + TCHAR *errInitDS; + TCHAR *ApplyNeedRestart; + TCHAR *errFrameTimer; +}; + +#define CUSTKEY_ALT_MASK 0x01 +#define CUSTKEY_CTRL_MASK 0x02 +#define CUSTKEY_SHIFT_MASK 0x04 + +struct SCustomKey { + WORD key; + WORD modifiers; +}; + +struct SCustomKeys { + SCustomKey SpeedUp; + SCustomKey SpeedDown; + SCustomKey Pause; + SCustomKey FrameAdvance; + SCustomKey SkipUp; + SCustomKey SkipDown; + SCustomKey ScopeTurbo; + SCustomKey ScopePause; + SCustomKey FrameCount; + SCustomKey ReadOnly; + SCustomKey Save [10]; + SCustomKey Load [10]; + SCustomKey FastForward; + SCustomKey ShowPressed; + SCustomKey SaveScreenShot; + SCustomKey SlotPlus; + SCustomKey SlotMinus; + SCustomKey SlotSave; + SCustomKey SlotLoad; + SCustomKey BGL1; + SCustomKey BGL2; + SCustomKey BGL3; + SCustomKey BGL4; + SCustomKey BGL5; + SCustomKey ClippingWindows; +// SCustomKey BGLHack; + SCustomKey Transparency; + SCustomKey HDMA; + SCustomKey GLCube; +// SCustomKey InterpMode7; + SCustomKey JoypadSwap; + SCustomKey SwitchControllers; + SCustomKey TurboA, TurboB, TurboY, TurboX, TurboL, TurboR, TurboStart, TurboSelect, TurboLeft, TurboUp, TurboRight, TurboDown; + SCustomKey SelectSave [10]; + SCustomKey ResetGame; + SCustomKey ToggleCheats; +}; + +struct SJoypad { + BOOL Enabled; + WORD Left; + WORD Right; + WORD Up; + WORD Down; + WORD Left_Up; + WORD Left_Down; + WORD Right_Up; + WORD Right_Down; + WORD Start; + WORD Select; + WORD A; + WORD B; + WORD X; + WORD Y; + WORD L; + WORD R; +}; + +#define S9X_JOY_NEUTRAL 60 + +struct SJoyState{ + bool Attached; + JOYCAPS Caps; + int Threshold; + bool Left; + bool Right; + bool Up; + bool Down; + bool PovLeft; + bool PovRight; + bool PovUp; + bool PovDown; + bool PovDnLeft; + bool PovDnRight; + bool PovUpLeft; + bool PovUpRight; + bool RUp; + bool RDown; + bool UUp; + bool UDown; + bool VUp; + bool VDown; + bool ZUp; + bool ZDown; + bool Button[32]; +}; + +enum +{ + SNES_JOYPAD, + SNES_MOUSE, + SNES_SUPERSCOPE, + SNES_MULTIPLAYER5, + SNES_JUSTIFIER, + SNES_MOUSE_SWAPPED, + SNES_MULTIPLAYER8, + SNES_JUSTIFIER_2, + SNES_MAX_CONTROLLER_OPTIONS +}; + +/*****************************************************************************/ + +void SetInfoDlgColor(unsigned char r, unsigned char g, unsigned char b); + +extern struct sGUI GUI; +extern struct sLanguages Languages[]; +extern struct SJoypad Joypad[16]; +extern struct SJoypad ToggleJoypadStorage[8]; +extern struct SJoypad TurboToggleJoypadStorage[8]; +extern struct SCustomKeys CustomKeys; + +enum +{ + WIN_SNES9X_DIRECT_SOUND_DRIVER=0, + WIN_FMOD_DIRECT_SOUND_DRIVER, + WIN_FMOD_WAVE_SOUND_DRIVER, + WIN_FMOD_A3D_SOUND_DRIVER, + WIN_XAUDIO2_SOUND_DRIVER, + WIN_FMODEX_DEFAULT_DRIVER, + WIN_FMODEX_ASIO_DRIVER, + WIN_FMODEX_OPENAL_DRIVER +}; + +#define S9X_REG_KEY_BASE MY_REG_KEY +#define S9X_REG_KEY_VERSION REG_KEY_VER + +#define EXT_WIDTH (MAX_SNES_WIDTH + 4) +#define EXT_PITCH (EXT_WIDTH * 2) +#define EXT_HEIGHT (MAX_SNES_HEIGHT + 4) +// Offset into buffer to allow a two pixel border around the whole rendered +// SNES image. This is a speed up hack to allow some of the image processing +// routines to access black pixel data outside the normal bounds of the buffer. +#define EXT_OFFSET (EXT_PITCH * 2 + 2 * 2) + +#define WIN32_WHITE RGB(255,255,255) + +#define SET_UI_COLOR(r,g,b) SetInfoDlgColor(r,g,b) + +/*****************************************************************************/ + +void S9xSetWinPixelFormat (); +//int CheckKey( WORD Key, int OldJoypad); +//void TranslateKey(WORD keyz,char *out); + +#define S9X_CONF_FILE_NAME "snes9x.conf" + +const char* GetFilterName(RenderFilter filterID); +int GetFilterScale(RenderFilter filterID); +bool GetFilterHiResSupport(RenderFilter filterID); + +#endif // !defined(SNES9X_H_INCLUDED)