OXYGENHUB
◆ main openmsx / src / fdc / NowindHost.hh
3.9 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef NOWINDHOST_HH
2
#define NOWINDHOST_HH
3
4
#include "DiskImageUtils.hh"
5
#include "circular_buffer.hh"
6
7
#include <array>
8
#include <cstdint>
9
#include <fstream>
10
#include <memory>
11
#include <optional>
12
#include <span>
13
#include <string>
14
#include <vector>
15
16
namespace openmsx {
17
18
class SectorAccessibleDisk;
19
class DiskContainer;
20
21
class NowindHost
22
{
23
public:
24
	using Drives = std::vector<std::unique_ptr<DiskContainer>>;
25
26
	explicit NowindHost(const Drives& drives);
27
	~NowindHost();
28
29
	// public for usb-host implementation
30
	[[nodiscard]] bool isDataAvailable() const;
31
32
	// read one byte of response-data from the host (msx <- pc)
33
	uint8_t read();
34
35
	// like read(), but without side effects (doesn't consume the data)
36
	[[nodiscard]] uint8_t peek() const;
37
38
	// Write one byte of command-data to the host   (msx -> pc)
39
	// Time parameter is in milliseconds. Emulators can pass emulation
40
	// time, USB-host can pass real time.
41
	void write(uint8_t data, unsigned time);
42
43
	void setAllowOtherDiskRoms(bool allow) { allowOtherDiskRoms = allow; }
44
	[[nodiscard]] bool getAllowOtherDiskRoms() const { return allowOtherDiskRoms; }
45
46
	void setEnablePhantomDrives(bool enable) { enablePhantomDrives = enable; }
47
	[[nodiscard]] bool getEnablePhantomDrives() const { return enablePhantomDrives; }
48
49
	template<typename Archive>
50
	void serialize(Archive& ar, unsigned version);
51
52
	// public for serialization
53
	enum class State : uint8_t {
54
		SYNC1,     // waiting for AF
55
		SYNC2,     // waiting for 05
56
		COMMAND,   // waiting for command (9 bytes)
57
		DISKREAD,  // waiting for AF07
58
		DISKWRITE, // waiting for AA<data>AA
59
		DEVOPEN,   // waiting for filename (11 bytes)
60
		IMAGE,     // waiting for filename
61
		MESSAGE,   // waiting for null-terminated message
62
	};
63
64
private:
65
	void msxReset();
66
	[[nodiscard]] SectorAccessibleDisk* getDisk() const;
67
	void executeCommand();
68
69
	void send(uint8_t value);
70
	void send16(uint16_t value);
71
	void sendHeader();
72
	void purge();
73
74
	void DRIVES();
75
	void DSKCHG();
76
	void CHOICE();
77
	void INIENV();
78
	void setDateMSX();
79
80
	[[nodiscard]] unsigned getSectorAmount() const;
81
	[[nodiscard]] unsigned getStartSector() const;
82
	[[nodiscard]] unsigned getStartAddress() const;
83
	[[nodiscard]] unsigned getCurrentAddress() const;
84
85
	void diskReadInit(SectorAccessibleDisk& disk);
86
	void doDiskRead1();
87
	void doDiskRead2();
88
	void transferSectors(unsigned transferAddress, unsigned amount);
89
	void transferSectorsBackwards(unsigned transferAddress, unsigned amount);
90
91
	void diskWriteInit(const SectorAccessibleDisk& disk);
92
	void doDiskWrite1();
93
	void doDiskWrite2();
94
95
	[[nodiscard]] uint16_t getFCB() const;
96
	[[nodiscard]] std::string extractName(int begin, int end) const;
97
	unsigned readHelper1(unsigned dev, std::span<char, 256> buffer);
98
	void readHelper2(std::span<const char> buffer);
99
	[[nodiscard]] int getDeviceNum() const;
100
	int getFreeDeviceNum();
101
	void deviceOpen();
102
	void deviceClose();
103
	void deviceWrite();
104
	void deviceRead();
105
106
	void callImage(const std::string& filename);
107
108
private:
109
	static constexpr unsigned MAX_DEVICES = 16;
110
111
	const Drives& drives;
112
113
	cb_queue<uint8_t> hostToMsxFifo;
114
115
	struct Device {
116
		std::optional<std::fstream> fs; // not in use when fs == nullopt
117
		uint16_t fcb;
118
	};
119
	std::array<Device, MAX_DEVICES> devices;
120
121
	// state-machine
122
	std::vector<SectorBuffer> buffer;// work buffer for disk read/write
123
	unsigned lastTime = 0;   // last time a byte was received from MSX
124
	State state = State::SYNC1;
125
	unsigned recvCount;      // how many bytes recv in this state
126
	unsigned transferred;    // progress within disk read/write
127
	unsigned retryCount;     // only used for disk read
128
	unsigned transferSize;   // size of current chunk
129
	std::array<uint8_t, 9> cmdData; // reg_[cbedlhfa] + cmd
130
	std::array<uint8_t, 240 + 2> extraData; // extra data for disk read/write
131
132
	uint8_t romDisk = 255;      // index of rom disk (255 = no rom disk)
133
	bool allowOtherDiskRoms = false;
134
	bool enablePhantomDrives = true;
135
};
136
137
} // namespace openmsx
138
139
#endif // NOWINDHOST_HH