/* * Copyright (C) 2020 Gavin MacGregor * * This file is part of QTeletextMaker. * * QTeletextMaker is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * QTeletextMaker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with QTeletextMaker. If not, see . */ #include "loadsave.h" #include #include #include #include "document.h" #include "pagebase.h" // Used by TTI and hashstring int controlBitsToPS(PageBase *subPage) { // C4 Erase page is stored in bit 14 int pageStatus = 0x8000 | (subPage->controlBit(PageBase::C4ErasePage) << 14); // C5 to C11 stored in order from bits 1 to 6 for (int i=PageBase::C5Newsflash; i<=PageBase::C11SerialMagazine; i++) pageStatus |= subPage->controlBit(i) << (i-1); // Apparently the TTI format stores the NOS bits backwards pageStatus |= subPage->controlBit(PageBase::C12NOS) << 9; pageStatus |= subPage->controlBit(PageBase::C13NOS) << 8; pageStatus |= subPage->controlBit(PageBase::C14NOS) << 7; return pageStatus; } void saveTTI(QSaveFile &file, const TeletextDocument &document) { int p; QTextStream outStream(&file); auto write7bitPacket=[&](int packetNumber) { if (document.subPage(p)->packetNeeded(packetNumber)) { QByteArray outLine = document.subPage(p)->packet(packetNumber); outStream << QString("OL,%1,").arg(packetNumber); for (int c=0; cpacketNeeded(packetNumber, designationCode)) { QByteArray outLine = document.subPage(p)->packet(packetNumber, designationCode); outStream << QString("OL,%1,").arg(packetNumber); // TTI stores raw values with bit 7 set, doesn't do Hamming encoding outLine[0] = designationCode | 0x40; for (int c=1; c 1; for (p=0; pcycleValue()).arg(document.subPage(p)->cycleType()==LevelOnePage::CTcycles ? 'C' : 'T') << Qt::endl; else // X/28/0 specifies page function and coding but the PF command // should make it obvious to a human that this isn't a Level One Page outStream << QString("PF,%1,%2").arg(document.pageFunction()).arg(document.packetCoding()) << Qt::endl; bool writeFLCommand = false; if (document.pageFunction() == TeletextDocument::PFLevelOnePage && document.subPage(p)->packetNeeded(27,0)) { // Subpage has FastText links - if any link to a specific subpage, we need to write X/27/0 as raw // otherwise we write the links as a human-readable FL command later on writeFLCommand = true; // TODO uncomment this when we can edit FastText subpage links /*for (int i=0; i<6; i++) if (document.subPage(p)->fastTextLinkSubPageNumber(i) != 0x3f7f) { writeFLCommand = false; break; }*/ } // X27 then X28 always come first for (int i=(writeFLCommand ? 1 : 0); i<16; i++) writeHammingPacket(27, i); for (int i=0; i<16; i++) writeHammingPacket(28, i); if (document.packetCoding() == TeletextDocument::Coding7bit) { // For 7 bit coding i.e. Level One Pages, X/26 are written before X/1 to X/25 for (int i=0; i<16; i++) writeHammingPacket(26, i); for (int i=1; i<=24; i++) write7bitPacket(i); } else { // For others (especially (G)POP pages) X/1 to X/25 are written before X/26 for (int i=1; i<=25; i++) writeHammingPacket(i); for (int i=0; i<16; i++) writeHammingPacket(26, i); } if (writeFLCommand) { outStream << "FL,"; for (int i=0; i<6; i++) { // Stored as page link with relative magazine number, convert to absolute page number for display int absoluteLinkPageNumber = document.subPage(p)->fastTextLinkPageNumber(i) ^ (document.pageNumber() & 0x700); // Fix magazine 0 to 8 if ((absoluteLinkPageNumber & 0x700) == 0x000) absoluteLinkPageNumber |= 0x800; outStream << QString("%1").arg(absoluteLinkPageNumber, 3, 16, QChar('0')); if (i<5) outStream << ','; } outStream << Qt::endl; } subPageNumber++; } }