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

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

//
// メインバス (LUNA)
//

// IODevice
//   +-- MainbusBaseDevice (InitMainbus() と FC アクセスを持つ)
//   |    +-- MainbusDevice (これがメインバス、システムに1つ)
//   |    |    +-- Mainbus24Device (上位8ビットがテーブルで表せるメインバス)
//   |    |    |    |  +-------------+
//   |    |    |    +--| LunaMainbus | (LUNA 共通部)
//   |    |    |    |  +-------------+
//   |    |    |    |    |  +--------------+
//   |    |    |    |    +--| Luna1Mainbus | (LUNA-I)
//   |    |    |    |    |  +--------------+
//   |    |    |    |    |  +----------------+
//   |    |    |    |    +--| Luna88kMainbus | (LUNA-88K)
//   |    |    |    |       +----------------+
//   |    |    |    |
//   |    |    |    +-- NewsMainbus
//   |    |    |    +-- Virt68kMainbus
//   |    |    +-- X68kMainbus
//   |    +-- X68kIODevice
//   +-- XPbusDevice

#include "mainbus_luna.h"
#include "bt45x.h"
#include "buserr.h"
#include "busio.h"
#include "cmmu.h"
#include "config.h"
#include "crtc2.h"
#include "fuserom.h"
#include "interrupt.h"
#include "lance.h"
#include "lunafb.h"
#include "mainapp.h"
#include "mainram.h"
#include "mk48t02.h"
#include "msxdos.h"
#include "nop.h"
#include "partialram.h"
#include "pio.h"
#include "prom.h"
#include "romemu_luna1.h"
#include "romemu_luna88k.h"
#include "sio.h"
#include "spc.h"
#include "subram.h"
#include "sysclk.h"
#include "sysctlr.h"
#include "tas.h"

//
// LUNA 共通部
//

// デバイスマップ用の識別子
enum {
	NONE,
	BUSERR,
	PROM,
	MK48,
	PIO0,
	PIO1,
	SIO,
	TAS,
	SYSCLK,
	SUBRAM,
	MROM,
	LUNAFB,
	BT45x,
	CRTC2,
	SCSI,
	LANCE,
	FUSE,
	SYSCTL,
	CMMU,
};

// コンストラクタ
LunaMainbus::LunaMainbus()
{
	NEWDV(BusErr, new BusErrDevice());
	NEWDV(NopIO, new NopIODevice());

	accstat_monitor->SetSize(80, 2 + 32);
}

// デストラクタ
LunaMainbus::~LunaMainbus()
{
}

// デバイスマップから devtable を作成 (ここは共通にできる)
void
LunaMainbus::MakeDevtable(const uint8 *maptable)
{
	for (int i = 0; i < devtable.size(); i++) {
		IODevice *d;
		switch (maptable[i]) {
		 case NONE:		d = pNopIO.get();		break;
		 case BUSERR:	d = pBusErr.get();		break;
		 case PROM:		d = pPROM.get();		break;
		 case MK48:		d = pRTC.get();			break;
		 case PIO0:		d = pPIO0.get();		break;
		 case PIO1:		d = pPIO1.get();		break;
		 case SIO:		d = pSIO.get();			break;
		 case TAS:		d = pTAS.get();			break;
		 case SYSCLK:	d = pSysClk.get();		break;
		 case SUBRAM:	d = pSubRAM.get();		break;
		 case MROM:		d = pNopIO.get();		break;
		 case LUNAFB:	d = pPlaneVRAM.get();	break;
		 case BT45x:	d = pBT45x.get();		break;
		 case CRTC2:	d = pCRTC2.get();		break;
		 case SCSI:		d = pSPC.get();			break;
		 case LANCE:	d = pEthernet.get();	break;
		 case SYSCTL:	d = pInterrupt.get();	break;
		 // これらはサブクラスが所有しているので Get で取得する必要がある。
		 case FUSE:		d = GetFuseROMDevice();	break;
		 case CMMU:		d = GetCMMUDevice();	break;
		 default:
			PANIC("corrupted maptable[%u]=%d", i, maptable[i]);
		}
		devtable[i] = d;
	}
}

// メインバスの初期化
bool
LunaMainbus::InitMainbus()
{
	auto mainram = dynamic_cast<MainRAMDevice *>(pMainRAM.get());
	auto partial = dynamic_cast<PartialRAMDevice *>(pPartialRAM.get());

	// RAM は容量が確定した後のここで配置。
	uint ram_size_MB = mainram->GetSizeMB();
	int i = 0;
	while (ram_size_MB >= 16) {
		// 16MB あれば RAM が直接担当
		devtable[i++] = mainram;
		ram_size_MB -= 16;
	}
	// 16MB 未満なら PartialRAM が担当
	if (ram_size_MB > 0) {
		devtable[i] = partial;
	}

	// 先頭 (mainram or partial) をブートページ切り替え用に覚えておく。
	ram0 = devtable[0];

	// アクセス状況用のマップを作成。
	InitAccStat();

	return true;
}

// ブートページを切り替える。
void
LunaMainbus::SwitchBootPage(bool isrom)
{
	// 共通処理
	inherited::SwitchBootPage(isrom);

	// ROM は 128KB しかないので 16MB まるごと切り替わったりはしないとは
	// 思うけど、具体的にどの範囲が切り替わるのかを知る方法がないのと
	// 大して副作用もないので、先頭の 1ブロックをまるごと切り替えておく。
	if (isrom) {
		auto prom0 = GetPROM0Device();
		devtable[0x00] = prom0;
		devtable[0x41] = prom0;
	} else {
		auto prom = GetPROMDevice();
		devtable[0x00] = ram0;
		devtable[0x41] = prom;
	}
}


//
// LUNA-I
//

// LUNA-I のデバイス割り当て表 (上位8ビット)
//
// 仕様	実際
// 00	00		メインメモリ
// --	01..03	二重バスフォールトするようだ
// --	04..0f	何かよく分からないものが読める
// --	10..3f	BUSERR
// 41	40..43	PROM (B、N=128KBでミラー)
// 45	44..47	mk48t02 (B、N=2048でミラー)
// 49	48..4b	pio0 (B、N=4でミラー)
// 4d	4c..4f	pio1 (B、N=4でミラー)
// 51	50..53	sio  (BB、N=4でミラー)
// --	54..5f	0xff が読めるようだ
// 61	60..61	TAS (B、N=1でミラー)
// 63	62..63	システムクロック (B、N=1でミラー)
// --           以降TASとSysClkで2枠ずつ。また無効ビットの読み出しは
// --	        必ずしも Hi とは限らず不安定のようだ。
// 71	70..7f	3ポートRAM (B、N=128KBでミラー)
// 81	80..	BUSERR (オンボード拡張スロットA)
// 83	  ..8f	BUSERR (オンボード拡張スロットB)
// 91	90..9f	0xff が読めるようだ (PC-9000 拡張スロット)
//
// a1			マスクROM
//              a0,a2,a4,... BUSERR
//              a1,a3,a5,... マスクROM(なければ0xffが読める)
// b1			ビットマップ
//              b0,b2,b4,... BUSERR
//              b1,b3,b5,... ビットマップ (内訳は lunafb.cpp 参照)
// c1			パレット
//              c0,c2,c4,... BUSERR
//              c1,c3,c5,... パレット (B、N=4でミラー)
// d1			CRTC-II
//              d0,d2,d4,... BUSERR
//              d1,d3,d5,... CRTC-II (B、N=2でミラー)
//
// e1	e0..e3	SCSI (BBBB、N=16 でミラー)
// --	e4..ef	0xff が読めるようだが不安定。
// f1	f0..f3	LANCE (WW、N=2 でミラー)
// --	f4..ff	0xff が読めるようだ

/*static*/ const uint8
Luna1Mainbus::maptable[256] = {
	// (00,)01,02,03 は実際にはたぶんパリティチェックが入っていて(?)
	// 非実装領域にアクセスすると二重バスフォールトになるがそれは未対応。
	// RAM は Init() で動的に配置する。
	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	// 00
	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	// 08
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 10
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 18
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 20
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 28
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 30
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 38

	PROM,	PROM,	PROM,	PROM,	MK48,	MK48,	MK48,	MK48,	// 40
	PIO0,	PIO0,	PIO0,	PIO0,	PIO1,	PIO1,	PIO1,	PIO1,	// 48
	SIO,	SIO,	SIO,	SIO,	NONE,	NONE,	NONE,	NONE,	// 50
	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	// 58
	TAS,	TAS,	SYSCLK,	SYSCLK,	TAS,	TAS,	SYSCLK,	SYSCLK,	// 60
	TAS,	TAS,	SYSCLK,	SYSCLK,	TAS,	TAS,	SYSCLK,	SYSCLK,	// 68
	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	// 70
	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	// 78

	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 80
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 88
	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	// 90
	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	// 98
	BUSERR,	MROM,	BUSERR,	MROM,	BUSERR,	MROM,	BUSERR,	MROM,	// a0
	BUSERR,	MROM,	BUSERR,	MROM,	BUSERR,	MROM,	BUSERR,	MROM,	// a8
	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	// b0
	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	// b8

	BUSERR,	BT45x,	BUSERR,	BT45x,	BUSERR,	BT45x,	BUSERR,	BT45x,	// c0
	BUSERR,	BT45x,	BUSERR,	BT45x,	BUSERR,	BT45x,	BUSERR,	BT45x,	// c8
	BUSERR,	CRTC2,	BUSERR,	CRTC2,	BUSERR,	CRTC2,	BUSERR,	CRTC2,	// d0
	BUSERR,	CRTC2,	BUSERR,	CRTC2,	BUSERR,	CRTC2,	BUSERR,	CRTC2,	// d8
	SCSI,	SCSI,	SCSI,	SCSI,	NONE,	NONE,	NONE,	NONE,	// e0
	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	// e8
	LANCE,	LANCE,	LANCE,	LANCE,	NONE,	NONE,	NONE,	NONE,	// f0
	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	// f8
};

// コンストラクタ
Luna1Mainbus::Luna1Mainbus()
{
	// デバイス (順序に注意)
	// BusErrDevice, NopIODevice は親コンストラクタで作成済み。

	NEWDV(Interrupt, new LunaInterrupt());
	NEWDV(RTC, new BusIO_B<MK48T02Device>());		// required by SysClk
	NEWDV(SysClk, new BusIO_B<SysClkDevice>());		// required by PROMEmu
	if (gMainApp.msxdos_mode) {
		NEWDV(PROM, new MSXDOSDevice());
	} else if (gMainApp.exec_file ||
	           gConfig->Find("prom-image").AsString().empty()) {
		NEWDV(PROM, new Luna1PROMEmuDevice());
	} else {
		NEWDV(PROM, new PROMDevice());				// required by RAM,BT45x
	}
	NEWDV(PROM0, new PROM0Device());
	NEWDV(MainRAM, new MainRAMDevice());			// required by PartialRAM
	NEWDV(PartialRAM, new PartialRAMDevice());
	NEWDV(PIO0, new BusIO_B<PIO0Device>());
	NEWDV(PIO1, new BusIO_B<PIO1Device>());
	NEWDV(SIO, new BusIO_BB<SIODevice>());
	NEWDV(TAS, new BusIO_B<TASDevice>());
	NEWDV(SubRAM, new SubRAMDevice(128));
	NEWDV(CRTC2, new BusIO_B<CRTC2Device>());
	NEWDV(SPC, new BusIO_BBBB<SPCDevice>());
	NEWDV(Ethernet, new BusIO_W<LanceDevice>());
}

// デストラクタ
Luna1Mainbus::~Luna1Mainbus()
{
}

// 動的なコンストラクション
bool
Luna1Mainbus::Create()
{
	int nplane = BT45xDevice::GetConfigPlaneCount();
	if (nplane < 0) {
		return false;
	}
	if (nplane == 8) {								// required by Lunafb
		NEWDV(BT45x, new BusIO_BFFF<BT458Device>());
	} else {
		NEWDV(BT45x, new BusIO_B<BT454Device>());
	}
	NEWDV(PlaneVRAM, new LunafbDevice());

	// 全部揃ったここで、デバイスマップから devtable を作成。
	MakeDevtable(maptable);
	return true;
}

//
// LUNA-88K
//

// 00..03		RAM (64MB 実機の場合)
// 04..3f		バスエラー
// 40,41		PROM (B、N=256KB でミラー)
// 42,43		FUSEROM (BFFF、N=256 でミラー)
// 44,45		NVRAM (BFFF、N=2048 でミラー)
// 46,47		バスエラー
// 48,49		PIO0 (BFFF、N=4 でミラー)
// 4a,4b		バスエラー
// 4c,4d		PIO1 (BFFF、N=4 でミラー)
// 4e,4f		バスエラー
// 50,51		SIO (BFFF、N=4 でミラー)
// 52..5f		バスエラー
// 60,61		TAS? (BFFF、N=1 ?)
// 62,63		SysClk (BFFF、N=1 ?)
// 64,65,66,67	SysCtlr? (L、N=1 ?)
// 68,69,6a,6b	SysCtlr? (L、N=4 ?)
// 6c,6d		CPU リセット
// 6e,6f		$ff (?)
// 70-7f		SubRAM
// 80-9f		バスエラー
// a0-af		偶数(a0,a2,..)はバスエラー、奇数(a1,a3,..)は $ff
// b0-bf		偶数(b0,b2,..)はバスエラー、奇数(b1,b3,..)は LUNAFB
// c0-cf		偶数(c0,c2,..)はバスエラー、奇数(c1,c3,..)は BT454(BFFF、N=4)
// d0-df		偶数(d0,d2,..)はバスエラー、奇数(d1,d3,..)はたぶん CRTC2
//				(CRTC2 は今の所 $ff しか観測できていないので詳細不明)
// e0,e1		SPC (BFFF、N=16 でミラー)
// e2-ef		$ff
// f0,f1		たぶん Lance (BFFF、N=2)
// f2-fd		$ff
// fe			$fe00'0000-$fef7'ffff まではアドレス(*)
//				$fef8'0000-$feff'ffff までは $ff
// ff			たぶん CMMU 以外はアドレス(*)
//
// バスエラーの領域は 3% くらいの確率で $ffffffff が読めることがある。まじか。
// (OpenBSD の CMMU 検出がバスエラーが起きるはずなのに起きなかった時のことを
// 考慮したコードになってるのはこのためだろうか…)
//
// アドレス(*) のところは、32ビットアドレスが読み出せる。バイトアクセスしても
// そのバイトに応じたところが読み出せるので 32ビットの (フルワード単位の)
// アドレスがデータバスに乗って返って来ているようだ…。
// 以下 PROM でのダンプ結果 (boot の machine read コマンドでも同じ)。
//	0> dw fe000000 fe00000f
//	fe000000:  fe000000  fe000004  fe000008  fe00000c
//	0> d fe000000 fe00000f
//	fe000000:  fe 00 00 00 fe 00 00 04 fe 00 00 08 fe 00 00 0c

/*static*/ const uint8
Luna88kMainbus::maptable[256] = {
	// RAM は Init() で動的に配置する (64MB なら 00..03 の4枠)。
	// 先頭 64MB の空間 (00..03) だけは、PROM 1.20 ではメモリが無いときでも
	// バスエラーにならないことを期待しているので NONE にしておく。
	// それ以降はバスエラー。
	NONE,	NONE,	NONE,	NONE,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 00
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 08
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 10
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 18
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 20
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 28
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 30
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 38

	// LUNA-88K2 は 47 に(も?) NVRAM がいるようだ
	// 69,6b,6d にも何かのコントローラ?
	PROM,	PROM,	FUSE,	FUSE,	MK48,	MK48,	BUSERR,	BUSERR,	// 40
	PIO0,	PIO0,	BUSERR,	BUSERR,	PIO1,	PIO1,	BUSERR,	BUSERR,	// 48
	SIO,	SIO,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 50
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 58
	TAS,	TAS,	SYSCLK,	SYSCLK,	SYSCTL,	SYSCTL,	SYSCTL,	SYSCTL,	// 60
	SYSCTL,	SYSCTL,	SYSCTL,	SYSCTL,	SYSCTL,	SYSCTL,	SYSCTL,	SYSCTL,	// 68
	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	// 70
	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	SUBRAM,	// 78

	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 80
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 88
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 90
	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	BUSERR,	// 98
	BUSERR,	MROM,	BUSERR,	MROM,	BUSERR,	MROM,	BUSERR,	MROM,	// a0
	BUSERR,	MROM,	BUSERR,	MROM,	BUSERR,	MROM,	BUSERR,	MROM,	// a8
	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	// b0
	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	BUSERR,	LUNAFB,	// b8

	// d0 にボードチェックレジスタ?
	BUSERR,	BT45x,	BUSERR,	BT45x,	BUSERR,	BT45x,	BUSERR,	BT45x,	// c0
	BUSERR,	BT45x,	BUSERR,	BT45x,	BUSERR,	BT45x,	BUSERR,	BT45x,	// c8
	BUSERR,	CRTC2,	BUSERR,	CRTC2,	BUSERR,	CRTC2,	BUSERR,	CRTC2,	// d0
	BUSERR,	CRTC2,	BUSERR,	CRTC2,	BUSERR,	CRTC2,	BUSERR,	CRTC2,	// d8
	SCSI,	SCSI,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	// e0
	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	// e8
	LANCE,	LANCE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	// f0
	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	NONE,	CMMU,	// f8
};

// コンストラクタ
Luna88kMainbus::Luna88kMainbus()
{
	// デバイス (順序に注意)
	// BusErrDevice, NopIODevice は親コンストラクタで作成済み。

	NEWDV(Interrupt, new SysCtlrDevice());
	NEWDV(RTC, new BusIO_BFFF<MK48T02Device>());	// required by SysClk
	NEWDV(SysClk, new BusIO_BFFF<SysClkDevice>());	// required by PROMEmu
	if (gMainApp.exec_file || gConfig->Find("prom-image").AsString().empty()) {
		NEWDV(PROM, new Luna88kPROMEmuDevice());
	} else {
		NEWDV(PROM, new PROMDevice());				// required by RAM
	}
	NEWDV(PROM0, new PROM0Device());
	NEWDV(MainRAM, new MainRAMDevice());			// required by PartialRAM
	NEWDV(PartialRAM, new PartialRAMDevice());
	NEWDV(FuseROM, new BusIO_BFFF<FuseROMDevice>());
	NEWDV(PIO0, new BusIO_BFFF<PIO0Device>());
	NEWDV(PIO1, new BusIO_BFFF<PIO1Device>());
	NEWDV(SIO, new BusIO_BFFF<SIODevice>());
	NEWDV(TAS, new BusIO_BFFF<TASDevice>());
	NEWDV(SubRAM, new SubRAMDevice(128));
	NEWDV(CRTC2, new BusIO_BFFF<CRTC2Device>());
	NEWDV(SPC, new BusIO_BFFF<SPCDevice>());
	NEWDV(Ethernet, new BusIO_WF<LanceDevice>());
	NEWDV(CMMU, new CMMUDevice());
}

// デストラクタ
Luna88kMainbus::~Luna88kMainbus()
{
}

// 動的なコンストラクション
bool
Luna88kMainbus::Create()
{
	int nplane = BT45xDevice::GetConfigPlaneCount();
	if (nplane < 0) {
		return false;
	}
	if (nplane == 8) {								// required by Lunafb
		NEWDV(BT45x, new BusIO_BFFF<BT458Device>());
	} else {
		NEWDV(BT45x, new BusIO_B<BT454Device>());
	}
	NEWDV(PlaneVRAM, new LunafbDevice());

	// 全部揃ったここで、デバイスマップから devtable を作成。
	MakeDevtable(maptable);
	return true;
}

unix.superglobalmegacorp.com

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