public AdLibChannel(IOpl opl, byte[] musicData, ushort startOfData) { _opl = opl; _musicData = musicData; _channelData.loopPoint = startOfData; _channelData.eventDataPtr = startOfData; _channelData.channelActive = true; _channelData.tremoVibro = 0; _channelData.assignedInstrument = 0xFF; _channelData.channelVolume = 0x7F; _channelData.nextEventTime = GetNextEventTime(); _channelData.adlibChannelNumber = _channelData.lastCommand = _channelData.note = _channelData.adlibReg1 = _channelData.adlibReg2 = _channelData.freqOffset = 0; _channelData.frequency = 0; _channelData.instrumentData = null; ushort instrumentDataLoc; if (SystemVars.Instance.GameVersion.Version.Minor == 109) { //instrumentDataLoc = (_musicData[0x11D0] << 8) | _musicData[0x11CF]; //_frequenceTable = (uint16 *)(_musicData + 0x835); //_registerTable = _musicData + 0xE35; //_opOutputTable = _musicData + 0xE47; //_adlibRegMirror = _musicData + 0xF4A; instrumentDataLoc = _musicData.ToUInt16(0x1204); _frequenceTable = new UShortAccess(_musicData, 0x868); _registerTable = new ByteAccess(_musicData, 0xE68); _opOutputTable = new ByteAccess(_musicData, 0xE7A); _adlibRegMirror = new ByteAccess(_musicData, 0xF7D); } else if (SystemVars.Instance.GameVersion.Version.Minor == 267) { instrumentDataLoc = _musicData.ToUInt16(0x11FB); _frequenceTable = new UShortAccess(_musicData, 0x7F4); _registerTable = new ByteAccess(_musicData, 0xDF4); _opOutputTable = new ByteAccess(_musicData, 0xE06); _adlibRegMirror = new ByteAccess(_musicData, 0xF55); } else { instrumentDataLoc = _musicData.ToUInt16(0x1205); _frequenceTable = new UShortAccess(_musicData, 0x7FE); _registerTable = new ByteAccess(_musicData, 0xDFE); _opOutputTable = new ByteAccess(_musicData, 0xE10); _adlibRegMirror = new ByteAccess(_musicData, 0xF5F); } _instrumentMap = new ByteAccess(_musicData, instrumentDataLoc); _instruments = new StructAccess<InstrumentStruct>(_musicData, instrumentDataLoc + 0x80); }
protected override void SetupPointers() { if (SystemVars.Instance.GameVersion.Version.Minor == 109) { _musicDataLoc = _musicData.ToUInt16(0x79B); _sysExSequence = new ByteAccess(_musicData, 0x1EF2); } else { _musicDataLoc = _musicData.ToUInt16(0x7DC); _sysExSequence = new ByteAccess(_musicData, _musicData.ToUInt16(0x7E0)); } }
/// <summary> /// Send packets over the opened socket (internal function only, no error checking, locking, etc. mechanism is implemented) /// Only CRC is calculated before sending packet /// </summary> /// <param name="in_endpoint"></param> /// <param name="in_packet"></param> private void InternalPacketSend(EndPoint in_endpoint, byte[] in_packet) { // copy packet to the buffer in_packet.CopyTo(m_transmit_buffer, 0); // calculate and store CRC UInt16 crc; crc = CRC16.CalculateForBlock(CRC16.InitValue, in_packet, in_packet.Length); m_transmit_buffer[in_packet.Length] = ByteAccess.LowByte(crc); m_transmit_buffer[in_packet.Length + 1] = ByteAccess.HighByte(crc); // send packet m_client.BeginSendTo(m_transmit_buffer, 0, in_packet.Length + PacketConstants.PacketCRCLength, 0, in_endpoint, new AsyncCallback(SendCallback), this); }
public uint LowTextManager(ByteAccess ascii, int width, byte pen) { _textCount++; if (_textCount > MaxTextObs) throw new InvalidOperationException("Text::lowTextManager: MAX_TEXT_OBS exceeded"); uint textObjId = ObjectMan.TEXT_sect * ObjectMan.ITM_PER_SEC - 1; do { textObjId++; } while (_objMan.FetchObject(textObjId).status != 0); // okay, found a free text object _objMan.FetchObject(textObjId).status = Logic.STAT_FORE; MakeTextSprite((byte)textObjId, ascii, (ushort)width, pen); return textObjId; }
public void Initialize() { ushort cnt; for (cnt = 0; cnt < TOTAL_SECTIONS; cnt++) _liveList[cnt] = 0; // we don't need to close the files here. When this routine is // called, the memory was flushed() anyways, so these resources // already *are* closed. _liveList[128] = _liveList[129] = _liveList[130] = _liveList[131] = _liveList[133] = _liveList[134] = _liveList[145] = _liveList[146] = _liveList[TEXT_sect] = 1; for (cnt = 0; cnt < TOTAL_SECTIONS; cnt++) { if (_liveList[cnt] != 0) _cptData[cnt] = new ByteAccess(_resMan.CptResOpen(_objectList[cnt]), Header.Size); else _cptData[cnt] = null; } }
/// <summary> /// Serializes packet header and pushes header and packet data into the queue with CRC calculation /// </summary> /// <param name="in_interface"></param> /// <param name="in_packet_header"></param> /// <param name="in_packet_data"></param> /// <returns></returns> public bool Push(byte in_interface, object in_packet_header, byte[] in_packet_data) { int packet_index; UInt16 crc; // reserve storage for packet packet_index = ReservePushBuffer(); if (packet_index == InvalidPacketIndex) { return(false); } // calculate packet size int raw_packet_size = Marshal.SizeOf(in_packet_header) + in_packet_data.Length; // serialize packet header byte[] raw_packet_buffer = m_packets[packet_index].Buffer; GCHandle handle = GCHandle.Alloc(raw_packet_buffer, GCHandleType.Pinned); IntPtr buffer = handle.AddrOfPinnedObject(); Marshal.StructureToPtr(in_packet_header, buffer, false); handle.Free(); // copy packet data in_packet_data.CopyTo(raw_packet_buffer, Marshal.SizeOf(in_packet_header)); // update CRC crc = CRC16.CalculateForBlock(CRC16.InitValue, raw_packet_buffer, raw_packet_size); raw_packet_buffer[raw_packet_size + 0] = ByteAccess.LowByte(crc); raw_packet_buffer[raw_packet_size + 1] = ByteAccess.HighByte(crc); // change buffer state m_packets[packet_index].Interface = in_interface; m_packets[packet_index].Length = (byte)(raw_packet_size + PacketConstants.PacketCRCLength); m_packets[packet_index].Timestamp = DateTime.Now; m_packets[packet_index].State = PacketBufferState.Valid; return(true); }
public ControlButton(ushort x, ushort y, uint resId, ButtonIds id, byte flag, ResMan pResMan, byte[] screenBuf, ISystem system) { _x = x; _y = y; _id = id; _flag = flag; _resId = resId; _resMan = pResMan; _frameIdx = 0; _resMan.ResOpen(_resId); FrameHeader tmp = new FrameHeader(_resMan.FetchFrame(_resMan.FetchRes(_resId), 0)); _width = _resMan.ReadUInt16(tmp.width); _width = (ushort)((_width > Screen.SCREEN_WIDTH) ? Screen.SCREEN_WIDTH : _width); _height = _resMan.ReadUInt16(tmp.height); if ((x == 0) && (y == 0)) { // center the frame (used for panels); _x = (ushort)((((640 - _width) / 2) < 0) ? 0 : ((640 - _width) / 2)); _y = (ushort)((((480 - _height) / 2) < 0) ? 0 : ((480 - _height) / 2)); } _dstBuf = new ByteAccess(screenBuf, _y * Screen.SCREEN_WIDTH + _x); _system = system; }
protected override void SetupPointers() { if (SystemVars.Instance.GameVersion.Version.Minor == 109) { // disk demo uses a different AdLib driver version, some offsets have changed //_musicDataLoc = (_musicData[0x11CC] << 8) | _musicData[0x11CB]; //_initSequence = _musicData + 0xEC8; _musicDataLoc = _musicData.ToUInt16(0x1200); _initSequence = new ByteAccess(_musicData, 0xEFB); } else if (SystemVars.Instance.GameVersion.Version.Minor == 267) { _musicDataLoc = _musicData.ToUInt16(0x11F7); _initSequence = new ByteAccess(_musicData, 0xE87); } else { _musicDataLoc = _musicData.ToUInt16(0x1201); _initSequence = new ByteAccess(_musicData, 0xE91); } _nextMusicPoll = 0; }
private bool ProcessPatchSysEx(ByteAccess sysExData) { byte[] sysExBuf = new byte[15]; byte crc = 0; if ((sysExData[0] & 0x80) != 0) { return(false); } // decompress data from stream sysExBuf[0] = 0x41; sysExBuf[1] = 0x10; sysExBuf[2] = 0x16; sysExBuf[3] = 0x12; sysExBuf[4] = 0x5; sysExBuf[5] = (byte)(sysExData[0] >> 4); // patch offset part 1 sysExBuf[6] = (byte)((sysExData[0] & 0xF) << 3); // patch offset part 2 sysExBuf[7] = (byte)(sysExData[1] >> 6); // timbre group sysExBuf[8] = (byte)(sysExData[1] & 0x3F); // timbre num sysExBuf[9] = (byte)(sysExData[2] & 0x3F); // key shift sysExBuf[10] = (byte)(sysExData[3] & 0x7F); // fine tune sysExBuf[11] = (byte)(sysExData[4] & 0x7F); // bender range sysExBuf[12] = (byte)(sysExData[2] >> 6); // assign mode sysExBuf[13] = (byte)(sysExData[3] >> 7); // reverb switch for (byte cnt = 4; cnt < 14; cnt++) { crc -= sysExBuf[cnt]; } sysExBuf[14] = (byte)(crc & 0x7F); // crc _midiDrv.SysEx(sysExBuf, 15); // We delay the time it takes to send the sysEx plus an // additional 40ms, which is required for MT-32 rev00, // to assure no buffer overflow or missing bytes ServiceLocator.Platform.Sleep(17 * 1000 / 3125 + 40); return(true); }
private ushort AnalyzeSentence(ByteAccess textSrc, ushort maxWidth, LineInfo[] line) { ushort lineNo = 0; var text = new ByteAccess(textSrc.Data, textSrc.Offset); var firstWord = true; while (text.Offset < text.Data.Length && text[0] != 0) { ushort wordWidth = 0; ushort wordLength = 0; while (text.Offset < text.Data.Length && (text[0] != ' ') && text[0] != 0) { wordWidth = (ushort)(wordWidth + CharWidth(text[0]) - Overlap); wordLength++; text.Offset++; } if (text.Offset < text.Data.Length && text[0] == ' ') text.Offset++; wordWidth += Overlap; // no overlap on final letter of word! if (firstWord) { // first word on first line, so no separating SPACE needed line[0].Width = wordWidth; line[0].Length = wordLength; firstWord = false; } else { // see how much extra space this word will need to fit on current line // (with a separating space character - also overlapped) var spaceNeeded = (ushort)(_joinWidth + wordWidth); if (line[lineNo].Width + spaceNeeded <= maxWidth) { line[lineNo].Width += spaceNeeded; line[lineNo].Length = (ushort)(line[lineNo].Length + 1 + wordLength); // NB. space+word characters } else { // put word (without separating SPACE) at start of next line lineNo++; Debug.Assert(lineNo < MaxLines); line[lineNo].Width = wordWidth; line[lineNo].Length = wordLength; } } } return (ushort)(lineNo + 1); // return no of lines }
private ushort CopyChar(byte ch, ByteAccess sprPtr, ushort sprWidth, byte pen) { if (ch < ' ') ch = 64; var chFrame = new FrameHeader(_resMan.FetchFrame(_font, (uint)(ch - ' '))); var chData = FrameHeader.Size; var dest = sprPtr; ByteAccess decChr; ushort frameHeight; if (SystemVars.Platform == Platform.PSX) { frameHeight = (ushort)(_resMan.ReadUInt16(chFrame.height) / 2); if (_fontId == SwordRes.CZECH_GAME_FONT) { //Czech game fonts are compressed var decBuf = new byte[_resMan.ReadUInt16(chFrame.width) * (_resMan.ReadUInt16(chFrame.height) / 2)]; Screen.DecompressHIF(chFrame.Data.Data, chFrame.Data.Offset + chData, decBuf); decChr = new ByteAccess(decBuf); } else //Normal game fonts are not compressed decChr = new ByteAccess(chFrame.Data.Data, chFrame.Data.Offset + chData); } else { frameHeight = _resMan.ReadUInt16(chFrame.height); decChr = new ByteAccess(chFrame.Data.Data, chFrame.Data.Offset + chData); } for (ushort cnty = 0; cnty < frameHeight; cnty++) { for (ushort cntx = 0; cntx < _resMan.ReadUInt16(chFrame.width); cntx++) { if (decChr[0] == LetterCol) dest[cntx] = pen; else if (((decChr[0] == BorderCol) || (decChr[0] == BorderColPsx)) && (dest[cntx] == 0)) // don't do a border if there's already a color underneath (chars can overlap) dest[cntx] = BorderCol; decChr.Offset++; } dest.Offset += sprWidth; } return _resMan.ReadUInt16(chFrame.width); }
/// <summary> /// Main thread function /// </summary> public void Run() { bool event_occured; UInt16 crc; int received_data_pos; int received_packet_pos; // init SLIPs m_receiver_slip.ResetDecoder(); try { m_serial_port = new SerialPort(PortName, BaudRate, Parity.None, 8, StopBits.One); m_serial_port.ReadTimeout = 50; m_serial_port.WriteTimeout = 50; m_serial_port.ReadBufferSize = 4096; m_serial_port.Open(); } catch { return; } // init m_upstream_bytes = 0; m_downstream_bytes = 0; received_data_pos = 0; received_packet_pos = 0; // start data reception m_read_pending = true; m_serial_port.BaseStream.BeginRead(m_receive_data_buffer, 0, m_receive_data_buffer.Length, m_receiver_callback, this); // communication loop while (!m_stop_requested) { // wait for event event_occured = m_thread_event.WaitOne(ThreadWaitTimeout); // exit loop if thread must be stopped if (m_stop_requested) { break; } // process received data if (m_received_data_length > 0) { received_data_pos = 0; while (received_data_pos < m_received_data_length) { // SLIP decode data if (m_receiver_slip.DecodeBlock(m_receive_data_buffer, ref received_data_pos, m_received_data_length, m_receive_packet_buffer, ref received_packet_pos)) { // packet decoded -> check CRC if (received_packet_pos > (Marshal.SizeOf(typeof(PacketBase)) + PacketConstants.PacketCRCLength)) { m_received_packet_length = received_packet_pos; crc = CRC16.CalculateForBlock(CRC16.InitValue, m_receive_packet_buffer, m_received_packet_length - PacketConstants.PacketCRCLength); if (ByteAccess.LowByte(crc) == m_receive_packet_buffer[m_received_packet_length - 2] && ByteAccess.HighByte(crc) == m_receive_packet_buffer[m_received_packet_length - 1]) { // CRC OK -> continue processing received packet PacketType type = (PacketType)m_receive_data_buffer[PacketConstants.TypeOffset]; // update statistics Interlocked.Add(ref m_upstream_bytes, m_received_data_length); // process received data if (m_received_packet_length <= PacketConstants.PacketMaxLength) { m_communication_manager.StoreReceivedPacket(m_communication_channel_index, m_receive_packet_buffer, (byte)m_received_packet_length); } } } // restart packet decoding received_packet_pos = 0; } m_read_pending = false; } } // restart reception if (!m_read_pending) { try { m_received_data_length = 0; m_read_pending = true; m_serial_port.BaseStream.BeginRead(m_receive_data_buffer, 0, m_receive_data_buffer.Length, m_receiver_callback, this); } catch { // stop thread because of the unexpected error m_stop_requested = true; m_thread_event.Set(); } } } // close socket m_serial_port.Close(); m_serial_port = null; // thread is finished m_thread_stopped.Set(); }
private void BlitBlockClear(ushort x, ushort y, ByteAccess data) { var dest = y * SCRNGRID_Y * _scrnSizeX + x * SCRNGRID_X; for (byte cnty = 0; cnty < (SystemVars.Platform == Platform.PSX ? SCRNGRID_Y / 2 : SCRNGRID_Y); cnty++) { for (byte cntx = 0; cntx < SCRNGRID_X; cntx++) if (data[cntx] != 0) _screenBuf[dest + cntx] = data[cntx]; if (SystemVars.Platform == Platform.PSX) { dest += _scrnSizeX; for (byte cntx = 0; cntx < SCRNGRID_X; cntx++) if (data[cntx] != 0) _screenBuf[dest + cntx] = data[cntx]; } data.Offset += SCRNGRID_X; dest += _scrnSizeX; } }
private void FastShrink(ByteAccess src, ushort width, ushort height, uint scale, byte[] dest) { uint resHeight = (height * scale) >> 8; uint resWidth = (width * scale) >> 8; uint step = 0x10000 / scale; byte[] columnTab = new byte[160]; uint res = step >> 1; for (ushort cnt = 0; cnt < resWidth; cnt++) { columnTab[cnt] = (byte)(res >> 8); res += step; } uint newRow = step >> 1; uint oldRow = 0; var destPos = 0; var srcPos = 0; ushort lnCnt; for (lnCnt = 0; lnCnt < resHeight; lnCnt++) { while (oldRow < (newRow >> 8)) { oldRow++; srcPos += width; } for (ushort colCnt = 0; colCnt < resWidth; colCnt++) { dest[destPos++] = src[srcPos + columnTab[colCnt]]; } newRow += step; } // scaled, now stipple shadows if there are any for (lnCnt = 0; lnCnt < resHeight; lnCnt++) { ushort xCnt = (ushort)(lnCnt & 1); destPos = (int)(lnCnt * resWidth + (lnCnt & 1)); while (xCnt < resWidth) { if (dest[destPos] == 200) dest[destPos] = 0; destPos += 2; xCnt += 2; } } }
private void VertMaskSub(UShortAccess grid, int gridOfs, int screenPtr, uint layerId) { for (var cntx = 0; cntx < _sprHeight; cntx++) { // start_x | block_loop if (grid[gridOfs] != 0) { if ((grid[gridOfs] & 0x8000) == 0) { var gridVal = grid[gridOfs] - 1; gridVal *= GridW * GridH; var dataSrc = new ByteAccess(SkyEngine.ItemList[Logic.ScriptVariables[(int) layerId]], gridVal); var dataTrg = screenPtr; for (var grdCntY = 0; grdCntY < GridH; grdCntY++) { for (var grdCntX = 0; grdCntX < GridW; grdCntX++) if (dataSrc[grdCntX] != 0) Current[dataTrg + grdCntX] = dataSrc[grdCntX]; dataSrc.Offset += GridW; dataTrg += GameScreenWidth; } } // dummy_end: screenPtr -= GridH * GameScreenWidth; gridOfs -= GridX; } else return; } // next_x }
private void DrawSprite(ByteAccess sprData, ushort sprX, ushort sprY, ushort sprWidth, ushort sprHeight, ushort sprPitch) { var dest = new ByteAccess(_screenBuf, sprY * _scrnSizeX + sprX); for (ushort cnty = 0; cnty < sprHeight; cnty++) { for (ushort cntx = 0; cntx < sprWidth; cntx++) if (sprData[cntx] != 0) dest[cntx] = sprData[cntx]; if (SystemVars.Platform == Platform.PSX) { //On PSX version we need to double horizontal lines dest.Offset += _scrnSizeX; for (ushort cntx = 0; cntx < sprWidth; cntx++) if (sprData[cntx] != 0) dest[cntx] = sprData[cntx]; } sprData.Offset += sprPitch; dest.Offset += _scrnSizeX; } }
private bool ProcessPatchSysEx(ByteAccess sysExData) { byte[] sysExBuf = new byte[15]; byte crc = 0; if ((sysExData[0] & 0x80) != 0) return false; // decompress data from stream sysExBuf[0] = 0x41; sysExBuf[1] = 0x10; sysExBuf[2] = 0x16; sysExBuf[3] = 0x12; sysExBuf[4] = 0x5; sysExBuf[5] = (byte)(sysExData[0] >> 4); // patch offset part 1 sysExBuf[6] = (byte)((sysExData[0] & 0xF) << 3); // patch offset part 2 sysExBuf[7] = (byte)(sysExData[1] >> 6); // timbre group sysExBuf[8] = (byte)(sysExData[1] & 0x3F); // timbre num sysExBuf[9] = (byte)(sysExData[2] & 0x3F); // key shift sysExBuf[10] = (byte)(sysExData[3] & 0x7F); // fine tune sysExBuf[11] = (byte)(sysExData[4] & 0x7F); // bender range sysExBuf[12] = (byte)(sysExData[2] >> 6); // assign mode sysExBuf[13] = (byte)(sysExData[3] >> 7); // reverb switch for (byte cnt = 4; cnt < 14; cnt++) crc -= sysExBuf[cnt]; sysExBuf[14] = (byte)(crc & 0x7F); // crc _midiDrv.SysEx(sysExBuf, 15); // We delay the time it takes to send the sysEx plus an // additional 40ms, which is required for MT-32 rev00, // to assure no buffer overflow or missing bytes ServiceLocator.Platform.Sleep(17 * 1000 / 3125 + 40); return true; }
private void ProcessImage(uint id) { FrameHeader frameHead; int scale; var compact = _objMan.FetchObject(id); if (compact.type == TYPE_TEXT) frameHead = new FrameHeader(_textMan.GiveSpriteData((byte)compact.target)); else frameHead = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes((uint)compact.resource), (uint)compact.frame)); ushort spriteX = (ushort)compact.anim_x; ushort spriteY = (ushort)compact.anim_y; if ((compact.status & STAT_SHRINK) != 0) { scale = (compact.scale_a * compact.ycoord + compact.scale_b) / 256; spriteX = (ushort)(spriteX + (_resMan.ReadInt16(frameHead.offsetX) * scale) / 256); spriteY = (ushort)(spriteY + (_resMan.ReadInt16(frameHead.offsetY) * scale) / 256); } else { scale = 256; spriteX = (ushort)(spriteX + _resMan.ReadInt16(frameHead.offsetX)); spriteY = (ushort)(spriteY + _resMan.ReadInt16(frameHead.offsetY)); } var sprData = new ByteAccess(frameHead.Data.Data, frameHead.Data.Offset + FrameHeader.Size); if (SystemVars.Platform == Platform.PSX && compact.type != TYPE_TEXT) { // PSX sprites are compressed with HIF var hifBuf = new byte[_resMan.ReadUInt16(frameHead.width) * _resMan.ReadUInt16(frameHead.height) / 2]; DecompressHIF(sprData.Data, sprData.Offset, hifBuf); sprData = new ByteAccess(hifBuf); } else if (frameHead.runTimeComp[3] == '7') { // RLE7 encoded? DecompressRLE7(sprData.Data, sprData.Offset, _resMan.ReadUInt32(frameHead.compSize), _rleBuffer); sprData = new ByteAccess(_rleBuffer); } else if (frameHead.runTimeComp[3] == '0') { // RLE0 encoded? DecompressRLE0(sprData.Data, sprData.Offset, _resMan.ReadUInt32(frameHead.compSize), _rleBuffer); sprData = new ByteAccess(_rleBuffer); } else if (frameHead.runTimeComp[1] == 'I') { // new type var tonyBuf = new byte[_resMan.ReadUInt32(frameHead.width) * _resMan.ReadUInt16(frameHead.height)]; DecompressTony(sprData.Data, sprData.Offset, _resMan.ReadUInt32(frameHead.compSize), tonyBuf); sprData = new ByteAccess(tonyBuf); } ushort sprSizeX, sprSizeY; if ((compact.status & STAT_SHRINK) != 0) { //Clean shrink buffer to avoid corruption Array.Clear(_shrinkBuffer, 0, SHRINK_BUFFER_SIZE); if (SystemVars.Platform == Platform.PSX && (compact.resource != SwordRes.GEORGE_MEGA)) { // PSX Height shrinked sprites sprSizeX = (ushort)((scale * _resMan.ReadUInt16(frameHead.width)) / 256); sprSizeY = (ushort)((scale * (_resMan.ReadUInt16(frameHead.height))) / 256 / 2); FastShrink(sprData, _resMan.ReadUInt16(frameHead.width), (ushort)((_resMan.ReadUInt16(frameHead.height)) / 2), (uint)scale, _shrinkBuffer); } else if (SystemVars.Platform == Platform.PSX) { // PSX width/height shrinked sprites sprSizeX = (ushort)((scale * _resMan.ReadUInt16(frameHead.width)) / 256 / 2); sprSizeY = (ushort)((scale * _resMan.ReadUInt16(frameHead.height)) / 256 / 2); FastShrink(sprData, (ushort)(_resMan.ReadUInt16(frameHead.width) / 2), (ushort)(_resMan.ReadUInt16(frameHead.height) / 2), (uint)scale, _shrinkBuffer); } else { sprSizeX = (ushort)(scale * _resMan.ReadUInt16(frameHead.width) / 256); sprSizeY = (ushort)(scale * _resMan.ReadUInt16(frameHead.height) / 256); FastShrink(sprData, _resMan.ReadUInt16(frameHead.width), _resMan.ReadUInt16(frameHead.height), (uint)scale, _shrinkBuffer); } sprData = new ByteAccess(_shrinkBuffer); } else { sprSizeX = _resMan.ReadUInt16(frameHead.width); if (SystemVars.Platform == Platform.PSX) { // PSX sprites are half height sprSizeY = (ushort)(_resMan.ReadUInt16(frameHead.height) / 2); } else sprSizeY = _resMan.ReadUInt16(frameHead.height); } if ((compact.status & STAT_OVERRIDE) == 0) { //mouse size linked to exact size & coordinates of sprite box - shrink friendly if (_resMan.ReadUInt16((ushort)frameHead.offsetX) != 0 || _resMan.ReadUInt16((ushort)frameHead.offsetY) != 0) { //for megas the mouse area is reduced to account for sprite not //filling the box size is reduced to 1/2 width, 4/5 height compact.mouse_x1 = spriteX + sprSizeX / 4; compact.mouse_x2 = spriteX + 3 * sprSizeX / 4; compact.mouse_y1 = spriteY + sprSizeY / 10; compact.mouse_y2 = spriteY + 9 * sprSizeY / 10; } else { compact.mouse_x1 = spriteX; compact.mouse_x2 = spriteX + sprSizeX; compact.mouse_y1 = spriteY; compact.mouse_y2 = spriteY + sprSizeY; } } ushort sprPitch = sprSizeX; ushort incr; SpriteClipAndSet(ref spriteX, ref spriteY, ref sprSizeX, ref sprSizeY, out incr); if ((sprSizeX > 0) && (sprSizeY > 0)) { if (SystemVars.Platform != Platform.PSX || (compact.type == TYPE_TEXT) || (compact.resource == SwordRes.LVSFLY) || (compact.resource != SwordRes.GEORGE_MEGA && (sprSizeX < 260))) { sprData.Offset += incr; DrawSprite(sprData, spriteX, spriteY, sprSizeX, sprSizeY, sprPitch); } else if (((sprSizeX >= 260) && (sprSizeX < 450)) || ((compact.resource == SwordRes.GMWRITH) && (sprSizeX < 515)) // a psx shrinked sprite (1/2 width) || ((compact.resource == SwordRes.GMPOWER) && (sprSizeX < 515))) { // some needs to be hardcoded, headers don't give useful infos DrawPsxHalfShrinkedSprite(sprData.Data, sprData.Offset + incr, spriteX, spriteY, (ushort)(sprSizeX / 2), sprSizeY, (ushort)(sprPitch / 2)); } else if (sprSizeX >= 450) // A PSX double shrinked sprite (1/3 width) { DrawPsxFullShrinkedSprite(sprData.Data, sprData.Offset + incr, spriteX, spriteY, (ushort)(sprSizeX / 3), sprSizeY, (ushort)(sprPitch / 3)); } else // This is for psx half shrinked, walking george and remaining sprites { DrawPsxHalfShrinkedSprite(sprData.Data, sprData.Offset + incr, spriteX, spriteY, sprSizeX, sprSizeY, sprPitch); } if ((compact.status & STAT_FORE) == 0 && !(SystemVars.Platform == Platform.PSX && (compact.resource == SwordRes.MOUBUSY))) // Check fixes moue sprite being masked by layer, happens only on psx { VerticalMask(spriteX, spriteY, sprSizeX, sprSizeY); } } if (compact.type != TYPE_TEXT) _resMan.ResClose((uint)compact.resource); }
public FrameHeader(ByteAccess data) { Data = data; }
public void ShowFrame(ushort x, ushort y, uint resId, uint frameNo, byte[] fadeMask = null, sbyte fadeStatus = 0) { byte[] frame = new byte[40 * 40]; int i, j; // PSX top menu is black if (SystemVars.Platform != Platform.PSX) { // Dark gray background frame.Set(0, 199, frame.Length); } if (resId != 0xffffffff) { FrameHeader frameHead = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes(resId), frameNo)); var frameData = new ByteAccess(frameHead.Data.Data, frameHead.Data.Offset + FrameHeader.Size); if (SystemVars.Platform == Platform.PSX) { //We need to decompress PSX frames var frameBufferPSX = new byte[_resMan.ReadUInt16(frameHead.width) * _resMan.ReadUInt16(frameHead.height) / 2]; DecompressHIF(frameData.Data, frameData.Offset, frameBufferPSX); for (i = 0; i < _resMan.ReadUInt16(frameHead.height) / 2; i++) { for (j = 0; j < _resMan.ReadUInt16(frameHead.width); j++) { var data = frameBufferPSX[i * _resMan.ReadUInt16(frameHead.width) + j]; frame[(i * 2 + 4) * 40 + j + 2] = data; frame[(i * 2 + 1 + 4) * 40 + j + 2] = data; //Linedoubling the sprite } } } else { for (i = 0; i < _resMan.ReadUInt16(frameHead.height); i++) for (j = 0; j < _resMan.ReadUInt16(frameHead.height); j++) frame[(i + 4) * 40 + j + 2] = frameData[i * _resMan.ReadUInt16(frameHead.width) + j]; } _resMan.ResClose(resId); } if (fadeMask != null) { for (i = 0; i < 40; i++) { for (j = 0; j < 40; j++) { if (fadeMask[((i % 8) * 8) + (j % 8)] >= fadeStatus) frame[i * 40 + j] = 0; } } } _system.GraphicsManager.CopyRectToScreen(frame, 40, x, y, 40, 40); }
public void NewScreen(uint screen) { // set sizes and scrolling, initialize/load screengrid, force screen refresh _currentScreen = (ushort)screen; _scrnSizeX = (ushort)SwordRes.RoomDefTable[screen].sizeX; _scrnSizeY = (ushort)SwordRes.RoomDefTable[screen].sizeY; _gridSizeX = (ushort)(_scrnSizeX / SCRNGRID_X); _gridSizeY = (ushort)(_scrnSizeY / SCRNGRID_Y); if (_scrnSizeX % SCRNGRID_X != 0 || _scrnSizeY % SCRNGRID_Y != 0) throw new InvalidOperationException($"Illegal screensize: {screen}: {_scrnSizeX}/{_scrnSizeY}"); if ((_scrnSizeX > SCREEN_WIDTH) || (_scrnSizeY > SCREEN_DEPTH)) { Logic.ScriptVars[(int)ScriptVariableNames.SCROLL_FLAG] = 2; Logic.ScriptVars[(int)ScriptVariableNames.MAX_SCROLL_OFFSET_X] = (uint)(_scrnSizeX - SCREEN_WIDTH); Logic.ScriptVars[(int)ScriptVariableNames.MAX_SCROLL_OFFSET_Y] = (uint)(_scrnSizeY - SCREEN_DEPTH); } else { Logic.ScriptVars[(int)ScriptVariableNames.SCROLL_FLAG] = 0; Logic.ScriptVars[(int)ScriptVariableNames.MAX_SCROLL_OFFSET_X] = 0; Logic.ScriptVars[(int)ScriptVariableNames.MAX_SCROLL_OFFSET_Y] = 0; } Logic.ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_X] = 0; Logic.ScriptVars[(int)ScriptVariableNames.SCROLL_OFFSET_Y] = 0; if (SystemVars.Platform == Platform.PSX) FlushPsxCache(); _screenBuf = new byte[_scrnSizeX * _scrnSizeY]; _screenGrid = new byte[_gridSizeX * _gridSizeY]; for (var cnt = 0; cnt < SwordRes.RoomDefTable[_currentScreen].totalLayers; cnt++) { // open and lock all resources, will be closed in quitScreen() _layerBlocks[cnt] = new ByteAccess(_resMan.OpenFetchRes(SwordRes.RoomDefTable[_currentScreen].layers[cnt])); if (cnt > 0) _layerBlocks[cnt].Offset += Header.Size; } for (var cnt = 0; cnt < SwordRes.RoomDefTable[_currentScreen].totalLayers - 1; cnt++) { // there's no grid for the background layer, so it's totalLayers - 1 _layerGrid[cnt] = new UShortAccess(_resMan.OpenFetchRes(SwordRes.RoomDefTable[_currentScreen].grids[cnt])); _layerGrid[cnt].Offset += 14 * 2; } _parallax[0] = _parallax[1] = null; if (SwordRes.RoomDefTable[_currentScreen].parallax[0] != 0) _parallax[0] = _resMan.OpenFetchRes(SwordRes.RoomDefTable[_currentScreen].parallax[0]); if (SwordRes.RoomDefTable[_currentScreen].parallax[1] != 0) _parallax[1] = _resMan.OpenFetchRes(SwordRes.RoomDefTable[_currentScreen].parallax[1]); _updatePalette = true; _fullRefresh = true; }
// needed because some psx backgrounds are half width and half height private byte[] PsxShrinkedBackgroundToIndexed(byte[] psxBackground, int offset, int bakXres, int bakYres) { int xresInTiles = ((bakXres / 2) % 16) != 0 ? (bakXres / 32) + 1 : (bakXres / 32); int yresInTiles = ((bakYres / 2) % 16) != 0 ? (bakYres / 32) + 1 : (bakYres / 32); int totTiles = xresInTiles * yresInTiles; int tileYpos = 0; //tile position in a virtual xresInTiles * yresInTiles grid int tileXpos = 0; uint dataBegin = psxBackground.ToUInt32(offset + 4); var decomp_tile = new byte[16 * 16]; //Tiles are always 16 * 16 var fullres_buffer = new byte[bakXres * (yresInTiles + 1) * 32]; bool isCompressed = (psxBackground.ToUInt32(offset) == ScummHelper.MakeTag('C', 'O', 'M', 'P')); totTiles -= xresInTiles; var b = offset + 4; //We skip the id tag int currentTile; for (currentTile = 0; currentTile < totTiles; currentTile++) { int tileOffset = psxBackground.ToInt32(b + 4 * currentTile); if (isCompressed) { DecompressHIF(psxBackground, b + tileOffset - 4, decomp_tile); //Decompress the tile into decomp_tile } else { Array.Copy(psxBackground, b + tileOffset - 4, decomp_tile, 0, 16 * 16); } if (currentTile > 0 && (currentTile % xresInTiles) == 0) { //Finished a line of tiles, going down tileYpos++; tileXpos = 0; } for (byte tileLine = 0; tileLine < 16; tileLine++) { var dest = new ByteAccess(fullres_buffer, tileLine * bakXres * 2 + tileXpos * 32 + tileYpos * bakXres * 16 * 2); for (byte tileColumn = 0; tileColumn < 16; tileColumn++) { byte pixData = decomp_tile[tileColumn + tileLine * 16]; dest[tileColumn * 2] = pixData; dest[tileColumn * 2 + 1] = pixData; } dest.Offset += bakXres; for (byte tileColumn = 0; tileColumn < 16; tileColumn++) { var pixData = decomp_tile[tileColumn + tileLine * 16]; dest[tileColumn * 2] = pixData; dest[tileColumn * 2 + 1] = pixData; } } tileXpos++; } //Calculate number of remaining tiles uint remainingTiles = (uint)((dataBegin - (currentTile * 4 + 4)) / 4); // Last line of tiles is full width! uint tileHeight = (remainingTiles == xresInTiles * 2) ? 16U : 8; tileXpos = 0; for (; currentTile < totTiles + remainingTiles; currentTile++) { int tileOffset = psxBackground.ToInt32(b + 4 * currentTile); if (isCompressed) { DecompressHIF(psxBackground, b + tileOffset - 4, decomp_tile); //Decompress the tile into decomp_tile } else { Array.Copy(psxBackground, b + tileOffset - 4, decomp_tile, 0, 256); } for (byte tileLine = 0; tileLine < tileHeight; tileLine++) { // Write the decoded tiles into last lines of background Array.Copy(decomp_tile, tileLine * 16, fullres_buffer, tileXpos * 16 + (tileLine + (yresInTiles - 1) * 16) * bakXres * 2, 16); Array.Copy(decomp_tile, tileLine * 16, fullres_buffer, tileXpos * 16 + (tileLine + (yresInTiles - 1) * 16) * bakXres * 2 + bakXres, 16); } tileXpos++; } return fullres_buffer; }
private void DrawPsxParallax(byte[] psxParallax, ushort paraScrlX, ushort scrnScrlX, ushort scrnWidth) { ushort totTiles = psxParallax.ToUInt16(14); // Total tiles ushort skipRow = (ushort)(paraScrlX / 16); // Rows of tiles we have to skip byte leftPixelSkip = (byte)(paraScrlX % 16); // Pixel columns we have to skip while drawing the first row var plxPos = new ByteAccess(psxParallax, 16); // Pointer to tile position header section var plxOff = new ByteAccess(psxParallax, 16 + totTiles * 2); // Pointer to tile relative offsets section var plxData = new ByteAccess(psxParallax, 16 + totTiles * 2 + totTiles * 4); //Pointer to beginning of tiles data section var tile_buffer = new byte[16 * 16]; // Buffer for 16x16 pix tile /* For parallax rendering we should check both horizontal and vertical scrolling, * but in PSX edition of the game, the only vertical scrolling parallax is disabled. * So, in this function i'll only check for horizontal scrolling. */ for (ushort currentTile = 0; currentTile < totTiles - 1; currentTile++) { byte tileXpos = plxPos[2 * currentTile]; // Fetch tile X and Y position in the grid byte tileYpos = (byte)(plxPos[2 * currentTile + 1] * 2); int tileBegin = (tileXpos * 16) - paraScrlX; tileBegin = (tileBegin < 0) ? 0 : tileBegin; ushort currentLine = (ushort)(tileYpos * 16); //Current line of the image we are drawing upon, used to avoid going out of screen if (tileXpos >= skipRow) { // Tiles not needed in the screen buffer are not uncompressed int tileOffset = plxOff.Data.ToInt32(plxOff.Offset + 4 * currentTile); ushort rightScreenLimit = (ushort)(_scrnSizeX - scrnScrlX); // Do not write over and beyond this limit, lest we get memory corruption var dest = new ByteAccess(_screenBuf, (tileYpos * 16 * _scrnSizeX) + tileBegin + scrnScrlX); var src = new ByteAccess(tile_buffer); DecompressHIF(plxData.Data, plxData.Offset + tileOffset, tile_buffer); // Decompress the tile if (tileXpos != skipRow) { // This tile will surely be drawn fully in the buffer for (byte tileLine = 0; (tileLine < 16) && (currentLine < SCREEN_DEPTH); tileLine++) { // Check that we are not going outside the bottom screen part for (byte tileColumn = 0; (tileColumn < 16) && (tileBegin + tileColumn) < rightScreenLimit; tileColumn++) if (src[tileColumn] != 0) dest[tileColumn] = src[tileColumn]; dest.Offset += _scrnSizeX; currentLine++; if (currentLine < SCREEN_DEPTH) { for (byte tileColumn = 0; (tileColumn < 16) && (tileBegin + tileColumn) < rightScreenLimit; tileColumn++) if (src[tileColumn] != 0) dest[tileColumn] = src[tileColumn]; dest.Offset += _scrnSizeX; currentLine++; } src.Offset += 16; // get to next line of decoded tile } } else { // This tile may be drawn only partially src.Offset += leftPixelSkip; //Skip hidden pixels for (byte tileLine = 0; (tileLine < 16) && (currentLine < SCREEN_DEPTH); tileLine++) { for (byte tileColumn = 0; tileColumn < (16 - leftPixelSkip); tileColumn++) if (src[tileColumn] != 0) dest[tileColumn] = src[tileColumn]; dest.Offset += _scrnSizeX; currentLine++; if (currentLine < SCREEN_DEPTH) { for (byte tileColumn = 0; tileColumn < (16 - leftPixelSkip); tileColumn++) if (src[tileColumn] != 0) dest[tileColumn] = src[tileColumn]; dest.Offset += _scrnSizeX; currentLine++; } src.Offset += 16; } } } } }
// Used to draw psx sprites which are 1/3 of original width private void DrawPsxFullShrinkedSprite(byte[] sprData, int offset, ushort sprX, ushort sprY, ushort sprWidth, ushort sprHeight, ushort sprPitch) { var dest = new ByteAccess(_screenBuf, (sprY * _scrnSizeX) + sprX); var data = new ByteAccess(sprData, offset); for (ushort cnty = 0; cnty < sprHeight; cnty++) { for (ushort cntx = 0; cntx < sprWidth; cntx++) if (data[cntx] != 0) { dest[cntx * 3] = data[cntx]; //In these sprites we need to double vertical lines too... dest[cntx * 3 + 1] = data[cntx]; dest[cntx * 3 + 2] = data[cntx]; } dest.Offset += _scrnSizeX; for (ushort cntx = 0; cntx < sprWidth; cntx++) if (data[cntx] != 0) { dest[cntx * 3] = data[cntx]; dest[cntx * 3 + 1] = data[cntx]; dest[cntx * 3 + 2] = data[cntx]; } data.Offset += sprPitch; dest.Offset += _scrnSizeX; } }
/// <summary> /// Main thread function /// </summary> public void Run() { bool event_occured; int i; UInt16 crc; AsyncCallback receiver_callback = new AsyncCallback(ReceiveCallback); // create endpoints m_receiver_endpoint = new IPEndPoint(IPAddress.Any, UDPLocalPort); // init socket m_timestamp = DateTime.MinValue; m_client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); m_client.Blocking = false; m_client.EnableBroadcast = true; m_client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); m_client.Bind(m_receiver_endpoint); // init m_upstream_bytes = 0; m_downstream_bytes = 0; // start data reception m_client.BeginReceive(m_receive_buffer, 0, m_receive_buffer.Length, 0, receiver_callback, this); // communication loop while (!m_stop_requested) { // wait for event event_occured = m_thread_event.WaitOne(ThreadWaitTimeout); // exit loop if thread must be stopped if (m_stop_requested) { break; } // process received data if (m_received_data_length > 0) { if (m_received_data_length > 2) { // check CRC crc = CRC16.CalculateForBlock(CRC16.InitValue, m_receive_buffer, m_received_data_length - 2); if (ByteAccess.LowByte(crc) == m_receive_buffer[m_received_data_length - 2] && ByteAccess.HighByte(crc) == m_receive_buffer[m_received_data_length - 1]) { // CRC OK -> continue processing received packet PacketType type = (PacketType)m_receive_buffer[PacketConstants.TypeOffset]; // update statistics Interlocked.Add(ref m_upstream_bytes, m_received_data_length); // process received packet switch (type) { // process device annnounce packet case PacketType.CommDeviceAnnounce: { PacketDeviceAnnounce device_info; // get announce packet device_info = (PacketDeviceAnnounce)RawBinarySerialization.DeserializeObject(m_receive_buffer, typeof(PacketDeviceAnnounce)); // check if it is already on the list of active devices DeviceInfo current_device_info = m_detected_devices.Find(x => x.UniqueID == device_info.UniqueID); if (current_device_info != null) { // device is on the list current_device_info.HostAnnouncePending = true; current_device_info.LastInfoTimestamp = DateTime.Now; } else { DeviceInfo new_device = new DeviceInfo(device_info); new_device.HostAnnouncePending = true; if (new_device.Address != IPAddress.None) { m_detected_devices.Add(new_device); if (m_detected_devices.Count == 1) { lock (m_detected_devices) { m_current_device = m_detected_devices[0]; } } } } } break; default: // process received data if (m_received_data_length <= PacketConstants.PacketMaxLength) { m_communication_manager.StoreReceivedPacket(m_communication_channel_index, m_receive_buffer, (byte)m_received_data_length); } break; } } } // restart reception try { m_received_data_length = 0; m_client.BeginReceive(m_receive_buffer, 0, m_receive_buffer.Length, 0, receiver_callback, this); } catch { // TODO: error handling } } // send host announce for devices for (i = 0; i < m_detected_devices.Count; i++) { IPAddress address_mask = new IPAddress(new byte[] { 255, 255, 255, 0 }); if (m_detected_devices[i].HostAnnouncePending) { IPAddress local_ip = GetLocalIPAddress(m_detected_devices[i].Address, address_mask); if (m_sender_lock.Wait(0)) { // create host info packet PacketHostAnnounce info = new PacketHostAnnounce(); info.Address = (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(local_ip.GetAddressBytes(), 0)); byte[] packet = RawBinarySerialization.SerializeObject(info); // send host info packet EndPoint transmitter_endpoint = new IPEndPoint(m_detected_devices[i].Address, UDPRemotePort); InternalPacketSend(transmitter_endpoint, packet); m_detected_devices[i].HostAnnouncePending = false; } } } // delete unreachable or connectecd devices from the list DateTime current_timestamp = DateTime.Now; i = 0; while (i < m_detected_devices.Count) { // if devlice is silent for a while -> remove from the list if ((current_timestamp - m_detected_devices[i].LastInfoTimestamp).TotalMilliseconds > DeviceAnnounceTimeout) { m_detected_devices.RemoveAt(i); } else { i++; } } } // close socket m_client.Shutdown(SocketShutdown.Both); Thread.Sleep(10); m_client.Close(); // thread is finished m_thread_stopped.Set(); }
protected override void SetupPointers() { _musicDataLoc = _musicData.ToUInt16(0x7DC); _sysExSequence = new ByteAccess(_musicData, _musicData.ToUInt16(0x7E0)); }
private Result TxRxAscii(byte[] TXBuf, int QueryLength, byte[] RXBuf, int ResponseLength) { var num = 0; var array = new byte[531]; var array2 = new byte[523]; Ascii.RTU2ASCII(TXBuf, QueryLength, array); var n = Ascii.LRC(TXBuf, QueryLength); array[0] = 58; array[QueryLength * 2 + 1] = Ascii.Num2Ascii(ByteAccess.HI4BITS(n)); array[QueryLength * 2 + 2] = Ascii.Num2Ascii(ByteAccess.LO4BITS(n)); array[QueryLength * 2 + 3] = 13; array[QueryLength * 2 + 4] = 10; this.port.DiscardInBuffer(); this.port.DiscardOutBuffer(); try { this.port.Write(array, 0, QueryLength * 2 + 5); } catch (Exception ex) { this.Error = ex.Message; return(Result.WRITE); } this._txBufSize = QueryLength * 2 + 5; Array.Copy(array, this._txBuf, this._txBufSize); if (TXBuf[0] == 0) { return(Result.SUCCESS); } if (this._removeEcho) { try { do { var num2 = this.port.Read(RXBuf, 0, this._txBufSize - num); num += num2; }while (this._txBufSize - num > 0); } catch (TimeoutException ex2) { this.Error = ex2.Message; return(Result.RESPONSE_TIMEOUT); } catch (Exception ex3) { this.Error = ex3.Message; return(Result.READ); } num = 0; } try { do { var num3 = this.port.Read(array2, num, 11 - num); num += num3; }while (11 - num > 0); } catch (TimeoutException ex4) { this.Error = ex4.Message; return(Result.RESPONSE_TIMEOUT); } catch (Exception ex5) { this.Error = ex5.Message; return(Result.READ); } finally { this._rxBufSize = num; Array.Copy(array2, this._rxBuf, this._rxBufSize); } if (Ascii.HiLo4BitsToByte(Ascii.Ascii2Num(array2[3]), Ascii.Ascii2Num(array2[4])) > 128) { if (!Ascii.VerifyRespLRC(array2, 11)) { return(Result.CRC); } return((Result)Ascii.HiLo4BitsToByte(Ascii.Ascii2Num(array2[5]), Ascii.Ascii2Num(array2[6]))); } if (ResponseLength == int.MaxValue) { if (Ascii.HiLo4BitsToByte(Ascii.Ascii2Num(array2[3]), Ascii.Ascii2Num(array2[4])) != 17) { return(Result.RESPONSE); } ResponseLength = Ascii.HiLo4BitsToByte(Ascii.Ascii2Num(array2[5]), Ascii.Ascii2Num(array2[6])) + 3; } try { var num4 = ResponseLength * 2 + 5; do { var num5 = this.port.Read(array2, num, num4 - num); num += num5; }while (num4 - num > 0); } catch (TimeoutException ex6) { this.Error = ex6.Message; return(Result.RESPONSE_TIMEOUT); } catch (Exception ex7) { this.Error = ex7.Message; return(Result.READ); } finally { this._rxBufSize = num; Array.Copy(array2, this._rxBuf, this._rxBufSize); } if (!Ascii.VerifyRespLRC(array2, num)) { return(Result.CRC); } if (array2[num - 2] != 13 || array2[num - 1] != 10) { return(Result.RESPONSE); } var num6 = (num - 5) / 2; for (var i = 0; i < num6; i++) { RXBuf[i] = Ascii.HiLo4BitsToByte(Ascii.Ascii2Num(array2[1 + i * 2]), Ascii.Ascii2Num(array2[2 + i * 2])); } return(Result.SUCCESS); }
public void MegaEntering(ushort section) { _liveList[section]++; if (_liveList[section] == 1) _cptData[section] = new ByteAccess(_resMan.CptResOpen(_objectList[section]), Header.Size); }
private void RenderVolumeBar(byte id, byte volL, byte volR) { ushort destX = (ushort)(_volumeButtons[id].x + 20); ushort destY = (ushort)(_volumeButtons[id].y + 116); for (var chCnt = 0; chCnt < 2; chCnt++) { byte vol = (chCnt == 0) ? volL : volR; FrameHeader frHead = new FrameHeader(_resMan.FetchFrame(_resMan.OpenFetchRes(SwordRes.SR_VLIGHT), (uint)((vol + 15) >> 4))); var destMem = new ByteAccess(_screenBuf, destY * Screen.SCREEN_WIDTH + destX); var srcMem = new ByteAccess(frHead.Data.Data, frHead.Data.Offset + FrameHeader.Size); ushort barHeight = _resMan.ReadUInt16(frHead.height); byte[] psxVolBuf = null; if (SystemVars.Platform == Platform.PSX) { psxVolBuf = new byte[_resMan.ReadUInt16(frHead.height) / 2 * _resMan.ReadUInt16(frHead.width)]; Screen.DecompressHIF(srcMem.Data, srcMem.Offset, psxVolBuf); srcMem = new ByteAccess(psxVolBuf); barHeight /= 2; } for (ushort cnty = 0; cnty < barHeight; cnty++) { Array.Copy(srcMem.Data, srcMem.Offset, destMem.Data, destMem.Offset, _resMan.ReadUInt16(frHead.width)); if (SystemVars.Platform == Platform.PSX) { //linedoubling destMem.Offset += Screen.SCREEN_WIDTH; Array.ConstrainedCopy(srcMem.Data, srcMem.Offset, destMem.Data, destMem.Offset, _resMan.ReadUInt16(frHead.width)); } srcMem.Offset += _resMan.ReadUInt16(frHead.width); destMem.Offset += Screen.SCREEN_WIDTH; } _system.GraphicsManager.CopyRectToScreen(_screenBuf, destY * Screen.SCREEN_WIDTH + destX, Screen.SCREEN_WIDTH, destX, destY, _resMan.ReadUInt16(frHead.width), _resMan.ReadUInt16(frHead.height)); _resMan.ResClose(SwordRes.SR_VLIGHT); destX += 32; } }
public void Draw() { FrameHeader fHead = new FrameHeader(_resMan.FetchFrame(_resMan.FetchRes(_resId), (uint)_frameIdx)); ByteAccess src = new ByteAccess(fHead.Data.Data, fHead.Data.Offset + FrameHeader.Size); var dst = new ByteAccess(_dstBuf); if (SystemVars.Platform == Platform.PSX && _resId != 0) { var HIFbuf = new byte[_resMan.ReadUInt16(fHead.height) * _resMan.ReadUInt16(fHead.width)]; Screen.DecompressHIF(src.Data, src.Offset, HIFbuf); src = new ByteAccess(HIFbuf); if (_resMan.ReadUInt16(fHead.width) < 300) for (var cnt = 0; cnt < _resMan.ReadUInt16(fHead.height); cnt++) { for (var cntx = 0; cntx < _resMan.ReadUInt16(fHead.width); cntx++) if (src[cntx] != 0) dst[cntx] = src[cntx]; dst.Offset += Screen.SCREEN_WIDTH; for (var cntx = 0; cntx < _resMan.ReadUInt16(fHead.width); cntx++) if (src[cntx] != 0) dst[cntx] = src[cntx]; dst.Offset += Screen.SCREEN_WIDTH; src.Offset += _resMan.ReadUInt16(fHead.width); } else if (_resId == SwordRes.SR_DEATHPANEL) { // Check for death panel psx version (which is 1/3 of original width) for (var cnt = 0; cnt < _resMan.ReadUInt16(fHead.height) / 2; cnt++) { //Stretched panel is bigger than 640px, check we don't draw outside screen for (var cntx = 0; (cntx < (_resMan.ReadUInt16(fHead.width)) / 3) && (cntx < (Screen.SCREEN_WIDTH - 3)); cntx++) if (src[cntx] != 0) { dst[cntx * 3] = src[cntx]; dst[cntx * 3 + 1] = src[cntx]; dst[cntx * 3 + 2] = src[cntx]; } dst.Offset += Screen.SCREEN_WIDTH; for (var cntx = 0; cntx < (_resMan.ReadUInt16(fHead.width)) / 3; cntx++) if (src[cntx] != 0) { dst[cntx * 3] = src[cntx]; dst[cntx * 3 + 1] = src[cntx]; dst[cntx * 3 + 2] = src[cntx]; } dst.Offset += Screen.SCREEN_WIDTH; src.Offset += _resMan.ReadUInt16(fHead.width) / 3; } } else { //save slots needs to be multiplied by 2 in height for (var cnt = 0; cnt < _resMan.ReadUInt16(fHead.height); cnt++) { for (var cntx = 0; cntx < _resMan.ReadUInt16(fHead.width) / 2; cntx++) if (src[cntx] != 0) { dst[cntx * 2] = src[cntx]; dst[cntx * 2 + 1] = src[cntx]; } dst.Offset += Screen.SCREEN_WIDTH; for (var cntx = 0; cntx < _resMan.ReadUInt16(fHead.width) / 2; cntx++) if (src[cntx] != 0) { dst[cntx * 2] = src[cntx]; dst[cntx * 2 + 1] = src[cntx]; } dst.Offset += Screen.SCREEN_WIDTH; src.Offset += _resMan.ReadUInt16(fHead.width) / 2; } } } else for (var cnt = 0; cnt < _resMan.ReadUInt16(fHead.height); cnt++) { for (var cntx = 0; cntx < _resMan.ReadUInt16(fHead.width); cntx++) if (src[cntx] != 0) dst[cntx] = src[cntx]; dst.Offset += Screen.SCREEN_WIDTH; src.Offset += _resMan.ReadUInt16(fHead.width); } _system.GraphicsManager.CopyRectToScreen(_dstBuf.Data, _dstBuf.Offset, Screen.SCREEN_WIDTH, _x, _y, _width, _height); }
private void PerformPostProcessing(byte[] screen) { // TODO: We don't support displaying these in true color yet, // nor using the PSX fonts to display subtitles. if (SystemVars.Platform == Core.IO.Platform.PSX /* || _decoderType == kVideoDecoderMP2*/) return; if (_movieTexts.Count > 0) { if (_decoder.CurrentFrame == _movieTexts[0]._startFrame) { var text = new ByteAccess(System.Text.Encoding.UTF8.GetBytes(_movieTexts[0]._text)); _textMan.MakeTextSprite(2, text, 600, Text.LetterCol); var frame = new FrameHeader(_textMan.GiveSpriteData(2)); _textWidth = _resMan.ReadUInt16(frame.width); _textHeight = _resMan.ReadUInt16(frame.height); _textX = 320 - _textWidth / 2; _textY = 420 - _textHeight; _textColor = _movieTexts[0]._color; } if (_decoder.CurrentFrame == _movieTexts[0]._endFrame) { _textMan.ReleaseText(2, false); _movieTexts.RemoveAt(0); } } ByteAccess src, dst; int x, y; if (_textMan.GiveSpriteData(2) != null) { src = new ByteAccess(_textMan.GiveSpriteData(2)); src.Offset += FrameHeader.Size; dst = new ByteAccess(screen, _textY * Screen.SCREEN_WIDTH + _textX * 1); for (y = 0; y < _textHeight; y++) { for (x = 0; x < _textWidth; x++) { switch (src[x]) { case Text.BorderCol: dst[x] = (byte)GetBlackColor(); break; case Text.LetterCol: dst[x] = (byte)FindTextColor(); break; } } src.Offset += _textWidth; dst.Offset += Screen.SCREEN_WIDTH; } } else if (_textX != 0 && _textY != 0) { // If the frame doesn't cover the entire screen, we have to // erase the subtitles manually. int frameWidth = _decoder.GetWidth(); int frameHeight = _decoder.GetHeight(); int frameX = (_vm.Settings.Game.Width - frameWidth) / 2; int frameY = (_vm.Settings.Game.Height - frameHeight) / 2; dst = new ByteAccess(screen, _textY * _vm.Settings.Game.Width); for (y = 0; y < _textHeight; y++) { if (_textY + y < frameY || _textY + y >= frameY + frameHeight) { dst.Data.Set(dst.Offset + _textX, (byte)GetBlackColor(), _textWidth); } else { if (frameX > _textX) { dst.Data.Set(dst.Offset + _textX, (byte)GetBlackColor(), frameX - _textX); } if (frameX + frameWidth < _textX + _textWidth) { dst.Data.Set(dst.Offset + frameX + frameWidth, (byte)GetBlackColor(), _textX + _textWidth - (frameX + frameWidth)); } } dst.Offset += _vm.Settings.Game.Width; } _textX = 0; _textY = 0; } }
public void MakeTextSprite(byte slot, ByteAccess text, ushort maxWidth, byte pen) { var lines = new LineInfo[MaxLines]; var numLines = AnalyzeSentence(text, maxWidth, lines); ushort sprWidth = 0; ushort lineCnt; for (lineCnt = 0; lineCnt < numLines; lineCnt++) if (lines[lineCnt].Width > sprWidth) sprWidth = lines[lineCnt].Width; var sprHeight = (ushort)(_charHeight * numLines); var sprSize = (uint)(sprWidth * sprHeight); Debug.Assert(_textBlocks[slot] == null); // if this triggers, the speechDriver failed to call Text::releaseText. _textBlocks[slot] = new FrameHeader(new byte[sprSize + FrameHeader.Size]); Array.Copy(new[] { (byte)'N', (byte)'u', (byte)' ', (byte)' ' }, 0, _textBlocks[slot].runTimeComp.Data, _textBlocks[slot].runTimeComp.Offset, 4); _textBlocks[slot].compSize = 0; _textBlocks[slot].width = _resMan.ReadUInt16(sprWidth); _textBlocks[slot].height = _resMan.ReadUInt16(sprHeight); _textBlocks[slot].offsetX = 0; _textBlocks[slot].offsetY = 0; var linePtr = new ByteAccess(_textBlocks[slot].Data.Data, _textBlocks[slot].Data.Offset + FrameHeader.Size); linePtr.Data.Set(linePtr.Offset, NoCol, (int)sprSize); for (lineCnt = 0; lineCnt < numLines; lineCnt++) { var sprPtr = (sprWidth - lines[lineCnt].Width) / 2; // center the text for (ushort pos = 0; pos < lines[lineCnt].Length; pos++) { sprPtr += CopyChar(text[0], new ByteAccess(linePtr.Data, linePtr.Offset + sprPtr), sprWidth, pen) - Overlap; text.Offset++; } text.Offset++; // skip space at the end of the line if (SystemVars.Platform == Platform.PSX) //Chars are half height in psx version linePtr.Offset += _charHeight / 2 * sprWidth; else linePtr.Offset += _charHeight * sprWidth; } }
public void LoadLiveList(UShortAccess src) { for (var cnt = 0; cnt < TOTAL_SECTIONS; cnt++) { if (_liveList[cnt] != 0) { _resMan.ResClose(_objectList[cnt]); _cptData[cnt] = null; } _liveList[cnt] = src[cnt]; if (_liveList[cnt] != 0) _cptData[cnt] = new ByteAccess(_resMan.CptResOpen(_objectList[cnt]), Header.Size); } }
private void VerticalMask(ushort x, ushort y, ushort bWidth, ushort bHeight) { if (SwordRes.RoomDefTable[_currentScreen].totalLayers <= 1) return; if (SystemVars.Platform == Platform.PSX) { // PSX sprites are vertical shrinked, and some width shrinked bHeight *= 2; bWidth *= 2; } bWidth = (ushort)((bWidth + (x & (SCRNGRID_X - 1)) + (SCRNGRID_X - 1)) / SCRNGRID_X); bHeight = (ushort)((bHeight + (y & (SCRNGRID_Y - 1)) + (SCRNGRID_Y - 1)) / SCRNGRID_Y); x /= SCRNGRID_X; y /= SCRNGRID_Y; if (x + bWidth > _gridSizeX) bWidth = (ushort)(_gridSizeX - x); if (y + bHeight > _gridSizeY) bHeight = (ushort)(_gridSizeY - y); ushort gridY = (ushort)(y + SCREEN_TOP_EDGE / SCRNGRID_Y); // imaginary screen on top gridY = (ushort)(gridY + bHeight - 1); // we start from the bottom edge ushort gridX = (ushort)(x + SCREEN_LEFT_EDGE / SCRNGRID_X); // imaginary screen left ushort lGridSizeX = (ushort)(_gridSizeX + 2 * (SCREEN_LEFT_EDGE / SCRNGRID_X)); // width of the grid for the imaginary screen for (ushort blkx = 0; blkx < bWidth; blkx++) { // A sprite can be masked by several layers at the same time, // so we have to check them all. See bug #917427. for (short level = (short)(SwordRes.RoomDefTable[_currentScreen].totalLayers - 2); level >= 0; level--) { if (_layerGrid[level][gridX + blkx + gridY * lGridSizeX] != 0) { var grid = new UShortAccess(_layerGrid[level].Data, _layerGrid[level].Offset + (gridX + blkx + gridY * lGridSizeX) * 2); for (short blky = (short)(bHeight - 1); blky >= 0; blky--) { if (grid[0] != 0) { ByteAccess blkData; if (SystemVars.Platform == Platform.PSX) blkData = new ByteAccess(_layerBlocks[level + 1].Data, _layerBlocks[level + 1].Offset + (_resMan.ReadUInt16(grid[0]) - 1) * 64); //PSX layers are half height too... else blkData = new ByteAccess(_layerBlocks[level + 1].Data, _layerBlocks[level + 1].Offset + (_resMan.ReadUInt16(grid[0]) - 1) * 128); BlitBlockClear((ushort)(x + blkx), (ushort)(y + blky), blkData); } else break; grid.Offset -= lGridSizeX * 2; } } } } }
public MousePtr(byte[] data) { Data = data; Offset = 0; dummyData = new ByteAccess(data, Offset + 10); }
public void DoRestore() { var bufPos = new ByteAccess(_restoreBuf); _objMan.LoadLiveList(new UShortAccess(_restoreBuf)); bufPos.Offset += ObjectMan.TOTAL_SECTIONS * 2; for (var cnt = 0; cnt < Logic.NUM_SCRIPT_VARS; cnt++) { Logic.ScriptVars[cnt] = bufPos.Data.ToUInt32(bufPos.Offset); bufPos.Offset += 4; } uint playerSize = (SwordObject.Size - 12000) / 4; var cpt = _objMan.FetchObject(Logic.PLAYER); var playerRaw = new UIntAccess(cpt.Data, cpt.Offset); for (var cnt2 = 0; cnt2 < playerSize; cnt2++) { playerRaw[0] = bufPos.Data.ToUInt32(bufPos.Offset); playerRaw.Offset += 4; bufPos.Offset += 4; } Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_DIR] = (uint)cpt.dir; Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_X] = (uint)cpt.xcoord; Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_Y] = (uint)cpt.ycoord; Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_STANCE] = StaticRes.STAND; Logic.ScriptVars[(int)ScriptVariableNames.CHANGE_PLACE] = (uint)cpt.place; SystemVars.JustRestoredGame = 1; if (SystemVars.IsDemo) Logic.ScriptVars[(int)ScriptVariableNames.PLAYINGDEMO] = 1; }