aboutsummaryrefslogtreecommitdiff
path: root/src/listalf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/listalf.c')
-rw-r--r--src/listalf.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/listalf.c b/src/listalf.c
new file mode 100644
index 0000000..051f2fe
--- /dev/null
+++ b/src/listalf.c
@@ -0,0 +1,118 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <f65.h>
+#include "unalf.h"
+#include "addrs.h"
+
+static const char *monthnames[] = {
+ "???",
+ "Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec",
+ "???", "???", "???",
+};
+
+u16 getword(int offs) {
+ return mem[offs] | (mem[offs + 1] << 8);
+}
+
+unsigned int getquad(int offs) {
+ return getword(offs) | ((getword(offs + 2) << 16));
+}
+
+/* see Arcinfo for details */
+void format_msdos_time(char *buf) {
+ u16 t, hour, min;
+ char ampm;
+
+ t = getword(alf_hdr_time0);
+
+ /* don't bother with seconds (arc doesn't print them either) */
+ hour = t >> 11;
+ min = (t >> 5) & 0x3f;
+
+ /* midnight prints as 12pm, not 12am... but 0:01 (1 min past
+ midnight) prints as 12:01am */
+ if(hour == 0 && min == 0) hour = 24;
+
+ ampm = (hour > 11 ? 'p' : 'a');
+ hour %= 12;
+
+ /* midnight and noon print as 12, not 0 */
+ if(hour == 0) hour = 12;
+
+ sprintf(buf, "%2d:%02d%c", hour, min, ampm);
+}
+
+/* see Arcinfo for details */
+void format_msdos_date(char *buf) {
+ u16 d, year, month, day;
+
+ d = getword(alf_hdr_date0);
+
+ /* year actually ranges 1980 to 2107... */
+ year = (d >> 9) + 1980;
+ year %= 100; /* ...but only print last 2 digits */
+
+ /* valid months range 1 to 12. values 0, 13, 14, 15 are possible
+ but invalid (print as ???) */
+ month = (d >> 5) && 0x0f;
+
+ /* valid day range is 1 to 31. 0 is invalid, print as-is. */
+ day = d & 0x1f;
+
+ sprintf(buf, "%2d %3s %02d", day, monthnames[month], year);
+}
+
+/* small files may be "compressed" larger than the original, so this
+ has to return a signed type. */
+static int comp_percent(unsigned int orig, unsigned int comp) {
+ if(orig == 0) return 0; /* no division by zero please */
+ return 100 - (int)((float)comp / (float)orig * 100.0);
+}
+
+/* output similar to "arc v", except we omit the compression type column
+ since there's only one type. also, don't call the checksum a CRC, it
+ isn't. */
+void list_alf(void) {
+ unsigned int c = 0, orig_size, comp_size, total_osize = 0, total_csize = 0;
+ char buf[100];
+ char *filename;
+
+ puts("Name Length Size now Comp Date Time CkSum");
+ puts("============ ======== ======== ==== ========= ====== =====");
+
+ while(read_alf_header()) {
+ c++;
+ orig_size = getquad(alf_hdr_origsize0);
+ comp_size = getquad(alf_hdr_compsize0);
+ filename = (char *)(mem + alf_hdr_filename);
+
+ total_osize += orig_size;
+ total_csize += comp_size;
+
+ printf("%-12s ", filename);
+ printf("%8d ", orig_size);
+ printf("%8d ", comp_size);
+ printf("%3d%% ", comp_percent(orig_size, comp_size));
+ format_msdos_date(buf);
+ printf("%9s ", buf);
+ format_msdos_time(buf);
+ printf("%6s ", buf);
+ printf(" %04x", getword(alf_hdr_cksum_l));
+ putchar('\n');
+
+ if(fseek(in_file, comp_size, SEEK_CUR) != 0) {
+ fputs(self, stderr);
+ perror(": fseek");
+ exit(1);
+ }
+ }
+
+ fputs(" ==== ======== ======== ====\nTotal ", stdout);
+ printf("%4d ", c);
+ printf("%8d ", total_osize);
+ printf("%8d ", total_csize);
+ printf("%3d%% ", comp_percent(total_osize, total_csize));
+ putchar('\n');
+}