X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=samples%2Fdiodemo.c;h=3e52f2fa920c8b67c69a17ceac128acf174252e4;hb=2eac69a94361323bf7556d2cdde8f61c85c5ef99;hp=55e5a9761fee4db77116ce7072989b4c5a620a74;hpb=16e88a489b01419825fecb836360f23845e1d5c8;p=cc65 diff --git a/samples/diodemo.c b/samples/diodemo.c index 55e5a9761..3e52f2fa9 100644 --- a/samples/diodemo.c +++ b/samples/diodemo.c @@ -1,13 +1,46 @@ +/*****************************************************************************/ +/* */ +/* diodemo.c */ +/* */ +/* Direct Disk I/O Demo Program */ +/* */ +/* */ +/* */ +/* (C) Copyright 2005, Oliver Schmidt, */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + #include #include #include #include #include #include +#include #include -#define MAX_CHUNKS 10 // Maximum acceptable number of chunks +#define MAX_CHUNKS 10 /* Maximum acceptable number of chunks */ static unsigned char ScreenX; @@ -15,32 +48,37 @@ static unsigned char ScreenY; static void ClearLine (void) +/* Clear the screen line the cursor is on */ { cputc ('\r'); cclear (ScreenX); } -static driveid_t AskForDrive (char* Name) +static unsigned char AskForDrive (const char* Name) +/* Ask for a drive id and return it */ { - driveid_t Drive = 0; - char Char; + unsigned char Drive = 0; + char Char; - cprintf ("\r\n%s Drive ID ?", Name); + cprintf ("\r\n%s Drive ID ? ", Name); + cursor (1); do { Char = cgetc (); if (isdigit (Char)) { cputc (Char); - Drive = (driveid_t) (Drive * 10 + Char - '0'); + Drive = Drive * 10 + Char - '0'; } } while (Char != CH_ENTER); + cursor (0); return Drive; } -static void AskForDisk (char* Name, driveid_t Drive) +static void AskForDisk (const char* Name, unsigned char Drive) +/* Ask the user to insert a specific disk */ { ClearLine (); cprintf ("\rInsert %s Disk into Drive %d !", Name, Drive); @@ -49,110 +87,151 @@ static void AskForDisk (char* Name, driveid_t Drive) } -static char* AllocBuffer (sectsize_t SectSize, sectnum_t SectCount, sectnum_t* ChunkCount) +static char* AllocBuffer (unsigned int SectSize, unsigned int SectCount, unsigned int* ChunkCount) +/* Allocate a copy buffer on the heap and return a pointer to it */ { - void* Buffer = NULL; + char* Buffer = NULL; unsigned long BufferSize; unsigned int Chunks = 1; + /* Increase number of chunks resp. decrease size */ + /* of one chunk until buffer allocation succeeds */ do { - *ChunkCount = (sectnum_t) ((SectCount + Chunks - 1) / Chunks); + *ChunkCount = (unsigned int) ((SectCount + Chunks - 1) / Chunks); BufferSize = *ChunkCount * (unsigned long) SectSize; if (BufferSize < UINT_MAX) { Buffer = malloc ((size_t) BufferSize); } } while (Buffer == NULL && ++Chunks <= MAX_CHUNKS); - return (char*) Buffer; + return Buffer; } -int main (void) +int main (int argc, const char* argv[]) { - driveid_t SourceId; - driveid_t TargetId; - dhandle_t Source = NULL; - dhandle_t Target = NULL; - sectsize_t SectSize; - sectnum_t SectCount; - char* Buffer; - sectnum_t Sector; - sectnum_t ChunkCount; - sectnum_t ChunkOffset = 0; + unsigned char SourceId; + unsigned char TargetId; + dhandle_t Source = NULL; + dhandle_t Target = NULL; + unsigned int SectSize; + unsigned int SectCount; + char* Buffer; + unsigned int Sector; + unsigned int ChunkCount; + unsigned int ChunkOffset = 0; clrscr (); screensize (&ScreenX, &ScreenY); + /* Allow user to read exit messages */ + if (doesclrscrafterexit ()) { + atexit ((void (*)) cgetc); + } + cputs ("Floppy Disk Copy\r\n"); chline (16); cputs ("\r\n"); - SourceId = AskForDrive ("Source"); - TargetId = AskForDrive ("Target"); - cputs ("\r\n\r\n"); + /* Get source and target drive id (which may very well be identical) */ + switch (argc) { + case 1: + SourceId = AskForDrive ("Source"); + TargetId = AskForDrive ("Target"); + cputs ("\r\n"); + break; + + case 2: + SourceId = TargetId = atoi (argv[1]); + break; + + case 3: + SourceId = atoi (argv[1]); + TargetId = atoi (argv[2]); + break; + + default: + cprintf ("\r\nToo many arguments\r\n"); + return EXIT_FAILURE; + } + + cputs ("\r\n"); do { + /* Check for single drive copy or inital iteration */ if (SourceId == TargetId || Source == NULL) { AskForDisk ("Source", SourceId); } + /* Check for initial iteration */ if (Source == NULL) { + + /* Open source drive */ Source = dio_open (SourceId); if (Source == NULL) { - cprintf ("\r\n\r\nError %d on opening Drive %d\r\n", (int) _oserror, SourceId); + cprintf ("\r\n\nError %d on opening Drive %d\r\n", (int) _oserror, SourceId); return EXIT_FAILURE; } SectSize = dio_query_sectsize (Source); SectCount = dio_query_sectcount (Source); + /* Allocate buffer */ Buffer = AllocBuffer (SectSize, SectCount, &ChunkCount); if (Buffer == NULL) { - cputs ("\r\n\r\nError on allocating Buffer\r\n"); + cputs ("\r\n\nError on allocating Buffer\r\n"); return EXIT_FAILURE; } } ClearLine (); + /* Read one chunk of sectors into buffer */ for (Sector = ChunkOffset; Sector < SectCount && (Sector - ChunkOffset) < ChunkCount; ++Sector) { cprintf ("\rReading Sector %d of %d", Sector + 1, SectCount); + /* Read one sector */ if (dio_read (Source, Sector, Buffer + (Sector - ChunkOffset) * SectSize) != 0) { - cprintf ("\r\n\r\nError %d on reading Drive %d\r\n", (int) _oserror, SourceId); + cprintf ("\r\n\nError %d on reading from Drive %d\r\n", (int) _oserror, SourceId); return EXIT_FAILURE; } } + /* Check for single drive copy or inital iteration */ if (TargetId == SourceId || Target == NULL) { AskForDisk ("Target", TargetId); } + /* Open target drive on initial iteration */ if (Target == NULL) { Target = dio_open (TargetId); if (Target == NULL) { - cprintf ("\r\n\r\nError %d on opening Drive %d\r\n", (int) _oserror, TargetId); + cprintf ("\r\n\nError %d on opening Drive %d\r\n", (int) _oserror, TargetId); return EXIT_FAILURE; } + /* Check for compatible drives */ if (dio_query_sectsize (Target) != SectSize || dio_query_sectcount (Target) != SectCount) { - cputs ("\r\n\r\nFormat mismatch between Drives\r\n"); + cputs ("\r\n\nFormat mismatch between Drives\r\n"); return EXIT_FAILURE; } } ClearLine (); + /* Write one chunk of sectors from buffer */ for (Sector = ChunkOffset; Sector < SectCount && (Sector - ChunkOffset) < ChunkCount; ++Sector) { cprintf ("\rWriting Sector %d of %d", Sector + 1, SectCount); + /* Write one sector */ if (dio_write (Target, Sector, Buffer + (Sector - ChunkOffset) * SectSize) != 0) { - cprintf ("\r\n\r\nError %d on opening Drive %d\r\n", (int) _oserror, TargetId); + cprintf ("\r\n\nError %d on writing to Drive %d\r\n", (int) _oserror, TargetId); return EXIT_FAILURE; } } + /* Advance to next chunk */ ChunkOffset += ChunkCount; } while (Sector < SectCount);