// File: /workspace/github_c_makefile_star2_O1/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 0x13b7
movq 0x8(%rsi), %rbx
leaq 0xe08(%rip), %rsi       # 0x2059
movq %rbx, %rdi
callq 0x10f0
testq %rax, %rax
je 0x13d4
movq %rax, %r13
movq %rbx, 0x38(%rsp)
xorl %ebx, %ebx
movq %rax, %rdi
xorl %esi, %esi
movl $0x2, %edx
callq 0x10e0
movq %r13, %rdi
callq 0x10b0
xorl %edx, %edx
cmpq $0x1344000, %rax        # imm = 0x1344000
sete %dl
setne %cl
addl %edx, %edx
movq %rax, 0x48(%rsp)
cmpq $0xe73000, %rax         # imm = 0xE73000
sete %bpl
movl $0x1, %r15d
cmovnel %edx, %r15d
xorb %cl, %bpl
movq %r13, 0x18(%rsp)
jne 0x1375
movb %bpl, 0x14(%rsp)
movq %r15, 0x8(%rsp)
movq %r13, %rdi
callq 0x10a0
leaq 0x30(%rsp), %rdi
movl $0x1, %esi
movl $0x8, %edx
movq %r13, %rcx
callq 0x1070
movq $-0x2, %rax
movzwl 0x32(%rsp,%rax), %ecx
rolw $0x8, %cx
movw %cx, 0x5a(%rsp,%rax)
addq $0x2, %rax
cmpq $0x6, %rax
jb 0x12ea
xorl %r13d, %r13d
leaq 0x2ad4(%rip), %rbp      # 0x3de0
leaq 0x58(%rsp), %rbx
leaq 0x30(%rsp), %r14
movq (%r13,%rbp), %r12
movl $0x8, %edx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1040
movl %eax, %r15d
testl %eax, %eax
je 0x1349
movl $0x8, %edx
movq %r14, %rdi
movq %r12, %rsi
callq 0x1040
testl %eax, %eax
sete %al
jmp 0x134b
movb $0x1, %al
testq %r13, %r13
jne 0x1358
addq $0x8, %r13
testb %al, %al
je 0x1316
testl %r15d, %r15d
sete %bl
testb %al, %al
movq 0x18(%rsp), %r13
movq 0x8(%rsp), %r15
movb 0x14(%rsp), %bpl
je 0x13f8
xorl %edi, %edi
callq 0x1120
testq %rax, %rax
je 0x13ea
movq %rax, %r14
leaq 0xd46(%rip), %rsi       # 0x20d1
movq %rax, %rdi
callq 0x10f0
movq %rax, 0x8(%rsp)
testq %rax, %rax
je 0x140f
testb %bpl, %bpl
je 0x142d
leaq 0xd7c(%rip), %rdi       # 0x2129
callq 0x1050
jmp 0x1456
leaq 0xc65(%rip), %rdi       # 0x2023
callq 0x1050
leaq 0xc70(%rip), %rdi       # 0x203a
callq 0x1050
jmp 0x169d
leaq 0xc81(%rip), %rdi       # 0x205c
movq %rbx, %rsi
xorl %eax, %eax
callq 0x1090
jmp 0x169d
leaq 0xcb3(%rip), %rdi       # 0x20a4
callq 0x1050
jmp 0x1420
orl $0x4, %r15d
leaq 0xc70(%rip), %rdi       # 0x2073
movl %r15d, %esi
xorl %eax, %eax
callq 0x1090
jmp 0x1420
leaq 0xcbe(%rip), %rdi       # 0x20d4
movq %r14, %rsi
xorl %eax, %eax
callq 0x1090
movq %r13, %rdi
callq 0x1080
jmp 0x169d
leal 0x4(%r15), %esi
movzbl %bl, %eax
leaq 0x2995(%rip), %rcx      # 0x3dd0
movq (%rcx,%rax,8), %rdx
xorb $0x1, %al
movzbl %al, %eax
movq (%rcx,%rax,8), %rcx
leaq 0xc9e(%rip), %rdi       # 0x20ed
xorl %eax, %eax
callq 0x1090
movq %r14, 0x20(%rsp)
movq 0x2b7e(%rip), %rax      # 0x3fe0
movq (%rax), %rdi
callq 0x10d0
movl %eax, %edi
callq 0x1060
movl %eax, 0x14(%rsp)
movq %r13, %rdi
callq 0x10a0
testb %bpl, %bpl
je 0x14e8
movq %r13, %rdi
callq 0x10c0
testl %eax, %eax
jne 0x1664
leaq 0x60(%rsp), %rbx
movl $0x1, %esi
movl $0x6000, %edx           # imm = 0x6000
movq %rbx, %rdi
movq %r13, %rcx
callq 0x1070
testq %rax, %rax
je 0x14c2
xorl %ecx, %ecx
rolw $0x8, 0x60(%rsp,%rcx)
addq $0x2, %rcx
cmpq %rcx, %rax
ja 0x14b3
movl $0x1, %esi
movq %rbx, %rdi
movq %rax, %rdx
movq 0x8(%rsp), %rcx
callq 0x1110
movq %r13, %rdi
callq 0x10c0
testl %eax, %eax
je 0x1497
jmp 0x1664
shll $0xc, %r15d
leal (%r15,%r15,2), %eax
movq %rax, 0x40(%rsp)
testb %bl, %bl
movq %r13, %rbp
cmovneq 0x8(%rsp), %rbp
leaq 0x60(%rsp), %r14
xorl %esi, %esi
cmpq $0xe73000, 0x48(%rsp)   # imm = 0xE73000
sete %al
testl %esi, %esi
movq 0x40(%rsp), %rcx
movq %rcx, %r15
movl $0x6000, %edx           # imm = 0x6000
cmoveq %rdx, %r15
movl $0x6000, %ebx           # imm = 0x6000
cmoveq %rcx, %rbx
movq %rsi, 0x50(%rsp)
cmpl $0x1, %esi
sete %cl
andb %al, %cl
movb %cl, 0x7(%rsp)
xorl %r12d, %r12d
movq %rbx, 0x28(%rsp)
cmpl $0x0, 0x14(%rsp)
jne 0x15e7
movq %r15, %rbx
movq %r14, %r15
movq %rbp, %r14
movq %r13, %rdi
callq 0x10b0
movabsq $0x2aaaaaaaaaaaaaab, %rbp # imm = 0x2AAAAAAAAAAAAAAB
imulq %rbp
movq %rdx, %r13
movq %rdx, %rax
shrq $0x3f, %rax
shrq $0xb, %r13
addl %eax, %r13d
movq 0x8(%rsp), %rdi
callq 0x10b0
imulq %rbp
movq %rdx, %rcx
movq %rdx, %rax
shrq $0x3f, %rax
shrq $0xb, %rcx
addl %eax, %ecx
cmpb $0x0, 0x7(%rsp)
je 0x15bb
leaq 0xb93(%rip), %rdi       # 0x2140
movl %r13d, %esi
movl %ecx, %edx
xorl %eax, %eax
callq 0x1090
jmp 0x15d4
leal 0x1(%r13), %edx
leal 0x1(%rcx), %r8d
leaq 0xb86(%rip), %rdi       # 0x2150
movl %r13d, %esi
xorl %eax, %eax
callq 0x1090
movq 0x18(%rsp), %r13
movq %r14, %rbp
movq %r15, %r14
movq %rbx, %r15
movq 0x28(%rsp), %rbx
movl $0x1, %esi
movq %r14, %rdi
movq %r15, %rdx
movq %r13, %rcx
callq 0x1070
testq %rax, %rax
je 0x1610
xorl %ecx, %ecx
rolw $0x8, 0x60(%rsp,%rcx)
addq $0x2, %rcx
cmpq %rcx, %rax
ja 0x1601
movl $0x1, %esi
movq %r14, %rdi
movq %rax, %rdx
movq 0x8(%rsp), %rcx
callq 0x1110
movq %rbp, %rdi
movq %rbx, %rsi
movl $0x1, %edx
callq 0x10e0
incl %r12d
cmpl $0x19b, %r12d           # imm = 0x19B
jne 0x1548
movq %rbp, %rdi
movq %r15, %rsi
xorl %edx, %edx
callq 0x10e0
movq 0x50(%rsp), %rcx
leal 0x1(%rcx), %eax
testl %ecx, %ecx
movl %eax, %esi
je 0x1507
movq %r13, %rdi
callq 0x1080
movq 0x8(%rsp), %rdi
callq 0x1080
movq 0x38(%rsp), %rbx
movq %rbx, %rdi
callq 0x1030
testl %eax, %eax
je 0x16b4
leaq 0xada(%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 0x16d7
leaq 0xad2(%rip), %rdi       # 0x21a1
movq %r14, %rsi
jmp 0x13de
xorl %eax, %eax
jmp 0x16a2