+/*
+ * (C) Copyright 2019 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+
+char *progname;
+FILE *prlfile;
+char *prlfilename;
+FILE *outfile;
+char *outfilename;
+uint16_t progsize;
+
+void die(int status, const char *format, ...)
+{
+ va_list arg;
+
+ fflush(stdout);
+ va_start(arg, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, arg);
+ va_end(arg);
+
+ exit(status);
+}
+
+static
+int get_bit(void)
+{
+ static unsigned bitpos;
+ static int bytebuf;
+ int retval;
+
+ if (bitpos == progsize) {
+ return -2;
+ }
+ if (bitpos%8 == 0) {
+ bytebuf = fgetc(prlfile);
+ if (bytebuf == EOF) {
+ return -1;
+ }
+ }
+ retval = (bytebuf & 0x80) !=0;
+ bytebuf <<= 1;
+ bitpos++;
+
+ return retval;
+}
+
+static
+int get_nr_of_bits(void)
+{
+ int bits = 0;
+ int bit;
+
+ do {
+ bits++;
+ } while ((bit = get_bit()) == 0);
+
+ if (bit >= 0)
+ return bits;
+
+ if (bit == -2)
+ return 0;
+
+ return bit;
+}
+
+static
+void put_bits(int width, unsigned val)
+{
+ static unsigned bytebuf;
+ static int bitcount = 8;
+
+ while (width--) {
+ bytebuf <<= 1;
+ if (val & (1 << width))
+ bytebuf += 1;
+ bitcount--;
+ if (bitcount == 0) {
+ if (fputc(bytebuf, outfile) == EOF)
+ die(1,"Error writing output file %s: %s\n",
+ outfilename, strerror(errno));
+ bitcount = 8;
+ }
+ }
+}
+
+static
+void fill_sector(void)
+{
+ long curpos;
+
+ if ((curpos = ftell(outfile)) == -1)
+ die(1,"File error %s: %s\n", outfilename, strerror(errno));
+
+ for (int i = 0; i < 128 - curpos % 128; i++)
+ if (fputc(0, outfile) == EOF)
+ die(1,"Error writing output file %s: %s\n",
+ outfilename, strerror(errno));
+
+ return;
+}
+
+
+static
+int process_prlfile(void)
+{
+ fgetc(prlfile);
+ progsize = fgetc(prlfile) + (fgetc(prlfile) << 8);
+
+ /* skip header */
+ fseek(prlfile, 0x100, SEEK_SET);
+
+ for (unsigned i = 0; i < progsize; i++) {
+ int c = fgetc(prlfile);
+ if (c == EOF)
+ die(1,"Unexpected end of prl file %s\n", prlfilename);
+ if (fputc(c, outfile) == EOF)
+ die(1,"Error writing output file %s: %s\n",
+ outfilename, strerror(errno));
+ }
+
+
+ int bits;
+ while ((bits = get_nr_of_bits()) >= 2) {
+ unsigned off = bits - 2;
+ if (off < (1<<2)) {
+ put_bits(0 + 2 + 1, off);
+ } else if (off < (1<<4) + (1<<2)) {
+ off -= (1<<2);
+ off += (1<<(4+1));
+ put_bits(1 + 4 + 1, off);
+ } else if (off < (1<<8) + (1<<4) + (1<<2)) {
+ off -= (1<<4) + (1<<2);
+ off += (1<<(8+1));
+ off += (1<<(8+2));
+ put_bits(2 + 8 + 1, off);
+ } else {
+ off -= (1<<8) + (1<<4) + (1<<2);
+ off += (1<<(16+1));
+ off += (1<<(16+2));
+ off += (1<<(16+3));
+ put_bits(3 + 16 + 1, off);
+ }
+ }
+
+ if (bits == 1)
+ die(1,"Bitmap error");
+
+ if (bits < 0)
+ die(1,"Error while reading bitmap from prl file %s\n", prlfilename);
+
+ /* end mark */
+ put_bits(4, 0xf);
+
+ /* flush output bit buffer */
+ put_bits(7, 0);
+
+ fill_sector();
+
+ return 0;
+}
+
+static
+void usage(void)
+{
+ fprintf(stderr,
+"Usage:\n"
+"%s prlfile outfile\n", progname);
+
+}
+
+int main(int argc, char **argv)
+{
+ progname = argv[0];
+
+ if (argc != 3) {
+ usage();
+ die(1, "");
+ }
+
+ prlfilename = argv[1];
+ prlfile=fopen(prlfilename,"rb");
+ if (prlfile==NULL)
+ die(1,"Cannot open prl file %s: %s\n",
+ prlfilename, strerror(errno));
+
+ outfilename = argv[2];
+ outfile=fopen(outfilename,"wb");
+ if (outfile==NULL)
+ die(1,"Cannot open output file %s: %s\n",
+ outfilename, strerror(errno));
+
+ process_prlfile();
+ fclose(prlfile);
+ fclose(outfile);
+
+ return 0;
+}