// File: /workspace/github_c_makefile_star2_O2/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 $0x6078, %rsp           # imm = 0x6078
pushq $0x1
popq %rbx
cmpl $0x2, %edi
jne 0x1296
movq 0x8(%rsi), %r12
leaq 0xe09(%rip), %rsi       # 0x2059
movq %r12, %rdi
callq 0x10f0
testq %rax, %rax
je 0x12b3
movq %rax, %r15
xorl %r14d, %r14d
pushq $0x2
popq %rbp
movq %rax, %rdi
xorl %esi, %esi
movl %ebp, %edx
callq 0x10e0
movq %r15, %rdi
callq 0x10b0
cmpq $0xe73000, %rax         # imm = 0xE73000
movq %r15, 0x20(%rsp)
movq %r12, 0x50(%rsp)
movq %rax, 0x60(%rsp)
jne 0x12c9
pushq $0x1
popq %rbp
jmp 0x12d5
leaq 0xd86(%rip), %rdi       # 0x2023
callq 0x1050
leaq 0xd91(%rip), %rdi       # 0x203a
callq 0x1050
jmp 0x13ff
leaq 0xda2(%rip), %rdi       # 0x205c
movq %r12, %rsi
xorl %eax, %eax
callq 0x1090
jmp 0x13ff
cmpq $0x1344000, %rax        # imm = 0x1344000
jne 0x1393
movq %r15, %rdi
callq 0x10a0
leaq 0x48(%rsp), %rdi
pushq $0x1
popq %rsi
pushq $0x8
popq %rdx
movq %r15, %rcx
callq 0x1070
xorl %eax, %eax
cmpq $0x8, %rax
jae 0x130c
movzwl 0x48(%rsp,%rax), %ecx
rolw $0x8, %cx
movw %cx, 0x68(%rsp,%rax)
addq $0x2, %rax
jmp 0x12f2
movl %ebp, 0x10(%rsp)
leaq 0x2ac9(%rip), %rbx      # 0x3de0
xorl %r12d, %r12d
leaq 0x68(%rsp), %r14
pushq $0x8
popq %r15
xorl %eax, %eax
xorl %ebp, %ebp
cmpq $0x1, %r12
ja 0x136c
testb $0x1, %al
jne 0x136c
movq (%rbx), %r13
movq %r14, %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x1040
testl %eax, %eax
sete %bpl
je 0x1361
leaq 0x48(%rsp), %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x1040
testl %eax, %eax
sete %al
jmp 0x1363
movb $0x1, %al
incq %r12
addq $0x8, %rbx
jmp 0x1327
testb $0x1, %al
je 0x137c
xorl %r15d, %r15d
movl 0x10(%rsp), %eax
movl %eax, %r14d
jmp 0x1398
movl 0x10(%rsp), %esi
orl $0x4, %esi
leaq 0xce9(%rip), %rdi       # 0x2073
xorl %eax, %eax
callq 0x1090
jmp 0x13f2
movb $0x1, %r15b
xorl %ebp, %ebp
xorl %edi, %edi
callq 0x1120
testq %rax, %rax
je 0x13d3
movq %rax, %rbx
leaq 0xd23(%rip), %rsi       # 0x20d1
movq %rax, %rdi
callq 0x10f0
movq %rax, 0x10(%rsp)
testq %rax, %rax
je 0x13e1
testb %r15b, %r15b
je 0x1413
leaq 0xd5d(%rip), %rdi       # 0x2129
callq 0x1050
jmp 0x143d
leaq 0xcca(%rip), %rdi       # 0x20a4
callq 0x1050
jmp 0x13f2
leaq 0xcec(%rip), %rdi       # 0x20d4
movq %rbx, %rsi
xorl %eax, %eax
callq 0x1090
movq 0x20(%rsp), %rdi
callq 0x1080
pushq $0x1
popq %rbx
movl %ebx, %eax
addq $0x6078, %rsp           # imm = 0x6078
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leal 0x4(%r14), %esi
movzbl %bpl, %eax
leaq 0x29ae(%rip), %rcx      # 0x3dd0
movq (%rcx,%rax,8), %rdx
xorb $0x1, %al
movzbl %al, %eax
movq (%rcx,%rax,8), %rcx
leaq 0xcb7(%rip), %rdi       # 0x20ed
xorl %eax, %eax
callq 0x1090
movq 0x2b9c(%rip), %rax      # 0x3fe0
movq (%rax), %rdi
callq 0x10d0
movl %eax, %edi
callq 0x1060
movl %eax, 0x1c(%rsp)
movq 0x20(%rsp), %r12
movq %r12, %rdi
callq 0x10a0
testb %r15b, %r15b
movq %rbx, 0x30(%rsp)
je 0x14c5
leaq 0x70(%rsp), %rbx
pushq $0x1
popq %r14
movq %r12, %rbp
movq %rbp, %rdi
callq 0x10c0
testl %eax, %eax
jne 0x162a
movl $0x6000, %edx           # imm = 0x6000
movq %rbx, %rdi
movq %r14, %rsi
movq %rbp, %rcx
callq 0x1070
xorl %ecx, %ecx
cmpq %rcx, %rax
jbe 0x14b0
rolw $0x8, 0x70(%rsp,%rcx)
addq $0x2, %rcx
jmp 0x149f
movq %rbx, %rdi
movq %r14, %rsi
movq %rax, %rdx
movq 0x10(%rsp), %rcx
callq 0x1110
jmp 0x147a
imull $0x3000, %r14d, %eax    # imm = 0x3000
movq %rax, 0x58(%rsp)
testb $0x1, %bpl
movq %r12, %rax
cmovneq 0x10(%rsp), %rax
movq %rax, 0x38(%rsp)
leaq 0x70(%rsp), %r15
xorl %esi, %esi
movq %r12, %rbp
movl 0x1c(%rsp), %r14d
cmpl $0x2, %esi
je 0x162a
cmpq $0xe73000, 0x60(%rsp)   # imm = 0xE73000
sete %al
testl %esi, %esi
movq 0x58(%rsp), %rcx
movq %rcx, %rdi
movl $0x6000, %edx           # imm = 0x6000
cmoveq %rdx, %rdi
movq %rdi, 0x40(%rsp)
movl $0x6000, %r13d          # imm = 0x6000
cmoveq %rcx, %r13
movl %esi, 0x2c(%rsp)
cmpl $0x1, %esi
sete %cl
andb %al, %cl
movb %cl, 0xf(%rsp)
xorl %ebx, %ebx
pushq $0x1
popq %r12
cmpl $0x19b, %ebx            # imm = 0x19B
je 0x160e
testl %r14d, %r14d
jne 0x15be
movq %r15, %r12
movq %rbp, %r14
movq %rbp, %rdi
callq 0x10b0
cqto
movl $0x3000, %r15d          # imm = 0x3000
idivq %r15
movq %rax, %rbp
movq 0x10(%rsp), %rdi
callq 0x10b0
cqto
idivq %r15
cmpb $0x0, 0xf(%rsp)
je 0x1596
leaq 0xbb7(%rip), %rdi       # 0x2140
movl %ebp, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x1090
jmp 0x15af
leal 0x1(%rbp), %edx
leal 0x1(%rax), %r8d
leaq 0xbac(%rip), %rdi       # 0x2150
movl %ebp, %esi
movl %eax, %ecx
xorl %eax, %eax
callq 0x1090
movq %r14, %rbp
movl 0x1c(%rsp), %r14d
movq %r12, %r15
pushq $0x1
popq %r12
movq %r15, %rdi
movq %r12, %rsi
movq 0x40(%rsp), %rdx
movq %rbp, %rcx
callq 0x1070
xorl %ecx, %ecx
cmpq %rcx, %rax
jbe 0x15e4
rolw $0x8, 0x70(%rsp,%rcx)
addq $0x2, %rcx
jmp 0x15d3
movq %r15, %rdi
movq %r12, %rsi
movq %rax, %rdx
movq 0x10(%rsp), %rcx
callq 0x1110
movq 0x38(%rsp), %rdi
movq %r13, %rsi
pushq $0x1
popq %rdx
callq 0x10e0
incl %ebx
jmp 0x153f
movq 0x38(%rsp), %rdi
movq 0x40(%rsp), %rsi
xorl %edx, %edx
callq 0x10e0
movl 0x2c(%rsp), %esi
incl %esi
jmp 0x14f2
movq %rbp, %rdi
callq 0x1080
movq 0x10(%rsp), %rdi
callq 0x1080
movq 0x50(%rsp), %rbx
movq %rbx, %rdi
callq 0x1030
testl %eax, %eax
je 0x1668
leaq 0xb14(%rip), %rdi       # 0x2168
callq 0x1050
movq 0x30(%rsp), %rdi
callq 0x1030
jmp 0x13fc
movq 0x30(%rsp), %r14
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1100
testl %eax, %eax
je 0x1692
leaq 0xb1e(%rip), %rdi       # 0x21a1
movq %r14, %rsi
xorl %eax, %eax
callq 0x1090
jmp 0x13fc
xorl %ebx, %ebx
jmp 0x13ff