From b55462fb70ea71750d3a65f9b6fcfb6a5db737fa Mon Sep 17 00:00:00 2001 From: Marek Karcz Date: Thu, 6 Sep 2018 11:01:23 -0400 Subject: [PATCH] Add mass storage device. Start implementation of mass storage device emulation. --- DevJournal.txt | 16 ++++ MassStorage.cpp | 224 ++++++++++++++++++++++++++++++++++++++++++++++++ MassStorage.h | 100 +++++++++++++++++++++ makefile | 7 +- makefile.mingw | 7 +- 5 files changed, 350 insertions(+), 4 deletions(-) create mode 100644 MassStorage.cpp create mode 100644 MassStorage.h diff --git a/DevJournal.txt b/DevJournal.txt index c53f456..4cf852b 100644 --- a/DevJournal.txt +++ b/DevJournal.txt @@ -174,6 +174,22 @@ STATUS: In progress. - characters table - cursor and cursor position control/movement/mode +* Add mass storage device emulator. +STATUS: Started. + + Created MassStorage.h, MassStorage.cpp for implementation of a disk-like + device. The device will emulate abstracts typical to disk surface, like + track, sector, block. It will be rather low level but will keep the images + of the emulated disk media on the hard drive. + This device will be then mapped to memory via MemMapDev class. + The memory registers will represent the functions of a low level disk + controller. E.g.: there will be a register to initiate a required data + access function (read, write, format) and registers for arguments. + There may be registers for byte-by-byte data transfer with handshaking + like protocol or a memory address register for DMA transfer mode. + Internally I will try to emulate Commodore 1541 disk format, compatible with + popular D64 image. + ---------------------------------------------- TEXT TEMPLATES: /* diff --git a/MassStorage.cpp b/MassStorage.cpp new file mode 100644 index 0000000..7e1fdbb --- /dev/null +++ b/MassStorage.cpp @@ -0,0 +1,224 @@ +/* + *-------------------------------------------------------------------- + * Project: VM65 - Virtual Machine/CPU emulator programming + * framework. + * + * File: MassStorage.cpp + * + * Purpose: Implementation of MassStorage class. + * To emulate disk-like mass storage device for data. + * + * Date: 8/16/2017 + * + * Copyright: (C) by Marek Karcz 2016, 2017. All rights reserved. + * + * Contact: makarcz@yahoo.com + * + * License Agreement and Warranty: + + This software is provided with No Warranty. + I (Marek Karcz) will not be held responsible for any damage to + computer systems, data or user's health resulting from use. + Please proceed responsibly and apply common sense. + This software is provided in hope that it will be useful. + It is free of charge for non-commercial and educational use. + Distribution of this software in non-commercial and educational + derivative work is permitted under condition that original + copyright notices and comments are preserved. Some 3-rd party work + included with this project may require separate application for + permission from their respective authors/copyright owners. + + *-------------------------------------------------------------------- + */ + +#include +#include "MassStorage.h" +#include "MKGenException.h" +#include "system.h" + +namespace MKBasic { + +constexpr int MassStorage::sect_per_track[]; + +/* + *-------------------------------------------------------------------- + * Method: MassStorage() + * Purpose: Class default constructor. + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +MassStorage::MassStorage() +{ + Initialize(); +} + + /* + *-------------------------------------------------------------------- + * Method: ~MassStorage() + * Purpose: Class destructor. + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +MassStorage::~MassStorage() +{ + +} + + /* + *-------------------------------------------------------------------- + * Method: Initialize() + * Purpose: Initialize internal variables. + * Arguments: + * Returns: + *-------------------------------------------------------------------- + */ +void MassStorage::Initialize() +{ + // TO DO: add code to initialize class + + // initialize standard disk images + DiskTrack dtrk; + DiskImage ditbl[] = { + {0, "DISK0", {dtrk}}, + {1, "DISK1", {dtrk}}, + {2, "DISK2", {dtrk}}, + {3, "DISK3", {dtrk}}, + {4, "DISK4", {dtrk}}, + {5, "DISK5", {dtrk}}, + {6, "DISK6", {dtrk}}, + {7, "DISK7", {dtrk}}, + {8, "DISK8", {dtrk}}, + {9, "DISK9", {dtrk}} + }; + for (int i=0; i < num_of_images; i++) { + mDiskImages[i].id = ditbl[i].id; + mDiskImages[i].name = ditbl[i].name; + string fname = mDiskImages[i].name + "_" + to_string(mDiskImages[i].id) + ".disk"; + FILE *fp = fopen(fname.c_str(), "r"); + if (NULL == fp) { + Format(mDiskImages[i].id, mDiskImages[i].name); + Flush(mDiskImages[i].id); + } else { + LoadFromFile(mDiskImages[i].id, mDiskImages[i].name); + fclose(fp); + } + } +} + + /* + *-------------------------------------------------------------------- + * Method: Format() + * Purpose: Format the disk image. + * Arguments: id - the number / id of the disk image to format + * name - the new name of the disk image + * Returns: int - 0 if OK, less than 0 if error. + *-------------------------------------------------------------------- + */ +int MassStorage::Format (int id, string name) +{ + int ret = 0; + + // TO DO: add code to format disk image + DiskImage dimg; + dimg.name = name; + for (int track=0; track < max_numof_tracks; track++) { + dimg.data[track].num = track+1; + dimg.data[track].num_of_sectors = sect_per_track[track]; + if (track+1 == 18) { // BAM + directory + dimg.data[track].data[0x00] = 0x12; // point to track 18 + dimg.data[track].data[0x01] = 0x01; // and sector 1 (directory) + dimg.data[track].data[0x02] = 0x41; // DOS version + dimg.data[track].data[0x03] = 0x01; // unused + // BAM + for (int sector = 0x04; sector < 0x90; sector += 4) { + dimg.data[track].data[sector] = dimg.data[track].num_of_sectors; + dimg.data[track].data[sector+1] = 0xff; + dimg.data[track].data[sector+2] = 0xff; + dimg.data[track].data[sector+3] = ~(0xff << (dimg.data[track].num_of_sectors - 16)); + } + } else { + + } + } + + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: Flush() + * Purpose: Save image data to disk file. + * Arguments: id - the disk image id + * Returns: int - 0 if OK, less than 0 if error + *-------------------------------------------------------------------- + */ +int MassStorage::Flush (int id) +{ + int ret = 0; + + // TO DO: add code to flush disk image to file + + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: ReadSectorData() + * Purpose: Read data from disk's image sector. + * Arguments: id - disk image id + * track - track# + * sector - sector# + * Returns: pointer to data + *-------------------------------------------------------------------- + */ +unsigned char * MassStorage::ReadSectorData(int id, + int track, + int sector) +{ + // TO DO: add code to read data + + return mSectorBuf; +} + +/* + *-------------------------------------------------------------------- + * Method: WriteSectorData() + * Purpose: Write data to disk's image sector. + * Arguments: id - the disk image id + * track - track# + * sector - sector# + * buf - pointer to data + * Returns: int - 0 if OK, less than 0 if error + *-------------------------------------------------------------------- + */ +int MassStorage::WriteSectorData (int id, + int track, + int sector, + unsigned char *buf) +{ + int ret = 0; + + // TO DO: add code to write sector data + + return ret; +} + +/* + *-------------------------------------------------------------------- + * Method: LoadFromFile() + * Purpose: Load image data from file. + * Arguments: id - the disk image id + * name - disk image name + * Returns: int - 0 if OK, less than 0 if error + *-------------------------------------------------------------------- + */ +int MassStorage::LoadFromFile(int id, string name) +{ + int ret = 0; + + return ret; +} + +} // namespace MKBasic \ No newline at end of file diff --git a/MassStorage.h b/MassStorage.h new file mode 100644 index 0000000..17bd568 --- /dev/null +++ b/MassStorage.h @@ -0,0 +1,100 @@ +/* + *-------------------------------------------------------------------- + * Project: VM65 - Virtual Machine/CPU emulator programming + * framework. + * + * File: MassStorage.h + * + * Purpose: Prototype of MassStorage class and supporting data + * structures, constants, enumerations and macros. + * + * Date: 8/16/2017 + * + * Copyright: (C) by Marek Karcz 2016, 2017. All rights reserved. + * + * Contact: makarcz@yahoo.com + * + * License Agreement and Warranty: + + This software is provided with No Warranty. + I (Marek Karcz) will not be held responsible for any damage to + computer systems, data or user's health resulting from use. + Please proceed responsibly and apply common sense. + This software is provided in hope that it will be useful. + It is free of charge for non-commercial and educational use. + Distribution of this software in non-commercial and educational + derivative work is permitted under condition that original + copyright notices and comments are preserved. Some 3-rd party work + included with this project may require separate application for + permission from their respective authors/copyright owners. + + *-------------------------------------------------------------------- + */ +#ifndef MASSSTORAGE_H +#define MASSSTORAGE_H + +#include + +using namespace std; + +namespace MKBasic { + + class MassStorage { + + public: + + // CBM 1541 format + static const int max_numof_sectors = 21; + static const int sector_size = 256; + static const int max_numof_tracks = 35; + static const int num_of_images = 10; + constexpr static int sect_per_track[] = + {21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, + 19, 19, 19, 19, 19, 19, 19, + 18, 18, 18, 18, 18, 18, + 17, 17, 17, 17, 17}; + + MassStorage(); + ~MassStorage(); + int Format (int id, string name); // format disk image + int Flush (int id); // flush disk image to hard drive + unsigned char *ReadSectorData(int id, + int track, + int sector); // read data from sector + int WriteSectorData (int id, + int track, + int sector, + unsigned char *buf); // write data to sector + + private: + + // definition of a disk track structure + struct DiskTrack { + + int num; + int num_of_sectors; + unsigned char data[max_numof_sectors * sector_size]; + + }; + + // definition of a disk image structure + struct DiskImage { + + int id; + string name; + DiskTrack data[max_numof_tracks]; + }; + + unsigned char mSectorBuf[sector_size]; // buffer for sector data + DiskImage mDiskImages[num_of_images]; // buffer for all disk images + + void Initialize(); + int LoadFromFile(int id, string name); // load image from disk cache + + }; // class MassStorage + +} // namespace MKBasic + +#endif diff --git a/makefile b/makefile index 1d69d3a..d5abb93 100644 --- a/makefile +++ b/makefile @@ -4,8 +4,8 @@ SDLBASE = $(SDLDIR) SDLINCS = -I"$(SDLBASE)/include" CPP = g++ -D__DEBUG__ -DLINUX CC = gcc -D__DEBUG__ -OBJ = main.o VMachine.o MKCpu.o Memory.o Display.o GraphDisp.o MemMapDev.o MKGenException.o ConsoleIO.o -LINKOBJ = main.o VMachine.o MKCpu.o Memory.o Display.o GraphDisp.o MemMapDev.o MKGenException.o ConsoleIO.o +OBJ = main.o VMachine.o MKCpu.o Memory.o Display.o GraphDisp.o MemMapDev.o MKGenException.o ConsoleIO.o MassStorage.o +LINKOBJ = main.o VMachine.o MKCpu.o Memory.o Display.o GraphDisp.o MemMapDev.o MKGenException.o ConsoleIO.o MassStorage.o BIN = vm65 SDLLIBS = -L/usr/local/lib -lSDL2main -lSDL2 LIBS = -static-libgcc -m32 -g3 -ltermcap -lncurses @@ -59,3 +59,6 @@ MemMapDev.o: MemMapDev.cpp MemMapDev.h ConsoleIO.o: ConsoleIO.cpp ConsoleIO.h $(CPP) -c ConsoleIO.cpp -o ConsoleIO.o $(CXXFLAGS) + +MassStorage.o: MassStorage.cpp MassStorage.h + $(CPP) -c MassStorage.cpp -o MassStorage.o $(CXXFLAGS) diff --git a/makefile.mingw b/makefile.mingw index a42f14c..b3d5148 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -7,9 +7,9 @@ SDLBASE = $(SDLDIR) CPP = g++.exe -D__DEBUG__ CC = gcc.exe -D__DEBUG__ WINDRES = windres.exe -OBJ = main.o VMachine.o MKCpu.o Memory.o Display.o GraphDisp.o MemMapDev.o MKGenException.o ConsoleIO.o +OBJ = main.o VMachine.o MKCpu.o Memory.o Display.o GraphDisp.o MemMapDev.o MKGenException.o ConsoleIO.o MassStorage.o OBJ2 = bin2hex.o -LINKOBJ = main.o VMachine.o MKCpu.o Memory.o Display.o GraphDisp.o MemMapDev.o MKGenException.o ConsoleIO.o +LINKOBJ = main.o VMachine.o MKCpu.o Memory.o Display.o GraphDisp.o MemMapDev.o MKGenException.o ConsoleIO.o MassStorage.o LINKOBJ2 = bin2hex.o LIBS = -L"C:\mingw-w64\x86_64-5.3.0\mingw64\x86_64-w64-mingw32/lib" -L"C:\mingw-w64\x86_64-5.3.0\mingw64\x86_64-w64-mingw32/lib" -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic -lmingw32 SDLLIBS = -L"$(SDLBASE)\x86_64-w64-mingw32/lib" -lSDL2main -lSDL2 @@ -61,6 +61,9 @@ MKGenException.o: MKGenException.cpp MKGenException.h ConsoleIO.o: ConsoleIO.cpp ConsoleIO.h $(CPP) -c ConsoleIO.cpp -o ConsoleIO.o $(CXXFLAGS) +MassStorage.o: MassStorage.cpp MassStorage.h + $(CPP) -c MassStorage.cpp -o MassStorage.o $(CXXFLAGS) + $(BIN2): $(OBJ2) $(CC) $(LINKOBJ2) -o $(BIN2) $(LIBS)