// Translates an Errno code into an exception. // Throws an exception based on the given error code (usually taken from ANSI C's errno) BaseException* Exception::FromErrno( const wxString& streamname, int errcode ) { pxAssumeDev( errcode != 0, "Invalid NULL error code? (errno)" ); switch( errcode ) { case EINVAL: pxFailDev( L"Invalid argument" ); return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Invalid argument? (likely caused by an unforgivable programmer error!)" ); case EACCES: // Access denied! return new Exception::AccessDenied( streamname ); case EMFILE: // Too many open files! return &(new Exception::CannotCreateStream( streamname ))->SetDiagMsg(L"Too many open files"); // File handle allocation failure case EEXIST: return &(new Exception::CannotCreateStream( streamname ))->SetDiagMsg(L"File already exists"); case ENOENT: // File not found! return new Exception::FileNotFound( streamname ); case EPIPE: return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Broken pipe"); case EBADF: return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Bad file number"); default: return &(new Exception::BadStream( streamname ))->SetDiagMsg(pxsFmt( L"General file/stream error [errno: %d]", errcode )); } }
xAddressVoid& xAddressVoid::Add( const xAddressReg& src ) { if( src == Index ) { Factor++; } else if( src == Base ) { // Compound the existing register reference into the Index/Scale pair. Base = xEmptyReg; if( src == Index ) Factor++; else { pxAssertDev( Index.IsEmpty(), "x86Emitter: Only one scaled index register is allowed in an address modifier." ); Index = src; Factor = 2; } } else if( Base.IsEmpty() ) Base = src; else if( Index.IsEmpty() ) Index = src; else pxAssumeDev( false, L"x86Emitter: address modifiers cannot have more than two index registers." ); // oops, only 2 regs allowed per ModRm! return *this; }
// This method allows the programmer to specify the block size of the array as a function // of its reserved size. This function *must* be called *after* the reserve has been made, // and *before* the array contents have been accessed. // // Calls to this function prior to initializing the reserve or after the reserve has been // accessed (resulting in committed blocks) will be ignored -- and will generate an assertion // in debug builds. SpatialArrayReserve& SpatialArrayReserve::SetBlockCount( uint blocks ) { pxAssumeDev( !m_pages_commited, "Invalid object state: SetBlockCount must be called prior to reserved memory accesses." ); // Calculate such that the last block extends past the end of the array, if necessary. m_numblocks = blocks; m_blocksize = (m_pages_reserved + m_numblocks-1) / m_numblocks; return *this; }
xAddressVoid &xAddressVoid::Add(const xAddressVoid &src) { Add(src.Base); Add(src.Displacement); // If the factor is 1, we can just treat index like a base register also. if (src.Factor == 1) { Add(src.Index); } else if (Index.IsEmpty()) { Index = src.Index; Factor = src.Factor; } else if (Index == src.Index) { Factor += src.Factor; } else pxAssumeDev(false, L"x86Emitter: address modifiers cannot have more than two index registers."); // oops, only 2 regs allowed per ModRm! return *this; }
// Generates a 'reduced' ModSib form, which has valid Base, Index, and Scale values. // Necessary because by default ModSib compounds registers into Index when possible. // // If the ModSib is in illegal form ([Base + Index*5] for example) then an assertion // followed by an InvalidParameter Exception will be tossed around in haphazard // fashion. // // Optimization Note: Currently VC does a piss poor job of inlining this, even though // constant propagation *should* resove it to little or no code (VC's constprop fails // on C++ class initializers). There is a work around [using array initializers instead] // but it's too much trouble for code that isn't performance critical anyway. // And, with luck, maybe VC10 will optimize it better and make it a non-issue. :D // void xIndirectVoid::Reduce() { if( Index.IsStackPointer() ) { // esp cannot be encoded as the index, so move it to the Base, if possible. // note: intentionally leave index assigned to esp also (generates correct // encoding later, since ESP cannot be encoded 'alone') pxAssert( Scale == 0 ); // esp can't have an index modifier! pxAssert( Base.IsEmpty() ); // base must be empty or else! Base = Index; return; } // If no index reg, then load the base register into the index slot. if( Index.IsEmpty() ) { Index = Base; Scale = 0; if( !Base.IsStackPointer() ) // prevent ESP from being encoded 'alone' Base = xEmptyReg; return; } // The Scale has a series of valid forms, all shown here: switch( Scale ) { case 0: break; case 1: Scale = 0; break; case 2: Scale = 1; break; case 3: // becomes [reg*2+reg] pxAssertDev( Base.IsEmpty(), "Cannot scale an Index register by 3 when Base is not empty!" ); Base = Index; Scale = 1; break; case 4: Scale = 2; break; case 5: // becomes [reg*4+reg] pxAssertDev( Base.IsEmpty(), "Cannot scale an Index register by 5 when Base is not empty!" ); Base = Index; Scale = 2; break; case 6: // invalid! pxAssumeDev( false, "x86 asm cannot scale a register by 6." ); break; case 7: // so invalid! pxAssumeDev( false, "x86 asm cannot scale a register by 7." ); break; case 8: Scale = 3; break; case 9: // becomes [reg*8+reg] pxAssertDev( Base.IsEmpty(), "Cannot scale an Index register by 9 when Base is not empty!" ); Base = Index; Scale = 3; break; jNO_DEFAULT } }
void SIO_CommandWrite(u8 value,int way) { PAD_LOG("sio write8 %x", value); // PAD COMMANDS switch (sio.padst) { case 1: SIO_INT(); if ((value&0x40) == 0x40) { sio.padst = 2; sio.parp = 1; switch (sio.CtrlReg&0x2002) { case 0x0002: sio.packetsize ++; // Total packet size sent sio.buf[sio.parp] = PADpoll(value); break; case 0x2002: sio.packetsize ++; // Total packet size sent sio.buf[sio.parp] = PADpoll(value); break; } if (!(sio.buf[sio.parp] & 0x0f)) { sio.bufcount = 2 + 32; } else { sio.bufcount = 2 + (sio.buf[sio.parp] & 0x0f) * 2; } } else sio.padst = 0; return; case 2: sio.parp++; switch (sio.CtrlReg&0x2002) { case 0x0002: sio.packetsize ++; sio.buf[sio.parp] = PADpoll(value); break; case 0x2002: sio.packetsize ++; sio.buf[sio.parp] = PADpoll(value); break; } if (sio.parp == sio.bufcount) { sio.padst = 0; return; } SIO_INT(); return; case 3: // No pad connected. sio.parp++; if (sio.parp == sio.bufcount) { sio.padst = 0; return; } SIO_INT(); return; } // MEMORY CARD COMMANDS switch (sio.mcdst) { case 1: { sio.packetsize++; SIO_INT(); if (sio.rdwr) { sio.parp++; return; } sio.parp = 1; const char* log_cmdname = ""; switch (value) { case 0x11: // RESET log_cmdname = "Reset1"; sio.bufcount = 8; memset8<0xff>(sio.buf); sio.buf[3] = sio.terminator; sio.buf[2] = '+'; sio.mcdst = 99; sio2.packet.recvVal3 = 0x8c; break; // FIXME : Why are there two identical cases for resetting the // memorycard(s)? there doesn't appear to be anything dealing with // card slots here. --air case 0x12: // RESET log_cmdname = "Reset2"; sio.bufcount = 8; memset8<0xff>(sio.buf); sio.buf[3] = sio.terminator; sio.buf[2] = '+'; sio.mcdst = 99; sio2.packet.recvVal3 = 0x8c; break; case 0x81: // COMMIT log_cmdname = "Commit"; sio.bufcount = 8; memset8<0xff>(sio.buf); sio.mcdst = 99; sio.buf[3] = sio.terminator; sio.buf[2] = '+'; sio2.packet.recvVal3 = 0x8c; if(value == 0x81) { if(sio.mc_command==0x42) sio2.packet.recvVal1 = 0x1600; // Writing else if(sio.mc_command==0x43) sio2.packet.recvVal1 = 0x1700; // Reading } break; case 0x21: case 0x22: case 0x23: // SECTOR SET log_cmdname = "SetSector"; sio.bufcount = 8; sio.mcdst = 99; sio.sector=0; sio.k=0; memset8<0xff>(sio.buf); sio2.packet.recvVal3 = 0x8c; sio.buf[8]=sio.terminator; sio.buf[7]='+'; break; case 0x24: break; case 0x25: break; case 0x26: { log_cmdname = "GetInfo"; const uint port = sio.GetMemcardIndex(); const uint slot = sio.activeMemcardSlot[port]; mc_command_0x26_tag cmd = mc_sizeinfo_8mb; PS2E_McdSizeInfo info; info.SectorSize = cmd.sectorSize; info.EraseBlockSizeInSectors = cmd.eraseBlocks; info.McdSizeInSectors = cmd.mcdSizeInSectors; SysPlugins.McdGetSizeInfo( port, slot, info ); pxAssumeDev( cmd.mcdSizeInSectors >= mc_sizeinfo_8mb.mcdSizeInSectors, "Mcd plugin returned an invalid memorycard size: Cards smaller than 8MB are not supported." ); cmd.sectorSize = info.SectorSize; cmd.eraseBlocks = info.EraseBlockSizeInSectors; cmd.mcdSizeInSectors = info.McdSizeInSectors; // Recalculate the xor summation // This uses a trick of removing the known xor values for a default 8mb memorycard (for which the XOR // was calculated), and replacing it with our new values. apply_xor( cmd.mc_xor, mc_sizeinfo_8mb.sectorSize ); apply_xor( cmd.mc_xor, mc_sizeinfo_8mb.eraseBlocks ); apply_xor( cmd.mc_xor, mc_sizeinfo_8mb.mcdSizeInSectors ); apply_xor( cmd.mc_xor, cmd.sectorSize ); apply_xor( cmd.mc_xor, cmd.eraseBlocks ); apply_xor( cmd.mc_xor, cmd.mcdSizeInSectors ); sio.bufcount = 12; sio.mcdst = 99; sio2.packet.recvVal3 = 0x83; memset8<0xff>(sio.buf); memcpy_fast(&sio.buf[2], &cmd, sizeof(cmd)); sio.buf[12]=sio.terminator; } break; case 0x27: case 0x28: case 0xBF: log_cmdname = "NotSure"; // FIXME !! sio.bufcount = 4; sio.mcdst = 99; sio2.packet.recvVal3 = 0x8b; memset8<0xff>(sio.buf); sio.buf[4]=sio.terminator; sio.buf[3]='+'; break; // FIXME ? // sio.lastsector and sio.mode are unused. case 0x42: // WRITE log_cmdname = "Write"; //sio.mode = 0; goto __doReadWrite; case 0x43: // READ log_cmdname = "Read"; //sio.lastsector = sio.sector; // Reading goto __doReadWrite; case 0x82: log_cmdname = "Read(?)"; // FIXME !! //if(sio.lastsector==sio.sector) sio.mode = 2; __doReadWrite: sio.bufcount =133; sio.mcdst = 99; memset8<0xff>(sio.buf); sio.buf[133]=sio.terminator; sio.buf[132]='+'; break; case 0xf0: case 0xf1: case 0xf2: log_cmdname = "NoClue"; // FIXME !! sio.mcdst = 99; break; case 0xf3: case 0xf7: log_cmdname = "NoClueHereEither"; // FIXME !! sio.bufcount = 4; sio.mcdst = 99; memset8<0xff>(sio.buf); sio.buf[4]=sio.terminator; sio.buf[3]='+'; break; case 0x52: log_cmdname = "FixMe"; // FIXME !! sio.rdwr = 1; memset8<0xff>(sio.buf); sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+'; break; case 0x57: log_cmdname = "FixMe"; // FIXME !! sio.rdwr = 2; memset8<0xff>(sio.buf); sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+'; break; default: log_cmdname = "Unknown"; sio.mcdst = 0; memset8<0xff>(sio.buf); sio.buf[sio.bufcount]=sio.terminator; sio.buf[sio.bufcount-1]='+'; } MEMCARDS_LOG("MC(%d) command 0x%02X [%s]", sio.GetMemcardIndex()+1, value, log_cmdname); sio.mc_command = value; } return; // END CASE 1. // FURTHER PROCESSING OF THE MEMORY CARD COMMANDS case 99: { sio.packetsize++; sio.parp++; switch(sio.mc_command) { // SET_ERASE_PAGE; the next erase commands will *clear* data starting with the page set here case 0x21: // SET_WRITE_PAGE; the next write commands will commit data starting with the page set here case 0x22: // SET_READ_PAGE; the next read commands will return data starting with the page set here case 0x23: if (sio.parp==2)sio.sector|=(value & 0xFF)<< 0; if (sio.parp==3)sio.sector|=(value & 0xFF)<< 8; if (sio.parp==4)sio.sector|=(value & 0xFF)<<16; if (sio.parp==5)sio.sector|=(value & 0xFF)<<24; if (sio.parp==6) { if (sio_xor((u8 *)&sio.sector, 4) == value) MEMCARDS_LOG("MC(%d) SET PAGE sio.sector, sector=0x%04X", sio.GetMemcardIndex()+1, sio.sector); else MEMCARDS_LOG("MC(%d) SET PAGE XOR value ERROR 0x%02X != ^0x%02X", sio.GetMemcardIndex()+1, value, sio_xor((u8 *)&sio.sector, 4)); } break; // SET_TERMINATOR; reads the new terminator code case 0x27: if(sio.parp==2) { sio.terminator = value; sio.buf[4] = value; MEMCARDS_LOG("MC(%d) SET TERMINATOR command, value=0x%02X", sio.GetMemcardIndex()+1, value); } break; // GET_TERMINATOR; puts in position 3 the current terminator code and in 4 the default one // depending on the param case 0x28: if(sio.parp == 2) { sio.buf[2] = '+'; sio.buf[3] = sio.terminator; //if(value == 0) sio.buf[4] = 0xFF; sio.buf[4] = 0x55; MEMCARDS_LOG("MC(%d) GET TERMINATOR command, value=0x%02X", sio.GetMemcardIndex()+1, value); } break; // WRITE DATA case 0x42: if (sio.parp==2) { sio.bufcount=5+value; memset8<0xff>(sio.buf); sio.buf[sio.bufcount-1]='+'; sio.buf[sio.bufcount]=sio.terminator; MEMCARDS_LOG("MC(%d) WRITE command, size=0x%02X", sio.GetMemcardIndex()+1, value); } else if ((sio.parp>2) && (sio.parp<sio.bufcount-2)) { sio.buf[sio.parp]=value; //MEMCARDS_LOG("MC(%d) WRITING 0x%02X", sio.GetMemcardIndex()+1, value); } else if (sio.parp==sio.bufcount-2) { if (sio_xor(&sio.buf[3], sio.bufcount-5)==value) { _SaveMcd(&sio.buf[3], (512+16)*sio.sector+sio.k, sio.bufcount-5); sio.buf[sio.bufcount-1]=value; sio.k+=sio.bufcount-5; } else { MEMCARDS_LOG("MC(%d) write XOR value error 0x%02X != ^0x%02X", sio.GetMemcardIndex()+1, value, sio_xor(&sio.buf[3], sio.bufcount-5)); } } break; // READ DATA case 0x43: if (sio.parp==2) { //int i; sio.bufcount=value+5; sio.buf[3]='+'; MEMCARDS_LOG("MC(%d) READ command, size=0x%02X", sio.GetMemcardIndex()+1, value); _ReadMcd(&sio.buf[4], (512+16)*sio.sector+sio.k, value); /*if(sio.mode==2) { int j; for(j=0; j < value; j++) sio.buf[4+j] = ~sio.buf[4+j]; }*/ sio.k+=value; sio.buf[sio.bufcount-1]=sio_xor(&sio.buf[4], value); sio.buf[sio.bufcount]=sio.terminator; } break; // INTERNAL ERASE case 0x82: if(sio.parp==2) { sio.buf[2]='+'; sio.buf[3]=sio.terminator; //if (sio.k != 0 || (sio.sector & 0xf) != 0) // Console.Warning("saving : odd position for erase."); _EraseMCDBlock((512+16)*(sio.sector&~0xf)); /* memset(sio.buf, -1, 256); _SaveMcd(sio.buf, (512+16)*sio.sector, 256); _SaveMcd(sio.buf, (512+16)*sio.sector+256, 256); _SaveMcd(sio.buf, (512+16)*sio.sector+512, 16); sio.buf[2]='+'; sio.buf[3]=sio.terminator;*/ //sio.buf[sio.bufcount] = sio.terminator; MEMCARDS_LOG("MC(%d) INTERNAL ERASE command 0x%02X", sio.GetMemcardIndex()+1, value); } break; // CARD AUTHENTICATION CHECKS case 0xF0: if (sio.parp==2) { MEMCARDS_LOG("MC(%d) CARD AUTH :0x%02X", sio.GetMemcardIndex()+1, value); switch(value){ case 1: case 2: case 4: case 15: case 17: case 19: sio.bufcount=13; memset8<0xff>(sio.buf); sio.buf[12] = 0; // Xor value of data from index 4 to 11 sio.buf[3]='+'; sio.buf[13] = sio.terminator; break; case 6: case 7: case 11: sio.bufcount=13; memset8<0xff>(sio.buf); sio.buf[12]='+'; sio.buf[13] = sio.terminator; break; default: sio.bufcount=4; memset8<0xff>(sio.buf); sio.buf[3]='+'; sio.buf[4] = sio.terminator; } } break; } if (sio.bufcount<=sio.parp) sio.mcdst = 0; } return; // END CASE 99. } switch (sio.mtapst) { case 0x1: sio.packetsize++; sio.parp = 1; SIO_INT(); switch(value) { case 0x12: // Query number of pads supported. sio.buf[3] = 4; sio.mtapst = 2; sio.bufcount = 5; break; case 0x13: // Query number of memcards supported. sio.buf[3] = 4; sio.mtapst = 2; sio.bufcount = 5; break; case 0x21: // Set pad slot. sio.mtapst = value; sio.bufcount = 6; // No idea why this is 6, saved from old code. break; case 0x22: // Set memcard slot. sio.mtapst = value; sio.bufcount = 6; // No idea why this is 6, saved from old code. break; } // Commented out values are from original code. They break multitap in bios. sio.buf[sio.bufcount-1]=0;//'+'; sio.buf[sio.bufcount]=0;//'Z'; return; case 0x2: sio.packetsize++; sio.parp++; if (sio.bufcount<=sio.parp) sio.mcdst = 0; SIO_INT(); return; case 0x21: // Set pad slot. sio.packetsize++; sio.parp++; sio.mtapst = 2; if (sio.CtrlReg & 2) { int port = sio.GetMultitapPort(); if (IsMtapPresent(port)) sio.activePadSlot[port] = value; } SIO_INT(); return; case 0x22: // Set memcard slot. sio.packetsize++; sio.parp++; sio.mtapst = 2; if (sio.CtrlReg & 2) { int port = sio.GetMultitapPort(); if (IsMtapPresent(port)) sio.activeMemcardSlot[port] = value; } SIO_INT(); return; } if(sio.count == 1 || way == 0) InitializeSIO(value); }