mirror of
https://github.com/makarcz/vm6502.git
synced 2024-12-27 14:30:00 +00:00
Mass Storage Device Emulation
Started implementation of mass storage device.
This commit is contained in:
parent
c90ad3e7c0
commit
df392fa326
@ -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:
|
||||
|
||||
/*
|
||||
|
224
MassStorage.cpp
Normal file
224
MassStorage.cpp
Normal file
@ -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 <stdio.h>
|
||||
#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
|
100
MassStorage.h
Normal file
100
MassStorage.h
Normal file
@ -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 <string>
|
||||
|
||||
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
|
7
makefile
7
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)
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user