diff options
Diffstat (limited to 'src/listalf.c')
| -rw-r--r-- | src/listalf.c | 118 |
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'); +} |
