Esempio n. 1
0
plString hsStream::ReadSafeString_TEMP()
{
    plStringBuffer<char> name;
    uint16_t numChars = ReadLE16();

#ifndef REMOVE_ME_SOON
    // Backward compat hack - remove in a week or so (from 6/30/03)
    bool oldFormat = !(numChars & 0xf000);
    if (oldFormat)
        ReadLE16();
#endif

    numChars &= ~0xf000;
    hsAssert(numChars <= GetSizeLeft(), "Bad string");
    if (numChars > 0 && numChars <= GetSizeLeft())
    {
        char *buff = name.CreateWritableBuffer(numChars);
        Read(numChars, buff);
        buff[numChars] = 0;

        // if the high bit is set, flip the bits. Otherwise it's a normal string, do nothing.
        if (buff[0] & 0x80)
        {
            int i;
            for (i = 0; i < numChars; i++)
                buff[i] = ~buff[i];
        }
    }

    return name;
}
Esempio n. 2
0
/* load TIL object to AGG::Cache */
void AGG::Cache::LoadTIL(const TIL::til_t til)
{
    til_cache_t & v = til_cache[til];

    if(v.sprites) return;

    DEBUG(DBG_ENGINE , DBG_INFO, "AGG::Cache::LoadTIL: " << TIL::GetString(til));

    std::vector<u8> body;

    if(ReadChunk(TIL::GetString(til), body))
    {
	const u16 count = ReadLE16(&body.at(0));
	const u16 width = ReadLE16(&body.at(2));
	const u16 height= ReadLE16(&body.at(4));

	const u32 tile_size = width * height;
	const u32 body_size = 6 + count * tile_size;

	// check size
	if(body.size() != body_size)
	{
	    DEBUG(DBG_ENGINE , DBG_WARN, "AGG::Cache::LoadTIL: size mismach, skipping...");
	    return;
	}

	v.count = count * 4;  // rezerve for rotate sprites
	v.sprites = new Surface [v.count];

	for(u16 ii = 0; ii < count; ++ii)
	    v.sprites[ii].Set(&body[6 + ii * tile_size], width, height, 1, false);
    }
}
Esempio n. 3
0
void ICN::Header::Load(const u8* p)
{
    offset_x = ReadLE16(&p[0]);
    offset_y = ReadLE16(&p[2]);
    width = ReadLE16(&p[4]);
    height= ReadLE16(&p[6]);
    type = p[8];
    offset_data = ReadLE32(&p[9]);
}
Esempio n. 4
0
void i82557eeprom::dumpContents()
{
	EEPROM_t * eeprom_p = &image.fields;

    IOLog("The EEPROM contains the following information:\n");

    IOLog("ethernet address: ");
    _logAddr((unsigned char *) &eeprom_p->addr);
    IOLog("\n");

	if (eeprom_p->compatibility_0 & EEPROM_C0_MC_10)
		IOLog("compatibility: MCSETUP workaround required for 10 Mbits\n");
    if (eeprom_p->compatibility_0 & EEPROM_C0_MC_100)
		IOLog("compatibility: MCSETUP workaround required for 100 Mbits\n");

	IOLog("connectors: %s %s %s %s\n", 
		eeprom_p->connectors & EEPROM_CON_RJ45 ? "RJ-45" : "",
		eeprom_p->connectors & EEPROM_CON_BNC ? "BNC" : "",
		eeprom_p->connectors & EEPROM_CON_AUI ? "AUI" : "",
		eeprom_p->connectors & EEPROM_CON_MII ? "MII" : "");

    IOLog("controller type: %d\n", eeprom_p->controllerType);

	for (int i = 0; i < NUM_PHYS; i++) {
		const char * s = (i == PRIMARY_PHY) ? "primary" : "secondary";
		UInt16 phy = ReadLE16(&eeprom_p->phys[i]);

		IOLog("%s PHY: %s\n", s,
			PHYDeviceNames(CSR_VALUE(EEPROM_PHY_DEVICE, phy)));
		if (CSR_VALUE(EEPROM_PHY_DEVICE, phy) != PHYDevice_None_e) {
			if (phy & EEPROM_PHY_VSCR)
				IOLog("%s PHY: vendor specific code required\n", s);
			if (phy & EEPROM_PHY_10)
				IOLog("%s PHY: 10 Mbits only, requires 503 interface\n", s);
			IOLog("%s PHY address: 0x%x\n", s,
				CSR_VALUE(EEPROM_PHY_ADDRESS, phy));
		}
    }

    IOLog("PWA Number: %d %d %d-0%d\n", eeprom_p->PWANumber[1],
	  eeprom_p->PWANumber[0], eeprom_p->PWANumber[3],
	  eeprom_p->PWANumber[2]);

    IOLog("Checksum: 0x%x\n", ReadLE16(&eeprom_p->checkSum));
#if 0
    if (eeprom_p->checkSum != image.words[NUM_EEPROM_WORDS - 1])
		IOLog("the checksum in the struct doesn't match that in the array\n");
#endif	
	return;
}
Esempio n. 5
0
void AGG::Cache::LoadOrgICN(Sprite & sp, const ICN::icn_t icn, const u16 index, bool reflect)
{
    std::vector<u8> body;

    if(ReadChunk(ICN::GetString(icn), body))
    {
	// loading original
	DEBUG(DBG_ENGINE, DBG_TRACE, "AGG::Cache::LoadOrgICN: " << ICN::GetString(icn) << ", " << index);

	const u16 count = ReadLE16(&body[0]);
	ICN::Header header1, header2;

	header1.Load(&body[6 + index * ICN::Header::SizeOf()]);
	if(index + 1 != count) header2.Load(&body[6 + (index + 1) * ICN::Header::SizeOf()]);

	const u32 size_data = (index + 1 != count ? header2.OffsetData() - header1.OffsetData() :
				    // total size
				    ReadLE32(&body[2]) - header1.OffsetData());

	sp.Set(header1.Width(), header1.Height(), ICN::RequiresAlpha(icn));
	sp.SetOffset(header1.OffsetX(), header1.OffsetY());
	sp.SetColorKey();
	Sprite::DrawICN(sp, &body[6 + header1.OffsetData()], size_data, reflect);
	Sprite::AddonExtensionModify(sp, icn, index);
    }
    else
	Error::Except("AGG::Cache::LoadOrgICN: ReadChunk: ", ICN::GetString(icn));
}
Esempio n. 6
0
plString hsStream::ReadSafeWStringLong_TEMP()
{
    plStringBuffer<uint16_t> retVal;
    uint32_t numChars = ReadLE32();
    if (numChars > 0 && numChars <= (GetSizeLeft()/2)) // divide by two because each char is two bytes
    {
        uint16_t *buff = retVal.CreateWritableBuffer(numChars);
        for (int i=0; i<numChars; i++)
            buff[i] = ReadLE16();
        ReadLE16(); // we wrote the null out, read it back in
        buff[numChars] = 0; // But terminate it safely anyway

        if (buff[0]* 0x80)
        {
            for (int i=0; i<numChars; i++)
                buff[i] = ~buff[i];
        }
    }

    return plString::FromUtf16(retVal);
}
Esempio n. 7
0
bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)
{
    opcodeRet = OP_INVALIDOPCODE;
    if (pvchRet)
        pvchRet->clear();
    if (pc >= end)
        return false;

    // Read instruction
    if (end - pc < 1)
        return false;
    unsigned int opcode = *pc++;

    // Immediate operand
    if (opcode <= OP_PUSHDATA4)
    {
        unsigned int nSize = 0;
        if (opcode < OP_PUSHDATA1)
        {
            nSize = opcode;
        }
        else if (opcode == OP_PUSHDATA1)
        {
            if (end - pc < 1)
                return false;
            nSize = *pc++;
        }
        else if (opcode == OP_PUSHDATA2)
        {
            if (end - pc < 2)
                return false;
            nSize = ReadLE16(&pc[0]);
            pc += 2;
        }
        else if (opcode == OP_PUSHDATA4)
        {
            if (end - pc < 4)
                return false;
            nSize = ReadLE32(&pc[0]);
            pc += 4;
        }
        if (end - pc < 0 || (unsigned int)(end - pc) < nSize)
            return false;
        if (pvchRet)
            pvchRet->assign(pc, pc + nSize);
        pc += nSize;
    }

    opcodeRet = static_cast<opcodetype>(opcode);
    return true;
}
Esempio n. 8
0
bool i82557eeprom::initWithAddress(volatile eeprom_control_t * p)
{
    int 	i;
    UInt16	sum;

    if (!super::init())
		return false;

    ee_p = p;

    /*
     * Find out the number of bits in the address by issuing a read to address
     * 0 ie. keep feeding eeprom address bits with value 0, until the eeprom
     * says that the address is complete.  It tells us by setting EEDO to 0 
     * after a write cycle.
     */
    EEPROMEnable(ee_p);
    EEPROMWriteBit(ee_p, 1); /* read */
    EEPROMWriteBit(ee_p, 1);
    EEPROMWriteBit(ee_p, 0);
    nbits = 1;

    do {
		EEPROMWriteBit(ee_p, 0);
		if ((ReadLE16(ee_p) & EEPROM_CONTROL_EEDO) == 0)
	    	break;
		nbits++;
    } while (nbits <= 32);

	// IOLog("nbits: %d\n", nbits);

    EEPROMDisable(ee_p);

    // Read NUM_EEPROM_WORDS words into memory.
    // Also compute a sum of the entire EEPROM.

    for (sum = 0, i = 0; i < (1 << nbits); i++) {
		UInt16 w = readWord(i);
		sum += w;
        if (i < NUM_EEPROM_WORDS)
            WriteLE16(&image.words[i], w);
    }
    if (sum != EEPROM_CHECKSUM_VALUE) {
		IOLog("i82557eeprom: checksum %x incorrect\n", sum);
        return false;
    }

    return true;
}
Esempio n. 9
0
void AGG::Cache::LoadOrgICN(icn_cache_t & v, const ICN::icn_t icn, const u16 index, bool reflect)
{
    if(NULL == v.sprites)
    {
	std::vector<u8> body;
	ReadChunk(ICN::GetString(icn), body);

	v.count = ReadLE16(&body[0]);
	v.sprites = new Sprite [v.count];
	v.reflect = new Sprite [v.count];
    }

    Sprite & sp = reflect ? v.reflect[index] : v.sprites[index];

    LoadOrgICN(sp, icn, index, reflect);
    // set display format
    if(8 != sp.depth() &&
       !(Settings::Get().QVGA() && ICN::NeedMinify4PocketPC(icn, index))) sp.SetDisplayFormat();
}
Esempio n. 10
0
static void UpdateVGM(VGM_PBK* vgmPlay, UINT16 Samples)
{
	const dword/*32*/ vgmLen = vgmPlay->file->dataLen;
	const UINT8* vgmData = vgmPlay->file->data;
	const UINT8* VGMPnt;
	dword/*32*/ VGMPos;
	dword/*32*/ VGMSmplPos;
	UINT8 Command;
	UINT8 blockType;
	dword/*32*/ blockLen;

	vgmPlay->pbSmplPos += Samples;
	VGMPos = vgmPlay->vgmPos;
	VGMSmplPos = vgmPlay->vgmSmplPos;
	while(VGMSmplPos < vgmPlay->pbSmplPos && ! vgmPlay->vgmEnd)
	{
		VGMPnt = &vgmData[VGMPos];
		Command = VGMPnt[0x00];
		switch(Command & 0xF0)
		{
		case 0x70:	// small delay (1-16 samples)
			VGMSmplPos += (Command & 0x0F) + 0x01;
			VGMPos += 0x01;
			break;
		case 0x80:	// DAC write + small delay (0-15 samples)
			VGMSmplPos += (Command & 0x0F);
			VGMPos += 0x01;
			break;
		case 0x60:
			switch(Command)
			{
			case 0x66:	// End Of File
				vgmPlay->vgmPos = VGMPos;
				vgmPlay->vgmSmplPos = VGMSmplPos;
				if (! DoVgmLoop(vgmPlay))
					vgmPlay->vgmEnd = 0x01;
				VGMPos = vgmPlay->vgmPos;
				VGMSmplPos = vgmPlay->vgmSmplPos;
				break;
			case 0x62:	// 1/60s delay
				VGMSmplPos += 735;
				VGMPos += 0x01;
				break;
			case 0x63:	// 1/50s delay
				VGMSmplPos += 882;
				VGMPos += 0x01;
				break;
			case 0x61:	// xx Sample Delay
				VGMSmplPos += ReadLE16(&VGMPnt[0x01]);
				VGMPos += 0x03;
				break;
			case 0x67:	// Data Block (PCM Data Stream)
				blockType = VGMPnt[0x02];
				blockLen = ReadLE32(&VGMPnt[0x03]);
				blockLen &= 0x7FFFFFFF;
				VGMPos += 0x07 + blockLen;
				break;
			case 0x68:	// PCM RAM write
				VGMPos += 0x0C;
				break;
			default:
				vgmPlay->vgmEnd = 0x01;
				break;
			}
			break;
		case 0x50:
			if (Command == 0x50)
			{
				VGMPos += 0x02;	// SN76496 write
				break;
			}
			switch(Command)
			{
			case 0x51:	// YM2413 write
				ym2413_write(vgmPlay, VGMPnt[0x01], VGMPnt[0x02]);
				break;
			case 0x5A:	// YM3812 write
				ym3812_write(vgmPlay, VGMPnt[0x01], VGMPnt[0x02]);
				break;
			case 0x5B:	// YM3526 write
			case 0x5C:	// Y8950 write
				ym3512_write(vgmPlay, VGMPnt[0x01], VGMPnt[0x02]);
				break;
			case 0x5E:	// YMF262 write, port 0
			case 0x5F:	// YMF262 write, port 1
				ymf262_write(vgmPlay, Command & 0x01, VGMPnt[0x01], VGMPnt[0x02]);
				break;
			}
			VGMPos += 0x03;
			break;
		case 0x30:
			VGMPos += 0x02;
			break;
		case 0x40:
		case 0xA0:
		case 0xB0:
			VGMPos += 0x03;
			break;
		case 0xC0:
		case 0xD0:
			VGMPos += 0x04;
			break;
		case 0xE0:
		case 0xF0:
			VGMPos += 0x05;
			break;
		case 0x90:
			switch(Command)
			{
			case 0x90:	// DAC Ctrl: Setup Chip
				VGMPos += 0x05;
				break;
			case 0x91:	// DAC Ctrl: Set Data
				VGMPos += 0x05;
				break;
			case 0x92:	// DAC Ctrl: Set Freq
				VGMPos += 0x06;
				break;
			case 0x93:	// DAC Ctrl: Play from Start Pos
				VGMPos += 0x0B;
				break;
			case 0x94:	// DAC Ctrl: Stop immediately
				VGMPos += 0x02;
				break;
			case 0x95:	// DAC Ctrl: Play Block (small)
				VGMPos += 0x05;
				break;
			default:
				vgmPlay->vgmEnd = 0x01;
				break;
			}
			break;
		default:
			vgmPlay->vgmEnd = 0x01;
			return;
		}

		if (VGMPos >= vgmLen)
			vgmPlay->vgmEnd = 0x01;
	}
	vgmPlay->vgmPos = VGMPos;
	vgmPlay->vgmSmplPos = VGMSmplPos;
	if (vgmPlay->vgmEnd)
		StopPlayback(vgmPlay);

	return;
}
Esempio n. 11
0
EventDate::EventDate(const void *ptr)
{
    const u8  *ptr8  = static_cast<const u8 *>(ptr);
    u16 byte16 = 0;
    u32 byte32 = 0;

    // id
    if(0x00 != *ptr8)
    {
	DEBUG(DBG_GAME , DBG_WARN, "unknown id");
	return;
    }
    ++ptr8;

    // resource
    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.wood = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.mercury = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.ore = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.sulfur = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.crystal = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.gems = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.gold = byte32;

    // skip artifact
    byte16 = ReadLE16(ptr8);
    ++ptr8;
    ++ptr8;

    // allow computer
    byte16 = ReadLE16(ptr8);
    ++ptr8;
    ++ptr8;
    computer = byte16;

    // day of first occurent
    byte16 = ReadLE16(ptr8);
    ++ptr8;
    ++ptr8;
    first = byte16;

    // subsequent occurrences
    byte16 = ReadLE16(ptr8);
    ++ptr8;
    ++ptr8;
    subsequent = byte16;

    ptr8 += 6;

    colors = 0;
    
    // blue
    if(*ptr8) colors |= Color::BLUE;
    ++ptr8;

    // green
    if(*ptr8) colors |= Color::GREEN;
    ++ptr8;

    // red
    if(*ptr8) colors |= Color::RED;
    ++ptr8;

    // yellow
    if(*ptr8) colors |= Color::YELLOW;
    ++ptr8;

    // orange
    if(*ptr8) colors |= Color::ORANGE;
    ++ptr8;

    // purple
    if(*ptr8) colors |= Color::PURPLE;
    ++ptr8;

    // message
    message = Game::GetEncodeString(reinterpret_cast<const char *>(ptr8));

    //if(SIZEMESSAGE < message.size()) DEBUG(DBG_GAME , DBG_WARN, "long message, incorrect block?");

    DEBUG(DBG_GAME, DBG_INFO, "add: " << message);
}
Esempio n. 12
0
Riddle::Riddle(s32 index, const void *ptr) : valid(false)
{
    SetIndex(index);

    const u8  *ptr8  = static_cast<const u8 *>(ptr);
    u16 byte16 = 0;
    u32 byte32 = 0;

    // id
    if(0x00 != *ptr8)
    {
	DEBUG(DBG_GAME , DBG_WARN, "unknown id");
	return;
    }
    ++ptr8;

    // resource
    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.wood = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.mercury = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.ore = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.sulfur = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.crystal = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.gems = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.gold = byte32;

    // artifact
    byte16 = ReadLE16(ptr8);
    ++ptr8;
    ++ptr8;
    artifact = byte16;

    // count answers
    u8 count = *ptr8;
    ++ptr8;

    // answers
    for(u8 i = 0; i < 8; ++i)
    {
	std::string str = String::Lower(reinterpret_cast<const char *>(ptr8));

	if(count-- && str.size())
	{
	    answers.push_back(Game::GetEncodeString(str.c_str()));
	    answers.push_back(Game::GetEncodeString(reinterpret_cast<const char *>(ptr8)));
	};
	ptr8 += 13;
    }

    // message
    message = Game::GetEncodeString(reinterpret_cast<const char *>(ptr8));

    valid = true;

    DEBUG(DBG_GAME, DBG_INFO, "add: " << message);
}
Esempio n. 13
0
EventMaps::EventMaps(s32 index, const void *ptr)
{
    SetIndex(index);

    const u8  *ptr8  = static_cast<const u8 *>(ptr);
    u16 byte16 = 0;
    u32 byte32 = 0;

    // id
    if(0x01 != *ptr8)
    {
	DEBUG(DBG_GAME, DBG_WARN, "unknown id");
	return;
    }
    ++ptr8;

    // resource
    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.wood = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.mercury = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.ore = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.sulfur = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.crystal = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.gems = byte32;

    byte32 = ReadLE32(ptr8);
    ptr8 += 4;;
    resource.gold = byte32;

    // artifact
    byte16 = ReadLE16(ptr8);
    ++ptr8;
    ++ptr8;
    artifact = byte16;

    // allow computer
    computer = *ptr8;
    ++ptr8;

    // cancel event after first visit
    cancel = *ptr8;
    ptr8 += 11;

    colors = 0;
    
    // blue
    if(*ptr8) colors |= Color::BLUE;
    ++ptr8;

    // green
    if(*ptr8) colors |= Color::GREEN;
    ++ptr8;

    // red
    if(*ptr8) colors |= Color::RED;
    ++ptr8;

    // yellow
    if(*ptr8) colors |= Color::YELLOW;
    ++ptr8;

    // orange
    if(*ptr8) colors |= Color::ORANGE;
    ++ptr8;

    // purple
    if(*ptr8) colors |= Color::PURPLE;
    ++ptr8;

    // message
    message = Game::GetEncodeString(reinterpret_cast<const char *>(ptr8));

    DEBUG(DBG_GAME , DBG_INFO, "add: " << message);
}
Esempio n. 14
0
// Parses Opus Header. Header spec: http://wiki.xiph.org/OggOpus#ID_Header
static bool ParseOpusHeader(const uint8_t *data, size_t data_size,
                            OpusHeader* header) {
    // Size of the Opus header excluding optional mapping information.
    const size_t kOpusHeaderSize = 19;

    // Offset to the channel count byte in the Opus header.
    const size_t kOpusHeaderChannelsOffset = 9;

    // Offset to the pre-skip value in the Opus header.
    const size_t kOpusHeaderSkipSamplesOffset = 10;

    // Offset to the gain value in the Opus header.
    const size_t kOpusHeaderGainOffset = 16;

    // Offset to the channel mapping byte in the Opus header.
    const size_t kOpusHeaderChannelMappingOffset = 18;

    // Opus Header contains a stream map. The mapping values are in the header
    // beyond the always present |kOpusHeaderSize| bytes of data. The mapping
    // data contains stream count, coupling information, and per channel mapping
    // values:
    //   - Byte 0: Number of streams.
    //   - Byte 1: Number coupled.
    //   - Byte 2: Starting at byte 2 are |header->channels| uint8 mapping
    //             values.
    const size_t kOpusHeaderNumStreamsOffset = kOpusHeaderSize;
    const size_t kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1;
    const size_t kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2;

    if (data_size < kOpusHeaderSize) {
        ALOGV("Header size is too small.");
        return false;
    }
    header->channels = *(data + kOpusHeaderChannelsOffset);

    if (header->channels <= 0 || header->channels > kMaxChannels) {
        ALOGV("Invalid Header, wrong channel count: %d", header->channels);
        return false;
    }
    header->skip_samples = ReadLE16(data, data_size,
                                        kOpusHeaderSkipSamplesOffset);
    header->gain_db = static_cast<int16_t>(
                              ReadLE16(data, data_size,
                                       kOpusHeaderGainOffset));
    header->channel_mapping = *(data + kOpusHeaderChannelMappingOffset);
    if (!header->channel_mapping) {
        if (header->channels > kMaxChannelsWithDefaultLayout) {
            ALOGV("Invalid Header, missing stream map.");
            return false;
        }
        header->num_streams = 1;
        header->num_coupled = header->channels > 1;
        header->stream_map[0] = 0;
        header->stream_map[1] = 1;
        return true;
    }
    if (data_size < kOpusHeaderStreamMapOffset + header->channels) {
        ALOGV("Invalid stream map; insufficient data for current channel "
              "count: %d", header->channels);
        return false;
    }
    header->num_streams = *(data + kOpusHeaderNumStreamsOffset);
    header->num_coupled = *(data + kOpusHeaderNumCoupledOffset);
    if (header->num_streams + header->num_coupled != header->channels) {
        ALOGV("Inconsistent channel mapping.");
        return false;
    }
    for (int i = 0; i < header->channels; ++i)
      header->stream_map[i] = *(data + kOpusHeaderStreamMapOffset + i);
    return true;
}