// File: /workspace/github_c_makefile_star2_O3/simh[P]simtools/converters/hpconvert/hpconvert.c
// Function: main
int main (int    argc,
          char **argv)

{
    const char *format [] = { "HPDrive", "SIMH" };

    const char *signatures [] = { "\x67\x6D\x06\xC0\x77\x6B\x0B\x40",   /* RTE ICD */
                                  "SYSTEM D" };                         /* MPE */

    #define  SIGNATURE_SIZE  sizeof (signatures [0])

    const int signature_count = sizeof (signatures) / SIGNATURE_SIZE;

    FILE   *fin, *fout;
    size_t file_size, record_size;
    char   *name_in, *name_out;
    char   sig_fwd [SIGNATURE_SIZE], sig_rev [SIGNATURE_SIZE];
    char   hold, cylinder [CYLINDER_SIZE];
    bool   identified = false, reversed = false, debug = false;
    int    i, cyl, from_cyl, to_cyl, remap;
    int    platter, cylinder_size, hole_size;


/* Read the disc image filename. */

    if (argc != 2) {
        puts ("\nHPConvert version 1.1");
        puts ("\nUsage: hpconvert <disc-image>");
        return 1;
        }

    name_in = argv [1];

/* Open the source image file. */

    fin = fopen (name_in, "rb");

    if (!fin) {
        printf ("Error: cannot open %s\n", name_in);
        return 1;
        }

/* Get the size of the image. */

    fseek (fin, 0, SEEK_END);
    file_size = ftell (fin);


/* The blocks of a 7905 or 7906 image (as determined by the image file size)
   will need to be rearranged.  Set "remap" to the number of surfaces that must
   be remapped. */

    if (file_size == HP7905_SIZE)
        remap = 1;
    else if (file_size == HP7906_SIZE)
        remap = 2;
    else
        remap = 0;


/* If the image is a 7905 or 7906, it must be remapped it for the target system.
   To do that, check the OS signature to determine if it is in SIMH or HPDrive
   format, and set the "reversed" flag if the signature bytes in the image are
   reversed (this implies a platter-to-cylinder remapping of a 7905 or 7906
   image. */

    if (remap) {
        rewind (fin);
        file_size = fread (sig_fwd, 1, SIGNATURE_SIZE, fin);

        for (i = 0; i < SIGNATURE_SIZE; i = i + 2) {
            sig_rev [i]     = sig_fwd [i + 1];
            sig_rev [i + 1] = sig_fwd [i];
            }

        for (i = 0; i < signature_count && identified == false; i++) {
            reversed = strncmp (sig_rev, signatures [i], SIGNATURE_SIZE) == 0;
            identified = reversed || strncmp (sig_fwd, signatures [i], SIGNATURE_SIZE) == 0;
            }

/* If the signature cannot be identified, then we do not know how to remap it,
   so report the problem and exit. */

        if (identified == false) {
            printf ("Error: 790%i image OS signature not recognized.\n", remap + 4);
            fclose (fin);
            return 1;
            }
        }


/* Generate a temporary filename for the converted image. */

    name_out = tmpnam (NULL);

    if (name_out == NULL) {
        puts ("Error: cannot generate a temporary filename.");
        fclose (fin);
        return 1;
        }

/* Create the temporary target image. */

    fout = fopen (name_out, "wb");

    if (!fout) {
        printf ("Error: cannot create %s\n", name_out);
        fclose (fin);
        return 1;
        }

/* Report the conversion that will be performed. */

    if (remap)
        printf ("Converting and remapping 790%i %s disc image to %s format.\n",
                remap + 4,
                format [reversed],
                format [!reversed]);
    else
        puts ("Converting disc image.");


/* Enable debugging output if stdout has been redirected to a file. */

    debug = isatty (fileno (stdout)) == 0;


/* Copy the source to the target image while swapping each byte pair.  If the
   disc image is for a 7905 or 7906, remap from platter to cylinder mode (or
   vice-versa if the source image is not reversed).

   In a platter-mode image, the upper platter tracks appear in order before the
   lower platter tracks.  For the 7906, the cylinder-head order of the tracks is
   0-0, 0-1, 1-0, 1-1, ..., 410-0, 410-1, 0-2, 0-3, 1-2, 1-3, ..., 410-2, 410-3.
   The 7905 order is the same, except that head 3 tracks are omitted.

   In a cylinder-mode image, all tracks appear in cylinder-head order, i.e.,
   0-0, 0-1, 0-2, 0-3, 1-0, 1-1, ..., 410-2, 410-3, for the 7906.

   Remapping is performed in two passes, corresponding to the two platters.  In
   the first pass, the source tracks corresponding to the upper platter are
   spread (platter-to-cylinder) or condensed (cylinder-to-platter) as they are
   copied to the target file.  In the second pass, the source tracks
   corresponding to the lower platter are interleaved (platter-to-cylinder) or
   appended (cylinder-to-platter) as they are copied to the target file.

   In either case, the bytes of each 16-bit word are swapped before copying.
*/

    rewind (fin);

/* If the image is not a 7905/06, simply swap each pair of bytes until EOF. */

    if (!remap)
        while (!feof (fin)) {
            record_size = fread (cylinder, 1, CYLINDER_SIZE, fin);

            for (i = 0; i < record_size; i = i + 2) {
                hold = cylinder [i];
                cylinder [i] = cylinder [i + 1];
                cylinder [i + 1] = hold;
                }

            fwrite (cylinder, 1, record_size, fout);
            }

/* If the image is a 7905/06, remap the tracks and swap pairs of bytes.  Because
   we know the disc type, we know the number of platters and cylinders present
   in the image. */

    else
        for (platter = 0; platter < 2; platter++) {

/* Calculate the number of bytes per cylinder for the current platter.  The
   upper platter always has two tracks per cylinder.  The lower platter has
   either one (7905) or two (7906) tracks per cylinder. */

            if (platter == 0) {
                cylinder_size = TRACK_SIZE * 2;
                hole_size     = TRACK_SIZE * remap;
                }
            else {
                cylinder_size = TRACK_SIZE * remap;
                hole_size     = TRACK_SIZE * 2;
                }

/* Copy a platter. */

            for (cyl = 0; cyl < 411; cyl++) {

/* If stdout has been redirected, output the remapping information. */

                if (debug) {
                    from_cyl = ftell (fin) / TRACK_SIZE;
                    to_cyl   = ftell (fout) / TRACK_SIZE;

                    if (platter == 1 && remap == 1)
                        printf ("track %i => %i\n", from_cyl, to_cyl);
                    else
                        printf ("track %i, %i => %i, %i\n",
                                from_cyl, from_cyl + 1, to_cyl, to_cyl + 1);
                    }

/* Read a cylinder from the source location. */

                record_size = fread (cylinder, 1, cylinder_size, fin);

/* Swap the bytes. */

                for (i = 0; i < record_size; i = i + 2) {
                    hold = cylinder [i];
                    cylinder [i] = cylinder [i + 1];
                    cylinder [i + 1] = hold;
                    }

/* Write the cylinder to the target location. */

                fwrite (cylinder, 1, record_size, fout);

/* For platter-to-cylinder remapping, spread the tracks by seeking ahead in the
   target file; this leaves room for the lower-platter tracks in between the
   upper-platter tracks.  For cylinder-to-platter remapping, condense the
   cylinders by seeking ahead in the source file to the next track on the
   current platter. */

                if (reversed)
                    fseek (fout, hole_size, SEEK_CUR);
                else
                    fseek (fin, hole_size, SEEK_CUR);
                }


/* End of the current platter.  For platter-to-cylinder remapping, reposition
   the target file to the first "hole" left for the lower-platter tracks.  For
   cylinder-to-platter remapping, reposition the source file to access the first
   lower-platter tracks. */

            if (reversed)
                fseek (fout, cylinder_size, SEEK_SET);
            else
                fseek (fin, cylinder_size, SEEK_SET);
            }


/* Close the files. */

    fclose (fin);
    fclose (fout);


/* Delete the original file and replace it by the reversed file. */

    if (unlink (name_in)) {
        puts ("Error: cannot replace original file, which is unchanged.");
        unlink (name_out);
        return 1;
        }

    else if (rename (name_out, name_in)) {
        printf ("Error: cannot rename temporary file %s.\n", name_out);
        return 1;
        }


/* Return success. */

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x6068, %rsp           # imm = 0x6068
cmpl $0x2, %edi
jne 0x1362
movq 0x8(%rsi), %rbx
leaq 0xe08(%rip), %rsi       # 0x2059
movq %rbx, %rdi
callq 0x10f0
testq %rax, %rax
je 0x137f
movq %rbx, 0x48(%rsp)
movq %rax, %r14
xorl %ebx, %ebx
movq %rax, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x10e0
movq %r14, 0x8(%rsp)
movq %r14, %rdi
callq 0x10b0
movl $0x1, %ebp
movq %rax, 0x28(%rsp)
cmpq $0xe73000, %rax         # imm = 0xE73000
je 0x12ae
movl $0x2, %ebp
cmpq $0x1344000, 0x28(%rsp)  # imm = 0x1344000
jne 0x13a3
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x10a0
leaq 0x40(%rsp), %rdi
movl $0x1, %esi
movl $0x8, %edx
movq %rbx, %rcx
callq 0x1070
movq $-0x2, %rax
movzwl 0x42(%rsp,%rax), %ecx
rolw $0x8, %cx
movw %cx, 0x5a(%rsp,%rax)
addq $0x2, %rax
cmpq $0x6, %rax
jb 0x12d9
xorl %r12d, %r12d
leaq 0x2ae5(%rip), %r13      # 0x3de0
leaq 0x58(%rsp), %r14
leaq 0x40(%rsp), %rbx
xorl %ecx, %ecx
movq (%r13,%rcx,8), %r15
movl $0x8, %edx
movq %r14, %rdi
movq %r15, %rsi
callq 0x1040
testl %eax, %eax
je 0x1395
movl $0x8, %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x1040
testl %eax, %eax
sete %cl
orb %cl, %r12b
movl $0x1, %ecx
testb $0x1, %r12b
movb $0x1, %r12b
je 0x1307
testl %eax, %eax
je 0x13a8
orl $0x4, %ebp
leaq 0xd1f(%rip), %rdi       # 0x2073
movl %ebp, %esi
xorl %eax, %eax
callq 0x1090
jmp 0x1413
leaq 0xcba(%rip), %rdi       # 0x2023
callq 0x1050
leaq 0xcc5(%rip), %rdi       # 0x203a
callq 0x1050
jmp 0x16ab
leaq 0xcd6(%rip), %rdi       # 0x205c
movq %rbx, %rsi
xorl %eax, %eax
callq 0x1090
jmp 0x16ab
movb $0x1, %al
movq %rax, 0x10(%rsp)
xorl %r14d, %r14d
movl %ebp, %ebx
jmp 0x13b6
movb $0x1, %r14b
jmp 0x13ad
xorl %r14d, %r14d
movl %ebp, %ebx
movq $0x0, 0x10(%rsp)
xorl %edi, %edi
callq 0x1120
testq %rax, %rax
je 0x13f4
movq %rax, %r15
leaq 0xd05(%rip), %rsi       # 0x20d1
movq %rax, %rdi
callq 0x10f0
testq %rax, %rax
je 0x1402
movq %rax, %r13
testb %r14b, %r14b
movq %r15, 0x20(%rsp)
je 0x1422
leaq 0xd3c(%rip), %rdi       # 0x2129
callq 0x1050
jmp 0x144c
leaq 0xca9(%rip), %rdi       # 0x20a4
callq 0x1050
jmp 0x1413
leaq 0xccb(%rip), %rdi       # 0x20d4
movq %r15, %rsi
xorl %eax, %eax
callq 0x1090
movq 0x8(%rsp), %rdi
callq 0x1080
jmp 0x16ab
leal 0x4(%rbx), %esi
movzbl 0x10(%rsp), %eax
leaq 0x299f(%rip), %rcx      # 0x3dd0
movq (%rcx,%rax,8), %rdx
xorb $0x1, %al
movzbl %al, %eax
movq (%rcx,%rax,8), %rcx
leaq 0xca8(%rip), %rdi       # 0x20ed
xorl %eax, %eax
callq 0x1090
movq 0x2b8d(%rip), %rax      # 0x3fe0
movq (%rax), %rdi
callq 0x10d0
movl %eax, %edi
callq 0x1060
movl %eax, 0x1c(%rsp)
movq 0x8(%rsp), %r12
movq %r12, %rdi
callq 0x10a0
testb %r14b, %r14b
je 0x14df
movq %r12, %rdi
callq 0x10c0
testl %eax, %eax
movq %r12, %rbx
jne 0x1674
leaq 0x60(%rsp), %r14
movl $0x1, %esi
movl $0x6000, %edx           # imm = 0x6000
movq %r14, %rdi
movq %rbx, %rcx
callq 0x1070
testq %rax, %rax
je 0x14bb
xorl %ecx, %ecx
rolw $0x8, 0x60(%rsp,%rcx)
addq $0x2, %rcx
cmpq %rcx, %rax
ja 0x14ac
movl $0x1, %esi
movq %r14, %rdi
movq %rax, %rdx
movq %r13, %rcx
callq 0x1110
movq %rbx, %rdi
callq 0x10c0
testl %eax, %eax
je 0x1490
jmp 0x1674
shll $0xc, %ebx
leal (%rbx,%rbx,2), %eax
movq %rax, 0x50(%rsp)
movb $0x1, %cl
xorl %eax, %eax
leaq 0x60(%rsp), %r15
movq %r12, %rbx
cmpq $0xe73000, 0x28(%rsp)   # imm = 0xE73000
sete %sil
movl %ecx, 0x18(%rsp)
testb $0x1, %cl
movq 0x50(%rsp), %rcx
movq %rcx, %r14
movl $0x6000, %edx           # imm = 0x6000
cmovneq %rdx, %r14
movl $0x6000, %r12d          # imm = 0x6000
cmovneq %rcx, %r12
andb %al, %sil
movb %sil, 0x7(%rsp)
xorl %ebp, %ebp
movq %r14, 0x38(%rsp)
movq %r12, 0x30(%rsp)
cmpl $0x0, 0x1c(%rsp)
jne 0x15d1
movq %r15, %r12
movq %rbx, %rdi
callq 0x10b0
movabsq $0x2aaaaaaaaaaaaaab, %r15 # imm = 0x2AAAAAAAAAAAAAAB
imulq %r15
movq %rdx, %rbx
movq %rdx, %rax
shrq $0x3f, %rax
shrq $0xb, %rbx
addl %eax, %ebx
movq %r13, %r14
movq %r13, %rdi
callq 0x10b0
imulq %r15
movq %rdx, %rcx
movq %rdx, %rax
shrq $0x3f, %rax
shrq $0xb, %rcx
addl %eax, %ecx
cmpb $0x0, 0x7(%rsp)
je 0x15a5
leaq 0xba8(%rip), %rdi       # 0x2140
movl %ebx, %esi
movl %ecx, %edx
xorl %eax, %eax
callq 0x1090
jmp 0x15bc
leal 0x1(%rbx), %edx
leal 0x1(%rcx), %r8d
leaq 0xb9d(%rip), %rdi       # 0x2150
movl %ebx, %esi
xorl %eax, %eax
callq 0x1090
movq 0x8(%rsp), %rbx
movq %r12, %r15
movq %r14, %r13
movq 0x38(%rsp), %r14
movq 0x30(%rsp), %r12
movl $0x1, %esi
movq %r15, %rdi
movq %r14, %rdx
movq %rbx, %rcx
callq 0x1070
testq %rax, %rax
je 0x15fa
xorl %ecx, %ecx
rolw $0x8, 0x60(%rsp,%rcx)
addq $0x2, %rcx
cmpq %rcx, %rax
ja 0x15eb
movl $0x1, %esi
movq %r15, %rdi
movq %rax, %rdx
movq %r13, %rcx
callq 0x1110
incl %ebp
cmpb $0x0, 0x10(%rsp)
je 0x1634
movq %r13, %rdi
movq %r12, %rsi
movl $0x1, %edx
callq 0x10e0
cmpl $0x19b, %ebp            # imm = 0x19B
jne 0x1539
jmp 0x1655
movq %rbx, %rdi
movq %r12, %rsi
movl $0x1, %edx
callq 0x10e0
cmpl $0x19b, %ebp            # imm = 0x19B
jne 0x1539
movq %rbx, %rdi
jmp 0x1658
movq %r13, %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0x10e0
movb $0x1, %al
testb $0x1, 0x18(%rsp)
movl $0x0, %ecx
jne 0x14f6
movq %rbx, %rdi
callq 0x1080
movq %r13, %rdi
callq 0x1080
movq 0x48(%rsp), %rbx
movq %rbx, %rdi
callq 0x1030
testl %eax, %eax
je 0x16c2
leaq 0xacc(%rip), %rdi       # 0x2168
callq 0x1050
movq 0x20(%rsp), %rdi
callq 0x1030
movl $0x1, %eax
addq $0x6068, %rsp           # imm = 0x6068
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x20(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1100
testl %eax, %eax
je 0x16e5
leaq 0xac4(%rip), %rdi       # 0x21a1
movq %r14, %rsi
jmp 0x1389
xorl %eax, %eax
jmp 0x16b0