mednafen/psx/dis.cpp000664 001750 001750 00000030461 12611054044 015555 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include "psx.h" struct OpEntry { uint32 mask; uint32 value; const char *mnemonic; const char *format; }; #define MASK_OP (0x3FU << 26) #define MASK_FUNC (0x3FU) #define MASK_RS (0x1FU << 21) #define MASK_RT (0x1FU << 16) #define MASK_RD (0x1FU << 11) #define MASK_SA (0x1FU << 6) #define MK_OP(mnemonic, format, op, func, extra_mask) { MASK_OP | (op ? 0 : MASK_FUNC) | extra_mask, ((unsigned)op << 26) | func, mnemonic, format } #define MK_OP_REGIMM(mnemonic, regop_mask, regop) { MASK_OP | (regop_mask << 16), (0x01U << 26) | (regop << 16), mnemonic, "s, p" } #define MK_COPZ(z) { MASK_OP | (0x1U << 25), (0x1U << 25) | ((0x10U | z) << 26), "cop" #z, "F" } #define MK_COP0_FUNC(mnemonic, func) { MASK_OP | (0x1U << 25) | MASK_FUNC, (0x10U << 26) | (0x1U << 25) | func, mnemonic, "" } #define MK_COPZ_XFER(z, mnemonic, format, xf) { MASK_OP | (0x1FU << 21), ((0x10U | z) << 26) | (xf << 21), mnemonic, format } #define MK_COPZ_BCzx(z, x) { MASK_OP | (0x1BU << 21) | (0x01 << 16), ((0x10U | z) << 26) | (0x08 << 21) | (x << 16), (x ? "bc" #z "t" : "bc" #z "f"), "p" } #define MK_COPZ_BC(z) MK_COPZ_BCzx(z, 0), MK_COPZ_BCzx(z, 1) #define MK_GTE(mnemonic, format, func) { MASK_OP | (0x1U << 25) | MASK_FUNC, (0x1U << 25) | (0x12U << 26) | func, mnemonic, format } static OpEntry ops[] = { MK_OP("nop", "", 0, 0, MASK_RT | MASK_RD | MASK_SA), // // // MK_OP("sll", "d, t, a", 0, 0, 0), MK_OP("srl", "d, t, a", 0, 2, 0), MK_OP("sra", "d, t, a", 0, 3, 0), MK_OP("sllv", "d, t, s", 0, 4, 0), MK_OP("srlv", "d, t, s", 0, 6, 0), MK_OP("srav", "d, t, s", 0, 7, 0), MK_OP("jr", "s", 0, 8, 0), MK_OP("jalr", "d, s", 0, 9, 0), MK_OP("syscall", "", 0, 12, 0), // TODO MK_OP("break", "", 0, 13, 0), // TODO MK_OP("mfhi", "d", 0, 16, 0), MK_OP("mthi", "s", 0, 17, 0), MK_OP("mflo", "d", 0, 18, 0), MK_OP("mtlo", "s", 0, 19, 0), MK_OP("mult", "s, t", 0, 24, 0), MK_OP("multu", "s, t", 0, 25, 0), MK_OP("div", "s, t", 0, 26, 0), MK_OP("divu", "s, t", 0, 27, 0), MK_OP("add", "d, s, t", 0, 32, 0), MK_OP("addu", "d, s, t", 0, 33, 0), MK_OP("sub", "d, s, t", 0, 34, 0), MK_OP("subu", "d, s, t", 0, 35, 0), MK_OP("and", "d, s, t", 0, 36, 0), MK_OP("or", "d, s, t", 0, 37, 0), MK_OP("xor", "d, s, t", 0, 38, 0), MK_OP("nor", "d, s, t", 0, 39, 0), MK_OP("slt", "d, s, t", 0, 42, 0), MK_OP("sltu", "d, s, t", 0, 43, 0), /* keep *al before the non-linking versions, due to mask setup. */ MK_OP_REGIMM("bgezal", 0x1F, 0x11), MK_OP_REGIMM("bltzal", 0x1F, 0x10), MK_OP_REGIMM("bgez", 0x01, 0x01), MK_OP_REGIMM("bltz", 0x00, 0x00), MK_OP("j", "P", 2, 0, 0), MK_OP("jal", "P", 3, 0, 0), MK_OP("beq", "s, t, p", 4, 0, 0), MK_OP("bne", "s, t, p", 5, 0, 0), MK_OP("blez", "s, p", 6, 0, 0), MK_OP("bgtz", "s, p", 7, 0, 0), MK_OP("addi", "t, s, i", 8, 0, 0), MK_OP("addiu", "t, s, i", 9, 0, 0), MK_OP("slti", "t, s, i", 10, 0, 0), MK_OP("sltiu", "t, s, i", 11, 0, 0), MK_OP("andi", "t, s, z", 12, 0, 0), MK_OP("ori", "t, s, z", 13, 0, 0), MK_OP("xori", "t, s, z", 14, 0, 0), MK_OP("lui", "t, z", 15, 0, 0), MK_COPZ_XFER(0, "mfc0", "t, 0", 0x00), MK_COPZ_XFER(1, "mfc1", "t, ?", 0x00), MK_COPZ_XFER(2, "mfc2", "t, g", 0x00), MK_COPZ_XFER(3, "mfc3", "t, ?", 0x00), MK_COPZ_XFER(0, "mtc0", "t, 0", 0x04), MK_COPZ_XFER(1, "mtc1", "t, ?", 0x04), MK_COPZ_XFER(2, "mtc2", "t, g", 0x04), MK_COPZ_XFER(3, "mtc3", "t, ?", 0x04), MK_COPZ_XFER(0, "cfc0", "t, ?", 0x02), MK_COPZ_XFER(1, "cfc1", "t, ?", 0x02), MK_COPZ_XFER(2, "cfc2", "t, G", 0x02), MK_COPZ_XFER(3, "cfc3", "t, ?", 0x02), MK_COPZ_XFER(0, "ctc0", "t, ?", 0x06), MK_COPZ_XFER(1, "ctc1", "t, ?", 0x06), MK_COPZ_XFER(2, "ctc2", "t, G", 0x06), MK_COPZ_XFER(3, "ctc3", "t, ?", 0x06), MK_COPZ_BC(0), MK_COPZ_BC(1), MK_COPZ_BC(2), MK_COPZ_BC(3), // COP0 stuff here MK_COP0_FUNC("rfe", 0x10), MK_OP("lwc0", "?, i(s)", 0x30, 0, 0), MK_OP("lwc1", "?, i(s)", 0x31, 0, 0), MK_OP("lwc2", "h, i(s)", 0x32, 0, 0), MK_OP("lwc3", "?, i(s)", 0x33, 0, 0), MK_OP("swc0", "?, i(s)", 0x38, 0, 0), MK_OP("swc1", "?, i(s)", 0x39, 0, 0), MK_OP("swc2", "h, i(s)", 0x3A, 0, 0), MK_OP("swc3", "?, i(s)", 0x3B, 0, 0), MK_OP("lb", "t, i(s)", 0x20, 0, 0), MK_OP("lh", "t, i(s)", 0x21, 0, 0), MK_OP("lwl", "t, i(s)", 0x22, 0, 0), MK_OP("lw", "t, i(s)", 0x23, 0, 0), MK_OP("lbu", "t, i(s)", 0x24, 0, 0), MK_OP("lhu", "t, i(s)", 0x25, 0, 0), MK_OP("lwr", "t, i(s)", 0x26, 0, 0), MK_OP("sb", "t, i(s)", 0x28, 0, 0), MK_OP("sh", "t, i(s)", 0x29, 0, 0), MK_OP("swl", "t, i(s)", 0x2A, 0, 0), MK_OP("sw", "t, i(s)", 0x2B, 0, 0), MK_OP("swr", "t, i(s)", 0x2E, 0, 0), // // GTE specific instructions // // sf mx v cv lm // MK_GTE("rtps", "#sf# #lm#", 0x00), MK_GTE("rtps", "#sf# #lm#", 0x01), MK_GTE("nclip", "", 0x06), MK_GTE("op", "#sf# #lm#", 0x0C), MK_GTE("dpcs", "#sf# #lm#", 0x10), MK_GTE("intpl", "#sf# #lm#", 0x11), MK_GTE("mvmva", "#sf# #mx# #v# #cv# #lm#", 0x12), MK_GTE("ncds", "#sf# #lm#", 0x13), MK_GTE("cdp", "#sf# #lm#", 0x14), MK_GTE("ncdt", "#sf# #lm#", 0x16), MK_GTE("dcpl", "#sf# #lm#", 0x1A), MK_GTE("nccs", "#sf# #lm#", 0x1B), MK_GTE("cc", "#sf# #lm#", 0x1C), MK_GTE("ncs", "#sf# #lm#", 0x1E), MK_GTE("nct", "#sf# #lm#", 0x20), MK_GTE("sqr", "#sf# #lm#", 0x28), MK_GTE("dcpl", "#sf# #lm#", 0x29), MK_GTE("dpct", "#sf# #lm#", 0x2A), MK_GTE("avsz3", "", 0x2D), MK_GTE("avsz4", "", 0x2E), MK_GTE("rtpt", "#sf# #lm#", 0x30), MK_GTE("gpf", "#sf# #lm#", 0x3D), MK_GTE("gpl", "#sf# #lm#", 0x3E), MK_GTE("ncct", "#sf# #lm#", 0x3F), // // // MK_COPZ(0), MK_COPZ(1), MK_COPZ(2), MK_COPZ(3), { 0, 0, NULL, NULL } }; std::string DisassembleMIPS(uint32 PC, uint32 instr) { std::string ret = "UNKNOWN"; unsigned int rs = (instr >> 21) & 0x1F; unsigned int rt = (instr >> 16) & 0x1F; unsigned int rd = (instr >> 11) & 0x1F; unsigned int shamt = (instr >> 6) & 0x1F; unsigned int immediate = (int32)(int16)(instr & 0xFFFF); unsigned int immediate_ze = (instr & 0xFFFF); unsigned int jt = instr & ((1 << 26) - 1); static const char *gpr_names[32] = { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra" }; static const char *cop0_names[32] = { "CPR0", "CPR1", "CPR2", "BPC", "CPR4", "BDA", "TAR", "DCIC", "BADVA", "BDAM", "CPR10", "BPCM", "SR", "CAUSE", "EPC", "PRID", "CPR16", "CPR17", "CPR18", "CPR19", "CPR20", "CPR21", "CPR22", "CPR23", "CPR24", "CPR25", "CPR26", "CPR27", "CPR28", "CPR29", "CPR30", "CPR31" }; static const char *gte_cr_names[32] = { "R11R12", "R13R21", "R22R23", "R31R32", "R33", "TRX", "TRY", "TRZ", "L11L12", "L13L21", "L22L23", "L31L32", "L33", "RBK", "GBK", "BBK", "LR1LR2", "LR3LG1", "LG2LG3", "LB1LB2", "LB3", "RFC", "GFC", "BFC", "OFX", "OFY", "H", "DQA", "DQB", "ZSF3", "ZSF4", "FLAG" }; static const char *gte_dr_names[32] = { "VXY0", "VZ0", "VXY1", "VZ1", "VXY2", "VZ2", "RGB", "OTZ", "IR0", "IR1", "IR2", "IR3", "SXY0", "SXY1", "SXY2", "SXYP", "SZ0", "SZ1", "SZ2", "SZ3", "RGB0", "RGB1", "RGB2", "RES1", "MAC0", "MAC1", "MAC2", "MAC3", "IRGB", "ORGB", "LZCS", "LZCR" }; OpEntry *op = ops; while(op->mnemonic) { if((instr & op->mask) == op->value) { // a = shift amount // s = rs // t = rt // d = rd // i = immediate // z = immediate, zero-extended // p = PC + 4 + immediate // P = ((PC + 4) & 0xF0000000) | (26bitval << 2) // // 0 = rd(cop0 registers) // c = rd(copz data registers) // C = rd(copz control registers) // g = rd(GTE data registers) // G = rd(GTE control registers) // h = rt(GTE data registers) char s_a[16]; char s_i[16]; char s_z[16]; char s_p[16]; char s_P[16]; char s_c[16]; char s_C[16]; snprintf(s_a, sizeof(s_a), "%d", shamt); #if 0 if(immediate < 0) snprintf(s_i, sizeof(s_i), "%d", immediate); else #endif snprintf(s_i, sizeof(s_i), "0x%04x", (uint32)immediate); snprintf(s_z, sizeof(s_z), "0x%04x", immediate_ze); snprintf(s_p, sizeof(s_p), "0x%08x", PC + 4 + (immediate << 2)); snprintf(s_P, sizeof(s_P), "0x%08x", ((PC + 4) & 0xF0000000) | (jt << 2)); snprintf(s_c, sizeof(s_c), "CPR%d", rd); snprintf(s_C, sizeof(s_C), "CCR%d", rd); ret = std::string(op->mnemonic); ret.append(10 - ret.size(), ' '); for(unsigned int i = 0; i < strlen(op->format); i++) { switch(op->format[i]) { case '#': // sf mx v cv lm { char as[16]; as[0] = 0; if(!strncmp(&op->format[i], "#sf#", 4)) { i += 3; snprintf(as, 16, "sf=%d", (int)(bool)(instr & (1 << 19))); } else if(!strncmp(&op->format[i], "#mx#", 4)) { i += 3; snprintf(as, 16, "mx=%d", (instr >> 17) & 0x3); } else if(!strncmp(&op->format[i], "#v#", 3)) { i += 2; snprintf(as, 16, "v=%d", (instr >> 15) & 0x3); } else if(!strncmp(&op->format[i], "#cv#", 4)) { i += 3; snprintf(as, 16, "cv=%d", (instr >> 13) & 0x3); } else if(!strncmp(&op->format[i], "#lm#", 4)) { i += 3; snprintf(as, 16, "lm=%d", (int)(bool)(instr & (1 << 10))); } ret.append(as); } break; case 'F': { char s_F[16]; snprintf(s_F, 16, "0x%07x", instr & 0x1FFFFFF); ret.append(s_F); } break; case 'h': ret.append(gte_dr_names[rt]); break; case 'g': ret.append(gte_dr_names[rd]); break; case 'G': ret.append(gte_cr_names[rd]); break; case '0': ret.append(cop0_names[rd]); break; case 'c': ret.append(s_c); break; case 'C': ret.append(s_C); break; case 'a': ret.append(s_a); break; case 'i': ret.append(s_i); break; case 'z': ret.append(s_z); break; case 'p': ret.append(s_p); break; case 'P': ret.append(s_P); break; case 's': ret.append(gpr_names[rs]); break; case 't': ret.append(gpr_names[rt]); break; case 'd': ret.append(gpr_names[rd]); break; default: ret.append(1, op->format[i]); break; } } break; } op++; } return(ret); } mednafen/cdrom/misc.h000664 001750 001750 00000000212 12611054044 015657 0ustar00sergiosergio000000 000000 #ifndef __MDFN_CDROM_MISC_H #define __MDFN_CDROM_MISC_H void MDFN_strtoupper(std::string &str); void MDFN_strtoupper(char *str); #endif link.T000664 001750 001750 00000000047 12611054044 012762 0ustar00sergiosergio000000 000000 { global: retro_*; local: *; }; mednafen/tremor/codec_internal.h000664 001750 001750 00000006014 12611054044 020107 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: libvorbis codec headers ********************************************************************/ #ifndef _V_CODECI_H_ #define _V_CODECI_H_ #include "codebook.h" typedef void vorbis_look_mapping; typedef void vorbis_look_floor; typedef void vorbis_look_residue; typedef void vorbis_look_transform; /* mode ************************************************************/ typedef struct { int blockflag; int windowtype; int transformtype; int mapping; } vorbis_info_mode; typedef void vorbis_info_floor; typedef void vorbis_info_residue; typedef void vorbis_info_mapping; typedef struct private_state { /* local lookup storage */ const void *window[2]; /* backend lookups are tied to the mode, not the backend or naked mapping */ int modebits; vorbis_look_mapping **mode; ogg_int64_t sample_count; } private_state; /* codec_setup_info contains all the setup information specific to the specific compression/decompression mode in progress (eg, psychoacoustic settings, channel setup, options, codebook etc). *********************************************************************/ typedef struct codec_setup_info { /* Vorbis supports only short and long blocks, but allows the encoder to choose the sizes */ long blocksizes[2]; /* modes are the primary means of supporting on-the-fly different blocksizes, different channel mappings (LR or M/A), different residue backends, etc. Each mode consists of a blocksize flag and a mapping (along with the mapping setup */ int modes; int maps; int times; int floors; int residues; int books; vorbis_info_mode *mode_param[64]; int map_type[64]; vorbis_info_mapping *map_param[64]; int time_type[64]; int floor_type[64]; vorbis_info_floor *floor_param[64]; int residue_type[64]; vorbis_info_residue *residue_param[64]; static_codebook *book_param[256]; codebook *fullbooks; int passlimit[32]; /* iteration limit per couple/quant pass */ int coupling_passes; } codec_setup_info; #endif mednafen/psx/irq.h000664 001750 001750 00000001335 12611054044 015234 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_IRQ_H #define __MDFN_PSX_IRQ_H #include enum { IRQ_VBLANK = 0, IRQ_GPU = 1, IRQ_CD = 2, IRQ_DMA = 3, IRQ_TIMER_0 = 4, IRQ_TIMER_1 = 5, IRQ_TIMER_2 = 6, IRQ_SIO = 7, IRQ_SPU = 9, IRQ_PIO = 10 }; enum { IRQ_GSREG_ASSERTED = 0, IRQ_GSREG_STATUS = 1, IRQ_GSREG_MASK = 2 }; void IRQ_Power(void); void IRQ_Assert(int which, bool asserted); void IRQ_Write(uint32_t A, uint32_t V); uint32_t IRQ_Read(uint32_t A); uint32_t IRQ_GetRegister(unsigned int which, char *special, const uint32_t special_len); void IRQ_SetRegister(unsigned int which, uint32_t value); int IRQ_StateAction(void *data, int load, int data_only); #endif scrc32.c000664 001750 001750 00000007776 12611054044 013163 0ustar00sergiosergio000000 000000 #ifdef __cplusplus extern "C" { #endif #ifdef WANT_CRC32 static const unsigned long crc_table[256] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; #define DO1_CRC32(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); #define DO2_CRC32(buf) DO1_CRC32(buf); DO1_CRC32(buf); #define DO4_CRC32(buf) DO2_CRC32(buf); DO2_CRC32(buf); #define DO8_CRC32(buf) DO4_CRC32(buf); DO4_CRC32(buf); unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len) { if (buf == 0) return 0L; crc = crc ^ 0xffffffffL; while (len >= 8) { DO8_CRC32(buf); len -= 8; } if (len) do { DO1_CRC32(buf); } while (--len); return crc ^ 0xffffffffL; } #endif #ifdef __cplusplus } #endif mednafen/psx/gpu_polygon.cpp000664 001750 001750 00000032234 12611054044 017340 0ustar00sergiosergio000000 000000 #define COORD_FBS 12 #define COORD_MF_INT(n) ((n) << COORD_FBS) #define COORD_POST_PADDING 12 struct i_group { uint32_t u, v; uint32_t r, g, b; }; struct i_deltas { uint32_t du_dx, dv_dx; uint32_t dr_dx, dg_dx, db_dx; uint32_t du_dy, dv_dy; uint32_t dr_dy, dg_dy, db_dy; }; /* Store and do most math with interpolant coordinates and deltas as unsigned to avoid violating strict overflow(due to biasing), but when actually grabbing the coordinates, treat them as signed(with signed right shift) so we can do saturation properly. */ static INLINE int32_t COORD_GET_INT(int32_t n) { return(n >> COORD_FBS); } static INLINE int64_t MakePolyXFP(uint32_t x) { return ((uint64_t)x << 32) + ((UINT64_C(1) << 32) - (1 << 11)); } static INLINE int64_t MakePolyXFPStep(int32_t dx, int32_t dy) { int64_t ret; int64_t dx_ex = (int64_t)dx << 32; if(dx_ex < 0) dx_ex -= dy - 1; if(dx_ex > 0) dx_ex += dy - 1; ret = dx_ex / dy; return(ret); } static INLINE int32_t GetPolyXFP_Int(int64_t xfp) { return(xfp >> 32); } #define CALCIS(x,y) (((B.x - A.x) * (C.y - B.y)) - ((C.x - B.x) * (B.y - A.y))) static INLINE bool CalcIDeltas(i_deltas &idl, const tri_vertex &A, const tri_vertex &B, const tri_vertex &C) { const unsigned sa = 32; int64_t num = ((int64_t)COORD_MF_INT(1)) << sa; int64_t denom = CALCIS(x, y); int64_t one_div; if(!denom) return(false); one_div = num / denom; idl.dr_dx = ((one_div * CALCIS(r, y)) + 0x00000000) >> sa; idl.dr_dy = ((one_div * CALCIS(x, r)) + 0x00000000) >> sa; idl.dg_dx = ((one_div * CALCIS(g, y)) + 0x00000000) >> sa; idl.dg_dy = ((one_div * CALCIS(x, g)) + 0x00000000) >> sa; idl.db_dx = ((one_div * CALCIS(b, y)) + 0x00000000) >> sa; idl.db_dy = ((one_div * CALCIS(x, b)) + 0x00000000) >> sa; idl.du_dx = ((one_div * CALCIS(u, y)) + 0x00000000) >> sa; idl.du_dy = ((one_div * CALCIS(x, u)) + 0x00000000) >> sa; idl.dv_dx = ((one_div * CALCIS(v, y)) + 0x00000000) >> sa; idl.dv_dy = ((one_div * CALCIS(x, v)) + 0x00000000) >> sa; // idl.du_dx = ((int64_t)CALCIS(u, y) << COORD_FBS) / denom; // idl.du_dy = ((int64_t)CALCIS(x, u) << COORD_FBS) / denom; // idl.dv_dx = ((int64_t)CALCIS(v, y) << COORD_FBS) / denom; // idl.dv_dy = ((int64_t)CALCIS(x, v) << COORD_FBS) / denom; //printf("Denom=%lld - CIS_UY=%d, CIS_XU=%d, CIS_VY=%d, CIS_XV=%d\n", denom, CALCIS(u, y), CALCIS(x, u), CALCIS(v, y), CALCIS(x, v)); //printf(" du_dx=0x%08x, du_dy=0x%08x --- dv_dx=0x%08x, dv_dy=0x%08x\n", idl.du_dx, idl.du_dy, idl.dv_dx, idl.dv_dy); return(true); } #undef CALCIS template static INLINE void AddIDeltas_DX(i_group &ig, const i_deltas &idl, uint32_t count = 1) { if(textured) { ig.u += idl.du_dx * count; ig.v += idl.dv_dx * count; } if(goraud) { ig.r += idl.dr_dx * count; ig.g += idl.dg_dx * count; ig.b += idl.db_dx * count; } } template static INLINE void AddIDeltas_DY(i_group &ig, const i_deltas &idl, uint32_t count = 1) { if(textured) { ig.u += idl.du_dy * count; ig.v += idl.dv_dy * count; } if(goraud) { ig.r += idl.dr_dy * count; ig.g += idl.dg_dy * count; ig.b += idl.db_dy * count; } } template INLINE void PS_GPU::DrawSpan(int y, uint32_t clut_offset, const int32_t x_start, const int32_t x_bound, i_group ig, const i_deltas &idl) { int32_t xs = x_start, xb = x_bound; if(LineSkipTest(this, y)) return; if(xs < xb) // (xs != xb) { if(xs < ClipX0) xs = ClipX0; if(xb > (ClipX1 + 1)) xb = ClipX1 + 1; if(xs < xb) { DrawTimeAvail -= (xb - xs); if(goraud || textured) { DrawTimeAvail -= (xb - xs); } else if((BlendMode >= 0) || MaskEval_TA) { DrawTimeAvail -= (((xb + 1) & ~1) - (xs & ~1)) >> 1; } } if(textured) { ig.u += (xs * idl.du_dx) + (y * idl.du_dy); ig.v += (xs * idl.dv_dx) + (y * idl.dv_dy); } if(goraud) { ig.r += (xs * idl.dr_dx) + (y * idl.dr_dy); ig.g += (xs * idl.dg_dx) + (y * idl.dg_dy); ig.b += (xs * idl.db_dx) + (y * idl.db_dy); } for(int32_t x = xs; MDFN_LIKELY(x < xb); x++) { uint32_t r, g, b; if(goraud) { r = RGB8SAT[COORD_GET_INT(ig.r)]; g = RGB8SAT[COORD_GET_INT(ig.g)]; b = RGB8SAT[COORD_GET_INT(ig.b)]; } else { r = COORD_GET_INT(ig.r); g = COORD_GET_INT(ig.g); b = COORD_GET_INT(ig.b); } if(textured) { uint16_t fbw = GetTexel(clut_offset, COORD_GET_INT(ig.u), COORD_GET_INT(ig.v)); if(fbw) { if(TexMult) fbw = ModTexel(fbw, r, g, b, (dtd) ? (x & 3) : 3, (dtd) ? (y & 3) : 2); PlotPixel(x, y, fbw); } } else { uint16_t pix = 0x8000; if(goraud && dtd) { pix |= DitherLUT[y & 3][x & 3][r] << 0; pix |= DitherLUT[y & 3][x & 3][g] << 5; pix |= DitherLUT[y & 3][x & 3][b] << 10; } else { pix |= (r >> 3) << 0; pix |= (g >> 3) << 5; pix |= (b >> 3) << 10; } PlotPixel(x, y, pix); } AddIDeltas_DX(ig, idl); //AddStep(perp_coord, perp_step); } } } template void PS_GPU::DrawTriangle(tri_vertex *vertices, uint32_t clut) { i_deltas idl; // // Sort vertices by y. // if(vertices[2].y < vertices[1].y) { tri_vertex tmp = vertices[1]; vertices[1] = vertices[2]; vertices[2] = tmp; } if(vertices[1].y < vertices[0].y) { tri_vertex tmp = vertices[0]; vertices[0] = vertices[1]; vertices[1] = tmp; } if(vertices[2].y < vertices[1].y) { tri_vertex tmp = vertices[1]; vertices[1] = vertices[2]; vertices[2] = tmp; } if(vertices[0].y == vertices[2].y) return; if((vertices[2].y - vertices[0].y) >= 512) { //PSX_WARNING("[GPU] Triangle height too large: %d", (vertices[2].y - vertices[0].y)); return; } if(abs(vertices[2].x - vertices[0].x) >= 1024 || abs(vertices[2].x - vertices[1].x) >= 1024 || abs(vertices[1].x - vertices[0].x) >= 1024) { //PSX_WARNING("[GPU] Triangle width too large: %d %d %d", abs(vertices[2].x - vertices[0].x), abs(vertices[2].x - vertices[1].x), abs(vertices[1].x - vertices[0].x)); return; } if(!CalcIDeltas(idl, vertices[0], vertices[1], vertices[2])) return; // [0] should be top vertex, [2] should be bottom vertex, [1] should be off to the side vertex. // // int32_t y_start = vertices[0].y; int32_t y_middle = vertices[1].y; int32_t y_bound = vertices[2].y; int64_t base_coord; int64_t base_step; int64_t bound_coord_ul; int64_t bound_coord_us; int64_t bound_coord_ll; int64_t bound_coord_ls; bool right_facing; //bool bottom_up; i_group ig; // // Find vertex with lowest X coordinate, and use as the base for calculating interpolants from. // { unsigned iggvi = 0; // // <=, not < // if(vertices[1].x <= vertices[iggvi].x) iggvi = 1; if(vertices[2].x <= vertices[iggvi].x) iggvi = 2; ig.u = COORD_MF_INT(vertices[iggvi].u) + (1 << (COORD_FBS - 1)); ig.v = COORD_MF_INT(vertices[iggvi].v) + (1 << (COORD_FBS - 1)); ig.r = COORD_MF_INT(vertices[iggvi].r); ig.g = COORD_MF_INT(vertices[iggvi].g); ig.b = COORD_MF_INT(vertices[iggvi].b); AddIDeltas_DX(ig, idl, -vertices[iggvi].x); AddIDeltas_DY(ig, idl, -vertices[iggvi].y); } base_coord = MakePolyXFP(vertices[0].x); base_step = MakePolyXFPStep((vertices[2].x - vertices[0].x), (vertices[2].y - vertices[0].y)); bound_coord_ul = MakePolyXFP(vertices[0].x); bound_coord_ll = MakePolyXFP(vertices[1].x); // // // if(vertices[1].y == vertices[0].y) { bound_coord_us = 0; right_facing = (bool)(vertices[1].x > vertices[0].x); } else { bound_coord_us = MakePolyXFPStep((vertices[1].x - vertices[0].x), (vertices[1].y - vertices[0].y)); right_facing = (bool)(bound_coord_us > base_step); } if(vertices[2].y == vertices[1].y) bound_coord_ls = 0; else bound_coord_ls = MakePolyXFPStep((vertices[2].x - vertices[1].x), (vertices[2].y - vertices[1].y)); if(y_start < ClipY0) { int32_t count = ClipY0 - y_start; y_start = ClipY0; base_coord += base_step * count; bound_coord_ul += bound_coord_us * count; if(y_middle < ClipY0) { int32_t count_ls = ClipY0 - y_middle; y_middle = ClipY0; bound_coord_ll += bound_coord_ls * count_ls; } } if(y_bound > (ClipY1 + 1)) { y_bound = ClipY1 + 1; if(y_middle > y_bound) y_middle = y_bound; } if(right_facing) { for(int32_t y = y_start; y < y_middle; y++) { DrawSpan(y, clut, GetPolyXFP_Int(base_coord), GetPolyXFP_Int(bound_coord_ul), ig, idl); base_coord += base_step; bound_coord_ul += bound_coord_us; } for(int32_t y = y_middle; y < y_bound; y++) { DrawSpan(y, clut, GetPolyXFP_Int(base_coord), GetPolyXFP_Int(bound_coord_ll), ig, idl); base_coord += base_step; bound_coord_ll += bound_coord_ls; } } else { for(int32_t y = y_start; y < y_middle; y++) { DrawSpan(y, clut, GetPolyXFP_Int(bound_coord_ul), GetPolyXFP_Int(base_coord), ig, idl); base_coord += base_step; bound_coord_ul += bound_coord_us; } for(int32_t y = y_middle; y < y_bound; y++) { DrawSpan(y, clut, GetPolyXFP_Int(bound_coord_ll), GetPolyXFP_Int(base_coord), ig, idl); base_coord += base_step; bound_coord_ll += bound_coord_ls; } } #if 0 printf("[GPU] Vertices: %d:%d(r=%d, g=%d, b=%d) -> %d:%d(r=%d, g=%d, b=%d) -> %d:%d(r=%d, g=%d, b=%d)\n\n\n", vertices[0].x, vertices[0].y, vertices[0].r, vertices[0].g, vertices[0].b, vertices[1].x, vertices[1].y, vertices[1].r, vertices[1].g, vertices[1].b, vertices[2].x, vertices[2].y, vertices[2].r, vertices[2].g, vertices[2].b); #endif } template INLINE void PS_GPU::Command_DrawPolygon(const uint32_t *cb) { const unsigned cb0 = cb[0]; tri_vertex vertices[3]; uint32_t clut = 0; unsigned sv = 0; //uint32_t tpage = 0; // Base timing is approximate, and could be improved. if(numvertices == 4 && InCmd == INCMD_QUAD) DrawTimeAvail -= (28 + 18); else DrawTimeAvail -= (64 + 18); if(goraud && textured) DrawTimeAvail -= 150 * 3; else if(goraud) DrawTimeAvail -= 96 * 3; else if(textured) DrawTimeAvail -= 60 * 3; if(numvertices == 4) { if(InCmd == INCMD_QUAD) { memcpy(&vertices[0], &InQuad_F3Vertices[1], 2 * sizeof(tri_vertex)); clut = InQuad_clut; sv = 2; } } //else // memset(vertices, 0, sizeof(vertices)); for(unsigned v = sv; v < 3; v++) { if(v == 0 || goraud) { uint32_t raw_color = (*cb & 0xFFFFFF); vertices[v].r = raw_color & 0xFF; vertices[v].g = (raw_color >> 8) & 0xFF; vertices[v].b = (raw_color >> 16) & 0xFF; cb++; } else { vertices[v].r = vertices[0].r; vertices[v].g = vertices[0].g; vertices[v].b = vertices[0].b; } vertices[v].x = sign_x_to_s32(11, ((int16_t)(*cb & 0xFFFF))) + OffsX; vertices[v].y = sign_x_to_s32(11, ((int16_t)(*cb >> 16))) + OffsY; cb++; if(textured) { vertices[v].u = (*cb & 0xFF); vertices[v].v = (*cb >> 8) & 0xFF; if(v == 0) { clut = ((*cb >> 16) & 0xFFFF) << 4; } cb++; } } if(numvertices == 4) { if(InCmd == INCMD_QUAD) { InCmd = INCMD_NONE; } else { InCmd = INCMD_QUAD; InCmd_CC = cb0 >> 24; memcpy(&InQuad_F3Vertices[0], &vertices[0], sizeof(tri_vertex) * 3); InQuad_clut = clut; } } DrawTriangle(vertices, clut); } #undef COORD_POST_PADDING #undef COORD_FBS #undef COORD_MF_INT mednafen/tremor/000700 001750 001750 00000000000 12702525066 014760 5ustar00sergiosergio000000 000000 mednafen/psx/input/dualanalog.h000664 001750 001750 00000000413 12611054044 017703 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_INPUT_DUALANALOG_H #define __MDFN_PSX_INPUT_DUALANALOG_H InputDevice *Device_DualAnalog_Create(bool joystick_mode); extern InputDeviceInputInfoStruct Device_DualAnalog_IDII[24]; extern InputDeviceInputInfoStruct Device_AnalogJoy_IDII[24]; #endif libretro-common/rthreads/gx_pthread.h000664 001750 001750 00000011473 12611054044 021127 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (gx_pthread.h). * --------------------------------------------------------------------------------------- * * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef _GX_PTHREAD_WRAP_GX_ #define _GX_PTHREAD_WRAP_GX_ #include #include #include #include #ifndef OSThread #define OSThread lwp_t #endif #ifndef OSCond #define OSCond lwpq_t #endif #ifndef OSThreadQueue #define OSThreadQueue lwpq_t #endif #ifndef OSInitMutex #define OSInitMutex(mutex) LWP_MutexInit(mutex, 0) #endif #ifndef OSLockMutex #define OSLockMutex(mutex) LWP_MutexLock(mutex) #endif #ifndef OSUnlockMutex #define OSUnlockMutex(mutex) LWP_MutexUnlock(mutex) #endif #ifndef OSTryLockMutex #define OSTryLockMutex(mutex) LWP_MutexTryLock(mutex) #endif #ifndef OSInitCond #define OSInitCond(cond) LWP_CondInit(cond) #endif #if 0 #ifndef OSSignalCond #define OSSignalCond(cond) LWP_ThreadSignal(cond) #endif #endif #ifndef OSWaitCond #define OSWaitCond(cond, mutex) LWP_CondWait(cond, mutex) #endif #ifndef OSInitThreadQueue #define OSInitThreadQueue(queue) LWP_InitQueue(queue) #endif #ifndef OSSleepThread #define OSSleepThread(queue) LWP_ThreadSleep(queue) #endif #ifndef OSJoinThread #define OSJoinThread(thread, val) LWP_JoinThread(thread, val) #endif #ifndef OSSignalCond #define OSSignalCond(thread) LWP_CondSignal(thread) #endif #ifndef OSCreateThread #define OSCreateThread(thread, func, intarg, ptrarg, stackbase, stacksize, priority, attrs) LWP_CreateThread(thread, func, ptrarg, stackbase, stacksize, priority) #endif #define STACKSIZE (8 * 1024) typedef OSThread pthread_t; typedef mutex_t pthread_mutex_t; typedef void* pthread_mutexattr_t; typedef int pthread_attr_t; typedef OSCond pthread_cond_t; typedef OSCond pthread_condattr_t; static INLINE int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg) { *thread = 0; return OSCreateThread(thread, start_routine, 0 /* unused */, arg, 0, STACKSIZE, 64, 0 /* unused */); } static INLINE int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) { return OSInitMutex(mutex); } static INLINE int pthread_mutex_destroy(pthread_mutex_t *mutex) { return LWP_MutexDestroy(*mutex); } static INLINE int pthread_mutex_lock(pthread_mutex_t *mutex) { return OSLockMutex(*mutex); } static INLINE int pthread_mutex_unlock(pthread_mutex_t *mutex) { return OSUnlockMutex(*mutex); } static INLINE void pthread_exit(void *retval) { /* FIXME: No LWP equivalent for this? */ (void)retval; } static INLINE int pthread_detach(pthread_t thread) { /* FIXME: pthread_detach equivalent missing? */ (void)thread; return 0; } static INLINE int pthread_join(pthread_t thread, void **retval) { return OSJoinThread(thread, retval); } static INLINE int pthread_mutex_trylock(pthread_mutex_t *mutex) { return OSTryLockMutex(*mutex); } static INLINE int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { return OSWaitCond(*cond, *mutex); } static INLINE int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { return LWP_CondTimedWait(*cond, *mutex, abstime); } static INLINE int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { return OSInitCond(cond); } static INLINE int pthread_cond_signal(pthread_cond_t *cond) { OSSignalCond(*cond); return 0; } static INLINE int pthread_cond_broadcast(pthread_cond_t *cond) { return LWP_CondBroadcast(*cond); } static INLINE int pthread_cond_destroy(pthread_cond_t *cond) { return LWP_CondDestroy(*cond); } #endif mednafen/FileStream.h000664 001750 001750 00000002665 12611054044 015671 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ // TODO/WIP #ifndef __MDFN_FILESTREAM_H #define __MDFN_FILESTREAM_H #include #include #include "Stream.h" class FileStream : public Stream { public: FileStream(const char *path, const int mode); virtual ~FileStream(); virtual uint64_t attributes(void); virtual uint64_t read(void *data, uint64_t count, bool error_on_eos = true); virtual void write(const void *data, uint64_t count); virtual void seek(int64_t offset, int whence); virtual int64_t tell(void); virtual int64_t size(void); virtual void close(void); private: RFILE *fp; char *original_path; const int OpenedMode; }; #endif mednafen/psx/000700 001750 001750 00000000000 12702525066 014262 5ustar00sergiosergio000000 000000 scrc32.h000664 001750 001750 00000000310 12611054044 013141 0ustar00sergiosergio000000 000000 #ifndef _S_CRC32_H #define _S_CRC32_H #ifdef __cplusplus extern "C" { #endif unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len); #ifdef __cplusplus } #endif #endif mednafen/settings.h000755 001750 001750 00000001326 12611054044 015470 0ustar00sergiosergio000000 000000 #ifndef MDFN_SETTINGS_H #define MDFN_SETTINGS_H #include extern uint32_t setting_psx_multitap_port_1; extern uint32_t setting_psx_multitap_port_2; extern uint32_t setting_psx_analog_toggle; extern uint32_t setting_psx_fastboot; extern int setting_initial_scanline; extern int setting_initial_scanline_pal; extern int setting_last_scanline; extern int setting_last_scanline_pal; // This should assert() or something if the setting isn't found, since it would // be a totally tubular error! uint64 MDFN_GetSettingUI(const char *name); int64 MDFN_GetSettingI(const char *name); double MDFN_GetSettingF(const char *name); bool MDFN_GetSettingB(const char *name); std::string MDFN_GetSettingS(const char *name); #endif mednafen/include/config.h.in000664 001750 001750 00000051437 12611054044 017134 0ustar00sergiosergio000000 000000 /* include/config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Define if we are compiling for PPC architectures. */ #undef ARCH_POWERPC /* Define if we are compiling with AltiVec usage. */ #undef ARCH_POWERPC_ALTIVEC /* Define if we are compiling for 32-bit or 64-bit x86 architectures. */ #undef ARCH_X86 /* Define if we are compiling for 32-bit x86 architectures. */ #undef ARCH_X86_32 /* Define if we are compiling for 64-bit x86 architectures. */ #undef ARCH_X86_64 /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ #undef CRAY_STACKSEG_END /* Define to 1 if using `alloca.c'. */ #undef C_ALLOCA /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef ENABLE_NLS /* Define to 1 if you have the `accept' function. */ #undef HAVE_ACCEPT /* Define to 1 if you have `alloca', as a function or macro. */ #undef HAVE_ALLOCA /* Define to 1 if you have and it should be used (not on Ultrix). */ #undef HAVE_ALLOCA_H /* Define if we are compiling with ALSA support. */ #undef HAVE_ALSA /* Define if altivec.h is present and usable. */ #undef HAVE_ALTIVEC_H /* Define if we should include from OpenGL instead of GL */ #undef HAVE_APPLE_OPENGL_FRAMEWORK /* Define to 1 if you have the `argz_count' function. */ #undef HAVE_ARGZ_COUNT /* Define to 1 if you have the header file. */ #undef HAVE_ARGZ_H /* Define to 1 if you have the `argz_next' function. */ #undef HAVE_ARGZ_NEXT /* Define to 1 if you have the `argz_stringify' function. */ #undef HAVE_ARGZ_STRINGIFY /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF /* Define to 1 if you have the `bind' function. */ #undef HAVE_BIND /* Define to 1 if the compiler understands __builtin_expect. */ #undef HAVE_BUILTIN_EXPECT /* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the CoreFoundation framework. */ #undef HAVE_CFLOCALECOPYCURRENT /* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in the CoreFoundation framework. */ #undef HAVE_CFPREFERENCESCOPYAPPVALUE /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME /* Define to 1 if you have the `close' function. */ #undef HAVE_CLOSE /* Define to 1 if you have the `connect' function. */ #undef HAVE_CONNECT /* Define if the GNU dcgettext() function is already present or preinstalled. */ #undef HAVE_DCGETTEXT /* Define to 1 if you have the declaration of `feof_unlocked', and to 0 if you don't. */ #undef HAVE_DECL_FEOF_UNLOCKED /* Define to 1 if you have the declaration of `fgets_unlocked', and to 0 if you don't. */ #undef HAVE_DECL_FGETS_UNLOCKED /* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you don't. */ #undef HAVE_DECL_GETC_UNLOCKED /* Define to 1 if you have the declaration of `_snprintf', and to 0 if you don't. */ #undef HAVE_DECL__SNPRINTF /* Define to 1 if you have the declaration of `_snwprintf', and to 0 if you don't. */ #undef HAVE_DECL__SNWPRINTF /* Define if we are compiling with DirectSound support. */ #undef HAVE_DIRECTSOUND /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the `fcntl' function. */ #undef HAVE_FCNTL /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `fopen64' function. */ #undef HAVE_FOPEN64 /* Define to 1 if you have the `freeaddrinfo' function. */ #undef HAVE_FREEADDRINFO /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #undef HAVE_FSEEKO /* Define to 1 if you have the `fseeko64' function. */ #undef HAVE_FSEEKO64 /* Define to 1 if you have the `fstat64' function. */ #undef HAVE_FSTAT64 /* Define to 1 if you have the `ftello' function. */ #undef HAVE_FTELLO /* Define to 1 if you have the `ftello64' function. */ #undef HAVE_FTELLO64 /* Define to 1 if you have the `fwprintf' function. */ #undef HAVE_FWPRINTF /* Define to 1 if you have the `gai_strerror' function. */ #undef HAVE_GAI_STRERROR /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD /* Define to 1 if you have the `getegid' function. */ #undef HAVE_GETEGID /* Define to 1 if you have the `getenv' function. */ #undef HAVE_GETENV /* Define to 1 if you have the `geteuid' function. */ #undef HAVE_GETEUID /* Define to 1 if you have the `getgid' function. */ #undef HAVE_GETGID /* Define to 1 if you have the `gethostbyaddr' function. */ #undef HAVE_GETHOSTBYADDR /* Define to 1 if you have the `gethostbyname' function. */ #undef HAVE_GETHOSTBYNAME /* Define to 1 if you have the `getpagesize' function. */ #undef HAVE_GETPAGESIZE /* Define to 1 if you have the `getpwuid' function. */ #undef HAVE_GETPWUID /* Define to 1 if you have the `getsockopt' function. */ #undef HAVE_GETSOCKOPT /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the `getuid' function. */ #undef HAVE_GETUID /* Define if you have the iconv() function and it works. */ #undef HAVE_ICONV /* Define if you have the 'intmax_t' type in or . */ #undef HAVE_INTMAX_T /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define if exists, doesn't clash with , and declares uintmax_t. */ #undef HAVE_INTTYPES_H_WITH_UINTMAX /* Define if we are compiling with JACK support. */ #undef HAVE_JACK /* Define if you have and nl_langinfo(CODESET). */ #undef HAVE_LANGINFO_CODESET /* Define if your file defines LC_MESSAGES. */ #undef HAVE_LC_MESSAGES /* Define to 1 if you have the `asound' library (-lasound). */ #undef HAVE_LIBASOUND /* Define if we are compiling with libsndfile support. */ #undef HAVE_LIBSNDFILE /* Define to 1 if you have the `z' library (-lz). */ #undef HAVE_LIBZ /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define if we are compiling with Linux joystick support. */ #undef HAVE_LINUX_JOYSTICK /* Define to 1 if you have the `listen' function. */ #undef HAVE_LISTEN /* Define to 1 if the system has the type `long long int'. */ #undef HAVE_LONG_LONG_INT /* Define to 1 if you have the `madvise' function. */ #undef HAVE_MADVISE /* Define to 1 if you have the `mbrtowc' function. */ #undef HAVE_MBRTOWC /* Define to 1 if you have the `memcmp' function. */ #undef HAVE_MEMCMP /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mempcpy' function. */ #undef HAVE_MEMPCPY /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the `mkdir' function. */ #undef HAVE_MKDIR /* Define to 1 if you have a working `mmap' system call. */ #undef HAVE_MMAP /* Define to 1 if you have the `munmap' function. */ #undef HAVE_MUNMAP /* Define to 1 if you have the `nanosleep' function. */ #undef HAVE_NANOSLEEP /* Define to 1 if you have the `newlocale' function. */ #undef HAVE_NEWLOCALE /* Define if we are compiling with OSS support. */ #undef HAVE_OSSDSP /* Define if your printf() function supports format strings with positions. */ #undef HAVE_POSIX_PRINTF /* Define if we are compiling with POSIX sockets support. */ #undef HAVE_POSIX_SOCKETS /* Define if the defines PTHREAD_MUTEX_RECURSIVE. */ #undef HAVE_PTHREAD_MUTEX_RECURSIVE /* Define if the POSIX multithreading library has read/write locks. */ #undef HAVE_PTHREAD_RWLOCK /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV /* Define to 1 if you have the `recv' function. */ #undef HAVE_RECV /* Define if we are compiling with SDL sound support. */ #undef HAVE_SDL /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the `send' function. */ #undef HAVE_SEND /* Define to 1 if you have the `setenv' function. */ #undef HAVE_SETENV /* Define to 1 if you have the `setlocale' function. */ #undef HAVE_SETLOCALE /* Define to 1 if you have the `setsockopt' function. */ #undef HAVE_SETSOCKOPT /* Define to 1 if you have the `sigaction' function. */ #undef HAVE_SIGACTION /* Define to 1 if you have the `signal' function. */ #undef HAVE_SIGNAL /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* Define to 1 if you have the header file. */ #undef HAVE_STDDEF_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define if exists, doesn't clash with , and declares uintmax_t. */ #undef HAVE_STDINT_H_WITH_UINTMAX /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `stpcpy' function. */ #undef HAVE_STPCPY /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the `strerror_r' function. */ #undef HAVE_STRERROR_R /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strnlen' function. */ #undef HAVE_STRNLEN /* Define to 1 if you have the `strtoul' function. */ #undef HAVE_STRTOUL /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the `tsearch' function. */ #undef HAVE_TSEARCH /* Define if you have the 'uintmax_t' type in or . */ #undef HAVE_UINTMAX_T /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if the system has the type `unsigned long long int'. */ #undef HAVE_UNSIGNED_LONG_LONG_INT /* Define to 1 if you have the `uselocale' function. */ #undef HAVE_USELOCALE /* Define to 1 if you have the `usleep' function. */ #undef HAVE_USLEEP /* Define to 1 or 0, depending whether the compiler supports simple visibility declarations. */ #undef HAVE_VISIBILITY /* Define if you have the 'wchar_t' type. */ #undef HAVE_WCHAR_T /* Define to 1 if you have the `wcrtomb' function. */ #undef HAVE_WCRTOMB /* Define to 1 if you have the `wcslen' function. */ #undef HAVE_WCSLEN /* Define to 1 if you have the `wcsnlen' function. */ #undef HAVE_WCSNLEN /* Define if you have the 'wint_t' type. */ #undef HAVE_WINT_T /* Define to 1 if O_NOATIME works. */ #undef HAVE_WORKING_O_NOATIME /* Define to 1 if O_NOFOLLOW works. */ #undef HAVE_WORKING_O_NOFOLLOW /* Define to 1 if you have the `_mkdir' function. */ #undef HAVE__MKDIR /* Define to 1 if you have the `__fsetlocking' function. */ #undef HAVE___FSETLOCKING /* Define as const if the declaration of iconv() needs const. */ #undef ICONV_CONST /* Define if integer division by zero raises signal SIGFPE. */ #undef INTDIV0_RAISES_SIGFPE /* Define on little-endian platforms. */ #undef LSB_FIRST /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Mednafen version definition. */ #undef MEDNAFEN_VERSION /* Mednafen version numeric. */ #undef MEDNAFEN_VERSION_NUMERIC /* Define if config.h is present */ #undef MINILZO_HAVE_CONFIG_H /* Define if mkdir takes only one argument. */ #undef MKDIR_TAKES_ONE_ARG /* Define to use fixed-point MPC decoder. */ #undef MPC_FIXED_POINT /* Define on big-endian platforms. */ #undef MSB_FIRST /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define if exists and defines unusable PRI* macros. */ #undef PRI_MACROS_BROKEN /* Defines the filesystem path-separator type. */ #undef PSS_STYLE /* Define if the pthread_in_use() detection is hard. */ #undef PTHREAD_IN_USE_DETECTION_HARD /* The size of `double', as computed by sizeof. */ #undef SIZEOF_DOUBLE /* The size of `int', as computed by sizeof. */ #undef SIZEOF_INT /* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG /* The size of `long long', as computed by sizeof. */ #undef SIZEOF_LONG_LONG /* The size of `off_t', as computed by sizeof. */ #undef SIZEOF_OFF_T /* The size of `ptrdiff_t', as computed by sizeof. */ #undef SIZEOF_PTRDIFF_T /* The size of `short', as computed by sizeof. */ #undef SIZEOF_SHORT /* The size of `size_t', as computed by sizeof. */ #undef SIZEOF_SIZE_T /* The size of `void *', as computed by sizeof. */ #undef SIZEOF_VOID_P /* The size of `__int64', as computed by sizeof. */ #undef SIZEOF___INT64 /* Define as the maximum value of type 'size_t', if the system doesn't define it. */ #ifndef SIZE_MAX # undef SIZE_MAX #endif /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ #undef STACK_DIRECTION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if the POSIX multithreading library can be used. */ #undef USE_POSIX_THREADS /* Define if references to the POSIX multithreading library should be made weak. */ #undef USE_POSIX_THREADS_WEAK /* Define if the GNU Pth multithreading library can be used. */ #undef USE_PTH_THREADS /* Define if references to the GNU Pth multithreading library should be made weak. */ #undef USE_PTH_THREADS_WEAK /* Define if the old Solaris multithreading library can be used. */ #undef USE_SOLARIS_THREADS /* Define if references to the old Solaris multithreading library should be made weak. */ #undef USE_SOLARIS_THREADS_WEAK /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Define if the Win32 multithreading API can be used. */ #undef USE_WIN32_THREADS /* Version number of package */ #undef VERSION /* Define if we are compiling with debugger. */ #undef WANT_DEBUGGER /* Define if we are compiling with GBA emulation. */ #undef WANT_GBA_EMU /* Define if we are compiling with GB emulation. */ #undef WANT_GB_EMU /* Define if we are compiling with internal CJK fonts. */ #undef WANT_INTERNAL_CJK /* Define if we are compiling with Lynx emulation. */ #undef WANT_LYNX_EMU /* Define if we are compiling with Sega Genesis/MegaDrive emulation. */ #undef WANT_MD_EMU /* Define if we are compiling with NES emulation. */ #undef WANT_NES_EMU /* Define if we are compiling with NGP emulation. */ #undef WANT_NGP_EMU /* Define if we are compiling with PCE emulation. */ #undef WANT_PCE_EMU /* Define if we are compiling with separate fast PCE emulation. */ #undef WANT_PCE_FAST_EMU /* Define if we are compiling with PC-FX emulation. */ #undef WANT_PCFX_EMU /* Define if we are compiling with PlayStation emulation. */ #undef WANT_PSX_EMU /* Define if we are compiling with SMS+GG emulation. */ #undef WANT_SMS_EMU /* Define if we are compiling with SNES emulation. */ #undef WANT_SNES_EMU /* Define if we are compiling with Virtual Boy emulation. */ #undef WANT_VB_EMU /* Define if we are compiling with WonderSwan emulation. */ #undef WANT_WSWAN_EMU /* Define if we are compiling for Win32. */ #undef WIN32 /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ #undef _LARGEFILE_SOURCE /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* Define to 1 if on MINIX. */ #undef _MINIX /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ #undef _POSIX_SOURCE /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define as the type of the result of subtracting two pointers, if the system doesn't define it. */ #undef ptrdiff_t /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to unsigned long or unsigned long long if and don't define. */ #undef uintmax_t #define __libc_lock_t gl_lock_t #define __libc_lock_define gl_lock_define #define __libc_lock_define_initialized gl_lock_define_initialized #define __libc_lock_init gl_lock_init #define __libc_lock_lock gl_lock_lock #define __libc_lock_unlock gl_lock_unlock #define __libc_lock_recursive_t gl_recursive_lock_t #define __libc_lock_define_recursive gl_recursive_lock_define #define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized #define __libc_lock_init_recursive gl_recursive_lock_init #define __libc_lock_lock_recursive gl_recursive_lock_lock #define __libc_lock_unlock_recursive gl_recursive_lock_unlock #define glthread_in_use libintl_thread_in_use #define glthread_lock_init_func libintl_lock_init_func #define glthread_lock_lock_func libintl_lock_lock_func #define glthread_lock_unlock_func libintl_lock_unlock_func #define glthread_lock_destroy_func libintl_lock_destroy_func #define glthread_rwlock_init_multithreaded libintl_rwlock_init_multithreaded #define glthread_rwlock_init_func libintl_rwlock_init_func #define glthread_rwlock_rdlock_multithreaded libintl_rwlock_rdlock_multithreaded #define glthread_rwlock_rdlock_func libintl_rwlock_rdlock_func #define glthread_rwlock_wrlock_multithreaded libintl_rwlock_wrlock_multithreaded #define glthread_rwlock_wrlock_func libintl_rwlock_wrlock_func #define glthread_rwlock_unlock_multithreaded libintl_rwlock_unlock_multithreaded #define glthread_rwlock_unlock_func libintl_rwlock_unlock_func #define glthread_rwlock_destroy_multithreaded libintl_rwlock_destroy_multithreaded #define glthread_rwlock_destroy_func libintl_rwlock_destroy_func #define glthread_recursive_lock_init_multithreaded libintl_recursive_lock_init_multithreaded #define glthread_recursive_lock_init_func libintl_recursive_lock_init_func #define glthread_recursive_lock_lock_multithreaded libintl_recursive_lock_lock_multithreaded #define glthread_recursive_lock_lock_func libintl_recursive_lock_lock_func #define glthread_recursive_lock_unlock_multithreaded libintl_recursive_lock_unlock_multithreaded #define glthread_recursive_lock_unlock_func libintl_recursive_lock_unlock_func #define glthread_recursive_lock_destroy_multithreaded libintl_recursive_lock_destroy_multithreaded #define glthread_recursive_lock_destroy_func libintl_recursive_lock_destroy_func #define glthread_once_func libintl_once_func #define glthread_once_singlethreaded libintl_once_singlethreaded #define glthread_once_multithreaded libintl_once_multithreaded mednafen/include/desa68000777 001750 001750 00000000000 12702525066 020215 2../src/desa68/ustar00sergiosergio000000 000000 jni/Application.mk000664 001750 001750 00000000051 12611054044 015247 0ustar00sergiosergio000000 000000 APP_STL := gnustl_static APP_ABI := all mednafen/tremor/os_types.h000664 001750 001750 00000010257 12611054044 017007 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** function: #ifdef jail to whip a few platforms into the UNIX ideal. last mod: $Id: os_types.h 17712 2010-12-03 17:10:02Z xiphmont $ ********************************************************************/ #ifndef _OS_TYPES_H #define _OS_TYPES_H /* make it easy on the folks that want to compile the libs with a different malloc than stdlib */ #define _ogg_malloc malloc #define _ogg_calloc calloc #define _ogg_realloc realloc #define _ogg_free free #if defined(_WIN32) # if defined(__CYGWIN__) # include typedef int16_t ogg_int16_t; typedef uint16_t ogg_uint16_t; typedef int32_t ogg_int32_t; typedef uint32_t ogg_uint32_t; typedef int64_t ogg_int64_t; typedef uint64_t ogg_uint64_t; # elif defined(__MINGW32__) # include typedef short ogg_int16_t; typedef unsigned short ogg_uint16_t; typedef int ogg_int32_t; typedef unsigned int ogg_uint32_t; typedef long long ogg_int64_t; typedef unsigned long long ogg_uint64_t; # elif defined(__MWERKS__) typedef long long ogg_int64_t; typedef int ogg_int32_t; typedef unsigned int ogg_uint32_t; typedef short ogg_int16_t; typedef unsigned short ogg_uint16_t; # else /* MSVC/Borland */ typedef __int64 ogg_int64_t; typedef __int32 ogg_int32_t; typedef unsigned __int32 ogg_uint32_t; typedef __int16 ogg_int16_t; typedef unsigned __int16 ogg_uint16_t; # endif #elif defined(__MACOS__) # include typedef SInt16 ogg_int16_t; typedef UInt16 ogg_uint16_t; typedef SInt32 ogg_int32_t; typedef UInt32 ogg_uint32_t; typedef SInt64 ogg_int64_t; #elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ # include typedef int16_t ogg_int16_t; typedef uint16_t ogg_uint16_t; typedef int32_t ogg_int32_t; typedef uint32_t ogg_uint32_t; typedef int64_t ogg_int64_t; #elif defined(__HAIKU__) /* Haiku */ # include typedef short ogg_int16_t; typedef unsigned short ogg_uint16_t; typedef int ogg_int32_t; typedef unsigned int ogg_uint32_t; typedef long long ogg_int64_t; #elif defined(__BEOS__) /* Be */ # include typedef int16_t ogg_int16_t; typedef uint16_t ogg_uint16_t; typedef int32_t ogg_int32_t; typedef uint32_t ogg_uint32_t; typedef int64_t ogg_int64_t; #elif defined (__EMX__) /* OS/2 GCC */ typedef short ogg_int16_t; typedef unsigned short ogg_uint16_t; typedef int ogg_int32_t; typedef unsigned int ogg_uint32_t; typedef long long ogg_int64_t; #elif defined (DJGPP) /* DJGPP */ typedef short ogg_int16_t; typedef int ogg_int32_t; typedef unsigned int ogg_uint32_t; typedef long long ogg_int64_t; #elif defined(R5900) /* PS2 EE */ typedef long ogg_int64_t; typedef int ogg_int32_t; typedef unsigned ogg_uint32_t; typedef short ogg_int16_t; #elif defined(__SYMBIAN32__) /* Symbian GCC */ typedef signed short ogg_int16_t; typedef unsigned short ogg_uint16_t; typedef signed int ogg_int32_t; typedef unsigned int ogg_uint32_t; typedef long long int ogg_int64_t; #elif defined(__TMS320C6X__) /* TI C64x compiler */ typedef signed short ogg_int16_t; typedef unsigned short ogg_uint16_t; typedef signed int ogg_int32_t; typedef unsigned int ogg_uint32_t; typedef long long int ogg_int64_t; #else # include "config_types.h" #endif #endif /* _OS_TYPES_H */ mednafen/tremor/ivorbisfile.h000664 001750 001750 00000010466 12611054044 017461 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: stdio-based convenience library for opening/seeking/decoding ********************************************************************/ #ifndef _OV_FILE_H_ #define _OV_FILE_H_ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #include #include "ivorbiscodec.h" #define CHUNKSIZE 1024 /* The function prototypes for the callbacks are basically the same as for * the stdio functions fread, fseek, fclose, ftell. * The one difference is that the FILE * arguments have been replaced with * a void * - this is to be used as a pointer to whatever internal data these * functions might need. In the stdio case, it's just a FILE * cast to a void * * * If you use other functions, check the docs for these functions and return * the right values. For seek_func(), you *MUST* return -1 if the stream is * unseekable */ typedef struct { size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); int (*close_func) (void *datasource); long (*tell_func) (void *datasource); } ov_callbacks; #define NOTOPEN 0 #define PARTOPEN 1 #define OPENED 2 #define STREAMSET 3 #define INITSET 4 typedef struct OggVorbis_File { void *datasource; /* Pointer to a FILE *, etc. */ int seekable; ogg_int64_t offset; ogg_int64_t end; ogg_sync_state oy; /* If the FILE handle isn't seekable (eg, a pipe), only the current stream appears */ int links; ogg_int64_t *offsets; ogg_int64_t *dataoffsets; ogg_uint32_t *serialnos; ogg_int64_t *pcmlengths; vorbis_info *vi; vorbis_comment *vc; /* Decoding working state local storage */ ogg_int64_t pcm_offset; int ready_state; ogg_uint32_t current_serialno; int current_link; ogg_int64_t bittrack; ogg_int64_t samptrack; ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */ vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ vorbis_block vb; /* local working space for packet->PCM decode */ ov_callbacks callbacks; } OggVorbis_File; extern int ov_clear(OggVorbis_File *vf); extern int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes); extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks); extern long ov_bitrate(OggVorbis_File *vf,int i); extern long ov_bitrate_instant(OggVorbis_File *vf); extern long ov_streams(OggVorbis_File *vf); extern long ov_seekable(OggVorbis_File *vf); extern long ov_serialnumber(OggVorbis_File *vf,int i); extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i); extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i); extern ogg_int64_t ov_time_total(OggVorbis_File *vf,int i); extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos); extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos); extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos); extern int ov_time_seek(OggVorbis_File *vf,ogg_int64_t pos); extern int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t pos); extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf); extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf); extern vorbis_info *ov_info(OggVorbis_File *vf,int link); extern long ov_read(OggVorbis_File *vf,char *buffer,int length, int *bitstream); #ifdef __cplusplus } #endif /* __cplusplus */ #endif beetle_psx_griffin_c.c000664 001750 001750 00000001710 12611054044 016202 0ustar00sergiosergio000000 000000 #include "mednafen/tremor/codebook.c" #include "mednafen/tremor/floor0.c" #include "mednafen/tremor/floor1.c" #include "mednafen/tremor/mdct.c" #include "mednafen/tremor/registry.c" #include "mednafen/tremor/mapping0.c" #include "mednafen/tremor/info.c" #include "mednafen/tremor/res012.c" #include "mednafen/tremor/framing.c" #include "mednafen/tremor/block.c" #include "mednafen/tremor/sharedbook.c" #include "mednafen/tremor/synthesis.c" #include "mednafen/tremor/vorbisfile.c" #include "mednafen/tremor/bitwise.c" #include "mednafen/tremor/window.c" #include "mednafen/file.c" #include "mednafen/mednafen-endian.c" #include "mednafen/trio/trio.c" #include "mednafen/trio/triostr.c" #include "threads.c" #include "scrc32.c" #ifdef NEED_CD #include "mednafen/cdrom/CDUtility.c" #include "mednafen/cdrom/edc_crc32.c" #include "mednafen/cdrom/l-ec.c" #include "mednafen/cdrom/lec.c" #include "mednafen/cdrom/recover-raw.c" #include "mednafen/cdrom/galois.c" #endif libretro-common/include/rthreads/rthreads.h000664 001750 001750 00000012340 12611054044 022233 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rthreads.h). * --------------------------------------------------------------------------------------- * * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_RTHREADS_H__ #define __LIBRETRO_SDK_RTHREADS_H__ #include #include #include #include #if defined(__cplusplus) && !defined(_MSC_VER) extern "C" { #endif typedef struct sthread sthread_t; typedef struct slock slock_t; typedef struct scond scond_t; /** * sthread_create: * @start_routine : thread entry callback function * @userdata : pointer to userdata that will be made * available in thread entry callback function * * Create a new thread. * * Returns: pointer to new thread if successful, otherwise NULL. */ sthread_t *sthread_create(void (*thread_func)(void*), void *userdata); /** * sthread_detach: * @thread : pointer to thread object * * Detach a thread. When a detached thread terminates, its * resource sare automatically released back to the system * without the need for another thread to join with the * terminated thread. * * Returns: 0 on success, otherwise it returns a non-zero error number. */ int sthread_detach(sthread_t *thread); /** * sthread_join: * @thread : pointer to thread object * * Join with a terminated thread. Waits for the thread specified by * @thread to terminate. If that thread has already terminated, then * it will return immediately. The thread specified by @thread must * be joinable. * * Returns: 0 on success, otherwise it returns a non-zero error number. */ void sthread_join(sthread_t *thread); /** * slock_new: * * Create and initialize a new mutex. Must be manually * freed. * * Returns: pointer to a new mutex if successful, otherwise NULL. **/ slock_t *slock_new(void); /** * slock_free: * @lock : pointer to mutex object * * Frees a mutex. **/ void slock_free(slock_t *lock); /** * slock_lock: * @lock : pointer to mutex object * * Locks a mutex. If a mutex is already locked by * another thread, the calling thread shall block until * the mutex becomes available. **/ void slock_lock(slock_t *lock); /** * slock_unlock: * @lock : pointer to mutex object * * Unlocks a mutex. **/ void slock_unlock(slock_t *lock); /** * scond_new: * * Creates and initializes a condition variable. Must * be manually freed. * * Returns: pointer to new condition variable on success, * otherwise NULL. **/ scond_t *scond_new(void); /** * scond_free: * @cond : pointer to condition variable object * * Frees a condition variable. **/ void scond_free(scond_t *cond); /** * scond_wait: * @cond : pointer to condition variable object * @lock : pointer to mutex object * * Block on a condition variable (i.e. wait on a condition). **/ void scond_wait(scond_t *cond, slock_t *lock); /** * scond_wait_timeout: * @cond : pointer to condition variable object * @lock : pointer to mutex object * @timeout_us : timeout (in microseconds) * * Try to block on a condition variable (i.e. wait on a condition) until * @timeout_us elapses. * * Returns: false (0) if timeout elapses before condition variable is * signaled or broadcast, otherwise true (1). **/ bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us); /** * scond_broadcast: * @cond : pointer to condition variable object * * Broadcast a condition. Unblocks all threads currently blocked * on the specified condition variable @cond. **/ int scond_broadcast(scond_t *cond); /** * scond_signal: * @cond : pointer to condition variable object * * Signal a condition. Unblocks at least one of the threads currently blocked * on the specified condition variable @cond. **/ void scond_signal(scond_t *cond); #if defined(__cplusplus) && !defined(_MSC_VER) } #endif #endif mednafen/settings.cpp000755 001750 001750 00000012213 12611054044 016020 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include #include #include #include "mednafen.h" #include "settings.h" int setting_initial_scanline = 0; int setting_initial_scanline_pal = 0; int setting_last_scanline = 239; int setting_last_scanline_pal = 287; uint32_t setting_psx_multitap_port_1 = 0; uint32_t setting_psx_multitap_port_2 = 0; uint32_t setting_psx_analog_toggle = 0; uint32_t setting_psx_fastboot = 1; extern char retro_cd_base_name[4096]; extern char retro_save_directory[4096]; extern char retro_base_directory[4096]; bool MDFN_SaveSettings(const char *path) { return(1); } uint64_t MDFN_GetSettingUI(const char *name) { if (!strcmp("psx.spu.resamp_quality", name)) /* make configurable */ return 4; fprintf(stderr, "unhandled setting UI: %s\n", name); return 0; } int64 MDFN_GetSettingI(const char *name) { if (!strcmp("psx.region_default", name)) /* make configurable */ return 1; /* REGION_JP = 0, REGION_NA = 1, REGION_EU = 2 */ if (!strcmp("psx.slstart", name)) return setting_initial_scanline; if (!strcmp("psx.slstartp", name)) return setting_initial_scanline_pal; if (!strcmp("psx.slend", name)) return setting_last_scanline; if (!strcmp("psx.slendp", name)) return setting_last_scanline_pal; fprintf(stderr, "unhandled setting I: %s\n", name); return 0; } double MDFN_GetSettingF(const char *name) { if (!strcmp("psx.input.mouse_sensitivity", name)) return 1.00; /* TODO - make configurable */ fprintf(stderr, "unhandled setting F: %s\n", name); return 0; } bool MDFN_GetSettingB(const char *name) { if (!strcmp("cheats", name)) return 0; /* LIBRETRO */ if (!strcmp("libretro.cd_load_into_ram", name)) return 0; if (!strcmp("psx.input.port1.memcard", name)) return 1; if (!strcmp("psx.input.port2.memcard", name)) return 1; if (!strcmp("psx.input.port3.memcard", name)) return 1; if (!strcmp("psx.input.port4.memcard", name)) return 1; if (!strcmp("psx.input.port5.memcard", name)) return 1; if (!strcmp("psx.input.port6.memcard", name)) return 1; if (!strcmp("psx.input.port7.memcard", name)) return 1; if (!strcmp("psx.input.port8.memcard", name)) return 1; if (!strcmp("psx.input.pport1.multitap", name)) /* make configurable */ return setting_psx_multitap_port_1; if (!strcmp("psx.input.pport2.multitap", name)) /* make configurable */ return setting_psx_multitap_port_2; if (!strcmp("psx.region_autodetect", name)) /* make configurable */ return 1; if (!strcmp("psx.input.analog_mode_ct", name)) /* make configurable */ return setting_psx_analog_toggle; if (!strcmp("psx.fastboot", name)) return setting_psx_fastboot; /* CDROM */ if (!strcmp("cdrom.lec_eval", name)) return 1; /* FILESYS */ if (!strcmp("filesys.untrusted_fip_check", name)) return 0; if (!strcmp("filesys.disablesavegz", name)) return 1; fprintf(stderr, "unhandled setting B: %s\n", name); return 0; } std::string MDFN_GetSettingS(const char *name) { if (!strcmp("psx.bios_eu", name)) return std::string("scph5502.bin"); if (!strcmp("psx.bios_jp", name)) return std::string("scph5500.bin"); if (!strcmp("psx.bios_na", name)) return std::string("scph5501.bin"); if (!strcmp("psx.region_default", name)) /* make configurable */ return "na"; /* FILESYS */ if (!strcmp("filesys.path_firmware", name)) return std::string(retro_base_directory); if (!strcmp("filesys.path_sav", name)) return std::string(retro_save_directory); if (!strcmp("filesys.path_state", name)) return std::string(retro_save_directory); if (!strcmp("filesys.fname_state", name)) { char fullpath[4096]; snprintf(fullpath, sizeof(fullpath), "%s.sav", retro_cd_base_name); return std::string(fullpath); } if (!strcmp("filesys.fname_sav", name)) { char fullpath[4096]; snprintf(fullpath, sizeof(fullpath), "%s.bsv", retro_cd_base_name); return std::string(fullpath); } fprintf(stderr, "unhandled setting S: %s\n", name); return 0; } bool MDFNI_SetSetting(const char *name, const char *value, bool NetplayOverride) { return false; } bool MDFNI_SetSettingB(const char *name, bool value) { return false; } bool MDFNI_SetSettingUI(const char *name, uint64_t value) { return false; } bool MDFNI_DumpSettingsDef(const char *path) { return true; } mednafen/psx/input/memcard.cpp000664 001750 001750 00000031572 12611054044 017551 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ // I could find no other commands than 'R', 'W', and 'S' (not sure what 'S' is for, however) #include "../psx.h" #include "../frontio.h" #include "memcard.h" class InputDevice_Memcard : public InputDevice { public: InputDevice_Memcard(); virtual ~InputDevice_Memcard(); virtual void Power(void); virtual int StateAction(StateMem* sm, int load, int data_only, const char* section_name); // // // virtual void SetDTR(bool new_dtr); virtual bool GetDSR(void); virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); // // virtual uint8 *GetNVData(void); virtual uint32 GetNVSize(void); virtual void ReadNV(uint8 *buffer, uint32 offset, uint32 size); virtual void WriteNV(const uint8 *buffer, uint32 offset, uint32 size); virtual uint64 GetNVDirtyCount(void); virtual void ResetNVDirtyCount(void); private: void Format(void); bool presence_new; uint8 card_data[1 << 17]; uint8 rw_buffer[128]; uint8 write_xor; // // Used to avoid saving unused memory cards' card data in save states. // Set to false on object initialization, set to true when data is written to card_data that differs // from existing data(either from loading a memory card saved to disk, or from a game writing to the memory card). // // Save and load its state to/from save states. // bool data_used; // // Do not save dirty_count in save states! // uint64 dirty_count; bool dtr; int32 command_phase; uint32 bitpos; uint8 receive_buffer; uint8 command; uint16 addr; uint8 calced_xor; uint8 transmit_buffer; uint32 transmit_count; }; void InputDevice_Memcard::Format(void) { memset(card_data, 0x00, sizeof(card_data)); card_data[0x00] = 0x4D; card_data[0x01] = 0x43; card_data[0x7F] = 0x0E; for(unsigned int A = 0x80; A < 0x800; A += 0x80) { card_data[A + 0x00] = 0xA0; card_data[A + 0x08] = 0xFF; card_data[A + 0x09] = 0xFF; card_data[A + 0x7F] = 0xA0; } for(unsigned int A = 0x0800; A < 0x1200; A += 0x80) { card_data[A + 0x00] = 0xFF; card_data[A + 0x01] = 0xFF; card_data[A + 0x02] = 0xFF; card_data[A + 0x03] = 0xFF; card_data[A + 0x08] = 0xFF; card_data[A + 0x09] = 0xFF; } } InputDevice_Memcard::InputDevice_Memcard() { Power(); data_used = false; dirty_count = 0; // Init memcard as formatted. assert(sizeof(card_data) == (1 << 17)); Format(); } InputDevice_Memcard::~InputDevice_Memcard() { } void InputDevice_Memcard::Power(void) { dtr = 0; //buttons[0] = buttons[1] = 0; command_phase = 0; bitpos = 0; receive_buffer = 0; command = 0; transmit_buffer = 0; transmit_count = 0; addr = 0; presence_new = true; } int InputDevice_Memcard::StateAction(StateMem* sm, int load, int data_only, const char* section_name) { // Don't save dirty_count. SFORMAT StateRegs[] = { SFVAR(presence_new), SFARRAY(rw_buffer, sizeof(rw_buffer)), SFVAR(write_xor), SFVAR(dtr), SFVAR(command_phase), SFVAR(bitpos), SFVAR(receive_buffer), SFVAR(command), SFVAR(addr), SFVAR(calced_xor), SFVAR(transmit_buffer), SFVAR(transmit_count), SFVAR(data_used), SFEND }; SFORMAT CD_StateRegs[] = { SFARRAY(card_data, sizeof(card_data)), SFEND }; int ret = 1; if(MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name) != 0) { //printf("%s data_used=%d\n", section_name, data_used); if(data_used) { std::string tmp_name = std::string(section_name) + "_DT"; ret &= MDFNSS_StateAction(sm, load, data_only, CD_StateRegs, tmp_name.c_str()); } if(load) { if(data_used) dirty_count++; } } else ret = 0; return(ret); } void InputDevice_Memcard::SetDTR(bool new_dtr) { if(!dtr && new_dtr) { command_phase = 0; bitpos = 0; transmit_count = 0; } else if(dtr && !new_dtr) { if(command_phase > 0) PSX_WARNING("[MCR] Communication aborted???"); } dtr = new_dtr; } bool InputDevice_Memcard::GetDSR(void) { if(!dtr) return(0); if(!bitpos && transmit_count) return(1); return(0); } bool InputDevice_Memcard::Clock(bool TxD, int32 &dsr_pulse_delay) { bool ret = 1; dsr_pulse_delay = 0; if(!dtr) return(1); if(transmit_count) ret = (transmit_buffer >> bitpos) & 1; receive_buffer &= ~(1 << bitpos); receive_buffer |= TxD << bitpos; bitpos = (bitpos + 1) & 0x7; if(!bitpos) { //if(command_phase > 0 || transmit_count) // printf("[MCRDATA] Received_data=0x%02x, Sent_data=0x%02x\n", receive_buffer, transmit_buffer); if(transmit_count) { transmit_count--; } if (command_phase >= 1024 && command_phase <= 1151) { // Transmit actual 128 bytes data transmit_buffer = card_data[(addr << 7) + (command_phase - 1024)]; calced_xor ^= transmit_buffer; transmit_count = 1; command_phase++; } else if (command_phase >= 2048 && command_phase <= 2175) { calced_xor ^= receive_buffer; rw_buffer[command_phase - 2048] = receive_buffer; transmit_buffer = receive_buffer; transmit_count = 1; command_phase++; } else switch(command_phase) { case 0: if(receive_buffer != 0x81) command_phase = -1; else { //printf("[MCR] Device selected\n"); transmit_buffer = presence_new ? 0x08 : 0x00; transmit_count = 1; command_phase++; } break; case 1: command = receive_buffer; //printf("[MCR] Command received: %c\n", command); if(command == 'R' || command == 'W') { command_phase++; transmit_buffer = 0x5A; transmit_count = 1; } else { if(command == 'S') { PSX_WARNING("[MCR] Memcard S command unsupported."); } command_phase = -1; transmit_buffer = 0; transmit_count = 0; } break; case 2: transmit_buffer = 0x5D; transmit_count = 1; command_phase++; break; case 3: transmit_buffer = 0x00; transmit_count = 1; if(command == 'R') command_phase = 1000; else if(command == 'W') command_phase = 2000; break; // // Read // case 1000: addr = receive_buffer << 8; transmit_buffer = receive_buffer; transmit_count = 1; command_phase++; break; case 1001: addr |= receive_buffer & 0xFF; transmit_buffer = '\\'; transmit_count = 1; command_phase++; break; case 1002: //printf("[MCR] READ ADDR=0x%04x\n", addr); if(addr >= (sizeof(card_data) >> 7)) addr = 0xFFFF; calced_xor = 0; transmit_buffer = ']'; transmit_count = 1; command_phase++; // TODO: enable this code(or something like it) when CPU instruction timing is a bit better. // //dsr_pulse_delay = 32000; //goto SkipDPD; // break; case 1003: transmit_buffer = addr >> 8; calced_xor ^= transmit_buffer; transmit_count = 1; command_phase++; break; case 1004: transmit_buffer = addr & 0xFF; calced_xor ^= transmit_buffer; if(addr == 0xFFFF) { transmit_count = 1; command_phase = -1; } else { transmit_count = 1; command_phase = 1024; } break; // XOR case (1024 + 128): transmit_buffer = calced_xor; transmit_count = 1; command_phase++; break; // End flag case (1024 + 129): transmit_buffer = 'G'; transmit_count = 1; command_phase = -1; break; // // Write // case 2000: calced_xor = receive_buffer; addr = receive_buffer << 8; transmit_buffer = receive_buffer; transmit_count = 1; command_phase++; break; case 2001: calced_xor ^= receive_buffer; addr |= receive_buffer & 0xFF; //printf("[MCR] WRITE ADDR=0x%04x\n", addr); transmit_buffer = receive_buffer; transmit_count = 1; command_phase = 2048; break; case (2048 + 128): // XOR write_xor = receive_buffer; transmit_buffer = '\\'; transmit_count = 1; command_phase++; break; case (2048 + 129): transmit_buffer = ']'; transmit_count = 1; command_phase++; break; case (2048 + 130): // End flag //MDFN_DispMessage("%02x %02x", calced_xor, write_xor); //printf("[MCR] Write End. Actual_XOR=0x%02x, CW_XOR=0x%02x\n", calced_xor, write_xor); if(calced_xor != write_xor) transmit_buffer = 'N'; else if(addr >= (sizeof(card_data) >> 7)) transmit_buffer = 0xFF; else { transmit_buffer = 'G'; presence_new = false; // If the current data is different from the data to be written, increment the dirty count. // memcpy()'ing over to card_data is also conditionalized here for a slight optimization. if(memcmp(&card_data[addr << 7], rw_buffer, 128)) { memcpy(&card_data[addr << 7], rw_buffer, 128); dirty_count++; data_used = true; } } transmit_count = 1; command_phase = -1; break; } //if(command_phase != -1 || transmit_count) // printf("[MCR] Receive: 0x%02x, Send: 0x%02x -- %d\n", receive_buffer, transmit_buffer, command_phase); } if(!bitpos && transmit_count) dsr_pulse_delay = 0x100; //SkipDPD: ; return(ret); } uint8 *InputDevice_Memcard::GetNVData(void) { return card_data; } uint32 InputDevice_Memcard::GetNVSize(void) { return(sizeof(card_data)); } void InputDevice_Memcard::ReadNV(uint8 *buffer, uint32 offset, uint32 size) { while(size--) { *buffer = card_data[offset & (sizeof(card_data) - 1)]; buffer++; offset++; } } void InputDevice_Memcard::WriteNV(const uint8 *buffer, uint32 offset, uint32 size) { if(size) { dirty_count++; } while(size--) { if(card_data[offset & (sizeof(card_data) - 1)] != *buffer) data_used = true; card_data[offset & (sizeof(card_data) - 1)] = *buffer; buffer++; offset++; } } uint64 InputDevice_Memcard::GetNVDirtyCount(void) { return(dirty_count); } void InputDevice_Memcard::ResetNVDirtyCount(void) { dirty_count = 0; } InputDevice *Device_Memcard_Create(void) { return new InputDevice_Memcard(); } mednafen/cdrom/SimpleFIFO.cpp000664 001750 001750 00000000065 12611054044 017162 0ustar00sergiosergio000000 000000 #include "../mednafen.h" #include "SimpleFIFO.h" mednafen/cdrom/recover-raw.h000664 001750 001750 00000000740 12611054044 017166 0ustar00sergiosergio000000 000000 #ifndef _RECOVER_RAW_H #define _RECOVER_RAW_H #include #include #ifdef __cplusplus extern "C" { #endif #define CD_RAW_SECTOR_SIZE 2352 #define CD_RAW_C2_SECTOR_SIZE (2352+294) /* main channel plus C2 vector */ int CheckEDC(const unsigned char *a, bool b); int CheckMSF(unsigned char *a, int b); int ValidateRawSector(unsigned char *frame, bool xaMode); bool Init_LEC_Correct(void); void Kill_LEC_Correct(void); #ifdef __cplusplus } #endif #endif Makefile.common000664 001750 001750 00000006524 12611054044 014635 0ustar00sergiosergio000000 000000 SOURCES_CXX := SOURCES_C := LIBRETRO_DIR := $(CORE_DIR)/libretro-common MEDNAFEN_DIR := $(CORE_DIR)/mednafen CORE_EMU_DIR := $(MEDNAFEN_DIR)/psx INCFLAGS := -I$(CORE_DIR) -I$(MEDNAFEN_DIR) -I$(MEDNAFEN_DIR)/include -I$(MEDNAFEN_DIR)/intl -I$(MEDNAFEN_DIR)/hw_sound -I$(MEDNAFEN_DIR)/hw_cpu -I$(MEDNAFEN_DIR)/hw_misc -I$(LIBRETRO_DIR)/include ifeq ($(HAVE_GRIFFIN),1) SOURCES_CXX += beetle_psx_griffin.cpp \ $(CORE_EMU_DIR)/dma.cpp \ $(CORE_EMU_DIR)/sio.cpp else SOURCES_CXX += $(CORE_EMU_DIR)/irq.cpp \ $(CORE_EMU_DIR)/timer.cpp \ $(CORE_EMU_DIR)/dma.cpp \ $(CORE_EMU_DIR)/frontio.cpp \ $(CORE_EMU_DIR)/sio.cpp \ $(CORE_EMU_DIR)/cpu.cpp \ $(CORE_EMU_DIR)/gte.cpp \ $(CORE_EMU_DIR)/cdc.cpp \ $(CORE_EMU_DIR)/spu.cpp \ $(CORE_EMU_DIR)/gpu.cpp \ $(CORE_EMU_DIR)/mdec.cpp \ $(CORE_EMU_DIR)/input/gamepad.cpp \ $(CORE_EMU_DIR)/input/dualanalog.cpp \ $(CORE_EMU_DIR)/input/dualshock.cpp \ $(CORE_EMU_DIR)/input/justifier.cpp \ $(CORE_EMU_DIR)/input/guncon.cpp \ $(CORE_EMU_DIR)/input/negcon.cpp \ $(CORE_EMU_DIR)/input/memcard.cpp \ $(CORE_EMU_DIR)/input/multitap.cpp \ $(CORE_EMU_DIR)/input/mouse.cpp endif ifeq ($(DEBUG), 1) SOURCES_CXX += \ $(CORE_EMU_DIR)/dis.cpp endif ifeq ($(NEED_THREADING), 1) FLAGS += -DWANT_THREADING endif ifeq ($(NEED_CRC32), 1) FLAGS += -DWANT_CRC32 SOURCES_C += $(CORE_DIR)/scrc32.c endif ifeq ($(NEED_DEINTERLACER), 1) FLAGS += -DNEED_DEINTERLACER endif ifeq ($(IS_X86), 1) FLAGS += -DARCH_X86 endif ifeq ($(NEED_BPP), 8) FLAGS += -DWANT_8BPP endif ifeq ($(NEED_BPP), 16) FLAGS += -DWANT_16BPP endif ifeq ($(NEED_BPP), 32) FLAGS += -DWANT_32BPP endif ifeq ($(WANT_NEW_API), 1) FLAGS += -DWANT_NEW_API endif ifeq ($(NO_COMPUTED_GOTO), 1) FLAGS += -DNO_COMPUTED_GOTO endif ifeq ($(FRONTEND_SUPPORTS_RGB565), 1) FLAGS += -DFRONTEND_SUPPORTS_RGB565 endif ifeq ($(NEED_CD), 1) ifneq ($(HAVE_GRIFFIN),1) SOURCES_CXX += $(MEDNAFEN_DIR)/cdrom/CDAccess.cpp \ $(MEDNAFEN_DIR)/cdrom/CDAccess_Image.cpp \ $(MEDNAFEN_DIR)/cdrom/CDAccess_CCD.cpp \ $(MEDNAFEN_DIR)/cdrom/SimpleFIFO.cpp \ $(MEDNAFEN_DIR)/cdrom/audioreader.cpp \ $(MEDNAFEN_DIR)/cdrom/misc.cpp \ $(MEDNAFEN_DIR)/cdrom/cdromif.cpp SOURCES_C += \ $(MEDNAFEN_DIR)/cdrom/CDUtility.c \ $(MEDNAFEN_DIR)/cdrom/galois.c \ $(MEDNAFEN_DIR)/cdrom/l-ec.c \ $(MEDNAFEN_DIR)/cdrom/lec.c \ $(MEDNAFEN_DIR)/cdrom/recover-raw.c \ $(MEDNAFEN_DIR)/cdrom/edc_crc32.c endif FLAGS += -DNEED_CD endif ifeq ($(NEED_TREMOR), 1) SOURCES_C += $(wildcard $(MEDNAFEN_DIR)/tremor/*.c) FLAGS += -DNEED_TREMOR endif ifneq ($(HAVE_GRIFFIN), 1) SOURCES_CXX += \ $(MEDNAFEN_DIR)/error.cpp \ $(MEDNAFEN_DIR)/settings.cpp \ $(MEDNAFEN_DIR)/general.cpp \ $(MEDNAFEN_DIR)/FileStream.cpp \ $(MEDNAFEN_DIR)/MemoryStream.cpp \ $(MEDNAFEN_DIR)/Stream.cpp \ $(MEDNAFEN_DIR)/state.cpp \ $(MEDNAFEN_DIR)/mempatcher.cpp \ $(MEDNAFEN_DIR)/video/Deinterlacer.cpp \ $(MEDNAFEN_DIR)/video/surface.cpp \ $(CORE_DIR)/libretro.cpp SOURCES_C += \ $(MEDNAFEN_DIR)/file.c \ $(MEDNAFEN_DIR)/md5.c \ $(MEDNAFEN_DIR)/mednafen-endian.c endif SOURCES_C += $(MEDNAFEN_DIR)/trio/trio.c \ $(MEDNAFEN_DIR)/trio/triostr.c ifeq ($(HAVE_GRIFFIN), 1) SOURCES_C += beetle_psx_griffin_c.c endif ifneq ($(STATIC_LINKING), 1) SOURCES_C += $(LIBRETRO_DIR)/file/retro_file.c \ $(LIBRETRO_DIR)/file/retro_stat.c ifeq ($(NEED_THREADING), 1) SOURCES_C += $(LIBRETRO_DIR)/rthreads/rthreads.c endif endif libretro-common/include/rthreads/000700 001750 001750 00000000000 12702525066 020242 5ustar00sergiosergio000000 000000 mednafen/cdrom/recover-raw.c000664 001750 001750 00000012507 12611054044 017165 0ustar00sergiosergio000000 000000 /* dvdisaster: Additional error correction for optical media. * Copyright (C) 2004-2007 Carsten Gnoerlich. * Project home page: http://www.dvdisaster.com * Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org * * 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, * or direct your browser at http://www.gnu.org. */ #include #include #include "recover-raw.h" #include "l-ec.h" #include "edc_crc32.h" #include "galois.h" static GaloisTables *gt = NULL; /* for L-EC Reed-Solomon */ static ReedSolomonTables *rt = NULL; bool Init_LEC_Correct(void) { gt = CreateGaloisTables(0x11d); rt = CreateReedSolomonTables(gt, 0, 1, 10); return(1); } void Kill_LEC_Correct(void) { FreeGaloisTables(gt); FreeReedSolomonTables(rt); } /*** *** CD level CRC calculation ***/ /* * Test raw sector against its 32bit CRC. * Returns TRUE if frame is good. */ int CheckEDC(const unsigned char *cd_frame, bool xa_mode) { unsigned int expected_crc, real_crc; unsigned int crc_base = xa_mode ? 2072 : 2064; expected_crc = cd_frame[crc_base + 0] << 0; expected_crc |= cd_frame[crc_base + 1] << 8; expected_crc |= cd_frame[crc_base + 2] << 16; expected_crc |= cd_frame[crc_base + 3] << 24; if(xa_mode) real_crc = EDCCrc32(cd_frame+16, 2056); else real_crc = EDCCrc32(cd_frame, 2064); if(expected_crc == real_crc) return(1); //printf("Bad EDC CRC: Calculated: %08x, Recorded: %08x\n", real_crc, expected_crc); return(0); } /*** *** A very simple L-EC error correction. *** * Perform just one pass over the Q and P vectors to see if everything * is okay respectively correct minor errors. This is pretty much the * same stuff the drive is supposed to do in the final L-EC stage. */ static int simple_lec(unsigned char *frame) { unsigned char byte_state[2352]; unsigned char p_vector[P_VECTOR_SIZE]; unsigned char q_vector[Q_VECTOR_SIZE]; unsigned char p_state[P_VECTOR_SIZE]; int erasures[Q_VECTOR_SIZE], erasure_count; int ignore[2]; int p_failures, q_failures; int p_corrected, q_corrected; int p,q; /* Setup */ memset(byte_state, 0, 2352); p_failures = q_failures = 0; p_corrected = q_corrected = 0; /* Perform Q-Parity error correction */ for(q=0; q 2) { GetPVector(byte_state, p_state, p); erasure_count = 0; for(i=0; i 0 && erasure_count <= 2) { GetPVector(frame, p_vector, p); err = DecodePQ(rt, p_vector, P_PADDING, erasures, erasure_count); } } /* See what we've got */ if(err < 0) /* Uncorrectable. */ p_failures++; else /* Correctable. */ { if(err == 1 || err == 2) /* Store back corrected vector */ { SetPVector(frame, p_vector, p); p_corrected++; } } } /* Sum up */ if(q_failures || p_failures || q_corrected || p_corrected) return 1; return 0; } /*** *** Validate CD raw sector ***/ int ValidateRawSector(unsigned char *frame, bool xaMode) { int lec_did_sth = false; /* Do simple L-EC. It seems that drives stop their internal L-EC as soon as the EDC is okay, so we may see uncorrected errors in the parity bytes. Since we are also interested in the user data only and doing the L-EC is expensive, we skip our L-EC as well when the EDC is fine. */ if(!CheckEDC(frame, xaMode)) lec_did_sth = simple_lec(frame); /* Test internal sector checksum again */ /* EDC failure in RAW sector */ if(!CheckEDC(frame, xaMode)) return false; return true; } mednafen/psx/spu.h000664 001750 001750 00000016562 12611054044 015260 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_SPU_H #define __MDFN_PSX_SPU_H extern uint32_t IntermediateBufferPos; extern int16_t IntermediateBuffer[4096][2]; enum { ADSR_ATTACK = 0, ADSR_DECAY = 1, ADSR_SUSTAIN = 2, ADSR_RELEASE = 3 }; // Buffers 44.1KHz samples, should have enough for two(worst-case scenario) video frames(2* ~735 frames NTSC, 2* ~882 PAL) plus jitter plus enough for the resampler leftovers. // We'll just go with 4096 because powers of 2 are AWESOME and such. struct SPU_ADSR { uint16_t EnvLevel; // We typecast it to (int16) in several places, but keep it here as (uint16) to prevent signed overflow/underflow, which compilers // may not treat consistently. uint32_t Divider; uint32_t Phase; bool AttackExp; bool SustainExp; bool SustainDec; bool ReleaseExp; int32_t AttackRate; // Ar int32_t DecayRate; // Dr * 4 int32_t SustainRate; // Sr int32_t ReleaseRate; // Rr * 4 int32_t SustainLevel; // (Sl + 1) << 11 }; class PS_SPU; class SPU_Sweep { friend class PS_SPU; // For save states - FIXME(remove in future?) public: SPU_Sweep() { } ~SPU_Sweep() { } void Power(void); void WriteControl(uint16_t value); int16 ReadVolume(void); void WriteVolume(int16 value); void Clock(void); private: uint16_t Control; uint16_t Current; uint32_t Divider; }; struct SPU_Voice { int16 DecodeBuffer[0x20]; int16 DecodeM2; int16 DecodeM1; uint32 DecodePlayDelay; uint32 DecodeWritePos; uint32 DecodeReadPos; uint32 DecodeAvail; bool IgnoreSampLA; uint8 DecodeShift; uint8 DecodeWeight; uint8_t DecodeFlags; SPU_Sweep Sweep[2]; uint16_t Pitch; uint32_t CurPhase; uint32_t StartAddr; uint32_t CurAddr; uint32_t ADSRControl; uint32_t LoopAddr; int32_t PreLRSample; // After enveloping, but before L/R volume. Range of -32768 to 32767 SPU_ADSR ADSR; }; class PS_SPU { public: PS_SPU(); ~PS_SPU(); int StateAction(StateMem *sm, int load, int data_only); void Power(void); void Write(int32_t timestamp, uint32_t A, uint16_t V); uint16_t Read(int32_t timestamp, uint32_t A); void WriteDMA(uint32_t V); uint32_t ReadDMA(void); int32_t UpdateFromCDC(int32_t clocks); private: void CheckIRQAddr(uint32_t addr); void WriteSPURAM(uint32_t addr, uint16_t value); uint16_t ReadSPURAM(uint32_t addr); void RunDecoder(SPU_Voice *voice); void CacheEnvelope(SPU_Voice *voice); void ResetEnvelope(SPU_Voice *voice); void ReleaseEnvelope(SPU_Voice *voice); void RunEnvelope(SPU_Voice *voice); void RunReverb(const int32* in, int32* out); void RunNoise(void); bool GetCDAudio(int32_t &l, int32_t &r); SPU_Voice Voices[24]; uint32_t NoiseDivider; uint32_t NoiseCounter; uint16_t LFSR; uint32_t FM_Mode; uint32_t Noise_Mode; uint32_t Reverb_Mode; uint32_t ReverbWA; SPU_Sweep GlobalSweep[2]; // Doesn't affect reverb volume! int32_t ReverbVol[2]; int32_t CDVol[2]; int32_t ExternVol[2]; uint32_t IRQAddr; uint32_t RWAddr; uint16_t SPUControl; uint32_t VoiceOn; uint32_t VoiceOff; uint32_t BlockEnd; uint32_t CWA; union { uint16_t Regs[0x100]; struct { uint16_t VoiceRegs[0xC0]; union { uint16_t GlobalRegs[0x20]; struct { uint16_t _Global0[0x17]; uint16_t SPUStatus; uint16_t _Global1[0x08]; }; }; union { uint16 ReverbRegs[0x20]; struct { uint16 FB_SRC_A; uint16 FB_SRC_B; int16 IIR_ALPHA; int16 ACC_COEF_A; int16 ACC_COEF_B; int16 ACC_COEF_C; int16 ACC_COEF_D; int16 IIR_COEF; int16 FB_ALPHA; int16 FB_X; uint16 IIR_DEST_A0; uint16 IIR_DEST_A1; uint16 ACC_SRC_A0; uint16 ACC_SRC_A1; uint16 ACC_SRC_B0; uint16 ACC_SRC_B1; uint16 IIR_SRC_A0; uint16 IIR_SRC_A1; uint16 IIR_DEST_B0; uint16 IIR_DEST_B1; uint16 ACC_SRC_C0; uint16 ACC_SRC_C1; uint16 ACC_SRC_D0; uint16 ACC_SRC_D1; uint16 IIR_SRC_B1; uint16 IIR_SRC_B0; uint16 MIX_DEST_A0; uint16 MIX_DEST_A1; uint16 MIX_DEST_B0; uint16 MIX_DEST_B1; int16 IN_COEF_L; int16 IN_COEF_R; }; }; }; }; uint16_t AuxRegs[0x10]; int16 RDSB[2][128]; // [40] int16 RUSB[2][64]; int32_t RvbResPos; uint32_t ReverbCur; uint32_t Get_Reverb_Offset(uint32_t offset); int16 RD_RVB(uint16 raw_offs, int32 extra_offs = 0); void WR_RVB(uint16 raw_offs, int16 sample); bool IRQAsserted; int32_t clock_divider; uint16_t SPURAM[524288 / sizeof(uint16)]; int last_rate; uint32_t last_quality; public: enum { GSREG_SPUCONTROL = 0, GSREG_FM_ON, GSREG_NOISE_ON, GSREG_REVERB_ON, GSREG_CDVOL_L, GSREG_CDVOL_R, GSREG_MAINVOL_CTRL_L, GSREG_MAINVOL_CTRL_R, GSREG_MAINVOL_L, GSREG_MAINVOL_R, GSREG_RVBVOL_L, GSREG_RVBVOL_R, GSREG_RWADDR, GSREG_IRQADDR, GSREG_REVERBWA, GSREG_VOICEON, GSREG_VOICEOFF, GSREG_BLOCKEND, // Note: the order of these should match the reverb reg array GSREG_FB_SRC_A, GSREG_FB_SRC_B, GSREG_IIR_ALPHA, GSREG_ACC_COEF_A, GSREG_ACC_COEF_B, GSREG_ACC_COEF_C, GSREG_ACC_COEF_D, GSREG_IIR_COEF, GSREG_FB_ALPHA, GSREG_FB_X, GSREG_IIR_DEST_A0, GSREG_IIR_DEST_A1, GSREG_ACC_SRC_A0, GSREG_ACC_SRC_A1, GSREG_ACC_SRC_B0, GSREG_ACC_SRC_B1, GSREG_IIR_SRC_A0, GSREG_IIR_SRC_A1, GSREG_IIR_DEST_B0, GSREG_IIR_DEST_B1, GSREG_ACC_SRC_C0, GSREG_ACC_SRC_C1, GSREG_ACC_SRC_D0, GSREG_ACC_SRC_D1, GSREG_IIR_SRC_B1, GSREG_IIR_SRC_B0, GSREG_MIX_DEST_A0, GSREG_MIX_DEST_A1, GSREG_MIX_DEST_B0, GSREG_MIX_DEST_B1, GSREG_IN_COEF_L, GSREG_IN_COEF_R, // Multiply v * 256 for each extra voice GSREG_V0_VOL_CTRL_L = 0x8000, GSREG_V0_VOL_CTRL_R, GSREG_V0_VOL_L, GSREG_V0_VOL_R, GSREG_V0_PITCH, GSREG_V0_STARTADDR, GSREG_V0_ADSR_CTRL, GSREG_V0_ADSR_LEVEL, GSREG_V0_LOOP_ADDR, GSREG_V0_READ_ADDR }; uint32_t GetRegister(unsigned int which, char *special, const uint32_t special_len); void SetRegister(unsigned int which, uint32_t value); uint16_t PeekSPURAM(uint32_t address); void PokeSPURAM(uint32_t address, uint16_t value); }; #endif libretro-common/file/retro_file.c000664 001750 001750 00000022145 12611054044 020230 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_file.c). * --------------------------------------------------------------------------------------- * * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #if defined(_WIN32) # ifdef _MSC_VER # define setmode _setmode # endif # ifdef _XBOX # include # define INVALID_FILE_ATTRIBUTES -1 # else # include # include # include # include # endif #elif defined(VITA) # include # include #define PSP_O_RDONLY PSP2_O_RDONLY #define PSP_O_RDWR PSP2_O_RDWR #define PSP_O_CREAT PSP2_O_CREAT #define PSP_O_WRONLY PSP2_O_WRONLY #define PSP_O_TRUNC PSP2_O_TRUNC #else # if defined(PSP) # include # endif # include # include # include # include #endif #ifdef __CELLOS_LV2__ #include #else #include #endif #ifdef RARCH_INTERNAL #include #endif #include #if 1 #define HAVE_BUFFERED_IO 1 #endif struct RFILE { #if defined(PSP) || defined(VITA) SceUID fd; #elif defined(__CELLOS_LV2__) int fd; #elif defined(HAVE_BUFFERED_IO) FILE *fd; #else int fd; #endif }; int retro_get_fd(RFILE *stream) { if (!stream) return -1; #if defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) return stream->fd; #elif defined(HAVE_BUFFERED_IO) return fileno(stream->fd); #else return stream->fd; #endif } RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len) { int flags = 0; int mode_int = 0; const char *mode_str = NULL; RFILE *stream = (RFILE*)calloc(1, sizeof(*stream)); if (!stream) return NULL; (void)mode_str; (void)mode_int; (void)flags; switch (mode) { case RFILE_MODE_READ: #if defined(VITA) || defined(PSP) mode_int = 0777; flags = PSP_O_RDONLY; #elif defined(__CELLOS_LV2__) mode_int = 0777; flags = CELL_FS_O_RDONLY; #elif defined(HAVE_BUFFERED_IO) mode_str = "rb"; #else flags = O_RDONLY; #endif break; case RFILE_MODE_WRITE: #if defined(VITA) || defined(PSP) mode_int = 0777; flags = PSP_O_CREAT | PSP_O_WRONLY | PSP_O_TRUNC; #elif defined(__CELLOS_LV2__) mode_int = 0777; flags = CELL_FS_O_CREAT | CELL_FS_O_WRONLY | CELL_FS_O_TRUNC; #elif defined(HAVE_BUFFERED_IO) mode_str = "wb"; #else flags = O_WRONLY | O_CREAT | O_TRUNC | S_IRUSR | S_IWUSR; #endif break; case RFILE_MODE_READ_WRITE: #if defined(VITA) || defined(PSP) mode_int = 0777; flags = PSP_O_RDWR; #elif defined(__CELLOS_LV2__) mode_int = 0777; flags = CELL_FS_O_RDWR; #elif defined(HAVE_BUFFERED_IO) mode_str = "w+"; #else flags = O_RDWR; #ifdef _WIN32 flags |= O_BINARY; #endif #endif break; } #if defined(VITA) || defined(PSP) stream->fd = sceIoOpen(path, flags, mode_int); #elif defined(__CELLOS_LV2__) cellFsOpen(path, flags, &stream->fd, NULL, 0); #elif defined(HAVE_BUFFERED_IO) stream->fd = fopen(path, mode_str); #else stream->fd = open(path, flags); #endif #if defined(HAVE_BUFFERED_IO) if (!stream->fd) goto error; #else if (stream->fd == -1) goto error; #endif return stream; error: retro_fclose(stream); return NULL; } ssize_t retro_fseek(RFILE *stream, ssize_t offset, int whence) { int ret = 0; if (!stream) return -1; (void)ret; #if defined(VITA) || defined(PSP) ret = sceIoLseek(stream->fd, (SceOff)offset, whence); if (ret == -1) return -1; return 0; #elif defined(__CELLOS_LV2__) uint64_t pos = 0; if (cellFsLseek(stream->fd, offset, whence, &pos) != CELL_FS_SUCCEEDED) return -1; return 0; #elif defined(HAVE_BUFFERED_IO) return fseek(stream->fd, (long)offset, whence); #else ret = lseek(stream->fd, offset, whence); if (ret == -1) return -1; return 0; #endif } ssize_t retro_ftell(RFILE *stream) { if (!stream) return -1; #if defined(VITA) || defined(PSP) return sceIoLseek(stream->fd, 0, SEEK_CUR); #elif defined(__CELLOS_LV2__) uint64_t pos = 0; if (cellFsLseek(stream->fd, 0, CELL_FS_SEEK_CUR, &pos) != CELL_FS_SUCCEEDED) return -1; return 0; #elif defined(HAVE_BUFFERED_IO) return ftell(stream->fd); #else return lseek(stream->fd, 0, SEEK_CUR); #endif } void retro_frewind(RFILE *stream) { retro_fseek(stream, 0L, SEEK_SET); } ssize_t retro_fread(RFILE *stream, void *s, size_t len) { if (!stream || !s) return -1; #if defined(VITA) || defined(PSP) return sceIoRead(stream->fd, s, len); #elif defined(__CELLOS_LV2__) uint64_t bytes_written; if (cellFsRead(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED) return -1; return bytes_written; #elif defined(HAVE_BUFFERED_IO) return fread(s, 1, len, stream->fd); #else return read(stream->fd, s, len); #endif } ssize_t retro_fwrite(RFILE *stream, const void *s, size_t len) { if (!stream) return -1; #if defined(VITA) || defined(PSP) return sceIoWrite(stream->fd, s, len); #elif defined(__CELLOS_LV2__) uint64_t bytes_written; if (cellFsWrite(stream->fd, s, len, &bytes_written) != CELL_FS_SUCCEEDED) return -1; return bytes_written; #elif defined(HAVE_BUFFERED_IO) return fwrite(s, 1, len, stream->fd); #else return write(stream->fd, s, len); #endif } int retro_fclose(RFILE *stream) { if (!stream) return -1; #if defined(VITA) || defined(PSP) if (stream->fd > 0) sceIoClose(stream->fd); #elif defined(__CELLOS_LV2__) if (stream->fd > 0) cellFsClose(stream->fd); #elif defined(HAVE_BUFFERED_IO) if (stream->fd) fclose(stream->fd); #else if (stream->fd > 0) close(stream->fd); #endif free(stream); return 0; } /** * retro_read_file: * @path : path to file. * @buf : buffer to allocate and read the contents of the * file into. Needs to be freed manually. * * Read the contents of a file into @buf. * * Returns: number of items read, -1 on error. */ int retro_read_file(const char *path, void **buf, ssize_t *len) { ssize_t ret = 0; ssize_t content_buf_size = 0; void *content_buf = NULL; RFILE *file = retro_fopen(path, RFILE_MODE_READ, -1); if (!file) goto error; if (retro_fseek(file, 0, SEEK_END) != 0) goto error; content_buf_size = retro_ftell(file); if (content_buf_size < 0) goto error; retro_frewind(file); content_buf = malloc(content_buf_size + 1); if (!content_buf) goto error; if ((ret = retro_fread(file, content_buf, content_buf_size)) < content_buf_size) { #ifdef RARCH_INTERNAL RARCH_WARN("Didn't read whole file: %s.\n", path); #else printf("Didn't read whole file: %s.\n", path); #endif } if (!content_buf) goto error; *buf = content_buf; /* Allow for easy reading of strings to be safe. * Will only work with sane character formatting (Unix). */ ((char*)content_buf)[content_buf_size] = '\0'; if (retro_fclose(file) != 0) printf("Failed to close file stream.\n"); if (len) *len = ret; return 1; error: retro_fclose(file); if (content_buf) free(content_buf); if (len) *len = -1; *buf = NULL; return 0; } /** * retro_write_file: * @path : path to file. * @data : contents to write to the file. * @size : size of the contents. * * Writes data to a file. * * Returns: true (1) on success, false (0) otherwise. */ bool retro_write_file(const char *path, const void *data, ssize_t size) { ssize_t ret = 0; RFILE *file = retro_fopen(path, RFILE_MODE_WRITE, -1); if (!file) return false; ret = retro_fwrite(file, data, size); retro_fclose(file); return (ret == size); } mednafen/tremor/COPYING000664 001750 001750 00000002672 12611054044 016026 0ustar00sergiosergio000000 000000 Copyright (c) 2002, Xiph.org Foundation Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Xiph.org Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. mednafen/include/trio/000700 001750 001750 00000000000 12702525066 016050 5ustar00sergiosergio000000 000000 mednafen/state.cpp000664 001750 001750 00000033540 12611054044 015305 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include #include #include "mednafen.h" #include "driver.h" #include "general.h" #include "state.h" #include "video.h" #include "msvc_compat.h" #define RLSB MDFNSTATE_RLSB //0x80000000 int32_t smem_read(StateMem *st, void *buffer, uint32_t len) { if ((len + st->loc) > st->len) return 0; memcpy(buffer, st->data + st->loc, len); st->loc += len; return(len); } int32_t smem_write(StateMem *st, void *buffer, uint32_t len) { if ((len + st->loc) > st->malloced) { uint32_t newsize = (st->malloced >= 32768) ? st->malloced : (st->initial_malloc ? st->initial_malloc : 32768); while(newsize < (len + st->loc)) newsize *= 2; st->data = (uint8_t *)realloc(st->data, newsize); st->malloced = newsize; } memcpy(st->data + st->loc, buffer, len); st->loc += len; if (st->loc > st->len) st->len = st->loc; return(len); } int32_t smem_putc(StateMem *st, int value) { uint8_t tmpval = value; if(smem_write(st, &tmpval, 1) != 1) return(-1); return(1); } int32_t smem_tell(StateMem *st) { return(st->loc); } int32_t smem_seek(StateMem *st, uint32_t offset, int whence) { switch(whence) { case SEEK_SET: st->loc = offset; break; case SEEK_END: st->loc = st->len - offset; break; case SEEK_CUR: st->loc += offset; break; } if(st->loc > st->len) { st->loc = st->len; return(-1); } if(st->loc < 0) { st->loc = 0; return(-1); } return(0); } int smem_write32le(StateMem *st, uint32_t b) { uint8_t s[4]; s[0]=b; s[1]=b>>8; s[2]=b>>16; s[3]=b>>24; return((smem_write(st, s, 4)<4)?0:4); } int smem_read32le(StateMem *st, uint32_t *b) { uint8_t s[4]; if(smem_read(st, s, 4) < 4) return(0); *b = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); return(4); } static bool SubWrite(StateMem *st, SFORMAT *sf, const char *name_prefix = NULL) { while(sf->size || sf->name) // Size can sometimes be zero, so also check for the text name. These two should both be zero only at the end of a struct. { if(!sf->size || !sf->v) { sf++; continue; } if(sf->size == (uint32_t)~0) /* Link to another struct. */ { if(!SubWrite(st, (SFORMAT *)sf->v, name_prefix)) return(0); sf++; continue; } int32_t bytesize = sf->size; char nameo[1 + 256]; int slen; slen = snprintf(nameo + 1, 256, "%s%s", name_prefix ? name_prefix : "", sf->name); nameo[0] = slen; if(slen >= 255) { printf("Warning: state variable name possibly too long: %s %s %s %d\n", sf->name, name_prefix, nameo, slen); slen = 255; } smem_write(st, nameo, 1 + nameo[0]); smem_write32le(st, bytesize); #ifdef MSB_FIRST /* Flip the byte order... */ if(sf->flags & MDFNSTATE_BOOL) { } else if(sf->flags & MDFNSTATE_RLSB64) Endian_A64_NE_to_LE(sf->v, bytesize / sizeof(uint64_t)); else if(sf->flags & MDFNSTATE_RLSB32) Endian_A32_NE_to_LE(sf->v, bytesize / sizeof(uint32_t)); else if(sf->flags & MDFNSTATE_RLSB16) Endian_A16_NE_to_LE(sf->v, bytesize / sizeof(uint16_t)); else if(sf->flags & RLSB) Endian_V_NE_to_LE(sf->v, bytesize); #endif // Special case for the evil bool type, to convert bool to 1-byte elements. // Don't do it if we're only saving the raw data. if(sf->flags & MDFNSTATE_BOOL) { for(int32_t bool_monster = 0; bool_monster < bytesize; bool_monster++) { uint8_t tmp_bool = ((bool *)sf->v)[bool_monster]; //printf("Bool write: %.31s\n", sf->name); smem_write(st, &tmp_bool, 1); } } else smem_write(st, (uint8_t *)sf->v, bytesize); #ifdef MSB_FIRST /* Now restore the original byte order. */ if(sf->flags & MDFNSTATE_BOOL) { } else if(sf->flags & MDFNSTATE_RLSB64) Endian_A64_LE_to_NE(sf->v, bytesize / sizeof(uint64_t)); else if(sf->flags & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(sf->v, bytesize / sizeof(uint32_t)); else if(sf->flags & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(sf->v, bytesize / sizeof(uint16_t)); else if(sf->flags & RLSB) Endian_V_LE_to_NE(sf->v, bytesize); #endif sf++; } return(TRUE); } static int WriteStateChunk(StateMem *st, const char *sname, SFORMAT *sf) { int32_t data_start_pos; int32_t end_pos; uint8_t sname_tmp[32]; memset(sname_tmp, 0, sizeof(sname_tmp)); strncpy((char *)sname_tmp, sname, 32); if(strlen(sname) > 32) printf("Warning: section name is too long: %s\n", sname); smem_write(st, sname_tmp, 32); smem_write32le(st, 0); // We'll come back and write this later. data_start_pos = smem_tell(st); if(!SubWrite(st, sf)) return(0); end_pos = smem_tell(st); smem_seek(st, data_start_pos - 4, SEEK_SET); smem_write32le(st, end_pos - data_start_pos); smem_seek(st, end_pos, SEEK_SET); return(end_pos - data_start_pos); } struct compare_cstr { bool operator()(const char *s1, const char *s2) const { return(strcmp(s1, s2) < 0); } }; typedef std::map SFMap_t; static void MakeSFMap(SFORMAT *sf, SFMap_t &sfmap) { while(sf->size || sf->name) // Size can sometimes be zero, so also check for the text name. These two should both be zero only at the end of a struct. { if(!sf->size || !sf->v) { sf++; continue; } if(sf->size == (uint32_t)~0) /* Link to another SFORMAT structure. */ MakeSFMap((SFORMAT *)sf->v, sfmap); else { assert(sf->name); if(sfmap.find(sf->name) != sfmap.end()) printf("Duplicate save state variable in internal emulator structures(CLUB THE PROGRAMMERS WITH BREADSTICKS): %s\n", sf->name); sfmap[sf->name] = sf; } sf++; } } // Fast raw chunk reader static void DOReadChunk(StateMem *st, SFORMAT *sf) { while(sf->size || sf->name) // Size can sometimes be zero, so also check for the text name. // These two should both be zero only at the end of a struct. { if(!sf->size || !sf->v) { sf++; continue; } if(sf->size == (uint32_t) ~0) // Link to another SFORMAT struct { DOReadChunk(st, (SFORMAT *)sf->v); sf++; continue; } int32_t bytesize = sf->size; // Loading raw data, bool types are stored as they appear in memory, not as single bytes in the full state format. // In the SFORMAT structure, the size member for bool entries is the number of bool elements, not the total in-memory size, // so we adjust it here. if(sf->flags & MDFNSTATE_BOOL) bytesize *= sizeof(bool); smem_read(st, (uint8_t *)sf->v, bytesize); sf++; } } static int ReadStateChunk(StateMem *st, SFORMAT *sf, int size) { int temp; { SFMap_t sfmap; SFMap_t sfmap_found; // Used for identifying variables that are missing in the save state. MakeSFMap(sf, sfmap); temp = smem_tell(st); while(smem_tell(st) < (temp + size)) { uint32_t recorded_size; // In bytes uint8_t toa[1 + 256]; // Don't change to char unless cast toa[0] to unsigned to smem_read() and other places. if(smem_read(st, toa, 1) != 1) { puts("Unexpected EOF"); return(0); } if(smem_read(st, toa + 1, toa[0]) != toa[0]) { puts("Unexpected EOF?"); return 0; } toa[1 + toa[0]] = 0; smem_read32le(st, &recorded_size); SFMap_t::iterator sfmit; sfmit = sfmap.find((char *)toa + 1); if(sfmit != sfmap.end()) { SFORMAT *tmp = sfmit->second; uint32_t expected_size = tmp->size; // In bytes if(recorded_size != expected_size) { printf("Variable in save state wrong size: %s. Need: %d, got: %d\n", toa + 1, expected_size, recorded_size); if(smem_seek(st, recorded_size, SEEK_CUR) < 0) { puts("Seek error"); return(0); } } else { sfmap_found[tmp->name] = tmp; smem_read(st, (uint8_t *)tmp->v, expected_size); if(tmp->flags & MDFNSTATE_BOOL) { // Converting downwards is necessary for the case of sizeof(bool) > 1 for(int32_t bool_monster = expected_size - 1; bool_monster >= 0; bool_monster--) { ((bool *)tmp->v)[bool_monster] = ((uint8_t *)tmp->v)[bool_monster]; } } #ifdef MSB_FIRST if(tmp->flags & MDFNSTATE_RLSB64) Endian_A64_LE_to_NE(tmp->v, expected_size / sizeof(uint64_t)); else if(tmp->flags & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(tmp->v, expected_size / sizeof(uint32_t)); else if(tmp->flags & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(tmp->v, expected_size / sizeof(uint16_t)); else if(tmp->flags & RLSB) Endian_V_LE_to_NE(tmp->v, expected_size); #endif } } else { printf("Unknown variable in save state: %s\n", toa + 1); if(smem_seek(st, recorded_size, SEEK_CUR) < 0) { puts("Seek error"); return(0); } } } // while(...) for(SFMap_t::const_iterator it = sfmap.begin(); it != sfmap.end(); it++) { if(sfmap_found.find(it->second->name) == sfmap_found.end()) { printf("Variable missing from save state: %s\n", it->second->name); } } assert(smem_tell(st) == (temp + size)); } return 1; } static int CurrentState = 0; /* This function is called by the game driver(NES, GB, GBA) to save a state. */ int MDFNSS_StateAction(void *st_p, int load, int data_only, std::vector §ions) { StateMem *st = (StateMem*)st_p; std::vector::iterator section; if(load) { { char sname[32]; for(section = sections.begin(); section != sections.end(); section++) { int found = 0; uint32_t tmp_size; uint32_t total = 0; while(smem_read(st, (uint8_t *)sname, 32) == 32) { if(smem_read32le(st, &tmp_size) != 4) return(0); total += tmp_size + 32 + 4; // Yay, we found the section if(!strncmp(sname, section->name, 32)) { if(!ReadStateChunk(st, section->sf, tmp_size)) { printf("Error reading chunk: %s\n", section->name); return(0); } found = 1; break; } else { if(smem_seek(st, tmp_size, SEEK_CUR) < 0) { puts("Chunk seek failure"); return(0); } } } if(smem_seek(st, -total, SEEK_CUR) < 0) { puts("Reverse seek error"); return(0); } if(!found && !section->optional) // Not found. We are sad! { printf("Section missing: %.32s\n", section->name); return(0); } } } } else { for(section = sections.begin(); section != sections.end(); section++) { if(!WriteStateChunk(st, section->name, section->sf)) return(0); } } return(1); } int MDFNSS_StateAction(void *st_p, int load, int data_only, SFORMAT *sf, const char *name, bool optional) { StateMem *st = (StateMem*)st_p; std::vector love; love.push_back(SSDescriptor(sf, name, optional)); return(MDFNSS_StateAction(st, load, 0, love)); } int MDFNSS_SaveSM(void *st_p, int, int, const void*, const void*, const void*) { uint8_t header[32]; StateMem *st = (StateMem*)st_p; static const char *header_magic = "MDFNSVST"; int neowidth = 0, neoheight = 0; memset(header, 0, sizeof(header)); memcpy(header, header_magic, 8); MDFN_en32lsb(header + 16, MEDNAFEN_VERSION_NUMERIC); MDFN_en32lsb(header + 24, neowidth); MDFN_en32lsb(header + 28, neoheight); smem_write(st, header, 32); if(!MDFNGameInfo->StateAction(st, 0, 0)) return(0); uint32_t sizy = smem_tell(st); smem_seek(st, 16 + 4, SEEK_SET); smem_write32le(st, sizy); return(1); } int MDFNSS_LoadSM(void *st_p, int, int) { uint8_t header[32]; uint32_t stateversion; StateMem *st = (StateMem*)st_p; smem_read(st, header, 32); if(memcmp(header, "MEDNAFENSVESTATE", 16) && memcmp(header, "MDFNSVST", 8)) return(0); stateversion = MDFN_de32lsb(header + 16); return(MDFNGameInfo->StateAction(st, stateversion, 0)); } libretro.cpp000755 001750 001750 00000315022 12611054044 014231 0ustar00sergiosergio000000 000000 #include "mednafen/mednafen.h" #include "mednafen/mempatcher.h" #include "mednafen/git.h" #include "mednafen/general.h" #include "mednafen/md5.h" #include "mednafen/msvc_compat.h" #ifdef NEED_DEINTERLACER #include "mednafen/video/Deinterlacer.h" #endif #include "libretro.h" #include #include struct retro_perf_callback perf_cb; retro_get_cpu_features_t perf_get_cpu_features_cb = NULL; retro_log_printf_t log_cb; static retro_video_refresh_t video_cb; static retro_audio_sample_t audio_cb; static retro_audio_sample_batch_t audio_batch_cb; static retro_environment_t environ_cb; static retro_input_poll_t input_poll_cb; static retro_input_state_t input_state_cb; static retro_rumble_interface rumble; static unsigned players = 2; unsigned char widescreen_hack; unsigned char widescreen_auto_ar; unsigned char widescreen_auto_ar_old; static bool is_pal; char retro_save_directory[4096]; char retro_base_directory[4096]; static char retro_cd_base_directory[4096]; static char retro_cd_path[4096]; char retro_cd_base_name[4096]; #ifdef _WIN32 static char retro_slash = '\\'; #else static char retro_slash = '/'; #endif static void extract_basename(char *buf, const char *path, size_t size) { const char *base = strrchr(path, '/'); if (!base) base = strrchr(path, '\\'); if (!base) base = path; if (*base == '\\' || *base == '/') base++; strncpy(buf, base, size - 1); buf[size - 1] = '\0'; char *ext = strrchr(buf, '.'); if (ext) *ext = '\0'; } static void extract_directory(char *buf, const char *path, size_t size) { strncpy(buf, path, size - 1); buf[size - 1] = '\0'; char *base = strrchr(buf, '/'); if (!base) base = strrchr(buf, '\\'); if (base) *base = '\0'; else buf[0] = '\0'; } /* start of Mednafen psx.cpp */ /* Mednafen - Multi-system Emulator * * 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 */ #include "mednafen/psx/psx.h" #include "mednafen/psx/mdec.h" #include "mednafen/psx/frontio.h" #include "mednafen/psx/timer.h" #include "mednafen/psx/sio.h" #include "mednafen/psx/cdc.h" #include "mednafen/psx/spu.h" #include "mednafen/mempatcher.h" #include #include bool setting_apply_analog_toggle = false; bool use_mednafen_memcard0_method = false; extern MDFNGI EmulatedPSX; MDFNGI *MDFNGameInfo = &EmulatedPSX; enum { REGION_JP = 0, REGION_NA = 1, REGION_EU = 2, }; #if PSX_DBGPRINT_ENABLE static unsigned psx_dbg_level = 0; void PSX_DBG(unsigned level, const char *format, ...) { if(psx_dbg_level >= level) { va_list ap; va_start(ap, format); trio_vprintf(format, ap); va_end(ap); } } #else static unsigned const psx_dbg_level = 0; #endif /* Based off(but not the same as) public-domain "JKISS" PRNG. */ struct MDFN_PseudoRNG { uint32_t x,y,z,c; uint64_t lcgo; }; static MDFN_PseudoRNG PSX_PRNG; uint32_t PSX_GetRandU32(uint32_t mina, uint32_t maxa) { uint32_t tmp; const uint32_t range_m1 = maxa - mina; uint32_t range_mask = range_m1; range_mask |= range_mask >> 1; range_mask |= range_mask >> 2; range_mask |= range_mask >> 4; range_mask |= range_mask >> 8; range_mask |= range_mask >> 16; do { uint64_t t = 4294584393ULL * PSX_PRNG.z + PSX_PRNG.c; PSX_PRNG.x = 314527869 * PSX_PRNG.x + 1234567; PSX_PRNG.y ^= PSX_PRNG.y << 5; PSX_PRNG.y ^= PSX_PRNG.y >> 7; PSX_PRNG.y ^= PSX_PRNG.y << 22; PSX_PRNG.c = t >> 32; PSX_PRNG.z = t; PSX_PRNG.lcgo = (19073486328125ULL * PSX_PRNG.lcgo) + 1; tmp = ((PSX_PRNG.x + PSX_PRNG.y + PSX_PRNG.z) ^ (PSX_PRNG.lcgo >> 16)) & range_mask; } while(tmp > range_m1); return(mina + tmp); } static std::vector *cdifs = NULL; static std::vector cdifs_scex_ids; static bool CD_TrayOpen; static int CD_SelectedDisc; // -1 for no disc static uint64_t Memcard_PrevDC[8]; static int64_t Memcard_SaveDelay[8]; PS_CPU *CPU = NULL; PS_SPU *SPU = NULL; PS_GPU *GPU = NULL; PS_CDC *CDC = NULL; FrontIO *FIO = NULL; static MultiAccessSizeMem<512 * 1024, uint32, false> *BIOSROM = NULL; static MultiAccessSizeMem<65536, uint32, false> *PIOMem = NULL; MultiAccessSizeMem<2048 * 1024, uint32, false> MainRAM; static uint32_t TextMem_Start; static std::vector TextMem; static const uint32_t SysControl_Mask[9] = { 0x00ffffff, 0x00ffffff, 0xffffffff, 0x2f1fffff, 0xffffffff, 0x2f1fffff, 0x2f1fffff, 0xffffffff, 0x0003ffff }; static const uint32_t SysControl_OR[9] = { 0x1f000000, 0x1f000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; static struct { union { struct { uint32_t PIO_Base; // 0x1f801000 // BIOS Init: 0x1f000000, Writeable bits: 0x00ffffff(assumed, verify), FixedOR = 0x1f000000 uint32_t Unknown0; // 0x1f801004 // BIOS Init: 0x1f802000, Writeable bits: 0x00ffffff, FixedOR = 0x1f000000 uint32_t Unknown1; // 0x1f801008 // BIOS Init: 0x0013243f, ???? uint32_t Unknown2; // 0x1f80100c // BIOS Init: 0x00003022, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000 uint32_t BIOS_Mapping; // 0x1f801010 // BIOS Init: 0x0013243f, ???? uint32_t SPU_Delay; // 0x1f801014 // BIOS Init: 0x200931e1, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000 - Affects bus timing on access to SPU uint32_t CDC_Delay; // 0x1f801018 // BIOS Init: 0x00020843, Writeable bits: 0x2f1fffff, FixedOR = 0x00000000 uint32_t Unknown4; // 0x1f80101c // BIOS Init: 0x00070777, ???? uint32_t Unknown5; // 0x1f801020 // BIOS Init: 0x00031125(but rewritten with other values often), Writeable bits: 0x0003ffff, FixedOR = 0x00000000 -- Possibly CDC related }; uint32_t Regs[9]; }; } SysControl; static unsigned DMACycleSteal = 0; // Doesn't need to be saved in save states, since it's calculated in the ForceEventUpdates() call chain. void PSX_SetDMACycleSteal(unsigned stealage) { if (stealage > 200) // Due to 8-bit limitations in the CPU core. stealage = 200; DMACycleSteal = stealage; } // // Event stuff // static int32_t Running; // Set to -1 when not desiring exit, and 0 when we are. struct event_list_entry { uint32_t which; int32_t event_time; event_list_entry *prev; event_list_entry *next; }; static event_list_entry events[PSX_EVENT__COUNT]; static void EventReset(void) { unsigned i; for(i = 0; i < PSX_EVENT__COUNT; i++) { events[i].which = i; if(i == PSX_EVENT__SYNFIRST) events[i].event_time = 0; else if(i == PSX_EVENT__SYNLAST) events[i].event_time = 0x7FFFFFFF; else events[i].event_time = PSX_EVENT_MAXTS; events[i].prev = (i > 0) ? &events[i - 1] : NULL; events[i].next = (i < (PSX_EVENT__COUNT - 1)) ? &events[i + 1] : NULL; } } //static void RemoveEvent(event_list_entry *e) //{ // e->prev->next = e->next; // e->next->prev = e->prev; //} static void RebaseTS(const int32_t timestamp) { unsigned i; for(i = 0; i < PSX_EVENT__COUNT; i++) { if(i == PSX_EVENT__SYNFIRST || i == PSX_EVENT__SYNLAST) continue; assert(events[i].event_time > timestamp); events[i].event_time -= timestamp; } CPU->SetEventNT(events[PSX_EVENT__SYNFIRST].next->event_time); } void PSX_SetEventNT(const int type, const int32_t next_timestamp) { event_list_entry *e = &events[type]; if(next_timestamp < e->event_time) { event_list_entry *fe = e; do { fe = fe->prev; }while(next_timestamp < fe->event_time); // Remove this event from the list, temporarily of course. e->prev->next = e->next; e->next->prev = e->prev; // Insert into the list, just after "fe". e->prev = fe; e->next = fe->next; fe->next->prev = e; fe->next = e; e->event_time = next_timestamp; } else if(next_timestamp > e->event_time) { event_list_entry *fe = e; do { fe = fe->next; } while(next_timestamp > fe->event_time); // Remove this event from the list, temporarily of course e->prev->next = e->next; e->next->prev = e->prev; // Insert into the list, just BEFORE "fe". e->prev = fe->prev; e->next = fe; fe->prev->next = e; fe->prev = e; e->event_time = next_timestamp; } CPU->SetEventNT(events[PSX_EVENT__SYNFIRST].next->event_time & Running); } // Called from debug.cpp too. void ForceEventUpdates(const int32_t timestamp) { PSX_SetEventNT(PSX_EVENT_GPU, GPU->Update(timestamp)); PSX_SetEventNT(PSX_EVENT_CDC, CDC->Update(timestamp)); PSX_SetEventNT(PSX_EVENT_TIMER, TIMER_Update(timestamp)); PSX_SetEventNT(PSX_EVENT_DMA, DMA_Update(timestamp)); PSX_SetEventNT(PSX_EVENT_FIO, FIO->Update(timestamp)); CPU->SetEventNT(events[PSX_EVENT__SYNFIRST].next->event_time); } bool MDFN_FASTCALL PSX_EventHandler(const int32_t timestamp) { event_list_entry *e = events[PSX_EVENT__SYNFIRST].next; while(timestamp >= e->event_time) // If Running = 0, PSX_EventHandler() may be called even if there isn't an event per-se, so while() instead of do { ... } while { int32_t nt; event_list_entry *prev = e->prev; switch(e->which) { default: abort(); case PSX_EVENT_GPU: nt = GPU->Update(e->event_time); break; case PSX_EVENT_CDC: nt = CDC->Update(e->event_time); break; case PSX_EVENT_TIMER: nt = TIMER_Update(e->event_time); break; case PSX_EVENT_DMA: nt = DMA_Update(e->event_time); break; case PSX_EVENT_FIO: nt = FIO->Update(e->event_time); break; } PSX_SetEventNT(e->which, nt); // Order of events can change due to calling PSX_SetEventNT(), this prev business ensures we don't miss an event due to reordering. e = prev->next; } return(Running); } void PSX_RequestMLExit(void) { Running = 0; CPU->SetEventNT(0); } // // End event stuff // // Remember to update MemPeek<>() when we change address decoding in MemRW() template static INLINE void MemRW(int32_t ×tamp, uint32_t A, uint32_t &V) { #if 0 if(IsWrite) printf("Write%d: %08x(orig=%08x), %08x\n", (int)(sizeof(T) * 8), A & mask[A >> 29], A, V); else printf("Read%d: %08x(orig=%08x)\n", (int)(sizeof(T) * 8), A & mask[A >> 29], A); #endif if(!IsWrite) timestamp += DMACycleSteal; //if(A == 0xa0 && IsWrite) // DBG_Break(); if(A < 0x00800000) { if(IsWrite) { //timestamp++; // Best-case timing. } else { timestamp += 3; } if(Access24) { if(IsWrite) MainRAM.WriteU24(A & 0x1FFFFF, V); else V = MainRAM.ReadU24(A & 0x1FFFFF); } else { if(IsWrite) MainRAM.Write(A & 0x1FFFFF, V); else V = MainRAM.Read(A & 0x1FFFFF); } return; } if(A >= 0x1FC00000 && A <= 0x1FC7FFFF) { if(!IsWrite) { if(Access24) V = BIOSROM->ReadU24(A & 0x7FFFF); else V = BIOSROM->Read(A & 0x7FFFF); } return; } if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time) PSX_EventHandler(timestamp); if(A >= 0x1F801000 && A <= 0x1F802FFF) { //if(IsWrite) // printf("HW Write%d: %08x %08x\n", (unsigned int)(sizeof(T)*8), (unsigned int)A, (unsigned int)V); //else // printf("HW Read%d: %08x\n", (unsigned int)(sizeof(T)*8), (unsigned int)A); if(A >= 0x1F801C00 && A <= 0x1F801FFF) // SPU { if(sizeof(T) == 4 && !Access24) { if(IsWrite) { //timestamp += 15; //if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time) // PSX_EventHandler(timestamp); SPU->Write(timestamp, A | 0, V); SPU->Write(timestamp, A | 2, V >> 16); } else { timestamp += 36; if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time) PSX_EventHandler(timestamp); V = SPU->Read(timestamp, A) | (SPU->Read(timestamp, A | 2) << 16); } } else { if(IsWrite) { //timestamp += 8; //if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time) // PSX_EventHandler(timestamp); SPU->Write(timestamp, A & ~1, V); } else { timestamp += 16; // Just a guess, need to test. if(timestamp >= events[PSX_EVENT__SYNFIRST].next->event_time) PSX_EventHandler(timestamp); V = SPU->Read(timestamp, A & ~1); } } return; } // End SPU // CDC: TODO - 8-bit access. if(A >= 0x1f801800 && A <= 0x1f80180F) { if(!IsWrite) { timestamp += 6 * sizeof(T); //24; } if(IsWrite) CDC->Write(timestamp, A & 0x3, V); else V = CDC->Read(timestamp, A & 0x3); return; } if(A >= 0x1F801810 && A <= 0x1F801817) { if(!IsWrite) timestamp++; if(IsWrite) GPU->Write(timestamp, A, V); else V = GPU->Read(timestamp, A); return; } if(A >= 0x1F801820 && A <= 0x1F801827) { if(!IsWrite) timestamp++; if(IsWrite) MDEC_Write(timestamp, A, V); else V = MDEC_Read(timestamp, A); return; } if(A >= 0x1F801000 && A <= 0x1F801023) { unsigned index = (A & 0x1F) >> 2; if(!IsWrite) timestamp++; //if(A == 0x1F801014 && IsWrite) // fprintf(stderr, "%08x %08x\n",A,V); if(IsWrite) { V <<= (A & 3) * 8; SysControl.Regs[index] = V & SysControl_Mask[index]; } else { V = SysControl.Regs[index] | SysControl_OR[index]; V >>= (A & 3) * 8; } return; } if(A >= 0x1F801040 && A <= 0x1F80104F) { if(!IsWrite) timestamp++; if(IsWrite) FIO->Write(timestamp, A, V); else V = FIO->Read(timestamp, A); return; } if(A >= 0x1F801050 && A <= 0x1F80105F) { if(!IsWrite) timestamp++; #if 0 if(IsWrite) { PSX_WARNING("[SIO] Write: 0x%08x 0x%08x %u", A, V, (unsigned)sizeof(T)); } else { PSX_WARNING("[SIO] Read: 0x%08x", A); } #endif if(IsWrite) SIO_Write(timestamp, A, V); else V = SIO_Read(timestamp, A); return; } #if 0 if(A >= 0x1F801060 && A <= 0x1F801063) { if(IsWrite) { } else { } return; } #endif if(A >= 0x1F801070 && A <= 0x1F801077) // IRQ { if(!IsWrite) timestamp++; if(IsWrite) ::IRQ_Write(A, V); else V = ::IRQ_Read(A); return; } if(A >= 0x1F801080 && A <= 0x1F8010FF) // DMA { if(!IsWrite) timestamp++; if(IsWrite) DMA_Write(timestamp, A, V); else V = DMA_Read(timestamp, A); return; } if(A >= 0x1F801100 && A <= 0x1F80113F) // Root counters { if(!IsWrite) timestamp++; if(IsWrite) TIMER_Write(timestamp, A, V); else V = TIMER_Read(timestamp, A); return; } } if(A >= 0x1F000000 && A <= 0x1F7FFFFF) { if(!IsWrite) { //if((A & 0x7FFFFF) <= 0x84) //PSX_WARNING("[PIO] Read%d from 0x%08x at time %d", (int)(sizeof(T) * 8), A, timestamp); V = ~0U; // A game this affects: Tetris with Cardcaptor Sakura if(PIOMem) { if((A & 0x7FFFFF) < 65536) { if(Access24) V = PIOMem->ReadU24(A & 0x7FFFFF); else V = PIOMem->Read(A & 0x7FFFFF); } else if((A & 0x7FFFFF) < (65536 + TextMem.size())) { if(Access24) V = MDFN_de24lsb(&TextMem[(A & 0x7FFFFF) - 65536]); else switch(sizeof(T)) { case 1: V = TextMem[(A & 0x7FFFFF) - 65536]; break; case 2: V = MDFN_de16lsb(&TextMem[(A & 0x7FFFFF) - 65536]); break; case 4: V = MDFN_de32lsb(&TextMem[(A & 0x7FFFFF) - 65536]); break; } } } } return; } if(A == 0xFFFE0130) // Per tests on PS1, ignores the access(sort of, on reads the value is forced to 0 if not aligned) if not aligned to 4-bytes. { if(!IsWrite) V = CPU->GetBIU(); else CPU->SetBIU(V); return; } if(IsWrite) { PSX_WARNING("[MEM] Unknown write%d to %08x at time %d, =%08x(%d)", (int)(sizeof(T) * 8), A, timestamp, V, V); } else { V = 0; PSX_WARNING("[MEM] Unknown read%d from %08x at time %d", (int)(sizeof(T) * 8), A, timestamp); } } void MDFN_FASTCALL PSX_MemWrite8(int32_t timestamp, uint32_t A, uint32_t V) { MemRW(timestamp, A, V); } void MDFN_FASTCALL PSX_MemWrite16(int32_t timestamp, uint32_t A, uint32_t V) { MemRW(timestamp, A, V); } void MDFN_FASTCALL PSX_MemWrite24(int32_t timestamp, uint32_t A, uint32_t V) { MemRW(timestamp, A, V); } void MDFN_FASTCALL PSX_MemWrite32(int32_t timestamp, uint32_t A, uint32_t V) { MemRW(timestamp, A, V); } uint8_t MDFN_FASTCALL PSX_MemRead8(int32_t ×tamp, uint32_t A) { uint32_t V; MemRW(timestamp, A, V); return(V); } uint16_t MDFN_FASTCALL PSX_MemRead16(int32_t ×tamp, uint32_t A) { uint32_t V; MemRW(timestamp, A, V); return(V); } uint32_t MDFN_FASTCALL PSX_MemRead24(int32_t ×tamp, uint32_t A) { uint32_t V; MemRW(timestamp, A, V); return(V); } uint32_t MDFN_FASTCALL PSX_MemRead32(int32_t ×tamp, uint32_t A) { uint32_t V; MemRW(timestamp, A, V); return(V); } template static INLINE uint32_t MemPeek(int32_t timestamp, uint32_t A) { if(A < 0x00800000) { if(Access24) return(MainRAM.ReadU24(A & 0x1FFFFF)); return(MainRAM.Read(A & 0x1FFFFF)); } if(A >= 0x1FC00000 && A <= 0x1FC7FFFF) { if(Access24) return(BIOSROM->ReadU24(A & 0x7FFFF)); return(BIOSROM->Read(A & 0x7FFFF)); } if(A >= 0x1F801000 && A <= 0x1F802FFF) { if(A >= 0x1F801C00 && A <= 0x1F801FFF) // SPU { // TODO } // End SPU // CDC: TODO - 8-bit access. if(A >= 0x1f801800 && A <= 0x1f80180F) { // TODO } if(A >= 0x1F801810 && A <= 0x1F801817) { // TODO } if(A >= 0x1F801820 && A <= 0x1F801827) { // TODO } if(A >= 0x1F801000 && A <= 0x1F801023) { unsigned index = (A & 0x1F) >> 2; return((SysControl.Regs[index] | SysControl_OR[index]) >> ((A & 3) * 8)); } if(A >= 0x1F801040 && A <= 0x1F80104F) { // TODO } if(A >= 0x1F801050 && A <= 0x1F80105F) { // TODO } if(A >= 0x1F801070 && A <= 0x1F801077) // IRQ { // TODO } if(A >= 0x1F801080 && A <= 0x1F8010FF) // DMA { // TODO } if(A >= 0x1F801100 && A <= 0x1F80113F) // Root counters { // TODO } } if(A >= 0x1F000000 && A <= 0x1F7FFFFF) { if(PIOMem) { if((A & 0x7FFFFF) < 65536) { if(Access24) return(PIOMem->ReadU24(A & 0x7FFFFF)); return(PIOMem->Read(A & 0x7FFFFF)); } else if((A & 0x7FFFFF) < (65536 + TextMem.size())) { if(Access24) return(MDFN_de24lsb(&TextMem[(A & 0x7FFFFF) - 65536])); else switch(sizeof(T)) { case 1: return(TextMem[(A & 0x7FFFFF) - 65536]); case 2: return(MDFN_de16lsb(&TextMem[(A & 0x7FFFFF) - 65536])); case 4: return(MDFN_de32lsb(&TextMem[(A & 0x7FFFFF) - 65536])); } } } return(~0U); } if(A == 0xFFFE0130) return CPU->GetBIU(); return(0); } uint8_t PSX_MemPeek8(uint32_t A) { return MemPeek(0, A); } uint16_t PSX_MemPeek16(uint32_t A) { return MemPeek(0, A); } uint32_t PSX_MemPeek32(uint32_t A) { return MemPeek(0, A); } // FIXME: Add PSX_Reset() and FrontIO::Reset() so that emulated input devices don't get power-reset on reset-button reset. static void PSX_Power(void) { unsigned i; PSX_PRNG.x = 123456789; PSX_PRNG.y = 987654321; PSX_PRNG.z = 43219876; PSX_PRNG.c = 6543217; PSX_PRNG.lcgo = 0xDEADBEEFCAFEBABEULL; memset(MainRAM.data32, 0, 2048 * 1024); for(i = 0; i < 9; i++) SysControl.Regs[i] = 0; CPU->Power(); EventReset(); TIMER_Power(); DMA_Power(); FIO->Power(); SIO_Power(); MDEC_Power(); CDC->Power(); GPU->Power(); //SPU->Power(); // Called from CDC->Power() IRQ_Power(); ForceEventUpdates(0); } void PSX_GPULineHook(const int32_t timestamp, const int32_t line_timestamp, bool vsync, uint32_t *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider) { FIO->GPULineHook(timestamp, line_timestamp, vsync, pixels, format, width, pix_clock_offset, pix_clock, pix_clock_divider); } static bool TestMagic(const char *name, MDFNFILE *fp) { if(GET_FSIZE_PTR(fp) < 0x800) return(false); if(memcmp(GET_FDATA_PTR(fp), "PS-X EXE", 8)) return(false); return(true); } static bool TestMagicCD(std::vector *CDInterfaces) { uint8_t buf[2048]; TOC toc; int dt; TOC_Clear(&toc); (*CDInterfaces)[0]->ReadTOC(&toc); dt = TOC_FindTrackByLBA(&toc, 4); if(dt > 0 && !(toc.tracks[dt].control & 0x4)) return(false); if((*CDInterfaces)[0]->ReadSector(buf, 4, 1) != 0x2) return(false); if(strncmp((char *)buf + 10, "Licensed by", strlen("Licensed by"))) return(false); //if(strncmp((char *)buf + 32, "Sony", 4)) // return(false); //for(int i = 0; i < 2048; i++) // printf("%d, %02x %c\n", i, buf[i], buf[i]); //exit(1); #if 0 { uint8_t buf[2048 * 7]; if((*cdifs)[0]->ReadSector(buf, 5, 7) == 0x2) { printf("CRC32: 0x%08x\n", (uint32)crc32(0, &buf[0], 0x3278)); } } #endif return(true); } static const char *CalcDiscSCEx_BySYSTEMCNF(CDIF *c, unsigned *rr) { const char *ret = NULL; Stream *fp = NULL; uint8_t pvd[2048]; unsigned pvd_search_count = 0; fp = c->MakeStream(0, ~0U); fp->seek(0x8000, SEEK_SET); do { if((pvd_search_count++) == 32) throw MDFN_Error(0, "PVD search count limit met."); fp->read(pvd, 2048); if(memcmp(&pvd[1], "CD001", 5)) throw MDFN_Error(0, "Not ISO-9660"); if(pvd[0] == 0xFF) throw MDFN_Error(0, "Missing Primary Volume Descriptor"); } while(pvd[0] != 0x01); //[156 ... 189], 34 bytes uint32_t rdel = MDFN_de32lsb(&pvd[0x9E]); uint32_t rdel_len = MDFN_de32lsb(&pvd[0xA6]); if(rdel_len >= (1024 * 1024 * 10)) // Arbitrary sanity check. throw MDFN_Error(0, "Root directory table too large"); fp->seek((int64)rdel * 2048, SEEK_SET); //printf("%08x, %08x\n", rdel * 2048, rdel_len); while(fp->tell() < (((int64)rdel * 2048) + rdel_len)) { uint8_t len_dr = fp->get_u8(); uint8_t dr[256 + 1]; memset(dr, 0xFF, sizeof(dr)); if(!len_dr) break; memset(dr, 0, sizeof(dr)); dr[0] = len_dr; fp->read(dr + 1, len_dr - 1); uint8_t len_fi = dr[0x20]; if(len_fi == 12 && !memcmp(&dr[0x21], "SYSTEM.CNF;1", 12)) { uint32_t file_lba = MDFN_de32lsb(&dr[0x02]); //uint32_t file_len = MDFN_de32lsb(&dr[0x0A]); uint8_t fb[2048 + 1]; char *bootpos; memset(fb, 0, sizeof(fb)); fp->seek(file_lba * 2048, SEEK_SET); fp->read(fb, 2048); bootpos = strstr((char*)fb, "BOOT") + 4; while(*bootpos == ' ' || *bootpos == '\t') bootpos++; if(*bootpos == '=') { bootpos++; while(*bootpos == ' ' || *bootpos == '\t') bootpos++; if(!strncasecmp(bootpos, "cdrom:\\", 7)) { bootpos += 7; char *tmp; if((tmp = strchr(bootpos, '_'))) *tmp = 0; if((tmp = strchr(bootpos, '.'))) *tmp = 0; if((tmp = strchr(bootpos, ';'))) *tmp = 0; //puts(bootpos); if(strlen(bootpos) == 4 && bootpos[0] == 'S' && (bootpos[1] == 'C' || bootpos[1] == 'L' || bootpos[1] == 'I')) { switch(bootpos[2]) { case 'E': if(rr) *rr = REGION_EU; ret = "SCEE"; goto Breakout; case 'U': if(rr) *rr = REGION_NA; ret = "SCEA"; goto Breakout; case 'K': // Korea? case 'B': case 'P': if(rr) *rr = REGION_JP; ret = "SCEI"; goto Breakout; } } } } //puts((char*)fb); //puts("ASOFKOASDFKO"); } } Breakout: if(fp) { delete fp; fp = NULL; } return(ret); } static unsigned CalcDiscSCEx(void) { const char *prev_valid_id = NULL; unsigned ret_region = MDFN_GetSettingI("psx.region_default"); cdifs_scex_ids.clear(); if(cdifs) for(unsigned i = 0; i < cdifs->size(); i++) { uint8_t buf[2048]; uint8_t fbuf[2048 + 1]; const char *id = CalcDiscSCEx_BySYSTEMCNF((*cdifs)[i], (i == 0) ? &ret_region : NULL); memset(fbuf, 0, sizeof(fbuf)); if(id == NULL && (*cdifs)[i]->ReadSector(buf, 4, 1) == 0x2) { unsigned ipos, opos; for(ipos = 0, opos = 0; ipos < 0x48; ipos++) { if(buf[ipos] > 0x20 && buf[ipos] < 0x80) { fbuf[opos++] = tolower(buf[ipos]); } } fbuf[opos++] = 0; PSX_DBG(PSX_DBG_SPARSE, "License string: %s", (char *)fbuf); if(strstr((char *)fbuf, "licensedby") != NULL) { if(strstr((char *)fbuf, "america") != NULL) { id = "SCEA"; if(!i) ret_region = REGION_NA; } else if(strstr((char *)fbuf, "europe") != NULL) { id = "SCEE"; if(!i) ret_region = REGION_EU; } else if(strstr((char *)fbuf, "japan") != NULL) { id = "SCEI"; // ? if(!i) ret_region = REGION_JP; } else if(strstr((char *)fbuf, "sonycomputerentertainmentinc.") != NULL) { id = "SCEI"; if(!i) ret_region = REGION_JP; } else // Failure case { if(prev_valid_id != NULL) id = prev_valid_id; else { switch(ret_region) // Less than correct, but meh, what can we do. { case REGION_JP: id = "SCEI"; break; case REGION_NA: id = "SCEA"; break; case REGION_EU: id = "SCEE"; break; } } } } } if(id != NULL) prev_valid_id = id; cdifs_scex_ids.push_back(id); } return ret_region; } static void InitCommon(std::vector *CDInterfaces, const bool EmulateMemcards = true, const bool WantPIOMem = false) { unsigned region, i; bool emulate_memcard[8]; bool emulate_multitap[2]; int sls, sle; #if PSX_DBGPRINT_ENABLE psx_dbg_level = MDFN_GetSettingUI("psx.dbg_level"); #endif for(i = 0; i < 8; i++) { char buf[64]; snprintf(buf, sizeof(buf), "psx.input.port%u.memcard", i + 1); emulate_memcard[i] = EmulateMemcards && MDFN_GetSettingB(buf); } for(i = 0; i < 2; i++) { char buf[64]; snprintf(buf, sizeof(buf), "psx.input.pport%u.multitap", i + 1); emulate_multitap[i] = MDFN_GetSettingB(buf); } cdifs = CDInterfaces; region = CalcDiscSCEx(); if(!MDFN_GetSettingB("psx.region_autodetect")) region = MDFN_GetSettingI("psx.region_default"); sls = MDFN_GetSettingI((region == REGION_EU) ? "psx.slstartp" : "psx.slstart"); sle = MDFN_GetSettingI((region == REGION_EU) ? "psx.slendp" : "psx.slend"); if(sls > sle) { int tmp = sls; sls = sle; sle = tmp; } CPU = new PS_CPU(); SPU = new PS_SPU(); GPU = new PS_GPU(region == REGION_EU, sls, sle); CDC = new PS_CDC(); FIO = new FrontIO(emulate_memcard, emulate_multitap); FIO->SetAMCT(MDFN_GetSettingB("psx.input.analog_mode_ct")); for(unsigned i = 0; i < 8; i++) { char buf[64]; snprintf(buf, sizeof(buf), "psx.input.port%u.gun_chairs", i + 1); FIO->SetCrosshairsColor(i, MDFN_GetSettingUI(buf)); } DMA_Init(); GPU->FillVideoParams(&EmulatedPSX); CD_TrayOpen = true; CD_SelectedDisc = -1; if(cdifs) { CD_TrayOpen = false; CD_SelectedDisc = 0; } CDC->SetDisc(true, NULL, NULL); CDC->SetDisc(CD_TrayOpen, (CD_SelectedDisc >= 0 && !CD_TrayOpen) ? (*cdifs)[CD_SelectedDisc] : NULL, (CD_SelectedDisc >= 0 && !CD_TrayOpen) ? cdifs_scex_ids[CD_SelectedDisc] : NULL); BIOSROM = new MultiAccessSizeMem<512 * 1024, uint32, false>(); PIOMem = NULL; if(WantPIOMem) PIOMem = new MultiAccessSizeMem<65536, uint32, false>(); for(uint32_t ma = 0x00000000; ma < 0x00800000; ma += 2048 * 1024) { CPU->SetFastMap(MainRAM.data32, 0x00000000 + ma, 2048 * 1024); CPU->SetFastMap(MainRAM.data32, 0x80000000 + ma, 2048 * 1024); CPU->SetFastMap(MainRAM.data32, 0xA0000000 + ma, 2048 * 1024); } CPU->SetFastMap(BIOSROM->data32, 0x1FC00000, 512 * 1024); CPU->SetFastMap(BIOSROM->data32, 0x9FC00000, 512 * 1024); CPU->SetFastMap(BIOSROM->data32, 0xBFC00000, 512 * 1024); if(PIOMem) { CPU->SetFastMap(PIOMem->data32, 0x1F000000, 65536); CPU->SetFastMap(PIOMem->data32, 0x9F000000, 65536); CPU->SetFastMap(PIOMem->data32, 0xBF000000, 65536); } MDFNMP_Init(1024, ((uint64)1 << 29) / 1024); MDFNMP_AddRAM(2048 * 1024, 0x00000000, MainRAM.data8); #if 0 MDFNMP_AddRAM(1024, 0x1F800000, ScratchRAM.data8); #endif const char *biospath_sname; if(region == REGION_JP) biospath_sname = "psx.bios_jp"; else if(region == REGION_EU) biospath_sname = "psx.bios_eu"; else if(region == REGION_NA) biospath_sname = "psx.bios_na"; else abort(); { const char *biospath = MDFN_MakeFName(MDFNMKF_FIRMWARE, 0, MDFN_GetSettingS(biospath_sname).c_str()); FileStream BIOSFile(biospath, MODE_READ); BIOSFile.read(BIOSROM->data8, 512 * 1024); } i = 0; if (!use_mednafen_memcard0_method) { FIO->LoadMemcard(0); i = 1; } for(; i < 8; i++) { char ext[64]; const char *memcard = NULL; snprintf(ext, sizeof(ext), "%d.mcr", i); memcard = MDFN_MakeFName(MDFNMKF_SAV, 0, ext); FIO->LoadMemcard(i, memcard); } for(i = 0; i < 8; i++) { Memcard_PrevDC[i] = FIO->GetMemcardDirtyCount(i); Memcard_SaveDelay[i] = -1; } #ifdef WANT_DEBUGGER DBG_Init(); #endif PSX_Power(); } static void LoadEXE(const uint8_t *data, const uint32_t size, bool ignore_pcsp = false) { uint32 PC = MDFN_de32lsb(&data[0x10]); uint32 SP = MDFN_de32lsb(&data[0x30]); uint32 TextStart = MDFN_de32lsb(&data[0x18]); uint32 TextSize = MDFN_de32lsb(&data[0x1C]); if(ignore_pcsp) log_cb(RETRO_LOG_INFO, "TextStart=0x%08x\nTextSize=0x%08x\n", TextStart, TextSize); else log_cb(RETRO_LOG_INFO, "PC=0x%08x\nSP=0x%08x\nTextStart=0x%08x\nTextSize=0x%08x\n", PC, SP, TextStart, TextSize); TextStart &= 0x1FFFFF; if(TextSize > 2048 * 1024) throw(MDFN_Error(0, "Text section too large")); if(TextSize > (size - 0x800)) throw(MDFN_Error(0, "Text section recorded size is larger than data available in file. Header=0x%08x, Available=0x%08x", TextSize, size - 0x800)); if(TextSize < (size - 0x800)) throw(MDFN_Error(0, "Text section recorded size is smaller than data available in file. Header=0x%08x, Available=0x%08x", TextSize, size - 0x800)); if(!TextMem.size()) { TextMem_Start = TextStart; TextMem.resize(TextSize); } if(TextStart < TextMem_Start) { uint32 old_size = TextMem.size(); //printf("RESIZE: 0x%08x\n", TextMem_Start - TextStart); TextMem.resize(old_size + TextMem_Start - TextStart); memmove(&TextMem[TextMem_Start - TextStart], &TextMem[0], old_size); TextMem_Start = TextStart; } if(TextMem.size() < (TextStart - TextMem_Start + TextSize)) TextMem.resize(TextStart - TextMem_Start + TextSize); memcpy(&TextMem[TextStart - TextMem_Start], data + 0x800, TextSize); // BIOS patch BIOSROM->WriteU32(0x6990, (3 << 26) | ((0xBF001000 >> 2) & ((1 << 26) - 1))); #if 0 BIOSROM->WriteU32(0x691C, (3 << 26) | ((0xBF001000 >> 2) & ((1 << 26) - 1))); #endif uint8 *po; po = &PIOMem->data8[0x0800]; MDFN_en32lsb(po, (0x0 << 26) | (31 << 21) | (0x8 << 0)); // JR po += 4; MDFN_en32lsb(po, 0); // NOP(kinda) po += 4; po = &PIOMem->data8[0x1000]; // Load cacheable-region target PC into r2 MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | (0x9F001010 >> 16)); // LUI po += 4; MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (2 << 16) | (0x9F001010 & 0xFFFF)); // ORI po += 4; // Jump to r2 MDFN_en32lsb(po, (0x0 << 26) | (2 << 21) | (0x8 << 0)); // JR po += 4; MDFN_en32lsb(po, 0); // NOP(kinda) po += 4; // // 0x9F001010: // // Load source address into r8 uint32 sa = 0x9F000000 + 65536; MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | (sa >> 16)); // LUI po += 4; MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (8 << 16) | (sa & 0xFFFF)); // ORI po += 4; // Load dest address into r9 MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | (TextMem_Start >> 16)); // LUI po += 4; MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (9 << 16) | (TextMem_Start & 0xFFFF)); // ORI po += 4; // Load size into r10 MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | (TextMem.size() >> 16)); // LUI po += 4; MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (10 << 16) | (TextMem.size() & 0xFFFF)); // ORI po += 4; // // Loop begin // MDFN_en32lsb(po, (0x24 << 26) | (8 << 21) | (1 << 16)); // LBU to r1 po += 4; MDFN_en32lsb(po, (0x08 << 26) | (10 << 21) | (10 << 16) | 0xFFFF); // Decrement size po += 4; MDFN_en32lsb(po, (0x28 << 26) | (9 << 21) | (1 << 16)); // SB from r1 po += 4; MDFN_en32lsb(po, (0x08 << 26) | (8 << 21) | (8 << 16) | 0x0001); // Increment source addr po += 4; MDFN_en32lsb(po, (0x05 << 26) | (0 << 21) | (10 << 16) | (-5 & 0xFFFF)); po += 4; MDFN_en32lsb(po, (0x08 << 26) | (9 << 21) | (9 << 16) | 0x0001); // Increment dest addr po += 4; // // Loop end // // Load SP into r29 if(ignore_pcsp) { po += 16; } else { MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | (SP >> 16)); // LUI po += 4; MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (29 << 16) | (SP & 0xFFFF)); // ORI po += 4; // Load PC into r2 MDFN_en32lsb(po, (0xF << 26) | (0 << 21) | (1 << 16) | ((PC >> 16) | 0x8000)); // LUI po += 4; MDFN_en32lsb(po, (0xD << 26) | (1 << 21) | (2 << 16) | (PC & 0xFFFF)); // ORI po += 4; } // Half-assed instruction cache flush. ;) for(unsigned i = 0; i < 1024; i++) { MDFN_en32lsb(po, 0); po += 4; } // Jump to r2 MDFN_en32lsb(po, (0x0 << 26) | (2 << 21) | (0x8 << 0)); // JR po += 4; MDFN_en32lsb(po, 0); // NOP(kinda) po += 4; } static void Cleanup(void); static int Load(const char *name, MDFNFILE *fp) { const bool IsPSF = false; if(!TestMagic(name, fp)) throw MDFN_Error(0, _("File format is unknown to module \"%s\"."), MDFNGameInfo->shortname); InitCommon(NULL, !IsPSF, true); TextMem.resize(0); if(GET_FSIZE_PTR(fp) >= 0x800) LoadEXE(GET_FDATA_PTR(fp), GET_FSIZE_PTR(fp)); return(1); } static int LoadCD(std::vector *CDInterfaces) { InitCommon(CDInterfaces); MDFNGameInfo->GameType = GMT_CDROM; return(1); } static void Cleanup(void) { TextMem.resize(0); if(CDC) delete CDC; CDC = NULL; if(SPU) delete SPU; SPU = NULL; if(GPU) delete GPU; GPU = NULL; if(CPU) delete CPU; CPU = NULL; if(FIO) delete FIO; FIO = NULL; DMA_Kill(); if(BIOSROM) delete BIOSROM; BIOSROM = NULL; if(PIOMem) delete PIOMem; PIOMem = NULL; cdifs = NULL; } static void CloseGame(void) { int i; for(i = 0; i < 8; i++) { if (i == 0 && !use_mednafen_memcard0_method) { FIO->SaveMemcard(i); continue; } // If there's an error saving one memcard, don't skip trying to save the other, since it might succeed and // we can reduce potential data loss! try { char ext[64]; const char *memcard = NULL; snprintf(ext, sizeof(ext), "%d.mcr", i); memcard = MDFN_MakeFName(MDFNMKF_SAV, 0, ext); FIO->SaveMemcard(i, memcard); } catch(std::exception &e) { log_cb(RETRO_LOG_ERROR, "%s\n", e.what()); } } Cleanup(); } static void SetInput(int port, const char *type, void *ptr) { FIO->SetInput(port, type, ptr); } static int StateAction(StateMem *sm, int load, int data_only) { #if 0 if(!MDFN_GetSettingB("psx.clobbers_lament")) { return(0); } #endif SFORMAT StateRegs[] = { SFVAR(CD_TrayOpen), SFVAR(CD_SelectedDisc), SFARRAY(MainRAM.data8, 1024 * 2048), SFARRAY32(SysControl.Regs, 9), SFVAR(PSX_PRNG.lcgo), SFVAR(PSX_PRNG.x), SFVAR(PSX_PRNG.y), SFVAR(PSX_PRNG.z), SFVAR(PSX_PRNG.c), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "MAIN"); // Call SetDisc() BEFORE we load CDC state, since SetDisc() has emulation side effects. We might want to clean this up in the future. if(load) { if(!cdifs || CD_SelectedDisc >= (int)cdifs->size()) CD_SelectedDisc = -1; CDC->SetDisc(CD_TrayOpen, (CD_SelectedDisc >= 0 && !CD_TrayOpen) ? (*cdifs)[CD_SelectedDisc] : NULL, (CD_SelectedDisc >= 0 && !CD_TrayOpen) ? cdifs_scex_ids[CD_SelectedDisc] : NULL); } // TODO: Remember to increment dirty count in memory card state loading routine. ret &= CPU->StateAction(sm, load, data_only); ret &= DMA_StateAction(sm, load, data_only); ret &= TIMER_StateAction(sm, load, data_only); ret &= SIO_StateAction(sm, load, data_only); ret &= CDC->StateAction(sm, load, data_only); ret &= MDEC_StateAction(sm, load, data_only); ret &= GPU->StateAction(sm, load, data_only); ret &= SPU->StateAction(sm, load, data_only); ret &= FIO->StateAction(sm, load, data_only); ret &= IRQ_StateAction(sm, load, data_only); // Do it last. if(load) { ForceEventUpdates(0); // FIXME to work with debugger step mode. } return(ret); } static void CDInsertEject(void) { CD_TrayOpen = !CD_TrayOpen; for(unsigned disc = 0; disc < cdifs->size(); disc++) { if(!(*cdifs)[disc]->Eject(CD_TrayOpen)) { MDFN_DispMessage(_("Eject error.")); CD_TrayOpen = !CD_TrayOpen; } } if(CD_TrayOpen) MDFN_DispMessage(_("Virtual CD Drive Tray Open")); else MDFN_DispMessage(_("Virtual CD Drive Tray Closed")); CDC->SetDisc(CD_TrayOpen, (CD_SelectedDisc >= 0 && !CD_TrayOpen) ? (*cdifs)[CD_SelectedDisc] : NULL, (CD_SelectedDisc >= 0 && !CD_TrayOpen) ? cdifs_scex_ids[CD_SelectedDisc] : NULL); } static void CDEject(void) { if(!CD_TrayOpen) CDInsertEject(); } static void CDSelect(void) { if(cdifs && CD_TrayOpen) { CD_SelectedDisc = (CD_SelectedDisc + 1) % (cdifs->size() + 1); if((unsigned)CD_SelectedDisc == cdifs->size()) CD_SelectedDisc = -1; if(CD_SelectedDisc == -1) MDFN_DispMessage(_("Disc absence selected.")); else MDFN_DispMessage(_("Disc %d of %d selected."), CD_SelectedDisc + 1, (int)cdifs->size()); } } static void DoSimpleCommand(int cmd) { switch(cmd) { case MDFN_MSC_RESET: PSX_Power(); break; case MDFN_MSC_POWER: PSX_Power(); break; case MDFN_MSC_INSERT_DISK: CDInsertEject(); break; case MDFN_MSC_SELECT_DISK: CDSelect(); break; case MDFN_MSC_EJECT_DISK: CDEject(); break; } } static void GSCondCode(MemoryPatch* patch, const char* cc, const unsigned len, const uint32 addr, const uint16 val) { char tmp[256]; if(patch->conditions.size() > 0) patch->conditions.append(", "); if(len == 2) trio_snprintf(tmp, 256, "%u L 0x%08x %s 0x%04x", len, addr, cc, val & 0xFFFFU); else trio_snprintf(tmp, 256, "%u L 0x%08x %s 0x%02x", len, addr, cc, val & 0xFFU); patch->conditions.append(tmp); } static bool DecodeGS(const std::string& cheat_string, MemoryPatch* patch) { uint64 code = 0; unsigned nybble_count = 0; for(unsigned i = 0; i < cheat_string.size(); i++) { if(cheat_string[i] == ' ' || cheat_string[i] == '-' || cheat_string[i] == ':') continue; nybble_count++; code <<= 4; if(cheat_string[i] >= '0' && cheat_string[i] <= '9') code |= cheat_string[i] - '0'; else if(cheat_string[i] >= 'a' && cheat_string[i] <= 'f') code |= cheat_string[i] - 'a' + 0xA; else if(cheat_string[i] >= 'A' && cheat_string[i] <= 'F') code |= cheat_string[i] - 'A' + 0xA; else { if(cheat_string[i] & 0x80) log_cb(RETRO_LOG_ERROR, "[Mednafen]: Invalid character in GameShark code..\n"); else log_cb(RETRO_LOG_ERROR, "[Mednafen]: Invalid character in GameShark code: %c.\n", cheat_string[i]); return false; } } if(nybble_count != 12) { log_cb(RETRO_LOG_ERROR, "GameShark code is of an incorrect length.\n"); return false; } const uint8 code_type = code >> 40; const uint64 cl = code & 0xFFFFFFFFFFULL; patch->bigendian = false; patch->compare = 0; if(patch->type == 'T') { if(code_type != 0x80) log_cb(RETRO_LOG_ERROR, "Unrecognized GameShark code type for second part to copy bytes code.\n"); patch->addr = cl >> 16; return(false); } switch(code_type) { default: log_cb(RETRO_LOG_ERROR, "GameShark code type 0x%02X is currently not supported.\n", code_type); return(false); // TODO: case 0x10: // 16-bit increment patch->length = 2; patch->type = 'A'; patch->addr = cl >> 16; patch->val = cl & 0xFFFF; return(false); case 0x11: // 16-bit decrement patch->length = 2; patch->type = 'A'; patch->addr = cl >> 16; patch->val = (0 - cl) & 0xFFFF; return(false); case 0x20: // 8-bit increment patch->length = 1; patch->type = 'A'; patch->addr = cl >> 16; patch->val = cl & 0xFF; return(false); case 0x21: // 8-bit decrement patch->length = 1; patch->type = 'A'; patch->addr = cl >> 16; patch->val = (0 - cl) & 0xFF; return(false); // // // case 0x30: // 8-bit constant patch->length = 1; patch->type = 'R'; patch->addr = cl >> 16; patch->val = cl & 0xFF; return(false); case 0x80: // 16-bit constant patch->length = 2; patch->type = 'R'; patch->addr = cl >> 16; patch->val = cl & 0xFFFF; return(false); case 0x50: // Repeat thingy { const uint8 wcount = (cl >> 24) & 0xFF; const uint8 addr_inc = (cl >> 16) & 0xFF; const uint8 val_inc = (cl >> 0) & 0xFF; patch->mltpl_count = wcount; patch->mltpl_addr_inc = addr_inc; patch->mltpl_val_inc = val_inc; } return(true); case 0xC2: // Copy { const uint16 ccount = cl & 0xFFFF; patch->type = 'T'; patch->val = 0; patch->length = 1; patch->copy_src_addr = cl >> 16; patch->copy_src_addr_inc = 1; patch->mltpl_count = ccount; patch->mltpl_addr_inc = 1; patch->mltpl_val_inc = 0; } return(true); case 0xD0: // 16-bit == condition GSCondCode(patch, "==", 2, cl >> 16, cl); return(true); case 0xD1: // 16-bit != condition GSCondCode(patch, "!=", 2, cl >> 16, cl); return(true); case 0xD2: // 16-bit < condition GSCondCode(patch, "<", 2, cl >> 16, cl); return(true); case 0xD3: // 16-bit > condition GSCondCode(patch, ">", 2, cl >> 16, cl); return(true); case 0xE0: // 8-bit == condition GSCondCode(patch, "==", 1, cl >> 16, cl); return(true); case 0xE1: // 8-bit != condition GSCondCode(patch, "!=", 1, cl >> 16, cl); return(true); case 0xE2: // 8-bit < condition GSCondCode(patch, "<", 1, cl >> 16, cl); return(true); case 0xE3: // 8-bit > condition GSCondCode(patch, ">", 1, cl >> 16, cl); return(true); } } static CheatFormatStruct CheatFormats[] = { { "GameShark", "Sharks with lamprey eels for eyes.", DecodeGS }, }; static CheatFormatInfoStruct CheatFormatInfo = { 1, CheatFormats }; static const FileExtensionSpecStruct KnownExtensions[] = { { ".psf", "PSF1 Rip" }, { ".psx", "PS-X Executable" }, { ".exe", "PS-X Executable" }, { NULL, NULL } }; static const MDFNSetting_EnumList Region_List[] = { { "jp", REGION_JP, "Japan" }, { "na", REGION_NA, "North America" }, { "eu", REGION_EU, "Europe" }, { NULL, 0 }, }; #if 0 static const MDFNSetting_EnumList MultiTap_List[] = { { "0", 0, "Disabled" }, { "1", 1, "Enabled" }, { "auto", 0, "Automatically-enable multitap.", "NOT IMPLEMENTED YET(currently equivalent to 0") }, { NULL, 0 }, }; #endif static MDFNSetting PSXSettings[] = { { "psx.input.mouse_sensitivity", MDFNSF_NOFLAGS, "Emulated mouse sensitivity.", NULL, MDFNST_FLOAT, "1.00", NULL, NULL }, { "psx.input.analog_mode_ct", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Enable analog mode combo-button alternate toggle.", "When enabled, instead of the configured Analog mode toggle button for the emulated DualShock, use a combination of buttons to toggle it instead. When Select, Start, and all four shoulder buttons are held down for about 1 second, the mode will toggle.", MDFNST_BOOL, "0", NULL, NULL }, { "psx.input.pport1.multitap", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Enable multitap on PSX port 1.", "Makes 3 more virtual ports available.\n\nNOTE: Enabling multitap in games that don't fully support it may cause deleterious effects.", MDFNST_BOOL, "0", NULL, NULL }, //MDFNST_ENUM, "auto", NULL, NULL, NULL, NULL, MultiTap_List }, { "psx.input.pport2.multitap", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Enable multitap on PSX port 2.", "Makes 3 more virtual ports available.\n\nNOTE: Enabling multitap in games that don't fully support it may cause deleterious effects.", MDFNST_BOOL, "0", NULL, NULL }, { "psx.input.port1.memcard", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Emulate memcard on virtual port 1.", NULL, MDFNST_BOOL, "1", NULL, NULL, }, { "psx.input.port2.memcard", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Emulate memcard on virtual port 2.", NULL, MDFNST_BOOL, "1", NULL, NULL, }, { "psx.input.port3.memcard", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Emulate memcard on virtual port 3.", NULL, MDFNST_BOOL, "1", NULL, NULL, }, { "psx.input.port4.memcard", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Emulate memcard on virtual port 4.", NULL, MDFNST_BOOL, "1", NULL, NULL, }, { "psx.input.port5.memcard", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Emulate memcard on virtual port 5.", NULL, MDFNST_BOOL, "1", NULL, NULL, }, { "psx.input.port6.memcard", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Emulate memcard on virtual port 6.", NULL, MDFNST_BOOL, "1", NULL, NULL, }, { "psx.input.port7.memcard", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Emulate memcard on virtual port 7.", NULL, MDFNST_BOOL, "1", NULL, NULL, }, { "psx.input.port8.memcard", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Emulate memcard on virtual port 8.", NULL, MDFNST_BOOL, "1", NULL, NULL, }, { "psx.input.port1.gun_chairs", MDFNSF_NOFLAGS, "Crosshairs color for lightgun on virtual port 1.", "A value of 0x1000000 disables crosshair drawing.", MDFNST_UINT, "0xFF0000", "0x000000", "0x1000000" }, { "psx.input.port2.gun_chairs", MDFNSF_NOFLAGS, "Crosshairs color for lightgun on virtual port 2.", "A value of 0x1000000 disables crosshair drawing.", MDFNST_UINT, "0x00FF00", "0x000000", "0x1000000" }, { "psx.input.port3.gun_chairs", MDFNSF_NOFLAGS, "Crosshairs color for lightgun on virtual port 3.", "A value of 0x1000000 disables crosshair drawing.", MDFNST_UINT, "0xFF00FF", "0x000000", "0x1000000" }, { "psx.input.port4.gun_chairs", MDFNSF_NOFLAGS, "Crosshairs color for lightgun on virtual port 4.", "A value of 0x1000000 disables crosshair drawing.", MDFNST_UINT, "0xFF8000", "0x000000", "0x1000000" }, { "psx.input.port5.gun_chairs", MDFNSF_NOFLAGS, "Crosshairs color for lightgun on virtual port 5.", "A value of 0x1000000 disables crosshair drawing.", MDFNST_UINT, "0xFFFF00", "0x000000", "0x1000000" }, { "psx.input.port6.gun_chairs", MDFNSF_NOFLAGS, "Crosshairs color for lightgun on virtual port 6.", "A value of 0x1000000 disables crosshair drawing.", MDFNST_UINT, "0x00FFFF", "0x000000", "0x1000000" }, { "psx.input.port7.gun_chairs", MDFNSF_NOFLAGS, "Crosshairs color for lightgun on virtual port 7.", "A value of 0x1000000 disables crosshair drawing.", MDFNST_UINT, "0x0080FF", "0x000000", "0x1000000" }, { "psx.input.port8.gun_chairs", MDFNSF_NOFLAGS, "Crosshairs color for lightgun on virtual port 8.", "A value of 0x1000000 disables crosshair drawing.", MDFNST_UINT, "0x8000FF", "0x000000", "0x1000000" }, { "psx.region_autodetect", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Attempt to auto-detect region of game.", NULL, MDFNST_BOOL, "1" }, { "psx.region_default", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Default region to use.", "Used if region autodetection fails or is disabled.", MDFNST_ENUM, "jp", NULL, NULL, NULL, NULL, Region_List }, { "psx.bios_jp", MDFNSF_EMU_STATE, "Path to the Japan SCPH-5500 ROM BIOS", NULL, MDFNST_STRING, "scph5500.bin" }, { "psx.bios_na", MDFNSF_EMU_STATE, "Path to the North America SCPH-5501 ROM BIOS", "SHA1 0555c6fae8906f3f09baf5988f00e55f88e9f30b", MDFNST_STRING, "scph5501.bin" }, { "psx.bios_eu", MDFNSF_EMU_STATE, "Path to the Europe SCPH-5502 ROM BIOS", NULL, MDFNST_STRING, "scph5502.bin" }, { "psx.spu.resamp_quality", MDFNSF_NOFLAGS, "SPU output resampler quality.", "0 is lowest quality and CPU usage, 10 is highest quality and CPU usage. The resampler that this setting refers to is used for converting from 44.1KHz to the sampling rate of the host audio device Mednafen is using. Changing Mednafen's output rate, via the \"sound.rate\" setting, to \"44100\" will bypass the resampler, which will decrease CPU usage by Mednafen, and can increase or decrease audio quality, depending on various operating system and hardware factors.", MDFNST_UINT, "5", "0", "10" }, { "psx.slstart", MDFNSF_NOFLAGS, "First displayed scanline in NTSC mode.", NULL, MDFNST_INT, "0", "0", "239" }, { "psx.slend", MDFNSF_NOFLAGS, "Last displayed scanline in NTSC mode.", NULL, MDFNST_INT, "239", "0", "239" }, { "psx.slstartp", MDFNSF_NOFLAGS, "First displayed scanline in PAL mode.", NULL, MDFNST_INT, "0", "0", "287" }, { "psx.slendp", MDFNSF_NOFLAGS, "Last displayed scanline in PAL mode.", NULL, MDFNST_INT, "287", "0", "287" }, #if PSX_DBGPRINT_ENABLE { "psx.dbg_level", MDFNSF_NOFLAGS, "Debug printf verbosity level.", NULL, MDFNST_UINT, "0", "0", "4" }, #endif { "psx.clobbers_lament", MDFNSF_NOFLAGS, "Enable experimental save state functionality.", "Save states will destroy your saved game/memory card data if you're careless, and that will make clobber sad. Poor clobber.", MDFNST_BOOL, "0" }, { NULL }, }; // Note for the future: If we ever support PSX emulation with non-8-bit RGB color components, or add a new linear RGB colorspace to MDFN_PixelFormat, we'll need // to buffer the intermediate 24-bit non-linear RGB calculation into an array and pass that into the GPULineHook stuff, otherwise netplay could break when // an emulated GunCon is used. This IS assuming, of course, that we ever implement save state support so that netplay actually works at all... MDFNGI EmulatedPSX = { "psx", "Sony PlayStation", KnownExtensions, MODPRIO_INTERNAL_HIGH, #ifdef WANT_DEBUGGER &PSX_DBGInfo, #else NULL, #endif &FIO_InputInfo, Load, TestMagic, LoadCD, TestMagicCD, CloseGame, NULL, //ToggleLayer, "GPU\0", //"Background Scroll\0Foreground Scroll\0Sprites\0", NULL, NULL, NULL, NULL, NULL, NULL, false, StateAction, NULL, SetInput, DoSimpleCommand, PSXSettings, MDFN_MASTERCLOCK_FIXED(33868800), 0, true, // Multires possible? // // Note: Following video settings will be overwritten during game load. // 0, // lcm_width 0, // lcm_height NULL, // Dummy 320, // Nominal width 240, // Nominal height 0, // Framebuffer width 0, // Framebuffer height // // // 2, // Number of output sound channels }; /* end of Mednafen psx.cpp */ //forward decls extern void Emulate(EmulateSpecStruct *espec); extern void SetInput(int port, const char *type, void *ptr); static bool overscan; static double last_sound_rate; static MDFN_Surface *surf; static bool failed_init; char *psx_analog_type; #define RETRO_DEVICE_PS1PAD RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 0) #define RETRO_DEVICE_DUALANALOG RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_ANALOG, 0) #define RETRO_DEVICE_DUALSHOCK RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_ANALOG, 1) #define RETRO_DEVICE_FLIGHTSTICK RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_ANALOG, 2) ; #ifdef NEED_DEINTERLACER static bool PrevInterlaced; static Deinterlacer deint; #endif #define MEDNAFEN_CORE_NAME_MODULE "psx" #define MEDNAFEN_CORE_NAME "Mednafen PSX" #define MEDNAFEN_CORE_VERSION "v0.9.38.6" #define MEDNAFEN_CORE_EXTENSIONS "cue|toc|ccd|m3u" #define MEDNAFEN_CORE_GEOMETRY_BASE_W 320 #define MEDNAFEN_CORE_GEOMETRY_BASE_H 240 #define MEDNAFEN_CORE_GEOMETRY_MAX_W 700 #define MEDNAFEN_CORE_GEOMETRY_MAX_H 576 #define MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO (4.0 / 3.0) static void check_system_specs(void) { // Hints that we need a fairly powerful system to run this. unsigned level = 15; environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); } static unsigned disk_get_num_images(void) { return cdifs ? cdifs->size() : 0; } static bool eject_state; static bool disk_set_eject_state(bool ejected) { log_cb(RETRO_LOG_INFO, "[Mednafen]: Ejected: %u.\n", ejected); if (ejected == eject_state) return false; DoSimpleCommand(ejected ? MDFN_MSC_EJECT_DISK : MDFN_MSC_INSERT_DISK); eject_state = ejected; return true; } static bool disk_get_eject_state(void) { return eject_state; } static unsigned disk_get_image_index(void) { // PSX global. Hacky. return CD_SelectedDisc; } static bool disk_set_image_index(unsigned index) { CD_SelectedDisc = index; if (CD_SelectedDisc > disk_get_num_images()) CD_SelectedDisc = disk_get_num_images(); // Very hacky. CDSelect command will increment first. CD_SelectedDisc--; DoSimpleCommand(MDFN_MSC_SELECT_DISK); return true; } // Mednafen PSX really doesn't support adding disk images on the fly ... // Hack around this. static void update_md5_checksum(CDIF *iface) { uint8 LayoutMD5[16]; md5_context layout_md5; CD_TOC toc; md5_starts(&layout_md5); TOC_Clear(&toc); iface->ReadTOC(&toc); md5_update_u32_as_lsb(&layout_md5, toc.first_track); md5_update_u32_as_lsb(&layout_md5, toc.last_track); md5_update_u32_as_lsb(&layout_md5, toc.tracks[100].lba); for (uint32 track = toc.first_track; track <= toc.last_track; track++) { md5_update_u32_as_lsb(&layout_md5, toc.tracks[track].lba); md5_update_u32_as_lsb(&layout_md5, toc.tracks[track].control & 0x4); } md5_finish(&layout_md5, LayoutMD5); memcpy(MDFNGameInfo->MD5, LayoutMD5, 16); char *md5 = md5_asciistr(MDFNGameInfo->MD5); log_cb(RETRO_LOG_INFO, "[Mednafen]: Updated md5 checksum: %s.\n", md5); } // Untested ... static bool disk_replace_image_index(unsigned index, const struct retro_game_info *info) { if (index >= disk_get_num_images()) return false; if (!eject_state) return false; if (!info) { delete cdifs->at(index); cdifs->erase(cdifs->begin() + index); if (index < CD_SelectedDisc) CD_SelectedDisc--; // Poke into psx.cpp CalcDiscSCEx(); return true; } try { CDIF *iface = CDIF_Open(info->path, false, false); delete cdifs->at(index); cdifs->at(index) = iface; CalcDiscSCEx(); /* If we replace, we want the "swap disk manually effect". */ extract_basename(retro_cd_base_name, info->path, sizeof(retro_cd_base_name)); /* Ugly, but needed to get proper disk swapping effect. */ update_md5_checksum(iface); return true; } catch (const std::exception &e) { return false; } } static bool disk_add_image_index(void) { cdifs->push_back(NULL); return true; } static struct retro_disk_control_callback disk_interface = { disk_set_eject_state, disk_get_eject_state, disk_get_image_index, disk_set_image_index, disk_get_num_images, disk_replace_image_index, disk_add_image_index, }; static void fallback_log(enum retro_log_level level, const char *fmt, ...) { } void retro_init(void) { struct retro_log_callback log; if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) log_cb = log.log; else log_cb = fallback_log; #ifdef NEED_CD CDUtility_Init(); #endif eject_state = false; const char *dir = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) { snprintf(retro_base_directory, sizeof(retro_base_directory), "%s", dir); } else { /* TODO: Add proper fallback */ log_cb(RETRO_LOG_WARN, "System directory is not defined. Fallback on using same dir as ROM for system directory later ...\n"); failed_init = true; } if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &dir) && dir) { // If save directory is defined use it, otherwise use system directory if (dir) snprintf(retro_save_directory, sizeof(retro_save_directory), "%s", dir); else snprintf(retro_save_directory, sizeof(retro_save_directory), "%s", retro_base_directory); } else { /* TODO: Add proper fallback */ log_cb(RETRO_LOG_WARN, "Save directory is not defined. Fallback on using SYSTEM directory ...\n"); snprintf(retro_save_directory, sizeof(retro_save_directory), "%s", retro_base_directory); } environ_cb(RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE, &disk_interface); if (environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb)) perf_get_cpu_features_cb = perf_cb.get_cpu_features; else perf_get_cpu_features_cb = NULL; setting_initial_scanline = 0; setting_last_scanline = 239; setting_initial_scanline_pal = 0; setting_last_scanline_pal = 287; check_system_specs(); } void retro_reset(void) { DoSimpleCommand(MDFN_MSC_RESET); } bool retro_load_game_special(unsigned, const struct retro_game_info *, size_t) { return false; } static bool old_cdimagecache = false; static bool boot = true; // shared memory cards support static bool shared_memorycards = false; static bool shared_memorycards_toggle = false; static void check_variables(void) { struct retro_variable var = {0}; extern void PSXDitherApply(bool); var.key = "beetle_psx_cdimagecache"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { bool cdimage_cache = true; if (strcmp(var.value, "enabled") == 0) cdimage_cache = true; else if (strcmp(var.value, "disabled") == 0) cdimage_cache = false; if (cdimage_cache != old_cdimagecache) { old_cdimagecache = cdimage_cache; } } var.key = "beetle_psx_widescreen_hack"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "enabled") == 0) widescreen_hack = true; else if (strcmp(var.value, "disabled") == 0) widescreen_hack = false; } else widescreen_hack = false; var.key = "beetle_psx_widescreen_auto_ar"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "enabled") == 0 && widescreen_hack) widescreen_auto_ar = true; else if (strcmp(var.value, "disabled") == 0) widescreen_auto_ar = false; } else widescreen_auto_ar = false; var.key = "beetle_psx_analog_toggle"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if ((strcmp(var.value, "enabled") == 0) && setting_psx_analog_toggle != 1) { setting_psx_analog_toggle = 1; setting_apply_analog_toggle = true; } else if ((strcmp(var.value, "disabled") == 0) && setting_psx_analog_toggle != 0) { setting_psx_analog_toggle = 0; setting_apply_analog_toggle = true; } } var.key = "beetle_psx_enable_multitap_port1"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "enabled") == 0) setting_psx_multitap_port_1 = true; else if (strcmp(var.value, "disabled") == 0) setting_psx_multitap_port_1 = false; } var.key = "beetle_psx_enable_multitap_port2"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "enabled") == 0) setting_psx_multitap_port_2 = true; else if (strcmp(var.value, "disabled") == 0) setting_psx_multitap_port_2 = false; } var.key = "beetle_psx_initial_scanline"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { setting_initial_scanline = atoi(var.value); } var.key = "beetle_psx_last_scanline"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { setting_last_scanline = atoi(var.value); } var.key = "beetle_psx_initial_scanline_pal"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { setting_initial_scanline_pal = atoi(var.value); } var.key = "beetle_psx_last_scanline_pal"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { setting_last_scanline_pal = atoi(var.value); } if(setting_psx_multitap_port_1) { if(setting_psx_multitap_port_2) players = 8; else players = 4; } else { if(setting_psx_multitap_port_2) players = 4; else players = 2; } var.key = "beetle_psx_use_mednafen_memcard0_method"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "libretro") == 0) use_mednafen_memcard0_method = false; else if (strcmp(var.value, "mednafen") == 0) use_mednafen_memcard0_method = true; } //this option depends on beetle_psx_use_mednafen_memcard0_method being disabled so it should be evaluated that var.key = "beetle_psx_shared_memory_cards"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "enabled") == 0) { if(boot) { if(use_mednafen_memcard0_method) shared_memorycards_toggle = true; } else { if(use_mednafen_memcard0_method) shared_memorycards_toggle = true; } } else if (strcmp(var.value, "disabled") == 0) { if(boot) shared_memorycards_toggle = false; else { shared_memorycards = false; } } } } #ifdef NEED_CD static void ReadM3U(std::vector &file_list, std::string path, unsigned depth = 0) { std::string dir_path; char linebuf[2048]; FILE *fp = fopen(path.c_str(), "rb"); if (fp == NULL) return; MDFN_GetFilePathComponents(path, &dir_path); while(fgets(linebuf, sizeof(linebuf), fp) != NULL) { std::string efp; if(linebuf[0] == '#') continue; MDFN_rtrim(linebuf); if(linebuf[0] == 0) continue; efp = MDFN_EvalFIP(dir_path, std::string(linebuf)); if(efp.size() >= 4 && efp.substr(efp.size() - 4) == ".m3u") { if(efp == path) { log_cb(RETRO_LOG_ERROR, "M3U at \"%s\" references self.\n", efp.c_str()); goto end; } if(depth == 99) { log_cb(RETRO_LOG_ERROR, "M3U load recursion too deep!\n"); goto end; } ReadM3U(file_list, efp, depth++); } else file_list.push_back(efp); } end: fclose(fp); } #ifdef NEED_CD static std::vector CDInterfaces; // FIXME: Cleanup on error out. #endif // TODO: LoadCommon() MDFNGI *MDFNI_LoadCD(const char *force_module, const char *devicename) { uint8 LayoutMD5[16]; log_cb(RETRO_LOG_INFO, "Loading %s...\n", devicename ? devicename : "PHYSICAL CD"); try { if(devicename && strlen(devicename) > 4 && !strcasecmp(devicename + strlen(devicename) - 4, ".m3u")) { std::vector file_list; ReadM3U(file_list, devicename); for(unsigned i = 0; i < file_list.size(); i++) { CDInterfaces.push_back(CDIF_Open(file_list[i].c_str(), false, old_cdimagecache)); } } else { CDInterfaces.push_back(CDIF_Open(devicename, false, old_cdimagecache)); } } catch(std::exception &e) { log_cb(RETRO_LOG_ERROR, "Error opening CD.\n"); return(0); } // // Print out a track list for all discs. // for(unsigned i = 0; i < CDInterfaces.size(); i++) { TOC toc; TOC_Clear(&toc); CDInterfaces[i]->ReadTOC(&toc); log_cb(RETRO_LOG_DEBUG, "CD %d Layout:\n", i + 1); for(int32 track = toc.first_track; track <= toc.last_track; track++) { log_cb(RETRO_LOG_DEBUG, "Track %2d, LBA: %6d %s\n", track, toc.tracks[track].lba, (toc.tracks[track].control & 0x4) ? "DATA" : "AUDIO"); } log_cb(RETRO_LOG_DEBUG, "Leadout: %6d\n", toc.tracks[100].lba); } // Calculate layout MD5. The system emulation LoadCD() code is free to ignore this value and calculate // its own, or to use it to look up a game in its database. { md5_context layout_md5; md5_starts(&layout_md5); for(unsigned i = 0; i < CDInterfaces.size(); i++) { CD_TOC toc; TOC_Clear(&toc); CDInterfaces[i]->ReadTOC(&toc); md5_update_u32_as_lsb(&layout_md5, toc.first_track); md5_update_u32_as_lsb(&layout_md5, toc.last_track); md5_update_u32_as_lsb(&layout_md5, toc.tracks[100].lba); for(uint32 track = toc.first_track; track <= toc.last_track; track++) { md5_update_u32_as_lsb(&layout_md5, toc.tracks[track].lba); md5_update_u32_as_lsb(&layout_md5, toc.tracks[track].control & 0x4); } } md5_finish(&layout_md5, LayoutMD5); } // This if statement will be true if force_module references a system without CDROM support. if(!MDFNGameInfo->LoadCD) { log_cb(RETRO_LOG_ERROR, "Specified system \"%s\" doesn't support CDs!", force_module); return 0; } // TODO: include module name in hash memcpy(MDFNGameInfo->MD5, LayoutMD5, 16); if(!(MDFNGameInfo->LoadCD(&CDInterfaces))) { for(unsigned i = 0; i < CDInterfaces.size(); i++) delete CDInterfaces[i]; CDInterfaces.clear(); MDFNGameInfo = NULL; return(0); } //MDFNI_SetLayerEnableMask(~0ULL); MDFN_LoadGameCheats(NULL); MDFNMP_InstallReadPatches(); return(MDFNGameInfo); } #endif static MDFNGI *MDFNI_LoadGame(const char *force_module, const char *name) { MDFNFILE *GameFile = file_open(name); if(!GameFile) goto error; #ifdef NEED_CD if(strlen(name) > 4 && (!strcasecmp(name + strlen(name) - 4, ".cue") || !strcasecmp(name + strlen(name) - 4, ".ccd") || !strcasecmp(name + strlen(name) - 4, ".toc") || !strcasecmp(name + strlen(name) - 4, ".m3u"))) return(MDFNI_LoadCD(force_module, name)); #endif if(MDFNGameInfo->Load(name, GameFile) <= 0) goto error; file_close(GameFile); GameFile = NULL; if(!MDFNGameInfo->name) { unsigned int x; char *tmp; MDFNGameInfo->name = (UTF8 *)strdup(GetFNComponent(name)); for(x=0;xname);x++) { if(MDFNGameInfo->name[x] == '_') MDFNGameInfo->name[x] = ' '; } if((tmp = strrchr((char *)MDFNGameInfo->name, '.'))) *tmp = 0; } return(MDFNGameInfo); error: if (GameFile) file_close(GameFile); GameFile = NULL; MDFNGameInfo = NULL; return NULL; } #define MAX_PLAYERS 8 #define MAX_BUTTONS 16 union { uint32_t u32[MAX_PLAYERS][1 + 8 + 1]; // Buttons + Axes + Rumble uint8_t u8[MAX_PLAYERS][(1 + 8 + 1) * sizeof(uint32_t)]; } static buf; static uint16_t input_buf[MAX_PLAYERS] = {0}; bool retro_load_game(const struct retro_game_info *info) { char tocbasepath[4096]; if (failed_init) return false; struct retro_input_descriptor desc[] = { { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 2, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 2, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, { 2, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, { 2, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, { 2, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 3, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 3, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, { 3, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, { 3, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, { 3, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 4, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 4, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, { 4, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, { 4, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, { 4, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 5, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, { 5, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 6, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, { 6, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Cross" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Circle" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Triangle" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Square" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "L1" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "L2" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3, "L3" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "R1" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "R2" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3, "R3" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Select" }, { 7, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" }, { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" }, { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" }, { 7, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" }, { 0 }, }; environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888; if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) return false; overscan = false; environ_cb(RETRO_ENVIRONMENT_GET_OVERSCAN, &overscan); extract_basename(retro_cd_base_name, info->path, sizeof(retro_cd_base_name)); extract_directory(retro_cd_base_directory, info->path, sizeof(retro_cd_base_directory)); snprintf(tocbasepath, sizeof(tocbasepath), "%s%c%s.toc", retro_cd_base_directory, retro_slash, retro_cd_base_name); if (path_is_valid(tocbasepath)) snprintf(retro_cd_path, sizeof(retro_cd_path), "%s", tocbasepath); else snprintf(retro_cd_path, sizeof(retro_cd_path), "%s", info->path); log_cb(RETRO_LOG_INFO, "PATH IS NOW!!!!! %s\n", retro_cd_path); check_variables(); //make sure shared memory cards and save states are enabled only at startup shared_memorycards = shared_memorycards_toggle; if (environ_cb(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumble) && log_cb) log_cb(RETRO_LOG_INFO, "Rumble interface supported!\n"); if (!MDFNI_LoadGame(MEDNAFEN_CORE_NAME_MODULE, retro_cd_path)) return false; MDFN_LoadGameCheats(NULL); MDFNMP_InstallReadPatches(); MDFN_PixelFormat pix_fmt(MDFN_COLORSPACE_RGB, 16, 8, 0, 24); is_pal = (CalcDiscSCEx() == REGION_EU); surf = new MDFN_Surface(NULL, MEDNAFEN_CORE_GEOMETRY_MAX_W, is_pal ? MEDNAFEN_CORE_GEOMETRY_MAX_H : 480, MEDNAFEN_CORE_GEOMETRY_MAX_W, pix_fmt); #ifdef NEED_DEINTERLACER PrevInterlaced = false; deint.ClearState(); #endif //SetInput(0, "gamepad", &input_buf[0]); //SetInput(1, "gamepad", &input_buf[1]); for (unsigned i = 0; i < players; i++) { SetInput(i, "gamepad", &input_buf[i]); } boot = false; return true; } void retro_unload_game(void) { if(!MDFNGameInfo) return; MDFN_FlushGameCheats(0); MDFNGameInfo->CloseGame(); if(MDFNGameInfo->name) free(MDFNGameInfo->name); MDFNGameInfo->name = NULL; MDFNMP_Kill(); MDFNGameInfo = NULL; #ifdef NEED_CD for(unsigned i = 0; i < CDInterfaces.size(); i++) delete CDInterfaces[i]; CDInterfaces.clear(); #endif retro_cd_base_directory[0] = '\0'; retro_cd_path[0] = '\0'; retro_cd_base_name[0] = '\0'; } // Hardcoded for PSX. No reason to parse lots of structures ... // See mednafen/psx/input/gamepad.cpp static void update_input(void) { //input_buf[0] = 0; //input_buf[1] = 0; for (unsigned j = 0; j < players; j++) { input_buf[j] = 0; } static unsigned map[] = { RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_DEVICE_ID_JOYPAD_L3, RETRO_DEVICE_ID_JOYPAD_R3, RETRO_DEVICE_ID_JOYPAD_START, RETRO_DEVICE_ID_JOYPAD_UP, RETRO_DEVICE_ID_JOYPAD_RIGHT, RETRO_DEVICE_ID_JOYPAD_DOWN, RETRO_DEVICE_ID_JOYPAD_LEFT, RETRO_DEVICE_ID_JOYPAD_L2, RETRO_DEVICE_ID_JOYPAD_R2, RETRO_DEVICE_ID_JOYPAD_L, RETRO_DEVICE_ID_JOYPAD_R, RETRO_DEVICE_ID_JOYPAD_X, RETRO_DEVICE_ID_JOYPAD_A, RETRO_DEVICE_ID_JOYPAD_B, RETRO_DEVICE_ID_JOYPAD_Y, }; for (unsigned j = 0; j < players; j++) { for (unsigned i = 0; i < MAX_BUTTONS; i++) input_buf[j] |= input_state_cb(j, RETRO_DEVICE_JOYPAD, 0, map[i]) ? (1 << i) : 0; } // Buttons. //buf.u8[0][0] = (input_buf[0] >> 0) & 0xff; //buf.u8[0][1] = (input_buf[0] >> 8) & 0xff; //buf.u8[1][0] = (input_buf[1] >> 0) & 0xff; //buf.u8[1][1] = (input_buf[1] >> 8) & 0xff; for (unsigned j = 0; j < players; j++) { buf.u8[j][0] = (input_buf[j] >> 0) & 0xff; buf.u8[j][1] = (input_buf[j] >> 8) & 0xff; } // Analogs for (unsigned j = 0; j < players; j++) { int analog_left_x = input_state_cb(j, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X); int analog_left_y = input_state_cb(j, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y); int analog_right_x = input_state_cb(j, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X); int analog_right_y = input_state_cb(j, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y); uint32_t r_right = analog_right_x > 0 ? analog_right_x : 0; uint32_t r_left = analog_right_x < 0 ? -analog_right_x : 0; uint32_t r_down = analog_right_y > 0 ? analog_right_y : 0; uint32_t r_up = analog_right_y < 0 ? -analog_right_y : 0; uint32_t l_right = analog_left_x > 0 ? analog_left_x : 0; uint32_t l_left = analog_left_x < 0 ? -analog_left_x : 0; uint32_t l_down = analog_left_y > 0 ? analog_left_y : 0; uint32_t l_up = analog_left_y < 0 ? -analog_left_y : 0; buf.u32[j][1] = r_right; buf.u32[j][2] = r_left; buf.u32[j][3] = r_down; buf.u32[j][4] = r_up; buf.u32[j][5] = l_right; buf.u32[j][6] = l_left; buf.u32[j][7] = l_down; buf.u32[j][8] = l_up; } //fprintf(stderr, "Rumble strong: %u, weak: %u.\n", buf.u8[0][9 * 4 + 1], buf.u8[0][9 * 4]); if (rumble.set_rumble_state) { // Appears to be correct. //rumble.set_rumble_state(0, RETRO_RUMBLE_WEAK, buf.u8[0][9 * 4] * 0x101); //rumble.set_rumble_state(0, RETRO_RUMBLE_STRONG, buf.u8[0][9 * 4 + 1] * 0x101); //rumble.set_rumble_state(1, RETRO_RUMBLE_WEAK, buf.u8[1][9 * 4] * 0x101); //rumble.set_rumble_state(1, RETRO_RUMBLE_STRONG, buf.u8[1][9 * 4 + 1] * 0x101); for (unsigned j = 0; j < players; j++) { rumble.set_rumble_state(j, RETRO_RUMBLE_WEAK, buf.u8[j][9 * 4] * 0x101); rumble.set_rumble_state(j, RETRO_RUMBLE_STRONG, buf.u8[j][9 * 4 + 1] * 0x101); } } } static uint64_t video_frames, audio_frames; #define SOUND_CHANNELS 2 void retro_run(void) { bool updated = false; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) { widescreen_auto_ar_old = widescreen_auto_ar; check_variables(); if (widescreen_auto_ar != widescreen_auto_ar_old) { struct retro_system_av_info new_av_info; retro_get_system_av_info(&new_av_info); environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &new_av_info); } } if (setting_apply_analog_toggle) { FIO->SetAMCT(setting_psx_analog_toggle); setting_apply_analog_toggle = false; } input_poll_cb(); update_input(); static int32 rects[MEDNAFEN_CORE_GEOMETRY_MAX_H]; rects[0] = ~0; EmulateSpecStruct spec = {0}; spec.surface = surf; spec.SoundRate = 44100; spec.SoundBuf = NULL; spec.LineWidths = rects; spec.SoundBufMaxSize = 0; spec.SoundVolume = 1.0; spec.soundmultiplier = 1.0; spec.SoundBufSize = 0; spec.VideoFormatChanged = false; spec.SoundFormatChanged = false; EmulateSpecStruct *espec = (EmulateSpecStruct*)&spec; /* start of Emulate */ int32_t timestamp = 0; espec->skip = false; MDFNGameInfo->mouse_sensitivity = MDFN_GetSettingF("psx.input.mouse_sensitivity"); MDFNMP_ApplyPeriodicCheats(); espec->MasterCycles = 0; espec->SoundBufSize = 0; FIO->UpdateInput(); GPU->StartFrame(espec); Running = -1; timestamp = CPU->Run(timestamp); assert(timestamp); ForceEventUpdates(timestamp); if(GPU->GetScanlineNum() < 100) PSX_DBG(PSX_DBG_ERROR, "[BUUUUUUUG] Frame timing end glitch; scanline=%u, st=%u\n", GPU->GetScanlineNum(), timestamp); //printf("scanline=%u, st=%u\n", GPU->GetScanlineNum(), timestamp); espec->SoundBufSize = IntermediateBufferPos; IntermediateBufferPos = 0; CDC->ResetTS(); TIMER_ResetTS(); DMA_ResetTS(); GPU->ResetTS(); FIO->ResetTS(); RebaseTS(timestamp); espec->MasterCycles = timestamp; // Save memcards if dirty. for(int i = 0; i < players; i++) { uint64_t new_dc = FIO->GetMemcardDirtyCount(i); if(new_dc > Memcard_PrevDC[i]) { Memcard_PrevDC[i] = new_dc; Memcard_SaveDelay[i] = 0; } if(Memcard_SaveDelay[i] >= 0) { Memcard_SaveDelay[i] += timestamp; if(Memcard_SaveDelay[i] >= (33868800 * 2)) // Wait until about 2 seconds of no new writes. { char ext[64]; const char *memcard = NULL; log_cb(RETRO_LOG_INFO, "Saving memcard %d...\n", i); if (i == 0 && !use_mednafen_memcard0_method) { FIO->SaveMemcard(i); Memcard_SaveDelay[i] = -1; Memcard_PrevDC[i] = 0; continue; } snprintf(ext, sizeof(ext), "%d.mcr", i); memcard = MDFN_MakeFName(MDFNMKF_SAV, 0, ext); FIO->SaveMemcard(i, memcard); Memcard_SaveDelay[i] = -1; Memcard_PrevDC[i] = 0; } } } /* end of Emulate */ #ifdef NEED_DEINTERLACER if (spec.InterlaceOn) { if (!PrevInterlaced) deint.ClearState(); deint.Process(spec.surface, spec.DisplayRect, spec.LineWidths, spec.InterlaceField); PrevInterlaced = true; spec.InterlaceOn = false; spec.InterlaceField = 0; } else PrevInterlaced = false; #endif int16_t *interbuf = (int16_t*)&IntermediateBuffer; // PSX is rather special, and needs specific handling ... unsigned width = rects[0]; // spec.DisplayRect.w is 0. Only rects[0].w seems to return something sane. unsigned height = spec.DisplayRect.h; //fprintf(stderr, "(%u x %u)\n", width, height); // PSX core inserts padding on left and right (overscan). Optionally crop this. const uint32_t *pix = surf->pixels; if (!overscan) { // 320 width -> 350 width. // 364 width -> 400 width. // 256 width -> 280 width. // 560 width -> 512 width. // 640 width -> 700 width. // Rectify this. switch (width) { // The shifts are not simply (padded_width - real_width) / 2. case 280: pix += 10; width = 256; break; case 350: pix += 14; width = 320; break; case 400: pix += 15; width = 364; break; case 560: pix += 26; width = 512; break; case 700: pix += 33; width = 640; break; default: // This shouldn't happen. break; } if (is_pal) { // Attempt to remove black bars. // These numbers are arbitrary since the bars differ some by game. // Changes aspect ratio in the process. height -= 36; pix += 5 * (MEDNAFEN_CORE_GEOMETRY_MAX_W << 2); } } video_cb(pix, width, height, MEDNAFEN_CORE_GEOMETRY_MAX_W << 2); video_frames++; audio_frames += spec.SoundBufSize; audio_batch_cb(interbuf, spec.SoundBufSize); } void retro_get_system_info(struct retro_system_info *info) { memset(info, 0, sizeof(*info)); info->library_name = MEDNAFEN_CORE_NAME; info->library_version = MEDNAFEN_CORE_VERSION; info->need_fullpath = true; info->valid_extensions = MEDNAFEN_CORE_EXTENSIONS; info->block_extract = false; } void retro_get_system_av_info(struct retro_system_av_info *info) { memset(info, 0, sizeof(*info)); info->timing.fps = is_pal ? 49.842 : 59.941; info->timing.sample_rate = 44100; info->geometry.base_width = MEDNAFEN_CORE_GEOMETRY_BASE_W; info->geometry.base_height = MEDNAFEN_CORE_GEOMETRY_BASE_H; info->geometry.max_width = MEDNAFEN_CORE_GEOMETRY_MAX_W; info->geometry.max_height = MEDNAFEN_CORE_GEOMETRY_MAX_H; info->geometry.aspect_ratio = !widescreen_auto_ar ? MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO : (float)16/9; } void retro_deinit(void) { delete surf; surf = NULL; log_cb(RETRO_LOG_INFO, "[%s]: Samples / Frame: %.5f\n", MEDNAFEN_CORE_NAME, (double)audio_frames / video_frames); log_cb(RETRO_LOG_INFO, "[%s]: Estimated FPS: %.5f\n", MEDNAFEN_CORE_NAME, (double)video_frames * 44100 / audio_frames); } unsigned retro_get_region(void) { if (is_pal) return RETRO_REGION_PAL; return RETRO_REGION_NTSC; } unsigned retro_api_version(void) { return RETRO_API_VERSION; } void retro_set_controller_port_device(unsigned in_port, unsigned device) { switch (device) { case RETRO_DEVICE_JOYPAD: case RETRO_DEVICE_PS1PAD: log_cb(RETRO_LOG_INFO, "[%s]: Selected controller type standard gamepad.\n", MEDNAFEN_CORE_NAME); SetInput(in_port, "gamepad", &buf.u8[in_port]); break; case RETRO_DEVICE_DUALANALOG: log_cb(RETRO_LOG_INFO, "[%s]: Selected controller type Dual Analog.\n", MEDNAFEN_CORE_NAME); SetInput(in_port, "dualanalog", &buf.u8[in_port]); break; case RETRO_DEVICE_DUALSHOCK: log_cb(RETRO_LOG_INFO, "[%s]: Selected controller type DualShock.\n", MEDNAFEN_CORE_NAME); SetInput(in_port, "dualshock", &buf.u8[in_port]); break; case RETRO_DEVICE_FLIGHTSTICK: log_cb(RETRO_LOG_INFO, "[%s]: Selected controller type FlightStick.\n", MEDNAFEN_CORE_NAME); SetInput(in_port, "analogjoy", &buf.u8[in_port]); break; default: log_cb(RETRO_LOG_WARN, "[%s]: Unsupported controller device %u, falling back to gamepad.\n", MEDNAFEN_CORE_NAME,device); } if (rumble.set_rumble_state) { rumble.set_rumble_state(in_port, RETRO_RUMBLE_STRONG, 0); rumble.set_rumble_state(in_port, RETRO_RUMBLE_WEAK, 0); buf.u32[in_port][9] = 0; } } void retro_set_environment(retro_environment_t cb) { environ_cb = cb; static const struct retro_variable vars[] = { { "beetle_psx_cdimagecache", "CD Image Cache (restart); disabled|enabled" }, { "beetle_psx_widescreen_hack", "Widescreen mode hack; disabled|enabled" }, { "beetle_psx_widescreen_auto_ar", "Widescreen hack auto aspect ratio; disabled|enabled" }, { "beetle_psx_use_mednafen_memcard0_method", "Memcard 0 method; libretro|mednafen" }, { "beetle_psx_shared_memory_cards", "Shared memcards (restart); disabled|enabled" }, { "beetle_psx_initial_scanline", "Initial scanline; 0|1|2|3|4|5|6|7|8|9|10|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40" }, { "beetle_psx_initial_scanline_pal", "Initial scanline PAL; 0|1|2|3|4|5|6|7|8|9|10|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40" }, { "beetle_psx_last_scanline", "Last scanline; 239|238|237|236|235|234|232|231|230|229|228|227|226|225|224|223|222|221|220|219|218|217|216|215|214|213|212|211|210" }, { "beetle_psx_last_scanline_pal", "Last scanline PAL; 287|286|285|284|283|283|282|281|280|279|278|277|276|275|274|273|272|271|270|269|268|267|266|265|264|263|262|261|260" }, { "beetle_psx_analog_toggle", "Dualshock analog toggle; disabled|enabled" }, { "beetle_psx_enable_multitap_port1", "Port 1: Multitap enable; disabled|enabled" }, { "beetle_psx_enable_multitap_port2", "Port 2: Multitap enable; disabled|enabled" }, { NULL, NULL }, }; static const struct retro_controller_description pads[] = { { "PS1 Joypad", RETRO_DEVICE_JOYPAD }, { "DualAnalog", RETRO_DEVICE_DUALANALOG }, { "DualShock", RETRO_DEVICE_DUALSHOCK }, { "FlightStick", RETRO_DEVICE_FLIGHTSTICK }, }; static const struct retro_controller_info ports[] = { { pads, 4 }, { pads, 4 }, { pads, 4 }, { pads, 4 }, { pads, 4 }, { pads, 4 }, { pads, 4 }, { pads, 4 }, { 0 }, }; cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars); environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports); } void retro_set_audio_sample(retro_audio_sample_t cb) { audio_cb = cb; } void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; } void retro_set_input_poll(retro_input_poll_t cb) { input_poll_cb = cb; } void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; } void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } static size_t serialize_size; size_t retro_serialize_size(void) { StateMem st; memset(&st, 0, sizeof(st)); if (!MDFNSS_SaveSM(&st, 0, 0, NULL, NULL, NULL)) { return 0; } free(st.data); return serialize_size = st.len; } bool retro_serialize(void *data, size_t size) { /* it seems that mednafen can realloc pointers sent to it? since we don't know the disposition of void* data (is it safe to realloc?) we have to manage a new buffer here */ StateMem st; memset(&st, 0, sizeof(st)); st.data = (uint8_t*)malloc(size); st.malloced = size; bool ret = MDFNSS_SaveSM(&st, 0, 0, NULL, NULL, NULL); /* there are still some errors with the save states, the size seems to change on some games for now just log when this happens */ if (st.len != size) log_cb(RETRO_LOG_WARN, "warning, save state size has changed\n"); memcpy(data,st.data,size); free(st.data); return ret; } bool retro_unserialize(const void *data, size_t size) { StateMem st; memset(&st, 0, sizeof(st)); st.data = (uint8_t*)data; st.len = size; return MDFNSS_LoadSM(&st, 0, 0); } void *retro_get_memory_data(unsigned type) { uint8_t *data; switch (type) { case RETRO_MEMORY_SAVE_RAM: if (use_mednafen_memcard0_method) return NULL; return FIO->GetMemcardDevice(0)->GetNVData(); default: break; } return NULL; } size_t retro_get_memory_size(unsigned type) { switch (type) { case RETRO_MEMORY_SAVE_RAM: if (use_mednafen_memcard0_method) return 0; return (1 << 17); default: break; } return 0; } void retro_cheat_reset(void) {} void retro_cheat_set(unsigned, bool, const char *) {} #ifdef _WIN32 static void sanitize_path(std::string &path) { size_t size = path.size(); for (size_t i = 0; i < size; i++) if (path[i] == '/') path[i] = '\\'; } #endif // Use a simpler approach to make sure that things go right for libretro. const char *MDFN_MakeFName(MakeFName_Type type, int id1, const char *cd1) { static char fullpath[4096]; fullpath[0] = '\0'; switch (type) { case MDFNMKF_SAV: snprintf(fullpath, sizeof(fullpath), "%s%c%s.%s", retro_save_directory, retro_slash, (!shared_memorycards) ? retro_cd_base_name : "mednafen_psx_libretro_shared", cd1); break; case MDFNMKF_FIRMWARE: snprintf(fullpath, sizeof(fullpath), "%s%c%s", retro_base_directory, retro_slash, cd1); break; default: break; } return fullpath; } void MDFND_DispMessage(unsigned char *str) { const char *strc = (const char*)str; struct retro_message msg = { strc, 180 }; environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &msg); } void MDFN_DispMessage(const char *format, ...) { struct retro_message msg; va_list ap; va_start(ap,format); char *str = NULL; const char *strc = NULL; trio_vasprintf(&str, format,ap); va_end(ap); strc = str; msg.frames = 180; msg.msg = strc; environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &msg); } mednafen/tremor/mdct_lookup.h000664 001750 001750 00000100331 12611054044 017453 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: sin,cos lookup tables ********************************************************************/ #include "misc.h" /* {sin(2*i*PI/4096), cos(2*i*PI/4096)}, with i = 0 to 512 */ static const LOOKUP_T sincos_lookup0[1026] = { X(0x00000000), X(0x7fffffff), X(0x003243f5), X(0x7ffff621), X(0x006487e3), X(0x7fffd886), X(0x0096cbc1), X(0x7fffa72c), X(0x00c90f88), X(0x7fff6216), X(0x00fb5330), X(0x7fff0943), X(0x012d96b1), X(0x7ffe9cb2), X(0x015fda03), X(0x7ffe1c65), X(0x01921d20), X(0x7ffd885a), X(0x01c45ffe), X(0x7ffce093), X(0x01f6a297), X(0x7ffc250f), X(0x0228e4e2), X(0x7ffb55ce), X(0x025b26d7), X(0x7ffa72d1), X(0x028d6870), X(0x7ff97c18), X(0x02bfa9a4), X(0x7ff871a2), X(0x02f1ea6c), X(0x7ff75370), X(0x03242abf), X(0x7ff62182), X(0x03566a96), X(0x7ff4dbd9), X(0x0388a9ea), X(0x7ff38274), X(0x03bae8b2), X(0x7ff21553), X(0x03ed26e6), X(0x7ff09478), X(0x041f6480), X(0x7feeffe1), X(0x0451a177), X(0x7fed5791), X(0x0483ddc3), X(0x7feb9b85), X(0x04b6195d), X(0x7fe9cbc0), X(0x04e8543e), X(0x7fe7e841), X(0x051a8e5c), X(0x7fe5f108), X(0x054cc7b1), X(0x7fe3e616), X(0x057f0035), X(0x7fe1c76b), X(0x05b137df), X(0x7fdf9508), X(0x05e36ea9), X(0x7fdd4eec), X(0x0615a48b), X(0x7fdaf519), X(0x0647d97c), X(0x7fd8878e), X(0x067a0d76), X(0x7fd6064c), X(0x06ac406f), X(0x7fd37153), X(0x06de7262), X(0x7fd0c8a3), X(0x0710a345), X(0x7fce0c3e), X(0x0742d311), X(0x7fcb3c23), X(0x077501be), X(0x7fc85854), X(0x07a72f45), X(0x7fc560cf), X(0x07d95b9e), X(0x7fc25596), X(0x080b86c2), X(0x7fbf36aa), X(0x083db0a7), X(0x7fbc040a), X(0x086fd947), X(0x7fb8bdb8), X(0x08a2009a), X(0x7fb563b3), X(0x08d42699), X(0x7fb1f5fc), X(0x09064b3a), X(0x7fae7495), X(0x09386e78), X(0x7faadf7c), X(0x096a9049), X(0x7fa736b4), X(0x099cb0a7), X(0x7fa37a3c), X(0x09cecf89), X(0x7f9faa15), X(0x0a00ece8), X(0x7f9bc640), X(0x0a3308bd), X(0x7f97cebd), X(0x0a6522fe), X(0x7f93c38c), X(0x0a973ba5), X(0x7f8fa4b0), X(0x0ac952aa), X(0x7f8b7227), X(0x0afb6805), X(0x7f872bf3), X(0x0b2d7baf), X(0x7f82d214), X(0x0b5f8d9f), X(0x7f7e648c), X(0x0b919dcf), X(0x7f79e35a), X(0x0bc3ac35), X(0x7f754e80), X(0x0bf5b8cb), X(0x7f70a5fe), X(0x0c27c389), X(0x7f6be9d4), X(0x0c59cc68), X(0x7f671a05), X(0x0c8bd35e), X(0x7f62368f), X(0x0cbdd865), X(0x7f5d3f75), X(0x0cefdb76), X(0x7f5834b7), X(0x0d21dc87), X(0x7f531655), X(0x0d53db92), X(0x7f4de451), X(0x0d85d88f), X(0x7f489eaa), X(0x0db7d376), X(0x7f434563), X(0x0de9cc40), X(0x7f3dd87c), X(0x0e1bc2e4), X(0x7f3857f6), X(0x0e4db75b), X(0x7f32c3d1), X(0x0e7fa99e), X(0x7f2d1c0e), X(0x0eb199a4), X(0x7f2760af), X(0x0ee38766), X(0x7f2191b4), X(0x0f1572dc), X(0x7f1baf1e), X(0x0f475bff), X(0x7f15b8ee), X(0x0f7942c7), X(0x7f0faf25), X(0x0fab272b), X(0x7f0991c4), X(0x0fdd0926), X(0x7f0360cb), X(0x100ee8ad), X(0x7efd1c3c), X(0x1040c5bb), X(0x7ef6c418), X(0x1072a048), X(0x7ef05860), X(0x10a4784b), X(0x7ee9d914), X(0x10d64dbd), X(0x7ee34636), X(0x11082096), X(0x7edc9fc6), X(0x1139f0cf), X(0x7ed5e5c6), X(0x116bbe60), X(0x7ecf1837), X(0x119d8941), X(0x7ec8371a), X(0x11cf516a), X(0x7ec14270), X(0x120116d5), X(0x7eba3a39), X(0x1232d979), X(0x7eb31e78), X(0x1264994e), X(0x7eabef2c), X(0x1296564d), X(0x7ea4ac58), X(0x12c8106f), X(0x7e9d55fc), X(0x12f9c7aa), X(0x7e95ec1a), X(0x132b7bf9), X(0x7e8e6eb2), X(0x135d2d53), X(0x7e86ddc6), X(0x138edbb1), X(0x7e7f3957), X(0x13c0870a), X(0x7e778166), X(0x13f22f58), X(0x7e6fb5f4), X(0x1423d492), X(0x7e67d703), X(0x145576b1), X(0x7e5fe493), X(0x148715ae), X(0x7e57dea7), X(0x14b8b17f), X(0x7e4fc53e), X(0x14ea4a1f), X(0x7e47985b), X(0x151bdf86), X(0x7e3f57ff), X(0x154d71aa), X(0x7e37042a), X(0x157f0086), X(0x7e2e9cdf), X(0x15b08c12), X(0x7e26221f), X(0x15e21445), X(0x7e1d93ea), X(0x16139918), X(0x7e14f242), X(0x16451a83), X(0x7e0c3d29), X(0x1676987f), X(0x7e0374a0), X(0x16a81305), X(0x7dfa98a8), X(0x16d98a0c), X(0x7df1a942), X(0x170afd8d), X(0x7de8a670), X(0x173c6d80), X(0x7ddf9034), X(0x176dd9de), X(0x7dd6668f), X(0x179f429f), X(0x7dcd2981), X(0x17d0a7bc), X(0x7dc3d90d), X(0x1802092c), X(0x7dba7534), X(0x183366e9), X(0x7db0fdf8), X(0x1864c0ea), X(0x7da77359), X(0x18961728), X(0x7d9dd55a), X(0x18c7699b), X(0x7d9423fc), X(0x18f8b83c), X(0x7d8a5f40), X(0x192a0304), X(0x7d808728), X(0x195b49ea), X(0x7d769bb5), X(0x198c8ce7), X(0x7d6c9ce9), X(0x19bdcbf3), X(0x7d628ac6), X(0x19ef0707), X(0x7d58654d), X(0x1a203e1b), X(0x7d4e2c7f), X(0x1a517128), X(0x7d43e05e), X(0x1a82a026), X(0x7d3980ec), X(0x1ab3cb0d), X(0x7d2f0e2b), X(0x1ae4f1d6), X(0x7d24881b), X(0x1b161479), X(0x7d19eebf), X(0x1b4732ef), X(0x7d0f4218), X(0x1b784d30), X(0x7d048228), X(0x1ba96335), X(0x7cf9aef0), X(0x1bda74f6), X(0x7ceec873), X(0x1c0b826a), X(0x7ce3ceb2), X(0x1c3c8b8c), X(0x7cd8c1ae), X(0x1c6d9053), X(0x7ccda169), X(0x1c9e90b8), X(0x7cc26de5), X(0x1ccf8cb3), X(0x7cb72724), X(0x1d00843d), X(0x7cabcd28), X(0x1d31774d), X(0x7ca05ff1), X(0x1d6265dd), X(0x7c94df83), X(0x1d934fe5), X(0x7c894bde), X(0x1dc4355e), X(0x7c7da505), X(0x1df5163f), X(0x7c71eaf9), X(0x1e25f282), X(0x7c661dbc), X(0x1e56ca1e), X(0x7c5a3d50), X(0x1e879d0d), X(0x7c4e49b7), X(0x1eb86b46), X(0x7c4242f2), X(0x1ee934c3), X(0x7c362904), X(0x1f19f97b), X(0x7c29fbee), X(0x1f4ab968), X(0x7c1dbbb3), X(0x1f7b7481), X(0x7c116853), X(0x1fac2abf), X(0x7c0501d2), X(0x1fdcdc1b), X(0x7bf88830), X(0x200d888d), X(0x7bebfb70), X(0x203e300d), X(0x7bdf5b94), X(0x206ed295), X(0x7bd2a89e), X(0x209f701c), X(0x7bc5e290), X(0x20d0089c), X(0x7bb9096b), X(0x21009c0c), X(0x7bac1d31), X(0x21312a65), X(0x7b9f1de6), X(0x2161b3a0), X(0x7b920b89), X(0x219237b5), X(0x7b84e61f), X(0x21c2b69c), X(0x7b77ada8), X(0x21f3304f), X(0x7b6a6227), X(0x2223a4c5), X(0x7b5d039e), X(0x225413f8), X(0x7b4f920e), X(0x22847de0), X(0x7b420d7a), X(0x22b4e274), X(0x7b3475e5), X(0x22e541af), X(0x7b26cb4f), X(0x23159b88), X(0x7b190dbc), X(0x2345eff8), X(0x7b0b3d2c), X(0x23763ef7), X(0x7afd59a4), X(0x23a6887f), X(0x7aef6323), X(0x23d6cc87), X(0x7ae159ae), X(0x24070b08), X(0x7ad33d45), X(0x243743fa), X(0x7ac50dec), X(0x24677758), X(0x7ab6cba4), X(0x2497a517), X(0x7aa8766f), X(0x24c7cd33), X(0x7a9a0e50), X(0x24f7efa2), X(0x7a8b9348), X(0x25280c5e), X(0x7a7d055b), X(0x2558235f), X(0x7a6e648a), X(0x2588349d), X(0x7a5fb0d8), X(0x25b84012), X(0x7a50ea47), X(0x25e845b6), X(0x7a4210d8), X(0x26184581), X(0x7a332490), X(0x26483f6c), X(0x7a24256f), X(0x26783370), X(0x7a151378), X(0x26a82186), X(0x7a05eead), X(0x26d809a5), X(0x79f6b711), X(0x2707ebc7), X(0x79e76ca7), X(0x2737c7e3), X(0x79d80f6f), X(0x27679df4), X(0x79c89f6e), X(0x27976df1), X(0x79b91ca4), X(0x27c737d3), X(0x79a98715), X(0x27f6fb92), X(0x7999dec4), X(0x2826b928), X(0x798a23b1), X(0x2856708d), X(0x797a55e0), X(0x288621b9), X(0x796a7554), X(0x28b5cca5), X(0x795a820e), X(0x28e5714b), X(0x794a7c12), X(0x29150fa1), X(0x793a6361), X(0x2944a7a2), X(0x792a37fe), X(0x29743946), X(0x7919f9ec), X(0x29a3c485), X(0x7909a92d), X(0x29d34958), X(0x78f945c3), X(0x2a02c7b8), X(0x78e8cfb2), X(0x2a323f9e), X(0x78d846fb), X(0x2a61b101), X(0x78c7aba2), X(0x2a911bdc), X(0x78b6fda8), X(0x2ac08026), X(0x78a63d11), X(0x2aefddd8), X(0x789569df), X(0x2b1f34eb), X(0x78848414), X(0x2b4e8558), X(0x78738bb3), X(0x2b7dcf17), X(0x786280bf), X(0x2bad1221), X(0x7851633b), X(0x2bdc4e6f), X(0x78403329), X(0x2c0b83fa), X(0x782ef08b), X(0x2c3ab2b9), X(0x781d9b65), X(0x2c69daa6), X(0x780c33b8), X(0x2c98fbba), X(0x77fab989), X(0x2cc815ee), X(0x77e92cd9), X(0x2cf72939), X(0x77d78daa), X(0x2d263596), X(0x77c5dc01), X(0x2d553afc), X(0x77b417df), X(0x2d843964), X(0x77a24148), X(0x2db330c7), X(0x7790583e), X(0x2de2211e), X(0x777e5cc3), X(0x2e110a62), X(0x776c4edb), X(0x2e3fec8b), X(0x775a2e89), X(0x2e6ec792), X(0x7747fbce), X(0x2e9d9b70), X(0x7735b6af), X(0x2ecc681e), X(0x77235f2d), X(0x2efb2d95), X(0x7710f54c), X(0x2f29ebcc), X(0x76fe790e), X(0x2f58a2be), X(0x76ebea77), X(0x2f875262), X(0x76d94989), X(0x2fb5fab2), X(0x76c69647), X(0x2fe49ba7), X(0x76b3d0b4), X(0x30133539), X(0x76a0f8d2), X(0x3041c761), X(0x768e0ea6), X(0x30705217), X(0x767b1231), X(0x309ed556), X(0x76680376), X(0x30cd5115), X(0x7654e279), X(0x30fbc54d), X(0x7641af3d), X(0x312a31f8), X(0x762e69c4), X(0x3158970e), X(0x761b1211), X(0x3186f487), X(0x7607a828), X(0x31b54a5e), X(0x75f42c0b), X(0x31e39889), X(0x75e09dbd), X(0x3211df04), X(0x75ccfd42), X(0x32401dc6), X(0x75b94a9c), X(0x326e54c7), X(0x75a585cf), X(0x329c8402), X(0x7591aedd), X(0x32caab6f), X(0x757dc5ca), X(0x32f8cb07), X(0x7569ca99), X(0x3326e2c3), X(0x7555bd4c), X(0x3354f29b), X(0x75419de7), X(0x3382fa88), X(0x752d6c6c), X(0x33b0fa84), X(0x751928e0), X(0x33def287), X(0x7504d345), X(0x340ce28b), X(0x74f06b9e), X(0x343aca87), X(0x74dbf1ef), X(0x3468aa76), X(0x74c7663a), X(0x34968250), X(0x74b2c884), X(0x34c4520d), X(0x749e18cd), X(0x34f219a8), X(0x7489571c), X(0x351fd918), X(0x74748371), X(0x354d9057), X(0x745f9dd1), X(0x357b3f5d), X(0x744aa63f), X(0x35a8e625), X(0x74359cbd), X(0x35d684a6), X(0x74208150), X(0x36041ad9), X(0x740b53fb), X(0x3631a8b8), X(0x73f614c0), X(0x365f2e3b), X(0x73e0c3a3), X(0x368cab5c), X(0x73cb60a8), X(0x36ba2014), X(0x73b5ebd1), X(0x36e78c5b), X(0x73a06522), X(0x3714f02a), X(0x738acc9e), X(0x37424b7b), X(0x73752249), X(0x376f9e46), X(0x735f6626), X(0x379ce885), X(0x73499838), X(0x37ca2a30), X(0x7333b883), X(0x37f76341), X(0x731dc70a), X(0x382493b0), X(0x7307c3d0), X(0x3851bb77), X(0x72f1aed9), X(0x387eda8e), X(0x72db8828), X(0x38abf0ef), X(0x72c54fc1), X(0x38d8fe93), X(0x72af05a7), X(0x39060373), X(0x7298a9dd), X(0x3932ff87), X(0x72823c67), X(0x395ff2c9), X(0x726bbd48), X(0x398cdd32), X(0x72552c85), X(0x39b9bebc), X(0x723e8a20), X(0x39e6975e), X(0x7227d61c), X(0x3a136712), X(0x7211107e), X(0x3a402dd2), X(0x71fa3949), X(0x3a6ceb96), X(0x71e35080), X(0x3a99a057), X(0x71cc5626), X(0x3ac64c0f), X(0x71b54a41), X(0x3af2eeb7), X(0x719e2cd2), X(0x3b1f8848), X(0x7186fdde), X(0x3b4c18ba), X(0x716fbd68), X(0x3b78a007), X(0x71586b74), X(0x3ba51e29), X(0x71410805), X(0x3bd19318), X(0x7129931f), X(0x3bfdfecd), X(0x71120cc5), X(0x3c2a6142), X(0x70fa74fc), X(0x3c56ba70), X(0x70e2cbc6), X(0x3c830a50), X(0x70cb1128), X(0x3caf50da), X(0x70b34525), X(0x3cdb8e09), X(0x709b67c0), X(0x3d07c1d6), X(0x708378ff), X(0x3d33ec39), X(0x706b78e3), X(0x3d600d2c), X(0x70536771), X(0x3d8c24a8), X(0x703b44ad), X(0x3db832a6), X(0x7023109a), X(0x3de4371f), X(0x700acb3c), X(0x3e10320d), X(0x6ff27497), X(0x3e3c2369), X(0x6fda0cae), X(0x3e680b2c), X(0x6fc19385), X(0x3e93e950), X(0x6fa90921), X(0x3ebfbdcd), X(0x6f906d84), X(0x3eeb889c), X(0x6f77c0b3), X(0x3f1749b8), X(0x6f5f02b2), X(0x3f430119), X(0x6f463383), X(0x3f6eaeb8), X(0x6f2d532c), X(0x3f9a5290), X(0x6f1461b0), X(0x3fc5ec98), X(0x6efb5f12), X(0x3ff17cca), X(0x6ee24b57), X(0x401d0321), X(0x6ec92683), X(0x40487f94), X(0x6eaff099), X(0x4073f21d), X(0x6e96a99d), X(0x409f5ab6), X(0x6e7d5193), X(0x40cab958), X(0x6e63e87f), X(0x40f60dfb), X(0x6e4a6e66), X(0x4121589b), X(0x6e30e34a), X(0x414c992f), X(0x6e174730), X(0x4177cfb1), X(0x6dfd9a1c), X(0x41a2fc1a), X(0x6de3dc11), X(0x41ce1e65), X(0x6dca0d14), X(0x41f93689), X(0x6db02d29), X(0x42244481), X(0x6d963c54), X(0x424f4845), X(0x6d7c3a98), X(0x427a41d0), X(0x6d6227fa), X(0x42a5311b), X(0x6d48047e), X(0x42d0161e), X(0x6d2dd027), X(0x42faf0d4), X(0x6d138afb), X(0x4325c135), X(0x6cf934fc), X(0x4350873c), X(0x6cdece2f), X(0x437b42e1), X(0x6cc45698), X(0x43a5f41e), X(0x6ca9ce3b), X(0x43d09aed), X(0x6c8f351c), X(0x43fb3746), X(0x6c748b3f), X(0x4425c923), X(0x6c59d0a9), X(0x4450507e), X(0x6c3f055d), X(0x447acd50), X(0x6c242960), X(0x44a53f93), X(0x6c093cb6), X(0x44cfa740), X(0x6bee3f62), X(0x44fa0450), X(0x6bd3316a), X(0x452456bd), X(0x6bb812d1), X(0x454e9e80), X(0x6b9ce39b), X(0x4578db93), X(0x6b81a3cd), X(0x45a30df0), X(0x6b66536b), X(0x45cd358f), X(0x6b4af279), X(0x45f7526b), X(0x6b2f80fb), X(0x4621647d), X(0x6b13fef5), X(0x464b6bbe), X(0x6af86c6c), X(0x46756828), X(0x6adcc964), X(0x469f59b4), X(0x6ac115e2), X(0x46c9405c), X(0x6aa551e9), X(0x46f31c1a), X(0x6a897d7d), X(0x471cece7), X(0x6a6d98a4), X(0x4746b2bc), X(0x6a51a361), X(0x47706d93), X(0x6a359db9), X(0x479a1d67), X(0x6a1987b0), X(0x47c3c22f), X(0x69fd614a), X(0x47ed5be6), X(0x69e12a8c), X(0x4816ea86), X(0x69c4e37a), X(0x48406e08), X(0x69a88c19), X(0x4869e665), X(0x698c246c), X(0x48935397), X(0x696fac78), X(0x48bcb599), X(0x69532442), X(0x48e60c62), X(0x69368bce), X(0x490f57ee), X(0x6919e320), X(0x49389836), X(0x68fd2a3d), X(0x4961cd33), X(0x68e06129), X(0x498af6df), X(0x68c387e9), X(0x49b41533), X(0x68a69e81), X(0x49dd282a), X(0x6889a4f6), X(0x4a062fbd), X(0x686c9b4b), X(0x4a2f2be6), X(0x684f8186), X(0x4a581c9e), X(0x683257ab), X(0x4a8101de), X(0x68151dbe), X(0x4aa9dba2), X(0x67f7d3c5), X(0x4ad2a9e2), X(0x67da79c3), X(0x4afb6c98), X(0x67bd0fbd), X(0x4b2423be), X(0x679f95b7), X(0x4b4ccf4d), X(0x67820bb7), X(0x4b756f40), X(0x676471c0), X(0x4b9e0390), X(0x6746c7d8), X(0x4bc68c36), X(0x67290e02), X(0x4bef092d), X(0x670b4444), X(0x4c177a6e), X(0x66ed6aa1), X(0x4c3fdff4), X(0x66cf8120), X(0x4c6839b7), X(0x66b187c3), X(0x4c9087b1), X(0x66937e91), X(0x4cb8c9dd), X(0x6675658c), X(0x4ce10034), X(0x66573cbb), X(0x4d092ab0), X(0x66390422), X(0x4d31494b), X(0x661abbc5), X(0x4d595bfe), X(0x65fc63a9), X(0x4d8162c4), X(0x65ddfbd3), X(0x4da95d96), X(0x65bf8447), X(0x4dd14c6e), X(0x65a0fd0b), X(0x4df92f46), X(0x65826622), X(0x4e210617), X(0x6563bf92), X(0x4e48d0dd), X(0x6545095f), X(0x4e708f8f), X(0x6526438f), X(0x4e984229), X(0x65076e25), X(0x4ebfe8a5), X(0x64e88926), X(0x4ee782fb), X(0x64c99498), X(0x4f0f1126), X(0x64aa907f), X(0x4f369320), X(0x648b7ce0), X(0x4f5e08e3), X(0x646c59bf), X(0x4f857269), X(0x644d2722), X(0x4faccfab), X(0x642de50d), X(0x4fd420a4), X(0x640e9386), X(0x4ffb654d), X(0x63ef3290), X(0x50229da1), X(0x63cfc231), X(0x5049c999), X(0x63b0426d), X(0x5070e92f), X(0x6390b34a), X(0x5097fc5e), X(0x637114cc), X(0x50bf031f), X(0x635166f9), X(0x50e5fd6d), X(0x6331a9d4), X(0x510ceb40), X(0x6311dd64), X(0x5133cc94), X(0x62f201ac), X(0x515aa162), X(0x62d216b3), X(0x518169a5), X(0x62b21c7b), X(0x51a82555), X(0x6292130c), X(0x51ced46e), X(0x6271fa69), X(0x51f576ea), X(0x6251d298), X(0x521c0cc2), X(0x62319b9d), X(0x524295f0), X(0x6211557e), X(0x5269126e), X(0x61f1003f), X(0x528f8238), X(0x61d09be5), X(0x52b5e546), X(0x61b02876), X(0x52dc3b92), X(0x618fa5f7), X(0x53028518), X(0x616f146c), X(0x5328c1d0), X(0x614e73da), X(0x534ef1b5), X(0x612dc447), X(0x537514c2), X(0x610d05b7), X(0x539b2af0), X(0x60ec3830), X(0x53c13439), X(0x60cb5bb7), X(0x53e73097), X(0x60aa7050), X(0x540d2005), X(0x60897601), X(0x5433027d), X(0x60686ccf), X(0x5458d7f9), X(0x604754bf), X(0x547ea073), X(0x60262dd6), X(0x54a45be6), X(0x6004f819), X(0x54ca0a4b), X(0x5fe3b38d), X(0x54efab9c), X(0x5fc26038), X(0x55153fd4), X(0x5fa0fe1f), X(0x553ac6ee), X(0x5f7f8d46), X(0x556040e2), X(0x5f5e0db3), X(0x5585adad), X(0x5f3c7f6b), X(0x55ab0d46), X(0x5f1ae274), X(0x55d05faa), X(0x5ef936d1), X(0x55f5a4d2), X(0x5ed77c8a), X(0x561adcb9), X(0x5eb5b3a2), X(0x56400758), X(0x5e93dc1f), X(0x566524aa), X(0x5e71f606), X(0x568a34a9), X(0x5e50015d), X(0x56af3750), X(0x5e2dfe29), X(0x56d42c99), X(0x5e0bec6e), X(0x56f9147e), X(0x5de9cc33), X(0x571deefa), X(0x5dc79d7c), X(0x5742bc06), X(0x5da5604f), X(0x57677b9d), X(0x5d8314b1), X(0x578c2dba), X(0x5d60baa7), X(0x57b0d256), X(0x5d3e5237), X(0x57d5696d), X(0x5d1bdb65), X(0x57f9f2f8), X(0x5cf95638), X(0x581e6ef1), X(0x5cd6c2b5), X(0x5842dd54), X(0x5cb420e0), X(0x58673e1b), X(0x5c9170bf), X(0x588b9140), X(0x5c6eb258), X(0x58afd6bd), X(0x5c4be5b0), X(0x58d40e8c), X(0x5c290acc), X(0x58f838a9), X(0x5c0621b2), X(0x591c550e), X(0x5be32a67), X(0x594063b5), X(0x5bc024f0), X(0x59646498), X(0x5b9d1154), X(0x598857b2), X(0x5b79ef96), X(0x59ac3cfd), X(0x5b56bfbd), X(0x59d01475), X(0x5b3381ce), X(0x59f3de12), X(0x5b1035cf), X(0x5a1799d1), X(0x5aecdbc5), X(0x5a3b47ab), X(0x5ac973b5), X(0x5a5ee79a), X(0x5aa5fda5), X(0x5a82799a), X(0x5a82799a) }; /* {sin((2*i+1)*PI/4096), cos((2*i+1)*PI/4096)}, with i = 0 to 511 */ static const LOOKUP_T sincos_lookup1[1024] = { X(0x001921fb), X(0x7ffffd88), X(0x004b65ee), X(0x7fffe9cb), X(0x007da9d4), X(0x7fffc251), X(0x00afeda8), X(0x7fff8719), X(0x00e23160), X(0x7fff3824), X(0x011474f6), X(0x7ffed572), X(0x0146b860), X(0x7ffe5f03), X(0x0178fb99), X(0x7ffdd4d7), X(0x01ab3e97), X(0x7ffd36ee), X(0x01dd8154), X(0x7ffc8549), X(0x020fc3c6), X(0x7ffbbfe6), X(0x024205e8), X(0x7ffae6c7), X(0x027447b0), X(0x7ff9f9ec), X(0x02a68917), X(0x7ff8f954), X(0x02d8ca16), X(0x7ff7e500), X(0x030b0aa4), X(0x7ff6bcf0), X(0x033d4abb), X(0x7ff58125), X(0x036f8a51), X(0x7ff4319d), X(0x03a1c960), X(0x7ff2ce5b), X(0x03d407df), X(0x7ff1575d), X(0x040645c7), X(0x7fefcca4), X(0x04388310), X(0x7fee2e30), X(0x046abfb3), X(0x7fec7c02), X(0x049cfba7), X(0x7feab61a), X(0x04cf36e5), X(0x7fe8dc78), X(0x05017165), X(0x7fe6ef1c), X(0x0533ab20), X(0x7fe4ee06), X(0x0565e40d), X(0x7fe2d938), X(0x05981c26), X(0x7fe0b0b1), X(0x05ca5361), X(0x7fde7471), X(0x05fc89b8), X(0x7fdc247a), X(0x062ebf22), X(0x7fd9c0ca), X(0x0660f398), X(0x7fd74964), X(0x06932713), X(0x7fd4be46), X(0x06c5598a), X(0x7fd21f72), X(0x06f78af6), X(0x7fcf6ce8), X(0x0729bb4e), X(0x7fcca6a7), X(0x075bea8c), X(0x7fc9ccb2), X(0x078e18a7), X(0x7fc6df08), X(0x07c04598), X(0x7fc3dda9), X(0x07f27157), X(0x7fc0c896), X(0x08249bdd), X(0x7fbd9fd0), X(0x0856c520), X(0x7fba6357), X(0x0888ed1b), X(0x7fb7132b), X(0x08bb13c5), X(0x7fb3af4e), X(0x08ed3916), X(0x7fb037bf), X(0x091f5d06), X(0x7facac7f), X(0x09517f8f), X(0x7fa90d8e), X(0x0983a0a7), X(0x7fa55aee), X(0x09b5c048), X(0x7fa1949e), X(0x09e7de6a), X(0x7f9dbaa0), X(0x0a19fb04), X(0x7f99ccf4), X(0x0a4c1610), X(0x7f95cb9a), X(0x0a7e2f85), X(0x7f91b694), X(0x0ab0475c), X(0x7f8d8de1), X(0x0ae25d8d), X(0x7f895182), X(0x0b147211), X(0x7f850179), X(0x0b4684df), X(0x7f809dc5), X(0x0b7895f0), X(0x7f7c2668), X(0x0baaa53b), X(0x7f779b62), X(0x0bdcb2bb), X(0x7f72fcb4), X(0x0c0ebe66), X(0x7f6e4a5e), X(0x0c40c835), X(0x7f698461), X(0x0c72d020), X(0x7f64aabf), X(0x0ca4d620), X(0x7f5fbd77), X(0x0cd6da2d), X(0x7f5abc8a), X(0x0d08dc3f), X(0x7f55a7fa), X(0x0d3adc4e), X(0x7f507fc7), X(0x0d6cda53), X(0x7f4b43f2), X(0x0d9ed646), X(0x7f45f47b), X(0x0dd0d01f), X(0x7f409164), X(0x0e02c7d7), X(0x7f3b1aad), X(0x0e34bd66), X(0x7f359057), X(0x0e66b0c3), X(0x7f2ff263), X(0x0e98a1e9), X(0x7f2a40d2), X(0x0eca90ce), X(0x7f247ba5), X(0x0efc7d6b), X(0x7f1ea2dc), X(0x0f2e67b8), X(0x7f18b679), X(0x0f604faf), X(0x7f12b67c), X(0x0f923546), X(0x7f0ca2e7), X(0x0fc41876), X(0x7f067bba), X(0x0ff5f938), X(0x7f0040f6), X(0x1027d784), X(0x7ef9f29d), X(0x1059b352), X(0x7ef390ae), X(0x108b8c9b), X(0x7eed1b2c), X(0x10bd6356), X(0x7ee69217), X(0x10ef377d), X(0x7edff570), X(0x11210907), X(0x7ed94538), X(0x1152d7ed), X(0x7ed28171), X(0x1184a427), X(0x7ecbaa1a), X(0x11b66dad), X(0x7ec4bf36), X(0x11e83478), X(0x7ebdc0c6), X(0x1219f880), X(0x7eb6aeca), X(0x124bb9be), X(0x7eaf8943), X(0x127d7829), X(0x7ea85033), X(0x12af33ba), X(0x7ea1039b), X(0x12e0ec6a), X(0x7e99a37c), X(0x1312a230), X(0x7e922fd6), X(0x13445505), X(0x7e8aa8ac), X(0x137604e2), X(0x7e830dff), X(0x13a7b1bf), X(0x7e7b5fce), X(0x13d95b93), X(0x7e739e1d), X(0x140b0258), X(0x7e6bc8eb), X(0x143ca605), X(0x7e63e03b), X(0x146e4694), X(0x7e5be40c), X(0x149fe3fc), X(0x7e53d462), X(0x14d17e36), X(0x7e4bb13c), X(0x1503153a), X(0x7e437a9c), X(0x1534a901), X(0x7e3b3083), X(0x15663982), X(0x7e32d2f4), X(0x1597c6b7), X(0x7e2a61ed), X(0x15c95097), X(0x7e21dd73), X(0x15fad71b), X(0x7e194584), X(0x162c5a3b), X(0x7e109a24), X(0x165dd9f0), X(0x7e07db52), X(0x168f5632), X(0x7dff0911), X(0x16c0cef9), X(0x7df62362), X(0x16f2443e), X(0x7ded2a47), X(0x1723b5f9), X(0x7de41dc0), X(0x17552422), X(0x7ddafdce), X(0x17868eb3), X(0x7dd1ca75), X(0x17b7f5a3), X(0x7dc883b4), X(0x17e958ea), X(0x7dbf298d), X(0x181ab881), X(0x7db5bc02), X(0x184c1461), X(0x7dac3b15), X(0x187d6c82), X(0x7da2a6c6), X(0x18aec0db), X(0x7d98ff17), X(0x18e01167), X(0x7d8f4409), X(0x19115e1c), X(0x7d85759f), X(0x1942a6f3), X(0x7d7b93da), X(0x1973ebe6), X(0x7d719eba), X(0x19a52ceb), X(0x7d679642), X(0x19d669fc), X(0x7d5d7a74), X(0x1a07a311), X(0x7d534b50), X(0x1a38d823), X(0x7d4908d9), X(0x1a6a0929), X(0x7d3eb30f), X(0x1a9b361d), X(0x7d3449f5), X(0x1acc5ef6), X(0x7d29cd8c), X(0x1afd83ad), X(0x7d1f3dd6), X(0x1b2ea43a), X(0x7d149ad5), X(0x1b5fc097), X(0x7d09e489), X(0x1b90d8bb), X(0x7cff1af5), X(0x1bc1ec9e), X(0x7cf43e1a), X(0x1bf2fc3a), X(0x7ce94dfb), X(0x1c240786), X(0x7cde4a98), X(0x1c550e7c), X(0x7cd333f3), X(0x1c861113), X(0x7cc80a0f), X(0x1cb70f43), X(0x7cbcccec), X(0x1ce80906), X(0x7cb17c8d), X(0x1d18fe54), X(0x7ca618f3), X(0x1d49ef26), X(0x7c9aa221), X(0x1d7adb73), X(0x7c8f1817), X(0x1dabc334), X(0x7c837ad8), X(0x1ddca662), X(0x7c77ca65), X(0x1e0d84f5), X(0x7c6c06c0), X(0x1e3e5ee5), X(0x7c602fec), X(0x1e6f342c), X(0x7c5445e9), X(0x1ea004c1), X(0x7c4848ba), X(0x1ed0d09d), X(0x7c3c3860), X(0x1f0197b8), X(0x7c3014de), X(0x1f325a0b), X(0x7c23de35), X(0x1f63178f), X(0x7c179467), X(0x1f93d03c), X(0x7c0b3777), X(0x1fc4840a), X(0x7bfec765), X(0x1ff532f2), X(0x7bf24434), X(0x2025dcec), X(0x7be5ade6), X(0x205681f1), X(0x7bd9047c), X(0x208721f9), X(0x7bcc47fa), X(0x20b7bcfe), X(0x7bbf7860), X(0x20e852f6), X(0x7bb295b0), X(0x2118e3dc), X(0x7ba59fee), X(0x21496fa7), X(0x7b989719), X(0x2179f64f), X(0x7b8b7b36), X(0x21aa77cf), X(0x7b7e4c45), X(0x21daf41d), X(0x7b710a49), X(0x220b6b32), X(0x7b63b543), X(0x223bdd08), X(0x7b564d36), X(0x226c4996), X(0x7b48d225), X(0x229cb0d5), X(0x7b3b4410), X(0x22cd12bd), X(0x7b2da2fa), X(0x22fd6f48), X(0x7b1feee5), X(0x232dc66d), X(0x7b1227d3), X(0x235e1826), X(0x7b044dc7), X(0x238e646a), X(0x7af660c2), X(0x23beab33), X(0x7ae860c7), X(0x23eeec78), X(0x7ada4dd8), X(0x241f2833), X(0x7acc27f7), X(0x244f5e5c), X(0x7abdef25), X(0x247f8eec), X(0x7aafa367), X(0x24afb9da), X(0x7aa144bc), X(0x24dfdf20), X(0x7a92d329), X(0x250ffeb7), X(0x7a844eae), X(0x25401896), X(0x7a75b74f), X(0x25702cb7), X(0x7a670d0d), X(0x25a03b11), X(0x7a584feb), X(0x25d0439f), X(0x7a497feb), X(0x26004657), X(0x7a3a9d0f), X(0x26304333), X(0x7a2ba75a), X(0x26603a2c), X(0x7a1c9ece), X(0x26902b39), X(0x7a0d836d), X(0x26c01655), X(0x79fe5539), X(0x26effb76), X(0x79ef1436), X(0x271fda96), X(0x79dfc064), X(0x274fb3ae), X(0x79d059c8), X(0x277f86b5), X(0x79c0e062), X(0x27af53a6), X(0x79b15435), X(0x27df1a77), X(0x79a1b545), X(0x280edb23), X(0x79920392), X(0x283e95a1), X(0x79823f20), X(0x286e49ea), X(0x797267f2), X(0x289df7f8), X(0x79627e08), X(0x28cd9fc1), X(0x79528167), X(0x28fd4140), X(0x79427210), X(0x292cdc6d), X(0x79325006), X(0x295c7140), X(0x79221b4b), X(0x298bffb2), X(0x7911d3e2), X(0x29bb87bc), X(0x790179cd), X(0x29eb0957), X(0x78f10d0f), X(0x2a1a847b), X(0x78e08dab), X(0x2a49f920), X(0x78cffba3), X(0x2a796740), X(0x78bf56f9), X(0x2aa8ced3), X(0x78ae9fb0), X(0x2ad82fd2), X(0x789dd5cb), X(0x2b078a36), X(0x788cf94c), X(0x2b36ddf7), X(0x787c0a36), X(0x2b662b0e), X(0x786b088c), X(0x2b957173), X(0x7859f44f), X(0x2bc4b120), X(0x7848cd83), X(0x2bf3ea0d), X(0x7837942b), X(0x2c231c33), X(0x78264849), X(0x2c52478a), X(0x7814e9df), X(0x2c816c0c), X(0x780378f1), X(0x2cb089b1), X(0x77f1f581), X(0x2cdfa071), X(0x77e05f91), X(0x2d0eb046), X(0x77ceb725), X(0x2d3db928), X(0x77bcfc3f), X(0x2d6cbb10), X(0x77ab2ee2), X(0x2d9bb5f6), X(0x77994f11), X(0x2dcaa9d5), X(0x77875cce), X(0x2df996a3), X(0x7775581d), X(0x2e287c5a), X(0x776340ff), X(0x2e575af3), X(0x77511778), X(0x2e863267), X(0x773edb8b), X(0x2eb502ae), X(0x772c8d3a), X(0x2ee3cbc1), X(0x771a2c88), X(0x2f128d99), X(0x7707b979), X(0x2f41482e), X(0x76f5340e), X(0x2f6ffb7a), X(0x76e29c4b), X(0x2f9ea775), X(0x76cff232), X(0x2fcd4c19), X(0x76bd35c7), X(0x2ffbe95d), X(0x76aa670d), X(0x302a7f3a), X(0x76978605), X(0x30590dab), X(0x768492b4), X(0x308794a6), X(0x76718d1c), X(0x30b61426), X(0x765e7540), X(0x30e48c22), X(0x764b4b23), X(0x3112fc95), X(0x76380ec8), X(0x31416576), X(0x7624c031), X(0x316fc6be), X(0x76115f63), X(0x319e2067), X(0x75fdec60), X(0x31cc7269), X(0x75ea672a), X(0x31fabcbd), X(0x75d6cfc5), X(0x3228ff5c), X(0x75c32634), X(0x32573a3f), X(0x75af6a7b), X(0x32856d5e), X(0x759b9c9b), X(0x32b398b3), X(0x7587bc98), X(0x32e1bc36), X(0x7573ca75), X(0x330fd7e1), X(0x755fc635), X(0x333debab), X(0x754bafdc), X(0x336bf78f), X(0x7537876c), X(0x3399fb85), X(0x75234ce8), X(0x33c7f785), X(0x750f0054), X(0x33f5eb89), X(0x74faa1b3), X(0x3423d78a), X(0x74e63108), X(0x3451bb81), X(0x74d1ae55), X(0x347f9766), X(0x74bd199f), X(0x34ad6b32), X(0x74a872e8), X(0x34db36df), X(0x7493ba34), X(0x3508fa66), X(0x747eef85), X(0x3536b5be), X(0x746a12df), X(0x356468e2), X(0x74552446), X(0x359213c9), X(0x744023bc), X(0x35bfb66e), X(0x742b1144), X(0x35ed50c9), X(0x7415ece2), X(0x361ae2d3), X(0x7400b69a), X(0x36486c86), X(0x73eb6e6e), X(0x3675edd9), X(0x73d61461), X(0x36a366c6), X(0x73c0a878), X(0x36d0d746), X(0x73ab2ab4), X(0x36fe3f52), X(0x73959b1b), X(0x372b9ee3), X(0x737ff9ae), X(0x3758f5f2), X(0x736a4671), X(0x37864477), X(0x73548168), X(0x37b38a6d), X(0x733eaa96), X(0x37e0c7cc), X(0x7328c1ff), X(0x380dfc8d), X(0x7312c7a5), X(0x383b28a9), X(0x72fcbb8c), X(0x38684c19), X(0x72e69db7), X(0x389566d6), X(0x72d06e2b), X(0x38c278d9), X(0x72ba2cea), X(0x38ef821c), X(0x72a3d9f7), X(0x391c8297), X(0x728d7557), X(0x39497a43), X(0x7276ff0d), X(0x39766919), X(0x7260771b), X(0x39a34f13), X(0x7249dd86), X(0x39d02c2a), X(0x72333251), X(0x39fd0056), X(0x721c7580), X(0x3a29cb91), X(0x7205a716), X(0x3a568dd4), X(0x71eec716), X(0x3a834717), X(0x71d7d585), X(0x3aaff755), X(0x71c0d265), X(0x3adc9e86), X(0x71a9bdba), X(0x3b093ca3), X(0x71929789), X(0x3b35d1a5), X(0x717b5fd3), X(0x3b625d86), X(0x7164169d), X(0x3b8ee03e), X(0x714cbbeb), X(0x3bbb59c7), X(0x71354fc0), X(0x3be7ca1a), X(0x711dd220), X(0x3c143130), X(0x7106430e), X(0x3c408f03), X(0x70eea28e), X(0x3c6ce38a), X(0x70d6f0a4), X(0x3c992ec0), X(0x70bf2d53), X(0x3cc5709e), X(0x70a7589f), X(0x3cf1a91c), X(0x708f728b), X(0x3d1dd835), X(0x70777b1c), X(0x3d49fde1), X(0x705f7255), X(0x3d761a19), X(0x70475839), X(0x3da22cd7), X(0x702f2ccd), X(0x3dce3614), X(0x7016f014), X(0x3dfa35c8), X(0x6ffea212), X(0x3e262bee), X(0x6fe642ca), X(0x3e52187f), X(0x6fcdd241), X(0x3e7dfb73), X(0x6fb5507a), X(0x3ea9d4c3), X(0x6f9cbd79), X(0x3ed5a46b), X(0x6f841942), X(0x3f016a61), X(0x6f6b63d8), X(0x3f2d26a0), X(0x6f529d40), X(0x3f58d921), X(0x6f39c57d), X(0x3f8481dd), X(0x6f20dc92), X(0x3fb020ce), X(0x6f07e285), X(0x3fdbb5ec), X(0x6eeed758), X(0x40074132), X(0x6ed5bb10), X(0x4032c297), X(0x6ebc8db0), X(0x405e3a16), X(0x6ea34f3d), X(0x4089a7a8), X(0x6e89ffb9), X(0x40b50b46), X(0x6e709f2a), X(0x40e064ea), X(0x6e572d93), X(0x410bb48c), X(0x6e3daaf8), X(0x4136fa27), X(0x6e24175c), X(0x416235b2), X(0x6e0a72c5), X(0x418d6729), X(0x6df0bd35), X(0x41b88e84), X(0x6dd6f6b1), X(0x41e3abbc), X(0x6dbd1f3c), X(0x420ebecb), X(0x6da336dc), X(0x4239c7aa), X(0x6d893d93), X(0x4264c653), X(0x6d6f3365), X(0x428fbabe), X(0x6d551858), X(0x42baa4e6), X(0x6d3aec6e), X(0x42e584c3), X(0x6d20afac), X(0x43105a50), X(0x6d066215), X(0x433b2585), X(0x6cec03af), X(0x4365e65b), X(0x6cd1947c), X(0x43909ccd), X(0x6cb71482), X(0x43bb48d4), X(0x6c9c83c3), X(0x43e5ea68), X(0x6c81e245), X(0x44108184), X(0x6c67300b), X(0x443b0e21), X(0x6c4c6d1a), X(0x44659039), X(0x6c319975), X(0x449007c4), X(0x6c16b521), X(0x44ba74bd), X(0x6bfbc021), X(0x44e4d71c), X(0x6be0ba7b), X(0x450f2edb), X(0x6bc5a431), X(0x45397bf4), X(0x6baa7d49), X(0x4563be60), X(0x6b8f45c7), X(0x458df619), X(0x6b73fdae), X(0x45b82318), X(0x6b58a503), X(0x45e24556), X(0x6b3d3bcb), X(0x460c5cce), X(0x6b21c208), X(0x46366978), X(0x6b0637c1), X(0x46606b4e), X(0x6aea9cf8), X(0x468a624a), X(0x6acef1b2), X(0x46b44e65), X(0x6ab335f4), X(0x46de2f99), X(0x6a9769c1), X(0x470805df), X(0x6a7b8d1e), X(0x4731d131), X(0x6a5fa010), X(0x475b9188), X(0x6a43a29a), X(0x478546de), X(0x6a2794c1), X(0x47aef12c), X(0x6a0b7689), X(0x47d8906d), X(0x69ef47f6), X(0x48022499), X(0x69d3090e), X(0x482badab), X(0x69b6b9d3), X(0x48552b9b), X(0x699a5a4c), X(0x487e9e64), X(0x697dea7b), X(0x48a805ff), X(0x69616a65), X(0x48d16265), X(0x6944da10), X(0x48fab391), X(0x6928397e), X(0x4923f97b), X(0x690b88b5), X(0x494d341e), X(0x68eec7b9), X(0x49766373), X(0x68d1f68f), X(0x499f8774), X(0x68b5153a), X(0x49c8a01b), X(0x689823bf), X(0x49f1ad61), X(0x687b2224), X(0x4a1aaf3f), X(0x685e106c), X(0x4a43a5b0), X(0x6840ee9b), X(0x4a6c90ad), X(0x6823bcb7), X(0x4a957030), X(0x68067ac3), X(0x4abe4433), X(0x67e928c5), X(0x4ae70caf), X(0x67cbc6c0), X(0x4b0fc99d), X(0x67ae54ba), X(0x4b387af9), X(0x6790d2b6), X(0x4b6120bb), X(0x677340ba), X(0x4b89badd), X(0x67559eca), X(0x4bb24958), X(0x6737ecea), X(0x4bdacc28), X(0x671a2b20), X(0x4c034345), X(0x66fc596f), X(0x4c2baea9), X(0x66de77dc), X(0x4c540e4e), X(0x66c0866d), X(0x4c7c622d), X(0x66a28524), X(0x4ca4aa41), X(0x66847408), X(0x4ccce684), X(0x6666531d), X(0x4cf516ee), X(0x66482267), X(0x4d1d3b7a), X(0x6629e1ec), X(0x4d455422), X(0x660b91af), X(0x4d6d60df), X(0x65ed31b5), X(0x4d9561ac), X(0x65cec204), X(0x4dbd5682), X(0x65b0429f), X(0x4de53f5a), X(0x6591b38c), X(0x4e0d1c30), X(0x657314cf), X(0x4e34ecfc), X(0x6554666d), X(0x4e5cb1b9), X(0x6535a86b), X(0x4e846a60), X(0x6516dacd), X(0x4eac16eb), X(0x64f7fd98), X(0x4ed3b755), X(0x64d910d1), X(0x4efb4b96), X(0x64ba147d), X(0x4f22d3aa), X(0x649b08a0), X(0x4f4a4f89), X(0x647bed3f), X(0x4f71bf2e), X(0x645cc260), X(0x4f992293), X(0x643d8806), X(0x4fc079b1), X(0x641e3e38), X(0x4fe7c483), X(0x63fee4f8), X(0x500f0302), X(0x63df7c4d), X(0x50363529), X(0x63c0043b), X(0x505d5af1), X(0x63a07cc7), X(0x50847454), X(0x6380e5f6), X(0x50ab814d), X(0x63613fcd), X(0x50d281d5), X(0x63418a50), X(0x50f975e6), X(0x6321c585), X(0x51205d7b), X(0x6301f171), X(0x5147388c), X(0x62e20e17), X(0x516e0715), X(0x62c21b7e), X(0x5194c910), X(0x62a219aa), X(0x51bb7e75), X(0x628208a1), X(0x51e22740), X(0x6261e866), X(0x5208c36a), X(0x6241b8ff), X(0x522f52ee), X(0x62217a72), X(0x5255d5c5), X(0x62012cc2), X(0x527c4bea), X(0x61e0cff5), X(0x52a2b556), X(0x61c06410), X(0x52c91204), X(0x619fe918), X(0x52ef61ee), X(0x617f5f12), X(0x5315a50e), X(0x615ec603), X(0x533bdb5d), X(0x613e1df0), X(0x536204d7), X(0x611d66de), X(0x53882175), X(0x60fca0d2), X(0x53ae3131), X(0x60dbcbd1), X(0x53d43406), X(0x60bae7e1), X(0x53fa29ed), X(0x6099f505), X(0x542012e1), X(0x6078f344), X(0x5445eedb), X(0x6057e2a2), X(0x546bbdd7), X(0x6036c325), X(0x54917fce), X(0x601594d1), X(0x54b734ba), X(0x5ff457ad), X(0x54dcdc96), X(0x5fd30bbc), X(0x5502775c), X(0x5fb1b104), X(0x55280505), X(0x5f90478a), X(0x554d858d), X(0x5f6ecf53), X(0x5572f8ed), X(0x5f4d4865), X(0x55985f20), X(0x5f2bb2c5), X(0x55bdb81f), X(0x5f0a0e77), X(0x55e303e6), X(0x5ee85b82), X(0x5608426e), X(0x5ec699e9), X(0x562d73b2), X(0x5ea4c9b3), X(0x565297ab), X(0x5e82eae5), X(0x5677ae54), X(0x5e60fd84), X(0x569cb7a8), X(0x5e3f0194), X(0x56c1b3a1), X(0x5e1cf71c), X(0x56e6a239), X(0x5dfade20), X(0x570b8369), X(0x5dd8b6a7), X(0x5730572e), X(0x5db680b4), X(0x57551d80), X(0x5d943c4e), X(0x5779d65b), X(0x5d71e979), X(0x579e81b8), X(0x5d4f883b), X(0x57c31f92), X(0x5d2d189a), X(0x57e7afe4), X(0x5d0a9a9a), X(0x580c32a7), X(0x5ce80e41), X(0x5830a7d6), X(0x5cc57394), X(0x58550f6c), X(0x5ca2ca99), X(0x58796962), X(0x5c801354), X(0x589db5b3), X(0x5c5d4dcc), X(0x58c1f45b), X(0x5c3a7a05), X(0x58e62552), X(0x5c179806), X(0x590a4893), X(0x5bf4a7d2), X(0x592e5e19), X(0x5bd1a971), X(0x595265df), X(0x5bae9ce7), X(0x59765fde), X(0x5b8b8239), X(0x599a4c12), X(0x5b68596d), X(0x59be2a74), X(0x5b452288), X(0x59e1faff), X(0x5b21dd90), X(0x5a05bdae), X(0x5afe8a8b), X(0x5a29727b), X(0x5adb297d), X(0x5a4d1960), X(0x5ab7ba6c), X(0x5a70b258), X(0x5a943d5e), }; mednafen/psx/mdec.h000664 001750 001750 00000000656 12611054044 015356 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_MDEC_H #define __MDFN_PSX_MDEC_H void MDEC_DMAWrite(uint32_t V); uint32_t MDEC_DMARead(uint32_t *offs); void MDEC_Write(const int32_t timestamp, uint32_t A, uint32_t V); uint32_t MDEC_Read(const int32_t timestamp, uint32_t A); void MDEC_Power(void); bool MDEC_DMACanWrite(void); bool MDEC_DMACanRead(void); void MDEC_Run(int32 clocks); int MDEC_StateAction(StateMem *sm, int load, int data_only); #endif msvc/000700 001750 001750 00000000000 12702525066 012643 5ustar00sergiosergio000000 000000 mednafen/tremor/os.h000664 001750 001750 00000003274 12611054044 015564 0ustar00sergiosergio000000 000000 #ifndef _OS_H #define _OS_H /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: #ifdef jail to whip a few platforms into the UNIX ideal. ********************************************************************/ #include #include "os_types.h" #ifndef _V_IFDEFJAIL_H_ # define _V_IFDEFJAIL_H_ # ifdef __GNUC__ # define STIN static __inline__ # elif _WIN32 # define STIN static __inline # endif #else # define STIN static #endif #ifndef M_PI # define M_PI (3.1415926536f) #endif #ifdef _WIN32 # include # define rint(x) (floor((x)+0.5f)) # define NO_FLOAT_MATH_LIB # define FAST_HYPOT(a, b) sqrt((a)*(a) + (b)*(b)) # define LITTLE_ENDIAN 1 #endif #ifdef HAVE_ALLOCA_H # include #endif #ifdef USE_MEMORY_H # include #endif #ifndef min # define min(x,y) ((x)>(y)?(y):(x)) #endif #ifndef max # define max(x,y) ((x)<(y)?(y):(x)) #endif #endif /* _OS_H */ mednafen/include/trio/trio.h000664 001750 001750 00000016674 12611054044 017220 0ustar00sergiosergio000000 000000 /************************************************************************* * * $Id: trio.h,v 1.19 2009/09/13 10:12:22 breese Exp $ * * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg. * * Permission to use, copy, modify, and 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. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************* * * http://ctrio.sourceforge.net/ * ************************************************************************/ #ifndef TRIO_TRIO_H #define TRIO_TRIO_H #if !defined(WITHOUT_TRIO) /* * Use autoconf defines if present. Packages using trio must define * HAVE_CONFIG_H as a compiler option themselves. */ #if defined(HAVE_CONFIG_H) # include #endif #include "triop.h" #include #ifdef __cplusplus extern "C" { #endif /* * Error codes. * * Remember to add a textual description to trio_strerror. */ enum { TRIO_EOF = 1, TRIO_EINVAL = 2, TRIO_ETOOMANY = 3, TRIO_EDBLREF = 4, TRIO_EGAP = 5, TRIO_ENOMEM = 6, TRIO_ERANGE = 7, TRIO_ERRNO = 8, TRIO_ECUSTOM = 9 }; /* Error macros */ #define TRIO_ERROR_CODE(x) ((-(x)) & 0x00FF) #define TRIO_ERROR_POSITION(x) ((-(x)) >> 8) #define TRIO_ERROR_NAME(x) trio_strerror(x) typedef int (*trio_outstream_t) TRIO_PROTO((trio_pointer_t, int)); typedef int (*trio_instream_t) TRIO_PROTO((trio_pointer_t)); TRIO_CONST char *trio_strerror TRIO_PROTO((int)); /************************************************************************* * Print Functions */ int trio_printf TRIO_PROTO((TRIO_CONST char *format, ...)); int trio_vprintf TRIO_PROTO((TRIO_CONST char *format, va_list args)); int trio_printfv TRIO_PROTO((TRIO_CONST char *format, void **args)); int trio_fprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...)); int trio_vfprintf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args)); int trio_fprintfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args)); int trio_dprintf TRIO_PROTO((int fd, TRIO_CONST char *format, ...)); int trio_vdprintf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args)); int trio_dprintfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args)); int trio_cprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, ...)); int trio_vcprintf TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, va_list args)); int trio_cprintfv TRIO_PROTO((trio_outstream_t stream, trio_pointer_t closure, TRIO_CONST char *format, void **args)); int trio_sprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, ...)); int trio_vsprintf TRIO_PROTO((char *buffer, TRIO_CONST char *format, va_list args)); int trio_sprintfv TRIO_PROTO((char *buffer, TRIO_CONST char *format, void **args)); int trio_snprintf TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...)); int trio_vsnprintf TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, va_list args)); int trio_snprintfv TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, void **args)); int trio_snprintfcat TRIO_PROTO((char *buffer, size_t max, TRIO_CONST char *format, ...)); int trio_vsnprintfcat TRIO_PROTO((char *buffer, size_t bufferSize, TRIO_CONST char *format, va_list args)); #if defined(TRIO_DEPRECATED) char *trio_aprintf TRIO_PROTO((TRIO_CONST char *format, ...)); char *trio_vaprintf TRIO_PROTO((TRIO_CONST char *format, va_list args)); #endif int trio_asprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, ...)); int trio_vasprintf TRIO_PROTO((char **ret, TRIO_CONST char *format, va_list args)); int trio_asprintfv TRIO_PROTO((char **result, TRIO_CONST char *format, trio_pointer_t * args)); /************************************************************************* * Scan Functions */ int trio_scanf TRIO_PROTO((TRIO_CONST char *format, ...)); int trio_vscanf TRIO_PROTO((TRIO_CONST char *format, va_list args)); int trio_scanfv TRIO_PROTO((TRIO_CONST char *format, void **args)); int trio_fscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, ...)); int trio_vfscanf TRIO_PROTO((FILE *file, TRIO_CONST char *format, va_list args)); int trio_fscanfv TRIO_PROTO((FILE *file, TRIO_CONST char *format, void **args)); int trio_dscanf TRIO_PROTO((int fd, TRIO_CONST char *format, ...)); int trio_vdscanf TRIO_PROTO((int fd, TRIO_CONST char *format, va_list args)); int trio_dscanfv TRIO_PROTO((int fd, TRIO_CONST char *format, void **args)); int trio_cscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, ...)); int trio_vcscanf TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, va_list args)); int trio_cscanfv TRIO_PROTO((trio_instream_t stream, trio_pointer_t closure, TRIO_CONST char *format, void **args)); int trio_sscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, ...)); int trio_vsscanf TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, va_list args)); int trio_sscanfv TRIO_PROTO((TRIO_CONST char *buffer, TRIO_CONST char *format, void **args)); /************************************************************************* * Locale Functions */ void trio_locale_set_decimal_point TRIO_PROTO((char *decimalPoint)); void trio_locale_set_thousand_separator TRIO_PROTO((char *thousandSeparator)); void trio_locale_set_grouping TRIO_PROTO((char *grouping)); /************************************************************************* * Renaming */ #ifdef TRIO_REPLACE_STDIO /* Replace the functions */ #ifndef HAVE_PRINTF # undef printf # define printf trio_printf #endif #ifndef HAVE_VPRINTF # undef vprintf # define vprintf trio_vprintf #endif #ifndef HAVE_FPRINTF # undef fprintf # define fprintf trio_fprintf #endif #ifndef HAVE_VFPRINTF # undef vfprintf # define vfprintf trio_vfprintf #endif #ifndef HAVE_SPRINTF # undef sprintf # define sprintf trio_sprintf #endif #ifndef HAVE_VSPRINTF # undef vsprintf # define vsprintf trio_vsprintf #endif #ifndef HAVE_SNPRINTF # undef snprintf # define snprintf trio_snprintf #endif #ifndef HAVE_VSNPRINTF # undef vsnprintf # define vsnprintf trio_vsnprintf #endif #ifndef HAVE_SCANF # undef scanf # define scanf trio_scanf #endif #ifndef HAVE_VSCANF # undef vscanf # define vscanf trio_vscanf #endif #ifndef HAVE_FSCANF # undef fscanf # define fscanf trio_fscanf #endif #ifndef HAVE_VFSCANF # undef vfscanf # define vfscanf trio_vfscanf #endif #ifndef HAVE_SSCANF # undef sscanf # define sscanf trio_sscanf #endif #ifndef HAVE_VSSCANF # undef vsscanf # define vsscanf trio_vsscanf #endif /* These aren't stdio functions, but we make them look similar */ #undef dprintf #define dprintf trio_dprintf #undef vdprintf #define vdprintf trio_vdprintf #undef aprintf #define aprintf trio_aprintf #undef vaprintf #define vaprintf trio_vaprintf #undef asprintf #define asprintf trio_asprintf #undef vasprintf #define vasprintf trio_vasprintf #undef dscanf #define dscanf trio_dscanf #undef vdscanf #define vdscanf trio_vdscanf #endif #ifdef __cplusplus } /* extern "C" */ #endif #endif /* WITHOUT_TRIO */ #endif /* TRIO_TRIO_H */ mednafen/psx/input/guncon.h000664 001750 001750 00000000257 12611054044 017073 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_INPUT_GUNCON_H #define __MDFN_PSX_INPUT_GUNCON_H InputDevice *Device_GunCon_Create(void); extern InputDeviceInputInfoStruct Device_GunCon_IDII[6]; #endif mednafen/mednafen-driver.h000664 001750 001750 00000001356 12611054044 016700 0ustar00sergiosergio000000 000000 #ifndef __MDFN_MEDNAFEN_DRIVER_H #define __MDFN_MEDNAFEN_DRIVER_H #include #include #include #include "settings-common.h" extern std::vectorMDFNSystems; MDFNGI *MDFNI_LoadCD(const char *sysname, const char *devicename); // Call this function as early as possible, even before MDFNI_Initialize() bool MDFNI_InitializeModule(void); /* Sets the base directory(save states, snapshots, etc. are saved in directories below this directory. */ void MDFNI_SetBaseDirectory(const char *dir); /* Closes currently loaded game */ void MDFNI_CloseGame(void); void MDFN_DispMessage(const char *format, ...); #define MDFNI_DispMessage MDFN_DispMessage uint32 MDFNI_CRC32(uint32 crc, uint8 *buf, uint32 len); #endif jni/Android.mk000664 001750 001750 00000002504 12611054044 014371 0ustar00sergiosergio000000 000000 LOCAL_PATH := $(call my-dir) DEBUG = 0 FRONTEND_SUPPORTS_RGB565 = 1 FAST = 1 include $(CLEAR_VARS) ifeq ($(TARGET_ARCH),arm) ANDROID_FLAGS := -DANDROID_ARM LOCAL_ARM_MODE := arm endif ifeq ($(TARGET_ARCH),x86) ANDROID_FLAGS := -DANDROID_X86 IS_X86 = 1 endif ifeq ($(TARGET_ARCH),mips) ANDROID_FLAGS := -DANDROID_MIPS -D__mips__ -D__MIPSEL__ endif LOCAL_CXXFLAGS += $(ANDROID_FLAGS) LOCAL_CFLAGS += $(ANDROID_FLAGS) CORE_DIR := .. LOCAL_MODULE := libretro PTHREAD_FLAGS = -pthread NEED_CD = 1 NEED_BPP = 32 WANT_NEW_API = 1 NEED_DEINTERLACER = 1 NEED_THREADING = 1 NEED_TREMOR = 1 CORE_DEFINE := -DWANT_PSX_EMU TARGET_NAME := mednafen_psx_libretro include ../Makefile.common LOCAL_SRC_FILES += $(SOURCES_CXX) $(SOURCES_C) EXTRA_GCC_FLAGS := -funroll-loops ifeq ($(DEBUG),0) FLAGS += -O3 $(EXTRA_GCC_FLAGS) else FLAGS += -O0 -g endif LDFLAGS += $(fpic) $(SHARED) FLAGS += $(fpic) $(NEW_GCC_FLAGS) $(INCFLAGS) FLAGS += $(ENDIANNESS_DEFINES) -DSIZEOF_DOUBLE=8 $(WARNINGS) -DMEDNAFEN_VERSION=\"0.9.26\" -DPACKAGE=\"mednafen\" -DMEDNAFEN_VERSION_NUMERIC=926 -DPSS_STYLE=1 -DMPC_FIXED_POINT $(CORE_DEFINE) -DSTDC_HEADERS -D__STDC_LIMIT_MACROS -D__LIBRETRO__ -DNDEBUG -D_LOW_ACCURACY_ $(SOUND_DEFINE) -D__STDC_CONSTANT_MACROS LOCAL_CFLAGS = $(FLAGS) LOCAL_CXXFLAGS = $(FLAGS) -fexceptions include $(BUILD_SHARED_LIBRARY) mednafen/include/retro_inline.h000664 001750 001750 00000003253 12611054044 017744 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_inline.h). * --------------------------------------------------------------------------------------- * * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_INLINE_H #define __LIBRETRO_SDK_INLINE_H #ifndef INLINE #if !defined(__cplusplus) && defined(_WIN32) #define INLINE _inline #elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L #define INLINE inline #elif defined(__GNUC__) #define INLINE __inline__ #else #define INLINE #endif #endif #endif mednafen/tremor/window.h000664 001750 001750 00000002215 12611054044 016444 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: window functions ********************************************************************/ #ifndef _V_WINDOW_ #define _V_WINDOW_ extern const void *_vorbis_window(int type,int left); extern void _vorbis_apply_window(ogg_int32_t *d,const void *window[2], long *blocksizes, int lW,int W,int nW); #endif mednafen/include/trio/triostr.h000664 001750 001750 00000040110 12611054044 017727 0ustar00sergiosergio000000 000000 /************************************************************************* * * $Id: triostr.h,v 1.18 2010/01/26 13:02:02 breese Exp $ * * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg. * * Permission to use, copy, modify, and 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. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************/ #ifndef TRIO_TRIOSTR_H #define TRIO_TRIOSTR_H /* * Documentation is located in triostr.c */ #include #include #include #include #include "triodef.h" #include "triop.h" #ifdef __cplusplus extern "C" { #endif enum { TRIO_HASH_NONE = 0, TRIO_HASH_PLAIN, TRIO_HASH_TWOSIGNED }; #if !defined(TRIO_PUBLIC_STRING) # if !defined(TRIO_PUBLIC) # define TRIO_PUBLIC # endif # define TRIO_PUBLIC_STRING TRIO_PUBLIC #endif /************************************************************************* * Dependencies */ #if defined(TRIO_EMBED_STRING) /* * The application that triostr is embedded in must define which functions * it uses. * * The following resolves internal dependencies. */ # if defined(TRIO_FUNC_XSTRING_SET) # if !defined(TRIO_FUNC_DUPLICATE) # define TRIO_FUNC_DUPLICATE # endif # endif # if defined(TRIO_FUNC_DUPLICATE) \ || defined(TRIO_FUNC_DUPLICATE_MAX) \ || defined(TRIO_FUNC_STRING_DUPLICATE) \ || defined(TRIO_FUNC_XSTRING_DUPLICATE) # if !defined(TRIO_FUNC_CREATE) # define TRIO_FUNC_CREATE # endif # if !defined(TRIO_FUNC_COPY_MAX) # define TRIO_FUNC_COPY_MAX # endif # endif # if defined(TRIO_FUNC_STRING_CREATE) # if !defined(TRIO_FUNC_STRING_DESTROY) # define TRIO_FUNC_STRING_DESTROY # endif # endif # if defined(TRIO_FUNC_STRING_DESTROY) \ || defined(TRIO_FUNC_XSTRING_SET) # if !defined(TRIO_FUNC_DESTROY) # define TRIO_FUNC_DESTROY # endif # endif # if defined(TRIO_FUNC_EQUAL_LOCALE) \ || defined(TRIO_FUNC_STRING_EQUAL) \ || defined(TRIO_FUNC_XSTRING_EQUAL) # if !defined(TRIO_FUNC_EQUAL) # define TRIO_FUNC_EQUAL # endif # endif # if defined(TRIO_FUNC_EQUAL_CASE) \ || defined(TRIO_FUNC_STRING_EQUAL_CASE) \ || defined(TRIO_FUNC_XSTRING_EQUAL_CASE) # if !defined(TRIO_FUNC_EQUAL_CASE) # define TRIO_FUNC_EQUAL_CASE # endif # endif # if defined(TRIO_FUNC_SUBSTRING_MAX) \ || defined(TRIO_FUNC_STRING_EQUAL_MAX) \ || defined(TRIO_FUNC_XSTRING_EQUAL_MAX) # if !defined(TRIO_FUNC_EQUAL_MAX) # define TRIO_FUNC_EQUAL_MAX # endif # endif # if defined(TRIO_FUNC_TO_DOUBLE) \ || defined(TRIO_FUNC_TO_FLOAT) # if !defined(TRIO_FUNC_TO_LONG_DOUBLE) # define TRIO_FUNC_TO_LONG_DOUBLE # endif # endif # if defined(TRIO_FUNC_STRING_TERMINATE) # if !defined(TRIO_FUNC_XSTRING_APPEND_CHAR) # define TRIO_FUNC_XSTRING_APPEND_CHAR # endif # endif # if defined(TRIO_FUNC_XSTRING_APPEND_CHAR) # if !defined(TRIO_FUNC_STRING_SIZE) # define TRIO_FUNC_STRING_SIZE # endif # endif #else /* * When triostr is not embedded all functions are defined. */ # define TRIO_FUNC_APPEND # define TRIO_FUNC_APPEND_MAX # define TRIO_FUNC_CONTAINS # define TRIO_FUNC_COPY # define TRIO_FUNC_COPY_MAX # define TRIO_FUNC_CREATE # define TRIO_FUNC_DESTROY # define TRIO_FUNC_DUPLICATE # define TRIO_FUNC_DUPLICATE_MAX # define TRIO_FUNC_EQUAL # define TRIO_FUNC_EQUAL_CASE # define TRIO_FUNC_EQUAL_CASE_MAX # define TRIO_FUNC_EQUAL_LOCALE # define TRIO_FUNC_EQUAL_MAX # define TRIO_FUNC_ERROR # if !defined(TRIO_PLATFORM_WINCE) # define TRIO_FUNC_FORMAT_DATE_MAX # endif # define TRIO_FUNC_HASH # define TRIO_FUNC_INDEX # define TRIO_FUNC_INDEX_LAST # define TRIO_FUNC_LENGTH # define TRIO_FUNC_LENGTH_MAX # define TRIO_FUNC_LOWER # define TRIO_FUNC_MATCH # define TRIO_FUNC_MATCH_CASE # define TRIO_FUNC_SPAN_FUNCTION # define TRIO_FUNC_SUBSTRING # define TRIO_FUNC_SUBSTRING_MAX # define TRIO_FUNC_TO_DOUBLE # define TRIO_FUNC_TO_FLOAT # define TRIO_FUNC_TO_LONG # define TRIO_FUNC_TO_LONG_DOUBLE # define TRIO_FUNC_TO_LOWER # define TRIO_FUNC_TO_UNSIGNED_LONG # define TRIO_FUNC_TO_UPPER # define TRIO_FUNC_TOKENIZE # define TRIO_FUNC_UPPER # define TRIO_FUNC_STRING_APPEND # define TRIO_FUNC_STRING_CONTAINS # define TRIO_FUNC_STRING_COPY # define TRIO_FUNC_STRING_CREATE # define TRIO_FUNC_STRING_DESTROY # define TRIO_FUNC_STRING_DUPLICATE # define TRIO_FUNC_STRING_EQUAL # define TRIO_FUNC_STRING_EQUAL_CASE # define TRIO_FUNC_STRING_EQUAL_CASE_MAX # define TRIO_FUNC_STRING_EQUAL_MAX # define TRIO_FUNC_STRING_EXTRACT # if !defined(TRIO_PLATFORM_WINCE) # define TRIO_FUNC_STRING_FORMAT_DATE_MAX # endif # define TRIO_FUNC_STRING_GET # define TRIO_FUNC_STRING_INDEX # define TRIO_FUNC_STRING_INDEX_LAST # define TRIO_FUNC_STRING_LENGTH # define TRIO_FUNC_STRING_LOWER # define TRIO_FUNC_STRING_MATCH # define TRIO_FUNC_STRING_MATCH_CASE # define TRIO_FUNC_STRING_SIZE # define TRIO_FUNC_STRING_SUBSTRING # define TRIO_FUNC_STRING_TERMINATE # define TRIO_FUNC_STRING_UPPER # define TRIO_FUNC_XSTRING_APPEND # define TRIO_FUNC_XSTRING_APPEND_CHAR # define TRIO_FUNC_XSTRING_APPEND_MAX # define TRIO_FUNC_XSTRING_CONTAINS # define TRIO_FUNC_XSTRING_COPY # define TRIO_FUNC_XSTRING_DUPLICATE # define TRIO_FUNC_XSTRING_EQUAL # define TRIO_FUNC_XSTRING_EQUAL_CASE # define TRIO_FUNC_XSTRING_EQUAL_CASE_MAX # define TRIO_FUNC_XSTRING_EQUAL_MAX # define TRIO_FUNC_XSTRING_MATCH # define TRIO_FUNC_XSTRING_MATCH_CASE # define TRIO_FUNC_XSTRING_SET # define TRIO_FUNC_XSTRING_SUBSTRING #endif /************************************************************************* * String functions */ #if defined(TRIO_FUNC_APPEND) TRIO_PUBLIC_STRING int trio_append TRIO_PROTO((char *target, TRIO_CONST char *source)); #endif #if defined(TRIO_FUNC_APPEND_MAX) TRIO_PUBLIC_STRING int trio_append_max TRIO_PROTO((char *target, size_t max, TRIO_CONST char *source)); #endif #if defined(TRIO_FUNC_CONTAINS) TRIO_PUBLIC_STRING int trio_contains TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *substring)); #endif #if defined(TRIO_FUNC_COPY) TRIO_PUBLIC_STRING int trio_copy TRIO_PROTO((char *target, TRIO_CONST char *source)); #endif #if defined(TRIO_FUNC_COPY_MAX) TRIO_PUBLIC_STRING int trio_copy_max TRIO_PROTO((char *target, size_t max, TRIO_CONST char *source)); #endif #if defined(TRIO_FUNC_CREATE) TRIO_PUBLIC_STRING char * trio_create TRIO_PROTO((size_t size)); #endif #if defined(TRIO_FUNC_DESTROY) TRIO_PUBLIC_STRING void trio_destroy TRIO_PROTO((char *string)); #endif #if defined(TRIO_FUNC_DUPLICATE) TRIO_PUBLIC_STRING char * trio_duplicate TRIO_PROTO((TRIO_CONST char *source)); #endif #if defined(TRIO_FUNC_DUPLICATE_MAX) TRIO_PUBLIC_STRING char * trio_duplicate_max TRIO_PROTO((TRIO_CONST char *source, size_t max)); #endif #if defined(TRIO_FUNC_EQUAL) TRIO_PUBLIC_STRING int trio_equal TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second)); #endif #if defined(TRIO_FUNC_EQUAL_CASE) TRIO_PUBLIC_STRING int trio_equal_case TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second)); #endif #if defined(TRIO_FUNC_EQUAL_CASE_MAX) TRIO_PUBLIC_STRING int trio_equal_case_max TRIO_PROTO((TRIO_CONST char *first, size_t max, TRIO_CONST char *second)); #endif #if defined(TRIO_FUNC_EQUAL_LOCALE) TRIO_PUBLIC_STRING int trio_equal_locale TRIO_PROTO((TRIO_CONST char *first, TRIO_CONST char *second)); #endif #if defined(TRIO_FUNC_EQUAL_MAX) TRIO_PUBLIC_STRING int trio_equal_max TRIO_PROTO((TRIO_CONST char *first, size_t max, TRIO_CONST char *second)); #endif #if defined(TRIO_FUNC_ERROR) TRIO_PUBLIC_STRING TRIO_CONST char * trio_error TRIO_PROTO((int)); #endif #if defined(TRIO_FUNC_FORMAT_DATE_MAX) TRIO_PUBLIC_STRING size_t trio_format_date_max TRIO_PROTO((char *target, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime)); #endif #if defined(TRIO_FUNC_HASH) TRIO_PUBLIC_STRING unsigned long trio_hash TRIO_PROTO((TRIO_CONST char *string, int type)); #endif #if defined(TRIO_FUNC_INDEX) TRIO_PUBLIC_STRING char * trio_index TRIO_PROTO((TRIO_CONST char *string, int character)); #endif #if defined(TRIO_FUNC_INDEX_LAST) TRIO_PUBLIC_STRING char * trio_index_last TRIO_PROTO((TRIO_CONST char *string, int character)); #endif #if defined(TRIO_FUNC_LENGTH) TRIO_PUBLIC_STRING size_t trio_length TRIO_PROTO((TRIO_CONST char *string)); #endif #if defined(TRIO_FUNC_LENGTH_MAX) TRIO_PUBLIC_STRING size_t trio_length_max TRIO_PROTO((TRIO_CONST char *string, size_t max)); #endif #if defined(TRIO_FUNC_LOWER) TRIO_PUBLIC_STRING int trio_lower TRIO_PROTO((char *target)); #endif #if defined(TRIO_FUNC_MATCH) TRIO_PUBLIC_STRING int trio_match TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *pattern)); #endif #if defined(TRIO_FUNC_MATCH_CASE) TRIO_PUBLIC_STRING int trio_match_case TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *pattern)); #endif #if defined(TRIO_FUNC_SPAN_FUNCTION) TRIO_PUBLIC_STRING size_t trio_span_function TRIO_PROTO((char *target, TRIO_CONST char *source, int (*Function) TRIO_PROTO((int)))); #endif #if defined(TRIO_FUNC_SUBSTRING) TRIO_PUBLIC_STRING char * trio_substring TRIO_PROTO((TRIO_CONST char *string, TRIO_CONST char *substring)); #endif #if defined(TRIO_FUNC_SUBSTRING_MAX) TRIO_PUBLIC_STRING char * trio_substring_max TRIO_PROTO((TRIO_CONST char *string, size_t max, TRIO_CONST char *substring)); #endif #if defined(TRIO_FUNC_TO_DOUBLE) TRIO_PUBLIC_STRING double trio_to_double TRIO_PROTO((TRIO_CONST char *source, char **endp)); #endif #if defined(TRIO_FUNC_TO_FLOAT) TRIO_PUBLIC_STRING float trio_to_float TRIO_PROTO((TRIO_CONST char *source, char **endp)); #endif #if defined(TRIO_FUNC_TO_LONG) TRIO_PUBLIC_STRING long trio_to_long TRIO_PROTO((TRIO_CONST char *source, char **endp, int base)); #endif #if defined(TRIO_FUNC_TO_LOWER) TRIO_PUBLIC_STRING int trio_to_lower TRIO_PROTO((int source)); #endif #if defined(TRIO_FUNC_TO_LONG_DOUBLE) TRIO_PUBLIC_STRING trio_long_double_t trio_to_long_double TRIO_PROTO((TRIO_CONST char *source, char **endp)); #endif #if defined(TRIO_FUNC_TO_UNSIGNED_LONG) TRIO_PUBLIC_STRING unsigned long trio_to_unsigned_long TRIO_PROTO((TRIO_CONST char *source, char **endp, int base)); #endif #if defined(TRIO_FUNC_TO_UPPER) TRIO_PUBLIC_STRING int trio_to_upper TRIO_PROTO((int source)); #endif #if defined(TRIO_FUNC_TOKENIZE) TRIO_PUBLIC_STRING char * trio_tokenize TRIO_PROTO((char *string, TRIO_CONST char *delimiters)); #endif #if defined(TRIO_FUNC_UPPER) TRIO_PUBLIC_STRING int trio_upper TRIO_PROTO((char *target)); #endif /************************************************************************* * Dynamic string functions */ /* * Opaque type for dynamic strings */ typedef struct _trio_string_t trio_string_t; #if defined(TRIO_FUNC_STRING_APPEND) TRIO_PUBLIC_STRING int trio_string_append TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_CONTAINS) TRIO_PUBLIC_STRING int trio_string_contains TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_COPY) TRIO_PUBLIC_STRING int trio_string_copy TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_CREATE) TRIO_PUBLIC_STRING trio_string_t * trio_string_create TRIO_PROTO((int initial_size)); #endif #if defined(TRIO_FUNC_STRING_DESTROY) TRIO_PUBLIC_STRING void trio_string_destroy TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_DUPLICATE) TRIO_PUBLIC_STRING trio_string_t * trio_string_duplicate TRIO_PROTO((trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_EQUAL) TRIO_PUBLIC_STRING int trio_string_equal TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_EQUAL_MAX) TRIO_PUBLIC_STRING int trio_string_equal_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *second)); #endif #if defined(TRIO_FUNC_STRING_EQUAL_CASE) TRIO_PUBLIC_STRING int trio_string_equal_case TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_EQUAL_CASE_MAX) TRIO_PUBLIC_STRING int trio_string_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_EXTRACT) TRIO_PUBLIC_STRING char * trio_string_extract TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_FORMAT_DATE_MAX) TRIO_PUBLIC_STRING size_t trio_string_format_date_max TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime)); #endif #if defined(TRIO_FUNC_STRING_GET) TRIO_PUBLIC_STRING char * trio_string_get TRIO_PROTO((trio_string_t *self, int offset)); #endif #if defined(TRIO_FUNC_STRING_INDEX) TRIO_PUBLIC_STRING char * trio_string_index TRIO_PROTO((trio_string_t *self, int character)); #endif #if defined(TRIO_FUNC_STRING_INDEX_LAST) TRIO_PUBLIC_STRING char * trio_string_index_last TRIO_PROTO((trio_string_t *self, int character)); #endif #if defined(TRIO_FUNC_STRING_LENGTH) TRIO_PUBLIC_STRING int trio_string_length TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_LOWER) TRIO_PUBLIC_STRING int trio_string_lower TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_MATCH) TRIO_PUBLIC_STRING int trio_string_match TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_MATCH_CASE) TRIO_PUBLIC_STRING int trio_string_match_case TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_SIZE) TRIO_PUBLIC_STRING int trio_string_size TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_SUBSTRING) TRIO_PUBLIC_STRING char * trio_string_substring TRIO_PROTO((trio_string_t *self, trio_string_t *other)); #endif #if defined(TRIO_FUNC_STRING_TERMINATE) TRIO_PUBLIC_STRING void trio_string_terminate TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_STRING_UPPER) TRIO_PUBLIC_STRING int trio_string_upper TRIO_PROTO((trio_string_t *self)); #endif #if defined(TRIO_FUNC_XSTRING_APPEND) TRIO_PUBLIC_STRING int trio_xstring_append TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_APPEND_CHAR) TRIO_PUBLIC_STRING int trio_xstring_append_char TRIO_PROTO((trio_string_t *self, char character)); #endif #if defined(TRIO_FUNC_XSTRING_APPEND_MAX) TRIO_PUBLIC_STRING int trio_xstring_append_max TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other, size_t max)); #endif #if defined(TRIO_FUNC_XSTRING_CONTAINS) TRIO_PUBLIC_STRING int trio_xstring_contains TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_COPY) TRIO_PUBLIC_STRING int trio_xstring_copy TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_DUPLICATE) TRIO_PUBLIC_STRING trio_string_t * trio_xstring_duplicate TRIO_PROTO((TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_EQUAL) TRIO_PUBLIC_STRING int trio_xstring_equal TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_EQUAL_MAX) TRIO_PUBLIC_STRING int trio_xstring_equal_max TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_EQUAL_CASE) TRIO_PUBLIC_STRING int trio_xstring_equal_case TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_EQUAL_CASE_MAX) TRIO_PUBLIC_STRING int trio_xstring_equal_case_max TRIO_PROTO((trio_string_t *self, size_t max, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_MATCH) TRIO_PUBLIC_STRING int trio_xstring_match TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_MATCH_CASE) TRIO_PUBLIC_STRING int trio_xstring_match_case TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #if defined(TRIO_FUNC_XSTRING_SET) TRIO_PUBLIC_STRING void trio_xstring_set TRIO_PROTO((trio_string_t *self, char *buffer)); #endif #if defined(TRIO_FUNC_XSTRING_SUBSTRING) TRIO_PUBLIC_STRING char * trio_xstring_substring TRIO_PROTO((trio_string_t *self, TRIO_CONST char *other)); #endif #ifdef __cplusplus } #endif #endif /* TRIO_TRIOSTR_H */ mednafen/tremor/tremor_shared.h000664 001750 001750 00000001255 12611054044 017776 0ustar00sergiosergio000000 000000 #ifndef _TREMOR_SHARED_H_ #define _TREMOR_SHARED_H_ #include #include #include #ifdef __cplusplus extern "C" { #endif static INLINE int ilog(unsigned int v) { int ret=0; while(v) { ret++; v>>=1; } return(ret); } #include "os_types.h" static INLINE ogg_uint32_t bitreverse(ogg_uint32_t x) { x= ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL); x= ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL); x= ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL); x= ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL); return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL); } #ifdef __cplusplus } #endif #endif mednafen/tremor/codebook.h000664 001750 001750 00000007752 12611054044 016735 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: basic shared codebook operations ********************************************************************/ #ifndef _V_CODEBOOK_H_ #define _V_CODEBOOK_H_ #include "ogg.h" /* This structure encapsulates huffman and VQ style encoding books; it doesn't do anything specific to either. valuelist/quantlist are nonNULL (and q_* significant) only if there's entry->value mapping to be done. If encode-side mapping must be done (and thus the entry needs to be hunted), the auxiliary encode pointer will point to a decision tree. This is true of both VQ and huffman, but is mostly useful with VQ. */ typedef struct static_codebook{ long dim; /* codebook dimensions (elements per vector) */ long entries; /* codebook entries */ long *lengthlist; /* codeword lengths in bits */ /* mapping ***************************************************************/ int maptype; /* 0=none 1=implicitly populated values from map column 2=listed arbitrary values */ /* The below does a linear, single monotonic sequence mapping. */ long q_min; /* packed 32 bit float; quant value 0 maps to minval */ long q_delta; /* packed 32 bit float; val 1 - val 0 == delta */ int q_quant; /* bits: 0 < quant <= 16 */ int q_sequencep; /* bitflag */ long *quantlist; /* map == 1: (int)(entries^(1/dim)) element column map map == 2: list of dim*entries quantized entry vals */ } static_codebook; typedef struct codebook{ long dim; /* codebook dimensions (elements per vector) */ long entries; /* codebook entries */ long used_entries; /* populated codebook entries */ /* the below are ordered by bitreversed codeword and only used entries are populated */ int binarypoint; ogg_int32_t *valuelist; /* list of dim*entries actual entry values */ ogg_uint32_t *codelist; /* list of bitstream codewords for each entry */ int *dec_index; char *dec_codelengths; ogg_uint32_t *dec_firsttable; int dec_firsttablen; int dec_maxlength; long q_min; /* packed 32 bit float; quant value 0 maps to minval */ long q_delta; /* packed 32 bit float; val 1 - val 0 == delta */ } codebook; extern void vorbis_staticbook_destroy(static_codebook *b); extern int vorbis_book_init_decode(codebook *dest,const static_codebook *source); extern void vorbis_book_clear(codebook *b); extern long _book_maptype1_quantvals(const static_codebook *b); extern static_codebook *vorbis_staticbook_unpack(oggpack_buffer *b); extern long vorbis_book_decode(codebook *book, oggpack_buffer *b); extern long vorbis_book_decodevs_add(codebook *book, ogg_int32_t *a, oggpack_buffer *b,int n,int point); extern long vorbis_book_decodev_set(codebook *book, ogg_int32_t *a, oggpack_buffer *b,int n,int point); extern long vorbis_book_decodev_add(codebook *book, ogg_int32_t *a, oggpack_buffer *b,int n,int point); extern long vorbis_book_decodevv_add(codebook *book, ogg_int32_t **a, long off,int ch, oggpack_buffer *b,int n,int point); extern int _ilog(unsigned int v); #endif mednafen/psx/dma.h000664 001750 001750 00000000571 12611054044 015203 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_DMA_H #define __MDFN_PSX_DMA_H int32_t DMA_Update(const int32_t timestamp); void DMA_Write(const int32_t timestamp, uint32_t A, uint32_t V); uint32_t DMA_Read(const int32_t timestamp, uint32_t A); void DMA_ResetTS(void); void DMA_Power(void); void DMA_Init(void); void DMA_Kill(void); int DMA_StateAction(StateMem *sm, int load, int data_only); #endif mednafen/tremor/window.c000664 001750 001750 00000004107 12611054044 016441 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: window functions ********************************************************************/ #include #include #include "misc.h" #include "window.h" #include "window_lookup.h" const void *_vorbis_window(int type, int left){ switch(type){ case 0: switch(left){ case 32: return vwin64; case 64: return vwin128; case 128: return vwin256; case 256: return vwin512; case 512: return vwin1024; case 1024: return vwin2048; case 2048: return vwin4096; case 4096: return vwin8192; default: return(0); } break; default: return(0); } } void _vorbis_apply_window(ogg_int32_t *d,const void *window_p[2], long *blocksizes, int lW,int W,int nW){ LOOKUP_T *window[2]={window_p[0],window_p[1]}; long n=blocksizes[W]; long ln=blocksizes[lW]; long rn=blocksizes[nW]; long leftbegin=n/4-ln/4; long leftend=leftbegin+ln/2; long rightbegin=n/2+n/4-rn/4; long rightend=rightbegin+rn/2; int i,p; for(i=0;i #include #include #include "ogg.h" #include "ivorbiscodec.h" #include "codebook.h" #include "misc.h" #include "tremor_shared.h" /* unpacks a codebook from the packet buffer into the codebook struct, readies the codebook auxiliary structures for decode *************/ static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){ long i,j; static_codebook *s=_ogg_calloc(1,sizeof(*s)); /* make sure alignment is correct */ if(oggpack_read(opb,24)!=0x564342)goto _eofout; /* first the basic parameters */ s->dim=oggpack_read(opb,16); s->entries=oggpack_read(opb,24); if(s->entries==-1)goto _eofout; if(ilog(s->dim)+ ilog(s->entries)>24)goto _eofout; /* codeword ordering.... length ordered or unordered? */ switch((int)oggpack_read(opb,1)){ case 0:{ long unused; /* allocated but unused entries? */ unused=oggpack_read(opb,1); if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb)) goto _eofout; /* unordered */ s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); /* allocated but unused entries? */ if(unused){ /* yes, unused entries */ for(i=0;ientries;i++){ if(oggpack_read(opb,1)){ long num=oggpack_read(opb,5); if(num==-1)goto _eofout; s->lengthlist[i]=num+1; }else s->lengthlist[i]=0; } }else{ /* all entries used; no tagging */ for(i=0;ientries;i++){ long num=oggpack_read(opb,5); if(num==-1)goto _eofout; s->lengthlist[i]=num+1; } } break; } case 1: /* ordered */ { long length=oggpack_read(opb,5)+1; if(length==0)goto _eofout; s->lengthlist=(long *)_ogg_malloc(sizeof(*s->lengthlist)*s->entries); for(i=0;ientries;){ long num=oggpack_read(opb, ilog(s->entries-i)); if(num==-1)goto _eofout; if(length>32 || num>s->entries-i || (num>0 && (num-1)>>(length>>1)>>((length+1)>>1))>0){ goto _errout; } for(j=0;jlengthlist[i]=length; length++; } } break; default: /* EOF */ goto _eofout; } /* Do we have a mapping to unpack? */ switch((s->maptype=oggpack_read(opb,4))){ case 0: /* no mapping */ break; case 1: case 2: /* implicitly populated value mapping */ /* explicitly populated value mapping */ s->q_min=oggpack_read(opb,32); s->q_delta=oggpack_read(opb,32); s->q_quant=oggpack_read(opb,4)+1; s->q_sequencep=oggpack_read(opb,1); if(s->q_sequencep==-1)goto _eofout; { int quantvals=0; switch(s->maptype){ case 1: quantvals=(s->dim==0?0:_book_maptype1_quantvals(s)); break; case 2: quantvals=s->entries*s->dim; break; } /* quantized values */ if((quantvals*s->q_quant+7)>>3>opb->storage-oggpack_bytes(opb)) goto _eofout; s->quantlist=(long *)_ogg_malloc(sizeof(*s->quantlist)*quantvals); for(i=0;iquantlist[i]=oggpack_read(opb,s->q_quant); if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout; } break; default: goto _errout; } /* all set */ return(s); _errout: _eofout: vorbis_staticbook_destroy(s); return(NULL); } STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){ int read=book->dec_maxlength; long lo,hi; long lok = oggpack_look(b,book->dec_firsttablen); if (lok >= 0) { long entry = book->dec_firsttable[lok]; if(entry&0x80000000UL){ lo=(entry>>15)&0x7fff; hi=book->used_entries-(entry&0x7fff); }else{ oggpack_adv(b, book->dec_codelengths[entry-1]); return(entry-1); } }else{ lo=0; hi=book->used_entries; } lok = oggpack_look(b, read); while(lok<0 && read>1) lok = oggpack_look(b, --read); if(lok<0){ oggpack_adv(b,1); /* force eop */ return -1; } /* bisect search for the codeword in the ordered list */ { ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok); while(hi-lo>1){ long p=(hi-lo)>>1; long test=book->codelist[lo+p]>testword; lo+=p&(test-1); hi-=p&(-test); } if(book->dec_codelengths[lo]<=read){ oggpack_adv(b, book->dec_codelengths[lo]); return(lo); } } oggpack_adv(b, read+1); return(-1); } /* Decode side is specced and easier, because we don't need to find matches using different criteria; we simply read and map. There are two things we need to do 'depending': We may need to support interleave. We don't really, but it's convenient to do it here rather than rebuild the vector later. Cascades may be additive or multiplicitive; this is not inherent in the codebook, but set in the code using the codebook. Like interleaving, it's easiest to do it here. addmul==0 -> declarative (set the value) addmul==1 -> additive addmul==2 -> multiplicitive */ /* returns the [original, not compacted] entry number or -1 on eof *********/ long vorbis_book_decode(codebook *book, oggpack_buffer *b){ if(book->used_entries>0){ long packed_entry=decode_packed_entry_number(book,b); if(packed_entry>=0) return(book->dec_index[packed_entry]); } /* if there's no dec_index, the codebook unpacking isn't collapsed */ return(-1); } /* returns 0 on OK or -1 on eof *************************************/ /* decode vector / dim granularity gaurding is done in the upper layer */ long vorbis_book_decodevs_add(codebook *book,ogg_int32_t *a, oggpack_buffer *b,int n,int point){ if(book->used_entries>0){ int step=n/book->dim; long *entry = (long *)alloca(sizeof(*entry)*step); ogg_int32_t **t = (ogg_int32_t **)alloca(sizeof(*t)*step); int i,j,o; int shift=point-book->binarypoint; if(shift>=0){ for (i = 0; i < step; i++) { entry[i]=decode_packed_entry_number(book,b); if(entry[i]==-1)return(-1); t[i] = book->valuelist+entry[i]*book->dim; } for(i=0,o=0;idim;i++,o+=step) for (j=0;j>shift; }else{ for (i = 0; i < step; i++) { entry[i]=decode_packed_entry_number(book,b); if(entry[i]==-1)return(-1); t[i] = book->valuelist+entry[i]*book->dim; } for(i=0,o=0;idim;i++,o+=step) for (j=0;jused_entries>0){ int i,j,entry; ogg_int32_t *t; int shift=point-book->binarypoint; if(shift>=0){ for(i=0;ivaluelist+entry*book->dim; for (j=0;jdim;) a[i++]+=t[j++]>>shift; } }else{ for(i=0;ivaluelist+entry*book->dim; for (j=0;jdim;) a[i++]+=t[j++]<<-shift; } } } return(0); } /* unlike the others, we guard against n not being an integer number of internally rather than in the upper layer (called only by floor0) */ long vorbis_book_decodev_set(codebook *book,ogg_int32_t *a, oggpack_buffer *b,int n,int point){ if(book->used_entries>0){ int i,j,entry; ogg_int32_t *t; int shift=point-book->binarypoint; if(shift>=0){ for(i=0;ivaluelist+entry*book->dim; for (j=0;idim;){ a[i++]=t[j++]>>shift; } } }else{ for(i=0;ivaluelist+entry*book->dim; for (j=0;idim;){ a[i++]=t[j++]<<-shift; } } } }else{ int i,j; for(i=0;iused_entries>0){ long i,j,entry; int chptr=0; int shift=point-book->binarypoint; if(shift>=0){ for(i=offset;ivaluelist+entry*book->dim; for (j=0;jdim;j++){ a[chptr++][i]+=t[j]>>shift; if(chptr==ch){ chptr=0; i++; } } } } }else{ for(i=offset;ivaluelist+entry*book->dim; for (j=0;jdim;j++){ a[chptr++][i]+=t[j]<<-shift; if(chptr==ch){ chptr=0; i++; } } } } } } return(0); } libretro-common/rthreads/000700 001750 001750 00000000000 12702525066 016617 5ustar00sergiosergio000000 000000 msvc/msvc-2003/000700 001750 001750 00000000000 12702525066 014175 5ustar00sergiosergio000000 000000 msvc/msvc-2003/msvc-2003.vcproj000664 001750 001750 00000035317 12611054044 016771 0ustar00sergiosergio000000 000000 msvc/msvc-2003.sln000664 001750 001750 00000001600 12611054044 014714 0ustar00sergiosergio000000 000000 Microsoft Visual Studio Solution File, Format Version 8.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msvc-2003", "msvc-2003/msvc-2003.vcproj", "{A9C675CC-DDF4-4BC5-A212-25AE2465D253}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug Release = Release EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {A9C675CC-DDF4-4BC5-A212-25AE2465D253}.Debug.ActiveCfg = Debug|Win32 {A9C675CC-DDF4-4BC5-A212-25AE2465D253}.Debug.Build.0 = Debug|Win32 {A9C675CC-DDF4-4BC5-A212-25AE2465D253}.Release.ActiveCfg = Release|Win32 {A9C675CC-DDF4-4BC5-A212-25AE2465D253}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection EndGlobal msvc/msvc-2003/stdint.h000664 001750 001750 00000017100 12611054044 015656 0ustar00sergiosergio000000 000000 // ISO C9x compliant stdint.h for Microsoft Visual Studio // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 // // Copyright (c) 2006-2008 Alexander Chemeris // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. The name of the author may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////////// #ifndef __RARCH_STDINT_H #define __RARCH_STDINT_H #if _MSC_VER && (_MSC_VER < 1600) //pre-MSVC 2010 needs an implementation of stdint.h #if _MSC_VER > 1000 #pragma once #endif #include // For Visual Studio 6 in C++ mode and for many Visual Studio versions when // compiling for ARM we should wrap include with 'extern "C++" {}' // or compiler give many errors like this: // error C2733: second C linkage of overloaded function 'wmemchr' not allowed #ifdef __cplusplus extern "C" { #endif # include #ifdef __cplusplus } #endif // Define _W64 macros to mark types changing their size, like intptr_t. #ifndef _W64 # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 # define _W64 __w64 # else # define _W64 # endif #endif // 7.18.1 Integer types // 7.18.1.1 Exact-width integer types // Visual Studio 6 and Embedded Visual C++ 4 doesn't // realize that, e.g. char has the same size as __int8 // so we give up on __intX for them. #if (_MSC_VER < 1300) typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #else typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; #endif typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; // 7.18.1.2 Minimum-width integer types typedef int8_t int_least8_t; typedef int16_t int_least16_t; typedef int32_t int_least32_t; typedef int64_t int_least64_t; typedef uint8_t uint_least8_t; typedef uint16_t uint_least16_t; typedef uint32_t uint_least32_t; typedef uint64_t uint_least64_t; // 7.18.1.3 Fastest minimum-width integer types typedef int8_t int_fast8_t; typedef int16_t int_fast16_t; typedef int32_t int_fast32_t; typedef int64_t int_fast64_t; typedef uint8_t uint_fast8_t; typedef uint16_t uint_fast16_t; typedef uint32_t uint_fast32_t; typedef uint64_t uint_fast64_t; // 7.18.1.4 Integer types capable of holding object pointers #ifdef _WIN64 // [ typedef signed __int64 intptr_t; typedef unsigned __int64 uintptr_t; #else // _WIN64 ][ typedef _W64 signed int intptr_t; typedef _W64 unsigned int uintptr_t; #endif // _WIN64 ] // 7.18.1.5 Greatest-width integer types typedef int64_t intmax_t; typedef uint64_t uintmax_t; // 7.18.2 Limits of specified-width integer types #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 // 7.18.2.1 Limits of exact-width integer types #define INT8_MIN ((int8_t)_I8_MIN) #define INT8_MAX _I8_MAX #define INT16_MIN ((int16_t)_I16_MIN) #define INT16_MAX _I16_MAX #define INT32_MIN ((int32_t)_I32_MIN) #define INT32_MAX _I32_MAX #define INT64_MIN ((int64_t)_I64_MIN) #define INT64_MAX _I64_MAX #define UINT8_MAX _UI8_MAX #define UINT16_MAX _UI16_MAX #define UINT32_MAX _UI32_MAX #define UINT64_MAX _UI64_MAX // 7.18.2.2 Limits of minimum-width integer types #define INT_LEAST8_MIN INT8_MIN #define INT_LEAST8_MAX INT8_MAX #define INT_LEAST16_MIN INT16_MIN #define INT_LEAST16_MAX INT16_MAX #define INT_LEAST32_MIN INT32_MIN #define INT_LEAST32_MAX INT32_MAX #define INT_LEAST64_MIN INT64_MIN #define INT_LEAST64_MAX INT64_MAX #define UINT_LEAST8_MAX UINT8_MAX #define UINT_LEAST16_MAX UINT16_MAX #define UINT_LEAST32_MAX UINT32_MAX #define UINT_LEAST64_MAX UINT64_MAX // 7.18.2.3 Limits of fastest minimum-width integer types #define INT_FAST8_MIN INT8_MIN #define INT_FAST8_MAX INT8_MAX #define INT_FAST16_MIN INT16_MIN #define INT_FAST16_MAX INT16_MAX #define INT_FAST32_MIN INT32_MIN #define INT_FAST32_MAX INT32_MAX #define INT_FAST64_MIN INT64_MIN #define INT_FAST64_MAX INT64_MAX #define UINT_FAST8_MAX UINT8_MAX #define UINT_FAST16_MAX UINT16_MAX #define UINT_FAST32_MAX UINT32_MAX #define UINT_FAST64_MAX UINT64_MAX // 7.18.2.4 Limits of integer types capable of holding object pointers #ifdef _WIN64 // [ # define INTPTR_MIN INT64_MIN # define INTPTR_MAX INT64_MAX # define UINTPTR_MAX UINT64_MAX #else // _WIN64 ][ # define INTPTR_MIN INT32_MIN # define INTPTR_MAX INT32_MAX # define UINTPTR_MAX UINT32_MAX #endif // _WIN64 ] // 7.18.2.5 Limits of greatest-width integer types #define INTMAX_MIN INT64_MIN #define INTMAX_MAX INT64_MAX #define UINTMAX_MAX UINT64_MAX // 7.18.3 Limits of other integer types #ifdef _WIN64 // [ # define PTRDIFF_MIN _I64_MIN # define PTRDIFF_MAX _I64_MAX #else // _WIN64 ][ # define PTRDIFF_MIN _I32_MIN # define PTRDIFF_MAX _I32_MAX #endif // _WIN64 ] #define SIG_ATOMIC_MIN INT_MIN #define SIG_ATOMIC_MAX INT_MAX #ifndef SIZE_MAX // [ # ifdef _WIN64 // [ # define SIZE_MAX _UI64_MAX # else // _WIN64 ][ # define SIZE_MAX _UI32_MAX # endif // _WIN64 ] #endif // SIZE_MAX ] // WCHAR_MIN and WCHAR_MAX are also defined in #ifndef WCHAR_MIN // [ # define WCHAR_MIN 0 #endif // WCHAR_MIN ] #ifndef WCHAR_MAX // [ # define WCHAR_MAX _UI16_MAX #endif // WCHAR_MAX ] #define WINT_MIN 0 #define WINT_MAX _UI16_MAX #endif // __STDC_LIMIT_MACROS ] // 7.18.4 Limits of other integer types #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 // 7.18.4.1 Macros for minimum-width integer constants #define INT8_C(val) val##i8 #define INT16_C(val) val##i16 #define INT32_C(val) val##i32 #define INT64_C(val) val##i64 #define UINT8_C(val) val##ui8 #define UINT16_C(val) val##ui16 #define UINT32_C(val) val##ui32 #define UINT64_C(val) val##ui64 // 7.18.4.2 Macros for greatest-width integer constants #define INTMAX_C INT64_C #define UINTMAX_C UINT64_C #endif // __STDC_CONSTANT_MACROS ] #else //sanity for everything else #include #endif #endif mednafen/psx/input/multitap.cpp000664 001750 001750 00000025211 12611054044 017771 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include "../psx.h" #include "../frontio.h" #include "multitap.h" /* TODO: PS1 multitap appears to have some internal knowledge of controller IDs, so it won't get "stuck" waiting for data from a controller that'll never come. We currently sort of "cheat" due to how the dsr_pulse_delay stuff works, but in the future we should try to emulate this multitap functionality. Also, full-mode read startup and subport controller ID read timing isn't quite right, so we should fix that too. */ /* Notes from tests on real thing(not necessarily emulated the same way here): Manual port selection read mode: Write 0x01-0x04 instead of 0x01 as first byte, selects port(1=A,2=B,3=C,4=D) to access. Ports that don't exist(0x00, 0x05-0xFF) or don't have a device plugged in will not respond(no DSR pulse). Full read mode: Bit0 of third byte(from-zero-index=0x02) should be set to 1 to enter full read mode, on subsequent reads. Appears to require a controller to be plugged into the port specified by the first byte as per manual port selection read mode, to write the byte necessary to enter full-read mode; but once the third byte with the bit set has been written, no controller in that port is required for doing full reads(and the manual port selection is ignored when doing a full read). However, if there are no controllers plugged in, the returned data will be short: % 0: 0xff % 1: 0x80 % 2: 0x5a Example full-read bytestream(with controllers plugged into port A, port B, and port C, with port D empty): % 0: 0xff % 1: 0x80 % 2: 0x5a % 3: 0x73 (Port A controller data start) % 4: 0x5a % 5: 0xff % 6: 0xff % 7: 0x80 % 8: 0x8c % 9: 0x79 % 10: 0x8f % 11: 0x53 (Port B controller data start) % 12: 0x5a % 13: 0xff % 14: 0xff % 15: 0x80 % 16: 0x80 % 17: 0x75 % 18: 0x8e % 19: 0x41 (Port C controller data start) % 20: 0x5a % 21: 0xff % 22: 0xff % 23: 0xff % 24: 0xff % 25: 0xff % 26: 0xff % 27: 0xff (Port D controller data start) % 28: 0xff % 29: 0xff % 30: 0xff % 31: 0xff % 32: 0xff % 33: 0xff % 34: 0xff */ InputDevice_Multitap::InputDevice_Multitap() { for(int i = 0; i < 4; i++) { pad_devices[i] = NULL; mc_devices[i] = NULL; } Power(); } InputDevice_Multitap::~InputDevice_Multitap() { } void InputDevice_Multitap::SetSubDevice(unsigned int sub_index, InputDevice *device, InputDevice *mc_device) { assert(sub_index < 4); //printf("%d\n", sub_index); pad_devices[sub_index] = device; mc_devices[sub_index] = mc_device; } void InputDevice_Multitap::Power(void) { selected_device = -1; bit_counter = 0; receive_buffer = 0; byte_counter = 0; mc_mode = false; full_mode = false; full_mode_setting = false; prev_fm_success = false; memset(sb, 0, sizeof(sb)); fm_dp = 0; memset(fm_buffer, 0, sizeof(fm_buffer)); fm_command_error = false; for(int i = 0; i < 4; i++) { if(pad_devices[i]) pad_devices[i]->Power(); if(mc_devices[i]) mc_devices[i]->Power(); } } int InputDevice_Multitap::StateAction(StateMem* sm, int load, int data_only, const char* section_name) { SFORMAT StateRegs[] = { SFVAR(dtr), SFVAR(selected_device), SFVAR(full_mode_setting), SFVAR(full_mode), SFVAR(mc_mode), SFVAR(prev_fm_success), SFVAR(fm_dp), SFARRAY(&fm_buffer[0][0], sizeof(fm_buffer) / sizeof(fm_buffer[0][0])), SFARRAY(&sb[0][0], sizeof(sb) / sizeof(sb[0][0])), SFVAR(fm_command_error), SFVAR(command), SFVAR(receive_buffer), SFVAR(bit_counter), SFVAR(byte_counter), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name); if(load) { } return(ret); } void InputDevice_Multitap::SetDTR(bool new_dtr) { bool old_dtr = dtr; dtr = new_dtr; if(!dtr) { if(old_dtr) { //printf("Multitap stop.\n"); } bit_counter = 0; receive_buffer = 0; selected_device = -1; mc_mode = false; full_mode = false; } if(!old_dtr && dtr) { full_mode = full_mode_setting; if(!prev_fm_success) { unsigned i; memset(sb, 0, sizeof(sb)); for(i = 0; i < 4; i++) sb[i][0] = 0x42; } prev_fm_success = false; byte_counter = 0; //if(full_mode) // printf("Multitap start: %d\n", full_mode); } for(int i = 0; i < 4; i++) { pad_devices[i]->SetDTR(dtr); mc_devices[i]->SetDTR(dtr); } } bool InputDevice_Multitap::GetDSR(void) { return(0); } bool InputDevice_Multitap::Clock(bool TxD, int32 &dsr_pulse_delay) { if(!dtr) return(1); bool ret = 1; int32 tmp_pulse_delay[2][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; //printf("Receive bit: %d\n", TxD); //printf("TxD %d\n", TxD); receive_buffer &= ~ (1 << bit_counter); receive_buffer |= TxD << bit_counter; if(1) { if(byte_counter == 0) { bool mangled_txd = TxD; if(bit_counter < 4) mangled_txd = (0x01 >> bit_counter) & 1; for(unsigned i = 0; i < 4; i++) { pad_devices[i]->Clock(mangled_txd, tmp_pulse_delay[0][i]); mc_devices[i]->Clock(mangled_txd, tmp_pulse_delay[1][i]); } } else { if(full_mode) { if(byte_counter == 1) ret = (0x80 >> bit_counter) & 1; else if(byte_counter == 2) ret = (0x5A >> bit_counter) & 1; else if(byte_counter >= 0x03 && byte_counter < 0x03 + 0x08 * 4) { if(!fm_command_error && byte_counter < (0x03 + 0x08)) { unsigned i; for(i = 0; i < 4; i++) { fm_buffer[i][byte_counter - 0x03] &= (pad_devices[i]->Clock((sb[i][byte_counter - 0x03] >> bit_counter) & 1, tmp_pulse_delay[0][i]) << bit_counter) | (~(1U << bit_counter)); } } ret &= ((&fm_buffer[0][0])[byte_counter - 0x03] >> bit_counter) & 1; } } else // to if(full_mode) { if((unsigned)selected_device < 4) { ret &= pad_devices[selected_device]->Clock(TxD, tmp_pulse_delay[0][selected_device]); ret &= mc_devices[selected_device]->Clock(TxD, tmp_pulse_delay[1][selected_device]); } } } // end else to if(byte_counter == 0) } // // // bit_counter = (bit_counter + 1) & 0x7; if(bit_counter == 0) { //printf("MT Receive: 0x%02x\n", receive_buffer); if(byte_counter == 0) { mc_mode = (bool)(receive_buffer & 0xF0); if(mc_mode) full_mode = false; //printf("Zoomba: 0x%02x\n", receive_buffer); //printf("Full mode: %d %d %d\n", full_mode, bit_counter, byte_counter); if(full_mode) { memset(fm_buffer, 0xFF, sizeof(fm_buffer)); selected_device = 0; } else { //printf("Device select: %02x\n", receive_buffer); selected_device = ((receive_buffer & 0xF) - 1) & 0xFF; } } if(byte_counter == 1) { command = receive_buffer; fm_command_error = false; //printf("Multitap sub-command: %02x\n", command); if(full_mode && command != 0x42) fm_command_error = true; } if((!mc_mode || full_mode) && byte_counter == 2) { //printf("Full mode setting: %02x\n", receive_buffer); full_mode_setting = receive_buffer & 0x01; } if(full_mode) { if(byte_counter >= 3 + 8 * 0 && byte_counter < (3 + 8 * 4)) { const unsigned adjbi = byte_counter - 3; sb[adjbi >> 3][adjbi & 0x7] = receive_buffer; } if(byte_counter == 33) prev_fm_success = true; } // Handle DSR stuff if(full_mode) { if(byte_counter == 0) // Next byte: 0x80 { dsr_pulse_delay = 1000; fm_dp = 0; for(unsigned i = 0; i < 4; i++) fm_dp |= (((bool)(tmp_pulse_delay[0][i])) << i); } else if(byte_counter == 1) // Next byte: 0x5A dsr_pulse_delay = 0x40; else if(byte_counter == 2) // Next byte(typically, controller-dependent): 0x41 { if(fm_dp) dsr_pulse_delay = 0x40; else { byte_counter = 255; dsr_pulse_delay = 0; } } else if(byte_counter >= 3 && byte_counter < 34) // Next byte when byte_counter==3 (typically, controller-dependent): 0x5A { if(byte_counter < 10) { unsigned i; int d = 0x40; for(i = 0; i < 4; i++) { int32 tpd = tmp_pulse_delay[0][i]; if(byte_counter == 3 && (fm_dp & (1U << i)) && tpd == 0) { //printf("SNORG: %u %02x\n", i, sb[i][0]); fm_command_error = true; } if(tpd > d) d = tpd; } dsr_pulse_delay = d; } else dsr_pulse_delay = 0x20; if(byte_counter == 3 && fm_command_error) { byte_counter = 255; dsr_pulse_delay = 0; } } } // end if(full_mode) else { if((unsigned)selected_device < 4) { dsr_pulse_delay = std::max(tmp_pulse_delay[0][selected_device], tmp_pulse_delay[1][selected_device]); } } // // // //printf("Byte Counter Increment\n"); if(byte_counter < 255) byte_counter++; } return(ret); } mednafen/tremor/asm_arm.h000664 001750 001750 00000014606 12611054044 016563 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: arm7 and later wide math functions ********************************************************************/ #ifdef _ARM_ASSEM_ #if !defined(_V_WIDE_MATH) && !defined(_LOW_ACCURACY_) #define _V_WIDE_MATH static inline ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) { int lo,hi; asm volatile("smull\t%0, %1, %2, %3" : "=&r"(lo),"=&r"(hi) : "%r"(x),"r"(y) : "cc"); return(hi); } static inline ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) { return MULT32(x,y)<<1; } static inline ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { int lo,hi; asm volatile("smull %0, %1, %2, %3\n\t" "movs %0, %0, lsr #15\n\t" "adc %1, %0, %1, lsl #17\n\t" : "=&r"(lo),"=&r"(hi) : "%r"(x),"r"(y) : "cc"); return(hi); } #define MB() asm volatile ("" : : : "memory") static inline void XPROD32(ogg_int32_t a, ogg_int32_t b, ogg_int32_t t, ogg_int32_t v, ogg_int32_t *x, ogg_int32_t *y) { int x1, y1, l; asm( "smull %0, %1, %4, %6\n\t" "smlal %0, %1, %5, %7\n\t" "rsb %3, %4, #0\n\t" "smull %0, %2, %5, %6\n\t" "smlal %0, %2, %3, %7" : "=&r" (l), "=&r" (x1), "=&r" (y1), "=r" (a) : "3" (a), "r" (b), "r" (t), "r" (v) : "cc" ); *x = x1; MB(); *y = y1; } static inline void XPROD31(ogg_int32_t a, ogg_int32_t b, ogg_int32_t t, ogg_int32_t v, ogg_int32_t *x, ogg_int32_t *y) { int x1, y1, l; asm( "smull %0, %1, %4, %6\n\t" "smlal %0, %1, %5, %7\n\t" "rsb %3, %4, #0\n\t" "smull %0, %2, %5, %6\n\t" "smlal %0, %2, %3, %7" : "=&r" (l), "=&r" (x1), "=&r" (y1), "=r" (a) : "3" (a), "r" (b), "r" (t), "r" (v) : "cc" ); *x = x1 << 1; MB(); *y = y1 << 1; } static inline void XNPROD31(ogg_int32_t a, ogg_int32_t b, ogg_int32_t t, ogg_int32_t v, ogg_int32_t *x, ogg_int32_t *y) { int x1, y1, l; asm( "rsb %2, %4, #0\n\t" "smull %0, %1, %3, %5\n\t" "smlal %0, %1, %2, %6\n\t" "smull %0, %2, %4, %5\n\t" "smlal %0, %2, %3, %6" : "=&r" (l), "=&r" (x1), "=&r" (y1) : "r" (a), "r" (b), "r" (t), "r" (v) : "cc" ); *x = x1 << 1; MB(); *y = y1 << 1; } #endif #ifndef _V_CLIP_MATH #define _V_CLIP_MATH static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) { int tmp; asm volatile("subs %1, %0, #32768\n\t" "movpl %0, #0x7f00\n\t" "orrpl %0, %0, #0xff\n" "adds %1, %0, #32768\n\t" "movmi %0, #0x8000" : "+r"(x),"=r"(tmp) : : "cc"); return(x); } #endif #ifndef _V_LSP_MATH_ASM #define _V_LSP_MATH_ASM static inline void lsp_loop_asm(ogg_uint32_t *qip,ogg_uint32_t *pip, ogg_int32_t *qexpp, ogg_int32_t *ilsp,ogg_int32_t wi, ogg_int32_t m){ ogg_uint32_t qi=*qip,pi=*pip; ogg_int32_t qexp=*qexpp; asm("mov r0,%3;" "movs r1,%5,asr#1;" "add r0,r0,r1,lsl#3;" "beq 2f;\n" "1:" "ldmdb r0!,{r1,r3};" "subs r1,r1,%4;" //ilsp[j]-wi "rsbmi r1,r1,#0;" //labs(ilsp[j]-wi) "umull %0,r2,r1,%0;" //qi*=labs(ilsp[j]-wi) "subs r1,r3,%4;" //ilsp[j+1]-wi "rsbmi r1,r1,#0;" //labs(ilsp[j+1]-wi) "umull %1,r3,r1,%1;" //pi*=labs(ilsp[j+1]-wi) "cmn r2,r3;" // shift down 16? "beq 0f;" "add %2,%2,#16;" "mov %0,%0,lsr #16;" "orr %0,%0,r2,lsl #16;" "mov %1,%1,lsr #16;" "orr %1,%1,r3,lsl #16;" "0:" "cmp r0,%3;\n" "bhi 1b;\n" "2:" // odd filter assymetry "ands r0,%5,#1;\n" "beq 3f;\n" "add r0,%3,%5,lsl#2;\n" "ldr r1,[r0,#-4];\n" "mov r0,#0x4000;\n" "subs r1,r1,%4;\n" //ilsp[j]-wi "rsbmi r1,r1,#0;\n" //labs(ilsp[j]-wi) "umull %0,r2,r1,%0;\n" //qi*=labs(ilsp[j]-wi) "umull %1,r3,r0,%1;\n" //pi*=labs(ilsp[j+1]-wi) "cmn r2,r3;\n" // shift down 16? "beq 3f;\n" "add %2,%2,#16;\n" "mov %0,%0,lsr #16;\n" "orr %0,%0,r2,lsl #16;\n" "mov %1,%1,lsr #16;\n" "orr %1,%1,r3,lsl #16;\n" //qi=(pi>>shift)*labs(ilsp[j]-wi); //pi=(qi>>shift)*labs(ilsp[j+1]-wi); //qexp+=shift; //} /* normalize to max 16 sig figs */ "3:" "mov r2,#0;" "orr r1,%0,%1;" "tst r1,#0xff000000;" "addne r2,r2,#8;" "movne r1,r1,lsr #8;" "tst r1,#0x00f00000;" "addne r2,r2,#4;" "movne r1,r1,lsr #4;" "tst r1,#0x000c0000;" "addne r2,r2,#2;" "movne r1,r1,lsr #2;" "tst r1,#0x00020000;" "addne r2,r2,#1;" "movne r1,r1,lsr #1;" "tst r1,#0x00010000;" "addne r2,r2,#1;" "mov %0,%0,lsr r2;" "mov %1,%1,lsr r2;" "add %2,%2,r2;" : "+r"(qi),"+r"(pi),"+r"(qexp) : "r"(ilsp),"r"(wi),"r"(m) : "r0","r1","r2","r3","cc"); *qip=qi; *pip=pi; *qexpp=qexp; } static inline void lsp_norm_asm(ogg_uint32_t *qip,ogg_int32_t *qexpp){ ogg_uint32_t qi=*qip; ogg_int32_t qexp=*qexpp; asm("tst %0,#0x0000ff00;" "moveq %0,%0,lsl #8;" "subeq %1,%1,#8;" "tst %0,#0x0000f000;" "moveq %0,%0,lsl #4;" "subeq %1,%1,#4;" "tst %0,#0x0000c000;" "moveq %0,%0,lsl #2;" "subeq %1,%1,#2;" "tst %0,#0x00008000;" "moveq %0,%0,lsl #1;" "subeq %1,%1,#1;" : "+r"(qi),"+r"(qexp) : : "cc"); *qip=qi; *qexpp=qexp; } #endif #endif mednafen/video/surface.h000664 001750 001750 00000005023 12611054044 016363 0ustar00sergiosergio000000 000000 #ifndef __MDFN_SURFACE_H #define __MDFN_SURFACE_H #define RED_SHIFT 16 #define GREEN_SHIFT 8 #define BLUE_SHIFT 0 #define ALPHA_SHIFT 24 #define MAKECOLOR(r, g, b, a) ((r << RED_SHIFT) | (g << GREEN_SHIFT) | (b << BLUE_SHIFT) | (a << ALPHA_SHIFT)) struct MDFN_PaletteEntry { uint8 r, g, b; }; typedef struct { int32 x, y, w, h; } MDFN_Rect; enum { MDFN_COLORSPACE_RGB = 0, MDFN_COLORSPACE_YCbCr = 1, MDFN_COLORSPACE_YUV = 2, // TODO, maybe. }; class MDFN_PixelFormat { public: MDFN_PixelFormat(); MDFN_PixelFormat(const unsigned int p_colorspace, const uint8 p_rs, const uint8 p_gs, const uint8 p_bs, const uint8 p_as); unsigned int bpp; unsigned int colorspace; union { uint8 Rshift; // Bit position of the lowest bit of the red component uint8 Yshift; }; union { uint8 Gshift; // [...] green component uint8 Ushift; uint8 Cbshift; }; union { uint8 Bshift; // [...] blue component uint8 Vshift; uint8 Crshift; }; uint8 Ashift; // [...] alpha component. // Gets the R/G/B/A values for the passed 32-bit surface pixel value INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const { r = (value >> RED_SHIFT) & 0xFF; g = (value >> GREEN_SHIFT) & 0xFF; b = (value >> BLUE_SHIFT) & 0xFF; a = (value >> ALPHA_SHIFT) & 0xFF; } }; // MDFN_PixelFormat; // Supports 32-bit RGBA // 16-bit is WIP class MDFN_Surface //typedef struct { public: MDFN_Surface(); MDFN_Surface(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf); ~MDFN_Surface(); uint32 *pixels; // w, h, and pitch32 should always be > 0 int32 w; int32 h; union { int32 pitch32; // In pixels, not in bytes. int32 pitchinpix; // New name, new code should use this. }; MDFN_PaletteEntry *palette; MDFN_PixelFormat format; void SetFormat(const MDFN_PixelFormat &new_format, bool convert); // Gets the R/G/B/A values for the passed 32-bit surface pixel value INLINE void DecodeColor(uint32 value, int &r, int &g, int &b, int &a) const { r = (value >> RED_SHIFT) & 0xFF; g = (value >> GREEN_SHIFT) & 0xFF; b = (value >> BLUE_SHIFT) & 0xFF; a = (value >> ALPHA_SHIFT) & 0xFF; } INLINE void DecodeColor(uint32 value, int &r, int &g, int &b) const { r = (value >> RED_SHIFT) & 0xFF; g = (value >> GREEN_SHIFT) & 0xFF; b = (value >> BLUE_SHIFT) & 0xFF; } private: void Init(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf); }; #endif mednafen/psx/gte.h000664 001750 001750 00000000612 12611054044 015215 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_GTE_H #define __MDFN_PSX_GTE_H void GTE_Init(void); void GTE_Power(void); int GTE_StateAction(StateMem *sm, int load, int data_only); int32 GTE_Instruction(uint32_t instr); void GTE_WriteCR(unsigned int which, uint32_t value); void GTE_WriteDR(unsigned int which, uint32_t value); uint32_t GTE_ReadCR(unsigned int which); uint32_t GTE_ReadDR(unsigned int which); #endif mednafen/psx/notes/000700 001750 001750 00000000000 12702525066 015412 5ustar00sergiosergio000000 000000 libretro-common/rthreads/xenon_sdl_threads.c000664 001750 001750 00000004064 12611054044 022476 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (xenon_sdl_threads.c). * --------------------------------------------------------------------------------------- * * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // libSDLxenon doesn't implement this yet :[. Implement it very stupidly for now. ;) #include "SDL_thread.h" #include "SDL_mutex.h" #include #include SDL_cond *SDL_CreateCond(void) { bool *sleeping = calloc(1, sizeof(*sleeping)); return (SDL_cond*)sleeping; } void SDL_DestroyCond(SDL_cond *sleeping) { free(sleeping); } int SDL_CondWait(SDL_cond *cond, SDL_mutex *lock) { (void)lock; volatile bool *sleeping = (volatile bool*)cond; SDL_mutexV(lock); *sleeping = true; while (*sleeping); /* Yeah, we all love busyloops don't we? ._. */ SDL_mutexP(lock); return 0; } int SDL_CondSignal(SDL_cond *cond) { *(volatile bool*)cond = false; return 0; } mednafen/tremor/ogg.h000664 001750 001750 00000020355 12611054044 015716 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** function: toplevel libogg include last mod: $Id: ogg.h 18044 2011-08-01 17:55:20Z gmaxwell $ ********************************************************************/ #ifndef _OGG_H #define _OGG_H #ifdef __cplusplus extern "C" { #endif #include #include "os_types.h" typedef struct { void *iov_base; size_t iov_len; } ogg_iovec_t; typedef struct { long endbyte; int endbit; unsigned char *buffer; unsigned char *ptr; long storage; } oggpack_buffer; /* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/ typedef struct { unsigned char *header; long header_len; unsigned char *body; long body_len; } ogg_page; /* ogg_stream_state contains the current encode/decode state of a logical Ogg bitstream **********************************************************/ typedef struct { unsigned char *body_data; /* bytes from packet bodies */ long body_storage; /* storage elements allocated */ long body_fill; /* elements stored; fill mark */ long body_returned; /* elements of fill returned */ int *lacing_vals; /* The values that will go to the segment table */ ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact this way, but it is simple coupled to the lacing fifo */ long lacing_storage; long lacing_fill; long lacing_packet; long lacing_returned; unsigned char header[282]; /* working space for header encode */ int header_fill; int e_o_s; /* set when we have buffered the last packet in the logical bitstream */ int b_o_s; /* set after we've written the initial page of a logical bitstream */ long serialno; long pageno; ogg_int64_t packetno; /* sequence number for decode; the framing knows where there's a hole in the data, but we need coupling so that the codec (which is in a separate abstraction layer) also knows about the gap */ ogg_int64_t granulepos; } ogg_stream_state; /* ogg_packet is used to encapsulate the data and metadata belonging to a single raw Ogg/Vorbis packet *************************************/ typedef struct { unsigned char *packet; long bytes; long b_o_s; long e_o_s; ogg_int64_t granulepos; ogg_int64_t packetno; /* sequence number for decode; the framing knows where there's a hole in the data, but we need coupling so that the codec (which is in a separate abstraction layer) also knows about the gap */ } ogg_packet; typedef struct { unsigned char *data; int storage; int fill; int returned; int unsynced; int headerbytes; int bodybytes; } ogg_sync_state; /* Ogg BITSTREAM PRIMITIVES: bitstream ************************/ extern void oggpack_writeinit(oggpack_buffer *b); extern int oggpack_writecheck(oggpack_buffer *b); extern void oggpack_writetrunc(oggpack_buffer *b,long bits); extern void oggpack_writealign(oggpack_buffer *b); extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits); extern void oggpack_reset(oggpack_buffer *b); extern void oggpack_writeclear(oggpack_buffer *b); extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits); extern long oggpack_look(oggpack_buffer *b,int bits); extern long oggpack_look1(oggpack_buffer *b); extern void oggpack_adv(oggpack_buffer *b,int bits); extern void oggpack_adv1(oggpack_buffer *b); extern long oggpack_read(oggpack_buffer *b,int bits); extern long oggpack_read1(oggpack_buffer *b); extern long oggpack_bytes(oggpack_buffer *b); extern long oggpack_bits(oggpack_buffer *b); extern unsigned char *oggpack_get_buffer(oggpack_buffer *b); extern void oggpackB_writeinit(oggpack_buffer *b); extern int oggpackB_writecheck(oggpack_buffer *b); extern void oggpackB_writetrunc(oggpack_buffer *b,long bits); extern void oggpackB_writealign(oggpack_buffer *b); extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits); extern void oggpackB_reset(oggpack_buffer *b); extern void oggpackB_writeclear(oggpack_buffer *b); extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes); extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits); extern long oggpackB_look(oggpack_buffer *b,int bits); extern long oggpackB_look1(oggpack_buffer *b); extern void oggpackB_adv(oggpack_buffer *b,int bits); extern void oggpackB_adv1(oggpack_buffer *b); extern long oggpackB_read(oggpack_buffer *b,int bits); extern long oggpackB_read1(oggpack_buffer *b); extern long oggpackB_bytes(oggpack_buffer *b); extern long oggpackB_bits(oggpack_buffer *b); extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b); /* Ogg BITSTREAM PRIMITIVES: encoding **************************/ extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op); extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov, int count, long e_o_s, ogg_int64_t granulepos); extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og); extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill); extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og); extern int ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill); /* Ogg BITSTREAM PRIMITIVES: decoding **************************/ extern int ogg_sync_init(ogg_sync_state *oy); extern int ogg_sync_clear(ogg_sync_state *oy); extern int ogg_sync_reset(ogg_sync_state *oy); extern int ogg_sync_destroy(ogg_sync_state *oy); extern int ogg_sync_check(ogg_sync_state *oy); extern char *ogg_sync_buffer(ogg_sync_state *oy, long size); extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes); extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og); extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og); extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og); extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op); extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op); /* Ogg BITSTREAM PRIMITIVES: general ***************************/ extern int ogg_stream_init(ogg_stream_state *os,int serialno); extern int ogg_stream_clear(ogg_stream_state *os); extern int ogg_stream_reset(ogg_stream_state *os); extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno); extern int ogg_stream_destroy(ogg_stream_state *os); extern int ogg_stream_check(ogg_stream_state *os); extern int ogg_stream_eos(ogg_stream_state *os); extern void ogg_page_checksum_set(ogg_page *og); extern int ogg_page_version(const ogg_page *og); extern int ogg_page_continued(const ogg_page *og); extern int ogg_page_bos(const ogg_page *og); extern int ogg_page_eos(const ogg_page *og); extern ogg_int64_t ogg_page_granulepos(const ogg_page *og); extern int ogg_page_serialno(const ogg_page *og); extern long ogg_page_pageno(const ogg_page *og); extern int ogg_page_packets(const ogg_page *og); extern void ogg_packet_clear(ogg_packet *op); #ifdef __cplusplus } #endif #endif /* _OGG_H */ mednafen/tremor/res012.c000664 001750 001750 00000023705 12611054044 016153 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: residue backend 0, 1 and 2 implementation ********************************************************************/ #include #include #include #include "ogg.h" #include "ivorbiscodec.h" #include "codec_internal.h" #include "registry.h" #include "codebook.h" #include "misc.h" #include "os.h" #include "block.h" #include "tremor_shared.h" typedef struct { vorbis_info_residue0 *info; int map; int parts; int stages; codebook *fullbooks; codebook *phrasebook; codebook ***partbooks; int partvals; int **decodemap; } vorbis_look_residue0; void res0_free_info(vorbis_info_residue *i){ vorbis_info_residue0 *info=(vorbis_info_residue0 *)i; if(info){ memset(info,0,sizeof(*info)); _ogg_free(info); } } void res0_free_look(vorbis_look_residue *i){ int j; if(i){ vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; for(j=0;jparts;j++) if(look->partbooks[j])_ogg_free(look->partbooks[j]); _ogg_free(look->partbooks); for(j=0;jpartvals;j++) _ogg_free(look->decodemap[j]); _ogg_free(look->decodemap); memset(look,0,sizeof(*look)); _ogg_free(look); } } static int icount(unsigned int v){ int ret=0; while(v){ ret+=v&1; v>>=1; } return(ret); } /* vorbis_info is for range checking */ vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ int j,acc=0; vorbis_info_residue0 *info=(vorbis_info_residue0 *)_ogg_calloc(1,sizeof(*info)); codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; info->begin=oggpack_read(opb,24); info->end=oggpack_read(opb,24); info->grouping=oggpack_read(opb,24)+1; info->partitions=oggpack_read(opb,6)+1; info->groupbook=oggpack_read(opb,8); /* check for premature EOP */ if(info->groupbook<0)goto errout; for(j=0;jpartitions;j++){ int cascade=oggpack_read(opb,3); int cflag=oggpack_read(opb,1); if(cflag<0) goto errout; if(cflag){ int c=oggpack_read(opb,5); if(c<0) goto errout; cascade|=(c<<3); } info->secondstages[j]=cascade; acc+=icount(cascade); } for(j=0;jbooklist[j]=book; } if(info->groupbook>=ci->books)goto errout; for(j=0;jbooklist[j]>=ci->books)goto errout; if(ci->book_param[info->booklist[j]]->maptype==0)goto errout; } /* verify the phrasebook is not specifying an impossible or inconsistent partitioning scheme. */ /* modify the phrasebook ranging check from r16327; an early beta encoder had a bug where it used an oversized phrasebook by accident. These files should continue to be playable, but don't allow an exploit */ { int entries = ci->book_param[info->groupbook]->entries; int dim = ci->book_param[info->groupbook]->dim; int partvals = 1; if (dim<1) goto errout; while(dim>0){ partvals *= info->partitions; if(partvals > entries) goto errout; dim--; } info->partvals = partvals; } return(info); errout: res0_free_info(info); return(NULL); } vorbis_look_residue *res0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm, vorbis_info_residue *vr){ vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; vorbis_look_residue0 *look=(vorbis_look_residue0 *)_ogg_calloc(1,sizeof(*look)); codec_setup_info *ci=(codec_setup_info *)vd->vi->codec_setup; int j,k,acc=0; int dim; int maxstage=0; look->info=info; look->map=vm->mapping; look->parts=info->partitions; look->fullbooks=ci->fullbooks; look->phrasebook=ci->fullbooks+info->groupbook; dim=look->phrasebook->dim; look->partbooks=(codebook ***)_ogg_calloc(look->parts,sizeof(*look->partbooks)); for(j=0;jparts;j++){ int stages=ilog(info->secondstages[j]); if(stages){ if(stages>maxstage)maxstage=stages; look->partbooks[j]=(codebook **)_ogg_calloc(stages,sizeof(*look->partbooks[j])); for(k=0;ksecondstages[j]&(1<partbooks[j][k]=ci->fullbooks+info->booklist[acc++]; #ifdef TRAIN_RES look->training_data[k][j]=calloc(look->partbooks[j][k]->entries, sizeof(***look->training_data)); #endif } } } look->partvals=look->parts; for(j=1;jpartvals*=look->parts; look->stages=maxstage; look->decodemap=(int **)_ogg_malloc(look->partvals*sizeof(*look->decodemap)); for(j=0;jpartvals;j++){ long val=j; long mult=look->partvals/look->parts; look->decodemap[j]=(int *)_ogg_malloc(dim*sizeof(*look->decodemap[j])); for(k=0;kparts; look->decodemap[j][k]=deco; } } return(look); } /* a truncated packet here just means 'stop working'; it's not an error */ static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl, ogg_int32_t **in,int ch, long (*decodepart)(codebook *, ogg_int32_t *, oggpack_buffer *,int,int)){ long i,j,k,l,s; vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; vorbis_info_residue0 *info=look->info; /* move all this setup out later */ int samples_per_partition=info->grouping; int partitions_per_word=look->phrasebook->dim; int max=vb->pcmend>>1; int end=(info->endend:max); int n=end-info->begin; if(n>0){ int partvals=n/samples_per_partition; int partwords=(partvals+partitions_per_word-1)/partitions_per_word; int ***partword=(int ***)alloca(ch*sizeof(*partword)); for(j=0;jstages;s++){ /* each loop decodes on partition codeword containing partitions_pre_word partitions */ for(i=0,l=0;iphrasebook,&vb->opb); if(temp==-1 || temp>=info->partvals)goto eopbreak; partword[j][l]=look->decodemap[temp]; if(partword[j][l]==NULL)goto errout; } } /* now we decode residual values for the partitions */ for(k=0;kbegin+i*samples_per_partition; if(info->secondstages[partword[j][l][k]]&(1<partbooks[partword[j][l][k]][s]; if(stagebook){ if(decodepart(stagebook,in[j]+offset,&vb->opb, samples_per_partition,-8)==-1)goto eopbreak; } } } } } } errout: eopbreak: return(0); } int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl, ogg_int32_t **in,int *nonzero,int ch){ int i,used=0; for(i=0;iinfo; /* move all this setup out later */ int samples_per_partition=info->grouping; int partitions_per_word=look->phrasebook->dim; int max=(vb->pcmend*ch)>>1; int end=(info->endend:max); int n=end-info->begin; if(n>0){ int partvals=n/samples_per_partition; int partwords=(partvals+partitions_per_word-1)/partitions_per_word; int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword)); int beginoff=info->begin/ch; for(i=0;istages;s++){ for(i=0,l=0;iphrasebook,&vb->opb); if(temp==-1 || temp>=info->partvals)goto eopbreak; partword[l]=look->decodemap[temp]; if(partword[l]==NULL)goto errout; } /* now we decode residual values for the partitions */ for(k=0;ksecondstages[partword[l][k]]&(1<partbooks[partword[l][k]][s]; if(stagebook){ if(vorbis_book_decodevv_add(stagebook,in, i*samples_per_partition+beginoff,ch, &vb->opb, samples_per_partition,-8)==-1) goto eopbreak; } } } } } errout: eopbreak: return(0); } vorbis_func_residue residue0_exportbundle={ &res0_unpack, &res0_look, &res0_free_info, &res0_free_look, &res0_inverse }; vorbis_func_residue residue1_exportbundle={ &res0_unpack, &res0_look, &res0_free_info, &res0_free_look, &res1_inverse }; vorbis_func_residue residue2_exportbundle={ &res0_unpack, &res0_look, &res0_free_info, &res0_free_look, &res2_inverse }; mednafen/general.cpp000664 001750 001750 00000013137 12611054044 015602 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include "mednafen.h" #include #include #include #include #include "general.h" #include "state.h" #include "md5.h" using namespace std; static bool IsAbsolutePath(const char *path) { if ( #ifdef _WIN32 path[0] == '\\' || #endif path[0] == '/' ) return(TRUE); #if defined(WIN32) || defined(DOS) if((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z')) { if(path[1] == ':') return(TRUE); } #endif return(FALSE); } bool MDFN_IsFIROPSafe(const std::string &path) { // We could make this more OS-specific, but it shouldn't hurt to try to weed out usage of characters that are path // separators in one OS but not in another, and we'd also run more of a risk of missing a special path separator case // in some OS. if(!MDFN_GetSettingB("filesys.untrusted_fip_check")) return(true); if(path.find('\0') != string::npos) return(false); if(path.find(':') != string::npos) return(false); if(path.find('\\') != string::npos) return(false); if(path.find('/') != string::npos) return(false); return(true); } void MDFN_GetFilePathComponents(const std::string &file_path, std::string *dir_path_out, std::string *file_base_out, std::string *file_ext_out) { size_t final_ds; // in file_path string file_name; size_t fn_final_dot; // in local var file_name string dir_path, file_base, file_ext; // Temporary output #ifdef _WIN32 final_ds = file_path.find_last_of('\\'); size_t alt_final_ds = file_path.find_last_of('/'); if(final_ds == string::npos || (alt_final_ds != string::npos && alt_final_ds > final_ds)) final_ds = alt_final_ds; #else final_ds = file_path.find_last_of('/'); #endif if(final_ds == string::npos) { dir_path = string("."); file_name = file_path; } else { dir_path = file_path.substr(0, final_ds); file_name = file_path.substr(final_ds + 1); } fn_final_dot = file_name.find_last_of('.'); if(fn_final_dot != string::npos) { file_base = file_name.substr(0, fn_final_dot); file_ext = file_name.substr(fn_final_dot); } else { file_base = file_name; file_ext = string(""); } if(dir_path_out) *dir_path_out = dir_path; if(file_base_out) *file_base_out = file_base; if(file_ext_out) *file_ext_out = file_ext; } std::string MDFN_EvalFIP(const std::string &dir_path, const std::string &rel_path, bool skip_safety_check) { char slash; #ifdef _WIN32 slash = '\\'; #else slash = '/'; #endif if(!skip_safety_check && !MDFN_IsFIROPSafe(rel_path)) throw MDFN_Error(0, _("Referenced path \"%s\" is potentially unsafe. See \"filesys.untrusted_fip_check\" setting.\n"), rel_path.c_str()); if(IsAbsolutePath(rel_path.c_str())) return(rel_path); else return(dir_path + slash + rel_path); } const char * GetFNComponent(const char *str) { const char *tp1; #ifdef _WIN32 tp1 = ((char *)strrchr(str,'\\')); const char *tp3; tp3 = ((char *)strrchr(str,'/')); if (tp1= 0; x--) { if(string[x] == ' ' || string[x] == '\r' || string[x] == '\n' || string[x] == '\t' || string[x] == 0x0b) string[x] = 0; else break; } } } void MDFN_trim(char *string) { MDFN_rtrim(string); MDFN_ltrim(string); } // Remove whitespace from beginning of string void MDFN_ltrim(std::string &string) { size_t len = string.length(); size_t di, si; bool InWhitespace = TRUE; di = si = 0; while(si < len) { if(InWhitespace && (string[si] == ' ' || string[si] == '\r' || string[si] == '\n' || string[si] == '\t' || string[si] == 0x0b)) { } else { InWhitespace = FALSE; string[di] = string[si]; di++; } si++; } string.resize(di); } // Remove whitespace from end of string void MDFN_rtrim(std::string &string) { size_t len = string.length(); if(len) { size_t x = len; size_t new_len = len; do { x--; if(!(string[x] == ' ' || string[x] == '\r' || string[x] == '\n' || string[x] == '\t' || string[x] == 0x0b)) break; new_len--; } while(x); string.resize(new_len); } } void MDFN_trim(std::string &string) { MDFN_rtrim(string); MDFN_ltrim(string); } mednafen/video/surface.cpp000664 001750 001750 00000004472 12611054044 016725 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include "../mednafen.h" #include "surface.h" MDFN_PixelFormat::MDFN_PixelFormat() { bpp = 0; colorspace = 0; Rshift = 0; Gshift = 0; Bshift = 0; Ashift = 0; } MDFN_PixelFormat::MDFN_PixelFormat(const unsigned int p_colorspace, const uint8 p_rs, const uint8 p_gs, const uint8 p_bs, const uint8 p_as) { bpp = 32; colorspace = p_colorspace; Rshift = p_rs; Gshift = p_gs; Bshift = p_bs; Ashift = p_as; } MDFN_Surface::MDFN_Surface() { memset(&format, 0, sizeof(format)); pixels = NULL; pitchinpix = 0; w = 0; h = 0; } MDFN_Surface::MDFN_Surface(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf) { Init(p_pixels, p_width, p_height, p_pitchinpix, nf); } void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf) { void *rpix = NULL; assert(nf.bpp == 16 || nf.bpp == 32); format = nf; pixels = NULL; if(!(rpix = calloc(1, p_pitchinpix * p_height * (nf.bpp / 8)))) throw(1); pixels = (uint32 *)rpix; w = p_width; h = p_height; pitchinpix = p_pitchinpix; } // When we're converting, only convert the w*h area(AKA leave the last part of the line, pitch32 - w, alone), // for places where we store auxillary information there(graphics viewer in the debugger), and it'll be faster // to boot. void MDFN_Surface::SetFormat(const MDFN_PixelFormat &nf, bool convert) { format = nf; } MDFN_Surface::~MDFN_Surface() { if(pixels) free(pixels); } mednafen/cdrom/CDAccess_Image.cpp000664 001750 001750 00000104104 12611054044 017776 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ /* Notes and TODO: POSTGAP in CUE sheets may not be handled properly, should the directive automatically increment the index number? INDEX nn where 02 <= nn <= 99 is not supported in CUE sheets. TOC reading code is extremely barebones, leaving out support for more esoteric features. A PREGAP statement in the first track definition in a CUE sheet may not work properly(depends on what is proper); it will be added onto the implicit default 00:02:00 of pregap. Trying to read sectors at an LBA of less than 0 is not supported. TODO: support it(at least up to -150). */ #include #include "../mednafen.h" #include #include #include #include #include "../general.h" #include "../FileStream.h" #include "../MemoryStream.h" #include "CDAccess.h" #include "CDAccess_Image.h" #include "CDUtility.h" #include "audioreader.h" #include "../../libretro.h" extern retro_log_printf_t log_cb; #include enum { CDRF_SUBM_NONE = 0, CDRF_SUBM_RW = 1, CDRF_SUBM_RW_RAW = 2 }; // Disk-image(rip) track/sector formats enum { DI_FORMAT_AUDIO = 0x00, DI_FORMAT_MODE1 = 0x01, DI_FORMAT_MODE1_RAW = 0x02, DI_FORMAT_MODE2 = 0x03, DI_FORMAT_MODE2_FORM1 = 0x04, DI_FORMAT_MODE2_FORM2 = 0x05, DI_FORMAT_MODE2_RAW = 0x06, _DI_FORMAT_COUNT }; static const int32 DI_Size_Table[7] = { 2352, // Audio 2048, // MODE1 2352, // MODE1 RAW 2336, // MODE2 2048, // MODE2 Form 1 2324, // Mode 2 Form 2 2352 }; static const char *DI_CDRDAO_Strings[7] = { "AUDIO", "MODE1", "MODE1_RAW", "MODE2", "MODE2_FORM1", "MODE2_FORM2", "MODE2_RAW" }; static const char *DI_CUE_Strings[7] = { "AUDIO", "MODE1/2048", "MODE1/2352", // FIXME: These are just guesses: "MODE2/2336", "MODE2/2048", "MODE2/2324", "MODE2/2352" }; // Should return an offset to the start of the next argument(past any whitespace), or if there isn't a next argument, // it'll return the length of the src string. static size_t UnQuotify(const std::string &src, size_t source_offset, std::string &dest, bool parse_quotes = true) { const size_t source_len = src.length(); bool in_quote = 0; bool already_normal = 0; dest.clear(); while(source_offset < source_len) { if(src[source_offset] == ' ' || src[source_offset] == '\t') { if(!in_quote) { if(already_normal) // Trailing whitespace(IE we're done with this argument) break; else // Leading whitespace, ignore it. { source_offset++; continue; } } } if(src[source_offset] == '"' && parse_quotes) { if(in_quote) { source_offset++; // Not sure which behavior is most useful(or correct :b). #if 0 in_quote = false; already_normal = true; #else break; #endif } else in_quote = 1; } else { dest.push_back(src[source_offset]); already_normal = 1; } source_offset++; } while(source_offset < source_len) { if(src[source_offset] != ' ' && src[source_offset] != '\t') break; source_offset++; } return source_offset; } uint32 CDAccess_Image::GetSectorCount(CDRFILE_TRACK_INFO *track) { int64 size; if(track->DIFormat == DI_FORMAT_AUDIO) { if(track->AReader) return(((track->AReader->FrameCount() * 4) - track->FileOffset) / 2352); size = track->fp->size(); //printf("%d %d %d\n", (int)stat_buf.st_size, (int)track->FileOffset, (int)stat_buf.st_size - (int)track->FileOffset); if(track->SubchannelMode) return((size - track->FileOffset) / (2352 + 96)); return((size - track->FileOffset) / 2352); } size = track->fp->size(); return((size - track->FileOffset) / DI_Size_Table[track->DIFormat]); } void CDAccess_Image::ParseTOCFileLineInfo(CDRFILE_TRACK_INFO *track, const int tracknum, const std::string &filename, const char *binoffset, const char *msfoffset, const char *length, bool image_memcache, std::map &toc_streamcache) { long offset = 0; // In bytes! long tmp_long; int m, s, f; uint32 sector_mult; long sectors; std::map::iterator ribbit; ribbit = toc_streamcache.find(filename); if(ribbit != toc_streamcache.end()) { track->FirstFileInstance = 0; track->fp = ribbit->second; } else { std::string efn; track->FirstFileInstance = 1; efn = MDFN_EvalFIP(base_dir, filename); if(image_memcache) track->fp = new MemoryStream(new FileStream(efn.c_str(), MODE_READ)); else track->fp = new FileStream(efn.c_str(), MODE_READ); toc_streamcache[filename] = track->fp; } if(filename.length() >= 4 && !strcasecmp(filename.c_str() + filename.length() - 4, ".wav")) { track->AReader = AR_Open(track->fp); if(!track->AReader) throw MDFN_Error(0, "TODO ERROR"); } sector_mult = DI_Size_Table[track->DIFormat]; if(track->SubchannelMode) sector_mult += 96; if(binoffset && sscanf(binoffset, "%ld", &tmp_long) == 1) { offset += tmp_long; } if(msfoffset && sscanf(msfoffset, "%d:%d:%d", &m, &s, &f) == 3) { offset += ((m * 60 + s) * 75 + f) * sector_mult; } track->FileOffset = offset; // Make sure this is set before calling GetSectorCount()! sectors = GetSectorCount(track); //printf("Track: %d, offset: %ld, %ld\n", tracknum, offset, sectors); if(length) { tmp_long = sectors; if(sscanf(length, "%d:%d:%d", &m, &s, &f) == 3) tmp_long = (m * 60 + s) * 75 + f; else if(track->DIFormat == DI_FORMAT_AUDIO) { char *endptr = NULL; tmp_long = strtol(length, &endptr, 10); // Error? if(endptr == length) { tmp_long = sectors; } else tmp_long /= 588; } if(tmp_long > sectors) { throw MDFN_Error(0, _("Length specified in TOC file for track %d is too large by %ld sectors!\n"), tracknum, (long)(tmp_long - sectors)); } sectors = tmp_long; } track->sectors = sectors; } int CDAccess_Image::LoadSBI(const char* sbi_path) { /* Loading SBI file */ uint8 header[4]; uint8 ed[4 + 10]; uint8 tmpq[12]; FileStream sbis(sbi_path, MODE_READ); sbis.read(header, 4); if(memcmp(header, "SBI\0", 4)) return -1; while(sbis.read(ed, sizeof(ed), false) == sizeof(ed)) { /* Bad BCD MSF offset in SBI file. */ if(!BCD_is_valid(ed[0]) || !BCD_is_valid(ed[1]) || !BCD_is_valid(ed[2])) return -1; /* Unrecognized boogly oogly in SBI file */ if(ed[3] != 0x01) return -1; memcpy(tmpq, &ed[4], 10); subq_generate_checksum(tmpq); tmpq[10] ^= 0xFF; tmpq[11] ^= 0xFF; uint32 aba = AMSF_to_ABA(BCD_to_U8(ed[0]), BCD_to_U8(ed[1]), BCD_to_U8(ed[2])); memcpy(SubQReplaceMap[aba].data, tmpq, 12); } //MDFN_printf(_("Loaded Q subchannel replacements for %zu sectors.\n"), SubQReplaceMap.size()); return 0; } void CDAccess_Image::ImageOpen(const char *path, bool image_memcache) { MemoryStream fp(new FileStream(path, MODE_READ)); static const unsigned max_args = 4; std::string linebuf; std::string cmdbuf, args[max_args]; bool IsTOC = FALSE; int32 active_track = -1; int32 AutoTrackInc = 1; // For TOC CDRFILE_TRACK_INFO TmpTrack; std::string file_base, file_ext; std::map toc_streamcache; disc_type = DISC_TYPE_CDDA_OR_M1; memset(&TmpTrack, 0, sizeof(TmpTrack)); MDFN_GetFilePathComponents(path, &base_dir, &file_base, &file_ext); if(!strcasecmp(file_ext.c_str(), ".toc")) { log_cb(RETRO_LOG_INFO, "TOC file detected.\n"); IsTOC = true; } // Check for annoying UTF-8 BOM. if(!IsTOC) { uint8 bom_tmp[3]; if(fp.read(bom_tmp, 3, false) == 3 && bom_tmp[0] == 0xEF && bom_tmp[1] == 0xBB && bom_tmp[2] == 0xBF) { log_cb(RETRO_LOG_ERROR, "UTF-8 BOM detected at start of CUE sheet.\n"); } else fp.seek(0, SEEK_SET); } // Assign opposite maximum values so our tests will work! FirstTrack = 99; LastTrack = 0; linebuf.reserve(1024); while(fp.get_line(linebuf) >= 0) { unsigned argcount = 0; if(IsTOC) { // Handle TOC format comments size_t ss_loc = linebuf.find("//"); if(ss_loc != std::string::npos) linebuf.resize(ss_loc); } // Call trim AFTER we handle TOC-style comments, so we'll be sure to remove trailing whitespace in lines like: MONKEY // BABIES MDFN_trim(linebuf); if(linebuf.length() == 0) // Skip blank lines. continue; // Grab command and arguments. { size_t offs = 0; offs = UnQuotify(linebuf, offs, cmdbuf, false); for(argcount = 0; argcount < max_args && offs < linebuf.length(); argcount++) offs = UnQuotify(linebuf, offs, args[argcount]); // Make sure unused arguments are cleared out so we don't have inter-line leaks! for(unsigned x = argcount; x < max_args; x++) args[x].clear(); MDFN_strtoupper(cmdbuf); } //printf("%s\n", cmdbuf.c_str()); //: %s %s %s %s\n", cmdbuf.c_str(), args[0].c_str(), args[1].c_str(), args[2].c_str(), args[3].c_str()); if(IsTOC) { if(cmdbuf == "TRACK") { if(active_track >= 0) { memcpy(&Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); memset(&TmpTrack, 0, sizeof(TmpTrack)); active_track = -1; } if(AutoTrackInc > 99) { throw(MDFN_Error(0, _("Invalid track number: %d"), AutoTrackInc)); } active_track = AutoTrackInc++; if(active_track < FirstTrack) FirstTrack = active_track; if(active_track > LastTrack) LastTrack = active_track; int format_lookup; for(format_lookup = 0; format_lookup < _DI_FORMAT_COUNT; format_lookup++) { if(!strcasecmp(args[0].c_str(), DI_CDRDAO_Strings[format_lookup])) { TmpTrack.DIFormat = format_lookup; break; } } if(format_lookup == _DI_FORMAT_COUNT) { throw(MDFN_Error(0, _("Invalid track format: %s"), args[0].c_str())); } if(TmpTrack.DIFormat == DI_FORMAT_AUDIO) TmpTrack.RawAudioMSBFirst = TRUE; // Silly cdrdao... if(!strcasecmp(args[1].c_str(), "RW")) { TmpTrack.SubchannelMode = CDRF_SUBM_RW; throw(MDFN_Error(0, _("\"RW\" format subchannel data not supported, only \"RW_RAW\" is!"))); } else if(!strcasecmp(args[1].c_str(), "RW_RAW")) TmpTrack.SubchannelMode = CDRF_SUBM_RW_RAW; } // end to TRACK else if(cmdbuf == "SILENCE") { //throw MDFN_Error(0, _("Unsupported directive: %s"), cmdbuf.c_str()); } else if(cmdbuf == "ZERO") { //throw MDFN_Error(0, _("Unsupported directive: %s"), cmdbuf.c_str()); } else if(cmdbuf == "FIFO") { throw MDFN_Error(0, _("Unsupported directive: %s"), cmdbuf.c_str()); } else if(cmdbuf == "FILE" || cmdbuf == "AUDIOFILE") { const char *binoffset = NULL; const char *msfoffset = NULL; const char *length = NULL; if(args[1].c_str()[0] == '#') { binoffset = args[1].c_str() + 1; msfoffset = args[2].c_str(); length = args[3].c_str(); } else { msfoffset = args[1].c_str(); length = args[2].c_str(); } //printf("%s, %s, %s, %s\n", args[0].c_str(), binoffset, msfoffset, length); ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, msfoffset, length, image_memcache, toc_streamcache); } else if(cmdbuf == "DATAFILE") { const char *binoffset = NULL; const char *length = NULL; if(args[1].c_str()[0] == '#') { binoffset = args[1].c_str() + 1; length = args[2].c_str(); } else length = args[1].c_str(); ParseTOCFileLineInfo(&TmpTrack, active_track, args[0], binoffset, NULL, length, image_memcache, toc_streamcache); } else if(cmdbuf == "INDEX") { } else if(cmdbuf == "PREGAP") { if(active_track < 0) { throw(MDFN_Error(0, _("Command %s is outside of a TRACK definition!\n"), cmdbuf.c_str())); } int m,s,f; sscanf(args[0].c_str(), "%d:%d:%d", &m, &s, &f); TmpTrack.pregap = (m * 60 + s) * 75 + f; } // end to PREGAP else if(cmdbuf == "START") { if(active_track < 0) { throw(MDFN_Error(0, _("Command %s is outside of a TRACK definition!\n"), cmdbuf.c_str())); } int m,s,f; sscanf(args[0].c_str(), "%d:%d:%d", &m, &s, &f); TmpTrack.pregap = (m * 60 + s) * 75 + f; } else if(cmdbuf == "TWO_CHANNEL_AUDIO") { TmpTrack.subq_control &= ~SUBQ_CTRLF_4CH; } else if(cmdbuf == "FOUR_CHANNEL_AUDIO") { TmpTrack.subq_control |= SUBQ_CTRLF_4CH; } else if(cmdbuf == "NO") { MDFN_strtoupper(args[0]); if(args[0] == "COPY") { TmpTrack.subq_control &= ~SUBQ_CTRLF_DCP; } else if(args[0] == "PRE_EMPHASIS") { TmpTrack.subq_control &= ~SUBQ_CTRLF_PRE; } else { throw MDFN_Error(0, _("Unsupported argument to \"NO\" directive: %s"), args[0].c_str()); } } else if(cmdbuf == "COPY") { TmpTrack.subq_control |= SUBQ_CTRLF_DCP; } else if(cmdbuf == "PRE_EMPHASIS") { TmpTrack.subq_control |= SUBQ_CTRLF_PRE; } // TODO: Confirm that these are taken from the TOC of the disc, and not synthesized by cdrdao. else if(cmdbuf == "CD_DA") disc_type = DISC_TYPE_CDDA_OR_M1; else if(cmdbuf == "CD_ROM") disc_type = DISC_TYPE_CDDA_OR_M1; else if(cmdbuf == "CD_ROM_XA") disc_type = DISC_TYPE_CD_XA; else { //throw MDFN_Error(0, _("Unsupported directive: %s"), cmdbuf.c_str()); } // TODO: CATALOG } /*********** END TOC HANDLING ************/ else // now for CUE sheet handling { if(cmdbuf == "FILE") { if(active_track >= 0) { memcpy(&Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); memset(&TmpTrack, 0, sizeof(TmpTrack)); active_track = -1; } if(!MDFN_IsFIROPSafe(args[0])) { throw(MDFN_Error(0, _("Referenced path \"%s\" is potentially unsafe. See \"filesys.untrusted_fip_check\" setting.\n"), args[0].c_str())); } std::string efn = MDFN_EvalFIP(base_dir, args[0]); TmpTrack.fp = new FileStream(efn.c_str(), MODE_READ); TmpTrack.FirstFileInstance = 1; if(image_memcache) TmpTrack.fp = new MemoryStream(TmpTrack.fp); if(!strcasecmp(args[1].c_str(), "BINARY")) { //TmpTrack.Format = TRACK_FORMAT_DATA; //struct stat stat_buf; //fstat(fileno(TmpTrack.fp), &stat_buf); //TmpTrack.sectors = stat_buf.st_size; // / 2048; } else if(!strcasecmp(args[1].c_str(), "OGG") || !strcasecmp(args[1].c_str(), "VORBIS") || !strcasecmp(args[1].c_str(), "WAVE") || !strcasecmp(args[1].c_str(), "WAV") || !strcasecmp(args[1].c_str(), "PCM") || !strcasecmp(args[1].c_str(), "MPC") || !strcasecmp(args[1].c_str(), "MP+")) { TmpTrack.AReader = AR_Open(TmpTrack.fp); if(!TmpTrack.AReader) { throw(MDFN_Error(0, _("Unsupported audio track file format: %s\n"), args[0].c_str())); } } else { throw(MDFN_Error(0, _("Unsupported track format: %s\n"), args[1].c_str())); } } else if(cmdbuf == "TRACK") { if(active_track >= 0) { memcpy(&Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); TmpTrack.FirstFileInstance = 0; TmpTrack.pregap = 0; TmpTrack.pregap_dv = 0; TmpTrack.postgap = 0; TmpTrack.index[0] = -1; TmpTrack.index[1] = 0; } active_track = atoi(args[0].c_str()); if(active_track < FirstTrack) FirstTrack = active_track; if(active_track > LastTrack) LastTrack = active_track; int format_lookup; for(format_lookup = 0; format_lookup < _DI_FORMAT_COUNT; format_lookup++) { if(!strcasecmp(args[1].c_str(), DI_CUE_Strings[format_lookup])) { TmpTrack.DIFormat = format_lookup; break; } } if(format_lookup == _DI_FORMAT_COUNT) { throw(MDFN_Error(0, _("Invalid track format: %s\n"), args[1].c_str())); } if(active_track < 0 || active_track > 99) { throw(MDFN_Error(0, _("Invalid track number: %d\n"), active_track)); } } else if(cmdbuf == "INDEX") { if(active_track >= 0) { unsigned int m,s,f; if(sscanf(args[1].c_str(), "%u:%u:%u", &m, &s, &f) != 3) { throw MDFN_Error(0, _("Malformed m:s:f time in \"%s\" directive: %s"), cmdbuf.c_str(), args[0].c_str()); } if(!strcasecmp(args[0].c_str(), "01") || !strcasecmp(args[0].c_str(), "1")) TmpTrack.index[1] = (m * 60 + s) * 75 + f; else if(!strcasecmp(args[0].c_str(), "00") || !strcasecmp(args[0].c_str(), "0")) TmpTrack.index[0] = (m * 60 + s) * 75 + f; } } else if(cmdbuf == "PREGAP") { if(active_track >= 0) { unsigned int m,s,f; if(sscanf(args[0].c_str(), "%u:%u:%u", &m, &s, &f) != 3) { throw MDFN_Error(0, _("Malformed m:s:f time in \"%s\" directive: %s"), cmdbuf.c_str(), args[0].c_str()); } TmpTrack.pregap = (m * 60 + s) * 75 + f; } } else if(cmdbuf == "POSTGAP") { if(active_track >= 0) { unsigned int m,s,f; if(sscanf(args[0].c_str(), "%u:%u:%u", &m, &s, &f) != 3) { throw MDFN_Error(0, _("Malformed m:s:f time in \"%s\" directive: %s"), cmdbuf.c_str(), args[0].c_str()); } TmpTrack.postgap = (m * 60 + s) * 75 + f; } } else if(cmdbuf == "REM") { } else if(cmdbuf == "FLAGS") { TmpTrack.subq_control &= ~(SUBQ_CTRLF_PRE | SUBQ_CTRLF_DCP | SUBQ_CTRLF_4CH); for(unsigned i = 0; i < argcount; i++) { if(args[i] == "DCP") { TmpTrack.subq_control |= SUBQ_CTRLF_DCP; } else if(args[i] == "4CH") { TmpTrack.subq_control |= SUBQ_CTRLF_4CH; } else if(args[i] == "PRE") { TmpTrack.subq_control |= SUBQ_CTRLF_PRE; } else if(args[i] == "SCMS") { // Not implemented, likely pointless. PROBABLY indicates that the copy bit of the subchannel Q control field is supposed to // alternate between 1 and 0 at 9.375 Hz(four 1, four 0, four 1, four 0, etc.). } else { throw MDFN_Error(0, _("Unknown CUE sheet \"FLAGS\" directive flag \"%s\".\n"), args[i].c_str()); } } } else if(cmdbuf == "CDTEXTFILE" || cmdbuf == "CATALOG" || cmdbuf == "ISRC" || cmdbuf == "TITLE" || cmdbuf == "PERFORMER" || cmdbuf == "SONGWRITER") log_cb(RETRO_LOG_ERROR, "Unsupported CUE sheet directive: \"%s\".\n", cmdbuf.c_str()); else { throw MDFN_Error(0, _("Unknown CUE sheet directive \"%s\".\n"), cmdbuf.c_str()); } } // end of CUE sheet handling } // end of fgets() loop if(active_track >= 0) memcpy(&Tracks[active_track], &TmpTrack, sizeof(TmpTrack)); if(FirstTrack > LastTrack) throw(MDFN_Error(0, _("No tracks found!\n"))); NumTracks = 1 + LastTrack - FirstTrack; int32 RunningLBA = 0; int32 LastIndex = 0; long FileOffset = 0; for(int x = FirstTrack; x < (FirstTrack + NumTracks); x++) { if(Tracks[x].DIFormat == DI_FORMAT_AUDIO) Tracks[x].subq_control &= ~SUBQ_CTRLF_DATA; else Tracks[x].subq_control |= SUBQ_CTRLF_DATA; if(!IsTOC) // TOC-format disc_type calculation is handled differently. { switch(Tracks[x].DIFormat) { default: break; case DI_FORMAT_MODE2: case DI_FORMAT_MODE2_FORM1: case DI_FORMAT_MODE2_FORM2: case DI_FORMAT_MODE2_RAW: disc_type = DISC_TYPE_CD_XA; break; } } if(IsTOC) { RunningLBA += Tracks[x].pregap; Tracks[x].LBA = RunningLBA; RunningLBA += Tracks[x].sectors; RunningLBA += Tracks[x].postgap; } else // else handle CUE sheet... { if(Tracks[x].FirstFileInstance) { LastIndex = 0; FileOffset = 0; } RunningLBA += Tracks[x].pregap; Tracks[x].pregap_dv = 0; if(Tracks[x].index[0] != -1) Tracks[x].pregap_dv = Tracks[x].index[1] - Tracks[x].index[0]; FileOffset += Tracks[x].pregap_dv * DI_Size_Table[Tracks[x].DIFormat]; RunningLBA += Tracks[x].pregap_dv; Tracks[x].LBA = RunningLBA; // Make sure FileOffset this is set before the call to GetSectorCount() Tracks[x].FileOffset = FileOffset; Tracks[x].sectors = GetSectorCount(&Tracks[x]); if((x + 1) >= (FirstTrack + NumTracks) || Tracks[x+1].FirstFileInstance) { } else { // Fix the sector count if we have multiple tracks per one binary image file. if(Tracks[x + 1].index[0] == -1) Tracks[x].sectors = Tracks[x + 1].index[1] - Tracks[x].index[1]; else Tracks[x].sectors = Tracks[x + 1].index[0] - Tracks[x].index[1]; //Tracks[x + 1].index - Tracks[x].index; } //printf("Poo: %d %d\n", x, Tracks[x].sectors); RunningLBA += Tracks[x].sectors; RunningLBA += Tracks[x].postgap; //printf("%d, %ld %d %d %d %d\n", x, FileOffset, Tracks[x].index, Tracks[x].pregap, Tracks[x].sectors, Tracks[x].LBA); FileOffset += Tracks[x].sectors * DI_Size_Table[Tracks[x].DIFormat]; } // end to cue sheet handling } // end to track loop total_sectors = RunningLBA; // // Load SBI file, if present // if(!IsTOC) { const char *sbi_path = NULL; char sbi_ext[4] = { 's', 'b', 'i', 0 }; if(file_ext.length() == 4 && file_ext[0] == '.') { unsigned i; for(i = 0; i < 3; i++) { if(file_ext[1 + i] >= 'A' && file_ext[1 + i] <= 'Z') sbi_ext[i] += 'A' - 'a'; } } sbi_path = MDFN_EvalFIP(base_dir, file_base + std::string(".") + std::string(sbi_ext), true).c_str(); if (path_is_valid(sbi_path)) LoadSBI(sbi_path); } } void CDAccess_Image::Cleanup(void) { int32_t track; for(track = 0; track < 100; track++) { CDRFILE_TRACK_INFO *this_track = &Tracks[track]; if(this_track->FirstFileInstance) { if(Tracks[track].AReader) { delete Tracks[track].AReader; Tracks[track].AReader = NULL; } if(this_track->fp) { delete this_track->fp; this_track->fp = NULL; } } } } CDAccess_Image::CDAccess_Image(const char *path, bool image_memcache) : NumTracks(0), FirstTrack(0), LastTrack(0), total_sectors(0) { memset(Tracks, 0, sizeof(Tracks)); ImageOpen(path, image_memcache); } CDAccess_Image::~CDAccess_Image() { Cleanup(); } void CDAccess_Image::Read_Raw_Sector(uint8 *buf, int32 lba) { int32_t track; uint8_t SimuQ[0xC]; bool TrackFound = FALSE; memset(buf + 2352, 0, 96); MakeSubPQ(lba, buf + 2352); subq_deinterleave(buf + 2352, SimuQ); for(track = FirstTrack; track < (FirstTrack + NumTracks); track++) { CDRFILE_TRACK_INFO *ct = &Tracks[track]; if(lba >= (ct->LBA - ct->pregap_dv - ct->pregap) && lba < (ct->LBA + ct->sectors + ct->postgap)) { TrackFound = TRUE; // Handle pregap and postgap reading if(lba < (ct->LBA - ct->pregap_dv) || lba >= (ct->LBA + ct->sectors)) { //printf("Pre/post-gap read, LBA=%d(LBA-track_start_LBA=%d)\n", lba, lba - ct->LBA); memset(buf, 0, 2352); // Null sector data, per spec } else { if(ct->AReader) { int16 AudioBuf[588 * 2]; int frames_read = ct->AReader->Read((ct->FileOffset / 4) + (lba - ct->LBA) * 588, AudioBuf, 588); ct->LastSamplePos += frames_read; if(frames_read < 0 || frames_read > 588) // This shouldn't happen. { printf("Error: frames_read out of range: %d\n", frames_read); frames_read = 0; } if(frames_read < 588) memset((uint8 *)AudioBuf + frames_read * 2 * sizeof(int16), 0, (588 - frames_read) * 2 * sizeof(int16)); for(int i = 0; i < 588 * 2; i++) MDFN_en16lsb(buf + i * 2, AudioBuf[i]); } else // Binary, woo. { long SeekPos = ct->FileOffset; long LBARelPos = lba - ct->LBA; SeekPos += LBARelPos * DI_Size_Table[ct->DIFormat]; if(ct->SubchannelMode) SeekPos += 96 * (lba - ct->LBA); ct->fp->seek(SeekPos, SEEK_SET); switch(ct->DIFormat) { case DI_FORMAT_AUDIO: ct->fp->read(buf, 2352); if(ct->RawAudioMSBFirst) Endian_A16_Swap(buf, 588 * 2); break; case DI_FORMAT_MODE1: ct->fp->read(buf + 12 + 3 + 1, 2048); encode_mode1_sector(lba + 150, buf); break; case DI_FORMAT_MODE1_RAW: case DI_FORMAT_MODE2_RAW: ct->fp->read(buf, 2352); break; case DI_FORMAT_MODE2: ct->fp->read(buf + 16, 2336); encode_mode2_sector(lba + 150, buf); break; // FIXME: M2F1, M2F2, does sub-header come before or after user data(standards say before, but I wonder // about cdrdao...). case DI_FORMAT_MODE2_FORM1: ct->fp->read(buf + 24, 2048); //encode_mode2_form1_sector(lba + 150, buf); break; case DI_FORMAT_MODE2_FORM2: ct->fp->read(buf + 24, 2324); //encode_mode2_form2_sector(lba + 150, buf); break; } if(ct->SubchannelMode) ct->fp->read(buf + 2352, 96); } } // end if audible part of audio track read. break; } // End if LBA is in range } // end track search loop if(!TrackFound) throw(MDFN_Error(0, _("Could not find track for sector %u!"), lba)); #if 0 if(qbuf[0] & 0x40) { uint8 dummy_buf[2352 + 96]; bool any_mismatch = FALSE; memcpy(dummy_buf + 16, buf + 16, 2048); memset(dummy_buf + 2352, 0, 96); MakeSubPQ(lba, dummy_buf + 2352); encode_mode1_sector(lba + 150, dummy_buf); for(int i = 0; i < 2352 + 96; i++) { if(dummy_buf[i] != buf[i]) { printf("Mismatch at %d, %d: %02x:%02x; ", lba, i, dummy_buf[i], buf[i]); any_mismatch = TRUE; } } if(any_mismatch) puts("\n"); } #endif //subq_deinterleave(buf + 2352, qbuf); //printf("%02x\n", qbuf[0]); //printf("%02x\n", buf[12 + 3]); } // Note: this function makes use of the current contents(as in |=) in SubPWBuf. void CDAccess_Image::MakeSubPQ(int32 lba, uint8 *SubPWBuf) { unsigned i; uint8_t buf[0xC], adr, control; int32_t track; uint32_t lba_relative; uint32_t ma, sa, fa; uint32_t m, s, f; uint8_t pause_or = 0x00; bool track_found = FALSE; for(track = FirstTrack; track < (FirstTrack + NumTracks); track++) { if(lba >= (Tracks[track].LBA - Tracks[track].pregap_dv - Tracks[track].pregap) && lba < (Tracks[track].LBA + Tracks[track].sectors + Tracks[track].postgap)) { track_found = TRUE; break; } } //printf("%d %d\n", Tracks[1].LBA, Tracks[1].sectors); if(!track_found) { printf("MakeSubPQ error for sector %u!", lba); track = FirstTrack; } lba_relative = abs((int32)lba - Tracks[track].LBA); f = (lba_relative % 75); s = ((lba_relative / 75) % 60); m = (lba_relative / 75 / 60); fa = (lba + 150) % 75; sa = ((lba + 150) / 75) % 60; ma = ((lba + 150) / 75 / 60); adr = 0x1; // Q channel data encodes position control = Tracks[track].subq_control; // Handle pause(D7 of interleaved subchannel byte) bit, should be set to 1 when in pregap or postgap. if((lba < Tracks[track].LBA) || (lba >= Tracks[track].LBA + Tracks[track].sectors)) { //printf("pause_or = 0x80 --- %d\n", lba); pause_or = 0x80; } // Handle pregap between audio->data track { int32_t pg_offset = (int32)lba - Tracks[track].LBA; // If we're more than 2 seconds(150 sectors) from the real "start" of the track/INDEX 01, and the track is a data track, // and the preceding track is an audio track, encode it as audio(by taking the SubQ control field from the preceding track). // // TODO: Look into how we're supposed to handle subq control field in the four combinations of track types(data/audio). // if(pg_offset < -150) { if((Tracks[track].subq_control & SUBQ_CTRLF_DATA) && (FirstTrack < track) && !(Tracks[track - 1].subq_control & SUBQ_CTRLF_DATA)) { //printf("Pregap part 1 audio->data: lba=%d track_lba=%d\n", lba, Tracks[track].LBA); control = Tracks[track - 1].subq_control; } } } memset(buf, 0, 0xC); buf[0] = (adr << 0) | (control << 4); buf[1] = U8_to_BCD(track); if(lba < Tracks[track].LBA) // Index is 00 in pregap buf[2] = U8_to_BCD(0x00); else buf[2] = U8_to_BCD(0x01); /* Track relative MSF address */ buf[3] = U8_to_BCD(m); buf[4] = U8_to_BCD(s); buf[5] = U8_to_BCD(f); buf[6] = 0; /* Absolute MSF address */ buf[7] = U8_to_BCD(ma); buf[8] = U8_to_BCD(sa); buf[9] = U8_to_BCD(fa); subq_generate_checksum(buf); if(!SubQReplaceMap.empty()) { //printf("%d\n", lba); std::map::const_iterator it = SubQReplaceMap.find(LBA_to_ABA(lba)); if(it != SubQReplaceMap.end()) { //printf("Replace: %d\n", lba); memcpy(buf, it->second.data, 12); } } for (i = 0; i < 96; i++) SubPWBuf[i] |= (((buf[i >> 3] >> (7 - (i & 0x7))) & 1) ? 0x40 : 0x00) | pause_or; } void CDAccess_Image::Read_TOC(TOC *toc) { unsigned i; TOC_Clear(toc); toc->first_track = FirstTrack; toc->last_track = FirstTrack + NumTracks - 1; toc->disc_type = disc_type; for(i = toc->first_track; i <= toc->last_track; i++) { toc->tracks[i].lba = Tracks[i].LBA; toc->tracks[i].adr = ADR_CURPOS; toc->tracks[i].control = Tracks[i].subq_control; } toc->tracks[100].lba = total_sectors; toc->tracks[100].adr = ADR_CURPOS; toc->tracks[100].control = toc->tracks[toc->last_track].control & 0x4; // Convenience leadout track duplication. if(toc->last_track < 99) toc->tracks[toc->last_track + 1] = toc->tracks[100]; } void CDAccess_Image::Eject(bool eject_status) { } mednafen/tremor/README000664 001750 001750 00000003625 12611054044 015652 0ustar00sergiosergio000000 000000 This README covers the Ogg Vorbis 'Tremor' integer playback codec source as of date 2002 09 02, version 1.0.0. ****** The C source in this package will build on any ANSI C compiler and function completely and properly on any platform. The included build system assumes GNU build system and make tools (m4, automake, autoconf, libtool and gmake). GCC is not required, although GCC is the most tested compiler. To build using GNU tools, type in the source directory: ./autogen.sh make Currently, the source implements playback in pure C on all platforms except ARM, where a [currently] small amount of assembly (see asm_arm.h) is used to implement 64 bit math operations and fast LSP computation. If building on ARM without the benefit of GNU build system tools, be sure that '_ARM_ASSEM_' is #defined by the build system if this assembly is desired, else the resulting library will use whatever 64 bit math builtins the compiler implements. No math library is required by this source. No floating point operations are used at any point in either setup or decode. This decoder library will properly decode any past, current or future Vorbis I file or stream. ******** The build system produces a static and [when supported by the OS] dynamic library named 'libvorbisidec'. This library exposes an API nearly identical to the BSD reference library's 'libvorbisfile', including all the features familiar to users of vorbisfile. This API is similar enough that the proper header file to include is named 'ivorbisfile.h' [included in the source build directory]. Lower level libvorbis-style headers and structures are in 'ivorbiscodec.h' [included in the source build directory]. A simple example program, ivorbisfile_example.c, can be built with 'make example'. ******** Detailed Tremor API Documentation begins at doc/index.html Monty xiph.org mednafen/tremor/config_types.h000664 001750 001750 00000000353 12611054044 017627 0ustar00sergiosergio000000 000000 #ifndef __CONFIG_TYPES_H__ #define __CONFIG_TYPES_H__ #include typedef int16_t ogg_int16_t; typedef uint16_t ogg_uint16_t; typedef int32_t ogg_int32_t; typedef uint32_t ogg_uint32_t; typedef int64_t ogg_int64_t; #endif mednafen/cdrom/CDAccess_CCD.h000664 001750 001750 00000002551 12611054044 017015 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #ifndef _CDROM_CDACCESS_CCD_H_ #define _CDROM_CDACCESS_CCD_H_ #include "../FileStream.h" #include "../MemoryStream.h" #include "CDAccess.h" #include class CDAccess_CCD : public CDAccess { public: CDAccess_CCD(const char *path, bool image_memcache); virtual ~CDAccess_CCD(); virtual void Read_Raw_Sector(uint8_t *buf, int32_t lba); virtual void Read_TOC(TOC *toc); virtual void Eject(bool eject_status); private: void Load(const char *path, bool image_memcache); void Cleanup(void); void CheckSubQSanity(void); Stream* img_stream; Stream* sub_stream; size_t img_numsectors; TOC tocd; }; #endif mednafen/psx/input/multitap.h000664 001750 001750 00000002033 12611054044 017433 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_INPUT_MULTITAP_H #define __MDFN_PSX_INPUT_MULTITAP_H class InputDevice_Multitap : public InputDevice { public: InputDevice_Multitap(); virtual ~InputDevice_Multitap(); virtual void Power(void); virtual int StateAction(StateMem* sm, int load, int data_only, const char* section_name); void SetSubDevice(unsigned int sub_index, InputDevice *device, InputDevice *mc_device); // // // virtual void SetDTR(bool new_dtr); virtual bool GetDSR(void); virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); private: InputDevice *pad_devices[4]; InputDevice *mc_devices[4]; bool dtr; int selected_device; bool full_mode_setting; bool full_mode; bool mc_mode; bool prev_fm_success; uint8 fm_dp; // Device-present. uint8 fm_buffer[4][8]; uint8 sb[4][8]; bool fm_command_error; uint8 command; uint8 receive_buffer; uint8 bit_counter; uint8 byte_counter; }; #endif mednafen/tremor/info.c000664 001750 001750 00000026466 12611054044 016101 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: maintain the info structure, info <-> header packets ********************************************************************/ /* general handling of the header and the vorbis_info structure (and substructures) */ #include #include #include #include #include "ogg.h" #include "ivorbiscodec.h" #include "codec_internal.h" #include "codebook.h" #include "registry.h" #include "window.h" #include "misc.h" /* helpers */ static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){ while(bytes--){ *buf++=oggpack_read(o,8); } } void vorbis_comment_init(vorbis_comment *vc){ memset(vc,0,sizeof(*vc)); } /* This is more or less the same as strncasecmp - but that doesn't exist * everywhere, and this is a fairly trivial function, so we include it */ static int tagcompare(const char *s1, const char *s2, int n){ int c=0; while(c < n){ if(toupper(s1[c]) != toupper(s2[c])) return !0; c++; } return 0; } char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){ long i; int found = 0; int taglen = strlen(tag)+1; /* +1 for the = we append */ char *fulltag = (char *)alloca(taglen+ 1); strcpy(fulltag, tag); strcat(fulltag, "="); for(i=0;icomments;i++){ if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ if(count == found) /* We return a pointer to the data, not a copy */ return vc->user_comments[i] + taglen; else found++; } } return NULL; /* didn't find anything */ } int vorbis_comment_query_count(vorbis_comment *vc, char *tag){ int i,count=0; int taglen = strlen(tag)+1; /* +1 for the = we append */ char *fulltag = (char *)alloca(taglen+1); strcpy(fulltag,tag); strcat(fulltag, "="); for(i=0;icomments;i++){ if(!tagcompare(vc->user_comments[i], fulltag, taglen)) count++; } return count; } void vorbis_comment_clear(vorbis_comment *vc){ if(vc){ long i; if(vc->user_comments){ for(i=0;icomments;i++) if(vc->user_comments[i])_ogg_free(vc->user_comments[i]); _ogg_free(vc->user_comments); } if(vc->comment_lengths)_ogg_free(vc->comment_lengths); if(vc->vendor)_ogg_free(vc->vendor); memset(vc,0,sizeof(*vc)); } } /* blocksize 0 is guaranteed to be short, 1 is guarantted to be long. They may be equal, but short will never ge greater than long */ int vorbis_info_blocksize(vorbis_info *vi,int zo){ codec_setup_info *ci = (codec_setup_info *)vi->codec_setup; return ci ? ci->blocksizes[zo] : -1; } /* used by synthesis, which has a full, alloced vi */ void vorbis_info_init(vorbis_info *vi){ memset(vi,0,sizeof(*vi)); vi->codec_setup=(codec_setup_info *)_ogg_calloc(1,sizeof(codec_setup_info)); } void vorbis_info_clear(vorbis_info *vi){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int i; if(ci){ for(i=0;imodes;i++) if(ci->mode_param[i])_ogg_free(ci->mode_param[i]); for(i=0;imaps;i++) /* unpack does the range checking */ if(ci->map_param[i]) _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]); for(i=0;ifloors;i++) /* unpack does the range checking */ if(ci->floor_param[i]) _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]); for(i=0;iresidues;i++) /* unpack does the range checking */ if(ci->residue_param[i]) _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]); for(i=0;ibooks;i++){ if(ci->book_param[i]){ /* knows if the book was not alloced */ vorbis_staticbook_destroy(ci->book_param[i]); } if(ci->fullbooks) vorbis_book_clear(ci->fullbooks+i); } if(ci->fullbooks) _ogg_free(ci->fullbooks); _ogg_free(ci); } memset(vi,0,sizeof(*vi)); } /* Header packing/unpacking ********************************************/ static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; if(!ci)return(OV_EFAULT); vi->version=oggpack_read(opb,32); if(vi->version!=0)return(OV_EVERSION); vi->channels=oggpack_read(opb,8); vi->rate=oggpack_read(opb,32); vi->bitrate_upper=oggpack_read(opb,32); vi->bitrate_nominal=oggpack_read(opb,32); vi->bitrate_lower=oggpack_read(opb,32); ci->blocksizes[0]=1<blocksizes[1]=1<rate<1)goto err_out; if(vi->channels<1)goto err_out; if(ci->blocksizes[0]<64)goto err_out; if(ci->blocksizes[1]blocksizes[0])goto err_out; if(ci->blocksizes[1]>8192)goto err_out; if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ return(0); err_out: vorbis_info_clear(vi); return(OV_EBADHEADER); } static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){ int i; int vendorlen; vendorlen=oggpack_read(opb,32); if(vendorlen<0)goto err_out; if(vendorlen>opb->storage-oggpack_bytes(opb))goto err_out; vc->vendor=(char *)_ogg_calloc(vendorlen+1,1); if(vc->vendor==NULL)goto err_out; _v_readstring(opb,vc->vendor,vendorlen); i=oggpack_read(opb,32); if(i<0||i>=INT_MAX||i>(opb->storage-oggpack_bytes(opb))>>2)goto err_out; vc->user_comments=(char **)_ogg_calloc(i+1,sizeof(*vc->user_comments)); vc->comment_lengths=(int *)_ogg_calloc(i+1, sizeof(*vc->comment_lengths)); if(vc->user_comments==NULL||vc->comment_lengths==NULL)goto err_out; vc->comments=i; for(i=0;icomments;i++){ int len=oggpack_read(opb,32); if(len<0||len>opb->storage-oggpack_bytes(opb))goto err_out; vc->comment_lengths[i]=len; vc->user_comments[i]=(char *)_ogg_calloc(len+1,1); if(vc->user_comments[i]==NULL){ vc->comments=i; goto err_out; } _v_readstring(opb,vc->user_comments[i],len); } if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */ return(0); err_out: vorbis_comment_clear(vc); return(OV_EBADHEADER); } /* all of the real encoding details are here. The modes, books, everything */ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int i; if(!ci)return(OV_EFAULT); /* codebooks */ ci->books=oggpack_read(opb,8)+1; if(ci->books<=0)goto err_out; for(i=0;ibooks;i++){ ci->book_param[i]=vorbis_staticbook_unpack(opb); if(!ci->book_param[i])goto err_out; } /* time backend settings */ ci->times=oggpack_read(opb,6)+1; if(ci->times<=0)goto err_out; for(i=0;itimes;i++){ ci->time_type[i]=oggpack_read(opb,16); if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out; /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb); Vorbis I has no time backend */ /*if(!ci->time_param[i])goto err_out;*/ } /* floor backend settings */ ci->floors=oggpack_read(opb,6)+1; if(ci->floors<=0)goto err_out; for(i=0;ifloors;i++){ ci->floor_type[i]=oggpack_read(opb,16); if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); if(!ci->floor_param[i])goto err_out; } /* residue backend settings */ ci->residues=oggpack_read(opb,6)+1; if(ci->residues<=0)goto err_out; for(i=0;iresidues;i++){ ci->residue_type[i]=oggpack_read(opb,16); if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); if(!ci->residue_param[i])goto err_out; } /* map backend settings */ ci->maps=oggpack_read(opb,6)+1; if(ci->maps<=0)goto err_out; for(i=0;imaps;i++){ ci->map_type[i]=oggpack_read(opb,16); if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); if(!ci->map_param[i])goto err_out; } /* mode settings */ ci->modes=oggpack_read(opb,6)+1; if(ci->modes<=0)goto err_out; for(i=0;imodes;i++){ ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i])); ci->mode_param[i]->blockflag=oggpack_read(opb,1); ci->mode_param[i]->windowtype=oggpack_read(opb,16); ci->mode_param[i]->transformtype=oggpack_read(opb,16); ci->mode_param[i]->mapping=oggpack_read(opb,8); if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; if(ci->mode_param[i]->mapping<0)goto err_out; } if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ return(0); err_out: vorbis_info_clear(vi); return(OV_EBADHEADER); } /* Is this packet a vorbis ID header? */ int vorbis_synthesis_idheader(ogg_packet *op){ oggpack_buffer opb; char buffer[6]; if(op){ oggpack_readinit(&opb,op->packet,op->bytes); if(!op->b_o_s) return(0); /* Not the initial packet */ if(oggpack_read(&opb,8) != 1) return 0; /* not an ID header */ memset(buffer,0,6); _v_readstring(&opb,buffer,6); if(memcmp(buffer,"vorbis",6)) return 0; /* not vorbis */ return 1; } return 0; } /* The Vorbis header is in three packets; the initial small packet in the first page that identifies basic parameters, a second packet with bitstream comments and a third packet that holds the codebook. */ int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){ oggpack_buffer opb; if(op){ oggpack_readinit(&opb,op->packet,op->bytes); /* Which of the three types of header is this? */ /* Also verify header-ness, vorbis */ { char buffer[6]; int packtype=oggpack_read(&opb,8); memset(buffer,0,6); _v_readstring(&opb,buffer,6); if(memcmp(buffer,"vorbis",6)){ /* not a vorbis header */ return(OV_ENOTVORBIS); } switch(packtype){ case 0x01: /* least significant *bit* is read first */ if(!op->b_o_s){ /* Not the initial packet */ return(OV_EBADHEADER); } if(vi->rate!=0){ /* previously initialized info header */ return(OV_EBADHEADER); } return(_vorbis_unpack_info(vi,&opb)); case 0x03: /* least significant *bit* is read first */ if(vi->rate==0){ /* um... we didn't get the initial header */ return(OV_EBADHEADER); } return(_vorbis_unpack_comment(vc,&opb)); case 0x05: /* least significant *bit* is read first */ if(vi->rate==0 || vc->vendor==NULL){ /* um... we didn;t get the initial header or comments yet */ return(OV_EBADHEADER); } return(_vorbis_unpack_books(vi,&opb)); default: /* Not a valid vorbis header type */ return(OV_EBADHEADER); break; } } } return(OV_EBADHEADER); } mednafen/settings-common.h000664 001750 001750 00000002545 12611054044 016761 0ustar00sergiosergio000000 000000 #ifndef _MDFN_SETTINGS_COMMON_H #define _MDFN_SETTINGS_COMMON_H #include typedef enum { MDFNST_INT = 0, MDFNST_UINT, MDFNST_BOOL, MDFNST_FLOAT, MDFNST_STRING, MDFNST_ENUM, MDFNST_ALIAS } MDFNSettingType; #define MDFNSF_NOFLAGS 0 #define MDFNSF_CAT_INPUT (1 << 8) #define MDFNSF_CAT_SOUND (1 << 9) #define MDFNSF_CAT_VIDEO (1 << 10) #define MDFNSF_EMU_STATE (1 << 17) #define MDFNSF_UNTRUSTED_SAFE (1 << 18) #define MDFNSF_SUPPRESS_DOC (1 << 19) #define MDFNSF_COMMON_TEMPLATE (1 << 20) #define MDFNSF_REQUIRES_RELOAD (1 << 24) #define MDFNSF_REQUIRES_RESTART (1 << 25) typedef struct { const char *string; int number; const char *description; const char *description_extra; } MDFNSetting_EnumList; typedef struct { const char *name; uint32 flags; const char *description; const char *description_extra; MDFNSettingType type; const char *default_value; const char *minimum; const char *maximum; bool (*validate_func)(const char *name, const char *value); void (*ChangeNotification)(const char *name); const MDFNSetting_EnumList *enum_list; } MDFNSetting; typedef struct __MDFNCS { char *name; char *value; char *game_override; const MDFNSetting *desc; void (*ChangeNotification)(const char *name); uint32_t name_hash; } MDFNCS; #endif mednafen/cdrom/CDAccess_CCD.cpp000664 001750 001750 00000025536 12611054044 017360 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include "../mednafen.h" #include "../general.h" #include "../msvc_compat.h" #include "CDAccess_CCD.h" #include "CDUtility.h" #include #include #include typedef std::map CCD_Section; template static T CCD_ReadInt(CCD_Section &s, const std::string &propname, const bool have_defval = false, const int defval = 0) { const char *vp; char *ep = NULL; int scan_base = 10; size_t scan_offset = 0; long ret = 0; CCD_Section::iterator zit = s.find(propname); if(zit == s.end()) { if(have_defval) return defval; throw MDFN_Error(0, _("Missing property: %s"), propname.c_str()); } const std::string &v = zit->second; if(v.length() >= 3 && v[0] == '0' && v[1] == 'x') { scan_base = 16; scan_offset = 2; } vp = v.c_str() + scan_offset; if(std::numeric_limits::is_signed) ret = strtol(vp, &ep, scan_base); else ret = strtoul(vp, &ep, scan_base); if(!vp[0] || ep[0]) throw MDFN_Error(0, _("Property %s: Malformed integer: %s"), propname.c_str(), v.c_str()); return ret; } CDAccess_CCD::CDAccess_CCD(const char *path, bool image_memcache) : img_stream(NULL), sub_stream(NULL), img_numsectors(0) { try { TOC_Clear(&tocd); Load(path, image_memcache); } catch(...) { Cleanup(); throw; } } void CDAccess_CCD::Load(const char *path, bool image_memcache) { FileStream cf(path, MODE_READ); std::map Sections; std::string linebuf; std::string cur_section_name; std::string dir_path, file_base, file_ext; char img_extsd[4] = { 'i', 'm', 'g', 0 }; char sub_extsd[4] = { 's', 'u', 'b', 0 }; MDFN_GetFilePathComponents(path, &dir_path, &file_base, &file_ext); if(file_ext.length() == 4 && file_ext[0] == '.') { int i; signed char av = -1; signed char extupt[3] = { -1, -1, -1 }; for(i = 1; i < 4; i++) { if(file_ext[i] >= 'A' && file_ext[i] <= 'Z') extupt[i - 1] = 'A' - 'a'; else if(file_ext[i] >= 'a' && file_ext[i] <= 'z') extupt[i - 1] = 0; } for(i = 0; i < 3; i++) { if(extupt[i] != -1) av = extupt[i]; else extupt[i] = av; } if(av == -1) av = 0; for(i = 0; i < 3; i++) { if(extupt[i] == -1) extupt[i] = av; } for(i = 0; i < 3; i++) { img_extsd[i] += extupt[i]; sub_extsd[i] += extupt[i]; } } //printf("%s %d %d %d\n", file_ext.c_str(), extupt[0], extupt[1], extupt[2]); linebuf.reserve(256); while(cf.get_line(linebuf) >= 0) { MDFN_trim(linebuf); if(linebuf.length() == 0) // Skip blank lines. continue; if(linebuf[0] == '[') { if(linebuf.length() < 3 || linebuf[linebuf.length() - 1] != ']') throw MDFN_Error(0, _("Malformed section specifier: %s"), linebuf.c_str()); cur_section_name = linebuf.substr(1, linebuf.length() - 2); MDFN_strtoupper(cur_section_name); } else { std::string k, v; const size_t feqpos = linebuf.find('='); const size_t leqpos = linebuf.rfind('='); if(feqpos == std::string::npos || feqpos != leqpos) throw MDFN_Error(0, _("Malformed value pair specifier: %s"), linebuf.c_str()); k = linebuf.substr(0, feqpos); v = linebuf.substr(feqpos + 1); MDFN_trim(k); MDFN_trim(v); MDFN_strtoupper(k); Sections[cur_section_name][k] = v; } } { unsigned te; CCD_Section &ds = Sections["DISC"]; unsigned toc_entries = CCD_ReadInt(ds, "TOCENTRIES"); unsigned num_sessions = CCD_ReadInt(ds, "SESSIONS"); bool data_tracks_scrambled = CCD_ReadInt(ds, "DATATRACKSSCRAMBLED"); if(num_sessions != 1) throw MDFN_Error(0, _("Unsupported number of sessions: %u"), num_sessions); if(data_tracks_scrambled) throw MDFN_Error(0, _("Scrambled CCD data tracks currently not supported.")); //printf("MOO: %d\n", toc_entries); for(te = 0; te < toc_entries; te++) { char tmpbuf[64]; snprintf(tmpbuf, sizeof(tmpbuf), "ENTRY %u", te); CCD_Section & ts = Sections[std::string(tmpbuf)]; unsigned session = CCD_ReadInt(ts, "SESSION"); uint8_t point = CCD_ReadInt(ts, "POINT"); uint8_t adr = CCD_ReadInt(ts, "ADR"); uint8_t control = CCD_ReadInt(ts, "CONTROL"); uint8_t pmin = CCD_ReadInt(ts, "PMIN"); uint8_t psec = CCD_ReadInt(ts, "PSEC"); uint8_t pframe = CCD_ReadInt(ts, "PFRAME"); signed plba = CCD_ReadInt(ts, "PLBA"); if(session != 1) throw MDFN_Error(0, "Unsupported TOC entry Session value: %u", session); // Reference: ECMA-394, page 5-14 if (point >= 1 && point <= 99) { tocd.tracks[point].adr = adr; tocd.tracks[point].control = control; tocd.tracks[point].lba = plba; } else switch(point) { default: throw MDFN_Error(0, "Unsupported TOC entry Point value: %u", point); case 0xA0: tocd.first_track = pmin; tocd.disc_type = psec; break; case 0xA1: tocd.last_track = pmin; break; case 0xA2: tocd.tracks[100].adr = adr; tocd.tracks[100].control = control; tocd.tracks[100].lba = plba; break; } } } /* Convenience leadout track duplication. */ if(tocd.last_track < 99) tocd.tracks[tocd.last_track + 1] = tocd.tracks[100]; /* Open image stream. */ { std::string image_path = MDFN_EvalFIP(dir_path, file_base + std::string(".") + std::string(img_extsd), true); FileStream *str = new FileStream(image_path.c_str(), MODE_READ); if(image_memcache) img_stream = new MemoryStream(str); else img_stream = str; int64 ss = img_stream->size(); if(ss % 2352) throw MDFN_Error(0, _("CCD image size is not evenly divisible by 2352.")); img_numsectors = ss / 2352; } { /* Open subchannel stream */ std::string sub_path = MDFN_EvalFIP(dir_path, file_base + std::string(".") + std::string(sub_extsd), true); FileStream *str = new FileStream(sub_path.c_str(), MODE_READ); if(image_memcache) sub_stream = new MemoryStream(str); else sub_stream = str; if(sub_stream->size() != (int64)img_numsectors * 96) throw MDFN_Error(0, _("CCD SUB file size mismatch.")); } CheckSubQSanity(); } // // Checks for Q subchannel mode 1(current time) data that has a correct checksum, but the data is nonsensical or corrupted nonetheless; this is the // case for some bad rips floating around on the Internet. Allowing these bad rips to be used will cause all sorts of problems during emulation, so we // error out here if a bad rip is detected. // // This check is not as aggressive or exhaustive as it could be, and will not detect all potential Q subchannel rip errors; as such, it should definitely NOT be // used in an effort to "repair" a broken rip. // void CDAccess_CCD::CheckSubQSanity(void) { size_t s; size_t checksum_pass_counter = 0; int prev_lba = INT_MAX; uint8_t prev_track = 0; for(s = 0; s < img_numsectors; s++) { uint8_t adr; union { uint8 full[96]; struct { uint8 pbuf[12]; uint8 qbuf[12]; }; } buf; sub_stream->seek(s * 96, SEEK_SET); sub_stream->read(buf.full, 96); if(!subq_check_checksum(buf.qbuf)) continue; adr = buf.qbuf[0] & 0xF; if(adr == 0x01) { int lba; uint8_t track; uint8_t track_bcd = buf.qbuf[1]; uint8_t index_bcd = buf.qbuf[2]; uint8_t rm_bcd = buf.qbuf[3]; uint8_t rs_bcd = buf.qbuf[4]; uint8_t rf_bcd = buf.qbuf[5]; uint8_t am_bcd = buf.qbuf[7]; uint8_t as_bcd = buf.qbuf[8]; uint8_t af_bcd = buf.qbuf[9]; //printf("%2x %2x %2x\n", am_bcd, as_bcd, af_bcd); if(!BCD_is_valid(track_bcd) || !BCD_is_valid(index_bcd) || !BCD_is_valid(rm_bcd) || !BCD_is_valid(rs_bcd) || !BCD_is_valid(rf_bcd) || !BCD_is_valid(am_bcd) || !BCD_is_valid(as_bcd) || !BCD_is_valid(af_bcd) || rs_bcd > 0x59 || rf_bcd > 0x74 || as_bcd > 0x59 || af_bcd > 0x74) throw MDFN_Error(0, _("Garbage subchannel Q data detected(bad BCD/out of range): %02x:%02x:%02x %02x:%02x:%02x"), rm_bcd, rs_bcd, rf_bcd, am_bcd, as_bcd, af_bcd); lba = ((BCD_to_U8(am_bcd) * 60 + BCD_to_U8(as_bcd)) * 75 + BCD_to_U8(af_bcd)) - 150; track = BCD_to_U8(track_bcd); prev_lba = lba; if(track < prev_track) throw MDFN_Error(0, _("Garbage subchannel Q data detected(bad track number)")); prev_track = track; checksum_pass_counter++; } } //printf("%u/%u\n", checksum_pass_counter, img_numsectors); } void CDAccess_CCD::Cleanup(void) { if(img_stream) { delete img_stream; img_stream = NULL; } if(sub_stream) { delete sub_stream; sub_stream = NULL; } } CDAccess_CCD::~CDAccess_CCD() { Cleanup(); } void CDAccess_CCD::Read_Raw_Sector(uint8 *buf, int32 lba) { uint8_t sub_buf[96]; if(lba < 0 || (size_t)lba >= img_numsectors) throw(MDFN_Error(0, _("LBA out of range."))); img_stream->seek(lba * 2352, SEEK_SET); img_stream->read(buf, 2352); sub_stream->seek(lba * 96, SEEK_SET); sub_stream->read(sub_buf, 96); subpw_interleave(sub_buf, buf + 2352); } void CDAccess_CCD::Read_TOC(TOC *toc) { *toc = tocd; } void CDAccess_CCD::Eject(bool eject_status) { } libretro-common/include/000700 001750 001750 00000000000 12702525066 016426 5ustar00sergiosergio000000 000000 mednafen/psx/input/memcard.h000664 001750 001750 00000000171 12611054044 017205 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_INPUT_MEMCARD_H #define __MDFN_PSX_INPUT_MEMCARD_H InputDevice *Device_Memcard_Create(void); #endif mednafen/error.cpp000664 001750 001750 00000005472 12611054044 015321 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include "mednafen.h" #include "error.h" #include #include #include "include/trio/trio.h" #include "../libretro.h" extern retro_log_printf_t log_cb; MDFN_Error::MDFN_Error() throw() { abort(); } MDFN_Error::MDFN_Error(int errno_code_new, const char *format, ...) throw() { errno_code = errno_code_new; va_list ap; va_start(ap, format); error_message = trio_vaprintf(format, ap); va_end(ap); log_cb(RETRO_LOG_ERROR, "%s\n", error_message); } MDFN_Error::MDFN_Error(const ErrnoHolder &enh) { errno_code = enh.Errno(); error_message = trio_aprintf("%s", enh.StrError()); } MDFN_Error::~MDFN_Error() throw() { if(error_message) { free(error_message); error_message = NULL; } } MDFN_Error::MDFN_Error(const MDFN_Error &ze_error) throw() { if(ze_error.error_message) error_message = strdup(ze_error.error_message); else error_message = NULL; errno_code = ze_error.errno_code; } MDFN_Error& MDFN_Error::operator=(const MDFN_Error &ze_error) throw() { char *new_error_message = ze_error.error_message ? strdup(ze_error.error_message) : NULL; int new_errno_code = ze_error.errno_code; if(error_message) free(error_message); error_message = new_error_message; errno_code = new_errno_code; return(*this); } const char * MDFN_Error::what(void) const throw() { if(!error_message) return("Error allocating memory for the error message!"); return(error_message); } int MDFN_Error::GetErrno(void) const throw() { return(errno_code); } static const char *srr_wrap(int ret, const char *local_strerror) { if(ret == -1) return("ERROR IN strerror_r()!!!"); return(local_strerror); } static const char *srr_wrap(const char *ret, const char *local_strerror) { if(ret == NULL) return("ERROR IN strerror_r()!!!"); return(ret); } void ErrnoHolder::SetErrno(int the_errno) { local_errno = the_errno; if(the_errno == 0) local_strerror[0] = 0; else { strncpy(local_strerror, strerror(the_errno), 255); local_strerror[255] = 0; } } mednafen/git.h000664 001750 001750 00000030736 12611054044 014421 0ustar00sergiosergio000000 000000 #ifndef _GIT_H #define _GIT_H #include #include "video.h" #include "state.h" #include "settings-common.h" typedef struct { const char *extension; const char *description; } FileExtensionSpecStruct; #include "file.h" enum { MDFN_ROTATE0 = 0, MDFN_ROTATE90, MDFN_ROTATE180, MDFN_ROTATE270 }; typedef enum { VIDSYS_NONE, VIDSYS_PAL, VIDSYS_PAL_M, VIDSYS_NTSC, VIDSYS_SECAM } VideoSystems; typedef enum { GMT_CART, GMT_ARCADE, GMT_DISK, GMT_CDROM, GMT_PLAYER } GameMediumTypes; typedef enum { IDIT_BUTTON, IDIT_BUTTON_CAN_RAPID, IDIT_X_AXIS, IDIT_Y_AXIS, IDIT_X_AXIS_REL, IDIT_Y_AXIS_REL, IDIT_BYTE_SPECIAL, IDIT_BUTTON_ANALOG, IDIT_RUMBLE } InputDeviceInputType; #define IDIT_BUTTON_ANALOG_FLAG_SQLR 0x00000001 typedef struct { const char *SettingName; const char *Name; const int ConfigOrder; const InputDeviceInputType Type; const char *ExcludeName; const char *RotateName[3]; unsigned Flags; } InputDeviceInputInfoStruct; typedef struct { const char *ShortName; const char *FullName; const char *Description; const void *PortExpanderDeviceInfo; int NumInputs; const InputDeviceInputInfoStruct *IDII; } InputDeviceInfoStruct; typedef struct { const char *ShortName; const char *FullName; int NumTypes; InputDeviceInfoStruct *DeviceInfo; const char *DefaultDevice; } InputPortInfoStruct; typedef struct { int InputPorts; const InputPortInfoStruct *Types; } InputInfoStruct; struct MemoryPatch; struct CheatFormatStruct { const char *FullName; const char *Description; bool (*DecodeCheat)(const std::string& cheat_string, MemoryPatch* patch); }; struct CheatFormatInfoStruct { unsigned NumFormats; CheatFormatStruct *Formats; }; enum { MDFN_MSC_RESET = 0x01, MDFN_MSC_POWER = 0x02, MDFN_MSC_INSERT_COIN = 0x07, MDFN_MSC_TOGGLE_DIP0 = 0x10, MDFN_MSC_TOGGLE_DIP1, MDFN_MSC_TOGGLE_DIP2, MDFN_MSC_TOGGLE_DIP3, MDFN_MSC_TOGGLE_DIP4, MDFN_MSC_TOGGLE_DIP5, MDFN_MSC_TOGGLE_DIP6, MDFN_MSC_TOGGLE_DIP7, MDFN_MSC_TOGGLE_DIP8, MDFN_MSC_TOGGLE_DIP9, MDFN_MSC_TOGGLE_DIP10, MDFN_MSC_TOGGLE_DIP11, MDFN_MSC_TOGGLE_DIP12, MDFN_MSC_TOGGLE_DIP13, MDFN_MSC_TOGGLE_DIP14, MDFN_MSC_TOGGLE_DIP15, // n of DISKn translates to is emulation module specific. MDFN_MSC_INSERT_DISK0 = 0x20, MDFN_MSC_INSERT_DISK1, MDFN_MSC_INSERT_DISK2, MDFN_MSC_INSERT_DISK3, MDFN_MSC_INSERT_DISK4, MDFN_MSC_INSERT_DISK5, MDFN_MSC_INSERT_DISK6, MDFN_MSC_INSERT_DISK7, MDFN_MSC_INSERT_DISK8, MDFN_MSC_INSERT_DISK9, MDFN_MSC_INSERT_DISK10, MDFN_MSC_INSERT_DISK11, MDFN_MSC_INSERT_DISK12, MDFN_MSC_INSERT_DISK13, MDFN_MSC_INSERT_DISK14, MDFN_MSC_INSERT_DISK15, MDFN_MSC_INSERT_DISK = 0x30, MDFN_MSC_EJECT_DISK = 0x31, MDFN_MSC_SELECT_DISK = 0x32, MDFN_MSC__LAST = 0x3F }; typedef struct { // Pitch(32-bit) must be equal to width and >= the "fb_width" specified in the MDFNGI struct for the emulated system. // Height must be >= to the "fb_height" specified in the MDFNGI struct for the emulated system. // The framebuffer pointed to by surface->pixels is written to by the system emulation code. MDFN_Surface *surface; // Will be set to TRUE if the video pixel format has changed since the last call to Emulate(), FALSE otherwise. // Will be set to TRUE on the first call to the Emulate() function/method bool VideoFormatChanged; // Set by the system emulation code every frame, to denote the horizontal and vertical offsets of the image, and the size // of the image. If the emulated system sets the elements of LineWidths, then the horizontal offset(x) and width(w) of this structure // are ignored while drawing the image. MDFN_Rect DisplayRect; // Pointer to an array of MDFN_Rect, number of elements = fb_height, set by the driver code. Individual MDFN_Rect structs written // to by system emulation code. If the emulated system doesn't support multiple screen widths per frame, or if you handle // such a situation by outputting at a constant width-per-frame that is the least-common-multiple of the screen widths, then // you can ignore this. If you do wish to use this, you must set all elements every frame. int32_t *LineWidths; // TODO bool *IsFMV; // Set(optionally) by emulation code. If InterlaceOn is true, then assume field height is 1/2 DisplayRect.h, and // only every other line in surface (with the start line defined by InterlacedField) has valid data // (it's up to internal Mednafen code to deinterlace it). bool InterlaceOn; bool InterlaceField; // Skip rendering this frame if true. Set by the driver code. int skip; // // If sound is disabled, the driver code must set SoundRate to false, SoundBuf to NULL, SoundBufMaxSize to 0. // Will be set to TRUE if the sound format(only rate for now, at least) has changed since the last call to Emulate(), FALSE otherwise. // Will be set to TRUE on the first call to the Emulate() function/method bool SoundFormatChanged; // Sound rate. Set by driver side. double SoundRate; // Pointer to sound buffer, set by the driver code, that the emulation code should render sound to. // Guaranteed to be at least 500ms in length, but emulation code really shouldn't exceed 40ms or so. Additionally, if emulation code // generates >= 100ms, // DEPRECATED: Emulation code may set this pointer to a sound buffer internal to the emulation module. int16_t *SoundBuf; // Maximum size of the sound buffer, in frames. Set by the driver code. int32_t SoundBufMaxSize; // Number of frames currently in internal sound buffer. Set by the system emulation code, to be read by the driver code. int32_t SoundBufSize; int32_t SoundBufSizeALMS; // SoundBufSize value at last MidSync(), 0 // if mid sync isn't implemented for the emulation module in use. // Number of cycles that this frame consumed, using MDFNGI::MasterClock as a time base. // Set by emulation code. int64_t MasterCycles; int64_t MasterCyclesALMS; // MasterCycles value at last MidSync(), 0 // if mid sync isn't implemented for the emulation module in use. // Current sound volume(0.000...<=volume<=1.000...). If, after calling Emulate(), it is still != 1, Mednafen will handle it internally. // Emulation modules can handle volume themselves if they like, for speed reasons. If they do, afterwards, they should set its value to 1. double SoundVolume; // Current sound speed multiplier. Set by the driver code. If, after calling Emulate(), it is still != 1, Mednafen will handle it internally // by resampling the audio. This means that emulation modules can handle(and set the value to 1 after handling it) it if they want to get the most // performance possible. HOWEVER, emulation modules must make sure the value is in a range(with minimum and maximum) that their code can handle // before they try to handle it. double soundmultiplier; // True if we want to rewind one frame. Set by the driver code. bool NeedRewind; // Sound reversal during state rewinding is normally done in mednafen.cpp, but // individual system emulation code can also do it if this is set, and clear it after it's done. // (Also, the driver code shouldn't touch this variable) bool NeedSoundReverse; } EmulateSpecStruct; typedef enum { MODPRIO_INTERNAL_EXTRA_LOW = 0, // For "cdplay" module, mostly. MODPRIO_INTERNAL_LOW = 10, MODPRIO_EXTERNAL_LOW = 20, MODPRIO_INTERNAL_HIGH = 30, MODPRIO_EXTERNAL_HIGH = 40 } ModPrio; class CDIF; typedef struct { /* Private functions to Mednafen. Do not call directly from the driver code, or else bad things shall happen. Maybe. Probably not, but don't do it(yet)! */ // Short system name, lowercase a-z, 0-9, and _ are the only allowable characters! const char *shortname; // Full system name. Preferably English letters, but can be UTF8 const char *fullname; // Pointer to an array of FileExtensionSpecStruct, with the last entry being { NULL, NULL } to terminate the list. // This list is used to make best-guess choices, when calling the TestMagic*() functions would be unreasonable, such // as when scanning a ZIP archive for a file to load. The list may also be used in the future for GUI file open windows. const FileExtensionSpecStruct *FileExtensions; ModPrio ModulePriority; void *Debugger; InputInfoStruct *InputInfo; // Returns 1 on successful load, 0 on fatal error(deprecated: -1 on unrecognized format) int (*Load)(const char *name, MDFNFILE *fp); // Return TRUE if the file is a recognized type, FALSE if not. bool (*TestMagic)(const char *name, MDFNFILE *fp); // // (*CDInterfaces).size() is guaranteed to be >= 1. int (*LoadCD)(std::vector *CDInterfaces); bool (*TestMagicCD)(std::vector *CDInterfaces); void (*CloseGame)(void); void (*SetLayerEnableMask)(uint64_t mask); // Video const char *LayerNames; void (*SetChanEnableMask)(uint64_t mask); // Audio(TODO, placeholder) const char *ChanNames; void (*InstallReadPatch)(uint32_t address); void (*RemoveReadPatches)(void); uint8_t (*MemRead)(uint32_t addr); #ifdef WANT_NEW_API CheatFormatInfoStruct *CheatFormatInfo; #endif bool SaveStateAltersState; // true for bsnes and some libco-style emulators, false otherwise. // Main save state routine, called by the save state code in state.cpp. // When saving, load is set to 0. When loading, load is set to the version field of the save state being loaded. // data_only is true when the save state data is temporary, such as being saved into memory for state rewinding. int (*StateAction)(StateMem *sm, int load, int data_only); void (*Emulate)(EmulateSpecStruct *espec); void (*SetInput)(int port, const char *type, void *ptr); void (*DoSimpleCommand)(int cmd); const MDFNSetting *Settings; // Time base for EmulateSpecStruct::MasterCycles #define MDFN_MASTERCLOCK_FIXED(n) ((int64_t)((double)(n) * (INT64_C(1) << 32))) int64_t MasterClock; uint32_t fps; // frames per second * 65536 * 256, truncated // multires is a hint that, if set, indicates that the system has fairly programmable video modes(particularly, the ability // to display multiple horizontal resolutions, such as the PCE, PC-FX, or Genesis). In practice, it will cause the driver // code to set the linear interpolation on by default. // // lcm_width and lcm_height are the least common multiples of all possible // resolutions in the frame buffer as specified by DisplayRect/LineWidths(Ex for PCE: widths of 256, 341.333333, 512, // lcm = 1024) // // nominal_width and nominal_height specify the resolution that Mednafen should display // the framebuffer image in at 1x scaling, scaled from the dimensions of DisplayRect, and optionally the LineWidths array // passed through espec to the Emulate() function. // bool multires; int lcm_width; int lcm_height; void *dummy_separator; // int nominal_width; int nominal_height; int fb_width; // Width of the framebuffer(not necessarily width of the image). MDFN_Surface width should be >= this. int fb_height; // Height of the framebuffer passed to the Emulate() function(not necessarily height of the image) int soundchan; // Number of output sound channels. int rotated; uint8_t *name; /* Game name, UTF8 encoding */ uint8_t MD5[16]; uint8_t GameSetMD5[16]; /* A unique ID for the game set this CD belongs to, only used in PC-FX emulation. */ bool GameSetMD5Valid; /* True if GameSetMD5 is valid. */ uint8_t StateMD5[16]; // ID to use in save state naming and netplay session IDs, if bool StateMD5Valid; // StateMD5Valid is true(useful for systems with multiple BIOS revisions, e.g. PS1). int soundrate; /* For Ogg Vorbis expansion sound wacky support. 0 for default. */ VideoSystems VideoSystem; GameMediumTypes GameType; //int DiskLogicalCount; // A single double-sided disk would be 2 here. //const char *DiskNames; // Null-terminated. const char *cspecial; /* Special cart expansion: DIP switches, barcode reader, etc. */ std::vectorDesiredInput; // Desired input device for the input ports, NULL for don't care // For mouse relative motion. double mouse_sensitivity; // For absolute coordinates(IDIT_X_AXIS and IDIT_Y_AXIS), usually mapped to a mouse(hence the naming). float mouse_scale_x, mouse_scale_y; float mouse_offs_x, mouse_offs_y; } MDFNGI; #endif mednafen/video/Deinterlacer.h000664 001750 001750 00000002762 12611054044 017343 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #ifndef __MDFN_DEINTERLACER_H #define __MDFN_DEINTERLACER_H #include class Deinterlacer { public: Deinterlacer(); ~Deinterlacer(); enum { DEINT_BOB_OFFSET = 0, // Code will fall-through to this case under certain conditions, too. DEINT_BOB, DEINT_WEAVE, }; void SetType(unsigned t); inline unsigned GetType(void) { return(DeintType); } void Process(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32 *LineWidths, const bool field); void ClearState(void); private: template void InternalProcess(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32 *LineWidths, const bool field); MDFN_Surface *FieldBuffer; std::vector LWBuffer; bool StateValid; MDFN_Rect PrevDRect; unsigned DeintType; }; #endif mednafen/psx/input/mouse.cpp000664 001750 001750 00000013425 12611054044 017266 0ustar00sergiosergio000000 000000 #include "../psx.h" #include "../frontio.h" #include "mouse.h" class InputDevice_Mouse : public InputDevice { public: InputDevice_Mouse(); virtual ~InputDevice_Mouse(); virtual void Power(void); virtual int StateAction(StateMem* sm, int load, int data_only, const char* section_name); virtual void UpdateInput(const void *data); virtual void Update(const int32_t timestamp); virtual void ResetTS(void); // // // virtual void SetDTR(bool new_dtr); virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); private: int32 lastts; int32 clear_timeout; bool dtr; uint8 button; uint8 button_post_mask; int32 accum_xdelta; int32 accum_ydelta; int32 command_phase; uint32 bitpos; uint8 receive_buffer; uint8 command; uint8 transmit_buffer[5]; uint32 transmit_pos; uint32 transmit_count; }; InputDevice_Mouse::InputDevice_Mouse() { Power(); } InputDevice_Mouse::~InputDevice_Mouse() { } void InputDevice_Mouse::Update(const int32_t timestamp) { int32 cycles = timestamp - lastts; clear_timeout += cycles; if(clear_timeout >= (33868800 / 4)) { //puts("Mouse timeout\n"); clear_timeout = 0; accum_xdelta = 0; accum_ydelta = 0; button &= button_post_mask; } lastts = timestamp; } void InputDevice_Mouse::ResetTS(void) { lastts = 0; } void InputDevice_Mouse::Power(void) { lastts = 0; clear_timeout = 0; dtr = 0; button = 0; button_post_mask = 0; accum_xdelta = 0; accum_ydelta = 0; command_phase = 0; bitpos = 0; receive_buffer = 0; command = 0; memset(transmit_buffer, 0, sizeof(transmit_buffer)); transmit_pos = 0; transmit_count = 0; } int InputDevice_Mouse::StateAction(StateMem* sm, int load, int data_only, const char* section_name) { SFORMAT StateRegs[] = { SFVAR(clear_timeout), SFVAR(dtr), SFVAR(button), SFVAR(button_post_mask), SFVAR(accum_xdelta), SFVAR(accum_ydelta), SFVAR(command_phase), SFVAR(bitpos), SFVAR(receive_buffer), SFVAR(command), SFARRAY(transmit_buffer, sizeof(transmit_buffer)), SFVAR(transmit_pos), SFVAR(transmit_count), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name); if(load) { if((transmit_pos + transmit_count) > sizeof(transmit_buffer)) { transmit_pos = 0; transmit_count = 0; } } return(ret); } void InputDevice_Mouse::UpdateInput(const void *data) { accum_xdelta += (int32)MDFN_de32lsb((uint8*)data + 0); accum_ydelta += (int32)MDFN_de32lsb((uint8*)data + 4); if(accum_xdelta > 30 * 127) accum_xdelta = 30 * 127; if(accum_xdelta < 30 * -128) accum_xdelta = 30 * -128; if(accum_ydelta > 30 * 127) accum_ydelta = 30 * 127; if(accum_ydelta < 30 * -128) accum_ydelta = 30 * -128; button |= *((uint8 *)data + 8); button_post_mask = *((uint8 *)data + 8); //if(button) // MDFN_DispMessage("Button\n"); //printf("%d %d\n", accum_xdelta, accum_ydelta); } void InputDevice_Mouse::SetDTR(bool new_dtr) { if(!dtr && new_dtr) { command_phase = 0; bitpos = 0; transmit_pos = 0; transmit_count = 0; } else if(dtr && !new_dtr) { //if(bitpos || transmit_count) // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); } dtr = new_dtr; } bool InputDevice_Mouse::Clock(bool TxD, int32 &dsr_pulse_delay) { bool ret = 1; dsr_pulse_delay = 0; if(!dtr) return(1); if(transmit_count) ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; receive_buffer &= ~(1 << bitpos); receive_buffer |= TxD << bitpos; bitpos = (bitpos + 1) & 0x7; if(!bitpos) { //printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase); if(transmit_count) { transmit_pos++; transmit_count--; } switch(command_phase) { case 0: if(receive_buffer != 0x01) command_phase = -1; else { transmit_buffer[0] = 0x12; transmit_pos = 0; transmit_count = 1; command_phase++; } break; case 1: command = receive_buffer; command_phase++; transmit_buffer[0] = 0x5A; if(command == 0x42) { int32 xdelta = accum_xdelta; int32 ydelta = accum_ydelta; if(xdelta < -128) xdelta = -128; if(xdelta > 127) xdelta = 127; if(ydelta < -128) ydelta = -128; if(ydelta > 127) ydelta = 127; transmit_buffer[1] = 0xFF; transmit_buffer[2] = 0xFC ^ (button << 2); transmit_buffer[3] = xdelta; transmit_buffer[4] = ydelta; accum_xdelta -= xdelta; accum_ydelta -= ydelta; button &= button_post_mask; transmit_pos = 0; transmit_count = 5; clear_timeout = 0; } else { command_phase = -1; transmit_pos = 0; transmit_count = 0; } break; } } if(!bitpos && transmit_count) dsr_pulse_delay = 0x40; //0x100; return(ret); } InputDevice *Device_Mouse_Create(void) { return new InputDevice_Mouse(); } InputDeviceInputInfoStruct Device_Mouse_IDII[4] = { { "x_axis", "X Axis", -1, IDIT_X_AXIS_REL }, { "y_axis", "Y Axis", -1, IDIT_Y_AXIS_REL }, { "right", "Right Button", 1, IDIT_BUTTON, NULL }, { "left", "Left Button", 0, IDIT_BUTTON, NULL }, }; mednafen/psx/notes/NOTES000664 001750 001750 00000000310 12611054044 016223 0ustar00sergiosergio000000 000000 Capcom games(MMX4, MMX5, etc) - Sensitive about CD access and XA timing(XA playback problems). Viewpoint - Extra-sensitive about GPU LL DMA timing? (It was generating exceptions for some timings...) mednafen/psx/input/justifier.h000664 001750 001750 00000000273 12611054044 017604 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_INPUT_JUSTIFIER_H #define __MDFN_PSX_INPUT_JUSTIFIER_H InputDevice *Device_Justifier_Create(void); extern InputDeviceInputInfoStruct Device_Justifier_IDII[6]; #endif mednafen/FileStream.cpp000664 001750 001750 00000004377 12611054044 016226 0ustar00sergiosergio000000 000000 // TODO/WIP /* Mednafen - Multi-system Emulator * * 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 */ #include "mednafen.h" #include "Stream.h" #include "FileStream.h" #include #include FileStream::FileStream(const char *path, const int mode): OpenedMode(mode) { fp = retro_fopen(path, (mode == MODE_WRITE) ? RFILE_MODE_WRITE : RFILE_MODE_READ, -1); if (!fp) { ErrnoHolder ene(errno); throw(MDFN_Error(ene.Errno(), "Error opening file %s", ene.StrError())); } original_path = strdup(path); } FileStream::~FileStream() { if (original_path) free(original_path); original_path = NULL; } uint64_t FileStream::attributes(void) { uint64_t ret = ATTRIBUTE_SEEKABLE; switch(OpenedMode) { case MODE_READ: ret |= ATTRIBUTE_READABLE; break; case MODE_WRITE_SAFE: case MODE_WRITE: ret |= ATTRIBUTE_WRITEABLE; break; } return ret; } uint64_t FileStream::read(void *data, uint64_t count, bool error_on_eos) { if (!fp) return 0; return retro_fread(fp, data, count); } void FileStream::write(const void *data, uint64_t count) { if (!fp) return; retro_fwrite(fp, data, count); } void FileStream::seek(int64_t offset, int whence) { if (!fp) return; retro_fseek(fp, offset, whence); } int64_t FileStream::tell(void) { if (!fp) return -1; return retro_ftell(fp); } int64_t FileStream::size(void) { if (!original_path) return -1; return path_get_size(original_path); } void FileStream::close(void) { if (!fp) return; retro_fclose(fp); } mednafen/tremor/mdct.h000664 001750 001750 00000002676 12611054044 016077 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: modified discrete cosine transform prototypes ********************************************************************/ #ifndef _OGG_mdct_H_ #define _OGG_mdct_H_ #include "ivorbiscodec.h" #include "misc.h" #define DATA_TYPE ogg_int32_t #define REG_TYPE register ogg_int32_t #ifdef _LOW_ACCURACY_ #define cPI3_8 (0x0062) #define cPI2_8 (0x00b5) #define cPI1_8 (0x00ed) #else #define cPI3_8 (0x30fbc54d) #define cPI2_8 (0x5a82799a) #define cPI1_8 (0x7641af3d) #endif extern void mdct_forward(int n, DATA_TYPE *in, DATA_TYPE *out); extern void mdct_backward(int n, DATA_TYPE *in, DATA_TYPE *out); #endif README.md000664 001750 001750 00000004366 12611054044 013167 0ustar00sergiosergio000000 000000 # Beetle PSX libretro This is fork of Mednafen PSX. It has been ported to the libretro API. It currently runs on Linux, OSX and possibly Windows. ## Running To run this core, the "system directory" must be defined if running in RetroArch. The PSX BIOS must be placed there, $sysdir/SCPH550{0,1,2} for Japanese, NA and EU regions respectively. Memory cards will be saved to "save directory", memory card #1 is saved using libretro's standard interface. The rest of memory cards are saved using Mednafen's starndard mechanism. You might have to rename your old memory cards to gamename.srm. Alternatively you may just rename it from gamename.gamenamehash.0.mcr to gamename.gamenamehash.1.mcr and load them off the corresponding slot. Core now supports save states. Keep in mind states might result on loss your memorycards if you are careless. ## Loading ISOs Beetle differs from other PS1 emulators in that it needs a cue-sheets that points to an image file, usually an .iso/.bin file. If you have e.g. foo.iso, you should create a foo.cue, and fill this in: FILE "foo.iso" BINARY TRACK 01 MODE1/2352 INDEX 01 00:00:00 After that, you can load the foo.cue file as a ROM. Note that this is a dirty hack and will not work on all games. Ideally, make sure to use rips that have cue-sheets. ## Suggested Firmware - scph5500.bin (8dd7d5296a650fac7319bce665a6a53c) - scph5501.bin (490f666e1afb15b7362b406ed1cea246) - scph5502.bin (32736f17079d0b2b7024407c39bd3050) ## Options * CD Image Cache - Loads the complete image in memory at startup * PSX Dithering - Enables Dithering * PSX Initial Scanline - Sets the first scanline to be drawn on screen * PSX Initial Scanline PAL - Sets the first scanline to be drawn on screen for PAL systems * PSX Last Scanline - Sets the last scanline to be drawn on screen * PSX Last Scanline PAL - Sets the last scanline to be drawn on screen for PAL systems * Dualshock analog toggle - Enables/Disables the analog button from Dualshock controllers, if disabled analogs are always on, if enabled you can toggle it's state with START+SELECT+L1+L2+R1+R2 * Port 1 PSX Enable Multitap - Enables/Disables multitap functionality on port 1 * Port 2 PSX Enable Multitap - Enables/Disables multitap functionality on port 2 mednafen/cdrom/cdromif.cpp000664 001750 001750 00000047046 12611054044 016722 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include "../mednafen.h" #include #include #include "cdromif.h" #include "CDAccess.h" #include "../general.h" #include #include #include "../../libretro.h" extern retro_log_printf_t log_cb; enum { // Status/Error messages CDIF_MSG_DONE = 0, CDIF_MSG_INFO, CDIF_MSG_FATAL_ERROR, // Command messages. CDIF_MSG_DIEDIEDIE, CDIF_MSG_READ_SECTOR, CDIF_MSG_EJECT }; class CDIF_Message { public: CDIF_Message(); CDIF_Message(unsigned int message_, uint32 arg0 = 0, uint32 arg1 = 0, uint32 arg2 = 0, uint32 arg3 = 0); CDIF_Message(unsigned int message_, const std::string &str); ~CDIF_Message(); unsigned int message; uint32 args[4]; void *parg; std::string str_message; }; class CDIF_Queue { public: CDIF_Queue(); ~CDIF_Queue(); bool Read(CDIF_Message *message, bool blocking = TRUE); void Write(const CDIF_Message &message); private: std::queue ze_queue; slock_t *ze_mutex; scond_t *ze_cond; }; typedef struct { bool valid; bool error; uint32 lba; uint8 data[2352 + 96]; } CDIF_Sector_Buffer; /* TODO: prohibit copy constructor */ class CDIF_MT : public CDIF { public: CDIF_MT(CDAccess *cda); virtual ~CDIF_MT(); virtual void HintReadSector(uint32 lba); virtual bool ReadRawSector(uint8 *buf, uint32 lba); virtual bool ReadRawSectorPWOnly(uint8 *buf, uint32 lba, bool hint_fullread); // Return true if operation succeeded or it was a NOP(either due to not being implemented, or the current status matches eject_status). // Returns false on failure(usually drive error of some kind; not completely fatal, can try again). virtual bool Eject(bool eject_status); // FIXME: Semi-private: int ReadThreadStart(void); private: CDAccess *disc_cdaccess; sthread_t *CDReadThread; // Queue for messages to the read thread. CDIF_Queue ReadThreadQueue; // Queue for messages to the emu thread. CDIF_Queue EmuThreadQueue; enum { SBSize = 256 }; CDIF_Sector_Buffer SectorBuffers[SBSize]; uint32 SBWritePos; slock_t *SBMutex; scond_t *SBCond; // // Read-thread-only: // void RT_EjectDisc(bool eject_status, bool skip_actual_eject = false); uint32 ra_lba; int ra_count; uint32 last_read_lba; }; /* TODO: prohibit copy constructor */ class CDIF_ST : public CDIF { public: CDIF_ST(CDAccess *cda); virtual ~CDIF_ST(); virtual void HintReadSector(uint32 lba); virtual bool ReadRawSector(uint8 *buf, uint32 lba); virtual bool ReadRawSectorPWOnly(uint8 *buf, uint32 lba, bool hint_fullread); virtual bool Eject(bool eject_status); private: CDAccess *disc_cdaccess; }; CDIF::CDIF() : UnrecoverableError(false), DiscEjected(false) { TOC_Clear(&disc_toc); } CDIF::~CDIF() { } CDIF_Message::CDIF_Message() { message = 0; memset(args, 0, sizeof(args)); } CDIF_Message::CDIF_Message(unsigned int message_, uint32 arg0, uint32 arg1, uint32 arg2, uint32 arg3) { message = message_; args[0] = arg0; args[1] = arg1; args[2] = arg2; args[3] = arg3; } CDIF_Message::CDIF_Message(unsigned int message_, const std::string &str) { message = message_; str_message = str; } CDIF_Message::~CDIF_Message() { } CDIF_Queue::CDIF_Queue() { ze_mutex = slock_new(); ze_cond = scond_new(); } CDIF_Queue::~CDIF_Queue() { slock_free(ze_mutex); scond_free(ze_cond); } // Returns FALSE if message not read, TRUE if it was read. Will always return TRUE if "blocking" is set. // Will throw MDFN_Error if the read message code is CDIF_MSG_FATAL_ERROR bool CDIF_Queue::Read(CDIF_Message *message, bool blocking) { bool ret = true; slock_lock((slock_t*)ze_mutex); if(blocking) { while(ze_queue.size() == 0) // while, not just if. scond_wait((scond_t*)ze_cond, (slock_t*)ze_mutex); } if(ze_queue.size() == 0) ret = false; else { *message = ze_queue.front(); ze_queue.pop(); } slock_unlock((slock_t*)ze_mutex); if(ret && message->message == CDIF_MSG_FATAL_ERROR) throw MDFN_Error(0, "%s", message->str_message.c_str()); return(ret); } void CDIF_Queue::Write(const CDIF_Message &message) { slock_lock((slock_t*)ze_mutex); ze_queue.push(message); scond_signal((scond_t*)ze_cond); // Signal while the mutex is held to prevent icky race conditions slock_unlock((slock_t*)ze_mutex); } void CDIF_MT::RT_EjectDisc(bool eject_status, bool skip_actual_eject) { int32_t old_de = DiscEjected; DiscEjected = eject_status; if(old_de != DiscEjected) { if(!skip_actual_eject) disc_cdaccess->Eject(eject_status); if(!eject_status) // Re-read the TOC { disc_cdaccess->Read_TOC(&disc_toc); if(disc_toc.first_track < 1 || disc_toc.last_track > 99 || disc_toc.first_track > disc_toc.last_track) throw(MDFN_Error(0, _("TOC first(%d)/last(%d) track numbers bad."), disc_toc.first_track, disc_toc.last_track)); } SBWritePos = 0; ra_lba = 0; ra_count = 0; last_read_lba = ~0U; memset(SectorBuffers, 0, SBSize * sizeof(CDIF_Sector_Buffer)); } } struct RTS_Args { CDIF_MT *cdif_ptr; }; static int ReadThreadStart_C(void *v_arg) { RTS_Args *args = (RTS_Args *)v_arg; return args->cdif_ptr->ReadThreadStart(); } int CDIF_MT::ReadThreadStart() { bool Running = TRUE; DiscEjected = true; SBWritePos = 0; ra_lba = 0; ra_count = 0; last_read_lba = ~0U; try { RT_EjectDisc(false, true); } catch(std::exception &e) { EmuThreadQueue.Write(CDIF_Message(CDIF_MSG_FATAL_ERROR, std::string(e.what()))); return(0); } EmuThreadQueue.Write(CDIF_Message(CDIF_MSG_DONE)); while(Running) { CDIF_Message msg; // Only do a blocking-wait for a message if we don't have any sectors to read-ahead. // MDFN_DispMessage("%d %d %d\n", last_read_lba, ra_lba, ra_count); if(ReadThreadQueue.Read(&msg, ra_count ? FALSE : TRUE)) { switch(msg.message) { case CDIF_MSG_DIEDIEDIE: Running = FALSE; break; case CDIF_MSG_EJECT: try { RT_EjectDisc(msg.args[0]); EmuThreadQueue.Write(CDIF_Message(CDIF_MSG_DONE)); } catch(std::exception &e) { EmuThreadQueue.Write(CDIF_Message(CDIF_MSG_FATAL_ERROR, std::string(e.what()))); } break; case CDIF_MSG_READ_SECTOR: { static const int max_ra = 16; static const int initial_ra = 1; static const int speedmult_ra = 2; uint32_t new_lba = msg.args[0]; assert((unsigned int)max_ra < (SBSize / 4)); if(last_read_lba != ~0U && new_lba == (last_read_lba + 1)) { int how_far_ahead = ra_lba - new_lba; if(how_far_ahead <= max_ra) ra_count = std::min(speedmult_ra, 1 + max_ra - how_far_ahead); else ra_count++; } else if(new_lba != last_read_lba) { ra_lba = new_lba; ra_count = initial_ra; } last_read_lba = new_lba; } break; } } // Don't read >= the "end" of the disc, silly snake. Slither. if(ra_count && ra_lba == disc_toc.tracks[100].lba) { ra_count = 0; //printf("Ephemeral scarabs: %d!\n", ra_lba); } if(ra_count) { uint8_t tmpbuf[2352 + 96]; bool error_condition = false; try { disc_cdaccess->Read_Raw_Sector(tmpbuf, ra_lba); } catch(std::exception &e) { log_cb(RETRO_LOG_ERROR, "Sector %u read error: %s\n", ra_lba, e.what()); memset(tmpbuf, 0, sizeof(tmpbuf)); error_condition = true; } slock_lock((slock_t*)SBMutex); SectorBuffers[SBWritePos].lba = ra_lba; memcpy(SectorBuffers[SBWritePos].data, tmpbuf, 2352 + 96); SectorBuffers[SBWritePos].valid = TRUE; SectorBuffers[SBWritePos].error = error_condition; SBWritePos = (SBWritePos + 1) % SBSize; scond_signal((scond_t*)SBCond); slock_unlock((slock_t*)SBMutex); ra_lba++; ra_count--; } } return(1); } CDIF_MT::CDIF_MT(CDAccess *cda) : disc_cdaccess(cda), CDReadThread(NULL), SBMutex(NULL), SBCond(NULL) { try { CDIF_Message msg; RTS_Args s; SBMutex = slock_new(); SBCond = scond_new(); UnrecoverableError = false; s.cdif_ptr = this; CDReadThread = sthread_create((void (*)(void*))ReadThreadStart_C, &s); EmuThreadQueue.Read(&msg); } catch(...) { if(CDReadThread) { sthread_join((sthread_t*)CDReadThread); CDReadThread = NULL; } if(SBMutex) { slock_free((slock_t*)SBMutex); SBMutex = NULL; } if(SBCond) { scond_free((scond_t*)SBCond); SBCond = NULL; } if(disc_cdaccess) { delete disc_cdaccess; disc_cdaccess = NULL; } throw; } } CDIF_MT::~CDIF_MT() { bool thread_deaded_failed = false; try { ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_DIEDIEDIE)); } catch(std::exception &e) { log_cb(RETRO_LOG_ERROR, "%s.\n", e.what()); thread_deaded_failed = true; } if(!thread_deaded_failed) sthread_join((sthread_t*)CDReadThread); if(SBMutex) { slock_free((slock_t*)SBMutex); SBMutex = NULL; } if(disc_cdaccess) { delete disc_cdaccess; disc_cdaccess = NULL; } } bool CDIF::ValidateRawSector(uint8 *buf) { int mode = buf[12 + 3]; if(mode != 0x1 && mode != 0x2) return(false); if(!edc_lec_check_and_correct(buf, mode == 2)) return(false); return(true); } bool CDIF_MT::ReadRawSector(uint8 *buf, uint32 lba) { bool found = FALSE; bool error_condition = false; if(UnrecoverableError) { memset(buf, 0, 2352 + 96); return(false); } // This shouldn't happen, the emulated-system-specific CDROM emulation code should make sure the emulated program doesn't try // to read past the last "real" sector of the disc. if(lba >= disc_toc.tracks[100].lba) { printf("Attempt to read LBA %d, >= LBA %d\n", lba, disc_toc.tracks[100].lba); return(FALSE); } ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_READ_SECTOR, lba)); slock_lock((slock_t*)SBMutex); do { int i; for(i = 0; i < SBSize; i++) { if(SectorBuffers[i].valid && SectorBuffers[i].lba == lba) { error_condition = SectorBuffers[i].error; memcpy(buf, SectorBuffers[i].data, 2352 + 96); found = TRUE; } } if(!found) scond_wait((scond_t*)SBCond, (slock_t*)SBMutex); } while(!found); slock_unlock((slock_t*)SBMutex); return(!error_condition); } bool CDIF_MT::ReadRawSectorPWOnly(uint8 *buf, uint32 lba, bool hint_fullread) { uint8 tmpbuf[2352 + 96]; bool ret; if(UnrecoverableError) { memset(buf, 0, 96); return(false); } // This shouldn't happen, the emulated-system-specific CDROM emulation code should make sure the emulated program doesn't try // to read past the last "real" sector of the disc. if(lba >= disc_toc.tracks[100].lba) { printf("Attempt to read LBA %d, >= LBA %d\n", lba, disc_toc.tracks[100].lba); memset(buf, 0, 96); return(FALSE); } ret = ReadRawSector(tmpbuf, lba); memcpy(buf, tmpbuf + 2352, 96); return ret; } void CDIF_MT::HintReadSector(uint32 lba) { if(UnrecoverableError) return; ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_READ_SECTOR, lba)); } int CDIF::ReadSector(uint8* pBuf, uint32 lba, uint32 nSectors) { int ret = 0; if(UnrecoverableError) return(false); while(nSectors--) { int mode; uint8_t tmpbuf[2352 + 96]; if(!ReadRawSector(tmpbuf, lba)) { puts("CDIF Raw Read error"); return(FALSE); } if(!ValidateRawSector(tmpbuf)) return(false); mode = tmpbuf[12 + 3]; if(!ret) ret = mode; switch (mode) { case 1: memcpy(pBuf, &tmpbuf[12 + 4], 2048); break; case 2: memcpy(pBuf, &tmpbuf[12 + 4 + 8], 2048); break; default: printf("CDIF_ReadSector() invalid sector type at LBA=%u\n", (unsigned int)lba); return(false); } pBuf += 2048; lba++; } return(ret); } bool CDIF_MT::Eject(bool eject_status) { if(UnrecoverableError) return(false); try { CDIF_Message msg; ReadThreadQueue.Write(CDIF_Message(CDIF_MSG_EJECT, eject_status)); EmuThreadQueue.Read(&msg); } catch(std::exception &e) { log_cb(RETRO_LOG_ERROR, "Error on eject/insert attempt: %s\n", e.what()); return(false); } return(true); } // Single-threaded implementation follows. CDIF_ST::CDIF_ST(CDAccess *cda) : disc_cdaccess(cda) { //puts("***WARNING USING SINGLE-THREADED CD READER***"); UnrecoverableError = false; DiscEjected = false; disc_cdaccess->Read_TOC(&disc_toc); if(disc_toc.first_track < 1 || disc_toc.last_track > 99 || disc_toc.first_track > disc_toc.last_track) throw(MDFN_Error(0, _("TOC first(%d)/last(%d) track numbers bad."), disc_toc.first_track, disc_toc.last_track)); } CDIF_ST::~CDIF_ST() { if(disc_cdaccess) { delete disc_cdaccess; disc_cdaccess = NULL; } } void CDIF_ST::HintReadSector(uint32 lba) { /* TODO: disc_cdaccess seek hint? (probably not, would require asynchronousitycamel) */ } bool CDIF_ST::ReadRawSector(uint8 *buf, uint32 lba) { if(UnrecoverableError) { memset(buf, 0, 2352 + 96); return(false); } try { disc_cdaccess->Read_Raw_Sector(buf, lba); } catch(std::exception &e) { log_cb(RETRO_LOG_ERROR, "Sector %u read error: %s\n", lba, e.what()); memset(buf, 0, 2352 + 96); return(false); } return(true); } bool CDIF_ST::ReadRawSectorPWOnly(uint8 *buf, uint32 lba, bool hint_fullread) { uint8 tmpbuf[2352 + 96]; bool ret; if(UnrecoverableError) { memset(buf, 0, 96); return(false); } // This shouldn't happen, the emulated-system-specific CDROM emulation code should make sure the emulated program doesn't try // to read past the last "real" sector of the disc. if(lba >= disc_toc.tracks[100].lba) { printf("Attempt to read LBA %d, >= LBA %d\n", lba, disc_toc.tracks[100].lba); memset(buf, 0, 96); return(FALSE); } ret = ReadRawSector(tmpbuf, lba); memcpy(buf, tmpbuf + 2352, 96); return ret; } bool CDIF_ST::Eject(bool eject_status) { if(UnrecoverableError) return(false); try { int32_t old_de = DiscEjected; DiscEjected = eject_status; if(old_de != DiscEjected) { disc_cdaccess->Eject(eject_status); if(!eject_status) // Re-read the TOC { disc_cdaccess->Read_TOC(&disc_toc); if(disc_toc.first_track < 1 || disc_toc.last_track > 99 || disc_toc.first_track > disc_toc.last_track) throw(MDFN_Error(0, _("TOC first(%d)/last(%d) track numbers bad."), disc_toc.first_track, disc_toc.last_track)); } } } catch(std::exception &e) { log_cb(RETRO_LOG_ERROR, "%s\n", e.what()); return(false); } return(true); } class CDIF_Stream_Thing : public Stream { public: CDIF_Stream_Thing(CDIF *cdintf_arg, uint32 lba_arg, uint32 sector_count_arg); ~CDIF_Stream_Thing(); virtual uint64 attributes(void); virtual uint8 *map(void); virtual void unmap(void); virtual uint64 read(void *data, uint64 count, bool error_on_eos = true); virtual void write(const void *data, uint64 count); virtual void seek(int64 offset, int whence); virtual int64 tell(void); virtual int64 size(void); virtual void close(void); private: CDIF *cdintf; const uint32 start_lba; const uint32 sector_count; int64 position; }; CDIF_Stream_Thing::CDIF_Stream_Thing(CDIF *cdintf_arg, uint32 start_lba_arg, uint32 sector_count_arg) : cdintf(cdintf_arg), start_lba(start_lba_arg), sector_count(sector_count_arg) { } CDIF_Stream_Thing::~CDIF_Stream_Thing() { } uint64 CDIF_Stream_Thing::attributes(void) { return(ATTRIBUTE_READABLE | ATTRIBUTE_SEEKABLE); } uint8 *CDIF_Stream_Thing::map(void) { return NULL; } void CDIF_Stream_Thing::unmap(void) { } uint64 CDIF_Stream_Thing::read(void *data, uint64 count, bool error_on_eos) { uint64_t rp; if(count > (((uint64)sector_count * 2048) - position)) { if(error_on_eos) throw MDFN_Error(0, "EOF"); count = ((uint64)sector_count * 2048) - position; } if(!count) return(0); for(rp = position; rp < (position + count); rp = (rp &~ 2047) + 2048) { uint8_t buf[2048]; if(!cdintf->ReadSector(buf, start_lba + (rp / 2048), 1)) throw MDFN_Error(ErrnoHolder(EIO)); memcpy((uint8_t*)data + (rp - position), buf + (rp & 2047), std::min(2048 - (rp & 2047),count - (rp - position)) ); } position += count; return count; } void CDIF_Stream_Thing::write(const void *data, uint64 count) { throw MDFN_Error(ErrnoHolder(EBADF)); } void CDIF_Stream_Thing::seek(int64 offset, int whence) { int64 new_position; switch(whence) { case SEEK_SET: new_position = offset; break; case SEEK_CUR: new_position = position + offset; break; case SEEK_END: new_position = ((int64)sector_count * 2048) + offset; break; } if(new_position < 0 || new_position > ((int64)sector_count * 2048)) throw MDFN_Error(ErrnoHolder(EINVAL)); position = new_position; } int64 CDIF_Stream_Thing::tell(void) { return position; } int64 CDIF_Stream_Thing::size(void) { return(sector_count * 2048); } void CDIF_Stream_Thing::close(void) { } Stream *CDIF::MakeStream(uint32 lba, uint32 sector_count) { return new CDIF_Stream_Thing(this, lba, sector_count); } CDIF *CDIF_Open(const char *path, const bool is_device, bool image_memcache) { CDAccess *cda = cdaccess_open_image(path, image_memcache); if(!image_memcache) return new CDIF_MT(cda); return new CDIF_ST(cda); } mednafen/psx/sio.h000664 001750 001750 00000000416 12611054044 015232 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_SIO_H #define __MDFN_PSX_SIO_H #include void SIO_Write(int32_t timestamp, uint32_t A, uint32_t V); uint32_t SIO_Read(int32_t timestamp, uint32_t A); void SIO_Power(void); int SIO_StateAction(void *data, int load, int data_only); #endif mednafen/cdrom/CDAccess.cpp000664 001750 001750 00000002414 12611054044 016675 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include #ifdef _WIN32 #include #else #include #endif #include "../mednafen.h" #include "CDAccess.h" #include "CDAccess_Image.h" #include "CDAccess_CCD.h" CDAccess::CDAccess() { } CDAccess::~CDAccess() { } CDAccess *cdaccess_open_image(const char *path, bool image_memcache) { CDAccess *ret = NULL; if(strlen(path) >= 4 && !strcasecmp(path + strlen(path) - 4, ".ccd")) ret = new CDAccess_CCD(path, image_memcache); else ret = new CDAccess_Image(path, image_memcache); return ret; } mednafen/tremor/mdct.c000664 001750 001750 00000033065 12611054044 016066 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: normalized modified discrete cosine transform power of two length transform only [64 <= n ] last mod: $Id: mdct.c,v 1.9 2002/10/16 09:17:39 xiphmont Exp $ Original algorithm adapted long ago from _The use of multirate filter banks for coding of high quality digital audio_, by T. Sporer, K. Brandenburg and B. Edler, collection of the European Signal Processing Conference (EUSIPCO), Amsterdam, June 1992, Vol.1, pp 211-214 The below code implements an algorithm that no longer looks much like that presented in the paper, but the basic structure remains if you dig deep enough to see it. This module DOES NOT INCLUDE code to generate/apply the window function. Everybody has their own weird favorite including me... I happen to like the properties of y=sin(.5PI*sin^2(x)), but others may vehemently disagree. ********************************************************************/ #include "ivorbiscodec.h" #include "codebook.h" #include "misc.h" #include "mdct.h" #include "mdct_lookup.h" /* 8 point butterfly (in place) */ STIN void mdct_butterfly_8(DATA_TYPE *x){ REG_TYPE r0 = x[4] + x[0]; REG_TYPE r1 = x[4] - x[0]; REG_TYPE r2 = x[5] + x[1]; REG_TYPE r3 = x[5] - x[1]; REG_TYPE r4 = x[6] + x[2]; REG_TYPE r5 = x[6] - x[2]; REG_TYPE r6 = x[7] + x[3]; REG_TYPE r7 = x[7] - x[3]; x[0] = r5 + r3; x[1] = r7 - r1; x[2] = r5 - r3; x[3] = r7 + r1; x[4] = r4 - r0; x[5] = r6 - r2; x[6] = r4 + r0; x[7] = r6 + r2; MB(); } /* 16 point butterfly (in place, 4 register) */ STIN void mdct_butterfly_16(DATA_TYPE *x){ REG_TYPE r0, r1; r0 = x[ 0] - x[ 8]; x[ 8] += x[ 0]; r1 = x[ 1] - x[ 9]; x[ 9] += x[ 1]; x[ 0] = MULT31((r0 + r1) , cPI2_8); x[ 1] = MULT31((r1 - r0) , cPI2_8); MB(); r0 = x[10] - x[ 2]; x[10] += x[ 2]; r1 = x[ 3] - x[11]; x[11] += x[ 3]; x[ 2] = r1; x[ 3] = r0; MB(); r0 = x[12] - x[ 4]; x[12] += x[ 4]; r1 = x[13] - x[ 5]; x[13] += x[ 5]; x[ 4] = MULT31((r0 - r1) , cPI2_8); x[ 5] = MULT31((r0 + r1) , cPI2_8); MB(); r0 = x[14] - x[ 6]; x[14] += x[ 6]; r1 = x[15] - x[ 7]; x[15] += x[ 7]; x[ 6] = r0; x[ 7] = r1; MB(); mdct_butterfly_8(x); mdct_butterfly_8(x+8); } /* 32 point butterfly (in place, 4 register) */ STIN void mdct_butterfly_32(DATA_TYPE *x){ REG_TYPE r0, r1; r0 = x[30] - x[14]; x[30] += x[14]; r1 = x[31] - x[15]; x[31] += x[15]; x[14] = r0; x[15] = r1; MB(); r0 = x[28] - x[12]; x[28] += x[12]; r1 = x[29] - x[13]; x[29] += x[13]; XNPROD31( r0, r1, cPI1_8, cPI3_8, &x[12], &x[13] ); MB(); r0 = x[26] - x[10]; x[26] += x[10]; r1 = x[27] - x[11]; x[27] += x[11]; x[10] = MULT31((r0 - r1) , cPI2_8); x[11] = MULT31((r0 + r1) , cPI2_8); MB(); r0 = x[24] - x[ 8]; x[24] += x[ 8]; r1 = x[25] - x[ 9]; x[25] += x[ 9]; XNPROD31( r0, r1, cPI3_8, cPI1_8, &x[ 8], &x[ 9] ); MB(); r0 = x[22] - x[ 6]; x[22] += x[ 6]; r1 = x[ 7] - x[23]; x[23] += x[ 7]; x[ 6] = r1; x[ 7] = r0; MB(); r0 = x[ 4] - x[20]; x[20] += x[ 4]; r1 = x[ 5] - x[21]; x[21] += x[ 5]; XPROD31 ( r0, r1, cPI3_8, cPI1_8, &x[ 4], &x[ 5] ); MB(); r0 = x[ 2] - x[18]; x[18] += x[ 2]; r1 = x[ 3] - x[19]; x[19] += x[ 3]; x[ 2] = MULT31((r1 + r0) , cPI2_8); x[ 3] = MULT31((r1 - r0) , cPI2_8); MB(); r0 = x[ 0] - x[16]; x[16] += x[ 0]; r1 = x[ 1] - x[17]; x[17] += x[ 1]; XPROD31 ( r0, r1, cPI1_8, cPI3_8, &x[ 0], &x[ 1] ); MB(); mdct_butterfly_16(x); mdct_butterfly_16(x+16); } /* N/stage point generic N stage butterfly (in place, 2 register) */ STIN void mdct_butterfly_generic(DATA_TYPE *x,int points,int step){ LOOKUP_T *T = sincos_lookup0; DATA_TYPE *x1 = x + points - 8; DATA_TYPE *x2 = x + (points>>1) - 8; REG_TYPE r0; REG_TYPE r1; do{ r0 = x1[6] - x2[6]; x1[6] += x2[6]; r1 = x2[7] - x1[7]; x1[7] += x2[7]; XPROD31( r1, r0, T[0], T[1], &x2[6], &x2[7] ); T+=step; r0 = x1[4] - x2[4]; x1[4] += x2[4]; r1 = x2[5] - x1[5]; x1[5] += x2[5]; XPROD31( r1, r0, T[0], T[1], &x2[4], &x2[5] ); T+=step; r0 = x1[2] - x2[2]; x1[2] += x2[2]; r1 = x2[3] - x1[3]; x1[3] += x2[3]; XPROD31( r1, r0, T[0], T[1], &x2[2], &x2[3] ); T+=step; r0 = x1[0] - x2[0]; x1[0] += x2[0]; r1 = x2[1] - x1[1]; x1[1] += x2[1]; XPROD31( r1, r0, T[0], T[1], &x2[0], &x2[1] ); T+=step; x1-=8; x2-=8; }while(Tsincos_lookup0); do{ r0 = x2[6] - x1[6]; x1[6] += x2[6]; r1 = x2[7] - x1[7]; x1[7] += x2[7]; XPROD31( r0, r1, T[0], T[1], &x2[6], &x2[7] ); T+=step; r0 = x2[4] - x1[4]; x1[4] += x2[4]; r1 = x2[5] - x1[5]; x1[5] += x2[5]; XPROD31( r0, r1, T[0], T[1], &x2[4], &x2[5] ); T+=step; r0 = x2[2] - x1[2]; x1[2] += x2[2]; r1 = x2[3] - x1[3]; x1[3] += x2[3]; XPROD31( r0, r1, T[0], T[1], &x2[2], &x2[3] ); T+=step; r0 = x2[0] - x1[0]; x1[0] += x2[0]; r1 = x2[1] - x1[1]; x1[1] += x2[1]; XPROD31( r0, r1, T[0], T[1], &x2[0], &x2[1] ); T+=step; x1-=8; x2-=8; }while(Tsincos_lookup0); } STIN void mdct_butterflies(DATA_TYPE *x,int points,int shift){ int stages=8-shift; int i,j; for(i=0;--stages>0;i++){ for(j=0;j<(1<>i)*j,points>>i,4<<(i+shift)); } for(j=0;j>8]|(bitrev[(x&0x0f0)>>4]<<4)|(((int)bitrev[x&0x00f])<<8); } STIN void mdct_bitreverse(DATA_TYPE *x,int n,int step,int shift){ int bit = 0; DATA_TYPE *w0 = x; DATA_TYPE *w1 = x = w0+(n>>1); LOOKUP_T *T = (step>=4)?(sincos_lookup0+(step>>1)):sincos_lookup1; LOOKUP_T *Ttop = T+1024; DATA_TYPE r2; do{ DATA_TYPE r3 = bitrev12(bit++); DATA_TYPE *x0 = x + ((r3 ^ 0xfff)>>shift) -1; DATA_TYPE *x1 = x + (r3>>shift); REG_TYPE r0 = x0[0] + x1[0]; REG_TYPE r1 = x1[1] - x0[1]; XPROD32( r0, r1, T[1], T[0], &r2, &r3 ); T+=step; w1 -= 4; r0 = (x0[1] + x1[1])>>1; r1 = (x0[0] - x1[0])>>1; w0[0] = r0 + r2; w0[1] = r1 + r3; w1[2] = r0 - r2; w1[3] = r3 - r1; r3 = bitrev12(bit++); x0 = x + ((r3 ^ 0xfff)>>shift) -1; x1 = x + (r3>>shift); r0 = x0[0] + x1[0]; r1 = x1[1] - x0[1]; XPROD32( r0, r1, T[1], T[0], &r2, &r3 ); T+=step; r0 = (x0[1] + x1[1])>>1; r1 = (x0[0] - x1[0])>>1; w0[2] = r0 + r2; w0[3] = r1 + r3; w1[0] = r0 - r2; w1[1] = r3 - r1; w0 += 4; }while(T>shift) -1; DATA_TYPE *x1 = x + (r3>>shift); REG_TYPE r0 = x0[0] + x1[0]; REG_TYPE r1 = x1[1] - x0[1]; T-=step; XPROD32( r0, r1, T[0], T[1], &r2, &r3 ); w1 -= 4; r0 = (x0[1] + x1[1])>>1; r1 = (x0[0] - x1[0])>>1; w0[0] = r0 + r2; w0[1] = r1 + r3; w1[2] = r0 - r2; w1[3] = r3 - r1; r3 = bitrev12(bit++); x0 = x + ((r3 ^ 0xfff)>>shift) -1; x1 = x + (r3>>shift); r0 = x0[0] + x1[0]; r1 = x1[1] - x0[1]; T-=step; XPROD32( r0, r1, T[0], T[1], &r2, &r3 ); r0 = (x0[1] + x1[1])>>1; r1 = (x0[0] - x1[0])>>1; w0[2] = r0 + r2; w0[3] = r1 + r3; w1[0] = r0 - r2; w1[1] = r3 - r1; w0 += 4; }while(w0>1; int n4=n>>2; DATA_TYPE *iX; DATA_TYPE *oX; LOOKUP_T *T; LOOKUP_T *V; int shift; int step; for (shift=6;!(n&(1<=in+n4); do{ oX-=4; XPROD31( iX[4], iX[6], T[1], T[0], &oX[2], &oX[3] ); T-=step; XPROD31( iX[0], iX[2], T[1], T[0], &oX[0], &oX[1] ); T-=step; iX-=8; }while(iX>=in); iX = in+n2-8; oX = out+n2+n4; T = sincos_lookup0; do{ T+=step; XNPROD31( iX[6], iX[4], T[0], T[1], &oX[0], &oX[1] ); T+=step; XNPROD31( iX[2], iX[0], T[0], T[1], &oX[2], &oX[3] ); iX-=8; oX+=4; }while(iX>=in+n4); do{ T-=step; XNPROD31( iX[6], iX[4], T[1], T[0], &oX[0], &oX[1] ); T-=step; XNPROD31( iX[2], iX[0], T[1], T[0], &oX[2], &oX[3] ); iX-=8; oX+=4; }while(iX>=in); mdct_butterflies(out+n2,n2,shift); mdct_bitreverse(out,n,step,shift); /* rotate + window */ step>>=2; { DATA_TYPE *oX1=out+n2+n4; DATA_TYPE *oX2=out+n2+n4; DATA_TYPE *iX =out; switch(step) { default: { T=(step>=4)?(sincos_lookup0+(step>>1)):sincos_lookup1; do{ oX1-=4; XPROD31( iX[0], -iX[1], T[0], T[1], &oX1[3], &oX2[0] ); T+=step; XPROD31( iX[2], -iX[3], T[0], T[1], &oX1[2], &oX2[1] ); T+=step; XPROD31( iX[4], -iX[5], T[0], T[1], &oX1[1], &oX2[2] ); T+=step; XPROD31( iX[6], -iX[7], T[0], T[1], &oX1[0], &oX2[3] ); T+=step; oX2+=4; iX+=8; }while(iX>1; t1 = (*T++)>>1; do{ oX1-=4; t0 += (v0 = (*V++)>>1); t1 += (v1 = (*V++)>>1); XPROD31( iX[0], -iX[1], t0, t1, &oX1[3], &oX2[0] ); v0 += (t0 = (*T++)>>1); v1 += (t1 = (*T++)>>1); XPROD31( iX[2], -iX[3], v0, v1, &oX1[2], &oX2[1] ); t0 += (v0 = (*V++)>>1); t1 += (v1 = (*V++)>>1); XPROD31( iX[4], -iX[5], t0, t1, &oX1[1], &oX2[2] ); v0 += (t0 = (*T++)>>1); v1 += (t1 = (*T++)>>1); XPROD31( iX[6], -iX[7], v0, v1, &oX1[0], &oX2[3] ); oX2+=4; iX+=8; }while(iX>2); t1 += (q1 = (v1-t1)>>2); XPROD31( iX[0], -iX[1], t0, t1, &oX1[3], &oX2[0] ); t0 = v0-q0; t1 = v1-q1; XPROD31( iX[2], -iX[3], t0, t1, &oX1[2], &oX2[1] ); t0 = *T++; t1 = *T++; v0 += (q0 = (t0-v0)>>2); v1 += (q1 = (t1-v1)>>2); XPROD31( iX[4], -iX[5], v0, v1, &oX1[1], &oX2[2] ); v0 = t0-q0; v1 = t1-q1; XPROD31( iX[6], -iX[7], v0, v1, &oX1[0], &oX2[3] ); oX2+=4; iX+=8; }while(iXoX2); } } mednafen/psx/gte.cpp000664 001750 001750 00000103065 12611054044 015556 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include "psx.h" #include "gte.h" #include "../clamp.h" /* Notes: AVSZ3/AVSZ4: OTZ is MAC0 >> 12 OTZ overflow/underflow flag is set in an overflow condition even if MAC0 == 0. sf field bit has no effect? FLAG register: Bits present mask: 0xfffff000 Checksum bit can't be directly set, it's apparently calculated like (bool)(FLAGS & 0x7f87e000) Instructions effectively clear it 0 at start. (todo: test "invalid" instructions) X/Y FIFO [3] register write pushes a copy down to [2] */ typedef struct { int16_t MX[3][3]; int16_t dummy; } #ifndef _MSC_VER __attribute__((__packed__)) #endif gtematrix; typedef struct { union { struct { uint8_t R; uint8_t G; uint8_t B; uint8_t CD; }; uint8_t Raw8[4]; }; } gtergb; typedef struct { int16_t X; int16_t Y; } gtexy; static uint32_t CR[32]; static uint32_t FLAGS; // Temporary for instruction execution, copied into CR[31] at end of instruction execution. typedef union { gtematrix All[4]; int32_t Raw[4][5]; // Don't read from this(Raw[][]), only write(and when writing, if running on a big-endian platform, swap the upper 16-bits with the lower 16-bits) int16_t Raw16[4][10]; struct { gtematrix Rot; gtematrix Light; gtematrix Color; gtematrix AbbyNormal; }; } Matrices_t; static Matrices_t Matrices; static union { int32_t All[4][4]; // Really only [4][3], but [4] to ease address calculation. struct { int32_t T[4]; int32_t B[4]; int32_t FC[4]; int32_t Null[4]; }; } CRVectors; static int32_t OFX; static int32_t OFY; static uint16_t H; static int16_t DQA; static int32_t DQB; static int16_t ZSF3; static int16_t ZSF4; // Begin DR static int16_t Vectors[3][4]; static gtergb RGB; static uint16_t OTZ; static int16_t IR[4]; #define IR0 IR[0] #define IR1 IR[1] #define IR2 IR[2] #define IR3 IR[3] static gtexy XY_FIFO[4]; static uint16_t Z_FIFO[4]; static gtergb RGB_FIFO[3]; static int32_t MAC[4]; static uint32_t LZCS; static uint32_t LZCR; static uint32_t Reg23; // end DR extern unsigned char widescreen_hack; static INLINE uint8_t Sat5(int16_t cc) { if(cc < 0) cc = 0; if(cc > 0x1F) cc = 0x1F; return(cc); } // // Newton-Raphson division table. (Initialized at startup; do NOT save in save states!) // static uint8_t DivTable[0x100 + 1]; static INLINE int32_t CalcRecip(uint16 divisor) { int32_t x = (0x101 + DivTable[(((divisor & 0x7FFF) + 0x40) >> 7)]); int32_t tmp = (((int32_t)divisor * -x) + 0x80) >> 8; int32_t tmp2 = ((x * (131072 + tmp)) + 0x80) >> 8; return(tmp2); } void GTE_Init(void) { uint32_t divisor; for(divisor = 0x8000; divisor < 0x10000; divisor += 0x80) { unsigned i; uint32_t xa = 512; for(i = 1; i < 5; i++) xa = (xa * (1024 * 512 - ((divisor >> 7) * xa))) >> 18; DivTable[(divisor >> 7) & 0xFF] = ((xa + 1) >> 1) - 0x101; //printf("%04x, %02x\n", divisor, ((xa + 1) >> 1) - 0x101); } // To avoid a bounds limiting if statement in the emulation code: DivTable[0x100] = DivTable[0xFF]; } void GTE_Power(void) { memset(CR, 0, sizeof(CR)); //memset(DR, 0, sizeof(DR)); memset(Matrices.All, 0, sizeof(Matrices.All)); memset(CRVectors.All, 0, sizeof(CRVectors.All)); OFX = 0; OFY = 0; H = 0; DQA = 0; DQB = 0; ZSF3 = 0; ZSF4 = 0; memset(Vectors, 0, sizeof(Vectors)); memset(&RGB, 0, sizeof(RGB)); OTZ = 0; IR0 = 0; IR1 = 0; IR2 = 0; IR3 = 0; memset(XY_FIFO, 0, sizeof(XY_FIFO)); memset(Z_FIFO, 0, sizeof(Z_FIFO)); memset(RGB_FIFO, 0, sizeof(RGB_FIFO)); memset(MAC, 0, sizeof(MAC)); LZCS = 0; LZCR = 0; Reg23 = 0; } // TODO: Don't save redundant state, regarding CR cache variables int GTE_StateAction(StateMem *sm, int load, int data_only) { SFORMAT StateRegs[] = { { CR, (uint32_t)(32 * sizeof(uint32_t)), MDFNSTATE_RLSB32 | 0, "CR" }, { &FLAGS, sizeof(FLAGS), MDFNSTATE_RLSB | 0, "FLAGS" }, SFARRAY16(&Matrices.Raw16[0][0], 4 * 10), SFARRAY32(&CRVectors.All[0][0], 4 * 4), SFVARN(OFX, "OFX"), SFVARN(OFY, "OFY"), SFVARN(H, "H"), SFVARN(DQA, "DQA"), SFVARN(DQB, "DQB"), SFVARN(ZSF3, "ZSF3"), SFVARN(ZSF4, "ZSF4"), SFARRAY16(&Vectors[0][0], 3 * 4), SFARRAY(RGB.Raw8, 4), SFVARN(OTZ, "OTZ"), SFARRAY16(IR, 4), SFVAR(XY_FIFO[0].X), SFVAR(XY_FIFO[0].Y), SFVAR(XY_FIFO[1].X), SFVAR(XY_FIFO[1].Y), SFVAR(XY_FIFO[2].X), SFVAR(XY_FIFO[2].Y), SFVAR(XY_FIFO[3].X), SFVAR(XY_FIFO[3].Y), SFARRAY16(Z_FIFO, 4), SFARRAY(RGB_FIFO[0].Raw8, 4), SFARRAY(RGB_FIFO[1].Raw8, 4), SFARRAY(RGB_FIFO[2].Raw8, 4), SFARRAY32(MAC, 4), SFVARN(LZCS, "LZCS"), SFVARN(LZCR, "LZCR"), SFVARN(Reg23, "Reg23"), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "GTE"); if(load) { } return(ret); } void GTE_WriteCR(unsigned int which, uint32_t value) { static const uint32_t mask_table[32] = { /* 0x00 */ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, /* 0x08 */ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, /* 0x10 */ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, /* 0x18 */ 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0x0000FFFF, 0xFFFFFFFF, 0x0000FFFF, 0x0000FFFF, 0xFFFFFFFF }; //PSX_WARNING("[GTE] Write CR %d, 0x%08x", which, value); value &= mask_table[which]; CR[which] = value | (CR[which] & ~mask_table[which]); if(which < 24) { int we = which >> 3; which &= 0x7; if(which >= 5) CRVectors.All[we][which - 5] = value; else { #ifdef MSB_FIRST Matrices.Raw[we][which] = (value << 16) | (value >> 16); #else Matrices.Raw[we][which] = value; #endif } return; } switch(which) { case 24: OFX = value; break; case 25: OFY = value; break; case 26: H = value; break; case 27: DQA = value; break; case 28: DQB = value; break; case 29: ZSF3 = value; break; case 30: ZSF4 = value; break; case 31: CR[31] = (value & 0x7ffff000) | ((value & 0x7f87e000) ? (1 << 31) : 0); break; } } uint32_t GTE_ReadCR(unsigned int which) { uint32_t ret = 0; switch(which) { default: ret = CR[which]; if(which == 4 || which == 12 || which == 20) ret = (int16)ret; break; case 24: ret = OFX; break; case 25: ret = OFY; break; case 26: ret = (int16)H; break; case 27: ret = (int16)DQA; break; case 28: ret = DQB; break; case 29: ret = (int16)ZSF3; break; case 30: ret = (int16)ZSF4; break; case 31: ret = CR[31]; break; } return(ret); } void GTE_WriteDR(unsigned int which, uint32_t value) { switch(which & 0x1F) { case 0: Vectors[0][0] = value; Vectors[0][1] = value >> 16; break; case 1: Vectors[0][2] = value; break; case 2: Vectors[1][0] = value; Vectors[1][1] = value >> 16; break; case 3: Vectors[1][2] = value; break; case 4: Vectors[2][0] = value; Vectors[2][1] = value >> 16; break; case 5: Vectors[2][2] = value; break; case 6: RGB.R = value >> 0; RGB.G = value >> 8; RGB.B = value >> 16; RGB.CD = value >> 24; break; case 7: OTZ = value; break; case 8: IR0 = value; break; case 9: IR1 = value; break; case 10: IR2 = value; break; case 11: IR3 = value; break; case 12: XY_FIFO[0].X = value; XY_FIFO[0].Y = value >> 16; break; case 13: XY_FIFO[1].X = value; XY_FIFO[1].Y = value >> 16; break; case 14: XY_FIFO[2].X = value; XY_FIFO[2].Y = value >> 16; XY_FIFO[3].X = value; XY_FIFO[3].Y = value >> 16; break; case 15: XY_FIFO[3].X = value; XY_FIFO[3].Y = value >> 16; XY_FIFO[0] = XY_FIFO[1]; XY_FIFO[1] = XY_FIFO[2]; XY_FIFO[2] = XY_FIFO[3]; break; case 16: Z_FIFO[0] = value; break; case 17: Z_FIFO[1] = value; break; case 18: Z_FIFO[2] = value; break; case 19: Z_FIFO[3] = value; break; case 20: RGB_FIFO[0].R = value; RGB_FIFO[0].G = value >> 8; RGB_FIFO[0].B = value >> 16; RGB_FIFO[0].CD = value >> 24; break; case 21: RGB_FIFO[1].R = value; RGB_FIFO[1].G = value >> 8; RGB_FIFO[1].B = value >> 16; RGB_FIFO[1].CD = value >> 24; break; case 22: RGB_FIFO[2].R = value; RGB_FIFO[2].G = value >> 8; RGB_FIFO[2].B = value >> 16; RGB_FIFO[2].CD = value >> 24; break; case 23: Reg23 = value; break; case 24: MAC[0] = value; break; case 25: MAC[1] = value; break; case 26: MAC[2] = value; break; case 27: MAC[3] = value; break; case 28: IR1 = ((value >> 0) & 0x1F) << 7; IR2 = ((value >> 5) & 0x1F) << 7; IR3 = ((value >> 10) & 0x1F) << 7; break; case 29: // Read-only break; case 30: LZCS = value; { uint32_t test = value & 0x80000000; LZCR = 0; while((value & 0x80000000) == test && LZCR < 32) { LZCR++; value <<= 1; } } break; case 31: // Read-only break; } } uint32_t GTE_ReadDR(unsigned int which) { uint32_t ret = 0; switch(which & 0x1F) { case 0: ret = (uint16_t)Vectors[0][0] | ((uint16_t)Vectors[0][1] << 16); break; case 1: ret = (int16_t)Vectors[0][2]; break; case 2: ret = (uint16_t)Vectors[1][0] | ((uint16_t)Vectors[1][1] << 16); break; case 3: ret = (int16_t)Vectors[1][2]; break; case 4: ret = (uint16_t)Vectors[2][0] | ((uint16_t)Vectors[2][1] << 16); break; case 5: ret = (int16_t)Vectors[2][2]; break; case 6: ret = RGB.R | (RGB.G << 8) | (RGB.B << 16) | (RGB.CD << 24); break; case 7: ret = (uint16_t)OTZ; break; case 8: ret = (int16_t)IR0; break; case 9: ret = (int16_t)IR1; break; case 10: ret = (int16_t)IR2; break; case 11: ret = (int16_t)IR3; break; case 12: ret = (uint16_t)XY_FIFO[0].X | ((uint16_t)XY_FIFO[0].Y << 16); break; case 13: ret = (uint16_t)XY_FIFO[1].X | ((uint16_t)XY_FIFO[1].Y << 16); break; case 14: ret = (uint16_t)XY_FIFO[2].X | ((uint16_t)XY_FIFO[2].Y << 16); break; case 15: ret = (uint16_t)XY_FIFO[3].X | ((uint16_t)XY_FIFO[3].Y << 16); break; case 16: ret = (uint16_t)Z_FIFO[0]; break; case 17: ret = (uint16_t)Z_FIFO[1]; break; case 18: ret = (uint16_t)Z_FIFO[2]; break; case 19: ret = (uint16_t)Z_FIFO[3]; break; case 20: ret = RGB_FIFO[0].R | (RGB_FIFO[0].G << 8) | (RGB_FIFO[0].B << 16) | (RGB_FIFO[0].CD << 24); break; case 21: ret = RGB_FIFO[1].R | (RGB_FIFO[1].G << 8) | (RGB_FIFO[1].B << 16) | (RGB_FIFO[1].CD << 24); break; case 22: ret = RGB_FIFO[2].R | (RGB_FIFO[2].G << 8) | (RGB_FIFO[2].B << 16) | (RGB_FIFO[2].CD << 24); break; case 23: ret = Reg23; break; case 24: ret = MAC[0]; break; case 25: ret = MAC[1]; break; case 26: ret = MAC[2]; break; case 27: ret = MAC[3]; break; case 28: case 29: ret = Sat5(IR1 >> 7) | (Sat5(IR2 >> 7) << 5) | (Sat5(IR3 >> 7) << 10); break; case 30: ret = LZCS; break; case 31: ret = LZCR; break; } return(ret); } #define sign_x_to_s64(_bits, _value) (((int64_t)((uint64_t)(_value) << (64 - _bits))) >> (64 - _bits)) static INLINE int64_t A_MV(unsigned which, int64_t value) { if(value >= (INT64_C(1) << 43)) FLAGS |= 1 << (30 - which); if(value < -(INT64_C(1) << 43)) FLAGS |= 1 << (27 - which); return sign_x_to_s64(44, value); } static INLINE int64_t F(int64_t value) { if(value < -2147483648LL) { // flag set here FLAGS |= 1 << 15; } if(value > 2147483647LL) { // flag set here FLAGS |= 1 << 16; } return(value); } static INLINE int16_t Lm_B(unsigned int which, int32_t value, int lm) { int32_t tmp = lm << 15; if(value < (-32768 + tmp)) { // set flag here FLAGS |= 1 << (24 - which); value = -32768 + tmp; } if(value > 32767) { // Set flag here FLAGS |= 1 << (24 - which); value = 32767; } return(value); } static INLINE int16_t Lm_B_PTZ(unsigned int which, int32_t value, int32_t ftv_value, int lm) { int32_t tmp = lm << 15; if(ftv_value < -32768) FLAGS |= 1 << (24 - which); if(ftv_value > 32767) FLAGS |= 1 << (24 - which); clamp(&value, (-32768 + tmp), 32767); return(value); } static INLINE uint8_t Lm_C(unsigned int which, int32_t value) { if(value & ~0xFF) { // Set flag here FLAGS |= 1 << (21 - which); // Tested with GPF if(value < 0) value = 0; if(value > 255) value = 255; } return(value); } static INLINE int32_t Lm_D(int32_t value, int unchained) { // Not sure if we should have it as int64, or just chain on to and special case when the F flags are set. if(!unchained) { if(FLAGS & (1 << 15)) { FLAGS |= 1 << 18; return(0); } if(FLAGS & (1 << 16)) { FLAGS |= 1 << 18; return(0xFFFF); } } if(value < 0) { // Set flag here value = 0; FLAGS |= 1 << 18; // Tested with AVSZ3 } else if(value > 65535) { // Set flag here. value = 65535; FLAGS |= 1 << 18; // Tested with AVSZ3 } return(value); } static INLINE int32_t Lm_G(unsigned int which, int32_t value) { if(value < -1024) { // Set flag here value = -1024; FLAGS |= 1 << (14 - which); } if(value > 1023) { // Set flag here. value = 1023; FLAGS |= 1 << (14 - which); } return(value); } // limit to 4096, not 4095 static INLINE int32_t Lm_H(int32_t value) { if(value < 0) { value = 0; FLAGS |= 1 << 12; } if(value > 4096) { value = 4096; FLAGS |= 1 << 12; } return(value); } static INLINE void MAC_to_RGB_FIFO(void) { RGB_FIFO[0] = RGB_FIFO[1]; RGB_FIFO[1] = RGB_FIFO[2]; RGB_FIFO[2].R = Lm_C(0, MAC[1] >> 4); RGB_FIFO[2].G = Lm_C(1, MAC[2] >> 4); RGB_FIFO[2].B = Lm_C(2, MAC[3] >> 4); RGB_FIFO[2].CD = RGB.CD; } static INLINE void MAC_to_IR(int lm) { IR1 = Lm_B(0, MAC[1], lm); IR2 = Lm_B(1, MAC[2], lm); IR3 = Lm_B(2, MAC[3], lm); } static INLINE void MultiplyMatrixByVector(const gtematrix *matrix, const int16_t *v, const int32_t *crv, uint32_t sf, int lm) { unsigned i; for(i = 0; i < 3; i++) { int64_t tmp; int32_t mulr[3]; tmp = (uint64_t)(int64_t)crv[i] << 12; if(matrix == &Matrices.AbbyNormal) { if(i == 0) { mulr[0] = -(RGB.R << 4); mulr[1] = (RGB.R << 4); mulr[2] = IR0; } else { mulr[0] = (int16_t)CR[i]; mulr[1] = (int16_t)CR[i]; mulr[2] = (int16_t)CR[i]; } } else { mulr[0] = matrix->MX[i][0]; mulr[1] = matrix->MX[i][1]; mulr[2] = matrix->MX[i][2]; } mulr[0] *= v[0]; mulr[1] *= v[1]; mulr[2] *= v[2]; tmp = A_MV(i, tmp + mulr[0]); if(crv == CRVectors.FC) { Lm_B(i, tmp >> sf, FALSE); tmp = 0; } tmp = A_MV(i, tmp + mulr[1]); tmp = A_MV(i, tmp + mulr[2]); MAC[1 + i] = tmp >> sf; } MAC_to_IR(lm); } static INLINE void MultiplyMatrixByVector_PT(const gtematrix *matrix, const int16_t *v, const int32_t *crv, uint32_t sf, int lm) { int64_t tmp[3]; unsigned i; for(i = 0; i < 3; i++) { int32_t mulr[3]; tmp[i] = (uint64_t)(int64_t)crv[i] << 12; mulr[0] = matrix->MX[i][0] * v[0]; mulr[1] = matrix->MX[i][1] * v[1]; mulr[2] = matrix->MX[i][2] * v[2]; tmp[i] = A_MV(i, tmp[i] + mulr[0]); tmp[i] = A_MV(i, tmp[i] + mulr[1]); tmp[i] = A_MV(i, tmp[i] + mulr[2]); MAC[1 + i] = tmp[i] >> sf; } IR1 = Lm_B(0, MAC[1], lm); IR2 = Lm_B(1, MAC[2], lm); //printf("FTV: %08x %08x\n", crv[2], (uint32)(tmp[2] >> 12)); IR3 = Lm_B_PTZ(2, MAC[3], tmp[2] >> 12, lm); Z_FIFO[0] = Z_FIFO[1]; Z_FIFO[1] = Z_FIFO[2]; Z_FIFO[2] = Z_FIFO[3]; Z_FIFO[3] = Lm_D(tmp[2] >> 12, TRUE); } static int32_t SQR(uint32_t instr) { const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; MAC[1] = ((IR1 * IR1) >> sf); MAC[2] = ((IR2 * IR2) >> sf); MAC[3] = ((IR3 * IR3) >> sf); MAC_to_IR(lm); return(5); } static int32_t MVMVA(uint32_t instr) { int16_t v[3]; const uint32_t mx = (instr >> 17) & 0x3; const int32* cv = CRVectors.All[(instr >> 13) & 0x3]; const uint32_t v_i = (instr >> 15) & 0x3; const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; if(v_i == 3) { v[0] = IR1; v[1] = IR2; v[2] = IR3; } else { v[0] = Vectors[v_i][0]; v[1] = Vectors[v_i][1]; v[2] = Vectors[v_i][2]; } MultiplyMatrixByVector(&Matrices.All[mx], v, cv, sf, lm); return(8); } static INLINE unsigned CountLeadingZeroU16(uint16_t val) { unsigned ret = 0; while(!(val & 0x8000) && ret < 16) { val <<= 1; ret++; } return ret; } static INLINE uint32_t Divide(uint32_t dividend, uint32_t divisor) { //if((Z_FIFO[3] * 2) > H) if((divisor * 2) > dividend) { unsigned shift_bias = CountLeadingZeroU16(divisor); dividend <<= shift_bias; divisor <<= shift_bias; return ((int64_t)dividend * CalcRecip(divisor | 0x8000) + 32768) >> 16; } FLAGS |= 1 << 17; return 0x1FFFF; } static INLINE void TransformXY(int64_t h_div_sz) { MAC[0] = F((int64_t)OFX + IR1 * h_div_sz * ((widescreen_hack) ? 0.75 : 1.00)) >> 16; XY_FIFO[3].X = Lm_G(0, MAC[0]); MAC[0] = F((int64_t)OFY + IR2 * h_div_sz) >> 16; XY_FIFO[3].Y = Lm_G(1, MAC[0]); XY_FIFO[0] = XY_FIFO[1]; XY_FIFO[1] = XY_FIFO[2]; XY_FIFO[2] = XY_FIFO[3]; } static INLINE void TransformDQ(int64_t h_div_sz) { MAC[0] = F((int64_t)DQB + DQA * h_div_sz); IR0 = Lm_H(((int64_t)DQB + DQA * h_div_sz) >> 12); } static int32_t RTPS(uint32_t instr) { int64_t h_div_sz; const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; MultiplyMatrixByVector_PT(&Matrices.Rot, Vectors[0], CRVectors.T, sf, lm); h_div_sz = Divide(H, Z_FIFO[3]); TransformXY(h_div_sz); TransformDQ(h_div_sz); return(15); } static int32_t RTPT(uint32_t instr) { unsigned i; const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; for(i = 0; i < 3; i++) { int64_t h_div_sz; MultiplyMatrixByVector_PT(&Matrices.Rot, Vectors[i], CRVectors.T, sf, lm); h_div_sz = Divide(H, Z_FIFO[3]); TransformXY(h_div_sz); if(i == 2) TransformDQ(h_div_sz); } return(23); } static INLINE void NormColor(uint32_t sf, int lm, uint32_t v) { int16_t tmp_vector[3]; MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm); tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3; MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm); MAC_to_RGB_FIFO(); } static int32_t NCS(uint32_t instr) { const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; NormColor(sf, lm, 0); return(14); } static int32_t NCT(uint32_t instr) { unsigned i; const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; for(i = 0; i < 3; i++) NormColor(sf, lm, i); return(30); } INLINE void NormColorColor(uint32_t v, uint32_t sf, int lm) { int16_t tmp_vector[3]; MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm); tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3; MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm); MAC[1] = ((RGB.R << 4) * IR1) >> sf; MAC[2] = ((RGB.G << 4) * IR2) >> sf; MAC[3] = ((RGB.B << 4) * IR3) >> sf; MAC_to_IR(lm); MAC_to_RGB_FIFO(); } static int32_t NCCS(uint32_t instr) { const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; NormColorColor(0, sf, lm); return(17); } static int32_t NCCT(uint32_t instr) { unsigned i; const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; for(i = 0; i < 3; i++) NormColorColor(i, sf, lm); return(39); } static INLINE void DepthCue(int mult_IR123, int RGB_from_FIFO, uint32_t sf, int lm) { int i; int32_t RGB_temp[3]; int32_t IR_temp[3] = { IR1, IR2, IR3 }; //assert(sf); RGB_temp[0] = RGB.R; RGB_temp[1] = RGB.G; RGB_temp[2] = RGB.B; if(RGB_from_FIFO) { RGB_temp[0] = RGB_FIFO[0].R; RGB_temp[1] = RGB_FIFO[0].G; RGB_temp[2] = RGB_FIFO[0].B; } RGB_temp[0] <<= 4; RGB_temp[1] <<= 4; RGB_temp[2] <<= 4; if(mult_IR123) { for(i = 0; i < 3; i++) { MAC[1 + i] = A_MV(i, ((int64_t)((uint64_t)(int64_t)CRVectors.FC[i] << 12) - RGB_temp[i] * IR_temp[i])) >> sf; MAC[1 + i] = A_MV(i, (RGB_temp[i] * IR_temp[i] + IR0 * Lm_B(i, MAC[1 + i], FALSE))) >> sf; } } else { for(i = 0; i < 3; i++) { MAC[1 + i] = A_MV(i, ((int64_t)((uint64_t)(int64_t)CRVectors.FC[i] << 12) - (int32)((uint32)RGB_temp[i] << 12))) >> sf; MAC[1 + i] = A_MV(i, ((int64_t)((uint64_t)(int64_t)RGB_temp[i] << 12) + IR0 * Lm_B(i, MAC[1 + i], FALSE))) >> sf; } } MAC_to_IR(lm); MAC_to_RGB_FIFO(); } static int32_t DCPL(uint32_t instr) { const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; DepthCue(TRUE, FALSE, sf, lm); return(8); } static int32_t DPCS(uint32_t instr) { const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; DepthCue(FALSE, FALSE, sf, lm); return(8); } static int32_t DPCT(uint32_t instr) { unsigned i; const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; for(i = 0; i < 3; i++) DepthCue(FALSE, TRUE, sf, lm); return(17); } static int32_t INTPL(uint32_t instr) { const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; MAC[1] = A_MV(0, ((int64_t)((uint64_t)(int64_t)CRVectors.FC[0] << 12) - (int32)((uint32)(int32)IR1 << 12))) >> sf; MAC[2] = A_MV(1, ((int64_t)((uint64_t)(int64_t)CRVectors.FC[1] << 12) - (int32)((uint32)(int32)IR2 << 12))) >> sf; MAC[3] = A_MV(2, ((int64_t)((uint64_t)(int64_t)CRVectors.FC[2] << 12) - (int32)((uint32)(int32)IR3 << 12))) >> sf; MAC[1] = A_MV(0, ((int64_t)((uint64_t)(int64_t)IR1 << 12) + IR0 * Lm_B(0, MAC[1], FALSE)) >> sf); MAC[2] = A_MV(1, ((int64_t)((uint64_t)(int64_t)IR2 << 12) + IR0 * Lm_B(1, MAC[2], FALSE)) >> sf); MAC[3] = A_MV(2, ((int64_t)((uint64_t)(int64_t)IR3 << 12) + IR0 * Lm_B(2, MAC[3], FALSE)) >> sf); MAC_to_IR(lm); MAC_to_RGB_FIFO(); return(8); } static INLINE void NormColorDepthCue(uint32_t v, uint32_t sf, int lm) { int16_t tmp_vector[3]; MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm); tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3; MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm); DepthCue(TRUE, FALSE, sf, lm); } static int32_t NCDS(uint32_t instr) { const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; NormColorDepthCue(0, sf, lm); return(19); } static int32_t NCDT(uint32_t instr) { unsigned i; const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; for(i = 0; i < 3; i++) NormColorDepthCue(i, sf, lm); return(44); } static int32_t CC(uint32_t instr) { int16_t tmp_vector[3]; const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3; MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm); MAC[1] = ((RGB.R << 4) * IR1) >> sf; MAC[2] = ((RGB.G << 4) * IR2) >> sf; MAC[3] = ((RGB.B << 4) * IR3) >> sf; MAC_to_IR(lm); MAC_to_RGB_FIFO(); return(11); } static int32_t CDP(uint32_t instr) { int16_t tmp_vector[3]; const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3; MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm); DepthCue(TRUE, FALSE, sf, lm); return(13); } static int32_t NCLIP(uint32_t instr) { MAC[0] = F( (int64_t)(XY_FIFO[0].X * (XY_FIFO[1].Y - XY_FIFO[2].Y)) + (XY_FIFO[1].X * (XY_FIFO[2].Y - XY_FIFO[0].Y)) + (XY_FIFO[2].X * (XY_FIFO[0].Y - XY_FIFO[1].Y)) ); return(8); } static int32_t AVSZ3(uint32_t instr) { MAC[0] = F(((int64_t)ZSF3 * (Z_FIFO[1] + Z_FIFO[2] + Z_FIFO[3]))); OTZ = Lm_D(MAC[0] >> 12, FALSE); return(5); } static int32_t AVSZ4(uint32_t instr) { MAC[0] = F(((int64_t)ZSF4 * (Z_FIFO[0] + Z_FIFO[1] + Z_FIFO[2] + Z_FIFO[3]))); OTZ = Lm_D(MAC[0] >> 12, FALSE); return(5); } // -32768 * -32768 - 32767 * -32768 = 2147450880 // (2 ^ 31) - 1 = 2147483647 static int32_t OP(uint32_t instr) { const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; MAC[1] = ((Matrices.Rot.MX[1][1] * IR3) - (Matrices.Rot.MX[2][2] * IR2)) >> sf; MAC[2] = ((Matrices.Rot.MX[2][2] * IR1) - (Matrices.Rot.MX[0][0] * IR3)) >> sf; MAC[3] = ((Matrices.Rot.MX[0][0] * IR2) - (Matrices.Rot.MX[1][1] * IR1)) >> sf; MAC_to_IR(lm); return(6); } static int32_t GPF(uint32_t instr) { const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; MAC[1] = (IR0 * IR1) >> sf; MAC[2] = (IR0 * IR2) >> sf; MAC[3] = (IR0 * IR3) >> sf; MAC_to_IR(lm); MAC_to_RGB_FIFO(); return(5); } static int32_t GPL(uint32_t instr) { const uint32_t sf = (instr & (1 << 19)) ? 12 : 0; const int lm = (instr >> 10) & 1; MAC[1] = A_MV(0, (int64_t)((uint64_t)(int64_t)MAC[1] << sf) + (IR0 * IR1)) >> sf; MAC[2] = A_MV(1, (int64_t)((uint64_t)(int64_t)MAC[2] << sf) + (IR0 * IR2)) >> sf; MAC[3] = A_MV(2, (int64_t)((uint64_t)(int64_t)MAC[3] << sf) + (IR0 * IR3)) >> sf; MAC_to_IR(lm); MAC_to_RGB_FIFO(); return(5); } /* --------------------------------------------------------------------------------------------- | 24 23 22 21 20 | 19 | 18 17 | 16 15 | 14 13 | 12 11 | 10 | 9 8 7 6 | 5 4 3 2 1 0 | |-------------------------------------------------------------------------------------------| | (unused) | sf | mx | v | cv |(unused)| lm | (unused) | opcode | --------------------------------------------------------------------------------------------- (unused) = unused, ignored sf = shift 12 mx = matrix selection v = source vector cv = add vector(translation/back/far color(bugged)/none) (unused) = unused, ignored lm = limit negative results to 0 (unused) = unused, ignored opcode = operation code */ int32_t GTE_Instruction(uint32_t instr) { const unsigned code = instr & 0x3F; int32_t ret = 1; FLAGS = 0; switch(code) { default: break; case 0x00: // alternate? case 0x01: ret = RTPS(instr); break; /* case 0x02: // UNSTABLE? break; case 0x03: // UNSTABLE? break; case 0x04: // Probably simple with v,cv,sf,mx,lm ignored. Same calculation as 0x3B? break; case 0x05: // UNSTABLE? break; */ case 0x06: ret = NCLIP(instr); break; /* case 0x07: // UNSTABLE? break; case 0x08: // UNSTABLE? break; case 0x09: // UNSTABLE? break; case 0x0A: // UNSTABLE? break; case 0x0B: // UNSTABLE? break; */ case 0x0C: ret = OP(instr); break; /* case 0x0D: // UNSTABLE? break; case 0x0E: // UNSTABLE? break; case 0x0F: // UNSTABLE? break; */ case 0x10: ret = DPCS(instr); break; case 0x11: ret = INTPL(instr); break; case 0x12: ret = MVMVA(instr); break; case 0x13: ret = NCDS(instr); break; case 0x14: ret = CDP(instr); break; /* case 0x15: // does one push on RGB FIFO, what else... break; */ case 0x16: ret = NCDT(instr); break; /* case 0x17: // PARTIALLY UNSTABLE(depending on sf or v or cv or mx or lm), similar behavior under some conditions to 0x16? break; case 0x18: break; case 0x19: break; */ case 0x1A: // Alternate for 0x29? ret = DCPL(instr); break; case 0x1B: ret = NCCS(instr); break; case 0x1C: ret = CC(instr); break; /* case 0x1D: break; */ case 0x1E: ret = NCS(instr); break; /* case 0x1F: break; */ case 0x20: ret = NCT(instr); break; /* case 0x21: break; case 0x22: // UNSTABLE? break; case 0x23: break; case 0x24: break; case 0x25: break; case 0x26: break; case 0x27: break; */ case 0x28: ret = SQR(instr); break; case 0x29: ret = DCPL(instr); break; case 0x2A: ret = DPCT(instr); break; /* case 0x2B: break; case 0x2C: break; */ case 0x2D: ret = AVSZ3(instr); break; case 0x2E: ret = AVSZ4(instr); break; /* case 0x2F: // UNSTABLE? break; */ case 0x30: ret = RTPT(instr); break; /* case 0x31: // UNSTABLE? break; case 0x32: // UNSTABLE? break; case 0x33: // UNSTABLE? break; case 0x34: // UNSTABLE? break; case 0x35: // UNSTABLE? break; case 0x36: // UNSTABLE? break; case 0x37: // UNSTABLE? break; case 0x38: break; case 0x39: // Probably simple with v,cv,sf,mx,lm ignored. break; case 0x3A: // Probably simple with v,cv,sf,mx,lm ignored. break; case 0x3B: // Probably simple with v,cv,sf,mx,lm ignored. Same calculation as 0x04? break; case 0x3C: // UNSTABLE? break; */ case 0x3D: ret = GPF(instr); break; case 0x3E: ret = GPL(instr); break; case 0x3F: ret = NCCT(instr); break; } if(FLAGS & 0x7f87e000) FLAGS |= 1 << 31; CR[31] = FLAGS; return(ret - 1); } mednafen/tremor/misc.h000664 001750 001750 00000013452 12611054044 016075 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: miscellaneous math and prototypes ********************************************************************/ #ifndef _V_RANDOM_H_ #define _V_RANDOM_H_ #include "ivorbiscodec.h" #include "os.h" #include "tremor_shared.h" #ifdef _LOW_ACCURACY_ # define X(n) (((((n)>>22)+1)>>1) - ((((n)>>22)+1)>>9)) # define LOOKUP_T const unsigned char #else # define X(n) (n) # define LOOKUP_T const ogg_int32_t #endif #include "asm_arm.h" #include /* for abs() */ #ifndef _V_WIDE_MATH #define _V_WIDE_MATH #ifndef _LOW_ACCURACY_ /* 64 bit multiply */ #if !(defined WIN32 && defined WINCE) #include #endif union magic { struct { #ifdef MSB_FIRST ogg_int32_t hi; ogg_int32_t lo; #else ogg_int32_t lo; ogg_int32_t hi; #endif } halves; ogg_int64_t whole; }; STIN ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) { union magic magic; magic.whole = (ogg_int64_t)x * y; return magic.halves.hi; } STIN ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) { return MULT32(x,y)<<1; } STIN ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { union magic magic; magic.whole = (ogg_int64_t)x * y; return ((ogg_uint32_t)(magic.halves.lo)>>15) | ((magic.halves.hi)<<17); } #else /* 32 bit multiply, more portable but less accurate */ /* * Note: Precision is biased towards the first argument therefore ordering * is important. Shift values were chosen for the best sound quality after * many listening tests. */ /* * For MULT32 and MULT31: The second argument is always a lookup table * value already preshifted from 31 to 8 bits. We therefore take the * opportunity to save on text space and use unsigned char for those * tables in this case. */ STIN ogg_int32_t MULT32(ogg_int32_t x, ogg_int32_t y) { return (x >> 9) * y; /* y preshifted >>23 */ } STIN ogg_int32_t MULT31(ogg_int32_t x, ogg_int32_t y) { return (x >> 8) * y; /* y preshifted >>23 */ } STIN ogg_int32_t MULT31_SHIFT15(ogg_int32_t x, ogg_int32_t y) { return (x >> 6) * y; /* y preshifted >>9 */ } #endif /* * This should be used as a memory barrier, forcing all cached values in * registers to wr writen back to memory. Might or might not be beneficial * depending on the architecture and compiler. */ #define MB() /* * The XPROD functions are meant to optimize the cross products found all * over the place in mdct.c by forcing memory operation ordering to avoid * unnecessary register reloads as soon as memory is being written to. * However this is only beneficial on CPUs with a sane number of general * purpose registers which exclude the Intel x86. On Intel, better let the * compiler actually reload registers directly from original memory by using * macros. */ #ifdef __i386__ #define XPROD32(_a, _b, _t, _v, _x, _y) \ { *(_x)=MULT32(_a,_t)+MULT32(_b,_v); \ *(_y)=MULT32(_b,_t)-MULT32(_a,_v); } #define XPROD31(_a, _b, _t, _v, _x, _y) \ { *(_x)=MULT31(_a,_t)+MULT31(_b,_v); \ *(_y)=MULT31(_b,_t)-MULT31(_a,_v); } #define XNPROD31(_a, _b, _t, _v, _x, _y) \ { *(_x)=MULT31(_a,_t)-MULT31(_b,_v); \ *(_y)=MULT31(_b,_t)+MULT31(_a,_v); } #else STIN void XPROD32(ogg_int32_t a, ogg_int32_t b, ogg_int32_t t, ogg_int32_t v, ogg_int32_t *x, ogg_int32_t *y) { *x = MULT32(a, t) + MULT32(b, v); *y = MULT32(b, t) - MULT32(a, v); } STIN void XPROD31(ogg_int32_t a, ogg_int32_t b, ogg_int32_t t, ogg_int32_t v, ogg_int32_t *x, ogg_int32_t *y) { *x = MULT31(a, t) + MULT31(b, v); *y = MULT31(b, t) - MULT31(a, v); } STIN void XNPROD31(ogg_int32_t a, ogg_int32_t b, ogg_int32_t t, ogg_int32_t v, ogg_int32_t *x, ogg_int32_t *y) { *x = MULT31(a, t) - MULT31(b, v); *y = MULT31(b, t) + MULT31(a, v); } #endif #endif #ifndef _V_CLIP_MATH #define _V_CLIP_MATH STIN ogg_int32_t CLIP_TO_15(ogg_int32_t x) { int ret=x; ret-= ((x<=32767)-1)&(x-32767); ret-= ((x>=-32768)-1)&(x+32768); return(ret); } #endif STIN ogg_int32_t VFLOAT_MULT(ogg_int32_t a,ogg_int32_t ap, ogg_int32_t b,ogg_int32_t bp, ogg_int32_t *p){ if(a && b){ #ifndef _LOW_ACCURACY_ *p=ap+bp+32; return MULT32(a,b); #else *p=ap+bp+31; return (a>>15)*(b>>16); #endif }else return 0; } STIN ogg_int32_t VFLOAT_MULTI(ogg_int32_t a,ogg_int32_t ap, ogg_int32_t i, ogg_int32_t *p){ int ip= ilog(abs(i))-31; return VFLOAT_MULT(a,ap,i<<-ip,ip,p); } STIN ogg_int32_t VFLOAT_ADD(ogg_int32_t a,ogg_int32_t ap, ogg_int32_t b,ogg_int32_t bp, ogg_int32_t *p){ if(!a){ *p=bp; return b; }else if(!b){ *p=ap; return a; } /* yes, this can leak a bit. */ if(ap>bp){ int shift=ap-bp+1; *p=ap+1; a>>=1; if(shift<32){ b=(b+(1<<(shift-1)))>>shift; }else{ b=0; } }else{ int shift=bp-ap+1; *p=bp+1; b>>=1; if(shift<32){ a=(a+(1<<(shift-1)))>>shift; }else{ a=0; } } a+=b; if((a&0xc0000000)==0xc0000000 || (a&0xc0000000)==0){ a<<=1; (*p)--; } return(a); } #endif mednafen/video/Deinterlacer.cpp000664 001750 001750 00000012455 12611054044 017676 0ustar00sergiosergio000000 000000 #include "../mednafen.h" #include "../video.h" #include "../general.h" #include "../state.h" #include "../driver.h" #include "Deinterlacer.h" Deinterlacer::Deinterlacer() : FieldBuffer(NULL), StateValid(false), DeintType(DEINT_WEAVE) { PrevDRect.x = 0; PrevDRect.y = 0; PrevDRect.w = 0; PrevDRect.h = 0; } Deinterlacer::~Deinterlacer() { if(FieldBuffer) { delete FieldBuffer; FieldBuffer = NULL; } } void Deinterlacer::SetType(unsigned dt) { if(DeintType != dt) { DeintType = dt; LWBuffer.resize(0); if(FieldBuffer) { delete FieldBuffer; FieldBuffer = NULL; } StateValid = false; } } template void Deinterlacer::InternalProcess(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32 *LineWidths, const bool field) { // // We need to output with LineWidths as always being valid to handle the case of horizontal resolution change between fields // while in interlace mode, so clear the first LineWidths entry if it's == ~0, and // [...] const bool LineWidths_In_Valid = (LineWidths[0] != ~0); const bool WeaveGood = (StateValid && PrevDRect.h == DisplayRect.h && DeintType == DEINT_WEAVE); // // XReposition stuff is to prevent exceeding the dimensions of the video surface under certain conditions(weave deinterlacer, previous field has higher // horizontal resolution than current field, and current field's rectangle has an x offset that's too large when taking into consideration the previous field's // width; for simplicity, we don't check widths, but just assume that the previous field's maximum width is >= than the current field's maximum width). // const int32 XReposition = ((WeaveGood && DisplayRect.x > PrevDRect.x) ? DisplayRect.x : 0); //printf("%2d %2d, %d\n", DisplayRect.x, PrevDRect.x, XReposition); if(XReposition) DisplayRect.x = 0; if(surface->h && !LineWidths_In_Valid) { LineWidths[0] = 0; } for(int y = 0; y < DisplayRect.h / 2; y++) { // [...] // set all relevant source line widths to the contents of DisplayRect(also simplifies the src_lw and related pointer calculation code // farther below. if(!LineWidths_In_Valid) LineWidths[(y * 2) + field + DisplayRect.y] = DisplayRect.w; if(XReposition) { memmove(surface->pixels + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix, surface->pixels + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + XReposition, LineWidths[(y * 2) + field + DisplayRect.y] * sizeof(T)); } if(WeaveGood) { const T* src = FieldBuffer->pixels + y * FieldBuffer->pitchinpix; T* dest = surface->pixels + ((y * 2) + (field ^ 1) + DisplayRect.y) * surface->pitchinpix + DisplayRect.x; int32 *dest_lw = &LineWidths[(y * 2) + (field ^ 1) + DisplayRect.y]; *dest_lw = LWBuffer[y]; memcpy(dest, src, LWBuffer[y] * sizeof(T)); } else if(DeintType == DEINT_BOB) { const T* src = surface->pixels + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + DisplayRect.x; T* dest = surface->pixels + ((y * 2) + (field ^ 1) + DisplayRect.y) * surface->pitchinpix + DisplayRect.x; const int32 *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y]; int32 *dest_lw = &LineWidths[(y * 2) + (field ^ 1) + DisplayRect.y]; *dest_lw = *src_lw; memcpy(dest, src, *src_lw * sizeof(T)); } else { const int32 *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y]; const T* src = surface->pixels + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + DisplayRect.x; const int32 dly = ((y * 2) + (field + 1) + DisplayRect.y); T* dest = surface->pixels + dly * surface->pitchinpix + DisplayRect.x; if(y == 0 && field) { T black = MAKECOLOR(0, 0, 0, 0); T* dm2 = surface->pixels + (dly - 2) * surface->pitchinpix; LineWidths[dly - 2] = *src_lw; for(int x = 0; x < *src_lw; x++) dm2[x] = black; } if(dly < (DisplayRect.y + DisplayRect.h)) { LineWidths[dly] = *src_lw; memcpy(dest, src, *src_lw * sizeof(T)); } } // // // // // // if(DeintType == DEINT_WEAVE) { const int32 *src_lw = &LineWidths[(y * 2) + field + DisplayRect.y]; const T* src = surface->pixels + ((y * 2) + field + DisplayRect.y) * surface->pitchinpix + DisplayRect.x; T* dest = FieldBuffer->pixels + y * FieldBuffer->pitchinpix; memcpy(dest, src, *src_lw * sizeof(uint32)); LWBuffer[y] = *src_lw; StateValid = true; } } } void Deinterlacer::Process(MDFN_Surface *surface, MDFN_Rect &DisplayRect, int32 *LineWidths, const bool field) { const MDFN_Rect DisplayRect_Original = DisplayRect; if(DeintType == DEINT_WEAVE) { if(!FieldBuffer || FieldBuffer->w < surface->w || FieldBuffer->h < (surface->h / 2)) { if(FieldBuffer) delete FieldBuffer; FieldBuffer = new MDFN_Surface(NULL, surface->w, surface->h / 2, surface->w, surface->format); LWBuffer.resize(FieldBuffer->h); } else if(memcmp(&surface->format, &FieldBuffer->format, sizeof(MDFN_PixelFormat))) { FieldBuffer->SetFormat(surface->format, StateValid && PrevDRect.h == DisplayRect.h); } } #if defined(WANT_32BPP) InternalProcess(surface, DisplayRect, LineWidths, field); #elif defined(WANT_16BPP) InternalProcess(surface, DisplayRect, LineWidths, field); #endif PrevDRect = DisplayRect_Original; } void Deinterlacer::ClearState(void) { StateValid = false; PrevDRect.x = 0; PrevDRect.y = 0; PrevDRect.w = 0; PrevDRect.h = 0; } mednafen/psx/FastFIFO.h000664 001750 001750 00000002026 12611054044 016000 0ustar00sergiosergio000000 000000 #ifndef __MDFN_FASTFIFO_H #define __MDFN_FASTFIFO_H // size should be a power of 2. template class FastFIFO { public: FastFIFO() { memset(data, 0, sizeof(data)); read_pos = 0; write_pos = 0; in_count = 0; } INLINE ~FastFIFO() { } INLINE void SaveStatePostLoad(void) { read_pos %= size; write_pos %= size; in_count %= (size + 1); } INLINE uint32 CanRead(void) { return(in_count); } INLINE uint32 CanWrite(void) { return(size - in_count); } INLINE T Peek(void) { return data[read_pos]; } INLINE T Read(void) { T ret = data[read_pos]; read_pos = (read_pos + 1) & (size - 1); in_count--; return(ret); } INLINE void Write(const T& wr_data) { data[write_pos] = wr_data; write_pos = (write_pos + 1) & (size - 1); in_count++; } INLINE void Flush(void) { read_pos = 0; write_pos = 0; in_count = 0; } T data[size]; uint32 read_pos; // Read position uint32 write_pos; // Write position uint32 in_count; // Number of units in the FIFO }; #endif mednafen/tremor/CHANGELOG000664 001750 001750 00000000723 12611054044 016200 0ustar00sergiosergio000000 000000 *** 20020517: 1.0.2 *** Playback bugfix to floor1; mode mistakenly used for sizing instead of blockflag *** 20020515: 1.0.1 *** Added complete API documentation to source tarball. No code changes. *** 20020412: 1.0.1 *** Fixed a clipping bug that affected ARM processors; negative overflows were being properly clipped, but then clobbered to positive by the positive overflow chec (asm_arm.h:CLIP_TO_15) *** 20020403: 1.0.0 *** Initial versionmednafen/psx/notes/tristep.cpp000664 001750 001750 00000003047 12611054044 017620 0ustar00sergiosergio000000 000000 #include #include #include typedef int8_t int8; typedef int16_t int16; typedef int32_t int32; typedef int64_t int64; typedef uint8_t uint8; typedef uint16_t uint16; typedef uint32_t uint32; typedef uint64_t uint64; #define INLINE inline static INLINE int64 MakePolyXFP(int32 x) { return ((int64)x << 32) + ((1LL << 32) - (1 << 11)); } static INLINE int64 MakePolyXFPStep(int32 dx, int32 dy) { int64 ret; int64 dx_ex = (int64)dx << 32; if(dx_ex < 0) dx_ex -= dy - 1; if(dx_ex > 0) dx_ex += dy - 1; ret = dx_ex / dy; return(ret); } static INLINE int32 GetPolyXFP_Int(int64 xfp) { return(xfp >> 32); } // Test X delta of -1023 ... 1023 // Test Y delta of 1 ... 511 int main() { for(int xbase = -1; xbase < 1025; xbase += 1025) { for(int dx = -1023; dx <= 1023; dx++) { for(int dy = 1; dy <= 511; dy++) { int64 x_coord, x_step; int32 alt_x_coord; int32 alt_x_error; x_coord = MakePolyXFP(xbase); x_step = MakePolyXFPStep(dx, dy); alt_x_coord = xbase; if(dx >= 0) alt_x_error = dy - 1; else alt_x_error = 0; for(int step = 0; step < dy; step++) { if(GetPolyXFP_Int(x_coord) != alt_x_coord) { printf("xbase=%d, dx=%d, dy=%d, step=%d --- xfpx=%d, altx=%d\n", xbase, dx, dy, step, GetPolyXFP_Int(x_coord), alt_x_coord); } x_coord += x_step; alt_x_error += abs(dx); while(alt_x_error >= dy) { if(dx < 0) alt_x_coord--; else alt_x_coord++; alt_x_error -= dy; } } } } } } mednafen/cdrom/l-ec.h000664 001750 001750 00000002345 12611054044 015555 0ustar00sergiosergio000000 000000 #ifndef _L_EC_H #define _L_EC_H #include #include "galois.h" #ifdef __cplusplus extern "C" { #endif #define N_P_VECTORS 86 /* 43 16bit p vectors */ #define P_VECTOR_SIZE 26 /* using RS(26,24) ECC */ #define N_Q_VECTORS 52 /* 26 16bit q vectors */ #define Q_VECTOR_SIZE 45 /* using RS(45,43) ECC */ #define P_PADDING 229 /* padding values for */ #define Q_PADDING 210 /* shortened RS code */ int PToByteIndex(int, int); int QToByteIndex(int, int); void ByteIndexToP(int, int*, int*); void ByteIndexToQ(int, int*, int*); void GetPVector(unsigned char*, unsigned char*, int); void SetPVector(unsigned char*, unsigned char*, int); void FillPVector(unsigned char*, unsigned char, int); void AndPVector(unsigned char*, unsigned char, int); void OrPVector(unsigned char*, unsigned char, int); void GetQVector(unsigned char*, unsigned char*, int); void SetQVector(unsigned char*, unsigned char*, int); void FillQVector(unsigned char*, unsigned char, int); void AndQVector(unsigned char*, unsigned char, int); void OrQVector(unsigned char*, unsigned char, int); int DecodePQ(ReedSolomonTables*, unsigned char*, int, int*, int); int CountC2Errors(unsigned char*); #ifdef __cplusplus } #endif #endif mednafen/include/rthreads/000700 001750 001750 00000000000 12702525066 016707 5ustar00sergiosergio000000 000000 mednafen/cdrom/l-ec.c000664 001750 001750 00000027436 12611054044 015560 0ustar00sergiosergio000000 000000 /* dvdisaster: Additional error correction for optical media. * Copyright (C) 2004-2007 Carsten Gnoerlich. * Project home page: http://www.dvdisaster.com * Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org * * The Reed-Solomon error correction draws a lot of inspiration - and even code - * from Phil Karn's excellent Reed-Solomon library: http://www.ka9q.net/code/fec/ * * 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, * or direct your browser at http://www.gnu.org. */ #include "l-ec.h" #include #include #define MIN(a, b) (((a) < (b)) ? (a) : (b)) /*** *** Mapping between cd frame and parity vectors ***/ /* * Mapping of frame bytes to P/Q Vectors */ int PToByteIndex(int p, int i) { return 12 + p + i*86; } void ByteIndexToP(int b, int *p, int *i) { *p = (b-12)%86; *i = (b-12)/86; } int QToByteIndex(int q, int i) { int offset = 12 + (q & 1); if(i == 43) return 2248+q; if(i == 44) return 2300+q; q&=~1; return offset + (q*43 + i*88) % 2236; } void ByteIndexToQ(int b, int *q, int *i) { int x,y,offset; if(b >= 2300) { *i = 44; *q = (b-2300); return; } if(b >= 2248) { *i = 43; *q = (b-2248); return; } offset = b&1; b = (b-12)/2; x = b/43; y = (b-(x*43))%26; *i = b-(x*43); *q = 2*((x+26-y)%26)+offset; } /* * There are 86 vectors of P-parity, yielding a RS(26,24) code. */ void GetPVector(unsigned char *frame, unsigned char *data, int n) { int i; int w_idx = n+12; for(i=0; i<26; i++, w_idx+=86) data[i] = frame[w_idx]; } void SetPVector(unsigned char *frame, unsigned char *data, int n) { int i; int w_idx = n+12; for(i=0; i<26; i++, w_idx+=86) frame[w_idx] = data[i]; } void FillPVector(unsigned char *frame, unsigned char data, int n) { int i; int w_idx = n+12; for(i=0; i<26; i++, w_idx+=86) frame[w_idx] = data; } void OrPVector(unsigned char *frame, unsigned char value, int n) { int i; int w_idx = n+12; for(i=0; i<26; i++, w_idx+=86) frame[w_idx] |= value; } void AndPVector(unsigned char *frame, unsigned char value, int n) { int i; int w_idx = n+12; for(i=0; i<26; i++, w_idx+=86) frame[w_idx] &= value; } /* * There are 52 vectors of Q-parity, yielding a RS(45,43) code. */ void GetQVector(unsigned char *frame, unsigned char *data, int n) { int offset = 12 + (n & 1); int w_idx = (n&~1) * 43; int i; for(i=0; i<43; i++, w_idx+=88) data[i] = frame[(w_idx % 2236) + offset]; data[43] = frame[2248 + n]; data[44] = frame[2300 + n]; } void SetQVector(unsigned char *frame, unsigned char *data, int n) { int offset = 12 + (n & 1); int w_idx = (n&~1) * 43; int i; for(i=0; i<43; i++, w_idx+=88) frame[(w_idx % 2236) + offset] = data[i]; frame[2248 + n] = data[43]; frame[2300 + n] = data[44]; } void FillQVector(unsigned char *frame, unsigned char data, int n) { int offset = 12 + (n & 1); int w_idx = (n&~1) * 43; int i; for(i=0; i<43; i++, w_idx+=88) frame[(w_idx % 2236) + offset] = data; frame[2248 + n] = data; frame[2300 + n] = data; } void OrQVector(unsigned char *frame, unsigned char data, int n) { int offset = 12 + (n & 1); int w_idx = (n&~1) * 43; int i; for(i=0; i<43; i++, w_idx+=88) frame[(w_idx % 2236) + offset] |= data; frame[2248 + n] |= data; frame[2300 + n] |= data; } void AndQVector(unsigned char *frame, unsigned char data, int n) { int offset = 12 + (n & 1); int w_idx = (n&~1) * 43; int i; for(i=0; i<43; i++, w_idx+=88) frame[(w_idx % 2236) + offset] &= data; frame[2248 + n] &= data; frame[2300 + n] &= data; } /*** *** C2 error counting ***/ int CountC2Errors(unsigned char *frame) { int i,count = 0; frame += 2352; for(i=0; i<294; i++, frame++) { if(*frame & 0x01) count++; if(*frame & 0x02) count++; if(*frame & 0x04) count++; if(*frame & 0x08) count++; if(*frame & 0x10) count++; if(*frame & 0x20) count++; if(*frame & 0x40) count++; if(*frame & 0x80) count++; } return count; } /*** *** L-EC error correction for CD raw data sectors ***/ /* * These could be used from ReedSolomonTables, * but hardcoding them is faster. */ #define NROOTS 2 #define LEC_FIRST_ROOT 0 //GF_ALPHA0 #define LEC_PRIM_ELEM 1 #define LEC_PRIMTH_ROOT 1 /* * Calculate the error syndrome */ int DecodePQ(ReedSolomonTables *rt, unsigned char *data, int padding, int *erasure_list, int erasure_count) { GaloisTables *gt = rt->gfTables; int syndrome[NROOTS]; int lambda[NROOTS+1]; int omega[NROOTS+1]; int b[NROOTS+1]; int reg[NROOTS+1]; int root[NROOTS]; int loc[NROOTS]; int syn_error; int deg_lambda,lambda_roots; int deg_omega; int shortened_size = GF_FIELDMAX - padding; int corrected = 0; int i,j,k; int r,el; /*** Form the syndromes: Evaluate data(x) at roots of g(x) */ for(i=0; ialphaTo[mod_fieldmax(gt->indexOf[syndrome[i]] + (LEC_FIRST_ROOT+i)*LEC_PRIM_ELEM)]; /*** Convert syndrome to index form, check for nonzero condition. */ syn_error = 0; for(i=0; iindexOf[syndrome[i]]; } /*** If the syndrome is zero, everything is fine. */ if(!syn_error) return 0; /*** Initialize lambda to be the erasure locator polynomial */ lambda[0] = 1; lambda[1] = lambda[2] = 0; erasure_list[0] += padding; erasure_list[1] += padding; if(erasure_count > 2) /* sanity check */ erasure_count = 0; if(erasure_count > 0) { lambda[1] = gt->alphaTo[mod_fieldmax(LEC_PRIM_ELEM*(GF_FIELDMAX-1-erasure_list[0]))]; for(i=1; i0; j--) { int tmp = gt->indexOf[lambda[j-1]]; if(tmp != GF_ALPHA0) lambda[j] ^= gt->alphaTo[mod_fieldmax(u + tmp)]; } } } for(i=0; iindexOf[lambda[i]]; /*** Berlekamp-Massey algorithm to determine error+erasure locator polynomial */ r = erasure_count; /* r is the step number */ el = erasure_count; /* Compute discrepancy at the r-th step in poly-form */ while(++r <= NROOTS) { int discr_r = 0; for(i=0; ialphaTo[mod_fieldmax(gt->indexOf[lambda[i]] + syndrome[r-i-1])]; discr_r = gt->indexOf[discr_r]; if(discr_r == GF_ALPHA0) { /* B(x) = x*B(x) */ memmove(b+1, b, NROOTS*sizeof(b[0])); b[0] = GF_ALPHA0; } else { int t[NROOTS+1]; /* T(x) = lambda(x) - discr_r*x*b(x) */ t[0] = lambda[0]; for(i=0; ialphaTo[mod_fieldmax(discr_r + b[i])]; else t[i+1] = lambda[i+1]; } if(2*el <= r+erasure_count-1) { el = r + erasure_count - el; /* B(x) <-- inv(discr_r) * lambda(x) */ for(i=0; i<=NROOTS; i++) b[i] = (lambda[i] == 0) ? GF_ALPHA0 : mod_fieldmax(gt->indexOf[lambda[i]] - discr_r + GF_FIELDMAX); } else { /* 2 lines below: B(x) <-- x*B(x) */ memmove(b+1, b, NROOTS*sizeof(b[0])); b[0] = GF_ALPHA0; } memcpy(lambda, t, (NROOTS+1)*sizeof(t[0])); } } /*** Convert lambda to index form and compute deg(lambda(x)) */ deg_lambda = 0; for(i=0; iindexOf[lambda[i]]; if(lambda[i] != GF_ALPHA0) deg_lambda = i; } /*** Find roots of the error+erasure locator polynomial by Chien search */ memcpy(reg+1, lambda+1, NROOTS*sizeof(reg[0])); lambda_roots = 0; /* Number of roots of lambda(x) */ for(i=1, k=LEC_PRIMTH_ROOT-1; i<=GF_FIELDMAX; i++, k=mod_fieldmax(k+LEC_PRIMTH_ROOT)) { int q=1; /* lambda[0] is always 0 */ for(j=deg_lambda; j>0; j--) { if(reg[j] != GF_ALPHA0) { reg[j] = mod_fieldmax(reg[j] + j); q ^= gt->alphaTo[reg[j]]; } } if(q != 0) continue; /* Not a root */ /* store root in index-form and the error location number */ root[lambda_roots] = i; loc[lambda_roots] = k; /* If we've already found max possible roots, abort the search to save time */ if(++lambda_roots == deg_lambda) break; } /* deg(lambda) unequal to number of roots => uncorrectable error detected This is not reliable for very small numbers of roots, e.g. nroots = 2 */ if(deg_lambda != lambda_roots) { return -1; } /* Compute err+eras evaluator poly omega(x) = syn(x)*lambda(x) (modulo x**nroots). in index form. Also find deg(omega). */ deg_omega = deg_lambda-1; for(i=0; i<=deg_omega; i++) { int tmp = 0; for(j=i; j>=0; j--) { if((syndrome[i - j] != GF_ALPHA0) && (lambda[j] != GF_ALPHA0)) tmp ^= gt->alphaTo[mod_fieldmax(syndrome[i - j] + lambda[j])]; } omega[i] = gt->indexOf[tmp]; } /* Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = inv(X(l))**(FIRST_ROOT-1) and den = lambda_pr(inv(X(l))) all in poly-form. */ for(j=lambda_roots-1; j>=0; j--) { int num1 = 0; int num2; int den; int location = loc[j]; for(i=deg_omega; i>=0; i--) { if(omega[i] != GF_ALPHA0) num1 ^= gt->alphaTo[mod_fieldmax(omega[i] + i * root[j])]; } num2 = gt->alphaTo[mod_fieldmax(root[j] * (LEC_FIRST_ROOT - 1) + GF_FIELDMAX)]; den = 0; /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ for(i=MIN(deg_lambda, NROOTS-1) & ~1; i>=0; i-=2) { if(lambda[i+1] != GF_ALPHA0) den ^= gt->alphaTo[mod_fieldmax(lambda[i+1] + i * root[j])]; } /* Apply error to data */ if(num1 != 0 && location >= padding) { corrected++; data[location-padding] ^= gt->alphaTo[mod_fieldmax(gt->indexOf[num1] + gt->indexOf[num2] + GF_FIELDMAX - gt->indexOf[den])]; /* If no erasures were given, at most one error was corrected. Return its position in erasure_list[0]. */ if(!erasure_count) erasure_list[0] = location-padding; } else return -3; } /*** Form the syndromes: Evaluate data(x) at roots of g(x) */ for(i=0; ialphaTo[mod_fieldmax(gt->indexOf[syndrome[i]] + (LEC_FIRST_ROOT+i)*LEC_PRIM_ELEM)]; } /*** Convert syndrome to index form, check for nonzero condition. */ for(i=0; i #include #include #include "misc.h" void MDFN_strtoupper(char *str) { size_t x; for(x = 0; str[x]; x++) { if(str[x] >= 'a' && str[x] <= 'z') str[x] = str[x] - 'a' + 'A'; } } void MDFN_strtoupper(std::string &str) { size_t x; const size_t len = str.length(); for(x = 0; x < len; x++) { if(str[x] >= 'a' && str[x] <= 'z') str[x] = str[x] - 'a' + 'A'; } } mednafen/psx/gpu.cpp000664 001750 001750 00000122633 12611054044 015574 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include "psx.h" #include "timer.h" /* GPU display timing master clock is nominally 53.693182 MHz for NTSC PlayStations, and 53.203425 MHz for PAL PlayStations. Non-interlaced NTSC mode line timing notes(real-world times calculated via PS1 timer and math with nominal CPU clock value): 263 lines per frame ~16714.85 us per frame, average. ~63.55456 us per line, average. Multiplying the results of counter 0 in pixel clock mode by the clock divider of the current dot clock mode/width gives a result that's slightly less than expected; the dot clock divider is probably being reset each scanline. Non-interlaced PAL mode(but with an NTSC source clock in an NTSC PS1; calculated same way as NTSC values): 314 lines per frame ~19912.27 us per frame, average. ~63.41486 us per line, average. FB X and Y display positions can be changed during active display; and Y display position appears to be treated as an offset to the current Y readout position that gets reset around vblank time. */ /* November 29, 2012 notes: PAL mode can be turned on, and then off again, mid-frame(creates a neat effect). Pixel clock can be changed mid-frame with effect(the effect is either instantaneous, or cached at some point in the scanline, not tested to see which); interestingly, alignment is off on a PS1 when going 5MHz->10MHz>5MHz with a grid image. Vertical start and end can be changed during active display, with effect(though it needs to be vs0->ve0->vs1->ve1->..., vs0->vs1->ve0 doesn't apparently do anything different from vs0->ve0. */ static const int8 dither_table[4][4] = { { -4, 0, -3, 1 }, { 2, -2, 3, -1 }, { -3, 1, -4, 0 }, { 3, -1, 2, -2 }, }; PS_GPU::PS_GPU(bool pal_clock_and_tv, int sls, int sle) { int x, y, v; HardwarePALType = pal_clock_and_tv; for(y = 0; y < 4; y++) for(x = 0; x < 4; x++) for(v = 0; v < 512; v++) { int value = v + dither_table[y][x]; value >>= 3; if(value < 0) value = 0; if(value > 0x1F) value = 0x1F; DitherLUT[y][x][v] = value; } if(HardwarePALType == false) // NTSC clock GPUClockRatio = 103896; // 65536 * 53693181.818 / (44100 * 768) else // PAL clock GPUClockRatio = 102948; // 65536 * 53203425 / (44100 * 768) memset(RGB8SAT_Under, 0, sizeof(RGB8SAT_Under)); for(int i = 0; i < 256; i++) RGB8SAT[i] = i; memset(RGB8SAT_Over, 0xFF, sizeof(RGB8SAT_Over)); LineVisFirst = sls; LineVisLast = sle; } PS_GPU::~PS_GPU() { } void PS_GPU::FillVideoParams(MDFNGI* gi) { if(HardwarePALType) { gi->lcm_width = 2800; gi->lcm_height = (LineVisLast + 1 - LineVisFirst) * 2; //576; gi->nominal_width = 384; // Dunno. :( gi->nominal_height = LineVisLast + 1 - LineVisFirst; //288; gi->fb_width = 768; gi->fb_height = 576; gi->fps = 836203078; // 49.842 gi->VideoSystem = VIDSYS_PAL; } else { gi->lcm_width = 2800; gi->lcm_height = (LineVisLast + 1 - LineVisFirst) * 2; //480; gi->nominal_width = 320; gi->nominal_height = LineVisLast + 1 - LineVisFirst; //240; gi->fb_width = 768; gi->fb_height = 480; gi->fps = 1005643085; // 59.941 gi->VideoSystem = VIDSYS_NTSC; } // // For Justifier and Guncon. // gi->mouse_scale_x = (float)gi->lcm_width / gi->nominal_width; gi->mouse_offs_x = (float)(2800 - gi->lcm_width) / 2; gi->mouse_scale_y = 1.0; gi->mouse_offs_y = LineVisFirst; } void PS_GPU::SoftReset(void) // Control command 0x00 { IRQPending = false; IRQ_Assert(IRQ_GPU, IRQPending); InvalidateCache(); DMAControl = 0; if(DrawTimeAvail < 0) DrawTimeAvail = 0; BlitterFIFO.Flush(); DataReadBufferEx = 0; InCmd = INCMD_NONE; DisplayOff = 1; DisplayFB_XStart = 0; DisplayFB_YStart = 0; DisplayMode = 0; HorizStart = 0x200; HorizEnd = 0xC00; VertStart = 0x10; VertEnd = 0x100; // TexPageX = 0; TexPageY = 0; SpriteFlip = 0; abr = 0; TexMode = 0; dtd = 0; dfe = 0; // tww = 0; twh = 0; twx = 0; twy = 0; RecalcTexWindowStuff(); // ClipX0 = 0; ClipY0 = 0; // ClipX1 = 0; ClipY1 = 0; // OffsX = 0; OffsY = 0; // MaskSetOR = 0; MaskEvalAND = 0; TexDisable = false; TexDisableAllowChange = false; } void PS_GPU::Power(void) { memset(GPURAM, 0, sizeof(GPURAM)); memset(CLUT_Cache, 0, sizeof(CLUT_Cache)); CLUT_Cache_VB = ~0U; memset(TexCache, 0xFF, sizeof(TexCache)); DMAControl = 0; ClipX0 = 0; ClipY0 = 0; ClipX1 = 0; ClipY1 = 0; OffsX = 0; OffsY = 0; dtd = false; dfe = false; MaskSetOR = 0; MaskEvalAND = 0; TexDisable = false; TexDisableAllowChange = false; tww = 0; twh = 0; twx = 0; twy = 0; RecalcTexWindowStuff(); TexPageX = 0; TexPageY = 0; SpriteFlip = 0; abr = 0; TexMode = 0; BlitterFIFO.Flush(); DataReadBuffer = 0; // Don't reset in SoftReset() DataReadBufferEx = 0; InCmd = INCMD_NONE; FBRW_X = 0; FBRW_Y = 0; FBRW_W = 0; FBRW_H = 0; FBRW_CurY = 0; FBRW_CurX = 0; DisplayMode = 0; DisplayOff = 1; DisplayFB_XStart = 0; DisplayFB_YStart = 0; HorizStart = 0; HorizEnd = 0; VertStart = 0; VertEnd = 0; // // // DisplayFB_CurYOffset = 0; DisplayFB_CurLineYReadout = 0; InVBlank = true; // TODO: factor out in a separate function. LinesPerField = 263; // // // scanline = 0; field = 0; field_ram_readout = 0; PhaseChange = 0; // // // DotClockCounter = 0; GPUClockCounter = 0; LineClockCounter = 3412 - 200; LinePhase = 0; DrawTimeAvail = 0; lastts = 0; SoftReset(); IRQ_Assert(IRQ_VBLANK, InVBlank); TIMER_SetVBlank(InVBlank); } void PS_GPU::ResetTS(void) { lastts = 0; } #include "gpu_common.cpp" #include "gpu_polygon.cpp" #include "gpu_sprite.cpp" #include "gpu_line.cpp" // // C-style function wrappers so our command table isn't so ginormous(in memory usage). // template static void G_Command_DrawPolygon(PS_GPU* g, const uint32 *cb) { g->Command_DrawPolygon(cb); } template static void G_Command_DrawSprite(PS_GPU* g, const uint32 *cb) { g->Command_DrawSprite(cb); } template static void G_Command_DrawLine(PS_GPU* g, const uint32 *cb) { g->Command_DrawLine(cb); } void PS_GPU::InvalidateTexCache() { unsigned i; for (i = 0; i < 256; i++) TexCache[i].Tag = ~0U; } void PS_GPU::InvalidateCache() { CLUT_Cache_VB = ~0U; InvalidateTexCache(); } static void G_Command_ClearCache(PS_GPU* g, const uint32 *cb) { g->InvalidateCache(); } static void G_Command_IRQ(PS_GPU* g, const uint32 *cb) { g->IRQPending = true; IRQ_Assert(IRQ_GPU, g->IRQPending); } // Special RAM write mode(16 pixels at a time), does *not* appear to use mask drawing environment settings. // static void G_Command_FBFill(PS_GPU* gpu, const uint32 *cb) { int32_t x, y, r, g, b, destX, destY, width, height; r = cb[0] & 0xFF; g = (cb[0] >> 8) & 0xFF; b = (cb[0] >> 16) & 0xFF; const uint16_t fill_value = ((r >> 3) << 0) | ((g >> 3) << 5) | ((b >> 3) << 10); destX = (cb[1] >> 0) & 0x3F0; destY = (cb[1] >> 16) & 0x3FF; width = (((cb[2] >> 0) & 0x3FF) + 0xF) & ~0xF; height = (cb[2] >> 16) & 0x1FF; //printf("[GPU] FB Fill %d:%d w=%d, h=%d\n", destX, destY, width, height); gpu->DrawTimeAvail -= 46; // Approximate for(y = 0; y < height; y++) { const int32 d_y = (y + destY) & 511; if(LineSkipTest(gpu, d_y)) continue; gpu->DrawTimeAvail -= (width >> 3) + 9; for(x = 0; x < width; x++) { const int32 d_x = (x + destX) & 1023; gpu->GPURAM[d_y][d_x] = fill_value; } } } static void G_Command_FBCopy(PS_GPU* g, const uint32 *cb) { int32 sourceX = (cb[1] >> 0) & 0x3FF; int32 sourceY = (cb[1] >> 16) & 0x3FF; int32 destX = (cb[2] >> 0) & 0x3FF; int32 destY = (cb[2] >> 16) & 0x3FF; int32 width = (cb[3] >> 0) & 0x3FF; int32 height = (cb[3] >> 16) & 0x1FF; if(!width) width = 0x400; if(!height) height = 0x200; g->InvalidateTexCache(); //printf("FB Copy: %d %d %d %d %d %d\n", sourceX, sourceY, destX, destY, width, height); g->DrawTimeAvail -= (width * height) * 2; for(int32 y = 0; y < height; y++) { for(int32 x = 0; x < width; x += 128) { const int32 chunk_x_max = std::min(width - x, 128); uint16 tmpbuf[128]; // TODO: Check and see if the GPU is actually (ab)using the CLUT or texture cache. for(int32 chunk_x = 0; chunk_x < chunk_x_max; chunk_x++) { int32 s_y = (y + sourceY) & 511; int32 s_x = (x + chunk_x + sourceX) & 1023; tmpbuf[chunk_x] = g->GPURAM[s_y][s_x]; } for(int32 chunk_x = 0; chunk_x < chunk_x_max; chunk_x++) { int32 d_y = (y + destY) & 511; int32 d_x = (x + chunk_x + destX) & 1023; if(!(g->GPURAM[d_y][d_x] & g->MaskEvalAND)) g->GPURAM[d_y][d_x] = tmpbuf[chunk_x] | g->MaskSetOR; } } } } static void G_Command_FBWrite(PS_GPU* g, const uint32 *cb) { //assert(InCmd == INCMD_NONE); g->FBRW_X = (cb[1] >> 0) & 0x3FF; g->FBRW_Y = (cb[1] >> 16) & 0x3FF; g->FBRW_W = (cb[2] >> 0) & 0x3FF; g->FBRW_H = (cb[2] >> 16) & 0x1FF; if(!g->FBRW_W) g->FBRW_W = 0x400; if(!g->FBRW_H) g->FBRW_H = 0x200; g->FBRW_CurX = g->FBRW_X; g->FBRW_CurY = g->FBRW_Y; g->InvalidateTexCache(); if(g->FBRW_W != 0 && g->FBRW_H != 0) g->InCmd = INCMD_FBWRITE; } /* FBRead: PS1 GPU in SCPH-5501 gives odd, inconsistent results when * raw_height == 0, or raw_height != 0x200 && (raw_height & 0x1FF) == 0 */ static void G_Command_FBRead(PS_GPU* g, const uint32 *cb) { //assert(g->InCmd == INCMD_NONE); g->FBRW_X = (cb[1] >> 0) & 0x3FF; g->FBRW_Y = (cb[1] >> 16) & 0x3FF; g->FBRW_W = (cb[2] >> 0) & 0x3FF; g->FBRW_H = (cb[2] >> 16) & 0x3FF; if(!g->FBRW_W) g->FBRW_W = 0x400; if(g->FBRW_H > 0x200) g->FBRW_H &= 0x1FF; g->FBRW_CurX = g->FBRW_X; g->FBRW_CurY = g->FBRW_Y; g->InvalidateTexCache(); if(g->FBRW_W != 0 && g->FBRW_H != 0) g->InCmd = INCMD_FBREAD; } static void G_Command_DrawMode(PS_GPU* g, const uint32 *cb) { const uint32 cmdw = *cb; g->SetTPage(cmdw); g->SpriteFlip = (cmdw & 0x3000); g->dtd = (cmdw >> 9) & 1; g->dfe = (cmdw >> 10) & 1; //printf("*******************DFE: %d -- scanline=%d\n", dfe, scanline); } static void G_Command_TexWindow(PS_GPU* g, const uint32 *cb) { g->tww = (*cb & 0x1F); g->twh = ((*cb >> 5) & 0x1F); g->twx = ((*cb >> 10) & 0x1F); g->twy = ((*cb >> 15) & 0x1F); g->RecalcTexWindowStuff(); } static void G_Command_Clip0(PS_GPU* g, const uint32 *cb) { g->ClipX0 = *cb & 1023; g->ClipY0 = (*cb >> 10) & 1023; } static void G_Command_Clip1(PS_GPU* g, const uint32 *cb) { g->ClipX1 = *cb & 1023; g->ClipY1 = (*cb >> 10) & 1023; } static void G_Command_DrawingOffset(PS_GPU* g, const uint32 *cb) { g->OffsX = sign_x_to_s32(11, (*cb & 2047)); g->OffsY = sign_x_to_s32(11, ((*cb >> 11) & 2047)); //fprintf(stderr, "[GPU] Drawing offset: %d(raw=%d) %d(raw=%d) -- %d\n", OffsX, *cb, OffsY, *cb >> 11, scanline); } static void G_Command_MaskSetting(PS_GPU* g, const uint32 *cb) { //printf("Mask setting: %08x\n", *cb); g->MaskSetOR = (*cb & 1) ? 0x8000 : 0x0000; g->MaskEvalAND = (*cb & 2) ? 0x8000 : 0x0000; } CTEntry PS_GPU::Commands[256] = { /* 0x00 */ NULLCMD(), OTHER_HELPER(1, 2, false, G_Command_ClearCache), OTHER_HELPER(3, 3, false, G_Command_FBFill), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), /* 0x10 */ NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), OTHER_HELPER(1, 1, false, G_Command_IRQ), /* 0x20 */ POLY_HELPER(0x20), POLY_HELPER(0x21), POLY_HELPER(0x22), POLY_HELPER(0x23), POLY_HELPER(0x24), POLY_HELPER(0x25), POLY_HELPER(0x26), POLY_HELPER(0x27), POLY_HELPER(0x28), POLY_HELPER(0x29), POLY_HELPER(0x2a), POLY_HELPER(0x2b), POLY_HELPER(0x2c), POLY_HELPER(0x2d), POLY_HELPER(0x2e), POLY_HELPER(0x2f), POLY_HELPER(0x30), POLY_HELPER(0x31), POLY_HELPER(0x32), POLY_HELPER(0x33), POLY_HELPER(0x34), POLY_HELPER(0x35), POLY_HELPER(0x36), POLY_HELPER(0x37), POLY_HELPER(0x38), POLY_HELPER(0x39), POLY_HELPER(0x3a), POLY_HELPER(0x3b), POLY_HELPER(0x3c), POLY_HELPER(0x3d), POLY_HELPER(0x3e), POLY_HELPER(0x3f), LINE_HELPER(0x40), LINE_HELPER(0x41), LINE_HELPER(0x42), LINE_HELPER(0x43), LINE_HELPER(0x44), LINE_HELPER(0x45), LINE_HELPER(0x46), LINE_HELPER(0x47), LINE_HELPER(0x48), LINE_HELPER(0x49), LINE_HELPER(0x4a), LINE_HELPER(0x4b), LINE_HELPER(0x4c), LINE_HELPER(0x4d), LINE_HELPER(0x4e), LINE_HELPER(0x4f), LINE_HELPER(0x50), LINE_HELPER(0x51), LINE_HELPER(0x52), LINE_HELPER(0x53), LINE_HELPER(0x54), LINE_HELPER(0x55), LINE_HELPER(0x56), LINE_HELPER(0x57), LINE_HELPER(0x58), LINE_HELPER(0x59), LINE_HELPER(0x5a), LINE_HELPER(0x5b), LINE_HELPER(0x5c), LINE_HELPER(0x5d), LINE_HELPER(0x5e), LINE_HELPER(0x5f), SPR_HELPER(0x60), SPR_HELPER(0x61), SPR_HELPER(0x62), SPR_HELPER(0x63), SPR_HELPER(0x64), SPR_HELPER(0x65), SPR_HELPER(0x66), SPR_HELPER(0x67), SPR_HELPER(0x68), SPR_HELPER(0x69), SPR_HELPER(0x6a), SPR_HELPER(0x6b), SPR_HELPER(0x6c), SPR_HELPER(0x6d), SPR_HELPER(0x6e), SPR_HELPER(0x6f), SPR_HELPER(0x70), SPR_HELPER(0x71), SPR_HELPER(0x72), SPR_HELPER(0x73), SPR_HELPER(0x74), SPR_HELPER(0x75), SPR_HELPER(0x76), SPR_HELPER(0x77), SPR_HELPER(0x78), SPR_HELPER(0x79), SPR_HELPER(0x7a), SPR_HELPER(0x7b), SPR_HELPER(0x7c), SPR_HELPER(0x7d), SPR_HELPER(0x7e), SPR_HELPER(0x7f), /* 0x80 ... 0x9F */ OTHER_HELPER_X32(4, 2, false, G_Command_FBCopy), /* 0xA0 ... 0xBF */ OTHER_HELPER_X32(3, 2, false, G_Command_FBWrite), /* 0xC0 ... 0xDF */ OTHER_HELPER_X32(3, 2, false, G_Command_FBRead), /* 0xE0 */ NULLCMD(), OTHER_HELPER(1, 2, false, G_Command_DrawMode), OTHER_HELPER(1, 2, false, G_Command_TexWindow), OTHER_HELPER(1, 1, true, G_Command_Clip0), OTHER_HELPER(1, 1, true, G_Command_Clip1), OTHER_HELPER(1, 1, true, G_Command_DrawingOffset), OTHER_HELPER(1, 2, false, G_Command_MaskSetting), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), /* 0xF0 */ NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), NULLCMD(), }; void PS_GPU::ProcessFIFO(void) { uint32_t CB[0x10], InData; unsigned i; uint32_t cc = InCmd_CC; unsigned command_len; const CTEntry *command = &Commands[cc]; bool read_fifo = false; if(!BlitterFIFO.CanRead()) return; switch(InCmd) { default: case INCMD_NONE: break; case INCMD_FBREAD: return; case INCMD_FBWRITE: InData = BlitterFIFO.Read(); for(i = 0; i < 2; i++) { if(!(GPURAM[FBRW_CurY & 511][FBRW_CurX & 1023] & MaskEvalAND)) GPURAM[FBRW_CurY & 511][FBRW_CurX & 1023] = InData | MaskSetOR; FBRW_CurX++; if(FBRW_CurX == (FBRW_X + FBRW_W)) { FBRW_CurX = FBRW_X; FBRW_CurY++; if(FBRW_CurY == (FBRW_Y + FBRW_H)) { InCmd = INCMD_NONE; break; // Break out of the for() loop. } } InData >>= 16; } return; case INCMD_QUAD: if(DrawTimeAvail < 0) return; command_len = 1 + (bool)(cc & 0x4) + (bool)(cc & 0x10); read_fifo = true; break; case INCMD_PLINE: if(DrawTimeAvail < 0) return; command_len = 1 + (bool)(InCmd_CC & 0x10); if((BlitterFIFO.Peek() & 0xF000F000) == 0x50005000) { BlitterFIFO.Read(); InCmd = INCMD_NONE; return; } read_fifo = true; break; } if (!read_fifo) { cc = BlitterFIFO.Peek() >> 24; command = &Commands[cc]; command_len = command->len; if(DrawTimeAvail < 0 && !command->ss_cmd) return; } if(BlitterFIFO.CanRead() < command_len) return; for(i = 0; i < command_len; i++) CB[i] = BlitterFIFO.Read(); if (!read_fifo) { if(!command->ss_cmd) DrawTimeAvail -= 2; // A very very ugly kludge to support texture mode specialization. fixme/cleanup/SOMETHING in the future. /* Don't alter SpriteFlip here. */ if(cc >= 0x20 && cc <= 0x3F && (cc & 0x4)) SetTPage(CB[4 + ((cc >> 4) & 0x1)] >> 16); } if ((cc >= 0x80) && (cc <= 0x9F)) G_Command_FBCopy(this, CB); else if ((cc >= 0xA0) && (cc <= 0xBF)) G_Command_FBWrite(this, CB); else if ((cc >= 0xC0) && (cc <= 0xDF)) G_Command_FBRead(this, CB); else switch (cc) { case 0x01: CLUT_Cache_VB = ~0U; InvalidateTexCache(); break; case 0x02: G_Command_FBFill(this, CB); break; case 0x1F: this->IRQPending = true; IRQ_Assert(IRQ_GPU, this->IRQPending); break; case 0xe1: G_Command_DrawMode(this, CB); break; case 0xe2: G_Command_TexWindow(this, CB); break; case 0xe3: /* Clip 0 */ this->ClipX0 = *CB & 1023; this->ClipY0 = (*CB >> 10) & 1023; break; case 0xe4: /* Clip 1 */ this->ClipX1 = *CB & 1023; this->ClipY1 = (*CB >> 10) & 1023; break; case 0xe5: /* Drawing Offset */ this->OffsX = sign_x_to_s32(11, (*CB & 2047)); this->OffsY = sign_x_to_s32(11, ((*CB >> 11) & 2047)); break; case 0xe6: /* Mask Setting */ this->MaskSetOR = (*CB & 1) ? 0x8000 : 0x0000; this->MaskEvalAND = (*CB & 2) ? 0x8000 : 0x0000; break; default: if(command->func[abr][TexMode]) command->func[abr][TexMode | (MaskEvalAND ? 0x4 : 0x0)](this, CB); break; } } INLINE void PS_GPU::WriteCB(uint32_t InData) { if(BlitterFIFO.CanRead() >= 0x10 && (InCmd != INCMD_NONE || (BlitterFIFO.CanRead() - 0x10) >= Commands[BlitterFIFO.Peek() >> 24].fifo_fb_len)) { PSX_DBG(PSX_DBG_WARNING, "GPU FIFO overflow!!!\n"); return; } BlitterFIFO.Write(InData); ProcessFIFO(); } void PS_GPU::SetTPage(const uint32_t cmdw) { const unsigned NewTexPageX = (cmdw & 0xF) * 64; const unsigned NewTexPageY = (cmdw & 0x10) * 16; const unsigned NewTexMode = (cmdw >> 7) & 0x3; abr = (cmdw >> 5) & 0x3; if(!NewTexMode != !TexMode || NewTexPageX != TexPageX || NewTexPageY != TexPageY) { InvalidateTexCache(); } if(TexDisableAllowChange) { bool NewTexDisable = (cmdw >> 11) & 1; if (NewTexDisable != TexDisable) InvalidateTexCache(); TexDisable = NewTexDisable; //printf("TexDisable: %02x\n", TexDisable); } TexPageX = NewTexPageX; TexPageY = NewTexPageY; TexMode = NewTexMode; } void PS_GPU::Write(const int32_t timestamp, uint32_t A, uint32_t V) { V <<= (A & 3) * 8; if(A & 4) // GP1 ("Control") { uint32_t command = V >> 24; V &= 0x00FFFFFF; //PSX_WARNING("[GPU] Control command: %02x %06x %d", command, V, scanline); switch(command) { /* 0x40-0xFF do NOT appear to be mirrors, at least not on my PS1's GPU. */ default: PSX_WARNING("[GPU] Unknown control command %02x - %06x", command, V); break; case 0x00: // Reset GPU //printf("\n\n************ Soft Reset %u ********* \n\n", scanline); SoftReset(); break; case 0x01: // Reset command buffer if(DrawTimeAvail < 0) DrawTimeAvail = 0; BlitterFIFO.Flush(); InCmd = INCMD_NONE; break; case 0x02: // Acknowledge IRQ IRQPending = false; IRQ_Assert(IRQ_GPU, IRQPending); break; case 0x03: // Display enable DisplayOff = V & 1; break; case 0x04: // DMA Setup DMAControl = V & 0x3; break; case 0x05: // Start of display area in framebuffer DisplayFB_XStart = V & 0x3FE; // Lower bit is apparently ignored. DisplayFB_YStart = (V >> 10) & 0x1FF; break; case 0x06: // Horizontal display range HorizStart = V & 0xFFF; HorizEnd = (V >> 12) & 0xFFF; break; case 0x07: VertStart = V & 0x3FF; VertEnd = (V >> 10) & 0x3FF; break; case 0x08: //printf("\n\nDISPLAYMODE SET: 0x%02x, %u *************************\n\n\n", V & 0xFF, scanline); DisplayMode = V & 0xFF; break; case 0x09: TexDisableAllowChange = V & 1; break; case 0x10: // GPU info(?) switch(V & 0xF) { // DataReadBuffer must remain unchanged for any unhandled GPU info index. default: break; case 0x2: DataReadBufferEx &= 0xFFF00000; DataReadBufferEx |= (tww << 0) | (twh << 5) | (twx << 10) | (twy << 15); DataReadBuffer = DataReadBufferEx; break; case 0x3: DataReadBufferEx &= 0xFFF00000; DataReadBufferEx |= (ClipY0 << 10) | ClipX0; DataReadBuffer = DataReadBufferEx; break; case 0x4: DataReadBufferEx &= 0xFFF00000; DataReadBufferEx |= (ClipY1 << 10) | ClipX1; DataReadBuffer = DataReadBufferEx; break; case 0x5: DataReadBufferEx &= 0xFFC00000; DataReadBufferEx |= (OffsX & 2047) | ((OffsY & 2047) << 11); DataReadBuffer = DataReadBufferEx; break; case 0x7: DataReadBufferEx = 2; DataReadBuffer = DataReadBufferEx; break; case 0x8: DataReadBufferEx = 0; DataReadBuffer = DataReadBufferEx; break; } break; } } else // GP0 ("Data") { //uint32_t command = V >> 24; //printf("Meow command: %02x\n", command); //assert(!(DMAControl & 2)); WriteCB(V); } } void PS_GPU::WriteDMA(uint32_t V) { WriteCB(V); } INLINE uint32_t PS_GPU::ReadData(void) { if(InCmd == INCMD_FBREAD) { DataReadBufferEx = 0; for(int i = 0; i < 2; i++) { DataReadBufferEx |= GPURAM[FBRW_CurY & 511][FBRW_CurX & 1023] << (i * 16); FBRW_CurX++; if(FBRW_CurX == (FBRW_X + FBRW_W)) { if((FBRW_CurY + 1) == (FBRW_Y + FBRW_H)) { InCmd = INCMD_NONE; } else { FBRW_CurY++; FBRW_CurX = FBRW_X; } } } return DataReadBufferEx; } return DataReadBuffer; } uint32_t PS_GPU::ReadDMA(void) { return ReadData(); } uint32_t PS_GPU::Read(const int32_t timestamp, uint32_t A) { uint32_t ret = 0; if(A & 4) // Status { ret = (((DisplayMode << 1) & 0x7F) | ((DisplayMode >> 6) & 1)) << 16; ret |= (DisplayMode & 0x80) << 7; ret |= DMAControl << 29; ret |= (DisplayFB_CurLineYReadout & 1) << 31; ret |= (!field) << 13; if(DMAControl & 0x02) ret |= 1 << 25; ret |= IRQPending << 24; ret |= DisplayOff << 23; if(InCmd == INCMD_NONE && DrawTimeAvail >= 0 && BlitterFIFO.CanRead() == 0x00) // GPU idle bit. ret |= 1 << 26; if(InCmd == INCMD_FBREAD) // Might want to more accurately emulate this in the future? ret |= (1 << 27); ret |= CalcFIFOReadyBit() << 28; // FIFO has room bit? (kinda). // // ret |= TexPageX >> 6; ret |= TexPageY >> 4; ret |= abr << 5; ret |= TexMode << 7; ret |= dtd << 9; ret |= dfe << 10; if(MaskSetOR) ret |= 1 << 11; if(MaskEvalAND) ret |= 1 << 12; ret |= TexDisable << 15; } else // "Data" ret = ReadData(); if(DMAControl & 2) { //PSX_WARNING("[GPU READ WHEN (DMACONTROL&2)] 0x%08x - ret=0x%08x, scanline=%d", A, ret, scanline); } return(ret >> ((A & 3) * 8)); } INLINE void PS_GPU::ReorderRGB_Var(uint32_t out_Rshift, uint32_t out_Gshift, uint32_t out_Bshift, bool bpp24, const uint16_t *src, uint32_t *dest, const int32 dx_start, const int32 dx_end, int32 fb_x) { if(bpp24) // 24bpp { for(int32 x = dx_start; x < dx_end; x++) { uint32_t srcpix; srcpix = src[(fb_x >> 1) + 0] | (src[((fb_x >> 1) + 1) & 0x7FF] << 16); srcpix >>= (fb_x & 1) * 8; dest[x] = (((srcpix >> 0) << RED_SHIFT) & (0xFF << RED_SHIFT)) | (((srcpix >> 8) << GREEN_SHIFT) & (0xFF << GREEN_SHIFT)) | (((srcpix >> 16) << BLUE_SHIFT) & (0xFF << BLUE_SHIFT)); fb_x = (fb_x + 3) & 0x7FF; } } // 15bpp else { for(int32 x = dx_start; x < dx_end; x++) { uint32_t srcpix = src[fb_x >> 1]; dest[x] = MAKECOLOR((((srcpix >> 0) & 0x1F) << 3), (((srcpix >> 5) & 0x1F) << 3), (((srcpix >> 10) & 0x1F) << 3), 0); fb_x = (fb_x + 2) & 0x7FF; } } } int32_t PS_GPU::Update(const int32_t sys_timestamp) { static const uint32_t DotClockRatios[5] = { 10, 8, 5, 4, 7 }; const uint32_t dmc = (DisplayMode & 0x40) ? 4 : (DisplayMode & 0x3); const uint32_t dmw = 2800 / DotClockRatios[dmc]; // Must be <= 768 int32 sys_clocks = sys_timestamp - lastts; int32 gpu_clocks; //printf("GPUISH: %d\n", sys_timestamp - lastts); if(!sys_clocks) goto TheEnd; DrawTimeAvail += sys_clocks << 1; if(DrawTimeAvail > 256) DrawTimeAvail = 256; ProcessFIFO(); //puts("GPU Update Start"); GPUClockCounter += (uint64)sys_clocks * GPUClockRatio; gpu_clocks = GPUClockCounter >> 16; GPUClockCounter -= gpu_clocks << 16; while(gpu_clocks > 0) { int32 chunk_clocks = gpu_clocks; int32 dot_clocks; if(chunk_clocks > LineClockCounter) { //printf("Chunk: %u, LCC: %u\n", chunk_clocks, LineClockCounter); chunk_clocks = LineClockCounter; } gpu_clocks -= chunk_clocks; LineClockCounter -= chunk_clocks; DotClockCounter += chunk_clocks; dot_clocks = DotClockCounter / DotClockRatios[DisplayMode & 0x3]; DotClockCounter -= dot_clocks * DotClockRatios[DisplayMode & 0x3]; TIMER_AddDotClocks(dot_clocks); if(!LineClockCounter) { PSX_SetEventNT(PSX_EVENT_TIMER, TIMER_Update(sys_timestamp)); // We could just call this at the top of GPU_Update(), but do it here for slightly less CPU usage(presumably). LinePhase = (LinePhase + 1) & 1; if(LinePhase) { TIMER_SetHRetrace(true); LineClockCounter = 200; TIMER_ClockHRetrace(); } else { const unsigned int FirstVisibleLine = LineVisFirst + (HardwarePALType ? 20 : 16); const unsigned int VisibleLineCount = LineVisLast + 1 - LineVisFirst; //HardwarePALType ? 288 : 240; TIMER_SetHRetrace(false); if(DisplayMode & 0x08) LineClockCounter = 3405 - 200; else LineClockCounter = 3412 + PhaseChange - 200; scanline = (scanline + 1) % LinesPerField; PhaseChange = !PhaseChange; #ifdef WANT_DEBUGGER DBG_GPUScanlineHook(scanline); #endif // // // if(scanline == (HardwarePALType ? 308 : 256)) // Will need to be redone if we ever allow for visible vertical overscan with NTSC. { if(sl_zero_reached) { //printf("Req Exit(visible fallthrough case): %u\n", scanline); PSX_RequestMLExit(); } } if(scanline == (LinesPerField - 1)) { if(sl_zero_reached) { //printf("Req Exit(final fallthrough case): %u\n", scanline); PSX_RequestMLExit(); } if(DisplayMode & 0x20) field = !field; else field = 0; } if(scanline == 0) { assert(sl_zero_reached == false); sl_zero_reached = true; if(DisplayMode & 0x20) { if(DisplayMode & 0x08) // PAL LinesPerField = 313 - field; else // NTSC LinesPerField = 263 - field; } else { field = 0; // May not be the correct place for this? if(DisplayMode & 0x08) // PAL LinesPerField = 314; else // NTSC LinesPerField = 263; } if(espec) { if((bool)(DisplayMode & 0x08) != HardwarePALType) { DisplayRect->x = 0; DisplayRect->y = 0; DisplayRect->w = 384; DisplayRect->h = VisibleLineCount; for(int32 y = 0; y < DisplayRect->h; y++) { uint32_t *dest = surface->pixels + y * surface->pitch32; LineWidths[y] = 384; memset(dest, 0, 384 * sizeof(int32)); } //char buffer[256]; //snprintf(buffer, sizeof(buffer), _("VIDEO STANDARD MISMATCH")); //DrawTextTrans(surface->pixels + ((DisplayRect->h / 2) - (13 / 2)) * surface->pitch32, surface->pitch32 << 2, DisplayRect->w, (UTF8*)buffer, //MAKECOLOR(0x00, 0xFF, 0x00), true, MDFN_FONT_6x13_12x13, 0); } else { espec->InterlaceOn = (bool)(DisplayMode & 0x20); espec->InterlaceField = (bool)(DisplayMode & 0x20) && field; DisplayRect->x = 0; DisplayRect->y = 0; DisplayRect->w = 0; DisplayRect->h = VisibleLineCount << (bool)(DisplayMode & 0x20); // Clear ~0 state. LineWidths[0] = 0; for(int i = 0; i < (DisplayRect->y + DisplayRect->h); i++) { surface->pixels[i * surface->pitch32 + 0] = surface->pixels[i * surface->pitch32 + 1] = 0; LineWidths[i] = 2; } } } } // // Don't mess with the order of evaluation of these scanline == VertXXX && (InVblankwhatever) if statements and the following IRQ/timer vblank stuff // unless you know what you're doing!!! (IE you've run further tests to refine the behavior) // if(scanline == VertEnd && !InVBlank) { if(sl_zero_reached) { // Gameplay in Descent(NTSC) has vblank at scanline 236 // // Mikagura Shoujo Tanteidan has vblank at scanline 192 during intro // FMV(which we don't handle here because low-latency in that case is not so important). // if(scanline >= (HardwarePALType ? 260 : 232)) { //printf("Req Exit(vblank case): %u\n", scanline); PSX_RequestMLExit(); } #if 0 else { //printf("VBlank too early, chickening out early exit: %u!\n", scanline); } #endif } //printf("VBLANK: %u\n", scanline); InVBlank = true; DisplayFB_CurYOffset = 0; if((DisplayMode & 0x24) == 0x24) field_ram_readout = !field; else field_ram_readout = 0; } if(scanline == VertStart && InVBlank) { InVBlank = false; // Note to self: X-Men Mutant Academy relies on this being set on the proper scanline in 480i mode(otherwise it locks up on startup). //if(HeightMode) // DisplayFB_CurYOffset = field; } IRQ_Assert(IRQ_VBLANK, InVBlank); TIMER_SetVBlank(InVBlank); // // // // Needs to occur even in vblank. // Not particularly confident about the timing of this in regards to vblank and the upper bit(ODE) of the GPU status port, though the test that // showed an oddity was pathological in that VertEnd < VertStart in it. if((DisplayMode & 0x24) == 0x24) DisplayFB_CurLineYReadout = (DisplayFB_YStart + (DisplayFB_CurYOffset << 1) + (InVBlank ? 0 : field_ram_readout)) & 0x1FF; else DisplayFB_CurLineYReadout = (DisplayFB_YStart + DisplayFB_CurYOffset) & 0x1FF; unsigned dmw_width = 0; unsigned pix_clock_offset = 0; unsigned pix_clock = 0; unsigned pix_clock_div = 0; uint32_t *dest = NULL; if((bool)(DisplayMode & 0x08) == HardwarePALType && scanline >= FirstVisibleLine && scanline < (FirstVisibleLine + VisibleLineCount)) { int32 dest_line; int32 fb_x = DisplayFB_XStart * 2; int32 dx_start = HorizStart, dx_end = HorizEnd; dest_line = ((scanline - FirstVisibleLine) << espec->InterlaceOn) + espec->InterlaceField; dest = surface->pixels + dest_line * surface->pitch32; if(dx_end < dx_start) dx_end = dx_start; dx_start = dx_start / DotClockRatios[dmc]; dx_end = dx_end / DotClockRatios[dmc]; dx_start -= 488 / DotClockRatios[dmc]; dx_end -= 488 / DotClockRatios[dmc]; if(dx_start < 0) { fb_x -= dx_start * ((DisplayMode & 0x10) ? 3 : 2); fb_x &= 0x7FF; //0x3FF; dx_start = 0; } if((uint32)dx_end > dmw) dx_end = dmw; if(InVBlank || DisplayOff) dx_start = dx_end = 0; LineWidths[dest_line] = dmw; { uint32_t x; const uint16_t *src = GPURAM[DisplayFB_CurLineYReadout]; memset(dest, 0, dx_start * sizeof(int32)); //printf("%d %d %d - %d %d\n", scanline, dx_start, dx_end, HorizStart, HorizEnd); ReorderRGB_Var(RED_SHIFT, GREEN_SHIFT, BLUE_SHIFT, DisplayMode & 0x10, src, dest, dx_start, dx_end, fb_x); for(x = dx_end; x < dmw; x++) dest[x] = 0; } //if(scanline == 64) // printf("%u\n", sys_timestamp - ((uint64)gpu_clocks * 65536) / GPUClockRatio); dmw_width = dmw; pix_clock_offset = (488 - 146) / DotClockRatios[dmc]; pix_clock = (HardwarePALType ? 53203425 : 53693182) / DotClockRatios[dmc]; pix_clock_div = DotClockRatios[dmc]; } PSX_GPULineHook(sys_timestamp, sys_timestamp - ((uint64)gpu_clocks * 65536) / GPUClockRatio, scanline == 0, dest, &surface->format, dmw_width, pix_clock_offset, pix_clock, pix_clock_div); if(!InVBlank) { DisplayFB_CurYOffset = (DisplayFB_CurYOffset + 1) & 0x1FF; } } PSX_SetEventNT(PSX_EVENT_TIMER, TIMER_Update(sys_timestamp)); // Mostly so the next event time gets recalculated properly in regards to our calls // to TIMER_SetVBlank() and TIMER_SetHRetrace(). } // end if(!LineClockCounter) } // end while(gpu_clocks > 0) //puts("GPU Update End"); TheEnd: lastts = sys_timestamp; { int32 next_dt = LineClockCounter; next_dt = (((int64)next_dt << 16) - GPUClockCounter + GPUClockRatio - 1) / GPUClockRatio; next_dt = std::max(1, next_dt); next_dt = std::min(128, next_dt); //printf("%d\n", next_dt); return(sys_timestamp + next_dt); } } void PS_GPU::StartFrame(EmulateSpecStruct *espec_arg) { sl_zero_reached = false; espec = espec_arg; surface = espec->surface; DisplayRect = &espec->DisplayRect; LineWidths = espec->LineWidths; } int PS_GPU::StateAction(StateMem *sm, int load, int data_only) { uint32 TexCache_Tag[256]; uint16 TexCache_Data[256][4]; for(unsigned i = 0; i < 256; i++) { TexCache_Tag[i] = TexCache[i].Tag; for(unsigned j = 0; j < 4; j++) TexCache_Data[i][j] = TexCache[i].Data[j]; } SFORMAT StateRegs[] = { SFARRAY16(&GPURAM[0][0], sizeof(GPURAM) / sizeof(GPURAM[0][0])), SFVAR(DMAControl), SFVAR(ClipX0), SFVAR(ClipY0), SFVAR(ClipX1), SFVAR(ClipY1), SFVAR(OffsX), SFVAR(OffsY), SFVAR(dtd), SFVAR(dfe), SFVAR(MaskSetOR), SFVAR(MaskEvalAND), SFVAR(TexDisable), SFVAR(TexDisableAllowChange), SFVAR(tww), SFVAR(twh), SFVAR(twx), SFVAR(twy), SFVAR(TexPageX), SFVAR(TexPageY), SFVAR(SpriteFlip), SFVAR(abr), SFVAR(TexMode), SFARRAY32(&BlitterFIFO.data[0], sizeof(BlitterFIFO.data) / sizeof(BlitterFIFO.data[0])), SFVAR(BlitterFIFO.read_pos), SFVAR(BlitterFIFO.write_pos), SFVAR(BlitterFIFO.in_count), SFVAR(DataReadBuffer), SFVAR(DataReadBufferEx), SFVAR(IRQPending), SFVAR(InCmd), SFVAR(InCmd_CC), #define TVHELPER(n) SFVAR(n.x), SFVAR(n.y), SFVAR(n.u), SFVAR(n.v), SFVAR(n.r), SFVAR(n.g), SFVAR(n.b) TVHELPER(InQuad_F3Vertices[0]), TVHELPER(InQuad_F3Vertices[1]), TVHELPER(InQuad_F3Vertices[2]), #undef TVHELPER SFVAR(InPLine_PrevPoint.x), SFVAR(InPLine_PrevPoint.y), SFVAR(InPLine_PrevPoint.r), SFVAR(InPLine_PrevPoint.g), SFVAR(InPLine_PrevPoint.b), SFVAR(FBRW_X), SFVAR(FBRW_Y), SFVAR(FBRW_W), SFVAR(FBRW_H), SFVAR(FBRW_CurY), SFVAR(FBRW_CurX), SFVAR(DisplayMode), SFVAR(DisplayOff), SFVAR(DisplayFB_XStart), SFVAR(DisplayFB_YStart), SFVAR(HorizStart), SFVAR(HorizEnd), SFVAR(VertStart), SFVAR(VertEnd), SFVAR(DisplayFB_CurYOffset), SFVAR(DisplayFB_CurLineYReadout), SFVAR(InVBlank), SFVAR(LinesPerField), SFVAR(scanline), SFVAR(field), SFVAR(field_ram_readout), SFVAR(PhaseChange), SFVAR(DotClockCounter), SFVAR(GPUClockCounter), SFVAR(LineClockCounter), SFVAR(LinePhase), SFVAR(DrawTimeAvail), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "GPU"); if(load) { for(unsigned i = 0; i < 256; i++) { TexCache[i].Tag = TexCache_Tag[i]; for(unsigned j = 0; j < 4; j++) TexCache[i].Data[j] = TexCache_Data[i][j]; } RecalcTexWindowStuff(); BlitterFIFO.SaveStatePostLoad(); HorizStart &= 0xFFF; HorizEnd &= 0xFFF; IRQ_Assert(IRQ_GPU, IRQPending); } return(ret); } libretro-common/include/retro_file.h000664 001750 001750 00000004274 12611054044 020744 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_file.h). * --------------------------------------------------------------------------------------- * * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __RETRO_FILE_H #define __RETRO_FILE_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct RFILE RFILE; enum { RFILE_MODE_READ = 0, RFILE_MODE_WRITE, RFILE_MODE_READ_WRITE }; RFILE *retro_fopen(const char *path, unsigned mode, ssize_t len); ssize_t retro_fseek(RFILE *stream, ssize_t offset, int whence); ssize_t retro_fread(RFILE *stream, void *s, size_t len); ssize_t retro_fwrite(RFILE *stream, const void *s, size_t len); ssize_t retro_ftell(RFILE *stream); void retro_frewind(RFILE *stream); int retro_fclose(RFILE *stream); int retro_read_file(const char *path, void **buf, ssize_t *len); bool retro_write_file(const char *path, const void *data, ssize_t size); int retro_get_fd(RFILE *stream); #ifdef __cplusplus } #endif #endif mednafen/tremor/window_lookup.h000664 001750 001750 00000371447 12611054044 020055 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: window lookup tables ********************************************************************/ #include "os_types.h" static const LOOKUP_T vwin64[32] = { X(0x001f0003), X(0x01168c98), X(0x030333c8), X(0x05dfe3a4), X(0x09a49562), X(0x0e45df18), X(0x13b47ef2), X(0x19dcf676), X(0x20a74d83), X(0x27f7137c), X(0x2fabb05a), X(0x37a1105a), X(0x3fb0ab28), X(0x47b2dcd1), X(0x4f807bc6), X(0x56f48e70), X(0x5dedfc79), X(0x64511653), X(0x6a08cfff), X(0x6f079328), X(0x734796f4), X(0x76cab7f2), X(0x7999d6e8), X(0x7bc3cf9f), X(0x7d5c20c1), X(0x7e7961df), X(0x7f33a567), X(0x7fa2e1d0), X(0x7fdd78a5), X(0x7ff6ec6d), X(0x7ffed0e9), X(0x7ffffc3f), }; static const LOOKUP_T vwin128[64] = { X(0x0007c04d), X(0x0045bb89), X(0x00c18b87), X(0x017ae294), X(0x02714a4e), X(0x03a4217a), X(0x05129952), X(0x06bbb24f), X(0x089e38a1), X(0x0ab8c073), X(0x0d09a228), X(0x0f8ef6bd), X(0x12469488), X(0x152e0c7a), X(0x1842a81c), X(0x1b81686d), X(0x1ee705d9), X(0x226ff15d), X(0x26185705), X(0x29dc21cc), X(0x2db700fe), X(0x31a46f08), X(0x359fb9c1), X(0x39a40c0c), X(0x3dac78b6), X(0x41b40674), X(0x45b5bcb0), X(0x49acb109), X(0x4d94152b), X(0x516744bd), X(0x5521d320), X(0x58bf98a5), X(0x5c3cbef4), X(0x5f95cc5d), X(0x62c7add7), X(0x65cfbf64), X(0x68abd2ba), X(0x6b5a3405), X(0x6dd9acab), X(0x7029840d), X(0x72497e38), X(0x7439d8ac), X(0x75fb4532), X(0x778ee30a), X(0x78f6367e), X(0x7a331f1a), X(0x7b47cccd), X(0x7c36b416), X(0x7d028192), X(0x7dae0d18), X(0x7e3c4caa), X(0x7eb04763), X(0x7f0d08a7), X(0x7f5593b7), X(0x7f8cd7d5), X(0x7fb5a513), X(0x7fd2a1fc), X(0x7fe64212), X(0x7ff2bd4c), X(0x7ffa0890), X(0x7ffdcf39), X(0x7fff6dac), X(0x7fffed01), X(0x7fffffc4), }; static const LOOKUP_T vwin256[128] = { X(0x0001f018), X(0x00117066), X(0x00306e9e), X(0x005ee5f1), X(0x009ccf26), X(0x00ea208b), X(0x0146cdea), X(0x01b2c87f), X(0x022dfedf), X(0x02b85ced), X(0x0351cbbd), X(0x03fa317f), X(0x04b17167), X(0x05776b90), X(0x064bfcdc), X(0x072efedd), X(0x082047b4), X(0x091fa9f1), X(0x0a2cf477), X(0x0b47f25d), X(0x0c706ad2), X(0x0da620ff), X(0x0ee8d3ef), X(0x10383e75), X(0x11941716), X(0x12fc0ff6), X(0x146fd6c8), X(0x15ef14c2), X(0x17796e8e), X(0x190e844f), X(0x1aadf196), X(0x1c574d6e), X(0x1e0a2a62), X(0x1fc61688), X(0x218a9b9c), X(0x23573f12), X(0x252b823d), X(0x2706e269), X(0x28e8d913), X(0x2ad0dc0e), X(0x2cbe5dc1), X(0x2eb0cd60), X(0x30a79733), X(0x32a224d5), X(0x349fdd8b), X(0x36a02690), X(0x38a2636f), X(0x3aa5f65e), X(0x3caa409e), X(0x3eaea2df), X(0x40b27da6), X(0x42b531b8), X(0x44b62086), X(0x46b4ac99), X(0x48b03a05), X(0x4aa82ed5), X(0x4c9bf37d), X(0x4e8af349), X(0x50749ccb), X(0x52586246), X(0x5435ba1c), X(0x560c1f31), X(0x57db1152), X(0x59a21591), X(0x5b60b6a3), X(0x5d168535), X(0x5ec31839), X(0x60660d36), X(0x61ff0886), X(0x638db595), X(0x6511c717), X(0x668af734), X(0x67f907b0), X(0x695bc207), X(0x6ab2f787), X(0x6bfe815a), X(0x6d3e4090), X(0x6e721e16), X(0x6f9a0ab5), X(0x70b5fef8), X(0x71c5fb16), X(0x72ca06cd), X(0x73c2313d), X(0x74ae90b2), X(0x758f4275), X(0x76646a85), X(0x772e335c), X(0x77eccda0), X(0x78a06fd7), X(0x79495613), X(0x79e7c19c), X(0x7a7bf894), X(0x7b064596), X(0x7b86f757), X(0x7bfe6044), X(0x7c6cd615), X(0x7cd2b16e), X(0x7d304d71), X(0x7d860756), X(0x7dd43e06), X(0x7e1b51ad), X(0x7e5ba355), X(0x7e95947e), X(0x7ec986bb), X(0x7ef7db4a), X(0x7f20f2b9), X(0x7f452c7f), X(0x7f64e6a7), X(0x7f807d71), X(0x7f984aff), X(0x7faca700), X(0x7fbde662), X(0x7fcc5b04), X(0x7fd85372), X(0x7fe21a99), X(0x7fe9f791), X(0x7ff02d58), X(0x7ff4fa9e), X(0x7ff89990), X(0x7ffb3faa), X(0x7ffd1d8b), X(0x7ffe5ecc), X(0x7fff29e0), X(0x7fff9ff3), X(0x7fffdcd2), X(0x7ffff6d6), X(0x7ffffed0), X(0x7ffffffc), }; static const LOOKUP_T vwin512[256] = { X(0x00007c06), X(0x00045c32), X(0x000c1c62), X(0x0017bc4c), X(0x00273b7a), X(0x003a9955), X(0x0051d51c), X(0x006cede7), X(0x008be2a9), X(0x00aeb22a), X(0x00d55b0d), X(0x00ffdbcc), X(0x012e32b6), X(0x01605df5), X(0x01965b85), X(0x01d02939), X(0x020dc4ba), X(0x024f2b83), X(0x02945ae6), X(0x02dd5004), X(0x032a07d3), X(0x037a7f19), X(0x03ceb26e), X(0x04269e37), X(0x04823eab), X(0x04e18fcc), X(0x05448d6d), X(0x05ab3329), X(0x06157c68), X(0x0683645e), X(0x06f4e607), X(0x0769fc25), X(0x07e2a146), X(0x085ecfbc), X(0x08de819f), X(0x0961b0cc), X(0x09e856e3), X(0x0a726d46), X(0x0affed1d), X(0x0b90cf4c), X(0x0c250c79), X(0x0cbc9d0b), X(0x0d577926), X(0x0df598aa), X(0x0e96f337), X(0x0f3b8026), X(0x0fe3368f), X(0x108e0d42), X(0x113bfaca), X(0x11ecf56b), X(0x12a0f324), X(0x1357e9ac), X(0x1411ce70), X(0x14ce9698), X(0x158e3702), X(0x1650a444), X(0x1715d2aa), X(0x17ddb638), X(0x18a842aa), X(0x19756b72), X(0x1a4523b9), X(0x1b175e62), X(0x1bec0e04), X(0x1cc324f0), X(0x1d9c9532), X(0x1e78508a), X(0x1f564876), X(0x20366e2e), X(0x2118b2a2), X(0x21fd0681), X(0x22e35a37), X(0x23cb9dee), X(0x24b5c18e), X(0x25a1b4c0), X(0x268f66f1), X(0x277ec74e), X(0x286fc4cc), X(0x29624e23), X(0x2a5651d7), X(0x2b4bbe34), X(0x2c428150), X(0x2d3a8913), X(0x2e33c332), X(0x2f2e1d35), X(0x30298478), X(0x3125e62d), X(0x32232f61), X(0x33214cfc), X(0x34202bc2), X(0x351fb85a), X(0x361fdf4f), X(0x37208d10), X(0x3821adf7), X(0x39232e49), X(0x3a24fa3c), X(0x3b26fdf6), X(0x3c292593), X(0x3d2b5d29), X(0x3e2d90c8), X(0x3f2fac7f), X(0x40319c5f), X(0x41334c81), X(0x4234a905), X(0x43359e16), X(0x443617f3), X(0x453602eb), X(0x46354b65), X(0x4733dde1), X(0x4831a6ff), X(0x492e937f), X(0x4a2a9045), X(0x4b258a5f), X(0x4c1f6f06), X(0x4d182ba2), X(0x4e0fadce), X(0x4f05e35b), X(0x4ffaba53), X(0x50ee20fd), X(0x51e005e1), X(0x52d057ca), X(0x53bf05ca), X(0x54abff3b), X(0x559733c7), X(0x56809365), X(0x57680e62), X(0x584d955d), X(0x59311952), X(0x5a128b96), X(0x5af1dddd), X(0x5bcf023a), X(0x5ca9eb27), X(0x5d828b81), X(0x5e58d68d), X(0x5f2cbffc), X(0x5ffe3be9), X(0x60cd3edf), X(0x6199bdda), X(0x6263ae45), X(0x632b0602), X(0x63efbb66), X(0x64b1c53f), X(0x65711ad0), X(0x662db3d7), X(0x66e7888d), X(0x679e91a5), X(0x6852c84e), X(0x69042635), X(0x69b2a582), X(0x6a5e40dd), X(0x6b06f36c), X(0x6bacb8d2), X(0x6c4f8d30), X(0x6cef6d26), X(0x6d8c55d4), X(0x6e2644d4), X(0x6ebd3840), X(0x6f512ead), X(0x6fe2272e), X(0x7070214f), X(0x70fb1d17), X(0x71831b06), X(0x72081c16), X(0x728a21b5), X(0x73092dc8), X(0x738542a6), X(0x73fe631b), X(0x74749261), X(0x74e7d421), X(0x75582c72), X(0x75c59fd5), X(0x76303333), X(0x7697ebdd), X(0x76fccf85), X(0x775ee443), X(0x77be308a), X(0x781abb2e), X(0x78748b59), X(0x78cba88e), X(0x79201aa7), X(0x7971e9cd), X(0x79c11e79), X(0x7a0dc170), X(0x7a57dbc2), X(0x7a9f76c1), X(0x7ae49c07), X(0x7b27556b), X(0x7b67ad02), X(0x7ba5ad1b), X(0x7be1603a), X(0x7c1ad118), X(0x7c520a9e), X(0x7c8717e1), X(0x7cba0421), X(0x7ceadac3), X(0x7d19a74f), X(0x7d46756e), X(0x7d7150e5), X(0x7d9a4592), X(0x7dc15f69), X(0x7de6aa71), X(0x7e0a32c0), X(0x7e2c0479), X(0x7e4c2bc7), X(0x7e6ab4db), X(0x7e87abe9), X(0x7ea31d24), X(0x7ebd14be), X(0x7ed59edd), X(0x7eecc7a3), X(0x7f029b21), X(0x7f17255a), X(0x7f2a723f), X(0x7f3c8daa), X(0x7f4d835d), X(0x7f5d5f00), X(0x7f6c2c1b), X(0x7f79f617), X(0x7f86c83a), X(0x7f92ada2), X(0x7f9db146), X(0x7fa7ddf3), X(0x7fb13e46), X(0x7fb9dcb0), X(0x7fc1c36c), X(0x7fc8fc83), X(0x7fcf91c7), X(0x7fd58cd2), X(0x7fdaf702), X(0x7fdfd979), X(0x7fe43d1c), X(0x7fe82a8b), X(0x7febaa29), X(0x7feec412), X(0x7ff1801c), X(0x7ff3e5d6), X(0x7ff5fc86), X(0x7ff7cb29), X(0x7ff9586f), X(0x7ffaaaba), X(0x7ffbc81e), X(0x7ffcb660), X(0x7ffd7af3), X(0x7ffe1afa), X(0x7ffe9b42), X(0x7fff0047), X(0x7fff4e2f), X(0x7fff88c9), X(0x7fffb390), X(0x7fffd1a6), X(0x7fffe5d7), X(0x7ffff296), X(0x7ffff9fd), X(0x7ffffdcd), X(0x7fffff6d), X(0x7fffffed), X(0x7fffffff), }; static const LOOKUP_T vwin1024[512] = { X(0x00001f02), X(0x0001170e), X(0x00030724), X(0x0005ef40), X(0x0009cf59), X(0x000ea767), X(0x0014775e), X(0x001b3f2e), X(0x0022fec8), X(0x002bb618), X(0x00356508), X(0x00400b81), X(0x004ba968), X(0x00583ea0), X(0x0065cb0a), X(0x00744e84), X(0x0083c8ea), X(0x00943a14), X(0x00a5a1da), X(0x00b80010), X(0x00cb5488), X(0x00df9f10), X(0x00f4df76), X(0x010b1584), X(0x01224101), X(0x013a61b2), X(0x01537759), X(0x016d81b6), X(0x01888087), X(0x01a47385), X(0x01c15a69), X(0x01df34e6), X(0x01fe02b1), X(0x021dc377), X(0x023e76e7), X(0x02601ca9), X(0x0282b466), X(0x02a63dc1), X(0x02cab85d), X(0x02f023d6), X(0x03167fcb), X(0x033dcbd3), X(0x03660783), X(0x038f3270), X(0x03b94c29), X(0x03e4543a), X(0x04104a2e), X(0x043d2d8b), X(0x046afdd5), X(0x0499ba8c), X(0x04c9632d), X(0x04f9f734), X(0x052b7615), X(0x055ddf46), X(0x05913237), X(0x05c56e53), X(0x05fa9306), X(0x06309fb6), X(0x066793c5), X(0x069f6e93), X(0x06d82f7c), X(0x0711d5d9), X(0x074c60fe), X(0x0787d03d), X(0x07c422e4), X(0x0801583e), X(0x083f6f91), X(0x087e681f), X(0x08be4129), X(0x08fef9ea), X(0x0940919a), X(0x0983076d), X(0x09c65a92), X(0x0a0a8a38), X(0x0a4f9585), X(0x0a957b9f), X(0x0adc3ba7), X(0x0b23d4b9), X(0x0b6c45ee), X(0x0bb58e5a), X(0x0bffad0f), X(0x0c4aa11a), X(0x0c966982), X(0x0ce3054d), X(0x0d30737b), X(0x0d7eb308), X(0x0dcdc2eb), X(0x0e1da21a), X(0x0e6e4f83), X(0x0ebfca11), X(0x0f1210ad), X(0x0f652238), X(0x0fb8fd91), X(0x100da192), X(0x10630d11), X(0x10b93ee0), X(0x111035cb), X(0x1167f09a), X(0x11c06e13), X(0x1219acf5), X(0x1273abfb), X(0x12ce69db), X(0x1329e54a), X(0x13861cf3), X(0x13e30f80), X(0x1440bb97), X(0x149f1fd8), X(0x14fe3ade), X(0x155e0b40), X(0x15be8f92), X(0x161fc662), X(0x1681ae38), X(0x16e4459b), X(0x17478b0b), X(0x17ab7d03), X(0x181019fb), X(0x18756067), X(0x18db4eb3), X(0x1941e34a), X(0x19a91c92), X(0x1a10f8ea), X(0x1a7976af), X(0x1ae29439), X(0x1b4c4fda), X(0x1bb6a7e2), X(0x1c219a9a), X(0x1c8d2649), X(0x1cf9492e), X(0x1d660188), X(0x1dd34d8e), X(0x1e412b74), X(0x1eaf996a), X(0x1f1e959b), X(0x1f8e1e2f), X(0x1ffe3146), X(0x206ecd01), X(0x20dfef78), X(0x215196c2), X(0x21c3c0f0), X(0x22366c10), X(0x22a9962a), X(0x231d3d45), X(0x23915f60), X(0x2405fa7a), X(0x247b0c8c), X(0x24f09389), X(0x25668d65), X(0x25dcf80c), X(0x2653d167), X(0x26cb175e), X(0x2742c7d0), X(0x27bae09e), X(0x28335fa2), X(0x28ac42b3), X(0x292587a5), X(0x299f2c48), X(0x2a192e69), X(0x2a938bd1), X(0x2b0e4247), X(0x2b894f8d), X(0x2c04b164), X(0x2c806588), X(0x2cfc69b2), X(0x2d78bb9a), X(0x2df558f4), X(0x2e723f6f), X(0x2eef6cbb), X(0x2f6cde83), X(0x2fea9270), X(0x30688627), X(0x30e6b74e), X(0x31652385), X(0x31e3c86b), X(0x3262a39e), X(0x32e1b2b8), X(0x3360f352), X(0x33e06303), X(0x345fff5e), X(0x34dfc5f8), X(0x355fb462), X(0x35dfc82a), X(0x365ffee0), X(0x36e0560f), X(0x3760cb43), X(0x37e15c05), X(0x386205df), X(0x38e2c657), X(0x39639af5), X(0x39e4813e), X(0x3a6576b6), X(0x3ae678e3), X(0x3b678547), X(0x3be89965), X(0x3c69b2c1), X(0x3ceacedc), X(0x3d6beb37), X(0x3ded0557), X(0x3e6e1abb), X(0x3eef28e6), X(0x3f702d5a), X(0x3ff1259a), X(0x40720f29), X(0x40f2e789), X(0x4173ac3f), X(0x41f45ad0), X(0x4274f0c2), X(0x42f56b9a), X(0x4375c8e0), X(0x43f6061d), X(0x447620db), X(0x44f616a5), X(0x4575e509), X(0x45f58994), X(0x467501d6), X(0x46f44b62), X(0x477363cb), X(0x47f248a6), X(0x4870f78e), X(0x48ef6e1a), X(0x496da9e8), X(0x49eba897), X(0x4a6967c8), X(0x4ae6e521), X(0x4b641e47), X(0x4be110e5), X(0x4c5dbaa7), X(0x4cda193f), X(0x4d562a5f), X(0x4dd1ebbd), X(0x4e4d5b15), X(0x4ec87623), X(0x4f433aa9), X(0x4fbda66c), X(0x5037b734), X(0x50b16acf), X(0x512abf0e), X(0x51a3b1c5), X(0x521c40ce), X(0x52946a06), X(0x530c2b50), X(0x53838292), X(0x53fa6db8), X(0x5470eab3), X(0x54e6f776), X(0x555c91fc), X(0x55d1b844), X(0x56466851), X(0x56baa02f), X(0x572e5deb), X(0x57a19f98), X(0x58146352), X(0x5886a737), X(0x58f8696d), X(0x5969a81c), X(0x59da6177), X(0x5a4a93b4), X(0x5aba3d0f), X(0x5b295bcb), X(0x5b97ee30), X(0x5c05f28d), X(0x5c736738), X(0x5ce04a8d), X(0x5d4c9aed), X(0x5db856c1), X(0x5e237c78), X(0x5e8e0a89), X(0x5ef7ff6f), X(0x5f6159b0), X(0x5fca17d4), X(0x6032386e), X(0x6099ba15), X(0x61009b69), X(0x6166db11), X(0x61cc77b9), X(0x62317017), X(0x6295c2e7), X(0x62f96eec), X(0x635c72f1), X(0x63becdc8), X(0x64207e4b), X(0x6481835a), X(0x64e1dbde), X(0x654186c8), X(0x65a0830e), X(0x65fecfb1), X(0x665c6bb7), X(0x66b95630), X(0x67158e30), X(0x677112d7), X(0x67cbe34b), X(0x6825feb9), X(0x687f6456), X(0x68d81361), X(0x69300b1e), X(0x69874ada), X(0x69ddd1ea), X(0x6a339fab), X(0x6a88b382), X(0x6add0cdb), X(0x6b30ab2a), X(0x6b838dec), X(0x6bd5b4a6), X(0x6c271ee2), X(0x6c77cc36), X(0x6cc7bc3d), X(0x6d16ee9b), X(0x6d6562fb), X(0x6db31911), X(0x6e001099), X(0x6e4c4955), X(0x6e97c311), X(0x6ee27d9f), X(0x6f2c78d9), X(0x6f75b4a2), X(0x6fbe30e4), X(0x7005ed91), X(0x704ceaa1), X(0x70932816), X(0x70d8a5f8), X(0x711d6457), X(0x7161634b), X(0x71a4a2f3), X(0x71e72375), X(0x7228e500), X(0x7269e7c8), X(0x72aa2c0a), X(0x72e9b209), X(0x73287a12), X(0x73668476), X(0x73a3d18f), X(0x73e061bc), X(0x741c3566), X(0x74574cfa), X(0x7491a8ee), X(0x74cb49be), X(0x75042fec), X(0x753c5c03), X(0x7573ce92), X(0x75aa882f), X(0x75e08979), X(0x7615d313), X(0x764a65a7), X(0x767e41e5), X(0x76b16884), X(0x76e3da40), X(0x771597dc), X(0x7746a221), X(0x7776f9dd), X(0x77a69fe6), X(0x77d59514), X(0x7803da49), X(0x7831706a), X(0x785e5861), X(0x788a9320), X(0x78b6219c), X(0x78e104cf), X(0x790b3dbb), X(0x7934cd64), X(0x795db4d5), X(0x7985f51d), X(0x79ad8f50), X(0x79d48486), X(0x79fad5de), X(0x7a208478), X(0x7a45917b), X(0x7a69fe12), X(0x7a8dcb6c), X(0x7ab0fabb), X(0x7ad38d36), X(0x7af5841a), X(0x7b16e0a3), X(0x7b37a416), X(0x7b57cfb8), X(0x7b7764d4), X(0x7b9664b6), X(0x7bb4d0b0), X(0x7bd2aa14), X(0x7beff23b), X(0x7c0caa7f), X(0x7c28d43c), X(0x7c4470d2), X(0x7c5f81a5), X(0x7c7a081a), X(0x7c940598), X(0x7cad7b8b), X(0x7cc66b5e), X(0x7cded680), X(0x7cf6be64), X(0x7d0e247b), X(0x7d250a3c), X(0x7d3b711c), X(0x7d515a95), X(0x7d66c822), X(0x7d7bbb3c), X(0x7d903563), X(0x7da43814), X(0x7db7c4d0), X(0x7dcadd16), X(0x7ddd826a), X(0x7defb64d), X(0x7e017a44), X(0x7e12cfd3), X(0x7e23b87f), X(0x7e3435cc), X(0x7e444943), X(0x7e53f467), X(0x7e6338c0), X(0x7e7217d5), X(0x7e80932b), X(0x7e8eac49), X(0x7e9c64b7), X(0x7ea9bdf8), X(0x7eb6b994), X(0x7ec35910), X(0x7ecf9def), X(0x7edb89b6), X(0x7ee71de9), X(0x7ef25c09), X(0x7efd4598), X(0x7f07dc16), X(0x7f122103), X(0x7f1c15dc), X(0x7f25bc1f), X(0x7f2f1547), X(0x7f3822cd), X(0x7f40e62b), X(0x7f4960d6), X(0x7f519443), X(0x7f5981e7), X(0x7f612b31), X(0x7f689191), X(0x7f6fb674), X(0x7f769b45), X(0x7f7d416c), X(0x7f83aa51), X(0x7f89d757), X(0x7f8fc9df), X(0x7f958348), X(0x7f9b04ef), X(0x7fa0502e), X(0x7fa56659), X(0x7faa48c7), X(0x7faef8c7), X(0x7fb377a7), X(0x7fb7c6b3), X(0x7fbbe732), X(0x7fbfda67), X(0x7fc3a196), X(0x7fc73dfa), X(0x7fcab0ce), X(0x7fcdfb4a), X(0x7fd11ea0), X(0x7fd41c00), X(0x7fd6f496), X(0x7fd9a989), X(0x7fdc3bff), X(0x7fdead17), X(0x7fe0fdee), X(0x7fe32f9d), X(0x7fe54337), X(0x7fe739ce), X(0x7fe9146c), X(0x7fead41b), X(0x7fec79dd), X(0x7fee06b2), X(0x7fef7b94), X(0x7ff0d97b), X(0x7ff22158), X(0x7ff35417), X(0x7ff472a3), X(0x7ff57de0), X(0x7ff676ac), X(0x7ff75de3), X(0x7ff8345a), X(0x7ff8fae4), X(0x7ff9b24b), X(0x7ffa5b58), X(0x7ffaf6cd), X(0x7ffb8568), X(0x7ffc07e2), X(0x7ffc7eed), X(0x7ffceb38), X(0x7ffd4d6d), X(0x7ffda631), X(0x7ffdf621), X(0x7ffe3dd8), X(0x7ffe7dea), X(0x7ffeb6e7), X(0x7ffee959), X(0x7fff15c4), X(0x7fff3ca9), X(0x7fff5e80), X(0x7fff7bc0), X(0x7fff94d6), X(0x7fffaa2d), X(0x7fffbc29), X(0x7fffcb29), X(0x7fffd786), X(0x7fffe195), X(0x7fffe9a3), X(0x7fffeffa), X(0x7ffff4dd), X(0x7ffff889), X(0x7ffffb37), X(0x7ffffd1a), X(0x7ffffe5d), X(0x7fffff29), X(0x7fffffa0), X(0x7fffffdd), X(0x7ffffff7), X(0x7fffffff), X(0x7fffffff), }; static const LOOKUP_T vwin2048[1024] = { X(0x000007c0), X(0x000045c4), X(0x0000c1ca), X(0x00017bd3), X(0x000273de), X(0x0003a9eb), X(0x00051df9), X(0x0006d007), X(0x0008c014), X(0x000aee1e), X(0x000d5a25), X(0x00100428), X(0x0012ec23), X(0x00161216), X(0x001975fe), X(0x001d17da), X(0x0020f7a8), X(0x00251564), X(0x0029710c), X(0x002e0a9e), X(0x0032e217), X(0x0037f773), X(0x003d4ab0), X(0x0042dbca), X(0x0048aabe), X(0x004eb788), X(0x00550224), X(0x005b8a8f), X(0x006250c5), X(0x006954c1), X(0x0070967e), X(0x007815f9), X(0x007fd32c), X(0x0087ce13), X(0x009006a9), X(0x00987ce9), X(0x00a130cc), X(0x00aa224f), X(0x00b3516b), X(0x00bcbe1a), X(0x00c66856), X(0x00d0501a), X(0x00da755f), X(0x00e4d81f), X(0x00ef7853), X(0x00fa55f4), X(0x010570fc), X(0x0110c963), X(0x011c5f22), X(0x01283232), X(0x0134428c), X(0x01409027), X(0x014d1afb), X(0x0159e302), X(0x0166e831), X(0x01742a82), X(0x0181a9ec), X(0x018f6665), X(0x019d5fe5), X(0x01ab9663), X(0x01ba09d6), X(0x01c8ba34), X(0x01d7a775), X(0x01e6d18d), X(0x01f63873), X(0x0205dc1e), X(0x0215bc82), X(0x0225d997), X(0x02363350), X(0x0246c9a3), X(0x02579c86), X(0x0268abed), X(0x0279f7cc), X(0x028b801a), X(0x029d44c9), X(0x02af45ce), X(0x02c1831d), X(0x02d3fcaa), X(0x02e6b269), X(0x02f9a44c), X(0x030cd248), X(0x03203c4f), X(0x0333e255), X(0x0347c44b), X(0x035be225), X(0x03703bd5), X(0x0384d14d), X(0x0399a280), X(0x03aeaf5e), X(0x03c3f7d9), X(0x03d97be4), X(0x03ef3b6e), X(0x0405366a), X(0x041b6cc8), X(0x0431de78), X(0x04488b6c), X(0x045f7393), X(0x047696dd), X(0x048df53b), X(0x04a58e9b), X(0x04bd62ee), X(0x04d57223), X(0x04edbc28), X(0x050640ed), X(0x051f0060), X(0x0537fa70), X(0x05512f0a), X(0x056a9e1e), X(0x05844798), X(0x059e2b67), X(0x05b84978), X(0x05d2a1b8), X(0x05ed3414), X(0x06080079), X(0x062306d3), X(0x063e470f), X(0x0659c119), X(0x067574dd), X(0x06916247), X(0x06ad8941), X(0x06c9e9b8), X(0x06e68397), X(0x070356c8), X(0x07206336), X(0x073da8cb), X(0x075b2772), X(0x0778df15), X(0x0796cf9c), X(0x07b4f8f3), X(0x07d35b01), X(0x07f1f5b1), X(0x0810c8eb), X(0x082fd497), X(0x084f189e), X(0x086e94e9), X(0x088e495e), X(0x08ae35e6), X(0x08ce5a68), X(0x08eeb6cc), X(0x090f4af8), X(0x093016d3), X(0x09511a44), X(0x09725530), X(0x0993c77f), X(0x09b57115), X(0x09d751d8), X(0x09f969ae), X(0x0a1bb87c), X(0x0a3e3e26), X(0x0a60fa91), X(0x0a83eda2), X(0x0aa7173c), X(0x0aca7743), X(0x0aee0d9b), X(0x0b11da28), X(0x0b35dccc), X(0x0b5a156a), X(0x0b7e83e5), X(0x0ba3281f), X(0x0bc801fa), X(0x0bed1159), X(0x0c12561c), X(0x0c37d025), X(0x0c5d7f55), X(0x0c83638d), X(0x0ca97cae), X(0x0ccfca97), X(0x0cf64d2a), X(0x0d1d0444), X(0x0d43efc7), X(0x0d6b0f92), X(0x0d926383), X(0x0db9eb79), X(0x0de1a752), X(0x0e0996ee), X(0x0e31ba29), X(0x0e5a10e2), X(0x0e829af6), X(0x0eab5841), X(0x0ed448a2), X(0x0efd6bf4), X(0x0f26c214), X(0x0f504ade), X(0x0f7a062e), X(0x0fa3f3df), X(0x0fce13cd), X(0x0ff865d2), X(0x1022e9ca), X(0x104d9f8e), X(0x107886f9), X(0x10a39fe5), X(0x10ceea2c), X(0x10fa65a6), X(0x1126122d), X(0x1151ef9a), X(0x117dfdc5), X(0x11aa3c87), X(0x11d6abb6), X(0x12034b2c), X(0x12301ac0), X(0x125d1a48), X(0x128a499b), X(0x12b7a891), X(0x12e536ff), X(0x1312f4bb), X(0x1340e19c), X(0x136efd75), X(0x139d481e), X(0x13cbc16a), X(0x13fa692f), X(0x14293f40), X(0x14584371), X(0x14877597), X(0x14b6d585), X(0x14e6630d), X(0x15161e04), X(0x1546063b), X(0x15761b85), X(0x15a65db3), X(0x15d6cc99), X(0x16076806), X(0x16382fcd), X(0x166923bf), X(0x169a43ab), X(0x16cb8f62), X(0x16fd06b5), X(0x172ea973), X(0x1760776b), X(0x1792706e), X(0x17c49449), X(0x17f6e2cb), X(0x18295bc3), X(0x185bfeff), X(0x188ecc4c), X(0x18c1c379), X(0x18f4e452), X(0x19282ea4), X(0x195ba23c), X(0x198f3ee6), X(0x19c3046e), X(0x19f6f2a1), X(0x1a2b094a), X(0x1a5f4833), X(0x1a93af28), X(0x1ac83df3), X(0x1afcf460), X(0x1b31d237), X(0x1b66d744), X(0x1b9c034e), X(0x1bd15621), X(0x1c06cf84), X(0x1c3c6f40), X(0x1c72351e), X(0x1ca820e6), X(0x1cde3260), X(0x1d146953), X(0x1d4ac587), X(0x1d8146c3), X(0x1db7eccd), X(0x1deeb76c), X(0x1e25a667), X(0x1e5cb982), X(0x1e93f085), X(0x1ecb4b33), X(0x1f02c953), X(0x1f3a6aaa), X(0x1f722efb), X(0x1faa160b), X(0x1fe21f9e), X(0x201a4b79), X(0x2052995d), X(0x208b0910), X(0x20c39a53), X(0x20fc4cea), X(0x21352097), X(0x216e151c), X(0x21a72a3a), X(0x21e05fb5), X(0x2219b54d), X(0x22532ac3), X(0x228cbfd8), X(0x22c6744d), X(0x230047e2), X(0x233a3a58), X(0x23744b6d), X(0x23ae7ae3), X(0x23e8c878), X(0x242333ec), X(0x245dbcfd), X(0x24986369), X(0x24d326f1), X(0x250e0750), X(0x25490446), X(0x25841d90), X(0x25bf52ec), X(0x25faa417), X(0x263610cd), X(0x267198cc), X(0x26ad3bcf), X(0x26e8f994), X(0x2724d1d6), X(0x2760c451), X(0x279cd0c0), X(0x27d8f6e0), X(0x2815366a), X(0x28518f1b), X(0x288e00ac), X(0x28ca8ad8), X(0x29072d5a), X(0x2943e7eb), X(0x2980ba45), X(0x29bda422), X(0x29faa53c), X(0x2a37bd4a), X(0x2a74ec07), X(0x2ab2312b), X(0x2aef8c6f), X(0x2b2cfd8b), X(0x2b6a8437), X(0x2ba8202c), X(0x2be5d120), X(0x2c2396cc), X(0x2c6170e7), X(0x2c9f5f29), X(0x2cdd6147), X(0x2d1b76fa), X(0x2d599ff7), X(0x2d97dbf5), X(0x2dd62aab), X(0x2e148bcf), X(0x2e52ff16), X(0x2e918436), X(0x2ed01ae5), X(0x2f0ec2d9), X(0x2f4d7bc6), X(0x2f8c4562), X(0x2fcb1f62), X(0x300a097a), X(0x3049035f), X(0x30880cc6), X(0x30c72563), X(0x31064cea), X(0x3145830f), X(0x3184c786), X(0x31c41a03), X(0x32037a39), X(0x3242e7dc), X(0x3282629f), X(0x32c1ea36), X(0x33017e53), X(0x33411ea9), X(0x3380caec), X(0x33c082ce), X(0x34004602), X(0x34401439), X(0x347fed27), X(0x34bfd07e), X(0x34ffbdf0), X(0x353fb52e), X(0x357fb5ec), X(0x35bfbfda), X(0x35ffd2aa), X(0x363fee0f), X(0x368011b9), X(0x36c03d5a), X(0x370070a4), X(0x3740ab48), X(0x3780ecf7), X(0x37c13562), X(0x3801843a), X(0x3841d931), X(0x388233f7), X(0x38c2943d), X(0x3902f9b4), X(0x3943640d), X(0x3983d2f8), X(0x39c44626), X(0x3a04bd48), X(0x3a45380e), X(0x3a85b62a), X(0x3ac6374a), X(0x3b06bb20), X(0x3b47415c), X(0x3b87c9ae), X(0x3bc853c7), X(0x3c08df57), X(0x3c496c0f), X(0x3c89f99f), X(0x3cca87b6), X(0x3d0b1605), X(0x3d4ba43d), X(0x3d8c320e), X(0x3dccbf27), X(0x3e0d4b3a), X(0x3e4dd5f6), X(0x3e8e5f0c), X(0x3ecee62b), X(0x3f0f6b05), X(0x3f4fed49), X(0x3f906ca8), X(0x3fd0e8d2), X(0x40116177), X(0x4051d648), X(0x409246f6), X(0x40d2b330), X(0x41131aa7), X(0x41537d0c), X(0x4193da10), X(0x41d43162), X(0x421482b4), X(0x4254cdb7), X(0x4295121b), X(0x42d54f91), X(0x431585ca), X(0x4355b477), X(0x4395db49), X(0x43d5f9f1), X(0x44161021), X(0x44561d8a), X(0x449621dd), X(0x44d61ccc), X(0x45160e08), X(0x4555f544), X(0x4595d230), X(0x45d5a47f), X(0x46156be3), X(0x4655280e), X(0x4694d8b2), X(0x46d47d82), X(0x4714162f), X(0x4753a26d), X(0x479321ef), X(0x47d29466), X(0x4811f987), X(0x48515104), X(0x48909a91), X(0x48cfd5e1), X(0x490f02a7), X(0x494e2098), X(0x498d2f66), X(0x49cc2ec7), X(0x4a0b1e6f), X(0x4a49fe11), X(0x4a88cd62), X(0x4ac78c18), X(0x4b0639e6), X(0x4b44d683), X(0x4b8361a2), X(0x4bc1dafa), X(0x4c004241), X(0x4c3e972c), X(0x4c7cd970), X(0x4cbb08c5), X(0x4cf924e1), X(0x4d372d7a), X(0x4d752247), X(0x4db30300), X(0x4df0cf5a), X(0x4e2e870f), X(0x4e6c29d6), X(0x4ea9b766), X(0x4ee72f78), X(0x4f2491c4), X(0x4f61de02), X(0x4f9f13ec), X(0x4fdc333b), X(0x50193ba8), X(0x50562ced), X(0x509306c3), X(0x50cfc8e5), X(0x510c730d), X(0x514904f6), X(0x51857e5a), X(0x51c1def5), X(0x51fe2682), X(0x523a54bc), X(0x52766961), X(0x52b2642c), X(0x52ee44d9), X(0x532a0b26), X(0x5365b6d0), X(0x53a14793), X(0x53dcbd2f), X(0x54181760), X(0x545355e5), X(0x548e787d), X(0x54c97ee6), X(0x550468e1), X(0x553f362c), X(0x5579e687), X(0x55b479b3), X(0x55eeef70), X(0x5629477f), X(0x566381a1), X(0x569d9d97), X(0x56d79b24), X(0x57117a0a), X(0x574b3a0a), X(0x5784dae9), X(0x57be5c69), X(0x57f7be4d), X(0x5831005a), X(0x586a2254), X(0x58a32400), X(0x58dc0522), X(0x5914c57f), X(0x594d64de), X(0x5985e305), X(0x59be3fba), X(0x59f67ac3), X(0x5a2e93e9), X(0x5a668af2), X(0x5a9e5fa6), X(0x5ad611ce), X(0x5b0da133), X(0x5b450d9d), X(0x5b7c56d7), X(0x5bb37ca9), X(0x5bea7ede), X(0x5c215d41), X(0x5c58179d), X(0x5c8eadbe), X(0x5cc51f6f), X(0x5cfb6c7c), X(0x5d3194b2), X(0x5d6797de), X(0x5d9d75cf), X(0x5dd32e51), X(0x5e08c132), X(0x5e3e2e43), X(0x5e737551), X(0x5ea8962d), X(0x5edd90a7), X(0x5f12648e), X(0x5f4711b4), X(0x5f7b97ea), X(0x5faff702), X(0x5fe42ece), X(0x60183f20), X(0x604c27cc), X(0x607fe8a6), X(0x60b38180), X(0x60e6f22f), X(0x611a3a89), X(0x614d5a62), X(0x61805190), X(0x61b31fe9), X(0x61e5c545), X(0x62184179), X(0x624a945d), X(0x627cbdca), X(0x62aebd98), X(0x62e0939f), X(0x63123fba), X(0x6343c1c1), X(0x6375198f), X(0x63a646ff), X(0x63d749ec), X(0x64082232), X(0x6438cfad), X(0x64695238), X(0x6499a9b3), X(0x64c9d5f9), X(0x64f9d6ea), X(0x6529ac63), X(0x65595643), X(0x6588d46a), X(0x65b826b8), X(0x65e74d0e), X(0x6616474b), X(0x66451552), X(0x6673b704), X(0x66a22c44), X(0x66d074f4), X(0x66fe90f8), X(0x672c8033), X(0x675a428a), X(0x6787d7e1), X(0x67b5401f), X(0x67e27b27), X(0x680f88e1), X(0x683c6934), X(0x68691c05), X(0x6895a13e), X(0x68c1f8c7), X(0x68ee2287), X(0x691a1e68), X(0x6945ec54), X(0x69718c35), X(0x699cfdf5), X(0x69c8417f), X(0x69f356c0), X(0x6a1e3da3), X(0x6a48f615), X(0x6a738002), X(0x6a9ddb5a), X(0x6ac80808), X(0x6af205fd), X(0x6b1bd526), X(0x6b457575), X(0x6b6ee6d8), X(0x6b982940), X(0x6bc13c9f), X(0x6bea20e5), X(0x6c12d605), X(0x6c3b5bf1), X(0x6c63b29c), X(0x6c8bd9fb), X(0x6cb3d200), X(0x6cdb9aa0), X(0x6d0333d0), X(0x6d2a9d86), X(0x6d51d7b7), X(0x6d78e25a), X(0x6d9fbd67), X(0x6dc668d3), X(0x6dece498), X(0x6e1330ad), X(0x6e394d0c), X(0x6e5f39ae), X(0x6e84f68d), X(0x6eaa83a2), X(0x6ecfe0ea), X(0x6ef50e5e), X(0x6f1a0bfc), X(0x6f3ed9bf), X(0x6f6377a4), X(0x6f87e5a8), X(0x6fac23c9), X(0x6fd03206), X(0x6ff4105c), X(0x7017becc), X(0x703b3d54), X(0x705e8bf5), X(0x7081aaaf), X(0x70a49984), X(0x70c75874), X(0x70e9e783), X(0x710c46b2), X(0x712e7605), X(0x7150757f), X(0x71724523), X(0x7193e4f6), X(0x71b554fd), X(0x71d6953e), X(0x71f7a5bd), X(0x72188681), X(0x72393792), X(0x7259b8f5), X(0x727a0ab2), X(0x729a2cd2), X(0x72ba1f5d), X(0x72d9e25c), X(0x72f975d8), X(0x7318d9db), X(0x73380e6f), X(0x735713a0), X(0x7375e978), X(0x73949003), X(0x73b3074c), X(0x73d14f61), X(0x73ef684f), X(0x740d5222), X(0x742b0ce9), X(0x744898b1), X(0x7465f589), X(0x74832381), X(0x74a022a8), X(0x74bcf30e), X(0x74d994c3), X(0x74f607d8), X(0x75124c5f), X(0x752e6268), X(0x754a4a05), X(0x7566034b), X(0x75818e4a), X(0x759ceb16), X(0x75b819c4), X(0x75d31a66), X(0x75eded12), X(0x760891dc), X(0x762308da), X(0x763d5221), X(0x76576dc8), X(0x76715be4), X(0x768b1c8c), X(0x76a4afd9), X(0x76be15e0), X(0x76d74ebb), X(0x76f05a82), X(0x7709394d), X(0x7721eb35), X(0x773a7054), X(0x7752c8c4), X(0x776af49f), X(0x7782f400), X(0x779ac701), X(0x77b26dbd), X(0x77c9e851), X(0x77e136d8), X(0x77f8596f), X(0x780f5032), X(0x78261b3f), X(0x783cbab2), X(0x78532eaa), X(0x78697745), X(0x787f94a0), X(0x789586db), X(0x78ab4e15), X(0x78c0ea6d), X(0x78d65c03), X(0x78eba2f7), X(0x7900bf68), X(0x7915b179), X(0x792a7949), X(0x793f16fb), X(0x79538aaf), X(0x7967d488), X(0x797bf4a8), X(0x798feb31), X(0x79a3b846), X(0x79b75c0a), X(0x79cad6a1), X(0x79de282e), X(0x79f150d5), X(0x7a0450bb), X(0x7a172803), X(0x7a29d6d3), X(0x7a3c5d50), X(0x7a4ebb9f), X(0x7a60f1e6), X(0x7a73004a), X(0x7a84e6f2), X(0x7a96a604), X(0x7aa83da7), X(0x7ab9ae01), X(0x7acaf73a), X(0x7adc1979), X(0x7aed14e6), X(0x7afde9a8), X(0x7b0e97e8), X(0x7b1f1fcd), X(0x7b2f8182), X(0x7b3fbd2d), X(0x7b4fd2f9), X(0x7b5fc30f), X(0x7b6f8d98), X(0x7b7f32bd), X(0x7b8eb2a9), X(0x7b9e0d85), X(0x7bad437d), X(0x7bbc54b9), X(0x7bcb4166), X(0x7bda09ae), X(0x7be8adbc), X(0x7bf72dbc), X(0x7c0589d8), X(0x7c13c23d), X(0x7c21d716), X(0x7c2fc88f), X(0x7c3d96d5), X(0x7c4b4214), X(0x7c58ca78), X(0x7c66302d), X(0x7c737362), X(0x7c809443), X(0x7c8d92fc), X(0x7c9a6fbc), X(0x7ca72aaf), X(0x7cb3c404), X(0x7cc03be8), X(0x7ccc9288), X(0x7cd8c814), X(0x7ce4dcb9), X(0x7cf0d0a5), X(0x7cfca406), X(0x7d08570c), X(0x7d13e9e5), X(0x7d1f5cbf), X(0x7d2aafca), X(0x7d35e335), X(0x7d40f72e), X(0x7d4bebe4), X(0x7d56c188), X(0x7d617848), X(0x7d6c1054), X(0x7d7689db), X(0x7d80e50e), X(0x7d8b221b), X(0x7d954133), X(0x7d9f4286), X(0x7da92643), X(0x7db2ec9b), X(0x7dbc95bd), X(0x7dc621da), X(0x7dcf9123), X(0x7dd8e3c6), X(0x7de219f6), X(0x7deb33e2), X(0x7df431ba), X(0x7dfd13af), X(0x7e05d9f2), X(0x7e0e84b4), X(0x7e171424), X(0x7e1f8874), X(0x7e27e1d4), X(0x7e302074), X(0x7e384487), X(0x7e404e3c), X(0x7e483dc4), X(0x7e501350), X(0x7e57cf11), X(0x7e5f7138), X(0x7e66f9f4), X(0x7e6e6979), X(0x7e75bff5), X(0x7e7cfd9a), X(0x7e842298), X(0x7e8b2f22), X(0x7e922366), X(0x7e98ff97), X(0x7e9fc3e4), X(0x7ea6707f), X(0x7ead0598), X(0x7eb38360), X(0x7eb9ea07), X(0x7ec039bf), X(0x7ec672b7), X(0x7ecc9521), X(0x7ed2a12c), X(0x7ed8970a), X(0x7ede76ea), X(0x7ee440fd), X(0x7ee9f573), X(0x7eef947d), X(0x7ef51e4b), X(0x7efa930d), X(0x7efff2f2), X(0x7f053e2b), X(0x7f0a74e8), X(0x7f0f9758), X(0x7f14a5ac), X(0x7f19a013), X(0x7f1e86bc), X(0x7f2359d8), X(0x7f281995), X(0x7f2cc623), X(0x7f315fb1), X(0x7f35e66e), X(0x7f3a5a8a), X(0x7f3ebc33), X(0x7f430b98), X(0x7f4748e7), X(0x7f4b7450), X(0x7f4f8e01), X(0x7f539629), X(0x7f578cf5), X(0x7f5b7293), X(0x7f5f4732), X(0x7f630b00), X(0x7f66be2b), X(0x7f6a60df), X(0x7f6df34b), X(0x7f71759b), X(0x7f74e7fe), X(0x7f784aa0), X(0x7f7b9daf), X(0x7f7ee156), X(0x7f8215c3), X(0x7f853b22), X(0x7f88519f), X(0x7f8b5967), X(0x7f8e52a6), X(0x7f913d87), X(0x7f941a36), X(0x7f96e8df), X(0x7f99a9ad), X(0x7f9c5ccb), X(0x7f9f0265), X(0x7fa19aa5), X(0x7fa425b5), X(0x7fa6a3c1), X(0x7fa914f3), X(0x7fab7974), X(0x7fadd16f), X(0x7fb01d0d), X(0x7fb25c78), X(0x7fb48fd9), X(0x7fb6b75a), X(0x7fb8d323), X(0x7fbae35d), X(0x7fbce831), X(0x7fbee1c7), X(0x7fc0d047), X(0x7fc2b3d9), X(0x7fc48ca5), X(0x7fc65ad3), X(0x7fc81e88), X(0x7fc9d7ee), X(0x7fcb872a), X(0x7fcd2c63), X(0x7fcec7bf), X(0x7fd05966), X(0x7fd1e17c), X(0x7fd36027), X(0x7fd4d58d), X(0x7fd641d3), X(0x7fd7a51e), X(0x7fd8ff94), X(0x7fda5157), X(0x7fdb9a8e), X(0x7fdcdb5b), X(0x7fde13e2), X(0x7fdf4448), X(0x7fe06caf), X(0x7fe18d3b), X(0x7fe2a60e), X(0x7fe3b74b), X(0x7fe4c114), X(0x7fe5c38b), X(0x7fe6bed2), X(0x7fe7b30a), X(0x7fe8a055), X(0x7fe986d4), X(0x7fea66a7), X(0x7feb3ff0), X(0x7fec12cd), X(0x7fecdf5f), X(0x7feda5c5), X(0x7fee6620), X(0x7fef208d), X(0x7fefd52c), X(0x7ff0841c), X(0x7ff12d7a), X(0x7ff1d164), X(0x7ff26ff9), X(0x7ff30955), X(0x7ff39d96), X(0x7ff42cd9), X(0x7ff4b739), X(0x7ff53cd4), X(0x7ff5bdc5), X(0x7ff63a28), X(0x7ff6b217), X(0x7ff725af), X(0x7ff7950a), X(0x7ff80043), X(0x7ff86773), X(0x7ff8cab4), X(0x7ff92a21), X(0x7ff985d1), X(0x7ff9dddf), X(0x7ffa3262), X(0x7ffa8374), X(0x7ffad12c), X(0x7ffb1ba1), X(0x7ffb62ec), X(0x7ffba723), X(0x7ffbe85c), X(0x7ffc26b0), X(0x7ffc6233), X(0x7ffc9afb), X(0x7ffcd11e), X(0x7ffd04b1), X(0x7ffd35c9), X(0x7ffd647b), X(0x7ffd90da), X(0x7ffdbafa), X(0x7ffde2f0), X(0x7ffe08ce), X(0x7ffe2ca7), X(0x7ffe4e8e), X(0x7ffe6e95), X(0x7ffe8cce), X(0x7ffea94a), X(0x7ffec41b), X(0x7ffedd52), X(0x7ffef4ff), X(0x7fff0b33), X(0x7fff1ffd), X(0x7fff336e), X(0x7fff4593), X(0x7fff567d), X(0x7fff663a), X(0x7fff74d8), X(0x7fff8265), X(0x7fff8eee), X(0x7fff9a81), X(0x7fffa52b), X(0x7fffaef8), X(0x7fffb7f5), X(0x7fffc02d), X(0x7fffc7ab), X(0x7fffce7c), X(0x7fffd4a9), X(0x7fffda3e), X(0x7fffdf44), X(0x7fffe3c6), X(0x7fffe7cc), X(0x7fffeb60), X(0x7fffee8a), X(0x7ffff153), X(0x7ffff3c4), X(0x7ffff5e3), X(0x7ffff7b8), X(0x7ffff94b), X(0x7ffffaa1), X(0x7ffffbc1), X(0x7ffffcb2), X(0x7ffffd78), X(0x7ffffe19), X(0x7ffffe9a), X(0x7ffffeff), X(0x7fffff4e), X(0x7fffff89), X(0x7fffffb3), X(0x7fffffd2), X(0x7fffffe6), X(0x7ffffff3), X(0x7ffffffa), X(0x7ffffffe), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), }; static const LOOKUP_T vwin4096[2048] = { X(0x000001f0), X(0x00001171), X(0x00003072), X(0x00005ef5), X(0x00009cf8), X(0x0000ea7c), X(0x00014780), X(0x0001b405), X(0x0002300b), X(0x0002bb91), X(0x00035698), X(0x0004011e), X(0x0004bb25), X(0x000584ac), X(0x00065db3), X(0x0007463a), X(0x00083e41), X(0x000945c7), X(0x000a5ccc), X(0x000b8350), X(0x000cb954), X(0x000dfed7), X(0x000f53d8), X(0x0010b857), X(0x00122c55), X(0x0013afd1), X(0x001542ca), X(0x0016e541), X(0x00189735), X(0x001a58a7), X(0x001c2995), X(0x001e09ff), X(0x001ff9e6), X(0x0021f948), X(0x00240826), X(0x00262680), X(0x00285454), X(0x002a91a3), X(0x002cde6c), X(0x002f3aaf), X(0x0031a66b), X(0x003421a0), X(0x0036ac4f), X(0x00394675), X(0x003bf014), X(0x003ea92a), X(0x004171b7), X(0x004449bb), X(0x00473135), X(0x004a2824), X(0x004d2e8a), X(0x00504463), X(0x005369b2), X(0x00569e74), X(0x0059e2aa), X(0x005d3652), X(0x0060996d), X(0x00640bf9), X(0x00678df7), X(0x006b1f66), X(0x006ec045), X(0x00727093), X(0x00763051), X(0x0079ff7d), X(0x007dde16), X(0x0081cc1d), X(0x0085c991), X(0x0089d671), X(0x008df2bc), X(0x00921e71), X(0x00965991), X(0x009aa41a), X(0x009efe0c), X(0x00a36766), X(0x00a7e028), X(0x00ac6850), X(0x00b0ffde), X(0x00b5a6d1), X(0x00ba5d28), X(0x00bf22e4), X(0x00c3f802), X(0x00c8dc83), X(0x00cdd065), X(0x00d2d3a8), X(0x00d7e64a), X(0x00dd084c), X(0x00e239ac), X(0x00e77a69), X(0x00ecca83), X(0x00f229f9), X(0x00f798ca), X(0x00fd16f5), X(0x0102a479), X(0x01084155), X(0x010ded89), X(0x0113a913), X(0x011973f3), X(0x011f4e27), X(0x012537af), X(0x012b308a), X(0x013138b7), X(0x01375035), X(0x013d7702), X(0x0143ad1f), X(0x0149f289), X(0x01504741), X(0x0156ab44), X(0x015d1e92), X(0x0163a12a), X(0x016a330b), X(0x0170d433), X(0x017784a3), X(0x017e4458), X(0x01851351), X(0x018bf18e), X(0x0192df0d), X(0x0199dbcd), X(0x01a0e7cd), X(0x01a8030c), X(0x01af2d89), X(0x01b66743), X(0x01bdb038), X(0x01c50867), X(0x01cc6fd0), X(0x01d3e670), X(0x01db6c47), X(0x01e30153), X(0x01eaa593), X(0x01f25907), X(0x01fa1bac), X(0x0201ed81), X(0x0209ce86), X(0x0211beb8), X(0x0219be17), X(0x0221cca2), X(0x0229ea56), X(0x02321733), X(0x023a5337), X(0x02429e60), X(0x024af8af), X(0x02536220), X(0x025bdab3), X(0x02646267), X(0x026cf93a), X(0x02759f2a), X(0x027e5436), X(0x0287185d), X(0x028feb9d), X(0x0298cdf4), X(0x02a1bf62), X(0x02aabfe5), X(0x02b3cf7b), X(0x02bcee23), X(0x02c61bdb), X(0x02cf58a2), X(0x02d8a475), X(0x02e1ff55), X(0x02eb693e), X(0x02f4e230), X(0x02fe6a29), X(0x03080127), X(0x0311a729), X(0x031b5c2d), X(0x03252031), X(0x032ef334), X(0x0338d534), X(0x0342c630), X(0x034cc625), X(0x0356d512), X(0x0360f2f6), X(0x036b1fce), X(0x03755b99), X(0x037fa655), X(0x038a0001), X(0x0394689a), X(0x039ee020), X(0x03a9668f), X(0x03b3fbe6), X(0x03bea024), X(0x03c95347), X(0x03d4154d), X(0x03dee633), X(0x03e9c5f9), X(0x03f4b49b), X(0x03ffb219), X(0x040abe71), X(0x0415d9a0), X(0x042103a5), X(0x042c3c7d), X(0x04378428), X(0x0442daa2), X(0x044e3fea), X(0x0459b3fd), X(0x046536db), X(0x0470c880), X(0x047c68eb), X(0x0488181a), X(0x0493d60b), X(0x049fa2bc), X(0x04ab7e2a), X(0x04b76854), X(0x04c36137), X(0x04cf68d1), X(0x04db7f21), X(0x04e7a424), X(0x04f3d7d8), X(0x05001a3b), X(0x050c6b4a), X(0x0518cb04), X(0x05253966), X(0x0531b66e), X(0x053e421a), X(0x054adc68), X(0x05578555), X(0x05643cdf), X(0x05710304), X(0x057dd7c1), X(0x058abb15), X(0x0597acfd), X(0x05a4ad76), X(0x05b1bc7f), X(0x05beda14), X(0x05cc0635), X(0x05d940dd), X(0x05e68a0b), X(0x05f3e1bd), X(0x060147f0), X(0x060ebca1), X(0x061c3fcf), X(0x0629d176), X(0x06377194), X(0x06452027), X(0x0652dd2c), X(0x0660a8a2), X(0x066e8284), X(0x067c6ad1), X(0x068a6186), X(0x069866a1), X(0x06a67a1e), X(0x06b49bfc), X(0x06c2cc38), X(0x06d10acf), X(0x06df57bf), X(0x06edb304), X(0x06fc1c9d), X(0x070a9487), X(0x07191abe), X(0x0727af40), X(0x0736520b), X(0x0745031c), X(0x0753c270), X(0x07629004), X(0x07716bd6), X(0x078055e2), X(0x078f4e26), X(0x079e549f), X(0x07ad694b), X(0x07bc8c26), X(0x07cbbd2e), X(0x07dafc5f), X(0x07ea49b7), X(0x07f9a533), X(0x08090ed1), X(0x0818868c), X(0x08280c62), X(0x0837a051), X(0x08474255), X(0x0856f26b), X(0x0866b091), X(0x08767cc3), X(0x088656fe), X(0x08963f3f), X(0x08a63584), X(0x08b639c8), X(0x08c64c0a), X(0x08d66c45), X(0x08e69a77), X(0x08f6d69d), X(0x090720b3), X(0x091778b7), X(0x0927dea5), X(0x0938527a), X(0x0948d433), X(0x095963cc), X(0x096a0143), X(0x097aac94), X(0x098b65bb), X(0x099c2cb6), X(0x09ad0182), X(0x09bde41a), X(0x09ced47d), X(0x09dfd2a5), X(0x09f0de90), X(0x0a01f83b), X(0x0a131fa3), X(0x0a2454c3), X(0x0a359798), X(0x0a46e820), X(0x0a584656), X(0x0a69b237), X(0x0a7b2bc0), X(0x0a8cb2ec), X(0x0a9e47ba), X(0x0aafea24), X(0x0ac19a29), X(0x0ad357c3), X(0x0ae522ef), X(0x0af6fbab), X(0x0b08e1f1), X(0x0b1ad5c0), X(0x0b2cd712), X(0x0b3ee5e5), X(0x0b510234), X(0x0b632bfd), X(0x0b75633b), X(0x0b87a7eb), X(0x0b99fa08), X(0x0bac5990), X(0x0bbec67e), X(0x0bd140cf), X(0x0be3c87e), X(0x0bf65d89), X(0x0c08ffeb), X(0x0c1bafa1), X(0x0c2e6ca6), X(0x0c4136f6), X(0x0c540e8f), X(0x0c66f36c), X(0x0c79e588), X(0x0c8ce4e1), X(0x0c9ff172), X(0x0cb30b37), X(0x0cc6322c), X(0x0cd9664d), X(0x0ceca797), X(0x0cfff605), X(0x0d135193), X(0x0d26ba3d), X(0x0d3a2fff), X(0x0d4db2d5), X(0x0d6142ba), X(0x0d74dfac), X(0x0d8889a5), X(0x0d9c40a1), X(0x0db0049d), X(0x0dc3d593), X(0x0dd7b380), X(0x0deb9e60), X(0x0dff962f), X(0x0e139ae7), X(0x0e27ac85), X(0x0e3bcb05), X(0x0e4ff662), X(0x0e642e98), X(0x0e7873a2), X(0x0e8cc57d), X(0x0ea12423), X(0x0eb58f91), X(0x0eca07c2), X(0x0ede8cb1), X(0x0ef31e5b), X(0x0f07bcba), X(0x0f1c67cb), X(0x0f311f88), X(0x0f45e3ee), X(0x0f5ab4f7), X(0x0f6f92a0), X(0x0f847ce3), X(0x0f9973bc), X(0x0fae7726), X(0x0fc3871e), X(0x0fd8a39d), X(0x0fedcca1), X(0x10030223), X(0x1018441f), X(0x102d9291), X(0x1042ed74), X(0x105854c3), X(0x106dc879), X(0x10834892), X(0x1098d508), X(0x10ae6dd8), X(0x10c412fc), X(0x10d9c46f), X(0x10ef822d), X(0x11054c30), X(0x111b2274), X(0x113104f5), X(0x1146f3ac), X(0x115cee95), X(0x1172f5ab), X(0x118908e9), X(0x119f284a), X(0x11b553ca), X(0x11cb8b62), X(0x11e1cf0f), X(0x11f81ecb), X(0x120e7a90), X(0x1224e25a), X(0x123b5624), X(0x1251d5e9), X(0x126861a3), X(0x127ef94e), X(0x12959ce3), X(0x12ac4c5f), X(0x12c307bb), X(0x12d9cef2), X(0x12f0a200), X(0x130780df), X(0x131e6b8a), X(0x133561fa), X(0x134c642c), X(0x1363721a), X(0x137a8bbe), X(0x1391b113), X(0x13a8e214), X(0x13c01eba), X(0x13d76702), X(0x13eebae5), X(0x14061a5e), X(0x141d8567), X(0x1434fbfb), X(0x144c7e14), X(0x14640bae), X(0x147ba4c1), X(0x14934949), X(0x14aaf941), X(0x14c2b4a2), X(0x14da7b67), X(0x14f24d8a), X(0x150a2b06), X(0x152213d5), X(0x153a07f1), X(0x15520755), X(0x156a11fb), X(0x158227dd), X(0x159a48f5), X(0x15b2753d), X(0x15caacb1), X(0x15e2ef49), X(0x15fb3d01), X(0x161395d2), X(0x162bf9b6), X(0x164468a8), X(0x165ce2a1), X(0x1675679c), X(0x168df793), X(0x16a69280), X(0x16bf385c), X(0x16d7e922), X(0x16f0a4cc), X(0x17096b54), X(0x17223cb4), X(0x173b18e5), X(0x1753ffe2), X(0x176cf1a5), X(0x1785ee27), X(0x179ef562), X(0x17b80750), X(0x17d123eb), X(0x17ea4b2d), X(0x18037d10), X(0x181cb98d), X(0x1836009e), X(0x184f523c), X(0x1868ae63), X(0x1882150a), X(0x189b862c), X(0x18b501c4), X(0x18ce87c9), X(0x18e81836), X(0x1901b305), X(0x191b582f), X(0x193507ad), X(0x194ec17a), X(0x1968858f), X(0x198253e5), X(0x199c2c75), X(0x19b60f3a), X(0x19cffc2d), X(0x19e9f347), X(0x1a03f482), X(0x1a1dffd7), X(0x1a381540), X(0x1a5234b5), X(0x1a6c5e31), X(0x1a8691ac), X(0x1aa0cf21), X(0x1abb1687), X(0x1ad567da), X(0x1aefc311), X(0x1b0a2826), X(0x1b249712), X(0x1b3f0fd0), X(0x1b599257), X(0x1b741ea1), X(0x1b8eb4a7), X(0x1ba95462), X(0x1bc3fdcd), X(0x1bdeb0de), X(0x1bf96d91), X(0x1c1433dd), X(0x1c2f03bc), X(0x1c49dd27), X(0x1c64c017), X(0x1c7fac85), X(0x1c9aa269), X(0x1cb5a1be), X(0x1cd0aa7c), X(0x1cebbc9c), X(0x1d06d816), X(0x1d21fce4), X(0x1d3d2aff), X(0x1d586260), X(0x1d73a2fe), X(0x1d8eecd4), X(0x1daa3fda), X(0x1dc59c09), X(0x1de1015a), X(0x1dfc6fc5), X(0x1e17e743), X(0x1e3367cd), X(0x1e4ef15b), X(0x1e6a83e7), X(0x1e861f6a), X(0x1ea1c3da), X(0x1ebd7133), X(0x1ed9276b), X(0x1ef4e67c), X(0x1f10ae5e), X(0x1f2c7f0a), X(0x1f485879), X(0x1f643aa2), X(0x1f80257f), X(0x1f9c1908), X(0x1fb81536), X(0x1fd41a00), X(0x1ff02761), X(0x200c3d4f), X(0x20285bc3), X(0x204482b7), X(0x2060b221), X(0x207ce9fb), X(0x20992a3e), X(0x20b572e0), X(0x20d1c3dc), X(0x20ee1d28), X(0x210a7ebe), X(0x2126e895), X(0x21435aa6), X(0x215fd4ea), X(0x217c5757), X(0x2198e1e8), X(0x21b57493), X(0x21d20f51), X(0x21eeb21b), X(0x220b5ce7), X(0x22280fb0), X(0x2244ca6c), X(0x22618d13), X(0x227e579f), X(0x229b2a06), X(0x22b80442), X(0x22d4e649), X(0x22f1d015), X(0x230ec19d), X(0x232bbad9), X(0x2348bbc1), X(0x2365c44c), X(0x2382d474), X(0x239fec30), X(0x23bd0b78), X(0x23da3244), X(0x23f7608b), X(0x24149646), X(0x2431d36c), X(0x244f17f5), X(0x246c63da), X(0x2489b711), X(0x24a71193), X(0x24c47358), X(0x24e1dc57), X(0x24ff4c88), X(0x251cc3e2), X(0x253a425e), X(0x2557c7f4), X(0x2575549a), X(0x2592e848), X(0x25b082f7), X(0x25ce249e), X(0x25ebcd34), X(0x26097cb2), X(0x2627330e), X(0x2644f040), X(0x2662b441), X(0x26807f07), X(0x269e5089), X(0x26bc28c1), X(0x26da07a4), X(0x26f7ed2b), X(0x2715d94d), X(0x2733cc02), X(0x2751c540), X(0x276fc500), X(0x278dcb39), X(0x27abd7e2), X(0x27c9eaf3), X(0x27e80463), X(0x28062429), X(0x28244a3e), X(0x28427697), X(0x2860a92d), X(0x287ee1f7), X(0x289d20eb), X(0x28bb6603), X(0x28d9b134), X(0x28f80275), X(0x291659c0), X(0x2934b709), X(0x29531a49), X(0x29718378), X(0x298ff28b), X(0x29ae677b), X(0x29cce23e), X(0x29eb62cb), X(0x2a09e91b), X(0x2a287523), X(0x2a4706dc), X(0x2a659e3c), X(0x2a843b39), X(0x2aa2ddcd), X(0x2ac185ec), X(0x2ae0338f), X(0x2afee6ad), X(0x2b1d9f3c), X(0x2b3c5d33), X(0x2b5b208b), X(0x2b79e939), X(0x2b98b734), X(0x2bb78a74), X(0x2bd662ef), X(0x2bf5409d), X(0x2c142374), X(0x2c330b6b), X(0x2c51f87a), X(0x2c70ea97), X(0x2c8fe1b9), X(0x2caeddd6), X(0x2ccddee7), X(0x2cece4e1), X(0x2d0befbb), X(0x2d2aff6d), X(0x2d4a13ec), X(0x2d692d31), X(0x2d884b32), X(0x2da76de4), X(0x2dc69540), X(0x2de5c13d), X(0x2e04f1d0), X(0x2e2426f0), X(0x2e436095), X(0x2e629eb4), X(0x2e81e146), X(0x2ea1283f), X(0x2ec07398), X(0x2edfc347), X(0x2eff1742), X(0x2f1e6f80), X(0x2f3dcbf8), X(0x2f5d2ca0), X(0x2f7c916f), X(0x2f9bfa5c), X(0x2fbb675d), X(0x2fdad869), X(0x2ffa4d76), X(0x3019c67b), X(0x3039436f), X(0x3058c448), X(0x307848fc), X(0x3097d183), X(0x30b75dd3), X(0x30d6ede2), X(0x30f681a6), X(0x31161917), X(0x3135b42b), X(0x315552d8), X(0x3174f514), X(0x31949ad7), X(0x31b44417), X(0x31d3f0ca), X(0x31f3a0e6), X(0x32135462), X(0x32330b35), X(0x3252c555), X(0x327282b7), X(0x32924354), X(0x32b20720), X(0x32d1ce13), X(0x32f19823), X(0x33116546), X(0x33313573), X(0x3351089f), X(0x3370dec2), X(0x3390b7d1), X(0x33b093c3), X(0x33d0728f), X(0x33f05429), X(0x3410388a), X(0x34301fa7), X(0x34500977), X(0x346ff5ef), X(0x348fe506), X(0x34afd6b3), X(0x34cfcaeb), X(0x34efc1a5), X(0x350fbad7), X(0x352fb678), X(0x354fb47d), X(0x356fb4dd), X(0x358fb78e), X(0x35afbc86), X(0x35cfc3bc), X(0x35efcd25), X(0x360fd8b8), X(0x362fe66c), X(0x364ff636), X(0x3670080c), X(0x36901be5), X(0x36b031b7), X(0x36d04978), X(0x36f0631e), X(0x37107ea0), X(0x37309bf3), X(0x3750bb0e), X(0x3770dbe6), X(0x3790fe73), X(0x37b122aa), X(0x37d14881), X(0x37f16fee), X(0x381198e8), X(0x3831c365), X(0x3851ef5a), X(0x38721cbe), X(0x38924b87), X(0x38b27bac), X(0x38d2ad21), X(0x38f2dfde), X(0x391313d8), X(0x39334906), X(0x39537f5d), X(0x3973b6d4), X(0x3993ef60), X(0x39b428f9), X(0x39d46393), X(0x39f49f25), X(0x3a14dba6), X(0x3a35190a), X(0x3a555748), X(0x3a759657), X(0x3a95d62c), X(0x3ab616be), X(0x3ad65801), X(0x3af699ed), X(0x3b16dc78), X(0x3b371f97), X(0x3b576341), X(0x3b77a76c), X(0x3b97ec0d), X(0x3bb8311b), X(0x3bd8768b), X(0x3bf8bc55), X(0x3c19026d), X(0x3c3948ca), X(0x3c598f62), X(0x3c79d62b), X(0x3c9a1d1b), X(0x3cba6428), X(0x3cdaab48), X(0x3cfaf271), X(0x3d1b3999), X(0x3d3b80b6), X(0x3d5bc7be), X(0x3d7c0ea8), X(0x3d9c5569), X(0x3dbc9bf7), X(0x3ddce248), X(0x3dfd2852), X(0x3e1d6e0c), X(0x3e3db36c), X(0x3e5df866), X(0x3e7e3cf2), X(0x3e9e8106), X(0x3ebec497), X(0x3edf079b), X(0x3eff4a09), X(0x3f1f8bd7), X(0x3f3fccfa), X(0x3f600d69), X(0x3f804d1a), X(0x3fa08c02), X(0x3fc0ca19), X(0x3fe10753), X(0x400143a7), X(0x40217f0a), X(0x4041b974), X(0x4061f2da), X(0x40822b32), X(0x40a26272), X(0x40c29891), X(0x40e2cd83), X(0x41030140), X(0x412333bd), X(0x414364f1), X(0x416394d2), X(0x4183c355), X(0x41a3f070), X(0x41c41c1b), X(0x41e4464a), X(0x42046ef4), X(0x42249610), X(0x4244bb92), X(0x4264df72), X(0x428501a5), X(0x42a52222), X(0x42c540de), X(0x42e55dd0), X(0x430578ed), X(0x4325922d), X(0x4345a985), X(0x4365beeb), X(0x4385d255), X(0x43a5e3ba), X(0x43c5f30f), X(0x43e6004b), X(0x44060b65), X(0x44261451), X(0x44461b07), X(0x44661f7c), X(0x448621a7), X(0x44a6217d), X(0x44c61ef6), X(0x44e61a07), X(0x450612a6), X(0x452608ca), X(0x4545fc69), X(0x4565ed79), X(0x4585dbf1), X(0x45a5c7c6), X(0x45c5b0ef), X(0x45e59761), X(0x46057b15), X(0x46255bfe), X(0x46453a15), X(0x4665154f), X(0x4684eda2), X(0x46a4c305), X(0x46c4956e), X(0x46e464d3), X(0x4704312b), X(0x4723fa6c), X(0x4743c08d), X(0x47638382), X(0x47834344), X(0x47a2ffc9), X(0x47c2b906), X(0x47e26ef2), X(0x48022183), X(0x4821d0b1), X(0x48417c71), X(0x486124b9), X(0x4880c981), X(0x48a06abe), X(0x48c00867), X(0x48dfa272), X(0x48ff38d6), X(0x491ecb8a), X(0x493e5a84), X(0x495de5b9), X(0x497d6d22), X(0x499cf0b4), X(0x49bc7066), X(0x49dbec2e), X(0x49fb6402), X(0x4a1ad7db), X(0x4a3a47ad), X(0x4a59b370), X(0x4a791b1a), X(0x4a987ea1), X(0x4ab7ddfd), X(0x4ad73924), X(0x4af6900c), X(0x4b15e2ad), X(0x4b3530fc), X(0x4b547af1), X(0x4b73c082), X(0x4b9301a6), X(0x4bb23e53), X(0x4bd17681), X(0x4bf0aa25), X(0x4c0fd937), X(0x4c2f03ae), X(0x4c4e297f), X(0x4c6d4aa3), X(0x4c8c670f), X(0x4cab7eba), X(0x4cca919c), X(0x4ce99fab), X(0x4d08a8de), X(0x4d27ad2c), X(0x4d46ac8b), X(0x4d65a6f3), X(0x4d849c5a), X(0x4da38cb7), X(0x4dc27802), X(0x4de15e31), X(0x4e003f3a), X(0x4e1f1b16), X(0x4e3df1ba), X(0x4e5cc31e), X(0x4e7b8f3a), X(0x4e9a5603), X(0x4eb91771), X(0x4ed7d37b), X(0x4ef68a18), X(0x4f153b3f), X(0x4f33e6e7), X(0x4f528d08), X(0x4f712d97), X(0x4f8fc88e), X(0x4fae5de1), X(0x4fcced8a), X(0x4feb777f), X(0x5009fbb6), X(0x50287a28), X(0x5046f2cc), X(0x50656598), X(0x5083d284), X(0x50a23988), X(0x50c09a9a), X(0x50def5b1), X(0x50fd4ac7), X(0x511b99d0), X(0x5139e2c5), X(0x5158259e), X(0x51766251), X(0x519498d6), X(0x51b2c925), X(0x51d0f334), X(0x51ef16fb), X(0x520d3473), X(0x522b4b91), X(0x52495c4e), X(0x526766a2), X(0x52856a83), X(0x52a367e9), X(0x52c15ecd), X(0x52df4f24), X(0x52fd38e8), X(0x531b1c10), X(0x5338f892), X(0x5356ce68), X(0x53749d89), X(0x539265eb), X(0x53b02788), X(0x53cde257), X(0x53eb964f), X(0x54094369), X(0x5426e99c), X(0x544488df), X(0x5462212c), X(0x547fb279), X(0x549d3cbe), X(0x54babff4), X(0x54d83c12), X(0x54f5b110), X(0x55131ee7), X(0x5530858d), X(0x554de4fc), X(0x556b3d2a), X(0x55888e11), X(0x55a5d7a8), X(0x55c319e7), X(0x55e054c7), X(0x55fd883f), X(0x561ab447), X(0x5637d8d8), X(0x5654f5ea), X(0x56720b75), X(0x568f1971), X(0x56ac1fd7), X(0x56c91e9e), X(0x56e615c0), X(0x57030534), X(0x571fecf2), X(0x573cccf3), X(0x5759a530), X(0x577675a0), X(0x57933e3c), X(0x57affefd), X(0x57ccb7db), X(0x57e968ce), X(0x580611cf), X(0x5822b2d6), X(0x583f4bdd), X(0x585bdcdb), X(0x587865c9), X(0x5894e69f), X(0x58b15f57), X(0x58cdcfe9), X(0x58ea384e), X(0x5906987d), X(0x5922f071), X(0x593f4022), X(0x595b8788), X(0x5977c69c), X(0x5993fd57), X(0x59b02bb2), X(0x59cc51a6), X(0x59e86f2c), X(0x5a04843c), X(0x5a2090d0), X(0x5a3c94e0), X(0x5a589065), X(0x5a748359), X(0x5a906db4), X(0x5aac4f70), X(0x5ac82884), X(0x5ae3f8ec), X(0x5affc09f), X(0x5b1b7f97), X(0x5b3735cd), X(0x5b52e33a), X(0x5b6e87d8), X(0x5b8a239f), X(0x5ba5b689), X(0x5bc1408f), X(0x5bdcc1aa), X(0x5bf839d5), X(0x5c13a907), X(0x5c2f0f3b), X(0x5c4a6c6a), X(0x5c65c08d), X(0x5c810b9e), X(0x5c9c4d97), X(0x5cb78670), X(0x5cd2b623), X(0x5ceddcaa), X(0x5d08f9ff), X(0x5d240e1b), X(0x5d3f18f8), X(0x5d5a1a8f), X(0x5d7512da), X(0x5d9001d3), X(0x5daae773), X(0x5dc5c3b5), X(0x5de09692), X(0x5dfb6004), X(0x5e162004), X(0x5e30d68d), X(0x5e4b8399), X(0x5e662721), X(0x5e80c11f), X(0x5e9b518e), X(0x5eb5d867), X(0x5ed055a4), X(0x5eeac940), X(0x5f053334), X(0x5f1f937b), X(0x5f39ea0f), X(0x5f5436ea), X(0x5f6e7a06), X(0x5f88b35d), X(0x5fa2e2e9), X(0x5fbd08a6), X(0x5fd7248d), X(0x5ff13698), X(0x600b3ec2), X(0x60253d05), X(0x603f315b), X(0x60591bc0), X(0x6072fc2d), X(0x608cd29e), X(0x60a69f0b), X(0x60c06171), X(0x60da19ca), X(0x60f3c80f), X(0x610d6c3d), X(0x6127064d), X(0x6140963a), X(0x615a1bff), X(0x61739797), X(0x618d08fc), X(0x61a67029), X(0x61bfcd1a), X(0x61d91fc8), X(0x61f2682f), X(0x620ba64a), X(0x6224da13), X(0x623e0386), X(0x6257229d), X(0x62703754), X(0x628941a6), X(0x62a2418e), X(0x62bb3706), X(0x62d4220a), X(0x62ed0296), X(0x6305d8a3), X(0x631ea42f), X(0x63376533), X(0x63501bab), X(0x6368c793), X(0x638168e5), X(0x6399ff9e), X(0x63b28bb8), X(0x63cb0d2f), X(0x63e383ff), X(0x63fbf022), X(0x64145195), X(0x642ca853), X(0x6444f457), X(0x645d359e), X(0x64756c22), X(0x648d97e0), X(0x64a5b8d3), X(0x64bdcef6), X(0x64d5da47), X(0x64eddabf), X(0x6505d05c), X(0x651dbb19), X(0x65359af2), X(0x654d6fe3), X(0x656539e7), X(0x657cf8fb), X(0x6594ad1b), X(0x65ac5643), X(0x65c3f46e), X(0x65db8799), X(0x65f30fc0), X(0x660a8ce0), X(0x6621fef3), X(0x663965f7), X(0x6650c1e7), X(0x666812c1), X(0x667f5880), X(0x66969320), X(0x66adc29e), X(0x66c4e6f7), X(0x66dc0026), X(0x66f30e28), X(0x670a10fa), X(0x67210898), X(0x6737f4ff), X(0x674ed62b), X(0x6765ac19), X(0x677c76c5), X(0x6793362c), X(0x67a9ea4b), X(0x67c0931f), X(0x67d730a3), X(0x67edc2d6), X(0x680449b3), X(0x681ac538), X(0x68313562), X(0x68479a2d), X(0x685df396), X(0x6874419b), X(0x688a8438), X(0x68a0bb6a), X(0x68b6e72e), X(0x68cd0782), X(0x68e31c63), X(0x68f925cd), X(0x690f23be), X(0x69251633), X(0x693afd29), X(0x6950d89e), X(0x6966a88f), X(0x697c6cf8), X(0x699225d9), X(0x69a7d32d), X(0x69bd74f3), X(0x69d30b27), X(0x69e895c8), X(0x69fe14d2), X(0x6a138844), X(0x6a28f01b), X(0x6a3e4c54), X(0x6a539ced), X(0x6a68e1e4), X(0x6a7e1b37), X(0x6a9348e3), X(0x6aa86ae6), X(0x6abd813d), X(0x6ad28be7), X(0x6ae78ae2), X(0x6afc7e2b), X(0x6b1165c0), X(0x6b26419f), X(0x6b3b11c7), X(0x6b4fd634), X(0x6b648ee6), X(0x6b793bda), X(0x6b8ddd0e), X(0x6ba27281), X(0x6bb6fc31), X(0x6bcb7a1b), X(0x6bdfec3e), X(0x6bf45299), X(0x6c08ad29), X(0x6c1cfbed), X(0x6c313ee4), X(0x6c45760a), X(0x6c59a160), X(0x6c6dc0e4), X(0x6c81d493), X(0x6c95dc6d), X(0x6ca9d86f), X(0x6cbdc899), X(0x6cd1acea), X(0x6ce5855f), X(0x6cf951f7), X(0x6d0d12b1), X(0x6d20c78c), X(0x6d347087), X(0x6d480da0), X(0x6d5b9ed6), X(0x6d6f2427), X(0x6d829d94), X(0x6d960b1a), X(0x6da96cb9), X(0x6dbcc270), X(0x6dd00c3c), X(0x6de34a1f), X(0x6df67c16), X(0x6e09a221), X(0x6e1cbc3f), X(0x6e2fca6e), X(0x6e42ccaf), X(0x6e55c300), X(0x6e68ad60), X(0x6e7b8bd0), X(0x6e8e5e4d), X(0x6ea124d8), X(0x6eb3df70), X(0x6ec68e13), X(0x6ed930c3), X(0x6eebc77d), X(0x6efe5242), X(0x6f10d111), X(0x6f2343e9), X(0x6f35aacb), X(0x6f4805b5), X(0x6f5a54a8), X(0x6f6c97a2), X(0x6f7ecea4), X(0x6f90f9ae), X(0x6fa318be), X(0x6fb52bd6), X(0x6fc732f4), X(0x6fd92e19), X(0x6feb1d44), X(0x6ffd0076), X(0x700ed7ad), X(0x7020a2eb), X(0x7032622f), X(0x7044157a), X(0x7055bcca), X(0x70675821), X(0x7078e77e), X(0x708a6ae2), X(0x709be24c), X(0x70ad4dbd), X(0x70bead36), X(0x70d000b5), X(0x70e1483d), X(0x70f283cc), X(0x7103b363), X(0x7114d704), X(0x7125eead), X(0x7136fa60), X(0x7147fa1c), X(0x7158ede4), X(0x7169d5b6), X(0x717ab193), X(0x718b817d), X(0x719c4573), X(0x71acfd76), X(0x71bda988), X(0x71ce49a8), X(0x71deddd7), X(0x71ef6617), X(0x71ffe267), X(0x721052ca), X(0x7220b73e), X(0x72310fc6), X(0x72415c62), X(0x72519d14), X(0x7261d1db), X(0x7271faba), X(0x728217b1), X(0x729228c0), X(0x72a22dea), X(0x72b22730), X(0x72c21491), X(0x72d1f611), X(0x72e1cbaf), X(0x72f1956c), X(0x7301534c), X(0x7311054d), X(0x7320ab72), X(0x733045bc), X(0x733fd42d), X(0x734f56c5), X(0x735ecd86), X(0x736e3872), X(0x737d9789), X(0x738ceacf), X(0x739c3243), X(0x73ab6de7), X(0x73ba9dbe), X(0x73c9c1c8), X(0x73d8da08), X(0x73e7e67f), X(0x73f6e72e), X(0x7405dc17), X(0x7414c53c), X(0x7423a29f), X(0x74327442), X(0x74413a26), X(0x744ff44d), X(0x745ea2b9), X(0x746d456c), X(0x747bdc68), X(0x748a67ae), X(0x7498e741), X(0x74a75b23), X(0x74b5c356), X(0x74c41fdb), X(0x74d270b6), X(0x74e0b5e7), X(0x74eeef71), X(0x74fd1d57), X(0x750b3f9a), X(0x7519563c), X(0x75276140), X(0x753560a8), X(0x75435477), X(0x75513cae), X(0x755f1951), X(0x756cea60), X(0x757aafdf), X(0x758869d1), X(0x75961837), X(0x75a3bb14), X(0x75b1526a), X(0x75bede3c), X(0x75cc5e8d), X(0x75d9d35f), X(0x75e73cb5), X(0x75f49a91), X(0x7601ecf6), X(0x760f33e6), X(0x761c6f65), X(0x76299f74), X(0x7636c417), X(0x7643dd51), X(0x7650eb24), X(0x765ded93), X(0x766ae4a0), X(0x7677d050), X(0x7684b0a4), X(0x7691859f), X(0x769e4f45), X(0x76ab0d98), X(0x76b7c09c), X(0x76c46852), X(0x76d104bf), X(0x76dd95e6), X(0x76ea1bc9), X(0x76f6966b), X(0x770305d0), X(0x770f69fb), X(0x771bc2ef), X(0x772810af), X(0x7734533e), X(0x77408aa0), X(0x774cb6d7), X(0x7758d7e8), X(0x7764edd5), X(0x7770f8a2), X(0x777cf852), X(0x7788ece8), X(0x7794d668), X(0x77a0b4d5), X(0x77ac8833), X(0x77b85085), X(0x77c40dce), X(0x77cfc013), X(0x77db6756), X(0x77e7039b), X(0x77f294e6), X(0x77fe1b3b), X(0x7809969c), X(0x7815070e), X(0x78206c93), X(0x782bc731), X(0x783716ea), X(0x78425bc3), X(0x784d95be), X(0x7858c4e1), X(0x7863e92d), X(0x786f02a8), X(0x787a1156), X(0x78851539), X(0x78900e56), X(0x789afcb1), X(0x78a5e04d), X(0x78b0b92f), X(0x78bb875b), X(0x78c64ad4), X(0x78d1039e), X(0x78dbb1be), X(0x78e65537), X(0x78f0ee0e), X(0x78fb7c46), X(0x7905ffe4), X(0x791078ec), X(0x791ae762), X(0x79254b4a), X(0x792fa4a7), X(0x7939f380), X(0x794437d7), X(0x794e71b0), X(0x7958a111), X(0x7962c5fd), X(0x796ce078), X(0x7976f087), X(0x7980f62f), X(0x798af173), X(0x7994e258), X(0x799ec8e2), X(0x79a8a515), X(0x79b276f7), X(0x79bc3e8b), X(0x79c5fbd6), X(0x79cfaedc), X(0x79d957a2), X(0x79e2f62c), X(0x79ec8a7f), X(0x79f6149f), X(0x79ff9492), X(0x7a090a5a), X(0x7a1275fe), X(0x7a1bd781), X(0x7a252ee9), X(0x7a2e7c39), X(0x7a37bf77), X(0x7a40f8a7), X(0x7a4a27ce), X(0x7a534cf0), X(0x7a5c6813), X(0x7a65793b), X(0x7a6e806d), X(0x7a777dad), X(0x7a807100), X(0x7a895a6b), X(0x7a9239f4), X(0x7a9b0f9e), X(0x7aa3db6f), X(0x7aac9d6b), X(0x7ab55597), X(0x7abe03f9), X(0x7ac6a895), X(0x7acf4370), X(0x7ad7d48f), X(0x7ae05bf6), X(0x7ae8d9ac), X(0x7af14db5), X(0x7af9b815), X(0x7b0218d2), X(0x7b0a6ff2), X(0x7b12bd78), X(0x7b1b016a), X(0x7b233bce), X(0x7b2b6ca7), X(0x7b3393fc), X(0x7b3bb1d1), X(0x7b43c62c), X(0x7b4bd111), X(0x7b53d286), X(0x7b5bca90), X(0x7b63b935), X(0x7b6b9e78), X(0x7b737a61), X(0x7b7b4cf3), X(0x7b831634), X(0x7b8ad629), X(0x7b928cd8), X(0x7b9a3a45), X(0x7ba1de77), X(0x7ba97972), X(0x7bb10b3c), X(0x7bb893d9), X(0x7bc01350), X(0x7bc789a6), X(0x7bcef6e0), X(0x7bd65b03), X(0x7bddb616), X(0x7be5081c), X(0x7bec511c), X(0x7bf3911b), X(0x7bfac81f), X(0x7c01f62c), X(0x7c091b49), X(0x7c10377b), X(0x7c174ac7), X(0x7c1e5532), X(0x7c2556c4), X(0x7c2c4f80), X(0x7c333f6c), X(0x7c3a268e), X(0x7c4104ec), X(0x7c47da8a), X(0x7c4ea76f), X(0x7c556ba1), X(0x7c5c2724), X(0x7c62d9fe), X(0x7c698435), X(0x7c7025cf), X(0x7c76bed0), X(0x7c7d4f40), X(0x7c83d723), X(0x7c8a567f), X(0x7c90cd5a), X(0x7c973bb9), X(0x7c9da1a2), X(0x7ca3ff1b), X(0x7caa542a), X(0x7cb0a0d3), X(0x7cb6e51e), X(0x7cbd210f), X(0x7cc354ac), X(0x7cc97ffc), X(0x7ccfa304), X(0x7cd5bdc9), X(0x7cdbd051), X(0x7ce1daa3), X(0x7ce7dcc3), X(0x7cedd6b8), X(0x7cf3c888), X(0x7cf9b238), X(0x7cff93cf), X(0x7d056d51), X(0x7d0b3ec5), X(0x7d110830), X(0x7d16c99a), X(0x7d1c8306), X(0x7d22347c), X(0x7d27de00), X(0x7d2d7f9a), X(0x7d33194f), X(0x7d38ab24), X(0x7d3e351f), X(0x7d43b748), X(0x7d4931a2), X(0x7d4ea435), X(0x7d540f06), X(0x7d59721b), X(0x7d5ecd7b), X(0x7d64212a), X(0x7d696d2f), X(0x7d6eb190), X(0x7d73ee53), X(0x7d79237e), X(0x7d7e5117), X(0x7d837723), X(0x7d8895a9), X(0x7d8dacae), X(0x7d92bc3a), X(0x7d97c451), X(0x7d9cc4f9), X(0x7da1be39), X(0x7da6b017), X(0x7dab9a99), X(0x7db07dc4), X(0x7db5599e), X(0x7dba2e2f), X(0x7dbefb7b), X(0x7dc3c189), X(0x7dc8805e), X(0x7dcd3802), X(0x7dd1e879), X(0x7dd691ca), X(0x7ddb33fb), X(0x7ddfcf12), X(0x7de46315), X(0x7de8f00a), X(0x7ded75f8), X(0x7df1f4e3), X(0x7df66cd3), X(0x7dfaddcd), X(0x7dff47d7), X(0x7e03aaf8), X(0x7e080735), X(0x7e0c5c95), X(0x7e10ab1e), X(0x7e14f2d5), X(0x7e1933c1), X(0x7e1d6de8), X(0x7e21a150), X(0x7e25cdff), X(0x7e29f3fc), X(0x7e2e134c), X(0x7e322bf5), X(0x7e363dfd), X(0x7e3a496b), X(0x7e3e4e45), X(0x7e424c90), X(0x7e464454), X(0x7e4a3595), X(0x7e4e205a), X(0x7e5204aa), X(0x7e55e289), X(0x7e59b9ff), X(0x7e5d8b12), X(0x7e6155c7), X(0x7e651a24), X(0x7e68d831), X(0x7e6c8ff2), X(0x7e70416e), X(0x7e73ecac), X(0x7e7791b0), X(0x7e7b3082), X(0x7e7ec927), X(0x7e825ba6), X(0x7e85e804), X(0x7e896e48), X(0x7e8cee77), X(0x7e906899), X(0x7e93dcb2), X(0x7e974aca), X(0x7e9ab2e5), X(0x7e9e150b), X(0x7ea17141), X(0x7ea4c78e), X(0x7ea817f7), X(0x7eab6283), X(0x7eaea737), X(0x7eb1e61a), X(0x7eb51f33), X(0x7eb85285), X(0x7ebb8019), X(0x7ebea7f4), X(0x7ec1ca1d), X(0x7ec4e698), X(0x7ec7fd6d), X(0x7ecb0ea1), X(0x7ece1a3a), X(0x7ed1203f), X(0x7ed420b6), X(0x7ed71ba4), X(0x7eda110f), X(0x7edd00ff), X(0x7edfeb78), X(0x7ee2d081), X(0x7ee5b01f), X(0x7ee88a5a), X(0x7eeb5f36), X(0x7eee2eba), X(0x7ef0f8ed), X(0x7ef3bdd3), X(0x7ef67d73), X(0x7ef937d3), X(0x7efbecf9), X(0x7efe9ceb), X(0x7f0147ae), X(0x7f03ed4a), X(0x7f068dc4), X(0x7f092922), X(0x7f0bbf69), X(0x7f0e50a1), X(0x7f10dcce), X(0x7f1363f7), X(0x7f15e622), X(0x7f186355), X(0x7f1adb95), X(0x7f1d4ee9), X(0x7f1fbd57), X(0x7f2226e4), X(0x7f248b96), X(0x7f26eb74), X(0x7f294683), X(0x7f2b9cc9), X(0x7f2dee4d), X(0x7f303b13), X(0x7f328322), X(0x7f34c680), X(0x7f370533), X(0x7f393f40), X(0x7f3b74ad), X(0x7f3da581), X(0x7f3fd1c1), X(0x7f41f972), X(0x7f441c9c), X(0x7f463b43), X(0x7f48556d), X(0x7f4a6b21), X(0x7f4c7c64), X(0x7f4e893c), X(0x7f5091ae), X(0x7f5295c1), X(0x7f54957a), X(0x7f5690e0), X(0x7f5887f7), X(0x7f5a7ac5), X(0x7f5c6951), X(0x7f5e53a0), X(0x7f6039b8), X(0x7f621b9e), X(0x7f63f958), X(0x7f65d2ed), X(0x7f67a861), X(0x7f6979ba), X(0x7f6b46ff), X(0x7f6d1034), X(0x7f6ed560), X(0x7f709687), X(0x7f7253b1), X(0x7f740ce1), X(0x7f75c21f), X(0x7f777370), X(0x7f7920d8), X(0x7f7aca5f), X(0x7f7c7008), X(0x7f7e11db), X(0x7f7fafdd), X(0x7f814a13), X(0x7f82e082), X(0x7f847331), X(0x7f860224), X(0x7f878d62), X(0x7f8914f0), X(0x7f8a98d4), X(0x7f8c1912), X(0x7f8d95b0), X(0x7f8f0eb5), X(0x7f908425), X(0x7f91f605), X(0x7f93645c), X(0x7f94cf2f), X(0x7f963683), X(0x7f979a5d), X(0x7f98fac4), X(0x7f9a57bb), X(0x7f9bb14a), X(0x7f9d0775), X(0x7f9e5a41), X(0x7f9fa9b4), X(0x7fa0f5d3), X(0x7fa23ea4), X(0x7fa3842b), X(0x7fa4c66f), X(0x7fa60575), X(0x7fa74141), X(0x7fa879d9), X(0x7fa9af42), X(0x7faae182), X(0x7fac109e), X(0x7fad3c9a), X(0x7fae657d), X(0x7faf8b4c), X(0x7fb0ae0b), X(0x7fb1cdc0), X(0x7fb2ea70), X(0x7fb40420), X(0x7fb51ad5), X(0x7fb62e95), X(0x7fb73f64), X(0x7fb84d48), X(0x7fb95846), X(0x7fba6062), X(0x7fbb65a2), X(0x7fbc680c), X(0x7fbd67a3), X(0x7fbe646d), X(0x7fbf5e70), X(0x7fc055af), X(0x7fc14a31), X(0x7fc23bf9), X(0x7fc32b0d), X(0x7fc41773), X(0x7fc5012e), X(0x7fc5e844), X(0x7fc6ccba), X(0x7fc7ae94), X(0x7fc88dd8), X(0x7fc96a8a), X(0x7fca44af), X(0x7fcb1c4c), X(0x7fcbf167), X(0x7fccc403), X(0x7fcd9425), X(0x7fce61d3), X(0x7fcf2d11), X(0x7fcff5e3), X(0x7fd0bc4f), X(0x7fd1805a), X(0x7fd24207), X(0x7fd3015c), X(0x7fd3be5d), X(0x7fd47910), X(0x7fd53178), X(0x7fd5e79b), X(0x7fd69b7c), X(0x7fd74d21), X(0x7fd7fc8e), X(0x7fd8a9c8), X(0x7fd954d4), X(0x7fd9fdb5), X(0x7fdaa471), X(0x7fdb490b), X(0x7fdbeb89), X(0x7fdc8bef), X(0x7fdd2a42), X(0x7fddc685), X(0x7fde60be), X(0x7fdef8f0), X(0x7fdf8f20), X(0x7fe02353), X(0x7fe0b58d), X(0x7fe145d3), X(0x7fe1d428), X(0x7fe26091), X(0x7fe2eb12), X(0x7fe373b0), X(0x7fe3fa6f), X(0x7fe47f53), X(0x7fe50260), X(0x7fe5839b), X(0x7fe60308), X(0x7fe680ab), X(0x7fe6fc88), X(0x7fe776a4), X(0x7fe7ef02), X(0x7fe865a7), X(0x7fe8da97), X(0x7fe94dd6), X(0x7fe9bf68), X(0x7fea2f51), X(0x7fea9d95), X(0x7feb0a39), X(0x7feb7540), X(0x7febdeae), X(0x7fec4687), X(0x7fecaccf), X(0x7fed118b), X(0x7fed74be), X(0x7fedd66c), X(0x7fee3698), X(0x7fee9548), X(0x7feef27e), X(0x7fef4e3f), X(0x7fefa88e), X(0x7ff0016f), X(0x7ff058e7), X(0x7ff0aef8), X(0x7ff103a6), X(0x7ff156f6), X(0x7ff1a8eb), X(0x7ff1f988), X(0x7ff248d2), X(0x7ff296cc), X(0x7ff2e37a), X(0x7ff32edf), X(0x7ff378ff), X(0x7ff3c1de), X(0x7ff4097e), X(0x7ff44fe5), X(0x7ff49515), X(0x7ff4d911), X(0x7ff51bde), X(0x7ff55d7f), X(0x7ff59df7), X(0x7ff5dd4a), X(0x7ff61b7b), X(0x7ff6588d), X(0x7ff69485), X(0x7ff6cf65), X(0x7ff70930), X(0x7ff741eb), X(0x7ff77998), X(0x7ff7b03b), X(0x7ff7e5d7), X(0x7ff81a6f), X(0x7ff84e06), X(0x7ff880a1), X(0x7ff8b241), X(0x7ff8e2ea), X(0x7ff912a0), X(0x7ff94165), X(0x7ff96f3d), X(0x7ff99c2b), X(0x7ff9c831), X(0x7ff9f354), X(0x7ffa1d95), X(0x7ffa46f9), X(0x7ffa6f81), X(0x7ffa9731), X(0x7ffabe0d), X(0x7ffae416), X(0x7ffb0951), X(0x7ffb2dbf), X(0x7ffb5164), X(0x7ffb7442), X(0x7ffb965d), X(0x7ffbb7b8), X(0x7ffbd854), X(0x7ffbf836), X(0x7ffc175f), X(0x7ffc35d3), X(0x7ffc5394), X(0x7ffc70a5), X(0x7ffc8d09), X(0x7ffca8c2), X(0x7ffcc3d4), X(0x7ffcde3f), X(0x7ffcf809), X(0x7ffd1132), X(0x7ffd29be), X(0x7ffd41ae), X(0x7ffd5907), X(0x7ffd6fc9), X(0x7ffd85f9), X(0x7ffd9b97), X(0x7ffdb0a7), X(0x7ffdc52b), X(0x7ffdd926), X(0x7ffdec99), X(0x7ffdff88), X(0x7ffe11f4), X(0x7ffe23e0), X(0x7ffe354f), X(0x7ffe4642), X(0x7ffe56bc), X(0x7ffe66bf), X(0x7ffe764e), X(0x7ffe856a), X(0x7ffe9416), X(0x7ffea254), X(0x7ffeb026), X(0x7ffebd8e), X(0x7ffeca8f), X(0x7ffed72a), X(0x7ffee362), X(0x7ffeef38), X(0x7ffefaaf), X(0x7fff05c9), X(0x7fff1087), X(0x7fff1aec), X(0x7fff24f9), X(0x7fff2eb1), X(0x7fff3816), X(0x7fff4128), X(0x7fff49eb), X(0x7fff5260), X(0x7fff5a88), X(0x7fff6266), X(0x7fff69fc), X(0x7fff714b), X(0x7fff7854), X(0x7fff7f1a), X(0x7fff859f), X(0x7fff8be3), X(0x7fff91ea), X(0x7fff97b3), X(0x7fff9d41), X(0x7fffa296), X(0x7fffa7b3), X(0x7fffac99), X(0x7fffb14b), X(0x7fffb5c9), X(0x7fffba15), X(0x7fffbe31), X(0x7fffc21d), X(0x7fffc5dc), X(0x7fffc96f), X(0x7fffccd8), X(0x7fffd016), X(0x7fffd32d), X(0x7fffd61c), X(0x7fffd8e7), X(0x7fffdb8d), X(0x7fffde0f), X(0x7fffe071), X(0x7fffe2b1), X(0x7fffe4d2), X(0x7fffe6d5), X(0x7fffe8bb), X(0x7fffea85), X(0x7fffec34), X(0x7fffedc9), X(0x7fffef45), X(0x7ffff0aa), X(0x7ffff1f7), X(0x7ffff330), X(0x7ffff453), X(0x7ffff562), X(0x7ffff65f), X(0x7ffff749), X(0x7ffff823), X(0x7ffff8ec), X(0x7ffff9a6), X(0x7ffffa51), X(0x7ffffaee), X(0x7ffffb7e), X(0x7ffffc02), X(0x7ffffc7a), X(0x7ffffce7), X(0x7ffffd4a), X(0x7ffffda3), X(0x7ffffdf4), X(0x7ffffe3c), X(0x7ffffe7c), X(0x7ffffeb6), X(0x7ffffee8), X(0x7fffff15), X(0x7fffff3c), X(0x7fffff5e), X(0x7fffff7b), X(0x7fffff95), X(0x7fffffaa), X(0x7fffffbc), X(0x7fffffcb), X(0x7fffffd7), X(0x7fffffe2), X(0x7fffffea), X(0x7ffffff0), X(0x7ffffff5), X(0x7ffffff9), X(0x7ffffffb), X(0x7ffffffd), X(0x7ffffffe), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), }; static const LOOKUP_T vwin8192[4096] = { X(0x0000007c), X(0x0000045c), X(0x00000c1d), X(0x000017bd), X(0x0000273e), X(0x00003a9f), X(0x000051e0), X(0x00006d02), X(0x00008c03), X(0x0000aee5), X(0x0000d5a7), X(0x00010049), X(0x00012ecb), X(0x0001612d), X(0x00019770), X(0x0001d193), X(0x00020f96), X(0x00025178), X(0x0002973c), X(0x0002e0df), X(0x00032e62), X(0x00037fc5), X(0x0003d509), X(0x00042e2c), X(0x00048b30), X(0x0004ec13), X(0x000550d7), X(0x0005b97a), X(0x000625fe), X(0x00069661), X(0x00070aa4), X(0x000782c8), X(0x0007fecb), X(0x00087eae), X(0x00090271), X(0x00098a14), X(0x000a1597), X(0x000aa4f9), X(0x000b383b), X(0x000bcf5d), X(0x000c6a5f), X(0x000d0941), X(0x000dac02), X(0x000e52a3), X(0x000efd23), X(0x000fab84), X(0x00105dc3), X(0x001113e3), X(0x0011cde2), X(0x00128bc0), X(0x00134d7e), X(0x0014131b), X(0x0014dc98), X(0x0015a9f4), X(0x00167b30), X(0x0017504a), X(0x00182945), X(0x0019061e), X(0x0019e6d7), X(0x001acb6f), X(0x001bb3e6), X(0x001ca03c), X(0x001d9071), X(0x001e8485), X(0x001f7c79), X(0x0020784b), X(0x002177fc), X(0x00227b8c), X(0x002382fb), X(0x00248e49), X(0x00259d76), X(0x0026b081), X(0x0027c76b), X(0x0028e234), X(0x002a00dc), X(0x002b2361), X(0x002c49c6), X(0x002d7409), X(0x002ea22a), X(0x002fd42a), X(0x00310a08), X(0x003243c5), X(0x00338160), X(0x0034c2d9), X(0x00360830), X(0x00375165), X(0x00389e78), X(0x0039ef6a), X(0x003b4439), X(0x003c9ce6), X(0x003df971), X(0x003f59da), X(0x0040be20), X(0x00422645), X(0x00439247), X(0x00450226), X(0x004675e3), X(0x0047ed7e), X(0x004968f5), X(0x004ae84b), X(0x004c6b7d), X(0x004df28d), X(0x004f7d7a), X(0x00510c44), X(0x00529eeb), X(0x00543570), X(0x0055cfd1), X(0x00576e0f), X(0x00591029), X(0x005ab621), X(0x005c5ff5), X(0x005e0da6), X(0x005fbf33), X(0x0061749d), X(0x00632de4), X(0x0064eb06), X(0x0066ac05), X(0x006870e0), X(0x006a3998), X(0x006c062b), X(0x006dd69b), X(0x006faae6), X(0x0071830d), X(0x00735f10), X(0x00753eef), X(0x007722a9), X(0x00790a3f), X(0x007af5b1), X(0x007ce4fe), X(0x007ed826), X(0x0080cf29), X(0x0082ca08), X(0x0084c8c2), X(0x0086cb57), X(0x0088d1c7), X(0x008adc11), X(0x008cea37), X(0x008efc37), X(0x00911212), X(0x00932bc7), X(0x00954957), X(0x00976ac2), X(0x00999006), X(0x009bb925), X(0x009de61e), X(0x00a016f1), X(0x00a24b9e), X(0x00a48425), X(0x00a6c086), X(0x00a900c0), X(0x00ab44d4), X(0x00ad8cc2), X(0x00afd889), X(0x00b22829), X(0x00b47ba2), X(0x00b6d2f5), X(0x00b92e21), X(0x00bb8d26), X(0x00bdf004), X(0x00c056ba), X(0x00c2c149), X(0x00c52fb1), X(0x00c7a1f1), X(0x00ca180a), X(0x00cc91fb), X(0x00cf0fc5), X(0x00d19166), X(0x00d416df), X(0x00d6a031), X(0x00d92d5a), X(0x00dbbe5b), X(0x00de5333), X(0x00e0ebe3), X(0x00e3886b), X(0x00e628c9), X(0x00e8ccff), X(0x00eb750c), X(0x00ee20f0), X(0x00f0d0ab), X(0x00f3843d), X(0x00f63ba5), X(0x00f8f6e4), X(0x00fbb5fa), X(0x00fe78e5), X(0x01013fa7), X(0x01040a3f), X(0x0106d8ae), X(0x0109aaf2), X(0x010c810c), X(0x010f5afb), X(0x011238c0), X(0x01151a5b), X(0x0117ffcb), X(0x011ae910), X(0x011dd62a), X(0x0120c719), X(0x0123bbdd), X(0x0126b476), X(0x0129b0e4), X(0x012cb126), X(0x012fb53c), X(0x0132bd27), X(0x0135c8e6), X(0x0138d879), X(0x013bebdf), X(0x013f031a), X(0x01421e28), X(0x01453d0a), X(0x01485fbf), X(0x014b8648), X(0x014eb0a4), X(0x0151ded2), X(0x015510d4), X(0x015846a8), X(0x015b8050), X(0x015ebdc9), X(0x0161ff15), X(0x01654434), X(0x01688d24), X(0x016bd9e6), X(0x016f2a7b), X(0x01727ee1), X(0x0175d718), X(0x01793321), X(0x017c92fc), X(0x017ff6a7), X(0x01835e24), X(0x0186c972), X(0x018a3890), X(0x018dab7f), X(0x0191223f), X(0x01949ccf), X(0x01981b2f), X(0x019b9d5f), X(0x019f235f), X(0x01a2ad2f), X(0x01a63acf), X(0x01a9cc3e), X(0x01ad617c), X(0x01b0fa8a), X(0x01b49767), X(0x01b83813), X(0x01bbdc8d), X(0x01bf84d6), X(0x01c330ee), X(0x01c6e0d4), X(0x01ca9488), X(0x01ce4c0b), X(0x01d2075b), X(0x01d5c679), X(0x01d98964), X(0x01dd501d), X(0x01e11aa3), X(0x01e4e8f6), X(0x01e8bb17), X(0x01ec9104), X(0x01f06abd), X(0x01f44844), X(0x01f82996), X(0x01fc0eb5), X(0x01fff7a0), X(0x0203e456), X(0x0207d4d9), X(0x020bc926), X(0x020fc140), X(0x0213bd24), X(0x0217bcd4), X(0x021bc04e), X(0x021fc793), X(0x0223d2a3), X(0x0227e17d), X(0x022bf421), X(0x02300a90), X(0x023424c8), X(0x023842ca), X(0x023c6495), X(0x02408a2a), X(0x0244b389), X(0x0248e0b0), X(0x024d11a0), X(0x02514659), X(0x02557eda), X(0x0259bb24), X(0x025dfb35), X(0x02623f0f), X(0x026686b1), X(0x026ad21a), X(0x026f214b), X(0x02737443), X(0x0277cb02), X(0x027c2588), X(0x028083d5), X(0x0284e5e9), X(0x02894bc2), X(0x028db562), X(0x029222c8), X(0x029693f4), X(0x029b08e6), X(0x029f819d), X(0x02a3fe19), X(0x02a87e5b), X(0x02ad0261), X(0x02b18a2c), X(0x02b615bb), X(0x02baa50f), X(0x02bf3827), X(0x02c3cf03), X(0x02c869a3), X(0x02cd0807), X(0x02d1aa2d), X(0x02d65017), X(0x02daf9c4), X(0x02dfa734), X(0x02e45866), X(0x02e90d5b), X(0x02edc612), X(0x02f2828b), X(0x02f742c6), X(0x02fc06c3), X(0x0300ce80), X(0x030599ff), X(0x030a6940), X(0x030f3c40), X(0x03141302), X(0x0318ed84), X(0x031dcbc6), X(0x0322adc8), X(0x0327938a), X(0x032c7d0c), X(0x03316a4c), X(0x03365b4d), X(0x033b500c), X(0x03404889), X(0x034544c6), X(0x034a44c0), X(0x034f4879), X(0x03544ff0), X(0x03595b24), X(0x035e6a16), X(0x03637cc5), X(0x03689331), X(0x036dad5a), X(0x0372cb40), X(0x0377ece2), X(0x037d1240), X(0x03823b5a), X(0x03876830), X(0x038c98c1), X(0x0391cd0e), X(0x03970516), X(0x039c40d8), X(0x03a18055), X(0x03a6c38d), X(0x03ac0a7f), X(0x03b1552b), X(0x03b6a390), X(0x03bbf5af), X(0x03c14b88), X(0x03c6a519), X(0x03cc0263), X(0x03d16366), X(0x03d6c821), X(0x03dc3094), X(0x03e19cc0), X(0x03e70ca2), X(0x03ec803d), X(0x03f1f78e), X(0x03f77296), X(0x03fcf155), X(0x040273cb), X(0x0407f9f7), X(0x040d83d9), X(0x04131170), X(0x0418a2bd), X(0x041e37c0), X(0x0423d077), X(0x04296ce4), X(0x042f0d04), X(0x0434b0da), X(0x043a5863), X(0x044003a0), X(0x0445b290), X(0x044b6534), X(0x04511b8b), X(0x0456d595), X(0x045c9352), X(0x046254c1), X(0x046819e1), X(0x046de2b4), X(0x0473af39), X(0x04797f6e), X(0x047f5355), X(0x04852aec), X(0x048b0635), X(0x0490e52d), X(0x0496c7d6), X(0x049cae2e), X(0x04a29836), X(0x04a885ed), X(0x04ae7753), X(0x04b46c68), X(0x04ba652b), X(0x04c0619d), X(0x04c661bc), X(0x04cc658a), X(0x04d26d04), X(0x04d8782c), X(0x04de8701), X(0x04e49983), X(0x04eaafb0), X(0x04f0c98a), X(0x04f6e710), X(0x04fd0842), X(0x05032d1e), X(0x050955a6), X(0x050f81d8), X(0x0515b1b5), X(0x051be53d), X(0x05221c6e), X(0x05285748), X(0x052e95cd), X(0x0534d7fa), X(0x053b1dd0), X(0x0541674e), X(0x0547b475), X(0x054e0544), X(0x055459bb), X(0x055ab1d9), X(0x05610d9e), X(0x05676d0a), X(0x056dd01c), X(0x057436d5), X(0x057aa134), X(0x05810f38), X(0x058780e2), X(0x058df631), X(0x05946f25), X(0x059aebbe), X(0x05a16bfa), X(0x05a7efdb), X(0x05ae775f), X(0x05b50287), X(0x05bb9152), X(0x05c223c0), X(0x05c8b9d0), X(0x05cf5382), X(0x05d5f0d6), X(0x05dc91cc), X(0x05e33663), X(0x05e9de9c), X(0x05f08a75), X(0x05f739ee), X(0x05fded07), X(0x0604a3c0), X(0x060b5e19), X(0x06121c11), X(0x0618dda8), X(0x061fa2dd), X(0x06266bb1), X(0x062d3822), X(0x06340831), X(0x063adbde), X(0x0641b328), X(0x06488e0e), X(0x064f6c91), X(0x06564eaf), X(0x065d346a), X(0x06641dc0), X(0x066b0ab1), X(0x0671fb3d), X(0x0678ef64), X(0x067fe724), X(0x0686e27f), X(0x068de173), X(0x0694e400), X(0x069bea27), X(0x06a2f3e6), X(0x06aa013d), X(0x06b1122c), X(0x06b826b3), X(0x06bf3ed1), X(0x06c65a86), X(0x06cd79d1), X(0x06d49cb3), X(0x06dbc32b), X(0x06e2ed38), X(0x06ea1adb), X(0x06f14c13), X(0x06f880df), X(0x06ffb940), X(0x0706f535), X(0x070e34bd), X(0x071577d9), X(0x071cbe88), X(0x072408c9), X(0x072b569d), X(0x0732a802), X(0x0739fcf9), X(0x07415582), X(0x0748b19b), X(0x07501145), X(0x0757747f), X(0x075edb49), X(0x076645a3), X(0x076db38c), X(0x07752503), X(0x077c9a09), X(0x0784129e), X(0x078b8ec0), X(0x07930e70), X(0x079a91ac), X(0x07a21876), X(0x07a9a2cc), X(0x07b130ad), X(0x07b8c21b), X(0x07c05714), X(0x07c7ef98), X(0x07cf8ba6), X(0x07d72b3f), X(0x07dece62), X(0x07e6750e), X(0x07ee1f43), X(0x07f5cd01), X(0x07fd7e48), X(0x08053316), X(0x080ceb6d), X(0x0814a74a), X(0x081c66af), X(0x0824299a), X(0x082bf00c), X(0x0833ba03), X(0x083b8780), X(0x08435882), X(0x084b2d09), X(0x08530514), X(0x085ae0a3), X(0x0862bfb6), X(0x086aa24c), X(0x08728865), X(0x087a7201), X(0x08825f1e), X(0x088a4fbe), X(0x089243de), X(0x089a3b80), X(0x08a236a2), X(0x08aa3545), X(0x08b23767), X(0x08ba3d09), X(0x08c2462a), X(0x08ca52c9), X(0x08d262e7), X(0x08da7682), X(0x08e28d9c), X(0x08eaa832), X(0x08f2c645), X(0x08fae7d4), X(0x09030cdf), X(0x090b3566), X(0x09136168), X(0x091b90e5), X(0x0923c3dc), X(0x092bfa4d), X(0x09343437), X(0x093c719b), X(0x0944b277), X(0x094cf6cc), X(0x09553e99), X(0x095d89dd), X(0x0965d899), X(0x096e2acb), X(0x09768073), X(0x097ed991), X(0x09873625), X(0x098f962e), X(0x0997f9ac), X(0x09a0609e), X(0x09a8cb04), X(0x09b138dd), X(0x09b9aa29), X(0x09c21ee8), X(0x09ca9719), X(0x09d312bc), X(0x09db91d0), X(0x09e41456), X(0x09ec9a4b), X(0x09f523b1), X(0x09fdb087), X(0x0a0640cc), X(0x0a0ed47f), X(0x0a176ba2), X(0x0a200632), X(0x0a28a42f), X(0x0a31459a), X(0x0a39ea72), X(0x0a4292b5), X(0x0a4b3e65), X(0x0a53ed80), X(0x0a5ca006), X(0x0a6555f7), X(0x0a6e0f51), X(0x0a76cc16), X(0x0a7f8c44), X(0x0a884fda), X(0x0a9116d9), X(0x0a99e140), X(0x0aa2af0e), X(0x0aab8043), X(0x0ab454df), X(0x0abd2ce1), X(0x0ac60849), X(0x0acee716), X(0x0ad7c948), X(0x0ae0aedf), X(0x0ae997d9), X(0x0af28437), X(0x0afb73f7), X(0x0b04671b), X(0x0b0d5da0), X(0x0b165788), X(0x0b1f54d0), X(0x0b285579), X(0x0b315983), X(0x0b3a60ec), X(0x0b436bb5), X(0x0b4c79dd), X(0x0b558b63), X(0x0b5ea048), X(0x0b67b88a), X(0x0b70d429), X(0x0b79f324), X(0x0b83157c), X(0x0b8c3b30), X(0x0b95643f), X(0x0b9e90a8), X(0x0ba7c06c), X(0x0bb0f38a), X(0x0bba2a01), X(0x0bc363d1), X(0x0bcca0f9), X(0x0bd5e17a), X(0x0bdf2552), X(0x0be86c81), X(0x0bf1b706), X(0x0bfb04e2), X(0x0c045613), X(0x0c0daa99), X(0x0c170274), X(0x0c205da3), X(0x0c29bc25), X(0x0c331dfb), X(0x0c3c8323), X(0x0c45eb9e), X(0x0c4f576a), X(0x0c58c688), X(0x0c6238f6), X(0x0c6baeb5), X(0x0c7527c3), X(0x0c7ea421), X(0x0c8823cd), X(0x0c91a6c8), X(0x0c9b2d10), X(0x0ca4b6a6), X(0x0cae4389), X(0x0cb7d3b8), X(0x0cc16732), X(0x0ccafdf8), X(0x0cd49809), X(0x0cde3564), X(0x0ce7d609), X(0x0cf179f7), X(0x0cfb212e), X(0x0d04cbad), X(0x0d0e7974), X(0x0d182a83), X(0x0d21ded8), X(0x0d2b9673), X(0x0d355154), X(0x0d3f0f7b), X(0x0d48d0e6), X(0x0d529595), X(0x0d5c5d88), X(0x0d6628be), X(0x0d6ff737), X(0x0d79c8f2), X(0x0d839dee), X(0x0d8d762c), X(0x0d9751aa), X(0x0da13068), X(0x0dab1266), X(0x0db4f7a3), X(0x0dbee01e), X(0x0dc8cbd8), X(0x0dd2bace), X(0x0ddcad02), X(0x0de6a272), X(0x0df09b1e), X(0x0dfa9705), X(0x0e049627), X(0x0e0e9883), X(0x0e189e19), X(0x0e22a6e8), X(0x0e2cb2f0), X(0x0e36c230), X(0x0e40d4a8), X(0x0e4aea56), X(0x0e55033b), X(0x0e5f1f56), X(0x0e693ea7), X(0x0e73612c), X(0x0e7d86e5), X(0x0e87afd3), X(0x0e91dbf3), X(0x0e9c0b47), X(0x0ea63dcc), X(0x0eb07383), X(0x0ebaac6b), X(0x0ec4e883), X(0x0ecf27cc), X(0x0ed96a44), X(0x0ee3afea), X(0x0eedf8bf), X(0x0ef844c2), X(0x0f0293f2), X(0x0f0ce64e), X(0x0f173bd6), X(0x0f21948a), X(0x0f2bf069), X(0x0f364f72), X(0x0f40b1a5), X(0x0f4b1701), X(0x0f557f86), X(0x0f5feb32), X(0x0f6a5a07), X(0x0f74cc02), X(0x0f7f4124), X(0x0f89b96b), X(0x0f9434d8), X(0x0f9eb369), X(0x0fa9351e), X(0x0fb3b9f7), X(0x0fbe41f3), X(0x0fc8cd11), X(0x0fd35b51), X(0x0fddecb2), X(0x0fe88134), X(0x0ff318d6), X(0x0ffdb397), X(0x10085177), X(0x1012f275), X(0x101d9691), X(0x10283dca), X(0x1032e81f), X(0x103d9591), X(0x1048461e), X(0x1052f9c5), X(0x105db087), X(0x10686a62), X(0x10732756), X(0x107de763), X(0x1088aa87), X(0x109370c2), X(0x109e3a14), X(0x10a9067c), X(0x10b3d5f9), X(0x10bea88b), X(0x10c97e31), X(0x10d456eb), X(0x10df32b8), X(0x10ea1197), X(0x10f4f387), X(0x10ffd889), X(0x110ac09b), X(0x1115abbe), X(0x112099ef), X(0x112b8b2f), X(0x11367f7d), X(0x114176d9), X(0x114c7141), X(0x11576eb6), X(0x11626f36), X(0x116d72c1), X(0x11787957), X(0x118382f6), X(0x118e8f9e), X(0x11999f4f), X(0x11a4b208), X(0x11afc7c7), X(0x11bae08e), X(0x11c5fc5a), X(0x11d11b2c), X(0x11dc3d02), X(0x11e761dd), X(0x11f289ba), X(0x11fdb49b), X(0x1208e27e), X(0x12141362), X(0x121f4748), X(0x122a7e2d), X(0x1235b812), X(0x1240f4f6), X(0x124c34d9), X(0x125777b9), X(0x1262bd96), X(0x126e0670), X(0x12795245), X(0x1284a115), X(0x128ff2e0), X(0x129b47a5), X(0x12a69f63), X(0x12b1fa19), X(0x12bd57c7), X(0x12c8b86c), X(0x12d41c08), X(0x12df829a), X(0x12eaec21), X(0x12f6589d), X(0x1301c80c), X(0x130d3a6f), X(0x1318afc4), X(0x1324280b), X(0x132fa344), X(0x133b216d), X(0x1346a286), X(0x1352268e), X(0x135dad85), X(0x1369376a), X(0x1374c43c), X(0x138053fb), X(0x138be6a5), X(0x13977c3b), X(0x13a314bc), X(0x13aeb026), X(0x13ba4e79), X(0x13c5efb5), X(0x13d193d9), X(0x13dd3ae4), X(0x13e8e4d6), X(0x13f491ad), X(0x1400416a), X(0x140bf40b), X(0x1417a98f), X(0x142361f7), X(0x142f1d41), X(0x143adb6d), X(0x14469c7a), X(0x14526067), X(0x145e2734), X(0x1469f0df), X(0x1475bd69), X(0x14818cd0), X(0x148d5f15), X(0x14993435), X(0x14a50c31), X(0x14b0e708), X(0x14bcc4b8), X(0x14c8a542), X(0x14d488a5), X(0x14e06edf), X(0x14ec57f1), X(0x14f843d9), X(0x15043297), X(0x1510242b), X(0x151c1892), X(0x15280fcd), X(0x153409dc), X(0x154006bc), X(0x154c066e), X(0x155808f1), X(0x15640e44), X(0x15701666), X(0x157c2157), X(0x15882f16), X(0x15943fa2), X(0x15a052fb), X(0x15ac691f), X(0x15b8820f), X(0x15c49dc8), X(0x15d0bc4c), X(0x15dcdd98), X(0x15e901ad), X(0x15f52888), X(0x1601522b), X(0x160d7e93), X(0x1619adc1), X(0x1625dfb3), X(0x16321469), X(0x163e4be2), X(0x164a861d), X(0x1656c31a), X(0x166302d8), X(0x166f4555), X(0x167b8a92), X(0x1687d28e), X(0x16941d47), X(0x16a06abe), X(0x16acbaf0), X(0x16b90ddf), X(0x16c56388), X(0x16d1bbeb), X(0x16de1708), X(0x16ea74dd), X(0x16f6d56a), X(0x170338ae), X(0x170f9ea8), X(0x171c0758), X(0x172872bd), X(0x1734e0d6), X(0x174151a2), X(0x174dc520), X(0x175a3b51), X(0x1766b432), X(0x17732fc4), X(0x177fae05), X(0x178c2ef4), X(0x1798b292), X(0x17a538dd), X(0x17b1c1d4), X(0x17be4d77), X(0x17cadbc5), X(0x17d76cbc), X(0x17e4005e), X(0x17f096a7), X(0x17fd2f98), X(0x1809cb31), X(0x1816696f), X(0x18230a53), X(0x182faddc), X(0x183c5408), X(0x1848fcd8), X(0x1855a849), X(0x1862565d), X(0x186f0711), X(0x187bba64), X(0x18887057), X(0x189528e9), X(0x18a1e418), X(0x18aea1e3), X(0x18bb624b), X(0x18c8254e), X(0x18d4eaeb), X(0x18e1b321), X(0x18ee7df1), X(0x18fb4b58), X(0x19081b57), X(0x1914edec), X(0x1921c317), X(0x192e9ad6), X(0x193b7529), X(0x19485210), X(0x19553189), X(0x19621393), X(0x196ef82e), X(0x197bdf59), X(0x1988c913), X(0x1995b55c), X(0x19a2a432), X(0x19af9595), X(0x19bc8983), X(0x19c97ffd), X(0x19d67900), X(0x19e3748e), X(0x19f072a3), X(0x19fd7341), X(0x1a0a7665), X(0x1a177c10), X(0x1a248440), X(0x1a318ef4), X(0x1a3e9c2c), X(0x1a4babe7), X(0x1a58be24), X(0x1a65d2e2), X(0x1a72ea20), X(0x1a8003de), X(0x1a8d201a), X(0x1a9a3ed5), X(0x1aa7600c), X(0x1ab483bf), X(0x1ac1a9ee), X(0x1aced297), X(0x1adbfdba), X(0x1ae92b56), X(0x1af65b69), X(0x1b038df4), X(0x1b10c2f5), X(0x1b1dfa6b), X(0x1b2b3456), X(0x1b3870b5), X(0x1b45af87), X(0x1b52f0ca), X(0x1b60347f), X(0x1b6d7aa4), X(0x1b7ac339), X(0x1b880e3c), X(0x1b955bad), X(0x1ba2ab8b), X(0x1baffdd5), X(0x1bbd528a), X(0x1bcaa9a9), X(0x1bd80332), X(0x1be55f24), X(0x1bf2bd7d), X(0x1c001e3d), X(0x1c0d8164), X(0x1c1ae6ef), X(0x1c284edf), X(0x1c35b932), X(0x1c4325e7), X(0x1c5094fe), X(0x1c5e0677), X(0x1c6b7a4f), X(0x1c78f086), X(0x1c86691b), X(0x1c93e40d), X(0x1ca1615c), X(0x1caee107), X(0x1cbc630c), X(0x1cc9e76b), X(0x1cd76e23), X(0x1ce4f733), X(0x1cf2829a), X(0x1d001057), X(0x1d0da06a), X(0x1d1b32d1), X(0x1d28c78c), X(0x1d365e9a), X(0x1d43f7f9), X(0x1d5193a9), X(0x1d5f31aa), X(0x1d6cd1f9), X(0x1d7a7497), X(0x1d881982), X(0x1d95c0ba), X(0x1da36a3d), X(0x1db1160a), X(0x1dbec422), X(0x1dcc7482), X(0x1dda272b), X(0x1de7dc1a), X(0x1df59350), X(0x1e034ccb), X(0x1e11088a), X(0x1e1ec68c), X(0x1e2c86d1), X(0x1e3a4958), X(0x1e480e20), X(0x1e55d527), X(0x1e639e6d), X(0x1e7169f1), X(0x1e7f37b2), X(0x1e8d07b0), X(0x1e9ad9e8), X(0x1ea8ae5b), X(0x1eb68507), X(0x1ec45dec), X(0x1ed23908), X(0x1ee0165b), X(0x1eedf5e4), X(0x1efbd7a1), X(0x1f09bb92), X(0x1f17a1b6), X(0x1f258a0d), X(0x1f337494), X(0x1f41614b), X(0x1f4f5032), X(0x1f5d4147), X(0x1f6b3489), X(0x1f7929f7), X(0x1f872192), X(0x1f951b56), X(0x1fa31744), X(0x1fb1155b), X(0x1fbf159a), X(0x1fcd17ff), X(0x1fdb1c8b), X(0x1fe9233b), X(0x1ff72c0f), X(0x20053706), X(0x20134420), X(0x2021535a), X(0x202f64b4), X(0x203d782e), X(0x204b8dc6), X(0x2059a57c), X(0x2067bf4e), X(0x2075db3b), X(0x2083f943), X(0x20921964), X(0x20a03b9e), X(0x20ae5fef), X(0x20bc8657), X(0x20caaed5), X(0x20d8d967), X(0x20e7060e), X(0x20f534c7), X(0x21036592), X(0x2111986e), X(0x211fcd59), X(0x212e0454), X(0x213c3d5d), X(0x214a7873), X(0x2158b594), X(0x2166f4c1), X(0x217535f8), X(0x21837938), X(0x2191be81), X(0x21a005d0), X(0x21ae4f26), X(0x21bc9a81), X(0x21cae7e0), X(0x21d93743), X(0x21e788a8), X(0x21f5dc0e), X(0x22043174), X(0x221288da), X(0x2220e23e), X(0x222f3da0), X(0x223d9afe), X(0x224bfa58), X(0x225a5bac), X(0x2268bef9), X(0x2277243f), X(0x22858b7d), X(0x2293f4b0), X(0x22a25fda), X(0x22b0ccf8), X(0x22bf3c09), X(0x22cdad0d), X(0x22dc2002), X(0x22ea94e8), X(0x22f90bbe), X(0x23078482), X(0x2315ff33), X(0x23247bd1), X(0x2332fa5b), X(0x23417acf), X(0x234ffd2c), X(0x235e8173), X(0x236d07a0), X(0x237b8fb4), X(0x238a19ae), X(0x2398a58c), X(0x23a7334d), X(0x23b5c2f1), X(0x23c45477), X(0x23d2e7dd), X(0x23e17d22), X(0x23f01446), X(0x23fead47), X(0x240d4825), X(0x241be4dd), X(0x242a8371), X(0x243923dd), X(0x2447c622), X(0x24566a3e), X(0x24651031), X(0x2473b7f8), X(0x24826194), X(0x24910d03), X(0x249fba44), X(0x24ae6957), X(0x24bd1a39), X(0x24cbccea), X(0x24da816a), X(0x24e937b7), X(0x24f7efcf), X(0x2506a9b3), X(0x25156560), X(0x252422d6), X(0x2532e215), X(0x2541a31a), X(0x255065e4), X(0x255f2a74), X(0x256df0c7), X(0x257cb8dd), X(0x258b82b4), X(0x259a4e4c), X(0x25a91ba4), X(0x25b7eaba), X(0x25c6bb8e), X(0x25d58e1e), X(0x25e46269), X(0x25f3386e), X(0x2602102d), X(0x2610e9a4), X(0x261fc4d3), X(0x262ea1b7), X(0x263d8050), X(0x264c609e), X(0x265b429e), X(0x266a2650), X(0x26790bb3), X(0x2687f2c6), X(0x2696db88), X(0x26a5c5f7), X(0x26b4b213), X(0x26c39fda), X(0x26d28f4c), X(0x26e18067), X(0x26f0732b), X(0x26ff6796), X(0x270e5da7), X(0x271d555d), X(0x272c4eb7), X(0x273b49b5), X(0x274a4654), X(0x27594495), X(0x27684475), X(0x277745f4), X(0x27864910), X(0x27954dc9), X(0x27a4541e), X(0x27b35c0d), X(0x27c26596), X(0x27d170b7), X(0x27e07d6f), X(0x27ef8bbd), X(0x27fe9ba0), X(0x280dad18), X(0x281cc022), X(0x282bd4be), X(0x283aeaeb), X(0x284a02a7), X(0x28591bf2), X(0x286836cb), X(0x28775330), X(0x28867120), X(0x2895909b), X(0x28a4b19e), X(0x28b3d42a), X(0x28c2f83d), X(0x28d21dd5), X(0x28e144f3), X(0x28f06d94), X(0x28ff97b8), X(0x290ec35d), X(0x291df082), X(0x292d1f27), X(0x293c4f4a), X(0x294b80eb), X(0x295ab407), X(0x2969e89e), X(0x29791eaf), X(0x29885639), X(0x29978f3b), X(0x29a6c9b3), X(0x29b605a0), X(0x29c54302), X(0x29d481d7), X(0x29e3c21e), X(0x29f303d6), X(0x2a0246fd), X(0x2a118b94), X(0x2a20d198), X(0x2a301909), X(0x2a3f61e6), X(0x2a4eac2c), X(0x2a5df7dc), X(0x2a6d44f4), X(0x2a7c9374), X(0x2a8be359), X(0x2a9b34a2), X(0x2aaa8750), X(0x2ab9db60), X(0x2ac930d1), X(0x2ad887a3), X(0x2ae7dfd3), X(0x2af73962), X(0x2b06944e), X(0x2b15f096), X(0x2b254e38), X(0x2b34ad34), X(0x2b440d89), X(0x2b536f34), X(0x2b62d236), X(0x2b72368d), X(0x2b819c38), X(0x2b910336), X(0x2ba06b86), X(0x2bafd526), X(0x2bbf4015), X(0x2bceac53), X(0x2bde19de), X(0x2bed88b5), X(0x2bfcf8d7), X(0x2c0c6a43), X(0x2c1bdcf7), X(0x2c2b50f3), X(0x2c3ac635), X(0x2c4a3cbd), X(0x2c59b488), X(0x2c692d97), X(0x2c78a7e7), X(0x2c882378), X(0x2c97a049), X(0x2ca71e58), X(0x2cb69da4), X(0x2cc61e2c), X(0x2cd59ff0), X(0x2ce522ed), X(0x2cf4a723), X(0x2d042c90), X(0x2d13b334), X(0x2d233b0d), X(0x2d32c41a), X(0x2d424e5a), X(0x2d51d9cc), X(0x2d61666e), X(0x2d70f440), X(0x2d808340), X(0x2d90136e), X(0x2d9fa4c7), X(0x2daf374c), X(0x2dbecafa), X(0x2dce5fd1), X(0x2dddf5cf), X(0x2ded8cf4), X(0x2dfd253d), X(0x2e0cbeab), X(0x2e1c593b), X(0x2e2bf4ed), X(0x2e3b91c0), X(0x2e4b2fb1), X(0x2e5acec1), X(0x2e6a6eee), X(0x2e7a1037), X(0x2e89b29b), X(0x2e995618), X(0x2ea8faad), X(0x2eb8a05a), X(0x2ec8471c), X(0x2ed7eef4), X(0x2ee797df), X(0x2ef741dc), X(0x2f06eceb), X(0x2f16990a), X(0x2f264639), X(0x2f35f475), X(0x2f45a3bd), X(0x2f555412), X(0x2f650570), X(0x2f74b7d8), X(0x2f846b48), X(0x2f941fbe), X(0x2fa3d53a), X(0x2fb38bbb), X(0x2fc3433f), X(0x2fd2fbc5), X(0x2fe2b54c), X(0x2ff26fd3), X(0x30022b58), X(0x3011e7db), X(0x3021a55a), X(0x303163d4), X(0x30412348), X(0x3050e3b5), X(0x3060a519), X(0x30706773), X(0x30802ac3), X(0x308fef06), X(0x309fb43d), X(0x30af7a65), X(0x30bf417d), X(0x30cf0985), X(0x30ded27a), X(0x30ee9c5d), X(0x30fe672b), X(0x310e32e3), X(0x311dff85), X(0x312dcd0f), X(0x313d9b80), X(0x314d6ad7), X(0x315d3b12), X(0x316d0c30), X(0x317cde31), X(0x318cb113), X(0x319c84d4), X(0x31ac5974), X(0x31bc2ef1), X(0x31cc054b), X(0x31dbdc7f), X(0x31ebb48e), X(0x31fb8d74), X(0x320b6733), X(0x321b41c7), X(0x322b1d31), X(0x323af96e), X(0x324ad67e), X(0x325ab45f), X(0x326a9311), X(0x327a7291), X(0x328a52e0), X(0x329a33fb), X(0x32aa15e1), X(0x32b9f892), X(0x32c9dc0c), X(0x32d9c04d), X(0x32e9a555), X(0x32f98b22), X(0x330971b4), X(0x33195909), X(0x3329411f), X(0x333929f6), X(0x3349138c), X(0x3358fde1), X(0x3368e8f2), X(0x3378d4c0), X(0x3388c147), X(0x3398ae89), X(0x33a89c82), X(0x33b88b32), X(0x33c87a98), X(0x33d86ab2), X(0x33e85b80), X(0x33f84d00), X(0x34083f30), X(0x34183210), X(0x3428259f), X(0x343819db), X(0x34480ec3), X(0x34580455), X(0x3467fa92), X(0x3477f176), X(0x3487e902), X(0x3497e134), X(0x34a7da0a), X(0x34b7d384), X(0x34c7cda0), X(0x34d7c85e), X(0x34e7c3bb), X(0x34f7bfb7), X(0x3507bc50), X(0x3517b985), X(0x3527b756), X(0x3537b5c0), X(0x3547b4c3), X(0x3557b45d), X(0x3567b48d), X(0x3577b552), X(0x3587b6aa), X(0x3597b895), X(0x35a7bb12), X(0x35b7be1e), X(0x35c7c1b9), X(0x35d7c5e1), X(0x35e7ca96), X(0x35f7cfd6), X(0x3607d5a0), X(0x3617dbf3), X(0x3627e2cd), X(0x3637ea2d), X(0x3647f212), X(0x3657fa7b), X(0x36680366), X(0x36780cd2), X(0x368816bf), X(0x3698212b), X(0x36a82c14), X(0x36b83779), X(0x36c8435a), X(0x36d84fb4), X(0x36e85c88), X(0x36f869d2), X(0x37087793), X(0x371885c9), X(0x37289473), X(0x3738a38f), X(0x3748b31d), X(0x3758c31a), X(0x3768d387), X(0x3778e461), X(0x3788f5a7), X(0x37990759), X(0x37a91975), X(0x37b92bf9), X(0x37c93ee4), X(0x37d95236), X(0x37e965ed), X(0x37f97a08), X(0x38098e85), X(0x3819a363), X(0x3829b8a2), X(0x3839ce3f), X(0x3849e43a), X(0x3859fa91), X(0x386a1143), X(0x387a284f), X(0x388a3fb4), X(0x389a5770), X(0x38aa6f83), X(0x38ba87ea), X(0x38caa0a5), X(0x38dab9b2), X(0x38ead311), X(0x38faecbf), X(0x390b06bc), X(0x391b2107), X(0x392b3b9e), X(0x393b5680), X(0x394b71ac), X(0x395b8d20), X(0x396ba8dc), X(0x397bc4dd), X(0x398be124), X(0x399bfdae), X(0x39ac1a7a), X(0x39bc3788), X(0x39cc54d5), X(0x39dc7261), X(0x39ec902a), X(0x39fcae2f), X(0x3a0ccc70), X(0x3a1ceaea), X(0x3a2d099c), X(0x3a3d2885), X(0x3a4d47a5), X(0x3a5d66f9), X(0x3a6d8680), X(0x3a7da63a), X(0x3a8dc625), X(0x3a9de63f), X(0x3aae0688), X(0x3abe26fe), X(0x3ace47a0), X(0x3ade686d), X(0x3aee8963), X(0x3afeaa82), X(0x3b0ecbc7), X(0x3b1eed32), X(0x3b2f0ec2), X(0x3b3f3075), X(0x3b4f524a), X(0x3b5f7440), X(0x3b6f9656), X(0x3b7fb889), X(0x3b8fdada), X(0x3b9ffd46), X(0x3bb01fce), X(0x3bc0426e), X(0x3bd06526), X(0x3be087f6), X(0x3bf0aada), X(0x3c00cdd4), X(0x3c10f0e0), X(0x3c2113fe), X(0x3c31372d), X(0x3c415a6b), X(0x3c517db7), X(0x3c61a110), X(0x3c71c475), X(0x3c81e7e4), X(0x3c920b5c), X(0x3ca22edc), X(0x3cb25262), X(0x3cc275ee), X(0x3cd2997e), X(0x3ce2bd11), X(0x3cf2e0a6), X(0x3d03043b), X(0x3d1327cf), X(0x3d234b61), X(0x3d336ef0), X(0x3d43927a), X(0x3d53b5ff), X(0x3d63d97c), X(0x3d73fcf1), X(0x3d84205c), X(0x3d9443bd), X(0x3da46711), X(0x3db48a58), X(0x3dc4ad91), X(0x3dd4d0ba), X(0x3de4f3d1), X(0x3df516d7), X(0x3e0539c9), X(0x3e155ca6), X(0x3e257f6d), X(0x3e35a21d), X(0x3e45c4b4), X(0x3e55e731), X(0x3e660994), X(0x3e762bda), X(0x3e864e03), X(0x3e96700d), X(0x3ea691f7), X(0x3eb6b3bf), X(0x3ec6d565), X(0x3ed6f6e8), X(0x3ee71845), X(0x3ef7397c), X(0x3f075a8c), X(0x3f177b73), X(0x3f279c30), X(0x3f37bcc2), X(0x3f47dd27), X(0x3f57fd5f), X(0x3f681d68), X(0x3f783d40), X(0x3f885ce7), X(0x3f987c5c), X(0x3fa89b9c), X(0x3fb8baa7), X(0x3fc8d97c), X(0x3fd8f819), X(0x3fe9167e), X(0x3ff934a8), X(0x40095296), X(0x40197049), X(0x40298dbd), X(0x4039aaf2), X(0x4049c7e7), X(0x4059e49a), X(0x406a010a), X(0x407a1d36), X(0x408a391d), X(0x409a54bd), X(0x40aa7015), X(0x40ba8b25), X(0x40caa5ea), X(0x40dac063), X(0x40eada90), X(0x40faf46e), X(0x410b0dfe), X(0x411b273d), X(0x412b402a), X(0x413b58c4), X(0x414b710a), X(0x415b88fa), X(0x416ba093), X(0x417bb7d5), X(0x418bcebe), X(0x419be54c), X(0x41abfb7e), X(0x41bc1153), X(0x41cc26ca), X(0x41dc3be2), X(0x41ec5099), X(0x41fc64ef), X(0x420c78e1), X(0x421c8c6f), X(0x422c9f97), X(0x423cb258), X(0x424cc4b2), X(0x425cd6a2), X(0x426ce827), X(0x427cf941), X(0x428d09ee), X(0x429d1a2c), X(0x42ad29fb), X(0x42bd3959), X(0x42cd4846), X(0x42dd56bf), X(0x42ed64c3), X(0x42fd7252), X(0x430d7f6a), X(0x431d8c0a), X(0x432d9831), X(0x433da3dd), X(0x434daf0d), X(0x435db9c0), X(0x436dc3f5), X(0x437dcdab), X(0x438dd6df), X(0x439ddf92), X(0x43ade7c1), X(0x43bdef6c), X(0x43cdf691), X(0x43ddfd2f), X(0x43ee0345), X(0x43fe08d2), X(0x440e0dd4), X(0x441e124b), X(0x442e1634), X(0x443e198f), X(0x444e1c5a), X(0x445e1e95), X(0x446e203e), X(0x447e2153), X(0x448e21d5), X(0x449e21c0), X(0x44ae2115), X(0x44be1fd1), X(0x44ce1df4), X(0x44de1b7d), X(0x44ee186a), X(0x44fe14ba), X(0x450e106b), X(0x451e0b7e), X(0x452e05ef), X(0x453dffbf), X(0x454df8eb), X(0x455df173), X(0x456de956), X(0x457de092), X(0x458dd726), X(0x459dcd10), X(0x45adc251), X(0x45bdb6e5), X(0x45cdaacd), X(0x45dd9e06), X(0x45ed9091), X(0x45fd826a), X(0x460d7392), X(0x461d6407), X(0x462d53c8), X(0x463d42d4), X(0x464d3129), X(0x465d1ec6), X(0x466d0baa), X(0x467cf7d3), X(0x468ce342), X(0x469ccdf3), X(0x46acb7e7), X(0x46bca11c), X(0x46cc8990), X(0x46dc7143), X(0x46ec5833), X(0x46fc3e5f), X(0x470c23c6), X(0x471c0867), X(0x472bec40), X(0x473bcf50), X(0x474bb196), X(0x475b9311), X(0x476b73c0), X(0x477b53a1), X(0x478b32b4), X(0x479b10f6), X(0x47aaee67), X(0x47bacb06), X(0x47caa6d1), X(0x47da81c7), X(0x47ea5be7), X(0x47fa3530), X(0x480a0da1), X(0x4819e537), X(0x4829bbf3), X(0x483991d3), X(0x484966d6), X(0x48593afb), X(0x48690e3f), X(0x4878e0a3), X(0x4888b225), X(0x489882c4), X(0x48a8527e), X(0x48b82153), X(0x48c7ef41), X(0x48d7bc47), X(0x48e78863), X(0x48f75396), X(0x49071ddc), X(0x4916e736), X(0x4926afa2), X(0x4936771f), X(0x49463dac), X(0x49560347), X(0x4965c7ef), X(0x49758ba4), X(0x49854e63), X(0x4995102c), X(0x49a4d0fe), X(0x49b490d7), X(0x49c44fb6), X(0x49d40d9a), X(0x49e3ca82), X(0x49f3866c), X(0x4a034159), X(0x4a12fb45), X(0x4a22b430), X(0x4a326c19), X(0x4a4222ff), X(0x4a51d8e1), X(0x4a618dbd), X(0x4a714192), X(0x4a80f45f), X(0x4a90a623), X(0x4aa056dd), X(0x4ab0068b), X(0x4abfb52c), X(0x4acf62c0), X(0x4adf0f44), X(0x4aeebab9), X(0x4afe651c), X(0x4b0e0e6c), X(0x4b1db6a9), X(0x4b2d5dd1), X(0x4b3d03e2), X(0x4b4ca8dd), X(0x4b5c4cbf), X(0x4b6bef88), X(0x4b7b9136), X(0x4b8b31c8), X(0x4b9ad13d), X(0x4baa6f93), X(0x4bba0ccb), X(0x4bc9a8e2), X(0x4bd943d7), X(0x4be8dda9), X(0x4bf87658), X(0x4c080de1), X(0x4c17a444), X(0x4c27397f), X(0x4c36cd92), X(0x4c46607b), X(0x4c55f239), X(0x4c6582cb), X(0x4c75122f), X(0x4c84a065), X(0x4c942d6c), X(0x4ca3b942), X(0x4cb343e6), X(0x4cc2cd57), X(0x4cd25594), X(0x4ce1dc9c), X(0x4cf1626d), X(0x4d00e707), X(0x4d106a68), X(0x4d1fec8f), X(0x4d2f6d7a), X(0x4d3eed2a), X(0x4d4e6b9d), X(0x4d5de8d1), X(0x4d6d64c5), X(0x4d7cdf79), X(0x4d8c58eb), X(0x4d9bd11a), X(0x4dab4804), X(0x4dbabdaa), X(0x4dca3209), X(0x4dd9a520), X(0x4de916ef), X(0x4df88774), X(0x4e07f6ae), X(0x4e17649c), X(0x4e26d13c), X(0x4e363c8f), X(0x4e45a692), X(0x4e550f44), X(0x4e6476a4), X(0x4e73dcb2), X(0x4e83416c), X(0x4e92a4d1), X(0x4ea206df), X(0x4eb16796), X(0x4ec0c6f5), X(0x4ed024fa), X(0x4edf81a5), X(0x4eeedcf3), X(0x4efe36e5), X(0x4f0d8f79), X(0x4f1ce6ad), X(0x4f2c3c82), X(0x4f3b90f4), X(0x4f4ae405), X(0x4f5a35b1), X(0x4f6985fa), X(0x4f78d4dc), X(0x4f882257), X(0x4f976e6a), X(0x4fa6b914), X(0x4fb60254), X(0x4fc54a28), X(0x4fd49090), X(0x4fe3d58b), X(0x4ff31917), X(0x50025b33), X(0x50119bde), X(0x5020db17), X(0x503018dd), X(0x503f552f), X(0x504e900b), X(0x505dc971), X(0x506d0160), X(0x507c37d7), X(0x508b6cd3), X(0x509aa055), X(0x50a9d25b), X(0x50b902e4), X(0x50c831ef), X(0x50d75f7b), X(0x50e68b87), X(0x50f5b612), X(0x5104df1a), X(0x5114069f), X(0x51232ca0), X(0x5132511a), X(0x5141740f), X(0x5150957b), X(0x515fb55f), X(0x516ed3b8), X(0x517df087), X(0x518d0bca), X(0x519c257f), X(0x51ab3da7), X(0x51ba543f), X(0x51c96947), X(0x51d87cbd), X(0x51e78ea1), X(0x51f69ef1), X(0x5205adad), X(0x5214bad3), X(0x5223c662), X(0x5232d05a), X(0x5241d8b9), X(0x5250df7d), X(0x525fe4a7), X(0x526ee835), X(0x527dea26), X(0x528cea78), X(0x529be92c), X(0x52aae63f), X(0x52b9e1b0), X(0x52c8db80), X(0x52d7d3ac), X(0x52e6ca33), X(0x52f5bf15), X(0x5304b251), X(0x5313a3e5), X(0x532293d0), X(0x53318212), X(0x53406ea8), X(0x534f5993), X(0x535e42d2), X(0x536d2a62), X(0x537c1043), X(0x538af475), X(0x5399d6f6), X(0x53a8b7c4), X(0x53b796e0), X(0x53c67447), X(0x53d54ffa), X(0x53e429f6), X(0x53f3023b), X(0x5401d8c8), X(0x5410ad9c), X(0x541f80b5), X(0x542e5213), X(0x543d21b5), X(0x544bef9a), X(0x545abbc0), X(0x54698627), X(0x54784ece), X(0x548715b3), X(0x5495dad6), X(0x54a49e35), X(0x54b35fd0), X(0x54c21fa6), X(0x54d0ddb5), X(0x54df99fd), X(0x54ee547c), X(0x54fd0d32), X(0x550bc41d), X(0x551a793d), X(0x55292c91), X(0x5537de16), X(0x55468dce), X(0x55553bb6), X(0x5563e7cd), X(0x55729213), X(0x55813a87), X(0x558fe127), X(0x559e85f2), X(0x55ad28e9), X(0x55bbca08), X(0x55ca6950), X(0x55d906c0), X(0x55e7a257), X(0x55f63c13), X(0x5604d3f4), X(0x561369f8), X(0x5621fe1f), X(0x56309067), X(0x563f20d1), X(0x564daf5a), X(0x565c3c02), X(0x566ac6c7), X(0x56794faa), X(0x5687d6a8), X(0x56965bc1), X(0x56a4def4), X(0x56b36040), X(0x56c1dfa4), X(0x56d05d1f), X(0x56ded8af), X(0x56ed5255), X(0x56fbca0f), X(0x570a3fdc), X(0x5718b3bc), X(0x572725ac), X(0x573595ad), X(0x574403bd), X(0x57526fdb), X(0x5760da07), X(0x576f423f), X(0x577da883), X(0x578c0cd1), X(0x579a6f29), X(0x57a8cf8a), X(0x57b72df2), X(0x57c58a61), X(0x57d3e4d6), X(0x57e23d50), X(0x57f093cd), X(0x57fee84e), X(0x580d3ad1), X(0x581b8b54), X(0x5829d9d8), X(0x5838265c), X(0x584670dd), X(0x5854b95c), X(0x5862ffd8), X(0x5871444f), X(0x587f86c1), X(0x588dc72c), X(0x589c0591), X(0x58aa41ed), X(0x58b87c40), X(0x58c6b489), X(0x58d4eac7), X(0x58e31ef9), X(0x58f1511f), X(0x58ff8137), X(0x590daf40), X(0x591bdb3a), X(0x592a0524), X(0x59382cfc), X(0x594652c2), X(0x59547675), X(0x59629815), X(0x5970b79f), X(0x597ed513), X(0x598cf071), X(0x599b09b7), X(0x59a920e5), X(0x59b735f9), X(0x59c548f4), X(0x59d359d2), X(0x59e16895), X(0x59ef753b), X(0x59fd7fc4), X(0x5a0b882d), X(0x5a198e77), X(0x5a2792a0), X(0x5a3594a9), X(0x5a43948e), X(0x5a519251), X(0x5a5f8df0), X(0x5a6d876a), X(0x5a7b7ebe), X(0x5a8973ec), X(0x5a9766f2), X(0x5aa557d0), X(0x5ab34685), X(0x5ac1330f), X(0x5acf1d6f), X(0x5add05a3), X(0x5aeaebaa), X(0x5af8cf84), X(0x5b06b12f), X(0x5b1490ab), X(0x5b226df7), X(0x5b304912), X(0x5b3e21fc), X(0x5b4bf8b2), X(0x5b59cd35), X(0x5b679f84), X(0x5b756f9e), X(0x5b833d82), X(0x5b91092e), X(0x5b9ed2a3), X(0x5bac99e0), X(0x5bba5ee3), X(0x5bc821ac), X(0x5bd5e23a), X(0x5be3a08c), X(0x5bf15ca1), X(0x5bff1679), X(0x5c0cce12), X(0x5c1a836c), X(0x5c283686), X(0x5c35e760), X(0x5c4395f7), X(0x5c51424c), X(0x5c5eec5e), X(0x5c6c942b), X(0x5c7a39b4), X(0x5c87dcf7), X(0x5c957df3), X(0x5ca31ca8), X(0x5cb0b915), X(0x5cbe5338), X(0x5ccbeb12), X(0x5cd980a1), X(0x5ce713e5), X(0x5cf4a4dd), X(0x5d023387), X(0x5d0fbfe4), X(0x5d1d49f2), X(0x5d2ad1b1), X(0x5d38571f), X(0x5d45da3c), X(0x5d535b08), X(0x5d60d981), X(0x5d6e55a7), X(0x5d7bcf78), X(0x5d8946f5), X(0x5d96bc1c), X(0x5da42eec), X(0x5db19f65), X(0x5dbf0d86), X(0x5dcc794e), X(0x5dd9e2bd), X(0x5de749d1), X(0x5df4ae8a), X(0x5e0210e7), X(0x5e0f70e7), X(0x5e1cce8a), X(0x5e2a29ce), X(0x5e3782b4), X(0x5e44d93a), X(0x5e522d5f), X(0x5e5f7f23), X(0x5e6cce85), X(0x5e7a1b85), X(0x5e876620), X(0x5e94ae58), X(0x5ea1f42a), X(0x5eaf3797), X(0x5ebc789d), X(0x5ec9b73c), X(0x5ed6f372), X(0x5ee42d41), X(0x5ef164a5), X(0x5efe999f), X(0x5f0bcc2f), X(0x5f18fc52), X(0x5f262a09), X(0x5f335553), X(0x5f407e2f), X(0x5f4da49d), X(0x5f5ac89b), X(0x5f67ea29), X(0x5f750946), X(0x5f8225f2), X(0x5f8f402b), X(0x5f9c57f2), X(0x5fa96d44), X(0x5fb68023), X(0x5fc3908c), X(0x5fd09e7f), X(0x5fdda9fc), X(0x5feab302), X(0x5ff7b990), X(0x6004bda5), X(0x6011bf40), X(0x601ebe62), X(0x602bbb09), X(0x6038b534), X(0x6045ace4), X(0x6052a216), X(0x605f94cb), X(0x606c8502), X(0x607972b9), X(0x60865df2), X(0x609346aa), X(0x60a02ce1), X(0x60ad1096), X(0x60b9f1c9), X(0x60c6d079), X(0x60d3aca5), X(0x60e0864d), X(0x60ed5d70), X(0x60fa320d), X(0x61070424), X(0x6113d3b4), X(0x6120a0bc), X(0x612d6b3c), X(0x613a3332), X(0x6146f89f), X(0x6153bb82), X(0x61607bd9), X(0x616d39a5), X(0x6179f4e5), X(0x6186ad98), X(0x619363bd), X(0x61a01753), X(0x61acc85b), X(0x61b976d3), X(0x61c622bc), X(0x61d2cc13), X(0x61df72d8), X(0x61ec170c), X(0x61f8b8ad), X(0x620557ba), X(0x6211f434), X(0x621e8e18), X(0x622b2568), X(0x6237ba21), X(0x62444c44), X(0x6250dbd0), X(0x625d68c4), X(0x6269f320), X(0x62767ae2), X(0x6283000b), X(0x628f829a), X(0x629c028e), X(0x62a87fe6), X(0x62b4faa2), X(0x62c172c2), X(0x62cde844), X(0x62da5b29), X(0x62e6cb6e), X(0x62f33915), X(0x62ffa41c), X(0x630c0c83), X(0x63187248), X(0x6324d56d), X(0x633135ef), X(0x633d93ce), X(0x6349ef0b), X(0x635647a3), X(0x63629d97), X(0x636ef0e6), X(0x637b418f), X(0x63878f92), X(0x6393daef), X(0x63a023a4), X(0x63ac69b1), X(0x63b8ad15), X(0x63c4edd1), X(0x63d12be3), X(0x63dd674b), X(0x63e9a008), X(0x63f5d61a), X(0x64020980), X(0x640e3a39), X(0x641a6846), X(0x642693a5), X(0x6432bc56), X(0x643ee258), X(0x644b05ab), X(0x6457264e), X(0x64634441), X(0x646f5f83), X(0x647b7814), X(0x64878df3), X(0x6493a120), X(0x649fb199), X(0x64abbf5f), X(0x64b7ca71), X(0x64c3d2ce), X(0x64cfd877), X(0x64dbdb69), X(0x64e7dba6), X(0x64f3d92b), X(0x64ffd3fa), X(0x650bcc11), X(0x6517c16f), X(0x6523b415), X(0x652fa402), X(0x653b9134), X(0x65477bad), X(0x6553636a), X(0x655f486d), X(0x656b2ab3), X(0x65770a3d), X(0x6582e70a), X(0x658ec11a), X(0x659a986d), X(0x65a66d00), X(0x65b23ed5), X(0x65be0deb), X(0x65c9da41), X(0x65d5a3d7), X(0x65e16aac), X(0x65ed2ebf), X(0x65f8f011), X(0x6604aea1), X(0x66106a6e), X(0x661c2377), X(0x6627d9be), X(0x66338d40), X(0x663f3dfd), X(0x664aebf5), X(0x66569728), X(0x66623f95), X(0x666de53b), X(0x6679881b), X(0x66852833), X(0x6690c583), X(0x669c600b), X(0x66a7f7ca), X(0x66b38cc0), X(0x66bf1eec), X(0x66caae4f), X(0x66d63ae6), X(0x66e1c4b3), X(0x66ed4bb4), X(0x66f8cfea), X(0x67045153), X(0x670fcfef), X(0x671b4bbe), X(0x6726c4bf), X(0x67323af3), X(0x673dae58), X(0x67491eee), X(0x67548cb5), X(0x675ff7ab), X(0x676b5fd2), X(0x6776c528), X(0x678227ad), X(0x678d8761), X(0x6798e443), X(0x67a43e52), X(0x67af958f), X(0x67bae9f9), X(0x67c63b8f), X(0x67d18a52), X(0x67dcd640), X(0x67e81f59), X(0x67f3659d), X(0x67fea90c), X(0x6809e9a5), X(0x68152768), X(0x68206254), X(0x682b9a68), X(0x6836cfa6), X(0x6842020b), X(0x684d3199), X(0x68585e4d), X(0x68638829), X(0x686eaf2b), X(0x6879d354), X(0x6884f4a2), X(0x68901316), X(0x689b2eb0), X(0x68a6476d), X(0x68b15d50), X(0x68bc7056), X(0x68c78080), X(0x68d28dcd), X(0x68dd983e), X(0x68e89fd0), X(0x68f3a486), X(0x68fea65d), X(0x6909a555), X(0x6914a16f), X(0x691f9aa9), X(0x692a9104), X(0x69358480), X(0x6940751b), X(0x694b62d5), X(0x69564daf), X(0x696135a7), X(0x696c1abe), X(0x6976fcf3), X(0x6981dc46), X(0x698cb8b6), X(0x69979243), X(0x69a268ed), X(0x69ad3cb4), X(0x69b80d97), X(0x69c2db96), X(0x69cda6b0), X(0x69d86ee5), X(0x69e33436), X(0x69edf6a1), X(0x69f8b626), X(0x6a0372c5), X(0x6a0e2c7e), X(0x6a18e350), X(0x6a23973c), X(0x6a2e4840), X(0x6a38f65d), X(0x6a43a191), X(0x6a4e49de), X(0x6a58ef42), X(0x6a6391be), X(0x6a6e3151), X(0x6a78cdfa), X(0x6a8367ba), X(0x6a8dfe90), X(0x6a98927c), X(0x6aa3237d), X(0x6aadb194), X(0x6ab83cc0), X(0x6ac2c500), X(0x6acd4a55), X(0x6ad7ccbf), X(0x6ae24c3c), X(0x6aecc8cd), X(0x6af74271), X(0x6b01b929), X(0x6b0c2cf4), X(0x6b169dd1), X(0x6b210bc1), X(0x6b2b76c2), X(0x6b35ded6), X(0x6b4043fc), X(0x6b4aa632), X(0x6b55057a), X(0x6b5f61d3), X(0x6b69bb3d), X(0x6b7411b7), X(0x6b7e6541), X(0x6b88b5db), X(0x6b930385), X(0x6b9d4e3f), X(0x6ba79607), X(0x6bb1dadf), X(0x6bbc1cc6), X(0x6bc65bbb), X(0x6bd097bf), X(0x6bdad0d0), X(0x6be506f0), X(0x6bef3a1d), X(0x6bf96a58), X(0x6c0397a0), X(0x6c0dc1f5), X(0x6c17e957), X(0x6c220dc6), X(0x6c2c2f41), X(0x6c364dc9), X(0x6c40695c), X(0x6c4a81fc), X(0x6c5497a7), X(0x6c5eaa5d), X(0x6c68ba1f), X(0x6c72c6eb), X(0x6c7cd0c3), X(0x6c86d7a6), X(0x6c90db92), X(0x6c9adc8a), X(0x6ca4da8b), X(0x6caed596), X(0x6cb8cdab), X(0x6cc2c2ca), X(0x6cccb4f2), X(0x6cd6a424), X(0x6ce0905e), X(0x6cea79a1), X(0x6cf45fee), X(0x6cfe4342), X(0x6d0823a0), X(0x6d120105), X(0x6d1bdb73), X(0x6d25b2e8), X(0x6d2f8765), X(0x6d3958ea), X(0x6d432777), X(0x6d4cf30a), X(0x6d56bba5), X(0x6d608147), X(0x6d6a43f0), X(0x6d7403a0), X(0x6d7dc056), X(0x6d877a13), X(0x6d9130d6), X(0x6d9ae4a0), X(0x6da4956f), X(0x6dae4345), X(0x6db7ee20), X(0x6dc19601), X(0x6dcb3ae7), X(0x6dd4dcd3), X(0x6dde7bc4), X(0x6de817bb), X(0x6df1b0b6), X(0x6dfb46b7), X(0x6e04d9bc), X(0x6e0e69c7), X(0x6e17f6d5), X(0x6e2180e9), X(0x6e2b0801), X(0x6e348c1d), X(0x6e3e0d3d), X(0x6e478b62), X(0x6e51068a), X(0x6e5a7eb7), X(0x6e63f3e7), X(0x6e6d661b), X(0x6e76d552), X(0x6e80418e), X(0x6e89aacc), X(0x6e93110f), X(0x6e9c7454), X(0x6ea5d49d), X(0x6eaf31e9), X(0x6eb88c37), X(0x6ec1e389), X(0x6ecb37de), X(0x6ed48936), X(0x6eddd790), X(0x6ee722ee), X(0x6ef06b4d), X(0x6ef9b0b0), X(0x6f02f315), X(0x6f0c327c), X(0x6f156ee6), X(0x6f1ea852), X(0x6f27dec1), X(0x6f311232), X(0x6f3a42a5), X(0x6f43701a), X(0x6f4c9a91), X(0x6f55c20a), X(0x6f5ee686), X(0x6f680803), X(0x6f712682), X(0x6f7a4203), X(0x6f835a86), X(0x6f8c700b), X(0x6f958291), X(0x6f9e921a), X(0x6fa79ea4), X(0x6fb0a830), X(0x6fb9aebd), X(0x6fc2b24c), X(0x6fcbb2dd), X(0x6fd4b06f), X(0x6fddab03), X(0x6fe6a299), X(0x6fef9730), X(0x6ff888c9), X(0x70017763), X(0x700a62ff), X(0x70134b9c), X(0x701c313b), X(0x702513dc), X(0x702df37e), X(0x7036d021), X(0x703fa9c6), X(0x7048806d), X(0x70515415), X(0x705a24bf), X(0x7062f26b), X(0x706bbd17), X(0x707484c6), X(0x707d4976), X(0x70860b28), X(0x708ec9dc), X(0x70978591), X(0x70a03e48), X(0x70a8f400), X(0x70b1a6bb), X(0x70ba5677), X(0x70c30335), X(0x70cbacf5), X(0x70d453b6), X(0x70dcf77a), X(0x70e59840), X(0x70ee3607), X(0x70f6d0d1), X(0x70ff689d), X(0x7107fd6b), X(0x71108f3b), X(0x71191e0d), X(0x7121a9e2), X(0x712a32b9), X(0x7132b892), X(0x713b3b6e), X(0x7143bb4c), X(0x714c382d), X(0x7154b211), X(0x715d28f7), X(0x71659ce0), X(0x716e0dcc), X(0x71767bbb), X(0x717ee6ac), X(0x71874ea1), X(0x718fb399), X(0x71981594), X(0x71a07493), X(0x71a8d094), X(0x71b1299a), X(0x71b97fa2), X(0x71c1d2af), X(0x71ca22bf), X(0x71d26fd2), X(0x71dab9ea), X(0x71e30106), X(0x71eb4526), X(0x71f3864a), X(0x71fbc472), X(0x7203ff9e), X(0x720c37cf), X(0x72146d05), X(0x721c9f3f), X(0x7224ce7e), X(0x722cfac2), X(0x7235240b), X(0x723d4a59), X(0x72456dad), X(0x724d8e05), X(0x7255ab63), X(0x725dc5c7), X(0x7265dd31), X(0x726df1a0), X(0x72760315), X(0x727e1191), X(0x72861d12), X(0x728e259a), X(0x72962b28), X(0x729e2dbd), X(0x72a62d59), X(0x72ae29fc), X(0x72b623a5), X(0x72be1a56), X(0x72c60e0e), X(0x72cdfece), X(0x72d5ec95), X(0x72ddd764), X(0x72e5bf3b), X(0x72eda41a), X(0x72f58601), X(0x72fd64f1), X(0x730540e9), X(0x730d19e9), X(0x7314eff3), X(0x731cc305), X(0x73249321), X(0x732c6046), X(0x73342a75), X(0x733bf1ad), X(0x7343b5ef), X(0x734b773b), X(0x73533591), X(0x735af0f2), X(0x7362a95d), X(0x736a5ed3), X(0x73721153), X(0x7379c0df), X(0x73816d76), X(0x73891719), X(0x7390bdc7), X(0x73986181), X(0x73a00247), X(0x73a7a01a), X(0x73af3af8), X(0x73b6d2e4), X(0x73be67dc), X(0x73c5f9e1), X(0x73cd88f3), X(0x73d51513), X(0x73dc9e40), X(0x73e4247c), X(0x73eba7c5), X(0x73f3281c), X(0x73faa582), X(0x74021ff7), X(0x7409977b), X(0x74110c0d), X(0x74187daf), X(0x741fec61), X(0x74275822), X(0x742ec0f3), X(0x743626d5), X(0x743d89c7), X(0x7444e9c9), X(0x744c46dd), X(0x7453a101), X(0x745af837), X(0x74624c7f), X(0x74699dd8), X(0x7470ec44), X(0x747837c2), X(0x747f8052), X(0x7486c5f5), X(0x748e08ac), X(0x74954875), X(0x749c8552), X(0x74a3bf43), X(0x74aaf648), X(0x74b22a62), X(0x74b95b90), X(0x74c089d2), X(0x74c7b52a), X(0x74cedd97), X(0x74d6031a), X(0x74dd25b2), X(0x74e44561), X(0x74eb6226), X(0x74f27c02), X(0x74f992f5), X(0x7500a6ff), X(0x7507b820), X(0x750ec659), X(0x7515d1aa), X(0x751cda14), X(0x7523df96), X(0x752ae231), X(0x7531e1e5), X(0x7538deb2), X(0x753fd89a), X(0x7546cf9b), X(0x754dc3b7), X(0x7554b4ed), X(0x755ba33e), X(0x75628eaa), X(0x75697732), X(0x75705cd5), X(0x75773f95), X(0x757e1f71), X(0x7584fc6a), X(0x758bd67f), X(0x7592adb2), X(0x75998203), X(0x75a05371), X(0x75a721fe), X(0x75adeda9), X(0x75b4b673), X(0x75bb7c5c), X(0x75c23f65), X(0x75c8ff8d), X(0x75cfbcd6), X(0x75d6773f), X(0x75dd2ec8), X(0x75e3e373), X(0x75ea953f), X(0x75f1442d), X(0x75f7f03d), X(0x75fe996f), X(0x76053fc5), X(0x760be33d), X(0x761283d8), X(0x76192197), X(0x761fbc7b), X(0x76265482), X(0x762ce9af), X(0x76337c01), X(0x763a0b78), X(0x76409814), X(0x764721d7), X(0x764da8c1), X(0x76542cd1), X(0x765aae08), X(0x76612c67), X(0x7667a7ee), X(0x766e209d), X(0x76749675), X(0x767b0975), X(0x7681799f), X(0x7687e6f3), X(0x768e5170), X(0x7694b918), X(0x769b1deb), X(0x76a17fe9), X(0x76a7df13), X(0x76ae3b68), X(0x76b494ea), X(0x76baeb98), X(0x76c13f74), X(0x76c7907c), X(0x76cddeb3), X(0x76d42a18), X(0x76da72ab), X(0x76e0b86d), X(0x76e6fb5e), X(0x76ed3b7f), X(0x76f378d0), X(0x76f9b352), X(0x76ffeb05), X(0x77061fe8), X(0x770c51fe), X(0x77128145), X(0x7718adbf), X(0x771ed76c), X(0x7724fe4c), X(0x772b225f), X(0x773143a7), X(0x77376223), X(0x773d7dd3), X(0x774396ba), X(0x7749acd5), X(0x774fc027), X(0x7755d0af), X(0x775bde6f), X(0x7761e965), X(0x7767f193), X(0x776df6fa), X(0x7773f998), X(0x7779f970), X(0x777ff681), X(0x7785f0cd), X(0x778be852), X(0x7791dd12), X(0x7797cf0d), X(0x779dbe43), X(0x77a3aab6), X(0x77a99465), X(0x77af7b50), X(0x77b55f79), X(0x77bb40e0), X(0x77c11f85), X(0x77c6fb68), X(0x77ccd48a), X(0x77d2aaec), X(0x77d87e8d), X(0x77de4f6f), X(0x77e41d92), X(0x77e9e8f5), X(0x77efb19b), X(0x77f57782), X(0x77fb3aad), X(0x7800fb1a), X(0x7806b8ca), X(0x780c73bf), X(0x78122bf7), X(0x7817e175), X(0x781d9438), X(0x78234440), X(0x7828f18f), X(0x782e9c25), X(0x78344401), X(0x7839e925), X(0x783f8b92), X(0x78452b46), X(0x784ac844), X(0x7850628b), X(0x7855fa1c), X(0x785b8ef8), X(0x7861211e), X(0x7866b090), X(0x786c3d4d), X(0x7871c757), X(0x78774ead), X(0x787cd351), X(0x78825543), X(0x7887d483), X(0x788d5111), X(0x7892caef), X(0x7898421c), X(0x789db69a), X(0x78a32868), X(0x78a89787), X(0x78ae03f8), X(0x78b36dbb), X(0x78b8d4d1), X(0x78be393a), X(0x78c39af6), X(0x78c8fa06), X(0x78ce566c), X(0x78d3b026), X(0x78d90736), X(0x78de5b9c), X(0x78e3ad58), X(0x78e8fc6c), X(0x78ee48d7), X(0x78f3929b), X(0x78f8d9b7), X(0x78fe1e2c), X(0x79035ffb), X(0x79089f24), X(0x790ddba8), X(0x79131587), X(0x79184cc2), X(0x791d8159), X(0x7922b34d), X(0x7927e29e), X(0x792d0f4d), X(0x7932395a), X(0x793760c6), X(0x793c8591), X(0x7941a7bd), X(0x7946c749), X(0x794be435), X(0x7950fe84), X(0x79561634), X(0x795b2b47), X(0x79603dbc), X(0x79654d96), X(0x796a5ad4), X(0x796f6576), X(0x79746d7e), X(0x797972eb), X(0x797e75bf), X(0x798375f9), X(0x7988739b), X(0x798d6ea5), X(0x79926717), X(0x79975cf2), X(0x799c5037), X(0x79a140e6), X(0x79a62f00), X(0x79ab1a85), X(0x79b00376), X(0x79b4e9d3), X(0x79b9cd9d), X(0x79beaed4), X(0x79c38d79), X(0x79c8698d), X(0x79cd4310), X(0x79d21a03), X(0x79d6ee66), X(0x79dbc03a), X(0x79e08f7f), X(0x79e55c36), X(0x79ea265f), X(0x79eeedfc), X(0x79f3b30c), X(0x79f87590), X(0x79fd3589), X(0x7a01f2f7), X(0x7a06addc), X(0x7a0b6636), X(0x7a101c08), X(0x7a14cf52), X(0x7a198013), X(0x7a1e2e4d), X(0x7a22da01), X(0x7a27832f), X(0x7a2c29d7), X(0x7a30cdfa), X(0x7a356f99), X(0x7a3a0eb4), X(0x7a3eab4c), X(0x7a434561), X(0x7a47dcf5), X(0x7a4c7207), X(0x7a510498), X(0x7a5594a9), X(0x7a5a223a), X(0x7a5ead4d), X(0x7a6335e0), X(0x7a67bbf6), X(0x7a6c3f8f), X(0x7a70c0ab), X(0x7a753f4b), X(0x7a79bb6f), X(0x7a7e3519), X(0x7a82ac48), X(0x7a8720fe), X(0x7a8b933b), X(0x7a9002ff), X(0x7a94704b), X(0x7a98db20), X(0x7a9d437e), X(0x7aa1a967), X(0x7aa60cd9), X(0x7aaa6dd7), X(0x7aaecc61), X(0x7ab32877), X(0x7ab7821b), X(0x7abbd94b), X(0x7ac02e0a), X(0x7ac48058), X(0x7ac8d035), X(0x7acd1da3), X(0x7ad168a1), X(0x7ad5b130), X(0x7ad9f751), X(0x7ade3b05), X(0x7ae27c4c), X(0x7ae6bb27), X(0x7aeaf796), X(0x7aef319a), X(0x7af36934), X(0x7af79e64), X(0x7afbd12c), X(0x7b00018a), X(0x7b042f81), X(0x7b085b10), X(0x7b0c8439), X(0x7b10aafc), X(0x7b14cf5a), X(0x7b18f153), X(0x7b1d10e8), X(0x7b212e1a), X(0x7b2548e9), X(0x7b296155), X(0x7b2d7761), X(0x7b318b0b), X(0x7b359c55), X(0x7b39ab3f), X(0x7b3db7cb), X(0x7b41c1f8), X(0x7b45c9c8), X(0x7b49cf3b), X(0x7b4dd251), X(0x7b51d30b), X(0x7b55d16b), X(0x7b59cd70), X(0x7b5dc71b), X(0x7b61be6d), X(0x7b65b366), X(0x7b69a608), X(0x7b6d9653), X(0x7b718447), X(0x7b756fe5), X(0x7b79592e), X(0x7b7d4022), X(0x7b8124c3), X(0x7b850710), X(0x7b88e70a), X(0x7b8cc4b3), X(0x7b90a00a), X(0x7b947911), X(0x7b984fc8), X(0x7b9c242f), X(0x7b9ff648), X(0x7ba3c612), X(0x7ba79390), X(0x7bab5ec1), X(0x7baf27a5), X(0x7bb2ee3f), X(0x7bb6b28e), X(0x7bba7493), X(0x7bbe344e), X(0x7bc1f1c1), X(0x7bc5acec), X(0x7bc965cf), X(0x7bcd1c6c), X(0x7bd0d0c3), X(0x7bd482d4), X(0x7bd832a1), X(0x7bdbe02a), X(0x7bdf8b70), X(0x7be33473), X(0x7be6db34), X(0x7bea7fb4), X(0x7bee21f4), X(0x7bf1c1f3), X(0x7bf55fb3), X(0x7bf8fb35), X(0x7bfc9479), X(0x7c002b7f), X(0x7c03c04a), X(0x7c0752d8), X(0x7c0ae32b), X(0x7c0e7144), X(0x7c11fd23), X(0x7c1586c9), X(0x7c190e36), X(0x7c1c936c), X(0x7c20166b), X(0x7c239733), X(0x7c2715c6), X(0x7c2a9224), X(0x7c2e0c4e), X(0x7c318444), X(0x7c34fa07), X(0x7c386d98), X(0x7c3bdef8), X(0x7c3f4e26), X(0x7c42bb25), X(0x7c4625f4), X(0x7c498e95), X(0x7c4cf507), X(0x7c50594c), X(0x7c53bb65), X(0x7c571b51), X(0x7c5a7913), X(0x7c5dd4aa), X(0x7c612e17), X(0x7c64855b), X(0x7c67da76), X(0x7c6b2d6a), X(0x7c6e7e37), X(0x7c71ccdd), X(0x7c75195e), X(0x7c7863ba), X(0x7c7babf1), X(0x7c7ef206), X(0x7c8235f7), X(0x7c8577c6), X(0x7c88b774), X(0x7c8bf502), X(0x7c8f306f), X(0x7c9269bd), X(0x7c95a0ec), X(0x7c98d5fe), X(0x7c9c08f2), X(0x7c9f39cb), X(0x7ca26887), X(0x7ca59528), X(0x7ca8bfb0), X(0x7cabe81d), X(0x7caf0e72), X(0x7cb232af), X(0x7cb554d4), X(0x7cb874e2), X(0x7cbb92db), X(0x7cbeaebe), X(0x7cc1c88d), X(0x7cc4e047), X(0x7cc7f5ef), X(0x7ccb0984), X(0x7cce1b08), X(0x7cd12a7b), X(0x7cd437dd), X(0x7cd74330), X(0x7cda4c74), X(0x7cdd53aa), X(0x7ce058d3), X(0x7ce35bef), X(0x7ce65cff), X(0x7ce95c04), X(0x7cec58ff), X(0x7cef53f0), X(0x7cf24cd7), X(0x7cf543b7), X(0x7cf8388f), X(0x7cfb2b60), X(0x7cfe1c2b), X(0x7d010af1), X(0x7d03f7b2), X(0x7d06e26f), X(0x7d09cb29), X(0x7d0cb1e0), X(0x7d0f9696), X(0x7d12794b), X(0x7d1559ff), X(0x7d1838b4), X(0x7d1b156a), X(0x7d1df022), X(0x7d20c8dd), X(0x7d239f9b), X(0x7d26745e), X(0x7d294725), X(0x7d2c17f1), X(0x7d2ee6c4), X(0x7d31b39f), X(0x7d347e81), X(0x7d37476b), X(0x7d3a0e5f), X(0x7d3cd35d), X(0x7d3f9665), X(0x7d425779), X(0x7d451699), X(0x7d47d3c6), X(0x7d4a8f01), X(0x7d4d484b), X(0x7d4fffa3), X(0x7d52b50c), X(0x7d556885), X(0x7d581a0f), X(0x7d5ac9ac), X(0x7d5d775c), X(0x7d60231f), X(0x7d62ccf6), X(0x7d6574e3), X(0x7d681ae6), X(0x7d6abeff), X(0x7d6d612f), X(0x7d700178), X(0x7d729fd9), X(0x7d753c54), X(0x7d77d6e9), X(0x7d7a6f9a), X(0x7d7d0666), X(0x7d7f9b4f), X(0x7d822e55), X(0x7d84bf79), X(0x7d874ebc), X(0x7d89dc1e), X(0x7d8c67a1), X(0x7d8ef144), X(0x7d91790a), X(0x7d93fef2), X(0x7d9682fd), X(0x7d99052d), X(0x7d9b8581), X(0x7d9e03fb), X(0x7da0809b), X(0x7da2fb62), X(0x7da57451), X(0x7da7eb68), X(0x7daa60a8), X(0x7dacd413), X(0x7daf45a9), X(0x7db1b56a), X(0x7db42357), X(0x7db68f71), X(0x7db8f9b9), X(0x7dbb6230), X(0x7dbdc8d6), X(0x7dc02dac), X(0x7dc290b3), X(0x7dc4f1eb), X(0x7dc75156), X(0x7dc9aef4), X(0x7dcc0ac5), X(0x7dce64cc), X(0x7dd0bd07), X(0x7dd31379), X(0x7dd56821), X(0x7dd7bb01), X(0x7dda0c1a), X(0x7ddc5b6b), X(0x7ddea8f7), X(0x7de0f4bd), X(0x7de33ebe), X(0x7de586fc), X(0x7de7cd76), X(0x7dea122e), X(0x7dec5525), X(0x7dee965a), X(0x7df0d5d0), X(0x7df31386), X(0x7df54f7e), X(0x7df789b8), X(0x7df9c235), X(0x7dfbf8f5), X(0x7dfe2dfa), X(0x7e006145), X(0x7e0292d5), X(0x7e04c2ac), X(0x7e06f0cb), X(0x7e091d32), X(0x7e0b47e1), X(0x7e0d70db), X(0x7e0f981f), X(0x7e11bdaf), X(0x7e13e18a), X(0x7e1603b3), X(0x7e182429), X(0x7e1a42ed), X(0x7e1c6001), X(0x7e1e7b64), X(0x7e209518), X(0x7e22ad1d), X(0x7e24c375), X(0x7e26d81f), X(0x7e28eb1d), X(0x7e2afc70), X(0x7e2d0c17), X(0x7e2f1a15), X(0x7e31266a), X(0x7e333115), X(0x7e353a1a), X(0x7e374177), X(0x7e39472e), X(0x7e3b4b3f), X(0x7e3d4dac), X(0x7e3f4e75), X(0x7e414d9a), X(0x7e434b1e), X(0x7e4546ff), X(0x7e474140), X(0x7e4939e0), X(0x7e4b30e2), X(0x7e4d2644), X(0x7e4f1a09), X(0x7e510c30), X(0x7e52fcbc), X(0x7e54ebab), X(0x7e56d900), X(0x7e58c4bb), X(0x7e5aaedd), X(0x7e5c9766), X(0x7e5e7e57), X(0x7e6063b2), X(0x7e624776), X(0x7e6429a5), X(0x7e660a3f), X(0x7e67e945), X(0x7e69c6b8), X(0x7e6ba299), X(0x7e6d7ce7), X(0x7e6f55a5), X(0x7e712cd3), X(0x7e730272), X(0x7e74d682), X(0x7e76a904), X(0x7e7879f9), X(0x7e7a4962), X(0x7e7c173f), X(0x7e7de392), X(0x7e7fae5a), X(0x7e817799), X(0x7e833f50), X(0x7e85057f), X(0x7e86ca27), X(0x7e888d49), X(0x7e8a4ee5), X(0x7e8c0efd), X(0x7e8dcd91), X(0x7e8f8aa1), X(0x7e914630), X(0x7e93003c), X(0x7e94b8c8), X(0x7e966fd4), X(0x7e982560), X(0x7e99d96e), X(0x7e9b8bfe), X(0x7e9d3d10), X(0x7e9eeca7), X(0x7ea09ac2), X(0x7ea24762), X(0x7ea3f288), X(0x7ea59c35), X(0x7ea7446a), X(0x7ea8eb27), X(0x7eaa906c), X(0x7eac343c), X(0x7eadd696), X(0x7eaf777b), X(0x7eb116ed), X(0x7eb2b4eb), X(0x7eb45177), X(0x7eb5ec91), X(0x7eb7863b), X(0x7eb91e74), X(0x7ebab53e), X(0x7ebc4a99), X(0x7ebdde87), X(0x7ebf7107), X(0x7ec1021b), X(0x7ec291c3), X(0x7ec42001), X(0x7ec5acd5), X(0x7ec7383f), X(0x7ec8c241), X(0x7eca4adb), X(0x7ecbd20d), X(0x7ecd57da), X(0x7ecedc41), X(0x7ed05f44), X(0x7ed1e0e2), X(0x7ed3611d), X(0x7ed4dff6), X(0x7ed65d6d), X(0x7ed7d983), X(0x7ed95438), X(0x7edacd8f), X(0x7edc4586), X(0x7eddbc20), X(0x7edf315c), X(0x7ee0a53c), X(0x7ee217c1), X(0x7ee388ea), X(0x7ee4f8b9), X(0x7ee6672f), X(0x7ee7d44c), X(0x7ee94012), X(0x7eeaaa80), X(0x7eec1397), X(0x7eed7b59), X(0x7eeee1c6), X(0x7ef046df), X(0x7ef1aaa5), X(0x7ef30d18), X(0x7ef46e39), X(0x7ef5ce09), X(0x7ef72c88), X(0x7ef889b8), X(0x7ef9e599), X(0x7efb402c), X(0x7efc9972), X(0x7efdf16b), X(0x7eff4818), X(0x7f009d79), X(0x7f01f191), X(0x7f03445f), X(0x7f0495e4), X(0x7f05e620), X(0x7f073516), X(0x7f0882c5), X(0x7f09cf2d), X(0x7f0b1a51), X(0x7f0c6430), X(0x7f0daccc), X(0x7f0ef425), X(0x7f103a3b), X(0x7f117f11), X(0x7f12c2a5), X(0x7f1404fa), X(0x7f15460f), X(0x7f1685e6), X(0x7f17c47f), X(0x7f1901db), X(0x7f1a3dfb), X(0x7f1b78e0), X(0x7f1cb28a), X(0x7f1deafa), X(0x7f1f2231), X(0x7f20582f), X(0x7f218cf5), X(0x7f22c085), X(0x7f23f2de), X(0x7f252401), X(0x7f2653f0), X(0x7f2782ab), X(0x7f28b032), X(0x7f29dc87), X(0x7f2b07aa), X(0x7f2c319c), X(0x7f2d5a5e), X(0x7f2e81f0), X(0x7f2fa853), X(0x7f30cd88), X(0x7f31f18f), X(0x7f33146a), X(0x7f343619), X(0x7f35569c), X(0x7f3675f6), X(0x7f379425), X(0x7f38b12c), X(0x7f39cd0a), X(0x7f3ae7c0), X(0x7f3c0150), X(0x7f3d19ba), X(0x7f3e30fe), X(0x7f3f471e), X(0x7f405c1a), X(0x7f416ff3), X(0x7f4282a9), X(0x7f43943e), X(0x7f44a4b2), X(0x7f45b405), X(0x7f46c239), X(0x7f47cf4e), X(0x7f48db45), X(0x7f49e61f), X(0x7f4aefdc), X(0x7f4bf87e), X(0x7f4d0004), X(0x7f4e0670), X(0x7f4f0bc2), X(0x7f500ffb), X(0x7f51131c), X(0x7f521525), X(0x7f531618), X(0x7f5415f4), X(0x7f5514bb), X(0x7f56126e), X(0x7f570f0c), X(0x7f580a98), X(0x7f590511), X(0x7f59fe78), X(0x7f5af6ce), X(0x7f5bee14), X(0x7f5ce44a), X(0x7f5dd972), X(0x7f5ecd8b), X(0x7f5fc097), X(0x7f60b296), X(0x7f61a389), X(0x7f629370), X(0x7f63824e), X(0x7f647021), X(0x7f655ceb), X(0x7f6648ad), X(0x7f673367), X(0x7f681d19), X(0x7f6905c6), X(0x7f69ed6d), X(0x7f6ad40f), X(0x7f6bb9ad), X(0x7f6c9e48), X(0x7f6d81e0), X(0x7f6e6475), X(0x7f6f460a), X(0x7f70269d), X(0x7f710631), X(0x7f71e4c6), X(0x7f72c25c), X(0x7f739ef4), X(0x7f747a8f), X(0x7f75552e), X(0x7f762ed1), X(0x7f770779), X(0x7f77df27), X(0x7f78b5db), X(0x7f798b97), X(0x7f7a605a), X(0x7f7b3425), X(0x7f7c06fa), X(0x7f7cd8d9), X(0x7f7da9c2), X(0x7f7e79b7), X(0x7f7f48b8), X(0x7f8016c5), X(0x7f80e3e0), X(0x7f81b009), X(0x7f827b40), X(0x7f834588), X(0x7f840edf), X(0x7f84d747), X(0x7f859ec1), X(0x7f86654d), X(0x7f872aec), X(0x7f87ef9e), X(0x7f88b365), X(0x7f897641), X(0x7f8a3832), X(0x7f8af93a), X(0x7f8bb959), X(0x7f8c7890), X(0x7f8d36df), X(0x7f8df448), X(0x7f8eb0ca), X(0x7f8f6c67), X(0x7f90271e), X(0x7f90e0f2), X(0x7f9199e2), X(0x7f9251f0), X(0x7f93091b), X(0x7f93bf65), X(0x7f9474ce), X(0x7f952958), X(0x7f95dd01), X(0x7f968fcd), X(0x7f9741ba), X(0x7f97f2ca), X(0x7f98a2fd), X(0x7f995254), X(0x7f9a00d0), X(0x7f9aae71), X(0x7f9b5b38), X(0x7f9c0726), X(0x7f9cb23b), X(0x7f9d5c78), X(0x7f9e05de), X(0x7f9eae6e), X(0x7f9f5627), X(0x7f9ffd0b), X(0x7fa0a31b), X(0x7fa14856), X(0x7fa1ecbf), X(0x7fa29054), X(0x7fa33318), X(0x7fa3d50b), X(0x7fa4762c), X(0x7fa5167e), X(0x7fa5b601), X(0x7fa654b5), X(0x7fa6f29b), X(0x7fa78fb3), X(0x7fa82bff), X(0x7fa8c77f), X(0x7fa96234), X(0x7fa9fc1e), X(0x7faa953e), X(0x7fab2d94), X(0x7fabc522), X(0x7fac5be8), X(0x7facf1e6), X(0x7fad871d), X(0x7fae1b8f), X(0x7faeaf3b), X(0x7faf4222), X(0x7fafd445), X(0x7fb065a4), X(0x7fb0f641), X(0x7fb1861b), X(0x7fb21534), X(0x7fb2a38c), X(0x7fb33124), X(0x7fb3bdfb), X(0x7fb44a14), X(0x7fb4d56f), X(0x7fb5600c), X(0x7fb5e9ec), X(0x7fb6730f), X(0x7fb6fb76), X(0x7fb78323), X(0x7fb80a15), X(0x7fb8904d), X(0x7fb915cc), X(0x7fb99a92), X(0x7fba1ea0), X(0x7fbaa1f7), X(0x7fbb2497), X(0x7fbba681), X(0x7fbc27b5), X(0x7fbca835), X(0x7fbd2801), X(0x7fbda719), X(0x7fbe257e), X(0x7fbea331), X(0x7fbf2032), X(0x7fbf9c82), X(0x7fc01821), X(0x7fc09311), X(0x7fc10d52), X(0x7fc186e4), X(0x7fc1ffc8), X(0x7fc277ff), X(0x7fc2ef89), X(0x7fc36667), X(0x7fc3dc9a), X(0x7fc45221), X(0x7fc4c6ff), X(0x7fc53b33), X(0x7fc5aebe), X(0x7fc621a0), X(0x7fc693db), X(0x7fc7056f), X(0x7fc7765c), X(0x7fc7e6a3), X(0x7fc85645), X(0x7fc8c542), X(0x7fc9339b), X(0x7fc9a150), X(0x7fca0e63), X(0x7fca7ad3), X(0x7fcae6a2), X(0x7fcb51cf), X(0x7fcbbc5c), X(0x7fcc2649), X(0x7fcc8f97), X(0x7fccf846), X(0x7fcd6058), X(0x7fcdc7cb), X(0x7fce2ea2), X(0x7fce94dd), X(0x7fcefa7b), X(0x7fcf5f7f), X(0x7fcfc3e8), X(0x7fd027b7), X(0x7fd08aed), X(0x7fd0ed8b), X(0x7fd14f90), X(0x7fd1b0fd), X(0x7fd211d4), X(0x7fd27214), X(0x7fd2d1bf), X(0x7fd330d4), X(0x7fd38f55), X(0x7fd3ed41), X(0x7fd44a9a), X(0x7fd4a761), X(0x7fd50395), X(0x7fd55f37), X(0x7fd5ba48), X(0x7fd614c9), X(0x7fd66eba), X(0x7fd6c81b), X(0x7fd720ed), X(0x7fd77932), X(0x7fd7d0e8), X(0x7fd82812), X(0x7fd87eae), X(0x7fd8d4bf), X(0x7fd92a45), X(0x7fd97f40), X(0x7fd9d3b0), X(0x7fda2797), X(0x7fda7af5), X(0x7fdacdca), X(0x7fdb2018), X(0x7fdb71dd), X(0x7fdbc31c), X(0x7fdc13d5), X(0x7fdc6408), X(0x7fdcb3b6), X(0x7fdd02df), X(0x7fdd5184), X(0x7fdd9fa5), X(0x7fdded44), X(0x7fde3a60), X(0x7fde86fb), X(0x7fded314), X(0x7fdf1eac), X(0x7fdf69c4), X(0x7fdfb45d), X(0x7fdffe76), X(0x7fe04811), X(0x7fe0912e), X(0x7fe0d9ce), X(0x7fe121f0), X(0x7fe16996), X(0x7fe1b0c1), X(0x7fe1f770), X(0x7fe23da4), X(0x7fe2835f), X(0x7fe2c89f), X(0x7fe30d67), X(0x7fe351b5), X(0x7fe3958c), X(0x7fe3d8ec), X(0x7fe41bd4), X(0x7fe45e46), X(0x7fe4a042), X(0x7fe4e1c8), X(0x7fe522da), X(0x7fe56378), X(0x7fe5a3a1), X(0x7fe5e358), X(0x7fe6229b), X(0x7fe6616d), X(0x7fe69fcc), X(0x7fe6ddbb), X(0x7fe71b39), X(0x7fe75847), X(0x7fe794e5), X(0x7fe7d114), X(0x7fe80cd5), X(0x7fe84827), X(0x7fe8830c), X(0x7fe8bd84), X(0x7fe8f78f), X(0x7fe9312f), X(0x7fe96a62), X(0x7fe9a32b), X(0x7fe9db8a), X(0x7fea137e), X(0x7fea4b09), X(0x7fea822b), X(0x7feab8e5), X(0x7feaef37), X(0x7feb2521), X(0x7feb5aa4), X(0x7feb8fc1), X(0x7febc478), X(0x7febf8ca), X(0x7fec2cb6), X(0x7fec603e), X(0x7fec9363), X(0x7fecc623), X(0x7fecf881), X(0x7fed2a7c), X(0x7fed5c16), X(0x7fed8d4e), X(0x7fedbe24), X(0x7fedee9b), X(0x7fee1eb1), X(0x7fee4e68), X(0x7fee7dc0), X(0x7feeacb9), X(0x7feedb54), X(0x7fef0991), X(0x7fef3771), X(0x7fef64f5), X(0x7fef921d), X(0x7fefbee8), X(0x7fefeb59), X(0x7ff0176f), X(0x7ff0432a), X(0x7ff06e8c), X(0x7ff09995), X(0x7ff0c444), X(0x7ff0ee9c), X(0x7ff1189b), X(0x7ff14243), X(0x7ff16b94), X(0x7ff1948e), X(0x7ff1bd32), X(0x7ff1e581), X(0x7ff20d7b), X(0x7ff2351f), X(0x7ff25c70), X(0x7ff2836d), X(0x7ff2aa17), X(0x7ff2d06d), X(0x7ff2f672), X(0x7ff31c24), X(0x7ff34185), X(0x7ff36695), X(0x7ff38b55), X(0x7ff3afc4), X(0x7ff3d3e4), X(0x7ff3f7b4), X(0x7ff41b35), X(0x7ff43e69), X(0x7ff4614e), X(0x7ff483e6), X(0x7ff4a631), X(0x7ff4c82f), X(0x7ff4e9e1), X(0x7ff50b47), X(0x7ff52c62), X(0x7ff54d33), X(0x7ff56db9), X(0x7ff58df5), X(0x7ff5ade7), X(0x7ff5cd90), X(0x7ff5ecf1), X(0x7ff60c09), X(0x7ff62ada), X(0x7ff64963), X(0x7ff667a5), X(0x7ff685a1), X(0x7ff6a357), X(0x7ff6c0c7), X(0x7ff6ddf1), X(0x7ff6fad7), X(0x7ff71778), X(0x7ff733d6), X(0x7ff74fef), X(0x7ff76bc6), X(0x7ff78759), X(0x7ff7a2ab), X(0x7ff7bdba), X(0x7ff7d888), X(0x7ff7f315), X(0x7ff80d61), X(0x7ff8276c), X(0x7ff84138), X(0x7ff85ac4), X(0x7ff87412), X(0x7ff88d20), X(0x7ff8a5f0), X(0x7ff8be82), X(0x7ff8d6d7), X(0x7ff8eeef), X(0x7ff906c9), X(0x7ff91e68), X(0x7ff935cb), X(0x7ff94cf2), X(0x7ff963dd), X(0x7ff97a8f), X(0x7ff99105), X(0x7ff9a742), X(0x7ff9bd45), X(0x7ff9d30f), X(0x7ff9e8a0), X(0x7ff9fdf9), X(0x7ffa131a), X(0x7ffa2803), X(0x7ffa3cb4), X(0x7ffa512f), X(0x7ffa6573), X(0x7ffa7981), X(0x7ffa8d59), X(0x7ffaa0fc), X(0x7ffab46a), X(0x7ffac7a3), X(0x7ffadaa8), X(0x7ffaed78), X(0x7ffb0015), X(0x7ffb127f), X(0x7ffb24b6), X(0x7ffb36bb), X(0x7ffb488d), X(0x7ffb5a2e), X(0x7ffb6b9d), X(0x7ffb7cdb), X(0x7ffb8de9), X(0x7ffb9ec6), X(0x7ffbaf73), X(0x7ffbbff1), X(0x7ffbd03f), X(0x7ffbe05e), X(0x7ffbf04f), X(0x7ffc0012), X(0x7ffc0fa6), X(0x7ffc1f0d), X(0x7ffc2e47), X(0x7ffc3d54), X(0x7ffc4c35), X(0x7ffc5ae9), X(0x7ffc6971), X(0x7ffc77ce), X(0x7ffc8600), X(0x7ffc9407), X(0x7ffca1e4), X(0x7ffcaf96), X(0x7ffcbd1f), X(0x7ffcca7e), X(0x7ffcd7b4), X(0x7ffce4c1), X(0x7ffcf1a5), X(0x7ffcfe62), X(0x7ffd0af6), X(0x7ffd1763), X(0x7ffd23a9), X(0x7ffd2fc8), X(0x7ffd3bc1), X(0x7ffd4793), X(0x7ffd533f), X(0x7ffd5ec5), X(0x7ffd6a27), X(0x7ffd7563), X(0x7ffd807a), X(0x7ffd8b6e), X(0x7ffd963d), X(0x7ffda0e8), X(0x7ffdab70), X(0x7ffdb5d5), X(0x7ffdc017), X(0x7ffdca36), X(0x7ffdd434), X(0x7ffdde0f), X(0x7ffde7c9), X(0x7ffdf161), X(0x7ffdfad8), X(0x7ffe042f), X(0x7ffe0d65), X(0x7ffe167b), X(0x7ffe1f71), X(0x7ffe2848), X(0x7ffe30ff), X(0x7ffe3997), X(0x7ffe4211), X(0x7ffe4a6c), X(0x7ffe52a9), X(0x7ffe5ac8), X(0x7ffe62c9), X(0x7ffe6aae), X(0x7ffe7275), X(0x7ffe7a1f), X(0x7ffe81ad), X(0x7ffe891f), X(0x7ffe9075), X(0x7ffe97b0), X(0x7ffe9ece), X(0x7ffea5d2), X(0x7ffeacbb), X(0x7ffeb38a), X(0x7ffeba3e), X(0x7ffec0d8), X(0x7ffec758), X(0x7ffecdbf), X(0x7ffed40d), X(0x7ffeda41), X(0x7ffee05d), X(0x7ffee660), X(0x7ffeec4b), X(0x7ffef21f), X(0x7ffef7da), X(0x7ffefd7e), X(0x7fff030b), X(0x7fff0881), X(0x7fff0de0), X(0x7fff1328), X(0x7fff185b), X(0x7fff1d77), X(0x7fff227e), X(0x7fff276f), X(0x7fff2c4b), X(0x7fff3112), X(0x7fff35c4), X(0x7fff3a62), X(0x7fff3eeb), X(0x7fff4360), X(0x7fff47c2), X(0x7fff4c0f), X(0x7fff504a), X(0x7fff5471), X(0x7fff5885), X(0x7fff5c87), X(0x7fff6076), X(0x7fff6452), X(0x7fff681d), X(0x7fff6bd6), X(0x7fff6f7d), X(0x7fff7313), X(0x7fff7698), X(0x7fff7a0c), X(0x7fff7d6f), X(0x7fff80c2), X(0x7fff8404), X(0x7fff8736), X(0x7fff8a58), X(0x7fff8d6b), X(0x7fff906e), X(0x7fff9362), X(0x7fff9646), X(0x7fff991c), X(0x7fff9be3), X(0x7fff9e9c), X(0x7fffa146), X(0x7fffa3e2), X(0x7fffa671), X(0x7fffa8f1), X(0x7fffab65), X(0x7fffadca), X(0x7fffb023), X(0x7fffb26f), X(0x7fffb4ae), X(0x7fffb6e0), X(0x7fffb906), X(0x7fffbb20), X(0x7fffbd2e), X(0x7fffbf30), X(0x7fffc126), X(0x7fffc311), X(0x7fffc4f1), X(0x7fffc6c5), X(0x7fffc88f), X(0x7fffca4d), X(0x7fffcc01), X(0x7fffcdab), X(0x7fffcf4a), X(0x7fffd0e0), X(0x7fffd26b), X(0x7fffd3ec), X(0x7fffd564), X(0x7fffd6d2), X(0x7fffd838), X(0x7fffd993), X(0x7fffdae6), X(0x7fffdc31), X(0x7fffdd72), X(0x7fffdeab), X(0x7fffdfdb), X(0x7fffe104), X(0x7fffe224), X(0x7fffe33c), X(0x7fffe44d), X(0x7fffe556), X(0x7fffe657), X(0x7fffe751), X(0x7fffe844), X(0x7fffe930), X(0x7fffea15), X(0x7fffeaf3), X(0x7fffebca), X(0x7fffec9b), X(0x7fffed66), X(0x7fffee2a), X(0x7fffeee8), X(0x7fffefa0), X(0x7ffff053), X(0x7ffff0ff), X(0x7ffff1a6), X(0x7ffff247), X(0x7ffff2e4), X(0x7ffff37a), X(0x7ffff40c), X(0x7ffff499), X(0x7ffff520), X(0x7ffff5a3), X(0x7ffff621), X(0x7ffff69b), X(0x7ffff710), X(0x7ffff781), X(0x7ffff7ee), X(0x7ffff857), X(0x7ffff8bb), X(0x7ffff91c), X(0x7ffff979), X(0x7ffff9d2), X(0x7ffffa27), X(0x7ffffa79), X(0x7ffffac8), X(0x7ffffb13), X(0x7ffffb5b), X(0x7ffffba0), X(0x7ffffbe2), X(0x7ffffc21), X(0x7ffffc5d), X(0x7ffffc96), X(0x7ffffccd), X(0x7ffffd01), X(0x7ffffd32), X(0x7ffffd61), X(0x7ffffd8e), X(0x7ffffdb8), X(0x7ffffde0), X(0x7ffffe07), X(0x7ffffe2b), X(0x7ffffe4d), X(0x7ffffe6d), X(0x7ffffe8b), X(0x7ffffea8), X(0x7ffffec3), X(0x7ffffedc), X(0x7ffffef4), X(0x7fffff0a), X(0x7fffff1f), X(0x7fffff33), X(0x7fffff45), X(0x7fffff56), X(0x7fffff66), X(0x7fffff75), X(0x7fffff82), X(0x7fffff8f), X(0x7fffff9a), X(0x7fffffa5), X(0x7fffffaf), X(0x7fffffb8), X(0x7fffffc0), X(0x7fffffc8), X(0x7fffffce), X(0x7fffffd5), X(0x7fffffda), X(0x7fffffdf), X(0x7fffffe4), X(0x7fffffe8), X(0x7fffffeb), X(0x7fffffef), X(0x7ffffff1), X(0x7ffffff4), X(0x7ffffff6), X(0x7ffffff8), X(0x7ffffff9), X(0x7ffffffb), X(0x7ffffffc), X(0x7ffffffd), X(0x7ffffffd), X(0x7ffffffe), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), X(0x7fffffff), }; mednafen/tremor/floor1.c000664 001750 001750 00000034663 12611054044 016346 0ustar00sergiosergio000000 000000 /******************************************************************** * * * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. * * * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 * * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ * * * ******************************************************************** function: floor backend 1 implementation ********************************************************************/ #include #include #include #include "ogg.h" #include "ivorbiscodec.h" #include "codec_internal.h" #include "registry.h" #include "codebook.h" #include "misc.h" #include "block.h" #include "tremor_shared.h" #define floor1_rangedB 140 /* floor 1 fixed at -140dB to 0dB range */ typedef struct { int forward_index[VIF_POSIT+2]; int hineighbor[VIF_POSIT]; int loneighbor[VIF_POSIT]; int posts; int n; int quant_q; vorbis_info_floor1 *vi; } vorbis_look_floor1; /***********************************************/ static void floor1_free_info(vorbis_info_floor *i){ vorbis_info_floor1 *info=(vorbis_info_floor1 *)i; if(info){ memset(info,0,sizeof(*info)); _ogg_free(info); } } static void floor1_free_look(vorbis_look_floor *i){ vorbis_look_floor1 *look=(vorbis_look_floor1 *)i; if(look){ memset(look,0,sizeof(*look)); _ogg_free(look); } } static int icomp(const void *a,const void *b){ return(**(int **)a-**(int **)b); } static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int j,k,count=0,maxclass=-1,rangebits; vorbis_info_floor1 *info=(vorbis_info_floor1 *)_ogg_calloc(1,sizeof(*info)); /* read partitions */ info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */ for(j=0;jpartitions;j++){ info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */ if(info->partitionclass[j]<0)goto err_out; if(maxclasspartitionclass[j])maxclass=info->partitionclass[j]; } /* read partition classes */ for(j=0;jclass_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */ info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */ if(info->class_subs[j]<0) goto err_out; if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8); if(info->class_book[j]<0 || info->class_book[j]>=ci->books) goto err_out; for(k=0;k<(1<class_subs[j]);k++){ info->class_subbook[j][k]=oggpack_read(opb,8)-1; if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books) goto err_out; } } /* read the post list */ info->mult=oggpack_read(opb,2)+1; /* only 1,2,3,4 legal now */ rangebits=oggpack_read(opb,4); if(rangebits<0)goto err_out; for(j=0,k=0;jpartitions;j++){ count+=info->class_dim[info->partitionclass[j]]; if(count>VIF_POSIT)goto err_out; for(;kpostlist[k+2]=oggpack_read(opb,rangebits); if(t<0 || t>=(1<postlist[0]=0; info->postlist[1]=1<postlist+j; qsort(sortpointer,count+2,sizeof(*sortpointer),icomp); for(j=1;jvi=info; look->n=info->postlist[1]; /* we drop each position value in-between already decoded values, and use linear interpolation to predict each new value past the edges. The positions are read in the order of the position list... we precompute the bounding positions in the lookup. Of course, the neighbors can change (if a position is declined), but this is an initial mapping */ for(i=0;ipartitions;i++)n+=info->class_dim[info->partitionclass[i]]; n+=2; look->posts=n; /* also store a sorted position index */ for(i=0;ipostlist+i; qsort(sortpointer,n,sizeof(*sortpointer),icomp); /* points from sort order back to range number */ for(i=0;iforward_index[i]=sortpointer[i]-info->postlist; /* quantize values to multiplier spec */ switch(info->mult){ case 1: /* 1024 -> 256 */ look->quant_q=256; break; case 2: /* 1024 -> 128 */ look->quant_q=128; break; case 3: /* 1024 -> 86 */ look->quant_q=86; break; case 4: /* 1024 -> 64 */ look->quant_q=64; break; } /* discover our neighbors for decode where we don't use fit flags (that would push the neighbors outward) */ for(i=0;in; int currentx=info->postlist[i+2]; for(j=0;jpostlist[j]; if(x>lx && xcurrentx){ hi=j; hx=x; } } look->loneighbor[i]=lo; look->hineighbor[i]=hi; } return(look); } static int render_point(int x0,int x1,int y0,int y1,int x){ y0&=0x7fff; /* mask off flag */ y1&=0x7fff; { int dy=y1-y0; int adx=x1-x0; int ady=abs(dy); int err=ady*(x-x0); int off=err/adx; if(dy<0)return(y0-off); return(y0+off); } } #ifdef _LOW_ACCURACY_ # define XdB(n) ((((n)>>8)+1)>>1) #else # define XdB(n) (n) #endif static const ogg_int32_t FLOOR_fromdB_LOOKUP[256]={ XdB(0x000000e5), XdB(0x000000f4), XdB(0x00000103), XdB(0x00000114), XdB(0x00000126), XdB(0x00000139), XdB(0x0000014e), XdB(0x00000163), XdB(0x0000017a), XdB(0x00000193), XdB(0x000001ad), XdB(0x000001c9), XdB(0x000001e7), XdB(0x00000206), XdB(0x00000228), XdB(0x0000024c), XdB(0x00000272), XdB(0x0000029b), XdB(0x000002c6), XdB(0x000002f4), XdB(0x00000326), XdB(0x0000035a), XdB(0x00000392), XdB(0x000003cd), XdB(0x0000040c), XdB(0x00000450), XdB(0x00000497), XdB(0x000004e4), XdB(0x00000535), XdB(0x0000058c), XdB(0x000005e8), XdB(0x0000064a), XdB(0x000006b3), XdB(0x00000722), XdB(0x00000799), XdB(0x00000818), XdB(0x0000089e), XdB(0x0000092e), XdB(0x000009c6), XdB(0x00000a69), XdB(0x00000b16), XdB(0x00000bcf), XdB(0x00000c93), XdB(0x00000d64), XdB(0x00000e43), XdB(0x00000f30), XdB(0x0000102d), XdB(0x0000113a), XdB(0x00001258), XdB(0x0000138a), XdB(0x000014cf), XdB(0x00001629), XdB(0x0000179a), XdB(0x00001922), XdB(0x00001ac4), XdB(0x00001c82), XdB(0x00001e5c), XdB(0x00002055), XdB(0x0000226f), XdB(0x000024ac), XdB(0x0000270e), XdB(0x00002997), XdB(0x00002c4b), XdB(0x00002f2c), XdB(0x0000323d), XdB(0x00003581), XdB(0x000038fb), XdB(0x00003caf), XdB(0x000040a0), XdB(0x000044d3), XdB(0x0000494c), XdB(0x00004e10), XdB(0x00005323), XdB(0x0000588a), XdB(0x00005e4b), XdB(0x0000646b), XdB(0x00006af2), XdB(0x000071e5), XdB(0x0000794c), XdB(0x0000812e), XdB(0x00008993), XdB(0x00009283), XdB(0x00009c09), XdB(0x0000a62d), XdB(0x0000b0f9), XdB(0x0000bc79), XdB(0x0000c8b9), XdB(0x0000d5c4), XdB(0x0000e3a9), XdB(0x0000f274), XdB(0x00010235), XdB(0x000112fd), XdB(0x000124dc), XdB(0x000137e4), XdB(0x00014c29), XdB(0x000161bf), XdB(0x000178bc), XdB(0x00019137), XdB(0x0001ab4a), XdB(0x0001c70e), XdB(0x0001e4a1), XdB(0x0002041f), XdB(0x000225aa), XdB(0x00024962), XdB(0x00026f6d), XdB(0x000297f0), XdB(0x0002c316), XdB(0x0002f109), XdB(0x000321f9), XdB(0x00035616), XdB(0x00038d97), XdB(0x0003c8b4), XdB(0x000407a7), XdB(0x00044ab2), XdB(0x00049218), XdB(0x0004de23), XdB(0x00052f1e), XdB(0x0005855c), XdB(0x0005e135), XdB(0x00064306), XdB(0x0006ab33), XdB(0x00071a24), XdB(0x0007904b), XdB(0x00080e20), XdB(0x00089422), XdB(0x000922da), XdB(0x0009bad8), XdB(0x000a5cb6), XdB(0x000b091a), XdB(0x000bc0b1), XdB(0x000c8436), XdB(0x000d5471), XdB(0x000e3233), XdB(0x000f1e5f), XdB(0x001019e4), XdB(0x001125c1), XdB(0x00124306), XdB(0x001372d5), XdB(0x0014b663), XdB(0x00160ef7), XdB(0x00177df0), XdB(0x001904c1), XdB(0x001aa4f9), XdB(0x001c603d), XdB(0x001e384f), XdB(0x00202f0f), XdB(0x0022467a), XdB(0x002480b1), XdB(0x0026dff7), XdB(0x002966b3), XdB(0x002c1776), XdB(0x002ef4fc), XdB(0x0032022d), XdB(0x00354222), XdB(0x0038b828), XdB(0x003c67c2), XdB(0x004054ae), XdB(0x004482e8), XdB(0x0048f6af), XdB(0x004db488), XdB(0x0052c142), XdB(0x005821ff), XdB(0x005ddc33), XdB(0x0063f5b0), XdB(0x006a74a7), XdB(0x00715faf), XdB(0x0078bdce), XdB(0x0080967f), XdB(0x0088f1ba), XdB(0x0091d7f9), XdB(0x009b5247), XdB(0x00a56a41), XdB(0x00b02a27), XdB(0x00bb9ce2), XdB(0x00c7ce12), XdB(0x00d4ca17), XdB(0x00e29e20), XdB(0x00f15835), XdB(0x0101074b), XdB(0x0111bb4e), XdB(0x01238531), XdB(0x01367704), XdB(0x014aa402), XdB(0x016020a7), XdB(0x017702c3), XdB(0x018f6190), XdB(0x01a955cb), XdB(0x01c4f9cf), XdB(0x01e269a8), XdB(0x0201c33b), XdB(0x0223265a), XdB(0x0246b4ea), XdB(0x026c9302), XdB(0x0294e716), XdB(0x02bfda13), XdB(0x02ed9793), XdB(0x031e4e09), XdB(0x03522ee4), XdB(0x03896ed0), XdB(0x03c445e2), XdB(0x0402efd6), XdB(0x0445ac4b), XdB(0x048cbefc), XdB(0x04d87013), XdB(0x05290c67), XdB(0x057ee5ca), XdB(0x05da5364), XdB(0x063bb204), XdB(0x06a36485), XdB(0x0711d42b), XdB(0x0787710e), XdB(0x0804b299), XdB(0x088a17ef), XdB(0x0918287e), XdB(0x09af747c), XdB(0x0a50957e), XdB(0x0afc2f19), XdB(0x0bb2ef7f), XdB(0x0c759034), XdB(0x0d44d6ca), XdB(0x0e2195bc), XdB(0x0f0cad0d), XdB(0x10070b62), XdB(0x1111aeea), XdB(0x122da66c), XdB(0x135c120f), XdB(0x149e24d9), XdB(0x15f525b1), XdB(0x176270e3), XdB(0x18e7794b), XdB(0x1a85c9ae), XdB(0x1c3f06d1), XdB(0x1e14f07d), XdB(0x200963d7), XdB(0x221e5ccd), XdB(0x2455f870), XdB(0x26b2770b), XdB(0x29363e2b), XdB(0x2be3db5c), XdB(0x2ebe06b6), XdB(0x31c7a55b), XdB(0x3503ccd4), XdB(0x3875c5aa), XdB(0x3c210f44), XdB(0x4009632b), XdB(0x4432b8cf), XdB(0x48a149bc), XdB(0x4d59959e), XdB(0x52606733), XdB(0x57bad899), XdB(0x5d6e593a), XdB(0x6380b298), XdB(0x69f80e9a), XdB(0x70dafda8), XdB(0x78307d76), XdB(0x7fffffff), }; static void render_line(int n, int x0,int x1,int y0,int y1,ogg_int32_t *d){ int dy=y1-y0; int adx=x1-x0; int ady=abs(dy); int base=dy/adx; int sy=(dy<0?base-1:base+1); int x=x0; int y=y0; int err=0; if(n>x1)n=x1; ady-=abs(base*adx); if(x=adx){ err-=adx; y+=sy; }else{ y+=base; } d[x]= MULT31_SHIFT15(d[x],FLOOR_fromdB_LOOKUP[y]); } } static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; vorbis_info_floor1 *info=look->vi; codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; int i,j,k; codebook *books=ci->fullbooks; /* unpack wrapped/predicted values from stream */ if(oggpack_read(&vb->opb,1)==1){ int *fit_value=(int *)_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value)); fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); /* partition by partition */ /* partition by partition */ for(i=0,j=2;ipartitions;i++){ int classv=info->partitionclass[i]; int cdim=info->class_dim[classv]; int csubbits=info->class_subs[classv]; int csub=1<class_book[classv],&vb->opb); if(cval==-1)goto eop; } for(k=0;kclass_subbook[classv][cval&(csub-1)]; cval>>=csubbits; if(book>=0){ if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1) goto eop; }else{ fit_value[j+k]=0; } } j+=cdim; } /* unwrap positive values and reconsitute via linear interpolation */ for(i=2;iposts;i++){ int predicted=render_point(info->postlist[look->loneighbor[i-2]], info->postlist[look->hineighbor[i-2]], fit_value[look->loneighbor[i-2]], fit_value[look->hineighbor[i-2]], info->postlist[i]); int hiroom=look->quant_q-predicted; int loroom=predicted; int room=(hiroom=room){ if(hiroom>loroom){ val = val-loroom; }else{ val = -1-(val-hiroom); } }else{ if(val&1){ val= -((val+1)>>1); }else{ val>>=1; } } fit_value[i]=(val+predicted)&0x7fff;; fit_value[look->loneighbor[i-2]]&=0x7fff; fit_value[look->hineighbor[i-2]]&=0x7fff; }else{ fit_value[i]=predicted|0x8000; } } return(fit_value); } eop: return(NULL); } static int floor1_inverse2(vorbis_block *vb,vorbis_look_floor *in,void *memo, ogg_int32_t *out){ vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; vorbis_info_floor1 *info=look->vi; codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; int n=ci->blocksizes[vb->W]/2; int j; if(memo){ /* render the lines */ int *fit_value=(int *)memo; int hx=0; int lx=0; int ly=fit_value[0]*info->mult; /* guard lookup against out-of-range values */ ly=(ly<0?0:ly>255?255:ly); for(j=1;jposts;j++){ int current=look->forward_index[j]; int hy=fit_value[current]&0x7fff; if(hy==fit_value[current]){ hx=info->postlist[current]; hy*=info->mult; /* guard lookup against out-of-range values */ hy=(hy<0?0:hy>255?255:hy); render_line(n,lx,hx,ly,hy,out); lx=hx; ly=hy; } } for(j=hx;j #include #include #include "ogg.h" #include "misc.h" #include "ivorbiscodec.h" #include "codebook.h" #include "tremor_shared.h" /**** pack/unpack helpers ******************************************/ /* 32 bit float (not IEEE; nonnormalized mantissa + biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm Why not IEEE? It's just not that important here. */ #define VQ_FEXP 10 #define VQ_FMAN 21 #define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */ static ogg_int32_t _float32_unpack(long val,int *point){ long mant=val&0x1fffff; int sign=val&0x80000000; long exp =(val&0x7fe00000L)>>VQ_FMAN; exp-=(VQ_FMAN-1)+VQ_FEXP_BIAS; if(mant){ while(!(mant&0x40000000)){ mant<<=1; exp-=1; } if(sign)mant= -mant; }else{ sign=0; exp=-9999; } *point=exp; return mant; } /* given a list of word lengths, generate a list of codewords. Works for length ordered or unordered, always assigns the lowest valued codewords first. Extended to handle unused entries (length 0) */ ogg_uint32_t *_make_words(long *l,long n,long sparsecount){ long i,j,count=0; ogg_uint32_t marker[33]; ogg_uint32_t *r=(ogg_uint32_t *)_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r)); memset(marker,0,sizeof(marker)); for(i=0;i0){ ogg_uint32_t entry=marker[length]; /* when we claim a node for an entry, we also claim the nodes below it (pruning off the imagined tree that may have dangled from it) as well as blocking the use of any nodes directly above for leaves */ /* update ourself */ if(length<32 && (entry>>length)){ /* error condition; the lengths must specify an overpopulated tree */ _ogg_free(r); return(NULL); } r[count++]=entry; /* Look to see if the next shorter marker points to the node above. if so, update it and repeat. */ { for(j=length;j>0;j--){ if(marker[j]&1){ /* have to jump branches */ if(j==1) marker[1]++; else marker[j]=marker[j-1]<<1; break; /* invariant says next upper marker would already have been moved if it was on the same path */ } marker[j]++; } } /* prune the tree; the implicit invariant says all the longer markers were dangling from our just-taken node. Dangle them from our *new* node. */ for(j=length+1;j<33;j++) if((marker[j]>>1) == entry){ entry=marker[j]; marker[j]=marker[j-1]<<1; }else break; }else if(sparsecount==0)count++; } /* sanity check the huffman tree; an underpopulated tree must be rejected. The only exception is the one-node pseudo-nil tree, which appears to be underpopulated because the tree doesn't really exist; there's only one possible 'codeword' or zero bits, but the above tree-gen code doesn't mark that. */ if(sparsecount != 1){ for(i=1;i<33;i++) if(marker[i] & (0xffffffffUL>>(32-i))){ _ogg_free(r); return(NULL); } } /* bitreverse the words because our bitwise packer/unpacker is LSb endian */ for(i=0,count=0;i>j)&1; } if(sparsecount){ if(l[i]) r[count++]=temp; }else r[count++]=temp; } return(r); } /* there might be a straightforward one-line way to do the below that's portable and totally safe against roundoff, but I haven't thought of it. Therefore, we opt on the side of caution */ long _book_maptype1_quantvals(const static_codebook *b){ /* get us a starting hint, we'll polish it below */ int bits= ilog(b->entries); int vals=b->entries>>((bits-1)*(b->dim-1)/b->dim); while(1){ long acc=1; long acc1=1; int i; for(i=0;idim;i++){ acc*=vals; acc1*=vals+1; } if(acc<=b->entries && acc1>b->entries){ return(vals); }else{ if(acc>b->entries){ vals--; }else{ vals++; } } } } /* different than what _book_unquantize does for mainline: we repack the book in a fixed point format that shares the same binary point. Upon first use, we can shift point if needed */ /* we need to deal with two map types: in map type 1, the values are generated algorithmically (each column of the vector counts through the values in the quant vector). in map type 2, all the values came in in an explicit list. Both value lists must be unpacked */ ogg_int32_t *_book_unquantize(const static_codebook *b,int n,int *sparsemap, int *maxpoint){ long j,k,count=0; if(b->maptype==1 || b->maptype==2){ int quantvals; int minpoint,delpoint; ogg_int32_t mindel=_float32_unpack(b->q_min,&minpoint); ogg_int32_t delta=_float32_unpack(b->q_delta,&delpoint); ogg_int32_t *r=(ogg_int32_t *)_ogg_calloc(n*b->dim,sizeof(*r)); int *rp=(int *)_ogg_calloc(n*b->dim,sizeof(*rp)); *maxpoint=minpoint; /* maptype 1 and 2 both use a quantized value vector, but different sizes */ switch(b->maptype){ case 1: /* most of the time, entries%dimensions == 0, but we need to be well defined. We define that the possible vales at each scalar is values == entries/dim. If entries%dim != 0, we'll have 'too few' values (values*dimentries;j++){ if((sparsemap && b->lengthlist[j]) || !sparsemap){ ogg_int32_t last=0; int lastpoint=0; int indexdiv=1; for(k=0;kdim;k++){ int index= (j/indexdiv)%quantvals; int point=0; int val=VFLOAT_MULTI(delta,delpoint, abs(b->quantlist[index]),&point); val=VFLOAT_ADD(mindel,minpoint,val,point,&point); val=VFLOAT_ADD(last,lastpoint,val,point,&point); if(b->q_sequencep){ last=val; lastpoint=point; } if(sparsemap){ r[sparsemap[count]*b->dim+k]=val; rp[sparsemap[count]*b->dim+k]=point; }else{ r[count*b->dim+k]=val; rp[count*b->dim+k]=point; } if(*maxpointentries;j++){ if((sparsemap && b->lengthlist[j]) || !sparsemap){ ogg_int32_t last=0; int lastpoint=0; for(k=0;kdim;k++){ int point=0; int val=VFLOAT_MULTI(delta,delpoint, abs(b->quantlist[j*b->dim+k]),&point); val=VFLOAT_ADD(mindel,minpoint,val,point,&point); val=VFLOAT_ADD(last,lastpoint,val,point,&point); if(b->q_sequencep){ last=val; lastpoint=point; } if(sparsemap){ r[sparsemap[count]*b->dim+k]=val; rp[sparsemap[count]*b->dim+k]=point; }else{ r[count*b->dim+k]=val; rp[count*b->dim+k]=point; } if(*maxpointdim;j++) if(rp[j]<*maxpoint) r[j]>>=*maxpoint-rp[j]; _ogg_free(rp); return(r); } return(NULL); } void vorbis_staticbook_destroy(static_codebook *b){ if(b->quantlist)_ogg_free(b->quantlist); if(b->lengthlist)_ogg_free(b->lengthlist); memset(b,0,sizeof(*b)); _ogg_free(b); } void vorbis_book_clear(codebook *b){ /* static book is not cleared; we're likely called on the lookup and the static codebook belongs to the info struct */ if(b->valuelist)_ogg_free(b->valuelist); if(b->codelist)_ogg_free(b->codelist); if(b->dec_index)_ogg_free(b->dec_index); if(b->dec_codelengths)_ogg_free(b->dec_codelengths); if(b->dec_firsttable)_ogg_free(b->dec_firsttable); memset(b,0,sizeof(*b)); } static int sort32a(const void *a,const void *b){ return (**(ogg_uint32_t **)a>**(ogg_uint32_t **)b)- (**(ogg_uint32_t **)a<**(ogg_uint32_t **)b); } /* decode codebook arrangement is more heavily optimized than encode */ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ int i,j,n=0,tabn; int *sortindex; memset(c,0,sizeof(*c)); /* count actually used entries */ for(i=0;ientries;i++) if(s->lengthlist[i]>0) n++; c->entries=s->entries; c->used_entries=n; c->dim=s->dim; if(n>0){ /* two different remappings go on here. First, we collapse the likely sparse codebook down only to actually represented values/words. This collapsing needs to be indexed as map-valueless books are used to encode original entry positions as integers. Second, we reorder all vectors, including the entry index above, by sorted bitreversed codeword to allow treeless decode. */ /* perform sort */ ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries); ogg_uint32_t **codep=(ogg_uint32_t **)alloca(sizeof(*codep)*n); if(codes==NULL)goto err_out; for(i=0;icodelist=(ogg_uint32_t *)_ogg_malloc(n*sizeof(*c->codelist)); /* the index is a reverse index */ for(i=0;icodelist[sortindex[i]]=codes[i]; _ogg_free(codes); c->valuelist=_book_unquantize(s,n,sortindex,&c->binarypoint); c->dec_index=(int *)_ogg_malloc(n*sizeof(*c->dec_index)); for(n=0,i=0;ientries;i++) if(s->lengthlist[i]>0) c->dec_index[sortindex[n++]]=i; c->dec_codelengths=(char *)_ogg_malloc(n*sizeof(*c->dec_codelengths)); for(n=0,i=0;ientries;i++) if(s->lengthlist[i]>0) c->dec_codelengths[sortindex[n++]]=s->lengthlist[i]; c->dec_firsttablen= ilog(c->used_entries)-4; /* this is magic */ if(c->dec_firsttablen<5)c->dec_firsttablen=5; if(c->dec_firsttablen>8)c->dec_firsttablen=8; tabn=1<dec_firsttablen; c->dec_firsttable=(ogg_uint32_t *)_ogg_calloc(tabn,sizeof(*c->dec_firsttable)); c->dec_maxlength=0; for(i=0;idec_maxlengthdec_codelengths[i]) c->dec_maxlength=c->dec_codelengths[i]; if(c->dec_codelengths[i]<=c->dec_firsttablen){ ogg_uint32_t orig=bitreverse(c->codelist[i]); for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++) c->dec_firsttable[orig|(j<dec_codelengths[i])]=i+1; } } /* now fill in 'unused' entries in the firsttable with hi/lo search hints for the non-direct-hits */ { ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen); long lo=0,hi=0; for(i=0;idec_firsttablen); if(c->dec_firsttable[bitreverse(word)]==0){ while((lo+1)codelist[lo+1]<=word)lo++; while( hi=(c->codelist[hi]&mask))hi++; /* we only actually have 15 bits per hint to play with here. In order to overflow gracefully (nothing breaks, efficiency just drops), encode as the difference from the extremes. */ { unsigned long loval=lo; unsigned long hival=n-hi; if(loval>0x7fff)loval=0x7fff; if(hival>0x7fff)hival=0x7fff; c->dec_firsttable[bitreverse(word)]= 0x80000000UL | (loval<<15) | hival; } } } } } return(0); err_out: vorbis_book_clear(c); return(-1); } mednafen/cdrom/000700 001750 001750 00000000000 12702525066 014554 5ustar00sergiosergio000000 000000 mednafen/settings-driver.h000664 001750 001750 00000000541 12611054044 016756 0ustar00sergiosergio000000 000000 #ifndef _MDFN_SETTINGS_DRIVER_H #define _MDFN_SETTINGS_DRIVER_H #include "settings-common.h" bool MDFNI_SetSetting(const char *name, const char *value, bool NetplayOverride = FALSE); bool MDFNI_SetSettingB(const char *name, bool value); bool MDFNI_SetSettingUI(const char *name, uint64_t value); bool MDFNI_DumpSettingsDef(const char *path); #endif mednafen/MemoryStream.cpp000664 001750 001750 00000011135 12611054044 016605 0ustar00sergiosergio000000 000000 #include #include "MemoryStream.h" #include "msvc_compat.h" /* TODO: Write and Seek expansion that fail should not corrupt the state. Copy and assignment constructor fixes. */ // TODO 128-bit integers for range checking? MemoryStream::MemoryStream() : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0) { data_buffer_size = 0; data_buffer_alloced = 64; if(!(data_buffer = (uint8*)realloc(data_buffer, (size_t)data_buffer_alloced))) throw MDFN_Error(ErrnoHolder(errno)); } MemoryStream::MemoryStream(uint64 size_hint) : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0) { data_buffer_size = 0; data_buffer_alloced = (size_hint > SIZE_MAX) ? SIZE_MAX : size_hint; if(!(data_buffer = (uint8*)realloc(data_buffer, (size_t)data_buffer_alloced))) throw MDFN_Error(ErrnoHolder(errno)); } MemoryStream::MemoryStream(Stream *stream) : data_buffer(NULL), data_buffer_size(0), data_buffer_alloced(0), position(0) { if((position = stream->tell()) != 0) stream->seek(0, SEEK_SET); data_buffer_size = stream->size(); data_buffer_alloced = data_buffer_size; if(!(data_buffer = (uint8*)realloc(data_buffer, (size_t)data_buffer_alloced))) throw MDFN_Error(ErrnoHolder(errno)); stream->read(data_buffer, data_buffer_size); stream->close(); delete stream; } MemoryStream::MemoryStream(const MemoryStream *zs) { data_buffer_size = zs->data_buffer_size; data_buffer_alloced = zs->data_buffer_alloced; if(!(data_buffer = (uint8*)malloc((size_t)data_buffer_alloced))) throw MDFN_Error(ErrnoHolder(errno)); memcpy(data_buffer, zs->data_buffer, (size_t)data_buffer_size); position = zs->position; } MemoryStream::~MemoryStream() { if(data_buffer) { free(data_buffer); data_buffer = NULL; } } uint64 MemoryStream::attributes(void) { return (ATTRIBUTE_READABLE | ATTRIBUTE_WRITEABLE | ATTRIBUTE_SEEKABLE); } uint8 *MemoryStream::map(void) { return data_buffer; } void MemoryStream::unmap(void) { } INLINE void MemoryStream::grow_if_necessary(uint64 new_required_size) { if(new_required_size > data_buffer_size) { if(new_required_size > data_buffer_alloced) { uint64 new_required_alloced = round_up_pow2(new_required_size); uint8 *new_data_buffer; // first condition will happen at new_required_size > (UINT64_C(1) << 63) due to round_up_pow2() "wrapping". // second condition can occur when running on a 32-bit system. if(new_required_alloced < new_required_size || new_required_alloced > SIZE_MAX) new_required_alloced = SIZE_MAX; // If constrained alloc size isn't enough, throw an out-of-memory/address-space type error. if(new_required_alloced < new_required_size) throw MDFN_Error(ErrnoHolder(ENOMEM)); if(!(new_data_buffer = (uint8*)realloc(data_buffer, (size_t)new_required_alloced))) throw MDFN_Error(ErrnoHolder(errno)); // // Assign all in one go after the realloc() so we don't leave our object in an inconsistent state if the realloc() fails. // data_buffer = new_data_buffer; data_buffer_size = new_required_size; data_buffer_alloced = new_required_alloced; } else data_buffer_size = new_required_size; } } uint64 MemoryStream::read(void *data, uint64 count, bool error_on_eos) { if(count > data_buffer_size) { count = data_buffer_size; } if((uint64)position > (data_buffer_size - count)) { count = data_buffer_size - position; } memmove(data, &data_buffer[position], (size_t)count); position += count; return count; } void MemoryStream::write(const void *data, uint64 count) { uint64 nrs = position + count; if(nrs < position) throw MDFN_Error(ErrnoHolder(EFBIG)); grow_if_necessary(nrs); memmove(&data_buffer[position], data, (size_t)count); position += count; } void MemoryStream::seek(int64 offset, int whence) { int64 new_position; switch(whence) { case SEEK_SET: new_position = offset; break; case SEEK_CUR: new_position = position + offset; break; case SEEK_END: new_position = data_buffer_size + offset; break; } if(new_position < 0) throw MDFN_Error(ErrnoHolder(EINVAL)); else grow_if_necessary(new_position); position = new_position; } int64 MemoryStream::tell(void) { return position; } int64 MemoryStream::size(void) { return data_buffer_size; } void MemoryStream::close(void) { } int MemoryStream::get_line(std::string &str) { str.clear(); // or str.resize(0)?? while(position < data_buffer_size) { uint8 c = data_buffer[position++]; if(c == '\r' || c == '\n' || c == 0) return(c); str.push_back(c); // Should be faster than str.append(1, c) } return(-1); } libretro-common/file/000700 001750 001750 00000000000 12702525066 015722 5ustar00sergiosergio000000 000000 mednafen/psx/mdec.cpp000664 001750 001750 00000046370 12611054044 015714 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ /* MDEC_READ_FIFO(tfr) vs InCounter vs MDEC_DMACanRead() is a bit fragile right now. Actually, the entire horrible state machine monstrosity is fragile. TODO: OutFIFOReady, so <16bpp works right. TODO CODE: bool InFIFOReady; if(InFIFO.CanWrite()) { InFIFO.Write(V); if(InCommand) { if(InCounter != 0xFFFF) { InCounter--; // This condition when InFIFO.CanWrite() != 0 is a bit buggy on real hardware, decoding loop *seems* to be reading too // much and pulling garbage from the FIFO. if(InCounter == 0xFFFF) InFIFOReady = true; } if(InFIFO.CanWrite() == 0) InFIFOReady = true; } } */ // Good test-case games: // Dragon Knight 4(bad disc?) // Final Fantasy 7 intro movie. // GameShark Version 4.0 intro movie; (clever) abuse of DMA channel 0. // SimCity 2000 startup. #include "psx.h" #include "mdec.h" #include "../masmem.h" #include "FastFIFO.h" #include #if defined(__SSE2__) #include #include #endif #if defined(ARCH_POWERPC_ALTIVEC) && defined(HAVE_ALTIVEC_H) #include #endif static int32 ClockCounter; static unsigned MDRPhase; static FastFIFO InFIFO; static FastFIFO OutFIFO; static int8 block_y[8][8]; static int8 block_cb[8][8]; // [y >> 1][x >> 1] static int8 block_cr[8][8]; // [y >> 1][x >> 1] static uint32 Control; static uint32 Command; static bool InCommand; static uint8 QMatrix[2][64]; static uint32 QMIndex; static int16 IDCTMatrix[64] MDFN_ALIGN(16); static uint32 IDCTMIndex; static uint8 QScale; static int16 Coeff[64] MDFN_ALIGN(16); static uint32 CoeffIndex; static uint32 DecodeWB; static union { uint32 pix32[48]; uint16 pix16[96]; uint8 pix8[192]; } PixelBuffer; static uint32 PixelBufferReadOffset; static uint32 PixelBufferCount32; static uint16 InCounter; static uint8 RAMOffsetY; static uint8 RAMOffsetCounter; static uint8 RAMOffsetWWS; static const uint8 ZigZag[64] = { 0x00, 0x08, 0x01, 0x02, 0x09, 0x10, 0x18, 0x11, 0x0a, 0x03, 0x04, 0x0b, 0x12, 0x19, 0x20, 0x28, 0x21, 0x1a, 0x13, 0x0c, 0x05, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29, 0x30, 0x38, 0x31, 0x2a, 0x23, 0x1c, 0x15, 0x0e, 0x07, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39, 0x3a, 0x33, 0x2c, 0x25, 0x1e, 0x17, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x3c, 0x35, 0x2e, 0x27, 0x2f, 0x36, 0x3d, 0x3e, 0x37, 0x3f, }; void MDEC_Power(void) { ClockCounter = 0; MDRPhase = 0; InFIFO.Flush(); OutFIFO.Flush(); memset(block_y, 0, sizeof(block_y)); memset(block_cb, 0, sizeof(block_cb)); memset(block_cr, 0, sizeof(block_cr)); Control = 0; Command = 0; InCommand = false; memset(QMatrix, 0, sizeof(QMatrix)); QMIndex = 0; memset(IDCTMatrix, 0, sizeof(IDCTMatrix)); IDCTMIndex = 0; QScale = 0; memset(Coeff, 0, sizeof(Coeff)); CoeffIndex = 0; DecodeWB = 0; memset(PixelBuffer.pix32, 0, sizeof(PixelBuffer.pix32)); PixelBufferReadOffset = 0; PixelBufferCount32 = 0; InCounter = 0; RAMOffsetY = 0; RAMOffsetCounter = 0; RAMOffsetWWS = 0; } int MDEC_StateAction(StateMem *sm, int load, int data_only) { SFORMAT StateRegs[] = { SFVAR(ClockCounter), SFVAR(MDRPhase), #define SFFIFO32(fifoobj) SFARRAY32(&fifoobj.data[0], sizeof(fifoobj.data) / sizeof(fifoobj.data[0])), \ SFVAR(fifoobj.read_pos), \ SFVAR(fifoobj.write_pos), \ SFVAR(fifoobj.in_count) SFFIFO32(InFIFO), SFFIFO32(OutFIFO), #undef SFFIFO SFARRAY(&block_y[0][0], sizeof(block_y) / sizeof(block_y[0][0])), SFARRAY(&block_cb[0][0], sizeof(block_cb) / sizeof(block_cb[0][0])), SFARRAY(&block_cr[0][0], sizeof(block_cr) / sizeof(block_cr[0][0])), SFVAR(Control), SFVAR(Command), SFVAR(InCommand), SFARRAY(&QMatrix[0][0], sizeof(QMatrix) / sizeof(QMatrix[0][0])), SFVAR(QMIndex), SFARRAY16(&IDCTMatrix[0], sizeof(IDCTMatrix) / sizeof(IDCTMatrix[0])), SFVAR(IDCTMIndex), SFVAR(QScale), SFARRAY16(&Coeff[0], sizeof(Coeff) / sizeof(Coeff[0])), SFVAR(CoeffIndex), SFVAR(DecodeWB), SFARRAY32(&PixelBuffer.pix32[0], sizeof(PixelBuffer.pix32) / sizeof(PixelBuffer.pix32[0])), SFVAR(PixelBufferReadOffset), SFVAR(PixelBufferCount32), SFVAR(InCounter), SFVAR(RAMOffsetY), SFVAR(RAMOffsetCounter), SFVAR(RAMOffsetWWS), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "MDEC"); if(load) { InFIFO.SaveStatePostLoad(); OutFIFO.SaveStatePostLoad(); } return(ret); } static INLINE int8 Mask9ClampS8(int32 v) { v = sign_x_to_s32(9, v); if(v < -128) v = -128; if(v > 127) v = 127; return v; } template static void IDCT_1D_Multi(int16 *in_coeff, T *out_coeff) { #if defined(__SSE2__) { for(unsigned col = 0; col < 8; col++) { __m128i c = _mm_load_si128((__m128i *)&in_coeff[(col * 8)]); for(unsigned x = 0; x < 8; x++) { __m128i sum; __m128i m; int32 tmp[4] MDFN_ALIGN(16); m = _mm_load_si128((__m128i *)&IDCTMatrix[(x * 8)]); sum = _mm_madd_epi16(m, c); sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, (3 << 0) | (2 << 2) | (1 << 4) | (0 << 6))); sum = _mm_add_epi32(sum, _mm_shuffle_epi32(sum, (1 << 0) | (0 << 2))); //_mm_store_ss((float *)&tmp[0], (__m128)sum); _mm_store_si128((__m128i*)tmp, sum); if(sizeof(T) == 1) out_coeff[(col * 8) + x] = Mask9ClampS8((tmp[0] + 0x4000) >> 15); else out_coeff[(x * 8) + col] = (tmp[0] + 0x4000) >> 15; } } } #else for(unsigned col = 0; col < 8; col++) { for(unsigned x = 0; x < 8; x++) { int32 sum = 0; for(unsigned u = 0; u < 8; u++) { sum += (in_coeff[(col * 8) + u] * IDCTMatrix[(x * 8) + u]); } if(sizeof(T) == 1) out_coeff[(col * 8) + x] = Mask9ClampS8((sum + 0x4000) >> 15); else out_coeff[(x * 8) + col] = (sum + 0x4000) >> 15; } } #endif } static void IDCT(int16 *in_coeff, int8 *out_coeff) { int16 tmpbuf[64] MDFN_ALIGN(16); IDCT_1D_Multi(in_coeff, tmpbuf); IDCT_1D_Multi(tmpbuf, out_coeff); } static INLINE void YCbCr_to_RGB(const int8 y, const int8 cb, const int8 cr, int &r, int &g, int &b) { // The formula for green is still a bit off(precision/rounding issues when both cb and cr are non-zero). r = Mask9ClampS8(y + (((359 * cr) + 0x80) >> 8)); //g = Mask9ClampS8(y + (((-88 * cb) + (-183 * cr) + 0x80) >> 8)); g = Mask9ClampS8(y + ((((-88 * cb) &~ 0x1F) + ((-183 * cr) &~ 0x07) + 0x80) >> 8)); b = Mask9ClampS8(y + (((454 * cb) + 0x80) >> 8)); r ^= 0x80; g ^= 0x80; b ^= 0x80; } static INLINE uint16 RGB_to_RGB555(uint8 r, uint8 g, uint8 b) { r = (r + 4) >> 3; g = (g + 4) >> 3; b = (b + 4) >> 3; if(r > 0x1F) r = 0x1F; if(g > 0x1F) g = 0x1F; if(b > 0x1F) b = 0x1F; return((r << 0) | (g << 5) | (b << 10)); } static void EncodeImage(const unsigned ybn) { //printf("ENCODE, %d\n", (Command & 0x08000000) ? 256 : 384); PixelBufferCount32 = 0; switch((Command >> 27) & 0x3) { case 0: // 4bpp { const uint8 us_xor = (Command & (1U << 26)) ? 0x00 : 0x88; uint8* pix_out = PixelBuffer.pix8; for(int y = 0; y < 8; y++) { for(int x = 0; x < 8; x += 2) { uint8 p0 = std::min(127, block_y[y][x + 0] + 8); uint8 p1 = std::min(127, block_y[y][x + 1] + 8); *pix_out = ((p0 >> 4) | (p1 & 0xF0)) ^ us_xor; pix_out++; } } PixelBufferCount32 = 8; } break; case 1: // 8bpp { const uint8 us_xor = (Command & (1U << 26)) ? 0x00 : 0x80; uint8* pix_out = PixelBuffer.pix8; for(int y = 0; y < 8; y++) { for(int x = 0; x < 8; x++) { *pix_out = (uint8)block_y[y][x] ^ us_xor; pix_out++; } } PixelBufferCount32 = 16; } break; case 2: // 24bpp { const uint8 rgb_xor = (Command & (1U << 26)) ? 0x80 : 0x00; uint8* pix_out = PixelBuffer.pix8; for(int y = 0; y < 8; y++) { const int8* by = &block_y[y][0]; const int8* cb = &block_cb[(y >> 1) | ((ybn & 2) << 1)][(ybn & 1) << 2]; const int8* cr = &block_cr[(y >> 1) | ((ybn & 2) << 1)][(ybn & 1) << 2]; for(int x = 0; x < 8; x++) { int r, g, b; YCbCr_to_RGB(by[x], cb[x >> 1], cr[x >> 1], r, g, b); pix_out[0] = r ^ rgb_xor; pix_out[1] = g ^ rgb_xor; pix_out[2] = b ^ rgb_xor; pix_out += 3; } } PixelBufferCount32 = 48; } break; case 3: // 16bpp { uint16 pixel_xor = ((Command & 0x02000000) ? 0x8000 : 0x0000) | ((Command & (1U << 26)) ? 0x4210 : 0x0000); uint16* pix_out = PixelBuffer.pix16; for(int y = 0; y < 8; y++) { const int8* by = &block_y[y][0]; const int8* cb = &block_cb[(y >> 1) | ((ybn & 2) << 1)][(ybn & 1) << 2]; const int8* cr = &block_cr[(y >> 1) | ((ybn & 2) << 1)][(ybn & 1) << 2]; for(int x = 0; x < 8; x++) { int r, g, b; YCbCr_to_RGB(by[x], cb[x >> 1], cr[x >> 1], r, g, b); StoreU16_LE(pix_out, pixel_xor ^ RGB_to_RGB555(r, g, b)); pix_out++; } } PixelBufferCount32 = 32; } break; } } static INLINE void WriteImageData(uint16 V, int32* eat_cycles) { const uint32 qmw = (bool)(DecodeWB < 2); //printf("MDEC DMA SubWrite: %04x, %d\n", V, CoeffIndex); if(!CoeffIndex) { if(V == 0xFE00) { //printf("FE00 @ %u\n", DecodeWB); return; } QScale = V >> 10; { int q = QMatrix[qmw][0]; // No QScale here! int ci = sign_10_to_s16(V & 0x3FF); int tmp; if(q != 0) tmp = (int32)((uint32)(ci * q) << 4) + (ci ? ((ci < 0) ? 8 : -8) : 0); else tmp = (uint32)(ci * 2) << 4; // Not sure if it should be 0x3FFF or 0x3FF0 or maybe 0x3FF8? Coeff[ZigZag[0]] = std::min(0x3FFF, std::max(-0x4000, tmp)); CoeffIndex++; } } else { if(V == 0xFE00) { while(CoeffIndex < 64) Coeff[ZigZag[CoeffIndex++]] = 0; } else { uint32 rlcount = V >> 10; for(uint32 i = 0; i < rlcount && CoeffIndex < 64; i++) { Coeff[ZigZag[CoeffIndex]] = 0; CoeffIndex++; } if(CoeffIndex < 64) { int q = QScale * QMatrix[qmw][CoeffIndex]; int ci = sign_10_to_s16(V & 0x3FF); int tmp; if(q != 0) tmp = (int32)((uint32)((ci * q) >> 3) << 4) + (ci ? ((ci < 0) ? 8 : -8) : 0); else tmp = (uint32)(ci * 2) << 4; // Not sure if it should be 0x3FFF or 0x3FF0 or maybe 0x3FF8? Coeff[ZigZag[CoeffIndex]] = std::min(0x3FFF, std::max(-0x4000, tmp)); CoeffIndex++; } } } if(CoeffIndex == 64) { CoeffIndex = 0; //printf("Block %d finished\n", DecodeWB); switch(DecodeWB) { case 0: IDCT(Coeff, &block_cr[0][0]); break; case 1: IDCT(Coeff, &block_cb[0][0]); break; case 2: case 3: case 4: case 5: IDCT(Coeff, &block_y[0][0]); break; } // Timing in the actual PS1 MDEC is complex due to (apparent) pipelining, but the average when decoding a large number of blocks is // about 512. We'll go with a lower value here to be conservative due to timing granularity and other timing deficiencies in Mednafen. BUT, don't // go lower than 460, or Parasite Eve 2's 3D models will stutter like crazy during FMV-background sequences. // *eat_cycles += 474; if(DecodeWB >= 2) EncodeImage((DecodeWB + 4) % 6); DecodeWB++; if(DecodeWB == (((Command >> 27) & 2) ? 6 : 3)) DecodeWB = ((Command >> 27) & 2) ? 0 : 2; } } void MDEC_Run(int32 clocks) { static const unsigned MDRPhaseBias = 0 + 1; //MDFN_DispMessage("%u", OutFIFO.CanRead()); ClockCounter += clocks; if(ClockCounter > 128) { //if(MDRPhase != 0) // printf("SNORT: %d\n", ClockCounter); ClockCounter = 128; } switch(MDRPhase + MDRPhaseBias) { for(;;) { InCommand = false; { { case 1: if(!(InFIFO.CanRead())) { MDRPhase = 2 - MDRPhaseBias - 1; return; } }; Command = InFIFO.Read(); }; InCommand = true; { ClockCounter -= (1); { case 3: if(!(ClockCounter > 0)) { MDRPhase = 4 - MDRPhaseBias - 1; return; } }; }; //printf("****************** Command: %08x, %02x\n", Command, Command >> 29); // // // if(((Command >> 29) & 0x7) == 1) { InCounter = Command & 0xFFFF; OutFIFO.Flush(); //OutBuffer.Flush(); PixelBufferCount32 = 0; CoeffIndex = 0; if((Command >> 27) & 2) DecodeWB = 0; else DecodeWB = 2; switch((Command >> 27) & 0x3) { case 0: case 1: RAMOffsetWWS = 0; break; case 2: RAMOffsetWWS = 6; break; case 3: RAMOffsetWWS = 4; break; } RAMOffsetY = 0; RAMOffsetCounter = RAMOffsetWWS; InCounter--; do { uint32 tfr; int32 need_eat; // = 0; { { case 5: if(!(InFIFO.CanRead())) { MDRPhase = 6 - MDRPhaseBias - 1; return; } }; tfr = InFIFO.Read(); }; InCounter--; // printf("KA: %04x %08x\n", InCounter, tfr); need_eat = 0; PixelBufferCount32 = 0; WriteImageData(tfr, &need_eat); WriteImageData(tfr >> 16, &need_eat); { ClockCounter -= (need_eat); { case 7: if(!(ClockCounter > 0)) { MDRPhase = 8 - MDRPhaseBias - 1; return; } }; }; PixelBufferReadOffset = 0; while(PixelBufferReadOffset != PixelBufferCount32) { { { case 9: if(!(OutFIFO.CanWrite())) { MDRPhase = 10 - MDRPhaseBias - 1; return; } }; OutFIFO.Write(LoadU32_LE(&PixelBuffer.pix32[PixelBufferReadOffset++])); }; } } while(InCounter != 0xFFFF); } // // // else if(((Command >> 29) & 0x7) == 2) { QMIndex = 0; InCounter = 0x10 + ((Command & 0x1) ? 0x10 : 0x00); InCounter--; do { uint32 tfr; { { case 11: if(!(InFIFO.CanRead())) { MDRPhase = 12 - MDRPhaseBias - 1; return; } }; tfr = InFIFO.Read(); }; InCounter--; //printf("KA: %04x %08x\n", InCounter, tfr); for(int i = 0; i < 4; i++) { QMatrix[QMIndex >> 6][QMIndex & 0x3F] = (uint8)tfr; QMIndex = (QMIndex + 1) & 0x7F; tfr >>= 8; } } while(InCounter != 0xFFFF); } // // // else if(((Command >> 29) & 0x7) == 3) { IDCTMIndex = 0; InCounter = 0x20; InCounter--; do { uint32 tfr; { { case 13: if(!(InFIFO.CanRead())) { MDRPhase = 14 - MDRPhaseBias - 1; return; } }; tfr = InFIFO.Read(); }; InCounter--; for(unsigned i = 0; i < 2; i++) { IDCTMatrix[((IDCTMIndex & 0x7) << 3) | ((IDCTMIndex >> 3) & 0x7)] = (int16)(tfr & 0xFFFF) >> 3; IDCTMIndex = (IDCTMIndex + 1) & 0x3F; tfr >>= 16; } } while(InCounter != 0xFFFF); } else { InCounter = Command & 0xFFFF; } } // end for(;;) } } void MDEC_DMAWrite(uint32 V) { if(!InFIFO.CanWrite()) return; InFIFO.Write(V); MDEC_Run(0); } uint32 MDEC_DMARead(uint32* offs) { uint32 V = 0; *offs = 0; if(MDFN_LIKELY(OutFIFO.CanRead())) { V = OutFIFO.Read(); *offs = (RAMOffsetY & 0x7) * RAMOffsetWWS; if(RAMOffsetY & 0x08) { *offs = (*offs - RAMOffsetWWS*7); } RAMOffsetCounter--; if(!RAMOffsetCounter) { RAMOffsetCounter = RAMOffsetWWS; RAMOffsetY++; } MDEC_Run(0); } return(V); } bool MDEC_DMACanWrite(void) { return((InFIFO.CanWrite() >= 0x20) && (Control & (1U << 30)) && InCommand && InCounter != 0xFFFF); } bool MDEC_DMACanRead(void) { return((OutFIFO.CanRead() >= 0x20) && (Control & (1U << 29))); } void MDEC_Write(const int32_t timestamp, uint32 A, uint32 V) { //PSX_WARNING("[MDEC] Write: 0x%08x 0x%08x, %d --- %u %u", A, V, timestamp, InFIFO.CanRead(), OutFIFO.CanRead()); if(A & 4) { if(V & 0x80000000) // Reset? { MDRPhase = 0; InCounter = 0; Command = 0; InCommand = false; PixelBufferCount32 = 0; ClockCounter = 0; QMIndex = 0; IDCTMIndex = 0; QScale = 0; memset(Coeff, 0, sizeof(Coeff)); CoeffIndex = 0; DecodeWB = 0; InFIFO.Flush(); OutFIFO.Flush(); } Control = V & 0x7FFFFFFF; } else { if(InFIFO.CanWrite()) { InFIFO.Write(V); if(!InCommand) { if(ClockCounter < 1) ClockCounter = 1; } MDEC_Run(0); } } } uint32 MDEC_Read(const int32_t timestamp, uint32 A) { uint32 ret = 0; if(A & 4) { ret = 0; ret |= (OutFIFO.CanRead() == 0) << 31; ret |= (InFIFO.CanWrite() == 0) << 30; ret |= InCommand << 29; ret |= MDEC_DMACanWrite() << 28; ret |= MDEC_DMACanRead() << 27; ret |= ((Command >> 25) & 0xF) << 23; // Needs refactoring elsewhere to work right: ret |= ((DecodeWB + 4) % 6) << 16; ret |= InCounter & 0xFFFF; } else { if(OutFIFO.CanRead()) ret = OutFIFO.Read(); } //PSX_WARNING("[MDEC] Read: 0x%08x 0x%08x -- %d %d", A, ret, InputBuffer.CanRead(), InCounter); return(ret); } mednafen/psx/dma.cpp000664 001750 001750 00000050001 12611054044 015527 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #include "psx.h" #include "mdec.h" #include "cdc.h" #include "spu.h" /* Notes: Channel 4(SPU): Write: Doesn't seem to work properly with CHCR=0x01000001 Hung when CHCR=0x11000601 Channel 6: DMA hangs if D28 of CHCR is 0? D1 did not have an apparent effect. */ enum { CH_MDEC_IN = 0, CH_MDEC_OUT = 1, CH_GPU = 2, CH_CDC = 3, CH_SPU = 4, CH_FIVE = 5, CH_OT = 6 }; static int32_t DMACycleCounter; static uint32_t DMAControl; static uint32_t DMAIntControl; static uint8_t DMAIntStatus; static bool IRQOut; struct Channel { uint32_t BaseAddr; uint32_t BlockControl; uint32_t ChanControl; uint32_t CurAddr; uint16_t WordCounter; int32_t ClockCounter; }; static Channel DMACH[7]; static int32_t lastts; static const char *PrettyChannelNames[7] = { "MDEC IN", "MDEC OUT", "GPU", "CDC", "SPU", "PIO", "OTC" }; void DMA_Init(void) { } void DMA_Kill(void) { } static INLINE void RecalcIRQOut(void) { bool irqo = (bool)DMAIntStatus; irqo &= (DMAIntControl >> 23) & 1; irqo |= (DMAIntControl >> 15) & 1; IRQOut = irqo; ::IRQ_Assert(IRQ_DMA, irqo); } void DMA_ResetTS(void) { lastts = 0; } void DMA_Power(void) { lastts = 0; memset(DMACH, 0, sizeof(DMACH)); DMACycleCounter = 128; DMAControl = 0; DMAIntControl = 0; DMAIntStatus = 0; RecalcIRQOut(); } static INLINE bool ChCan(const unsigned ch, const uint32_t CRModeCache) { switch(ch) { case CH_MDEC_IN: return(MDEC_DMACanWrite()); case CH_MDEC_OUT: return(MDEC_DMACanRead()); case CH_GPU: if(CRModeCache & 0x1) return(GPU->DMACanWrite()); case CH_CDC: case CH_SPU: return(true); case CH_FIVE: return(false); case CH_OT: return((bool)(DMACH[ch].ChanControl & (1U << 28))); } /* should not happen */ return false; } static void RecalcHalt(void) { bool Halt = false; unsigned ch, tmp; ch = 0; tmp = 0; for(ch = 0; ch < 7; ch++) { if(DMACH[ch].ChanControl & (1U << 24)) { if(!(DMACH[ch].ChanControl & (7U << 8))) { if(DMACH[ch].WordCounter > 0) { Halt = true; break; } } } } #if 0 if((DMACH[0].WordCounter || (DMACH[0].ChanControl & (1 << 24))) && (DMACH[0].ChanControl & 0x200) /*&& MDEC_DMACanWrite()*/) Halt = true; if((DMACH[1].WordCounter || (DMACH[1].ChanControl & (1 << 24))) && (DMACH[1].ChanControl & 0x200) && (DMACH[1].WordCounter || MDEC_DMACanRead())) Halt = true; if((DMACH[2].WordCounter || (DMACH[2].ChanControl & (1 << 24))) && (DMACH[2].ChanControl & 0x200) && ((DMACH[2].ChanControl & 0x1) && (DMACH[2].WordCounter || GPU->DMACanWrite()))) Halt = true; if((DMACH[3].WordCounter || (DMACH[3].ChanControl & (1 << 24))) && !(DMACH[3].ChanControl & 0x100)) Halt = true; if(DMACH[6].WordCounter || (DMACH[6].ChanControl & (1 << 24))) Halt = true; #endif //printf("Halt: %d\n", Halt); if(!Halt && (DMACH[2].ChanControl & (1U << 24)) && ((DMACH[2].ChanControl & 0x700) == 0x200) && ChCan(2, DMACH[2].ChanControl)) { tmp = DMACH[2].BlockControl & 0xFFFF; if(tmp > 0) tmp--; PSX_SetDMACycleSteal(tmp); } else PSX_SetDMACycleSteal(0); CPU->SetHalt(Halt); } static INLINE void ChRW(const unsigned ch, const uint32_t CRModeCache, uint32_t *V, uint32_t *offset) { unsigned extra_cyc_overhead = 0; switch(ch) { case CH_MDEC_IN: if(CRModeCache & 0x1) MDEC_DMAWrite(*V); else *V = 0; break; case CH_MDEC_OUT: if(CRModeCache & 0x1) { } else *V = MDEC_DMARead(offset); break; case CH_GPU: if(CRModeCache & 0x1) GPU->WriteDMA(*V); else *V = GPU->ReadDMA(); break; case CH_CDC: // 0x1f801018 affects CDC DMA timing. #if 0 if(CRModeCache & 0x100) // For CDC DMA(at least): When this bit is set, DMA controller doesn't appear to hog the (RAM?) bus. { if(CRModeCache & 0x00400000) // For CDC DMA(at least): When this bit is set, DMA controller appears to get even less bus time(or has a lower priority?) { DMACH[ch].ClockCounter -= 44 * 20 / 12; } else { DMACH[ch].ClockCounter -= 29 * 20 / 12; } } else { DMACH[ch].ClockCounter -= 23 * 20 / 12; // (23 + 1) = 24. (Though closer to 24.5 or 24.4 on average per tests on a PS1) } #endif if(CRModeCache & 0x1) { } else { extra_cyc_overhead = 8; // FIXME: Test. *V = CDC->DMARead(); // Note: Legend of Mana's opening movie is sensitive to DMA timing, including CDC. } break; case CH_SPU: // 0x1f801014 affects SPU DMA timing. // Wild conjecture about 0x1f801014: // // & 0x0000000F // & 0x000001E0 --- Used if (& 0x20000000) == 0? // & 0x00001000 --- Double total bus cycle time if value == 0? // & 0x0f000000 --- (value << 1) 33MHz cycles, bus cycle extension(added to 4?)? // & 0x20000000 --- // // // TODO?: SPU DMA will "complete" much faster if there's a mismatch between the CHCR read/write mode bit and the SPU control register DMA mode. // // // Investigate: SPU DMA doesn't seem to work right if the value written to 0x1F801DAA doesn't have the upper bit set to 1(0x8000) on a PS1. extra_cyc_overhead = 47; // Should be closer to 69, average, but actual timing is...complicated. if(CRModeCache & 0x1) SPU->WriteDMA(*V); else *V = SPU->ReadDMA(); break; case CH_FIVE: if(CRModeCache & 0x1) { } else { *V = 0; } break; case CH_OT: if(DMACH[ch].WordCounter == 1) *V = 0xFFFFFF; else *V = (DMACH[ch].CurAddr - 4) & 0x1FFFFF; break; } // GROSS APPROXIMATION, shoehorning multiple effects together, TODO separate(especially SPU and CDC) DMACH[ch].ClockCounter -= std::max(extra_cyc_overhead, (CRModeCache & 0x100) ? 7 : 0); } static INLINE void RunChannelI(const unsigned ch, const uint32_t CRModeCache, int32_t clocks) { } static INLINE void RunChannel(int32_t timestamp, int32_t clocks, int ch) { // Mask out the bits that the DMA controller will modify during the course of operation. uint32_t CRModeCache = DMACH[ch].ChanControl &~(0x11 << 24); uint32_t crmodecache = CRModeCache; switch(ch) { case 0: if(MDFN_LIKELY(CRModeCache == 0x00000201)) crmodecache = 0x00000201; break; case 1: if(MDFN_LIKELY(CRModeCache == 0x00000200)) crmodecache = 0x00000200; break; case 2: switch (CRModeCache) { case 0x00000401: case 0x00000201: case 0x00000200: crmodecache = CRModeCache; break; } break; case 3: switch (CRModeCache) { case 0x00000000: case 0x00000100: crmodecache = CRModeCache; break; } break; case 4: switch (CRModeCache) { case 0x00000201: case 0x00000200: crmodecache = CRModeCache; break; } break; case 6: if(MDFN_LIKELY(CRModeCache == 0x00000002)) crmodecache = 0x00000002; break; } // // Remember to handle an end condition on the same iteration of the while(DMACH[ch].ClockCounter > 0) loop that caused it, // otherwise RecalcHalt() might take the CPU out of a halted state before the end-of-DMA is signaled(especially a problem considering our largeish // DMA update timing granularity). if (ch >= 0 && ch <= 6) { CRModeCache = crmodecache; DMACH[ch].ClockCounter += clocks; while(MDFN_LIKELY(DMACH[ch].ClockCounter > 0)) { if(DMACH[ch].WordCounter == 0) // Begin WordCounter reload. { if(!(DMACH[ch].ChanControl & (1 << 24))) // Needed for the forced-DMA-stop kludge(see DMA_Write()). break; if(!ChCan(ch, CRModeCache)) break; DMACH[ch].CurAddr = DMACH[ch].BaseAddr; if(CRModeCache & (1U << 10)) { uint32_t header; if(MDFN_UNLIKELY(DMACH[ch].CurAddr & 0x800000)) { DMACH[ch].ChanControl &= ~(0x11 << 24); DMAIntControl |= 0x8000; RecalcIRQOut(); break; } header = MainRAM.ReadU32(DMACH[ch].CurAddr & 0x1FFFFC); DMACH[ch].CurAddr = (DMACH[ch].CurAddr + 4) & 0xFFFFFF; DMACH[ch].WordCounter = header >> 24; DMACH[ch].BaseAddr = header & 0xFFFFFF; // printf to debug Soul Reaver ;) //if(DMACH[ch].WordCounter > 0x10) // printf("What the lala? 0x%02x @ 0x%08x\n", DMACH[ch].WordCounter, DMACH[ch].CurAddr - 4); if(DMACH[ch].WordCounter) DMACH[ch].ClockCounter -= 15; else DMACH[ch].ClockCounter -= 10; goto SkipPayloadStuff; // 3 cheers for gluten-free spaghetticode(necessary because the newly-loaded WordCounter might be 0, and we actually // want 0 to mean 0 and not 65536 in this context)! } else { DMACH[ch].WordCounter = DMACH[ch].BlockControl & 0xFFFF; if(CRModeCache & (1U << 9)) { if(ch == 2) // Technically should apply to all channels, but since we don't implement CPU read penalties for channels other than 2 yet, it's like this to avoid making DMA longer than what games can handle. DMACH[ch].ClockCounter -= 7; DMACH[ch].BlockControl = (DMACH[ch].BlockControl & 0xFFFF) | ((DMACH[ch].BlockControl - (1U << 16)) & 0xFFFF0000); } } } // End WordCounter reload. else if(CRModeCache & 0x100) // BLARGH BLARGH FISHWHALE { //printf("LoadWC: %u(oldWC=%u)\n", DMACH[ch].BlockControl & 0xFFFF, DMACH[ch].WordCounter); //MDFN_DispMessage("SPOOOON\n"); DMACH[ch].CurAddr = DMACH[ch].BaseAddr; DMACH[ch].WordCounter = DMACH[ch].BlockControl & 0xFFFF; } // Do the payload read/write { uint32_t vtmp; uint32_t voffs = 0; if(MDFN_UNLIKELY(DMACH[ch].CurAddr & 0x800000)) { DMACH[ch].ChanControl &= ~(0x11 << 24); DMAIntControl |= 0x8000; RecalcIRQOut(); break; } if(CRModeCache & 0x1) vtmp = MainRAM.ReadU32(DMACH[ch].CurAddr & 0x1FFFFC); ChRW(ch, CRModeCache, &vtmp, &voffs); if(!(CRModeCache & 0x1)) MainRAM.WriteU32((DMACH[ch].CurAddr + (voffs << 2)) & 0x1FFFFC, vtmp); } if(CRModeCache & 0x2) DMACH[ch].CurAddr = (DMACH[ch].CurAddr - 4) & 0xFFFFFF; else DMACH[ch].CurAddr = (DMACH[ch].CurAddr + 4) & 0xFFFFFF; DMACH[ch].WordCounter--; DMACH[ch].ClockCounter--; SkipPayloadStuff: ; if(CRModeCache & 0x100) // BLARGH BLARGH WHALEFISH { DMACH[ch].BaseAddr = DMACH[ch].CurAddr; DMACH[ch].BlockControl = (DMACH[ch].BlockControl & 0xFFFF0000) | DMACH[ch].WordCounter; //printf("SaveWC: %u\n", DMACH[ch].WordCounter); } // // Handle channel end condition: // if(DMACH[ch].WordCounter == 0) { bool ChannelEndTC = false; if(!(DMACH[ch].ChanControl & (1 << 24))) // Needed for the forced-DMA-stop kludge(see DMA_Write()). break; switch((CRModeCache >> 9) & 0x3) { case 0x0: ChannelEndTC = true; break; case 0x1: DMACH[ch].BaseAddr = DMACH[ch].CurAddr; if((DMACH[ch].BlockControl >> 16) == 0) ChannelEndTC = true; break; case 0x2: case 0x3: // Not sure about 0x3. if(DMACH[ch].BaseAddr == 0xFFFFFF) ChannelEndTC = true; break; } if(ChannelEndTC) { DMACH[ch].ChanControl &= ~(0x11 << 24); if(DMAIntControl & (1U << (16 + ch))) { DMAIntStatus |= 1U << ch; RecalcIRQOut(); } break; } } } if(DMACH[ch].ClockCounter > 0) DMACH[ch].ClockCounter = 0; } } static INLINE int32_t CalcNextEvent(int32_t next_event) { if(DMACycleCounter < next_event) next_event = DMACycleCounter; return(next_event); } int32_t DMA_Update(const int32_t timestamp) { int32_t clocks, i; // uint32_t dc = (DMAControl >> (ch * 4)) & 0xF; clocks = timestamp - lastts; lastts = timestamp; GPU->Update(timestamp); MDEC_Run(clocks); for (i = 0; i < 7; i++) RunChannel(timestamp, clocks, i); DMACycleCounter -= clocks; while(DMACycleCounter <= 0) DMACycleCounter += 128; RecalcHalt(); return (timestamp + CalcNextEvent(0x10000000)); } void DMA_Write(const int32_t timestamp, uint32_t A, uint32_t V) { bool will_set_event = false; int ch = (A & 0x7F) >> 4; //if(ch == 2 || ch == 7) //PSX_WARNING("[DMA] Write: %08x %08x, DMAIntStatus=%08x", A, V, DMAIntStatus); // FIXME if we ever have "accurate" bus emulation V <<= (A & 3) * 8; DMA_Update(timestamp); switch(A & 0xC) { case 0x0: if (ch == 7) { DMAControl = V; RecalcHalt(); } else { DMACH[ch].BaseAddr = V & 0xFFFFFF; will_set_event = true; } break; case 0x4: if (ch == 7) { DMAIntControl = V & 0x00ff803f; DMAIntStatus &= ~(V >> 24); RecalcIRQOut(); } else { DMACH[ch].BlockControl = V; will_set_event = true; } break; case 0xC: case 0x8: if (ch != 7) { uint32_t OldCC = DMACH[ch].ChanControl; //printf("CHCR: %u, %08x --- 0x%08x\n", ch, V, DMACH[ch].BlockControl); // // Kludge for DMA timing granularity and other issues. Needs to occur before setting all bits of ChanControl to the new value, to accommodate the // case of a game cancelling DMA and changing the type of DMA(read/write, etc.) at the same time. // if((DMACH[ch].ChanControl & (1 << 24)) && !(V & (1 << 24))) { DMACH[ch].ChanControl &= ~(1 << 24); // Clear bit before RunChannel(), so it will only finish the block it's on at most. RunChannel(timestamp, 128 * 16, ch); DMACH[ch].WordCounter = 0; #if 0 // TODO(maybe, need to work out worst-case performance for abnormally/brokenly large block sizes) DMACH[ch].ClockCounter = (1 << 30); RunChannel(timestamp, 1, ch); DMACH[ch].ClockCounter = 0; #endif PSX_WARNING("[DMA] Forced stop for channel %d -- scanline=%d", ch, GPU->GetScanlineNum()); //MDFN_DispMessage("[DMA] Forced stop for channel %d", ch); } if(ch == 6) DMACH[ch].ChanControl = (V & 0x51000000) | 0x2; else DMACH[ch].ChanControl = V & 0x71770703; if(!(OldCC & (1 << 24)) && (V & (1 << 24))) { //if(ch == 0 || ch == 1) // PSX_WARNING("[DMA] Started DMA for channel=%d --- CHCR=0x%08x --- BCR=0x%08x --- scanline=%d", ch, DMACH[ch].ChanControl, DMACH[ch].BlockControl, GPU->GetScanlineNum()); DMACH[ch].WordCounter = 0; DMACH[ch].ClockCounter = 0; // // Viewpoint starts a short MEM->GPU LL DMA and apparently has race conditions that can cause a crash if it doesn't finish almost immediately( // or at least very quickly, which the current DMA granularity has issues with, so run the channel ahead a bit to take of this issue and potentially // games with similar issues). // // Though, Viewpoint isn't exactly a good game, so maybe we shouldn't bother? ;) // // Also, it's needed for RecalcHalt() to work with some semblance of workiness. // RunChannel(timestamp, 64, ch); //std::max(128 - DMACycleCounter, 1)); //64); //1); //128 - DMACycleCounter); } RecalcHalt(); will_set_event = true; break; } default: PSX_WARNING("[DMA] Unknown write: %08x %08x", A, V); break; } if (will_set_event) PSX_SetEventNT(PSX_EVENT_DMA, timestamp + CalcNextEvent(0x10000000)); } uint32_t DMA_Read(const int32_t timestamp, uint32_t A) { int ch = (A & 0x7F) >> 4; uint32_t ret = 0; switch(A & 0xC) { case 0x0: if (ch == 7) ret = DMAControl; else ret = DMACH[ch].BaseAddr; break; case 0x4: if (ch == 7) ret = DMAIntControl | (DMAIntStatus << 24) | (IRQOut << 31); else ret = DMACH[ch].BlockControl; break; case 0xC: case 0x8: if (ch != 7) { ret = DMACH[ch].ChanControl; break; } default: PSX_WARNING("[DMA] Unknown read: %08x", A); break; } return (ret >> ((A & 3) * 8)); } #define SFDMACH(n) SFVARN(DMACH[n].BaseAddr, #n "BaseAddr"), \ SFVARN(DMACH[n].BlockControl, #n "BlockControl"), \ SFVARN(DMACH[n].ChanControl, #n "ChanControl"), \ SFVARN(DMACH[n].CurAddr, #n "CurAddr"), \ SFVARN(DMACH[n].WordCounter, #n "WordCounter"), \ SFVARN(DMACH[n].ClockCounter, #n "ClockCounter") int DMA_StateAction(StateMem *sm, int load, int data_only) { SFORMAT StateRegs[] = { SFVAR(DMACycleCounter), SFVAR(DMAControl), SFVAR(DMAIntControl), SFVAR(DMAIntStatus), SFVAR(IRQOut), SFDMACH(0), SFDMACH(1), SFDMACH(2), SFDMACH(3), SFDMACH(4), SFDMACH(5), SFDMACH(6), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "DMA"); if(load) { } return(ret); } mednafen/error.h000664 001750 001750 00000002032 12611054044 014753 0ustar00sergiosergio000000 000000 #ifndef __MDFN_ERROR_H #define __MDFN_ERROR_H #include #include #ifdef __cplusplus #include class ErrnoHolder; class MDFN_Error : public std::exception { public: MDFN_Error() throw(); MDFN_Error(int errno_code_new, const char *format, ...) throw(); MDFN_Error(const ErrnoHolder &enh); ~MDFN_Error() throw(); MDFN_Error(const MDFN_Error &ze_error) throw(); MDFN_Error & operator=(const MDFN_Error &ze_error) throw(); virtual const char *what(void) const throw(); int GetErrno(void) const throw(); private: int errno_code; char *error_message; }; class ErrnoHolder { public: ErrnoHolder() { local_errno = 0; local_strerror[0] = 0; } ErrnoHolder(int the_errno) { SetErrno(the_errno); } inline int Errno(void) const { return(local_errno); } const char *StrError(void) const { return(local_strerror); } void operator=(int the_errno) { SetErrno(the_errno); } private: void SetErrno(int the_errno); int local_errno; char local_strerror[256]; }; #endif #endif mednafen/psx/input/mouse.h000664 001750 001750 00000000253 12611054044 016726 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_INPUT_MOUSE_H #define __MDFN_PSX_INPUT_MOUSE_H InputDevice *Device_Mouse_Create(void); extern InputDeviceInputInfoStruct Device_Mouse_IDII[4]; #endif mednafen/cdrom/CDAccess_Image.h000664 001750 001750 00000003357 12611054044 017453 0ustar00sergiosergio000000 000000 #ifndef __MDFN_CDACCESS_IMAGE_H #define __MDFN_CDACCESS_IMAGE_H #include class Stream; class AudioReader; struct CDRFILE_TRACK_INFO { int32_t LBA; uint32_t DIFormat; uint8_t subq_control; int32_t pregap; int32_t pregap_dv; int32_t postgap; int32_t index[2]; int32_t sectors; // Not including pregap sectors! Stream *fp; bool FirstFileInstance; bool RawAudioMSBFirst; long FileOffset; unsigned int SubchannelMode; uint32_t LastSamplePos; AudioReader *AReader; }; class CDAccess_Image : public CDAccess { public: CDAccess_Image(const char *path, bool image_memcache); virtual ~CDAccess_Image(); virtual void Read_Raw_Sector(uint8_t *buf, int32_t lba); virtual void Read_TOC(TOC *toc); virtual void Eject(bool eject_status); private: int32_t NumTracks; int32_t FirstTrack; int32_t LastTrack; int32_t total_sectors; uint8_t disc_type; CDRFILE_TRACK_INFO Tracks[100]; // Track #0(HMM?) through 99 struct cpp11_array_doodad { uint8 data[12]; }; std::map SubQReplaceMap; std::string base_dir; void ImageOpen(const char *path, bool image_memcache); int LoadSBI(const char* sbi_path); void Cleanup(void); // MakeSubPQ will OR the simulated P and Q subchannel data into SubPWBuf. void MakeSubPQ(int32_t lba, uint8_t *SubPWBuf); void ParseTOCFileLineInfo(CDRFILE_TRACK_INFO *track, const int tracknum, const std::string &filename, const char *binoffset, const char *msfoffset, const char *length, bool image_memcache, std::map &toc_streamcache); uint32_t GetSectorCount(CDRFILE_TRACK_INFO *track); }; #endif Makefile000664 001750 001750 00000016206 12611054044 013344 0ustar00sergiosergio000000 000000 DEBUG = 0 FRONTEND_SUPPORTS_RGB565 = 1 CORE_DIR := . HAVE_GRIFFIN = 0 ifeq ($(platform),) platform = unix ifeq ($(shell uname -a),) platform = win else ifneq ($(findstring Darwin,$(shell uname -a)),) platform = osx arch = intel ifeq ($(shell uname -p),powerpc) arch = ppc endif else ifneq ($(findstring MINGW,$(shell uname -a)),) platform = win endif endif ifneq ($(platform), osx) ifeq ($(findstring Haiku,$(shell uname -a)),) PTHREAD_FLAGS = -pthread endif endif NEED_CD = 1 NEED_TREMOR = 1 NEED_BPP = 32 WANT_NEW_API = 1 NEED_DEINTERLACER = 1 NEED_THREADING = 1 CORE_DEFINE := -DWANT_PSX_EMU TARGET_NAME := mednafen_psx_libretro ifeq ($(platform), unix) TARGET := $(TARGET_NAME).so fpic := -fPIC SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T ifneq ($(shell uname -p | grep -E '((i.|x)86|amd64)'),) IS_X86 = 1 endif LDFLAGS += $(PTHREAD_FLAGS) FLAGS += $(PTHREAD_FLAGS) -DHAVE_MKDIR else ifeq ($(platform), osx) TARGET := $(TARGET_NAME).dylib fpic := -fPIC SHARED := -dynamiclib LDFLAGS += $(PTHREAD_FLAGS) FLAGS += $(PTHREAD_FLAGS) -DHAVE_MKDIR ifeq ($(arch),ppc) ENDIANNESS_DEFINES := -DMSB_FIRST OLD_GCC := 1 else endif OSXVER = `sw_vers -productVersion | cut -d. -f 2` OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` ifeq ($(OSX_LT_MAVERICKS),"YES") fpic += -mmacosx-version-min=10.5 endif # iOS else ifneq (,$(findstring ios,$(platform))) TARGET := $(TARGET_NAME)_ios.dylib fpic := -fPIC SHARED := -dynamiclib LDFLAGS += $(PTHREAD_FLAGS) FLAGS += $(PTHREAD_FLAGS) ifeq ($(IOSSDK),) IOSSDK := $(shell xcrun -sdk iphoneos -show-sdk-path) endif CC = cc -arch armv7 -isysroot $(IOSSDK) CXX = c++ -arch armv7 -isysroot $(IOSSDK) IPHONEMINVER := ifeq ($(platform),ios9) IPHONEMINVER = -miphoneos-version-min=8.0 else IPHONEMINVER = -miphoneos-version-min=5.0 endif LDFLAGS += $(IPHONEMINVER) FLAGS += $(IPHONEMINVER) CC += $(IPHONEMINVER) CXX += $(IPHONEMINVER) else ifeq ($(platform), qnx) TARGET := $(TARGET_NAME)_qnx.so fpic := -fPIC SHARED := -lcpp -lm -shared -Wl,--no-undefined -Wl,--version-script=link.T #LDFLAGS += $(PTHREAD_FLAGS) #FLAGS += $(PTHREAD_FLAGS) -DHAVE_MKDIR FLAGS += -DHAVE_MKDIR CC = qcc -Vgcc_ntoarmv7le CXX = QCC -Vgcc_ntoarmv7le_cpp AR = QCC -Vgcc_ntoarmv7le FLAGS += -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp else ifeq ($(platform), ps3) TARGET := $(TARGET_NAME)_ps3.a CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe CXX = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-g++.exe AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe ENDIANNESS_DEFINES := -DMSB_FIRST OLD_GCC := 1 FLAGS += -DHAVE_MKDIR -DARCH_POWERPC_ALTIVEC STATIC_LINKING = 1 else ifeq ($(platform), sncps3) TARGET := $(TARGET_NAME)_ps3.a CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe CXX = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe ENDIANNESS_DEFINES := -DMSB_FIRST CXXFLAGS += -Xc+=exceptions OLD_GCC := 1 NO_GCC := 1 FLAGS += -DHAVE_MKDIR -DARCH_POWERPC_ALTIVEC STATIC_LINKING = 1 else ifeq ($(platform), psl1ght) TARGET := $(TARGET_NAME)_psl1ght.a CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) CXX = $(PS3DEV)/ppu/bin/ppu-g++$(EXE_EXT) AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) ENDIANNESS_DEFINES := -DMSB_FIRST FLAGS += -DHAVE_MKDIR STATIC_LINKING = 1 # PSP else ifeq ($(platform), psp1) TARGET := $(TARGET_NAME)_psp1.a CC = psp-gcc$(EXE_EXT) CXX = psp-g++$(EXE_EXT) AR = psp-ar$(EXE_EXT) FLAGS += -DPSP -G0 FLAGS += -DHAVE_MKDIR STATIC_LINKING = 1 EXTRA_INCLUDES := -I$(shell psp-config --pspsdk-path)/include # Vita else ifeq ($(platform), vita) TARGET := $(TARGET_NAME)_vita.a CC = arm-vita-eabi-gcc$(EXE_EXT) CXX = arm-vita-eabi-g++$(EXE_EXT) AR = arm-vita-eabi-ar$(EXE_EXT) FLAGS += -DVITA FLAGS += -DHAVE_MKDIR STATIC_LINKING = 1 else ifeq ($(platform), xenon) TARGET := $(TARGET_NAME)_xenon360.a CC = xenon-gcc$(EXE_EXT) CXX = xenon-g++$(EXE_EXT) AR = xenon-ar$(EXE_EXT) ENDIANNESS_DEFINES += -D__LIBXENON__ -m32 -D__ppc__ -DMSB_FIRST LIBS := $(PTHREAD_FLAGS) FLAGS += -DHAVE_MKDIR STATIC_LINKING = 1 else ifeq ($(platform), ngc) TARGET := $(TARGET_NAME)_ngc.a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) ENDIANNESS_DEFINES += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DMSB_FIRST EXTRA_INCLUDES := -I$(DEVKITPRO)/libogc/include FLAGS += -DHAVE_MKDIR STATIC_LINKING = 1 else ifeq ($(platform), wii) TARGET := $(TARGET_NAME)_wii.a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) ENDIANNESS_DEFINES += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DMSB_FIRST EXTRA_INCLUDES := -I$(DEVKITPRO)/libogc/include FLAGS += -DHAVE_MKDIR STATIC_LINKING = 1 else ifneq (,$(findstring armv,$(platform))) TARGET := $(TARGET_NAME).so fpic := -fPIC SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T CC = gcc LDFLAGS += $(PTHREAD_FLAGS) FLAGS += $(PTHREAD_FLAGS) -DHAVE_MKDIR IS_X86 = 0 ifneq (,$(findstring cortexa8,$(platform))) FLAGS += -marm -mcpu=cortex-a8 ASFLAGS += -mcpu=cortex-a8 else ifneq (,$(findstring cortexa9,$(platform))) FLAGS += -marm -mcpu=cortex-a9 ASFLAGS += -mcpu=cortex-a9 endif FLAGS += -marm ifneq (,$(findstring neon,$(platform))) FLAGS += -mfpu=neon ASFLAGS += -mfpu=neon HAVE_NEON = 1 endif ifneq (,$(findstring softfloat,$(platform))) FLAGS += -mfloat-abi=softfp else ifneq (,$(findstring hardfloat,$(platform))) FLAGS += -mfloat-abi=hard endif FLAGS += -DARM else TARGET := $(TARGET_NAME).dll CC = gcc CXX = g++ IS_X86 = 1 SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T LDFLAGS += -static-libgcc -static-libstdc++ -lwinmm FLAGS += -DHAVE__MKDIR endif include Makefile.common WARNINGS := -Wall \ -Wno-sign-compare \ -Wno-unused-variable \ -Wno-unused-function \ -Wno-uninitialized \ $(NEW_GCC_WARNING_FLAGS) \ -Wno-strict-aliasing EXTRA_GCC_FLAGS := -funroll-loops ifeq ($(NO_GCC),1) EXTRA_GCC_FLAGS := WARNINGS := else EXTRA_GCC_FLAGS := -g endif OBJECTS := $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o) all: $(TARGET) ifeq ($(DEBUG),0) FLAGS += -O2 $(EXTRA_GCC_FLAGS) else FLAGS += -O0 endif LDFLAGS += $(fpic) $(SHARED) FLAGS += $(fpic) $(NEW_GCC_FLAGS) FLAGS += $(INCFLAGS) FLAGS += $(ENDIANNESS_DEFINES) -DSIZEOF_DOUBLE=8 $(WARNINGS) -DMEDNAFEN_VERSION=\"0.9.31\" -DPACKAGE=\"mednafen\" -DMEDNAFEN_VERSION_NUMERIC=931 -DPSS_STYLE=1 -DMPC_FIXED_POINT $(CORE_DEFINE) -DSTDC_HEADERS -D__STDC_LIMIT_MACROS -D__LIBRETRO__ -D_LOW_ACCURACY_ $(EXTRA_INCLUDES) $(SOUND_DEFINE) -D__STDC_CONSTANT_MACROS CXXFLAGS += $(FLAGS) CFLAGS += $(FLAGS) $(TARGET): $(OBJECTS) ifeq ($(STATIC_LINKING), 1) $(AR) rcs $@ $(OBJECTS) else $(CXX) -o $@ $^ $(LDFLAGS) endif %.o: %.cpp $(CXX) -c -o $@ $< $(CXXFLAGS) %.o: %.c $(CC) -c -o $@ $< $(CFLAGS) clean: rm -f $(TARGET) $(OBJECTS) .PHONY: clean mednafen/psx/input/negcon.h000664 001750 001750 00000000260 12611054044 017045 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_INPUT_NEGCON_H #define __MDFN_PSX_INPUT_NEGCON_H InputDevice *Device_neGcon_Create(void); extern InputDeviceInputInfoStruct Device_neGcon_IDII[21]; #endif mednafen/include/trio/triodef.h000664 001750 001750 00000020526 12611054044 017666 0ustar00sergiosergio000000 000000 /************************************************************************* * * $Id: triodef.h,v 1.35 2009/09/20 11:37:14 breese Exp $ * * Copyright (C) 2001 Bjorn Reese * * Permission to use, copy, modify, and 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. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************/ #ifndef TRIO_TRIODEF_H #define TRIO_TRIODEF_H /************************************************************************* * Compiler support detection */ #if defined(__GNUC__) # define TRIO_COMPILER_GCC #endif #if defined(__SUNPRO_CC) # define TRIO_COMPILER_SUNPRO __SUNPRO_CC #else # if defined(__SUNPRO_C) # define TRIO_COMPILER_SUNPRO __SUNPRO_C # endif #endif #if defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__) # define TRIO_COMPILER_XLC #else # if defined(_AIX) && !defined(__GNUC__) # define TRIO_COMPILER_XLC /* Workaround for old xlc */ # endif #endif #if defined(__DECC) || defined(__DECCXX) # define TRIO_COMPILER_DECC #else # if defined(__osf__) && defined(__LANGUAGE_C__) && !defined(__GNUC__) # define TRIO_COMPILER_DECC /* Workaround for old DEC C compilers */ # endif #endif #if defined(__HP_aCC) || defined(__HP_cc) # define TRIO_COMPILER_HP #endif #if defined(sgi) || defined(__sgi) # define TRIO_COMPILER_MIPSPRO #endif #if defined(_MSC_VER) # define TRIO_COMPILER_MSVC #endif #if defined(__BORLANDC__) # define TRIO_COMPILER_BCB #endif /************************************************************************* * Platform support detection */ #if defined(VMS) || defined(__VMS) # define TRIO_PLATFORM_VMS #endif #if defined(unix) || defined(__unix) || defined(__unix__) # define TRIO_PLATFORM_UNIX #endif #if defined(TRIO_COMPILER_XLC) || defined(_AIX) # define TRIO_PLATFORM_UNIX #endif #if defined(TRIO_COMPILER_DECC) || defined(__osf___) # if !defined(TRIO_PLATFORM_VMS) # define TRIO_PLATFORM_UNIX # endif #endif #if defined(__NetBSD__) # define TRIO_PLATFORM_UNIX #endif #if defined(__Lynx__) # define TRIO_PLATFORM_UNIX # define TRIO_PLATFORM_LYNX #endif #if defined(__APPLE__) && defined(__MACH__) # define TRIO_PLATFORM_UNIX #endif #if defined(__QNX__) # define TRIO_PLATFORM_UNIX # define TRIO_PLATFORM_QNX #endif #if defined(__CYGWIN__) # define TRIO_PLATFORM_UNIX #endif #if defined(AMIGA) && defined(TRIO_COMPILER_GCC) # define TRIO_PLATFORM_UNIX #endif #if defined(TRIO_COMPILER_MSVC) || defined(WIN32) || defined(_WIN32) # define TRIO_PLATFORM_WIN32 #endif #if defined(_WIN32_WCE) # define TRIO_PLATFORM_WINCE #endif #if defined(mpeix) || defined(__mpexl) # define TRIO_PLATFORM_MPEIX #endif #if defined(_AIX) # define TRIO_PLATFORM_AIX #endif #if defined(__hpux) # define TRIO_PLATFORM_HPUX #endif #if defined(sun) || defined(__sun__) # if defined(__SVR4) || defined(__svr4__) # define TRIO_PLATFORM_SOLARIS # else # define TRIO_PLATFORM_SUNOS # endif #endif /************************************************************************* * Standards support detection */ #if defined(__STDC__) \ || defined(_MSC_EXTENSIONS) \ || defined(TRIO_COMPILER_BCB) # define PREDEF_STANDARD_C89 #endif #if defined(__STDC_VERSION__) # define PREDEF_STANDARD_C90 #endif #if (__STDC_VERSION__ - 0 >= 199409L) # define PREDEF_STANDARD_C94 #endif #if (__STDC_VERSION__ - 0 >= 199901L) # define PREDEF_STANDARD_C99 #endif #if defined(TRIO_COMPILER_SUNPRO) && (TRIO_COMPILER_SUNPRO >= 0x420) # if !defined(PREDEF_STANDARD_C94) # define PREDEF_STANDARD_C94 # endif #endif #if defined(__cplusplus) # define PREDEF_STANDARD_CXX #endif #if __cplusplus - 0 >= 199711L # define PREDEF_STANDARD_CXX89 #endif #if defined(_POSIX_VERSION) # define PREDEF_STANDARD_POSIX _POSIX_VERSION # if (_POSIX_VERSION >= 199506L) # define PREDEF_STANDARD_POSIX_1996 # endif #endif #if (_XOPEN_VERSION - 0 >= 3) || defined(_XOPEN_XPG3) # define PREDEF_STANDARD_XPG3 #endif #if (_XOPEN_VERSION - 0 >= 4) || defined(_XOPEN_XPG4) # define PREDEF_STANDARD_XPG4 #endif #if (_XOPEN_VERSION - 0 > 4) \ || (defined(_XOPEN_UNIX) && (_XOPEN_VERSION - 0 == 4)) # define PREDEF_STANDARD_UNIX95 #endif #if (_XOPEN_VERSION - 0 >= 500) # define PREDEF_STANDARD_UNIX98 #endif #if (_XOPEN_VERSION - 0 >= 600) # define PREDEF_STANDARD_UNIX03 #endif /************************************************************************* * Generic defines */ #if !defined(TRIO_PUBLIC) # define TRIO_PUBLIC #endif #if !defined(TRIO_PRIVATE) # define TRIO_PRIVATE static #endif #if !(defined(PREDEF_STANDARD_C89) || defined(PREDEF_STANDARD_CXX)) # define TRIO_COMPILER_ANCIENT #endif #if defined(TRIO_COMPILER_ANCIENT) # define TRIO_CONST # define TRIO_VOLATILE # define TRIO_SIGNED typedef double trio_long_double_t; typedef char * trio_pointer_t; # define TRIO_SUFFIX_LONG(x) x # define TRIO_PROTO(x) () # define TRIO_NOARGS # define TRIO_ARGS1(list,a1) list a1; # define TRIO_ARGS2(list,a1,a2) list a1; a2; # define TRIO_ARGS3(list,a1,a2,a3) list a1; a2; a3; # define TRIO_ARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4; # define TRIO_ARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5; # define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) list a1; a2; a3; a4; a5; a6; # define TRIO_ARGS7(list,a1,a2,a3,a4,a5,a6,a7) list a1; a2; a3; a4; a5; a6; a7; # define TRIO_VARGS2(list,a1,a2) list a1; a2 # define TRIO_VARGS3(list,a1,a2,a3) list a1; a2; a3 # define TRIO_VARGS4(list,a1,a2,a3,a4) list a1; a2; a3; a4 # define TRIO_VARGS5(list,a1,a2,a3,a4,a5) list a1; a2; a3; a4; a5 # define TRIO_VA_DECL va_dcl # define TRIO_VA_START(x,y) va_start(x) # define TRIO_VA_END(x) va_end(x) #else /* ANSI C */ # define TRIO_CONST const # define TRIO_VOLATILE volatile # define TRIO_SIGNED signed typedef long double trio_long_double_t; typedef void * trio_pointer_t; # define TRIO_SUFFIX_LONG(x) x ## L # define TRIO_PROTO(x) x # define TRIO_NOARGS void # define TRIO_ARGS1(list,a1) (a1) # define TRIO_ARGS2(list,a1,a2) (a1,a2) # define TRIO_ARGS3(list,a1,a2,a3) (a1,a2,a3) # define TRIO_ARGS4(list,a1,a2,a3,a4) (a1,a2,a3,a4) # define TRIO_ARGS5(list,a1,a2,a3,a4,a5) (a1,a2,a3,a4,a5) # define TRIO_ARGS6(list,a1,a2,a3,a4,a5,a6) (a1,a2,a3,a4,a5,a6) # define TRIO_ARGS7(list,a1,a2,a3,a4,a5,a6,a7) (a1,a2,a3,a4,a5,a6,a7) # define TRIO_VARGS2 TRIO_ARGS2 # define TRIO_VARGS3 TRIO_ARGS3 # define TRIO_VARGS4 TRIO_ARGS4 # define TRIO_VARGS5 TRIO_ARGS5 # define TRIO_VA_DECL ... # define TRIO_VA_START(x,y) va_start(x,y) # define TRIO_VA_END(x) va_end(x) #endif #if defined(PREDEF_STANDARD_C99) || defined(PREDEF_STANDARD_CXX) # define TRIO_INLINE inline #else # if defined(TRIO_COMPILER_GCC) # define TRIO_INLINE __inline__ # endif # if defined(TRIO_COMPILER_MSVC) # define TRIO_INLINE _inline # endif # if defined(TRIO_COMPILER_BCB) # define TRIO_INLINE __inline # endif #endif #if !defined(TRIO_INLINE) # define TRIO_INLINE #endif /************************************************************************* * Workarounds */ #if defined(TRIO_PLATFORM_VMS) /* * Computations done with constants at compile time can trigger these * even when compiling with IEEE enabled. */ # pragma message disable (UNDERFLOW, FLOATOVERFL) # if (__CRTL_VER < 80210001) /* * Although the compiler supports C99 language constructs, the C * run-time library does not contain all C99 functions. */ # if defined(PREDEF_STANDARD_C99) # undef PREDEF_STANDARD_C99 # endif # endif #endif /* * Not all preprocessors supports the LL token. */ #if defined(TRIO_COMPILER_MSVC) || defined(TRIO_COMPILER_BCB) #else # define TRIO_COMPILER_SUPPORTS_LL #endif #if defined(__CYGWIN__) /* * Cygwin defines the macros for hosted C99, but does not support certain * long double math functions. */ # include # define TRIO_CYGWIN_VERSION_API CYGWIN_VERSION_API_MAJOR * 1000 + \ CYGWIN_VERSION_API_MINOR /* * Please change the version number below when the Cygwin API supports * long double math functions (powl, fmodl, etc.) */ # if TRIO_CYGWIN_VERSION_API < 99999999 # define TRIO_NO_FLOORL 1 # define TRIO_NO_CEILL 1 # define TRIO_NO_POWL 1 # define TRIO_NO_FMODL 1 # define TRIO_NO_LOG10L 1 # endif #endif #endif /* TRIO_TRIODEF_H */ mednafen/psx/input/gamepad.cpp000664 001750 001750 00000014055 12611054044 017534 0ustar00sergiosergio000000 000000 #include "../psx.h" #include "../frontio.h" #include "gamepad.h" class InputDevice_Gamepad : public InputDevice { public: InputDevice_Gamepad(); virtual ~InputDevice_Gamepad(); virtual void Power(void); virtual int StateAction(StateMem* sm, int load, int data_only, const char* section_name); virtual void UpdateInput(const void *data); // // // virtual void SetDTR(bool new_dtr); virtual bool GetDSR(void); virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); private: bool dtr; uint8 buttons[2]; int32 command_phase; uint32 bitpos; uint8 receive_buffer; uint8 command; uint8 transmit_buffer[3]; uint32 transmit_pos; uint32 transmit_count; }; InputDevice_Gamepad::InputDevice_Gamepad() { Power(); } InputDevice_Gamepad::~InputDevice_Gamepad() { } void InputDevice_Gamepad::Power(void) { dtr = 0; buttons[0] = buttons[1] = 0; command_phase = 0; bitpos = 0; receive_buffer = 0; command = 0; memset(transmit_buffer, 0, sizeof(transmit_buffer)); transmit_pos = 0; transmit_count = 0; } int InputDevice_Gamepad::StateAction(StateMem* sm, int load, int data_only, const char* section_name) { SFORMAT StateRegs[] = { SFVAR(dtr), SFARRAY(buttons, sizeof(buttons)), SFVAR(command_phase), SFVAR(bitpos), SFVAR(receive_buffer), SFVAR(command), SFARRAY(transmit_buffer, sizeof(transmit_buffer)), SFVAR(transmit_pos), SFVAR(transmit_count), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name); if(load) { if((transmit_pos + transmit_count) > sizeof(transmit_buffer)) { transmit_pos = 0; transmit_count = 0; } } return(ret); } void InputDevice_Gamepad::UpdateInput(const void *data) { uint8 *d8 = (uint8 *)data; buttons[0] = d8[0]; buttons[1] = d8[1]; } void InputDevice_Gamepad::SetDTR(bool new_dtr) { if(!dtr && new_dtr) { command_phase = 0; bitpos = 0; transmit_pos = 0; transmit_count = 0; } else if(dtr && !new_dtr) { //if(bitpos || transmit_count) // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); } dtr = new_dtr; } bool InputDevice_Gamepad::GetDSR(void) { if(!dtr) return(0); if(!bitpos && transmit_count) return(1); return(0); } bool InputDevice_Gamepad::Clock(bool TxD, int32 &dsr_pulse_delay) { bool ret = 1; dsr_pulse_delay = 0; if(!dtr) return(1); if(transmit_count) ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; receive_buffer &= ~(1 << bitpos); receive_buffer |= TxD << bitpos; bitpos = (bitpos + 1) & 0x7; if(!bitpos) { //printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase); if(transmit_count) { transmit_pos++; transmit_count--; } switch(command_phase) { case 0: if(receive_buffer != 0x01) command_phase = -1; else { transmit_buffer[0] = 0x41; transmit_pos = 0; transmit_count = 1; command_phase++; } break; case 1: command = receive_buffer; command_phase++; transmit_buffer[0] = 0x5A; //if(command != 0x42) // fprintf(stderr, "Gamepad unhandled command: 0x%02x\n", command); //assert(command == 0x42); if(command == 0x42) { //printf("PAD COmmand 0x42, sl=%u\n", GPU->GetScanlineNum()); transmit_buffer[1] = 0xFF ^ buttons[0]; transmit_buffer[2] = 0xFF ^ buttons[1]; transmit_pos = 0; transmit_count = 3; } else { command_phase = -1; transmit_buffer[1] = 0; transmit_buffer[2] = 0; transmit_pos = 0; transmit_count = 0; } break; } } if(!bitpos && transmit_count) dsr_pulse_delay = 0x40; //0x100; return(ret); } InputDevice *Device_Gamepad_Create(void) { return new InputDevice_Gamepad(); } InputDeviceInputInfoStruct Device_Gamepad_IDII[16] = { { "select", "SELECT", 4, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON }, { "start", "START", 5, IDIT_BUTTON, NULL }, { "up", "UP ↑", 0, IDIT_BUTTON, "down" }, { "right", "RIGHT →", 3, IDIT_BUTTON, "left" }, { "down", "DOWN ↓", 1, IDIT_BUTTON, "up" }, { "left", "LEFT ←", 2, IDIT_BUTTON, "right" }, { "l2", "L2 (rear left shoulder)", 11, IDIT_BUTTON, NULL }, { "r2", "R2 (rear right shoulder)", 13, IDIT_BUTTON, NULL }, { "l1", "L1 (front left shoulder)", 10, IDIT_BUTTON, NULL }, { "r1", "R1 (front right shoulder)", 12, IDIT_BUTTON, NULL }, { "triangle", "△ (upper)", 6, IDIT_BUTTON_CAN_RAPID, NULL }, { "circle", "○ (right)", 9, IDIT_BUTTON_CAN_RAPID, NULL }, { "cross", "x (lower)", 7, IDIT_BUTTON_CAN_RAPID, NULL }, { "square", "□ (left)", 8, IDIT_BUTTON_CAN_RAPID, NULL }, }; InputDeviceInputInfoStruct Device_Dancepad_IDII[16] = { { "select", "SELECT", 0, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON }, { "start", "START", 1, IDIT_BUTTON, NULL }, { "up", "UP ↑", 3, IDIT_BUTTON, NULL }, { "right", "RIGHT →", 6, IDIT_BUTTON, NULL }, { "down", "DOWN ↓", 8, IDIT_BUTTON, NULL }, { "left", "LEFT ←", 5, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON, NULL }, { "triangle", "△ (lower left)", 7, IDIT_BUTTON, NULL }, { "circle", "○ (upper right)", 4, IDIT_BUTTON, NULL }, { "cross", "x (upper left)", 2, IDIT_BUTTON, NULL }, { "square", "□ (lower right)", 9, IDIT_BUTTON, NULL }, }; mednafen/mednafen.h000664 001750 001750 00000001141 12611054044 015377 0ustar00sergiosergio000000 000000 #ifndef _MEDNAFEN_H #define _MEDNAFEN_H #include "mednafen-types.h" #include #include #include #define _(String) (String) #include "math_ops.h" #include "git.h" #ifdef _WIN32 #define strcasecmp _stricmp #endif #define GET_FDATA_PTR(fp) (fp->data) #define GET_FSIZE_PTR(fp) (fp->size) #define GET_FEXTS_PTR(fp) (fp->ext) extern MDFNGI *MDFNGameInfo; #include "settings.h" void MDFN_DispMessage(const char *format, ...); void MDFN_LoadGameCheats(void *override); void MDFN_FlushGameCheats(int nosave); #include "mednafen-driver.h" #include "mednafen-endian.h" #endif mednafen/state.h000664 001750 001750 00000007432 12611054044 014753 0ustar00sergiosergio000000 000000 #ifndef _STATE_H #define _STATE_H typedef struct { uint8_t *data; uint32_t loc; uint32_t len; uint32_t malloced; uint32_t initial_malloc; // A setting! } StateMem; // Eh, we abuse the smem_* in-memory stream code // in a few other places. :) int32_t smem_read(StateMem *st, void *buffer, uint32_t len); int32_t smem_write(StateMem *st, void *buffer, uint32_t len); int32_t smem_putc(StateMem *st, int value); int32_t smem_tell(StateMem *st); int32_t smem_seek(StateMem *st, uint32_t offset, int whence); int smem_write32le(StateMem *st, uint32_t b); int smem_read32le(StateMem *st, uint32_t *b); int MDFNSS_SaveSM(void *st, int, int, const void*, const void*, const void*); int MDFNSS_LoadSM(void *st, int, int); // Flag for a single, >= 1 byte native-endian variable #define MDFNSTATE_RLSB 0x80000000 // 32-bit native-endian elements #define MDFNSTATE_RLSB32 0x40000000 // 16-bit native-endian elements #define MDFNSTATE_RLSB16 0x20000000 // 64-bit native-endian elements #define MDFNSTATE_RLSB64 0x10000000 #define MDFNSTATE_BOOL 0x08000000 typedef struct { void *v; // Pointer to the variable/array uint32_t size; // Length, in bytes, of the data to be saved EXCEPT: // In the case of MDFNSTATE_BOOL, it is the number of bool elements to save(bool is not always 1-byte). // If 0, the subchunk isn't saved. uint32_t flags; // Flags const char *name; // Name //uint32_t struct_size; // Only used for MDFNSTATE_ARRAYOFS, sizeof(struct) that members of the linked SFORMAT struct are in. } SFORMAT; INLINE bool SF_IS_BOOL(bool *) { return(1); } INLINE bool SF_IS_BOOL(void *) { return(0); } INLINE uint32_t SF_FORCE_AB(bool *) { return(0); } INLINE uint32_t SF_FORCE_A8(int8_t *) { return(0); } INLINE uint32_t SF_FORCE_A8(uint8_t *) { return(0); } INLINE uint32_t SF_FORCE_A16(int16_t *) { return(0); } INLINE uint32_t SF_FORCE_A16(uint16_t *) { return(0); } INLINE uint32_t SF_FORCE_A32(int32_t *) { return(0); } INLINE uint32_t SF_FORCE_A32(uint32_t *) { return(0); } INLINE uint32_t SF_FORCE_A64(int64_t *) { return(0); } INLINE uint32_t SF_FORCE_A64(uint64_t *) { return(0); } INLINE uint32_t SF_FORCE_D(double *) { return(0); } #define SFVARN(x, n) { &(x), SF_IS_BOOL(&(x)) ? 1 : sizeof(x), MDFNSTATE_RLSB | (SF_IS_BOOL(&(x)) ? MDFNSTATE_BOOL : 0), n } #define SFVAR(x) SFVARN((x), #x) #define SFARRAYN(x, l, n) { (x), (uint32_t)(l), 0 | SF_FORCE_A8(x), n } #define SFARRAY(x, l) SFARRAYN((x), (l), #x) #define SFARRAYBN(x, l, n) { (x), (uint32_t)(l), MDFNSTATE_BOOL | SF_FORCE_AB(x), n } #define SFARRAYB(x, l) SFARRAYBN((x), (l), #x) #define SFARRAY16N(x, l, n) { (x), (uint32_t)((l) * sizeof(uint16_t)), MDFNSTATE_RLSB16 | SF_FORCE_A16(x), n } #define SFARRAY16(x, l) SFARRAY16N((x), (l), #x) #define SFARRAY32N(x, l, n) { (x), (uint32_t)((l) * sizeof(uint32_t)), MDFNSTATE_RLSB32 | SF_FORCE_A32(x), n } #define SFARRAY32(x, l) SFARRAY32N((x), (l), #x) #define SFARRAY64N(x, l, n) { (x), (uint32_t)((l) * sizeof(uint64_t)), MDFNSTATE_RLSB64 | SF_FORCE_A64(x), n } #define SFARRAY64(x, l) SFARRAY64N((x), (l), #x) #define SFARRAYDN(x, l, n) { (x), (uint32_t)((l) * 8), MDFNSTATE_RLSB64 | SF_FORCE_D(x), n } #define SFARRAYD(x, l) SFARRAYDN((x), (l), #x) #define SFEND { 0, 0, 0, 0 } #include // State-Section Descriptor class SSDescriptor { public: SSDescriptor(SFORMAT *n_sf, const char *n_name, bool n_optional = 0) { sf = n_sf; name = n_name; optional = n_optional; } ~SSDescriptor(void) { } SFORMAT *sf; const char *name; bool optional; }; int MDFNSS_StateAction(void *st, int load, int data_only, std::vector §ions); int MDFNSS_StateAction(void *st, int load, int data_only, SFORMAT *sf, const char *name, bool optional = 0); #endif mednafen/psx/input/gamepad.h000664 001750 001750 00000000360 12611054044 017173 0ustar00sergiosergio000000 000000 #ifndef __MDFN_PSX_INPUT_GAMEPAD_H #define __MDFN_PSX_INPUT_GAMEPAD_H InputDevice *Device_Gamepad_Create(void); extern InputDeviceInputInfoStruct Device_Gamepad_IDII[16]; extern InputDeviceInputInfoStruct Device_Dancepad_IDII[16]; #endif mednafen/trio/000700 001750 001750 00000000000 12702525066 014425 5ustar00sergiosergio000000 000000 mednafen/psx/gpu.h000664 001750 001750 00000020163 12611054044 015234 0ustar00sergiosergio000000 000000 // WARNING WARNING WARNING: ONLY use CanRead() method of BlitterFIFO, and NOT CanWrite(), since the FIFO is larger than the actual PS1 GPU FIFO to accommodate // our lack of fancy superscalarish command sequencer. #ifndef __MDFN_PSX_GPU_H #define __MDFN_PSX_GPU_H #include "FastFIFO.h" class PS_GPU; #define INCMD_NONE 0 #define INCMD_PLINE 1 #define INCMD_QUAD 2 #define INCMD_FBWRITE 4 #define INCMD_FBREAD 8 struct CTEntry { void (*func[4][8])(PS_GPU* g, const uint32 *cb); uint8 len; uint8 fifo_fb_len; bool ss_cmd; }; struct tri_vertex { int32 x, y; int32 u, v; int32 r, g, b; }; struct i_group; struct i_deltas; struct line_point { int32 x, y; uint8 r, g, b; }; class PS_GPU { public: PS_GPU(bool pal_clock_and_tv, int sls, int sle) MDFN_COLD; ~PS_GPU() MDFN_COLD; void FillVideoParams(MDFNGI* gi) MDFN_COLD; void Power(void) MDFN_COLD; int StateAction(StateMem *sm, int load, int data_only); void ResetTS(void); void StartFrame(EmulateSpecStruct *espec); int32_t Update(const int32_t timestamp); void Write(const int32_t timestamp, uint32 A, uint32 V); INLINE bool CalcFIFOReadyBit(void) { if(InCmd & (INCMD_PLINE | INCMD_QUAD)) return(false); if(BlitterFIFO.CanRead() == 0) return(true); if(InCmd & (INCMD_FBREAD | INCMD_FBWRITE)) return(false); if(BlitterFIFO.CanRead() >= Commands[BlitterFIFO.Peek() >> 24].fifo_fb_len) return(false); return(true); } INLINE bool DMACanWrite(void) { return CalcFIFOReadyBit(); } void WriteDMA(uint32 V); uint32 ReadDMA(void); uint32 Read(const int32_t timestamp, uint32 A); inline int32 GetScanlineNum(void) { return(scanline); } INLINE uint16 PeekRAM(uint32 A) { return(GPURAM[(A >> 10) & 0x1FF][A & 0x3FF]); } INLINE void PokeRAM(uint32 A, uint16 V) { GPURAM[(A >> 10) & 0x1FF][A & 0x3FF] = V; } // Y, X uint16 GPURAM[512][1024]; uint32 DMAControl; // Drawing stuff int32 ClipX0; int32 ClipY0; int32 ClipX1; int32 ClipY1; int32 OffsX; int32 OffsY; bool dtd; // Dithering enable bool dfe; uint32 MaskSetOR; uint32 MaskEvalAND; bool TexDisable; bool TexDisableAllowChange; uint8 tww, twh, twx, twy; struct { uint8 TexWindowXLUT_Pre[16]; uint8 TexWindowXLUT[256]; uint8 TexWindowXLUT_Post[16]; }; struct { uint8 TexWindowYLUT_Pre[16]; uint8 TexWindowYLUT[256]; uint8 TexWindowYLUT_Post[16]; }; void RecalcTexWindowStuff(void); uint32_t TexPageX; // 0, 64, 128, 192, etc up to 960 uint32_t TexPageY; // 0 or 256 uint32 SpriteFlip; uint32 abr; // Semi-transparency mode(0~3) uint32 TexMode; struct { uint8 RGB8SAT_Under[256]; uint8 RGB8SAT[256]; uint8 RGB8SAT_Over[256]; }; static CTEntry Commands[256]; FastFIFO BlitterFIFO; // 0x10 on an actual PS1 GPU, 0x20 here (see comment at top of gpu.h) uint32 DataReadBuffer; uint32 DataReadBufferEx; bool IRQPending; // Powers of 2 for faster multiple equality testing(just for multi-testing; InCmd itself will only contain 0, or a power of 2). uint8 InCmd; uint8 InCmd_CC; tri_vertex InQuad_F3Vertices[3]; uint32 InQuad_clut; line_point InPLine_PrevPoint; uint32 FBRW_X; uint32 FBRW_Y; uint32 FBRW_W; uint32 FBRW_H; uint32 FBRW_CurY; uint32 FBRW_CurX; // // Display Parameters // uint32 DisplayMode; bool DisplayOff; uint32 DisplayFB_XStart; uint32 DisplayFB_YStart; uint32 HorizStart; uint32 HorizEnd; uint32 VertStart; uint32 VertEnd; // // Display work vars // uint32 DisplayFB_CurYOffset; uint32 DisplayFB_CurLineYReadout; bool InVBlank; // // // uint32 LinesPerField; uint32 scanline; bool field; bool field_ram_readout; bool PhaseChange; uint32 DotClockCounter; uint64 GPUClockCounter; uint32 GPUClockRatio; int32 LineClockCounter; int32 LinePhase; int32 DrawTimeAvail; int32_t lastts; bool sl_zero_reached; EmulateSpecStruct *espec; MDFN_Surface *surface; MDFN_Rect *DisplayRect; int32 *LineWidths; bool HardwarePALType; int LineVisFirst, LineVisLast; uint16 CLUT_Cache[256]; uint32 CLUT_Cache_VB; // Don't try to be clever and reduce it to 16 bits... ~0U is value for invalidated state. struct // Speedup-cache varibles, derived from other variables; shouldn't be saved in save states. { // TW*_* variables derived from tww, twh, twx, twy, TexPageX, TexPageY uint32 TWX_AND; uint32 TWX_ADD; uint32 TWY_AND; uint32 TWY_ADD; } SUCV; struct { uint16 Data[4]; uint32 Tag; } TexCache[256]; void InvalidateTexCache(void); void InvalidateCache(void); void SetTPage(uint32_t data); uint8_t DitherLUT[4][4][512]; // Y, X, 8-bit source value(256 extra for saturation) private: template void Update_CLUT_Cache(uint16 raw_clut); void ProcessFIFO(void); void WriteCB(uint32 data); uint32 ReadData(void); void SoftReset(void); template void PlotPixel(int32 x, int32 y, uint16 pix); template uint16 GetTexel(uint32 clut_offset, int32 u, int32 v); uint16 ModTexel(uint16 texel, int32 r, int32 g, int32 b, const int32 dither_x, const int32 dither_y); template void DrawSpan(int y, uint32 clut_offset, const int32 x_start, const int32 x_bound, i_group ig, const i_deltas &idl); template void DrawTriangle(tri_vertex *vertices, uint32 clut); template void DrawSprite(int32 x_arg, int32 y_arg, int32 w, int32 h, uint8 u_arg, uint8 v_arg, uint32 color, uint32 clut_offset); template void DrawLine(line_point *vertices); public: template void Command_DrawPolygon(const uint32 *cb); template void Command_DrawSprite(const uint32 *cb); template void Command_DrawLine(const uint32 *cb); void Command_ClearCache(const uint32 *cb); void Command_IRQ(const uint32 *cb); void Command_FBFill(const uint32 *cb); void Command_FBCopy(const uint32 *cb); void Command_FBWrite(const uint32 *cb); void Command_FBRead(const uint32 *cb); void Command_DrawMode(const uint32 *cb); void Command_TexWindow(const uint32 *cb); void Command_Clip0(const uint32 *cb); void Command_Clip1(const uint32 *cb); void Command_DrawingOffset(const uint32 *cb); void Command_MaskSetting(const uint32 *cb); private: void ReorderRGB_Var(uint32 out_Rshift, uint32 out_Gshift, uint32 out_Bshift, bool bpp24, const uint16 *src, uint32 *dest, const int32 dx_start, const int32 dx_end, int32 fb_x); template void ReorderRGB(bool bpp24, const uint16 *src, uint32 *dest, const int32 dx_start, const int32 dx_end, int32 fb_x) NO_INLINE; }; #endif mednafen/trio/triostr.c000664 001750 001750 00000063521 12611054044 016312 0ustar00sergiosergio000000 000000 /************************************************************************* * * $Id: triostr.c,v 1.36 2010/01/26 13:02:02 breese Exp $ * * Copyright (C) 2001 Bjorn Reese and Daniel Stenberg. * * Permission to use, copy, modify, and 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. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER. * ************************************************************************/ /************************************************************************* * Include files */ #if defined(HAVE_CONFIG_H) # include #endif #include #include #include #include #include "../include/trio/triodef.h" #include "../include/trio/triostr.h" #if defined(TRIO_FUNC_TO_LONG_DOUBLE) # define USE_MATH #endif #if defined(USE_MATH) # include #endif /************************************************************************* * Definitions */ #if !defined(TRIO_PUBLIC_STRING) # define TRIO_PUBLIC_STRING TRIO_PUBLIC #endif #if !defined(TRIO_PRIVATE_STRING) # define TRIO_PRIVATE_STRING TRIO_PRIVATE #endif #if !defined(NULL) # define NULL 0 #endif #if !defined(NIL) # define NIL ((char)0) #endif #if !defined(FALSE) # define FALSE (1 == 0) # define TRUE (! FALSE) #endif #if !defined(BOOLEAN_T) # define BOOLEAN_T int #endif #if defined(USE_MATH) # if defined(PREDEF_STANDARD_C99) # if defined(TRIO_COMPILER_DECC) # if (TRIO_COMPILER_DECC - 0 > 80000000) /* * The OSF/1 runtime that comes with the DECC compiler does not support * hexfloats conversion. */ # define USE_STRTOD # define USE_STRTOF # endif # else # define USE_STRTOD # define USE_STRTOF # endif # else # if defined(TRIO_COMPILER_VISUALC) # define USE_STRTOD # endif #endif #endif #if defined(TRIO_PLATFORM_UNIX) # if defined(PREDEF_STANDARD_UNIX95) # define USE_STRCASECMP # define USE_STRNCASECMP # endif # if defined(TRIO_PLATFORM_SUNOS) # define USE_SYS_ERRLIST # else # define USE_STRERROR # endif # if defined(TRIO_PLATFORM_QNX) # define strcasecmp(x,y) stricmp(x,y) # define strncasecmp(x,y,n) strnicmp(x,y,n) # endif #endif #if defined(TRIO_PLATFORM_WIN32) # define USE_STRCASECMP # if defined(TRIO_PLATFORM_WINCE) # define strcasecmp(x,y) _stricmp(x,y) # else # define strcasecmp(x,y) strcmpi(x,y) # endif #endif #if !defined(HAVE_CONFIG_H) # if !(defined(TRIO_PLATFORM_SUNOS)) # define HAVE_TOLOWER # define HAVE_TOUPPER # endif #endif #if defined(USE_MATH) && !defined(TRIO_NO_POWL) # if !defined(HAVE_POWL) # if defined(PREDEF_STANDARD_C99) \ || defined(PREDEF_STANDARD_UNIX03) # define HAVE_POWL # else # if defined(TRIO_COMPILER_VISUALC) # if defined(powl) # define HAVE_POWL # endif # endif # endif # endif #endif #if defined(HAVE_POWL) # define trio_powl(x,y) powl((x),(y)) #else # define trio_powl(x,y) pow((double)(x),(double)(y)) #endif #if defined(TRIO_FUNC_TO_UPPER) \ || (defined(TRIO_FUNC_EQUAL) && !defined(USE_STRCASECMP)) \ || (defined(TRIO_FUNC_EQUAL_MAX) && !defined(USE_STRNCASECMP)) \ || defined(TRIO_FUNC_MATCH) \ || defined(TRIO_FUNC_TO_LONG_DOUBLE) \ || defined(TRIO_FUNC_UPPER) # define TRIO_FUNC_INTERNAL_TO_UPPER #endif /************************************************************************* * Structures */ struct _trio_string_t { char *content; size_t length; size_t allocated; }; /************************************************************************* * Constants */ #if !defined(TRIO_EMBED_STRING) static TRIO_CONST char rcsid[] = "@(#)$Id: triostr.c,v 1.36 2010/01/26 13:02:02 breese Exp $"; #endif /************************************************************************* * Static String Functions */ #if defined(TRIO_DOCUMENTATION) # include "doc/doc_static.h" #endif /** @addtogroup StaticStrings @{ */ /* * internal_duplicate_max */ #if defined(TRIO_FUNC_DUPLICATE) \ || defined(TRIO_FUNC_DUPLICATE_MAX) \ || defined(TRIO_FUNC_STRING_DUPLICATE) \ || defined(TRIO_FUNC_XSTRING_DUPLICATE) TRIO_PRIVATE_STRING char * internal_duplicate_max TRIO_ARGS2((source, size), TRIO_CONST char *source, size_t size) { char *target; assert(source); /* Make room for string plus a terminating zero */ size++; target = trio_create(size); if (target) { trio_copy_max(target, size, source); } return target; } #endif /* * internal_string_alloc */ #if defined(TRIO_FUNC_STRING_CREATE) \ || defined(TRIO_FUNC_STRING_DUPLICATE) \ || defined(TRIO_FUNC_XSTRING_DUPLICATE) TRIO_PRIVATE_STRING trio_string_t * internal_string_alloc(TRIO_NOARGS) { trio_string_t *self; self = (trio_string_t *)TRIO_MALLOC(sizeof(trio_string_t)); if (self) { self->content = NULL; self->length = 0; self->allocated = 0; } return self; } #endif /* * internal_string_grow * * The size of the string will be increased by 'delta' characters. If * 'delta' is zero, the size will be doubled. */ #if defined(TRIO_FUNC_STRING_CREATE) \ || defined(TRIO_FUNC_STRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND_CHAR) TRIO_PRIVATE_STRING BOOLEAN_T internal_string_grow TRIO_ARGS2((self, delta), trio_string_t *self, size_t delta) { BOOLEAN_T status = FALSE; char *new_content; size_t new_size; new_size = (delta == 0) ? ( (self->allocated == 0) ? 1 : self->allocated * 2 ) : self->allocated + delta; new_content = (char *)TRIO_REALLOC(self->content, new_size); if (new_content) { self->content = new_content; self->allocated = new_size; status = TRUE; } return status; } #endif /* * internal_string_grow_to * * The size of the string will be increased to 'length' plus one characters. * If 'length' is less than the original size, the original size will be * used (that is, the size of the string is never decreased). */ #if defined(TRIO_FUNC_STRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND) \ || defined(TRIO_FUNC_XSTRING_APPEND_MAX) TRIO_PRIVATE_STRING BOOLEAN_T internal_string_grow_to TRIO_ARGS2((self, length), trio_string_t *self, size_t length) { length++; /* Room for terminating zero */ return (self->allocated < length) ? internal_string_grow(self, length - self->allocated) : TRUE; } #endif #if defined(TRIO_FUNC_INTERNAL_TO_UPPER) TRIO_PRIVATE_STRING TRIO_INLINE int internal_to_upper TRIO_ARGS1((source), int source) { # if defined(HAVE_TOUPPER) return toupper(source); # else /* Does not handle locales or non-contiguous alphabetic characters */ return ((source >= (int)'a') && (source <= (int)'z')) ? source - 'a' + 'A' : source; # endif } #endif /** Create new string. @param size Size of new string. @return Pointer to string, or NULL if allocation failed. */ #if defined(TRIO_FUNC_CREATE) TRIO_PUBLIC_STRING char * trio_create TRIO_ARGS1((size), size_t size) { return (char *)TRIO_MALLOC(size); } #endif /** Destroy string. @param string String to be freed. */ #if defined(TRIO_FUNC_DESTROY) TRIO_PUBLIC_STRING void trio_destroy TRIO_ARGS1((string), char *string) { if (string) { TRIO_FREE(string); } } #endif /** Count the number of characters in a string. @param string String to measure. @return Number of characters in @p string. */ #if defined(TRIO_FUNC_LENGTH) TRIO_PUBLIC_STRING size_t trio_length TRIO_ARGS1((string), TRIO_CONST char *string) { return strlen(string); } #endif /** Count at most @p max characters in a string. @param string String to measure. @param max Maximum number of characters to count. @return The maximum value of @p max and number of characters in @p string. */ #if defined(TRIO_FUNC_LENGTH_MAX) TRIO_PUBLIC_STRING size_t trio_length_max TRIO_ARGS2((string, max), TRIO_CONST char *string, size_t max) { size_t i; for (i = 0; i < max; ++i) { if (string[i] == 0) break; } return i; } #endif /** Append @p source at the end of @p target. @param target Target string. @param source Source string. @return Boolean value indicating success or failure. @pre @p target must point to a memory chunk with sufficient room to contain the @p target string and @p source string. @pre No boundary checking is performed, so insufficient memory will result in a buffer overrun. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_APPEND) TRIO_PUBLIC_STRING int trio_append TRIO_ARGS2((target, source), char *target, TRIO_CONST char *source) { assert(target); assert(source); return (strcat(target, source) != NULL); } #endif /** Append at most @p max characters from @p source to @p target. @param target Target string. @param max Maximum number of characters to append. @param source Source string. @return Boolean value indicating success or failure. @pre @p target must point to a memory chuck with sufficient room to contain the @p target string and the @p source string (at most @p max characters). @pre No boundary checking is performed, so insufficient memory will result in a buffer overrun. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_APPEND_MAX) TRIO_PUBLIC_STRING int trio_append_max TRIO_ARGS3((target, max, source), char *target, size_t max, TRIO_CONST char *source) { size_t length; assert(target); assert(source); length = trio_length(target); if (max > length) { strncat(target, source, max - length - 1); } return TRUE; } #endif /** Determine if a string contains a substring. @param string String to be searched. @param substring String to be found. @return Boolean value indicating success or failure. */ #if defined(TRIO_FUNC_CONTAINS) TRIO_PUBLIC_STRING int trio_contains TRIO_ARGS2((string, substring), TRIO_CONST char *string, TRIO_CONST char *substring) { assert(string); assert(substring); return (0 != strstr(string, substring)); } #endif /** Copy @p source to @p target. @param target Target string. @param source Source string. @return Boolean value indicating success or failure. @pre @p target must point to a memory chunk with sufficient room to contain the @p source string. @pre No boundary checking is performed, so insufficient memory will result in a buffer overrun. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_COPY) TRIO_PUBLIC_STRING int trio_copy TRIO_ARGS2((target, source), char *target, TRIO_CONST char *source) { assert(target); assert(source); (void)strcpy(target, source); return TRUE; } #endif /** Copy at most @p max - 1 characters from @p source to @p target. @param target Target string. @param max Maximum number of characters to append (one of which is a NUL terminator). In other words @p source must point to at least @p max - 1 bytes, but @p target must point to at least @p max bytes. @param source Source string. @return Boolean value indicating success or failure. @pre @p target must point to a memory chunk with sufficient room to contain the @p source string and a NUL terminator (at most @p max bytes total). @pre No boundary checking is performed, so insufficient memory will result in a buffer overrun. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_COPY_MAX) TRIO_PUBLIC_STRING int trio_copy_max TRIO_ARGS3((target, max, source), char *target, size_t max, TRIO_CONST char *source) { assert(target); assert(source); assert(max > 0); /* Includes != 0 */ (void)strncpy(target, source, max - 1); target[max - 1] = (char)0; return TRUE; } #endif /** Duplicate @p source. @param source Source string. @return A copy of the @p source string. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_DUPLICATE) TRIO_PUBLIC_STRING char * trio_duplicate TRIO_ARGS1((source), TRIO_CONST char *source) { return internal_duplicate_max(source, trio_length(source)); } #endif /** Duplicate at most @p max characters of @p source. @param source Source string. @param max Maximum number of characters to duplicate. @return A copy of the @p source string. @post @p target will be zero terminated. */ #if defined(TRIO_FUNC_DUPLICATE_MAX) TRIO_PUBLIC_STRING char * trio_duplicate_max TRIO_ARGS2((source, max), TRIO_CONST char *source, size_t max) { size_t length; assert(source); assert(max > 0); length = trio_length(source); if (length > max) { length = max; } return internal_duplicate_max(source, length); } #endif /** Compare if two strings are equal. @param first First string. @param second Second string. @return Boolean indicating whether the two strings are equal or not. Case-insensitive comparison. */ #if defined(TRIO_FUNC_EQUAL) TRIO_PUBLIC_STRING int trio_equal TRIO_ARGS2((first, second), TRIO_CONST char *first, TRIO_CONST char *second) { assert(first); assert(second); if ((first != NULL) && (second != NULL)) { # if defined(USE_STRCASECMP) return (0 == strcasecmp(first, second)); # else while ((*first != NIL) && (*second != NIL)) { if (internal_to_upper(*first) != internal_to_upper(*second)) { break; } first++; second++; } return ((*first == NIL) && (*second == NIL)); # endif } return FALSE; } #endif /** Compare if two strings are equal. @param first First string. @param second Second string. @return Boolean indicating whether the two strings are equal or not. Case-sensitive comparison. */ #if defined(TRIO_FUNC_EQUAL_CASE) TRIO_PUBLIC_STRING int trio_equal_case TRIO_ARGS2((first, second), TRIO_CONST char *first, TRIO_CONST char *second) { assert(first); assert(second); if ((first != NULL) && (second != NULL)) { return (0 == strcmp(first, second)); } return FALSE; } #endif /** Compare if two strings up until the first @p max characters are equal. @param first First string. @param max Maximum number of characters to compare. @param second Second string. @return Boolean indicating whether the two strings are equal or not. Case-sensitive comparison. */ #if defined(TRIO_FUNC_EQUAL_CASE_MAX) TRIO_PUBLIC_STRING int trio_equal_case_max TRIO_ARGS3((first, max, second), TRIO_CONST char *first, size_t max, TRIO_CONST char *second) { assert(first); assert(second); if ((first != NULL) && (second != NULL)) { return (0 == strncmp(first, second, max)); } return FALSE; } #endif /** Compare if two strings are equal. @param first First string. @param second Second string. @return Boolean indicating whether the two strings are equal or not. Collating characters are considered equal. */ #if defined(TRIO_FUNC_EQUAL_LOCALE) TRIO_PUBLIC_STRING int trio_equal_locale TRIO_ARGS2((first, second), TRIO_CONST char *first, TRIO_CONST char *second) { assert(first); assert(second); # if defined(LC_COLLATE) return (strcoll(first, second) == 0); # else return trio_equal(first, second); # endif } #endif /** Compare if two strings up until the first @p max characters are equal. @param first First string. @param max Maximum number of characters to compare. @param second Second string. @return Boolean indicating whether the two strings are equal or not. Case-insensitive comparison. */ #if defined(TRIO_FUNC_EQUAL_MAX) TRIO_PUBLIC_STRING int trio_equal_max TRIO_ARGS3((first, max, second), TRIO_CONST char *first, size_t max, TRIO_CONST char *second) { assert(first); assert(second); if ((first != NULL) && (second != NULL)) { # if defined(USE_STRNCASECMP) return (0 == strncasecmp(first, second, max)); # else /* Not adequately tested yet */ size_t cnt = 0; while ((*first != NIL) && (*second != NIL) && (cnt <= max)) { if (internal_to_upper(*first) != internal_to_upper(*second)) { break; } first++; second++; cnt++; } return ((cnt == max) || ((*first == NIL) && (*second == NIL))); # endif } return FALSE; } #endif /** Provide a textual description of an error code (errno). @param error_number Error number. @return Textual description of @p error_number. */ #if defined(TRIO_FUNC_ERROR) TRIO_PUBLIC_STRING TRIO_CONST char * trio_error TRIO_ARGS1((error_number), int error_number) { # if defined(USE_STRERROR) return strerror(error_number); # else # if defined(USE_SYS_ERRLIST) extern char *sys_errlist[]; extern int sys_nerr; return ((error_number < 0) || (error_number >= sys_nerr)) ? "unknown" : sys_errlist[error_number]; # else return "unknown"; # endif # endif } #endif /** Format the date/time according to @p format. @param target Target string. @param max Maximum number of characters to format. @param format Formatting string. @param datetime Date/time structure. @return Number of formatted characters. The formatting string accepts the same specifiers as the standard C function strftime. */ #if defined(TRIO_FUNC_FORMAT_DATE_MAX) TRIO_PUBLIC_STRING size_t trio_format_date_max TRIO_ARGS4((target, max, format, datetime), char *target, size_t max, TRIO_CONST char *format, TRIO_CONST struct tm *datetime) { assert(target); assert(format); assert(datetime); assert(max > 0); return strftime(target, max, format, datetime); } #endif /** Calculate a hash value for a string. @param string String to be calculated on. @param type Hash function. @return Calculated hash value. @p type can be one of the following @li @c TRIO_HASH_PLAIN Plain hash function. */ #if defined(TRIO_FUNC_HASH) TRIO_PUBLIC_STRING unsigned long trio_hash TRIO_ARGS2((string, type), TRIO_CONST char *string, int type) { unsigned long value = 0L; char ch; assert(string); switch (type) { case TRIO_HASH_PLAIN: while ( (ch = *string++) != NIL ) { value *= 31; value += (unsigned long)ch; } break; default: assert(FALSE); break; } return value; } #endif /** Find first occurrence of a character in a string. @param string String to be searched. @param character Character to be found. @return A pointer to the found character, or NULL if character was not found. */ #if defined(TRIO_FUNC_INDEX) TRIO_PUBLIC_STRING char * trio_index TRIO_ARGS2((string, character), TRIO_CONST char *string, int character) { assert(string); return strchr(string, character); } #endif /** Find last occurrence of a character in a string. @param string String to be searched. @param character Character to be found. @return A pointer to the found character, or NULL if character was not found. */ #if defined(TRIO_FUNC_INDEX_LAST) TRIO_PUBLIC_STRING char * trio_index_last TRIO_ARGS2((string, character), TRIO_CONST char *string, int character) { assert(string); return strchr(string, character); } #endif /** Convert the alphabetic letters in the string to lower-case. @param target String to be converted. @return Number of processed characters (converted or not). */ #if defined(TRIO_FUNC_LOWER) TRIO_PUBLIC_STRING int trio_lower TRIO_ARGS1((target), char *target) { assert(target); return trio_span_function(target, target, trio_to_lower); } #endif /** Compare two strings using wildcards. @param string String to be searched. @param pattern Pattern, including wildcards, to search for. @return Boolean value indicating success or failure. Case-insensitive comparison. The following wildcards can be used @li @c * Match any number of characters. @li @c ? Match a single character. */ #if defined(TRIO_FUNC_MATCH) TRIO_PUBLIC_STRING int trio_match TRIO_ARGS2((string, pattern), TRIO_CONST char *string, TRIO_CONST char *pattern) { assert(string); assert(pattern); for (; ('*' != *pattern); ++pattern, ++string) { if (NIL == *string) { return (NIL == *pattern); } if ((internal_to_upper((int)*string) != internal_to_upper((int)*pattern)) && ('?' != *pattern)) { return FALSE; } } /* two-line patch to prevent *too* much recursiveness: */ while ('*' == pattern[1]) pattern++; do { if ( trio_match(string, &pattern[1]) ) { return TRUE; } } while (*string++); return FALSE; } #endif /** Compare two strings using wildcards. @param string String to be searched. @param pattern Pattern, including wildcards, to search for. @return Boolean value indicating success or failure. Case-sensitive comparison. The following wildcards can be used @li @c * Match any number of characters. @li @c ? Match a single character. */ #if defined(TRIO_FUNC_MATCH_CASE) TRIO_PUBLIC_STRING int trio_match_case TRIO_ARGS2((string, pattern), TRIO_CONST char *string, TRIO_CONST char *pattern) { assert(string); assert(pattern); for (; ('*' != *pattern); ++pattern, ++string) { if (NIL == *string) { return (NIL == *pattern); } if ((*string != *pattern) && ('?' != *pattern)) { return FALSE; } } /* two-line patch to prevent *too* much recursiveness: */ while ('*' == pattern[1]) pattern++; do { if ( trio_match_case(string, &pattern[1]) ) { return TRUE; } } while (*string++); return FALSE; } #endif /** Execute a function on each character in string. @param target Target string. @param source Source string. @param Function Function to be executed. @return Number of processed characters. */ #if defined(TRIO_FUNC_SPAN_FUNCTION) TRIO_PUBLIC_STRING size_t trio_span_function TRIO_ARGS3((target, source, Function), char *target, TRIO_CONST char *source, int (*Function) TRIO_PROTO((int))) { size_t count = 0; assert(target); assert(source); assert(Function); while (*source != NIL) { *target++ = Function(*source++); count++; } return count; } #endif /** Convert string to signed integer. @param string String to be converted. @param endp Pointer to end of converted string. @param base Radix number of number. */ #if defined(TRIO_FUNC_TO_LONG) TRIO_PUBLIC_STRING long trio_to_long TRIO_ARGS3((string, endp, base), TRIO_CONST char *string, char **endp, int base) { assert(string); assert((base >= 2) && (base <= 36)); return strtol(string, endp, base); } #endif /** Convert one alphabetic letter to lower-case. @param source The letter to be converted. @return The converted letter. */ #if defined(TRIO_FUNC_TO_LOWER) TRIO_PUBLIC_STRING int trio_to_lower TRIO_ARGS1((source), int source) { # if defined(HAVE_TOLOWER) return tolower(source); # else /* Does not handle locales or non-contiguous alphabetic characters */ return ((source >= (int)'A') && (source <= (int)'Z')) ? source - 'A' + 'a' : source; # endif } #endif /** Convert one alphabetic letter to upper-case. @param source The letter to be converted. @return The converted letter. */ #if defined(TRIO_FUNC_TO_UPPER) TRIO_PUBLIC_STRING int trio_to_upper TRIO_ARGS1((source), int source) { return internal_to_upper(source); } #endif /** @} End of StaticStrings */ /************************************************************************* * Dynamic String Functions */ #if defined(TRIO_DOCUMENTATION) # include "doc/doc_dynamic.h" #endif /** @addtogroup DynamicStrings @{ */ /** Deallocate the dynamic string and its contents. @param self Dynamic string */ #if defined(TRIO_FUNC_STRING_DESTROY) TRIO_PUBLIC_STRING void trio_string_destroy TRIO_ARGS1((self), trio_string_t *self) { assert(self); if (self) { trio_destroy(self->content); TRIO_FREE(self); } } #endif /** Extract the content. @param self Dynamic String @return Content of dynamic string. The content is removed from the dynamic string. This enables destruction of the dynamic string without deallocation of the content. */ #if defined(TRIO_FUNC_STRING_EXTRACT) TRIO_PUBLIC_STRING char * trio_string_extract TRIO_ARGS1((self), trio_string_t *self) { char *result; assert(self); result = self->content; /* FIXME: Allocate new empty buffer? */ self->content = NULL; self->length = self->allocated = 0; return result; } #endif /* * trio_string_size */ #if defined(TRIO_FUNC_STRING_SIZE) TRIO_PUBLIC_STRING int trio_string_size TRIO_ARGS1((self), trio_string_t *self) { assert(self); return self->allocated; } #endif /* * trio_string_terminate */ #if defined(TRIO_FUNC_STRING_TERMINATE) TRIO_PUBLIC_STRING void trio_string_terminate TRIO_ARGS1((self), trio_string_t *self) { trio_xstring_append_char(self, 0); } #endif /* * trio_xstring_append_char */ #if defined(TRIO_FUNC_XSTRING_APPEND_CHAR) TRIO_PUBLIC_STRING int trio_xstring_append_char TRIO_ARGS2((self, character), trio_string_t *self, char character) { assert(self); if ((int)self->length >= trio_string_size(self)) { if (!internal_string_grow(self, 0)) goto error; } self->content[self->length] = character; self->length++; return TRUE; error: return FALSE; } #endif /* * trio_xstring_duplicate */ #if defined(TRIO_FUNC_XSTRING_DUPLICATE) TRIO_PUBLIC_STRING trio_string_t * trio_xstring_duplicate TRIO_ARGS1((other), TRIO_CONST char *other) { trio_string_t *self; assert(other); self = internal_string_alloc(); if (self) { self->content = internal_duplicate_max(other, trio_length(other)); if (self->content) { self->length = trio_length(self->content); self->allocated = self->length + 1; } else { self->length = self->allocated = 0; } } return self; } #endif mednafen/cdrom/cdromif.h000664 001750 001750 00000004615 12611054044 016362 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * 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 */ #ifndef __MDFN_CDROM_CDROMIF_H #define __MDFN_CDROM_CDROMIF_H #include "CDUtility.h" #include "../Stream.h" #include typedef TOC CD_TOC; class CDIF { public: CDIF(); virtual ~CDIF(); inline void ReadTOC(TOC *read_target) { *read_target = disc_toc; } virtual void HintReadSector(uint32_t lba) = 0; virtual bool ReadRawSector(uint8_t *buf, uint32_t lba) = 0; virtual bool ReadRawSectorPWOnly(uint8_t *buf, uint32_t lba, bool hint_fullread) = 0; // Call for mode 1 or mode 2 form 1 only. bool ValidateRawSector(uint8_t *buf); // Utility/Wrapped functions // Reads mode 1 and mode2 form 1 sectors(2048 bytes per sector returned) // Will return the type(1, 2) of the first sector read to the buffer supplied, 0 on error int ReadSector(uint8_t *pBuf, uint32_t lba, uint32_t nSectors); // Return true if operation succeeded or it was a NOP(either due to not being implemented, or the current status matches eject_status). // Returns false on failure(usually drive error of some kind; not completely fatal, can try again). virtual bool Eject(bool eject_status) = 0; // For Mode 1, or Mode 2 Form 1. // No reference counting or whatever is done, so if you destroy the CDIF object before you destroy the returned Stream, things will go BOOM. Stream *MakeStream(uint32_t lba, uint32_t sector_count); protected: bool UnrecoverableError; TOC disc_toc; bool DiscEjected; }; CDIF *CDIF_Open(const char *path, const bool is_device, bool image_memcache); #endif mednafen/cdrom/edc_crc32.c000664 001750 001750 00000013706 12611054044 016462 0ustar00sergiosergio000000 000000 /* dvdisaster: Additional error correction for optical media. * Copyright (C) 2004-2007 Carsten Gnoerlich. * Project home page: http://www.dvdisaster.com * Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org * * CRC32 code based upon public domain code by Ross Williams (see notes below) * * 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, * or direct your browser at http://www.gnu.org. */ #include /*** *** EDC checksum used in CDROM sectors ***/ /*****************************************************************/ /* */ /* CRC LOOKUP TABLE */ /* ================ */ /* The following CRC lookup table was generated automagically */ /* by the Rocksoft^tm Model CRC Algorithm Table Generation */ /* Program V1.0 using the following model parameters: */ /* */ /* Width : 4 bytes. */ /* Poly : 0x8001801BL */ /* Reverse : TRUE. */ /* */ /* For more information on the Rocksoft^tm Model CRC Algorithm, */ /* see the document titled "A Painless Guide to CRC Error */ /* Detection Algorithms" by Ross Williams */ /* (ross@guest.adelaide.edu.au.). This document is likely to be */ /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */ /* */ /*****************************************************************/ unsigned long edctable[256] = { 0x00000000L, 0x90910101L, 0x91210201L, 0x01B00300L, 0x92410401L, 0x02D00500L, 0x03600600L, 0x93F10701L, 0x94810801L, 0x04100900L, 0x05A00A00L, 0x95310B01L, 0x06C00C00L, 0x96510D01L, 0x97E10E01L, 0x07700F00L, 0x99011001L, 0x09901100L, 0x08201200L, 0x98B11301L, 0x0B401400L, 0x9BD11501L, 0x9A611601L, 0x0AF01700L, 0x0D801800L, 0x9D111901L, 0x9CA11A01L, 0x0C301B00L, 0x9FC11C01L, 0x0F501D00L, 0x0EE01E00L, 0x9E711F01L, 0x82012001L, 0x12902100L, 0x13202200L, 0x83B12301L, 0x10402400L, 0x80D12501L, 0x81612601L, 0x11F02700L, 0x16802800L, 0x86112901L, 0x87A12A01L, 0x17302B00L, 0x84C12C01L, 0x14502D00L, 0x15E02E00L, 0x85712F01L, 0x1B003000L, 0x8B913101L, 0x8A213201L, 0x1AB03300L, 0x89413401L, 0x19D03500L, 0x18603600L, 0x88F13701L, 0x8F813801L, 0x1F103900L, 0x1EA03A00L, 0x8E313B01L, 0x1DC03C00L, 0x8D513D01L, 0x8CE13E01L, 0x1C703F00L, 0xB4014001L, 0x24904100L, 0x25204200L, 0xB5B14301L, 0x26404400L, 0xB6D14501L, 0xB7614601L, 0x27F04700L, 0x20804800L, 0xB0114901L, 0xB1A14A01L, 0x21304B00L, 0xB2C14C01L, 0x22504D00L, 0x23E04E00L, 0xB3714F01L, 0x2D005000L, 0xBD915101L, 0xBC215201L, 0x2CB05300L, 0xBF415401L, 0x2FD05500L, 0x2E605600L, 0xBEF15701L, 0xB9815801L, 0x29105900L, 0x28A05A00L, 0xB8315B01L, 0x2BC05C00L, 0xBB515D01L, 0xBAE15E01L, 0x2A705F00L, 0x36006000L, 0xA6916101L, 0xA7216201L, 0x37B06300L, 0xA4416401L, 0x34D06500L, 0x35606600L, 0xA5F16701L, 0xA2816801L, 0x32106900L, 0x33A06A00L, 0xA3316B01L, 0x30C06C00L, 0xA0516D01L, 0xA1E16E01L, 0x31706F00L, 0xAF017001L, 0x3F907100L, 0x3E207200L, 0xAEB17301L, 0x3D407400L, 0xADD17501L, 0xAC617601L, 0x3CF07700L, 0x3B807800L, 0xAB117901L, 0xAAA17A01L, 0x3A307B00L, 0xA9C17C01L, 0x39507D00L, 0x38E07E00L, 0xA8717F01L, 0xD8018001L, 0x48908100L, 0x49208200L, 0xD9B18301L, 0x4A408400L, 0xDAD18501L, 0xDB618601L, 0x4BF08700L, 0x4C808800L, 0xDC118901L, 0xDDA18A01L, 0x4D308B00L, 0xDEC18C01L, 0x4E508D00L, 0x4FE08E00L, 0xDF718F01L, 0x41009000L, 0xD1919101L, 0xD0219201L, 0x40B09300L, 0xD3419401L, 0x43D09500L, 0x42609600L, 0xD2F19701L, 0xD5819801L, 0x45109900L, 0x44A09A00L, 0xD4319B01L, 0x47C09C00L, 0xD7519D01L, 0xD6E19E01L, 0x46709F00L, 0x5A00A000L, 0xCA91A101L, 0xCB21A201L, 0x5BB0A300L, 0xC841A401L, 0x58D0A500L, 0x5960A600L, 0xC9F1A701L, 0xCE81A801L, 0x5E10A900L, 0x5FA0AA00L, 0xCF31AB01L, 0x5CC0AC00L, 0xCC51AD01L, 0xCDE1AE01L, 0x5D70AF00L, 0xC301B001L, 0x5390B100L, 0x5220B200L, 0xC2B1B301L, 0x5140B400L, 0xC1D1B501L, 0xC061B601L, 0x50F0B700L, 0x5780B800L, 0xC711B901L, 0xC6A1BA01L, 0x5630BB00L, 0xC5C1BC01L, 0x5550BD00L, 0x54E0BE00L, 0xC471BF01L, 0x6C00C000L, 0xFC91C101L, 0xFD21C201L, 0x6DB0C300L, 0xFE41C401L, 0x6ED0C500L, 0x6F60C600L, 0xFFF1C701L, 0xF881C801L, 0x6810C900L, 0x69A0CA00L, 0xF931CB01L, 0x6AC0CC00L, 0xFA51CD01L, 0xFBE1CE01L, 0x6B70CF00L, 0xF501D001L, 0x6590D100L, 0x6420D200L, 0xF4B1D301L, 0x6740D400L, 0xF7D1D501L, 0xF661D601L, 0x66F0D700L, 0x6180D800L, 0xF111D901L, 0xF0A1DA01L, 0x6030DB00L, 0xF3C1DC01L, 0x6350DD00L, 0x62E0DE00L, 0xF271DF01L, 0xEE01E001L, 0x7E90E100L, 0x7F20E200L, 0xEFB1E301L, 0x7C40E400L, 0xECD1E501L, 0xED61E601L, 0x7DF0E700L, 0x7A80E800L, 0xEA11E901L, 0xEBA1EA01L, 0x7B30EB00L, 0xE8C1EC01L, 0x7850ED00L, 0x79E0EE00L, 0xE971EF01L, 0x7700F000L, 0xE791F101L, 0xE621F201L, 0x76B0F300L, 0xE541F401L, 0x75D0F500L, 0x7460F600L, 0xE4F1F701L, 0xE381F801L, 0x7310F900L, 0x72A0FA00L, 0xE231FB01L, 0x71C0FC00L, 0xE151FD01L, 0xE0E1FE01L, 0x7070FF00L }; /* * CDROM EDC calculation */ uint32_t EDCCrc32(const unsigned char *data, int len) { uint32_t crc = 0; while(len--) crc = edctable[(crc ^ *data++) & 0xFF] ^ (crc >> 8); return crc; } mednafen/psx/input/dualanalog.cpp000664 001750 001750 00000022642 12611054044 020246 0ustar00sergiosergio000000 000000 #include "../psx.h" #include "../frontio.h" #include "dualanalog.h" class InputDevice_DualAnalog : public InputDevice { public: InputDevice_DualAnalog(bool joystick_mode_); virtual ~InputDevice_DualAnalog(); virtual void Power(void); virtual int StateAction(StateMem* sm, int load, int data_only, const char* section_name); virtual void UpdateInput(const void *data); // // // virtual void SetDTR(bool new_dtr); virtual bool GetDSR(void); virtual bool Clock(bool TxD, int32 &dsr_pulse_delay); private: bool joystick_mode; bool dtr; uint8 buttons[2]; uint8 axes[2][2]; int32 command_phase; uint32 bitpos; uint8 receive_buffer; uint8 command; uint8 transmit_buffer[8]; uint32 transmit_pos; uint32 transmit_count; }; InputDevice_DualAnalog::InputDevice_DualAnalog(bool joystick_mode_) : joystick_mode(joystick_mode_) { Power(); } InputDevice_DualAnalog::~InputDevice_DualAnalog() { } void InputDevice_DualAnalog::Power(void) { dtr = 0; buttons[0] = buttons[1] = 0; command_phase = 0; bitpos = 0; receive_buffer = 0; command = 0; memset(transmit_buffer, 0, sizeof(transmit_buffer)); transmit_pos = 0; transmit_count = 0; } int InputDevice_DualAnalog::StateAction(StateMem* sm, int load, int data_only, const char* section_name) { SFORMAT StateRegs[] = { SFVAR(dtr), SFARRAY(buttons, sizeof(buttons)), SFARRAY(&axes[0][0], sizeof(axes)), SFVAR(command_phase), SFVAR(bitpos), SFVAR(receive_buffer), SFVAR(command), SFARRAY(transmit_buffer, sizeof(transmit_buffer)), SFVAR(transmit_pos), SFVAR(transmit_count), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, section_name); if(load) { if((transmit_pos + transmit_count) > sizeof(transmit_buffer)) { transmit_pos = 0; transmit_count = 0; } } return(ret); } void InputDevice_DualAnalog::UpdateInput(const void *data) { uint8 *d8 = (uint8 *)data; buttons[0] = d8[0]; buttons[1] = d8[1]; for(int stick = 0; stick < 2; stick++) { for(int axis = 0; axis < 2; axis++) { const uint8* aba = &d8[2] + stick * 8 + axis * 4; int32 tmp; //revert to 0.9.33, should be fixed on libretro side instead //tmp = 32768 + MDFN_de16lsb(&aba[0]) - ((int32)MDFN_de16lsb(&aba[2]) * 32768 / 32767); tmp = 32768 + MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 4) - ((int32)MDFN_de32lsb((const uint8 *)data + stick * 16 + axis * 8 + 8) * 32768 / 32767); tmp >>= 8; axes[stick][axis] = tmp; } } //printf("%d %d %d %d\n", axes[0][0], axes[0][1], axes[1][0], axes[1][1]); } void InputDevice_DualAnalog::SetDTR(bool new_dtr) { if(!dtr && new_dtr) { command_phase = 0; bitpos = 0; transmit_pos = 0; transmit_count = 0; } else if(dtr && !new_dtr) { //if(bitpos || transmit_count) // printf("[PAD] Abort communication!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); } dtr = new_dtr; } bool InputDevice_DualAnalog::GetDSR(void) { if(!dtr) return(0); if(!bitpos && transmit_count) return(1); return(0); } bool InputDevice_DualAnalog::Clock(bool TxD, int32 &dsr_pulse_delay) { bool ret = 1; dsr_pulse_delay = 0; if(!dtr) return(1); if(transmit_count) ret = (transmit_buffer[transmit_pos] >> bitpos) & 1; receive_buffer &= ~(1 << bitpos); receive_buffer |= TxD << bitpos; bitpos = (bitpos + 1) & 0x7; if(!bitpos) { //printf("[PAD] Receive: %02x -- command_phase=%d\n", receive_buffer, command_phase); if(transmit_count) { transmit_pos++; transmit_count--; } switch(command_phase) { case 0: if(receive_buffer != 0x01) command_phase = -1; else { transmit_buffer[0] = joystick_mode ? 0x53 : 0x73; transmit_pos = 0; transmit_count = 1; command_phase++; } break; case 1: command = receive_buffer; command_phase++; transmit_buffer[0] = 0x5A; //if(command != 0x42) // fprintf(stderr, "Gamepad unhandled command: 0x%02x\n", command); if(command == 0x42) { transmit_buffer[1] = 0xFF ^ buttons[0]; transmit_buffer[2] = 0xFF ^ buttons[1]; transmit_buffer[3] = axes[0][0]; transmit_buffer[4] = axes[0][1]; transmit_buffer[5] = axes[1][0]; transmit_buffer[6] = axes[1][1]; transmit_pos = 0; transmit_count = 7; } else { command_phase = -1; transmit_buffer[1] = 0; transmit_buffer[2] = 0; transmit_pos = 0; transmit_count = 0; } break; case 2: //if(receive_buffer) // printf("%d: %02x\n", 7 - transmit_count, receive_buffer); break; } } if(!bitpos && transmit_count) dsr_pulse_delay = 0x40; //0x100; return(ret); } InputDevice *Device_DualAnalog_Create(bool joystick_mode) { return new InputDevice_DualAnalog(joystick_mode); } InputDeviceInputInfoStruct Device_DualAnalog_IDII[24] = { { "select", "SELECT", 4, IDIT_BUTTON, NULL }, { "l3", "Left Stick, Button(L3)", 18, IDIT_BUTTON, NULL }, { "r3", "Right stick, Button(R3)", 23, IDIT_BUTTON, NULL }, { "start", "START", 5, IDIT_BUTTON, NULL }, { "up", "D-Pad UP ↑", 0, IDIT_BUTTON, "down" }, { "right", "D-Pad RIGHT →", 3, IDIT_BUTTON, "left" }, { "down", "D-Pad DOWN ↓", 1, IDIT_BUTTON, "up" }, { "left", "D-Pad LEFT ←", 2, IDIT_BUTTON, "right" }, { "l2", "L2 (rear left shoulder)", 11, IDIT_BUTTON, NULL }, { "r2", "R2 (rear right shoulder)", 13, IDIT_BUTTON, NULL }, { "l1", "L1 (front left shoulder)", 10, IDIT_BUTTON, NULL }, { "r1", "R1 (front right shoulder)", 12, IDIT_BUTTON, NULL }, { "triangle", "△ (upper)", 6, IDIT_BUTTON_CAN_RAPID, NULL }, { "circle", "○ (right)", 9, IDIT_BUTTON_CAN_RAPID, NULL }, { "cross", "x (lower)", 7, IDIT_BUTTON_CAN_RAPID, NULL }, { "square", "□ (left)", 8, IDIT_BUTTON_CAN_RAPID, NULL }, { "rstick_right", "Right Stick RIGHT →", 22, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "rstick_left", "Right Stick LEFT ←", 21, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "rstick_down", "Right Stick DOWN ↓", 20, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "rstick_up", "Right Stick UP ↑", 19, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "lstick_right", "Left Stick RIGHT →", 17, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "lstick_left", "Left Stick LEFT ←", 16, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "lstick_down", "Left Stick DOWN ↓", 15, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "lstick_up", "Left Stick UP ↑", 14, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, }; // Not sure if all these buttons are named correctly! InputDeviceInputInfoStruct Device_AnalogJoy_IDII[24] = { { "select", "SELECT", 8, IDIT_BUTTON, NULL }, { NULL, "empty", 0, IDIT_BUTTON }, { NULL, "empty", 0, IDIT_BUTTON }, { "start", "START", 9, IDIT_BUTTON, NULL }, { "up", "Thumbstick UP ↑", 14, IDIT_BUTTON, "down" }, { "right", "Thumbstick RIGHT →", 17, IDIT_BUTTON, "left" }, { "down", "Thumbstick DOWN ↓", 15, IDIT_BUTTON, "up" }, { "left", "Thumbstick LEFT ←", 16, IDIT_BUTTON, "right" }, { "l2", "Left stick, Trigger", 2, IDIT_BUTTON, NULL }, { "r2", "Left stick, Pinky", 3, IDIT_BUTTON, NULL }, { "l1", "Left stick, L-thumb", 0, IDIT_BUTTON, NULL }, { "r1", "Left stick, R-thumb", 1, IDIT_BUTTON, NULL }, { "triangle", "Right stick, Pinky", 13, IDIT_BUTTON, NULL }, { "circle", "Right stick, R-thumb", 11, IDIT_BUTTON, NULL }, { "cross", "Right stick, L-thumb", 10, IDIT_BUTTON, NULL }, { "square", "Right stick, Trigger", 12, IDIT_BUTTON, NULL }, { "rstick_right", "Right Stick, RIGHT →", 21, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "rstick_left", "Right Stick, LEFT ←", 20, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "rstick_down", "Right Stick, BACK ↓", 19, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "rstick_up", "Right Stick, FORE ↑", 18, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "lstick_right", "Left Stick, RIGHT →", 7, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "lstick_left", "Left Stick, LEFT ←", 6, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "lstick_down", "Left Stick, BACK ↓", 5, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, { "lstick_up", "Left Stick, FORE ↑", 4, IDIT_BUTTON_ANALOG, NULL, { NULL, NULL, NULL }, IDIT_BUTTON_ANALOG_FLAG_SQLR }, }; beetle_psx_griffin.cpp000664 001750 001750 00000002650 12611054044 016244 0ustar00sergiosergio000000 000000 #include "mednafen/psx/irq.cpp" #include "mednafen/psx/timer.cpp" #include "mednafen/psx/frontio.cpp" #include "mednafen/psx/cpu.cpp" #include "mednafen/psx/gte.cpp" #include "mednafen/psx/dis.cpp" #include "mednafen/psx/cdc.cpp" #include "mednafen/psx/spu.cpp" #include "mednafen/psx/gpu.cpp" #include "mednafen/psx/mdec.cpp" #include "mednafen/psx/input/gamepad.cpp" #include "mednafen/psx/input/dualanalog.cpp" #include "mednafen/psx/input/dualshock.cpp" #include "mednafen/psx/input/justifier.cpp" #include "mednafen/psx/input/guncon.cpp" #include "mednafen/psx/input/negcon.cpp" #include "mednafen/psx/input/memcard.cpp" #include "mednafen/psx/input/multitap.cpp" #include "mednafen/psx/input/mouse.cpp" #include "mednafen/error.cpp" #include "mednafen/math_ops.cpp" #include "mednafen/settings.cpp" #include "mednafen/general.cpp" #include "mednafen/FileStream.cpp" #include "mednafen/MemoryStream.cpp" #include "mednafen/Stream.cpp" #include "mednafen/state.cpp" #ifdef NEED_CD #include "mednafen/cdrom/CDAccess.cpp" #include "mednafen/cdrom/CDAccess_Image.cpp" #include "mednafen/cdrom/CDAccess_CCD.cpp" #include "mednafen/cdrom/SimpleFIFO.cpp" #include "mednafen/cdrom/audioreader.cpp" #include "mednafen/cdrom/cdromif.cpp" #include "mednafen/cdrom/misc.cpp" #endif #include "mednafen/mempatcher.cpp" #include "mednafen/video/Deinterlacer.cpp" #include "mednafen/video/surface.cpp" #include "mednafen/md5.cpp" #include "libretro.cpp" mednafen/cdrom/edc_crc32.h000664 001750 001750 00000000273 12611054044 016462 0ustar00sergiosergio000000 000000 #ifndef _EDC_CRC32_H #define _EDC_CRC32_H #include #ifdef __cplusplus extern "C" { #endif uint32_t EDCCrc32(const unsigned char*, int); #ifdef __cplusplus } #endif #endif mednafen/mempatcher-driver.h000664 001750 001750 00000003671 12611054044 017252 0ustar00sergiosergio000000 000000 #ifndef __MDFN_MEMPATCHER_DRIVER_H #define __MDFN_MEMPATCHER_DRIVER_H struct MemoryPatch { MemoryPatch(); ~MemoryPatch(); std::string name; std::string conditions; uint32 addr; uint64 val; uint64 compare; uint32 mltpl_count; uint32 mltpl_addr_inc; uint64 mltpl_val_inc; uint32 copy_src_addr; uint32 copy_src_addr_inc; unsigned length; bool bigendian; bool status; // (in)active unsigned icount; char type; /* 'R' for replace, 'S' for substitute(GG), 'C' for substitute with compare */ /* 'T' for copy/transfer data, 'A' for add(variant of type R) */ //enum { TypeReplace, TypeSubst, TypeCompSubst }; //int type; }; int MDFNI_DecodePAR(const char *code, uint32 *a, uint8 *v, uint8 *c, char *type); int MDFNI_DecodeGG(const char *str, uint32 *a, uint8 *v, uint8 *c, char *type); int MDFNI_AddCheat(const char *name, uint32 addr, uint64 val, uint64 compare, char type, unsigned int length, bool bigendian); int MDFNI_DelCheat(uint32 which); int MDFNI_ToggleCheat(uint32 which); int32 MDFNI_CheatSearchGetCount(void); void MDFNI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current)); void MDFNI_CheatSearchGet(int (*callb)(uint32 a, uint64 last, uint64 current, void *data), void *data); void MDFNI_CheatSearchBegin(void); void MDFNI_CheatSearchEnd(int type, uint64 v1, uint64 v2, unsigned int bytelen, bool bigendian); void MDFNI_ListCheats(int (*callb)(char *name, uint32 a, uint64 v, uint64 compare, int s, char type, unsigned int length, bool bigendian, void *data), void *data); int MDFNI_GetCheat(uint32 which, char **name, uint32 *a, uint64 *v, uint64 *compare, int *s, char *type, unsigned int *length, bool *bigendian); int MDFNI_SetCheat(uint32 which, const char *name, uint32 a, uint64 v, uint64 compare, int s, char type, unsigned int length, bool bigendian); void MDFNI_CheatSearchShowExcluded(void); void MDFNI_CheatSearchSetCurrentAsOriginal(void); #endif mednafen/include/rthreads/rthreads.h000664 001750 001750 00000014522 12611054044 020704 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2015 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (rthreads.h). * --------------------------------------------------------------------------------------- * * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_RTHREADS_H__ #define __LIBRETRO_SDK_RTHREADS_H__ #include #include #include #if defined(__cplusplus) && !defined(_MSC_VER) extern "C" { #endif typedef struct sthread sthread_t; typedef struct slock slock_t; typedef struct scond scond_t; /** * sthread_create: * @start_routine : thread entry callback function * @userdata : pointer to userdata that will be made * available in thread entry callback function * * Create a new thread. * * Returns: pointer to new thread if successful, otherwise NULL. */ sthread_t *sthread_create(void (*thread_func)(void*), void *userdata); /** * sthread_detach: * @thread : pointer to thread object * * Detach a thread. When a detached thread terminates, its * resource sare automatically released back to the system * without the need for another thread to join with the * terminated thread. * * Returns: 0 on success, otherwise it returns a non-zero error number. */ int sthread_detach(sthread_t *thread); /** * sthread_join: * @thread : pointer to thread object * * Join with a terminated thread. Waits for the thread specified by * @thread to terminate. If that thread has already terminated, then * it will return immediately. The thread specified by @thread must * be joinable. * * Returns: 0 on success, otherwise it returns a non-zero error number. */ void sthread_join(sthread_t *thread); /** * slock_new: * * Create and initialize a new mutex. Must be manually * freed. * * Returns: pointer to a new mutex if successful, otherwise NULL. **/ slock_t *slock_new(void); /** * slock_free: * @lock : pointer to mutex object * * Frees a mutex. **/ void slock_free(slock_t *lock); /** * slock_lock: * @lock : pointer to mutex object * * Locks a mutex. If a mutex is already locked by * another thread, the calling thread shall block until * the mutex becomes available. **/ void slock_lock(slock_t *lock); /** * slock_unlock: * @lock : pointer to mutex object * * Unlocks a mutex. **/ void slock_unlock(slock_t *lock); /** * scond_new: * * Creates and initializes a condition variable. Must * be manually freed. * * Returns: pointer to new condition variable on success, * otherwise NULL. **/ scond_t *scond_new(void); /** * scond_free: * @cond : pointer to condition variable object * * Frees a condition variable. **/ void scond_free(scond_t *cond); /** * scond_wait: * @cond : pointer to condition variable object * @lock : pointer to mutex object * * Block on a condition variable (i.e. wait on a condition). **/ void scond_wait(scond_t *cond, slock_t *lock); /** * scond_wait_timeout: * @cond : pointer to condition variable object * @lock : pointer to mutex object * @timeout_us : timeout (in microseconds) * * Try to block on a condition variable (i.e. wait on a condition) until * @timeout_us elapses. * * Returns: false (0) if timeout elapses before condition variable is * signaled or broadcast, otherwise true (1). **/ bool scond_wait_timeout(scond_t *cond, slock_t *lock, int64_t timeout_us); /** * scond_broadcast: * @cond : pointer to condition variable object * * Broadcast a condition. Unblocks all threads currently blocked * on the specified condition variable @cond. **/ int scond_broadcast(scond_t *cond); /** * scond_signal: * @cond : pointer to condition variable object * * Signal a condition. Unblocks at least one of the threads currently blocked * on the specified condition variable @cond. **/ void scond_signal(scond_t *cond); #ifndef RARCH_INTERNAL #if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) #include #elif defined(XENON) #include