mirror of https://github.com/makarcz/vm6502.git
Add mass storage device.
Start implementation of mass storage device emulation.
This commit is contained in:
parent
c90ad3e7c0
commit
b55462fb70
|
@ -174,6 +174,22 @@ STATUS: In progress.
|
||||||
- characters table
|
- characters table
|
||||||
- cursor and cursor position control/movement/mode
|
- 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:
|
---------------------------------------------- TEXT TEMPLATES:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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
|
|
@ -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"
|
SDLINCS = -I"$(SDLBASE)/include"
|
||||||
CPP = g++ -D__DEBUG__ -DLINUX
|
CPP = g++ -D__DEBUG__ -DLINUX
|
||||||
CC = gcc -D__DEBUG__
|
CC = gcc -D__DEBUG__
|
||||||
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
|
||||||
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
|
||||||
BIN = vm65
|
BIN = vm65
|
||||||
SDLLIBS = -L/usr/local/lib -lSDL2main -lSDL2
|
SDLLIBS = -L/usr/local/lib -lSDL2main -lSDL2
|
||||||
LIBS = -static-libgcc -m32 -g3 -ltermcap -lncurses
|
LIBS = -static-libgcc -m32 -g3 -ltermcap -lncurses
|
||||||
|
@ -59,3 +59,6 @@ MemMapDev.o: MemMapDev.cpp MemMapDev.h
|
||||||
|
|
||||||
ConsoleIO.o: ConsoleIO.cpp ConsoleIO.h
|
ConsoleIO.o: ConsoleIO.cpp ConsoleIO.h
|
||||||
$(CPP) -c ConsoleIO.cpp -o ConsoleIO.o $(CXXFLAGS)
|
$(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__
|
CPP = g++.exe -D__DEBUG__
|
||||||
CC = gcc.exe -D__DEBUG__
|
CC = gcc.exe -D__DEBUG__
|
||||||
WINDRES = windres.exe
|
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
|
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
|
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
|
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
|
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
|
ConsoleIO.o: ConsoleIO.cpp ConsoleIO.h
|
||||||
$(CPP) -c ConsoleIO.cpp -o ConsoleIO.o $(CXXFLAGS)
|
$(CPP) -c ConsoleIO.cpp -o ConsoleIO.o $(CXXFLAGS)
|
||||||
|
|
||||||
|
MassStorage.o: MassStorage.cpp MassStorage.h
|
||||||
|
$(CPP) -c MassStorage.cpp -o MassStorage.o $(CXXFLAGS)
|
||||||
|
|
||||||
$(BIN2): $(OBJ2)
|
$(BIN2): $(OBJ2)
|
||||||
$(CC) $(LINKOBJ2) -o $(BIN2) $(LIBS)
|
$(CC) $(LINKOBJ2) -o $(BIN2) $(LIBS)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue