Renamed

Dependencies:   mbed

send_pc1403.cpp

Committer:
ffxx68
Date:
2022-03-29
Revision:
5:062962db7a48
Parent:
2:dff96be9617e

File content as of revision 5:062962db7a48:

#include "send_pc1403.h"

///////////////////////////////////////////////////////
// variables from PocketTools code
uint  SHCc = 0 ,      /* Read not from bin, but from Transfile PC plus SHC-format (header included) */
      SHCe = 0 ;      /* End marks are the SHC Basic image included only*/
uint  QTc  = 0 ;      /* Write to Quick-Tape wave format */
uint  STc  = 0 ;      /* Header of SuperTape or file header of PC-1600 format is in the image included */
uint  TAPc = 0 ;      /* Write not to wave format but to emulator tap format (raw bytes)*/
uint  Qcnt = 0 ;      /* Quiet, minimal output */
uint  Scnt = 0 ;      /* Number of sync parameters or sync and sync spaces was defined */
uint  Acnt = 0 ;      /* Number of address parameters, non standard load or entry addresses */
uint  Mcnt = 0 ;      /* Read header parameter from a file */

double  speed = 1.00 ;  /* Used it for modified Pocket Computer with a CPU Speed Up switched on */

ulong  pcId  = 1500 ;  /* ID number of the pocket computer */
ushort pcgrpId = IDENT_UNKNOWN ;
// ulong  pcAddr = 0 ;         /* PC-specific address, used for the end of variable data of PCs with DB-tables */
bool  cnvstr_upr = false ; /* Convert strings to upper, for Pokecon with SML-key not */
bool  type_asm = false ;   /* Image contains assembler source code (subtype), true for CASL and CAP-X */
// TODO (mr#2#): Count all warnings and errors
ulong  err_cnt = 0 ;    /* counts minor errors */
ulong  wrn_cnt = 0 ;    /* counts warnings */

FileInfo  fileInfo ;    /* File information */

////////////////////////////////////////////////////////////////////////////////
// WriteBitToWav replaced from PocketTools version (writing to a WAV file)
// Here we send directly signals to OUT lines
int WriteBitToWav (int   value)
{
    // Calling the buffered bit-sending routine
    switch ( value ) {
        case 1:
            if  ( bitWaitSend ( value, 0 ) > MAX_BIT_TIME_ERR )
                return ( ERR_NOK ) ;
            break;
        case 0:
            if  ( bitWaitSend ( value, 0 ) > MAX_BIT_TIME_ERR )
                return ( ERR_NOK ) ;
            break;
        default:
            break;
    }
        
    return ( ERR_OK ) ;
}

////////////////////////////////////////////////////////////////////////////////
// Write* methods taken from Pocket-Tools source code 
// https://www.peil-partner.de/ifhe.de/sharp/
int WriteQuaterToWav (uint   value,
                      uint   stopBits)
{
      uint  tmp ;
      uint  ii ;
       int  error ;

    // if (TAPc > 0) return (WriteQuaterToTap (value )); // no  
    
    do {
        
        error = WriteBitToWav (0 ) ;
        if (error != ERR_OK) break ;

        for ( ii = 0 ; ii < 4 ; ++ii ) {
            tmp = 1 << ii ;
            if ( (value & tmp) == 0 )
                error = WriteBitToWav (0 ) ;
            else
                error = WriteBitToWav (1 ) ;

            if (error != ERR_OK) break ;
        }
        if (error != ERR_OK) break ;

        for ( ii = 0 ; ii < stopBits ; ++ii ) {
            error = WriteBitToWav (1 ) ;
            if (error != ERR_OK) break ;
        }
        if (error != ERR_OK) break ;

    } while (0) ;
    return (error);
}

int WriteByteToWav (ulong  value,
                    uchar  order,
                    uchar  mode)
{
      uint  lsq ;
      uint  msq ;
      int  error ;

    // if (TAPc > 0) return (WriteByteToTap (value, order )) ; // no  

    // if (order == ORDER_E) return (WriteByteToEWav (value )) ; // no  1403

    do {
        lsq = value & 0x0F ;
        msq = (value >> 4) & 0x0F ;
        if (order == ORDER_INV) {
            error = WriteQuaterToWav (lsq, Mode[mode].stopb1 ) ;
            if (error != ERR_OK) break ;
            error = WriteQuaterToWav (msq, Mode[mode].stopb2 ) ;
            if (error != ERR_OK) break ;
        }
        else {
            error = WriteQuaterToWav (msq, Mode[mode].stopb1 ) ;
            if (error != ERR_OK) break ;
            error = WriteQuaterToWav (lsq, Mode[mode].stopb2 ) ;
            if (error != ERR_OK) break ;
        }

    } while (0) ;
    return (error);
}

int CheckSumB1 (  ulong  Byte )
{
    ushort sum ;

    /* Update the checksum */
        sum = fileInfo.sum + ((Byte & 0xF0) >> 4) ;
        if (sum > 0xFF) {
            ++sum ;
            sum &= 0xFF ;
            }
        fileInfo.sum = (sum + (Byte & 0x0F)) & 0xFF ;

    return (0);
}


int CheckSumE (  ulong  Byte 
//               ulong*  ptrSum 
      )
{
    uint tmp, ii ;

    /* Update the checksum */
    tmp = 0x80 ;
    for ( ii = 0 ; ii < 8 ; ++ii, tmp >>= 1 )
        if ( (Byte & tmp) != 0 )  
            // ++ *ptrSum ;
             ++ fileInfo.sum ;

    return (0);
}


int WriteSyncToWav (ulong  nbSync )
{
    ulong  ii ;
    int    error = ERR_OK ;

    if (TAPc > 0) return (ERR_OK); // no

    do {
        /* Write the Synchro patern */
        for ( ii = 0 ; ii < nbSync ; ++ii ) {
            error = WriteBitToWav (1 ) ;
            if (error != ERR_OK) break ;
        }
        if (error != ERR_OK) break ;

    } while (0) ;
    return (error);
}

int WriteUsedatLenToQTWav ( uchar  order, /* Quick-Tape incomplete blocks with fill data */
                            uchar  mode )
{   long tmpL ;
    int  error ;

    tmpL = fileInfo.nbByte - fileInfo.total_diff - fileInfo.total ; //not for IDENT_QT_DAT: variable block in RAM based

    if (tmpL > 0) {
            if (tmpL > BLK_OLD) tmpL = BLK_OLD ;
            --tmpL ;
            if (tmpL < BLK_OLD -1) fileInfo.usedat_len = tmpL + 1 ;
            else fileInfo.usedat_len = 0 ; /* L:0x4F ignored, no effect */

            error = WriteByteToWav (tmpL, order, mode ) ;
            if (error != ERR_OK) return (error) ;
            if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG (L:%02X)", (uint) tmpL);

            fileInfo.sum = tmpL ;
    }
    else if (tmpL == 0 ) error = ERR_OK ;
    else {
            printf(" WUsedatLQT: End of file was expected");
            error = ERR_FMT ;
    }
    fileInfo.count = 0 ;

    return (error);
}

int WriteByteSumToWav (ulong  value,
                       uchar  order,
                       uchar  mode)
{
    int   error ;
    bool  writ_full_block = false ;
    
    do {

        if ( (fileInfo.debug & 0x0040) > 0)  
            debug_printf(" %02X", (uchar) value);
        error = WriteByteToWav (value, order, mode ) ;
        if (error != ERR_OK) break ;

        if (mode == MODE_B22 || mode == MODE_B11) fileInfo.sum += value ;
        else if (mode == MODE_B9 || mode == MODE_B10) CheckSumE (value ) ; //ptrFile
        else CheckSumB1 (value ) ;

        ++fileInfo.count ;
        if (!writ_full_block) ++fileInfo.total ;

        if ( fileInfo.usedat_len > 0) { /* QTape incomplete block */
            if (--fileInfo.usedat_len == 0) {
                if ( ( (fileInfo.debug & 0x0040) > 0 ) && (Qcnt == 0) ) debug_printf("DEBUG Fill data:");
                value = 0x00 ;
                writ_full_block = true ;
            }
        }

        switch (mode) {
        case MODE_B22 :
            if ( fileInfo.count >= BLK_OLD ) {

                if ( (fileInfo.debug & 0x0040) > 0 )
                    debug_printf(" (%04X)\n\r", (uint) fileInfo.sum);

                /* Write the checksum */
                error = WriteByteToWav (fileInfo.sum >> 8 & 0xFF, order, mode ) ;
                if (error != ERR_OK) break ;
                error = WriteByteToWav (fileInfo.sum & 0xFF, order, mode ) ;
                if (error != ERR_OK) break ;

                fileInfo.count = 0 ;
                fileInfo.sum   = 0 ;
            }
            break ;

        case MODE_B21 :
        case MODE_B20 :
        case MODE_B19 :
            if ( (fileInfo.count % BLK_OLD_SUM) == 0) {

                if ( (fileInfo.debug & 0x0040) > 0 )
                    debug_printf(" (%02X)\n\r", (uchar) fileInfo.sum);

                /* Write the checksum */
                error = WriteByteToWav (fileInfo.sum, order, mode ) ;
                if (error != ERR_OK) break ;

                if ( fileInfo.count >= BLK_OLD ) {
                    fileInfo.count = 0 ;
                    fileInfo.sum   = 0 ;
                    // if (pcgrpId==IDENT_PC1211) error = WriteSyncToWav (1803 ) ; //DATA not
                    if (fileInfo.ident == IDENT_PC1211) /* default 1803 bits, data not */
                        error = WriteSyncToWav (fileInfo.nbSync ) ;
                }
            }
            break ;

        case MODE_B17 :
        case MODE_B16 :
        case MODE_B15 :
            if ( fileInfo.count >= BLK_OLD_SUM) {

                if ( (fileInfo.debug & 0x0040) > 0 )
                    debug_printf(" (%02X)\n\r", (uchar) fileInfo.sum);

                /* Write the checksum */
                error = WriteByteToWav (fileInfo.sum, order, mode) ;
                if (error != ERR_OK) break ;

                fileInfo.count = 0 ;
                fileInfo.sum   = 0 ;
            }
            break ;

        case MODE_B14 :
        case MODE_B13 :
            if ( fileInfo.count >= BLK_NEW ) {

                if ( (fileInfo.debug & 0x0040) > 0 )
                    debug_printf(" *(%02X)", (uchar) fileInfo.sum);

                /* Write the checksum */
                error = WriteByteToWav (fileInfo.sum, order, mode ) ;
                if (error != ERR_OK) break ;

                fileInfo.count = 0 ;
                fileInfo.sum   = 0 ;
            }
            break ;

        case MODE_B9 : /* PC-E/G/1600 */
            if ( fileInfo.count >= fileInfo.block_len ) {

                if ( (fileInfo.debug & 0x0040) > 0 )
                    debug_printf(" (%04X)\n\r", (uint) fileInfo.sum & 0xFFFF);

                /* Write the checksum */
                error = WriteByteToWav (fileInfo.sum >> 8 & 0xFF, order, mode ) ;
                if (error != ERR_OK) break ;
                error = WriteByteToWav (fileInfo.sum & 0xFF, order, mode ) ;
                if (error != ERR_OK) break ;

                fileInfo.count = 0 ;
                fileInfo.sum   = 0 ;
            }
            break ;

        case MODE_B10 : /* SuperTape */
            if ( fileInfo.count >= fileInfo.block_len ) {

                if ( (fileInfo.debug & 0x0040) > 0 )
                    debug_printf(" (%04X)", (uint) fileInfo.sum & 0xFFFF);

                /* Write the checksum */
                error = WriteByteToWav (fileInfo.sum & 0xFF, order, mode ) ;
                if (error != ERR_OK) break ;
                error = WriteByteToWav (fileInfo.sum >> 8 & 0xFF, order, mode ) ;
                if (error != ERR_OK) break ;

                if ( (fileInfo.debug & 0x0040) > 0) debug_printf(" %02X", (uchar) SUPT_END);
                error = WriteByteToWav (SUPT_END, order, mode ) ;
                if (error != ERR_OK) break ;

                fileInfo.count = 0 ;
                fileInfo.sum   = 0 ;
            }
            break ;

        case MODE_B11 :
            if ( fileInfo.count >= BLK_OLD ) {

                if ( (fileInfo.debug & 0x0040) > 0 )
                    debug_printf(" (%04X)\n\r", (uint) fileInfo.sum);
                /* Write the checksum */
                error = WriteByteToWav (fileInfo.sum >> 8 & 0xFF, order, mode ) ;
                if (error != ERR_OK) break ;
                error = WriteByteToWav (fileInfo.sum & 0xFF, order, mode ) ;
                if (error != ERR_OK) break ;

                error = WriteByteToWav (EOF_15, order, mode ) ;
                if (error != ERR_OK) break ;
                if ( (fileInfo.debug & 0x0040) > 0) debug_printf(" (E:%02X)", (uint) EOF_15);
                writ_full_block = false ;

                error = WriteSyncToWav (50 ) ; /* 0.02 s */
                if (error != ERR_OK) break ;
                error = WriteUsedatLenToQTWav (order, mode ) ;
            }
            break ;

        default :
            debug_printf ("%s: Unknown Mode\n", argP) ;
            break ;
        }

    } while (writ_full_block) ;

    return (error);
}

ulong SwapByte (ulong byte)
{
    return ( (byte >> 4) + (byte << 4 & 0xF0) );
}

/* File name for New and Old BASIC */
int WriteSaveNameToWav (char*  ptrName,
                        uchar  mode)
{
     uint  ii ;
     uint  tmpL ;
     char  byte ;
     char  tmpS[20] ;
      int  error ;

   if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG ptrName %s\n\r", ptrName);

    do {
        /* Uppercase the name is done in main if needed */
        // tmpL = strlen (ptrName) ;
        for (ii = 0; ii < cLPF-1 && ptrName[ii] != '\0'; ii++) ;
        tmpL = ii;
        
        if (tmpL > 7)
            tmpL = 7 ;
            
        for ( ii = 0 ; ii < tmpL ; ++ii )
            tmpS[ii] = ptrName[ii] ;
    
        tmpS[tmpL] = 0 ;
        //if (Qcnt == 0) debug_printf ("Save name    : %s\n", tmpS) ;
        // strncpy( ptrName, tmpS, cLPF-1) ;
        for (ii = 0; ii < cLPF-1 && ptrName[ii] != '\0'; ii++) 
           tmpS[ii] = ptrName[ii]; 
       /* crash?
       for ( ; ii < cLPF-1; ii++)
           tmpS[ii] = '\0';
       */
       tmpL = 7 - tmpL ;
       for ( ii = 0 ; ii < tmpL ; ++ii )
            tmpS[ii] = 0 ;

        if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG tmpS %s\n\r", tmpS);
        for ( ii = tmpL ; ii < 7 ; ++ii ) {
            byte = (ulong) ptrName[6 - ii] ;

            switch (mode) {
            case MODE_B19 :
            case MODE_B20 :

                if (byte < 0x80)
                    byte = (char)CodeOld[byte] ;
                else
                    byte = (char)CodeOld[0] ;
                break ;

            default :

                if (byte >= 0x80)
                    byte = 0x20 ;
                break ;
            }
            tmpS[ii] = (char) SwapByte(byte) ;
        }
        tmpS[7] = 0x5F ;

        /* Write the Name */
        fileInfo.count = 0 ;
        fileInfo.sum   = 0 ;
        for ( ii = 0 ; ii < 8 ; ++ii ) {
            error = WriteByteSumToWav (tmpS[ii], ORDER_STD, mode ) ;
            if (error != ERR_OK) break ;
        }

        if (fileInfo.ident == IDENT_PC1211)
            error = WriteSyncToWav (151 ) ;
        else if (fileInfo.ident == IDENT_PC121_DAT)
            error = WriteSyncToWav (111 ) ;

        fileInfo.count = 0 ;
        fileInfo.sum   = 0 ;

    } while (0) ;
    return (error);
}

int DEBUGSaveNameToWav (char*  ptrName,
                        uchar  mode)
{
     uint  ii ;
     uint  i ;
    ulong  byte ;
    ulong  tmpL ;
     char  tmpS[10] ;
      int  error ;

    do {
        /* Uppercase the name is done in main if needed */
        tmpL = strlen (ptrName) ;
        debug_printf("DEBUG tmpL %u\n\r", tmpL);

        if (tmpL > 7)
            tmpL = 7 ;

        for ( ii = 0 ; ii < tmpL ; ++ii ) {
            debug_printf("DEBUG ptrName[ii] %c\n\r", ptrName[ii]);
            tmpS[ii] = ptrName[ii] ;
        }
        tmpS[tmpL] = 0 ;
        //if (Qcnt == 0) debug_printf ("Save name    : %s\n", tmpS) ;
        debug_printf("DEBUG ptrName %s\n\r", ptrName);
        debug_printf("DEBUG i 1 ");

        // strncpy( ptrName, tmpS, cLPF-1) ;
        for (i = 0; i < cLPF-1 && ptrName[i] != '\0'; i++) {
           debug_printf("%u ", i);
           tmpS[i] = ptrName[i]; 
        }
        debug_printf("\n\rDEBUG i 2 ");
        /* crash?
        for ( ; i < cLPF-1; i++) {
            debug_printf("%u ", i);
            tmpS[i] = '\0';
        }
        */
        debug_printf("\n\rDEBUG tmpS %s\n\r", tmpS);
        tmpL = 7 - tmpL ;
        for ( ii = 0 ; ii < tmpL ; ++ii )
            tmpS[ii] = 0 ;
        debug_printf("DEBUG tmpS %s\n\r", tmpS);

        /* reverse-order bytes */
        for ( ii = tmpL ; ii < 7 ; ++ii ) {
            byte = (ulong) ptrName[6 - ii] ;
            debug_printf("DEBUG byte %u\n\r", byte);

            switch (mode) {
            case MODE_B19 :
            case MODE_B20 :

                if (byte < 0x80)
                    byte = (char)CodeOld[byte] ;
                else
                    byte = (char)CodeOld[0] ;
                break ;

            default :

                if (byte >= 0x80)
                    byte = 0x20 ;
                break ;
            }
            tmpS[ii] = (char) SwapByte(byte) ;
        }
        tmpS[7] = 0x5F ;
        debug_printf("DEBUG ii %u\n\r", ii);

        /* Write the Name */
        fileInfo.count = 0 ;
        fileInfo.sum   = 0 ;
        for ( ii = 0 ; ii < 8 ; ++ii ) {
            error = WriteByteSumToWav (tmpS[ii], ORDER_STD, mode ) ;
            if (error != ERR_OK) break ;
        }
        if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG Name - Bytes was printed swapped.\n\r");

        if (fileInfo.ident == IDENT_PC1211)
            error = WriteSyncToWav (151 ) ;
        else if (fileInfo.ident == IDENT_PC121_DAT)
            error = WriteSyncToWav (111 ) ;

        fileInfo.count = 0 ;
        fileInfo.sum   = 0 ;

    } while (0) ;
    return (error);
}

/* Head of Binary Data for New and Old series */
int WriteHeadToBinWav (ulong  addr,
                       ulong  size,
                       uchar  mode)
{
      int  ii ;
    ulong  len ;
    ulong  tmpL ;
      int  error ;

    do {
    /*    if (Qcnt == 0)
    {
        debug_printf ("Start Address: 0x%04X\n", (uint) addr);
        debug_printf ("End   Address: 0x%04X, Length: %d bytes\n", (uint) (addr + size -1), (uint) size);
    }
    */

        fileInfo.count = 0 ;
        fileInfo.sum   = 0 ;
        for ( ii = 0 ; ii < 4 ; ++ii ) {
            error = WriteByteSumToWav (0, ORDER_STD, mode ) ;
            if (error != ERR_OK) break ;
        }

        /* Write the address, this method is necessary because of swapped checksums in the header. */
        tmpL = ((addr >> 4) & 0xF0) + (addr >> 12) ;        /* H swapped */
        error = WriteByteSumToWav (tmpL, ORDER_STD, mode ) ;
        if (error != ERR_OK) break ;

        tmpL = ((addr << 4) & 0xF0) + ((addr >> 4) & 0x0F) ;/* L swapped */
        error = WriteByteSumToWav (tmpL, ORDER_STD, mode ) ;
        if (error != ERR_OK) break ;

        /* Write the Length */
        len = size - 1 ;
        tmpL = ((len >> 4) & 0xF0) + (len >> 12) ;
        error = WriteByteSumToWav (tmpL, ORDER_STD, mode ) ;
        if (error != ERR_OK) break ;

        tmpL = ((len << 4) & 0xF0) + ((len >> 4) & 0x0F) ;
        error = WriteByteSumToWav (tmpL, ORDER_STD, mode ) ;
        if (error != ERR_OK) break ;

        fileInfo.count = 0 ;
        fileInfo.sum   = 0 ;

    } while (0) ;
    return (error);
}

int WriteFooterToNewWav ( void )
{
    int  error ;

    do {
        fileInfo.count = 0 ; /* no checksum writing from here until the end */

        error = WriteByteSumToWav(BAS_NEW_EOF, ORDER_STD, fileInfo.mode ) ;
        // error = WriteByteSumToB13Wav (BAS_NEW_EOF ) ;
        if (error != ERR_OK) break ;

        error = WriteByteToWav(BAS_NEW_EOF, ORDER_STD, fileInfo.mode ) ;
        if (error != ERR_OK) break ;

        if ( (fileInfo.debug & 0x00C0) > 0 )
            debug_printf(" EOF:%02X", (uchar) BAS_NEW_EOF);

        error = WriteByteToWav(fileInfo.sum, ORDER_STD, fileInfo.mode ) ;
        if (error != ERR_OK) break ;

        if ( (fileInfo.debug & 0x0040) > 0 )
            debug_printf(" (%02X)", (uchar) fileInfo.sum);

    /* there are 2bits more HIGH at the end of transmission (at least for PC-1402) M. NOSSWITZ */
     error = WriteBitToWav (1 ) ;
    if (error != ERR_OK) break ;

    error = WriteBitToWav (1 ) ;
    if (error != ERR_OK) break ;
 
    /* This puts 2 bits of silence (or 2 HIGH bits alternatively) to the end of the wave file. */
    /* CLOAD does not accept any sound, that could be interpreted as a start bit,              */
    /* during post-processing. Original CSAVE switches the signal low ms after the            */
    /* end of transmission, before the motor of the cassette recorder is switched off.        */
    /* This level out is visible in the CSAVE audio signal after the last bit. T. Muecker     */
    /* not needed for the MBed direct-write version
    error = WriteBitToWav (3 ) ; 125us High , 
    if (error != ERR_OK) break ;
    error = WriteBitToWav (2 ) ; 1 ms Midsignal
    if (error != ERR_OK) break ;
    */

    } while (0) ;
    return (error);
}

int WriteFooterToMemoWav ( void )
{
    int  error ;

    do {
        error = WriteByteToWav(fileInfo.sum, ORDER_STD, fileInfo.mode ) ;
        if (error != ERR_OK) break ;

        if ( (fileInfo.debug & 0x0040) > 0 )
            debug_printf(" (%02X)", (uchar) fileInfo.sum);

    error = WriteBitToWav (1 ) ;
    if (error != ERR_OK) break ;

    error = WriteBitToWav (1 ) ;
    if (error != ERR_OK) break ;

    /* This puts 2 bits of silence (or 2 HIGH bits alternatively) to the end of the wave file. */
    /* not needed for the MBed send version
    error = WriteBitToWav (3 ) ;
    if (error != ERR_OK) break ;

    error = WriteBitToWav (2 ) ;
    if (error != ERR_OK) break ;
    */

    } while (0) ;
    return (error);
}


// File completion check
bool isFileSendComplete ( void ) {
#ifdef FILE_BUF_SIZE 
    return ( isFilePullComplete() ) ;
#else
    return ( file_pos == BIN_FILE_SIZE - 1 ) ; 
#endif
}

// Input file data access, depends on build
char fileGetNext ( void ) {
    // byte = fgetc (srcFd) ; // DOS / UNIX file - not applicable here 
#ifdef FILE_BUF_SIZE 
    return ( filePullData () ) ;
#else
    return ( bin_file_bytes[file_pos++] ); 
#endif
}


/////////////////////////////////////////////////////////////////////////////
// file-send implementation, largely inspired to Pocket-Tools source code
int FileSend ( void )
{
    
    int      pcId  =  PC_ID;  // hardcoded for PC-1403 here
    uint32_t nbSync = N_SYNC_BITS; 
    int      ii;
    uchar    type ;
    uint32_t nbByte;
    uint32_t addr;
    int      error ;
    char     inVal;   

    fileInfo.nbSync = nbSync;
#ifndef FILE_BUF_SIZE 
    file_pos = 0;
#endif

    switch (fileInfo.ident) {
    /* . . .*/
        case IDENT_NEW_BIN :
            pcgrpId = GRP_NEW ; /*or GRP_EXT */
            type = TYPE_BIN ;
            break ;
    /* . . .*/
        case IDENT_NEW_BAS :
            pcgrpId = GRP_NEW ;
            type = TYPE_IMG ;
            break ;
        default :
            debug_printf ("%s: Unknown Ident\n", argP) ;
            return (ERR_ARG);
    }

    /* if (pcgrpId == GRP_E || pcgrpId == GRP_G || pcgrpId == GRP_16) { 
       . . .
    }   
    else { //   PC-1211 to PC-1500, QTape 
    */   
        if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG WriteSyncToWav\n\r");
        error = WriteSyncToWav (nbSync ) ;
    /*
        . . .
    */
    if (error != ERR_OK) return ( error ) ;
                    
    switch (pcId) {
    /*
      . . . 
    */
    case 1403:
       /* if (type == TYPE_BIN && Acnt==0 && SHCc==0 && addr==0) */ addr = TYPE_BIN_ADDR;
    /*
      . . . 
    */
        break;
    default :
        debug_printf ("%s: Sharp PC-%d not implemented\n", argP, pcId) ;
        // MoreInfo (ERR_ARG);
        error = ERR_ARG ;
            // break ;
    }
    if (error != ERR_OK) return ( error )  ;

/*  ...
    else { // PC-121x ... PC-1475 
*/
    if ( (fileInfo.debug & 0x0040) > 0 ) 
        debug_printf("DEBUG set Header Mode (ident %d)\n\r", fileInfo.ident);
    switch (fileInfo.ident) { /* Header Mode */
    case IDENT_PC1211 :
        fileInfo.mode = fileInfo.mode_h = MODE_B20 ;
        break ;

    case IDENT_PC121_DAT :
    case IDENT_OLD_BAS :
    case IDENT_OLD_DAT :
    case IDENT_OLD_BIN :
    case IDENT_OLD_MEM :
        fileInfo.mode = fileInfo.mode_h = MODE_B19 ;
        break ;

    case IDENT_NEW_TEL :
    case IDENT_NEW_SCD :
    case IDENT_NEW_NOT :
    case IDENT_NEW_CRD :

    case IDENT_NEW_CSL :

    case IDENT_NEW_BAS :
    case IDENT_EXT_BAS :
    case IDENT_NEW_DAT :
    case IDENT_NEW_BIN :
        fileInfo.mode = fileInfo.mode_h = MODE_B16 ;
        break ;

    default :
        debug_printf ("%s: Unknown Ident\n", argP) ;
        fileInfo.mode = fileInfo.mode_h = MODE_B21 ;
        return (ERR_ARG);
    }
    if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG Header fileInfo.mode_h %u\n\r",fileInfo.mode_h);

    /* Write the TAPE code */
    if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG Write the TAPE code\n\r");
    error = WriteByteToWav ( (ulong) fileInfo.ident, ORDER_STD, fileInfo.mode_h ) ;
    if (error != ERR_OK) return ( error )  ;

    /* Write the Name */
    if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG Writing Name...\n\r");
    error = WriteSaveNameToWav ( "NONAME", fileInfo.mode_h ) ; // NOT USING FILENAME !!
    if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG error (ERR_OK) %d (%d)\n\r", error, ERR_OK);
    if (error != ERR_OK) return ( error )  ;
    
    if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG set Body Data Mode\n\r");
    switch (fileInfo.ident) { /* Body Data Mode */
        case IDENT_PC1211 :
            fileInfo.mode = MODE_B20 ;
            break ;
    
        case IDENT_PC121_DAT :
        case IDENT_OLD_BAS :
        case IDENT_OLD_BIN :
        case IDENT_OLD_MEM :
            fileInfo.mode = MODE_B19 ;
            break ;
    
        case IDENT_OLD_DAT :
        case IDENT_NEW_DAT :
            fileInfo.mode = MODE_B15 ;
        break ;
    
        case IDENT_EXT_BAS :
    
        case IDENT_NEW_BAS :
        case IDENT_NEW_CSL :
    
        case IDENT_NEW_TEL :
        case IDENT_NEW_SCD :
        case IDENT_NEW_NOT :
        case IDENT_NEW_CRD :
        case IDENT_NEW_BIN :
          // TODO (mr#2#): Check whitch MODE_B13 or _B14
            if (cnvstr_upr && pcId < 1440) fileInfo.mode = MODE_B13 ; /*older part of new series*/
            else  fileInfo.mode = MODE_B14 ;     /*new series and extended series*/
            break ;
    
        default :
            debug_printf ("%s: Unknown Ident\n", argP) ;
            return ( ERR_ARG );
        }
        if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG Body fileInfo.mode %u\n\r", fileInfo.mode);

        fileInfo.total = 0 ; /* count bytes of body only */
                
        switch (fileInfo.ident) { /* header was written, write all data now */
        /* ... 
        case 
        ... */
        case IDENT_NEW_BAS :
        case IDENT_NEW_CSL :
        case IDENT_EXT_BAS :
            if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG Writing data...\n\r");
            /* Write the datas */
//            info.mode = MODE_B13 ; /* PC-1403 and newer should be MODE_14 */
            /* the older simple algorithm seems to work as well, but this is now, what the PC does originally */
            while  ( !isFileSendComplete() ) {
                inVal = fileGetNext();
                if ( inVal == EOF ) break ; // ending if 
                if ( inVal == BAS_NEW_EOF ) {
                    if (fileInfo.count + 1 == BLK_NEW && fileInfo.sum == 0xE1) { /* Constellation will generate 2-times BAS_NEW_EOF */
                        printf ("\nERROR %i at %lu. byte, usually the low byte of a BASIC line number\n", ERR_SUM, fileInfo.total) ;
                        printf ("This binary constellation activates the CLOAD bug of this series. The line\n") ;
                        printf ("number must be changed or minor changes done in the BASIC text before.\n") ;
                        /* Seldom Bug in CLOAD, for PC-1402/(01) at known ROM address: 40666 */
                        if ((fileInfo.debug & 0x800) == 0 ) {
                            error = ERR_SUM ;
                            break ;
                        }
                    }
                }
                error = WriteByteSumToWav ( (uint) inVal, ORDER_STD, fileInfo.mode ) ;
                if (error != ERR_OK) break ;
            }
            if (error != ERR_OK) break ;
            if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("\n\rDEBUG ii %u\n\r", ii);

            inVal = fileGetNext(); /* Read the last byte before EOF mark */
            if (inVal == EOF) break ;
            if (inVal == BAS_NEW_EOF) {
                /* EOF mark should not be included for this file type normally*/
                if (Qcnt == 0) printf ("End of File mark %i should not be included in the image\n", inVal) ;
                /* if end of block, then an additional checksum would be written, but this does work anyhow */
            }
            else {
                if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG last byte: %02X\n\r", (uchar) inVal);
                error = WriteByteToWav ( (uint) inVal, ORDER_STD, fileInfo.mode ) ;
                if (error != ERR_OK) break ;
                CheckSumB1 ((uint) inVal ) ; /* never write the checksum before BAS_NEW_EOF */

                ++fileInfo.total ;
                ++fileInfo.count ; /* for debug purposes only, WriteFooter will reset it */
            }

            /* Write the END code */
            if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG WriteFooterToNewWav\n\r");
            error = WriteFooterToNewWav ( ) ;

            break ; // IDENT_NEW_BAS, IDENT_EXT_BAS

        case IDENT_NEW_BIN :
            /* Write the address and length */
            error = WriteHeadToBinWav (addr, nbByte, fileInfo.mode_h ) ;
            if (error != ERR_OK) break ;
            /* no break */

        case IDENT_NEW_TEL :
        case IDENT_NEW_SCD :
        case IDENT_NEW_NOT :
        case IDENT_NEW_CRD :

            /* Write the datas */
            while  ( !isFileSendComplete() ) {
                inVal = fileGetNext();
                if (inVal == EOF ) break ; // premature ending shouldn't happen ...

                error = WriteByteSumToWav ( (uint) inVal, ORDER_STD, fileInfo.mode ) ;
                if (error != ERR_OK) break ;
            }
            if (error != ERR_OK) break ;

            inVal = fileGetNext();
            if (inVal == EOF) break ;

            if ( (fileInfo.debug & 0x0040) > 0 ) debug_printf("DEBUG %02X", (uchar) inVal);
            error = WriteByteToWav ( (uint) inVal, ORDER_STD, fileInfo.mode ) ;
            if (error != ERR_OK) break ;
            CheckSumB1 ( (uint) inVal  ) ; /* never write the checksum before BAS_NEW_EOF */
            ++fileInfo.total ;
            ++fileInfo.count ; /* for debug purposes only, WriteFooter will reset it */

            /* Write the END code */
            if ( fileInfo.ident == IDENT_NEW_BIN) error = WriteFooterToNewWav ( ) ;
            else WriteFooterToMemoWav ( ) ;

            break ; // IDENT_NEW_BIN and IDENT_NEW_Memos
        default:
            printf ("%s: Unknown Ident\n", argP) ;
            error = ERR_ARG;
            break;
        }        

    return (error);

}