Ejemplo n.º 1
0
/*------------------------------------------------------*/
void	CheckScreen(void)
{
	int		i,j;
	char	r[128];

	j=0;
	for(i=0;i<80;++i)
		j = Crc(j,LcdBuffer[i]);
	for(i=0;i<32;++i)
		j = Crc(j,LcdExt[i]);
	j = Crc(j,GetLCDaddr());
	if(CheckScr != j)
	{
		CheckScr = j;
		sprintf(r,"=s %d,%d,%c\r\n",(int)LcdBuffer[80]%20,(int)LcdBuffer[80]/20,(int)LcdBuffer[81]);
		puts_pc(r);
		for(i=0;i<4;++i)
		{
			strncpy(r,&LcdBuffer[20*i],20);
			r[20]=0;
			puts_pc(r);
			puts_pc("\r\n");
		}
		for(i=0;i<4;++i)
		{
			strncpy(r,&LcdExt[8*i],8);
			r[8]=0;
			puts_pc(r);
			puts_pc("\r\n");
		}
		puts_pc(">");
	}
	SetTask(CheckScreen,2,RTC_task);
}
Ejemplo n.º 2
0
// fast method to just read the UID of a tag (collission detection not supported)
//		*buf	should be large enough to fit the 64bit uid
// returns 1 if suceeded
int getUID(uint8_t *buf) 
{
	UsbCommand resp;
	uint8_t *recv;
	UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
	uint8_t *req=c.d.asBytes;
	int reqlen=0;
	
	for (int retry=0;retry<3; retry++) { // don't give up the at the first try		
		
		req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | 
		        ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
		req[1]=ISO15_CMD_INVENTORY;
		req[2]=0; // mask length
		reqlen=AddCrc(req,3);
		c.arg[0]=reqlen;
	
		SendCommand(&c);
		
		if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
			recv = resp.d.asBytes;
			if (resp.arg[0]>=12 && ISO15_CRC_CHECK==Crc(recv,12)) {
			   memcpy(buf,&recv[2],8);
			   return 1;
			} 
		} 
	} // retry
	return 0;
}
Ejemplo n.º 3
0
void CONFIG_LoadTx()
{
    memset(&Transmitter, 0, sizeof(Transmitter));
    Transmitter.current_model = 1;
    Transmitter.music_shutdown = 0; // default to off
    Transmitter.mode = MODE_2;
    Transmitter.brightness = 5;
    Transmitter.contrast = 5;
    Transmitter.volume = 10;
    Transmitter.vibration_state = 0; // default to off since only devo10 support it
    Transmitter.power_alarm = 0;     // default to off 
    Transmitter.batt_alarm = DEFAULT_BATTERY_ALARM;
    Transmitter.batt_critical = DEFAULT_BATTERY_CRITICAL;
    Transmitter.batt_warning_interval = DEFAULT_BATTERY_WARNING_INTERVAL;
    Transmitter.splash_delay = DEFAULT_SPLASH_DELAY;
    Transmitter.auto_dimmer.timer = DEFAULT_BACKLIGHT_DIMTIME;
    Transmitter.auto_dimmer.backlight_dim_value = DEFAULT_BACKLIGHT_DIMVALUE;
    Transmitter.countdown_timer_settings.prealert_time = DEFAULT_PERALERT_TIME;
    Transmitter.countdown_timer_settings.prealert_interval = DEFAULT_PREALERT_INTERVAL;
    Transmitter.countdown_timer_settings.timeup_interval = DEFAULT_TIMEUP_INTERVAL;
#if HAS_EXTRA_SWITCHES
    CHAN_SetSwitchCfg("");
#endif
    MCU_InitModules();
    CONFIG_LoadHardware();
    CONFIG_IniParse("tx.ini", ini_handler, (void *)&Transmitter);
    crc32 = Crc(&Transmitter, sizeof(Transmitter));
    return;
}
Ejemplo n.º 4
0
void PAGE_ShowSafetyDialog()
{
    if (disable_safety) {
        return; // don't show safety dialog when calibrating
    }
    if (dialog) {
        u64 unsafe = PROTOCOL_CheckSafe();
        if (! unsafe) {
            GUI_RemoveObj(dialog);
            dialog = NULL;
            PROTOCOL_Init(0);
        } else {
            safety_string_cb(NULL, NULL);
            u32 crc = Crc(tempstring, strlen(tempstring));
            if (crc != dialogcrc) {
                GUI_Redraw(dialog);
                dialogcrc = crc;
            }
        }
    } else {
        tempstring[0] = 0;
        dialogcrc = 0;
        dialog = GUI_CreateDialog(&gui->dialog, 10 + DLG_XOFFSET, 42 + DLG_YOFFSET, 300, 188, _tr("Safety"), safety_string_cb, safety_ok_cb, dtOk, NULL);
    }
}
Ejemplo n.º 5
0
static const char *safety_string_cb(guiObject_t *obj, void *data)
{
    (void)data;
    int i;
    u32 crc = Crc(tempstring, strlen(tempstring));
    if (obj && crc == dialogcrc)
        return tempstring;
    int count = 0;
    const s8 safeval[4] = {0, -100, 0, 100};
    volatile s16 *raw = MIXER_GetInputs();
    u64 unsafe = PROTOCOL_CheckSafe();
    tempstring[0] = 0;
    for(i = 0; i < NUM_SOURCES + 1; i++) {
        if (! (unsafe & (1LL << i)))
            continue;
        int ch = (i == 0) ? PROTOCOL_MapChannel(INP_THROTTLE, NUM_INPUTS + 2) : i-1;
      
        s16 val = RANGE_TO_PCT((ch < NUM_INPUTS)
                      ? raw[ch+1]
                      : MIXER_GetChannel(ch - (NUM_INPUTS), APPLY_SAFETY));
        INPUT_SourceName(tempstring + strlen(tempstring), ch + 1);
        int len = strlen(tempstring);
        snprintf(tempstring + len, sizeof(tempstring) - len, _tr(" is %d%%, safe value = %d%%\n"),
                val, safeval[Model.safety[i]]);
        if (++count >= 5)
            break;
    }
    return tempstring;
}
Ejemplo n.º 6
0
guiObject_t *GUI_CreateImageOffset(guiImage_t *image, u16 x, u16 y, u16 width, u16 height, u16 x_off, u16 y_off, const char *file,
    void (*CallBack)(guiObject_t *obj, s8 press_type, const void *data), const void *cb_data)
{
    struct guiObject *obj = (guiObject_t *)image;
    struct guiBox    *box;
    CLEAR_OBJ(image);

    box = &obj->box;

    image->file = file;
    image->x_off = x_off;
    image->y_off = y_off;
    image->callback = CallBack;
    image->cb_data = cb_data;
    image->crc = Crc(file, strlen(file));

    box->x = x;
    box->y = y;
    box->width = width;
    box->height = height;

    obj->Type = Image;
    OBJ_SET_TRANSPARENT(obj, LCD_ImageIsTransparent(file));
    OBJ_SET_SELECTABLE(obj, CallBack ? 1 :0);
    connect_object(obj);

    return obj;

}
Ejemplo n.º 7
0
void CONFIG_SaveTxIfNeeded()
{
    uint32_t newCrc = Crc(&Transmitter, sizeof(Transmitter));
    if (crc32 == newCrc)
        return;
    crc32 = newCrc;
    CONFIG_WriteTx();
}
Ejemplo n.º 8
0
/*--------------------------------------------------------*/
lib		*CheckItem(lib *ll)
		{
		int		i,j;
		coord	*x;
        char	*p;

/*
		if(checktype(ll,TYPE_MT)) {
			if(targets_n(ll->x) > 1) {
				if(dtime(&LastCoord(ll)->t,&t) <= 0) {
       		    	add_coord(ll,0,0,0);
                    if(track_delay)
						addsecs(&ll->xc->t,track_delay);
                    else
						addsecs(&ll->xc->t,1);
					if(!interpolate(ll))
						erase_coord(ll,ll->xc);
                    else
						while(targets_n(ll->x) > 3)
							erase_coord(ll,FirstCoord(ll));
					}
                }
			}
*/
		p = (char *)ll;
		i = sizeof(lib) - 3 * sizeof(void *) - sizeof(int);
		j = 0;
		while(i--)
			j = Crc(j,*p++);
		for(x=ll->x; x; x=x->next) {
			p = (char *)x;
			i = sizeof(coord) - sizeof(void *);
			while(i--)
				j = Crc(j,*p++);
			}
		j = Crc(j,targets_xn(ll));
		if(ll->check != ~j) {
			ll->check = ~j;
			ListLib(ll);
			}
        return(ll);
		}
Ejemplo n.º 9
0
void GUI_ChangeImage(struct guiImage *image, const char *file, u16 x_off, u16 y_off)
{
    guiObject_t *obj = (guiObject_t *)image;
    //Use a CRC for comparison because the filename may change without the pointer changing
    u32 crc = Crc(file, strlen(file));
    if (image->file != file || image->crc != crc || image->x_off != x_off || image->y_off != y_off) {
        image->crc = crc;
        image->file = file;
        image->x_off = x_off;
        image->y_off = y_off;
        OBJ_SET_TRANSPARENT(obj, LCD_ImageIsTransparent(file));
        OBJ_SET_DIRTY(obj, 1);
    }
}
Ejemplo n.º 10
0
static const char *binding_string_cb(guiObject_t *obj, void *data)
{
    (void)data;
    u32 crc = Crc(tempstring, strlen(tempstring));
    if (obj && crc == dialogcrc)
        return tempstring;
    u32 bind_time = PROTOCOL_Binding();
    tempstring_cpy(_tr("Binding is in progress...\nMake sure model is on!\n\nPressing OK will NOT cancel binding procedure\nbut will allow full control of Tx."));
    u32 len = strlen(tempstring);
    if (bind_time != 0xFFFFFFFF && len < sizeof(tempstring)) {
        snprintf(tempstring + len, sizeof(tempstring) - len, _tr("\n\nBinding will end in %d seconds..."), (int)bind_time / 1000);
    }
    return tempstring;
}
Ejemplo n.º 11
0
void PAGE_ShowBindingDialog(u8 update)
{
    if (update && ! dialog)
        return;
    binding_string_cb(NULL, NULL);
    u32 crc = Crc(tempstring, strlen(tempstring));
    if (dialog && crc != dialogcrc) {
        GUI_Redraw(dialog);
    } else if(! dialog) {
        const char *title = Model.name[0] ? Model.name : _tr("Binding");
        dialog = GUI_CreateDialog(&gui->dialog, 10 + DLG_XOFFSET, 42 + DLG_YOFFSET, 300, 188, title, binding_string_cb, binding_ok_cb, dtOk, NULL);
    }
    dialogcrc = crc;
}
Ejemplo n.º 12
0
void PAGE_ShowBindingDialog(u8 update)
{
    if (update && ! dialog)
        return;
    binding_string_cb(NULL, NULL);
    u32 crc = Crc(tempstring, strlen(tempstring));
    if (dialog && crc != dialogcrc) {
        GUI_Redraw(dialog);
    } else if(! dialog) {
        dialog = GUI_CreateDialog(&gui->dialog, DIALOG2_X, DIALOG2_Y,
                     DIALOG2_WIDTH, DIALOG2_HEIGHT, NULL, NULL, binding_ok_cb, dtOk, tempstring);
    }
    dialogcrc = crc;
}
Ejemplo n.º 13
0
static const char *binding_string_cb(guiObject_t *obj, void *data)
{
    (void)data;
    u32 crc = Crc(tempstring, strlen(tempstring));
    if (obj && crc == dialogcrc)
        return tempstring;
    u32 bind_time = PROTOCOL_Binding();
    char tmp[10];
    snprintf(tmp, 10, "%s", Model.name);
    snprintf(tempstring, sizeof(tempstring), _tr("Binding %s...\nPress ENT to stop"), tmp);
    if (bind_time != 0xFFFFFFFF ) {
        int len = strlen(tempstring);
        snprintf(tempstring + len, sizeof(tempstring) - len, _tr("\n%d seconds left"), (int)bind_time / 1000);
    }
    return tempstring;
}
Ejemplo n.º 14
0
void PAGE_ShowSafetyDialog()
{
    if (dialog) {
        u64 unsafe = safety_check();
        if (! unsafe) {
            DialogClose(dialog, 0);
            safety_confirmed();
        } else {
            safety_string_cb(NULL, NULL);
            u32 crc = Crc(tempstring, strlen(tempstring));
            if (crc != dialogcrc) {
                GUI_Redraw(dialog);
                dialogcrc = crc;
            }
        }
    } else {
        tempstring[0] = 0;
        dialogcrc = 0;
        dialog = GUI_CreateDialog(&gui->dialog, DIALOG1_X, DIALOG1_Y,
                 DIALOG1_WIDTH, DIALOG1_HEIGHT, NULL, safety_string_cb, safety_ok_cb, dtOk, NULL);
    }
}
Ejemplo n.º 15
0
void _GUI_ChangeImage(struct guiImage *image, const char *file, u16 x_off, u16 y_off, u8 replace)
{
    guiObject_t *obj = (guiObject_t *)image;
    //Use a CRC for comparison because the filename may change without the pointer changing
    u32 crc = Crc(file, strlen(file));
    if (image->file != file || image->crc != crc || image->x_off != x_off || image->y_off != y_off) {
        if (replace) {
            // draw background where the old picture was bigger
            struct guiBox *box = &obj->box;
            u16 w, h;
            LCD_ImageDimensions(file, &w, &h);
            if (h < box->height) GUI_DrawBackground(box->x, box->y + h, box->width, box->height - h);    // remove lower left part of old image
            if (w < box->width) GUI_DrawBackground(box->x + w, box->y, box->width - w, h < box->height ? h : box->height);    // remove upper right part of old image
            box->width = w;
            box->height = h;
        }
        image->crc = crc;
        image->file = file;
        image->x_off = x_off;
        image->y_off = y_off;
        OBJ_SET_TRANSPARENT(obj, LCD_ImageIsTransparent(file));
        OBJ_SET_DIRTY(obj, 1);
    }
}
Ejemplo n.º 16
0
//=============================================================================
//	eFdd::UpdateCRC
//-----------------------------------------------------------------------------
void eFdd::UpdateCRC(eUdi::eTrack::eSector* s) const
{
	int len = s->Len();
	SectorDataW(s, len, swap_byte_order(Crc(s->data - 1, len + 1)));
}
Ejemplo n.º 17
0
// Reads all memory pages
int CmdHF15DumpMem(const char*Cmd) {
	UsbCommand resp;
	uint8_t uid[8];	
	uint8_t *recv=NULL;
	UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
	uint8_t *req=c.d.asBytes;
	int reqlen=0;
	int blocknum=0;
	char output[80];
		
	if (!getUID(uid)) {
		PrintAndLog("No Tag found.");
		return 0;
	}
	
	PrintAndLog("Reading memory from tag UID=%s",sprintUID(NULL,uid));
	PrintAndLog("Tag Info: %s",getTagInfo(uid));

	for (int retry=0; retry<5; retry++) {
		
		req[0]= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | 
		        ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS;
		req[1]=ISO15_CMD_READ;
		memcpy(&req[2],uid,8);
		req[10]=blocknum;
		reqlen=AddCrc(req,11);
		c.arg[0]=reqlen;
	
		SendCommand(&c);
		
		if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
			recv = resp.d.asBytes;
			if (ISO15_CRC_CHECK==Crc(recv,resp.arg[0])) {
				if (!(recv[0] & ISO15_RES_ERROR)) {
					retry=0;
					*output=0; // reset outputstring
					sprintf(output, "Block %02x   ",blocknum);
					for ( int i=1; i<resp.arg[0]-2; i++) { // data in hex
						sprintf(output+strlen(output),"%02X ",recv[i]);
					}					
					strcat(output,"   "); 
					for ( int i=1; i<resp.arg[0]-2; i++) { // data in cleaned ascii
						sprintf(output+strlen(output),"%c",(recv[i]>31 && recv[i]<127)?recv[i]:'.');					
					}					
					PrintAndLog("%s",output);	
					blocknum++;
					// PrintAndLog("bn=%i",blocknum);
				} else {
					PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1])); 
					return 0;
				}
			} // else PrintAndLog("crc");
		} // else PrintAndLog("r null");
	} // retry
  // TODO: need fix
//	if (resp.arg[0]<3)
//		PrintAndLog("Lost Connection");
//	else if (ISO15_CRC_CHECK!=Crc(resp.d.asBytes,resp.arg[0]))
//		PrintAndLog("CRC Failed");
//	else 
//		PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1])); 
	return 0;
}
Ejemplo n.º 18
0
//=============================================================================
//	eFdd::CreateTrd
//-----------------------------------------------------------------------------
void eFdd::CreateTrd()
{
	SAFE_DELETE(disk);
	disk = new eUdi(eUdi::MAX_CYL, eUdi::MAX_SIDE);
	for(int i = 0; i < disk->Cyls(); ++i)
	{
		for(int j = 0; j < disk->Sides(); ++j)
		{
			Seek(i, j);

			int id_len = Track().data_len / 8 + ((Track().data_len & 7) ? 1 : 0);
			memset(Track().data, 0, Track().data_len + id_len);

			int pos = 0;
			WriteBlock(pos, 0x4e, 80);		//gap4a
			WriteBlock(pos, 0, 12);			//sync
			WriteBlock(pos, 0xc2, 3, true);	//iam
			Write(pos++, 0xfc);

			const int max_trd_sectors = 16;
			static const byte lv[3][max_trd_sectors] =
			{
				{ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 },
				{ 1,9,2,10,3,11,4,12,5,13,6,14,7,15,8,16 },
				{ 1,12,7,2,13,8,3,14,9,4,15,10,5,16,11,6 }
			};
			Track().sectors_amount = max_trd_sectors;
			for(int i = 0; i < max_trd_sectors; ++i)
			{
				WriteBlock(pos, 0x4e, 40);		//gap1 50 fixme: recalculate gap1 only for non standard formats
				WriteBlock(pos, 0, 12);			//sync
				WriteBlock(pos, 0xa1, 3, true);	//id am
				Write(pos++, 0xfe);
				eUdi::eTrack::eSector& sec = Sector(i);
				sec.id = Track().data + pos;
				Write(pos++, cyl);
				Write(pos++, side);
				Write(pos++, lv[trdos_interleave][i]);
				Write(pos++, 1); //256byte
				word crc = Crc(Track().data + pos - 5, 5);
				Write(pos++, crc >> 8);
				Write(pos++, (byte)crc);

				WriteBlock(pos, 0x4e, 22);		//gap2
				WriteBlock(pos, 0, 12);			//sync
				WriteBlock(pos, 0xa1, 3, true);	//data am
				Write(pos++, 0xfb);
				sec.data = Track().data + pos;
				int len = sec.Len();
				crc = Crc(Track().data + pos - 1, len + 1);
				pos += len;
				Write(pos++, crc >> 8);
				Write(pos++, (byte)crc);
			}
			if(pos > Track().data_len)
			{
				assert(0); //track too long
			}
			WriteBlock(pos, 0x4e, Track().data_len - pos - 1); //gap3
		}
	}
	eUdi::eTrack::eSector* s = GetSector(0, 0, 9);
	if(!s)
		return;
	s->data[0xe2] = 1;					// first free track
	s->data[0xe3] = 0x16;				// 80T,DS
	SectorDataW(s, 0xe5, 2544);			// free sec
	s->data[0xe7] = 0x10;				// trdos flag
	UpdateCRC(s);
}
Ejemplo n.º 19
0
static typename Crc::value_type crc_( const char* buf, std::size_t size )
{
    return std::for_each( buf, buf + size, Crc() )();
}
Ejemplo n.º 20
0
// Mode 3
//helptext
int CmdHF15Demod(const char *Cmd) {
	char cmdp = param_getchar(Cmd, 0);
	if (cmdp == 'h' || cmdp == 'H') return usage_15_demod();
	
	// The sampling rate is 106.353 ksps/s, for T = 18.8 us
	int i, j;
	int max = 0, maxPos = 0;
	int skip = 4;

	if (GraphTraceLen < 1000) return 0;

	// First, correlate for SOF
	for (i = 0; i < 1000; i++) {
		int corr = 0;
		for (j = 0; j < ARRAYLEN(FrameSOF); j += skip) {
			corr += FrameSOF[j] * GraphBuffer[i + (j / skip)];
		}
		if (corr > max) {
			max = corr;
			maxPos = i;
		}
	}

	PrintAndLogEx(NORMAL, "SOF at %d, correlation %d", maxPos, max / (ARRAYLEN(FrameSOF) / skip));
	
	i = maxPos + ARRAYLEN(FrameSOF) / skip;
	int k = 0;
	uint8_t outBuf[20];
	memset(outBuf, 0, sizeof(outBuf));
	uint8_t mask = 0x01;
	for (;;) {
		int corr0 = 0, corr1 = 0, corrEOF = 0;
		for (j = 0; j < ARRAYLEN(Logic0); j += skip) {
			corr0 += Logic0[j] * GraphBuffer[i + (j / skip)];
		}
		for (j = 0; j < ARRAYLEN(Logic1); j += skip) {
			corr1 += Logic1[j] * GraphBuffer[i + (j / skip)];
		}
		for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) {
			corrEOF += FrameEOF[j] * GraphBuffer[i + (j / skip)];
		}
		// Even things out by the length of the target waveform.
		corr0 *= 4;
		corr1 *= 4;
		
		if (corrEOF > corr1 && corrEOF > corr0) {
			PrintAndLogEx(NORMAL, "EOF at %d", i);
			break;
		} else if (corr1 > corr0) {
			i += ARRAYLEN(Logic1) / skip;
			outBuf[k] |= mask;
		} else {
			i += ARRAYLEN(Logic0) / skip;
		}
		mask <<= 1;
		if (mask == 0) {
			k++;
			mask = 0x01;
		}
		if ((i + (int)ARRAYLEN(FrameEOF)) >= GraphTraceLen) {
			PrintAndLogEx(NORMAL, "ran off end!");
			break;
		}
	}
	
	if (mask != 0x01) {
		PrintAndLogEx(WARNING, "Error, uneven octet! (discard extra bits!)");
		PrintAndLogEx(NORMAL, "   mask = %02x", mask);
	}
	PrintAndLogEx(NORMAL, "%d octets", k);
	
	for (i = 0; i < k; i++)
		PrintAndLogEx(NORMAL, "# %2d: %02x ", i, outBuf[i]);

	PrintAndLogEx(NORMAL, "CRC %04x", Crc(outBuf, k - 2));
	return 0;
}
Ejemplo n.º 21
0
//=============================================================================
//	eFdd::ReadFdi
//-----------------------------------------------------------------------------
bool eFdd::ReadFdi(const void* _data, size_t data_size)
{
	const byte* buf = (const byte*)_data;
	SAFE_DELETE(disk);
	disk = new eUdi(buf[4], buf[6]);

	const byte* trk = buf + 0x0E + Word(buf + 0x0C);
	const byte* dat = buf + Word(buf + 0x0A);

	for(int i = 0; i < disk->Cyls(); ++i)
	{
		for(int j = 0; j < disk->Sides(); ++j)
		{
			Seek(i, j);

			int id_len = Track().data_len / 8 + ((Track().data_len & 7) ? 1 : 0);
			memset(Track().data, 0, Track().data_len + id_len);

			int pos = 0;
			WriteBlock(pos, 0x4e, 80);		//gap4a
			WriteBlock(pos, 0, 12);			//sync
			WriteBlock(pos, 0xc2, 3, true);	//iam
			Write(pos++, 0xfc);

			const byte* t0 = dat + Dword(trk);
			int ns = trk[6];
			Track().sectors_amount = ns;
			trk += 7;
			for(int i = 0; i < ns; ++i)
			{
				WriteBlock(pos, 0x4e, 40);		//gap1 50 fixme: recalculate gap1 only for non standard formats
				WriteBlock(pos, 0, 12);			//sync
				WriteBlock(pos, 0xa1, 3, true);	//id am
				Write(pos++, 0xfe);
				eUdi::eTrack::eSector& sec = Sector(i);
				sec.id = Track().data + pos;
				Write(pos++, trk[0]);
				Write(pos++, trk[1]);
				Write(pos++, trk[2]);
				Write(pos++, trk[3]);
				word crc = Crc(Track().data + pos - 5, 5);
				Write(pos++, crc >> 8);
				Write(pos++, (byte)crc);

				if(trk[4] & 0x40)
				{
					sec.data = NULL;
				}
				else
				{
					const byte* data = t0 + Word(trk+5);
					if(data + 128 > buf + data_size)
						return false;
					WriteBlock(pos, 0x4e, 22);		//gap2
					WriteBlock(pos, 0, 12);			//sync
					WriteBlock(pos, 0xa1, 3, true);	//data am
					Write(pos++, 0xfb);
					sec.data = Track().data + pos;
					int len = sec.Len();
					memcpy(sec.data, data, len);
					crc = Crc(Track().data + pos - 1, len + 1);
					if(!(trk[4] & (1<<(trk[3] & 3))))
						crc ^= 0xffff;
					pos += len;
					Write(pos++, crc >> 8);
					Write(pos++, (byte)crc);
				}
				trk += 7;
			}
			if(pos > Track().data_len)
			{
				assert(0); //track too long
			}
			WriteBlock(pos, 0x4e, Track().data_len - pos - 1); //gap3
		}
	}
	return true;
}