]> git.sur5r.net Git - cc65/blob - samples/diodemo.c
Fixed _textcolor definition.
[cc65] / samples / diodemo.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 diodemo.c                                 */
4 /*                                                                           */
5 /*                       Direct Disk I/O Demo Program                        */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) Copyright 2005, Oliver Schmidt, <ol.sc@web.de>                        */
10 /*                                                                           */
11 /*                                                                           */
12 /* This software is provided 'as-is', without any expressed or implied       */
13 /* warranty.  In no event will the authors be held liable for any damages    */
14 /* arising from the use of this software.                                    */
15 /*                                                                           */
16 /* Permission is granted to anyone to use this software for any purpose,     */
17 /* including commercial applications, and to alter it and redistribute it    */
18 /* freely, subject to the following restrictions:                            */
19 /*                                                                           */
20 /* 1. The origin of this software must not be misrepresented; you must not   */
21 /*    claim that you wrote the original software. If you use this software   */
22 /*    in a product, an acknowledgment in the product documentation would be  */
23 /*    appreciated but is not required.                                       */
24 /* 2. Altered source versions must be plainly marked as such, and must not   */
25 /*    be misrepresented as being the original software.                      */
26 /* 3. This notice may not be removed or altered from any source              */
27 /*    distribution.                                                          */
28 /*                                                                           */
29 /*****************************************************************************/
30
31
32
33 #include <stddef.h>
34 #include <stdlib.h>
35 #include <limits.h>
36 #include <conio.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <cc65.h>
40 #include <dio.h>
41
42
43 #define MAX_CHUNKS 10 /* Maximum acceptable number of chunks */
44
45
46 static unsigned char ScreenX;
47 static unsigned char ScreenY;
48
49
50 static void ClearLine (void)
51 /* Clear the screen line the cursor is on */
52 {
53     cputc ('\r');
54     cclear (ScreenX);
55 }
56
57
58 static unsigned char AskForDrive (const char* Name)
59 /* Ask for a drive id and return it */
60 {
61     unsigned char Drive = 0;
62     char          Char;
63
64     cprintf ("\r\n%s Drive ID ? ", Name);
65
66     cursor (1);
67     do {
68         Char = cgetc ();
69         if (isdigit (Char)) {
70             cputc (Char);
71             Drive = Drive * 10 + Char - '0';
72         }
73     } while (Char != CH_ENTER);
74     cursor (0);
75
76     return Drive;
77 }
78
79
80 static void AskForDisk (const char* Name, unsigned char Drive)
81 /* Ask the user to insert a specific disk */
82 {
83     ClearLine ();
84     cprintf ("\rInsert %s Disk into Drive %d !", Name, Drive);
85
86     cgetc ();
87 }
88
89
90 static char* AllocBuffer (unsigned int SectSize, unsigned int SectCount, unsigned int* ChunkCount)
91 /* Allocate a copy buffer on the heap and return a pointer to it */
92 {
93     char*         Buffer = NULL;
94     unsigned long BufferSize;
95     unsigned int  Chunks = 1;
96
97     /* Increase number of chunks resp. decrease size */
98     /* of one chunk until buffer allocation succeeds */
99     do {
100         *ChunkCount = (unsigned int) ((SectCount + Chunks - 1) / Chunks);
101         BufferSize = *ChunkCount * (unsigned long) SectSize;
102         if (BufferSize < UINT_MAX) {
103             Buffer = malloc ((size_t) BufferSize);
104         }
105     } while (Buffer == NULL && ++Chunks <= MAX_CHUNKS);
106
107     return Buffer;
108 }
109
110
111 int main (int argc, const char* argv[])
112 {
113     unsigned char SourceId;
114     unsigned char TargetId;
115     dhandle_t     Source = NULL;
116     dhandle_t     Target = NULL;
117     unsigned int  SectSize;
118     unsigned int  SectCount;
119     char*         Buffer;
120     unsigned int  Sector;
121     unsigned int  ChunkCount;
122     unsigned int  ChunkOffset = 0;
123
124     clrscr ();
125     screensize (&ScreenX, &ScreenY);
126
127     /* Allow user to read exit messages */
128     if (doesclrscrafterexit ()) {
129         atexit ((void (*)) cgetc);
130     }
131
132     cputs ("Floppy Disk Copy\r\n");
133     chline (16);
134     cputs ("\r\n");
135
136     /* Get source and target drive id (which may very well be identical) */
137     switch (argc) {
138       case 1:
139         SourceId = AskForDrive ("Source");
140         TargetId = AskForDrive ("Target");
141         cputs ("\r\n");
142         break;
143
144       case 2:
145         SourceId = TargetId = atoi (argv[1]);
146         break;
147
148       case 3:
149         SourceId = atoi (argv[1]);
150         TargetId = atoi (argv[2]);
151         break;
152
153       default:
154         cprintf ("\r\nToo many arguments\r\n");
155         return EXIT_FAILURE;
156     }
157
158     cputs ("\r\n");
159
160     do {
161         /* Check for single drive copy or inital iteration */
162         if (SourceId == TargetId || Source == NULL) {
163             AskForDisk ("Source", SourceId);
164         }
165
166         /* Check for initial iteration */
167         if (Source == NULL) {
168
169             /* Open source drive */
170             Source = dio_open (SourceId);
171             if (Source == NULL) {
172                 cprintf ("\r\n\nError %d on opening Drive %d\r\n", (int) _oserror, SourceId);
173                 return EXIT_FAILURE;
174             }
175
176             SectSize  = dio_query_sectsize (Source);
177             SectCount = dio_query_sectcount (Source);
178
179             /* Allocate buffer */
180             Buffer = AllocBuffer (SectSize, SectCount, &ChunkCount);
181             if (Buffer == NULL) {
182                 cputs ("\r\n\nError on allocating Buffer\r\n");
183                 return EXIT_FAILURE;
184             }
185         }
186
187         ClearLine ();
188
189         /* Read one chunk of sectors into buffer */
190         for (Sector = ChunkOffset; Sector < SectCount && (Sector - ChunkOffset) < ChunkCount; ++Sector) {
191             cprintf ("\rReading Sector %d of %d", Sector + 1, SectCount);
192
193             /* Read one sector */
194             if (dio_read (Source, Sector, Buffer + (Sector - ChunkOffset) * SectSize) != 0) {
195                 cprintf ("\r\n\nError %d on reading from Drive %d\r\n", (int) _oserror, SourceId);
196                 return EXIT_FAILURE;
197             }
198         }
199
200         /* Check for single drive copy or inital iteration */
201         if (TargetId == SourceId || Target == NULL) {
202             AskForDisk ("Target", TargetId);
203         }
204
205         /* Open target drive on initial iteration */
206         if (Target == NULL) {
207             Target = dio_open (TargetId);
208             if (Target == NULL) {
209                 cprintf ("\r\n\nError %d on opening Drive %d\r\n", (int) _oserror, TargetId);
210                 return EXIT_FAILURE;
211             }
212
213             /* Check for compatible drives */
214             if (dio_query_sectsize (Target)  != SectSize ||
215                 dio_query_sectcount (Target) != SectCount) {
216                 cputs ("\r\n\nFormat mismatch between Drives\r\n");
217                 return EXIT_FAILURE;
218             }
219         }
220
221         ClearLine ();
222
223         /* Write one chunk of sectors from buffer */
224         for (Sector = ChunkOffset; Sector < SectCount && (Sector - ChunkOffset) < ChunkCount; ++Sector) {
225             cprintf ("\rWriting Sector %d of %d", Sector + 1, SectCount);
226
227             /* Write one sector */
228             if (dio_write (Target, Sector, Buffer + (Sector - ChunkOffset) * SectSize) != 0) {
229                 cprintf ("\r\n\nError %d on writing to Drive %d\r\n", (int) _oserror, TargetId);
230                 return EXIT_FAILURE;
231             }
232         }
233
234         /* Advance to next chunk */
235         ChunkOffset += ChunkCount;
236
237     } while (Sector < SectCount);
238
239     ClearLine ();
240     cprintf ("\rSuccessfully copied %d Sectors\r\n", SectCount);
241
242     free (Buffer);
243     dio_close (Source);
244     dio_close (Target);
245
246     return EXIT_SUCCESS;
247 }