1 /***************************************************************************
3 * pisDOS disk file extractor
5 * Written by Ketmar Dark <ketmar@ketmar.no-ip.org>
6 * Used some information from HalfElf XiSD FAR plugin
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, version 3 of the License ONLY.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 **************************************************************************/
28 #include "../libfusefdc/libfusefdc.h"
31 //==========================================================================
35 //==========================================================================
36 static void cprintLibFDC (int type
, const char *msg
) {
38 case LIBFDC_MSG_DEBUG
: fprintf(stderr
, "LIBFDC[debug]: %s\n", msg
); break;
39 case LIBFDC_MSG_WARNING
: fprintf(stderr
, "LIBFDC[warn]: %s\n", msg
); break;
40 case LIBFDC_MSG_ERROR
: fprintf(stderr
, "LIBFDC[error]: %s\n", msg
); break;
41 default: fprintf(stderr
, "LIBFDC[???]: %s\n", msg
); break; // the thing that should not be
47 //==========================================================================
49 // pisdos_print_dir_entry
51 //==========================================================================
52 static int pisdos_print_dir_entry (const PisDOS_DirEnt
*de
, void *udata
) {
53 const char *month_names
[12] = {"jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"};
55 pisdos_unpack_date(&dt
, de
->date
);
56 if (dt
.month
> 11) dt
.month
= 11;
58 pisdos_get_name(name
, de
);
59 if (pisdos_is_dir(de
)) {
60 if (de
->attr
&PISDOS_FLAG_DIR
) strcat(name
, "/"); else strcat(name
, "*");
61 fprintf(stdout
, "%-13s", name
);
62 fprintf(stdout
, "%04u/%s/%02u --:--:--", dt
.year
, month_names
[dt
.month
], dt
.day
+1);
63 if (de
->attr
&PISDOS_FLAG_HIDDEN
) fprintf(stdout
, " [HIDDEN]");
64 if ((de
->attr
&PISDOS_FLAG_CONTINUOUS
) == 0) fprintf(stdout
, " [SEGMENTED]");
65 fprintf(stdout
, "\n");
67 pisdos_unpack_time(&dt
, de
->file
.time
);
68 fprintf(stdout
, "%-13s", name
);
69 fprintf(stdout
, "%04u/%s/%02u %02u:%02u:%02u", dt
.year
, month_names
[dt
.month
], dt
.day
+1,
70 dt
.hour
, dt
.minute
, dt
.second
);
71 fprintf(stdout
, " %8u", pisdos_get_entry_size(de
));
72 if (de
->attr
&PISDOS_FLAG_HIDDEN
) fprintf(stdout
, " [HIDDEN]");
73 if ((de
->attr
&PISDOS_FLAG_CONTINUOUS
) == 0) fprintf(stdout
, " [SEGMENTED]");
74 fprintf(stdout
, "\n");
80 //==========================================================================
84 //==========================================================================
85 static void pisdos_list_dir (disk_t
*dsk
, const PisDOS_DirEnt
*dirde
) {
86 pisdos_dir_foreach(dsk
, dirde
, &pisdos_print_dir_entry
, NULL
);
91 //==========================================================================
95 //==========================================================================
96 int main (int argc
, char **argv
) {
99 libfdcMessageCB
= &cprintLibFDC
;
102 const char *diskimg_fname
= NULL
;
105 for (int f
= 1; f
< argc
; ++f
) {
106 const char *arg
= argv
[f
];
107 if (!arg
|| !arg
[0]) continue;
109 if (strcmp(arg
, "--") == 0) {
110 fprintf(stderr
, "wtf?\n");
115 if (strcmp(arg
, "--dpb") == 0) { dump_dpb
= 1; continue; }
116 if (strcmp(arg
, "--help") == 0) { diskimg_fname
= NULL
; break; }
117 if (strcmp(arg
, "-h") == 0) { diskimg_fname
= NULL
; break; }
118 fprintf(stderr
, "FATAL: unknown option '%s'\n", arg
);
122 if (!diskimg_fname
) {
123 diskimg_fname
= argv
[f
];
132 if (!diskimg_fname
) {
133 fprintf(stderr
, "usage: pisdos diskimg [path]\n");
137 disk_init_struct(&dsk
);
139 const int dopres
= disk_open(&dsk
, diskimg_fname
);
140 if (dopres
!= DISK_OK
) {
141 fprintf(stderr
, "FATAL: cannot open disk image '%s'! (error: %s)\n",
142 diskimg_fname
, disk_strerror(dopres
));
148 fprintf(stdout
, "*** DISK INFO: %d heads, %d cylinders; %d BPT ***\n",
149 dsk
.sides
, dsk
.cylinders
, dsk
.bpt
);
154 pisdos_get_title(dsktitle
, pisdos_get_dpb(&dsk
));
155 if (dsktitle
[0]) fprintf(stdout
, "*** DISK TITLE: %s ***\n", dsktitle
);
160 disk_write(&dsk
, "_z00.fdi");
162 pisdos_debug_dump_dpb(&dsk
);
169 const uint8_t *blk
= pisdos_block_ptr(&dsk
, 43);
170 fprintf(stderr
, "frag_count : %u\n", blk
[0]);
171 fprintf(stderr
, "frag_start : %u\n", blk
[1]|(blk
[2]<<8));
172 fprintf(stderr
, "frag_length: %u\n", blk
[3]);
178 pisdos_list_dir(&dsk
, NULL
);
187 for (int f
= file_start
; f
< argc
; ++f
) {
188 const PisDOS_DirEnt
*de
= pisdos_findfirst(&fi
, &dsk
, argv
[f
]);
190 fprintf(stderr
, "ERROR: cannot find files with mask '%s'!\n", argv
[f
]);
195 memset(outfname
, 0, sizeof(outfname
));
196 pisdos_get_name(outfname
+1, de
);
199 if (pisdos_is_dir(de
)) {
200 fprintf(stdout
, "===== %s/ =====\n", outfname
+1);
201 pisdos_list_dir(&dsk
, de
);
202 fprintf(stdout
, "------------\n");
205 PisDOSFragList frags
;
206 if (pisdos_build_frags(&dsk
, de
, &frags
) != 0) {
207 fprintf(stderr
, "ERROR: cannot build fragment list for file '%s'\n", outfname
+1);
211 FILE *fo
= fopen(outfname
, "w");
213 fprintf(stderr
, "ERROR: cannot create host file '%s'!\n", outfname
);
218 uint32_t left
= pisdos_get_entry_size(de
);
220 uint32_t rd
= (left
> 256 ? 256 : left
);
221 const void *bp
= pisdos_next_block(&dsk
, &frags
);
223 fprintf(stderr
, "ERROR reading pisdos file at position %u (%u bytes left)\n",
227 if (fwrite(bp
, rd
, 1, fo
) != 1) {
228 fprintf(stderr
, "ERROR writing host file at position %u (%u bytes left)\n",
236 fprintf(stdout
, "extracted '%s'.\n", outfname
);
240 de
= pisdos_findnext(&fi
);