File:  [Isaki's NoNo m68k/m88k emulator] / nono / vm / iodevstream.h
Revision 1.1.1.7 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:42 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, v026, v025, v024, v023, HEAD
nono 1.3.0

//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//

#pragma once

#include "device.h"

// IODevice クラスへの Read/Write をストリームっぽく扱う。
// Read/Write とも受け渡しはホストバイトオーダの値で行い、
// デバイスへのアクセスはビッグエンディアンで行う。
// アクセス中にバスエラーが起きることは考慮していない。
//
// addr は基本的には物理アドレスだが、Read()/Write() がアドレスをマスクする
// タイプならオフセットを指定しても等価となる。
// MainRAM は物理アドレスだが、通常 0 から始まるのでどちらも等価にみえる。
// ExtRAM なら物理アドレスでなければならない。
// SubRAM はアドレスをマスクするので、アドレスでもオフセットでもよいが
// XP 視点でいえばオフセットのほうが処理しやすい、などそれぞれ事情が異なる。
// 指定したデバイスがどっちの振る舞いなのかは把握してから使うこと。
// どちらにしてもこのクラスでは "アドレス" と呼ぶ。
class IODeviceStream
{
 public:
	// コンストラクタ
	explicit IODeviceStream(IODevice *dev_) {
		dev = dev_;
	}
	IODeviceStream(IODevice *dev_, uint32 addr_) {
		dev = dev_;
		addr = addr_;
	}
	~IODeviceStream();

	// アドレスを設定する
	void SetAddr(uint32 addr_) {
		addr = addr_;
	}
	// アドレスを取得する
	uint32 GetAddr() const {
		return addr;
	}

	// 1バイト読み込んでポインタを進める
	uint64 Read1() {
		return ReadN(BusAddr::Size1);
	}

	// 2バイト読み込んでポインタを進める。addr はアラインしなくてよい
	uint64 Read2() {
		return ReadN(BusAddr::Size2);
	}

	// 4バイト読み込んでポインタを進める。addr はアラインしなくてよい
	// データはホストエンディアンで返される。
	uint64 Read4() {
		return ReadN(BusAddr::Size4);
	}

	// 1バイト書き込んでポインタを進める
	void Write1(uint32 data)
	{
		WriteN(BusAddr::Size1, data);
	}

	// 2バイト書き込んでポインタを進める。addr はアラインしてなくてよい
	void Write2(uint32 data)
	{
		WriteN(BusAddr::Size2, data);
	}

	// 3バイト書き込んでポインタを進める。addr はアラインしてなくてよい
	void Write3(uint32 data)
	{
		WriteN(BusAddr::Size3, data);
	}

	// 4バイト書き込んでポインタを進める。addr はアラインしてなくてよい
	void Write4(uint32 data)
	{
		WriteN(BusAddr::Size4, data);
	}

	// LE で2バイト書き込んでポインタを進める。addr はアラインしてなくてよい
	void Write2LE(uint32 data)
	{
		Write1(data & 0xff);
		Write1(data >> 8);
	}

	// 文字列を書き込んでポインタを進める。
	void WriteString(const char *p)
	{
		while (*p) {
			Write1(*p++);
		}
		Write1('\0');
	}

	// ホストの src から len バイトを書き込んでポインタを進める。
	void WriteMem(const void *src, uint len);

	// アドレスも指定する版。ポインタは同様に進める
	uint64 Read1(uint32 addr_) {
		SetAddr(addr_);
		return Read1();
	}
	uint64 Read2(uint32 addr_) {
		SetAddr(addr_);
		return Read2();
	}
	uint64 Read4(uint32 addr_) {
		SetAddr(addr_);
		return Read4();
	}
	void Write1(uint32 addr_, uint32 data) {
		SetAddr(addr_);
		Write1(data);
	}
	void Write2(uint32 addr_, uint32 data) {
		SetAddr(addr_);
		Write2(data);
	}
	void Write4(uint32 addr_, uint32 data) {
		SetAddr(addr_);
		Write4(data);
	}

 private:
	busdata ReadN(busaddr size);
	busdata WriteN(busaddr size, uint32 data);

	IODevice *dev {};
	uint32 addr {};
};

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.